; ---------------------------------------------------------------------------- ; Name: Group Link II Script ; Version: 1.91 ; Date: 041022 ; Author: KeyCat ; MP compability: Yes ; Requires: 1.91+ and Kegetys Editor Addon 1.11 ; Tested with: 1.96 ; ---------------------------------------------------------------------------- ; Credits: ; ; toadlife, Kegetys, Kriegerdaemon ; ---------------------------------------------------------------------------- ; Description: ; ; The original Group Link script was written by toadlife so credits should go ; to him first of all! This is a heavily modified version of his script and is ; tweaked and enhanced particular for my own co-op multiplayer missions. ; ; The main part of this script will run on the server and a Game Logic object ; named "SERVER" is required to be placed somewhere on the map (see example ; mission). ; ; This main script calls a couple of other scripts that is described below... ; ; UNMOUNTE.SQS - Makes east enemy infantry unmount from the truck/jeep/APC/helicopter ; at the conflict point. If they are engaged en route to the conflict point they ; halt and may use smoke to cover the unloading moment. If it's dark the enemy ; may use flares in the target area. If enemy infantry are in a helicopter they ; may paradrop over target area else they will land and unload. Note: Only the ; infantry unmounts i.e APC, tank crews and pilots stay in. ; ; UNMOUNTW.SQS - Same as above but for west enemy infantry. ; ; UNMOUNTR.SQS - Same as above but for resistance enemy infantry. ; ; REMOUNTE.SQS - Makes east enemy infantry group seek up their "parkingspot" and ; remount jeep/truck/APC/helicopter and return to their default WP's (if any) ; when alert is canceled. Helicopter will return to their base, needs a H named ; EastBase (see example mission). ; ; REMOUNTW.SQS - Same as above but for west enemy infantry. Needs a H named ; WestBase (see example mission). ; ; REMOUNTR.SQS - Same as above but for resistance enemy infantry. Needs a H ; named ResistanceBase (see example mission). ; ; ARTILLERY.SQS - Gives AI enemy random chance to request artillery support when ; you are spotted. The script checks so no other engaged AI groups are in the ; area, if they are no artillery support is given. ; ; EH_FIRE1.SQS - If _AIhearingaid = True this script executes on client computer every ; time players gun is fired . Used to give enemy AI the possibility to "hear" your ; gunfire if they are within a specific range. Range depends on actual weapon fired. ; ; EH_FIRE2.SQS - If _AIsuppresivefire = True this script executes on client computer ; every time players gun is fired. Used to make enemy AI to keep their heads down if ; you give suppressive fire ; ; AI_REACT1.SQS - Makes the enemy infantry react to your gunfire if you are ; in their vincinity. ; ; AI_REACT2.SQS - Makes the enemy infantry react to your suppresive fire if you ; are in their vincinity. ; ; AI_REACT3.SQS - Makes the enemy infantry perform house searches. ; ; AI_VOICE1.SQS - This is the server side of the voice alert routines. ; ; AI_VOICE2.SQS - This is the client side of the voice alert routines. ; ; For artillery to work you must place an object (preferable the static artillery ; object) somewhere on the map and name it "EastArtillery" if your AI is east side ; and "WestArtillery" if your AI is west side. If this object doesn't exists or ; gets destroyed during mission enemy AI will not get artillery support. ; ; This also mean that if you don't want artillery support in your mission just ; delete the static artillery object named "EastArtillery" or "WestArtillery". ; ; [[array of enemy groups],[array of static enemy groups],[array of enemy groups that shouldn't remount vehicles],target group,max number of support groups,courage for enemy groups] exec "ai\grouplink2.sqs" ; ; Example 1: ; ; [[ge1,ge2,ge3,ge4,ge5],[ge1,ge2],[ge3,ge4],gw1,3,0.10] exec "ai\grouplink2.sqs" ; ; Example 2: ; ; [[gw1,gw2,gw3,gw4,gw5],[],[gw1],ge1,3,0.10] exec "ai\grouplink2.sqs" ; ; ; Finally I want to say thanks to the following NOSIG members for helping me out ; with numerous (sometimes quite boring ;-) beta tests in multiplayer... ; ; Jotte, Renegade, ctrl, Bjoernen, Solid, DoubleOzero ; ; /KeyCat ; ; ---------------------------------------------------------------------------- ; Used to check if user overrides the default GL II value _nullstring = "scalar bool array string 0xfcffffef" ; Enable/disable enemy AI hearing aid in the script if (format ["%1",KEY_AIhearingaid] == _nullstring) then {KEY_AIhearingaid = True} ; Enable/disable suppresive fire support in the script if (format ["%1",KEY_AIsuppresivefire] == _nullstring) then {KEY_AIsuppresivefire = True} ; Enable/disable enemy AI vehicles using smoke screens for cover if (format ["%1",KEY_AIvehiclesmoke] == _nullstring) then {KEY_AIvehiclesmoke = True} ; Enable/disable enemy AI using smoke grenades for cover if (format ["%1",KEY_AIsmokegrenades] == _nullstring) then {KEY_AIsmokegrenades = True} ; Enable/disable enemy AI voice alert if (format ["%1",KEY_AIvoicealert] == _nullstring) then {KEY_AIvoicealert = True} ; Enable/disable enemy AI paradropping from helicopters if (format ["%1",KEY_AIparadrop] == _nullstring) then {KEY_AIparadrop = True} ; Enable/disable enemy AI doing house search if (format ["%1",KEY_AIhousesearch] == _nullstring) then {KEY_AIhousesearch = True} ; ---------------------------------------------------------------------------- ; Init variables and stuff for all (including clients) ; Check if AI should react to gunfire at long ranges or not? if !(KEY_AIhearingaid) then {goto "no_AIhearingaid"} ; Classify different weapons here. Weapons not listed here will be heard by enemy ; from max distance. Note! Weapon names is case sensitive. KEY_WpnClass0 = ["Bizon","HK","GlockS"] KEY_WpnClass1 = ["AK47GrenadeLauncher","AK74GrenadeLauncher","M16GrenadeLauncher","MM1","6G30"] KEY_WpnClass2 = ["AALauncher","9K32Launcher","Beretta","Glock","Revolver","Tokarev","Skorpian","Ingram","CZ75","UZI"] ; Set global variable to False at start KEY_VoiceAlert = False ; Set global variable to False at start KEY_FireAlert = False ; Set global variable to False at start KEY_Suppressed = False ; Clear variable at start KEY_BulletsFired = 0 ; Variable deciding rate of fire required of weapon able to ; suppress enemy, default value OK for BIS original M60/RPK ; (you may have to play around with this value). if (format ["%1",KEY_ROF] == _nullstring) then {KEY_ROF = 0.20} ; Variable deciding how many bullets have to be fired in row ; to be consodered suppresive fire, default value OK for BIS ; original M60/RPK (you may have to play around with this value). if (format ["%1",KEY_BulletsReq] == _nullstring) then {KEY_BulletsReq = 6} ; Add event handler to each player (in targetgroup only) if (group player == _this select 3) then {player AddEventHandler ["Fired", {_this exec "ai\eh_fire1.sqs"}]} ; Check if AI should react to suppresive fire, if add another event handler to each player (in targetgroup only) if ((group player == _this select 3) && KEY_AIsuppresivefire) then {player AddEventHandler ["Fired", {_this exec "ai\eh_fire2.sqs"}]} ; ########### DEBUG ########### ;hint format["DEBUG: Players group is %1",group player] ;hint format["DEBUG: Players group is %1",_this select 3] ; ############################# ; ---------------------------------------------------------------------------- #no_AIhearingaid ; Check if this is the server (host), if not then exit ? !(local Server) : exit ; Version check requiredVersion "1.91" ; ---------------------------------------------------------------------------- ; Init local server variables _groups = _this select 0 _staticgroups = _this select 1 _no_remount = _this select 2 _tg = _this select 3 _maxgroups = _this select 4 _ratio = _this select 5 ; ---------------------------------------------------------------------------- ; Automaticly create required objects for the script ; Using Game Logics didn't work in my first test????? ;ParkingSpot = "Logic" createVehicle [0,0] ;ParkingSpot1 = "Logic" createVehicle [0,0] ;ParkingSpot2 = "Logic" createVehicle [0,0] ;ParkingSpot3 = "Logic" createVehicle [0,0] ParkingSpot = "KEGres_Misc033" createVehicle [0,0] ParkingSpot1 = "KEGres_Misc033" createVehicle [0,0] ParkingSpot2 = "KEGres_Misc033" createVehicle [0,0] ParkingSpot3 = "KEGres_Misc033" createVehicle [0,0] TargetSpot = "HeliHEmpty" createVehicle [0,0] ; ---------------------------------------------------------------------------- ; Init global server variables and arrays ; Set global variable to False at start KEY_KillGroupLink2 = False ; Set global variable to True at start KEY_ArtilleryReady = True ; Define cars and trucks KEY_EastVehicleTypes = ["UAZ","BRDM","Ural","Scud"] KEY_WestVehicleTypes = ["Jeep","JeepMG","HMMWV","Truck5T","Truck5TOpen"] KEY_ResistanceVehicleTypes = ["GJeep","UAZG","TruckV3SG","SGUAZG"] ; Define APC's KEY_EastAPCTypes = ["BMP","BMP2"] KEY_WestAPCTypes = ["M113","Bradley"] KEY_ResistanceAPCTypes = ["BMPRes"] ; Define helicopters KEY_EastHeliTypes = ["Mi24","Mi17","Kamov"] KEY_WestHeliTypes = ["CH47D","UH60","UH60MG","OH58","AH1","AH64"] KEY_ResistanceHeliTypes = [] ; Define planes and helicopters that can do paradrops KEY_EastParaCapable = ["Mi24","Mi17"] KEY_WestParaCapable = ["CH47D","UH60","UH60MG"] KEY_ResistanceParaCapable = [] ; Define planes - FEATURE NOT IMPLEMENTED YET! ;KEY_EastPlaneTypes = ["Su25"] ;KEY_WestPlaneTypes = ["A10","A10LGB"] ;KEY_ResistancePlaneTypes = [] ; Define boats - FEATURE NOT IMPLEMENTED YET! ;KEY_EastBoatTypes = ["BoatE"] ;KEY_WestBoatTypes = ["BoatW"] ;KEY_ResistanceBoatTypes = [] ; Define searchable buildings (format is "object_name",spot#_to_move_to_when_searching) _Nogova = ["KEGres_Dum10",27,"KEGres_Dum07",5,"KEGres_Dum05",10,"KEGres_Dum11",3,"KEGres_Dum01",13,"KEGres_House55",4,"KEGres_House27",5,"KEGres_House52",6] _Everon = ["Housedum_mesto2",6,"Househospoda_mesto",33,"Housedum_rasovna",2,"Househelfenburk",10] _Malden = ["Housedeutshe_mini",7,"Housecihlovej_dum_mini",3,"Househruzdum",4,"Housecihlovej_dum_in",5,"Houseryb_domek",2] _Kolgujev = ["Housedum_mesto_in",6,"Housedum_zboreny",2,"Houseafdum_mesto3",2,"Housedum_zboreny_total",2] KEY_BuildingTypes = _Nogova + _Everon + _Malden + _Kolgujev ; Global array with groups already searching houses KEY_Housesearch = [] ; Global array with occupied groups KEY_occupied = [] ; Global array with unavailable groups (groups that are refueling, resting etc.) KEY_unavailable = [] ; Global array with available parking spots objects KEY_ParkingSpots = [] ; Global variable with available parking spots KEY_maxgroups = 0 ; Global array of vehicle crews that should not unload from vehicle (i.e tank crews and pilots) KEY_CrewMembers = ["SoldierECrew", "SoldierWCrew", "SoldierGCrew", "SoldierEPilot", "SoldierWPilot", "SoldierGPilot"] ; Global array with groups advancing towards gun fire sound KEY_advancing = [] ; Global array with groups that shouldnt move from their position KEY_staticgroups = _staticgroups ; If KEY_AIhearingaid = True then init AI reaction script 1 (gunfire detection) for each AI group if (KEY_AIhearingaid) then {"[_x] exec ""ai\ai_react1.sqs""" forEach _groups} ; If KEY_AIsuppresivefire= True then init AI reaction script 2 (suppressive fire) for each AI group if (KEY_AIsuppresivefire) then {"[_x] exec ""ai\ai_react2.sqs""" forEach _groups} ; Array of formations to select from _SupportFormation = ["COLUMN","STAG COLUMN","WEDGE","ECH LEFT","ECH RIGHT","VEE","LINE"] ; Array of speeds to select from _SupportSpeed = ["NORMAL","FULL","FULL","FULL"] ; Array of behavior modes to select from _SupportBehavior = ["COMBAT","COMBAT","COMBAT","AWARE","SAFE","AWARE","AWARE"] ; Array of combat modes to select from _SupportCombatMode = ["YELLOW","YELLOW","RED","RED","RED","WHITE"] ; Enemy awarness treshold til they are alerted (tweak lower for more alert enemies) _awareness = 0.10 ; Random spread around target spot in meters _sp = 100 ; Time until enemy AI aborts an alert, if you manage to hide long enough and ; they don't detect you, and returns to their wp's (if any). Each time you are ; detected the timeout counter is reset (200 ~ 5 min). Note if this time is to ; low support infantry may not have time to reach the conflict point by foot before ; alert is canceled. _timeout = 150 + (random 100) ; Main loop update frequency _update = 5 ; Set rated group flag _ratetg = true ; Set max courage for all AI groups "_x allowFleeing 0" foreach _groups ; Set number of maximum active enemy AI groups that can be called in for support, ; if _maxgroups = 0 then randomly set KEY_maxgroups between 2 and 5. if (_maxgroups != 0) then {KEY_maxgroups = _maxgroups + 1} else {goto "random_AI_groups"} ; ---------------------------------------------------------------------------- #start ; Check if we should kill the Group Link II script (KEY_KillGroupLink2 = True) if (KEY_KillGroupLink2) then {hint "Group Link II is disabled!";exit} _temparray = _groups _newarray = [] while "count _temparray > 0" do {_acount = (count _temparray); _rand = random _acount; _rand = _rand - (_rand mod 1);_moveunit = _temparray select _rand;_newarray = _newarray + [_moveunit]; _temparray = _temparray - [_moveunit]} _groups = _newarray ~1 ; Check each of the groups and occupied groups and remove any empties "if ((count units _x) == 0) then {_groups = _groups - [_x]; goto {start};}" foreach _groups "if ((count units _x) == 0) then {KEY_occupied = KEY_occupied - [_x]; goto {start};}" foreach KEY_occupied ; Get a count of groups _groupcount = count _groups ; ########### DEBUG ########### ;hint format["Group Count/Occupied Count: %1,%2",_groupcount,count KEY_occupied] ; ############################# ; If target group is empty, remove it and groups that are pursuing from occupied array and exit the script ? _groupcount <= 0 : KEY_occupied = KEY_occupied - [_tg,_hg,_nh]; _tg lockwp false; _nh lockwp false; _hg lockwp false; exit ; Check if group timed out, if cancel the alert ? (_time >= _timeout) && _alerted : goto "cancelalert" _groupselect = _groupcount _units = units _tg _unitcount = count _units ; ---------------------------------------------------------------------------- ; This part rates the groups and gives them different points depending on what ; strength the vehicle/units are (i.e a tank gets more point than a soldier) #rategroup ? _ratetg : _rateme = _tg ? _ratetg : _return = "ratedtg" _rating = 0 ; Truck "if (((count weapons vehicle _x) > 0) && ((count magazines vehicle _x) > 0) && (canfire vehicle _x) && !(vehicle _x in _rated) && ({truck} counttype [vehicle _x] == 1)) then {_rated = _rated + [vehicle _x]; _rating = _rating + 2}" foreach units _rateme ; Jeep "if (((count weapons vehicle _x) > 0) && ((count magazines vehicle _x) > 0) && (canfire vehicle _x) && !(vehicle _x in _rated) && ({jeep} counttype [vehicle _x] == 1)) then {_rated = _rated + [vehicle _x]; _rating = _rating + 2}" foreach units _rateme ; Car "if (((count weapons vehicle _x) > 0) && ((count magazines vehicle _x) > 0) && (canfire vehicle _x) && !(vehicle _x in _rated) && ({car} counttype [vehicle _x] == 1)) then {_rated = _rated + [vehicle _x]; _rating = _rating + 2}" foreach units _rateme ; Motorcycle "if (((count weapons vehicle _x) > 0) && ((count magazines vehicle _x) > 0) && (canfire vehicle _x) && !(vehicle _x in _rated) && ({motorcycle} counttype [vehicle _x] == 1)) then {_rated = _rated + [vehicle _x]; _rating = _rating + 1}" foreach units _rateme ; APC "if (((count weapons vehicle _x) > 0) && ((count magazines vehicle _x) > 0) && (canfire vehicle _x) && !(vehicle _x in _rated) && ({apc} counttype [vehicle _x] == 1)) then {_rated = _rated + [vehicle _x]; _rating = _rating + 5}" foreach units _rateme ; Tank "if (((count weapons vehicle _x) > 0) && ((count magazines vehicle _x) > 0) && (canfire vehicle _x) && !(vehicle _x in _rated) && ({tank} counttype [vehicle _x] == 1)) then {_rated = _rated + [vehicle _x]; _rating = _rating + 10}" foreach units _rateme ; Helicopter "if (((count weapons vehicle _x) > 0) && ((count magazines vehicle _x) > 0) && (canfire vehicle _x) && !(vehicle _x in _rated) && ({helicopter} counttype [vehicle _x] == 1)) then {_rated = _rated + [vehicle _x]; _rating = _rating + 1}" foreach units _rateme ; Plane "if (((count weapons vehicle _x) > 0) && ((count magazines vehicle _x) > 0) && (canfire vehicle _x) && !(vehicle _x in _rated) && ({plane} counttype [vehicle _x] == 1)) then {_rated = _rated + [vehicle _x]; _rating = _rating + 1}" foreach units _rateme ; ############################# ; This line gives error when more than one target group! ; Seems like the original script doesn't loop thru _tg groups if feeded in an array, possible ; solution would be to add recursive code just like for enemy groups ; ############################# ; Infantry "if (((count weapons _x) > 0) && ((count magazines _x) > 0) && !(_x in _rated) && ({Soldier} counttype [_x] == 1)) then {_rated = _rated + [_x]; _rating = _rating + 1}" foreach units _rateme _rated = [] ? !_ratetg : _temprating = _rating ? _ratetg : _tgrating = _rating _ratetg = true goto _return #ratedtg ; ---------------------------------------------------------------------------- #grouploop ~0.5 ; ########### DEBUG ########### ;hint "DEBUG: grouploop" ; ############################# _groupselect = _groupselect - 1 ; If _groupselect is less than 0 goto start ? _groupselect < 0 : goto "start" ; If all units in selected group is dead remove it from _groups and occupied array and goto start ? count units (_groups select _groupselect) == 0 : _groups = _groups - [(_groups select _groupselect)]; KEY_occupied = KEY_occupied - [(_groups select _groupselect)]; _groupcount = count _groups; goto "start" ; ---------------------------------------------------------------------------- ; This code checks if any enemy group knows anything about any member in your ; group #checkunits ~0.1 _unitcount = _unitcount - 1 ; Check if your group is dead, if goto cancelandexit ? _unitcount < 0 : KEY_occupied = KEY_occupied - [_hg,_nh]; goto "cancelandexit" _unit = (_units select _unitcount) ; Check all groups in _groups array if all units are killed remove the group from array "if ((count units _x) == 0) then {_groups = _groups - [_x]; goto {start};}" foreach _groups ; Check all groups in occupied array if all units are killed remove the group from array "if ((count units _x) == 0) then {KEY_occupied = KEY_occupied - [_x]; goto {start};}" foreach KEY_occupied ; Check if anyone in enemy AI group knows anything about any unit in your group ? (_groups select _groupselect) knowsabout vehicle _unit > _awareness : goto "alert" ; If looped thru all units goto checkdone ? _unitcount == 0 : goto "checkdone" goto "checkunits" ; ---------------------------------------------------------------------------- #checkdone ? _groupselect == 0 : goto "start" _units = units _tg _unitcount = count _units goto "grouploop" ; ---------------------------------------------------------------------------- #alert ; ########### DEBUG ########### ;hint "DEBUG: alert" ; ############################# ; Pause ~0.1 ; Get the group that was alerted _nh = (_groups select _groupselect) ; Check if voice alert is enabled and group is big enough then run approperiate script ; Random chance (80%) ;if (KEY_AIvoicealert && (random 100 < 20)) then {[_nh] exec "ai\ai_voice1.sqs"} if ((KEY_AIvoicealert) && ((count (units _nh)) > 3)) then {[_nh] exec "ai\ai_voice1.sqs"} ; Check if _nh already is alerted, if skip order them a random ; formation and behavior since they already have one ? _alerted : goto "skip_random_formation" ; Set alerted flag _alerted = true ; Randomize the _nh group formation ; ; Randomly pick one of alternatives in _SupportFormation _tmp = random (count _SupportFormation) ; Make it integer _tmp = _tmp - _tmp % 1 ; Set _nh group formation to that _nh setformation (_SupportFormation select _tmp) ; Randomize the _nh group speedmode ; ; Randomly pick one of alternatives in _SupportSpeed _tmp = random (count _SupportSpeed) ; Make it integer _tmp = _tmp - _tmp % 1 ; Set helpgroups speed to that _nh setspeedmode (_SupportSpeed select _tmp) ; Randomize the _nh group combat mode ; ; Randomly pick one of alternatives in _SupportCombatMode _tmp = random (count _SupportCombatMode) ; Make it integer _tmp = _tmp - _tmp % 1 ; Set helpgroups mode to that _nh setBehaviour (_SupportCombatMode select _tmp) ; Randomize the _nh group behavior mode ; ; Randomly pick one of alternatives in _SupportBehavior _tmp = random (count _SupportBehavior) ; Make it integer _tmp = _tmp - _tmp % 1 ; Set helpgroups behavior to that _nh setCombatMode (_SupportBehavior select _tmp) #skip_random_formation ; Get position of _unit _px = getpos _unit select 0 _py = getpos _unit select 1 ; Move (invisible) H object to units last seen position +/- random placement TargetSpot SetPos [((_px) + ((random _sp) - (random _sp))),((_py) + ((random _sp) - (random _sp)))] ; Instruct _nh group to move to the same position _nh move (getPos TargetSpot) ; ########### DEBUG ########### ; Update target marker on map ;"TargetMarker" setMarkerPos (getPos TargetSpot) ; ############################# ; Check side and run approperiate unmount script for the group that called for help if (side _nh == east && !(_nh in KEY_occupied)) then {[_nh,_tg] exec "ai\unmountE.sqs"} if (side _nh == west && !(_nh in KEY_occupied)) then {[_nh,_tg] exec "ai\unmountW.sqs"} if (side _nh == resistance && !(_nh in KEY_occupied)) then {[_nh,_tg] exec "ai\unmountR.sqs"} ; ---------------------------------------------------------------------------- ; ########### TEST HOUSE SEARCH ########### ; Check if house searches are disabled if !(KEY_AIhousesearch) then {goto "No_Housesearch"} ; Select the last unit in the _nh group _tmp = units _nh select (count units _nh - 1) ; Check distance to buildings, cancel if to far from unit ;if ((_tmp distance (nearestBuilding _tmp)) < 100) then {goto "No_Housesearch"} if ((_tmp distance (nearestBuilding _tmp)) > 100) then {goto "No_Housesearch"} ; If KEY_AIhousesearch=true then check if leader in _nh is on foot and it's not already searching houses ;if ((KEY_AIhousesearch) && ((vehicle (leader _nh)) == (leader _nh)) && !(_nh in KEY_Housesearch)) then {[_nh] exec "ai\ai_react3.sqs"} ; ; Check if last unit in group is on foot and group is not already searching houses ;if ((KEY_AIhousesearch) && ((vehicle _tmp) == _tmp) && !(_nh in KEY_Housesearch)) then {[_nh] exec "ai\ai_react3.sqs"} ;if ((KEY_AIhousesearch) && ((vehicle _tmp) == _tmp) && !(_nh in KEY_Housesearch) && ((_tmp distance (nearestBuilding _tmp)) < 100) then {[_nh] exec "ai\ai_react3.sqs"} if (((vehicle _tmp) == _tmp) && !(_nh in KEY_Housesearch)) then {[_nh] exec "ai\ai_react3.sqs"} #No_Housesearch ; ---------------------------------------------------------------------------- ; Reset _time variable _time = 0 ; Add the group to occupied and lock their wp's ? !(_nh in KEY_occupied) : KEY_occupied = KEY_occupied + [_nh] if (!(_nh in KEY_advancing) && !(_nh in KEY_occupied)) then {_nh lockwp true} goto "checkgroupstatus" ; ---------------------------------------------------------------------------- #checkgroupstatus ; ########### DEBUG ########### ;hint "DEBUG: checkgroupstatus" ; ############################# ~((random 1) + 1) _tempcount = count units _nh ? _tempcount == 0 : _groups = _groups - [_nh]; _groupcount = count _groups; goto "start" ; ---------------------------------------------------------------------------- #checkgroupstatusloop ; ########### DEBUG ########### ;hint "DEBUG: checkgroupstatusloop" ; ############################# ~0.1 _tempcount = _tempcount - 1 ? _tempcount < 0 : _groups = _groups - [_nh]; _groupcount = count _groups; goto "start" ? _tempcount > ((count units _nh) - 1) : goto "checkgroupstatus" ? alive ((units _nh) select _tempcount) : goto "radioforhelp" goto "checkgroupstatusloop" ; ---------------------------------------------------------------------------- #radioforhelp ; If number of groups specified in "KEY_maxgroups" already is occupied ; only update target position ? (count KEY_occupied >= KEY_maxgroups) : goto "only_update_targetspot" _ratetg = false _return = "rfh" _rateme = _nh goto "rategroup" #rfh _needshelprating = _temprating _ratingratio = (_tgrating + 0.01) / (_temprating + 0.01) _nhcourage = (_ratingratio + 0.01) / 2 ? _nhcourage > 1 : _nhcourage = 1 ; ########### DEBUG ########### ;hint "DEBUG: radioforhelp" ; ############################# ~0.1 ? _nhcourage <= _ratio : _hg = _nh; goto "callforhelp" ;_groups2 = _groups - KEY_occupied _groups2 = _groups ? _alerted : _groups2 =_groups2 + [_hg] ? _hg == _nh : _groups2 =_groups2 - [_nh] ; Remove _staticgroups from list of available support groups _groups2 = _groups2 - _staticgroups ; Remove already occupied groups from list of available support groups _groups2 = _groups2 - KEY_occupied ; ########### NEW ########### ; Remove unavailable groups from list of available support groups (Plus Pack) _groups2 = _groups2 - KEY_unavailable ; ########### NEW ########### _nearestdis = 400000 _helpgroupnumber = count _groups2 ? _helpgroupnumber == 0 : _hg = _nh; goto "callforhelp" ; ---------------------------------------------------------------------------- #grouploop2 _helpgroupnumber = _helpgroupnumber - 1 _grouptocall = _groups2 select _helpgroupnumber _ratetg = false _return = "gl2" _rateme = _grouptocall goto "rategroup" #gl2 ; If number of units in _grouptocall is 0 remove it from _groups and recount, then goto start ? (count units _grouptocall) == 0 : _groups = _groups - [_grouptocall]; _groupcount = count _groups; goto "start" ; Check distance from _nh group ? (((leader _grouptocall) distance (leader _nh) < _nearestdis) && ((_temprating + 0.1) / (_tgrating + 0.1) >= _ratio)):_hg = _grouptocall;_helpgrouprating = _temprating;_nearestdis = (leader _grouptocall) distance (leader _nh) ? _helpgroupnumber == 0 : goto "callforhelp" ~0.1 goto "grouploop2" ; ---------------------------------------------------------------------------- #callforhelp ; ########### DEBUG ########### ;if (_nhcourage <= _ratio) then {hint format[{%1 (%2) has spotted %3 (%4). They are not calling for backup},_nh,_needshelprating,_tg,_tgrating]} else {hint format[{%1 (%2) is overmatched by %3 (%4). They are calling %5 (%6) for backup},_nh,_needshelprating,_tg,_tgrating,_hg,_helpgrouprating]} ; ############################# ; Check if _nh groups courage is less than _ratio if so skip help ? _nhcourage <= _ratio : goto "skiphelp" ; Only call for support if less than given in _maxgroups are occupied but do ; update position of your group. ? (count KEY_occupied >= KEY_maxgroups) : goto "only_update_targetspot" ; The same if _hg already is occupied ? (_hg in KEY_occupied) : goto "only_update_targetspot" ; Check side and run approperiate unmount script for the _hg group if (side _hg == east) then {[_hg,_tg] exec "ai\unmountE.sqs"} if (side _hg == west) then {[_hg,_tg] exec "ai\unmountW.sqs"} if (side _hg == resistance) then {[_hg,_tg] exec "ai\unmountR.sqs"} ; Add the group to occupied and lock their wp's KEY_occupied = KEY_occupied + [_hg] if !(_hg in KEY_advancing) then {_hg lockwp true} ; Set max courage (i.e no fleeing) ;_hg allowFleeing 0 ; Randomize the _hg formation ; ; Randomly pick one of alternatives in _SupportFormation _tmp = random (count _SupportFormation) ; Make it integer _tmp = _tmp - _tmp % 1 ; Set helpgroups formation to that _hg setFormation (_SupportFormation select _tmp) ; Randomize the _hg speedmode ; ; Randomly pick one of alternatives in _SupportSpeed _tmp = random (count _SupportSpeed) ; Make it integer _tmp = _tmp - _tmp % 1 ; Set helpgroups speed to that _hg setSpeedmode (_SupportSpeed select _tmp) ; Randomize the _hg group mode ; ; Randomly pick one of alternatives in _SupportCombatMode _tmp = random (count _SupportCombatMode) ; Make it integer _tmp = _tmp - _tmp % 1 ; Set helpgroups mode to that _hg setBehaviour (_SupportCombatMode select _tmp) ; Randomize the _hg group behavior mode ; ; Randomly pick one of alternatives in _SupportBehavior _tmp = random (count _SupportBehavior) ; Make it integer _tmp = _tmp - _tmp % 1 ; Set helpgroups behavior to that _hg setCombatMode (_SupportBehavior select _tmp) #only_update_targetspot ; ########### DEBUG ########### ;hint "DEBUG: Updating TargetSpot" ; ############################# ; Reset _time variable _time = 0 ; Get most knowns position _px = getpos _unit select 0 _py = getpos _unit select 1 ; Move invisible H object to units last seen position +/- random placement TargetSpot SetPos [((_px) + ((random _sp) - (random _sp))),((_py) + ((random _sp) - (random _sp)))] ; Instruct all (except thoose static) groups in occupied to move to same location +/- some random placement ;"if ((_time < _timeout) && !(_x in _staticgroups)) then {_x move [((_px) + ((random _sp) - (random _sp))),((_py) + ((random _sp) - (random _sp))),0]}" forEach KEY_occupied ; ; ########### TEST ########### ; Testing with speed check to see if that prevents irring around when groups ; are in a car/BMP and get new move orders all the time??? Seems to affect ; supporting infantry troops??????? ;"if ((_time < _timeout) && !(_x in _staticgroups) && (speed (leader _x) < 5)) then {_x move [((_px) + ((random _sp) - (random _sp))),((_py) + ((random _sp) - (random _sp))),0]}" forEach KEY_occupied ; ; ########### TEST ########### ; Test using knowsabout instead. Only issue a move command if leader knows less than X about ; _unit in your group. This to prevent that enemy AI gets a new move order in the middle of ; a firefight "if ((_time < _timeout) && !(_x in _staticgroups) && ((leader _x) knowsabout _unit < 2.00)) then {_x move [((_px) + ((random _sp) - (random _sp))),((_py) + ((random _sp) - (random _sp))),0]}" forEach KEY_occupied ; ########### DEBUG ########### ; Update target marker on map ;"TargetMarker" setMarkerPos (getPos TargetSpot) ; ############################# ; ---------------------------------------------------------------------------- #skiphelp ; Set max courage ;_nh allowfleeing 0 ; Instruct AI group to move to last know location ? _nhcourage <= _ratio : _nh move (getPos TargetSpot) ? _nhcourage <= _ratio : goto "start" ; Reset _time variable _time = 0 ; Pause before updating ~_update ; Do it all over again goto "start" ; ---------------------------------------------------------------------------- #cancelalert ; ########### DEBUG ########### ;hint format["DEBUG: Alert Cancelled:\n%1",_hg] ; ############################# ; Set back both _hg and _nh behavior from full alert "_x setCombatMode ""BLUE""" forEach KEY_occupied "_x setBehaviour ""AWARE""" forEach KEY_occupied ; Check side and run approperiate remount script for all groups currently in occupied array, ; except thoose listed in the _no_remount array if (side _hg == east) then {"if !(_x in _no_remount) then {[_x] exec ""ai\remountE.sqs""}" forEach KEY_occupied} if (side _hg == west) then {"if !(_x in _no_remount) then {[_x] exec ""ai\remountW.sqs""}" forEach KEY_occupied} if (side _hg == resistance) then {"if !(_x in _no_remount) then {[_x] exec ""ai\remountR.sqs""}" forEach KEY_occupied} ; Pause 3 min. This pause must be high enough to let units find and ; remount their cars and trucks else they will start moving by foot before ; finding any car/truck objects. ~200 ; ########### DEBUG ########### ;hint "DEBUG: All groups WP's unlocked" ; ############################# ; Unlock wp's for all groups in KEY_occupied array "_x lockwp false" forEach KEY_occupied ; Clear array KEY_occupied = [] ; Clear array KEY_advancing = [] ; Count groups _groupcount = count _groups ; Clear alerted flag _alerted = false ; Clear array KEY_ParkingSpots = [] ; Random set a new time until enemy AI aborts next alert _timeout = 150 + (random 100) ; If number of maximum active enemy AI groups is randomly (i.e _maxgroups = 0) then ; generate a new number between 2 and 5 after each timeout if (_maxgroups == 0) then {goto "random_AI_groups"} goto "start" ; ---------------------------------------------------------------------------- #cancelandexit ; ########### DEBUG ########### ;hint format["DEBUG: cancelandexit"] ; ############################# ; Remove _nh and _hg groups from the occupied array and release wp's KEY_occupied = KEY_occupied - [_nh,_hg]; _nh lockwp false; _hg lockwp false exit ; ---------------------------------------------------------------------------- ; This generates random number of maximum active enemy AI groups between 2 and 5 #random_AI_groups ; Randomly generate number _tmp = 2 + (random 4) ; Make it integer _tmp = _tmp - _tmp % 1 ; Set global variable to that number KEY_maxgroups = _tmp goto "start" ; ----------------------------------------------------------------------------