Jump to content
Sign in to follow this  
thelegendarykhan

Simple random AI Respawn location question

Recommended Posts

I am using AIRS( which is a fantastic mod) to respawn killed AI units. What I am doing is I have placed "respawn_west" and whenever I am killing one blu for he is respawning correctly at the marker.

I am using this script in the unit init field:

nul = [this,[m1,attack],0,respawn_west,5] execVM "AIRS\addAIgroupToPool.sqf";

and in the mission folder I have placed the entire AIRS and LV folders. The respawn related files are:

AIrespawninit.sqf:

//AIrespawnInit 1.0 by SPUn
if(!isServer)exitWith{};
private["_defaultCleanUp","_diag"];

AIRS_respawn_delay = 25; //AI respawn delay (if not defined in squad leaders init)
_defaultCleanUp = true; //cleanUp script [WIP] (removes corpses & wrecks > 300m of player(s) every 60 secs)
_diag = false; //if true, script hints live unit amount statistics during editor testing, helps you to adjust group amounts & sizes better)

//You can set respawning off side related by changing these variables from your mission:
AIRS_respawn_WEST = true; //respawn WEST groups
AIRS_respawn_EAST = true; //respawn EAST groups
AIRS_respawn_INDE = true; //respawn INDEPENDENT groups

//Just to make sure it's safe to spawn units
WESTcenter = createCenter west;
EASTcenter = createCenter east;
INDEcenter = createCenter resistance;

//Prepare some AIRS functions
AIRS_SpawnGroup = compile preprocessFile "AIRS\spawnGroup.sqf";
AIRS_StartTask = compile preprocessFile "AIRS\startAItask.sqf";
AIRS_buildingPatrol = compile preprocessFile "AIRS\buildingPatrol.sqf";
AIRS_taskPatrol = compile preprocessFile "AIRS\BIS_fnc_taskpatrol2.sqf";
AIRS_taskDefend = compile preprocessFile "AIRS\BIS_fnc_taskdefend2.sqf";
AIRS_fnc_spawnVehicle = compile preprocessFile "AIRS\BIS_fnc_spawnVehicle2.sqf";
AIRS_fnc_spawnGroup = compile preprocessFile "AIRS\BIS_fnc_spawnGroup2.sqf";
AIRS_DestroyEmptyVehicle = compile preprocessFile "AIRS\destroyEmptyVehicle.sqf";
//Start monitoring AI groups
execVM "AIRS\monitorAIgroups.sqf";
//Prepare some LV functions
LV_GetPlayers = compile preprocessFile "LV\LV_functions\LV_fnc_getPlayers.sqf";
LV_NearestBuilding = compile preprocessFile "LV\LV_functions\LV_fnc_nearestBuilding.sqf";
LV_RemoveDead = compile preprocessFile "LV\LV_functions\LV_fnc_removeDead.sqf";
LV_VehicleInit = compile preprocessFile "LV\LV_functions\LV_fnc_vehicleInit.sqf";
LV_Follow = compile preprocessFile "LV\LV_functions\LV_fnc_follow.sqf";
LV_InMarker = compile preprocessFile "LV\LV_functions\LV_fnc_isInMarker.sqf";
//Cleanup:
if(_defaultCleanUp)then{execVM "AIRS\cleanUp.sqf"};
if(_diag)then{execVM "AIRS\diag.sqf"};

AIRS_Initialized = true;

How to randomise the AI's respawn locations by adding new markers to create that uncertainty? and I am needing this in SP only. Not a big fan of MP. I am kindof noob. i dont know what arrays are so please be lenient and bear with me. thanks :D

p.s.: I am wiling to try a new mod or let go of AIRS if a better suggestion comes across.

Share this post


Link to post
Share on other sites

Could you provide the spawnGroup.sqf and spawnGroup2.sqf?

Share this post


Link to post
Share on other sites
Could you provide the spawnGroup.sqf and spawnGroup2.sqf?

Thanks for the reply man. Yeah sure:

spawngroup.sqf:

//spawnGroup  1.0 by SPUn
if(!isServer)exitWith{};
private ["_array","_faction","_group","_side","_base","_grp","_tempGrp","_lifes","_setBase","_task","_delay","_air","_azi","_basePos"];

_array = _this select 0;
_faction = _this select 1;
_group = _this select 2;

_group setVariable ["state", "spawning"];

_delay = _group getVariable "delay";
sleep _delay;

switch(_faction)do{
case "BLU_F":{
	_side = west;
};
case "BLU_G_F":{
	_side = west;
};
case "OPF_F":{
	_side = east;
};
default {
	_side = resistance;
};
};
if((_side == west)&&(!AIRS_respawn_WEST))exitWith{};
if((_side == east)&&(!AIRS_respawn_EAST))exitWith{};
if((_side == resistance)&&(!AIRS_respawn_INDE))exitWith{};

_setBase = _group getVariable "base";
if(isNil("_setBase"))then{
if(_side == resistance)then{
	_base = "respawn_guerrila";
}else{
	_base = "respawn_" + (str _side);
};
_basePos = getMarkerPos _base;
}else{
if((typeName _setBase) == "ARRAY")then{
	if((_setBase select 0) in allMapMarkers)then{
		_base = _setBase call BIS_fnc_selectRandom;
		_basePos = getMarkerPos _base;
	}else{
		_basePos = _setBase;
	};
}else{
	_basePos = getMarkerPos _setBase;
};
};
_air = _group getVariable "air";
_azi = _group getVariable "azi";
_grp = [_basePos, _side, _array,nil,nil,nil,nil,nil,_azi,_air] call AIRS_fnc_spawnGroup;

_tempGrp = [];
{ _tempGrp set[(count _tempGrp),_x] }forEach units _grp;

_tempGrp joinSilent _group;
deleteGroup _grp;

_lifes = _group getVariable "lifes";
if(_lifes > 0)then{
if(_lifes > 1)then{
	_lifes = _lifes - 1;
	_group setVariable ["lifes", _lifes];
}else{
	_group setVariable ["classnames", nil];
	_group setVariable ["lifes", nil];
	_group setVariable ["task", nil];
	_group setVariable ["base", nil];
	_group setVariable ["state", nil];
	_group setVariable ["delay", nil];
	_group setVariable ["air", nil];
	_group setVariable ["azi", nil];
};
};
_group setVariable ["state", "alive"];
_task = _group getVariable "task";
if(!isNil("_task"))then{ [_group] call AIRS_StartTask; };

and "BIS_fnc_spawnGroup2.sqf":

/*
File: BIS_fnc_spawnGroup2.sqf (original: spawnGroup.sqf)
Author: Joris-Jan van 't Land, modified by Thomas Ryan (MODIFIED by SPUn [vehicle positioning check, air option])

Description:
Function which handles the spawning of a dynamic group of characters.
The composition of the group can be passed to the function.
Alternatively a number can be passed and the function will spawn that
amount of characters with a random type.

Parameter(s):
_this select 0: the group's starting position (Array)
_this select 1: the group's side (Side)
_this select 2: can be three different types:
	- list of character types (Array)
	- amount of characters (Number)
	- CfgGroups entry (Config)
_this select 3: (optional) list of relative positions (Array)
_this select 4: (optional) list of ranks (Array)
_this select 5: (optional) skill range (Array)
_this select 6: (optional) ammunition count range (Array)
_this select 7: (optional) randomization controls (Array)
	0: amount of mandatory units (Number)
	1: spawn chance for the remaining units (Number)
_this select 8: (optional) azimuth (Number)
_this select 9: (optional) if groups vehicles spawns flying (Boolean) DEFAULT: false

Returns:
The group (Group)
*/

//Validate parameter count
if ((count _this) < 3) exitWith {debugLog "Log: [spawnGroup] Function requires at leat 3 parameters!"; grpNull};

private ["_pos", "_side"];
_pos = [_this, 0, [], [[]]] call BIS_fnc_param;
_side = [_this, 1, sideUnknown, [sideUnknown]] call BIS_fnc_param;

private ["_chars", "_charsType", "_types"];
_chars = [_this, 2, [], [[], 0, configFile]] call BIS_fnc_param;
_charsType = typeName _chars;
if (_charsType == (typeName [])) then
{
_types = _chars;
}
else
{
if (_charsType == (typeName 0)) then 
{
	//Only a count was given, so ask this function for a good composition.
	_types = [_side, _chars] call BIS_fnc_returnGroupComposition;
} 
else 
{
	if (_charsType == (typeName configFile)) then 
	{
		_types = [];
	};
};
};

private ["_positions", "_ranks", "_skillRange", "_ammoRange", "_randomControls","_air"];
_positions = [_this, 3, [], [[]]] call BIS_fnc_param;
_ranks = [_this, 4, [], [[]]] call BIS_fnc_param;
_skillRange = [_this, 5, [], [[]]] call BIS_fnc_param;
_ammoRange = [_this, 6, [], [[]]] call BIS_fnc_param;
_randomControls = [_this, 7, [-1, 1], [[]]] call BIS_fnc_param;
_air = [_this, 9, false, [[]]] call BIS_fnc_param;

//Fetch the random controls.
private ["_minUnits", "_chance"];
_minUnits = _randomControls select 0;
_chance = _randomControls select 1;

private ["_azimuth"];
_azimuth = [_this, 8, 0, [0]] call BIS_fnc_param;

//Check parameter validity.
//TODO: Check for valid skill and ammo ranges?
if ((typeName _pos) != (typeName [])) exitWith {debugLog "Log: [spawnGroup] Position (0) should be an Array!"; grpNull};
if ((count _pos) < 2) exitWith {debugLog "Log: [spawnGroup] Position (0) should contain at least 2 elements!"; grpNull};
if ((typeName _side) != (typeName sideEnemy)) exitWith {debugLog "Log: [spawnGroup] Side (1) should be of type Side!"; grpNull};
if ((typeName _positions) != (typeName [])) exitWith {debugLog "Log: [spawnGroup] List of relative positions (3) should be an Array!"; grpNull};
if ((typeName _ranks) != (typeName [])) exitWith {debugLog "Log: [spawnGroup] List of ranks (4) should be an Array!"; grpNull};
if ((typeName _skillRange) != (typeName [])) exitWith {debugLog "Log: [spawnGroup] Skill range (5) should be an Array!"; grpNull};
if ((typeName _ammoRange) != (typeName [])) exitWith {debugLog "Log: [spawnGroup] Ammo range (6) should be an Array!"; grpNull};
if ((typeName _randomControls) != (typeName [])) exitWith {debugLog "Log: [spawnGroup] Random controls (7) should be an Array!"; grpNull};
if ((typeName _minUnits) != (typeName 0)) exitWith {debugLog "Log: [spawnGroup] Mandatory units (7 select 0) should be a Number!"; grpNull};
if ((typeName _chance) != (typeName 0)) exitWith {debugLog "Log: [spawnGroup] Spawn chance (7 select 1) should be a Number!"; grpNull};
if ((typeName _azimuth) != (typeName 0)) exitWith {debugLog "Log: [spawnGroup] Azimuth (8) should be a Number!"; grpNull};
if ((_minUnits != -1) && (_minUnits < 1)) exitWith {debugLog "Log: [spawnGroup] Mandatory units (7 select 0) should be at least 1!"; grpNull};
if ((_chance < 0) || (_chance > 1)) exitWith {debugLog "Log: [spawnGroup] Spawn chance (7 select 1) should be between 0 and 1!"; grpNull};
if (((count _positions) > 0) && ((count _types) != (count _positions))) exitWith {debugLog "Log: [spawnGroup] List of positions (3) should contain an equal amount of elements to the list of types (2)!"; grpNull};
if (((count _ranks) > 0) && ((count _types) != (count _ranks))) exitWith {debugLog "Log: [spawnGroup] List of ranks (4) should contain an equal amount of elements to the list of types (2)!"; grpNull};

//Convert a CfgGroups entry to types, positions and ranks.
if (_charsType == (typeName configFile)) then 
{
_ranks = [];
_positions = [];

for "_i" from 0 to ((count _chars) - 1) do 
{
	private ["_item"];
	_item = _chars select _i;

	if (isClass _item) then 
	{
		_types = _types + [getText(_item >> "vehicle")];
		_ranks = _ranks + [getText(_item >> "rank")];
		_positions = _positions + [getArray(_item >> "position")];
	};
};
};

private ["_grp"];
_grp = createGroup _side;

//Create the units according to the selected types.
for "_i" from 0 to ((count _types) - 1) do
{
//See if this unit should be skipped.
private ["_skip"];
_skip = false;
if (_minUnits != -1) then 
{
	//Has the mandatory minimum been reached?
	if (_i > (_minUnits - 1)) then 
	{
		//Has the spawn chance been satisfied?
		if ((random 1) > _chance) then {_skip = true};
	};
};

if (!_skip) then 
{
	private ["_unit", "_type"];
	_type = _types select _i;

	//If given, use relative position.
	private ["_itemPos"];
	if ((count _positions) > 0) then 
	{
		private ["_relPos"];
		_relPos = _positions select _i;
		_itemPos = [(_pos select 0) + (_relPos select 0), (_pos select 1) + (_relPos select 1)];
	} 
	else 
	{
		_itemPos = _pos;
	};

	//Is this a character or vehicle?	
	if (getNumber(configFile >> "CfgVehicles" >> _type >> "isMan") == 1) then 
	{	
		_unit = _grp createUnit [_type, _itemPos, [], 0, "FORM"];
		_unit setDir _azimuth;
	} 
	else 
	{
		//Find empty place for vehicle to spawn (if not spawning at air)
		private["_tempPos"];
		if(_air)then{
			_tempPos = _itemPos;
		}else{
			private["_isFlat","_eRange","_sim","_water","_asize"];
			_sim = getText(configFile >> "CfgVehicles" >> _type >> "simulation");
			if(_sim == "shipx")then{_water = 2}else{_water = 0};
			if(_sim == "airplanex")then{_asize = 12}else{_asize = 6};
			_isFlat = []; 	
			_eRange = 10; 
			while{count _isFlat == 0}do{
				_tempPos = [(_itemPos select 0) + (sin (random 360)) * _eRange, (_itemPos select 1) + (cos (random 360)) * _eRange, 0];
				_isFlat = _tempPos isflatempty [_asize,0,1,2,_water,false];
				_eRange = _eRange + 2;
			};
		};
		_unit = ([_tempPos, _azimuth, _type, _grp, _air] call AIRS_fnc_spawnVehicle) select 0;
		//_unit = ([_tempPos, _azimuth, _type, _grp] call BIS_fnc_spawnVehicle) select 0;
	};

	//If given, set the unit's rank.
	if ((count _ranks) > 0) then 
	{
		[_unit,_ranks select _i] call bis_fnc_setRank;
	};

	//If a range was given, set a random skill.
	if ((count _skillRange) > 0) then 
	{
		private ["_minSkill", "_maxSkill", "_diff"];
		_minSkill = _skillRange select 0;
		_maxSkill = _skillRange select 1;
		_diff = _maxSkill - _minSkill;

		_unit setUnitAbility (_minSkill + (random _diff));	
	};

	//If a range was given, set a random ammo count.
	if ((count _ammoRange) > 0) then 
	{
		private ["_minAmmo", "_maxAmmo", "_diff"];
		_minAmmo = _ammoRange select 0;
		_maxAmmo = _ammoRange select 1;
		_diff = _maxAmmo - _minAmmo;

		_unit setVehicleAmmo (_minAmmo + (random _diff));	
	};
};
};


//--- Sort group members by ranks (the same as 2D editor does it)
private ["_newGrp"];
_newGrp = createGroup _side;
while {count units _grp > 0} do {
private ["_maxRank","_unit"];
_maxRank = -1;
_unit = objnull;
{
	_rank = rankid _x;
	if (_rank > _maxRank) then {_maxRank = _rank; _unit = _x;};
} foreach units _grp;
[_unit] joinsilent _newGrp;
};
_newGrp selectleader (units _newGrp select 0);
deletegroup _grp;

_newGrp

Share this post


Link to post
Share on other sites

Finally got back home to be able to try and answer this, below is an alteration of the spawnGroup.sqf (new stuff highlighted):

//spawnGroup  1.0 by SPUn
if(!isServer)exitWith{};
private ["_array","_faction","_group","_side","_base","_grp","_tempGrp","_lifes","_setBase","_task","_delay","_air","_azi","_basePos"];

_array = _this select 0;
_faction = _this select 1;
_group = _this select 2;

_group setVariable ["state", "spawning"];

_delay = _group getVariable "delay";
sleep _delay;

switch(_faction)do{
case "BLU_F":{
	_side = west;
};
case "BLU_G_F":{
	_side = west;
};
case "OPF_F":{
	_side = east;
};
default {
	_side = resistance;
};
};
if((_side == west)&&(!AIRS_respawn_WEST))exitWith{};
if((_side == east)&&(!AIRS_respawn_EAST))exitWith{};
if((_side == resistance)&&(!AIRS_respawn_INDE))exitWith{};

_setBase = _group getVariable "base";
if(isNil("_setBase"))then{
//////////////////New below/////////////////
_base = ["respawn1","respawn2","respawn3"] call BIS_fnc_selectRandom; //fill this with the necessary marker names
_basePos = getMarkerPos _base;
////////////////////////////////////////////////
}else{
if((typeName _setBase) == "ARRAY")then{
	if((_setBase select 0) in allMapMarkers)then{
		_base = _setBase call BIS_fnc_selectRandom;
		_basePos = getMarkerPos _base;
	}else{
		_basePos = _setBase;
	};
}else{
	_basePos = getMarkerPos _setBase;
};
};
_air = _group getVariable "air";
_azi = _group getVariable "azi";
_grp = [_basePos, _side, _array,nil,nil,nil,nil,nil,_azi,_air] call AIRS_fnc_spawnGroup;

_tempGrp = [];
{ _tempGrp set[(count _tempGrp),_x] }forEach units _grp;

_tempGrp joinSilent _group;
deleteGroup _grp;

_lifes = _group getVariable "lifes";
if(_lifes > 0)then{
if(_lifes > 1)then{
	_lifes = _lifes - 1;
	_group setVariable ["lifes", _lifes];
}else{
	_group setVariable ["classnames", nil];
	_group setVariable ["lifes", nil];
	_group setVariable ["task", nil];
	_group setVariable ["base", nil];
	_group setVariable ["state", nil];
	_group setVariable ["delay", nil];
	_group setVariable ["air", nil];
	_group setVariable ["azi", nil];
};
};
_group setVariable ["state", "alive"];
_task = _group getVariable "task";
if(!isNil("_task"))then{ [_group] call AIRS_StartTask; };

---------- Post added at 03:20 ---------- Previous post was at 03:16 ----------

Actually I may also need the addAIgroupToPool.sqf for this to come together better. It's kind of hard to alter a big system of functions mainly because everything connects with all the other functions and such, so you make a change in one place, you have to change it in five other places.

Share this post


Link to post
Share on other sites

I'm not sure about the AIRS mod, but in vanilla, any marker you place that is prefixed with "respawn_side" is a valid respawn point for that side.

respawn_west1

respawn_west_1

respawn_west_1498asj

respawn_west2jasaslkj

respawn_westDREADEDENTITY

Are all valid respawn points for west units.

description.ext

Share this post


Link to post
Share on other sites
I'm not sure about the AIRS mod, but in vanilla, any marker you place that is prefixed with "respawn_side" is a valid respawn point for that side.

respawn_west1

respawn_west_1

respawn_west_1498asj

respawn_west2jasaslkj

respawn_westDREADEDENTITY

Are all valid respawn points for west units.

description.ext

Thanks a lot you all.

@DreadEntity, thanks but I have already tried this approach. I kill the AI and just watch the respawn locations. No1 pops up. I tried this after saving as a MP mission. Anyway, I basically need the AI, both enemy and my side, respawn when killed and proceed to marker for attack/defend/SAD etc and get in nearest vehicle when possible to reach there and disembark 200-300 distance away.

@ JShock I cant thank you enough for taking the trouble to reply after getting back from wherever you were :D

I know I am not asking for the world. You guys have been there and done that. ;)

I believe DAC serves the purpose but I need to ask you guys that does it come with an infinite respawn option?

P.S.: Again I am reinstating, if you have a better and simpler way to help me, please share. I am not hell bent on DAC. All I want is a perpetual wasteland like mission where no groups only individual units from all 3 sides move acros islands in search of new target. Simple guys. :'( I am not a MP fan, hence this I intend in SP mode. I can play in MP as the only player and rest AI.

THanks again for being patient.

Share this post


Link to post
Share on other sites

DAC will do this - it's not infinite respawns but you can set the # of respawns to say 999... it's really designed to spawn groups not individual soldiers (although it can do both). You can specify multiple respawn 'camps' and even tailor the loadouts of spawned units.

If you've never used DAC before it's a steep learning curve.. but it's the most powerful AI spawning script/mod out there IMHO.

Share this post


Link to post
Share on other sites
DAC will do this - it's not infinite respawns but you can set the # of respawns to say 999... it's really designed to spawn groups not individual soldiers (although it can do both). You can specify multiple respawn 'camps' and even tailor the loadouts of spawned units.

If you've never used DAC before it's a steep learning curve.. but it's the most powerful AI spawning script/mod out there IMHO.

Thank you SavageCDN, I find DAC interesting and its ok I like the way it scripts :)

You have any idea to make DAC spawn individual units too? I used the infantry array like this [8,1,20,8]. Technically meaning 8 = Number of Groups, 1 = size of the groups, 20 = no. of WPs, and 8 = no. of WPs to each group. I guesss it is supposed to mean spawn 8 groups with 1 member in each. Still it spawns groups with 4-5 members. What gives?

And also, how to make Respawn points invincible so that there is persistency in reinforcements?

Thank you.:D

Share this post


Link to post
Share on other sites
Thank you SavageCDN, I find DAC interesting and its ok I like the way it scripts :)

You have any idea to make DAC spawn individual units too? I used the infantry array like this [8,1,20,8]. Technically meaning 8 = Number of Groups, 1 = size of the groups, 20 = no. of WPs, and 8 = no. of WPs to each group. I guesss it is supposed to mean spawn 8 groups with 1 member in each. Still it spawns groups with 4-5 members. What gives?

And also, how to make Respawn points invincible so that there is persistency in reinforcements?

Thank you.:D

The #1 in your example [8,1,20,8] does not mean spawn 8 groups with one unit each, it means spawn 8 groups with a group size of 1. If you check the DAC_Config_Creator.sqf file (oh you should use the script version of DAC if you are learning how to use it.. much easier to customize than the mod version). Look for this value:

DAC_AI_Count_Level  = [[b][2,4][/b],[3,6],[4,8],[6,12],[1,0]]

The first set of values (min, max) are for group size 1 - it will create a group with between 2 and 4 units.

So group size one would be 2-4 units, size 2 would be 3-6 units, and so on. To create single unit groups change the 2,4 values to 1,1.

With regards to respawn being invincible your best bet is to use the NULL camp value (I believe it is case 2 in DAC_Config_Camps.sqf). This spawns a respawn camp with no objects or units, just an invisible point where units will 'appear' when respawned.

Share this post


Link to post
Share on other sites
The #1 in your example [8,1,20,8] does not mean spawn 8 groups with one unit each, it means spawn 8 groups with a group size of 1. If you check the DAC_Config_Creator.sqf file (oh you should use the script version of DAC if you are learning how to use it.. much easier to customize than the mod version). Look for this value:

DAC_AI_Count_Level  = [[b][2,4][/b],[3,6],[4,8],[6,12],[1,0]]

The first set of values (min, max) are for group size 1 - it will create a group with between 2 and 4 units.

So group size one would be 2-4 units, size 2 would be 3-6 units, and so on. To create single unit groups change the 2,4 values to 1,1.

With regards to respawn being invincible your best bet is to use the NULL camp value (I believe it is case 2 in DAC_Config_Camps.sqf). This spawns a respawn camp with no objects or units, just an invisible point where units will 'appear' when respawned.

Love you man. Will try tonight. :D

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  

×