dklollol / Olsen-Framework

0 stars 2 forks source link

[Feature request] intergrating Naughts Unitcaching #13

Open perfk opened 10 years ago

perfk commented 10 years ago

An easy way to intergrate Naughs http://forums.unitedoperations.net/index.php/topic/21527-ai-caching-and-distribution-script/

perfk commented 10 years ago

And if the above fails. then something like "murk´s"

// File: murk_spawn.sqf // 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. // The script also captures mission, so it can be loaded with murk_spawn_loaded.sqf. // Parameters: // _this select 0: OBJECT - unit name (this) // _this select 1: STRING - trigger name // _this select 2: STRING - spawn type ("once","repeated","wave" and "reset") // _this select 3 (optional): NUMBER - spawn lives (the amount of time the unit respawns, or wave number) // _this select 4 (optional): NUMBER - spawn delay // _this select 5 (optional): STRING - init string called for the leader of the group // _this select 6 (optional): NUMBER- will start removal sequence of all dead group members after X seconds (default 120)

// === Usage: === // Example trigger: Anybody Once (or whatever you want), onActivation: catch_trigger = "triggername"; publicVariable "catch_trigger"; // Unit (leader of group): nul = [this,"triggername","SPAWNTYPE",LIVES,DELAY] execVM "murk_spawn.sqf"; //
// Example: nul = [this,"triggername","once"] execVM "murk_spawn.sqf"; ---- Will spawn the editor unit once based on the trigger // Example: nul = [this,"triggername","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 // Example: nul = [this,"triggername","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 // Example: nul = [this,"triggername","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. // ----------------------------------------------------------------------------------------------------- // // V8 (ArmAIIholic) // - Waypoints are also remembered -- no dummy groups at all!!! // - You get the output on Clipboard you can paste and execute. Added loader for Clipboard missions. // V7 (ArmAIIholic) // - Added GameLogic center to reduce number of dummy groups at the beginning, and in modes repeated and reset // - Changed beginning scope to isServer, rather than using exitWith // - Shortened initializing trigger part in init.sqf // - Added original instructions and examples, adapted for v7 // - SQM is from v5 with some groups added // V6 - Dedicated to Xeno, for his advice // - Fix: Performance/effiency optimizations across the board // - Shortened parameters // - Improved group cleanup, units in groups are now always deleted so that the group can be deleted // - New type of unit cleanup, no longer spawns eventhandlers for each unit // - Better array usage, no more additions over multiple arrays // - Moved the internal turret crew function out // - Further attempt to make vehicle/infantry storage and recreation more similar in order to cut code // - Fix: Now supports mixed infantry and vehicle groups // V5 // - Change: Removed group and function scripts, everything done in a single file // - Change: Spawn trigger variable is now a setVariable of the trigger instead of a global variable // - Add: Option to enable removal of dead units, eventhandler attached to everyone spawning // - Fix: Should now work in multiplayer on a dedicated server (only tested on a local dedicated/join setup however) // - Fix: Performance issues with helos from V4 resolved // - Fix: Some minor bugs with the optional parameters // - Fix: Now properly support crews in turrets-on-turrets (had to bring in some BIS made functions) // V4 // - See older versions

// This script is serverside if(isServer) then {

// ------------------- Init ----------------------- // _countThis = count _this;

// ---------------- Parameters -------------------- // _unit = _this select 0; _trigger = _this select 1; _spawntype = _this select 2; _spawnlives = if (_countThis >= 4) then { _this select 3; } else { 1 }; // Optional _spawndelay = if (_countThis >= 5) then { _this select 4; } else { 1 }; // Optional _initString = if (_countThis >= 6) then { _this select 5; } else { "" }; // Optional _bodyRemove = if (_countThis >= 7) then { _this select 6; } else { 120 }; // Optional

// -- Delete the unit (this is always done ASAP) -- // _unitArray = []; _unitGroup = group _unit; _unitsInGroup = units _unitGroup; _unitCount = count _unitsInGroup; _unitsInGroupAdd = []; _side = side _unitGroup;

while { _unitCount > 0 } do { // The currently worked on unit _unitsInGroup = units _unitGroup; _unit = _unitsInGroup select 0; _unitCount = count _unitsInGroup; // Check if its a vehicle if ( (vehicle _unit) isKindOf "LandVehicle" OR (vehicle _unit) isKindOf "Air") then { _vcl = vehicle _unit; if (!(_vcl in _unitsInGroupAdd) AND (typeOf _vcl != "")) then { _unitsIngroupAdd set [count _unitsInGroupAdd, _vcl]; _unitCrewArray = []; _crew = crew _vcl; { _unitCrewArray set [count _unitCrewArray, typeOf _x]; } forEach _crew; _unitInfoArray = [typeOf _vcl,getPos _vcl,getDir _vcl,vehicleVarName _vcl,skill _vcl,rank _vcl,weapons _vcl,magazines _vcl,_unitCrewArray]; _unitArray set [count _unitArray, _unitInfoArray]; deleteVehicle _vcl; { deleteVehicle _x; } forEach _crew; }; } // Otherwise its infantry else { _unitInfoArray = [typeOf _unit,getPos _unit,getDir _unit,vehicleVarName _unit,skill _unit,rank _unit,weapons _unit,magazines _unit,[]]; _unitArray set [count _unitArray, _unitInfoArray]; deleteVehicle _unit; }; sleep 0.01; };

// Gathering waypoints _countWaypoints = 0; _waypointsArray = []; _waypointsEntry = [];

_countWaypoints = count(waypoints _unitGroup);

for [{_i=0}, {_i < _countWaypoints}, {_i=_i+1}] do { _waypointsEntry = [];

_wPos = waypointPosition [_unitGroup, _i];
_wHPos = waypointHousePosition [_unitGroup, _i];
_wBih = waypointBehaviour [_unitGroup, _i];
_wCM = waypointCombatMode [_unitGroup, _i];
_wCR = waypointCompletionRadius [_unitGroup, _i];
_wDes = waypointDescription [_unitGroup, _i];
_wForm = waypointFormation [_unitGroup, _i];
_wScr = waypointScript [_unitGroup, _i];
_wShw = waypointShow [_unitGroup, _i];
_wSp = waypointSpeed [_unitGroup, _i];
_wSt = waypointStatements [_unitGroup, _i]; //diag_log _wSt;
_wTo = waypointTimeout [_unitGroup, _i];
_wTy = waypointType [_unitGroup, _i];

_waypointsEntry = _waypointsEntry + [_wPos] + [_wHPos] + [_wBih] + [_wCM] + [_wCR] + [_wDes] + [_wForm] + [_wScr] + [_wShw] + [_wSp] + [_wSt] + [_wTo] + [_wTy];

_waypointsArray = _waypointsArray + [_waypointsEntry];

};

//diag_log format ["Waypoints' array : %1",_waypointsArray];

deleteGroup _unitGroup;

// -------------- Record mission ------------------ //

_gatherData = [];

_gatherData = _gatherData + [_unitArray] + [_side] + [_waypointsArray] + [_trigger] + [_spawntype] + [_spawnlives] + [_spawndelay] + [_initString] + [_bodyRemove];

Mission_capture = Mission_capture + [_gatherData];

// ----------------- Functions -------------------- //

// WARNING BIS FUNCTION RIPOFF - Taken from fn_returnConfigEntry as its needed for turrets and shortened a bit _fnc_returnConfigEntry = { private ["_config", "_entryName","_entry", "_value"]; _config = _this select 0; _entryName = _this select 1; _entry = _config >> _entryName; //If the entry is not found and we are not yet at the config root, explore the class' parent. if (((configName (_config >> _entryName)) == "") && (!((configName _config) in ["CfgVehicles", "CfgWeapons", ""]))) then { [inheritsFrom _config, _entryName] call _fnc_returnConfigEntry; } else { if (isNumber _entry) then { _value = getNumber _entry; } else { if (isText _entry) then { _value = getText _entry; }; }; }; //Make sure returning 'nil' works. if (isNil "_value") exitWith {nil}; _value; };

// WARNING BIS FUNCTION RIPOFF - Taken from fn_fnc_returnVehicleTurrets and shortened a bit _fnc_returnVehicleTurrets = { private ["_entry","_turrets", "_turretIndex"]; _entry = _this select 0; _turrets = []; _turretIndex = 0; //Explore all turrets and sub-turrets recursively. for "_i" from 0 to ((count _entry) - 1) do { private ["_subEntry"]; _subEntry = _entry select _i; if (isClass _subEntry) then { private ["_hasGunner"]; _hasGunner = [_subEntry, "hasGunner"] call _fnc_returnConfigEntry; //Make sure the entry was found. if (!(isNil "_hasGunner")) then { if (_hasGunner == 1) then { _turrets = _turrets + [_turretIndex];
//Include sub-turrets, if present. if (isClass (_subEntry >> "Turrets")) then { _turrets = _turrets + [[_subEntry >> "Turrets"] call _fnc_returnVehicleTurrets]; } else { _turrets = _turrets + [[]]; }; }; }; _turretIndex = _turretIndex + 1; }; }; _turrets; };

_fnc_moveInTurrets = {
private ["_turrets","_path","_i"]; _turrets = _this select 0; _path = _this select 1; _currentCrewMember = _this select 2; _crew = _this select 3; _spawnUnit = _this select 4; _i = 0;
while {_i < (count _turrets)} do { _turretIndex = _turrets select _i; _thisTurret = _path + [_turretIndex]; (_crew select _currentCrewMember) moveInTurret [_spawnUnit, _thisTurret]; _currentCrewMember = _currentCrewMember + 1; //Spawn units into subturrets. [_turrets select (_i + 1), _thisTurret, _currentCrewmember, _crew, _spawnUnit] call _fnc_moveInTurrets; _i = _i + 2; }; };

// This is the general cleanup function running in the background for the group, replaces the removebody eventhandler and delete group in V5 _fnc_cleanGroup = { _group = _this select 0; _unitsGroup = units _group; _sleep = _this select 1; // Hold until the entire group is dead while { ({alive _x} count _unitsGroup) > 0 } do { sleep 5; }; sleep _sleep; { _origPos = getPos _x; _z = _origPos select 2; _desiredPosZ = if ( (vehicle _x) iskindOf "Man") then { (_origPos select 2) - 0.5 } else { (_origPos select 2) - 3 }; if ( vehicle _x == _x ) then { _x enableSimulation false; while { _z > _desiredPosZ } do { _z = _z - 0.01; _x setPos [_origPos select 0, _origPos select 1, _z]; sleep 0.1; }; }; deleteVehicle _x; sleep 5; } forEach _unitsGroup;
// Now we know that all units are deleted deleteGroup _group; };

_fnc_spawnUnit = { // We need to pass the old group so we can copy waypoints from it, the rest we already know _oldGroup = _this select 0; _newGroup = createGroup (_this select 1); _waypointsArray = _this select 2; // If the old group doesnt have any units in it its a spawned group rather than respawned if ( count (units _oldGroup) == 0) then { deleteGroup _oldGroup; }; { _spawnUnit = Object; _unitType = _x select 0; _unitPos = _x select 1; _unitDir = _x select 2; _unitName = _x select 3; _unitSkill = _x select 4; _unitRank = _x select 5; _unitWeapons = _x select 6; _unitMagazines = _x select 7; _unitCrew = _x select 8; // Check if the unit has a crew, if so we know its a vehicle if (count _unitCrew > 0) then { if (_unitPos select 2 >= 10) then { _spawnUnit = createVehicle [_unitType,_unitPos, [], 0, "FLY"]; _spawnUnit setVelocity [50 * (sin _unitDir), 50 * (cos _unitDir), 0]; } else { _spawnUnit = _unitType createVehicle _unitPos; }; // Create the entire crew _crew = []; { _unit = _newGroup createUnit [_x, getPos _spawnUnit, [], 0, "NONE"]; _crew set [count _crew, _unit]; } forEach _unitCrew; // We assume that all vehicles have a driver, the first one of the crew (_crew select 0) moveInDriver _spawnUnit; // Count the turrets and move the men inside
_turrets = [configFile >> "CfgVehicles" >> _unitType >> "turrets"] call _fnc_returnVehicleTurrets; [_turrets, [], 1, _crew, _spawnUnit] call _fnc_moveInTurrets;
} // Otherwise its infantry else { _spawnUnit = _newGroup createUnit [_unitType,_unitPos, [], 0, "NONE"]; removeAllWeapons _spawnUnit; {_spawnUnit removeMagazine _x} forEach magazines _spawnUnit; removeAllItems _spawnUnit; {_spawnUnit addMagazine _x} forEach _unitMagazines; {_spawnUnit addWeapon _x} forEach _unitWeapons; _spawnUnit selectWeapon (primaryWeapon _spawnUnit); }; // Set all the things common to the spawned unit _spawnUnit setDir _unitDir; _spawnUnit setSkill _unitSkill; _spawnUnit setUnitRank _unitRank; if (_spawntype == "once" OR _spawntype == "repeated") then { _spawnUnit setVehicleVarName _unitName; if (vehiclevarname _spawnUnit != "") then { _spawnUnit setVehicleInit format["%1=this;",_unitName]; processInitCommands; }; }; } forEach _unitArray;

private ["_i"]; _i = 0;

//Let's return them their waypoints
{
    //diag_log format ["All data : %1",_x];
    _wp = _newGroup addWaypoint [(_x select 0),0,_i];
    [_newGroup, _i] setWaypointHousePosition (_x select 1); 
    [_newGroup, _i] setWaypointBehaviour (_x select 2);
    [_newGroup, _i] setWaypointCombatMode (_x select 3);
    [_newGroup, _i] setWaypointCompletionRadius (_x select 4);
    [_newGroup, _i] setWaypointDescription (_x select 5);
    [_newGroup, _i] setWaypointFormation (_x select 6);
    [_newGroup, _i] setWaypointScript (_x select 7);
    [_newGroup, _i] showWaypoint (_x select 8);
    [_newGroup, _i] setWaypointSpeed (_x select 9);
    [_newGroup, _i] setWaypointStatements (_x select 10);
    [_newGroup, _i] setWaypointTimeout (_x select 11);
    [_newGroup, _i] setWaypointType (_x select 12);

    _i = _i + 1;

} forEach _waypointsArray;

// Setting the leaders init and the groups body removal time
(vehicle (leader _newGroup)) setVehicleInit _initString; processInitCommands;
// Run the cleanup function for this group
[_newGroup, _bodyRemove] spawn _fnc_cleanGroup;

// Have to return the new group
_newGroup;

};

//diag_log format ["Number of groups : %1",(count allGroups)];

// -------------- Waiting period ------------------ // waitUntil { _trigger == catch_trigger };

// --------------- Spawn Modes ------------------- // // REPEAT MODE, i.e. basic respawn based on lives if (_spawntype == "repeated") then { while { _spawnlives > 0 } do { _unitGroup = [_unitGroup,_side,_waypointsArray] call _fnc_spawnUnit; _spawnLives = _spawnLives - 1; _unitsGroup = units _unitGroup; while { ({alive _x} count _unitsGroup) > 0 } do { sleep 2; }; sleep _spawndelay; }; };

// WAVE MODE, this is fairly simple, just sleep a while then respawn. Spawnlives in this case is number of waves if (_spawntype == "wave") then { while { _spawnlives > 0 } do { _unitGroup = [_unitGroup,_side,_waypointsArray] call _fnc_spawnUnit; _spawnLives = _spawnLives - 1; sleep _spawndelay; }; };

// 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. if (_spawntype == "reset") then { while { _spawnlives > 0 } do { _unitGroup = [_unitGroup,_side,_waypointsArray] call _fnc_spawnUnit; _spawnLives = _spawnLives - 1; sleep 15; catch_trigger = "none"; waitUntil {_trigger == catch_trigger}; }; };

// ONCE MODE if (_spawntype == "once") then { _unitGroup = [_unitGroup,_side,_waypointsArray] call _fnc_spawnUnit; };

};