Jump to content
scajolly

Players as insurgents blending in with civpop

Recommended Posts

Hi.

I am making a coop mission where 30+ players are acting as civpop that have decided to become rebels. I am looking for simple ways to make the occupation AI act as if it's never sure of whether a player is legit civilian or whether it's something one should engage. So I'm thinking a lot of different conditions that cycle the BLUFOR player through setCaptive true and false. Does anyone have good ideas, or know of others who've tried? I tried a fair bit of searching, but my wording didn't return any good results.

 

Here are some ways I'm going to try to go about it. Help is much appreciated.

 

1) Crowds can be treated as hostile. In real life some occupation forces disband the freedom of assembly and impose crowd limitations during curfew etc. I'm thinking of each player running a script that checks how close they are to others. If the script finds 3+ players (or AI civs) within a radius of X meters, they get flipped to setCaptive false. If there's civpop AI, those could conceivably be grouped silently with Resistance. For even more complexity, the script could avoid counting players/AI inside buildings. >>> How would I check whether players are inside buildings?

 

2) Anyone armed is hostile. The script checks for whether they are openly carrying a rifle/pistol, or are carrying a launcher of any kind. >>> How would I script the difference between a pistol in a backpack not being seen, as opposed to a holstered/backslung rifle being seen?

 

3) Anyone who ends up setCaptive false must then be un-detected by OPFOR before they can be flipped back to civilian. Not sure how to go about this. >>> Should I maybe check whether any units belonging to side==east have a knowsabout higher than 1 or 2?

 

4) Anyone running or sprinting while AI is within a certain radius. >>> Are there any isRunning commands that I could check?

 

 

Share this post


Link to post
Share on other sites

1) this is basically modified from a KillZone Kid script https://github.com/AZCoder/AZC-LIB/blob/master/utility/fn_InsideBuilding.sqf

I use it to turn snowfall off and on, seems to work pretty well at inside detection.

 

2) not sure how best to approach, but you could start with a list of weapons "weapons player" and commands like https://community.bistudio.com/wiki/backpackItems to see where each weapon is located

 

3) I tried doing this in the past and it was unreliable. Hopefully someone will have a better answer.

 

4) "speed player > 5"  or whatever number works

Share this post


Link to post
Share on other sites

I did this once, it's kind of half-assed and it kind of worked, it's definetly not perfect, I used INDE as enemies because their allegiance can be switched midgame.
So make Independants friendly to Bluefor then execute this code on every player's machine:

undercover = true;
publicVariable "undercover";
weapinhand = false;
detected = false;
indeguys = [];
knowsaboutplayer = [];
seesplayer = [];
{if ((side _x) == resistance) then {indeguys = indeguys + [_x]}} forEach allUnits;
sleep 1;

/////////detecte si le joueur a une arme en main et définit la variable weapinhand true ou false
[] spawn {
while {undercover} do {
{
weaponequipped = currentWeapon _x;
if (weaponequipped == "") then { _x setVariable ["weapinhand", false];} else { _x setVariable ["weapinhand", true];};

} forEach allplayers;
sleep 0.5;
};
};

sleep 1;
///////////verifie si le joueur est detecté
while {undercover} do {
{dist = _x distance player; if (dist < 10) then {seesplayer = seesplayer + [_x]} else {seesplayer = seesplayer - [_x]}  } forEach indeguys;
sleep 0.5;


{seen = _x knowsabout player; if (seen > 0.3) then {knowsaboutplayer = knowsaboutplayer + [_x]} else {knowsaboutplayer = knowsaboutplayer - [_x]}  } forEach seesplayer;
sleep 0.5;

weapinhand = player getVariable "weapinhand";
sleep 0.5;

{if (weapinhand) then {


detected = true;
publicVariable "detected";
} } forEach knowsaboutplayer;
sleep 0.05;
};

when the variable "detected" is set, execute the following code either through a mission eventhandler or a trigger:

west setFriend [independent, 0]; independent setFriend [west, 0];

As I said, this is fffffffffffaaaar from perfect but it worked in my mission in MP, it just detect players if they have a weapon in their hands, weapons mus be concealed in their uniforms.
This is just a pointer you will have to improve i greatly
 

  • Like 1

Share this post


Link to post
Share on other sites

Good luck, if you achieve what your looking for please post. I think there are many people that like that kind of script because it would add a cool concept to the game. Honestly Im not sure how open source it is, And obviously the code style is different but I would wonder what the specific parameters are for gran theft auto for the stars accumulation. They seem to have had the detection of good vs bad guy down pretty well. I tried this as well once but to achieve what I wanted became a seemingly endless nested if statements. Mostly I never cared for how the AI can tell a blufor is in a car in civ cloths(or any cloths for that matter) from 1000km away and start firing at you. I attempted a checkpoint mission once but you could never get to the checkpoint because they would pick you out form 600m away. No i didn't add anything im just moral support :)

Share this post


Link to post
Share on other sites

Thanks for the help and support, guys!

I'll try to keep this script clean and small. I plan on just a few hostility conditions. There are a few 'stretch goals', such as violence escalation by AI (warnings, warning shots), but that's not super likely to happen. I'm already operating at the very limits of what little coding I know. So if anyone knows how to put this SQS-style syntax into something sleeker, you just go right ahead and let me know. OR change the script yourselves -- my parts are all open source.

 

@Mr H., your solution would have meant that the entirety of side A becomes hostile against side B, and with a coop server running ~40-80 people I wanted to make people individually responsible instead.

 @AZCoder that script, with some changes, works wonders for what I want to achieve. :)

A small picture of what the testing stage looks like. That's where I check for crowds, for whether player is armed, whether is sprinting, whether enemy has LOS, and whether player is inside (house or vehicle).

 

It's not yet working quite right. The private declarations are currently thrown haphazardly around (I have no idea whether the while-loops should have them private or not). I've not yet tested for MP, and am not sure if player setCaptive false has to be sent to the server. Somehow? Maybe? The big issue right now is that I don't really know how to make the hostile while-loop re-start the captive while-loop when it has terminated. But that should be easy, surely? If anyone can lend a hand with this script I'd be real chuffed.

 

Other hostility conditions I'm keen on implementing might be whether player is breaking curfew at night and whether cloaked (balaclava or similar). 

    

/*
	* SCA's curfew script -- WIP
	* Initialise through init.sqf for players or individually in init line.
	*
	* This script changes the player from captive to not captive. It tries to take suspicious behaviour in hostility conditions and checks whether any AI belonging to the enemy side has seen that behaviour. If so, it subjects the player to setCaptive false for a certain amount of time. This script will in principle never change AI behaviour.
	*
	* The script is meant to work clientside in cooperative MP scenarios.
	*
	* If using ACRE, remember to configure babel so it won't treat different sides (setCaptive true and false) as different languages.
*/

// You're not you when you're not loaded. Grab a snickers.
waitUntil {player == player};
sleep 2;

// Run script on respawn.
player addEventHandler["Respawn",{execVM "scripts\curfew.sqf";}];

// Function to determine whether there is a roof or similar over player's head. Freedom of assembly is only checked outdoors. Based on AZCoder and Killzone Kid
// input: object
// output: bool
AZC_fnc_InsideBuilding = {
	params ["_object"];
	private ["_inside","_worldPos","_skyPos","_line"];
	_inside = false;
	_worldPos = getPosWorld _object;
	_skyPos = getPosWorld _object vectorAdd [0, 0, 50];
	_line = lineIntersectsSurfaces [_worldPos,_skyPos,_object,objNull,true,1,"GEOM","NONE"];
	if (count _line > 0) then
	{
		_result = _line select 0;
		_house = _result select 3;
		if (!(isNil "_house")) then { _inside = true };
	};
	_inside
};

// Function to check whether there is a clear line of sight between the player and anyone who could observe him.
// Input: object and object
// Output: bool
SCA_fnc_LineOfSight = {
	params ["_target","_observer"]; // this nomenclature is a bit misleading. The line originates with the target.
	private ["_intersects","_targetPos","_observerPos","_line"];
	_intersects = false;
	_targetPos = getposWorld _target;
	_observerPos = getposWorld _observer;
	_line = lineIntersects [_targetPos,_observerPos,_target,_observer]; //should it be other way around?
	if (_line) then 
	{
		_intersects = true;
	};
	_intersects
};

private ["_isArmed","_isCrowded","_isRunning","_pSide","_enSideAr","_runSpeed","_runRadius","_crowdSize","_crowdRadius"];
_isArmed = false;
_isCrowded = false;
_isRunning = false;
_pSide = side player;
_enSideAr = [_pSide] call BIS_fnc_enemySides;
_runSpeed = 15; // Jogging happens at about 14.5kmh, sprinting is a bit faster.
_runRadius = 15; // To taste.
_crowdSize = 5;
_crowdRadius = 20;
_detectRadius = 250; // day-time, clear weather. No other options for now.
player setCaptive true;

// This while-loop runs when the player meets the captive conditions.
while {alive player && captive player} do {
	private ["_nearSoldierAr","_nearFriendsAr","_isInside"];
	hint "check"; // Debug.
	sleep 1.5;
	// Creates array of enemy units within a certain distance.
	_nearSoldierAr = allUnits select {_x distance player < _runRadius && side _x in _enSideAr};
	// Creates an array of friendly units within a certain distance. Change to allPlayers if you don't want same-side AI to trip any hostility condition.
	_nearFriendsAr = allUnits select {_x distance player < _crowdRadius && side _x == _pSide};
	// Calls a function that checks whether the player has a roof over its head, output bool.
	_isInside = [player] call AZC_fnc_InsideBuilding;
	// Sets an eventhandler that checks for firing a gun.
	
	
	if (
		//(primaryWeapon player != "" || currentWeapon player == primaryWeapon player) // Detects rifles. Ideally checks an isKindOf instead. Also detects binoculars now and then. Not consistent. Good or bad? Takes care of dickers tbh. Sometimes detects something when there's nothing. TODO.
		//|| 
		(handgunWeapon player != "" && currentWeapon player == handgunWeapon player) // This detects handguns. Since they can easily be hidden, the condition checks the player both HAS and WIELDS a handgun.
		|| 
		secondaryWeapon player != "" // This detects launchers, whether carried on back or being used.
		||
		(speed player > _runSpeed && count _nearSoldierAr >= 1 && vehicle player == player) // Checks player is running (sprinting => 15), and whether has soldier nearby, and whether his vehicle is himself and not a car etc.
		||
		(count _nearFriendsAr >= _crowdSize && vehicle player == player && !(_isInside)) // Checks whether player is in a crowd. He is allowed to be if he is inside a vehicle or a house.
		) then {
			player setCaptive false;
			hint "now dangerous!"; // Debug.
			sleep 1;
		} else {
			player setCaptive true;
			hint "Player still captive"; // Debug.
			sleep 1;
		};
};

// This while-loop runs when the player has met a hostility condition.
while {alive player && !(captive player)} do {
	hint "In the danger scope"; // Debug hint
	sleep 1.5;
	
	// Find enemy soldiers within a certain radius of the player, then test them for LOS or knowsAbout. 
	// TODO find out whether knowsAbout decreases too slowly and we should rely purely on LOS.
	_farSoldierAr = allUnits select {_x distance player < _detectRadius && side _x in _enSideAr};
	
	if (
		((_farSoldierAr findIf {[player, _x] call SCA_fnc_LineOfSight}) == -1) 
		|| 
		((_farSoldierAr findIf {_x knowsAbout player > 1.5}) == -1)
	
	) then {
		// The enemy may have LOS to or knowledge about the player's hostility.
		sleep 10; // Debug sleep. Up to 60 or 120 later.
		hint "checking again"; // Debug hint.
		sleep 1; // Debug sleep.
	
	} else {
		// The enemy has neither LOS to nor knowledge about the player.
		player setCaptive true;
		hint "player now captive again"; // Debug hint.
		sleep 2; // Debug sleep.
	}
	
	
};
	

 

Share this post


Link to post
Share on other sites
19 hours ago, Harzach said:

Not to put you off of developing your own solution, but have you looked at @Incontinentia's Undercover?

Had not seen that! That's a formidable script there. Probably very suitable to my needs, too. But I'll continue making this since it's got far fewer parameters, making it less opaque for me and my friends, and is oriented towards martial law/curfew-type rules. Thanks a lot!

  • Like 1

Share this post


Link to post
Share on other sites

You may want to make an FSM for this. Could work better than an SQF script. 

Share this post


Link to post
Share on other sites
On 4.6.2018 at 1:47 AM, Crielaard said:

You may want to make an FSM for this. Could work better than an SQF script. 

Thanks for the input. I've zero experience with FSM though. :) So I doubt I'll venture there.

Share this post


Link to post
Share on other sites

Its no rocket science. If you are decent at scripting. Like you. You'll like it. 

 

Especially specifically with your script here. 

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

×