Advertisement
Guest User

Untitled

a guest
Mar 16th, 2015
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.28 KB | None | 0 0
  1. // File: murk_spawn.sqf
  2. // Function: To allow for simple trigger based spawning using editor placed units and waypoints. The script deletes all units when the mission start and the recreate them on command.
  3. // Parameters:
  4. // _this select 0: OBJECT - unit name (this)
  5. // _this select 1: STRING - spawn type ("once","repeated","wave" and "reset")
  6. // _this select 2 (optional): NUMBER - spawn lives (the amount of time the unit respawns, or wave number)
  7. // _this select 3 (optional): NUMBER - spawn delay
  8. // _this select 4 (optional): STRING - init string called for the leader of the group
  9. // _this select 5 (optional): NUMBER- will start removal sequence of all dead group members after X seconds (default 120)
  10. // Usage:
  11. // Example trigger: Anybody Once (or whatever you want), onActivation: triggername setVariable ["murk_spawn",true,true];
  12. // Unit (leader of group): nul = [this,"SPAWNTYPE",LIVES,DELAY] execVM "murk_spawn.sqf";
  13. //
  14. // Example: nul = [this,"once"] execVM "murk_spawn3.sqf"; ---- Will spawn the editor unit once based on the trigger
  15. // Example: nul = [this,"repeated",4,30] execVM "murk_spawn.sqf"; ---- Will spawn the editor unit based on the trigger, then respawn it 4 times with a 30 second delay upon death
  16. // Example: nul = [this,"wave",5,60] execVM "murk_spawn.sqf"; ---- Will spawn the editor unit once based on the trigger, then respawn the entire group (regardless of deaths) 5 times with 60 seconds between
  17. // Example: nul = [this,"reset",5] execVM "murk_spawn.sqf"; ---- Will spawn the editor unit once based on the trigger, then reset the trigger after a preset time (15 seconds default). The unit will be created when trigger is true again, maximum number of lives.
  18. // -----------------------------------------------------------------------------------------------------
  19. // V9.? Working Build (Wulfy Wulf)
  20. // - Change: unitInfoArray handles uniforms, vests, backpacks, and objects within now
  21. // - Fix: Some RPT errors from incorrect conditions not entering or terminating properly
  22. // - Fix: Some RPT errors from spawnUnit initializing to Object- uses null now
  23. // V9 (Murklor again :p)
  24. // - Note: Initial Arma 3 test script. Note that some functionality from V8/V7 has been taken out because my brain is too foggy to understand everything, this is simplified. Sort of.
  25. // - Fix: setVehicleInit has been removed from A3, testing another way
  26. // - Add: New example mission on Stratis
  27. // - Change: The trigger variable is held in the object that is synchronized to the group for improved WYSIWYG. This means that the trigger argument is no longer needed.
  28. // - Change: Updated this readme to reflect the changes
  29. // V8 (ArmAIIholic)
  30. // - Waypoints are also remembered -- no dummy groups at all!!!
  31. // - You get the output on Clipboard you can paste and execute. Added loader for Clipboard missions.
  32. // V7 (ArmAIIholic)
  33. // - Added GameLogic center to reduce number of dummy groups at the beginning, and in modes repeated and reset
  34. // - Changed beginning scope to isServer, rather than using exitWith
  35. // - Shortened initializing trigger part in init.sqf
  36. // - Added original instructions and examples, adapted for v7
  37. // - SQM is from v5 with some groups added
  38. // V6
  39. // - See older versions
  40.  
  41. // This script is serverside
  42. if(isServer) then
  43. {
  44.  
  45. // ------------------- Init ----------------------- //
  46. _countThis = count _this;
  47. _waitingPeriod = 5; // Waiting period between script refresh
  48.  
  49. // ---------------- Parameters -------------------- //
  50. _unit = _this select 0;
  51. _spawntype = _this select 1;
  52. _spawnlives = if (_countThis >= 3) then { _this select 2; } else { 1 }; // Optional
  53. _spawndelay = if (_countThis >= 4) then { _this select 3; } else { 1 }; // Optional
  54. _initString = if (_countThis >= 5) then { _this select 4; } else { "" }; // Optional
  55. _bodyRemove = if (_countThis >= 6) then { _this select 5; } else { 120 }; // Optional
  56.  
  57. // The object (trigger, whatever) the unit is synchronized to hold the trigger variable
  58. _triggerObject = (synchronizedObjects _unit) select 0;
  59. _triggerObject setVariable ["murk_spawn",false,false];
  60.  
  61. // -- Delete the unit (this is always done ASAP) -- //
  62. _unitArray = [];
  63. _unitGroup = group _unit;
  64. _unitsInGroup = units _unitGroup;
  65. _unitCount = count _unitsInGroup;
  66. _unitsInGroupAdd = [];
  67. _side = side _unitGroup;
  68.  
  69. while { count units _unitGroup > 0 } do {
  70. // The currently worked on unit
  71. _unitsInGroup = units _unitGroup;
  72. _unit = _unitsInGroup select 0;
  73. _unitCount = count _unitsInGroup;
  74. diag_log format["Unit: %1, Units left: %2",_unit,units _unitGroup];
  75. //hint format ["Deleting: %1 - vehicleVarName: %2", _unit, vehicleVarName _unit]; sleep 1;
  76.  
  77. // Check if its a vehicle
  78. if ( (vehicle _unit) isKindOf "LandVehicle" OR (vehicle _unit) isKindOf "Air") then {
  79. _vcl = vehicle _unit;
  80. if (!(_vcl in _unitsInGroupAdd) AND (typeOf _vcl != "")) then {
  81. _unitsInGroupAdd set [count _unitsInGroupAdd, _vcl];
  82. _unitCrewArray = [];
  83. _crew = crew _vcl;
  84. { _unitCrewArray set [count _unitCrewArray, typeOf _x]; } forEach _crew;
  85.  
  86. _unitInfoArray = [
  87. typeOf _vcl,
  88. getPos _vcl,
  89. getDir _vcl,
  90. vehicleVarName _vcl,
  91. skill _vcl,
  92. rank _vcl,
  93. _unitCrewArray,
  94. weapons _vcl,
  95. assignedItems _vcl,
  96. uniform _vcl,
  97. uniformItems _vcl,
  98. vest _vcl,
  99. vestItems _vcl,
  100. backpack _vcl,
  101. backpackItems _vcl,
  102. headgear _vcl,
  103. goggles _vcl
  104. ];
  105. _unitArray set [count _unitArray, _unitInfoArray];
  106. deleteVehicle _vcl;
  107. { deleteVehicle _x; } forEach _crew;
  108. };
  109. }
  110. // Otherwise its infantry
  111. else {
  112. _unitInfoArray = [
  113. typeOf _unit,
  114. getPos _unit,
  115. getDir _unit,
  116. vehicleVarName _unit,
  117. skill _unit,
  118. rank _unit,
  119. [],
  120. weapons _unit,
  121. assignedItems _unit,
  122. uniform _unit,
  123. uniformItems _unit,
  124. vest _unit,
  125. vestItems _unit,
  126. backpack _unit,
  127. backpackItems _unit,
  128. headgear _unit,
  129. goggles _unit
  130. ];
  131. _unitArray set [count _unitArray, _unitInfoArray];
  132. deleteVehicle _unit;
  133. };
  134. sleep 0.01;
  135. };
  136.  
  137. // Gathering waypoints
  138. _countWaypoints = 0;
  139. _waypointsArray = [];
  140. _waypointsEntry = [];
  141. _countWaypoints = count(waypoints _unitGroup);
  142.  
  143. for [{_i=0}, {_i < _countWaypoints}, {_i=_i+1}] do
  144. {
  145. _waypointsEntry = [];
  146.  
  147. _wPos = waypointPosition [_unitGroup, _i];
  148. _wHPos = waypointHousePosition [_unitGroup, _i];
  149. _wBih = waypointBehaviour [_unitGroup, _i];
  150. _wCM = waypointCombatMode [_unitGroup, _i];
  151. _wCR = waypointCompletionRadius [_unitGroup, _i];
  152. _wDes = waypointDescription [_unitGroup, _i];
  153. _wForm = waypointFormation [_unitGroup, _i];
  154. _wScr = waypointScript [_unitGroup, _i];
  155. _wShw = waypointShow [_unitGroup, _i];
  156. _wSp = waypointSpeed [_unitGroup, _i];
  157. _wSt = waypointStatements [_unitGroup, _i]; //diag_log _wSt;
  158. _wTo = waypointTimeout [_unitGroup, _i];
  159. _wTy = waypointType [_unitGroup, _i];
  160.  
  161. _waypointsEntry = _waypointsEntry + [_wPos] + [_wHPos] + [_wBih] + [_wCM] + [_wCR] + [_wDes] + [_wForm] + [_wScr] + [_wShw] + [_wSp] + [_wSt] + [_wTo] + [_wTy];
  162.  
  163. _waypointsArray = _waypointsArray + [_waypointsEntry];
  164. };
  165.  
  166. //diag_log format ["Waypoints' array : %1",_waypointsArray];
  167.  
  168. deleteGroup _unitGroup;
  169.  
  170. // ----------------- Functions -------------------- //
  171.  
  172. // *WARNING* BIS FUNCTION RIPOFF - Taken from fn_returnConfigEntry as its needed for turrets and shortened a bit
  173. _fnc_returnConfigEntry = {
  174. private ["_config", "_entryName","_entry", "_value"];
  175. _config = _this select 0;
  176. _entryName = _this select 1;
  177. _entry = _config >> _entryName;
  178. //If the entry is not found and we are not yet at the config root, explore the class' parent.
  179. if (((configName (_config >> _entryName)) == "") && (!((configName _config) in ["CfgVehicles", "CfgWeapons", ""]))) then {
  180. [inheritsFrom _config, _entryName] call _fnc_returnConfigEntry;
  181. }
  182. else { if (isNumber _entry) then { _value = getNumber _entry; } else { if (isText _entry) then { _value = getText _entry; }; }; };
  183. //Make sure returning 'nil' works.
  184. if (isNil "_value") exitWith {nil};
  185. _value;
  186. };
  187.  
  188. // *WARNING* BIS FUNCTION RIPOFF - Taken from fn_fnc_returnVehicleTurrets and shortened a bit
  189. _fnc_returnVehicleTurrets = {
  190. private ["_entry","_turrets", "_turretIndex"];
  191. _entry = _this select 0;
  192. _turrets = [];
  193. _turretIndex = 0;
  194. //Explore all turrets and sub-turrets recursively.
  195. for "_i" from 0 to ((count _entry) - 1) do {
  196. private ["_subEntry"];
  197. _subEntry = _entry select _i;
  198. if (isClass _subEntry) then {
  199. private ["_hasGunner"];
  200. _hasGunner = [_subEntry, "hasGunner"] call _fnc_returnConfigEntry;
  201. //Make sure the entry was found.
  202. if (!(isNil "_hasGunner")) then {
  203. if (_hasGunner == 1) then {
  204. _turrets = _turrets + [_turretIndex];
  205. //Include sub-turrets, if present.
  206. if (isClass (_subEntry >> "Turrets")) then { _turrets = _turrets + [[_subEntry >> "Turrets"] call _fnc_returnVehicleTurrets]; }
  207. else { _turrets = _turrets + [[]]; };
  208. };
  209. };
  210. _turretIndex = _turretIndex + 1;
  211. };
  212. };
  213. _turrets;
  214. };
  215.  
  216. _fnc_moveInTurrets = {
  217. private ["_turrets","_path","_i"];
  218. _turrets = _this select 0;
  219. _path = _this select 1;
  220. _currentCrewMember = _this select 2;
  221. _crew = _this select 3;
  222. _spawnUnit = _this select 4;
  223. _i = 0;
  224. while {_i < (count _turrets) AND _currentCrewMember < count _crew} do {
  225. _turretIndex = _turrets select _i;
  226. _thisTurret = _path + [_turretIndex];
  227. (_crew select _currentCrewMember) moveInTurret [_spawnUnit, _thisTurret]; _currentCrewMember = _currentCrewMember + 1;
  228. //Spawn units into subturrets.
  229. [_turrets select (_i + 1), _thisTurret, _currentCrewmember, _crew, _spawnUnit] call _fnc_moveInTurrets;
  230. _i = _i + 2;
  231. };
  232. };
  233.  
  234. // This is the general cleanup function running in the background for the group, replaces the removebody eventhandler and delete group in V5
  235. _fnc_cleanGroup = {
  236. _group = _this select 0;
  237. _unitsGroup = units _group;
  238. _sleep = _this select 1;
  239. // Hold until the entire group is dead
  240. while { ({alive _x} count _unitsGroup) > 0 } do { sleep 5; };
  241. sleep _sleep;
  242. {
  243. _origPos = getPos _x;
  244. _z = _origPos select 2;
  245. _desiredPosZ = if ( (vehicle _x) iskindOf "Man") then { (_origPos select 2) - 0.5 } else { (_origPos select 2) - 3 };
  246. if ( vehicle _x == _x ) then {
  247. _x enableSimulation false;
  248. while { _z > _desiredPosZ } do {
  249. _z = _z - 0.01;
  250. _x setPos [_origPos select 0, _origPos select 1, _z];
  251. sleep 0.1;
  252. };
  253. };
  254. deleteVehicle _x;
  255. sleep 5;
  256. } forEach _unitsGroup;
  257. // Now we know that all units are deleted
  258. deleteGroup _group;
  259. };
  260.  
  261.  
  262. _fnc_spawnUnit = {
  263. // We need to pass the old group so we can copy waypoints from it, the rest we already know
  264. _oldGroup = _this select 0;
  265. _newGroup = createGroup (_this select 1);
  266. _waypointsArray = _this select 2;
  267. // If the old group doesnt have any units in it its a spawned group rather than respawned
  268. if ( count (units _oldGroup) == 0) then { deleteGroup _oldGroup; };
  269. {
  270. _spawnUnit = null;
  271. _unitType = _x select 0; _unitPos = _x select 1; _unitDir = _x select 2;
  272. _unitName = _x select 3; _unitSkill = _x select 4; _unitRank = _x select 5;
  273. _unitCrew = _x select 6;
  274. // New A3 related gear
  275. _unitWeapons = _x select 7; _unitItems = _x select 8;
  276. _unitUniform = _x select 9; _unitUniformItems = _x select 10;
  277. _unitVest = _x select 11; _unitVestItems = _x select 12;
  278. _unitBackpack = _x select 13; _unitBackpackItems = _x select 14;
  279. _unitHeadgear = _x select 15; _unitGoggles = _x select 16;
  280. // Check if the unit has a crew, if so we know its a vehicle
  281. if (count _unitCrew > 0) then {
  282. if (_unitPos select 2 >= 10) then {
  283. _spawnUnit = createVehicle [_unitType,_unitPos, [], 0, "FLY"];
  284. _spawnUnit setVelocity [50 * (sin _unitDir), 50 * (cos _unitDir), 0];
  285. }
  286. else { _spawnUnit = _unitType createVehicle _unitPos; };
  287. // Create the entire crew
  288. _crew = [];
  289. { _unit = _newGroup createUnit [_x, getPos _spawnUnit, [], 0, "NONE"]; _crew set [count _crew, _unit]; } forEach _unitCrew;
  290. // We assume that all vehicles have a driver, the first one of the crew
  291. (_crew select 0) moveInDriver _spawnUnit;
  292. // Count the turrets and move the men inside
  293. _turrets = [configFile >> "CfgVehicles" >> _unitType >> "turrets"] call _fnc_returnVehicleTurrets;
  294. [_turrets, [], 1, _crew, _spawnUnit] call _fnc_moveInTurrets;
  295. }
  296. // Otherwise its infantry
  297. else {
  298. _spawnUnit = _newGroup createUnit [_unitType,_unitPos, [], 0, "NONE"];
  299. removeAllWeapons _spawnUnit;
  300. removeAllItems _spawnUnit;
  301. removeAllAssignedItems _spawnUnit;
  302. removeUniform _spawnUnit;
  303. removeVest _spawnUnit;
  304. removeBackpack _spawnUnit;
  305. removeHeadgear _spawnUnit;
  306. removeGoggles _spawnUnit;
  307.  
  308. _spawnUnit forceAddUniform _unitUniform;
  309. {_spawnUnit addItemToUniform _x} forEach _unitUniformItems;
  310.  
  311. _spawnUnit addVest _unitVest;
  312. {_spawnUnit addItemToVest _x} forEach _unitVestItems;
  313.  
  314. _spawnUnit addBackpack _unitBackpack;
  315. {_spawnUnit addItemToBackpack _x} forEach _unitBackpackItems;
  316.  
  317. _spawnUnit addHeadgear _unitHeadgear;
  318. _spawnUnit addGoggles _unitGoggles;
  319. {_spawnUnit linkItem _x} forEach _unitItems;
  320.  
  321. {_spawnUnit addWeapon _x} forEach _unitWeapons;
  322. _spawnUnit selectWeapon (primaryWeapon _spawnUnit);
  323. };
  324. // Set all the things common to the spawned unit
  325. _spawnUnit setDir _unitDir;
  326. _spawnUnit setSkill _unitSkill;
  327. _spawnUnit setUnitRank _unitRank;
  328. if (!isNil _unitName AND (_spawntype == "once" OR _spawntype == "repeated")) then {
  329. diag_log _unitName;
  330. _spawnUnit call compile format ["%1= _this; _this setVehicleVarName '%1'; PublicVariable '%1';",_unitName];
  331. };
  332. } forEach _unitArray;
  333.  
  334. private ["_i"]; _i = 0;
  335.  
  336. //Let's return them their waypoints
  337. {
  338. //diag_log format ["All data : %1",_x];
  339. _wp = _newGroup addWaypoint [(_x select 0),0,_i];
  340. [_newGroup, _i] setWaypointHousePosition (_x select 1);
  341. [_newGroup, _i] setWaypointBehaviour (_x select 2);
  342. [_newGroup, _i] setWaypointCombatMode (_x select 3);
  343. [_newGroup, _i] setWaypointCompletionRadius (_x select 4);
  344. [_newGroup, _i] setWaypointDescription (_x select 5);
  345. [_newGroup, _i] setWaypointFormation (_x select 6);
  346. [_newGroup, _i] setWaypointScript (_x select 7);
  347. [_newGroup, _i] showWaypoint (_x select 8);
  348. [_newGroup, _i] setWaypointSpeed (_x select 9);
  349. [_newGroup, _i] setWaypointStatements (_x select 10);
  350. [_newGroup, _i] setWaypointTimeout (_x select 11);
  351. [_newGroup, _i] setWaypointType (_x select 12);
  352.  
  353. _i = _i + 1;
  354.  
  355. } forEach _waypointsArray;
  356.  
  357. (vehicle (leader _newGroup)) call compile format ["%1",_initString];
  358.  
  359. // hint format ["Created object: %1 - vehicleVarName: %2", (vehicle (leader _newGroup)), vehicleVarName (vehicle (leader _newGroup))]; sleep 1;
  360.  
  361. // Run the cleanup function for this group
  362. [_newGroup, _bodyRemove] spawn _fnc_cleanGroup;
  363.  
  364. // Have to return the new group
  365. _newGroup;
  366. };
  367.  
  368. // -------------- Waiting period ------------------ //
  369. while { !(_triggerObject getVariable "murk_spawn") } do { sleep _waitingPeriod; };
  370.  
  371. //hint "Triggered spawn!";
  372.  
  373. // --------------- Spawn Modes ------------------- //
  374. // REPEAT MODE, i.e. basic respawn based on lives
  375. if (_spawntype == "repeated") then {
  376. while { _spawnlives > 0 } do {
  377. _unitGroup = [_unitGroup,_side,_waypointsArray] call _fnc_spawnUnit;
  378. _spawnLives = _spawnLives - 1;
  379. _unitsGroup = units _unitGroup;
  380. while { ({alive _x} count _unitsGroup) > 0 } do { sleep 2; };
  381. sleep _spawndelay;
  382. };
  383. };
  384.  
  385. // WAVE MODE, this is fairly simple, just sleep a while then respawn. Spawnlives in this case is number of waves
  386. if (_spawntype == "wave") then {
  387. while { _spawnlives > 0 } do {
  388. _unitGroup = [_unitGroup,_side,_waypointsArray] call _fnc_spawnUnit;
  389. _spawnLives = _spawnLives - 1;
  390. sleep _spawndelay;
  391. };
  392. };
  393.  
  394. // RESET MODE, sleep a while then set the variable to false (even if you set it like 50 times over). Spawn lives is used to tick how many times its possible to reset.
  395. if (_spawntype == "reset") then {
  396. while { _spawnlives > 0 } do {
  397. _unitGroup = [_unitGroup,_side,_waypointsArray] call _fnc_spawnUnit;
  398. _spawnLives = _spawnLives - 1;
  399. sleep 15;
  400. _triggerObject setVariable ["murk_spawn",false,false];
  401. while { !(_triggerObject getVariable "murk_spawn") } do { sleep _waitingPeriod; };
  402. };
  403. };
  404.  
  405. // ONCE MODE
  406. if (_spawntype == "once") then { _unitGroup = [_unitGroup,_side,_waypointsArray] call _fnc_spawnUnit; };
  407.  
  408. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement