Jump to content

Recommended Posts

                                                                                               AI INFANTRY RESPAWN SP/MP

 

Hi all,

Here is a script to allow AIs respawning according to parameters. This works in SP or MP.

Only infantry (on foot AI) concerned as far as the killed AIs while in vehicles is the object of a second script.

 

parameters:   SIDES  /  POSITIONS /   DELAY   /   MIN UNITS IN GROUPS  /   REMAINING LOADOUT

Spoiler

 

[

  <array of side>, //    example:  [WEST,EAST,RESISTANCE,CIVILIAN]                         (optional)    default: [WEST] - only these sides can respawn

  <string or array if string for respawn position>,  // examples: "marker1" or ["start","mk1",""].   (optional)   default:  "start"
                                                 you need one option for each side, so:

                                                 If more sides, completed by "start" for all remaining declared sides.
                                                 ([west,east,resistance] and ["mk1"] or "mk1" give... ["mk1","start","start"] )

                                                 if this string is a marker name, this position is chosen,

                                                 or "start" (not a marker name) gives the positions of units at start,

                                                 or "death", "", any unused string, gives the position of death for each unit,

  <number, seconds (minimum) before respawn>,  // example: 15                                             (optional)           default: 10

                                                takes 15 seconds to respawn a unit after death if the parameter to follow (min unit in groups)  allows that,

  <number, minimum for remaining AIs before regenerating the group>, // example: 3  (optional)  default: 144 (any whole group, so disabled feature)

                                                if nil or not defined, the units respawns without other delay than the previous parameter,

                                                same for any number above the group headcount (at start),

                                                the number defines the minimum remaining souls in any group, before the units can respawn (delay after death can apply if ongoing).

  <boolean, respawn with same loadout than when died>          // example: true                       (optional)          default: false

                                                the magazines are decreasing if set to true, there is no automatic rearming

                                                by default (false), the units recover their initial loadout

]

 

 

 

Examples:

[] spawn MGI_fnc_unitRespawn       //   [] passed  as parameter  equals to [ [WEST,EAST,RESISTANCE,CIVILIAN], "start", 10, 144, false]

                    All ai units can respawn on their position at start, after 10 sec delay, with their initial loadout.

 

[ [WEST,EAST], ["mrk1","death","start",""], nil, 3 ] spawn MGI_fnc_unitRespawn      //    equals to [ [WEST,EAST], ["mrk1","death"], 15, 3, false]

                   here, only WEST & EAST ai units can respawn:

                       - on the marker "mk1" if any, on death position if not, for BLUFOR

                       - on the position of death for OPFOR,

                  (other strings in positions array are useless), 10 second delay (default), if their group headcount is below 3 (delay already started at death), with their initial loadout.

                        


Code to be run on server. (trigger, server only, non-repeatable, condition true)   or initServer.sqf
 

Spoiler

 


MGI_fnc_unitRespawn = {
  if (!isServer && hasInterface) exitWith {};
  params [["_sides",[WEST,EAST,RESISTANCE,CIVILIAN],[[WEST]],[]],["_positions","start",["",["","","",""]],[]],["_delay",10,[0]],["_waitForGrp",144,[0]],["_existingLO",false,[true]]];
  private ["_pos","_positionArray"];
  MGIrespDelay = _delay max 2;
  MGIwaitForGrp = _waitForGrp;
  MGIexistingLO = _existingLO;

  fn_pos = {
    params ["_position","_pos"];
    call {
      if !(getMarkerPos _position isEqualTo [0,0,0]) exitWith {_pos = getMarkerPos _position};
      if (_position == "start") exitWith {_pos = getPos _x};
        _pos = [0,0,0];
     };
    _pos
  };

  if (_positions isEqualType "") then { _positions = [_positions]};
  if (_positions isEqualType []) then {
    _nbrSide = count _sides;
    _nbrPos = count _positions;
    if (_nbrPos < _nbrSide) then {
      for "_i" from 0 to (_nbrSide - _nbrPos - 1) do {
        _positions pushback "start";
      };
    };
  };

  _positionArray = [];
  for "_i" from 0 to count _sides - 1 do {
    _positionArray pushback (_sides select _i);
    _positionArray pushback (_positions select _i);
  };

  while {true} do {
    sleep 1;
    _allUnits = allUnits select {isnull objectParent _x && !isplayer _x && local _x};
    {
      if (!(_x getVariable ["MGIrespOK",false]) && (side _x in _sides)) then {
        _side = side _x;
        _position = _positionArray select ((_positionArray find _side) + 1);
        _pos = _position call fn_pos;
        _oldGrp = group _x;
        if (isnil {_oldGrp getVariable ["_squadNbr", nil]}) then {
          _oldGrp setVariable ["_squadNbr", count units _oldGrp]
        };
        _x setVariable ["MGIrespDATA",[typeOf _x ,_pos, side _x, getdir _x, _oldGrp,_oldGrp getVariable "_squadNbr"]];
        if !(MGIexistingLO) then {
          _x setVariable ["MGIloadout",getUnitLoadout _x]
        };
        _x setVariable ["MGIrespOK",true];
      };
    } foreach _allUnits;
  };
};


addMissionEventHandler ["entityKilled",{
  _killed = _this select 0;
  if (_killed getVariable ["MGIrespOK",false]) then {
    _killed spawn {
      private "_loadout";
      _killed = _this;
      _type = (_killed getVariable "MGIrespDATA") select 0;
      _pos = (_killed getVariable "MGIrespDATA") select 1;
      _side = (_killed getVariable "MGIrespDATA") select 2;
      _dir = (_killed getVariable "MGIrespDATA") select 3;
      _oldGrp = (_killed getVariable "MGIrespDATA") select 4;
      _squadNbr = (_killed getVariable "MGIrespDATA") select 5;
      if (MGIexistingLO) then {_loadout = getUnitLoadout _killed};
      if !(MGIexistingLO) then {_loadout = _killed getVariable "MGIloadout"};
      if (_pos isEqualTo [0,0,0]) then {_pos = getpos _killed};
      sleep MGIrespDelay;
      waitUntil {({alive _x} count units _oldGrp < (MGIwaitForGrp min _squadNbr)) or (_oldGrp getVariable ["fillIt",false])};
      _newbie = _oldGrp createUnit [_type, _pos, [],0,"CAN_COLLIDE"];
      _newbie setDir _dir;
      _oldGrp setVariable ["fillIt", true];
      if (({alive _x} count units _oldGrp == _squadNbr)) then {
        _oldGrp setVariable ["fillIt", false]
      };
      _newbie setUnitLoadout _loadout;
      sleep (MGIrespDelay +0.1);
      _killed setVariable ["MGIrespDATA",nil];
      _killed setVariable ["MGIrespOK",nil];
       deleteVehicle _killed;
    };
  };
}];

[[WEST,EAST,RESISTANCE,CIVILIAN],"start",15,3,true] spawn MGI_fnc_unitRespawn;  // example

 

 

 

 

  • Like 5
  • Thanks 1

Share this post


Link to post
Share on other sites

Just been trying this respawn function out. That is one incredibly compact and clever bit of code !

Edited by Mike Goode

Share this post


Link to post
Share on other sites

I can't for the life of me figure out how to make it work.. I've set up a server only, condition true, non repeatable trigger with the script in it's init, but when i go to test it by hosting a lan server and zeus bolting an AI soldier he still spawns in one of 4 respawn_west markers i've set up on different parts of the map.. any thoughts?

a really simplified visual example of pretty much what i'm trying to do:  s4nq6a.jpg

Share this post


Link to post
Share on other sites

In your picture, I understand you don't have specific groups, but rather some units inside areas at start.

 

you just have to run:

[[WEST],"start",15,nil,true] spawn MGI_fnc_unitRespawn;

All west units will respawn at their initial position.

If you need more conditions, you can add them in this line:

_allUnits = allUnits select {isnull objectParent _x && !isplayer _x && local _x};

 

 

 

Share this post


Link to post
Share on other sites

Nice release!

Although I'm confused on line 3 of your code:

why the strings for expectedArrayCount? Can't this be just a number and call it quits?

Regardless, this'll be useful in the future. Excellent work.

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

×