Jump to content

Recommended Posts

   AI REVIVE/HEAL SP/MP

 

Last update 10th/09/2018

 

Hi all,

Here is a script to allow AIs reviving and healing bros, according to parameters. This works in SP or MP.

Compatible so far with AI RESPAWN script (see tag)
Don't override the respawn system (MP)

Incapacitation: This script relies on incapacitated status for players or AIs. This status is created when not existing (SP, or MP Ais) to allow revive scenario.

 

parameters:   REACT  /  HEAL DELAY  /   AI CAN REVIVE   /  KIT NEEDED  /   NEED MEDIC / BROS

 

Parameters can be added to description.ext, class Params, just add what you want in classes: "react" "bleedOut" "noReviveForAI" "AiKit" "AiMedic" "bros".

So you can choose them while in lobby. Anyway, if you pass parameters calling the function, these params will override the lobby ones.

 

Spoiler

 

[

  <REACT: number, seconds (max) to choose the best healer>, //    example: 15  (optional)  default: 120

                                                 During this time, the script tries to find the best healer according to some priorities:

                                                 not in combat, not targeting, a medic, any bro within 200 m (if any according to other parameters)

  <HEAL DELAY: number, seconds (max) to heal action, remaining bleedout>,  //    example: 60  (optional)  default: 120
                                                 This amount of time is added to the first one. So, healer found or not, this is the remaining time before death unless be revived.

  <AI CAN REVIVE, boolean>,  // example: true                                            (optional)           default: true

                                                In SP/MP, if false, the AI can't revive but can heal the player (incapacitated).

                                                Note that AIs playable units can respawn in MP (Arma engine)

  <KIT: number, what kind of kit is needed to revive someone>, // example: 0  (optional)  default: 0

                                                0: no kit needed, no limit for revive

                                                1: need a first aid kit (FAK) , 1 FAK is removed per reviving action

                                                2: need a medic kit (mediKit) , 1 FAK is removed per reviving action, can heal even if no more FAK

  <NEED MEDIC: boolean, Medic trait mandatory>          // example: true                       (optional)          default: false

                                                When true, this limits drastically the chance to be revived.

  

 <BROS: side, or array of units>, // example: west  (optional)  default: playableUnits + switchableUnits

                                                Just decide who can be healed and revive. The default param works in SP/MP

                                                some custom arrays are working fine also: [blu1,blu2,indep1,indep2] or allUnits select {_x inArea some trigger && side _x == WEST}

                                                You can mix several sides but it's weird to make enemies as bros, with never ending shoot/heal loops!

                             

]

 

 

Note: You can add any unit in "bros" team, just setting a variable: yourUnit (or cursorTarget)  setVariable ["passedBros",true,true];

 

Examples:

call MGI_fnc_AICareandRevive       //   parameters are default ones, or defined by your description.ext

[30,60,true,0,false,west] call MGI_fnc_AICareandRevive;     //    this will override the MP parameters chosen in lobby! Better usage for SP

               

 

Code must run on all PCs. So, init.sqf, (trigger, non-repeatable, condition true)...


 

Spoiler

 


MGI_fn_medic = compileFinal "
  _wnded = _this;
  private '_medic';
  _wnded setVariable ['myMedic',nil,true];
  private _medics = MGI_potentialMedic select {
    _x distanceSqr _wnded < 40000
    && !isPlayer _x
    && _x != _wnded
    && alive _x
    && lifeState _x != 'incapacitated'
    && isNil {_x getVariable 'myPatient'}
  };
  call {
    if (isPlayer _wnded) exitWith {
      _medics
    };
    if ({behaviour _x != 'COMBAT'} count _medics > 0) exitWith {
      uiSleep (MGI_react/8);
      _medics = _medics select {behaviour _x != 'COMBAT'};
    };
    if ({(_x targets [true, 300]) isEqualTo []} count _medics > 0) exitWith {
      uiSleep (MGI_react/4);
      _medics = _medics select {(_x targets [true, 300]) isEqualTo []};
    };
    if ({{_x == 'MediKit'} count (items _x) > 0} count _medics > 0) exitWith {
      uiSleep MGI_react/2;
      _medics = _medics select {{_x == 'MediKit'} count (items _x) > 0};
    };
    uiSleep MGI_react;
    _medics;
  };
  _medics = +_medics select {
    _x distanceSqr _wnded < 40000
    && !isPlayer _x
    && _x != _wnded
    && alive _x
    && lifeState _x != 'incapacitated'
    && isNil {_x getVariable 'myPatient'}
  };
  if (count _medics == 0) exitWith {
    _medic = objNull;
    _medic
  };
  _medics = +_medics apply {[str(leader _x == _x),_x distance _wnded, _x]};
  _medics sort true;
  _medic = _medics select 0 select 2;
  _medic setHitPointDamage ['hitLegs',0];
  _medic setVariable ['myPatient',_wnded,true];
  _wnded setVariable ['myMedic',_medic,true];
  if (count units _medic > 1) then {
    _medic setVariable ['MGI_AIgrp',group _medic,true];
  };
  _medic setVariable ['flee',_medic skill 'courage',true];
  _medic
";

MGI_fn_medicRelease = compileFinal "
  _medic = _this;
  (_medic getVariable ['myMedic',objNull]) setVariable ['myMedic',nil,true];
  _medic setVariable ['myPatient',nil,true];
  _medic allowFleeing (1 - (_medic getVariable ['flee',0.5]));
  {_medic enableAI _x} count ['target','autotarget','autocombat','suppression'];
  _medic setBehaviour 'AWARE';
  [_medic] joinSilent (_medic getVariable 'MGI_AIgrp');
  [_medic,leader _medic] remoteExec ['doFollow',_medic];
  _medic spawn {
    _medic = _this;
    uiSleep 12;
    if (lifeState _medic != 'incapacitated' && isNil {_medic getVariable 'myPatient'}) then {_medic setCaptive false};
  };
";

MGI_fn_checkMedic = compileFinal "
  params [['_wnded',objNull],['_medic',objNull],'_timer'];
  uiSleep 2;
  {_check = _x; if (!isnil {_check getVariable 'myPatient'} && {_x getVariable 'myMedic' == _check} count MGI_bros  == 0) then {_check setVariable ['myPatient',nil,true]} } forEach MGI_bros;
  while {lifeState _wnded == 'incapacitated'} do {
    call {
      if (isnil '_medic' or isnil {_wnded getVariable 'myMedic'}) exitWith {
        _wnded call MGI_fn_medic;
      };
      if (isnull (_wnded getVariable 'myMedic')) exitWith {
        _medic setVariable ['myPatient',nil,true];
        _wnded call MGI_fn_medic
      };
      if (lifeState _medic == 'incapacitated'
         or isNil {_medic getVariable 'myPatient'}) exitWith {
        _medic call MGI_fn_medicRelease;
        _wnded call MGI_fn_medic;
      };
      if (_wnded distance2D _medic < 3 or (_wnded distance2D _medic >3 && unitReady _medic)) exitWith {
        [_wnded,_medic,_timer] spawn {
          params ['_wnded','_medic','_timer'];
        if (_wnded distanceSqr _medic > 9) then {
          waitUntil {sleep 0.5; unitReady _medic};
          _medic doMove getPosATL _wnded;
          uiSleep 3;
        };
        [_wnded,_medic,_timer] call MGI_fn_sortie;
      };
      };
    };
    uiSleep 1;
  };
  _medic call MGI_fn_medicRelease;
  _wnded setVariable ['myMedic',nil,true];
  if (_wnded getVariable ['uncsious',false]) then {
    _wnded setVariable ['uncsious',false,true];
  };
";

MGI_fn_911 = compileFinal "
  params ['_wnded','_medic','_timer'];
  [_wnded,_medic,_timer] spawn MGI_fn_checkMedic;
  _medic setCaptive true;
  [_medic] joinSilent grpNull;
  {_medic disableAI _x} count ['target','autotarget','autocombat','suppression'];
  group _medic setBehaviour 'CARELESS';
  _medic allowFleeing 0;
  _offset = [[0,0],[15, _wnded getRelDir _medic]] select (!isNull objectParent _medic);
  if (!isnull objectParent _medic) then {
    _medic setVariable ['veh',vehicle _medic,true];
    if !(_medic in [assignedDriver vehicle _medic,assignedGunner vehicle _medic]) then {
      unassignVehicle _medic;
      doGetOut _medic;
    };
  };
  _medic doMove (_wnded getpos _offset);
  uiSleep 1;
  if (isnull objectParent _medic) then {
    group _medic setSpeedMode 'FULL'
  } else {
    group _medic setSpeedMode 'LIMITED'
  };
  [_wnded,_medic,_timer] call MGI_fn_heal;
";

MGI_fn_sortie = compileFinal "
  params ['_wnded','_medic','_timer'];
  call {
    if (lifeState _wnded == 'incapacitated' && diag_tickTime < _timer + MGI_BleedOut) exitWith {
      _azimuth = _medic getDir _wnded;
      _medic setDir _azimuth;
      _medic removeitem 'FirstAidKit';
      call {
        if (stance _medic == 'PRONE') exitWith {
          _medic playMove 'ainvppnemstpslaywrfldnon_medicother';
        };
        _medic playMove 'ainvpknlmstpslaywrfldnon_medicother';
      };
      uiSleep 5;
      if (lifeState _medic != 'incapacitated' && alive _medic) then {
        if (_wnded call BIS_fnc_reviveEnabled) then {
          [['#rev',1,_wnded],BIS_fnc_reviveOnState] remoteExec ['call',_wnded];
          uisleep 0.5;
          _wnded setCaptive true;
        } else {
          _wnded setDamage 0;
          _wnded setUnconscious false;
        };
        {if (['Heal Bros',(_wnded actionParams _x) select 0] call bis_fnc_inString) then {[ _wnded,_x] call BIS_fnc_holdActionRemove}} count (actionIDs _wnded);
        _wnded setVariable ['uncsious',false,true];
      };
      uiSleep 2;
      _medic call MGI_fn_medicRelease;
      _wnded setVariable ['myMedic',nil,true];
      if (_wnded getVariable ['uncsious',false]) then {_wnded setVariable ['uncsious',false,true]};
      {_x setDamage 1} forEach (( _wnded nearEntities ['CAManBase',20]) select {side _x getFriend side _wnded < 0.6 && side _x != civilian});
      uiSleep 12;
      _wnded setCaptive false;
    };
    if (lifeState _wnded == 'incapacitated' && diag_tickTime > _timer + MGI_BleedOut) exitWith {};
    _medic call MGI_fn_medicRelease;
    if (_wnded getVariable ['uncsious',false]) then {
      _wnded setVariable ['uncsious',false,true];
    };
  };
";

MGI_fn_heal = compileFinal "
  params ['_wnded','_medic','_timer'];
  uiSleep 3;
  waitUntil {Sleep 0.5; (unitReady vehicle _medic && canMove vehicle _medic) or {diag_tickTime > _timer + MGI_BleedOut && lifeState _wnded == 'incapacitated'}};
  if ((diag_tickTime > _timer + MGI_BleedOut) && lifeState _wnded == 'incapacitated') exitWith {};
  doStop _medic;
  if (!isnull objectParent _medic) then {
    unassignVehicle _medic;
    doGetOut _medic;
  };
  _medic doMove getpos _wnded;
  _medic setSpeedMode 'FULL';
  uiSleep 3;
  if (isNull _medic or lifeState _medic == 'incapacitated') then {
    if (!isNull _medic) then {_medic call MGI_fn_medicRelease};
    _wnded spawn MGI_fn_unconscious;
  };
";

MGI_fn_death = compileFinal "
  params ['_wnded'];
  if (_wnded getVariable ['uncsious',false]) then {
    _wnded setVariable ['uncsious',false,true];
  };
  _wnded setVariable ['myMedic',nil,true];
  if (!(_wnded call BIS_fnc_reviveEnabled)) then {
    _wnded setUnconscious false;
  };
  if (!isMultiplayer && isplayer _wnded) then {
    _wnded setDamage 0;
    uiSleep 12;
    _wnded setCaptive false;
  } else {
    _wnded setDamage 1;
  };
";

MGI_fn_unconscious = compileFinal  "
  params ['_unit'];
  waituntil {sleep 0.5; lifeState _unit == 'incapacitated'  or damage _unit == 1 or (!(_unit call BIS_fnc_reviveEnabled) && damage _unit >=0.86)};
  if (!(_unit call BIS_fnc_reviveEnabled)) then {
    _unit setUnconscious true;
  };
  if (lifeState _unit == 'incapacitated') then {
    _unit setCaptive true;
    if (!isNil {_unit getVariable 'myPatient'}) then {
      _unit call MGI_fn_medicRelease
    };
    if (!isPlayer _unit) then {
      [_unit,'Heal Bros','\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_reviveMedic_ca.paa','\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_reviveMedic_ca.paa',
      '_this distance _target < 3 && lifeState _target == ""incapacitated"" ','_caller distance _target < 3 ',
      { call {
          if (stance _caller == 'PRONE') exitWith {
            _caller playMove 'ainvppnemstpslaywrfldnon_medicother';
          };
          _caller playMove 'ainvpknlmstpslaywrfldnon_medicother';
        };
      },
      {
       if ((diag_tickTime > (_this select 3 select 0) + MGI_react + MGI_BleedOut) && lifeState _target == 'incapacitated') then {
        (_target getVariable ['myMedic',objNull]) call MGI_fn_medicRelease;
        _target call MGI_fn_death;
        }
      },
      { if (_target call BIS_fnc_reviveEnabled) then {
          [['#rev',1,_target],BIS_fnc_reviveOnState] remoteExec ['call',_target];
          _target setCaptive true;
        } else {
          _target setDamage 0;
          _target setUnconscious false;
        };
          if (_target getVariable ['uncsious',false]) then {_target setVariable ['uncsious',false,true]};
        (_target getVariable ['myMedic',objNull]) spawn MGI_fn_medicRelease;
        _target setVariable ['myMedic',nil,true];
        _target spawn {_target = _this; uiSleep 12;
        _target setCaptive false};
      },
      { [_caller,''] remoteExec ['switchMove']
      },
      [diag_tickTime],5,12,true,false] remoteExec ['BIS_fnc_holdActionAdd',0,_unit];
    };
  };
  _timer = diag_tickTime;
  while {lifeState _unit == 'incapacitated' && diag_tickTime <= _timer + MGI_react + MGI_BleedOut} do {
    _unit setCaptive true;
    if (isnil {_unit getVariable 'myMedic'}) then {
      _medic = _unit call MGI_fn_medic;
      if (!isNull _medic) then {
        [_unit,_medic,_timer] call MGI_fn_911
      };
    };
    uiSleep 2;
  };
  if (lifeState _unit == 'incapacitated' && diag_tickTime > _timer + MGI_react + MGI_BleedOut) then {
    (_unit getVariable ['myMedic',objNull]) call MGI_fn_medicRelease;
    _unit call MGI_fn_death;
  };
  (_unit getVariable ['myMedic',objNull]) call MGI_fn_medicRelease;
  if (_unit getVariable ['uncsious',false]) then {_unit setVariable ['uncsious',false,true]};
  _unit setVariable ['myMedic',nil,true];
";


MGI_fn_BailOut = compileFinal "
  params ['_unit','_veh'];
  moveOut _unit;
  _unit setCaptive true;
  if (!(backpack _unit isKindOf 'B_parachute') && (getPosATL _veh select 2) > 30) then {
    uiSleep random 0.5;
    _p = createVehicle ['Steerable_Parachute_F', (getPosATL _unit) vectorAdd [0,0,1],[],0,'none'];
    uiSleep 0.1;
    _unit moveInDriver _p;
    _unit setBehaviour 'COMBAT';
    uiSleep 1;
    if (isnull driver _p) then {
      deleteVehicle _p;
      if (!isplayer _unit) then { _unit setDamage 1};
    };
  } else {
    uiSleep 3;
    if (isnull objectParent _unit && !isTouchingGround _unit) then {_unit setDamage 1};
  };
  uiSleep 3;
  if (!isNil {_veh getVariable 'incVeh'}) then {_veh setVariable ['incVeh',nil,true]};
  if (_unit getVariable ['uncsious',false]) then {_unit setVariable ['uncsious',false,true]};
  uisleep 4;
  _unit setCaptive false;
";


MGI_fn_EHDamage = {
  params ["_unit"];
  _unit addEventHandler ["handleDamage", {
    params ["_unit","","_dam"];
    if (side _unit != sideEnemy) then {
      private _veh = objectParent _unit;
      if (!isnull _veh  && isNil {_veh getVariable "incVeh"} && (damage _veh > 0.7 or (!canfire _veh && !canMove _veh) or _dam > 0.7)) then {
        _veh setVariable ["incVeh",true];
        _crew = +(crew _veh);
        call {
          if (_dam > 0.7 && {objectParent _unit isKindOf "air"} && {getPosATL _veh select 2 > 30}) exitWith {
            [_unit,_veh] spawn {
              params ["_unit","_veh"];
              waitUntil {isTouchingGround _veh};
              [_unit,_veh] call MGI_fn_BailOut;
            };
          };
          if (damage _veh > 0.7 or (!canMove _veh && !canFire _veh)) exitWith {
            {
              [_x,_veh] spawn MGI_fn_BailOut
            } forEach _crew;
          };
          if (_dam >0.7) then {
            [_unit,_veh] spawn MGI_fn_BailOut;
          };
        };
      };
      if (isNull objectParent _unit && {(count allPlayers == 1 && isPlayer _unit) or MGI_AiRevive}) then {
        if !(_unit getVariable ["uncsious",false]) then {
          _unit setVariable ["uncsious",true,true];
          [_unit,""] remoteExec ["switchMove"];
          _unit spawn MGI_fn_unconscious;
        };
      };
      if (!isPlayer _unit or !isMultiplayer) then {_dam min 0.86};
    };
  }];
};


MGI_fn_Revive = {
  MGI_react = "react" call BIS_fnc_getParamValue;
  MGI_BleedOut = "bleedOut" call BIS_fnc_getParamValue;
  MGI_AiRevive = "NoReviveforAi" call BIS_fnc_getParamValue;
  MGI_AIKit = "AIKit" call BIS_fnc_getParamValue;
  MGI_AIMedicTrait = "AIMedicTrait" call BIS_fnc_getParamValue;
  MGI_bros = "bros" call BIS_fnc_getParamValue;
  if (MGI_react == 0) then {MGI_react = 120};
  if (MGI_BleedOut == 0) then {MGI_BleedOut = 120};
  if (MGI_AiRevive == 0) then {MGI_AiRevive = true};
  if (MGI_AIMedicTrait == 0) then {MGI_AIMedicTrait = false};
  if (MGI_bros == 0) then {MGI_bros = switchableUnits+playableUnits};

  params [["_react",MGI_react,[0]],["_bleedOut",MGI_BleedOut,[0]],["_AiRevive",MGI_AiRevive,[true]],["_kit",MGI_AIKit,[0]],["_AIMedicTrait",MGI_AIMedicTrait,[true]],["_MGI_bros",MGI_bros,[[],WEST,objNull]]];
  MGI_react = _react;
  MGI_BleedOut = _bleedOut;
  MGI_AiRevive = _AiRevive;
  MGI_AIKit = _kit;
  MGI_AIMedicTrait = _AIMedicTrait;


  _MGI_bros spawn {
    params ["_MGI_bros","_bros"];
    if (_MGI_bros isEqualType objNull) then {
      _bros = [_MGI_bros];
      MGI_bros = _bros;
      MGI_potentialMedic = MGI_bros
    } else {
    while {true} do {
    call {
      if (_MGI_bros isEqualType WEST) exitWith {

        {_x setVariable ["passedBros",true]} forEach (allUnits select {side _x == _MGI_bros && isnil {_x getVariable "passedBros"} && _x != (missionNamespace getVariable [format ["BIS_SUPP_HQ_%1",_MGI_bros],objNull]) && _x isKindOf "CAManBase"});
      };
      if (allPlayers isEqualTo (switchableUnits + playableUnits)) exitWith {
          {_x setVariable ["passedBros",true]} forEach  (allPlayers select {isnil {_x getVariable "passedBros"}});
        };
      if (_MGI_bros isEqualTypeAll objNull) then {
       {_x setVariable ["passedBros",true]} forEach (_MGI_bros select {isnil {_x getVariable "passedBros"}});
      };
    };
    _bros = allUnits select {(_x getVariable "passedBros")};
    {
      if (isnil {_x getVariable "passEH"}) then {
        _x call MGI_fn_EHDamage;
        _x setVariable ["passEH", _x addEventHandler ["respawn",{
          (_this select 0) setVariable ['uncsious',false,true];
          (_this select 0) setVariable ["passedBros",true];
          (_this select 1) setVariable ["passedBros",nil];
        }]]
      }
    } forEach _bros;
    MGI_bros = +_bros;
    MGI_potentialMedic = MGI_bros select {
    [true,{_x == "FirstAidKit"} count (items _x) >0,{_x == "MediKit"} count (items _x) >0] select MGI_AIKit
    && [true,_x getUnitTrait "Medic"] select MGI_AIMedicTrait
    };
    uiSleep 5;
    };
  };
  };
};

[20,120,true,0,false,west] call MGI_fn_Revive; /* example

NOTE: if you want to add some units of another side, (so, some green + all WEST) just add in the init field of the greens:
 this setVariable ["passedBros",true];*/

 

 

Totally reworked (see below).

EDITED: This version has some MP issues when players respawn. A new version can be tested. Seems to me better so far.

 

 

 

  • Like 16

Share this post


Link to post
Share on other sites

Ohhhh, this looks promising!

I'll play around with this once I get some time c:

 

Thanks for sharing, pierre

Share this post


Link to post
Share on other sites
On 7/16/2017 at 0:31 AM, pierremgi said:

   AI REVIVE/HEAL SP/MP

 

Hi all,

Here is a script to allow AIs reviving and healing bros, according to parameters. This works in SP or MP.

Compatible so far with AI RESPAWN script (see tag)
Don't override the respawn system (MP)

Incapacitation: This script relies on incapacitated status for players or AIs. This status is created when not existing (SP, or MP Ais) to allow revive scenario.

 

parameters:   REACT DELAY  /  HEAL DELAY  /   AI CAN REVIVE   /  KIT NEEDED  /   NEED MEDIC / BROS

 

Parameters can be added to description.ext, class Params, just add what you want in classes: "react" "bleedOut" "noReviveForAI" "AiKit" "AiMedic" "bros".

So you can choose them while in lobby. Anyway, if you pass parameters calling the function, these params will override the lobby ones.

 

  Reveal hidden contents

 

[

  <number, seconds (max) to choose the best healer>, //    example: 15  (optional)  default: 120

                                                 During this time, the script tries to find the best healer according to some priorities:

                                                 not in combat, not targeting, a medic, any bro within 200 m (if any according to other parameters)

  <number, seconds (max) to heal action, remaining bleedout>,  //    example: 60  (optional)  default: 120
                                                 This amount of time is added to the first one. So, healer found or not, this is the remaining time before death unless be revived.

  <boolean, AI CAN REVIVE>,  // example: true                                            (optional)           default: true

                                                In SP/MP, if false, the AI can't revive but can heal the player (incapacitated).

                                                Note that AIs playable units can respawn in MP (Arma engine)

  <number, what kind of kit is needed to revive someone>, // example: 0  (optional)  default: 0

                                                0: not kit needed, no limit for revive

                                                1: need a first aid kit (FAK) , 1 FAK is removed per reviving action

                                                2: need a medic kit (mediKit) , 1 FAK is removed per reviving action, can heal even if no more FAK

  <boolean, Medic trait mandatory>          // example: true                       (optional)          default: false

                                                When true, this limits drastically the chance to be revived.

  

 <side or array of units>, // example: west  (optional)  default: playableUnits + switchableUnits

                                                Just decide who can be healed and revive. The default param works in SP/MP

                                                some custom arrays are working fine also: [blu1,blu2,indep1,indep2] or allUnits select {_x inArea some trigger && side _x == WEST}

                                                You can mix several sides but it's weird to make enemies as bros, with never ending shoot/heal loops!

                             

]

 

 

 

Examples:

call MGI_fnc_AICareandRevive       //   parameters are default ones, or defined by your description.ext

[30,60,true,0,false,west] call MGI_fnc_AICareandRevive;     //    this will override the MP parameters chosen in lobby! Better usage for SP

               

 

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


 

  Reveal hidden contents

 



fn_medicRelease = {
  _medic = _this;
  _medic setVariable ["MGImedic",false];
  [_medic] joinSilent (_medic getVariable ["grp",grpNull]);
  _medic doFollow leader _medic;
  _medic setSpeedMode (speedMode group _medic);
  {_medic enableAI _x} count ["target","autotarget","autocombat","suppression"];
  _medic allowFleeing (1 - (_medic getVariable ["flee",0.5]));
};

MGI_fnc_AICareandRevive = {
  if (isServer) then {
    MGI_react = "react" call BIS_fnc_getParamValue;
    MGI_BleedOut = "bleedOut" call BIS_fnc_getParamValue;
    MGI_AiRevive = "NoReviveforAi" call BIS_fnc_getParamValue;
    MGI_AIKit = "AIKit" call BIS_fnc_getParamValue;
    MGI_AIMedic = "AIMedic" call BIS_fnc_getParamValue;
    MGI_bros = "bros" call BIS_fnc_getParamValue;
    if (MGI_react == 0) then {MGI_react = 120};
    if (MGI_BleedOut == 0) then {MGI_BleedOut = 120};
    if (MGI_AiRevive == 0) then {MGI_AiRevive = true};
    if (MGI_AIMedic == 0) then {MGI_AIMedic = false};
    if (MGI_bros == 0) then {MGI_bros = switchableUnits+playableUnits};

    params [["_react",MGI_react,[0]],["_bleedOut",MGI_BleedOut,[0]],["_AiRevive",MGI_AiRevive,[true]],["_kit",MGI_AIKit,[0]],["_AiMedic",MGI_AIMedic,[true]],["_MGI_bros",MGI_bros,[[],WEST]]];
    MGI_react = _react;
    MGI_BleedOut = _bleedOut;
    MGI_AiRevive = _AiRevive;
    MGI_AIKit = _kit;
    MGI_AIMedic = _AiMedic;
    if (_MGI_bros isEqualType WEST) then {_bros = allUnits select {side _x == _MGI_bros}; _MGI_bros = +_bros};
    MGI_bros = _MGI_bros;

    {
      _unit = _x;
      _unit addEventHandler ["HandleDamage", {
        _wnded = _this select 0;
        _dam = _this select 2;
        if (side _wnded != sideEnemy && _dam > 0.85) then {
          if (((!isMultiplayer or !isPlayer _wnded) && MGI_AiRevive)
           or (!isMultiplayer && isPlayer _wnded && !MGI_AiRevive))
                then {
            _wnded setUnconscious true;
            if (!isNull objectParent _wnded) then {
              _wnded setPos getpos vehicle _wnded
            };
          };
          _wnded spawn {
            _wnded = _this;
            _timerUnc = diag_tickTime;
            waitUntil {sleep 0.5; lifeState _wnded == "incapacitated" or diag_tickTime > _timerUnc + 2};
            if (lifeState _wnded == "incapacitated" && !(_wnded getVariable ["treat",false])) then {
              _wnded setVariable ["treat",true];
              _wnded setCaptive true;
              private _fellows = (MGI_bros select {
                _x isKindOf "CAManBase"
                && _x distanceSqr _wnded < 40000
                && alive _x
                && lifeState _x != "incapacitated"
                && !(_x getVariable ["MGImedic",false])}) - [_wnded];
              _fellows = _fellows select {
                [true,{_x == "FirstAidKit"} count (items _x) >0,{_x == "MediKit"} count (items _x) >0] select MGI_AIKit
                && [true,_x getUnitTrait "Medic"] select MGI_AIMedic
              };
              call {
                if ({behaviour _x != "COMBAT"} count _fellows > 0) exitWith {
                  uiSleep (MGI_react/4); _fellows = _fellows select {behaviour _x != "COMBAT"}};
                if ({(_x targets [true, 300]) isEqualTo []} count _fellows > 0) exitWith {
                  uiSleep (MGI_react/2); _fellows = _fellows select {(_x targets [true, 300]) isEqualTo []}};
              if ({{_x == "MediKit"} count (items _x) > 0} count _fellows > 0) exitWith {
                uiSleep MGI_react;_fellows = _fellows select {{_x == "MediKit"} count (items _x) > 0}};
                _fellows;
              };
              if (count _fellows > 0) then {
                _fellows = _fellows apply {[_x distance _wnded, _x]};
                _fellows sort true;
                _medic = _fellows select 0 select 1;

                _medic setVariable ["MGImedic",true];
                _medic setCaptive true;
                _medic setVariable ["flee",_medic skill "courage"];
                _medic setVariable ["grp", group _medic];
                [_medic] joinSilent grpNull;
                {_medic disableAI _x} count ["target","autotarget","autocombat","suppression"];
                group _medic setBehaviour "AWARE";
                _medic allowFleeing 0;
                _offset = [[0,0],[15, _wnded getRelDir _medic]] select (!isNull objectParent _medic);
                if (!isnull objectParent _medic) then {
                  _medic setVariable ["veh",vehicle _medic];
                  if (assignedDriver vehicle _medic != _medic) then {
                    unassignVehicle _medic;
                    doGetOut _medic;
                  };
                };
                _medic doMove (_wnded getpos _offset);
                sleep 1;
                if (isnull objectParent _medic) then {
                  group _medic setSpeedMode "FULL"
                } else {
                  group _medic setSpeedMode "LIMITED"
                };

                [_medic,_wnded] spawn {
                  params ["_medic","_wnded"];
                  _timerTreat = diag_tickTime;
                  vehicle _medic disableCollisionWith _wnded;
                  uisleep 1;
                  waitUntil {sleep 0.5; unitReady vehicle _medic or !alive _wnded or diag_tickTime > _timerTreat + MGI_BleedOut or  (unitReady vehicle _medic && canmove vehicle _medic && !isnull objectParent _medic)};

                  if ((diag_tickTime > _timerTreat + MGI_BleedOut) or !alive _wnded) then {
                    if (alive _wnded) then {
                      _wnded setUnconscious false;
                      _wnded setDamage 1
                    };
                    _medic call fn_medicRelease;
                    _wnded setVariable ["treat",false];
                    sleep 10;
                    _wnded setCaptive false;
                    _medic setCaptive false;
                  } else {
                    doStop _medic;
                    if (!isnull objectParent _medic) then {
                      unassignVehicle _medic;
                      doGetOut _medic;
                    };
                    _medic doMove getpos _wnded;
                    group _medic setSpeedMode "FULL";
                    Sleep 1;
                    waitUntil {sleep 0.5; unitReady _medic or !alive _wnded or diag_tickTime > _timerTreat + MGI_BleedOut};
                    if (alive _wnded && diag_tickTime < _timerTreat + MGI_BleedOut) then {
                      _azimuth = _medic getDir _wnded;
                      _medic setDir _azimuth;
                      _medic removeitem "FirstAidKit";
                      call {
                        if (!isPlayer _wnded) exitWith {
                          call {
                            if (unitPos _medic == "DOWN") exitWith {
                              _medic playMove "ainvppnemstpslaywrfldnon_medicother";
                            };
                            _medic playMove "ainvpknlmstpslaywrfldnon_medicother";
                          };
                          Sleep 4;
                          _wnded setUnconscious false;
                          _wnded setDamage 0;
                        };
                        _medic action ["HealSoldier", _wnded];
                        sleep 4;
                        [_wnded,{
                          _wnded = _this;
                          BIS_oldLifeState == "HEALTY";
                          _wnded setVariable ["#rev_state",0];
                          _wnded setVariable ["#rev_blood",1];
                          _wnded setVariable ["bis_revive_incapacitated",false];
                          _wnded setVariable ["#rev",0];
                          _wnded setVariable ["#revl",-1],
                          {inGameUISetEventHandler [_x, ""]} forEach ["PrevAction", "NextAction"];
                          _wnded setUnconscious false;
                          _wnded setDamage 0;
                        }] remoteExec ["call",_wnded];
                      };
                      _wnded setVariable ["treat",false];
                      _medic call fn_medicRelease;
                      if (!isnil {_medic getVariable "veh"}) then {
                        _medic assignAsDriver (_medic getVariable "veh");
                      };
                      sleep 10;
                      vehicle _medic enableCollisionWith _wnded;
                      _wnded setCaptive false;
                      _medic setCaptive false;
                    };
                  };
                };
              } else {
                _timerTreat = diag_tickTime;
                waitUntil {sleep 0.5; !alive _wnded or diag_tickTime > _timerTreat + MGI_BleedOut};
                if (alive _wnded) then {
                  _wnded setUnconscious false;
                  _wnded setDamage 1
                };
              };
            };
          };
          if ((((!isMultiplayer or !isPlayer _wnded) && MGI_AiRevive)
              or (!isMultiplayer && !MGI_AiRevive && isPlayer _wnded)) && !(_wnded getVariable ["treat",false])) then {_dam min 0.95} else {_dam};
        };
      }]
    } forEach _MGI_bros;
  };
};

[30,60,true,0,false,west] call MGI_fnc_AICareandRevive;

 

 

 

Nice. Can you make an addon version too?

Share this post


Link to post
Share on other sites

Yes. Planned but not immediately. I'm looking for some feedback. My addons are usually "player oriented" (HUD, fatigue...) This code is for server. I can imagine what to do on a hosted one. Hosting player must have it. On the other hand, i'm lookng for the best way to make it for any server. In other words, how to install an addon on a dedicated one.

Share this post


Link to post
Share on other sites

Hello, and thank you for the script.

 

I am having an issue with testing this. As soon as one of my team is injured or incapacitated by enemy AI, I lose leadership of the team. Thoughts?

Also, as the player, when I get shot, I do not become disabled, I just die.

Share this post


Link to post
Share on other sites

Probably because you're the nearest available "medic" (according to parameters). So, medic quits the group for healing then regroup after action.

 

corrected

 

For your own player death, no problem on SP. You'll be incapacitated if damage > 0.85 (like for MP Arma engine). For MP, don't forget to allow the revive settings in mission parameters. Without MP revive, the engine kill you.  I'm not overriding these settings, just adding some behavior for AI units.

With revive settings, players can heal each others. If mono multiplayer, the player will be healed:

- if not too badly hurt (according to revive options)

- an AI is free to be healer. In harsh combat, there are some cases, nobody will come.  :(

Share this post


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

I just started making my own missions do you have a template with this?

 

What for? Just make your mission. Add a trigger (or write an sqf called (execVM) somewhere),

If trigger (no area): condition: true (instead of this),  on activation, copy/paste the code,

last line, change parameters as you want. (see spoiler).

Share this post


Link to post
Share on other sites

I am wondering if I can add this to the default tanoa ghost mission without to much trouble.

Ghost Missions

 

Any advice would be greatful.

 

We were using ins_revive and ai_revive, but they aren't supported anymore and giving lots of errors.

 

Thanks

Share this post


Link to post
Share on other sites

If there is no double revive feature (for AIs), i guess this could work.

Share this post


Link to post
Share on other sites

I added a 

MGI_fnc_AICareandRevive.sqf to mission folder in a scripts folder

then added

//SA AI Revive
//parameters are default ones
execVM "sa\scripts\MGI_fnc_AICareandRevive.sqf"

To init.server

 

No issues so far.

The description.ext

espawn = "BASE";
respawnDelay = 5;
respawnTemplates[] = {"MenuPosition","Ghst_recover_gear"};//,"menuInventory"
respawnOnStart = -1;
ReviveMode = 1;                         //0: disabled, 1: enabled, 2: controlled by player attributes
ReviveUnconsciousStateMode = 0;         //0: basic, 1: advanced, 2: realistic
ReviveRequiredTrait = 0;                //0: none, 1: medic trait is required
ReviveRequiredItems = 2;                //0: none, 1: medkit, 2: medkit or first aid kit
ReviveRequiredItemsFakConsumed = 1;     //0: first aid kit is not consumed upon revive, 1: first aid kit is consumed
ReviveDelay = 6;                        //time needed to revive someone (in secs)
ReviveMedicSpeedMultiplier = 2;         //speed multiplier for revive performed by medic
ReviveForceRespawnDelay = 5;            //time needed to perform force respawn (in secs)
ReviveBleedOutDelay = 180;              //unconscious state duration (in secs)
disabledAI = 1;
corpseManagerMode = 1; //Type of removed bodies: 0 - none, 1 - all, 2 - only respawnable, 3 - only non-respawnable 
corpseLimit = 20; //Max number of bodies which can be available at the same time. When exceeded, start deleting immediately. 
corpseRemovalMinTime = 120; //Minimal time in seconds a body stays in the scene (can't be removed sooner). 
corpseRemovalMaxTime = 240; //Maximal time in seconds after which a dead body is removed (can't stay longer) 

wreckManagerMode = 1; //Type of removed wrecks: 0 - none, 1 - all, 2 - only respawnable, 3 - only non-respawnable 
wreckLimit = 20; //Max number of wrecks which can be available at the same time. When exceeded, start deleting immediately. 
wreckRemovalMinTime = 120; //Minimal time in seconds a wreck stays in the scene (can't be removed sooner). 
wreckRemovalMaxTime = 240; //Maximal time in seconds after which a wreck is removed (can't stay longer)

Im sure your scipt is overriding some of these parameters in the .ext, I was just hoping your script improved how the AI revived each other and the players.

 

Thanks

Share this post


Link to post
Share on other sites

The script is compatible with your description.ext parameters. There are 6 parameters for that.

The way AIs must be revived  is the same parameter as Arma's engine for players (damage > 0.85) . If you want more chances to have unconscious guys decrease this value.

A second shot on an unconscious guy can kill him.

Share this post


Link to post
Share on other sites
On 8/31/2017 at 2:22 PM, pierremgi said:

The script is compatible with your description.ext parameters. There are 6 parameters for that.

The way AIs must be revived  is the same parameter as Arma's engine for players (damage > 0.85) . If you want more chances to have unconscious guys decrease this value.

A second shot on an unconscious guy can kill him.

Will this work if I am running ACE3?  It would be great to have my AI teammate use an Epi-pin on me to wake me up or bandage me if wounded etc.

 

 

Share this post


Link to post
Share on other sites
22 minutes ago, reaper lok said:

Will this work if I am running ACE3?  It would be great to have my AI teammate use an Epi-pin on me to wake me up or bandage me if wounded etc.

 

 

I don't know. Probably.

Share this post


Link to post
Share on other sites

Hi, good job man =) i'm new in Arma 3 and a noob with scripts but it works really great to me. I found a situation, 4 soldiers, 1 of them is a medic and he is the only one with FAKs (what is needed to revive according to my settings), when i shoot at two of them the medic leave the group to go there and revive both at the same time, not rlly bad, but when he finish, he doesn´t regroup =/ . Any idea how can i fix that without a zone trigger?? Ty =D

On 7/9/2017 at 10:10 PM, reaper lok said:

Will this work if I am running ACE3?  It would be great to have my AI teammate use an Epi-pin on me to wake me up or bandage me if wounded etc.

 

 

I read a loot and unfortunatly ACE mod is more for MP so AI can't heal you with the advanced system..what i did? Remove some medic files from ACE folder and then the Vanilla medic system is working again, and works really good with this script.

  • Like 1

Share this post


Link to post
Share on other sites
22 minutes ago, Dewaine_870 said:

I cant open the reveal contents to get the code. What have I done wrong?

Works for me. I don't know. Any problem with some other ones?

Share this post


Link to post
Share on other sites
11 minutes ago, pierremgi said:

Works for me. I don't know. Any problem with some other ones?

 

*Fixed*

Was using chrome didn't work. Tried Firefox and it worked. 

  • Like 1

Share this post


Link to post
Share on other sites

When using this, is there a way to have a High command function for the player with an AI medic in his group to select the AI medic and then "Heal Brothers"

 

The "Heal Brothers" command would then make the AI medic or any AI with a medkit or firstaid kit heal any down player or AI that are down around them.

 

For example, I join the server. I recruit a 4 man team. One person is a medic, but all will have firstaid kits. I give the command for the AI medic to heal any down brother when needed via HC. We get engaged and I the player and leader of group gets hit and goes down. The medic then heals me or another ai with first aid kit, whoever is closer. Auto_Revive is the best way to explain it.

 

Currently, we are still using the INS_Revive Script by Naong and a custom AI Revive by Duda from our team.

Spoiler

SA_fnc_moveGroupLocal = {
	private ["_target", "_group"];
	_group = [_this,0] call BIS_fnc_param;
	_target = [_this,1] call BIS_fnc_param;
	if(vehicle (leader _group) != (leader _group)) then {
		_group leaveVehicle vehicle (leader _group);
	};
	_group move (getPos _target);
	_group allowFleeing 0;
};

SA_fnc_doReviveLocal = {
	private ["_medic", "_unit"];
	_medic = [_this,0] call BIS_fnc_param;
	_unit = [_this,1] call BIS_fnc_param;
	[_unit,_medic] execVM 'INS_revive\revive\act_revive.sqf'; 
};

SA_fnc_isRevivable = {
	private ["_unit"];
	_unit = [_this,0] call BIS_fnc_param;
	if(	_unit getVariable ["INS_REV_PVAR_is_unconscious",false] && 
		isNil {_unit getVariable "INS_REV_PVAR_who_taking_care_of_injured"} && 
		alive _unit &&
		vehicle _unit == _unit ) then {
		true;
	} else {
		false;
	};
};

SA_fnc_restoreGroupLeaderLocal = {
	private ["_group"];
	_group = [_this,0] call BIS_fnc_param;
	_currentLeader = leader _group;
	_newLeader = _currentLeader;
	_newLeaderId = [_currentLeader] call SA_fnc_getUnitGroupId;
	{
		_id = [_x] call SA_fnc_getUnitGroupId;
		if( (_id < _newLeaderId || !isPlayer _newLeader) && isPlayer _x ) then {
			_newLeader = _x;
			_newLeaderId = _id;
		};
	} forEach (units _group);
	_group selectLeader _newLeader;
	waitUntil { leader _group == _newLeader };
	((units _group)-[_newLeader]) joinSilent _group;
};

SA_fnc_getUnitGroupId = {
	private ["_i", "_unit", "_ret","_group"];
	_ret = false;
	_unit = [_this,0] call BIS_fnc_param;
	_group = group _unit;
	_i = 0;
	while {!_ret AND _i <= 32} do
	{
		_i = _i + 1;
		if (format ["%1",_unit] == format["%1:%2", _group, _i]) then {_ret = true;};
		if (_unit == player) then {if(format ["%1",_unit] == format["%1:%2 (%3)", _group, _i, name _unit]) then {_ret = true;};};
	}; 
	_i
};

if(!isDedicated) then {
	player addEventHandler ["Respawn", {[[group player],"SA_fnc_restoreGroupLeaderLocal",group player] spawn BIS_fnc_MP}];
};

if(isServer) then {

	SA_fnc_availableAiMedics = {

		private ["_unit", "_group", "_medic_requested","_nearUnits","_availableAiMedicsWithMedkits","_possibleMedic"];
		_unit = [_this,0] call BIS_fnc_param;
		_group = group _unit;
		_availableAiMedics = [];

		{
			{
				_possibleMedic = _x;
				//diag_log format ["Possible Medic: %1, %2, %3, %4", !isPlayer _possibleMedic, alive _possibleMedic, !(_possibleMedic getVariable "INS_REV_PVAR_is_unconscious"), _possibleMedic isKindOf "Man"];
				if( !isPlayer _possibleMedic && 
					alive _possibleMedic &&
					(_possibleMedic getVariable ["SA_auto_revive",false] || !isPlayer (leader _possibleMedic) || leader _possibleMedic == _unit ) &&
					((_possibleMedic getVariable ["SA_auto_revive_count",0]) > 0 || !isPlayer (leader _possibleMedic) || leader _possibleMedic == _unit ) &&
					!(_possibleMedic getVariable ["INS_REV_PVAR_is_unconscious",false]) &&
					_possibleMedic isKindOf "Man" ) then {
					
					if( not (_possibleMedic in _availableAiMedics) ) then {				
						if( leader _possibleMedic == _possibleMedic || driver (vehicle _possibleMedic) == _possibleMedic || commander (vehicle _possibleMedic) == _possibleMedic ) then {
							_availableAiMedics = [_availableAiMedics, [_possibleMedic]] call BIS_fnc_arrayPushStack;
						} else {
							_availableAiMedics = [[_possibleMedic], _availableAiMedics] call BIS_fnc_arrayPushStack;
						};
					};
				};
			} forEach (crew _x);
		} forEach ([getPos _unit, 60, {West == side _x}] call SA_fnc_getNearEntities);
		
		if (INS_REV_CFG_require_medkit) then {
			_availableAiMedicsWithMedkits = [];
			{
				private ["_uniformItems","_vestItems","_backpackItems","_itemList"];
				_uniformItems = uniformItems _x;
				_vestItems = vestItems _x;
				_backpackItems = backpackItems _x;
				_itemList = _uniformItems + _vestItems + _backpackItems;
				if ("FirstAidKit" in _itemList) then {
					_availableAiMedicsWithMedkits pushBack _x;
				};
			} forEach _availableAiMedics;
			_availableAiMedicsWithMedkits;
		} else {
			_availableAiMedics;
		};
		
	};

	[] spawn {

		private ["_revivableUnits","_unit","_medic","_unitGroup","_reviveTarget","_all_medics_requested","_medics_to_remove","_newGroup","_medic_requested"];

		_all_medics_requested = [];
		
		while {true} do {

			_revivableUnits = [];
			{
				if([_x] call SA_fnc_isRevivable) then {
					_revivableUnits pushBack _x;
				};
			} forEach allUnits;
			
			//hint format ["%1", _revivableUnits];
		
			{
				_unit = _x;
				
				//diag_log format ["Avail Medics: %1", [_unit] call SA_fnc_availableAiMedics];
				
				{
					_medic = _x;
					if( _medic distance _unit < 50 && 
							[_unit] call SA_fnc_isRevivable && 
							isNull (_medic getVariable ["revive_target",objNull]) &&
							( 
								isNull (_unit getVariable ["medic_requested",objNull]) || 
								!alive (_unit getVariable ["medic_requested",_unit])
							) ) then {
						//diag_log format ["Medic Requested: %1", _medic];
						_unit setVariable ["medic_requested", _medic];
						_medic setVariable ["original_group", group _medic];
						_medic setVariable ["original_team", assignedTeam _medic];
						_medic setVariable ["revive_target", _unit];
						_medic setVariable ["start_time_sec", diag_tickTime];
						_medic setVariable ["SA_auto_revive_count", (_medic getVariable ["SA_auto_revive_count",1]) - 1, true];
						if(count (units group _medic) > 1) then {
							_newGroup = createGroup (side _medic);
							[_medic] join _newGroup;
						} else {
							_newGroup = group _medic;
						};
						[[_newGroup,_unit],"SA_fnc_moveGroupLocal",_medic] spawn BIS_fnc_MP; 
						_all_medics_requested pushBack _medic;
					};
				} forEach ([_unit] call SA_fnc_availableAiMedics);
				
				_medic_requested = _unit getVariable ["medic_requested",objNull];
				
				if( !isNull _medic_requested && _medic_requested distance _unit < 8 && 
						[_unit] call SA_fnc_isRevivable && alive _medic_requested) then {
					[[_medic_requested,_unit],"SA_fnc_doReviveLocal",_medic_requested] spawn BIS_fnc_MP; 
				};
				
			} forEach _revivableUnits;
			
			_medics_to_remove = [];
			{
				_medic = _x;
				_reviveTarget = _medic getVariable ["revive_target",objNull];
				//diag_log format ["%1, %2, %3, %4", !isNull _reviveTarget,  not ([_reviveTarget] call SA_fnc_isRevivable),  !alive _medic, _medic];
				if( (!isNull _reviveTarget && not ([_reviveTarget] call SA_fnc_isRevivable)) || ( !alive _medic) ) then {
					[_medic] joinSilent (_medic getVariable "original_group");
					[_medic,(_medic getVariable "original_team")] remoteExec ["assignTeam"];
					_medic setVariable ["original_group", nil];
					_medic setVariable ["original_team", nil];
					_medic setVariable ["revive_target",objNull];
					_reviveTarget setVariable ["medic_requested", objNull];
					_medics_to_remove pushBack _medic;
				} else {
					_start_time = _medic getVariable ["start_time_sec", diag_tickTime];
					if( diag_tickTime - _start_time > 60 ) then {
						[_medic] joinSilent (_medic getVariable "original_group");
						[_medic,(_medic getVariable "original_team")] remoteExec ["assignTeam"];
						_medic setVariable ["original_group", nil];
						_medic setVariable ["original_team", nil];
						_medic setVariable ["revive_target",objNull];
						_reviveTarget setVariable ["medic_requested", objNull];
						_medics_to_remove pushBack _medic;
					};
				};
			} forEach _all_medics_requested;
			
			if(count _medics_to_remove > 0) then {
				//diag_log format ["Medics Removed: %1", _medics_to_remove];
				_all_medics_requested = _all_medics_requested - _medics_to_remove;
				//diag_log format ["Medics Remaining: %1", _all_medics_requested];
			};
			
			sleep 5;
			
		};

	};

};

if(isServer) then {
	
	[] spawn {
	
		private ["_tempGroup","_tempGroupLeader","_newUnit"];
		private ["_lastLoadOut", "_lastGroup","_unitType","_position","_lastTeam"];
		_tempGroup = createGroup West;
		_tempGroupLeader = _tempGroup createUnit ["LOGIC",[0, 0, 0] , [], 0, ""];
	
		private ["_allFriendlyAiUnits"];
		_allFriendlyAiUnits = [];
		while {true} do {
			
			{
			   if ((side _x) == West && !(isPlayer _x)) then
			   {
					_x setVariable ["SA_Last_Known_Loadout", [_x] call SA_fnc_getLoadout];
					_x setVariable ["SA_Last_Known_Group", _x getVariable ["original_group",group _x]];
					_x setVariable ["SA_Last_Known_Team", _x getVariable ["original_team",assignedTeam _x]];
					_x setVariable ["SA_AI_Revive_Seen", true];
			   };
			   if (isPlayer _x && !(_x getVariable ["SA_AI_Revive_Is_Player",false])) then
			   {
					_x setVariable ["SA_AI_Revive_Is_Player", true];
			   };
			} forEach allUnits;

			{
				if ( !(_x getVariable ["SA_Handling_Revive",false]) && (_x getVariable ["SA_AI_Revive_Seen",false]) && !(_x getVariable ["SA_AI_Revive_Is_Player",false]) ) then {
				
					_x setVariable ["SA_Handling_Revive",true];
					_lastLoadOut = _x getVariable ["SA_Last_Known_Loadout", nil];
					_lastGroup = _x getVariable ["SA_Last_Known_Group", grpNull];
					_lastTeam = _x getVariable ["SA_Last_Known_Team", "MAIN"];
					
					_unitType = (format["%1", typeof _x]);
					_position = [(position _x) select 0, (position _x) select 1];

					deleteVehicle _x;
					
					_newUnit = _tempGroup createUnit [_unitType, _position, [], 0, "CAN_COLLIDE"];
					_newUnit setDir (random floor(random 361));
					
					_newUnitMarker = [position _newUnit, "ColorRed", "AI is down"] call SA_fnc_createDotMarker;
					
					[_newUnit,"AinjPpneMstpSnonWrflDnon"] remoteExec ["switchMove"]; 
					_newUnit disableAI "ANIM"; 
					[_newUnit, false] call INS_REV_FNCT_allowDamage;
					
					if(!isNil "_lastLoadOut") then {
						[_newUnit,_lastLoadOut] call SA_fnc_setLoadout;	
					};
					
					_newUnit setVariable ["SA_Last_Known_Loadout", _lastLoadOut];
					_newUnit setVariable ["SA_Last_Known_Group", _lastGroup];
					_newUnit setVariable ["SA_Last_Known_Team", _lastTeam];
					_newUnit setVariable ["SA_AI_Revive_Seen", true];
					
					_newUnit setVariable ["INS_REV_PVAR_is_unconscious", true, true];
					//_newUnit setVariable ["INS_REV_PVAR_playerSide", _side, true];
					//_newUnit setVariable ["INS_REV_PVAR_playerGroup", _group, true];
					_newUnit setVariable ["INS_REV_PVAR_who_taking_care_of_injured", nil, true];
					_newUnit setVariable ["INS_REV_revived", false, true];
					INS_REV_GVAR_start_unconscious = _newUnit;
					publicVariable "INS_REV_GVAR_start_unconscious";
					["INS_REV_GVAR_start_unconscious", _newUnit] call INS_REV_FNCT_add_actions;
								
					[_newUnit,_lastGroup,_newUnitMarker,_lastTeam] spawn {
						private ["_player", "_condition","_lastGroup","_newUnitMarker","_lastTeam","_isDead","_unconsciousStartTime"];
						_player = _this select 0;
						_lastGroup = _this select 1;
						_newUnitMarker = _this select 2;
						_lastTeam = _this select 3;
						_condition = _player getVariable ["INS_REV_PVAR_is_unconscious",false];
						_unconsciousStartTime = diag_tickTime;
						_isDead = false;
						while {_condition} do
						{
							_who_taking_care_of_injured = _player getVariable "INS_REV_PVAR_who_taking_care_of_injured";
								
							// If somebody is taking care of you
							if !(isNil "_who_taking_care_of_injured") then {
								// If the one who taking care of you is not alive.
								if (isNull _who_taking_care_of_injured || !alive _who_taking_care_of_injured) then	{
									// Reset player's state
									detach _player;
									if !(isNull _who_taking_care_of_injured) then {detach _who_taking_care_of_injured;};
									[_player,"AinjPpneMstpSnonWrflDnon"] remoteExec ["switchMove"]; 
									_player setVariable ["INS_REV_PVAR_who_taking_care_of_injured", nil, true];
								};
							};
							
							// Check MEDEVAC vehicle
							if (INS_REV_CFG_medevac) then {
								if (_player != vehicle _player) then {
									if (alive vehicle _player) then {
										INS_REV_GVAR_is_loaded = true;
										INS_REV_GVAR_loaded_vehicle = vehicle _player;
									} else {
										[] call INS_REV_FNCT_unload;
									};
								};
								
								if (_player == vehicle _player && !isNil "INS_REV_GVAR_is_loaded" && {INS_REV_GVAR_is_loaded}) then {
									[] call INS_REV_FNCT_unload;
								};
							};
							
							sleep 3;
							
							_condition = _player getVariable "INS_REV_PVAR_is_unconscious";
							[_player] call INS_REV_FNCT_prevent_drown;
							
							if(diag_tickTime - _unconsciousStartTime > (60 * ("PARAM_AIReviveLimit" call BIS_fnc_getParamValue))) then {
								_condition = false;
								_isDead = true;
							};
							
						};
						
						sleep 0.2;
						
						if(_isDead) then {
						
							deleteMarker _newUnitMarker;
							_player setVariable ["SA_Handling_Revive", true];
							
							// Remove revive action
							INS_REV_GVAR_end_unconscious = _player;
							publicVariable "INS_REV_GVAR_end_unconscious";		
							["INS_REV_GVAR_end_unconscious", INS_REV_GVAR_end_unconscious] spawn INS_REV_FNCT_remove_actions;
							
							_player enableAI "ANIM";
							
							[_player, true] call INS_REV_FNCT_allowDamage;
							
							_player setDamage 1;
						
						} else {
						
							// Select primary weapon
							_player selectWeapon (primaryWeapon _player);
							
							// Remove revive action
							INS_REV_GVAR_end_unconscious = _player;
							publicVariable "INS_REV_GVAR_end_unconscious";		
							["INS_REV_GVAR_end_unconscious", INS_REV_GVAR_end_unconscious] spawn INS_REV_FNCT_remove_actions;
							
							// Remove unload action
							if (!isNil "INS_REV_GVAR_is_loaded" && {INS_REV_GVAR_is_loaded} && INS_REV_CFG_medevac) then {
								INS_REV_GVAR_del_unload = [INS_REV_GVAR_loaded_vehicle, _player];
								publicVariable "INS_REV_GVAR_del_unload";
								["INS_REV_GVAR_del_unload", INS_REV_GVAR_del_unload] spawn INS_REV_FNCT_remove_unload_action;
								
								INS_REV_GVAR_is_loaded = false;
								INS_REV_GVAR_loaded_vehicle = nil;
							};
							
							[_player, true] call INS_REV_FNCT_allowDamage;

							_player setVariable ["INS_REV_PVAR_isTeleport", false, true];
							_player setVariable ["INS_REV_PVAR_is_dead", false, true];
							
							_player enableAI "ANIM";
							
							[_player,"AmovPercMstpSrasWrflDnon"] remoteExec ["playMove"]; 
							
							deleteMarker _newUnitMarker;
							
							[_player] joinSilent _lastGroup;
							[_player,_lastTeam] remoteExec ["assignTeam"];
							
						};
						
					};
					
				};
			} forEach allDeadMen;

			sleep 5;
			
		};
	};
};

SA_fnc_enableAutoRevive = {
	private ["_units","_enabled","_count"];
	_units = param [0,[]];
	_enabled = param [1,false];
	_count = param [2,1];
	{
		if( !isPlayer _x) then {
			_x setVariable ["SA_auto_revive", _enabled, true];
			_x setVariable ["SA_auto_revive_count", _count, true];
		};
	} forEach _units;
};


//SA_CUSTOM_ACTION_MENU_SUBMENU =
//[
//	["Action",true],
//	["Option-1", [2], "", -5, [["expression", "player sidechat ""-1"" "]], "0", "0", "\ca\ui\data\cursor_support_ca"],
//	["Option 0", [3], "", -5, [["expression", "player sidechat "" 0"" "]], "1", "0", "\ca\ui\data\cursor_support_ca"],
//	["Option 1", [4], "", -5, [["expression", "player sidechat "" 1"" "]], "1", "CursorOnGround", "\ca\ui\data\cursor_support_ca"]
//];

SA_CUSTOM_ACTION_MENU = 
[
	// First array: "User menu" This will be displayed under the menu, bool value: has Input Focus or not.
	// Note that as to version Arma2 1.05, if the bool value set to false, Custom Icons will not be displayed.
	["Action",false],
	// Syntax and semantics for following array elements:
	// ["Title_in_menu", [assigned_key], "Submenu_name", CMD, [["expression",script-string]], "isVisible", "isActive" <, optional icon path> ]
	// Title_in_menu: string that will be displayed for the player
	// Assigned_key: 0 - no key, 1 - escape key, 2 - key-1, 3 - key-2, ... , 10 - key-9, 11 - key-0, 12 and up... the whole keyboard
	// Submenu_name: User menu name string (eg "#USER:MY_SUBMENU_NAME" ), "" for script to execute.
	// CMD: (for main menu:) CMD_SEPARATOR -1; CMD_NOTHING -2; CMD_HIDE_MENU -3; CMD_BACK -4; (for custom menu:) CMD_EXECUTE -5
	// script-string: command to be executed on activation. (no arguments passed)
	// isVisible - Boolean 1 or 0 for yes or no, - or optional argument string, eg: "CursorOnGround"
	// isActive - Boolean 1 or 0 for yes or no - if item is not active, it appears gray.
	// optional icon path: The path to the texture of the cursor, that should be used on this menuitem.
	//["Enable Auto Revive", [0], "", -5, [["expression", "[groupSelectedUnits player, true] spawn SA_fnc_enableAutoRevive;"]], "1", "1"],
	["Enable Auto Revive (1 Revive)", [0], "", -5, [["expression", "[groupSelectedUnits player, true, 1] spawn SA_fnc_enableAutoRevive;"]], "1", "1"],
	["Disable Auto Revive", [0], "", -5, [["expression", "[groupSelectedUnits player, false, 0] spawn SA_fnc_enableAutoRevive;"]], "1", "1"],
	["Halo Jump (Without Leader)", [0], "", -5, [["expression", "[halo, groupSelectedUnits player] spawn SA_fnc_haloJumpMap"]], "1", "1"],
	["Form Squad", [0], "", -5, [["expression", "[groupSelectedUnits player] spawn SA_fnc_formNewGroup"]], "1", "1"],
	["Other Actions", [7], "#ACTION", -5, [["expression", "player sidechat ""Submenu"" "]], "1", "1"]
];

[] spawn {
	while {true} do {
		waitUntil { commandingMenu == "RscGroupRootMenu" };
		waitUntil { commandingMenu == "#ACTION" };
		showCommandingMenu "#USER:SA_CUSTOM_ACTION_MENU";
	};
};

[] spawn {
	private ["_selectedGroupUnits","_keyDownHandler"];
	while {true} do {
		waitUntil { commandingMenu == "#USER:SA_CUSTOM_ACTION_MENU" };
		SA_command_actions_backspace_pressed = false;
		SA_command_actions_selected_units = [];
		_keyDownHandler = (finddisplay 46) displayaddeventhandler ["keydown",
			"if( _this select 1 == 14 && commandingMenu == ""#USER:SA_CUSTOM_ACTION_MENU"") then { SA_command_actions_selected_units = groupSelectedUnits player; SA_command_actions_backspace_pressed = true};"];
		waitUntil { commandingMenu == "" };
		(finddisplay 46) displayremoveeventhandler ["keydown",_keyDownHandler];
		if(SA_command_actions_backspace_pressed) then {
			showCommandingMenu "RscGroupRootMenu";
			{
				player groupSelectUnit [_x, true];
			} forEach (SA_command_actions_selected_units);
		};
	};
};
	
	

 

 

Looking to streamline these scripts and improve performance, as the INS_Revive still has some Arma 2 code checks in it.

 

Thanks,

Share this post


Link to post
Share on other sites

I never use HC. I will have a look. This script (mine) should be improved anyway. I'm not playing with scripts form others but the Naong's one is fine. The approach is more "dead-respawn" oriented.

  • Like 1

Share this post


Link to post
Share on other sites

I would not want you to play with others scripts.

 

Just posting what we have going for now as reference.

 

I have used this (yours) in a few small missions and like it.

 

Just asking if a little more functionality could be added to the command menu or control of the AI healing players and each other. I meant Dudas AI command not high command sorry.

 

Thanks for the hard work

 

Reed

Share this post


Link to post
Share on other sites

No problem. I see what you mean with the command menu. Never tested that. Good idea but a lot of work. I should test what Arma's engine is able to do by default.

  • Like 1

Share this post


Link to post
Share on other sites

Best Scripts for Ai > Revive > Ai But i testing  ai can't revive player  < i am  Fix it is confused with my other scripts.

but you can set ai don't get damage when  incapacitated?

 

 

Share this post


Link to post
Share on other sites
18 hours ago, -XFIRE- said:

Best Scripts for Ai > Revive > Ai But i testing  ai can't revive player  < i am  Fix it is confused with my other scripts.

but you can set ai don't get damage when  incapacitated?

 

 

Yes. It's on my mind.

  • Haha 1

Share this post


Link to post
Share on other sites

Hey @pierre MGI Is there anything special I need to do get this to work on a dedicated server. If I am hosting the mission that I have placed your script into everything works as it should but on a dedicated it doesn't appear to be.

 

Thanks

 

Edit: Sorry I am running the ExecVM from initserver.sqf

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

×