Jump to content
Sign in to follow this  
Monsada

UPSMON - Urban Patrol Script Mon

Recommended Posts

Does anyone know how to disable ghost mode on UPSMON? if so thanks :)

---------- Post added at 12:31 PM ---------- Previous post was at 11:20 AM ----------

nvm you just have to turn off the debug :) Derp

Share this post


Link to post
Share on other sites

Hi,

Quick question for you guys...

I am working on a big map with UPSMON patrols over several areas. Basically I spawn UPSMON patrols in areas near the player. When the player moves away from the area, I want to be able to remove the UPSMON controlled units (as I no longer need them to patrol). As it is a big map, over time it gets full off patrolling units nowhere near the player and causes performance issues.

Is there a way to do this within UPSMON?

EDIT ---->

I have a subsequent question...

Is it possible to change the patrol area of a spawned UPSMON guy dynamically. ie when he first spawns, an UPSMON call is made to patrol "Area_0" and then later on I need him to then go and patrol "Area_1" if he is still alive.

Edited by Jedra

Share this post


Link to post
Share on other sites
Hi,

Quick question for you guys...

I am working on a big map with UPSMON patrols over several areas. Basically I spawn UPSMON patrols in areas near the player. When the player moves away from the area, I want to be able to remove the UPSMON controlled units (as I no longer need them to patrol). As it is a big map, over time it gets full off patrolling units nowhere near the player and causes performance issues.

Is there a way to do this within UPSMON?

You might want to check cB AI Unit Caching.

Share this post


Link to post
Share on other sites
You might want to check cB AI Unit Caching.

Hi,

Thanks for the tip. I did try this but unfortunately it did not play nicely with other scripts I have running (such as a paradrop script). It works well in other missions I have done, just not this one!

Share this post


Link to post
Share on other sites

Just a check guys

If AI surrender I presume they no longer count in the trigger area Opfor no present, so you do not have to kill them ?

Lao what happens to them , do they get deleted after a while still ?

Share this post


Link to post
Share on other sites

Lao what happens to them , do they get deleted after a while still ?

As far as I know, no, only if you killed them (script for deleting units uses the 'killed' event handler, and surrender script do not attach any time to live code to the units.)

Share this post


Link to post
Share on other sites

Is it possible to get this as module?

When I fool around in the editor I want to use UPSMON to test stuff, but right now I need to save the mission first and then put all UPSMON files there - which is quite uncomfortable.

Would've been nice to see this as a pbo addon that you use in the editor and use identical scripts (like the ones now) when publishing the mission

Share this post


Link to post
Share on other sites

Belay my last, I'm tinkering with different ways to use the UPSMON artillery module with my mission. Originally I had given each unit an UPS init line that was basically just a "nowp" "noai" line, but they still wouldn't behave like they would normally in ACE w/Zeus. So next I decided with placing an observer using this line:

this setCaptive true; this setPosATL [717.19,1613,9.51648]; this setDir 273.266; this setUnitPos "down"; this setCombatMode "blue"; nul=[this,"sangin","nowp3","noai"] execVM "scripts\upsmon.sqf";

however he goes prone for a moment, then UPSMON kicks in and he stands up, gets off the roof and walks around.

I've also tried "nowp" instead of "3"

Edited by The Hebrew Hammer

Share this post


Link to post
Share on other sites
Okay, I've got the hang of it for the most part, but I'm also using the UPS respawn script, after a unit respawns, I want it to adopt the parameters that it had before it died. I'm building a siege mission and I need units to constantly spawn, and move back to an area and get into cover and mounted guns.

nul=[this,"island","fortify","delete:",600] execVM "scripts\upsmon.sqf"; nul = [this, 3, 10, "spawn1","island"] execVM "AI_respawn_UPS\AI_respawn_UPS_init.sqf";

Is there a way I can set parameters like "fortify", "nofollow", or "random" to the respawn script? Because it seems to me it will only work if it's [this, # of spawns, spawn time, spawn marker, marker to move to] and spawning won't take place unless it's specifically like that

Hi Hebreu, can u test "respawn" parameter?

nul=[this,"island","fortify","delete:",600,"respawn"] execVM "scripts\upsmon.sqf";

you can add it in the spawn module too.

If you want only to respawn x times set "respawn:",x

i spect this can help u,

Monsada

Share this post


Link to post
Share on other sites

Hello, Is it possible to force where unit(s) will not be placed or patrol when using the "random" option? Like a nogo / nostart marker? I thought I read it somewhere in this thread, but after many searches I gave in and posted :(

Share this post


Link to post
Share on other sites

Also...

I am using an upsmon marker inside seized by triggers, the marker is set to move to other seized by triggers... this all works perfectly unless i use this condition

this && [triggername, getMarkerPos "markername"] call BIS_fnc_inTrigger

Could there be any solution to this?

Edit: this happens with the original ups also, so what in this original script should i look at? i put this up before looking at it sorry, as i probably wont know it if i see it?

// =========================================================================================================
//  Urban Patrol Script  
//  Version: 2.1.0
//  Author: Kronzky (www.kronzky.info / kronzky@gmail.com)
// ---------------------------------------------------------------------------------------------------------
//  Required parameters:
//    unit          = Unit to patrol area (1st argument)
//    markername    = Name of marker that covers the active area. (2nd argument)
//    (e.g. nul=[this,"town"] execVM "ups.sqf")
//
//  Optional parameters: 
//    random        = Place unit at random start position.
//    randomdn      = Only use random positions on ground level.
//    randomup      = Only use random positions at top building positions. 
//    min:n/max:n   = Create a random number (between min and max) of 'clones'.
//    init:string   = Cloned units' init string.
//    prefix:string = Cloned units' names will start with this prefix.
//    nomove        = Unit will stay at start position until enemy is spotted.
//    nofollow      = Unit will only follow an enemy within the marker area.
//    delete:n      = Delete dead units after 'n' seconds.
//    nowait        = Do not wait at patrol end points.
//    noslow        = Keep default behaviour of unit (don't change to "safe" and "limited").
//    noai          = Don't use enhanced AI for evasive and flanking maneuvers.
//    showmarker    = Display the area marker.
//    trigger       = Display a message when no more units are left in sector.
//    empty:n       = Consider area empty, even if 'n' units are left.
//    track         = Display a position and destination marker for each unit.
//
// =========================================================================================================

if (!isServer) exitWith {};

// how far opfors should move away if they're under attack
// set this to 200-300, when using the script in open areas (rural surroundings)
#define SAFEDIST 75

// how close unit has to be to target to generate a new one 
#define CLOSEENOUGH 10

// how close units have to be to each other to share information
#define SHAREDIST 100

// how long AI units should be in alert mode after initially spotting an enemy
#define ALERTTIME 180

// ---------------------------------------------------------------------------------------------------------
//echo format["[K] %1",_this];

// convert argument list to uppercase
_UCthis = [];
for [{_i=0},{_i<count _this},{_i=_i+1}] do {_e=_this select _i; if (typeName _e=="STRING") then {_e=toUpper(_e)};_UCthis set [_i,_e]};

// ***************************************** SERVER INITIALIZATION *****************************************

// global functions
if (isNil("KRON_UPS_INIT")) then {
KRON_UPS_INIT=0;

// find a random position within a radius
KRON_randomPos = {private["_cx","_cy","_rx","_ry","_cd","_sd","_ad","_tx","_ty","_xout","_yout"];_cx=_this select 0; _cy=_this select 1; _rx=_this select 2; _ry=_this select 3; _cd=_this select 4; _sd=_this select 5; _ad=_this select 6; _tx=random (_rx*2)-_rx; _ty=random (_ry*2)-_ry; _xout=if (_ad!=0) then {_cx+ (_cd*_tx - _sd*_ty)} else {_cx+_tx}; _yout=if (_ad!=0) then {_cy+ (_sd*_tx + _cd*_ty)} else {_cy+_ty}; [_xout,_yout]};
// find any building (and its possible building positions) near a position
KRON_PosInfo = {private["_pos","_lst","_bld","_bldpos"];_pos=_this select 0; _lst= nearestObjects [_pos,["House","vbs2_house"],20]; if (count _lst==0) then {_bld=0;_bldpos=0} else {_bld=_lst select 0; _bldpos=[_bld] call KRON_BldPos}; [_bld,_bldpos]};
/// find the highest building position	
KRON_BldPos = {private ["_bld","_bi","_bldpos","_maxZ","_bp","_bz","_higher"];_bld=_this select 0;_maxZ=0;_bi=0;_bldpos=0;while {_bi>=0} do {_bp = _bld BuildingPos _bi;if ((_bp select 0)==0) then {_bi=-99} else {_bz=_bp select 2; _higher = ((_bz>_maxZ) || ((abs(_bz-_maxZ)<.5) && (random 1>.5))); if ((_bz>4) && _higher) then {_maxZ=_bz; _bldpos=_bi}};_bi=_bi+1};_bldpos};
KRON_OnRoad = {private["_pos","_car","_tries","_lst"];_pos=_this select 0; _car=_this select 1; _tries=_this select 2; _lst=_pos nearRoads 4; if ((count _lst!=0) && (_car || !(surfaceIsWater _pos))) then {_tries=99}; (_tries+1)};
KRON_getDirPos = {private["_a","_b","_from","_to","_return"]; _from = _this select 0; _to = _this select 1; _return = 0; _a = ((_to select 0) - (_from select 0)); _b = ((_to select 1) - (_from select 1)); if (_a != 0 || _b != 0) then {_return = _a atan2 _b}; if ( _return < 0 ) then { _return = _return + 360 }; _return};
KRON_distancePosSqr = {(((_this select 0) select 0)-((_this select 1) select 0))^2 + (((_this select 0) select 1)-((_this select 1) select 1))^2};
KRON_relPos = {private["_p","_d","_a","_x","_y","_xout","_yout"];_p=_this select 0; _x=_p select 0; _y=_p select 1; _d=_this select 1; _a=_this select 2; _xout=_x + sin(_a)*_d; _yout=_y + cos(_a)*_d;[_xout,_yout,0]};
KRON_rotpoint = {private["_cp","_a","_tx","_ty","_cd","_sd","_cx","_cy","_xout","_yout"];_cp=_this select 0; _cx=_cp select 0; _cy=_cp select 1; _a=_this select 1; _cd=cos(_a*-1); _sd=sin(_a*-1); _tx=_this select 2; _ty=_this select 3; _xout=if (_a!=0) then {_cx+ (_cd*_tx - _sd*_ty)} else {_cx+_tx}; _yout=if (_a!=0) then {_cy+ (_sd*_tx + _cd*_ty)} else {_cy+_ty}; [_xout,_yout,0]};
KRON_stayInside = {
	private["_np","_nx","_ny","_cp","_cx","_cy","_rx","_ry","_d","_tp","_tx","_ty","_fx","_fy"];
	_np=_this select 0;	_nx=_np select 0;	_ny=_np select 1;
	_cp=_this select 1;	_cx=_cp select 0;	_cy=_cp select 1;
	_rx=_this select 2;	_ry=_this select 3;	_d=_this select 4;
	_tp = [_cp,_d,(_nx-_cx),(_ny-_cy)] call KRON_rotpoint;
	_tx = _tp select 0; _fx=_tx;
	_ty = _tp select 1; _fy=_ty;
	if (_tx<(_cx-_rx)) then {_fx=_cx-_rx};
	if (_tx>(_cx+_rx)) then {_fx=_cx+_rx};
	if (_ty<(_cy-_ry)) then {_fy=_cy-_ry};
	if (_ty>(_cy+_ry)) then {_fy=_cy+_ry};
	if ((_fx!=_tx) || (_fy!=_ty)) then {_np = [_cp,_d*-1,(_fx-_cx),(_fy-_cy)] call KRON_rotpoint};
	_np;
};
// Misc
KRON_getArg = {private["_cmd","_arg","_list","_a","_v"]; _cmd=_this select 0; _arg=_this select 1; _list=_this select 2; _a=-1; {_a=_a+1; _v=format["%1",_list select _a]; if (_v==_cmd) then {_arg=(_list select _a+1)}} foreach _list; _arg};
KRON_deleteDead = {private["_u","_s"];_u=_this select 0; _s= _this select 1; _u removeAllEventHandlers "killed"; sleep _s; deletevehicle _u};

KRON_AllWest=[];
KRON_AllEast=[];
KRON_AllRes=[];
KRON_KnownEnemy=[objNull,objNull];

// find all units in mission
{
	_s = side _x;
	switch (_s) do {
		case west: 
			{ KRON_AllWest=KRON_AllWest+[_x]; };
		case east: 
			{ KRON_AllEast=KRON_AllEast+[_x]; };
		case resistance: 
			{ KRON_AllRes=KRON_AllRes+[_x]; };
	};
}forEach allUnits;

if (isNil("KRON_UPS_Debug")) then {KRON_UPS_Debug=0};
KRON_HQ="Logic" createVehicle [0,0];
KRON_UPS_Instances=0;
KRON_UPS_Total=0;
KRON_UPS_Exited=0;
KRON_UPS_INIT=1;
};
if ((count _this)<2) exitWith {
if (format["%1",_this]!="INIT") then {hint "UPS: Unit and marker name have to be defined!"};
};
_exit = false;
_onroof = false;

// ---------------------------------------------------------------------------------------------------------
waitUntil {KRON_UPS_INIT==1};
sleep (random 1);

KRON_UPS_Instances =	KRON_UPS_Instances + 1;

// get name of area marker 
_areamarker = _this select 1;
if (isNil ("_areamarker")) exitWith {
hint "UPS: Area marker not defined.\n(Typo, or name not enclosed in quotation marks?)";
};	

_centerpos = [];
_centerX = [];
_centerY = [];
_rangeX = 0;
_rangeY = 0;
_areadir = 0;
_areaname = "";
_areatrigger = objNull;
_showmarker = "HIDEMARKER";
_getAreaInfo = {
if (typeName _areamarker=="String") then {
	// remember center position of area marker
	_centerpos = getMarkerPos _areamarker;
	_centerX = abs(_centerpos select 0);
	_centerY = abs(_centerpos select 1);

	// X/Y range of target area
	_areasize = getMarkerSize _areamarker;
	_rangeX = _areasize select 0;
	_rangeY = _areasize select 1;
	// marker orientation (needed as negative value!)
	_areadir = (markerDir _areamarker) * -1;

	_areaname = _areamarker;

	// show area marker 
	_showmarker = if ("SHOWMARKER" in _UCthis) then {"SHOWMARKER"} else {"HIDEMARKER"};
	if (_showmarker=="HIDEMARKER") then {
		_areamarker setMarkerPos [-abs(_centerX),-abs(_centerY)];
	};
} else {
	_centerpos = getPos _areamarker;
	_centerX = abs(_centerpos select 0);
	_centerY = abs(_centerpos select 1);

	// X/Y range of target area
	_rangeX = triggerArea _areamarker select 0;
	_rangeY = triggerArea _areamarker select 1;
	// marker orientation (needed as negative value!)
	_areadir = (getDir _areamarker) * -1;

	_areaname = vehicleVarName _areamarker;
};
// update trigger position
if !(isNull _areatrigger) then {
	_areatrigger setPos [_centerX,_centerY];
};
};
[] call _getAreaInfo;
sleep .01;

// unit that's moving
_obj = _this select 0;		
_npc = _obj;
// is anybody alive in the group?
_exit = true;		
if (typename _obj=="OBJECT") then {
if (alive _npc) then {_exit = false;}		
} else {
if (count _obj>0) then {
	{if (alive _x) then {_npc = _x; _exit = false;}} forEach _obj;
};
};

// give this group a unique index
_grpidx = format["%1",KRON_UPS_Instances];
_grpname = format["%1_%2",(side _npc),_grpidx];

// remember the original group members, so we can later find a new leader, in case he dies
_members = units _npc;
KRON_UPS_Total = KRON_UPS_Total + (count _members);

// what type of "vehicle" is unit ?
_isman = _npc isKindOf "Man";
_iscar = _npc isKindOf "vbs2_LandVehicles";
_isboat = _npc isKindOf "Ship";
_isplane = _npc isKindOf "Air";

// check to see whether group is an enemy of the player (for attack and avoidance maneuvers)
// since countenemy doesn't count vehicles, and also only counts enemies if they're known, 
// we just have to brute-force it for now, and declare *everyone* an enemy who isn't a civilian
_issoldier = side _npc != civilian;

_friends=[];
_enemies=[];	
_sharedenemy=0;
//TODO: FIND A WAY TO DETERMINE ASSOCIATION OF RESISTANCE UNITS
if (_issoldier) then {
switch (side _npc) do {
	case west:
		{ _friends=_friends+KRON_AllWest; _enemies=_enemies+KRON_AllEast+KRON_AllRes; _sharedenemy=0; };
	case east:
		{ _friends=_friends+KRON_AllEast; _enemies=_enemies+KRON_AllWest+KRON_AllRes; _sharedenemy=1; };
	case resistance:
		{ _enemies=_enemies+KRON_AllEast+KRON_AllWest; _sharedenemy=2; };
};
{
	_friends=_friends-[_x];
	_x disableAI "autotarget";
} forEach _members;
};
sleep .01;

// global unit variable to externally influence script 
_named = false;
_npcname = str(side _npc);
if ("NAMED" in _UCthis) then {
_named = true;
_npcname = format["%1",_npc];
_grpidx = _npcname;
};
// create global variable for this group
call compile format ["KRON_UPS_%1=1",_npcname];

// store some trig calculations
_cosdir=cos(_areadir);
_sindir=sin(_areadir);

// minimum distance of new target position
if (_rangeX==0) exitWith {
hint format["UPS: Cannot patrol Sector: %1\nArea Marker doesn't exist",_areaname]; 
};
_mindist=(_rangeX^2+_rangeY^2)/4;

// remember the original mode & speed
_orgMode = behaviour _npc;
_orgSpeed = speedmode _npc;
_speedmode = _orgSpeed;

// set first target to current position (so we'll generate a new one right away)
_currPos = getpos _npc;
_orgPos = _currPos;
_orgWatch=[_currPos,50,getDir _npc] call KRON_relPos; 
_orgDir = getDir _npc;
_avoidPos = [0,0];
_flankPos = [0,0];
_attackPos = [0,0];

_dist = 0;
_lastdist = 0;
_lastmove1 = 0;
_lastmove2 = 0;
_maxmove=0;
_moved=0;

_damm=0;
_dammchg=0;
_lastdamm = 0;
_timeontarget = 0;

_fightmode = "walk";
_fm=0;
_gothit = false;
_hitPos=[0,0,0];
_react = 99;
_lastdamage = 0;
_lastknown = 0;
_opfknowval = 0;

_sin90=1; _cos90=0;
_sin270=-1; _cos270=0;

// set target tolerance high for choppers & planes
_closeenough=CLOSEENOUGH*CLOSEENOUGH;
if (_isplane) then {_closeenough=5000};

sleep .01;
// ***************************************** optional arguments *****************************************

// wait at patrol end points
_pause = if ("NOWAIT" in _UCthis) then {"NOWAIT"} else {"WAIT"};
// don't move until an enemy is spotted
_nomove  = if ("NOMOVE" in _UCthis) then {"NOMOVE"} else {"MOVE"};
// don't follow outside of marker area
_nofollow = if ("NOFOLLOW" in _UCthis) then {"NOFOLLOW"} else {"FOLLOW"};
// share enemy info 
_shareinfo = if ("NOSHARE" in _UCthis) then {"NOSHARE"} else {"SHARE"};
// "area cleared" trigger activator
_usetrigger = if ("TRIGGER" in _UCthis) then {"TRIGGER"} else {if ("NOTRIGGER" in _UCthis) then {"NOTRIGGER"} else {"SILENTTRIGGER"}};
// suppress fight behaviour
if ("NOAI" in _UCthis) then {_issoldier=false};
// adjust cycle delay 
_cycle = ["CYCLE:",5,_UCthis] call KRON_getArg;
// drop units at random positions
_initpos = "ORIGINAL";
if ("RANDOM" in _UCthis) then {_initpos = "RANDOM"};
if ("RANDOMUP" in _UCthis) then {_initpos = "RANDOMUP"}; 
if ("RANDOMDN" in _UCthis) then {_initpos = "RANDOMDN"}; 
// don't position groups or vehicles on rooftops
if ((_initpos!="ORIGINAL") && ((!_isman) || (count _members)>1)) then {_initpos="RANDOMDN"};
// set behaviour modes (or not)
_noslow = if ("NOSLOW" in _UCthis) then {"NOSLOW"} else {"SLOW"};
if (_noslow!="NOSLOW") then {
_npc setbehaviour "aware"; 
_npc setSpeedMode "full";
_speedmode = "full";
}; 

// make start position random 
if (_initpos!="ORIGINAL") then {
// find a random position (try a max of 20 positions)
_try=0;
_bld=0;
_bldpos=0;
while {_try<20} do {
	_currPos=[_centerX,_centerY,_rangeX,_rangeY,_cosdir,_sindir,_areadir] call KRON_randomPos;
	if ((_initpos=="RANDOMUP") || ((_initpos=="RANDOM") && (random 1>.75))) then {
		_posinfo=[_currPos] call KRON_PosInfo;
		// _posinfo: [0,0]=no house near, [obj,-1]=house near, but no roof positions, [obj,pos]=house near, with roof pos
		_bld=_posinfo select 0;
		_bldpos=_posinfo select 1;
	};
	if (_isplane || _isboat || !(surfaceiswater _currPos)) then {
		if (((_initpos=="RANDOM") || (_initpos=="RANDOMUP")) && (_bldpos>0)) then {_try=99};
		if (((_initpos=="RANDOM") || (_initpos=="RANDOMDN")) && (_bldpos==0)) then {_try=99};
	};
	_try=_try+1;
};
if (_bldpos==0) then {
	if (_isman) then {
		{_x setPos _currPos} foreach units _npc; 
	} else {
		_npc setPos _currPos;
	};
} else {
// put the unit on top of a building
	_npc setPos (_bld buildingPos _bldpos); 
	_npc setUnitPos "up";
	_currPos = getPos _npc;
	_onroof = true;
	_exit=true; // don't patrol if on roof
};
};
sleep .01;

// track unit
_track = 	if (("TRACK" in _UCthis) || (KRON_UPS_Debug>0)) then {"TRACK"} else {"NOTRACK"};
_trackername = "";
_destname = "";
if (_track=="TRACK") then {
_track = "TRACK";
_trackername=format["trk_%1",_grpidx];
_markerobj = createMarker[_trackername,[0,0]];
_markerobj setMarkerShape "ICON";
_markertype = if (isClass(configFile >> "cfgMarkers" >> "WTF_Dot")) then {"WTF_DOT"} else {"DOT"};
_trackername setMarkerType _markertype;
_markercolor = switch (side _npc) do {
	case west: {"ColorGreen"};
	case east: {"ColorRed"};
	case resistance: {"ColorBlue"};
	default {"ColorBlack"};
};
_trackername setMarkerColor _markercolor;
_trackername setMarkerText format["%1",_grpidx];
_trackername setmarkerpos _currPos; 
_trackername setMarkerSize [.5,.5];

_destname=format["dest_%1",_grpidx];
_markerobj = createMarker[_destname,[0,0]];
_markerobj setMarkerShape "ICON";
_markertype = if (isClass(configFile >> "cfgMarkers" >> "WTF_Flag")) then {"WTF_FLAG"} else {"FLAG"};
_destname setMarkerType _markertype;
_destname setMarkerColor _markercolor;
_destname setMarkerText format["%1",_grpidx];
_destname setMarkerSize [.5,.5];
};	
sleep .01;

// delete dead units
_deletedead = ["DELETE:",0,_UCthis] call KRON_getArg;
if (_deletedead>0) then {
{_x addEventHandler['killed',format["[_this select 0,%1] spawn KRON_deleteDead",_deletedead]]}forEach _members;
};

// how many group clones?
// TBD: add to global side arrays?
_mincopies = ["MIN:",0,_UCthis] call KRON_getArg;
_maxcopies = ["MAX:",0,_UCthis] call KRON_getArg;
if (_mincopies>_maxcopies) then {_maxcopies=_mincopies};
if (_maxcopies>140) exitWith {hint "Cannot create more than 140 groups!"};
if (_maxcopies>0) then {
if !(_isMan) exitWith {hint "Vehicles cannot be cloned."};
_copies=_mincopies+round(random (_maxcopies-_mincopies));
// any init strings?
_initstr = ["INIT:","",_UCthis] call KRON_getArg;

// name of clones
_nameprefix = ["PREFIX:","UPSCLONE",_UCthis] call KRON_getArg;

// create the clones
for "_grpcnt" from 1 to _copies do {
	// group leader
	_unittype=typeof _npc;
	// copy groups
	if (isNil ("KRON_cloneindex")) then {
		KRON_cloneindex = 0;
	}; 
	// make the clones civilians
	// use random Civilian models for single unit groups
	if ((_unittype=="Civilian") && (count _members==1)) then {_rnd=1+round(random 20); if (_rnd>1) then {_unittype=format["Civilian%1",_rnd]}};

	_grp=createGroup side _npc;
	_lead = _grp createUnit [_unittype, getpos _npc, [], 0, "form"];
	KRON_cloneindex = KRON_cloneindex+1;
	_lead setVehicleVarName format["%1%2",_nameprefix,KRON_cloneindex];
	call compile format["%1%2=_lead",_nameprefix,KRON_cloneindex];
	_lead setBehaviour _orgMode;
	_lead setSpeedMode _orgSpeed;
	_lead setSkill skill _npc;
	_lead setVehicleInit _initstr;
	[_lead] join _grp;
	_grp selectLeader _lead;
	// copy team members (skip the leader)
	_c=0;
	{
		_c=_c+1;
		if (_c>1) then {
			_newunit = _grp createUnit [typeof _x, getpos _x, [],0,"form"];
			KRON_cloneindex = KRON_cloneindex+1;
			_newunit setVehicleVarName format["%1%2",_nameprefix,KRON_cloneindex];
			call compile format["%1%2=_newunit",_nameprefix,KRON_cloneindex];
			_newunit setBehaviour _orgMode;
			_newunit setSpeedMode _orgSpeed;
			_newunit setSkill skill _x;
			_newunit setVehicleInit _initstr;
			[_newunit] join _grp;
		};
	} foreach _members;
	_nul=[_lead,_areamarker,_pause,_noslow,_nomove,_nofollow,_initpos,_track,_showmarker,_shareinfo,"DELETE:",_deletedead] execVM "ups.sqf";
	sleep .05;
};	
processInitCommands;
};
sleep .01;


// units that can be left for area to be "cleared"
_zoneempty = ["EMPTY:",0,_UCthis] call KRON_getArg;

// create area trigger
if (_usetrigger!="NOTRIGGER") then {
_trgside = switch (side _npc) do { case west: {"WEST"}; case east: {"EAST"}; case resistance: {"GUER"}; case civilian: {"CIV"};};
_trgname="KRON_Trig_"+_trgside+"_"+_areaname;
_flgname="KRON_Cleared_"+_areaname;
// has the trigger been created already?
KRON_TRGFlag=-1;
call compile format["%1=false",_flgname];
call compile format["KRON_TRGFlag=%1",_trgname];
if (isNil ("KRON_TRGFlag")) then {
	// trigger doesn't exist yet, so create one (make it a bit bigger than the marker, to catch path finding 'excursions' and flanking moves)
	call compile format["%1=createTrigger['EmptyDetector',[_centerX,_centerY]];",_trgname];
	call compile format["_areatrigger = %1",_trgname];
	call compile format["%1 setTriggerArea[_rangeX*1.5,_rangeY*1.5,markerDir _areaname,true]",_trgname];
	call compile format["%1 setTriggerActivation[_trgside,'PRESENT',true]",_trgname];
	call compile format["%1 setEffectCondition 'true'",_trgname];
	call compile format["%1 setTriggerTimeout [5,7,10,true]",_trgname];
	if (_usetrigger!="SILENTTRIGGER") then {
		_markerhide = [-_centerX,-_centerY];
		_markershow = [_centerX,_centerY];
		if (_showmarker=="HIDEMARKER") then {
			_markershow = [-_centerX,-_centerY];
		};
		call compile format["%1 setTriggerStatements['count thislist<=%6', 'titletext [''SECTOR <%2> CLEARED'',''PLAIN''];''%2'' setmarkerpos %4;%3=true;', 'titletext [''SECTOR <%2> HAS BEEN RE-OCCUPIED'',''PLAIN''];''%2'' setmarkerpos %5;%3=false;']", _trgname,_areaname,_flgname,_markerhide,_markershow,_zoneempty];
	} else {
		call compile format["%1 setTriggerStatements['count thislist<=%3', '%2=true;', '%2=false;']", _trgname,_flgname,_zoneempty];
	};
};
sleep .01;
};

// init done
_makenewtarget=true;
_newpos=false;
_targetPos = _currPos;
_swimming = false;
_waiting = if (_nomove=="NOMOVE") then {9999} else {0};

// exit if something went wrong during initialization (or if unit is on roof)
if (_exit) exitWith {
if ((KRON_UPS_DEBUG>0) && !_onroof) then {hint "Initialization aborted"};
};

// ***********************************************************************************************************
// ************************************************ MAIN LOOP ************************************************
_loop=true;
_currcycle=_cycle;
while {_loop} do {
sleep .01;
// keep track of how long we've been moving towards a destination
_timeontarget=_timeontarget+_currcycle;
_react=_react+_currcycle;

// did anybody in the group got hit?
_newdamage=0; 
{
	if((damage _x)>0.2) then {
		_newdamage=_newdamage+(damage _x); 
		// damage has increased since last round
		if (_newdamage>_lastdamage) then {
			_lastdamage=_newdamage; 
			_gothit=true;
		};
		_hitPos=getpos _x; 
		if (!alive _x) then {
			_members=_members-[_x]; 
			_friends=_friends-[_x]; 
		};
	};
} foreach _members;
sleep .01;

// nobody left alive, exit routine
if (count _members==0) then {
	_exit=true;
} else {
	// did the leader die?
	if (!alive _npc) then {
		_npc = _members select 0; 
		group _npc selectLeader _npc;
		if (isPlayer _npc) then {_exit=true};
	};
};

// current position
_currPos = getpos _npc; _currX = _currPos select 0; _currY = _currPos select 1;
if (_track=="TRACK") then { _trackername setmarkerpos _currPos; };

// if the AI is a civilian we don't have to bother checking for enemy encounters
if ((_issoldier) && ((count _enemies)>0) && !(_exit)) then {

	// if the leader comes across another unit that's either injured or dead, go into combat mode as well. 
	// If the other person is still alive, share enemy information.
	if ((_shareinfo=="SHARE") && (behaviour _npc=="SAFE")) then {
		_others=_friends-_members;
		{
			if ((!(isNull _x) && (_npc distance _x<SHAREDIST)) && ((damage _x>.5) || (behaviour _x in ["AWARE","COMBAT"]))) exitWith {
				_npc setBehaviour "aware"; 
				_gothit=true; 
				if ((_hitPos select 0)==0) then {_hitPos = getPos _x};
				if (_npc knowsabout _x>3) then {
					if (alive _x) then {_npc reveal (KRON_KnownEnemy select _sharedenemy)}; 
				};
			};
		}forEach _others;
	};
	sleep .01;

	// did the group spot an enemy?
	_lastknown=_opfknowval;
	_opfknowval=0; 
	_maxknowledge=0;
	{
		_knows=_npc knowsabout _x; 
		if ((alive _x) && (_knows>0.2) && (_knows>_maxknowledge)) then {
			KRON_KnownEnemy set [_sharedenemy,_x]; 
			_opfknowval=_opfknowval+_knows; 
			_maxknowledge=_knows;
		};
		if (!alive _x) then {_enemies=_enemies-[_x]};
		if (_maxknowledge==4) exitWith {};
	}forEach _enemies;
	sleep .01;

	_pursue=false;
	_accuracy=100;
	// opfor spotted an enemy or got shot, so start pursuit
	if (_opfknowval>_lastknown || _gothit) then {
		_npc setbehaviour "combat";
		_pursue=true;
		// make the exactness of the target dependent on the knowledge about the shooter
		_accuracy=21-(_maxknowledge*5);
	};

	if (isNull (KRON_KnownEnemy select _sharedenemy)) then {
		_pursue=false;
	};

	// don't react to new fatalities if less than 60 seconds have passed since the last one
	if ((_react<60) && (_fightmode!="walk")) then {_pursue=false};

	if (_pursue) then	{
		// get position of spotted unit in player group, and watch that spot
		_offsx=_accuracy/2-random _accuracy; _offsY=_accuracy/2-random _accuracy;
		_targetPos = getpos (KRON_KnownEnemy select _sharedenemy);
		_targetPos = [(_targetPos select 0) + _offsX, (_targetPos select 1) + _offsY];
		_targetX = _targetPos select 0; _targetY = _targetPos select 1;
		{_x dowatch _targetPos} foreach units _npc;
		sleep .01;			

		// also go into "combat mode"
		_npc setSpeedMode "full"; 
		_speedmode = "full";
		_npc setbehaviour "combat";
		_pause="NOWAIT";
		_waiting=0;

		// angle from unit to target
		_dir1 = [_currPos,_targetPos] call KRON_getDirPos;
		// angle from target to unit (reverse direction)
		_dir2 = (_dir1+180) mod 360;
		// angle from fatality to target
		_dir3 = if (_hitPos select 0!=0) then {[_hitPos,_targetPos] call KRON_getDirPos} else {_dir1};
		_dd=(_dir1-_dir3);

		// unit position offset straight towards target
		_relUX = sin(_dir1)*SAFEDIST; _relUY = cos(_dir1)*SAFEDIST;
		// target position offset straight towards unit
		_relTX = sin(_dir2)*SAFEDIST; _relTY = cos(_dir2)*SAFEDIST;
		// go either left or right (depending on location of fatality - or randomly if no fatality)
		_sinU=_sin90; _cosU=_cos90; _sinT=_sin270; _cosT=_cos270;
		if ((_dd<0) || (_dd==0 && (random 1)>.5)) then {_sinU=_sin270; _cosU=_cos270; _sinT=_sin90; _cosT=_cos90};

		// avoidance position (right or left of unit)
		_avoidX = _currX + _cosU*_relUX - _sinU*_relUY;
		_avoidY = _currY + _sinU*_relUX + _cosU*_relUY;
		_avoidPos = [_avoidX,_avoidY];
		// flanking position (right or left of target)
		_flankX = _targetX + _cosT*_relTX - _sinT*_relTY;
		_flankY = _targetY + _sinT*_relTX + _cosT*_relTY;
		_flankPos = [_flankX,_flankY];
		// final target position
		_attackPos = _targetPos;
		// for now we're stepping a bit to the side
		_targetPos = _avoidPos;

		if (_nofollow=="NOFOLLOW") then {
			_avoidPos = [_avoidPos,_centerpos,_rangeX,_rangeY,_areadir] call KRON_stayInside;
			_flankPos = [_flankPos,_centerpos,_rangeX,_rangeY,_areadir] call KRON_stayInside;
			_attackPos = [_attackPos,_centerpos,_rangeX,_rangeY,_areadir] call KRON_stayInside;
			_targetPos = [_targetPos,_centerpos,_rangeX,_rangeY,_areadir] call KRON_stayInside;
		};

		_react=0;
		_fightmode="fight";
		_timeontarget=0; 
		_fm=1;
		 if (KRON_UPS_Debug!=0) then {
			"dead" setmarkerpos _hitPos; "avoid" setmarkerpos _avoidPos; "flank" setmarkerpos _flankPos; "target" setmarkerpos _attackPos;
		};
		_newpos=true;
		// speed up the cycle duration after an incident
		if (_currcycle>=_cycle) then {_currcycle=1};
	};
}; 
sleep .01;

if !(_newpos) then {
	// calculate new distance
	// if we're waiting at a waypoint, no calculating necessary
	if (_waiting<=0) then {
		// distance to target
		_dist = [_currPos,_targetPos] call KRON_distancePosSqr;
		if (_lastdist==0) then {_lastdist=_dist};
		_moved = abs(_dist-_lastdist);
		// adjust the target tolerance for fast moving vehicles
		if (_moved>_maxmove) then {_maxmove=_moved; if ((_maxmove/40) > _closeenough) then {_closeenough=_maxmove/40}};
		// how much did we move in the last three cycles?
		_totmove=_moved+_lastmove1+_lastmove2;
		_damm = damage _npc;
		// is our damage changing (increasing)?
		_dammchg = abs(_damm - _lastdamm);

		// we're either close enough, seem to be stuck, or are getting damaged, so find a new target 
		if ((!_swimming) && ((_dist<=_closeenough) || (_totmove<.2) || (_dammchg>0.01) || (_timeontarget>ALERTTIME))) then {_makenewtarget=true;};

		// in 'attack (approach) mode', so follow the flanking path (don't make it too predictable though)
		if ((_fightmode!="walk") && (_dist<=_closeenough)) then {
			if ((random 1)<.95) then {
				if (_flankPos select 0!=0) then {
					_targetPos=_flankPos; _flankPos=[0,0]; _makenewtarget=false; _newpos=true;
					_fm=1;
				} else {
					if (_attackPos select 0!=0) then {
						_targetPos=_attackPos; _attackPos=[0,0]; _makenewtarget=false; _newpos=true;
						_fm=2;
					};
				};
			};
		};
		sleep .01;

		// make new target
		if (_makenewtarget) then {
			if ((_nomove=="NOMOVE") && (_timeontarget>ALERTTIME)) then {
				if (([_currPos,_orgPos] call KRON_distancePosSqr)<_closeenough) then {
					_newpos = false;
				} else {
					_targetPos=_orgPos;
				};
			} else {
				// re-read marker position/size
				[] call _getAreaInfo;
				// find a new target that's not too close to the current position
				_targetPos=_currPos;
				_tries=0;
				while {((([_currPos,_targetPos] call KRON_distancePosSqr) < _mindist)) && (_tries<20)} do {
					_tries=_tries+1;
					// generate new target position (on the road)
					_tries=0;
					while {_tries<20} do {
						_targetPos=[_centerX,_centerY,_rangeX,_rangeY,_cosdir,_sindir,_areadir] call KRON_randomPos; 
						if (_iscar) then {
							_roadlist = _targetPos nearRoads 100;
							if (count _roadlist>0) then {
								_targetPos = getPos (_roadlist select 0);
								_tries=99;
							};
						} else {
							_tries=99;
						};
						//_road=[_targetPos,(_isplane||_isboat),_road] call KRON_OnRoad;
						sleep .01;			
					};
				};
			};
			_avoidPos = [0,0]; _flankPos = [0,0]; _attackPos = [0,0];
			_gothit=false;
			_hitPos=[0,0,0];
			_fm=0;
			_npc setSpeedMode _orgSpeed;
			_newpos=true;

			// if we're waiting at patrol end points then don't create a new target right away. Keep cycling though to check for enemy encounters
			if ((_pause!="NOWAIT") && (_waiting<0)) then {_waiting = (15 + random 20)};
		};
	};
};
sleep .01;

// if in water, get right back out of it again
if (surfaceIsWater _currPos) then {
	if (_isman && !_swimming) then {
		_drydist=999;
		// look around, to find a dry spot
		for [{_a=0}, {_a<=270}, {_a=_a+90}] do {
			_dp=[_currPos,30,_a] call KRON_relPos; 
			if !(surfaceIsWater _dp) then {_targetPos=_dp};
		};
		_newpos=true; 
		_swimming=true;
	};
} else {
	_swimming=false;
};

_waiting = _waiting - _currcycle;
if ((_waiting<=0) && _newpos) then {
	// tell unit about new target position
	if (_fightmode!="walk") then {
		// reset patrol speed after following enemy for a while
		if (_timeontarget>ALERTTIME) then {
			_fightmode="walk";
			_speedmode = _orgSpeed;
			{
				_x setSpeedMode _speedmode;
				_x setBehaviour _orgMode;
			}forEach _members;
		};
		// use individual doMoves if pursuing enemy, 
		// as otherwise the group breaks up too much
		{_x doMove _targetPos}forEach _members;
	} else {
		(group _npc) move _targetPos;
		(group _npc) setSpeedMode _speedmode;
	};
	if (_track=="TRACK") then { 
		switch (_fm) do {
			case 1: 
				{_destname setmarkerSize [.4,.4]};
			case 2: 
				{_destname setmarkerSize [.6,.6]};
			default
				{_destname setmarkerSize [.5,.5]};
		};
		_destname setMarkerPos _targetPos;
	};
	_dist=0; 
	_moved=0; 
	_lastmove1=10; 
	_waiting=-1; 
	_newpos=false;
	_swimming=false;
	_timeontarget = 0; 
};

// move on
_lastdist = _dist; _lastmove2 = _lastmove1; _lastmove1 = _moved; _lastdamm = _damm;

// check external loop switch
_cont = (call compile format ["KRON_UPS_%1",_npcname]);
if (_cont==0) then {_exit=true};

_makenewtarget=false;
if ((_exit) || (isNil("_npc"))) then {
	_loop=false;
} else {
	// slowly increase the cycle duration after an incident
	if (_currcycle<_cycle) then {_currcycle=_currcycle+.5};
	sleep _currcycle;
};
};

if !(isNil("_npc")) then {
{doStop _x; _x domove getPos _x; _x move getPos _x} forEach _members;
};

KRON_UPS_Exited=KRON_UPS_Exited+1;
if (_track=="TRACK") then {
_trackername setMarkerType "Dot";
_destname setMarkerType "Empty";
};
_friends=nil;
_enemies=nil;

EDIT: "showmarker" solved it

Edited by Katipo66

Share this post


Link to post
Share on other sites

Can someone let me know how i can delete Spawned groups , that are no longer needed, i.e when i have moved far away from the patrol zone they will still be alive !

_upsgrp1= [1,getMarkerPos "testspawn",1,["marker_test","spawned","move","showmarker","delete:",30,"respawn:",5]] execVM "SCRIPTS\UPSMON\MON_SPAWN.SQF";
waitUntil {mission1end};
Hint "Should delete";
deleteVehicle _upsgrp1;
{deleteVehicle _ x} foreach units _upsgrp1 ;

I get the Hint but they will not delete the Units

Error from RPT:-

Error position: <units _upsgrp1;

deleteGroup _upsgrp1; >

Error units: Type Script, expected Object,Group

Share this post


Link to post
Share on other sites
Is it just me who cannot connect to the UPSMON wiki at:

http://dev-heaven.net/projects/upsmon/wiki

??

and is there another site/location/doco for this info?

Works fine here.

Can someone let me know how i can delete Spawned groups , that are no longer needed, i.e when i have moved far away from the patrol zone they will still be alive !

_upsgrp1= [1,getMarkerPos "testspawn",1,["marker_test","spawned","move","showmarker","delete:",30,"respawn:",5]] execVM "SCRIPTS\UPSMON\MON_SPAWN.SQF";
waitUntil {mission1end};
Hint "Should delete";
deleteVehicle _upsgrp1;
{deleteVehicle _ x} foreach units _upsgrp1 ;

I get the Hint but they will not delete the Units

Error from RPT:-

Error position: <units _upsgrp1;

deleteGroup _upsgrp1; >

Error units: Type Script, expected Object,Group

Mate the execVm return a script. Acording to what I see the name of your leader is 1? You might want to change it to P1 or something and then write:

{deleteVehicle _ x} foreach units P1;
deletegroup P1;

Share this post


Link to post
Share on other sites

Mate the execVm return a script. Acording to what I see the name of your leader is 1? You might want to change it to P1 or something and then write:

That 1 is a reference to a template he's saved with UPS somewhere else. There's nothing by default that returns any units or groups created via the "spawned from template" method he's using unless he queries the UPS groups array somehow perhaps?

Share this post


Link to post
Share on other sites
Can someone let me know how i can delete Spawned groups , that are no longer needed, i.e when i have moved far away from the patrol zone they will still be alive !

_upsgrp1= [1,getMarkerPos "testspawn",1,["marker_test","spawned","move","showmarker","delete:",30,"respawn:",5]] execVM "SCRIPTS\UPSMON\MON_SPAWN.SQF";
waitUntil {mission1end};
Hint "Should delete";
deleteVehicle _upsgrp1;
{deleteVehicle _ x} foreach units _upsgrp1 ;

I get the Hint but they will not delete the Units

Error from RPT:-

Error position: <units _upsgrp1;

deleteGroup _upsgrp1; >

Error units: Type Script, expected Object,Group

I'm afraid you may not have an option there. Even if you would succeed in deleting/killing the units, you should terminate the UPSMON instance that will be referencing those units, or it will probably bitch about it.

I guess your best bet would be to setDammage 1 forEach unit, because that would terminate the script (provided you are not using auto respawn). But there's the problem of accessing the internal list of units. Maybe a trigger to kill all the units in the area, regardless of who's controlling them?

Share this post


Link to post
Share on other sites

{(vehicle _x) setDammage 1} foreach thisList;

will kill anything inside the trigger.

Share this post


Link to post
Share on other sites
I have put that in a trigger around the whole area but they do not die ?

First, make sure you're writing that in the onActivation field, and then change it to this ;):

{_x setDammage 1} foreach thisList;

Share this post


Link to post
Share on other sites

Well it must just be me as I have that and they just do not die !

Put 50x50 trigger in on alfa radio

condition = this

Act on = Hint "DELETE";{_x setDammage 1} foreach thisList;  

I get the hint but the group just stand there and do not die ?!

Share this post


Link to post
Share on other sites

call {if (count thislist > 0) then {{if (alive _x) then {_x setDamage 1; hint "Destroying BluFor unit!";}} forEach thislist}; false}

Put this in the condition field, and leave the activation field empty.

The reason other solutions don't work have something to do with the fact even repeated triggers must deactivate before they can be activated again.

Share this post


Link to post
Share on other sites
Well it must just be me as I have that and they just do not die !

Put 50x50 trigger in on alfa radio

condition = this

Act on = Hint "DELETE";{_x setDammage 1} foreach thisList;  

I get the hint but the group just stand there and do not die ?!

Naa, you're just starting with this and we've been all giving things for granted, hoping you will figure out the rest.

The radio trigger you're using for triggering the killing, is not the trigger you must be referencing and contains all the units. The thisList of a radio trigger will not be a list of the units on the area you see it covers in the editor. For that, create another trigger, 'condition = blufor present', 'repeatedly', and give it a name, i.e. myUnits.

Then in the onActivation of the Radio Alpha trigger put the line:

{_x setDammage 1} foreach list myUnits;

I hope that's the right syntax, but the point is that you get the idea, and use the BIKI for the rest.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×