Jump to content
celludriel

Capture building script

Recommended Posts

https://github.com/Celludriel/dyncap/releases/tag/1.1.0

 

I present DynCap 1.1.0 a script library for creating capturable objects (preferably buildings) by just giving it a location.

 

How it works:

 

The script will spawn a building or object you specifiy on the location you pass along to the script.  fe:

cap = [(getMarkerPos "spawn_position_1"),5,"Land_Cargo_Patrol_V1_F", 60, east] call compileFinal preprocessFileLineNumbers "dyncap\createCaptureLocation.sqf";

The script will return a handle to the capturable object so you can use it in any mission logic you require.  On server side a thread will spawn on a loop while the object is alive to see if there is anyone near to capture the point.  On client side another thread is spawned to track if you as a player are near.  If you are and you are eligable for capturing it a progressbar will appear for the duration of the capture.  The code is open and free to be forked on: https://github.com/Celludriel/dyncap

 

I did some basic testing on my own

 

- Captured the building then switched sides and captured it back

- Sent my AI squadmate to the building and let him capture it

 

What still could be tested is, move to the building with one bluefor and then move in two opfor without killing eachother and see if the opfor get the upper hand and they will either stop the capture or start the capture if the building is in blufor hands.  But I'm only one man so I couldn't test this.

Share this post


Link to post
Share on other sites

Heres a very simple example that may help you out, only checks for units on foot and does not check for draws. Area stays colour of last capturing side.

 

//[ position, radius, default owner, [ building class, dir ], sides ] call fnc_mission;

//POSITION and RADIUS or capture area
//( optional ) DEFAULT OWNER - side that initialy ownes the area - defaults to SIDEUNKNOWN
//( optional ) [ BUILDING, DIR ] - a building class to spawn at areas centre and a direction for it to face
//( optional )  SIDES - an ARRAY of sides that can capture the area - defaults to [ east, west, independent ]

captureAreas = [];
captureTime = 60;

fnc_mission = {

	if ( !isServer ) exitWith {};

	if !( params[
		[ "_pos", objNull, [ objNull, "", locationNull, [] ] ]
	] ) exitWith {};
	
	_this select [ 1, count _this ] params [ 
		[ "_radius", 100, [ 0 ] ],
		[ "_defaultOwner", sideUnknown, [ sideUnknown ] ],
		[ "_buildingInfo", [], [ [] ] ],
		[ "_sides", [ east, west, independent ], [ [] ] ]
	];

	switch ( typeName _pos ) do {
		case ( typeName objNull );
		case ( typeName locationNull ) : {
			if !( isNull _pos ) then {
				_pos = getPos _pos;
			}else{
				_pos = [0,0,0];
			};
		};
		case ( typeName "" ) : {
			_pos = getMarkerPos _pos;
		};
	};
	if ( _pos isEqualTo [0,0,0] ) exitWith {};

	//Create marker
	_marker = createMarker [ format[ "area_%1", count captureAreas ], _pos ];
	_marker setMarkerSize [ _radius, _radius ];
	_marker setMarkerDir 0;
	_marker setMarkerBrush "Grid";
	_marker setMarkerColor format[ "Color%1", _defaultOwner call BIS_fnc_sideName ];
	_marker setMarkerShape "ellipse";

	//Register the area
	captureAreas pushBack [ _marker, _sides, _defaultOwner, [ _defaultOwner, captureTime, time ] ];

	//Create building
	if ( count _buildingInfo > 0 ) then {
		_building = createVehicle [ _buildingInfo select 0, _pos, [], 0, "CAN_COLLIDE" ];
		_building setDir ( _buildingInfo select 1 );
	};

	//Monitor areas,  only start when 1st area is added to the list
	if ( count captureAreas isEqualTo 1 ) then {
		_nul = [] spawn {

			//While we have areas
			while { count captureAreas > 0 } do {
				sleep 5;

				//loop through each area
				{
					//Get area info
					_marker = _x select 0;
					_sides = _x select 1;
					_owner = _x select 2;
					_lastAttacking = _x select 3 select 0;
					_timeHeld = _x select 3 select 1;
					_lastCheck = _x select 3 select 2;

					//get area position and size
					_pos = getMarkerPos _marker;
					_radius = getMarkerSize _marker select 0;

					_competingCount = [];
					//for each man in the area
					{
						//if he is on a side that can capture this area
						if ( side _x in _sides ) then {

							//Add 1 to his sides count
							_index = side _x call BIS_fnc_sideID;
							if !( count _competingCount >= _index + 1 ) then {
								_competingCount set [ _index, 1 ];
							}else{
								_competingCount set [ _index, ( _competingCount select _index ) + 1 ];
							};

						};
					}forEach ( _pos nearEntities [ "CaManBase", _radius ] );

					//Find largest side count
					_attacking = -1;
					{
						if ( !isNil "_x" && { _x > _attacking } ) then {
							_attacking = _x;
						};
					}forEach _competingCount;

					//if there are units present
					if ( _attacking > 0 ) then {

						//Get side with largest count
						_attacking = ( _competingCount find _attacking ) call BIS_fnc_sideType;

						//if the attacking side was attacking last check
						if ( _attacking isEqualTo _lastAttacking ) then {

							//update amount of time they have held the area
							_timeHeld = _timeHeld + ( time - _lastCheck );

							//If they have held the are for longer than capture time
							if ( _timeHeld >= captureTime ) then {

								//update markers color to attacking sides color
								_marker setMarkerColor format[ "Color%1", _attacking call BIS_fnc_sideName ];
								//Set new owner
								_owner = _attacking;
							};
							//Store attacking side, timeHeld and last check time
							_attacking = [ _attacking, _timeHeld, time ];
						}else{
							//Otherwise a new side is dominent, store new side with 0 time held
							_attacking = [ _attacking, 0, time ];
						};

						//Update areas info
						captureAreas set [ _forEachIndex, [ _marker, _sides, _owner ] + [ _attacking ] ];
					};
				}forEach captureAreas;
			};
		};
	};

};

Not thourghly checked only spent about 30mins writing it and quickly testing, hopefully can give you some ideas on implementing your own.

EDIT: changed some of the params checking just to make sure its a valid position.

  • Like 2

Share this post


Link to post
Share on other sites

Well here we go

 

https://github.com/Celludriel/dyncap

 

I did go the trigger way but took some ideas from the code above.  It's not a complete domination mission I'll make that next, this is just a simple component.  Spawn an object that is capturable by either east, west or independent.  Not sure it is fully production ready yet, I only did some basic testing.  Feel free to let me know if there are bugs so I can fix them, or sent me a pull request if you want to have a go at it yourself

Share this post


Link to post
Share on other sites

Don't use this yet folks I fucked up ... createTrigger DOES NOT WORK IN MP plain and simple , they do not get synced for JIP making them useless.  I need to refactor most of the code to work in another way now ... thats one weekend down the drain ...

Share this post


Link to post
Share on other sites

Finished it , refactored all the trigger stuff out and put in monitor threads.  I rewrote my original post so please check it out for details to the script !

Share this post


Link to post
Share on other sites

Bugged.

 

There's a problem with sentence:

 

dynClientCaptureMonitor.sqf (line 3)

 

if (isServer) exitWith {}; // -> if (isServer) exitWith {}; ???

 

Changed line to:

 

if (!isServer) exitWith {};

 

Works fine.

  • Like 1

Share this post


Link to post
Share on other sites

Bugged.

 

There's a problem with sentence:

 

dynClientCaptureMonitor.sqf (line 3)

 

if (isServer) exitWith {}; // -> if (isServer) exitWith {}; ???

 

Changed line to:

 

if (!isServer) exitWith {};

 

Works fine.

 

Wait a minute ... no ... this is the client capture monitor ?  This should be exited by the server ... I believe I know what happened, I only tested on a dedicated server !  I forgot about testing the local server, and thats why it's not working !  Thanks I'll see if I can fix this and put out a new release.

 

I believe the correct code would be if(isDedicated) exitWith {};

 

I removed all the logging that was blowing up people's logfile

 

I made a new release: https://github.com/Celludriel/dyncap/releases/tag/1.0.2

Share this post


Link to post
Share on other sites

Hi man nice release :) Is there a way to change this so it works for groups rather than sides? 

Share this post


Link to post
Share on other sites

What do you mean by groups ? A group in arma is just a set of units in one collection ?

Share this post


Link to post
Share on other sites

What do you mean by groups ? A group in arma is just a set of units in one collection ?

Yes a group

For exile as they are all the same side, can it be changed to groups within in one side?

Share this post


Link to post
Share on other sites

Yes a group

For exile as they are all the same side, can it be changed to groups within in one side?

 

hmmm in principle the owner could be something else then a side, if I can add an abstraction layer to fetching the owning side instead of a Side make it a String perhaps.  But SQF isn't JAVA, it's a bit harder to pull of stuff here then what I regularly do.  I can't put time into this right away though, I still have another project going where I needed this one as a building block.  I'll add it to my backlog and see if I can create something but don't expect it soon.  However you can always fork the github and give it a shot yourself.  Add an abstraction for fetching the side in both monitor scripts

Share this post


Link to post
Share on other sites

Thanks for the reply, i was just wondering if it was possible and it iis :) It cool by the way :) 

Share this post


Link to post
Share on other sites

I've created a new release for my little library.  It's a total refactor to make use of the CfgFunctions and a hopefully conflict free Gui implementation with other libraries.

 

I've updated the first post with the new release link

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

×