briefing.sqf ,Z Description.ext "X gaia\gaia_init.sqf H@X_/ gaia\scripts\_bak\fnc_AddGroupToZone.sqf Q@X& gaia\scripts\_bak\fnc_CreateBlacklistMarker.sqf Q@X gaia\scripts\_bak\fnc_DeleteBlacklistMarker.sqf P@X gaia\scripts\_bak\fnc_DoOrganizeTransportation.sqf P@XM gaia\scripts\_bak\fnc_GetGroupAssets.sqf P@X gaia\scripts\_bak\fnc_GotClearencePositions.sqf P@XT gaia\scripts\_bak\fnc_HasLOS.sqf P@XJ gaia\scripts\_bak\fnc_isblacklisted.sqf P@X3
gaia\scripts\_bak\fnc_NearTargets.sqf P@X gaia\scripts\_bak\fnc_RepositionBlacklistMarker.sqf P@X gaia\scripts\_bak\fnc_SetCurrentGroupAssets.sqf P@X8 gaia\scripts\_bak\fnc_SetInitialGroupAssets.sqf P@X; gaia\scripts\_bak\fnc_UpdateBlacklistMarker.sqf P@X gaia\scripts\fn_cache.sqf I@Xb gaia\scripts\fn_cache_original_group.sqf I@X gaia\scripts\fn_cache_stage_2.sqf I@Xl gaia\scripts\fn_gaia_cache_init.sqf I@X gaia\scripts\fn_nearPlayer.sqf I@X gaia\scripts\fn_sync.sqf I@X gaia\scripts\fn_uncache.sqf I@XZ gaia\scripts\fn_uncache_original_group.sqf H@X gaia\scripts\fn_uncache_stage_2.sqf H@X gaia\scripts\fnc_AddGroupToGAIA.sqf M@X_ gaia\scripts\fnc_AnalyseUnit.sqf L@X
gaia\scripts\fnc_ClassifyUnits.sqf L@X* gaia\scripts\fnc_CountUnitTypes.sqf L@X gaia\scripts\fnc_DoTask.sqf L@X gaia\scripts\fnc_findclosestposition.sqf L@X gaia\scripts\fnc_FireFlare.sqf L@X gaia\scripts\fnc_GAIA.sqf L@X gaia\scripts\fnc_GAIA_AnalyzeForces.sqf L@X% gaia\scripts\fnc_GAIA_AnalyzeForces_bak.sqf L@X gaia\scripts\fnc_GAIA_AnalyzeTargets.sqf K@X( gaia\scripts\fnc_GAIA_Classify.sqf K@X gaia\scripts\fnc_GAIA_ConflictAreas.sqf K@X
gaia\scripts\fnc_GAIA_IssueOrders.sqf K@Xx gaia\scripts\fnc_GetCAPoints.sqf J@X gaia\scripts\fnc_GetDirectionalPos.sqf J@XM gaia\scripts\fnc_GetDistanceClosestZone.sqf J@X gaia\scripts\fnc_getmarkercorners.sqf J@X2 gaia\scripts\fnc_getmarkershape.sqf J@X gaia\scripts\fnc_getNearestBuildingPosDistance.sqf J@X gaia\scripts\fnc_getposfromcircle.sqf J@XZ gaia\scripts\fnc_getposfromellipse.sqf J@X gaia\scripts\fnc_getposfromrectangle.sqf J@X gaia\scripts\fnc_getposfromsquare.sqf J@Xx gaia\scripts\fnc_GetTurretsWeapons.sqf J@X gaia\scripts\fnc_GetZoneIntendFomGroup.sqf J@X/ gaia\scripts\fnc_GetZoneStatusBehavior.sqf J@X3 gaia\scripts\fnc_HasLOS.sqf J@XJ gaia\scripts\fnc_isblacklisted.sqf J@X gaia\scripts\fnc_isCleared.sqf J@XZ gaia\scripts\fnc_isincircle.sqf J@X, gaia\scripts\fnc_isinellipse.sqf I@Xo gaia\scripts\fnc_isinrectangle.sqf I@X gaia\scripts\fnc_issameposition.sqf I@X9 gaia\scripts\fnc_PosIsInMarker.sqf I@X) gaia\scripts\fnc_rotateposition.sqf I@XI gaia\scripts\fnc_ScanTerrain.sqf I@X gaia\scripts\fnc_SortGroupsByCA.sqf I@Xh gaia\scripts\fnc_TimeOut.sqf I@X gaia\scripts\Fortify\gaia_CBA_fnc_taskDefend.sqf M@X gaia\scripts\Fortify\Garrison_fncs\alerted_debug.sqf M@X gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_cansee.sqf M@X gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_cqc_target.sqf M@X[ gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_get_angle.sqf M@X gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_get_DoorPositions.sqf M@X gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_indoors.sqf M@X gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_MoveTo.sqf M@X gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_next_waypoint.sqf M@XM gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_Prone_Limit.sqf M@X gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_seek.sqf M@X gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_sillybuild_check.sqf M@Xj gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_smartlook.sqf M@X
gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_vision_check.sqf M@X gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_willsee.sqf M@X gaia\scripts\Fortify\Garrison_fncs\gaia_fnc_willwalk.sqf M@X8 gaia\scripts\Fortify\Garrison_fncs\Readme.txt M@X gaia\scripts\Orders\fnc_AddAttackWaypoint.sqf P@X gaia\scripts\Orders\fnc_AddWaypoint.sqf P@X gaia\scripts\Orders\fnc_CreateBuildingWP.sqf P@X gaia\scripts\Orders\fnc_CreateWP.sqf P@X gaia\scripts\Orders\fnc_DoArtillery.sqf P@X gaia\scripts\Orders\fnc_DoAttack.sqf P@X gaia\scripts\Orders\fnc_DoAttackCar.sqf O@X gaia\scripts\Orders\fnc_DoAttackHeli.sqf O@X gaia\scripts\Orders\fnc_DoAttackInf.sqf O@X gaia\scripts\Orders\fnc_DoAttackMechInf.sqf O@X gaia\scripts\Orders\fnc_DoAttackMotorInf.sqf O@X gaia\scripts\Orders\fnc_DoAttackMotorRecon.sqf O@X gaia\scripts\Orders\fnc_DoAttackRecon.sqf O@X gaia\scripts\Orders\fnc_DoAttackShip.sqf O@X gaia\scripts\Orders\fnc_DoAttackTank.sqf O@X gaia\scripts\Orders\fnc_DoClear.sqf O@X gaia\scripts\Orders\fnc_DoClearInf.sqf O@X gaia\scripts\Orders\fnc_DoClearRecon.sqf O@X gaia\scripts\Orders\fnc_DoFortify.sqf O@X9 gaia\scripts\Orders\fnc_DoHide.sqf O@X gaia\scripts\Orders\fnc_DoMortar.sqf O@X! gaia\scripts\Orders\fnc_DoOrganizeTransportation.sqf O@Xo gaia\scripts\Orders\fnc_DoPark.sqf O@X" gaia\scripts\Orders\fnc_DoPatrol.sqf O@X gaia\scripts\Orders\fnc_DoPatrolCar.sqf N@X gaia\scripts\Orders\fnc_DoPatrolHeli.sqf N@X gaia\scripts\Orders\fnc_DoPatrolInf.sqf N@X$ gaia\scripts\Orders\fnc_DoPatrolMechInf.sqf N@X gaia\scripts\Orders\fnc_DoPatrolMotorInf.sqf N@X gaia\scripts\Orders\fnc_DoPatrolMotorRecon.sqf N@X gaia\scripts\Orders\fnc_DoPatrolRecon.sqf N@X gaia\scripts\Orders\fnc_DoPatrolShip.sqf N@X gaia\scripts\Orders\fnc_DoSupport.sqf N@X gaia\scripts\Orders\fnc_DoTransportCar.sqf N@X gaia\scripts\Orders\fnc_DoTransportHeli.sqf N@Xm gaia\scripts\Orders\fnc_DoTransportTank.sqf N@XQ gaia\scripts\Orders\fnc_DoWait.sqf N@X gaia\scripts\Orders\fnc_GetPosition.sqf N@X# gaia\scripts\Orders\fnc_RemoveWaypoints.sqf N@X general2.jpg :^X init.sqf *YX}
initPlayerLocal.sqf kW inventory_briefing.sqf v|V loadout.sqf r-Z#B mission.sqm jAZ onPlayerRespawn.sqf V roster.sqf W
obj1 = player createSimpleTask["Capturer ou tuer le Général"];
obj1 setSimpleTaskDescription["Capturer ou tuer le Général Petrov", "Capturer ou tuer le Général", "Capturer ou tuer le Général"];
obj2 = player createSimpleTask["Détruire les T34"];
obj2 setSimpleTaskDescription["Trouver et détruire les T34", "Trouver et détruire les T34", "Trouver et détruire les T34"];
obj3 = player createSimpleTask["Détruire les canons Zis-3"];
obj3 setSimpleTaskDescription["Détruire les canons Zis-3", "Détruire les canons Zis-3", "Détruire les canons Zis-3"];
obj4 = player createSimpleTask["Extraction"];
obj4 setSimpleTaskDescription["Rejoindre votre point d'évacuation.", "Rejoindre votre point d'évacuation.", "Rejoindre votre point d'évacuation."];
player createDiaryRecord ["Diary", ["Credits", "Mission canardproof crée par Sardo pour les Vilains Canards d'Arma3
http://forum.canardpc.com/
Version 1."]];
player createDiaryRecord ["Diary", ["Insertion / Matériel", "Votre unité se trouve dans les bois à l'ouest du village de Czernica.
Véhicules à disposition :
- 1 kubelwagen
- 3 semi-chenillés Sdkfz 251
- 1 Char Tigre
Vous avez trois groupes de 5 panzergrenadiers, 1 sniper, 2 medecins de combat et les 4 hommes d'équipage du tigre.
Vous avez des panzersfausts et des charges explosives.
L'officier, les sergent-majors, le sniper et les medecins possèdent des radios courtes et moyennes portées.
"]];
player createDiaryRecord ["Diary", ["Renseignements", "Situation générale : après la percée effectuée par le Corps d'infanterie mécanisé LIII de la
division Vicking au sud-ouest de Bryanks, le Général russe Ivan Petrov s'est retiré dans les terres boisées au nord de Kurozweki avec les restes de la 50ème Armée durement secouée.
Le Général a été blessé en tentant de quitter la poche de Bryansk.
Des informateurs nous ont indiqué le groupe de fermes où il se trouve. Il ne peut pas être transporté avant d'être stabilisé.
Les russes attendent donc un chirurgien et des renforts mécanisés.
Nous savons que les russes se sont solidement retranchés dans un hameau au nord de Kurozweki.
L'escorte du Général est constituée d'une trentaine d'hommes et de véhicules blindés dont deux ou trois T34.
Au moins trois canons Zis-3 ont été mis en batterie pour défendre les abords des fermes.
De plus, hier matin une escouade mécanisée à déjà été envoyée sur zone, escortée par deux Panthers de la 24ème Panzerdivision. Malheureusement
nous sommes sans nouvelle. Il semblerait qu'ils aient été neutralisés.Voici leur dernière position.
Information de dernière minute, un détachement blindé de reconnaissance russe a été vu il y a quelques heures progressant sur cette axe.
"]];
player createDiaryRecord ["Diary", ["Mission", "Votre misson consiste à :
1 - Capturer ou tuer le Général Ivan Petrov.
2 - Trouver et détruire les T34 sur zone.
3 - Détruire les trois canons Zis-3.
Des renforts vont arriver par le sud avec un chirurgien et une antenne mobile médicale.
Il faut capturer ou tuer le Général avant que les secours n'arrivent sur zone ou les neutraliser car si le chirurgien stabilise le Général,
celui-ci risque de nous échapper.
Une fois les renforts sur zone, ils leur faudra 30 minutes pour rendre le Général transportable. Ne lambiner pas !
Nos informateurs vous renseigneront sur l'approche de l'antenne médicale.
Une fois les objectifs atteints, rejoindre votre point d'évacuation.
Pour mettre fin à la mission sélectionner la radio alpha puis 0.0.1.
"]];enableDebugConsole = 1;// Console
author = "Sardo"; // Author
onLoadName = "Général Petrov"; // Mission name (temporary solution; actual name set in editor will be used later in the alpha)
onLoadMission = "Capturer ou tuer le Général Ivan Petrov."; // Description
// Preview picture, 2:1 aspect ratio, ideally 1024x512 pixels.
loadScreen = "general2.jpg";
class Header
{
gameType = Coop; // MP misison type
};/*
Created by Spirit, 5-1-2014
*/
GAIA_INIT = FALSE;
GAIA_scripts = "gaia\scripts\";
GAIA_fsm = "gaia\fsm\";
//GAIA
fnc_GAIA = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GAIA.sqf");
fnc_GAIA_AnalyzeTargets = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GAIA_AnalyzeTargets.sqf");
fnc_GAIA_AnalyzeForces = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GAIA_AnalyzeForces.sqf");
fnc_GAIA_ConflictAreas = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GAIA_ConflictAreas.sqf");
fnc_GAIA_Classify = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GAIA_Classify.sqf");
fnc_GAIA_IssueOrders = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GAIA_IssueOrders.sqf");
//Cache
gaia_fn_cache = compile preprocessfilelinenumbers (GAIA_scripts + "fn_cache.sqf");
gaia_fn_cache_stage_2 = compile preprocessfilelinenumbers (GAIA_scripts + "fn_cache_stage_2.sqf");
gaia_fn_sync = compile preprocessfilelinenumbers (GAIA_scripts + "fn_sync.sqf");
gaia_fn_uncache = compile preprocessfilelinenumbers (GAIA_scripts + "fn_uncache.sqf");
gaia_fn_uncache_stage_2 = compile preprocessfilelinenumbers (GAIA_scripts + "fn_uncache_stage_2.sqf");
gaia_fn_nearPlayer = compile preprocessfilelinenumbers (GAIA_scripts + "fn_nearPlayer.sqf");
gaia_fn_gaia_cache_init = compile preprocessfilelinenumbers (GAIA_scripts + "fn_gaia_cache_init.sqf");
fn_cache_original_group = compile preprocessfilelinenumbers (GAIA_scripts + "fn_cache_original_group.sqf");
fn_uncache_original_group = compile preprocessfilelinenumbers (GAIA_scripts + "fn_uncache_original_group.sqf");
//Behavior Functions
fnc_GetCAPoints = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GetCAPoints.sqf");
fnc_DoTask = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_DoTask.sqf");
fnc_GetZoneIntendFomGroup = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GetZoneIntendFomGroup.sqf");
fnc_GetDistanceClosestZone = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GetDistanceClosestZone.sqf");
fnc_AddGroupToGAIA = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_AddGroupToGAIA.sqf");
fnc_HasLOS = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_HasLOS.sqf");
fnc_SortGroupsByCA = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_SortGroupsByCA.sqf");
fnc_FireFlare = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_FireFlare.sqf");
//Orders
fnc_GetPosition = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_GetPosition.sqf");
fnc_addWaypoint = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_addWaypoint.sqf");
fnc_AddAttackWaypoint = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_AddAttackWaypoint.sqf");
fnc_RemoveWayPoints = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_RemoveWayPoints.sqf");
fnc_CreateBuildingWP = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_CreateBuildingWP.sqf");
fnc_CreateWP = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_CreateWP.sqf");
fnc_DoPatrolInf = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPatrolInf.sqf");
fnc_DoPatrolRecon = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPatrolRecon.sqf");
fnc_DoPatrol = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPatrol.sqf");
fnc_DoPatrolCar = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPatrolCar.sqf");
fnc_DoPatrolMotorRecon = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPatrolMotorRecon.sqf");
fnc_DoPatrolMechInf = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPatrolMechInf.sqf");
fnc_DoPatrolMotorInf = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPatrolMotorInf.sqf");
fnc_DoPatrolShip = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPatrolShip.sqf");
fnc_DoPatrolHeli = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPatrolHeli.sqf");
fnc_DoFortify = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoFortify.sqf");
fnc_DoWait = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoWait.sqf");
//fnc_DoPatrolMotorizedRecon = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPatrolMotorizedRecon.sqf");
fnc_DoAttackRecon = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoAttackRecon.sqf");
fnc_DoAttackInf = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoAttackInf.sqf");
fnc_DoAttackCar = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoAttackCar.sqf");
fnc_DoAttackMotorRecon = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoAttackMotorRecon.sqf");
fnc_DoAttackMotorInf = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoAttackMotorInf.sqf");
fnc_DoAttack = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoAttack.sqf");
fnc_DoAttackMechInf = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoAttackMechInf.sqf");
fnc_DoAttackTank = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoAttackTank.sqf");
fnc_DoAttackShip = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoAttackShip.sqf");
fnc_DoAttackHeli = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoAttackHeli.sqf");
fnc_DoTransportCar = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoTransportCar.sqf");
fnc_DoTransportTank = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoTransportTank.sqf");
fnc_DoTransportHeli = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoTransportHeli.sqf");
fnc_DoClear = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoClear.sqf");
fnc_DoClearRecon = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoClearRecon.sqf");
fnc_DoClearInf = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoClearInf.sqf");
fnc_DoSupport = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoSupport.sqf");
fnc_DoHide = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoHide.sqf");
fnc_DoOrganizeTransportation = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoOrganizeTransportation.sqf");
fnc_DoPark = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoPark.sqf");
fnc_DoMortar = compile preprocessfilelinenumbers (GAIA_scripts + "orders\fnc_DoMortar.sqf");
// Subfunctions Positioning
fnc_PosIsInMarker = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_PosIsInMarker.sqf");
fnc_GetDirectionalPos = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GetDirectionalPos.sqf");
fnc_findClosestPosition = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_findclosestposition.sqf");
fnc_getMarkerCorners = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_getmarkercorners.sqf");
fnc_getMarkerShape = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_getmarkershape.sqf");
fnc_getPosFromCircle = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_getposfromcircle.sqf");
fnc_getPosFromEllipse = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_getposfromellipse.sqf");
fnc_getPosFromRectangle = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_getposfromrectangle.sqf");
fnc_getPosFromSquare = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_getposfromsquare.sqf");
fnc_isBlacklisted = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_isblacklisted.sqf");
fnc_isInCircle = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_isincircle.sqf");
fnc_isInEllipse = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_isinellipse.sqf");
fnc_isInRectangle = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_isinrectangle.sqf");
fnc_isSamePosition = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_issameposition.sqf");
fnc_rotatePosition = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_rotateposition.sqf");
fnc_getNearestBuildingPosDistance = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_getNearestBuildingPosDistance.sqf");
fnc_GetZoneStatusBehavior = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GetZoneStatusBehavior.sqf");
fnc_TimeOut = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_TimeOut.sqf");
fnc_isCleared = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_isCleared.sqf");
//Terrain functions
fnc_ScanTerrain = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_ScanTerrain.sqf");
//Statistic function
fnc_CountUnitTypes = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_CountUnitTypes.sqf");
fnc_ClassifyUnits = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_ClassifyUnits.sqf");
fnc_AnalyseUnit = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_AnalyseUnit.sqf");
fnc_GetTurretsWeapons = compile preprocessfilelinenumbers (GAIA_scripts + "fnc_GetTurretsWeapons.sqf");
//garrison specific
//define functions hint
gaia_CBA_fnc_taskDefend =compile preProcessFileLineNumbers (GAIA_scripts + "Fortify\gaia_CBA_fnc_taskDefend.sqf");
//GAIA Public (local) variables
MCC_GAIA_DEBUG = FALSE;
MCC_GAIA_CA_DEBUG = [];
MCC_GAIA_CACHE = false;
GAIA_CACHE_SLEEP = 0.5;
GAIA_CACHE_STAGE_2 = (2*GAIA_CACHE_STAGE_1);
MCC_GAIA_CACHE_STAGE2 = [];
// dont CHANGE without knowledge
MCC_GAIA_OPERATIONAL = false;
//Used for the breadcrumb blacklist system. How far should a waypoint be from a position a unit has last been?
MCC_GAIA_CYCLE = 1;
MCC_GAIA_AWARENESSRANGE = 100;
MCC_GAIA_CLEARRANGE = 70;
MCC_GAIA_SHARETARGET_DELAY = 10;
//If an order is older then 10 minutes, cancel it. There is probbaly something wrong.
MCC_GAIA_MAX_ORDER_AGE = 5000;
//Side specific
MCC_GAIA_CA_WEST = [];
MCC_GAIA_CA_EAST = [];
MCC_GAIA_CA_INDEP = [];
MCC_GAIA_ZONES_INDEP = [];
MCC_GAIA_ZONES_POS_INDEP = [];
MCC_GAIA_ZONES_EAST = [];
MCC_GAIA_ZONES_POS_EAST = [];
MCC_GAIA_ZONES_WEST = [];
MCC_GAIA_ZONES_POS_WEST = [];
MCC_GAIA_GROUPS_WEST = [];
MCC_GAIA_GROUPS_EAST = [];
MCC_GAIA_GROUPS_INDEP = [];
MCC_GAIA_BREADCRUMBS_WEST = [];
MCC_GAIA_BREADCRUMBS_EAST = [];
MCC_GAIA_BREADCRUMBS_INDEP= [];
MCC_GAIA_WPPOS_WEST = [];
MCC_GAIA_WPPOS_EAST = [];
MCC_GAIA_WPPOS_INDEP = [];
MCC_GAIA_ZONESTATUS_WEST = []; for "_i" from 0 to 90 do { MCC_GAIA_ZONESTATUS_WEST set [_i,"0"];};
MCC_GAIA_ZONESTATUS_EAST = []; for "_i" from 0 to 90 do { MCC_GAIA_ZONESTATUS_EAST set [_i,"0"];};
MCC_GAIA_ZONESTATUS_INDEP = []; for "_i" from 0 to 90 do { MCC_GAIA_ZONESTATUS_INDEP set [_i,"0"];};
MCC_GAIA_TARGETS_WEST = []; for "_i" from 0 to 90 do { MCC_GAIA_TARGETS_WEST set [_i,[]];};
MCC_GAIA_TARGETS_EAST = []; for "_i" from 0 to 90 do { MCC_GAIA_TARGETS_EAST set [_i,[]];};
MCC_GAIA_TARGETS_INDEP = []; for "_i" from 0 to 90 do { MCC_GAIA_TARGETS_INDEP set [_i,[]];};
//We spawn GAIA for each side (but dont worry, it will only be really active if there are units.)
//Still a smarter solution is welcome.
[WEST] spawn fnc_GAIA;
[EAST] spawn fnc_GAIA;
[independent] spawn fnc_GAIA;
[] spawn gaia_fn_gaia_cache_init;
GAIA_INIT = TRUE;
/* ----------------------------------------------------------------------------
Function: fnc_AddGroupToZone
Description:
Function adds a group to a zone (Marker on Map -> see MCC).
-Fill MCC_GAIA_GROUPS
Parameters:
- Group
- Marker (String)
Optional:
-
Returns:
true/false
Author:
Spirit
---------------------------------------------------------------------------- */
private ["_group"
,"_Zone"
,"_local_intel"
,"_blacklist"
,"_siz"
,"_nrgroups"
,"_X"
,"_Y"];
_group = _this select 0;
_zone = _this select 1;
// Every group that joins this zone reports in (position in array is the zone number)
_local_intel = MCC_GAIA_GROUPS select (parseNumber _zone );
_local_intel = _local_intel + [(_group)];
MCC_GAIA_GROUPS set [ (parseNumber _zone ),_local_intel];
/*
//Rebuild the blacklijst area's based on active units in zone.
_blacklist = [];
{
_blacklist= _blacklist + [format["%1_from" ,_x]];
_blacklist= _blacklist + [format["%1_to" ,_x]];
} forEach ( MCC_GAIA_GROUPS select (parseNumber _zone ));
MCC_GAIA_BLACKLIST set [ (parseNumber _zone ),_blacklist];
// relative blacklist SIZE, based on the number of groups we have in this Area
_siz =[];
_siz = getMarkerSize _zone;
_nrgroups = (count(MCC_GAIA_GROUPS select (parseNumber _zone ))) max 2;
_X = round((_siz select 0)/_nrgroups)*1.2;
_Y = round((_siz select 1)/_nrgroups)*1.2;
MCC_GAIA_BLACKLIST_SIZE set [ (parseNumber _zone ),[_X,_Y]];
// Then either create or Update the markers, as the size has been changed.
{
if (_x==_group) then
{[_group, _zone] call fnc_CreateBlacklistMarker;}
else
{[_x, _zone] call fnc_UpdateBlacklistMarker; jaja=true;}
} forEach ( MCC_GAIA_GROUPS select (parseNumber _zone ));
*/
true;
/* ----------------------------------------------------------------------------
Function: fnc_CreateBlacklistMarker
Description:
Create a _from and a _to Marker for each group, that is used to blacklist possible waypoint positions.
Parameters:
- Group
Optional:
-
Returns:
true/false
Author:
Spirit
---------------------------------------------------------------------------- */
private ["_group","_zone","_shape","_mshape"];
_group = _this select 0;
_zone = _this select 1;
//Every group has a from and a to blackzone. So where they are from and where they go to are no longer used as possible waypoint position.
_from = format ["%1_from" ,_group];
_to = format ["%1_to" ,_group];
//Awesome not have the getmarkershape command
_shape = _zone call fnc_getMarkerShape;
if (_shape in ["SQUARE","RECTANGLE"]) then
{_mshape = "RECTANGLE"}
else
{_mshape = "ELLIPSE"};
_from_marker = createMarker [_from, (position (leader _group))];
if !(MCC_GAIA_DEBUG) then {_from_marker setMarkerAlpha 0; };
_from_marker setMarkerShape _mshape;
_from_marker setMarkerSize (MCC_GAIA_BLACKLIST_SIZE select (parseNumber _zone ) );
_to_marker = createMarker [_to, (position (leader _group))];
if !(MCC_GAIA_DEBUG) then {_to_marker setMarkerAlpha 0; };
_to_marker setMarkerShape _mshape;
_to_marker setMarkerSize (MCC_GAIA_BLACKLIST_SIZE select (parseNumber _zone ) );
_to_marker setMarkerColor "ColorGreen";
true/* ----------------------------------------------------------------------------
Function: fnc_DeleteBlacklistMarker
Description:
Delete a _from and a _to Marker for each group(resize), that is used to blacklist possible waypoint positions.
Parameters:
- Group
Optional:
-
Returns:
true/false
Author:
Spirit
---------------------------------------------------------------------------- */
private ["_group"];
_group = _this select 0;
//Every group has a from and a to blackzone. So where they are from and where they go to are no longer used as possible waypoint position.
_from = format ["%1_from" ,_group];
_to = format ["%1_to" ,_group];
deleteMarker _from;
deleteMarker _to;
true//==================================================================fnc_DoInfPatrol===============================================================================================
// Validate if and organise transportation
//
// spirit 28-1-2014
//===========================================================================================================================================================================
private ["_group"];
_group = _this select 0;
_PosCloseRoadStart = [];
_PosCloseRoadEnd = [];
//where is this dude going?
_wpPos = (waypointPosition [_group ,(count(waypoints _group)-1)]);
_wptype = waypointType [_group ,(count(waypoints _group)-1)];
//Is he actualy going somewhere?
if (count(_wpPos)>0) then
{
//How fare does he need to travel?
_dist = _wpPos distance (position leader _group);
//If that is futther then the max range for slow speed groups, then he is legimate to receive transportation
if (_dist > MCC_GAIA_MAX_SLOW_SPEED_RANGE) then
{
//Loop through all groups until we find a transportation dude
{
_TransportGrp = _x;
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == (side _group))
and
(count(units _x)>0)
and
(alive (leader _x))
and
((behaviour leader _x)!="COMBAT")
and
//The transport vehicle must not be occupied
((_x getVariable ["GAIA_Order",""]) != "DoTransport")
and
// He must be able to do transport
("DoTransport" in (_x getVariable ["GAIA_Portfolio",[]]))
and
//He must be able to hold all of us
((count units _group)<=(_x getVariable ["GAIA_cargo",0]))
and
//The vehicle cannot be so far out from the requesting group that it even exeeds its own max range based on medium speed
(((leader _group) distance (leader _x))< MCC_GAIA_MAX_MEDIUM_SPEED_RANGE)
and
//The distance to transport must exceed the distance to the transport by 2 times.
((_dist*2) > ((leader _group) distance (leader _x)))
and
//A transporter takes atleast MCC_GAIA_TRANSPORT_RESTTIME seconds of breaktime before getting a new order
((time-(_x getVariable ["GAIA_Ordertime",0]))>MCC_GAIA_TRANSPORT_RESTTIME)
and
//Put in some random factor to prevent predictable behavior (chance is each cycle so can be low)
(random(10)>8)
)
then
//We found a possible dude
{
_nearRoad = (leader _group nearRoads 300);
if (count(_nearroad)>0) then
//Arrange a pickup on the side of the street, else we gonna have ai crazyness going on
{_road = (([_nearRoad,[],{leader _group distance _x},"ASCEND"] call BIS_fnc_sortBy ) select 0);
_roadConnectedTo = roadsConnectedTo _road;
_connectedRoad = _roadConnectedTo select 0;
_direction = [_road, _connectedRoad] call BIS_fnc_DirTo;
_PosCloseRoadStart = [(position _road), 7, (_direction - 45)] call BIS_fnc_relPos;
};
_nearRoad = ( _wpPos nearRoads 300);
if (count(_nearroad)>0) then
{_PosCloseRoadEnd = position(([_nearRoad,[],{_wpPos distance _x},"ASCEND"] call BIS_fnc_sortBy ) select 0);};
if (
//There is a road found to pickup and a road foudn to drop him off
(count(_PosCloseRoadStart)>0) and (count( _PosCloseRoadEnd)>0)
) then
{
//Make the transporter stop hiding
_dummy =[_x] call fnc_RemoveWayPoints;
_dummy =[_group] call fnc_RemoveWayPoints;
// Get in
_wpGroup = _group addWaypoint [_PosCloseRoadStart, 0];
_wpGroup setWaypointType "GETIN";
_wpGroup setWaypointCompletionRadius 20;
_wpTransporter = _x addWaypoint [_PosCloseRoadStart, 0];
_wpTransporter setWaypointType "LOAD";
_wpTransporter setWaypointCompletionRadius 20;
_wpTransporter setWaypointSpeed "FULL";
//Synchronize them
_wpGroup synchronizeWaypoint [_wpTransporter];
// Get the fuck out
_wpGroup = _group addWaypoint [_PosCloseRoadEnd, 0];
_wpGroup setWaypointType "GETOUT";
_wpGroup setWaypointCompletionRadius 20;
//We go on alone, set us free
_wpGroup setWaypointStatements ["true", " (group this) setVariable ['GAIA_Order' , 'DoPatrol', false];(group this) setVariable ['GAIA_CombinedOrder' , GrpNull, false];"];
_wpTransporter = _x addWaypoint [_PosCloseRoadEnd, 0];
_wpTransporter setWaypointType "TR UNLOAD";
_wpTransporter setWaypointCompletionRadius 20;
//release both groups from each other
//Synchronize them
_wpGroup synchronizeWaypoint [_wpTransporter];
//patrolling units will pick this up first
_group setVariable ["GAIA_OriginalDestination",_wpPos , false];
//Lets set the current Order of the vehilce transporting ( so he dont get a new DoTransport when we are going)
_x setVariable ["GAIA_Order" , "DoTransport", false];
_group setVariable ["GAIA_Order" , "DoTransport", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_x setVariable ["GAIA_OrderTime" , Time, false];
_x setVariable ["GAIA_OrderPosition" , (_PosCloseRoadEnd), false];
_x setVariable ["GAIA_CombinedOrder" , (_group), false];
_group setVariable ["GAIA_CombinedOrder" , (_x), false];
};
};
//If we have waypoints, stop (more then 1 as the initial patrol waypoint is the first).
//If this fails, every transport in the universe will try to serve us, maybe something smarter
if ( ((_group getVariable ["GAIA_Order",""]) == "DoTransport")) exitwith {true;};
}forEach ([AllGroups,[],{(leader _group) distance (leader _x)},"ASCEND",{alive (leader _x)}] call fnc_SortGroupsByCA);
//AllGroups;
};
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)/* ----------------------------------------------------------------------------
Function: fnc_GetGroupAssets
Description:
A function to get the Initial and the current assets of the group (known!)
As the group might loose number harsh, we just take a timestamp to judge.
Parameters:
- Group
Returns:
[_InitAsset,_CurrAsset]
Author:
Spirit, 7-1-2014
---------------------------------------------------------------------------- */
private ["_group"];
_group = _this select 0;
_InitAsset = _group getVariable "InitialAssets";
_CurrAsset = _group getVariable "CurrentAssets";
[_InitAsset,_CurrAsset]
private ["_pos","_IsBlackListed"];
/* ----------------------------------------------------------------------------
Function: fnc_isblacklisted
Description:
Checks if the given position is witin MCC_GAIA_AWARENESSRANGE.
Parameters:
- position
Returns:
true/false
Author:
Spirit
---------------------------------------------------------------------------- */
_pos = _this select 0;
_IsBlackListed = false;
{
if ((_pos distance (_x select 0)),,(,)] call FLAY_fnc_knowsAbout;
// returns true if can see and is less than meters from , otherwise returns false.
private ["_unit", "_target", "_range", "_fov", "_inView", "_inSight", "_inRange", "_knowsAbout"];
_unit = [_this,0] call BIS_fnc_param;
_target = [_this,1] call BIS_fnc_param;
_range = [_this,2,100,[0]] call BIS_fnc_param;
_fov = [_this,3,130,[0]] call BIS_fnc_param;
_knowsAbout = false;
_inRange = (_unit distance _target) < _range;
if (_inRange) then {
_inView = [position _unit, getdir _unit, _fov, position _target] call BIS_fnc_inAngleSector;
_inSight = count (lineIntersectsWith [eyePos _unit, eyepos _target, _unit, _target]) == 0;
_knowsAbout = _inView && _inSight;
};
_knowsAbout; // In: [position,blackListMarker]
// Out: boolean
private ["_pos","_area","_return"];
_pos = _this select 0;
_area = _this select 1;
_return = false;
// Find corner positions of the rectangle
private ["_dir"];
_dir = markerDir _area;
_dir = _dir % 360;
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _area;
_centerX = _center select 0;
_centerY = _center select 1;
private ["_shape"];
_shape = _area call fnc_getMarkerShape;
if (_shape == "ICON") then {
// Icon has only one position, so if it equals to the given position, then it's blacklisted.
if ([_pos,_center] call fnc_isSamePosition) then {
_return = true;
};
// Markers that have an area.
} else {
if (_shape in ["RECTANGLE","SQUARE"]) then {
private ["_corners"];
_corners = _area call fnc_getMarkerCorners;
// If rectangle is not axis-aligned.
if (_dir % 90 != 0) then {
// Add the point position to the array to have it shifted by the FOR below
_corners set [4,_pos];
// Rotate each corner position so that the rectangle is aligned with x and y axises
// Use origo as center while rotating, but for comparison shift positions back
private ["_posCor","_posNew","_orgX","_orgY","_shiftedX","_shiftedY","_newX","_newY"];
for "_i" from 0 to (count _corners - 1) do {
_posCor = _corners select _i;
// Original coordinates
_orgX = _posCor select 0;
_orgY = _posCor select 1;
// Subtract the marker center coordinates from corner coordinates.
// Rotation is done using origo (0,0) as anchor/centerpoint.
_shiftedX = _orgX - _centerX;
_shiftedY = _orgY - _centerY;
// Axis-aligned corner position
_posNew = [[_shiftedX,_shiftedY],_dir] call fnc_rotatePosition;
// Shift the aligned corner position back near to the original marker location.
_newX = _posNew select 0;
_newY = _posNew select 1;
_newX = _newX + _centerX;
_newY = _newY + _centerY;
_posCor = [_newX,_newY];
_corners set [_i,_posCor];
};
// Point position
_pos = _corners select 4;
};
// Check if the position is within the marker area.
_return = [_pos,_corners] call fnc_isInRectangle;
} else {
if (_shape == "CIRCLE") then {
_return = [_pos,_area] call fnc_isInCircle;
} else {
_return = [_pos,_area] call fnc_isInEllipse;
};
};
};
_returnprivate["_targets","_enemies","_enemySides","_side","_unit","_UPosG","_range","_UPosR","_me","_Dist"];
_range = _this select 1;
_me = _this select 0;
_targets = _me nearTargets _range;
_enemies = [];
_enemySides = _me call BIS_fnc_enemySides;
{
_unit = (_x select 4);
_side = (_x select 2);
_UPosG = (_x select 0);
_UPosR = [];
if ((_side in _enemySides) && (count crew _unit > 0)) then
{
if ((side driver _unit) in _enemySides) then
{
_UPosR = position _unit;
_Dist = [_UPosR, _UPosG] call CBA_fnc_getDistance;
_TDist = [(position _me),_UPosG] call CBA_fnc_getDistance;
_enemies set [count _enemies, [_unit,_UPosG, _UPosR, _Dist,_TDist, (_me knowsabout _unit) ]];
};
};
}
forEach _targets;
_enemies/* ----------------------------------------------------------------------------
Function: fnc_RepositionBlacklistMarker
Description:
Reposition the _from and a _to Marker for each group (usualy at the end of a waypoint).
That is used to blacklist possible waypoint positions.
Parameters:
- Group
- Zone
- Position TO (where are we going to)
Optional:
-
Returns:
true/false
Author:
Spirit
---------------------------------------------------------------------------- */
private ["_group","_zone","_position_to","_position_from"];
_group = _this select 0;
_zone = _this select 1;
_position_to = _this select 2;
//Every group has a from and a to blackzone. So where they are from and where they go to are no longer used as possible waypoint position.
_from = format ["%1_from" ,_group];
_to = format ["%1_to" ,_group];
_position_from = getmarkerpos _to;
_from setmarkerpos _position_from;
_to setmarkerpos _position_to;
true/* ----------------------------------------------------------------------------
Function: fnc_SetCurrentGroupAssets
Description:
A function to save the stuff we currently have AFTER we got destroyed, raped, etc
It is saved to a group variable CurrentAssets.
Parameters:
- Group
Returns:
true
Author:
Spirit, 7-1-2014
---------------------------------------------------------------------------- */
private ["_group"];
_group = _this select 0;
_group setVariable ["CurrentAssets", ([_group] call fnc_countgroup), false];
true;/* ----------------------------------------------------------------------------
Function: fnc_SetInitialGroupAssets
Description:
A function to save the stuff we initialy got (before we got destroyed, raped, etc)
It is saved to a group variable InitialAssets.
Parameters:
- Group
Returns:
true
Author:
Spirit, 7-1-2014
---------------------------------------------------------------------------- */
private ["_group"];
_group = _this select 0;
_group setVariable ["InitialAssets", ([_group] call fnc_countgroup), false];
true;
/* ----------------------------------------------------------------------------
Function: fnc_UpdateBlacklistMarker
Description:
Update a _from and a _to Marker for each group(resize), that is used to blacklist possible waypoint positions.
Parameters:
- Group
- Zone
Optional:
-
Returns:
true/false
Author:
Spirit
---------------------------------------------------------------------------- */
private ["_group","_zone"];
_group = _this select 0;
_zone = _this select 1;
//Every group has a from and a to blackzone. So where they are from and where they go to are no longer used as possible waypoint position.
_from = format ["%1_from" ,_group];
_to = format ["%1_to" ,_group];
_from setMarkerSize (MCC_GAIA_BLACKLIST_SIZE select (parseNumber _zone ) );
_to setMarkerSize (MCC_GAIA_BLACKLIST_SIZE select (parseNumber _zone ) );
trueif(!isServer) exitWith {};
private["_count"];
_count = 0;
{
private["_pos"];
if(_x != leader _this && !("Driver" in assignedVehicleRole _x)) then {
_x disableAI "TARGET";
_x disableAI "AUTOTARGET";
_x disableAI "MOVE";
_x disableAI "ANIM";
_x disableAI "FSM";
_x enableSimulation false;
_x allowDamage false;
//_x hideObject true;
//if (vehicle _x != _x) then {(vehicle _x) hideObject true};
if (vehicle _x == _x) then {
_pos = getPosATL _x;
_pos set [2, -100];
_x setPosATL _pos;
};
_count = _count + 1;
} else {
_x allowDamage true;
_x enableSimulation true;
_x enableAI "TARGET";
_x enableAI "AUTOTARGET";
_x enableAI "MOVE";
_x enableAI "ANIM";
_x enableAI "FSM";
//_x hideObject false;
//if (vehicle _x != _x) then {(vehicle _x) hideObject false};
};
} forEach units _this;
_this setVariable ["GAIA_CACHED_STAGE_1",true, false];if(!isServer) exitWith {};
private ["_group","_units","_vehicles"];
_group = _this select 0;
_units = units _group;
_vehicles = [_group] call BIS_fnc_groupVehicles;
_sf = [];
_uv = [];
_crew = [];
_gv = [];
if (({alive _x} count units _group) > 0) then
{
{
_veh = _x;
_crew = [];
{
if
(
( assignedVehicle _x == _veh)
and
( alive _x)
)
then
{
//player globalchat format ["%1, %2",_veh,_x];
_crew = _crew + [[(typeof _x),(getpos _x),damage _x,skill _x,rank _x,(assignedVehicleRole _x),getdir _x]];
_units = _units - [_x];
}
} foreach _units;
_gv = _gv + [[(typeof _veh),position _veh,damage _veh,fuel _veh,_crew,getdir _x]];
} foreach _vehicles;
{
if ( alive _x) then
{
_uv = _uv + [[typeof _x,(visiblePositionasl _x),damage _x,skill _x,rank _x,getdir _x]];
//deleteVehicle _x;
};
}
foreach _units;
_array = [];_waypoints=[];
if (((count (waypoints _group)) - currentWaypoint _group)>0) then
{
{
private "_waypoint";
if (( (waypointposition _x) distance [0,0,0])>0) then
{
_waypoint = [
waypointposition _x,
waypointtype _x,
waypointbehaviour _x,
waypointspeed _x,
waypointcombatmode _x,
waypointformation _x,
waypointstatements _x,
waypointtimeout _x,
waypointhouseposition _x
];
_array set [count _array, _waypoint];
};
} foreach (waypoints _group);
_waypoints = [_array, currentwaypoint _group];
};
_sf = [_gv
,_uv
,side _group
,(_x getVariable ["GAIA_zone_intend",[]])
,behaviour (leader _group)
,combatmode _group
,speedmode _group
,formation _group
,_waypoints
];
_var2 = "GAIA_RESPAWN_" + str(_group);
missionNamespace setVariable [_var2,[ _sf,((_x) getVariable ["MCC_GAIA_CACHE", false])] ];
};if(!isServer) exitWith {};
private ["_group"];
_group = _this select 0;
_units = units _group;
_vehicles = [_group] call BIS_fnc_groupVehicles;
_sf = [];
_uv = [];
_crew = [];
_gv = [];
{
_veh = _x;
_crew = [];
{
if
(
( assignedVehicle _x == _veh)
and
( alive _x)
)
then
{
//player globalchat format ["%1, %2",_veh,_x];
_crew = _crew + [[(typeof _x),(getpos _x),damage _x,skill _x,rank _x,(assignedVehicleRole _x),getdir _x]];
_units = _units - [_x];
}
} foreach _units;
_gv = _gv + [[(typeof _veh),position _veh,damage _veh,fuel _veh,_crew,getdir _x]];
} foreach _vehicles;
{
if ( alive _x) then
{
_uv = _uv + [[typeof _x,(visiblePositionasl _x),damage _x,skill _x,rank _x,getdir _x]];
//deleteVehicle _x;
};
}
foreach _units;
_array = [];_waypoints=[];
if (((count (waypoints _group)) - currentWaypoint _group)>0) then
{
{
private "_waypoint";
if (( (waypointposition _x) distance [0,0,0])>0) then
{
_waypoint = [
waypointposition _x,
waypointtype _x,
waypointbehaviour _x,
waypointspeed _x,
waypointcombatmode _x,
waypointformation _x,
waypointstatements _x,
waypointtimeout _x,
waypointhouseposition _x
];
_array set [count _array, _waypoint];
};
} foreach (waypoints _group);
_waypoints = [_array, currentwaypoint _group];
};
_sf = [_gv
,_uv
,side _group
,(_x getVariable ["GAIA_zone_intend",[]])
,behaviour (leader _group)
,combatmode _group
,speedmode _group
,formation _group
,_waypoints
,(_group getVariable ["MCC_GAIA_RESPAWN",-1])
, (missionNamespace getVariable [ "GAIA_RESPAWN_" + str(_group),[] ])
];
_pos = position leader _group;
MCC_GAIA_CACHE_STAGE2 = MCC_GAIA_CACHE_STAGE2+ [_pos];
_var2 = "GAIA_CACHE_" + str(_pos);
missionNamespace setVariable [_var2, _sf ];
//player globalchat format ["%1",_sf];
{deleteVehicle _x;} foreach units _group;
{deleteVehicle _x;} foreach _vehicles;
deletegroup _group;
if(!isServer ) exitWith {};
private["_count"];
while {!MCC_GAIA_CACHE}
do {
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
(count(units _x)>0)
and
(alive (leader _x))
and
((_x) getVariable ["MCC_GAIA_CACHE", false])
)
then {MCC_GAIA_CACHE=true;};
//stop
if (MCC_GAIA_CACHE) exitwith {true;};
} forEach allgroups;
//if not found go sleep
if !(MCC_GAIA_CACHE) then {sleep 20;};
//player globalchat "we wachten";
} ;
while {MCC_GAIA_CACHE} do
{
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
(count(units _x)>0)
and
(alive (leader _x))
)
then
{
//player globalchat "time to check caches";
//Cache stage 1
switch(true)do
{
//We are not cached, closest player is out of range 1, not in combat, exclude artillery and mortars
case (
!(_x getVariable ["GAIA_CACHED_STAGE_1",false])
and
!([getPosATL(leader _x),GAIA_CACHE_STAGE_1] call gaia_fn_nearPlayer)
and
(behaviour(leader _x)!="COMBAT")
and
(
(
(count(_x getVariable ["GAIA_zone_intend",[]])>1)
and
!("DoMortar" in (_x getVariable ["GAIA_Portfolio",[]]))
and
!("DoArtillery" in (_x getVariable ["GAIA_Portfolio",[]]))
)
or
(
(count(_x getVariable ["GAIA_zone_intend",[]])==0)
)
)
): { _x spawn gaia_fn_cache;};
//We are cached, player is in range 1
case (
(_x getVariable ["GAIA_CACHED_STAGE_1",false])
and
([getPosATL(leader _x),GAIA_CACHE_STAGE_1] call gaia_fn_nearPlayer)
): {_x spawn gaia_fn_uncache;};
//We are in combat, decache him at all times, no matter the range
case (
(_x getVariable ["GAIA_CACHED_STAGE_1",false])
and
(behaviour(leader _x)=="COMBAT")
): { _x spawn gaia_fn_uncache;};
default {_x spawn gaia_fn_sync;};
};
//Cache stage 2
if (
!([getPosATL(leader _x),GAIA_CACHE_STAGE_2] call gaia_fn_nearPlayer)
//and
//(behaviour(leader _x)!="COMBAT")
/*
and
(_x getVariable ["GAIA_class",""])!=""
and
!("DoMortar" in (_x getVariable ["GAIA_Portfolio",[]]))
and
!("DoArtillery" in (_x getVariable ["GAIA_Portfolio",[]]))
*/
)
then {[_x] call gaia_fn_cache_stage_2;};
};
//chill out, no rush
sleep 0.1;
} forEach ([ALLGROUPS, {_x getVariable ["mcc_gaia_cache", false]}] call BIS_fnc_conditionalSelect);
_idx = 0;
{
if ([_x,GAIA_CACHE_STAGE_2] call gaia_fn_nearPlayer)
then
{
[(missionNamespace getVariable [ "GAIA_CACHE_" + str(_x),[0,0,0]])] call gaia_fn_uncache_stage_2;
MCC_GAIA_CACHE_STAGE2 set [_idx, "delete_me"];
};
_idx= _idx + 1;
} forEach MCC_GAIA_CACHE_STAGE2;
// Delete respawned dudes
MCC_GAIA_CACHE_STAGE2 = MCC_GAIA_CACHE_STAGE2 - ["delete_me"];
//We checked allgroups so we need a break
sleep GAIA_CACHE_SLEEP;
};// F3 - Near Player Function
// Credits: Please see the F3 online manual (http://www.ferstaberinde.com/f3/en/)
// ====================================================================================
// DECLARE VARIABLES AND FUNCTIONS
private ["_ent","_distance","_pos","_players"];
_pos = (_this select 0);
_distance = _this select 1;
// ====================================================================================
// Create a list of all players
_players = [];
if (count(playableUnits)==0) then
{
_players = [player];
}
else
{
{
if (isPlayer _x) then {_players = _players + [_x]};
} forEach playableUnits;
};
// ====================================================================================
// Check whether a player is in the given distance - return true if yes
if (({_x distance _pos < _distance} count _players) > 0) exitWith {true};
false;private ["_count"];
_count = 0;
if (!(simulationEnabled (leader _this))) then {
private ["_x"];
_x = leader _this;
_x allowDamage true;
_x enableSimulation true;
_x enableAI "TARGET";
_x enableAI "AUTOTARGET";
_x enableAI "MOVE";
_x enableAI "ANIM";
_x enableAI "FSM";
_count = _count + 1;
};
if(!isServer) exitWith {};
private ["_count"];
_count = 0;
{
if(_x != leader _this && !("Driver" in assignedVehicleRole _x)) then {
if (vehicle _x == _x) then {
_x setPos [(formationPosition _x )select 0,(formationPosition _x )select 1];
};
_x allowDamage true;
_x enableSimulation true;
_x enableAI "TARGET";
_x enableAI "AUTOTARGET";
_x enableAI "MOVE";
_x enableAI "ANIM";
_x enableAI "FSM";
//_x hideObject false;
//if (vehicle _x != _x) then {(vehicle _x) hideObject false};
_count = _count + 1;
};
} forEach units _this;
_this setVariable ["GAIA_CACHED_STAGE_1",false, false];if(!isServer) exitWith {};
_sf = _this select 0 select 0;
_respawn = _this select 1;
_cache = _this select 2;
_zoneIntend = _this select 3;
if (_respawn >=0) then
{
_uv = [];
_crew = [];
_gv = [];
_group = creategroup (_sf select 2);
if (isnull _group) exitwith {};
_group setVariable ["GAIA_zone_intend", _zoneIntend,true];
_group setVariable ["mcc_gaia_cache", _cache];
_group setVariable ["MCC_GAIA_RESPAWN", (_respawn-1)];
//Create Vehicles in group
{
_veh = _x;
//_cv = (_veh select 0) createvehicle (_veh select 1);
_cv = createVehicle [(_veh select 0), (_veh select 1), [], 0, "CAN_COLLIDE"] ;
//_cv setPosasl (_veh select 1);
_cv setdamage (_veh select 2);
_cv setfuel (_veh select 3);
_cv setdir (_veh select 5);
{
_un = _group createUnit [(_x select 0), (_x select 1), [], 0, "FORM"] ;
_un setdamage (_x select 2);
_un setskill (_x select 3);
_un setrank (_x select 4);
//_un setdir (_x select 6);
_role = (_x select 5);
if ((_role select 0) == "Driver") then
{_un moveInDriver _cv ; };
if ((_role select 0) == "Turret") then
{_un moveInTurret [_cv, (_role select 1)]; };
if ((_role select 0) == "Cargo") then
{_un assignAsCargo _cv; };
} foreach (_veh select 4);
_group setFormDir (_veh select 5);
} foreach (_sf select 0);
//Create Infantry in group
{
//player globalchat format [" going %1",(_x select 0)];
//_un=(_x select 0) createUnit [(_x select 1), _group,"",(_x select 3),(_x select 4)];
_un = _group createUnit [(_x select 0), (_x select 1), [], 0, "CAN_COLLIDE"] ;
_un setdamage (_x select 2);
_un setskill (_x select 3);
_un setrank (_x select 4);
_un setPosasl (_x select 1);
_un setdir (_x select 5);
} foreach (_sf select 1);
_group setspeedmode (_sf select 6);
_group setformation (_sf select 7);
_group setbehaviour (_sf select 4);
_group setcombatmode (_sf select 5);
// Clear all way points
while {(count (waypoints _group)) > 0} do
{
deleteWaypoint ((waypoints _group) select 0);
};
if (count (_sf select 8)>1) then
{
_array = (_sf select 8) select 0;
_current = (_sf select 8) select 1;
{
private "_waypoint";
if (( (_x select 0) distance [0,0,0])>0) then
{
_waypoint = _group addwaypoint [(_x select 0), 0];
_waypoint setwaypointtype (_x select 1);
_waypoint setwaypointbehaviour (_x select 2);
_waypoint setwaypointspeed (_x select 3);
_waypoint setwaypointcombatmode (_x select 4);
_waypoint setwaypointformation (_x select 5);
_waypoint setwaypointstatements (_x select 6);
_waypoint setwaypointtimeout (_x select 7);
_waypoint setwaypointhouseposition (_x select 8);
};
} foreach _array;
_group setcurrentwaypoint [_group,_current];
};
};if(!isServer) exitWith {};
_sf = _this select 0;
_uv = [];
_crew = [];
_gv = [];
_group = creategroup (_sf select 2);
if (isnull _group) exitwith {};
_group setVariable ["GAIA_zone_intend", (_sf select 3),true];
_group setVariable ["MCC_GAIA_RESPAWN", (_sf select 9),true];
//Now the trick is to restore the original group variable before we got cached.
_var2 = "GAIA_RESPAWN_" + str(_group);
missionNamespace setVariable [_var2, (_sf select 10)];
//I gues we were cached, because we just got uncached.
_group setVariable ["mcc_gaia_cache", true,true];
//Create Vehicles in group
{
_veh = _x;
//_cv = (_veh select 0) createvehicle (_veh select 1);
_cv = createVehicle [(_veh select 0), (_veh select 1), [], 0, "CAN_COLLIDE"] ;
//_cv setPosasl (_veh select 1);
_cv setdamage (_veh select 2);
_cv setfuel (_veh select 3);
_cv setdir (_veh select 5);
{
_un = _group createUnit [(_x select 0), (_x select 1), [], 0, "FORM"] ;
_un setdamage (_x select 2);
_un setskill (_x select 3);
_un setrank (_x select 4);
//_un setdir (_x select 6);
_role = (_x select 5);
if ((_role select 0) == "Driver") then
{_un moveInDriver _cv ; };
if ((_role select 0) == "Turret") then
{_un moveInTurret [_cv, (_role select 1)]; };
if ((_role select 0) == "Cargo") then
{_un assignAsCargo _cv; };
} foreach (_veh select 4);
_group setFormDir (_veh select 5);
} foreach (_sf select 0);
//Create Infantry in group
{
//player globalchat format [" going %1",(_x select 0)];
//_un=(_x select 0) createUnit [(_x select 1), _group,"",(_x select 3),(_x select 4)];
_un = _group createUnit [(_x select 0), (_x select 1), [], 0, "CAN_COLLIDE"] ;
_un setdamage (_x select 2);
_un setskill (_x select 3);
_un setrank (_x select 4);
_un setPosasl (_x select 1);
_un setdir (_x select 5);
} foreach (_sf select 1);
_group setspeedmode (_sf select 6);
_group setformation (_sf select 7);
_group setbehaviour (_sf select 4);
_group setcombatmode (_sf select 5);
// Clear all way points
while {(count (waypoints _group)) > 0} do
{
deleteWaypoint ((waypoints _group) select 0);
};
if (count (_sf select 8)>1) then
{
_array = (_sf select 8) select 0;
_current = (_sf select 8) select 1;
{
private "_waypoint";
if (( (_x select 0) distance [0,0,0])>0) then
{
_waypoint = _group addwaypoint [(_x select 0), 0];
_waypoint setwaypointtype (_x select 1);
_waypoint setwaypointbehaviour (_x select 2);
_waypoint setwaypointspeed (_x select 3);
_waypoint setwaypointcombatmode (_x select 4);
_waypoint setwaypointformation (_x select 5);
_waypoint setwaypointstatements (_x select 6);
_waypoint setwaypointtimeout (_x select 7);
_waypoint setwaypointhouseposition (_x select 8);
};
} foreach _array;
_group setcurrentwaypoint [_group,_current];
};
/* ----------------------------------------------------------------------------
Function: fnc_AddGroupToGAIA
Description:
This function sets the group under GAIA control for the given side and the given intend.
Parameters:
- Group
_ zone
_ intend
Returns:
true
Author:
Spirit, 7-1-2014
---------------------------------------------------------------------------- */
private ["_group","_zone","_intend"];
_group = _this select 0;
_zone = _this select 1;
_intend = _this select 2;
_group setVariable ["GAIA_ZONE_INTEND",[_zone,_intend], false];
true;//==================================================================fnc_countUnit===============================================================================================
// Count the assets of a unit (at, aa etc) based on ammo (better then guns as guns dont kill)
// Flaw: the ammo carrier that does not have the gun will still be counted as the type of ammo it carries
// Example: [unit/vehicle] call fnc_countUnit;
// By Spirit 8-1-2014
//===========================================================================================================================================================================
private ["_unit","_MagazinesUnit","_ammo"];
_unit = _this select 0;
_MagazinesUnit=[];
_MagazinesUnit=(magazines _unit );
_at =false;//Is Anti tank
_aal=false;//Is Anti Air Light (Bullet based)
_aah=false;//Is Anti Air Heavy (rocket/launcher based) -> airlock
_art=false;//Is Artillery
_found_AT_stuff = false;
//_MagazinesUnit set [count _MagazinesUnit,(currentMagazine _unit)];
{
_irlock = 0;_laserlock=0;_airlock=0;_artilleryLock=0;
_ammo = tolower gettext (configFile >> "CfgMagazines" >> _x >> "ammo");
_irlock = getNumber (configfile >> "CfgAmmo" >> _ammo >> "irLock");
_laserlock = getNumber (configfile >> "CfgAmmo" >> _ammo >> "laserLock");
_airlock = getNumber (configfile >> "CfgAmmo" >> _ammo >> "airLock");
_airlock = getNumber (configfile >> "CfgAmmo" >> _ammo >> "airLock");
_artilleryLock = getNumber (configfile >> "CfgAmmo" >> _ammo >> "artilleryLock");
if (_airlock==1 and (_ammo iskindof "BulletBase")) then
{_aal=true;};
if (_airlock==2 and !(_ammo iskindof "BulletBase")) then
{_aah=true;};
if (
(_irlock>0 or _laserlock>0)
and
_airlock==0
and
( (_ammo iskindof "RocketBase")
or
(_ammo iskindof "MissileBase")
)
or
(_ammo iskindof "ShellBase" and _artilleryLock==0 )
)
then
{_at=true;};
if (_artilleryLock==1 and !(_ammo iskindof "BulletBase")) then
{_art=true;};
//Fail safe. If non of the above is true, we possible form still some AT stuff. Most likely non guide AT. So set him up.
if (
(_ammo iskindof "RocketBase")
or
(_ammo iskindof "MissileBase")
) then
{_found_AT_stuff = true;};
} foreach _MagazinesUnit;
//Ok this is absolutely crap. It needs more attention but for now it is the best show. If only the config was filled correctly by all.... Needs dynamic.
if ((!_at and !_aah and !_art)
and
_found_AT_stuff
)
then
{
_at = true;
};
[_at,_aal,_aah,_art]
/*
babba= [units group player] call fnc_countgroup;abba = [units group player] call fnc_gaia_Classifygroup; cabba = [vehicle player] call fnc_countunit;
*/
//==================================================================MCC_fnc_countGroup===============================================================================================
//
//
//
//===========================================================================================================================================================================
private ["_units","_class"];
_units = _this select 0;
_class = "";
//[_infantryCount,_vehicleCount,_tankCount,_artilleryCount,_airCount,_shipCount,_reconCount,_supportCount,_autonomousCount,_staticCount,_submarineCount
//,[_CarClass,_tankClass,_artilleryClass,_airClass,_boatClass,_supportClass,_autonomousClass]
//,[_at,_aal,_aah]];
_Assets = [_units] call fnc_CountUnitTypes;
_infantryCount = _Assets select 0;
_reconCount = _Assets select 6;
_CarCount = _Assets select 1;
_tankCount = _Assets select 2;
_artilleryCount = _Assets select 3;
_airCount = _Assets select 4;
_shipCount = _Assets select 5;
_supportCount = _Assets select 7;
_autonomousCount = _Assets select 8;
_staticCount = _Assets select 9;
_submarineCount = _Assets select 10;
_AACount = _Assets select 11;
_CargoCount = _Assets select 12;
_MortarCount = _Assets select 13;
//What is the total shit we got
_totalCount = _infantryCount+_CarCount+_tankCount+_artilleryCount+_airCount+_shipCount+_reconCount+_supportCount+_autonomousCount+_staticCount+_submarineCount+_AACount+_mortarcount;
//We have enough cargo for all units? Important to load / unload shit and affects the speed.
_EnoughCargo = (_cargocount >= (_infantryCount+_reconCount));
//Do the vehicles have gun? Affects points and also the possible portfolio of commands
_NrOfVehicleGuns = 0;
_DoClear = ['DoClear'];
_DoPatrol = ['DoPatrol'];
_DoRecon = ['DoRecon'];
_DoAttack = ['DoAttack'];
_DoHide = ['DoHide'];
_DoMortar = ['DoMortar'];
_DoArtillery = ['DoArtillery'];
_DoTransport = ['DoTransport'];
_DoCAS = ['DoCAS'];
_DoSupport = ['DoSupport'];
_DoGuard = ['DoGuard'];
_DoPark = ['DoPark'];
_DoWait = ['DoWait'];
_portfolio = [];
//For the sake of humanity, check the guns of the vehicle,
//How many times have we seen empty jeeps charge the field?
{
if (count(_x) > 0) then
{
{
_NrOfVehicleGuns = _NrOfVehicleGuns + (_x select 2);
} forEach (_x);
};
} forEach (_assets select 14);
_VehicleHasGuns = (_NrOfVehicleGuns>0);
_points = 0;
if (_totalCount >0) then
{
//This is the most basic point system ever. At a later version we go checkout if a car is more then just a car -> weapons, at etc. For now, this is it.
_points =(_infantryCount * 2)
+(_CarCount *5)
+(_tankCount *10)
+(_artilleryCount * 5)
+(_airCount * 20)
+(_shipCount * 10)
+(_reconCount * 3)
+(_supportCount * 1)
+(_autonomousCount * 0)
+(_staticCount * 4)
+(_submarineCount * 0)
+(_AACount * 5)
+(_Mortarcount * 5)
+(_NrOfVehicleGuns * 5);
};
//The default speed
_speed = "SLOW";
//The class system is far from ready. But it is a first shot, not even half of the conclusions from the above are in there.
switch(true)do
{
//Infantry
case (_infantryCount == _totalCount):
{
_class = "Infantry";
//_speed = "SLOW";
_portfolio = _portfolio + _DoClear;
_portfolio = _portfolio + _DoAttack;
_portfolio = _portfolio + _DoPatrol;
};
//Recon infantry
case (_reconCount == _totalCount):
{
_class = "ReconInfantry";
_portfolio = _portfolio + _DoClear;
_portfolio = _portfolio + _DoAttack;
_portfolio = _portfolio + _DoPatrol;
};
//Mixed infantry -> Infantry
case (_reconCount+_infantryCount == _totalCount):
{
_class = "Infantry";
_portfolio = _portfolio + _DoClear;
_portfolio = _portfolio + _DoAttack;
_portfolio = _portfolio + _DoPatrol;
};
// Mortar
case (_Mortarcount == _totalCount):
{
_class = "Mortar";
_portfolio = _portfolio + _DoMortar;
};
//AA If we holde infantry, recon, vehicles then we consider it guards.
case ((_AACount > 0)and (_tankCount==0)):
{
_class = "AA";
if (_EnoughCargo) then {_speed = "MEDIUM";};
_portfolio = _portfolio + _DoHide;
};
//Car
case (_CarCount == _totalCount):
{
_class = "Car";
if (_EnoughCargo) then {_speed = "MEDIUM";};
//No guns but do hold space? We are a transporter
if (!_VehicleHasGuns and _EnoughCargo ) then
{
_portfolio = _portfolio + _DoTransport;
_portfolio = _portfolio + _DoPark;
};
//Please, for the love of god check if we have guns before we charge in.
if (_VehicleHasGuns) then
{
_portfolio = _portfolio + _DoAttack;
_portfolio = _portfolio + _DoPatrol;
};
};
//Motorized Recon
case (_CarCount+_reconCount == _totalCount) :
{
_class = "MotorizedRecon";
if (_EnoughCargo) then {_speed = "MEDIUM";};
_portfolio = _portfolio + _DoPatrol;
_portfolio = _portfolio + _DoAttack;
};
//Motorized Infantry
case ((_CarCount+_infantryCount+ _reconCount == _totalCount)) :
{
_class = "MotorizedInfantry";
if (_EnoughCargo) then {_speed = "MEDIUM";};
_portfolio = _portfolio + _DoPatrol;
_portfolio = _portfolio + _DoAttack;
};
// Tanky Spanky. Also mixed with mobile AA is considered a TANK group. As soon as they loose their tanks -> AA
case (_tankCount+_AACount == _totalCount):
{
_class = "Tank";
if (_EnoughCargo) then {_speed = "MEDIUM";};
//For now i dont want tanks to patrol. Do needs a better option in a later version.
_portfolio = _portfolio + _DoHide;
//If we failed to see our tank class but it holds no guns, then please dont let it attack.
if (_VehicleHasGuns) then
{
_portfolio = _portfolio + _DoAttack;
};
//For now set on 5. I think just a few seats wont make it a transporter.
if (_CargoCount>5) then
{
_portfolio = _portfolio + _DoTransport;
};
};
//Mechanized inf (we dont acknowledge recon
case (_tankCount+_infantryCount+ _reconCount == _totalCount) :
{
_class = "MechanizedInfantry";
if (_EnoughCargo) then {_speed = "MEDIUM";};
_portfolio = _portfolio + _DoPatrol;
_portfolio = _portfolio + _DoAttack;
};
//If there is ARtillery, there is artillery. Rest is guard, but the group behaves like arty
case (_artilleryCount > 0):
{
_class = "Artillery";
if (_EnoughCargo) then {_speed = "MEDIUM";};
_portfolio = _portfolio + _DoHide;
_portfolio = _portfolio + _DoArtillery;
};
//This conclusion is incorrect, but sufficient for first release. We handle planes and jets in next release.
case (_airCount == _totalCount):
{
_class = "Helicopter";
_speed = "FAST";
_portfolio = _portfolio + _DoWait;
//No guns but do hold space? We are a transporter
if (!_VehicleHasGuns and _EnoughCargo ) then
{
_portfolio = _portfolio +_DoPatrol;
};
//Please, for the love of god check if we have guns before we charge in.
if (_VehicleHasGuns) then
{
_portfolio = _portfolio + _DoAttack;
};
};
//Ship
case (_shipCount == _totalCount):
{
_class = "Ship";
_speed = "MEDIUM";
_portfolio = _portfolio + _DoPatrol;
//It speaks for itself that they only Do Attack and Do Clear water locations.
if (_VehicleHasGuns) then
{
_portfolio = _portfolio + _DoAttack;
_portfolio = _portfolio + _DoClear;
};
};
//Motorized Recon
case ((_CarCount+_reconCount == _totalCount) and (_CarCount>0) and (_reconCount>0)) :
{
_class = "MotorizedInfantry";
if (_EnoughCargo) then {_speed = "MEDIUM";};
_portfolio = _portfolio + _DoPatrol;
_portfolio = _portfolio + _DoAttack;
_portfolio = _portfolio + _DoClear;
};
//We have a support unit? Then the whole group is support. Basta
case (_supportCount > 0):
{
_class = "Support";
_portfolio = _portfolio + _DoHide;
_portfolio = _portfolio + _DoSupport;
};
//Support . This version has no clue what to do with this shit. We just go do nothing i gues. Forget about this boys.
case (_autonomousCount == _totalCount):
{
_class = "Autonomous";
_speed = "SLOW";
_portfolio = _portfolio + _DoWait;
//No guns but do hold space? We are a transporter
if (!_VehicleHasGuns and _EnoughCargo ) then
{
_portfolio = _portfolio +_DoPatrol;
};
//Please, for the love of god check if we have guns before we charge in.
if (_VehicleHasGuns) then
{
_portfolio = _portfolio + _DoAttack;
};
};
//Static gun.
case (_staticCount >0 ):
{
_class = "Static";
_speed = "STATIC";
_portfolio = _portfolio + _DoGuard;
};
//Submarine
case (_submarineCount == _totalCount):
{
//Later version might make them to transports. Now this is it.
_class = "Submarine";
_speed = "MEDIUM";
_portfolio = _portfolio + _DoPatrol;
};
//This is the 'what the hell did you give me support'. If we have no clue what it is. Then just let it do what it is good at.
default
{
_class = "Unknown";
if (_EnoughCargo) then {_speed = "MEDIUM";};
_portfolio = _portfolio + _DoPatrol;
//If we have infantry, recon's or vehicles with guns, its ok.
if (_VehicleHasGuns or (_reconCount>0) or (_infantryCount>0)) then
{
_portfolio = _portfolio + _DoAttack;
_portfolio = _portfolio + _DoClear;
};
};
};
[_Class,_speed,_points,_portfolio,_CargoCount]//==================================================================MCC_fnc_countGroup===============================================================================================
// Count the number of infantry, vehicles, tank, air, ships in a group expand
// Example: [_group1] call MCC_fnc_countGroup;
// _group1 = group, the group name
//===========================================================================================================================================================================
private ["_group","_infantryCount","_CarCount","_tankCount","_airCount","_shipCount","_CarClass",
"_SoldierCargo","_tankClass","_airClass","_boatClass","_vehicleClass","_reconCount","_supportClass","_supportCount","_autonomousCount","_autonomousClass"
,"_staticCount","_staticClass","_submarineCount","_submarineClass","_TurretWeapons"];
_units = _this select 0;
_infantryCount = 0;
_reconCount = 0;
_mortarCount =0;
_CarCount = 0;
_tankCount = 0;
_supportCount = 0;
_airCount = 0;
_shipCount = 0;
_artilleryCount = 0;
_AACount = 0;
_autonomousCount = 0;
_staticCount = 0;
_submarineCount = 0 ;
_CargoCount =0;
_MortarCount =0;
_tempVehicles = [];
_CarClass = [];
_tankClass = [];
_artilleryClass = [];
_AAClass = [];
_supportClass = [];
_airClass = [];
_boatClass = [];
_autonomousClass = [];
_staticClass =[];
_mortarClass =[];
_submarineClass = [];
_UnitAssets = [];
_at =false;
_aa =false;
_art =false;
if (! isnil "_units") then {
{
if (alive _x) then
{
_vehicleClass = tolower (gettext (configFile >> "CfgVehicles" >> typeof (assignedVehicle _x) >> "vehicleClass"));
if ((assignedVehicle _x) != _x) then
{
if (!((assignedVehicle _x) in _tempVehicles) and !(_x in (assignedCargo assignedVehicle _x))) then {
_tempVehicles set [count _tempVehicles, vehicle _x];
_SoldierCargo = getNumber (configFile >> "CfgVehicles" >> typeof (assignedVehicle _x) >> "transportSoldier");
_CargoCount = _CargoCount + _SoldierCargo;
_TurretWeapons = (typeof (assignedVehicle _x)) call fnc_GetTurretsWeapons;
_at =false;_aa =false;_art =false;
_UnitAssets = [assignedVehicle _x] call fnc_AnalyseUnit;
if (_UnitAssets select 0) then {_at = true};
if (_UnitAssets select 2) then {_aa = true};
if (_UnitAssets select 3) then {_art = true};
if (_vehicleClass == "car") then
{
_CarCount = _CarCount + 1;
_CarClass set [count _CarClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
};
if (_vehicleClass == "armored") then
{
if (_art) then
{
_artilleryCount = _artilleryCount + 1;
_artilleryClass set [count _artilleryClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
}
else
{
if (_aa) then
{
_AACount = _AACount + 1;
_AAClass set [count _AAClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
}
else
{
_tankCount = _tankCount + 1;
_tankClass set [count _tankClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
};
};
};
if (_vehicleClass == "support" ) then //support
{
_supportCount = _supportCount + 1;
_supportClass set [count _supportClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
};
if (_vehicleClass == "static" and !_art ) then //support
{
_staticCount = _staticCount + 1;
_staticClass set [count _staticClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
};
if (_vehicleClass == "static" and _art ) then //support
{
_MortarCount = _staticCount + 1;
_MortarClass set [count _MortarClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
};
if (_vehicleClass == "air") then
{
_airCount = _airCount + 1;
_airClass set [count _airClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
};
if (_vehicleClass == "ship") then
{
_shipCount = _shipCount + 1;
_boatClass set [count _boatClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
};
if (_vehicleClass == "submarine") then
{
_submarineCount = _submarineCount + 1;
_submarineClass set [count _submarineClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
};
if (_vehicleClass == "autonomous") then //atunomos
{
_autonomousCount = _autonomousCount + 1;
_autonomousClass set [count _autonomousClass,[typeof(assignedVehicle _x),_SoldierCargo,count(_TurretWeapons)]];
};
};
};
_vehicleClass = tolower (gettext (configFile >> "CfgVehicles" >> typeof ( _x) >> "vehicleClass"));
_at =false;_aa =false;_art =false;
_UnitAssets = [vehicle _x] call fnc_Analyseunit;
if (_UnitAssets select 0) then {_at = true};
if (_UnitAssets select 2) then {_aa = true};
if (_UnitAssets select 3) then {_art = true};
if (
(format["%1", (assignedVehicleRole _x)]=="[]")
or
(format["%1", (assignedVehicleRole _x)]=='["Cargo"]')
)
then
{
if (_vehicleClass == "men" || _vehicleClass == "menstory" || _vehicleClass == "mensupport") then {_infantryCount = _infantryCount + 1};
if (_vehicleClass == "mendiver" || _vehicleClass == "menrecon" || _vehicleClass == "mensniper") then {_reconCount = _reconCount + 1};
};
};
} foreach _units;
[_infantryCount,_CarCount,_tankCount,_artilleryCount,_airCount,_shipCount,_reconCount,_supportCount,_autonomousCount,_staticCount,_submarineCount,_AACOUNT,_CargoCount,_MortarCount,[_CarClass,_tankClass,_artilleryClass,_airClass,_boatClass,_supportClass,_autonomousClass,_AAClass,_MortarClass],[_at,_aa]];
};
/* ----------------------------------------------------------------------------
TODO: ALL
Function: CBA_fnc_addWaypoint
Description:
A function used to add a waypoint to a group.
Parameters:
- Group (Group or Object)
- Position (XYZ, Object, Location or Group)
Optional:
- Radius (Scalar)
- Waypoint Type (String)
- Behaviour (String)
- Combat Mode (String)
- Speed Mode (String)
- Formation (String)
- Code To Execute at Each Waypoint (String)
- TimeOut at each Waypoint (Array [Min, Med, Max])
- Waypoint Completion Radius (Scalar)
Example:
(begin example)
[this, this, 300, "MOVE", "AWARE", "YELLOW", "FULL", "STAG COLUMN", "this spawn CBA_fnc_searchNearby", [3,6,9]]
(end)
Returns:
Waypoint
Author:
Rommel
---------------------------------------------------------------------------- */
private ["_group","_position","_radius"];
_group = (_this select 0) call CBA_fnc_getgroup;
_position = (_this select 1) call CBA_fnc_getpos;
_radius = if (count _this > 2) then {_this select 2} else {0};
private ["_count", "_waypoint"];
_count = count _this;
_waypoint = _group addWaypoint [_position, _radius];
if (_count < 4) exitWith {_waypoint};
_waypoint setWaypointType (_this select 3);
if (_count < 5) exitWith {_waypoint};
_waypoint setWaypointBehaviour (_this select 4);
if (_count < 6) exitWith {_waypoint};
_waypoint setWaypointCombatMode (_this select 5);
if (_count < 7) exitWith {_waypoint};
_waypoint setWaypointSpeed (_this select 6);
if (_count < 8) exitWith {_waypoint};
_waypoint setWaypointFormation (_this select 7);
if (_count < 9) exitWith {_waypoint};
_waypoint setWaypointStatements ["TRUE", (_this select 8)];
if (_count < 10) exitWith {_waypoint};
_waypoint setWaypointTimeout (_this select 9);
if (_count < 11) exitWith {_waypoint};
_waypoint setWaypointHousePosition (_this select 10);
if (_count < 12) exitWith {_waypoint};
_waypoint setWaypointCompletionRadius (_this select 11);
_waypoint;
// Return the closest position from array to the positionA.
// In: [positionA,[array of positions]]
// Out: positionB
private ["_pA","_ps","_p1","_p2"];
_pA = _this select 0;
_ps = _this select 1;
_p1 = _ps select 0;
if (count _ps > 1) then {
for "_i" from 1 to (count _ps - 1) do {
_p2 = _ps select _i;
if ((_p2 distance _pA) < (_p1 distance _pA)) then {
_p1 = _p2;
};
};
};
_p1/*
Fire a flare up in the sky
Start: The start position of the flare
- (ARRAY)
End: The end position of the flare
- (ARRAY)
Horizontal Speed: The added horizontal speed to the flare
- (NUMBER)
Vertical Speed: The added vertical speed to the flare
- (NUMBER)
Class: The flare class
- (STRING)
*/
//Params
private ["_start", "_end", "_horizontalSpeed", "_verticalSpeed"];
_start = [_this, 0, [0,0,0], [[]]] call BIS_fnc_param;
_end = [_this, 1, [0,0,0], [[]]] call BIS_fnc_param;
_horizontalSpeed = [_this, 2, 5, [0]] call BIS_fnc_param;
_verticalSpeed = [_this, 3, 30, [0]] call BIS_fnc_param;
//The flare class name
private "_class";
_class = [
"F_40mm_Cir",
"F_40mm_Green",
"F_40mm_Red",
"F_40mm_White",
"F_40mm_Yellow"
] call BIS_fnc_selectRandom;
//The moving direction of the flare
private "_direction";
_direction = [_start, _end] call BIS_fnc_dirTo;
//The flare
private "_flare";
_flare = _class createVehicle _start;
//Add motion
_flare setVelocity [
sin _direction * _horizontalSpeed,
cos _direction * _horizontalSpeed,
_verticalSpeed
];
//Flare weapon firing sound
_flare say3D "SN_Flare_Weapon_Fired";
//Flare sounds
_flare spawn {
sleep 0.5;
//The sound of the flare starting to burn
_this say3D "SN_Flare_Fired_4";
sleep 1;
//The flare burning loop sound
while { !isNull _this } do {
_this say3D "SN_Flare_Loop";
sleep 4;
};
//Log
"Flare stopped burning!" call BIS_fnc_log;
};
//Log
["Flare %1 (%2) fired! Start: %3 - End: %4 - Direction: %5 - Horizontal Speed: %6 - Vertical Speed: %7", _class, _flare, _start, _end, _direction, _horizontalSpeed, _verticalSpeed] call BIS_fnc_logFormat;
//Return value
_flare;if (!isServer) exitWith {};
private [ "_condition", "_targetlist", "_mklist", "_ActualTargets", "_cntC", "_target", "_mkname", "_i","_vehicleClass","_Handle","_gaiaunitsfound"];
_HQ_side = _this select 0;
_mklist = [];
//GAIA is down
switch (_HQ_side) do
{
case west : {MCC_GAIA_OPERATIONAL_WEST = FALSE;};
case east : {MCC_GAIA_OPERATIONAL_EAST = FALSE;};
case independent: {MCC_GAIA_OPERATIONAL_INDEP = FALSE;};
};
//
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase 0: GAIA never dies, even if all her units are destroyed. All HAIL GAIA!
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
if (MCC_GAIA_DEBUG) then{[_HQ_side,"HQ"] sideChat format ["Waking up GAIA...............%1",_HQ_side]; };
Sleep 2;
while {true} do
{
// This code checks if GAIA units are there (the code sucs as it was produced fast)
_gaiaunitsfound = false;
while {!_gaiaunitsfound}
do {
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _HQ_side)
and
(count(units _x)>0)
and
(alive (leader _x))
and
(count(_x getVariable ["GAIA_zone_intend",[]])>1)
)
then {_gaiaunitsfound=true;};
//stop
if (_gaiaunitsfound) exitwith {true};
} forEach allgroups;
//if not found go sleep
if !(_gaiaunitsfound) then {sleep 20;};
} ;
//GAIA IS A GO!
if (MCC_GAIA_DEBUG) then{[_HQ_side,"HQ"] sideChat format ["GAIA %1 wakes up and looks around the place. Man what a night. Time to destroy some player.",_HQ_side]; };
while { ( {side _x == _HQ_side } count allunits > 0 ) } do
{
MCC_GAIA_CYCLE = MCC_GAIA_CYCLE + 1;
publicVariable "MCC_GAIA_CYCLE" ;
//vlag setvariable ['gaia_cycle',MCC_GAIA_CYCLE,true];
GAIA_CACHE_STAGE_2 = (2*GAIA_CACHE_STAGE_1);
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase: Analyze Enemy
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
if (MCC_GAIA_DEBUG) then{[_HQ_side,"HQ"] sideChat format["Analyze Target...............................%1",_HQ_side]; };
_mklist = [_HQ_side,_mklist] call fnc_GAIA_AnalyzeTargets;
sleep 1;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase: Organise Contact Area's (CA's)
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
if (MCC_GAIA_DEBUG) then{[_HQ_side,"HQ"] sideChat format["Organise Contact Areas.......................%1",_HQ_side]; };
_dummy = [_HQ_side] CALL fnc_GAIA_ConflictAreas;
sleep 1;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase: Analyze GAIA Forces and Zones
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
if (MCC_GAIA_DEBUG) then{[_HQ_side,"HQ"] sideChat format["Analyze Forces...............................%1",_HQ_side]; };
_dummy = [_HQ_side] CALL fnc_GAIA_AnalyzeForces;
sleep 1;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase: Classify GAIA controlled groups
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
if (MCC_GAIA_DEBUG) then{[_HQ_side,"HQ"] sideChat format["Classify GAIA controlled groups...............%1",_HQ_side]; };
_dummy = [_HQ_side] CALL fnc_GAIA_Classify;
sleep 1;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase: Issue Orders
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
if (MCC_GAIA_DEBUG) then{[_HQ_side,"HQ"] sideChat format["Issue Orders.,,,,,,,,,,,,,,,,,,,..............%1",_HQ_side]; };
_dummy = [_HQ_side] CALL fnc_GAIA_IssueOrders;
sleep 1;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase: Sleep
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
if (MCC_GAIA_DEBUG) then{[_HQ_side,"HQ"] sideChat format["Sleep........................................%1",_HQ_side]; };
uisleep MCC_GAIA_SHARETARGET_DELAY;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase: Operational!
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
switch (_HQ_side) do
{
case west : {MCC_GAIA_OPERATIONAL_WEST = TRUE;};
case east : {MCC_GAIA_OPERATIONAL_EAST = TRUE;};
case independent: {MCC_GAIA_OPERATIONAL_INDEP = TRUE;};
};
};
//GAIA is down
switch (_HQ_side) do
{
case west : {MCC_GAIA_OPERATIONAL_WEST = FALSE;};
case east : {MCC_GAIA_OPERATIONAL_EAST = FALSE;};
case independent: {MCC_GAIA_OPERATIONAL_INDEP = FALSE;};
};
};
true/* ----------------------------------------------------------------------------
Function: fnc_GAIA_AnalyzeForces.sqf
Description:
Updates all GAIA controlled groups (MCC_GAIA_GROUPS_%SIDE%)
Updates the active zones (zones that still hold units) (MCC_GAIA_ZONES_%SIDE)
Updates the status of zones (MCC_GAIA_ZONESTATUS_%SIDE)
Updates all the troup behaviour based on MCC_GAIA_ZONESTATUS_%SIDE.
Parameters:
- Side
Returns:
true
Author:
Spirit, 17-1-2014
---------------------------------------------------------------------------- */
private ["_side","_TempGroups","__ZoneStatus","_Targets","_TargetInZone","_TargetNear","_ParentStatus","_class"];
if (MCC_GAIA_DEBUG) then{[_HQ_side,"HQ"] sideChat format["Analyze Forces1...............................%1",_HQ_side]; };
_side = _this select 0;
_TempGroups = [];
_TempZones = [];
_gaia_zone_intend = [];
_zone = "";
_ZoneStatus = [];
_Targets = [];
_TargetInZone = false;
_TargetNear = false;
_TempTargets = [];
_ParentStatus = 0;
_ChildStatus = 0;
_ZoneBehave = [];
_ZoneIntend = [];
_gaia_LeadPos = [];
_class = "";
switch (_side) do
{
case west : {
_ZoneStatus = MCC_GAIA_ZONESTATUS_WEST;
_Targets = MCC_GAIA_TARGETS_WEST;
};
case east : {
_ZoneStatus = MCC_GAIA_ZONESTATUS_EAST;
_Targets = MCC_GAIA_TARGETS_EAST
};
case independent: {
_ZoneStatus = MCC_GAIA_ZONESTATUS_INDEP;
_Targets = MCC_GAIA_TARGETS_INDEP;
};
};
//Get all zones that still hold forces.
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _side)
and
(count(units _x)>0)
)
then
{
if (count([_x] call fnc_GetZoneIntendFomGroup)>0) then {_TempGroups = _TempGroups + [_x];};
_gaia_zone_intend = _x getVariable ["GAIA_ZONE_INTEND",[]];
if ((count _gaia_zone_intend)>0) then
{
_zone = _gaia_zone_intend select 0;
if !(_zone in _TempZones) then
{
_TempZones = _TempZones + [_Zone];
//Remember the position of the zone, so we can see if it is updated
//The issue Orders function, in phase 'cancel orders' will react on this trigger
_var = "gaia_zone_lastpos_" + _zone;
_var2 = "gaia_zone_changed_" + _zone;
if (((missionNamespace getVariable [ _var,[0,0,0]]) distance [0,0,0])>0) then
{
if ( ( (getmarkerpos _zone ) distance (missionNamespace getVariable [ _var,[0,0,0]]) )>0) then
{
missionNamespace setVariable [_var2, true ];
}
else
{
missionNamespace setVariable [_var2, false ];
};
};
missionNamespace setVariable [_var, (getmarkerpos _zone ) ];
};
};
};
} forEach AllGroups;
//Update ZONE status
_zone = "";
_TempTargets = (_Targets select 0)+(_Targets select 1)+(_Targets select 2)+(_Targets select 3);
{
//For anything we have not cleared yet, we keep the zone alarm ringing "ALL ON BOARD!"
_TargetInZone = false;
_TargetNear = false;
_Zone = _x;
if ((count(getmarkerpos _Zone))>0) then
{
for "_T" from 0 to (count(_TempTargets)-1) do
{
//Target is in the zone
if ([(position (_TempTargets select _T)),_Zone] call fnc_PosIsInMarker ) exitWith {_TargetInZone= true;};
//Check if we got a target close by (Relatively 2 times bigger then largest of x and y of the marker size)
_Dist = ((((Getmarkersize _Zone)select 0) max ((Getmarkersize _Zone)select 1))*2);
if (((position (_TempTargets select _T)) distance (getmarkerpos _Zone))<_Dist) then {_TargetNear= true;};
};
switch(true)do
{
//Status Red
case (_TargetInZone): {
_ZoneStatus set [(parseNumber _zone ),2];
if (MCC_GAIA_DEBUG and _side==(Side player)) then {_zone setMarkerColorLocal "ColorRed"};
};
//Orange
case (_TargetNear) : {
_ZoneStatus set [(parseNumber _zone ),1];
if (MCC_GAIA_DEBUG and _side==(Side player)) then {_zone setMarkerColorLocal "ColorOrange"};
};
//Green
default {
_ZoneStatus set [(parseNumber _zone ),0];
if (MCC_GAIA_DEBUG and _side==(Side player)) then {_zone setMarkerColorLocal "ColorGreen"};
};
};
};
}ForEAch _TempZones;
//Now make sure that any child zones (the ones that have a center position inside a zone) are also warned of this upcoming danger
//Ofcourse to the max level of Orange as Red is a private indication (inside your zone).
{
_zone = _x;
_ZoneBehave =([_Zone,_side] call fnc_GetZoneStatusBehavior);
_ParentStatus = (_ZoneBehave select 0);
{
_ZoneBehave =([_x,_side] call fnc_GetZoneStatusBehavior);
_ChildStatus=(_ZoneBehave select 0);
if ( _Childstatus!=2 and _ParentStatus>0 and ([(getmarkerpos _x),_Zone] call fnc_PosIsInMarker)) then
//Set the child in Orange mode as Red is a private indication (is target in zone)
{
_ZoneStatus set [(parseNumber _x ),1];
if (MCC_GAIA_DEBUG and _side==(Side player)) then {_x setMarkerColorLocal "ColorOrange"};
};
//Exclude yourself here.
}ForEAch (_TempZones - [_x]);
}ForEAch _TempZones;
//Update FORCES based on Zone Status. Be warned brother!
//For now we choose to inform only GAIA controlled groups, but why not update all?
//Also check the progress of a unit. Is he a candidate stuck unit?
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _side)
and
(count(units _x)>0)
// and
// (behaviour _x !="COMBAT")
)
then
{
//Monitor the leaders progress.
//We count the number of cycles he has not move while he did have waypoints.
_gaia_LeadPos = _x getVariable ["GAIA_LeadPosition",[]];
if (count(_gaia_LeadPos)>0) then
{
//The dude has waypoints and he has done jackshit
if ((((count (waypoints _x)) - currentWaypoint _x)>0) and (((position leader _x) distance (_gaia_LeadPos select 0))<6) )
then
{_x setVariable ["GAIA_LeadPosition", [(_gaia_LeadPos select 0),((_gaia_LeadPos select 1)+1)], false];}
else
{_x setVariable ["GAIA_LeadPosition", [(position leader _x),1], false]; };
_class = _x getVariable ["GAIA_class",[]];
/*
if ((_class in ["Infantry","ReconInfantry"]) and (behaviour leader _x !="COMBAT") and ((_gaia_LeadPos select 1)>7)) then
{(leader _x) setpos (position(([((units _x)-[leader _x])] call BIS_fnc_selectRandom)select 0))};
*/
}
else
{
_x setVariable ["GAIA_LeadPosition", [(position leader _x),1], false];
};
_ZoneIntend = [(_x)] call fnc_GetZoneIntendFomGroup;
if (count(_zoneintend)>0) then
//Zone info on group found.
{
_ZoneBehave =([(_zoneintend select 0),_side] call fnc_GetZoneStatusBehavior);
if ( count(_zonebehave)>0
and
(behaviour leader _x !="COMBAT")
and
(behaviour leader _x !="STEALTH")
and
((_x getVariable ["GAIA_Order",""])!="DoFortify")
)
then
//We even found the expected bheavior.
{
/*
_Behaviour="SAFE"; _CombatMode="GREEN"; _Formation="COLUMN"; _Speed = "LIMITED";
_Behaviour="AWARE"; _CombatMode="YELLOW"; _Formation="WEDGE"; _Speed = "NORMAL";
_Behaviour="AWARE"; _CombatMode="RED"; _Formation="VEE"; _Speed = "NORMAL";
*/
//(currentWaypoint _x) setWaypointBehaviour (_ZoneBehave select 1);
//(currentWaypoint _x) setWaypointCombatMode (_ZoneBehave select 2);
//(currentWaypoint _x) setWaypointSpeed (_ZoneBehave select 4);
//(currentWaypoint _x) setWaypointFormation (_ZoneBehave select 3);
if !([(position leader _x),((_x getVariable ["GAIA_zone_intend",[]]) select 0)] call fnc_PosIsInMarker) then
{
_x setSpeedMode "NORMAL";
_x setBehaviour "AWARE";
}
else
{
_x setSpeedMode (_ZoneBehave select 4);
_x setBehaviour (_ZoneBehave select 1);
//_x setCombatMode (_ZoneBehave select 2);
_x setFormation (_ZoneBehave select 3);
};
};
};
};
}ForEach _TempGroups;
switch (_side) do
{
case west : {
MCC_GAIA_GROUPS_WEST =_TempGroups;
MCC_GAIA_ZONES_WEST =_TempZones;
MCC_GAIA_ZONESTATUS_WEST=_ZoneStatus;
};
case east : {
MCC_GAIA_GROUPS_EAST =_TempGroups;
MCC_GAIA_ZONES_EAST =_TempZones;
MCC_GAIA_ZONESTATUS_EAST=_ZoneStatus;
};
case independent: {
MCC_GAIA_GROUPS_INDEP =_TempGroups;
MCC_GAIA_ZONES_INDEP =_TempZones;
MCC_GAIA_ZONESTATUS_INDEP=_ZoneStatus;
};
};
true;/* ----------------------------------------------------------------------------
Function: fnc_GAIA_AnalyzeForces.sqf
Description:
This fills the MCC_GAIA_GROUPS_%SIDE% for each GROUP that is under control of GAIA.
Also fills the active zones for this side.
Parameters:
- Side
Returns:
true
Author:
Spirit, 17-1-2014
---------------------------------------------------------------------------- */
private ["_side","_TempGroups","__ZoneStatus","_Targets","_TargetInZone","_TargetNear"];
_side = _this select 0;
_TempGroups = [];
_TempZones = [];
_gaia_zone_intend = [];
_zone = "";
_ZoneStatus = [];
_Targets = [];
_TargetInZone = false;
_TargetNear = false;
_TempTargets = [];
switch (_side) do
{
case west : {
_ZoneStatus = MCC_GAIA_ZONESTATUS_WEST;
_Targets = MCC_GAIA_TARGETS_WEST;
};
case east : {
_ZoneStatus = MCC_GAIA_ZONESTATUS_EAST;
_Targets = MCC_GAIA_TARGETS_EAST
};
case independent: {
_ZoneStatus = MCC_GAIA_ZONESTATUS_INDEP;
_Targets = MCC_GAIA_TARGETS_INDEP;
};
};
//Get all zones that still hold forces.
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _side)
and
(count(units _x)>0)
)
then
{
if (count([_x] call fnc_GetZoneIntendFomGroup)>0) then {_TempGroups = _TempGroups + [_x];};
_gaia_zone_intend = _x getVariable ["GAIA_ZONE_INTEND",[]];
if ((count _gaia_zone_intend)>0) then
{
_zone = _gaia_zone_intend select 0;
if !(_zone in _TempZones) then
{
_TempZones = _TempZones + [_Zone];
};
};
};
} forEach AllGroups;
//Update ZONE status
_zone = "";
_TempTargets = (_Targets select 0)+(_Targets select 1)+(_Targets select 2)+(_Targets select 3);
{
//For anything we have not cleared yet, we keep the zone alarm ringing "ALL ON BOARD!"
_TargetInZone = false;
_TargetNear = false;
_Zone = _x;
if ((count(getmarkerpos _Zone))>0) then
{
for "_T" from 0 to (count(_TempTargets)-1) do
{
//Target is in the zone
if ([(position (_TempTargets select _T)),_Zone] call fnc_PosIsInMarker ) exitWith {_TargetInZone= true;};
//Check if we got a target close by (Relatively 2 times bigger then largest of x and y of the marker size)
_Dist = ((((Getmarkersize _Zone)select 0) max ((Getmarkersize _Zone)select 1))*2);
if (((position (_TempTargets select _T)) distance (getmarkerpos _Zone))<_Dist) then {_TargetNear= true;};
};
switch(true)do
{
//Status Red
case (_TargetInZone): {
_ZoneStatus set [(parseNumber _zone ),2];
if (MCC_GAIA_DEBUG and _side==(Side player)) then {_zone setMarkerColorLocal "ColorRed"};
};
//Orange
case (_TargetNear) : {
_ZoneStatus set [(parseNumber _zone ),1];
if (MCC_GAIA_DEBUG and _side==(Side player)) then {_zone setMarkerColorLocal "ColorOrange"};
};
//Green
default {
_ZoneStatus set [(parseNumber _zone ),0];
if (MCC_GAIA_DEBUG and _side==(Side player)) then {_zone setMarkerColorLocal "ColorGreen"};
};
};
};
}ForEAch _TempZones;
//Update Child Zones of the danger.
//Update FORCES based on Zone Status
switch (_side) do
{
case west : {
MCC_GAIA_GROUPS_WEST =_TempGroups;
MCC_GAIA_ZONES_WEST =_TempZones;
MCC_GAIA_ZONESTATUS_WEST=_ZoneStatus;
};
case east : {
MCC_GAIA_GROUPS_EAST =_TempGroups;
MCC_GAIA_ZONES_EAST =_TempZones;
MCC_GAIA_ZONESTATUS_EAST=_ZoneStatus;
};
case independent: {
MCC_GAIA_GROUPS_INDEP =_TempGroups;
MCC_GAIA_ZONES_INDEP =_TempZones;
MCC_GAIA_ZONESTATUS_INDEP=_ZoneStatus;
};
};
true;if (!isServer) exitWith {};
private [ "_condition", "_targetlist", "_mklist", "_ActualTargets", "_cntC", "_target", "_mkname", "_i","_vehicleClass","_HQ_side"];
_HQ_side = _this select 0;
_mklist = _this select 1;
//If a unit has recently been within 50 meter of a target location in _tobecleared,
//then if the time he has been there is more recent then the target, its called cleared.
_ClearedDistance = 50;
//AFter this period of time the target is automaticly cleared. (will not be searched by the ai).
_TArgetAutoCleared = 1200;
//This sets how long a position of a unit is stored in the breadcrumb system.
//Each set 'breadcrumb' holds a time and a location. As long as the breadcrumb is there, it will be use dto blacklist a location for possible patrolling.
//Also will it be used to 'clear' target locations. If a unit has recently been there, then we can savely say that it is clear.
_LiveTimeBreadcrumb = 300;
_targetlist = [];
//if (MCC_GAIA_DEBUG) then{[_HQ_side,"HQ"] sideChat "Gathering Intelligence......Waitout."; };
//
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase 1: Gather TArgets, drop breadcrumbs
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
_ActualTargets = [];
_RecentTargets = [];
_OldTargets = [];
_ToBeCleared = [];
_NearTargets = [];
_OldTargetInfo = [];
_NewTargetInfo = [];
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _HQ_side)
and
(count(units _x)>0)
)
then
{
_unit = leader _x;
//sleep 2;
//player globalchat format ["%1, %2, %3",(position _unit),_unit,_x];
//Place a breadcrumb
_vehicleClass = tolower (gettext (configFile >> "CfgVehicles" >> typeof (vehicle _unit) >> "vehicleClass"));
//Except for air, as air is not 'clearing the ground'
if ((_vehicleClass != "air")) then
{
//Now where ever a unit has last been, place a breadcrumb (so even static guards).
// This is used for making the patrols as optimized as possible. We try to avoid those positions.
switch (_HQ_side) do
{
case west : {MCC_GAIA_BREADCRUMBS_WEST = MCC_GAIA_BREADCRUMBS_WEST + [[(position _unit),time]];};
case east : {MCC_GAIA_BREADCRUMBS_EAST = MCC_GAIA_BREADCRUMBS_EAST + [[(position _unit),time]];};
case independent: {MCC_GAIA_BREADCRUMBS_INDEP = MCC_GAIA_BREADCRUMBS_INDEP + [[(position _unit),time]];};
};
};
{
_Target_Pos = _x select 0;
_Target_PosAcc= _x select 5;
_Target_Side = _x select 2;
_Target = _x select 4;
if (
_Target_Side!= _HQ_side
and
((_Target_Side getFriend _HQ_side)<0.6)
and
alive(leader(group _Target))
and
!captive(_target)
and
//How sure are we? For now accuracy of 18 seems to work ok
_Target_PosAcc < 18
and
(_Target iskindof "AllVehicles")
//and
//If the lead has a clear LOS to a unit, that is valid enough (might expand later to check on all members)
//([_unit,_Target,1500] call fnc_HasLOS)
)
then
{
_Target setVariable ["GAIA_TargetInfo", [time,_Target_Pos,_Target_posAcc], false];
};
}foreach (_unit neartargets 1500);
};
} forEach AllGroups;
//
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase 3: Update Target Lists
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
//if (MCC_GAIA_DEBUG) then {[_HQ_side,"HQ"] sideChat "Updating the targetlist."; };
{
if (
(((side _x) getFriend _HQ_side)<0.6)
)
then
{
//[_HQ_side,"HQ"] sideChat "Found!";
_OldTargetInfo = [];
_targetlist = [];
_OldTargetInfo = _x getVariable ["GAIA_TargetInfo",[]];
if (count(_OldTargetInfo)>0 ) then
{
_OldTarget_Time = time - (_OldTargetInfo select 0);
switch (true) do
{
case (_OldTarget_Time<60) : {_ActualTargets = _ActualTargets + [_x];};
case (_OldTarget_Time<200) : {_RecentTargets = _RecentTargets + [_x];};
case (_OldTarget_Time<360) : {_OldTargets = _OldTargets + [_x];};
case (_OldTarget_Time<_TargetAutoCleared) : {_ToBeCleared = _ToBeCleared + [_x];};
};
};
};
} forEach allUnits+vehicles;
// Debug to be cleared case (name the unit a)
//a setVariable ["GAIA_TargetInfo", [(time -400),(position a),1], false];
//_ToBeCleared = _ToBeCleared + [a];
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase 4: Send _ToBeCleared locations to Cleared if a unit has recently been there.
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
for [{_i=0},{_i < count _ToBeCleared},{_i=_i+1}] do
{
//Get the position of this dude
_OldTargetInfo = (_ToBeCleared select _i) getVariable ["GAIA_TargetInfo",[]];
//Check if we are in clear range and if so, clear this dude
if ([(_OldTargetInfo select 1),_HQ_side ] call fnc_isCleared) then
{
(_ToBeCleared select _i) setVariable ["GAIA_TargetInfo", [(time-_TArgetAutoCleared),(_OldTargetInfo select 1),(_OldTargetInfo select 2)], false];
}
};
//
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase 5: Share Target Lists
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
switch (_HQ_side) do
{
case west : {MCC_GAIA_TARGETS_WEST = [_ActualTargets,_RecentTargets,_OldTargets,_ToBeCleared];};
case east : {MCC_GAIA_TARGETS_EAST = [_ActualTargets,_RecentTargets,_OldTargets,_ToBeCleared];};
case independent: {MCC_GAIA_TARGETS_INDEP = [_ActualTargets,_RecentTargets,_OldTargets,_ToBeCleared];};
};
//
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase 6: Clear Outdated Breadcrumps
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
switch (_HQ_side) do
{
case west : {
for [{_i=0},{_i < count MCC_GAIA_BREADCRUMBS_WEST},{_i=_i+1}] do
{
if ((time-((MCC_GAIA_BREADCRUMBS_WEST select _i) select 1))>_LiveTimeBreadcrumb) then
{
MCC_GAIA_BREADCRUMBS_WEST set [_i, "REMOVE"];
MCC_GAIA_BREADCRUMBS_WEST = MCC_GAIA_BREADCRUMBS_WEST - ["REMOVE"];
}
};
};
case east : {
for [{_i=0},{_i < count MCC_GAIA_BREADCRUMBS_EAST},{_i=_i+1}] do
{
if ((time-((MCC_GAIA_BREADCRUMBS_EAST select _i) select 1))>_LiveTimeBreadcrumb) then
{
MCC_GAIA_BREADCRUMBS_EAST set [_i, "REMOVE"];
MCC_GAIA_BREADCRUMBS_EAST = MCC_GAIA_BREADCRUMBS_EAST - ["REMOVE"];
}
};
};
case independent: {
for [{_i=0},{_i < count MCC_GAIA_BREADCRUMBS_INDEP},{_i=_i+1}] do
{
if ((time-((MCC_GAIA_BREADCRUMBS_INDEP select _i) select 1))>_LiveTimeBreadcrumb) then
{
MCC_GAIA_BREADCRUMBS_INDEP set [_i, "REMOVE"];
MCC_GAIA_BREADCRUMBS_INDEP = MCC_GAIA_BREADCRUMBS_INDEP - ["REMOVE"];
}
};
};
};
//
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Phase 7: If debug is enabled, then show markers on the map
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
if (MCC_GAIA_DEBUG and _HQ_side==(Side player)) then
{
hint format ["Actual Targets: %1, Recent Targets: %2, Old Targets: %3,TBC: %4", _ActualTargets,_RecentTargets,_OldTargets,_tobecleared];
{
deleteMarkerLocal _x;
}
foreach _mklist;
_mklist = [];
{
_mkname = "mk" + str(_x);
createMarkerLocal [_mkname, getPos _x ];
_mklist = _mklist + [_mkname];
switch true do
{
case ( _x isKindOf "Man" ) : {_mkname setMarkerTypeLocal "b_inf";};
case ( _x isKindOf "Car" ) : {_mkname setMarkerTypeLocal "c_car";};
case ( _x isKindOf "Motorcycle" ) : {_mkname setMarkerTypeLocal "b_car";};
case ( _x isKindOf "Tank" ) : {_mkname setMarkerTypeLocal "b_armor";};
case ( _x isKindOf "Air" ) : {_mkname setMarkerTypeLocal "b_air";};
case ( _x isKindOf "Ship" ) : {_mkname setMarkerTypeLocal "b_naval";};
case ( _x isKindOf "StaticWeapon" ) : {_mkname setMarkerTypeLocal "b_installation";};
};
_OldTargetInfo = _x getVariable ["GAIA_TargetInfo",[]];
_mkname setMarkerPosLocal (_OldTargetInfo select 1);
_mkname setMarkerDirLocal getDir _x;
_mkname setMarkerAlphaLocal (1 - getDammage _x);
if (_x in _ActualTargets) then {_mkname setMarkerColorLocal "ColorGreen" };
if (_x in _RecentTargets) then {_mkname setMarkerColorLocal "ColorOrange" };
if (_x in _OldTargets) then {_mkname setMarkerColorLocal "ColorRed" };
if (_x in _ToBeCleared) then {_mkname setMarkerColorLocal "ColorWhite" };
}forEach _ActualTargets+_RecentTargets+_OldTargets+_ToBeCleared;
};
_mklist
/* ----------------------------------------------------------------------------
Function: fnc_GAIA_Classify
Description:
This function classifies all groups of a certain side and saves them to group variables by set_variable.
It determines the class, speed, cost and order portfolio of a group.
Parameters:
- Side
Returns:
true
Author:
Spirit, 17-1-2014
---------------------------------------------------------------------------- */
private ["_side","_ClassifiedGroup"];
_side = _this select 0;
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _side)
and
(count(units _x)>0)
)
then
{
_ClassifiedGroup = [(units _x)] call fnc_ClassifyUnits;
if (count (_ClassifiedGroup)>0) then
{
_PreviousClass = _x getVariable ["GAIA_class","None"];
//If we set it for the first time, then set them both equal so we dont monitor a class change on first cycle.
if (_PreviousClass == "None")
then {_x setVariable ["GAIA_PreviousClass" , (_ClassifiedGroup select 0), false]}
else {_x setVariable ["GAIA_PreviousClass" , _PreviousClass, false]};
//Remember the points so we see how bad we do
_x setVariable ["GAIA_PreviousPoints" , (_x getVariable ["GAIA_points",0]), false];
//[_Class,_speed,_points,_portfolio,cargo]
_x setVariable ["GAIA_class" , (_ClassifiedGroup select 0), false];
_x setVariable ["GAIA_speed" , (_ClassifiedGroup select 1), false];
_x setVariable ["GAIA_points" , (_ClassifiedGroup select 2), false];
_x setVariable ["GAIA_portfolio" , (_ClassifiedGroup select 3), false];
_x setVariable ["GAIA_cargo" , (_ClassifiedGroup select 4), false];
};
};
} forEach AllGroups;
true;//==================================================================Conflict Area's===============================================================================================
//a=[WEST] call fnc_GAIA_ConflictAreas; PLAYER setPoS (A SELECT 1)
//
//
//===========================================================================================================================================================================
private ["_units","_class","_TargetInfo"];
_HQ_side = _this select 0;
_class = "";
_Targets = [];
_CA = [];
_Spots = [];
switch (_HQ_side) do
{
case west : {_Targets = (MCC_GAIA_TARGETS_WEST select 0)+(MCC_GAIA_TARGETS_WEST select 1)+(MCC_GAIA_TARGETS_WEST select 2);
_Spots = (MCC_GAIA_TARGETS_WEST select 3);
_CA = MCC_GAIA_CA_WEST;
};
case east : {_Targets = (MCC_GAIA_TARGETS_EAST select 0)+(MCC_GAIA_TARGETS_EAST select 1)+(MCC_GAIA_TARGETS_EAST select 2);
_Spots = (MCC_GAIA_TARGETS_EAST select 3);
_CA = MCC_GAIA_CA_EAST;
};
case independent: {_Targets = (MCC_GAIA_TARGETS_INDEP select 0)+(MCC_GAIA_TARGETS_INDEP select 1)+(MCC_GAIA_TARGETS_INDEP select 2);
_Spots = (MCC_GAIA_TARGETS_INDEP select 3);
_CA = MCC_GAIA_CA_INDEP;
};
};
// Delete all CA's that no longer hold any Targets +
// Removed spots from selection (we leave that up to clear patrols, no longer attacks
//SPOTS (so fully cleared)
{
_SelectedCA = _x;
_delete = true;
{
_TargetInfo = (_x getVariable ["GAIA_TargetInfo",[]]);
if (count(_TargetInfo)>0) then
{
_TargetPos = _TargetInfo select 1;
if ((_SelectedCA distance _TargetPos)<100) exitwith {_delete = false;}
};
}forEach (_Targets /*+_Spots*/);
if (_delete) then {_ca=_ca - [_x]};
}forEach _Ca;
// Do create a CA on each position of a target that is not in range of 200 within the next the CA
{
_TargetInfo = _x getVariable ["GAIA_TargetInfo",[]];
if !((count([_ca, {((_x distance (_TargetInfo select 1))<200)}] call BIS_fnc_conditionalSelect))>0)
then
{_ca = _ca + [(_TargetInfo select 1)]; };
}forEach _Targets;
// Order the CA's. The one who is the closest to any zone wins
//_ca=[_ca,[],{[_HQ_side,_x] CALL fnc_GetDistanceClosestZone;},"ASCEND"] call BIS_fnc_sortBy;
if (count(_ca)>0) then
{
_CA=[_CA,[],{[_HQ_side,_x] CALL fnc_GetDistanceClosestZone;}] call BIS_fnc_sortBy;
};
//Debug info about the CA's
if (MCC_GAIA_DEBUG and _HQ_side==(Side player)) then
{
{
deleteMarkerLocal _x;
}
foreach MCC_GAIA_CA_DEBUG;
MCC_GAIA_CA_DEBUG = [];
{
_marker = createMarkerLocal [str(_x), _x ];
MCC_GAIA_CA_DEBUG = MCC_GAIA_CA_DEBUG + [str(_x)];
_marker setMarkerShapeLocal "ELLIPSE";
_marker setMarkerSizeLocal [100, 100]
}forEach _CA;
};
//Give the CA to the right side
switch (_HQ_side) do
{
case west : {
MCC_GAIA_CA_WEST = _CA;
};
case east : {
MCC_GAIA_CA_EAST = _CA;
};
case independent: {
MCC_GAIA_CA_INDEP = _CA;
};
};
_ca/* ----------------------------------------------------------------------------
Function: fnc_GAIA_Issue orders.
Description:
This function sends all groups of GAIA on their new destination. May the force be with us!
Parameters:
- Side
Returns:
true
Author:
Spirit, 24-1-2014
---------------------------------------------------------------------------- */
private ["_side"
,"_CA"
,"_grp"
,"_zns"
,"_trg"
,"_tbc"
,"_CaPoints"
,"_GrpIsInCombat"
,"_SelectCAisClosesttoGroup"
,"_Grpcost"
,"_PointsSpend"
,"_NrGrpsSend"
,"_StartTimeIssueOrders"
,"_GroupIsFleeing"
,"_EnoughPointsSpend"
,"_MinimumResponseSend"
,"_NumberOfForces"
,"_CanDoClear"
,"_GroupBusy"
,"_CanAttackCA"
,"_CanDoAttack"
,"_MortarFired"
,"_CaHoldsValidTargets"
,"_IsGaiaControlled"
,"_Spot"];
_side = _this select 0;
_CA = [];
_grp = [];
_zns = [];
_trg = [];
_tbc = [];
_CaPoints = 0;
_SelectCA = [];
_GrpIsInCombat = false;
_SelectCAisClosesttoGroup = false;
_GroupBusy = false;
_IsGaiaControlled = false;
_CanDoClear = false;
_Grpcost = 0;
_PointsSpend = 0;
_NrGrpsSend = 0;
_GroupHasOrdersThisRound = false;
_GroupIsFleeing = false;
_EnoughPointsSpend = false;
_MinimumResponseSend = false;
_NumberOfForces = 0;
_Spot = [];
_CanAttackCA = false;
_CaHoldsValidTargets = false;
_CanDoAttack = false;
_mpos = [];
//Get the right side arrays in
switch (_side) do
{
case west : {
_CA = MCC_GAIA_CA_WEST;
_zns = MCC_GAIA_ZONES_WEST;
_tbc = (MCC_GAIA_TARGETS_WEST select 3)
};
case east : {
_CA = MCC_GAIA_CA_EAST;
_zns = MCC_GAIA_ZONES_EAST;
_tbc = (MCC_GAIA_TARGETS_WEST select 3)
};
case independent: {
_CA = MCC_GAIA_CA_INDEP;
_zns = MCC_GAIA_ZONES_INDEP;
_tbc = (MCC_GAIA_TARGETS_WEST select 3)
};
};
//Note the time, as this is the time where THIS round is running the show.
_StartTimeIssueOrders = time;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// CANCEL OBSOLETE ORDERS
//
// Cancel Orders of groups Attacking CA'S that no longer exist.
// Cancel all Hide orders that are in combat(so they build a new one).
// Cancel orders of a group that has changed his class.
//
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _HQ_side)
and
(count(units _x)>0)
and
(alive (leader _x))
)
then
{
//Count the current number of groups (see under for need of it).
_NumberOfForces = _NumberOfForces+ 1;
//Mortar group is firing on a CA that no longer exists
//We cancel it to simulate that the spotter has died
if (
//The Target of the mortar is no longer a CA
!((_x getVariable ["GAIA_MortarTarget",[0,0,0]]) in _ca)
and
//The order he has is indeed mortar stuff.
((_x getVariable ["GAIA_Order",""]) != "DoMorter")
and
//He has actualy opened up his mortar rounds by atleast first cycle
(_x getVariable ["GAIA_MortarRound",0]>0)
)
then {
/*player globalchat "1";*/
[_x] call fnc_RemoveWayPoints;
_x setVariable ["GAIA_MortarRound" , 0, false];
_x setVariable ["GAIA_MortarTarget" ,[0,0,0] , false];
};
//Cancel orders when the class has changed
if ((_x getVariable ["GAIA_class","None"])!=(_x getVariable ["GAIA_PreviousClass","None"]))
then {[_x] call fnc_RemoveWayPoints;/*player globalchat "2"; */};
//Chancel orders when the zone is moved, except when attacking, fortifying or in combat (combat cancel orders are later)
if (
(count(_x getVariable ["GAIA_zone_intend",[]])>1)
and
((_x getVariable ["GAIA_Order",""]) != "DoAttack")
and
((_x getVariable ["GAIA_Order",""]) != "DoFortify")
and
(behaviour(leader _x)!="COMBAT")
)
then
{
//Check if the trigger detector for changed zone is active (zee analzye forces)
if (missionNamespace getVariable [ "gaia_zone_changed_"+((_x getVariable ["GAIA_zone_intend",[]])select 0),false]) then
{
[_x] call fnc_RemoveWayPoints;
};
};
//On combined order, the group that is combined must be on same order
if (
(!isnull(_x getVariable ["GAIA_CombinedOrder",grpNull]) )
and
(_x getVariable ["GAIA_Order",""])!=((_x getVariable ["GAIA_Combinedorder",grpNull]) getVariable ["GAIA_Order",""])
)
then {
[_x] call fnc_RemoveWayPoints;
/*player globalchat "3";*/
};
//The group where i combine with must be combined to me
if (
(!isnull(_x getVariable ["GAIA_CombinedOrder",grpNull]) )
)
then {
if ((((_x getVariable ["GAIA_CombinedOrder",grpNull]))getVariable ["GAIA_CombinedOrder",grpNull])!=_x)
then {[_x] call fnc_RemoveWayPoints;/*player globalchat "4";*/};
};
// Cancel orders when unit is in combat and not doing a DoAttack
//But DONT do that if it holds the air boyx
//And not when he is in fortify
if (
((_x getVariable ["GAIA_Order",""]) != "DoAttack")
and
((_x getVariable ["GAIA_Order",""]) != "DoFortify")
and
(behaviour(leader _x)=="COMBAT")
and
!((([_HQ_side,([_CA,leader _x] call BIS_fnc_nearestPosition)] call fnc_GetCAPoints) select 0 )in ["Helicopter","Autonomous"])
)
then {[_x] call fnc_RemoveWayPoints;/*player globalchat "5"+(_x getVariable ["GAIA_Order",""]);*/};
// This order is so old, Cancel it. No clue wtf he is doing.
//Except when fortify
if (
((time - (_x getVariable ["GAIA_OrderTime",0])) > MCC_GAIA_MAX_ORDER_AGE)
and
((_x getVariable ["GAIA_Order",""]) != "DoFortify")
)
then {[_x] call fnc_RemoveWayPoints;/*player globalchat "Timeout6";*/};
//Candel DoAttack order that attacks a no longer existing CA
if (
!((_x getVariable ["GAIA_OrderPosition",[0,0,0]]) in _ca)
and
((_x getVariable ["GAIA_Order",""]) == "DoAttack")
)
then {[_x] call fnc_RemoveWayPoints;/*player globalchat "7";*/};
};
}forEach AllGroups;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// ORGANISE DEFENSIVE ORDERS (FOR NOW FORTIFY)
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _HQ_side)
and
(count(units _x)>0)
and
(alive (leader _x))
and
(count(_x getVariable ["GAIA_zone_intend",[]])>1)
and
((_x getVariable ["GAIA_Order",""]) != "DoFortify")
)
then
{
if (((_x getVariable ["GAIA_zone_intend",[]]) select 1)=="FORTIFY") then
{_dummy=[_x,(position leader _x)] call fnc_DoFortify;};
};
}forEach AllGroups;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// ORGANISE ATTACKS ON Conflict Area's (CA's)
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
{
_SelectCA = _x;
//How many groups shall we maximum send in to one conflict area? That is depending on how many ca and how many groups we command.
//Lets say not more then half the forces shoudl respond to a maximum, but 2 at a minimum (unless you have one)
//_MinimumResponse = round(random(3));
//Dynamic set max response to CA variable
//If not set, then set it (so we dont determine this each cycle again). Based on CA priority the numbers might not be met.
_CAvar = "CA" + str(_SelectCA);
_MinimumResponse = missionNamespace getVariable [_CAvar,0];
if (_MinimumResponse==0) then
{
missionNamespace setVariable [_CAvar, (round(random(2))) ];
_MinimumResponse = missionNamespace getVariable [_CAvar,1];
};
//Determine Points of current CA (with how much do we need to attack this? (already taking multipier in effect)).
_CaPoints = ([_side,_SelectCA] call fnc_GetCAPoints) select 2;
//We start with zero points spend, each attacking group has a point cose. We stop when we meet the CA Cost
_PointsSpend = 0;
// Send a minimum of groups, even if points are met
_NrGrpsSend = 0;
//Now for each group make sure we check what he needs to do.
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _HQ_side)
and
(count(units _x)>0)
and
(alive (leader _x))
and
(count(_x getVariable ["GAIA_zone_intend",[]])>1)
)
then
{
//Zone intend holds ["Zonenumber","DEFEND"] (Or ATTACK or FORTIFY)
if (count(_x getVariable ["GAIA_zone_intend",[]])>1) then
{
_CanDoAttack = (
(((_x getVariable ["GAIA_zone_intend",[]]) select 1)=="MOVE")
or
(
(((_x getVariable ["GAIA_zone_intend",[]]) select 1)=="NOFOLLOW")
and
([_SelectCA,((_x getVariable ["GAIA_zone_intend",[]]) select 0)] call fnc_PosIsInMarker)
)
);
}
else
{
_CanDoAttack = false;
/*
_grp = _x;
//Non GAIA controlled units will be send into the attack if they are inside a zone
{
if ([(position leader _grp ),_x] call fnc_PosIsInMarker) exitwith {_CanDoAttack=true};
}foreach _zns;
*/
};
//Check the range of our dude. If however the CA is in our zone, then we dont care about the range
if ((_CanDoAttack) and (count(_x getVariable ["GAIA_zone_intend",[]])>1)) then
{
_CanDoAttack =
(
(
((_x getVariable ["GAIA_speed",""])=="SLOW" and ((leader _x) distance _SelectCA)1);
_CaHoldsValidTargets = !((([_HQ_side,_SelectCA] call fnc_GetCAPoints)select 0) in ["Helicopter","Autonomous"]);
//What is the cost in points of the current group?
_Grpcost = _x getVariable ["GAIA_points",0];
//Did we already give this group an order or was it last round?
_GroupHasOrdersThisRound = ((_x getVariable ["GAIA_Ordertime",0]) > _StartTimeIssueOrders);
//Is this group fleeing?
_GroupIsFleeing = fleeing (leader _x);
//Did we send more then enough points in troops already compared to the points in the ca?
_EnoughPointsSpend = (_PointsSpend >_CaPoints);
//The maximum number of groups that will be send to this CA (apart from points, that form the bare minimum
_MinimumResponseSend = (_NrGrpsSend>_MinimumResponse);
//The cases below are winner cases. In other words, the conditions to allow an attack
switch (true) do
{
//Group is fleeing, spending points on this shit is useless. Execute him?
case (
_GroupIsFleeing
) : {
//Clear the dude till he clears his mind.
//We do not count him into the attack
_dummy=[_x] call fnc_RemoveWayPoints;
};
//First come first serve, so the order is important here
case (
//The Group is in Combat, his is allowed to attack and the CA we check is the closest CA for him
//Even if the points are already spend, he is simply "involved" (combat) and not by choice. So count him in.
_GrpIsInCombat
and
_CanDoAttack
and
_IsGaiaControlled
and
_SelectCAisClosesttoGroup
and
!_GroupHasOrdersThisRound
and
!_GroupIsFleeing
and
_CaHoldsValidTargets
) : {
_dummy=[_x,_SelectCA] call fnc_DoAttack;
_PointsSpend = _PointsSpend + _Grpcost;
_NrGrpsSend = _NrGrpsSend + 1;
};
case (
//Not in combat and can do an attack. The most potential of all groups we look for.
(!_EnoughPointsSpend or !_MinimumResponseSend)
and
!_GrpIsInCombat
and
_CanDoAttack
and
_IsGaiaControlled
and
!_GroupHasOrdersThisRound
and
!_GroupIsFleeing
and
_CaHoldsValidTargets
) : {
_dummy=[_x,_SelectCA] call fnc_DoAttack;
_PointsSpend = _PointsSpend + _Grpcost;
_NrGrpsSend = _NrGrpsSend + 1;
};
};
};
//Next CA
sleep 0.1;
}forEach ([AllGroups,[],{_SelectCA distance (leader _x)},"ASCEND",{alive (leader _x)}] call fnc_SortGroupsByCA);
//We boot through all Conflict Area's in already pre-sorted order of priority
} forEach _CA;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Do Clear Spots (old targets) -> Boots on the ground needed
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
{
_Spot = _x;
_SpotInfo = (_Spot getVariable ["GAIA_TargetInfo",[]]);
if (count(_SpotInfo)>0) then
{
_SpotPos = _SpotInfo select 1;
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _HQ_side)
and
(count(units _x)>0)
and
(alive (leader _x))
and
(count(_x getVariable ["GAIA_zone_intend",[]])>1)
)
then
{
//Prepare checking conditions for our dear spots
//Is the group in combat?
_GrpIsInCombat = (behaviour(leader _x)=="COMBAT");
//Does the group have the order DoClear in its portfolio?
_CanDoClear = ("DoClear" in (_x getVariable ["GAIA_Portfolio",[]])) ;
//Is this group fleeing?
_GroupIsFleeing = fleeing (leader _x);
//Group is busy to attack by DoAttack?
_GroupBusy = ((_x getVariable ["GAIA_Order",""]) in ["DoAttack","DoClear"]) ;
//Is somebody already moving over there?
_SpotIsBeingCleared = [_SpotPos,_side] call fnc_isblacklisted;
//The dude should be hiding outside a CA (or we will already attack it)
_SpotIsOutsideCA = !((count([_CA, {(_x distance (_SpotPos)<100)}] call BIS_fnc_conditionalSelect))>0);
//He cannot be to far out (only one range as only footmobiles can clear)
//Or the spot is in the zone from the group, we clear it, no matter how far we need to go!
_SpotIsWithinRange = (
(((leader _x) distance _SpotPos)0)
//and
//((behaviour leader _x)!="COMBAT")
and
(alive (leader _x))
and
(count(_x getVariable ["GAIA_Portfolio",[]])>0)
and
(count(_x getVariable ["GAIA_zone_intend",[]])>1)
and
(
("DoMortar" in (_x getVariable ["GAIA_Portfolio",[]]))
or
("DoArtillery" in (_x getVariable ["GAIA_Portfolio",[]]))
)
and
//if we are already busy mortaring, forget the time out, ofcourse
(
((_x getVariable ["GAIA_MortarRound",0])>0)
or
((time - (_x getVariable ["GAIA_OrderTime",-MCC_GAIA_MORTAR_TIMEOUT])) > MCC_GAIA_MORTAR_TIMEOUT)
)
)
then
{
_MortarFired = false;
{
_SelectCA = _x;
([_side,_SelectCA] call fnc_GetCAPoints) select 2;
//Anybody of us near?
if (
!({side _x == (_HQ_side)} count nearestObjects [_SelectCA,["Man","Car","Tank"],200] >0)
and
//dont go for stupid targets please.
//if mixed, he will still fire (unknown)
!((([_HQ_side,_SelectCA] call fnc_GetCAPoints)select 0) in ["Car","Tank","Helicopter","Ship","Support","Autonomous","Submarine"])
and
//Dont fire on something we already fire on
!(({(side _x == (_HQ_side)) and alive (leader _x) and (( _x getVariable ["GAIA_MortarTarget",[0,0,0]] distance _SelectCA )==0)} count (allgroups-[_grp]))>0)
and
(
(((_grp getVariable ["GAIA_zone_intend",[]]) select 1)=="MOVE")
or
(
(((_grp getVariable ["GAIA_zone_intend",[]]) select 1)=="NOFOLLOW")
and
([_SelectCA,((_grp getVariable ["GAIA_zone_intend",[]]) select 0)] call fnc_PosIsInMarker)
)
)
)
then
{
//player globalchat format ["Mortar fired:%1",_grp];
_MortarFired = [_grp,_SelectCA] call fnc_domortar;
}
else
{
//Cancel! We got troops close!
if ((_grp getVariable ["GAIA_MortarRound",0])>0)
then
{
_grp setVariable ["GAIA_MortarRound" , 0, false];
_grp setVariable ["GAIA_MortarTarget" , [0,0,0], false];
};
};
if (_MortarFired) exitwith {true;};
} forEach _CA;
};
} forEach allgroups;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// NON COMBAT ORDERS
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
{
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _x) == _HQ_side)
and
(count(units _x)>0)
and
((behaviour leader _x)!="COMBAT")
and
(alive (leader _x))
and
(count(_x getVariable ["GAIA_Portfolio",[]])>0)
and
(count(_x getVariable ["GAIA_zone_intend",[]])>1)
and
//He is not fortifying
((_x getVariable ["GAIA_Order",""]) != "DoFortify")
)
then
{
//backward compatible fortify command
if (count (waypoints _x ) == (currentWaypoint _x)) then
{
switch (true) do
{
//Group is patrolling
case ("DoPatrol" in (_x getVariable ["GAIA_Portfolio",[]])) :
{
//Clear the dude till he clears his mind.
//We do not count him into the attack
_dummy=[_x] call fnc_DoPatrol;
};
//Group needs to wait (heli's)
case ("DoWait" in (_x getVariable ["GAIA_Portfolio",[]])) :
{
//Clear the dude till he clears his mind.
//We do not count him into the attack
_dummy=[_x] call fnc_DoWait;
};
//Lets give the support guys something to do.
case ("DoSupport" in (_x getVariable ["GAIA_Portfolio",[]])) :
{
//Clear the dude till he clears his mind.
//We do not count him into the attack
_dummy=[_x] call fnc_DoSupport;
}; \
//Units that need to hide like AA are set here.
case ("DoHide" in (_x getVariable ["GAIA_Portfolio",[]])) :
{
//Clear the dude till he clears his mind.
//We do not count him into the attack
_dummy=[_x] call fnc_DoHide;
};
//Units that need to hide like AA are set here.
case ("DoPark" in (_x getVariable ["GAIA_Portfolio",[]])) :
{
//Clear the dude till he clears his mind.
//We do not count him into the attack
_dummy=[_x] call fnc_DoPark;
};
};
};
};
} forEach allgroups;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// TRANSPORTATION SUPPORT PHASE
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
{
if (count(_x getVariable ["GAIA_zone_intend",[]])>1) then
{
if (
//The the one asking transport must be on our side
((side _x) == _HQ_side)
and
//There must be units in the group of the requester
(count(units _x)>0)
and
//The group cannot be in combat
((behaviour leader _x)!="COMBAT")
and
//The leader must be alive (null group check)
(alive (leader _x))
and
//There must be something to do in your portfolio
(count(_x getVariable ["GAIA_Portfolio",[]])>0)
and
(
((_x getVariable ["GAIA_Order",""]) == "DoPatrol")
and
!([(position leader _x),((_x getVariable ["GAIA_zone_intend",["",[0,0,0]]]) select 0)] call fnc_PosIsInMarker)
)
and
//You belong to a footmobile class or you wont be able to getin
((_x getVariable ["GAIA_class",""]) in ["Infantry","ReconInfantry"])
)
//If that is all the case, then go check if somebody can transport you and if you are allowed to be transported based on transport specific rule bases
then { _dummy= [_x] call fnc_DoOrganizeTransportation};
};
} forEach allgroups;
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// AMBIENT BEHAVIOR PHASE ( FOR GOOD LOOKS)
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
{
if (MCC_GAIA_AMBIANT)
then
{
if (
//The the one asking transport must be on our side
((side _x) == _HQ_side)
and
//There must be units in the group of the requester
(count(units _x)>0)
and
//The group is in combat
((behaviour leader _x)=="COMBAT")
and
//The leader must be alive (null group check)
(alive (leader _x))
and
//There must be something to do in your portfolio
(count(_x getVariable ["GAIA_Portfolio",[]])>0)
and
((_x getVariable ["GAIA_Order",""]) != "DoFortify")
)
then
{
_IsNight = (((selectBestPlaces [position (leader _x),2, "night", 1, 1]) select 0 select 1)>0.8);
_LetsDoSome = ((round(random(MCC_GAIA_AMBIANT_CHANCE)))==1);
_ClosestCA = ([_CA,leader _x] call BIS_fnc_nearestPosition);
_PosLead = position leader _x;
//Footmobile specific behavior
if ((_x getVariable ["GAIA_class",""]) in ["Infantry","ReconInfantry"]) then
{
//and _LetsDoSome and count(_ca)>0
//For flares: it must be night, we must have a ca within 400, the random factor must be met and closest enemy is futher then 100
if (_IsNight and count(_ca)>0 and ((_ClosestCA distance (leader _x))<400) and _LetsDoSome and (((leader _x) findNearestEnemy _PosLead) distance _PosLead >100) ) then
{
[[(_ClosestCA select 0),(_ClosestCA select 1),100],[(_PosLead select 0),(_PosLead select 1),40],50,30,"F_40mm_Green"] call fnc_fireflare;
};
//Check if this unit needs some smoke for cover. Make sure to check if previous points is bigger then 0, we dont like devide by zero
if (((_x getVariable ["GAIA_previouspoints",0])>0) and ((_x getVariable ["GAIA_points",0])>0)) then
{
//did we have more then 20% loss? go smoke it
if ((_x getVariable ["GAIA_PreviousPoints",1])>(_x getVariable ["GAIA_points",1])) then
//if (((((_x getVariable ["GAIA_PreviousPoints",1])-(_x getVariable ["GAIA_points",1]))/(_x getVariable ["GAIA_PreviousPoints",1]))*100)>20) then
{
if (alive leader _x) then {"SmokeShell" createVehicle (position leader _x);};
};
};
};
};
};
} forEach allgroups;
true;/* ----------------------------------------------------------------------------
Function: fnc_GetCAPoints
Description:
Get the points of the CA
Parameters:
- Side
Returns:
true
Author:
Spirit, 24-1-2014
---------------------------------------------------------------------------- */
private ["_side","_CA","_grp","_zns","_trg","_Zone","_CA","_TargetList"];
_side = _this select 0;
_CA = _this select 1;
_grp = [];
_zns = [];
_trg = [];
_Zone = "";
_TargetList = [];
_CACost = [];
// CA ATTACK ORDERS
switch (_side) do
{
case west : {
_grp = MCC_GAIA_GROUPS_WEST;
_zns = MCC_GAIA_ZONES_WEST;
_trg = (MCC_GAIA_TARGETS_WEST select 0)+(MCC_GAIA_TARGETS_WEST select 1)+(MCC_GAIA_TARGETS_WEST select 2);
};
case east : {
_grp = MCC_GAIA_GROUPS_EAST;
_zns = MCC_GAIA_ZONES_EAST;
_trg = (MCC_GAIA_TARGETS_EAST select 0)+(MCC_GAIA_TARGETS_EAST select 1)+(MCC_GAIA_TARGETS_EAST select 2);
};
case independent: {
_grp = MCC_GAIA_GROUPS_INDEP;
_zns = MCC_GAIA_ZONES_INDEP;
_trg = (MCC_GAIA_TARGETS_INDEP select 0)+(MCC_GAIA_TARGETS_INDEP select 1)+(MCC_GAIA_TARGETS_INDEP select 2);
};
};
{
if ([_CA,_x] call fnc_PosIsInMarker ) exitWith {_Zone=_x;};
}foreach _zns;
//Get the targets in the CA
{
if (count(_x getVariable ["GAIA_TargetInfo",[]])>0) then
{
if ((((_x getVariable ["GAIA_TargetInfo",[]])select 1) distance _CA)<100) then
{
if (_x iskindof "CAMANBASE") then
{_TargetList = _TargetList+ [_x];}
else
{_TargetList = _TargetList+ (units _x);}
};
};
} foreach _trg;
//Get the points of the CA
_CACost = ([_TargetList] call fnc_ClassifyUnits);
//Lets work on the points, this has to leave this function when we implement terrain factors and other stuff that also influences points
//For now its dirty in here by check if in zone then more points then outside
_Points = _CACost select 2 ;
//Calculate with multipliers
if !isnil(_Zone) then {_points = _points *3} else {_points = _points *2};
_CACost set [2,_Points ];
_CACost
// In: [position,distance,direction]
// Out: position
private ["_pos","_dst","_dir","_orgX","_orgY","_posX","_posY"];
_pos = _this select 0;
_dst = _this select 1;
_dir = _this select 2;
_orgX = _pos select 0;
_orgY = _pos select 1;
_posX = _orgX + (_dst * sin _dir);
_posY = _orgY + (_dst * cos _dir);
[_posX,_posY,0]// In: [side,position]
// Out: Distance to Closest Zone
// Spirit 19-1-2014
private ["_side","_ClosestZone","_zones","_Distance"];
_side = _this select 0;
_pos = _this select 1;
_Distance = 0;
Switch (_side) do
{
case west : {_Zones = MCC_GAIA_ZONES_WEST;};
case east : {_Zones = MCC_GAIA_ZONES_EAST;};
case independent: {_Zones = MCC_GAIA_ZONES_INDEP;};
};
_ClosestZone=(([_Zones,[],{_pos distance (getMarkerPos _x)},"ASCEND"] call BIS_fnc_sortBy)select 0);
if IsNil("_ClosestZone") then
{_Distance = 99999;}
else
{
_Distance = ((getMarkerPos _ClosestZone) distance _pos);
};
_Distance
// In: marker
// Out: array of positions
private ["_area","_corners"];
_area = _this;
_corners = [];
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _area;
_centerX = _center select 0;
_centerY = _center select 1;
// Direction and make sure it's between 0 and 360.
private ["_dir","_dirCos","_dirSin"];
_dir = (markerDir _area) * -1;
_dir = _dir % 360;
_dirCos = cos _dir;
_dirSin = sin _dir;
// Size
private ["_size","_sizeX","_sizeY"];
_size = getMarkerSize _area;
_sizeX = _size select 0;
_sizeY = _size select 1;
private ["_cosX","_sinX","_cosY","_sinY","_addX","_addY","_subX","_subY"];
_cosX = _dirCos * _sizeX;
_sinX = _dirSin * _sizeX;
_cosY = _dirCos * _sizeY;
_sinY = _dirSin * _sizeY;
_addX = _cosX + _sinY;
_addY = _sinX + _cosY;
_subX = _cosX - _sinY;
_subY = _sinX - _cosY;
private ["_posX","_posY"];
// Bottom Left
_posX = _centerX - _subX;
_posY = _centerY - _addY;
_corners set [0,[_posX,_posY]];
// Top Left
_posX = _centerX - _addX;
_posY = _centerY - _subY;
_corners set [1,[_posX,_posY]];
// Top Right
_posX = _centerX + _subX;
_posY = _centerY + _addY;
_corners set [2,[_posX,_posY]];
// Bottom Right
_posX = _centerX + _addX;
_posY = _centerY + _subY;
_corners set [3,[_posX,_posY]];
_corners// In: marker
// Out: string (marker shape)
private ["_size","_x","_y","_ret"];
_size = markersize _this;
_x = _size select 0;
_y = _size select 1;
_ret = "";
switch (tolower(markershape _this)) do {
case "rectangle": {
if (_x == _y) then {
_ret = "SQUARE";
} else {
_ret = "RECTANGLE";
};
};
case "ellipse": {
if (_x == _y) then {
_ret = "CIRCLE";
} else {
_ret = "ELLIPSE";
};
};
case "icon": {
_ret = "ICON";
};
};
_ret/* ----------------------------------------------------------------------------
Function: CBA_fnc_getNearestBuildingPosDistance
Description:
A function used to find out the nearest building and appropriate building positions available.
Parameters:
Object
Example:
(begin example)
_array = player call CBA_fnc_getNearestBuilding
(end)
Returns:
Array with [building object, building positions (count)]
Author:
Rommel
---------------------------------------------------------------------------- */
private ["_building", "_i","_BuildPos"];
_building = nearestBuilding _this;
_BuildPos = [];
_i = 0;
while {str(_building buildingPos _i) != "[0,0,0]"} do {_i = _i + 1;};
[_building,_i,(_building distance _this )]// In: marker
// Out: position
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _this;
_centerX = _center select 0;
_centerY = _center select 1;
// Size
private ["_size"];
_size = getMarkerSize _this;
_size = _size select 0;
// Randomly pick a direction,
private ["_dir","_posX","_posY","_rand","_pos"];
_dir = random 360;
_rand = sqrt random 1;
_posX = (_size * (cos _dir)) * _rand;
_posY = (_size * (sin _dir)) * _rand;
_pos = [_posX,_posY];
_posX = _centerX + (_pos select 0);
_posY = _centerY + (_pos select 1);
[_posX,_posY,0]
// In: ellipseMarker
// Out: position
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _this;
_centerX = _center select 0;
_centerY = _center select 1;
// Direction and make sure it's between 0 and 360.
private ["_dirMrk"];
_dirMrk = (markerDir _this) * -1;
_dirMrk = _dirMrk % 360;
// Size
private ["_size","_sizeX","_sizeY"];
_size = getMarkerSize _this;
_sizeX = _size select 0;
_sizeY = _size select 1;
// If B axis is longer than A, switch them and fix direction.
if (_sizeX < _sizeY) then {
_sizeX = _size select 1;
_sizeY = _size select 0;
_dirMrk = _dirMrk + 90;
};
// Randomly pick a direction,
private ["_dir","_posX","_posY","_rand","_pos"];
_dir = random 360;
_rand = sqrt random 1;
_posX = (_sizeX * (cos _dir)) * _rand;
_posY = (_sizeY * (sin _dir)) * _rand;
_pos = [_posX,_posY];
if (_dirMrk != 0) then {
_pos = [_pos,_dirMrk] call fnc_rotatePosition;
};
_posX = _centerX + (_pos select 0);
_posY = _centerY + (_pos select 1);
[_posX,_posY,0]
// In: marker
// Out: position
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _this;
_centerX = _center select 0;
_centerY = _center select 1;
// Size
private ["_size","_sizeX","_sizeY"];
_size = getMarkerSize _this;
_sizeX = _size select 0;
_sizeY = _size select 1;
// Direction and make sure it's between 0 and 360.
private ["_dir","_dirCos","_dirSin"];
_dir = (markerDir _this) * -1;
_dir = _dir % 360;
_dirCos = cos _dir;
_dirSin = sin _dir;
private ["_rndX","_rndY","_posX","_posY"];
// Select random X and Y
_rndX = (random (_sizeX * 2)) - _sizeX;
_rndY = (random (_sizeY * 2)) - _sizeY;
// If area is angled, shift X and Y
if (_dir != 0) then {
_posX = _centerX + (_dirCos * _rndX - _dirSin * _rndY);
_posY = _centerY + (_dirSin * _rndX + _dirCos * _rndY);
} else {
_posX = _centerX + _rndX;
_posY = _centerY + _rndY;
};
[_posX,_posY,0]// In: marker
// Out: position
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _this;
_centerX = _center select 0;
_centerY = _center select 1;
// Size
private ["_size"];
_size = getMarkerSize _this;
_size = _size select 0;
// Direction and make sure it's between 0 and 360.
private ["_dir","_dirCos","_dirSin"];
_dir = (markerDir _this) * -1;
_dir = _dir % 360;
_dirCos = cos _dir;
_dirSin = sin _dir;
private ["_rndX","_rndY","_posX","_posY"];
// Select random X and Y
_rndX = (random (_size * 2)) - _size;
_rndY = (random (_size * 2)) - _size;
// If area is angled, shift X and Y
if (_dir != 0) then {
_posX = _centerX + (_dirCos * _rndX - _dirSin * _rndY);
_posY = _centerY + (_dirSin * _rndX + _dirCos * _rndY);
} else {
_posX = _centerX + _rndX;
_posY = _centerY + _rndY;
};
[_posX,_posY,0] private ["_result", "_getAnyMagazines", "_findRecurse", "_class"];
_result = [];
_getAnyMagazines = {
private ["_weapon", "_mags"];
_weapon = configFile >> "CfgWeapons" >> _this;
_mags = [];
{
_mags = _mags + getArray (
(if (_x == "this") then { _weapon } else { _weapon >> _x }) >> "magazines"
)
} foreach getArray (_weapon >> "muzzles");
_mags
};
_findRecurse = {
private ["_root", "_class", "_path", "_currentPath"];
_root = (_this select 0);
_path = +(_this select 1);
for "_i" from 0 to count _root -1 do {
_class = _root select _i;
if (isClass _class) then {
_currentPath = _path + [_i];
{
_result set [count _result, [_x, _x call _getAnyMagazines, _currentPath, str _class]];
} foreach getArray (_class >> "weapons");
_class = _class >> "turrets";
if (isClass _class) then {
[_class, _currentPath] call _findRecurse;
};
};
};
};
_class = (
configFile >> "CfgVehicles" >> (
switch (typeName _this) do {
case "STRING" : {_this};
case "OBJECT" : {typeOf _this};
default {nil}
}
) >> "turrets"
);
[_class, []] call _findRecurse;
_result;/* ----------------------------------------------------------------------------
Function: fnc_GetZoneIntendFromGroup
Description:
Gets the Zone and the Intend from the group as given. (by the mission maker).
Parameters:
- Group
Returns:
[ Zone, Intend]
Author:
Spirit, 17-1-2014
---------------------------------------------------------------------------- */
private ["_group","_zone_intend"];
_group = _this select 0;
_zone_intend = [];
_zone_intend = _group getVariable ["GAIA_ZONE_INTEND",[]];
_zone_intend
/* fnc_GetZoneStatusBehavior
Purpose:
Sets the alert level of the zone on which the units will act on.
In : [zone]
Out : [_ZoneStatus,_Behaviour,_CombatMode,_Formation,_Speed]
By Spirit, 7-1-2014
*/
private
["_zone"
,"_Behaviour"
,"_CombatMode"
,"_Formation"
,"_Speed"
,"_side"
,"_ZoneStatus"
];
_zone = _this select 0;
_side = _this select 1;
_Behaviour ="SAFE";
_CombatMode="GREEN";
_Formation="COLUMN";
_Speed = "LIMITED";
switch (_side) do
{
case west : {_ZoneStatus = (MCC_GAIA_ZONESTATUS_WEST select (parseNumber _zone ));};
case east : {_ZoneStatus = (MCC_GAIA_ZONESTATUS_EAST select (parseNumber _zone ));};
case independent: {_ZoneStatus = (MCC_GAIA_ZONESTATUS_INDEP select (parseNumber _zone ));};
};
//Lets create the right behaviour for our friends
switch (_ZoneStatus) do
{
case (0) : {_Behaviour="SAFE"; _CombatMode="GREEN"; _Formation="COLUMN"; _Speed = "LIMITED";};
case (1) : {_Behaviour="AWARE"; _CombatMode="YELLOW"; _Formation="WEDGE"; _Speed = "NORMAL";};
case (2) : {_Behaviour="AWARE"; _CombatMode="YELLOW"; _Formation="VEE"; _Speed = "NORMAL";};
};
// Return position
[_ZoneStatus,_Behaviour,_CombatMode,_Formation,_Speed]// fnc_HasLOS.sqf
// usage: [,,(,)] call FLAY_fnc_knowsAbout;
// returns true if can see and is less than meters from , otherwise returns false.
private ["_unit", "_target", "_range", "_fov", "_inView", "_inSight", "_inRange", "_knowsAbout"];
_unit = [_this,0] call BIS_fnc_param;
_target = [_this,1] call BIS_fnc_param;
_range = [_this,2,100,[0]] call BIS_fnc_param;
_fov = [_this,3,130,[0]] call BIS_fnc_param;
_knowsAbout = false;
_inRange = (_unit distance _target) < _range;
if (_inRange) then {
_inView = [position _unit, getdir _unit, _fov, position _target] call BIS_fnc_inAngleSector;
_inSight = count (lineIntersectsWith [eyePos _unit, eyepos _target, _unit, _target]) == 0;
_knowsAbout = _inView && _inSight;
};
_knowsAbout; private ["_pos","_IsBlackListed","_WPPos","_TempArray"];
/* ----------------------------------------------------------------------------
Function: fnc_isblacklisted
Description:
Checks if the given position is witin MCC_GAIA_AWARENESSRANGE.
Parameters:
- position
Returns:
true/false
Author:
Spirit
---------------------------------------------------------------------------- */
_pos = _this select 0;
_side = _this select 1;
_IsBlackListed = false;
_WPPos = [];
_TempArray = [];
switch (_side) do
{
case west : {_TempArray =MCC_GAIA_WPPOS_WEST; };
case east : {_TempArray =MCC_GAIA_WPPOS_EAST; };
case independent: {_TempArray =MCC_GAIA_WPPOS_INDEP; };
};
{
_WPPos = _WPPos + [_x];
} forEach _TempArray;
switch (_side) do
{
case west : {_TempArray =MCC_GAIA_BREADCRUMBS_WEST; };
case east : {_TempArray =MCC_GAIA_BREADCRUMBS_EAST; };
case independent: {_TempArray =MCC_GAIA_BREADCRUMBS_INDEP; };
};
{
if ((_pos distance (_x select 0))= _left && _dotX < _right && _dotY >= _bottom && _dotY < _top) then {
_return = true;
};
_return// In: [array1,array2]
// Out: boolean
private ["_p1","_p2","_return"];
_p1 = _this select 0;
_p2 = _this select 1;
_return = true;
// Only compare X and Y coordinates, ignore Z.
for "_i" from 0 to 1 do {
if ((_p1 select _i) != (_p2 select _i)) exitwith {
_return = false;
};
};
_return// In: [position,blackListMarker]
// Out: boolean
private ["_pos","_area","_return"];
if (count(_this)<2) exitwith {false;};
if (typename (_this select 0)!="ARRAY") exitwith {false;};
if (typename (_this select 1)!="STRING") exitwith {false;};
if (((getmarkerpos (_this select 1)) distance [0,0,0])==0) exitwith {false;};
_pos = _this select 0;
_area = _this select 1;
_return = false;
// Find corner positions of the rectangle
private ["_dir"];
_dir = markerDir _area;
_dir = _dir % 360;
// Center point
private ["_center","_centerX","_centerY"];
_center = getMarkerPos _area;
_centerX = _center select 0;
_centerY = _center select 1;
private ["_shape"];
_shape = _area call fnc_getMarkerShape;
if (_shape == "ICON") then {
// Icon has only one position, so if it equals to the given position, then it's blacklisted.
if ([_pos,_center] call fnc_isSamePosition) then {
_return = true;
};
// Markers that have an area.
} else {
if (_shape in ["RECTANGLE","SQUARE"]) then {
private ["_corners"];
_corners = _area call fnc_getMarkerCorners;
// If rectangle is not axis-aligned.
if (_dir % 90 != 0) then {
// Add the point position to the array to have it shifted by the FOR below
_corners set [4,_pos];
// Rotate each corner position so that the rectangle is aligned with x and y axises
// Use origo as center while rotating, but for comparison shift positions back
private ["_posCor","_posNew","_orgX","_orgY","_shiftedX","_shiftedY","_newX","_newY"];
for "_i" from 0 to (count _corners - 1) do {
_posCor = _corners select _i;
// Original coordinates
_orgX = _posCor select 0;
_orgY = _posCor select 1;
// Subtract the marker center coordinates from corner coordinates.
// Rotation is done using origo (0,0) as anchor/centerpoint.
_shiftedX = _orgX - _centerX;
_shiftedY = _orgY - _centerY;
// Axis-aligned corner position
_posNew = [[_shiftedX,_shiftedY],_dir] call fnc_rotatePosition;
// Shift the aligned corner position back near to the original marker location.
_newX = _posNew select 0;
_newY = _posNew select 1;
_newX = _newX + _centerX;
_newY = _newY + _centerY;
_posCor = [_newX,_newY];
_corners set [_i,_posCor];
};
// Point position
_pos = _corners select 4;
};
// Check if the position is within the marker area.
_return = [_pos,_corners] call fnc_isInRectangle;
} else {
if (_shape == "CIRCLE") then {
_return = [_pos,_area] call fnc_isInCircle;
} else {
_return = [_pos,_area] call fnc_isInEllipse;
};
};
};
_return// In: [position,direction]
// Out: position
private ["_pos","_dir","_orgX","_orgY","_newX","_newY"];
_pos = _this select 0;
_dir = _this select 1;
_orgX = _pos select 0;
_orgY = _pos select 1;
_newX = (_orgX * (cos _dir)) - (_orgY * (sin _dir));
_newY = (_orgX * (sin _dir)) + (_orgY * (cos _dir));
[_newX,_newY]
private ["_position","_posX","_posY","_radius","_precision","_sourcesCount","_urban","_forest","_hills","_flat","_sea","_valS","_value","_val0","_samples","_sGr","_hprev","_hcurr","_samplePos","_i","_rds"];
_position = _this select 0;
_samples = _this select 1;
_rds = 100;
if ((count _this) > 2) then {_rds = _this select 2};
if not ((typeName _position) == "ARRAY") then {_position = getPosATL _position};
_posX = _position select 0;
_posY = _position select 1;
_radius = 5;
_precision = 1;
_sourcesCount = 1;
_urban = 0;
_forest = 0;
_hills = 0;
_flat = 0;
_sea = 0;
_sGr = 0;
_hprev = getTerrainHeightASL [_posX,_posY];
for "_i" from 1 to 10 do
{
_samplePos = [_posX + ((random (_rds * 2)) - _rds),_posY + ((random (_rds * 2)) - _rds)];
_hcurr = getTerrainHeightASL _samplePos;
_sGr = _sGr + abs (_hcurr - _hprev)
};
_sGr = _sGr/10;
{
_valS = 0;
for "_i" from 1 to _samples do
{
_position = [_posX + (random (_rds/5)) - (_rds/10),_posY + (random (_rds/5)) - (_rds/10)];
_value = selectBestPlaces [_position,_radius,_x,_precision,_sourcesCount];
_val0 = _value select 0;
_val0 = _val0 select 1;
_valS = _valS + _val0;
};
_valS = _valS/_samples;
switch (_x) do
{
case ("Houses") : {_urban = _urban + _valS};
case ("Trees") : {_forest = _forest + (_valS/3)};
case ("Forest") : {_forest = _forest + _valS};
case ("Hills") : {_hills = _hills + _valS};
case ("Meadow") : {_flat = _flat + _valS};
case ("Sea") : {_sea = _sea + _valS};
};
}
foreach ["Houses","Trees","Forest","Hills","Meadow","Sea"];
[_urban,_forest,_hills,_flat,_sea,_sGr]
/*
Author: Jiri Wainar (Warka)
Description:
Sorts an array according to given algorithm.
Parameter(s):
_this select 0: any unsorted array (Array)
- array can contain any types (object/numbers/strings ..)
_this select 1: input parameters (Array)
- used in the eval algorithm (object/numbers/strings ..)
- input params are referenced in the sorting algorithm by _input0, _input1 .. _input9
- max. number of 10 input params is supported (0-9)
_this select 2: sorted algorithm (Code) [optional: default {_x}]
- code needs to return a scalar
- variable _x refers to array item
_this select 3: sort direction (String) [optional: default "ASCEND"]
"ASCEND": sorts array in ascending direction (from lowest value to highest)
"DESCEND": sorts array in descending direction
_this select 4: filter (Code) [optional: default {true}]
- code that needs to evaluate true for the array item to be sorted, otherwise item is removed
Returns:
Array
Examples:
//sort numbers from lowest to highest
_sortedNumbers = [[1,-80,0,480,15,-40],[],{_x},"ASCEND"] call BIS_fnc_sortBy;
//sort helicopters by distance from player
_closestHelicopters = [[_heli1,_heli2,_heli3],[],{player distance _x},"ASCEND"] call BIS_fnc_sortBy;
//sort enemy by distance from friendly unit (referenced by local variable), the furtherest first
_furtherstEnemy = [[_enemy1,_enemy2,_enemy3],[_friendly],{_input0 distance _x},"DESCEND",{canMove _x}] call BIS_fnc_sortBy;
*/
private ["_unsortedArray","_inputParams","_algorithm","_sortDirection","_filter","_removeElement","_values","_sortedArray","_sortedValues","_fnc_sort","_initValue","_sortCode"];
_unsortedArray = [_this, 0, [], [[]]] call BIS_fnc_param;
_inputParams = [_this, 1, [], [[]]] call BIS_fnc_param;
_algorithm = [_this, 2, {_x}, [{}]] call BIS_fnc_param;
_sortDirection = [_this, 3, "ASCEND", [""]] call BIS_fnc_param;
_filter = [_this, 4, {true}, [{}]] call BIS_fnc_param;
_removeElement = "BIS_fnc_sortBy_RemoveMe";
if (count _unsortedArray == 0) exitWith {[]};
//create the input params
private["_input0","_input1","_input2","_input3","_input4","_input5","_input6","_input7","_input8","_input9"];
//--- ToDo: Pass arguments in _this instead of pre-defining limited number of input variables as below
_this = _inputParams;
_input0 = [_inputParams, 0, objNull] call BIS_fnc_param;
_input1 = [_inputParams, 1, objNull] call BIS_fnc_param;
_input2 = [_inputParams, 2, objNull] call BIS_fnc_param;
_input3 = [_inputParams, 3, objNull] call BIS_fnc_param;
_input4 = [_inputParams, 4, objNull] call BIS_fnc_param;
_input5 = [_inputParams, 5, objNull] call BIS_fnc_param;
_input6 = [_inputParams, 6, objNull] call BIS_fnc_param;
_input7 = [_inputParams, 7, objNull] call BIS_fnc_param;
_input8 = [_inputParams, 8, objNull] call BIS_fnc_param;
_input9 = [_inputParams, 9, objNull] call BIS_fnc_param;
//check the filter
{
if !(call _filter) then
{
_unsortedArray set [_forEachIndex,_removeElement];
};
}
forEach _unsortedArray;
//remove filtered-out items
_unsortedArray = _unsortedArray - [_removeElement];
//get the sort values
_values = [];
{
private ["_algorithmTemp"];
_algorithmTemp = _algorithm;
//--- Wipe out all existing variables to prevent accidental overwriting (except of _values)
private ["_unsortedArray","_inputParams","_algorithm","_sortDirection","_filter","_removeElement","_sortedArray","_sortedValues","_fnc_sort","_initValue","_sortCode"];
//--- Evaluate the algorithm
_values set [count _values,call _algorithmTemp];
}
forEach _unsortedArray;
//init sorted arrays
_sortedArray = [];
_sortedValues = [];
//handle ASCENDing vs. DESCENDing sorting
if (_sortDirection == "ASCEND") then
{
_initValue = 1e9;
_sortCode = {_x < _selectedValue};
}
else
{
_initValue = -1e9;
_sortCode = {_x > _selectedValue};
};
if (count _values > 0) then {
while {count _values > 0} do {
private["_selectedValue","_selectedItem","_selectedIndex"];
_selectedValue = _initValue;
{
if (call _sortCode) then
{
_selectedValue = _x;
_selectedItem = _unsortedArray select _forEachIndex;
_selectedIndex = _forEachIndex;
};
}
forEach _values;
//store selected
_sortedArray set [count _sortedArray,_selectedItem];
_sortedValues set [count _sortedValues,_selectedValue];
//remove stored from source pool
_unsortedArray set [_selectedIndex,_removeElement];
_unsortedArray = _unsortedArray - [_removeElement];
_values set [_selectedIndex,_removeElement];
_values = _values - [_removeElement];
};
};
//return sorted array
_sortedArray/* ----------------------------------------------------------------------------
Function: fnc_TimeOut
Description:
Used to make FSM code wait.
Parameters:
- _wait
Returns:
true
Author:
Spirit, 13-1-2014
---------------------------------------------------------------------------- */
private ["_wait"];
_wait = _this select 0;
sleep _wait;
true
/* ----------------------------------------------------------------------------
Function: CBA_fnc_taskDefend
//change by spirit 11-3-2014 for specific purposes of gaia
Description:
A function for a group to defend a parsed location. Groups will mount nearby static machine guns, and bunker in nearby buildings. They may also patrol the radius unless otherwise specified.
Parameters:
- Group (Group or Object)
Optional:
- Position (XYZ, Object, Location or Group)
- Defend Radius (Scalar)
- Building Size Threshold (Integer, default 2)
- Can patrol (boolean)
Example:
(begin example)
[this] call CBA_fnc_taskDefend
(end)
Returns:
Nil
Author:
Rommel
---------------------------------------------------------------------------- */
private ["_group","_position","_radius","_threshold"];
_group = (_this select 0) ;
_position = (_this select 1);
_radius = if (count _this > 2) then {_this select 2} else {50};
_threshold = 1;
_group enableattack false;
private ["_count", "_list", "_list2", "_units", "_i"];
//_statics = [_position, vehicles, _radius, {(_x iskindof "StaticWeapon") && {(_x emptypositions "Gunner" > 0)}}] call CBA_fnc_getnearest;
_statics = [(nearestObjects [_position,["StaticWeapon"], _radius]), {(_x iskindof "StaticWeapon") && (isnull(assignedGunner (_x))) && {[(position _x),_zone] CALL fnc_posisinmarker} && {(_x emptypositions "Gunner" > 0)}}] call BIS_fnc_conditionalSelect;
//[(position PLAYER),"1"] CALL FNC_POSISINMARKER
//_buildings = _position nearObjects ["building",_radius];
_buildings = [(_position nearObjects ["building",_radius]), {[(position _x),_zone] CALL fnc_posisinmarker}] call BIS_fnc_conditionalSelect;
_units = units _group;
_count = count _units;
_zone = (((_group) getVariable ["GAIA_zone_intend",[]])select 0);
if !(isnil("_Zone")) then
{
{
if (str(_x buildingpos _threshold) == "[0,0,0]") then {_buildings = _buildings - [_x]};
} foreach _buildings;
_i = 0;
{
_count = (count _statics) - 1;
if (_count > -1) then {
[_x] join grpNull;
_x assignasgunner (_statics select _count);
_statics resize _count;
[_x] ordergetin true;
_i = _i + 1;
} else {
if (count _buildings > 0) then {
private ["_building","_p","_array"];
_building = _buildings call BIS_fnc_selectRandom;
_array = _building getvariable "CBA_taskDefend_positions";
if (isnil "_array") then {
private "_k"; _k = 0;
_building setvariable ["CBA_taskDefend_positions",[]];
while {str(_building buildingpos _k) != "[0,0,0]"} do {
_building setvariable ["CBA_taskDefend_positions",(_building getvariable "CBA_taskDefend_positions") + [_k]];
_k = _k + 1;
};
_array = _building getvariable "CBA_taskDefend_positions";
};
if (count _array > 0) then {
_p = (_building getvariable "CBA_taskDefend_positions") call BIS_fnc_selectRandom;
_array = _array - [_p];
if (count _array == 0) then {
_buildings = _buildings - [_building];
_building setvariable ["CBA_taskDefend_positions",nil];
};
_building setvariable ["CBA_taskDefend_positions",_array];
[_x,_building buildingpos _p] spawn {
if (surfaceIsWater (_this select 1)) exitwith {};
(_this select 0) domove (_this select 1);
(_this select 0) setSpeedMode "FULL";
sleep 5;
waituntil {unitready (_this select 0)};
(_this select 0) disableai "move";
dostop _this;
waituntil {not (unitready (_this select 0))};
(_this select 0) enableai "move";
};
_i = _i + 1;
};
};
};
} foreach _units;
{
_x setvariable ["CBA_taskDefend_positions",nil];
} foreach _buildings;
};
{
_myBall = "Sign_Sphere25cm_F" createVehicle [0,0,0];
nul = [_x,_myBall] spawn
{
_unit = _this select 0;
_ball = _this select 1;
while {sleep 0.2; alive _unit} do
{
_pos = getPosAtl _unit;
_eyes = eyePos _unit;
_zDif = ((_eyes select 2) - ((getPosASL _unit) select 2));
_pos set [2,(_pos select 2) + _zDif + 0.2];
_ball setPos _pos;
_alert = time - (_unit getVariable ["alerted",0]);
if (_alert < 10) then
{
_ball setObjectTexture [0,"#(argb,8,8,3)color(1,0,0,1)"];
}
else
{
_ball setObjectTexture [0,"#(argb,8,8,3)color(0,0,1,1)"];
};
};
deleteVehicle _ball;
};
} foreach allUnits;private ["_angle","_cansee","_infront","_obstruction"];
_unit = _this select 0;
_focus = _this select 1;
_cansee = false;
if (isnil("_focus")) then
{
_eyes = eyepos _unit;
_angle = (getdir _unit);
_hyp = 5;
_adj = _hyp * (cos _angle);
_opp = sqrt ((_hyp*_hyp) - (_adj * _adj));
_infront = if ((_angle) >= 180) then {
[(_eyes select 0) - _opp,(_eyes select 1) + _adj,(_eyes select 2)]
} else {
[(_eyes select 0) + _opp,(_eyes select 1) + _adj,(_eyes select 2)]
};
_obstruction = (lineintersectswith [_eyes,_infront,_unit]) select 0;
if (!(isnil("_obstruction"))) then {
};
_cansee = if (isnil("_obstruction")) then {true} else {false};
};
_cansee
private ["_unit","_target","_vec","_posATL","_abx","_aby","_abz"];
_unit = _this select 0;
_target = _this select 1; if ((typeName _target) == "OBJECT") then {_target = (getPosATL _target)};
if (!(alive _unit)) exitWith {};
_posATL = getPosATL _unit;
_abx = (_target select 0) - (_posATL select 0);
_aby = (_target select 1) - (_posATL select 1);
_abz = (_target select 2) - (_posATL select 2);
_vec = [_abx, _aby, _abz];
// Main body of the function;
_unit doWatch objNull;
_unit doTarget objNull;
sleep 0.2;
_unit setVectorDir _vec;
sleep 0.02;
_unit doWatch _target;
private ["_angle"];
_obj1 = _this select 0;
_obj2 = _this select 1;
_pos1 = if ((typename _obj1) == "Array") then {_obj1} else {getposATL _obj1};
_pos2 = if ((typename _obj2) == "Array") then {_obj2} else {getposATL _obj2};
_adj = (_pos2 select 1) - (_pos1 select 1);
_opp = (_pos2 select 0) - (_pos1 select 0);
_angle = _opp atan2 _adj;
if (_angle < 0) then
{
_angle = _angle + 360;
};
_angleprivate ["_house","_uACfg","_sel","_position","_doorPositions"];
_house = _this select 0;
_uACfg = (configFile >> "cfgVehicles" >> (typeOf _house) >> "UserActions");
if ((count _uACfg) <= 0) exitwith {};
_doorPositions = [];
for "_i" from 0 to ((count _uACfg) - 1) step 3 do
{
if (_i >= (count _uACfg)) exitwith {};
_sel = _uACfg select _i;
_position = getText (_sel >> "position");
_doorPositions set [(count _doorPositions),(_house selectionPosition _position)];
};
_doorPositionsprivate ["_indoors","_pos","_unit","_posh","_abovehead","_house"];
_unit = _this select 0;
_pos = getposASL _unit;
_posh = _pos select 2;
_pos set [2,(_posh + 0.5)];
_abovehead = [_pos select 0,_pos select 1,(_pos select 2) + 10];
_house = (lineintersectswith [_pos,_abovehead,_unit]) select 0;
_indoors = if (isnil("_house")) then {false} else {true};
_indoors
private ["_unit","_pos","_move","_reached","_uPos","_dist","_cnt"];
_unit = _this select 0;
_pos =_this select 1; if ((typeName _pos) != "ARRAY") then {_pos = (getPosATL _pos)};
_move =
{
doStop _unit;
sleep 0.01;
_unit MoveTo _pos;
};
call _move;
_reached = false;
_cnt = 0;
_idleCnt = 0;
_idle = false;
while {!_reached} do
{
_uPos = getPosATL _unit;
_dist = _uPos distance _pos;
_speed = speed _unit;
_interupted = if ((time - (_unit getVariable ["alerted",0])) > 10) then {false} else {true};
if (!(alive _unit)) exitwith {};
if (_speed <= 0.1) then {_idleCnt = _idleCnt + 1} else {_idleCnt = 0; _idle = false};
if (_idleCnt >= 2) then {_idle = true};
if (_idle && (!_interupted)) then
{
_cnt = _cnt + 1;
call _move;
};
if (_dist < 1) exitwith {_reached = true};
if (_cnt > 3) exitwith {};
sleep 1.5;
};
if (_reached) then {doStop _unit};
if (_reached) then
{
_indoors = [_unit] call gaia_fnc_indoors;
_uh = (getposATL _unit) select 2;
// if he's not indoors and he is over 1 meter from the ground, crouch. if crouching makes him blind (from a wall) he will stand back up.
if ((!(_indoors)) && (_uh > 1)) then
{
_unit setunitpos "Middle";
sleep 2;
if (!([_unit] call gaia_fnc_cansee)) then {_unit setunitpos "auto"};
// check to make sure that when he is inside or on the ground again he stops crouching.
nul = [_unit] spawn {
_unit = _this select 0;
while {sleep 2;alive _unit} do
{
_indoors = [_unit] call gaia_fnc_indoors;
_uh = (getposATL _unit) select 2;
if ((_indoors) or (_uh < 2)) exitwith {_unit setunitpos "AUTO";};
};
};
};
(group _unit) setCombatMode "YELLOW";
if (_indoors) then {
_unit setvariable ["indoors",true];
nul = [_unit] spawn gaia_fnc_Prone_Limit;
_unit forcespeed 0;
_unit setvariable ["forcedspeed",0];
};
// if (_staying) then {
(group _unit) setCombatMode "YELLOW";
_unit disableAI "TARGET";
//_unit disableAI "AUTOTARGET";
//_unit disableAI "FSM";
//_unit allowfleeing 0;
//};
// make them randomly look around and move within the building.
nul = [_unit] spawn gaia_fnc_smartlook;
};
//hint (str(_reached));
_reached
private ["_group","_nextWaypointNumber"];
_unit = _this select 0;
_varName = _this select 1;
_storedGroup = _unit getVariable [_varName,grpNull];
_group = if (isNull _storedGroup) then {group _unit} else {_storedGroup};
_stuffToIgnore = ["TALK","SCRIPTED"];
//player sideChat (str(_group));
_waypoint = [_group,(currentWaypoint _group)];
_type = waypointType [_group,(currentWaypoint _group)];
_nextWaypointNumber = if (_type in _stuffToIgnore) then {(currentWaypoint _group) + 1} else {(currentWaypoint _group)};
_group setCurrentWaypoint [_group,_nextWaypointNumber];private ["_unit","_cansee","_cansee"];
_unit = _this select 0;
while {alive _unit} do
{
_stance = stance _unit;
if (_stance == "Prone") then
{
_unit setUnitPos "Middle";
_cansee = [_unit] call gaia_fnc_cansee;
if (_cansee) exitWith {sleep 5; _unit setUnitPos "Auto";};
_unit setUnitPos "Up";
sleep 5;
_unit setUnitPos "Auto"
};
sleep 2;
};_seekUnits = _this select 0;
_targetPos = _this select 1;
_build = _this select 2;
if (!isnil("_build")) then
{
_buildpositions = [];
_pcnt = 0;
while {format ["%1", _build buildingPos (_pcnt)] != "[0,0,0]" } do {
_pos = _build buildingPos (_pcnt);
_buildpositions set [count _buildpositions, _pos];
_pcnt = _pcnt + 1;
};
_cdist = 100;
_closest = 0;
for "_i" from 0 to ((count _buildpositions) - 1) do
{
_sel = _buildpositions select _i;
if ((_sel distance _targetPos) < _cdist) then
{
_cdist = (_sel distance _targetPos);
_closest = _i;
};
};
{
_x forcespeed 2;
_x setVariable ["Garrison_Moving", true];
doStop _x;
sleep 0.1;
_x doMove (_build buildingpos (_buildingpositions select _closest));
} foreach _seekUnits;
hint (str(_seekUnits));
}
else
{
{
_x forcespeed 2;
_x setVariable ["Garrison_Moving", true];
doStop _x;
sleep 0.1;
_x moveTo _targetPos;
} foreach _seekUnits;
hint "incoming";
};
_build = _this select 0;
_sillyarray = switch (typeof _build) do {
case "Land_vez" : {[true,[2]]};
case "Land_Misc_Cargo1Ao" : {[true,[1,2]]};
case "Land_Misc_Cargo1Bo" : {[true,[1,2]]};
case "Land_Misc_Cargo1Bo_military" : {[true,[1,2]]};
case "Land_Misc_deerstand" : {[true,[0,1]]};
case "Land_Vysilac_FM" : {[true,[0,2,4]]};
case "Land_vysilac_FM2" : {[true,[0,2,4]]};
case "Land_A_Crane_02a" : {[true,[0,1]]};
case "Land_A_Crane_02b" : {[true,[]]};
case "Land_Climbing_Obstacle" : {[true,[]]};
case "Land_Ind_MalyKomin" : {[true,[0,2,4]]};
default {[false]};
};
_sillyarray
private ["_dir","_unit","_infront","_willsee"];
_unit = _this select 0;
_dir = getdir _unit;
_group = group _unit;
_staying = _group getvariable ["defending",true];
//hint "running smart look";
_pos = getposATL _unit;
_build = _unit getVariable ["homebuild",nil]; if (isNil ("_build")) then { _build = (nearestobjects [getposATL _unit,["house"],30] select 0);};
_bpos = _unit getvariable ["homepos",0];
_dest = [];
_sleep_check =
{
sleep ((random 3) + 1);
if !((group _unit) getVariable ["Garrisoning",false]) exitWith {};
};
_unit setVariable ["forcedspeed",0];
while {alive _unit && ((group _unit) getVariable ["Garrisoning",false])} do
{
//player globalchat "wastart smart";
//if !((_unit getVariable ["forcedspeed",-1]) >= 0) exitWith {hint (str(_unit getVariable ["forcedspeed",-1]))};
call _sleep_check;
call _sleep_check;
call _sleep_check;
call _sleep_check;
call _sleep_check;
_bMoving = _unit getVariable ["Garrison_Moving",false];
if (!_bMoving) then
{
_action = 2;
_waittime = 0.1;
_rand = random 10;
if (_rand <= 1) then {_action = 1;_waittime = 5};
if ((_rand > 1) && (_rand <= 6)) then {_action = 0;_waittime = 3};
// if meant to be indoors and not indoors... go back inside before deciding to move anywhere
if (_staying) then
{
if (_action == 0) then
{
if (_unit getvariable ["indoors",false]) then
{
_indoors = [_unit] call gaia_fnc_indoors;
if (!(_indoors)) then
{
_action = 1;_waittime = 5
};
}
else
{
_homePos = _build buildingpos _bpos;
if ((_pos distance _homePos) > 15) then
{
_action = 1;_waittime = 5
};
};
};
};
switch (_action) do
{
case 0 :
{
_willwalk = false;
_i = 0;
while {!(_willwalk)} do
{
_rdir = random 360;
_homedir = [_unit,_pos] call gaia_fnc_get_angle;
_ofdir = if ((_rdir - _homedir) < 0) then {(_rdir - _homedir) + 360} else {_rdir - _homedir};
_dir = if (_ofdir > 180) then {_rdir + ((360 - _ofdir) / 2)} else {_homedir + (_ofdir / 2)};
_walkfncarray = [_unit,_dir] call gaia_fnc_willwalk;
_willwalk = _walkfncarray select 0;
_dest = _walkfncarray select 1;
/*
_ball1 = "Sign_Sphere25cm_F" createVehicle [0,0,0];
_ball1 setPosATL _dest;
hint (format ["%1 \n %2",_willwalk,_dest]);
sleep 2;
*/
//hint "walking";
if ((_i >= 20) && (!_willwalk)) exitwith {_dest = (getposATL _unit)};
_i = _i + 1;
};
//_ball1 = "Sign_Sphere25cm_F" createVehicle [0,0,0];
//_ball1 setPosATL _dest;
};
case 1 :
{
_dest = _build buildingpos _bpos;
//hint "retuning";
};
default
{
_dest = (getposATL _unit);
//hint "staying";
};
};
if ((combatmode (group _unit)) == "RED") then {(group _unit) setcombatmode "YELLOW"};
if !((group _unit) getVariable ["Garrisoning",false]) exitWith {};
if ((group _unit) getVariable ["Garrisoning",false]) then
{
_unit forcespeed 2;
[_unit,_dest] call gaia_fnc_MoveTo;
waituntil {sleep _waittime;true};
};
_unit forcespeed (_unit getvariable ["forcedspeed",-1]);
waituntil {(time - (_unit getvariable ["alerted",0])) > 10};
_willsee = false;
_infront = [];
while {!(_willsee)} do
{
_dir = random 360;
_fncarray = [_unit,_dir] call gaia_fnc_willsee;
_willsee = _fncarray select 0;
_infront = _fncarray select 1;
};
//hint "looking";
_unit lookat objNull;
_unit lookat (ASLtoATL _infront);
}
else
{
_unit forcespeed 2;
};
};
_unit enableAI "TARGET";
_unit enableAI "AUTOTARGET";
_unit enableAI "FSM";
//_unit allowfleeing 1;
private ["_unit","_cansee","_bMoving","_bAlerted","_infront","_willsee","_fncarray","_dir"];
_unit = _this select 0;
_group = group _unit;
while {alive _unit && (_group getVariable ["Garrisoning",false])} do
{
_bMoving = if ((speed _unit) > 0) then {true} else {false};
_bAlerted = if ((abs (time - (_unit getvariable ["alerted",0]))) < 10) then {true} else {false};
if (!(_bMoving or _bAlerted)) then
{
_cansee = [_unit] call gaia_fnc_cansee;
if (!_cansee) then
{
_willsee = false;
_infront = [];
while {!(_willsee)} do
{
_dir = random 360;
_fncarray = [_unit,_dir] call gaia_fnc_willsee;
_willsee = _fncarray select 0;
_infront = _fncarray select 1;
};
[_unit,(ASLtoATL _infront)] call gaia_fnc_cqc_target;
};
//_nearUnits = [];
//_nearUnits = _unit nearentities [["Man"],0.8];
//_bTooClose = if ((count _nearUnits) > 0) then {true} else {false};
};
sleep 1.5;
};private ["_willsee","_infront","_uposASL","_opp","_adj","_hyp","_eyes","_obstruction","_angle"];
_unit = _this select 0;
_angle = _this select 1;
_uposASL = getposASL _unit;
_eyes = eyepos _unit;
_hyp = 5;
_adj = _hyp * (cos _angle);
_opp = sqrt ((_hyp*_hyp) - (_adj * _adj));
_infront = if ((_angle) >= 180) then
{
[(_eyes select 0) - _opp,(_eyes select 1) + _adj,(_eyes select 2)]
}
else
{
[(_eyes select 0) + _opp,(_eyes select 1) + _adj,(_eyes select 2)]
};
_obstruction = (lineintersectswith [_eyes,_infront,_unit]) select 0;
_willsee = if (isnil("_obstruction")) then {true} else {false};
[_willsee,_infront]
private ["_infront","_willwalk","_upos","_obstruction","_opp","_adj","_hyp","_angle"];
_unit = _this select 0;
_angle = _this select 1;
_upos = getposASL _unit;
_upos set [2,(_upos select 2) + 0.5];
_hyp = (random 4) + 1; // distance to walk
_adj = _hyp * (cos _angle);
_opp = sqrt ((_hyp*_hyp) - (_adj * _adj));
_infront = if ((_angle) >= 180) then
{
[(_upos select 0) - _opp,(_upos select 1) + _adj,(_upos select 2)]
} else {
[(_upos select 0) + _opp,(_upos select 1) + _adj,(_upos select 2)]
};
_obstruction = (lineintersectswith [_upos,_infront,_unit]) select 0;
_willwalk = if (isnil("_obstruction")) then {true} else{false};
_infrontATL = (ASltoATL _infront);
if (_willwalk) then
{
if ((_infrontATL select 2) > 2) then
{
_below = [(_infront select 0),(_infront select 1),((_infront select 2) - 2)];
/*
_ball1 = "Sign_Sphere25cm_F" createVehicle [0,0,0];
_ball1 setPosASL _below;
_ball1 setObjectTexture [0,"#(argb,8,8,3)color(0,0,1,1)"];
_ball2 = "Sign_Sphere25cm_F" createVehicle [0,0,0];
_ball2 setPosASL _infront;
*/
_floor = (lineintersectswith [_infront,_below]) select 0;
_inAir = if (isnil("_floor")) then {true} else {false};
_willwalk = if (_inAir) then {false} else {true};
};
_nearUnits = [];
_nearUnits = _infrontATL nearentities [["Man"],0.8];
_bTooClose = if ((count _nearUnits) > 0) then {true} else {false};
_willwalk = if (_bTooClose or (!_willwalk)) then {false} else {true};
};
[_willwalk,_infrontATL]
Garrison script by zorilya
This script will allow you to make a more lively urban environment where you have to check every window and door in every house
rather than having in the back of your mind 'it's arma, AI don't go in buildings very well'. the units you put into buildings
will remain there pretty well under fire but if you get bogged down they might come to you so bust in a clear them out.
you can also use this to liven up a patrol route by setting the waypoint onAct with the script so the group gets there and garrisons a nearby building.
then to get them to leave run the "fnc_next_waypooint.sqf" the onAct of a scripted waypoint. set the condition to whatever you'd like and they will then
leave when the condition is met and regroup at the scripted waypoint position.
to run just use this template;
nul = [unit,radius,stationary (bool),capacityarray ([(0 - 100),max in one building] default [60,0]),warping (bool),allUseCQC_AI (including non garrisoned units) (bool)] execVM "Garrison_script.sqf";
where unit is the leader of the group and radius is the radius of the area he will search for buildings.
so like this
nul = [_leader,100,true,[60,3],false,true] execVM "Garrison_script.sqf"
then your dudes will wait a sec and pick a building from the area at random and fill it up then pick another
and fill it and so on until there are no more buildings or no more units.
if all buildings are occupied or none are in range, the group randomly patrol around staying in the general area of the nearest building
or
if no buildings at all the group will break up into 4 man squads and patrol around the original position
Please remember this makes a random choice from the buildings in an area... if you want them in a specific building just set the radius really small
and move the leader really close to the building. works a treat :)
you may Improve on this design so long as there is atleast a mention of the source and obviously that you share so we can all benifit.
works with vanilla AI as it has it's own CQC_AI improvments. the CQC_AI can be applyied to units without the need for the Garrison script too and really sharpens up a unit's reactions.
to run that just use
nul = [_unit] execVM "CQC_AI.sqf";
this will add more realistiic vision reaction, proximity reactions and weapon noise reactions. for further details on how they work, check out my videos describing them at "http://www.youtube.com/zorilya" or have a read of the scripts.
enjoy
suggested for fun !
add about 6 enemy groups into a building heavy area and run the garrison on all of the leaders setting the radius to about 50m.
try and kill them all it's quick to set up and a ton of fun.
Stress test:
I have run this on 24 groups (with 10 or more units each. 240 units give or take) and had a further 40 units without it on my PC, not a dedicated server and saw a minimal drop in performance.
320 runing this killed it for me though, FPS was noticably down. I have no doubt this is just because i was hosting and playing on the same machine. as of 1.5 this may have changed.
known issues :
AI will still occasionally be retarded. on the whole though things are better :)
ChangeLog v1.7.1
ADDED : extra parameter to control if CQC_AI is applied to all units or just Garrisoned Units (see template);
FIXED : Stupid doStop removed that was making units unable to complete waypoints if using CQC_AI;
ChangeLog v1.7
ADDED : TOO MANY THINGS TO COUNT. many different functions to improve moving, reacting, and patroling.
ADDED : whole new CQC_AI;
ADDED : ability for the use of waypoints to Garrison and unGarrison buildings (using above mentioned method);
FIXED : 3 major while loops that would under certain circumstances loop indefinately.
IMPROVED : performance through numerous reworks of functions.
Missed 1.6 :s
Changelog v1.5.1
hotfix
Fixed : sorted roaming problem caused by unstable variable. roaming now works as intended.
changed : Tweaked the willwalk.sqf to improve roaming.
Changelog v1.5
Added : cqc reaction funtions. Units are now more aware of enemies when they fire round close by and look in a logical direction.
Added : garrisoned units can now move inside buildings, improving randomness of the environment.
Changed : 4 man limit to patrol groups then next group is made and so on.
Changed : many other little optimisations.
Changelog v1.4
Added : indoors check to control behaviour i.e. crouching on roofs and balconys (works better than the old top third check);
Added : check for watch towers (and other buiildings) to avoid 3 units garrisoning the one tower (who makes a one man watch tower with 3 positions? who does that?)
Added : vision obscured check to stop units looking in useless directions.
Changed : increased time that script waits for a patrol group before exiting to 4 minutes to handle yet more pathfinding issues.
changelog v1.3
added : small tweak so that units look around a little more, it's random!
added : height check relative to building so that units now crouch when on roofs. balconys and overhangs that are not the top of a building are a liitle hit and miss.
added : persitance to getting into position. pathfinding being as problematic as it can be, a unit will try a few times to get into position before givin up and joining a patrol group.
changed : no longer required the World_build_list.sqf or any other over arching variables. This means you can nowuse in on any map!
Changed : optimised the script since the first change making it on average 3 seconds faster when executing (less standing around looking gormless).
Changed : Improved the checks for occuppied buildings to ensure even less doubling up when garrisoning with multiple groups in the same area (seems to only mess up when i accellerate time hehe).
changed : better system for patrol script to loop (doesn't constantly call the script anymore);
Removed : all world buildings lists. no need for them any more.
Removed : annoying debug hints that are no longer needed thanks to patrol script.
changelog v1.2
added : redesigned building check to include an occupied variable so as to avoid different groups garrisoning the same building.
added : patrol script. if all buildings are occupied or none are in range, the group randomly partol around staying in the general area of the nearest building.
changelog v1.1
added : compatibility with more islands
added : randomiser for stationary command
/* ----------------------------------------------------------------------------
Function: fnc_addWaypoint
Description:
A function used to add a waypoint to a group.
Parameters:
- Group
- Position
_ Zone
_ Type
Returns:
Waypoint
Author:
Spirit, 7-1-2014
---------------------------------------------------------------------------- */
private ["_group","_position","_Zone","_waypoint","_ZoneBehaviour"];
_group = _this select 0;
_position = _this select 1;
_WPType = _this select 2;
_Radius = 40;
_waypoint = _group addWaypoint [_position, 0];
_waypoint setWaypointType _WPType;
if (behaviour (leader _group) != "COMBAT") then
{_waypoint setWaypointBehaviour "AWARE";};
_waypoint setWaypointCombatMode "RED";
_waypoint setWaypointSpeed "FULL" ;
_waypoint setWaypointFormation "VEE" ;
_waypoint setWaypointCompletionRadius _Radius;
_waypoint;
/* ----------------------------------------------------------------------------
Function: fnc_addWaypoint
Description:
A function used to add a waypoint to a group.
Parameters:
- Group
- Position
_ Zone
_ Type
Returns:
Waypoint
Author:
Spirit, 7-1-2014
---------------------------------------------------------------------------- */
private ["_group","_position","_Zone","_waypoint","_ZoneBehaviour"];
_group = _this select 0;
_position = _this select 1;
_WPType = _this select 2;
_Radius = 40;
//Blacklist the target position (so no other dudes go here before we arrive and for that make us useless.
switch (side _group) do
{
case WEST : {MCC_GAIA_WPPOS_WEST = MCC_GAIA_WPPOS_WEST + [[_position,_group]];};
case EAST : {MCC_GAIA_WPPOS_EAST = MCC_GAIA_WPPOS_EAST + [[_position,_group]];};
case independent: {MCC_GAIA_WPPOS_INDEP = MCC_GAIA_WPPOS_INDEP + [[_position,_group]];};
};
//Do what you say you do. Go there.
_waypoint = _group addWaypoint [_position, 0];
_waypoint setWaypointType _WPType;
_waypoint setWaypointCompletionRadius _Radius;
_waypoint setWaypointTimeout [20, 30, 25];
_waypoint;
/* ----------------------------------------------------------------------------
Function: fnc_CreateBuildingWP
Description:
Create waypoints to patrol houses within the given radius
Parameters:
- Group
- pos
Returns:
Nr of generated waypoints
Author:
Spirit
---------------------------------------------------------------------------- */
private ["_group", "_buildings ","_max","_i","_wp","_pos"];
_group = _this select 0;
_pos = _this select 1;
//Then actualy go there.
_buildings = (nearestObjects [_pos, ["house"], 30]);
_nr =0;
{
_i=0;
while {str(_x buildingPos _i) != "[0,0,0]"} do {_i = _i + 1;};
_wp = _group addWaypoint [(getPos _x), 0];
_wp setWaypointType "MOVE";
_wp setWaypointHousePosition random(_i);
_wp waypointAttachObject _x;
_nr= _nr +1;
} foreach _buildings;
//We found buildings? Make sure nobody else goes here
if (_nr>0) then
{
//Make sure we dont go here again.
switch (side _group) do
{
case WEST : {MCC_GAIA_WPPOS_WEST = MCC_GAIA_WPPOS_WEST + [[_pos,_group]];};
case EAST : {MCC_GAIA_WPPOS_EAST = MCC_GAIA_WPPOS_EAST + [[_pos,_group]];};
case independent: {MCC_GAIA_WPPOS_INDEP = MCC_GAIA_WPPOS_INDEP + [[_pos,_group]];};
};
};
_nr/* ----------------------------------------------------------------------------
Function: fnc_CreatePatrolWP
Description:
Create waypoints for a group
Parameters:
- Group
- Zone
Returns:
Nr of generated waypoints
Author:
Spirit
---------------------------------------------------------------------------- */
private ["_group", "_newpos ","_zone","_max","_i","_wp"];
_group = _this select 0;
_zone = _this select 1;
_goal = _this select 2;
//Combined orders store the original location (where he wanted to go before getting in the transporter) in this variable. So check if it holds a position
_newpos = _group getVariable ["GAIA_OriginalDestination",[]];
_group setVariable ["GAIA_OriginalDestination", [], false];
if (count(_newpos)==0) then
{
_newpos = [_zone,_goal,(side _group)] call fnc_GetPosition;
};
if (count(_newpos)>0) then
{
//Now where ever a unit has last been, place a breadcrumb (so even static guards).
// This is used for making the patrols as optimized as possible. We try to avoid those positions.
_dummy = [_group,_newpos,"MOVE"] call fnc_addWaypoint;
};
_newpos//==================================================================fnc_DoInfPatrol===============================================================================================
// Mortar
// Example: [_group, Position] call fnc_DoMortar
// spirit 1-2-2014
//===========================================================================================================================================================================
private ["_group","_pos","_isInRange","_rounds","_MortarRound","_ammo","_radiusSpread"];
_group = _this select 0;
_pos = _this select 1;
_ammo = [];
_radiusSpread = 0;
_class = _group getVariable ["GAIA_class",[]];
_MortarRound = _group getVariable ["GAIA_MortarRound",0];
_ammo = (getArtilleryAmmo [(assignedVehicle (leader _group))] select 0);
//If we were busy somewhere, finish it
if (_MortarRound>0) then {_pos = _group getVariable ["GAIA_MortarTarget",[0,0,0]];};
//If this is the second round, we dont check for all sorts of stuff. Finish what you started
_isInRange = (_pos inRangeOfArtillery [[(leader _group)],_ammo ]) or (_MortarRound>0) ;
// First Shot
if (_isInRange) then
{
switch(true)do
{
case (_MortarRound<2) : {_radiusSpread= 120;_rounds =1;};
case (_MortarRound<3) : {_radiusSpread= 100;_rounds =1;};
case (_MortarRound<4) : {_radiusSpread= 080;_rounds =1;};
case (_MortarRound<5) : {_radiusSpread= 010;_rounds =3;};
//The 'Fire For Effect' will not always be achieved. It can be skipped if we roll 2 in the random roll in the code below
case (_MortarRound<=6): {_radiusSpread= 000;_rounds =8;};
case (_MortarRound<=10): {_radiusSpread= 010;_rounds =1;};
};
///Pos is for all mortar in group
_mortarPos = [_pos, _radiusSpread, random(360)] call BIS_fnc_relPos;;
//Fire dudes
{
if (alive _x) then
{
(vehicle _x) addMagazine _ammo;
_x commandArtilleryFire [_mortarPos, _ammo , _rounds ];
};
}foreach (units _group);
// We finished this round so go up (sometimes faster then other times)
_MortarRound = _MortarRound + round((random 2));
if (_MortarRound>=10) then
{
//Specific Mortar information
_group setVariable ["GAIA_MortarRound" , 0, false];
_group setVariable ["GAIA_MortarTarget" , [0,0,0], false];
}
else
{
//Specific Mortar information
_group setVariable ["GAIA_MortarRound" , _MortarRound, false];
_group setVariable ["GAIA_MortarTarget" , _pos, false];
};
//Lets set the current Order.
_group setVariable ["GAIA_Order" , "DoMortar", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_group setVariable ["GAIA_OrderTime" , Time, false];
_group setVariable ["GAIA_OrderPosition" , (position leader _group), false];
};
_isInRange
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos","_TargetPos"];
_group = _this select 0;
_TargetPos = _this select 1;
//Combat Requirements
if (
((_group getVariable ["GAIA_Order",""])!="DoAttack")
or
(((_group getVariable ["GAIA_OrderPosition",[0,0,0]]) distance _TargetPos)>0)
)
then
{ //Check Attack Requirements
_class = _group getVariable ["GAIA_class",[]];
if (!IsNil("_class") ) then
{
switch(_class) do
{
//Infantry
case "Infantry":
{ _dummy= [_group,_TargetPos] call fnc_DoAttackInf;};
case "ReconInfantry":
{ _dummy= [_group,_TargetPos] call fnc_DoAttackRecon;};
case "Car":
{ _dummy= [_group,_TargetPos] call fnc_DoAttackCar;};
case "MotorizedRecon":
{ _dummy= [_group,_TargetPos] call fnc_DoAttackMotorRecon;};
case "MechanizedInfantry":
{ _dummy= [_group,_TargetPos] call fnc_DoAttackMechInf;};
case "MotorizedInfantry":
{ _dummy= [_group,_TargetPos] call fnc_DoAttackMotorInf;};
case "Tank":
{ _dummy= [_group,_TargetPos] call fnc_DoAttackMotorRecon;};
case "Helicopter":
{ _dummy= [_group,_TargetPos] call fnc_DoAttackHeli;};
//Autonomous for now the same
case "Autonomous":
{ _dummy= [_group,_TargetPos] call fnc_DoAttackHeli;};
case "Ship":
{ _dummy= [_group,_TargetPos] call fnc_DoAttackShip;};
};
sleep 0.1;
//Lets set the current Order.
_group setVariable ["GAIA_Order" , "DoAttack", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_group setVariable ["GAIA_OrderTime" , Time, false];
_group setVariable ["GAIA_OrderPosition" , _TargetPos, false];
};
};
true
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our attack
// Example: [_group,_targetpos] call fnc_DoAttackInf
// spirit 20-1-2014
//===========================================================================================================================================================================
private ["_group","_TargetPos","_pos","_Degree","_NrOfBuildingWp"];
_group = _this select 0;
_TargetPos = _this select 1;
[_group] call fnc_RemoveWayPoints;
_dummy =[_group,_TargetPos, "MOVE"] call fnc_AddAttackWaypoint;
((count (waypoints _group)) - currentWaypoint _group)
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our attack
// Example: [_group,_targetpos] call fnc_DoAttackInf
// spirit 20-1-2014
//===========================================================================================================================================================================
private ["_group","_TargetPos","_pos","_Degree","_NrOfBuildingWp"];
_group = _this select 0;
_TargetPos = _this select 1;
[_group] call fnc_RemoveWayPoints;
_dummy =[_group,_TargetPos, "SAD"] call fnc_AddAttackWaypoint;
((count (waypoints _group)) - currentWaypoint _group)
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our attack
// Example: [_group,_targetpos] call fnc_DoAttackInf
// spirit 20-1-2014
//===========================================================================================================================================================================
private ["_group","_TargetPos","_pos","_Degree","_NrOfBuildingWp"];
_group = _this select 0;
_TargetPos = _this select 1;
_Pos = (position leader _group);
_CoverPos = [];
_NrOfBuildingWp = 0;
_Degree = 0;
_angle = [42,0,-42] call BIS_fnc_selectRandom;
[_group] call fnc_RemoveWayPoints;
if !(surfaceiswater _TargetPos ) then
{
while {(_Pos distance _TargetPos)>200} do
{
sleep 0.1;
//Determine our compass heading from group leader to _TargetPos
_Degree=[_Pos, _TargetPos] call BIS_fnc_dirTo;
//With a -30 to + 30 degree difference do move 100 to TargetPos
_pos =[_Pos, (((_Pos distance _TargetPos)/2) max 100),(_Degree-(_Angle)) ] call BIS_fnc_relPos;
//And please, please, please, try some cover ok.Within 50, so another wild flanking thingy
_CoverPos = [];
_CoverPos =selectBestPlaces [_pos, 30, "forest+trees+2*hills+houses", 1, 1];
//We found some good stuf, go use it
if ((count (_CoverPos))>0) then
{
_CoverPos=(_CoverPos select 0 select 0);
_pos = _CoverPos;
};
if !(surfaceiswater _pos ) then
{
//Give the dude an Attack Waypoint
_dummy =[_group,_pos, "MOVE"] call fnc_AddAttackWaypoint;
};
};
_dummy =[_group,_TargetPos, "SAD"] call fnc_AddAttackWaypoint;
//_NrOfBuildingWp = [_group]call fnc_CreateBuildingWP;
};
((count (waypoints _group)) - currentWaypoint _group)
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our attack
// Example: [_group,_targetpos] call fnc_DoAttackInf
// spirit 20-1-2014
//===========================================================================================================================================================================
private ["_group","_TargetPos","_pos","_Degree","_NrOfBuildingWp"];
_group = _this select 0;
_TargetPos = _this select 1;
[_group] call fnc_RemoveWayPoints;
_dummy =[_group,_TargetPos, "MOVE"] call fnc_AddAttackWaypoint;
((count (waypoints _group)) - currentWaypoint _group)
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our attack
// Example: [_group,_targetpos] call fnc_DoAttackInf
// spirit 20-1-2014
//===========================================================================================================================================================================
private ["_group","_TargetPos","_pos","_Degree","_NrOfBuildingWp"];
_group = _this select 0;
_TargetPos = _this select 1;
[_group] call fnc_RemoveWayPoints;
_dummy =[_group,_TargetPos, "MOVE"] call fnc_AddAttackWaypoint;
((count (waypoints _group)) - currentWaypoint _group)
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our attack
// Example: [_group,_targetpos] call fnc_DoAttackInf
// spirit 20-1-2014
//===========================================================================================================================================================================
private ["_group","_TargetPos","_pos","_Degree","_NrOfBuildingWp"];
_group = _this select 0;
_TargetPos = _this select 1;
[_group] call fnc_RemoveWayPoints;
_dummy =[_group,_TargetPos, "MOVE"] call fnc_AddAttackWaypoint;
((count (waypoints _group)) - currentWaypoint _group)
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our attack
// Example: [_group,_targetpos] call fnc_DoAttackInf
// spirit 20-1-2014
//===========================================================================================================================================================================
private ["_group","_TargetPos","_pos","_Degree","_NrOfBuildingWp"];
_group = _this select 0;
_TargetPos = _this select 1;
_Pos = (position leader _group);
_CoverPos = [];
_NrOfBuildingWp = 0;
_Degree = 0;
_angle = [42,0,-42] call BIS_fnc_selectRandom;
[_group] call fnc_RemoveWayPoints;
if !(surfaceiswater _TargetPos ) then
{
//Set the recon unit in stealth
_group setBehaviour "STEALTH";
while {(_Pos distance _TargetPos)>200} do
{
sleep 0.1;
//Determine our compass heading from group leader to _TargetPos
_Degree=[_Pos, _TargetPos] call BIS_fnc_dirTo;
//With a -30 to + 30 degree difference do move 100 to TargetPos
_pos =[_Pos, (((_Pos distance _TargetPos)/2) max 100),(_Degree-(_Angle)) ] call BIS_fnc_relPos;
//And please, please, please, try some cover ok.Within 50, so another wild flanking thingy
_CoverPos = [];
_CoverPos =selectBestPlaces [_pos, 30, "forest+trees+2*hills+houses", 1, 1];
//We found some good stuf, go use it
if ((count (_CoverPos))>0) then
{
_CoverPos=(_CoverPos select 0 select 0);
_pos = _CoverPos;
};
if !(surfaceiswater _pos ) then
{
//Give the dude an Attack Waypoint
_dummy =[_group,_pos, "MOVE"] call fnc_AddAttackWaypoint;
};
};
_dummy =[_group,_TargetPos, "SAD"] call fnc_AddAttackWaypoint;
//_NrOfBuildingWp = [_group]call fnc_CreateBuildingWP;
};
((count (waypoints _group)) - currentWaypoint _group)
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our attack
// Example: [_group,_targetpos] call fnc_DoAttackInf
// spirit 20-1-2014
//===========================================================================================================================================================================
private ["_group","_TargetPos","_pos","_Degree","_NrOfBuildingWp"];
_group = _this select 0;
_TargetPos = _this select 1;
[_group] call fnc_RemoveWayPoints;
_dummy =[_group,_TargetPos, "SAD"] call fnc_AddAttackWaypoint;
((count (waypoints _group)) - currentWaypoint _group)
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our attack
// Example: [_group,_targetpos] call fnc_DoAttackInf
// spirit 20-1-2014
//===========================================================================================================================================================================
private ["_group","_TargetPos","_pos","_Degree","_NrOfBuildingWp"];
_group = _this select 0;
_TargetPos = _this select 1;
[_group] call fnc_RemoveWayPoints;
_dummy =[_group,_TargetPos, "MOVE"] call fnc_AddAttackWaypoint;
((count (waypoints _group)) - currentWaypoint _group)
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos","_SpotPos"];
_group = _this select 0;
_SpotPos = _this select 1;
//Combat Requirements
if (
((_group getVariable ["GAIA_Order",""])!="DoClear")
or
(((_group getVariable ["GAIA_OrderPosition",[0,0,0]]) distance _SpotPos)>0)
)
then
{ //Check Attack Requirements
_class = _group getVariable ["GAIA_class",[]];
if (!IsNil("_class") ) then
{
switch(_class) do
{
//Infantry
case "Infantry":
{ _dummy= [_group,_SpotPos] call fnc_DoClearInf;};
case "ReconInfantry":
{ _dummy= [_group,_SpotPos] call fnc_DoClearRecon;};
};
sleep 0.1;
//Lets set the current Order.
_group setVariable ["GAIA_Order" , "DoClear", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_group setVariable ["GAIA_OrderTime" , Time, false];
_group setVariable ["GAIA_OrderPosition" , _SpotPos, false];
};
};
true
//==================================================================fnc_DoInfPatrol===============================================================================================
// Clear the area and or the house at the spot location
//
// spirit 26-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_pos = _this select 1;
_NrOfBuildingWp = 0;
[_group] call fnc_RemoveWayPoints;
_NrOfBuildingWp = [_group,_pos]call fnc_CreateBuildingWP;
//when no buildings found, put an SAD waypoint down
if (_NrOfBuildingWp == 0) then
{
_dummy = [_group,_pos,"SAD"] call fnc_addWaypoint;
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Clear the area and or the house at the spot location
//
// spirit 26-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_pos = _this select 1;
_NrOfBuildingWp = 0;
[_group] call fnc_RemoveWayPoints;
_NrOfBuildingWp = [_group,_pos]call fnc_CreateBuildingWP;
//when no buildings found, put an SAD waypoint down
if (_NrOfBuildingWp == 0) then
{
_dummy = [_group,_pos,"SAD"] call fnc_addWaypoint;
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoFortify
// spirit 11-2-2014
//===========================================================================================================================================================================
private ["_group","_TargetPos","_zone"];
_group = _this select 0;
_TargetPos = _this select 1;
_zone = (((_group) getVariable ["GAIA_zone_intend",[]])select 0);
if !(isnil("_Zone")) then
{
[_group] call fnc_RemoveWayPoints;
_group setSpeedMode "FULL";
[_group,(getMarkerpos _zone),((((getMarkerSize _zone)select 0) max ((getMarkerSize _zone)select 1)) min 500)] call gaia_CBA_fnc_taskDefend;
//Lets set the current Order.
_group setVariable ["GAIA_Order" , "DoFortify", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_group setVariable ["GAIA_OrderTime" , Time, false];
_group setVariable ["GAIA_OrderPosition" , _TargetPos, false];
};
true
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our support guys. Yes they are 'easy' at the moment. Just make it work is the goal for release 1.
//
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_pos","_zone"];
//Get the group
_group = _this select 0;
//Clear what ever orders we had before.
[_group] call fnc_RemoveWayPoints;
//Get the zone
_zone = (((_group) getVariable ["GAIA_zone_intend",[]])select 0);
if !(isnil("_Zone")) then
{
//Go somewhere
_pos= [_group,_zone,"VEH_HILLS_FOREST_FLAT"] call fnc_CreateWP;
if (count(_pos)>0) then
{
//Sentry has the nice habit to end the waypoint ones they seen enemy. That is good as they will "hide" again then.
_dummy = [_group,_pos,"MOVE"] call fnc_addWaypoint;
_dummy = [_group,_Pos,"SENTRY"] call fnc_addWaypoint;
//Lets set the current Order.
_group setVariable ["GAIA_Order" , "DoHide", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_group setVariable ["GAIA_OrderTime" , Time, false];
_group setVariable ["GAIA_OrderPosition" , (position leader _group), false];
};
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Mortar
// Example: [_group, Position] call fnc_DoMortar
// spirit 1-2-2014
//===========================================================================================================================================================================
private ["_group","_pos","_isInRange","_rounds","_MortarRound","_ammo","_radiusSpread"];
_group = _this select 0;
_pos = _this select 1;
_ammo = [];
_radiusSpread = 0;
_class = _group getVariable ["GAIA_class",[]];
_MortarRound = _group getVariable ["GAIA_MortarRound",0];
_ammo = (getArtilleryAmmo [(assignedVehicle (leader _group))] select 0);
//If we were busy somewhere, finish it
if (_MortarRound>0) then {_pos = _group getVariable ["GAIA_MortarTarget",[0,0,0]];};
//If this is the second round, we dont check for all sorts of stuff. Finish what you started
_isInRange = (_pos inRangeOfArtillery [[(leader _group)],_ammo ]) or (_MortarRound>0) ;
// First Shot
if ((_isInRange) and !Isnil("_ammo")) then
{
switch(true)do
{
case (_MortarRound<2) : {_radiusSpread= 120;_rounds =1;};
case (_MortarRound<3) : {_radiusSpread= 100;_rounds =1;};
case (_MortarRound<4) : {_radiusSpread= 080;_rounds =1;};
case (_MortarRound<5) : {_radiusSpread= 010;_rounds =3;};
//The 'Fire For Effect' will not always be achieved. It can be skipped if we roll 2 in the random roll in the code below
case (_MortarRound<=6): {_radiusSpread= 000;_rounds =8;};
case (_MortarRound<=10): {_radiusSpread= 010;_rounds =1;};
};
///Pos is for all mortar in group
_mortarPos = [_pos, _radiusSpread, random(360)] call BIS_fnc_relPos;;
//Fire dudes
{
if (alive _x) then
{
(vehicle _x) addMagazine _ammo;
_x commandArtilleryFire [_mortarPos, _ammo , _rounds ];
};
}foreach (units _group);
// We finished this round so go up (sometimes faster then other times)
_MortarRound = _MortarRound + round((random 2));
if (_MortarRound>=10) then
{
//Specific Mortar information
_group setVariable ["GAIA_MortarRound" , 0, false];
_group setVariable ["GAIA_MortarTarget" , [0,0,0], false];
}
else
{
//Specific Mortar information
_group setVariable ["GAIA_MortarRound" , _MortarRound, false];
_group setVariable ["GAIA_MortarTarget" , _pos, false];
};
//Lets set the current Order.
_group setVariable ["GAIA_Order" , "DoMortar", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_group setVariable ["GAIA_OrderTime" , Time, false];
_group setVariable ["GAIA_OrderPosition" , (position leader _group), false];
};
_isInRange
//==================================================================fnc_DoInfPatrol===============================================================================================
// Validate if and organise transportation
//
// spirit 28-1-2014
//===========================================================================================================================================================================
private ["_group","_wpPos","_wptype"];
_group = _this select 0;
//where is this dude going?
_wpPos = (waypointPosition [_group ,(count(waypoints _group)-1)]);
_wptype = waypointType [_group ,(count(waypoints _group)-1)];
if ( _wppos distance [0,0,0]>0) then
{
//How fare does he need to travel?
_dist = _wpPos distance (position leader _group);
//If that is futther then the max range for slow speed groups, then he is legimate to receive transportation
if (_dist > MCC_GAIA_MAX_SLOW_SPEED_RANGE) then
{
{
//Now we go see if we hold a valid transporter
_TransportGrp = _x;
_TransportClass = (_TransportGrp getVariable ["GAIA_class",""]);
//Lets set the max range for transport (yes a case thingy migh be better, do it!)
_TransportRange = MCC_GAIA_MAX_SLOW_SPEED_RANGE;
if (_TransportClass in ["Car","Tank"]) then {_TransportRange = MCC_GAIA_MAX_MEDIUM_SPEED_RANGE;};
if (_TransportClass in ["Helicopter"]) then {_TransportRange = MCC_GAIA_MAX_FAST_SPEED_RANGE;};
if (
//Seems like allgroups opens up with all sorts of empty groups, better check it
((side _TransportGrp) == (side _group))
and
(count(units _TransportGrp)>0)
and
(alive (leader _TransportGrp))
and
((behaviour leader _TransportGrp)!="COMBAT")
and
//The transport vehicle must not be occupied
((_x getVariable ["GAIA_Order",""]) != "DoTransport")
and
//The transport vehicle must not be busy with an attack
((_x getVariable ["GAIA_Order",""]) != "DoAttack")
and
// He must be able to do transport
("DoTransport" in (_TransportGrp getVariable ["GAIA_Portfolio",[]]))
and
//He must be able to hold all of us
((count units _group)<=(_TransportGrp getVariable ["GAIA_cargo",0]))
and
//The vehicle cannot be so far out from the requesting group that it even exeeds its own max range based on medium speed
(((leader _group) distance (leader _TransportGrp))< _TransportRange)
//and
//The distance to transport must exceed the distance to the transport by 2 times.
//((_dist*2) > ((leader _group) distance (leader _TransportGrp)))
//and
//A transporter takes atleast MCC_GAIA_TRANSPORT_RESTTIME seconds of breaktime before getting a new order
// ((time-(_TransportGrp getVariable ["GAIA_Ordertime",0]))>MCC_GAIA_TRANSPORT_RESTTIME)
//and
//Cars only support patrols that are out of zone, they refure combat (until bis pays them more)
)
then
{
switch(_TransportClass) do
{
//Infantry
case "Car":
{ _dummy= [_group,_TransportGrp] call fnc_DoTransportCar;};
case "Tank":
{ _dummy= [_group,_TransportGrp] call fnc_DoTransportTank;};
case "Helicopter":
{ _dummy= [_group,_TransportGrp] call fnc_DoTransportHeli;};
case "Ship":
{ _dummy= [_group,_TransportGrp] call fnc_DoTransportShip;};
};
};
//If we have waypoints, stop (more then 1 as the initial patrol waypoint is the first).
//If this fails, every transport in the universe will try to serve us, maybe something smarter
if ( ((_group getVariable ["GAIA_Order",""]) == "DoTransport")) exitwith {true;};
//Lets assume the closest valid transporter is the most logic one (not always true, but i dunno yet how to improve without overcomplicate stuff)
}forEach ([AllGroups,[],{(leader _group) distance (leader _x)},"ASCEND",{alive (leader _x)}] call fnc_SortGroupsByCA);
};
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our support guys. Yes they are 'easy' at the moment. Just make it work is the goal for release 1.
//
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_pos","_zone"];
//Get the group
_group = _this select 0;
//Clear what ever orders we had before.
[_group] call fnc_RemoveWayPoints;
//Get the zone
_zone = (((_group) getVariable ["GAIA_zone_intend",[]])select 0);
if !(isnil("_Zone")) then
{
//Go somewhere
_pos= [_group,_zone,"ROAD"] call fnc_CreateWP;
if (count(_pos)>0) then
{
_nearRoad = (_pos nearRoads 10);
if (count(_nearroad)>0) then
//Arrange a pickup on the side of the street, else we gonna have ai crazyness going on
{_road = (([_nearRoad,[],{leader _group distance _x},"ASCEND"] call BIS_fnc_sortBy ) select 0);
_roadConnectedTo = roadsConnectedTo _road;
if (count(_roadConnectedTo)>0) then
{
_connectedRoad = _roadConnectedTo select 0;
_direction = [_road, _connectedRoad] call BIS_fnc_DirTo;
_pos = [(position _road), 7, (_direction - 45)] call BIS_fnc_relPos;
};
};
//Sentry has the nice habit to end the waypoint ones they seen enemy. That is good as they will "hide" again then.
_dummy = [_group,_pos,"MOVE"] call fnc_addWaypoint;
_dummy = [_group,_Pos,"SENTRY"] call fnc_addWaypoint;
//Lets set the current Order.
_group setVariable ["GAIA_Order" , "DoPark", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_group setVariable ["GAIA_OrderTime" , Time, false];
_group setVariable ["GAIA_OrderPosition" , (position leader _group), false];
};
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_class = _group getVariable ["GAIA_class",[]];
_zone = (((_group) getVariable ["GAIA_zone_intend",[]])select 0);
if (!IsNil("_class") and !Isnil("_zone")) then
{
switch(_class) do
{
//Infantry
case "Infantry":
{ _dummy= [_group,_zone] call fnc_DoPatrolInf;};
case "ReconInfantry":
{ _dummy= [_group,_zone] call fnc_DoPatrolRecon;};
case "MechanizedInfantry":
{ _dummy= [_group,_zone] call fnc_DoPatrolMechInf;};
case "MotorizedInfantry":
{ _dummy= [_group,_zone] call fnc_DoPatrolMotorInf;};
case "Car":
{ _dummy= [_group,_zone] call fnc_DoPatrolCar;};
case "MotorizedRecon":
{ _dummy= [_group,_zone] call fnc_DoPatrolMotorRecon;};
case "Ship":
{ _dummy= [_group,_zone] call fnc_DoPatrolShip;};
case "Submarine":
{ _dummy= [_group,_zone] call fnc_DoPatrolShip;};
case "Helicopter":
{ _dummy= [_group,_zone] call fnc_DoPatrolHeli;};
//Autonomous for now the same as heli (might change later)
case "Autonomous":
{ _dummy= [_group,_zone] call fnc_DoPatrolHeli;};
};
//Lets set the current Order.
_group setVariable ["GAIA_Order" , "DoPatrol", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_group setVariable ["GAIA_OrderTime" , Time, false];
_group setVariable ["GAIA_OrderPosition" , (position leader _group), false];
};
true
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_zone = _this select 1;
[_group] call fnc_RemoveWayPoints;
//Go somewhere
_pos= [_group,_zone,"ROAD"] call fnc_CreateWP;
if (count (waypoints _group) != (currentWaypoint _group)) then
{
_dummy = [_group,_pos,"MOVE"] call fnc_addWaypoint;
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_zone = _this select 1;
[_group] call fnc_RemoveWayPoints;
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our support guys. Yes they are 'easy' at the moment. Just make it work is the goal for release 1.
//
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_pos","_zone","_newpos","_landpos","_landpad"];
//Get the group
_group = _this select 0;
_landpos = [];
_zns = [];
_rounds = 0 ;
_initial = false;
//Clear what ever orders we had before.
[_group] call fnc_RemoveWayPoints;
//Get the zone
_zone = (((_group) getVariable ["GAIA_zone_intend",[]])select 0);
switch (side leader _group) do
{
case west : {
_zns = MCC_GAIA_ZONES_WEST;
};
case east : {
_zns = MCC_GAIA_ZONES_EAST;
};
case independent: {
_zns = MCC_GAIA_ZONES_INDEP;
};
};
if !(isnil("_Zone")) then
{
//Check if the dude already has a 'home'. All helicopters need position where they land and go home to.
if ( ((_group) getVariable ["GAIA_LandingSpot",[0,0,0]] distance [0,0,0]==0) ) then
{
if (isTouchingGround (assignedvehicle leader _group)) then
{
_landpos = (position assignedvehicle leader _group);
_dummy = ("Land_HelipadEmpty_F" createvehicle _landpos);
_group setVariable ["GAIA_LandingSpot" , _landpos , false];
}
else
{
_landpos = [([_zone,"ARM_HILLS_FLAT",(side _group)] call fnc_GetPosition), 0,100, 12, 0, 60 * (pi / 180), 0] call BIS_fnc_findSafePos;
_dummy = ("Land_HelipadEmpty_F" createvehicle _landpos);
_group setVariable ["GAIA_LandingSpot" , _landpos , false];
_wp = _group addWaypoint [((_group) getVariable ["GAIA_LandingSpot",[0,0,0]]), 0];
_wp setWaypointType "MOVE";
_wp setWaypointCompletionRadius 20;
_wp setWaypointSpeed "LIMITED";
_wp setWaypointStatements ["true","(Vehicle this) land 'land'"];
};
_initial = true;
};
// In case we are sitting and waiting
if (
(round(random(20))==1)and (count (waypoints _group) == (currentWaypoint _group))
and
!_initial
and
(count(_group getVariable ["GAIA_zone_intend",[]])>1)
and
((_group) getVariable ["GAIA_LandingSpot",[0,0,0]] distance [0,0,0]!=0)
)
then
{
_rounds =round(random(9));
for "_x" from 1 to _rounds do
{
//Go somewhere
//Defensive
if (((_group getVariable ["GAIA_zone_intend",[]]) select 1)=="NOFOLLOW") then
{_pos= ([_zone ,"AIR",(side _group)] call fnc_GetPosition);}
else
{_pos= ([(_zns call BIS_fnc_selectRandom ) ,"AIR",(side _group)] call fnc_GetPosition);};
_dummy = [_group,_pos,"MOVE"] call fnc_addWaypoint;
};
_wp = _group addWaypoint [((_group) getVariable ["GAIA_LandingSpot",[0,0,0]]), 0];
_wp setWaypointType "MOVE";
_wp setWaypointCompletionRadius 20;
_wp setWaypointSpeed "LIMITED";
_wp setWaypointStatements ["true","(Vehicle this) land 'land'"];
};
//In case we somehow end up in the air without waypoins or anything to do, bring the baby down
if (!(isTouchingGround (vehicle leader _group)) and (count (waypoints _group) == (currentWaypoint _group)) and !_initial and ((_group) getVariable ["GAIA_LandingSpot",[0,0,0]] distance [0,0,0]!=0)) then
{
_wp = _group addWaypoint [((_group) getVariable ["GAIA_LandingSpot",[0,0,0]]), 0];
_wp setWaypointType "MOVE";
_wp setWaypointCompletionRadius 20;
_wp setWaypointSpeed "LIMITED";
_wp setWaypointStatements ["true","(Vehicle this) land 'land'"];
};
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_zone = _this select 1;
[_group] call fnc_RemoveWayPoints;
//Go somewhere
_pos= [_group,_zone,"INF_URBAN_ROADS"] call fnc_CreateWP;
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_zone = _this select 1;
[_group] call fnc_RemoveWayPoints;
//Go somewhere
_pos= [_group,_zone,"VEH_HILLS_ROAD_FLAT"] call fnc_CreateWP;
if (count (waypoints _group) != (currentWaypoint _group)) then
{
//_dummy = [_group,(position leader _group),"GETIN NEAREST"] call fnc_addWaypoint;
_dummy = [_group,_pos,"MOVE"] call fnc_addWaypoint;
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_zone = _this select 1;
[_group] call fnc_RemoveWayPoints;
//Go somewhere
_pos= [_group,_zone,"ROAD"] call fnc_CreateWP;
if (count (waypoints _group) != (currentWaypoint _group)) then
{
_dummy = [_group,_pos,"MOVE"] call fnc_addWaypoint;
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_zone = _this select 1;
[_group] call fnc_RemoveWayPoints;
//Go somewhere
_pos= [_group,_zone,"VEH_HILLS_FOREST_FLAT"] call fnc_CreateWP;
if (count (waypoints _group) != (currentWaypoint _group)) then
{
_dummy = [_group,_pos,"MOVE"] call fnc_addWaypoint;
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_zone = _this select 1;
[_group] call fnc_RemoveWayPoints;
//Go somewhere
_pos= [_group,_zone,"INF_HILLS_FLAT_FOREST"] call fnc_CreateWP;
if (count (waypoints _group) != (currentWaypoint _group)) then
{
_dummy = [_group,_pos,"MOVE"] call fnc_addWaypoint;
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our awesome patrol
// Example: [_group,_zone] call fnc_DoInfPatrol
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_NrOfBuildingWp","_zone","_pos"];
_group = _this select 0;
_zone = _this select 1;
[_group] call fnc_RemoveWayPoints;
//Go somewhere
_pos= [_group,_zone,"WATER"] call fnc_CreateWP;
if (count (waypoints _group) != (currentWaypoint _group)) then
{
_dummy = [_group,_pos,"MOVE"] call fnc_addWaypoint;
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our support guys. Yes they are 'easy' at the moment. Just make it work is the goal for release 1.
//
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_pos","_zone"];
//Get the group
_group = _this select 0;
//Clear what ever orders we had before.
[_group] call fnc_RemoveWayPoints;
//Get the zone
_zone = (((_group) getVariable ["GAIA_zone_intend",[]])select 0);
if !(isnil("_Zone")) then
{
//Go somewhere
_pos= [_group,_zone,"ROAD"] call fnc_CreateWP;
if (count(_pos)>0) then
{
_pos = selectBestPlaces [_pos, 30,"meadow", 1, 1];
if ((count (_pos))>0) then
{
_dummy = [_group,(_Pos select 0 select 0),"SUPPORT"] call fnc_addWaypoint;
//Lets set the current Order.
_group setVariable ["GAIA_Order" , "DoSupport", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_group setVariable ["GAIA_OrderTime" , Time, false];
_group setVariable ["GAIA_OrderPosition" , (position leader _group), false];
};
};
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)/* ----------------------------------------------------------------------------
Function: fnc_DoTransportCar
Description:
Organise transport Car
Parameters:
- group (to be transported
- group (transporter)
Returns:
waypoints
Author:
Spirit, 17-2-2014
---------------------------------------------------------------------------- */
_group = _this select 0;
_trnsprtgrp = _this select 1;
_PosCloseRoadStart = [];
_PosCloseRoadEnd = [];
//where is this dude going?
_wpPos = (waypointPosition [_group ,(count(waypoints _group)-1)]);
_wptype = waypointType [_group ,(count(waypoints _group)-1)];
_nearRoad = (leader _group nearRoads 300);
if (count(_nearroad)>0) then
//Arrange a pickup on the side of the street, else we gonna have ai crazyness going on
{_road = (([_nearRoad,[],{leader _group distance _x},"ASCEND"] call BIS_fnc_sortBy ) select 0);
_roadConnectedTo = roadsConnectedTo _road;
if (count(_roadConnectedTo)>0) then
{
_connectedRoad = _roadConnectedTo select 0;
_direction = [_road, _connectedRoad] call BIS_fnc_DirTo;
_PosCloseRoadStart = [(position _road), 7, (_direction - 45)] call BIS_fnc_relPos;
};
};
_nearRoad = ( _wpPos nearRoads 300);
if (count(_nearroad)>0) then
{_PosCloseRoadEnd = position(([_nearRoad,[],{_wpPos distance _x},"ASCEND"] call BIS_fnc_sortBy ) select 0);};
if (
//There is a road found to pickup and a road foudn to drop him off
(count(_PosCloseRoadStart)>0) and (count( _PosCloseRoadEnd)>0)
) then
{
//Make the transporter stop hiding
_dummy =[_trnsprtgrp] call fnc_RemoveWayPoints;
_dummy =[_group] call fnc_RemoveWayPoints;
// Get in
_wpGroup = _group addWaypoint [_PosCloseRoadStart, 0];
_wpGroup setWaypointType "GETIN";
_wpGroup setWaypointCompletionRadius 20;
_wpTransporter = _trnsprtgrp addWaypoint [_PosCloseRoadStart, 0];
_wpTransporter setWaypointType "LOAD";
_wpTransporter setWaypointCompletionRadius 20;
_wpTransporter setWaypointSpeed "FULL";
//Synchronize them
_wpGroup synchronizeWaypoint [_wpTransporter];
// Get the fuck out
_wpGroup = _group addWaypoint [_PosCloseRoadEnd, 0];
_wpGroup setWaypointType "GETOUT";
_wpGroup setWaypointCompletionRadius 20;
//We go on alone, set us free
_wpGroup setWaypointStatements ["true", " (group this) setVariable ['GAIA_Order' , 'DoPatrol', false];(group this) setVariable ['GAIA_CombinedOrder' , GrpNull, false];"];
_wpTransporter = _trnsprtgrp addWaypoint [_PosCloseRoadEnd, 0];
_wpTransporter setWaypointType "TR UNLOAD";
_wpTransporter setWaypointCompletionRadius 20;
//release both groups from each other
//Synchronize them
_wpGroup synchronizeWaypoint [_wpTransporter];
//patrolling units will pick this up first
_group setVariable ["GAIA_OriginalDestination",_wpPos , false];
//Lets set the current Order of the vehilce transporting ( so he dont get a new DoTransport when we are going)
_trnsprtgrp setVariable ["GAIA_Order" , "DoTransport", false];
_group setVariable ["GAIA_Order" , "DoTransport", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_trnsprtgrp setVariable ["GAIA_OrderTime" , Time, false];
_trnsprtgrp setVariable ["GAIA_OrderPosition" , (_PosCloseRoadEnd), false];
_x setVariable ["GAIA_CombinedOrder" , (_group), false];
_group setVariable ["GAIA_CombinedOrder" , (_trnsprtgrp), false];
};
/* ----------------------------------------------------------------------------
Function: fnc_DoTransportCar
Description:
Organise transport Car
Parameters:
- group (to be transported
- group (transporter)
Returns:
waypoints
Author:
Spirit, 17-2-2014
---------------------------------------------------------------------------- */
_group = _this select 0;
_trnsprtgrp = _this select 1;
//player globalchat format ["%1 instappper, %2 vervoer",_group,_trnsprtgrp];
_PosCloseRoadStart = [];
_PosCloseRoadEnd = [];
//where is this dude going?
_wpPos = (waypointPosition [_group ,(count(waypoints _group)-1)]);
_wptype = waypointType [_group ,(count(waypoints _group)-1)];
//Make the transporter stop hiding
_dummy =[_trnsprtgrp] call fnc_RemoveWayPoints;
_dummy =[_group] call fnc_RemoveWayPoints;
_PosCloseRoadStart = (position leader _group);
_PosCloseRoadEnd = _wpPos;
// Get in
_wpGroup = _group addWaypoint [_PosCloseRoadStart, 0];
_wpGroup setWaypointType "GETIN";
_wpGroup setWaypointCompletionRadius 20;
_wpTransporter = _trnsprtgrp addWaypoint [_PosCloseRoadStart, 0];
_wpTransporter setWaypointType "LOAD";
_wpTransporter setWaypointCompletionRadius 20;
_wpTransporter setWaypointSpeed "FULL";
//Synchronize them
_wpGroup synchronizeWaypoint [_wpTransporter];
// Get the fuck out
_wpGroup = _group addWaypoint [_PosCloseRoadEnd, 0];
_wpGroup setWaypointType "GETOUT";
_wpGroup setWaypointCompletionRadius 20;
//We go on alone, set us free
_wpGroup setWaypointStatements ["true", " (group this) setVariable ['GAIA_Order' , 'DoPatrol', false];(group this) setVariable ['GAIA_CombinedOrder' , GrpNull, false];"];
_wpTransporter = _trnsprtgrp addWaypoint [_PosCloseRoadEnd, 0];
_wpTransporter setWaypointType "TR UNLOAD";
_wpTransporter setWaypointCompletionRadius 20;
//release both groups from each other
//Synchronize them
_wpGroup synchronizeWaypoint [_wpTransporter];
//patrolling units will pick this up first
_group setVariable ["GAIA_OriginalDestination",_wpPos , false];
//Lets set the current Order of the vehilce transporting ( so he dont get a new DoTransport when we are going)
_trnsprtgrp setVariable ["GAIA_Order" , "DoTransport", false];
_group setVariable ["GAIA_Order" , "DoTransport", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_trnsprtgrp setVariable ["GAIA_OrderTime" , Time, false];
_trnsprtgrp setVariable ["GAIA_OrderPosition" , (_PosCloseRoadEnd), false];
_x setVariable ["GAIA_CombinedOrder" , (_group), false];
_group setVariable ["GAIA_CombinedOrder" , (_trnsprtgrp), false];
/* ----------------------------------------------------------------------------
Function: fnc_DoTransportCar
Description:
Organise transport Car
Parameters:
- group (to be transported
- group (transporter)
Returns:
waypoints
Author:
Spirit, 17-2-2014
---------------------------------------------------------------------------- */
_group = _this select 0;
_trnsprtgrp = _this select 1;
_PosCloseRoadStart = [];
_PosCloseRoadEnd = [];
//where is this dude going?
_wpPos = (waypointPosition [_group ,(count(waypoints _group)-1)]);
_wptype = waypointType [_group ,(count(waypoints _group)-1)];
if ((_group getVariable ["GAIA_Order",""]) == "DoPatrol") then
{
_nearRoad = (leader _group nearRoads 300);
if (count(_nearroad)>0) then
//Arrange a pickup on the side of the street, else we gonna have ai crazyness going on
{_road = (([_nearRoad,[],{leader _group distance _x},"ASCEND"] call BIS_fnc_sortBy ) select 0);
_roadConnectedTo = roadsConnectedTo _road;
if (count(_roadConnectedTo)>0) then
{
_connectedRoad = _roadConnectedTo select 0;
_direction = [_road, _connectedRoad] call BIS_fnc_DirTo;
_PosCloseRoadStart = [(position _road), 7, (_direction - 45)] call BIS_fnc_relPos;
};
};
_nearRoad = ( _wpPos nearRoads 300);
if (count(_nearroad)>0) then
{_PosCloseRoadEnd = position(([_nearRoad,[],{_wpPos distance _x},"ASCEND"] call BIS_fnc_sortBy ) select 0);};
if (
//There is a road found to pickup and a road foudn to drop him off
(count(_PosCloseRoadStart)>0) and (count( _PosCloseRoadEnd)>0)
) then
{
//Make the transporter stop hiding
_dummy =[_trnsprtgrp] call fnc_RemoveWayPoints;
_dummy =[_group] call fnc_RemoveWayPoints;
// Get in
_wpGroup = _group addWaypoint [_PosCloseRoadStart, 0];
_wpGroup setWaypointType "GETIN";
_wpGroup setWaypointCompletionRadius 90;
_wpGroup setWaypointSpeed "FULL";
_wpTransporter = _trnsprtgrp addWaypoint [_PosCloseRoadStart, 0];
_wpTransporter setWaypointType "LOAD";
_wpTransporter setWaypointCompletionRadius 90;
_wpTransporter setWaypointSpeed "FULL";
//Synchronize them
_wpGroup synchronizeWaypoint [_wpTransporter];
// Get the fuck out
_wpGroup = _group addWaypoint [_PosCloseRoadEnd, 0];
_wpGroup setWaypointType "GETOUT";
_wpGroup setWaypointCompletionRadius 20;
//We go on alone, set us free
_wpGroup setWaypointStatements ["true", " (group this) setVariable ['GAIA_Order' , 'DoPatrol', false];(group this) setVariable ['GAIA_CombinedOrder' , GrpNull, false];"];
_wpTransporter = _trnsprtgrp addWaypoint [_PosCloseRoadEnd, 0];
_wpTransporter setWaypointType "TR UNLOAD";
_wpTransporter setWaypointCompletionRadius 20;
//release both groups from each other
//Synchronize them
_wpGroup synchronizeWaypoint [_wpTransporter];
//patrolling units will pick this up first
_group setVariable ["GAIA_OriginalDestination",_wpPos , false];
//Lets set the current Order of the vehilce transporting ( so he dont get a new DoTransport when we are going)
_trnsprtgrp setVariable ["GAIA_Order" , "DoTransport", false];
_group setVariable ["GAIA_Order" , "DoTransport", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_trnsprtgrp setVariable ["GAIA_OrderTime" , Time, false];
_trnsprtgrp setVariable ["GAIA_OrderPosition" , (_PosCloseRoadEnd), false];
_x setVariable ["GAIA_CombinedOrder" , (_group), false];
_group setVariable ["GAIA_CombinedOrder" , (_trnsprtgrp), false];
};
};
//==================================================================fnc_DoInfPatrol===============================================================================================
// Generate some stuff to do for our support guys. Yes they are 'easy' at the moment. Just make it work is the goal for release 1.
//
// spirit 14-1-2014
//===========================================================================================================================================================================
private ["_group","_pos","_zone","_newpos","_landpos","_landpad"];
//Get the group
_group = _this select 0;
_landpos = [];
//Clear what ever orders we had before.
[_group] call fnc_RemoveWayPoints;
//Get the zone
_zone = (((_group) getVariable ["GAIA_zone_intend",[]])select 0);
if !(isnil("_Zone")) then
{
//Check if the dude already has a 'home'. All helicopters need position where they land and go home to.
if ( ((_group) getVariable ["GAIA_LandingSpot",[0,0,0]] distance [0,0,0]==0) ) then
{
if (isTouchingGround (vehicle leader _group)) then
{_landpos = (position leader _group);}
else
{_landpos = [([_zone,"ARM_HILLS_FLAT",(side _group)] call fnc_GetPosition), 0,100, 12, 0, 60 * (pi / 180), 0] call BIS_fnc_findSafePos;};
_dummy = ("Land_HelipadEmpty_F" createvehicle _landpos);
_group setVariable ["GAIA_LandingSpot" , _landpos , false];
};
if ( ((_group) getVariable ["GAIA_LandingSpot",[0,0,0]] distance [0,0,0]!=0) ) then
{
_wp = _group addWaypoint [((_group) getVariable ["GAIA_LandingSpot",[0,0,0]]), 0];
_wp setWaypointType "MOVE";
_wp setWaypointCompletionRadius 20;
_wp setWaypointSpeed "LIMITED";
_wp setWaypointStatements ["true","(Vehicle this) land 'land'"];
_dummy = [_group,((_group) getVariable ["GAIA_LandingSpot",[0,0,0]]),"SENTRY"] call fnc_addWaypoint;
/*
_wp setWaypointStatements ["true", "player globalchat 'hoi hoi';(vehicle leader _group) land 'LAND';"];
(vehicle leader _group) land "LAND";
_wp = _group addWaypoint [position((_group) getVariable ["GAIA_LandingSpot",objNull]), 0];
_wp setWaypointType "HOLD";
_wp setWaypointCompletionRadius 10;
_wp setWaypointSpeed "LIMITED";
*/
//Lets set the current Order.
_group setVariable ["GAIA_Order" , "DoWait", false];
//Also note when we gave that order and where the unit was. It gives us a chance to check his progress and to 'unstuck' him if needed.
//Also all orders have a lifespan. MCC_GAIA_ORDERLIFETIME
_group setVariable ["GAIA_OrderTime" , Time, false];
_group setVariable ["GAIA_OrderPosition" , (position leader _group), false];
};
};
//Our result is waypoints
((count (waypoints _group)) - currentWaypoint _group)/* Select a random position from an area defined by a marker.
In : [marker, goal]
Out : [position]
By Spirit, 7-1-2014
*/
private
["_area"
,"_blist"
,"_pos"
,"_iswater"
,"_found"
,"_fPos"
,"_goal"
,"_minimum"
,"_best_effort"
];
_area = _this select 0;
_goal = _this select 1;
_side = _this select 2;
//_blist = if (count _this > 2) then {_this select 2} else {[]};
_pos = [];
_fpos = [];
_best_effort = [];
_shape = _area call fnc_getMarkerShape;
// STart with the highest cost ever, before we know the cost (so we dont stop)
_minimum = 10000;
_best = -1000;
// Limited loop so the script won't get stuck
// Also the minimum is set in the formula (later), so we go to maximum 50 tries to the best shot or if we beat our miminum.
for [{_i = 0}, {((_i<50) and (_best<_minimum))or (_i<10)}, {_i = _i + 1}] do
{
// Rectangle or Ellipse marker given?
// Get a position from the found shaped marker
if (_shape in ["SQUARE","RECTANGLE"]) then
{
_pos = _area call fnc_getPosFromRectangle;
}
else
{
_pos = _area call fnc_getPosFromEllipse;
};
_SRange = 90;
//Scan the terrain
_topArr = [_pos,1] call fnc_ScanTerrain;
// Return the values of terrain
_sUrban = _topArr select 0;
_sForest = _topArr select 1;
_sHills = _topArr select 2;
_sFlat = _topArr select 3;
_sSea = _topArr select 4;
_sGr = _topArr select 5;
//Make them comparable
_sUrban = round (_sUrban*100);
_sForest = round (_sForest*100);
_sHills = round (_sHills*100);
_sFlat = round (_sFlat*100);
_sSea = round (_sSea*100);
_sGr = round _sGr;
_sRoads = count (_pos nearRoads _SRange);
//Calculate on formula's if this is a suitable
switch (_goal) do
{
case ("INF_URBAN_ROADS") : {_minimum=040;_found =_sUrban + _sRoads - _sForest - _sSea - _sHills - _sFlat;};
case ("INF_HILLS_FLAT_FOREST") : {_minimum=030;_found =_sHills + _sFlat + _sForest - _sRoads - _sSea - _sUrban;};
case ("INF_URBAN_FOREST") : {_minimum=020;_found =_sUrban + _sForest - _sFlat - _sSea - _sHills - _sRoads;};
case ("VEH_HILLS_ROAD_FLAT") : {_minimum=060;_found =_sHills + _sRoads - _sSea - _sForest - _sUrban + _sFlat;};
case ("VEH_HILLS_FOREST_FLAT") : {_minimum=050;_found =_sHills - _sRoads - _sSea + _sForest - _sUrban + _sFlat;};
case ("VEH_URBAN_FOREST") : {_minimum=020;_found =_sForest - _sRoads - _sSea - _sHills + _sUrban - _sFlat;};
case ("ARM_HILLS_FLAT") : {_minimum=020;_found =_sHills - _sRoads - _sSea - _sForest - _sUrban + _sFlat;};
case ("ARM_FOREST") : {_minimum=005;_found =_sForest - _sRoads - _sSea - _sHills - _sUrban - _sFlat;};
case ("AIR") : {_minimum=000;_found =_sUrban + _sRoads + _sForest + _sSea + _sHills + _sFlat;};
case ("FOREST") : {_minimum=005;_found =_sForest - _sUrban - _sFlat - _sSea - _sHills - _sRoads;};
case ("HILLS") : {_minimum=005;_found =_sHills - _sUrban - _sFlat - _sSea - _sForest - _sRoads;};
case ("URBAN") : {_minimum=005;_found =_sUrban - _sHills - _sFlat - _sSea - _sForest - _sRoads;};
case ("FLAT") : {_minimum=005;_found =_sFlat - _sUrban - _sHills - _sSea - _sForest - _sRoads;};
case ("ROAD") : {_minimum=010;_found =_sRoads;};
case ("WATER") : {_minimum=100;_found =_sSea - _sUrban - _sForest - _sFlat;};
};
//final checks
//If we are road depending then make sure we are ON road (good is not good enough).
if ((_goal == "VEH_HILLS_ROAD_FLAT" or _goal == "ROAD")and (_found>_best )) then
{
_roadlist = _pos nearRoads 60;
if (count(_roadlist)>0) then
{_pos = position (_roadlist select 0);_found=_minimum; }
};
//Non road depending check
if (!isonroad _pos) then
{
if ((_goal == "VEH_HILLS_ROAD_FLAT" or _goal == "VEH_HILLS_FOREST_FLAT" or _goal == "ARM_HILLS_FLAT" ) and (_found>_best ) ) then
//Make sure the vehicle actualy fits (NOT within 3 meter of objects)
{
//Maybe Findsafepos fails, so remember the old one
//Also somehow Findsafepos comes with absurd out of map positions, so guard it to check if in Area.
_oldpos = _pos;
_pos = [_pos, 0,40, 12, 0, 60 * (pi / 180), 0]call BIS_fnc_findSafePos;
if (count(_pos)==0 or !([_pos,_side] call fnc_isBlacklisted)) then
{_pos = _oldpos};
};
};
//if ((_goal != "AIR" AND _goal != "WATER") and (surfaceiswater _pos )) then
//This wont be good for land dudes, so ignore this one
// {_found= -10000;};
//Since we basicly take "best chance" its good to check the most important one, water.
if ( (surfaceiswater _pos) and _goal!="WATER" and _goal!="AIR") then
//This wont be good for land dudes, so ignore this one
{_found= -10000;};
if ((_goal == "WATER") and !(surfaceiswater _pos ) ) then
//If we look for water, then dry surface wont do it
{_found= -10000;};
//If we have blacklist and the found pos is better then the best so far then....
if (_found>_best ) then
{
//If we find nothing in the end, then forget about blacklist.
_best_effort = _pos;
// Check each blacklist marker
if ([_pos,_side] call fnc_isBlacklisted) exitwith
{
_found= -10000;
};
};
//If we make it up here then this position is actualy the best we got so far.
if (_found>_best ) then
{
_best = _found;
_Fpos = _pos;
};
};
//We failed? Go back to best effort (be advised, it may still be empty!)
if (count(_fPos) == 0) then
{_fPos = _best_effort;};
// Return position
_Fpos/* ----------------------------------------------------------------------------
Function: fnc_RemoveWayPoints
Description:
Delete all waypoints of a given group
Parameters:
- Group
Optional:
-
Returns:
true/false
Author:
Spirit
---------------------------------------------------------------------------- */
private ["_group"];
_group = _this select 0;
_TempArray = [];
_wpTransporter = [];
switch (side _group) do
{
case west : {_TempArray =MCC_GAIA_WPPOS_WEST; };
case east : {_TempArray =MCC_GAIA_WPPOS_EAST; };
case independent: {_TempArray =MCC_GAIA_WPPOS_INDEP; };
};
// Clear all way points
while {(count (waypoints _group)) > 0} do
{
deleteWaypoint ((waypoints _group) select 0);
};
//Clear the WP array also
for [{_i=0},{_i < count _TempArray},{_i=_i+1}] do
{
if ((_TempArray select _i select 1)==_group) then
{
_TempArray set [_i, "REMOVE"];
_TempArray = _TempArray - ["REMOVE"];
};
};
//In case of combined orders (for now transportation), then in case of we are the transporting party do unload the load
if (!isnull(_group getVariable ["GAIA_CombinedOrder",grpNull])) then
{
if !(_group getVariable ["GAIA_class",""] in ["Infantry","ReconInfantry"]) then
{ _wpTransporter = _x addWaypoint [(position leader _group), 0];
_wpTransporter setWaypointType "TR UNLOAD";
_wpTransporter setWaypointCompletionRadius 20;
};
};
//Clear the current order also
_group setVariable ["GAIA_Order" , "None", false];
_group setVariable ["GAIA_CombinedOrder" , grpNull, false];
//Clear fortify specific if needed.
_group setVariable ["Garrisoning",false];
_group setVariable ["GAIA_OriginalDestination", [], false];
switch (side _group) do
{
case west : {MCC_GAIA_WPPOS_WEST =_TempArray ; };
case east : {MCC_GAIA_WPPOS_EAST =_TempArray ; };
case independent: {MCC_GAIA_WPPOS_INDEP =_TempArray ; };
};
true JFIF ,, C
%# , #&')*)-0-(0%()( C
((((((((((((((((((((((((((((((((((((((((((((((((((( " kPKI5