Jump to content
dreadpirate

Reverse Engineering EOS

Recommended Posts

So, I think most mission makers and scripters have played around with @bangabob's excellent Enemy Occupation System (EOS) at some point:

 

https://forums.bohemia.net/forums/topic/144150-enemy-occupation-system-eos/

 

Basically you place a bunch of enemy zone markers, run the script which generates a trigger for each zone and when players enter the trigger, enemies are spawned.

When players leave the trigger, the enemies are deleted.

If players clear a zone of enemies, it turns green and no further enemies will spawn there.

(There is more to it than that, but that's the basics.....)

 

So, I made a script to auto-generate 100 x 100m markers for map grids with enterable buildings in them.

On Altis, this creates 3898 markers! (I'm blacklisting some buildings)

 

I'll blacklist friendly occupied areas and bases, but with EOS, I'll still wind up with over 3000 triggers, checking every 0.5 seconds.

 

So, my idea is: Instead of having triggers attached to zones checking for players, how about having a script running on players checking for nearby zones?

 

I modified my script to create Locations for each zone.

 

Now I can use:

https://community.bistudio.com/wiki/nearestLocations

to check if players are near zones and activate them accordingly.

 

Before I go much further down this rabbit hole, can you veteran scripters tell me: am I wasting my time here?

Will trading triggers for locations actually save any processing time?

What are some pitfalls I'll need to look out for in terms of multiplayer and locality?

 

  • Like 3

Share this post


Link to post
Share on other sites

I'd say that you can see server side performance improvements with this. Now I don't know how performance heavy nearestLocations is, but I guess you've already tested it so client side performance impact is negligible.

 

Activating:
Now the client activating part should be quite straightforward, when a client computer deems it's close enough to the zone it sends the information to server and other clients that this zone is activated. To the server so it knows to activate the zone and to other clients that they don't spam the same message through the network.
 

For server side activation easiest bulletproof method to know server side which sites are active and which are not is for the server to go through the array of all sites 3000 and check for true cases. This is maybe not the best method, but I'd say going through 3000 booleans is faster than the 3000 triggers.
Other way I can think of is creating a personal variable regarding each client in the server and the client sends the information of zone activation to the server using that server-client variable.
In other words one loop going through all the sites VS player amount of loops looking what they send.

 

It might be also possible to put the server-client variables to an array and just have one loop going through that, but removal and creation of new server-client variables while going through the array might break it.

So as it seems messages done with remoteExecCall are executed sequentially, so there will be no need to keep checking server side if anything has been updated, just check in the server side script if the zone has already been activated in the case of two or more clients arriving to the same zone at the same time.
With the addPublicVariableEventHandler it might also be possible to make the 3000 booleans without looping.

There might be some extra client side coding work regarding UAVs and drones depending how you want them to impact the sites, but you can also make it so that clients flying high or going fast enough don't trigger zones saving server performance.

Deactivating:

For this part creating a server side trigger checking for any clients in the designated zone is the easiest solution. When the conditions are met the server just deletes the trigger, deactivates the zone and sends the information to the clients.

Triggers:
Now the deactivating trigger can just be code you create yourself using spawn command as the 0.5 second trigger happens needlessly often. Server side zone deactivation check will work just fine with a 30 second sleep, and activation check with 3 second sleep for both client and server.

Edited by kauppapekka
Some activating thoughts and reading on remoteExecution and event handlers.

Share this post


Link to post
Share on other sites

You brave soul.  Eos is in need of desperate updating.

 

If you get something going I am sure the community would love to see it.  Eos was a great thing.  Now not so.

  • Like 1

Share this post


Link to post
Share on other sites

So, I finally got around to working on this and I have it working in SP.

 

zoneMonitor = {
	while {alive player} do {
		sleep 1;
		
		_nearbyZones = nearestLocations[position player, ["Strategic"], 400];
		{
			_status = _x getVariable "Status";
			if (_status != "Active") then {
				hint "Activate"; 
				[_x] remoteExec ["zoneActivate", 2];
			};
		}forEach _nearbyZones;
	};
};

player spawn zoneMonitor;

(this runs in initPlayerLocal.sqf)

 

zoneActivate = {
	params ["_zone"];
	
	_zone setVariable ["Status", "Active"];
	_marker = _zone getVariable "Marker";
	_marker setMarkerAlpha 1;
	
	_unit = (createGroup east) createUnit ["O_Soldier_F", getPos _zone, [], 10, "NONE"];
	
	while {[getPos _zone, 400] call jebus_fnc_playerInRadius} do {
		if ([getPos _zone, 50] call jebus_fnc_playerInRadius && !alive _unit) exitWith {
			deleteLocation _zone;
			_marker setMarkerAlpha 0.5;
			_marker setMarkerColor "ColorGreen";
		};
		
		sleep 1;
	};
	
	if (!isNull _zone) then {
		_zone setVariable ["Status", "Waiting"];
		_marker setMarkerAlpha 0.5;
		deleteVehicle _unit;
	};
};

(this runs in initServer.sqf)

 

As I say, this works perfectly in SP, but in MP the zones deactivate straight after they activate. The test unit is spawning, but being deleted straight away even when the player is within 400m. I can't quite see why it's skipping the "while" loop in "zoneActivate"

 

Here's jebus_fnc_playerInRadius if it helps:

// Detects if player is within a given radius
// [<position>, <radius>] call jebus_fnc_playerInRadius

params [
	"_position"
	,"_radius"
];

private ["_returnValue"];

_returnValue = false;

//Singleplayer test
if ((player distance2D _position) < _radius) then {
	_returnValue = true;
};

// Multiplayer test
{
	if ((_x distance2D _position) < _radius) exitWith { _returnValue = true; };
} forEach playableUnits;

_returnValue;

 

Share this post


Link to post
Share on other sites

Hey @dreadpirate,

 

I recently had similar concerns, and I ended up thinking that it would be easier to redesign a brand new occupation system from scratch. So that's what I did. You can find a very basic version of it right here : https://github.com/team-gsri/GOS (GOS standing for GSRI Occupation System, not related to the team named GOS).

 

Frankly, it's not as polished as I want it to be. Ultimately I will probably ship it as a mod, mainly for my team's needs, but for now I lack time to work on it. I don't forget it though, I really plan to perfect it at some point. For now, feel free to take inspiration from it, fork it, or eventually open a pull-request following the generic Contributing guidelines of our organization.

 

Have fun !

  • Thanks 3

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

×