Jump to content
Alpine_gremlin

Scripting Practice: Generic Error In Expression

Recommended Posts

Hello all,

 

I`m just messing around a bit, trying out new commands. For this I`m trying to use the switch command to spawn a random vehicle with crew and waypoints.

 

switchScript.sqf:

if (!isServer) exitWith {};

private ["_veh","_driver","_group","_unitArray"];
_myVar = floor random 4;

_vehicleVarNameBase = "mts_RandomVic";
_vehicleVarNameNo = 1;
_vehicleVarName = _vehicleVarNameBase + str _vehicleVarNameNo;
while {!(isNil _vehicleVarName)} do {
	_vehicleVarNameNo = _vehicleVarName + 1;
	_vehicleVarName = _vehicleVarNameBase + str _vehicleVarNameNo;
};

switch (_myVar) do {
	case 0:
	{
		_veh = createVehicle ["B_MRAP_01_F", getMarkerPos "startPos", [], 0, "NONE"];
		_veh setVehicleVarName _vehicleVarName;
		_veh call compile format ["%1=_this;", _vehicleVarName];
	};
	case 1:
	{
		_veh = createVehicle ["B_APC_Tracked_01_CRV_F", getMarkerPos "startPos", [], 0, "NONE"];
		_veh setVehicleVarName _vehicleVarName;
		_veh call compile format ["%1=_this;", _vehicleVarName];
	};
	case 2: 
	{
		_veh = createVehicle ["B_MBT_01_cannon_F", getMarkerPos "startPos", [], 0, "NONE"];
		_veh setVehicleVarName _vehicleVarName;
		_veh call compile format ["%1=_this;", _vehicleVarName];
	};
	case 3:
	{
		_veh = createVehicle ["B_Heli_Light_01_armed_F", getMarkerPos "startPos", [], 0, "FLY"];
		_veh flyInHeight 50;
		_veh setVehicleVarName _vehicleVarName;
		_veh call compile format ["%1=_this;", _vehicleVarName];
	};
};

_group = createGroup west;
_group createUnit ["B_crew_F", getMarkerPos "startPos", [], 0, "FORM"];

_unitArray = [];
_unitArray = _unitArray + units _group;
_driver = _unitArray select 0;
_driver assignAsDriver _veh;
_driver moveInDriver _veh;

_wp = _group addWaypoint [getMarkerPos "endPos",0];
[_group,0] setWaypointType "MOVE";
[_group,0] setWaypointCompletionRadius 50;
[_group,0] setWaypointSpeed "LIMITED";
_wp setWayPointStatements ["true","deleteVehicle _veh;{deleteVehicle _x} forEach (crew _veh)"];

Though it seems once I get to line 48 or so the game doesn`t seem to think that _veh has been defined. Am I missing something? I tried changing it to a global variable but I get the same error. The crewman spawns but the vehicle does not.

 

Any thoughts?

 

Cheers!

Share this post


Link to post
Share on other sites

Try adding "_veh = nil" before the switch statement. I know private should be enough, but sometimes it isn't. Also, floor random 3 will never equal 3. Change it to floor random 4.

  • Like 1

Share this post


Link to post
Share on other sites

Okay, so I got the vehicle to spawn in, and follow the waypoint. Upon completion however, the vehicle does not despawn as it should. I get no error in this regard.

_wp setWayPointStatements ["true","deleteVehicle _veh;{deleteVehicle _x} forEach (crew _veh)"];

Additionally, I get a generic error with the following lines after calling the script a second time:

while {!(isNil _vehicleVarName)} do {
_vehicleVarNameNo = _vehicleVarName + 1;
_vehicleVarName = _vehicleVarNameBase + str _vehicleVarNameNo;
};

My intent is to create a new variable for each vehicle that spawns, allowing this to run as many times as needed.

Share this post


Link to post
Share on other sites
1 hour ago, Alpine_gremlin said:

Hello all,

 

I`m just messing around a bit, trying out new commands. For this I`m trying to use the switch command to spawn a random vehicle with crew and waypoints.

 

switchScript.sqf:

 

Though it seems once I get to line 48 or so the game doesn`t seem to think that _veh has been defined. Am I missing something? I tried changing it to a global variable but I get the same error. The crewman spawns but the vehicle does not.

 

Any thoughts?

 

Cheers!

 

1 hour ago, Alpine_gremlin said:

Okay, so I got the vehicle to spawn in, and follow the waypoint. Upon completion however, the vehicle does not despawn as it should. I get no error in this regard.


_wp setWayPointStatements ["true","deleteVehicle _veh;{deleteVehicle _x} forEach (crew _veh)"];

Additionally, I get a generic error with the following lines after calling the script a second time:


while {!(isNil _vehicleVarName)} do {
_vehicleVarNameNo = _vehicleVarName + 1;
_vehicleVarName = _vehicleVarNameBase + str _vehicleVarNameNo;
};

My intent is to create a new variable for each vehicle that spawns, allowing this to run as many times as needed.

 

Why use a switch statement for that? Or was it just for testing purposes?

Take a look at scope and scope locality, since a variable is only local to the scope it was created in.

As pointed out by @AZCoder you need to define _veh before the switch statement, so the variable exists outside of its scope.

 

To give a vehicle a unique variable name you could use a global approach, not sure what you're trying to achieve with that while loop:

 

if (!isServer) exitWith {};

params [["_veh",objNull],["_driver",objNull],["_group",grpNull],["_unitArray",[]]];//define variables as private and give them default values
_myVar = floor random 4;

_vehicleVarNameBase = "mts_RandomVic";

//alternative approach to unique var names:
_vehicleVarNameNo = missionNamespace getVariable ["TAG_fnc_myVehCounter",1];//will return 1 for the first spawned vehicle and increase with every spawned one
_vehicleVarName = _vehicleVarNameBase + str _vehicleVarNameNo;


//remove this if my approach is working out for you
/*
_vehicleVarNameNo = 1;
_vehicleVarName = _vehicleVarNameBase + str _vehicleVarNameNo;
while {!(isNil _vehicleVarName)} do {
	_vehicleVarNameNo = _vehicleVarName + 1;
	_vehicleVarName = _vehicleVarNameBase + str _vehicleVarNameNo;
};
*/

switch (_myVar) do {
	case 0:
	{
		_veh = createVehicle ["B_MRAP_01_F", getMarkerPos "startPos", [], 0, "NONE"];
		_veh setVehicleVarName _vehicleVarName;
		_veh call compile format ["%1=_this;", _vehicleVarName];
	};
	case 1:
	{
		_veh = createVehicle ["B_APC_Tracked_01_CRV_F", getMarkerPos "startPos", [], 0, "NONE"];
		_veh setVehicleVarName _vehicleVarName;
		_veh call compile format ["%1=_this;", _vehicleVarName];
	};
	case 2:
	{
		_veh = createVehicle ["B_MBT_01_cannon_F", getMarkerPos "startPos", [], 0, "NONE"];
		_veh setVehicleVarName _vehicleVarName;
		_veh call compile format ["%1=_this;", _vehicleVarName];
	};
	case 3:
	{
		_veh = createVehicle ["B_Heli_Light_01_armed_F", getMarkerPos "startPos", [], 0, "FLY"];
		_veh flyInHeight 50;
		_veh setVehicleVarName _vehicleVarName;
		_veh call compile format ["%1=_this;", _vehicleVarName];
	};
};

//increase the vehicle counter
missionNamespace setVariable ["TAG_fnc_myVehCounter",_vehicleVarNameNo + 1,true];

_group = createGroup west;
_driver = _group createUnit ["B_crew_F", getMarkerPos "startPos", [], 0, "FORM"];//you can also reference the driver using this

_unitArray = units _group;//no need for more than this since units group returns an empty array if no units are in the group
_driver assignAsDriver _veh;
_driver moveInDriver _veh;

_wp = _group addWaypoint [getMarkerPos "endPos",0];
[_group,0] setWaypointType "MOVE";
[_group,0] setWaypointCompletionRadius 50;
[_group,0] setWaypointSpeed "LIMITED";

//_veh doesn't exist inside the scope as mentioned before, you can use "thisList" for an array of units in the group, or "this" for the group leader
_wp setWayPointStatements ["true","deleteVehicle vehicle this;{deleteVehicle _x} forEach thisList"];

Also take a look at setWaypointStatements, this refers to the group leader, while thisList holds an array of units that are in the group.

 

Cheers

 

  • Like 1

Share this post


Link to post
Share on other sites

@Grumpy Old Man

 

Thanks for the reply! This was mostly just me messing about. Would you be able to recommend a better alternative for creating this type of randomness? I ended up scrapping that while loop and tightened up the code. It works now!

 

if (!isServer) exitWith {};

private ["_veh","_driver","_group","_unitArray"];
_myVar = floor random 4;

switch (_myVar) do {
	case 0:
	{
		_veh = createVehicle ["B_MRAP_01_F", getMarkerPos "startPos", [], 0, "NONE"];
	};
	case 1:
	{
		_veh = createVehicle ["B_APC_Tracked_01_CRV_F", getMarkerPos "startPos", [], 0, "NONE"];
	};
	case 2: 
	{
		_veh = createVehicle ["B_MBT_01_cannon_F", getMarkerPos "startPos", [], 0, "NONE"];
	};
	case 3:
	{
		_veh = createVehicle ["B_Heli_Light_01_armed_F", getMarkerPos "startPos", [], 0, "FLY"];
		_veh flyInHeight 50;
	};
};

_group = createGroup west;
_group createUnit ["B_crew_F", getMarkerPos "startPos", [], 0, "FORM"];

_unitArray = [];
_unitArray = _unitArray + units _group;
_driver = _unitArray select 0;
_driver assignAsDriver _veh;
_driver moveInDriver _veh;

_wp = _group addWaypoint [getMarkerPos "endPos",0];
[_group,0] setWaypointType "MOVE";
[_group,0] setWaypointCompletionRadius 50;
[_group,0] setWaypointSpeed "LIMITED";

sleep 5;

waitUntil {unitReady _driver};

player sideChat "WP complete!";

deleteWaypoint [_group,0];
_wp2 = _group addWaypoint [getMarkerPos "startPos",0];
[_group,0] setWaypointType "MOVE";
[_group,0] setWaypointCompletionRadius 50;
[_group,0] setWaypointSpeed "LIMITED";

sleep 5;

waitUntil {unitReady _driver};

player sideChat "Script complete!";

{deleteVehicle _x} forEach (crew _veh);
deleteVehicle _veh;

As far as the while loop, it was something I remember seeing done in the famous Escape from Cherno mission back in A2. I thought I could create a similar effect here.

Share this post


Link to post
Share on other sites
1 hour ago, Alpine_gremlin said:

@Grumpy Old Man

 

Thanks for the reply! This was mostly just me messing about. Would you be able to recommend a better alternative for creating this type of randomness? I ended up scrapping that while loop and tightened up the code. It works now!

 

Well you can always add more randomness, or even weighted randomness.

You could do something like this:

_spawnParams = [["B_MRAP_01_F","startPos","NONE"],
		["B_APC_Tracked_01_CRV_F","startPos","NONE"],
		["B_MBT_01_cannon_F","startPos","NONE"],
		["B_Heli_Light_01_armed_F","startPos","FLY"]
		];

_rndSpawn = selectRandom _spawnParams;
_rndSpawn params ["_type","_marker","_special"];

_veh = createVehicle [_type, getMarkerPos _marker, [], 0, _special];
_veh setVehicleVarName _vehicleVarName;
_veh call compile format ["%1=_this;", _vehicleVarName];

Or use selectRandomWeighted to make certain types appear more often, with a number between 0 and 1 determining the chance of selection:

_spawnParams = [["B_MRAP_01_F","startPos","NONE"],0.5,
		["B_APC_Tracked_01_CRV_F","startPos","NONE"],0.35,
		["B_MBT_01_cannon_F","startPos","NONE"],0.2,
		["B_Heli_Light_01_armed_F","startPos","FLY"],0.1,
		];

_rndSpawn = selectRandomWeighted _spawnParams;
_rndSpawn params ["_type","_marker","_special"];

_veh = createVehicle [_type, getMarkerPos _marker, [], 0, _special];
_veh setVehicleVarName _vehicleVarName;
_veh call compile format ["%1=_this;", _vehicleVarName];

This way you could even randomize markers for spawn position and other stuff.

 

Cheers

  • Thanks 1

Share this post


Link to post
Share on other sites
10 hours ago, Alpine_gremlin said:

_wp = _group addWaypoint [getMarkerPos "endPos",0];
[_group,0] setWaypointType "MOVE";
[_group,0] setWaypointCompletionRadius 50;
[_group,0] setWaypointSpeed "LIMITED";

 

You should not do [_group,0] , you already have a reference to the waypoint in _wp. The second parameter of addWaypoint is not an index but a placement radius. There is no guarantee that the added waypoint is index 0.

In this particular instance it is definitely not. A spawned group has an automatic waypoint in index 0 of its starting position when placed in the editor. As this group was not placed in the editor but created via script the waypoint position of the waypoint in index 0 will be somewhere around [0,0,0].

 

12 hours ago, Alpine_gremlin said:

_veh call compile format ["%1=_this;", _vehicleVarName];

No point in call compiling the vehicleVarName as all this is doing is creating a global variable. It would be better to just...

missionNamespace setVariable[ _vehicleVarName, _veh ];

...and use the third parameter as true if you need it to be public.

 

Spoiler

if (!isServer) exitWith {};

//Select a random vehicle type and start and end markers
selectRandom [
	["B_MRAP_01_F", "startPos", "endPos"],
	["B_APC_Tracked_01_CRV_F", "startPos", "endPos"],
	["B_MBT_01_cannon_F", "startPos", "endPos"], 
	["B_Heli_Light_01_armed_F", "startPos", "endPos"]
] params[ "_vehType", "_startMarker", "_endMarker" ];

//Create the vehicle @ _startMarker and set to flying if an AIR vehicle
private _veh = createVehicle [ _vehType, getMarkerPos _startMarker, [], 0, [ "NONE", "FLY" ] select ( _vehType isKindOf "AIR" ) ];

//Give the vehicle a varName including counter
_veh setVehicleVarName format[ "mts_RandomVic%1", [ "mts_RandomVic_counter", 1 ] call BIS_fnc_counter ];
//Make global and public
[ _veh ] call BIS_fnc_objectVar;

//Create driver
private _unit = createGroup west createUnit ["B_crew_F", getMarkerPos _startMarker, [], 0, "FORM"];
_unit assignAsDriver _veh;
_unit moveInDriver _veh;

//If AIR vehicle set flying height
if ( _vehType isKindOf "AIR" ) then {
	_veh flyInHeight 50;
};

//Add end waypoint
_wp = group _unit addWaypoint [getMarkerPos _endMarker,0];
_wp setWaypointType "MOVE";
_wp setWaypointCompletionRadius 50;
_wp setWaypointSpeed "LIMITED";
_wp setWaypointStatements [ "true", "{ deleteVehicle _x; }foreach ( units this + [ vehicle this ] ); "];

 

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×