Blackwater France

Site internet de la team Blackwater France

Derniers sujets

Soirée du 04 / 12 / 2017

04/12/2017 17:48 11

RommY

01/12/2017 14:10 1

Mise à jour Arma

30/11/2017 17:11 1

Derniers membres

8 vues

script "Patrols.sqf" © Pumpkin

02/11/2017 18:08 Message non lu

Script de patrouille aléatoire avec comportement amélioré :
  • patrouille sur une zone déterminé par un déclencheur
  • interactions entre les patrouilles et mise en alerte générale
  • évite les étendues d'eau
  • visite des maisons
  • fonctionne pour les camps Est ou Ouest
C'est assez pénible pour un créateur de mission de savoir exactement le chemin qu'emprunte les patrouilles : le suspens, l'immersion,... sont grandement amoindris. On peut cependant créer des patrouilles avec un chemin plus ou moins aléatoire dans l'éditeur (rayon de position aléatoire des points de passage), mais, en cas d'attaque, on pourra observer des aberrations de comportement, comme une patrouille qui passe tranquillement à côté d'une escouade alliée qui se fait attaquer, sans lever le petit doigt (vers la gachette, entre autre). C'est là l'utilité du script : permettre à toutes les patrouilles d'un secteur de patrouiller aléatoirement et d'interagir entre elles : Si une patrouille se fait attaquer ou repère un ennemi, toutes les patrouilles du secteur seront averties, se mettront en mode combat, et pourront éventuellement rejoindre en renfort la patrouille qui a déclenché l'alerte. A noter que l'alerte a une durée limitée, ce qui permet un retour à la normale au bout d'un moment.
Le secteur de patrouille est déterminé par un déclencheur, peu importe la forme ou la taille (pas trop petit sinon la patrouille restera quasiment sur place, ou trop grand sinon vous n'aurez que peu de chance de la rencontrer). Si la zone (et donc le déclencheur) empiéte sur une étendue d'eau, la patrouille ne s'y dirigera pas; on peut donc,par exemple, placer un déclencheur unique au milieu d'un port, la patrouille n'ira pas faire trempette.
Les secteurs de patrouille peuvent se recouvrir : si une patrouille provenant d'un secteur A entre dans un secteur B, elle sera intégrée au secteur B en tant qu' "alliée", et en cas d'attaque de cette patrouille, les patrouilles du secteur B viendront à la rescousse. On peut aussi "attaché" plusieurs patrouilles a un même secteur, de façon à obtenir une interaction entre plusieurs patrouilles de plusieurs secteurs. Gaffe tout de même à ne pas exagérer ! Les ennemis sont sacrément hargneux et même 5 ou 6 bons soldats n'ont jamais tenu bien longtemps en face de 30 ou 40 ennemis qui leur tombent dessus en même temps.
D'autre part, je trouvais anormal qu'on puisse se cacher dans une maison sans jamais être inquiété. J'ai essayé de faire en sorte que, lorsqu'une patrouille passe à proximité de la maison où vous vous êtes planqué, il y a une chance que le chef de patrouille désigne un gars pour aller voir si d'aventure il n'y aurait pas un ennemi (donc vous !) sournoisement planqué dedans; ce n'est pas systématique mais c'est un risque !
Installation
  1. Copier le script "Patrols.sqf" dans le répertoire de la missionDans l'éditeur :
  2. Créer un déclencheur sur la zone de la patrouille et le nommer (zone grise dans l'exemple ci-dessous, nommé "tcherno_patrol1")
    il peut être elliptique ou rectangulaire, et orienté selon le bon vouloir du créateur de mission. Peu importe les autres paramètres du déclencheur, seule compte la taille ('Axe a' et 'Axe b'), l'angle, la forme et le nom. Le texte est optionnel et ne permet qu'au créateur de mieux s'y retrouver (dans l'exemple le texte est égale au nom du déclencheur, soit "tcherno_patrol1", mais, je le répète, il n'a aucune importance et peut être vide)

  3. mettre la ligne de lancement du script dans le champ initialisation du leader de la patrouille

    exemples :
    CODE:nul = [this,tcherno_patrol1] execVM "patrols.sqf"

    nul = [this,tcherno_patrol1,150,"patrol_strt1","patrol_dest1"] execVM "patrols.sqf"
    nota : la 1ère ligne est un exemple d'appel simplifié avec les 2 paramètres obligatoire, la 2ème contient tous les paramètres, y compris la désignation des 2 marqueurs de débuggage, qui se trouve en bas à droite dans la mission d'exemple (2 marqueurs pour la 1ère patrouille, 2 marqueurs pour la 2ème patrouille)
Paramètres[chef_de_groupe, libellé_du_déclencheur (, distance_de_convergence_sur_objectif , "nom_du_marqueur_départ", "nom_du_marqueur_fin")] execVM "Patrols.sqf" (ne pas oublier de faire précéder par 'nul = ' dans l'éditeur, sinon ce brave éditeur hurle à l'erreur "type script, rien attendu")
  • chef_de_groupe (obligatoire !): 'this', qui fait référence à l'unité qui contient la ligne de commande, ou éventuellement son nom (= issus du champ 'Nom', "chef_A" dans l'exemple ci-dessus)
  • libellé_du_déclencheur (obligatoire !): le nom issu du champ 'Nom' du déclencheur
  • distance de convergence sur objectif (optionnelle, devient obligatoire si on indique les 4ème et 5ème paramètres; par défaut 150m): Si une alerte est déclenché par une patrouille A, toute patrouille dans une rayon égale à cette distance de convergence est appelé en renfort.exemple : cas d'un appel simple ("nul = [this,tcherno_patrol1] execVM "patrols.sqf"")
    • 1er cas de figure : Un sniper a été repéré par la patrouille A (marqueurs orange) mais la patrouille B (marqueurs bleus) se trouve à ce moment-là à environ 400m. Si aucune distance de convergence n'a été donnée, la patrouille B se mettra en mode de combat et continuera vers son point de passage (= le marqueur bleu le plus bas). Il faudrai mettre au moins 400 comme 3ème paramètre pour que la patrouille B converge vers le lieu de l'alerte.
    • 2eme cas de figure : Le sniper a été repéré par la patrouille A (marqueurs orange) et la patrouille B (marqueurs bleus) se trouve à environ 150m. La patrouille B se mettra en mode de combat et convergera vers le lieu de l'alerte, en renfort de la patrouille A. Pour éviter cela, il faudrai mettre moins de 150 comme 3ème paramètre pour que la patrouille B converge pas vers le lieu de l'alerte.
  • "nom_du_marqueur_départ" (optionnel): pour débuggage et/ou observation; nom entre guillemets du marqueur préalablement créé dans l'éditeur, qui servira à indiquer le départ de chaque point de passage (égal, en gros, au point de passage précédent)
  • "nom_du_marqueur_départ" (obligatoire si le "nom_du_marqueur_départ" est précisé): pour débuggage et/ou observation; nom entre guillemets du marqueur préalablement créé dans l'éditeur, qui montre le point de passage vers lequel se dirige la patrouille
exemples :

CODE:nul = [this,tcherno_patrol1] execVM "patrols.sqf"
patrouille dans la zone du déclencheur nommé "tcherno_patrol1"
CODE:nul = [this,tcherno_patrol1,300] execVM "patrols.sqf"
patrouille dans la zone du déclencheur nommé "tcherno_patrol1", renfort uniquement si une attaque ou un ennemi est repéré à 300m de distance.
CODE:nul = [this,tcherno_patrol1,150,"patrol_strt1","patrol_dest1"] execVM "patrols.sqf"
patrouille dans la zone du déclencheur nommé "tcherno_patrol1", renfort si une attaque ou un ennemi est repéré à 150m de distance (valeur par défaut), avec mode de débuggage activé : déplacement suivis par les marqueurs "patrol_strt1" et "patrol_dest1"

/*
PATROLS.SQF
===========
version 2.7.3 (6.2.2012) © Pumpkin
- bug sur déclencheur rectangulaire corrigé
- amélioration de la boucle d'attente de regroupement des unités sur le chef
- bug du mode trace (avec 2 marqueurs) corrigé
- 1er position de maison visitée (précédemment oubliée)
- random position polaire modifiée
- erreur de frappe corrigée : variable "cntnear" => "_cntnear" dans la définition "private [..."
Patrouille aléatoire dans une zone déterminée par un déclencheur, avec visite des maisons. Utilisation d'un déclencheur de même taille que le déclencheur d'origine pour gérer
le déclenchement d'alerte : dés qu'un soldat ennemi se fait tuer dans la zone, tous les soldats dans la zone sont mis en mode combat, même s'il n'appartient pas au groupe.
Paramètres :
------------
nul = [chef_de_groupe, libellé_du_déclencheur, (, distance_de_convergence_sur_objectif , "nom_du_marqueur_départ" , "nom_du_marqueur_fin")] execVM "Patrols.sqf"
remarques :
® Le trigger d'origine peut empiéter sur une zone d'eau, celle-ci sera automatiquement évitée
® [code] la mise en "captive" d'un joueur désactive son repérage par le trigger "WEST" (s'il joue en BLUFOR)
® [code] valeurs de '_retVal' : 0=pas d'alerte; >0 = nb de morts; <0 = coeficient 'knowsabout'
® [code] la commande Move prend en compte les "SetBehaviour,SetCombatMode,..." au contraire de DoMove, qui n'en tient aucunement compte.
*/
if (not isServer) exitwith {};
// Délai pour arrivée en mission (= visuelle 1ère personne)
_checkstart = false;
for [{_s = 0},{_s <= 5},{_s = _s + 1}] do {
sleep 2;
if ((_this select 0) iskindof "Man") then {
_checkstart = true;
_s = 10;
};
};
// gestion des erreurs de paramètrage
if (not _checkstart) exitwith {
hint composeText[
parseText("<t color='#ff0000' size='1.5'>" + "Erreur script patrols.sqf" + "</t>"), lineBreak,
"le premier argument doit être un homme", lineBreak, lineBreak,
parseText("<t color='#ff0000' size='1.5'>" + "Error script patrols.sqf" + "</t>"), lineBreak,
"the first argument must be a man"
];
};
// ===========
// ARGUMENTS :
// ===========
_grppatrol = group (_this select 0);
// Déclencheur : à cloner en répétition
_trg = _this select 1;
// gestion des erreurs de paramètrage
_param_err = false;
if (typename _trg != "OBJECT") then { _param_err = true };
if (isnil "_trg") then { _param_err = true };
if ((not _param_err) and (typeof _trg != "EMPTYDETECTOR")) then { _param_err = true };
if ( _param_err ) exitwith {
hint composeText[
parseText("<t color='#ff0000' size='1.5'>" + "Erreur script patrols.sqf" + "</t>"), lineBreak,
"le 2ème argument doit être un déclencheur", lineBreak, lineBreak,
parseText("<t color='#ff0000' size='1.5'>" + "Error script patrols.sqf" + "</t>"), lineBreak,
"the 2nd argument must be a trigger"
];
};
//_checkdeadszone = false;
_checkdeadszone = 150;
if (count _this > 2) then { _checkdeadszone = _this select 2 };
if (typename _checkdeadszone != "SCALAR") exitwith {
hint composeText[
parseText("<t color='#ff0000' size='1.5'>" + "Erreur script patrols.sqf" + "</t>"), lineBreak,
"le 3ème argument doit être un nombre", lineBreak, lineBreak,
parseText("<t color='#ff0000' size='1.5'>" + "Error script patrols.sqf" + "</t>"), lineBreak,
"the 3rd argument must be a number"
];
};
// Marquage par icone pour debugage
_iconestrt = "";
_param_err = false;
if (count _this > 3) then {
_iconestrt = _this select 3;
// gestion des erreurs de paramètrage
if (typename _iconestrt != "STRING") then {
_param_err = true;
}
else {
if ( not((markershape _iconestrt == "ICON") or (markershape _iconestrt == "RECTANGLE") or (markershape _iconestrt == "ELLIPSE")) ) then { _param_err = true };
};
};
// gestion des erreurs de paramètrage
if ( _param_err ) exitwith {
hint composeText[
parseText("<t color='#ff0000' size='1.5'>" + "Erreur script patrols.sqf" + "</t>"), lineBreak,
"le 4ème argument doit être un nom de marqueur", lineBreak, lineBreak,
parseText("<t color='#ff0000' size='1.5'>" + "Error script patrols.sqf" + "</t>"), lineBreak,
"the 4th argument must be a marker name"
];
};
_iconedest = "";
_param_err = false;
if (count _this > 4) then {
_iconedest = _this select 4;
// gestion des erreurs de paramètrage
if (typename _iconedest != "STRING") then {
_param_err = true;
}
else {
if ( not((markershape _iconedest == "ICON") or (markershape _iconedest == "RECTANGLE") or (markershape _iconedest == "ELLIPSE")) ) then { _param_err = true };
};
};
// gestion des erreurs de paramètrage
if ( _param_err ) exitwith {
hint composeText[
parseText("<t color='#ff0000' size='1.5'>" + "Erreur script patrols.sqf" + "</t>"), lineBreak,
"le 5ème argument doit être un nom de marqueur", lineBreak, lineBreak,
parseText("<t color='#ff0000' size='1.5'>" + "Error script patrols.sqf" + "</t>"), lineBreak,
"the 5th argument must be a marker name"
];
};
if ((count _this < 2) or (count _this == 4)) exitwith {
hint composeText[
parseText("<t color='#ff0000' size='1.5'>" + "Erreur script patrols.sqf" + "</t>"), lineBreak,
"Nombre d'argument incorrect", lineBreak, lineBreak,
parseText("<t color='#ff0000' size='1.5'>" + "Error script patrols.sqf" + "</t>"), lineBreak,
"Wrong number of arguments"
];
};
if ((_iconestrt == "") or (_iconedest == "")) then {
_iconestrt = "";
_iconedest = "";
}
else {
player globalchat format ["mode debug - icone1 : %1 icone2 : %2",_iconestrt,_iconedest];
};
// ================
// INIT VARIABLES :
// ================
private ["_foesunits","_oldfoesunits","_grpplayers","_waypointok","_Xadd","_Yadd","_dist","_distX","_distY","_ang","_Xaxe","_Yaxe","_mkname","_mkcnt","_patrol","_oldcoefka","_oktovisit","_specman","_nBuilding","_bPosIdx","_bPosToGet","_bPosArray","_bldgPos","_bouclechk","_delai","_cntdead","_coefka","_detected","_maxcoefka","_retVal","_nommort","_deserteur","_nbrappel","_minmen","_cntnear","_timer","_lpos"];
_alerte = 0; // niveau d'alerte en cours = 0:pas d'alerte / 1:alerte ne concernant pas le groupe / 2:mort dans le groupe / 3:joueur repéré
_maxcoefka = 0;
_coords = getpos (leader _grppatrol);
_mkalerte = format ["mk_%1",_trg]; // marqueur indiquant un alerte
_alertetimeout = 0;
_alertestart = 0; // heure de début d'alerte en nombre de secondes
_attente = 0; // délai d'attente sur position d'attaque 0 pour détection knowsabout, 120s (par ex.) pour mort dans le groupe
_alertperiod = 500; // durée max de l'alerte
_maxdist = 100; // distance max d'éloignement du leader avant rappel
_rappel = []; // si unité ds table => "déserteur" potentiel
_visited = []; // si batiment ds table => déjà visité, ne pas y aller
// ===============
// DEBUT INIT PROG
// ===============
// récupération des données du déclencheur
// --------------------------------------->
_pivotX = (getpos _trg) select 0;
_pivotY = (getpos _trg) select 1;
_trgArea = triggerArea _trg;
_trgRect = _trgArea select 3;
_dimX = _trgArea select 0;
_dimY = _trgArea select 1;
_trgDir = _trgArea select 2;
_cosDir = cos _trgDir;
_sinDir = sin _trgDir;
// 1ère coords wp
_wpgrpx = _pivotX;
_wpgrpy = _pivotY;
// Détermination du numéro du groupe
_numgrp = 1;
while {not (isnil (format ["grptrigger%1",_numgrp]))} do {
_numgrp = _numgrp + 1;
sleep 1; // sécurité ! augmente l'attente en fonction du numéro
};
call compile format ["grptrigger%1=true",_numgrp];
// Détermination du camp de la patrouille
_camp = format ["%1",side _grppatrol];
_enemicamp = "WEST";
if (_camp == "WEST") then { _enemicamp = "EAST" };
// CREATION DE 2 TRIGGERS : LISTE DES ALLIÉS + LISTE DES OPPOSANTS
// ATTENTION !! Le(s) trigger(s) ne s'active(nt) pas de suite, il y peut y avoir une boucle à vide
// Clonage du trigger d'origine : création d'une liste nommée "playerslist + no de groupe"
// contenant la liste de toutes les unités du camp opposé à la patrouille qui pénètre dans la zone
// la "répétition = true" de la cmd "setTriggerActivation" est importante pour prendre en compte
// tous les enemis entrant dans la zone
call compile format ["playerslist%1 = []",_numgrp];
_playerstrg = createTrigger["EmptyDetector",[_pivotX,_pivotY]];
_playerstrg setTriggerActivation[_enemicamp,"PRESENT",true];
_playerstrg setTriggerTimeout [0,0,0,false];
_playerstrg setTriggerArea [_dimX,_dimY,_trgDir,_trgRect];
_playerstrg setTriggerStatements ["this", format ["playerslist%1 = thislist",_numgrp],""];
_playerstrg setTriggerType "NONE";
// Création d'un trigger qui créera une liste nommée "foestrglist + no de groupe" contenant la
// liste de toutes les unités du même camp que la patrouille (trigger englobant la zone du marqueur)
call compile format ["foestrglist%1 = []",_numgrp];
_alerttrg = createTrigger["EmptyDetector",[_pivotX,_pivotY]];
_alerttrg setTriggerActivation[_camp,"PRESENT",true];
_alerttrg setTriggerTimeout [0,0,0,false];
_alerttrg setTriggerArea [(_dimX + 50), (_dimY + 50), _trgDir, _trgRect]; // + 50m pour que les unités de la patrouille ne sortent pas du secteur
_alerttrg setTriggerStatements ["this", format ["foestrglist%1 = thislist",_numgrp], ""];
_alerttrg setTriggerType "NONE";
// Délai d'attente avant activation effective des triggers
sleep 5;
_grppatrol setbehaviour "CARELESS";
_grppatrol setcombatmode "RED";
_grppatrol setspeedmode "LIMITED";
// =================================
// FIN INIT: début de boucle infinie
// =================================
for [{_infinite = 0},{_infinite <= 1},{_infinite = _infinite + 1}] do {
// option à voir : Ne pas courir tout le temps
/*
if ((random 3) < 2) then {
_grppatrol setbehaviour "CARELESS";
//_grppatrol setspeedmode "LIMITED";
}
else {
_grppatrol setbehaviour "SAFE";
//_grppatrol setspeedmode "NORMAL";
};
*/
// Patrouille décimée
if (({alive _x} count units _grppatrol) == 0) exitwith {};
// Récupérer la liste de toutes les units ennemis dans la zone de patrouille (= taille trigger)
call compile format ["_foesunits = foestrglist%1",_numgrp];
_oldfoesunits = []; // Obligation de reconstruire la var '_oldfoesunits', car une simple assignation _oldfoesunits = _foesunits ne marche pas
{_oldfoesunits = _oldfoesunits + [_x]} foreach _foesunits;
_grpplayers = [];
call compile format ["_grpplayers = playerslist%1",_numgrp];
// DÉTERMINATION DU WAYPOINT en fonction du point-pivot (càd le centre du marker), de la taille XY et de la rotation du marker
_waypointok = true;
// Si alerte, coordonnées proche de l'alerte
if (_alerte > 0) then {
// NIVEAU 1 : Alerte ne concernant pas l'équipe : wp à 100m autour de l'alerte
if (_alerte == 1) then {
_r = 100;
_Xadd = (random (_r * 2)) - _r;
_Yadd = (random (_r * 2)) - _r;
};
// NIVEAU 2 : Alerte par mort au sein de l'équipe : wp à 50m autour de l'alerte
if (_alerte == 2) then {
_r = 50;
_Xadd = (random (_r * 2)) - _r;
_Yadd = (random (_r * 2)) - _r;
};
// NIVEAU 3 : Alerte par knowsabout : wp à 30m autour de l'alerte
if (_alerte == 3) then {
_r = 30;
_Xadd = (random (_r * 2)) - _r;
_Yadd = (random (_r * 2)) - _r;
};
_wpgrpx = (_coords select 0) + _Xadd;
_wpgrpy = (_coords select 1) + _Yadd;
// Attente sur coords d'alerte, modulée : si knowsabout, _attente = 0, sinon _attente = valeur fixée dans la gestion d'alerte
// POUR DEBUG !!
// Positionnement des icones pour debuggage
if (_iconestrt != "") then { _iconestrt setMarkerPos getpos leader _grppatrol};
if (_iconedest != "") then { _iconedest setMarkerPos [_wpgrpx,_wpgrpy]};
sleep _attente;
}
else {
_Xadd = 0;
_Yadd = 0;
// Si trigger rectangulaire... sinon trigger elipse
if (_trgRect) then {
_Xaxe = (random (_dimX * 2)) - _dimX;
_Yaxe = (random (_dimY * 2)) - _dimY;
}
else {
_dist = (random 100) / 100;
_distX = _dist * _dimX;
_distY = _dist * _dimY;
_ang = 180 - ((random 35) * 10 + (random 10)); // = 355,99... degré max
_Xaxe = _distX * (sin _ang);
_Yaxe = _distY * (cos _ang);
};
// rotation du point suivant direction du trigger
_Xadd = _Xaxe * _cosDir - _Yaxe * _sinDir;
_Yadd = _Yaxe * _cosDir + _Xaxe * _sinDir;
_wpgrpx = _pivotX + _Xadd;
_wpgrpy = _pivotY - _Yadd;
// condition(s) de non-changement du waypoint
if (surfaceIsWater [_wpgrpx,_wpgrpy]) then {_waypointok = false};
};
// POUR DEBUG !!
// Positionnement des icones pour debuggage/observation
if (_iconestrt != "") then { _iconestrt setMarkerPos getpos leader _grppatrol};
if (_iconedest != "") then { _iconedest setMarkerPos [_wpgrpx,_wpgrpy]};
if ((_iconestrt != "") and (_iconedest != "")) then {
// Création d'un point persistant sur chaque point visité par la patrouille
_mkname = "pat1";
_mkcnt = 1;
while {getmarkertype _mkname != ""} do {
_mkcnt = _mkcnt + 1;
_mkname = format ["pat%1",_mkcnt];
};
createMarker [_mkname, [_wpgrpx,_wpgrpy]];
_mkname setMarkerType "Dot";
_mkname setMarkerColor (getMarkerColor _iconestrt);
_mkname setMarkerSize [1,1];
};
// Si conditions bonnes, entrer dans la boucle de parcours vers le wp, sinon reinit complète
if (_waypointok) then {
_patrol = units _grppatrol;
// Order de déplacement sur coordonnées (normale ou alerte)
_grppatrol move [_wpgrpx,_wpgrpy];
_oldcoefka = 0; // Pour détermination du joueur le + repéré
// Boucle ré-enclanché tant que le chef n'est pas au moins à 30m du wp
while { leader _grppatrol distance [_wpgrpx,_wpgrpy] > 30 } do {
// Décompte timeout pour fin d'alerte
if (_alerte > 0) then {
_alertetimeout = _alertetimeout + (time - _alertestart);
};
// fin d'alerte
if (_alertetimeout > _alertperiod) then {
if (_alerte > 1) then {deletemarker _mkalerte};
_alerte = 0;
_alertetimeout = 0;
_grppatrol setbehaviour "CARELESS";
_grppatrol setcombatmode "RED";
_grppatrol setspeedmode "LIMITED";
};
// BOUCLE DE TRAITEMENT INDIVIDUEL POUR CHAQUE UNITÉS DE LA PATROUILLE ("foreach units") :
// 1) gestion de visite des bâtiments
// 2) gestion du nombre de morts dans la zone
// 3) gestion du coeficient de répèrage
{
// VISITE DE BATIMENT même en condition d'alerte
_oktovisit = true;
// si le type d'homme est à exclure, pas de visite de batiment
if (_x == leader _grppatrol) then {_oktovisit = false};
if (_x isKindOf "Ins_Soldier_Medic") then {_oktovisit = false};
if (_x isKindOf "RU_Soldier_Medic") then {_oktovisit = false};
if (_x isKindOf "USMC_Soldier_Medic") then {_oktovisit = false};
if (_x isKindOf "CDF_Soldier_Medic") then {_oktovisit = false};
if (_x isKindOf "GUE_Soldier_Medic") then {_oktovisit = false};
// type d'homme ok, autres conditions d'exclusion
_specman = not _oktovisit;
if ((count units _grppatrol) == 1) then {_oktovisit = true};
if (_x in _rappel) then {_oktovisit = false}; // _x ne doit pas être deserteur
if ((_x distance leader _grppatrol > _maxdist) and (_alerte == 0)) then {_oktovisit = false}; // _x est loin de son leader, pas de visite
// Pas d'exclusion à la visite de batiment
if (_oktovisit) then {
_nBuilding = nearestBuilding _x;
_bPosIdx = 0;
_bldgPos = _nBuilding buildingPos 0;
_bPosArray = [];
while {(_bldgPos select 0 != 0) and (_bldgPos select 1 != 0) and (_bldgPos select 2 != 0)} do {
_bldgPos = _nBuilding buildingPos _bPosIdx;
if ((_bldgPos select 0 != 0) and (_bldgPos select 1 != 0) and (_bldgPos select 2 != 0)) then {_bPosArray = _bPosArray + [_bldgPos]};
_bPosIdx = _bposIdx + 1;
};
if (count _bPosArray > 0) then {
_bPosIdx = floor (random (count _bPosArray));
_bPosToGet = _bPosArray select _bPosIdx;
if ( (not(_nBuilding in _visited)) and (_bPosToGet distance leader _grppatrol < (_maxdist + 50)) ) then {
_x doMove _bPosToGet;
_visited = _visited + [_nBuilding];
};
};
}; // <--- : if _oktovisit...
// Si non visite, gestion d'éloignement !! A CONSERVER EN "ELSE" SINON _X EST RAPELLÉ AVANT LA VISITE
if (_alerte == 0) then {
//if (_alerte > 0) exitwith {}; // Si _alerte => ne pas gérer de rappel !
if (_x == leader _grppatrol) exitwith {}; // si leader => ne pas traiter !
if (_specman) exitwith {}; // Si homme spécial => ne pas traiter !
if (_x distance leader _grppatrol > _maxdist) then {
_rappel = _rappel + [_x];
};
};
// VÉRIFICATION DU NOMBRE DE MORT(S) ENNEMI(S) OU DU COEF KNOWSABOUT : _retVal donne soit
// le nombre de morts soit l'index du joueur le + repéré (sous format : index +1 et en négatif)
_bouclechk = 3; // 3 boucles avant sortie du test : totalement arbitraire !
_retVal = 0; // reinit en début de boucle
_maxcoefka = 0; // reinit en début de boucle
_delai = 2 / (count units _grppatrol) + 1;
for [{_i = 0},{_i < _bouclechk},{_i = _i + 1}] do {
call compile format ["_foesunits = foestrglist%1",_numgrp];
call compile format ["_grpplayers = playerslist%1",_numgrp];
// Tenir compte du cas hyper-rare de groupe de 1 unité, pleinement repéré de suite (coef
// K.A. = 4) et abattu de suite par des "super"-IA type Lucky Luke qui dégaine très vite
if (count _grpplayers > O) then { _coords = getpos (_grpplayers select 0) };
// Mise à jour éventuelle des nouvelles unités entrées dans le trigger
if (count _foesunits > count _oldfoesunits) then {
_oldfoesunits = [];
{_oldfoesunits = _oldfoesunits + [_x]} foreach _foesunits;
};
if (count _foesunits < count _oldfoesunits) then {
_cntdead = 0;
{
if (not alive _x) then {_cntdead = _cntdead + 1};
} foreach _oldfoesunits;
// Si aucun morts => une ou plusieurs unités sont sorties du trigger
if (_cntdead == 0) then {
_oldfoesunits = [];
{_oldfoesunits = _oldfoesunits + [_x]} foreach _foesunits;
};
_retVal = _cntdead;
};
// Priorité au coef knowsabout : si repéré, alors coef remplace le nombre de morts
for [{_p = 0},{_p < count _grpplayers},{_p = _p + 1}] do {
if (count _grpplayers == 0) exitwith {};
{
if (count _grpplayers == 0) exitwith {};
_coefka = _x knowsabout (_grpplayers select _p);
if (_coefka > _maxcoefka) then {
_maxcoefka = _coefka;
_detected = _p;
};
} foreach units _grppatrol;
if (_maxcoefka > 0) then {_retVal = (_detected + 1) * -1};
};
sleep _delai;
}; // <--- : for _i < _bouclechk...
// GESTION DE L'ALERTE :
// =====================
// Cas 1/3 (moindre importance) : Apparition d'un marqueur d'alerte
if ( getMarkerType _mkalerte != "" ) then {
// inits communes aux différents types d'alerte
_alerte = 1;
_attente = 120; // 2mn pour parvenir sur le lieu de l'alerte
_alertestart = time;
_rappel = []; // Pour permettre l'accés au batiment à tous
_grppatrol setbehaviour "COMBAT";
_grppatrol setcombatmode "RED";
_grppatrol setspeedmode "FULL";
// <<< inits
if ((leader _grppatrol) distance (getmarkerpos _mkalerte) < _checkdeadszone) then {
_coords = getmarkerpos _mkalerte;
};
};
// Cas 2/3 : mort(s) répéré(s) : récupèrer les coords du premier parmi les morts effectifs sur toute
// la zone. Les coords ne sont prise en compte/modifiée que s'il n'y a pas eu d'alerte encore.
// Rem : _attente = nombre de secondes autour de l'alerte avant choix d'un nouveau wp, car, si le rayon < 30,
// alors boucle continuelle sur choix de wp, d'où attente minimale avant nouveau choix de wp.
if ((_retVal > 0) and (_alerte == 0)) then {
// inits communes aux différents types d'alerte
_alerte = 1;
_attente = 120;
_alertestart = time;
_rappel = []; // Pour permettre l'accés au batiment à tous
_grppatrol setbehaviour "COMBAT";
_grppatrol setcombatmode "RED";
_grppatrol setspeedmode "FULL";
// <<< inits
_nommort = (_oldfoesunits - _foesunits) select 0; // Prendre le 1er mort
_coords = getpos _nommort;
// Vérifier que le mort appartient au groupe
for [{_i = 0},{_i < count _patrol},{_i = _i + 1}] do {
if (not alive (_patrol select _i)) then {
_alerte = 2;
_attente = 60;
_grppatrol setbehaviour "STEALTH";
_grppatrol setcombatmode "RED";
_grppatrol setspeedmode "FULL";
_patrol = units _grppatrol;
};
};
};
// Cas 3/3 : repéré par coef knowsabout : _retVal donne l'index du joueur "le + repéré", incrémenté de 1 et en négatif (ex.: coef=0.4 _retVal = -1.4)
// géré à chaque CheckAlerte, malgré un état d'alerte existant ! Car cela permet de mettre à jour le wp en fonction du repérage
if (_retVal < 0) then {
// inits communes aux différents types d'alerte
_alerte = 3;
_alertestart = time;
_attente = 20; // Ne pas (trop) attendre si le wp est placé grâce à une détection knowsabout
// Si détection par knowsabout, attendre au moins 10s avant de réactualiser le wp, sinon le wp se remet à jour trop vite
_rappel = []; // Pour permettre l'accés au batiment à tous
_grppatrol setbehaviour "COMBAT";
_grppatrol setcombatmode "RED";
_grppatrol setspeedmode "FULL";
// <<< inits
if (_maxcoefka > _oldcoefka) then {
_oldcoefka = _maxcoefka;
_alertetimeout = 0; // !! Reset timeout à chaque fois tant qu'on est repéré
// Tenir compte du cas hyper-rare de groupe de 1 unité, pleinement repéré de suite (coef
// K.A. = 4) et abattu de suite par des "super"-IA type Lucky Luke qui dégaine très vite
if (count _grpplayers > 0) then { _coords = getpos (_grpplayers select ((_retVal * -1) - 1)) };
};
};
// PATROUILLE DÉCIMÉE !! sortie immédiate -=PRIORITAIRE=-
if ((count units _grppatrol) == 0) exitwith {};
// ATTAQUE DÉTECTÉE !! groupe en combat => sortie boucle foreach, reembrayé sur boucle 'while' du leader...
if (_alerte > 1) exitwith {};
} foreach units _grppatrol; // Tout ce qui est dans cette boucle s'y trouve pour réaction immédiate
// ALERTE => configuration de combat
if (_alerte > 0) then {
// Tenir compte du cas hyper-rare de groupe de 1 unité, pleinement repéré de suite (coef
// K.A. = 4) et abattue de suite par des "super"-IA type Lucky Luke qui dégaine très vite
// => ... and (count _coords == 3)
// _alerte est > 1 si le groupe est en attaque (cas 1:mort ou cas 2:knowsabout)
if ((_alerte > 1) and (count _coords == 3)) then {
if ( getMarkerType _mkalerte == "" ) then {
createMarker [_mkalerte, _coords];
_mkalerte setMarkerType "Empty";
if ((_iconestrt != "") and (_iconedest != "")) then {
_mkalerte setMarkerType "Flag";
_mkalerte setMarkerText "alerte";
_mkalerte setMarkerColor (getMarkerColor _iconestrt);
};
_mkalerte setMarkerSize [1,1];
};
_mkalerte setMarkerPos _coords;
};
}
// AUCUNE ALERTE
else {
// Boucle de "desertion" pour chaque unité de la patrouille : gestion du "_deserteur" indiqué dans le tableau "_rappel"
for [{_i = 0},{_i < count units _grppatrol},{_i = _i + 1}] do {
_deserteur = units _grppatrol select _i;
// Si un "déserteur" est revenu à - de [_maxdist], le retirer du tableau rappel
if (_deserteur distance [_wpgrpx,_wpgrpy] < _maxdist) then {_rappel = _rappel - [_deserteur]};
_nbrappel = {_x == _deserteur} count _rappel;
// 3 rappels = demande de rejoindre la formation; laisse le temps de visiter le batiment
if (_nbrappel == 3) then {
_deserteur setSpeedMode "FULL";
_grppatrol move [_wpgrpx,_wpgrpy];
};
// 10 rappels = risque de bug de waypoint, unités bloquée => téléportation
if (_nbrappel == 10) then {
_pos = getpos leader _grppatrol;
_deserteur setpos [(_pos select 0) + 1,(_pos select 1) + 1];
_rappel = _rappel - [_deserteur];
};
}; // <--- : for _i<count units _grppatrol...
}; // <--- : if _alerte > 0...
// PATROUILLE DÉCIMÉE !! sortie immédiate -=PRIORITAIRE=-
if ((count units _grppatrol) == 0) exitwith {};
// Si _alerte, determiner tout de suite un nouveau wp, sans attendre que le leader soit arrivé
if (_alerte > 0) exitwith {};
sleep 0.5;
}; // <--- : while leader _grppatrol distance [_wpgrpx,_wpgrpy] > 30 ...
}; // <--- : if _waypointok...
// wp hors alerte : attendre qu'au moins la 2/3 des hommes
// soient à proximité du waypoint/du leader une fois arrivé
if (_alerte == 0) then {
_minmen = floor ((count units _grppatrol) / 1.5);
_cntnear = 0;
_timer = 0;
while {_cntnear < _minmen} do {
_cntnear = 0;
{
if ((leader _grppatrol) distance _x < (_minmen * 10)) then {_cntnear = _cntnear + 1};
} foreach units _grppatrol;
_timer = _timer + 1;
sleep 1;
if (_timer > 120) then {
_lpos = getpos leader _grppatrol;
{_x setpos _lpos} foreach units _grppatrol;
};
};
}; // <--- : if not _alerte
_visited = [];
sleep 0.5;
_infinite = 0;
}; // for _infinite...
sleep 5;
if ( getMarkerType _mkalerte != "" ) then { deletemarker _mkalerte };
2 participants

1 réponse

03/11/2017 08:28 Message non lu

Pas mal du tout. Tu as testé ?
Il fonctionne mieux qu'UPS ?

Statistiques

  • 75 sujets créés
  • 134 messages postés
  • 6 annonces
  • 12 participants

Activité du forum

Il y a 0 utilisateur sur le forum

aucun visiteur
Propulsé par NeoFrag CMS version Alpha 0.1.6.1