Home   Help Search Login Register  

Author Topic: Spawn command within scripts  (Read 1525 times)

0 Members and 1 Guest are viewing this topic.

Offline Sparticus76

  • Members
  • *
Spawn command within scripts
« on: 08 Apr 2009, 03:50:06 »
I'm interesed in the blocks of code etc that can be spawned from within the script, as is done in this fine example of body armour by Wolfrug.

Code: [Select]
if (_curDam > _maxdam) then
{

[_unit, _dam] spawn RUG_BA_Down; if (_mode == 3) then {_unit setdamage -500};

}

else {_unit setdamage -5; if (_mode == 3) then {_unit setDamage -500}};



Code: [Select]
RUG_BA_Down = {
private ["_unit", "_dam", "_EH", "_mode", "_id", "_text"];
_unit = _this select 0;
_dam = _this select 1;
_EH = _unit getVariable "RUG_BA_EH";
_mode = _unit getVariable "RUG_BA_Mode";

_unit action ["eject", vehicle _unit];
if (_mode != 3) then {_unit removeEventhandler ["hit", _EH]};
if (_mode != 3) then {_unit setdamage _dam};
_unit switchmove "DeadState";
_unit setcaptive true;
_unit stop true;
_text = format ["Perform first aid on %1", _unit];
_id = _unit addAction [_text, "RUG_BodyArmor.sqf", _id, 9.8, true, true];
[_unit, _id] spawn RUG_BA_AIAction;
if (RUG_BA_Debug) then {hint format ["%1 is down!", _unit]};
_timer = [] spawn {sleep (120 + (random 15))};
if (_mode !=3) then
{
waitUntil {scriptDone _timer OR (damage _unit < _dam)}
}
else
{
waitUntil {scriptDone _timer OR (_unit getVariable "RUG_BodyArmor") == 0};
};
_unit removeAction _id;
_unit stop false;
if (RUG_BA_Debug) then {hint format ["%1 is back up!", _unit]};
// Checks different modes;

switch (_mode) do
{
case 0: {};
case 1: {//Full armor return after revival
_unit setdamage -5;
_EH = _unit addEventHandler ["hit", {_this call RUG_BA}];
_unit setvariable ["RUG_BA_EH", _EH];
_unit setVariable ["RUG_BodyArmor", 0];
};
case 2: {//"Medevac" mode -> unit only get their armor back after getting fully healed
_unit spawn
{
waitUntil {damage _this == 0};
_this setdamage -5;
_EH = _this addEventHandler ["hit", {_this call RUG_BA}];
_this setvariable ["RUG_BA_EH", _EH];
_this setVariable ["RUG_BodyArmor", 0];
};
};
case 3: {
_unit setdamage -500;
_unit setVariable ["RUG_BodyArmor", 0];
};

};

_unit switchMove "AmovPpneMstpSrasWrflDnon";
_unit setcaptive false;
};


Now here's the hole thing so you can see...

Code: [Select]
//RUG_BodyArmor by Wolfrug (www.ofpec.com)
//
//Calling: [UnitName, Mode, MaxDam] execVM "RUG_BodyArmor.sqf"
//UnitName : Name of unit, can be 'this' in the init field, or _x if used with foreach
//Mode : 0, 1, 2 or 3.
//0 = Once armor is depleted, it can never be recharged (except by calling the script again).
//1 = Armor returns fully after each revival
//2 = Armor returns fully once unit has been fully healed after revival
//3 = Armor is never depleted: unit can be knocked down but not killed (except by scripting)
//MaxDam : Must be a number less than 0: determines total body armor. -1 = 3 total, -2 = 6 total etc.
//Note : due to the usage of eventhandlers, you should avoid calling this script more than once on any unit!
//Enjoy! - Wolfrug

//Set this to false to disable the hints!
RUG_BA_Debug = true;

private ["_unit", "_mode", "_dam"];

_unit = _this select 0;
_mode = _this select 1;
_dam = _this select 2;
if ((count _this) > 3) exitWith {_this call RUG_BA_Action};

//Inits script
if (_dam < 0) exitWith
{
if (isNil "RUG_BA") then
{
RUG_BA = compile preprocessfilelinenumbers "RUG_BodyArmor.sqf";
RUG_BA_Action = {
private ["_unit", "_caller", "_id", "_mode"];
_unit = _this select 0;
_caller = _this select 1;
_id = _this select 2;
_mode = _unit getVariable "RUG_BA_Mode";
if (((_unit distance _caller) > 3 && _unit == Player) OR _unit == _caller) exitWith {};
if ((_unit distance _caller) > 3 && _caller !=Player) then
{
_caller doMove (getpos _unit);
waitUntil {((_caller distance _unit) < 3) OR (unitReady _caller) OR (!alive _caller)};
};
if ((_caller distance _unit) > 3 OR (!alive _caller)) exitWith {};   if (not (alive _unit) ) exitWith {_unit removeAction _id};
_caller playMove "AinvPknlMstpSlayWrflDnon_medic";
sleep 8;
if (alive _caller && alive _unit) then {if (_mode !=3) then {_unit setDamage ((damage _unit) - 0.1)};
_unit removeAction _id;
if (_mode ==3) then {_unit setVariable ["RUG_BodyArmor", 0]};
};
_caller doFollow (leader _caller);
};
RUG_BA_AIAction = {
private ["_unit", "_id", "_dam","_maxdam", "_side", "_trig", "_foundhelper", "_helper"];
_unit = _this select 0;
_id = _this select 1;
_dam = damage _unit;
_maxdam = _unit getVariable "RUG_BA_MaxD";
_side = switch (side _unit) do {case west: {"WEST"};
case east: {"EAST"}; case resistance: {"GUER"};
case civilian: {"CIV"};
};
_trig = createtrigger ["EmptyDetector", getpos _unit];
_trig setTriggerArea [50, 50, 0, false];
_trig settriggerActivation [_side, "PRESENT", true];
sleep 1;
_foundHelper = false;
if (_mode != 3) then
{
_condition = {(damage _unit) >= _dam}
}
else
{
_condition = {(_unit getVariable "RUG_BodyArmor") > _maxdam}
};
while _condition do
{
_list = ((list _trig) - [_unit]);
if ((count _list) > 0) then {_helper = _list select (floor (random (count _list)))};
if (isNull (_helper findNearestEnemy (position _helper))) then {_foundHelper = true};
if (!_foundHelper) then {
if (_helper distance (_helper findNearestEnemy (position _helper)) > 100) then {_foundHelper = true};
};
if (_helper != Player && _foundHelper && vehicle _helper == _helper) then
{
_helper action ["USER", _unit, _id];
waitUntil {((_helper distance _unit) < 3) OR (unitReady _helper) OR (!alive _helper)};
if (RUG_BA_Debug) then {hint format ["%1 is helping %2!", _helper, _unit]};
sleep 10;
};

sleep 5;
};
deleteVehicle _trig;
};


RUG_BA_Down = {
private ["_unit", "_dam", "_EH", "_mode", "_id", "_text"];
_unit = _this select 0;
_dam = _this select 1;
_EH = _unit getVariable "RUG_BA_EH";
_mode = _unit getVariable "RUG_BA_Mode";

_unit action ["eject", vehicle _unit];
if (_mode != 3) then {_unit removeEventhandler ["hit", _EH]};
if (_mode != 3) then {_unit setdamage _dam};
_unit switchmove "DeadState";
_unit setcaptive true;
_unit stop true;
_text = format ["Perform first aid on %1", _unit];
_id = _unit addAction [_text, "RUG_BodyArmor.sqf", _id, 9.8, true, true];
[_unit, _id] spawn RUG_BA_AIAction;
if (RUG_BA_Debug) then {hint format ["%1 is down!", _unit]};
_timer = [] spawn {sleep (120 + (random 15))};
if (_mode !=3) then
{
waitUntil {scriptDone _timer OR (damage _unit < _dam)}
}
else
{
waitUntil {scriptDone _timer OR (_unit getVariable "RUG_BodyArmor") == 0};
};
_unit removeAction _id;
_unit stop false;
if (RUG_BA_Debug) then {hint format ["%1 is back up!", _unit]};
// Checks different modes;

switch (_mode) do
{
case 0: {};
case 1: {//Full armor return after revival
_unit setdamage -5;
_EH = _unit addEventHandler ["hit", {_this call RUG_BA}];
_unit setvariable ["RUG_BA_EH", _EH];
_unit setVariable ["RUG_BodyArmor", 0];
};
case 2: {//"Medevac" mode -> unit only get their armor back after getting fully healed
_unit spawn
{
waitUntil {damage _this == 0};
_this setdamage -5;
_EH = _this addEventHandler ["hit", {_this call RUG_BA}];
_this setvariable ["RUG_BA_EH", _EH];
_this setVariable ["RUG_BodyArmor", 0];
};
};
case 3: {
_unit setdamage -500;
_unit setVariable ["RUG_BodyArmor", 0];
};

};

_unit switchMove "AmovPpneMstpSrasWrflDnon";
_unit setcaptive false;
};
};
_unit setdamage -5;
if (_mode == 3) then {_unit setdamage -500};
_EH = _unit addEventHandler ["hit", {_this call RUG_BA}];
_maxdam = (getNumber (configFile >> "CfgVehicles" >> typeOf _unit >> "armor") * -(_dam));

_unit setvariable ["RUG_BA_EH", _EH];
_unit setVariable ["RUG_BA_Mode", _mode];
_unit setVariable ["RUG_BA_MaxD", _maxdam];
_unit setVariable ["RUG_BodyArmor", 0];
};

//Actual script

_bodydam = _unit getvariable "RUG_BodyArmor";
_maxdam = _unit getvariable "RUG_BA_MaxD";
_mode = _unit getVariable "RUG_BA_Mode";

_curDam = _bodydam + _dam;
_unit setvariable ["RUG_BodyArmor", _curDam];


if (RUG_BA_Debug) then {hint format ["Unit:%1\nDamage:%2\nCurrent/Max:%3/%4", _unit, _dam, _curDam, _maxdam]};


if (_curDam > _maxdam) then
{

[_unit, _dam] spawn RUG_BA_Down; if (_mode == 3) then {_unit setdamage -500};

}

else {_unit setdamage -5; if (_mode == 3) then {_unit setDamage -500}};

My question is, does the spawned variable have to be set before spawned, as done here, and also can it be spawned from any scope within the script. Thankyou, Sparticus.

Offline Wolfrug

  • Addons Depot
  • Former Staff
  • ****
  • Official OFPEC Old Timer
Re: Spawn command within scripts
« Reply #1 on: 08 Apr 2009, 09:57:15 »
Hi,

Basically, I wanted to keep the script to a single file, instead of splitting it up into several scripts that would need to be separately preprocessed to be called. That's why I chose to put in all of the other scripts (RUG_BA_Action, RUG_BA_AIAction, RUG_BA_Down) into the main script, where they are "created" when the script is first run, and can then be called by it later. The way I've made a single script work both for an action, an eventhandler and a normal execvm required some tinkering, but it works. Basically, however, the part where the other scripts (listed above) are created is only run ONCE, which is when it is initially execvm'd : this is made sure by the if (_dam < 0) exitWith {code here} code (since you determine the maximum damage by using negative numbers - when the same script is activated with the eventhandler, that number will always be positive). Looking at it now, I could've easily created a separate script for the eventhandler too, but oh well ;)

Essentially, however, by doing this inside any script or anywhere else:

Code: [Select]
TAG_YourScript =
{
_boy = _this select 0;
_girl = _this select 1;
_kid = _boy + _girl;
hint format ["%1", _kid]
};

And then calling it using spawn (or call):

Code: [Select]
[1, 2] spawn TAG_YourScript;
Is the -exact same thing- as making a script in .sqf:

Code: [Select]
_boy = _this select 0;
_girl = _this select 1;
_kid = _boy + _girl;
hint format ["%1", _kid]

And then running it using execvm (or call compile preprocessfilelinenumbers):

Code: [Select]
[1,2] execvm "YourScript.sqf";
So yes, you do have to "create" the script before you can spawn or call it, but you only have to do that once (and you should only do it once). In -principle-, if you really hate working with notepad, and LOVE using the single line that triggers and initialization fields and such give us, you could create any script using this method without ever creating a single external script file. But as scripts get more complicated, it would get increasingly hard to create these scripts using only this method - not to mention, it'd be very impractical if you'd want to share it with anyone else.

Hope that answers your question!

Wolfrug out.
"When 900 years YOU reach, look as good you will not!"

Offline Sparticus76

  • Members
  • *
Re: Spawn command within scripts
« Reply #2 on: 08 Apr 2009, 12:07:02 »
It does, thankyou very much Wolfrug.