Jump to content
twakkie

Sector Module Scripting

Recommended Posts

Thanks Larrow,

 

I'm back working on my MP game using your updated version, and integrating into my own script.

 

I am trying to generate sectors before the game starts, and I don't want to call spawnSector from initPlayerLocal or initServer. So I am calling setUpSector with {postInit = 1} from the description.ext.

 

The sector module "ModuleSector_F" will not spawn, yet all the params are shown in the hint message, and I am not getting any error messages...any ideas what's going wrong?

 

I stripped everything out from your example mission, to try and figure it out, and only have the following:

in the mission folder: description.ext, mission.sqm

in folder functions>>SetUp>> createSectorExecution.hpp, fn_createSector.sqf, fn_setUpSector.sqf

 

description.ext

Quote

class CfgFunctions {
	class BEAKS
	{
		class SetUp
		{
			file = "functions\SetUp";	
			class setUpSector {postInit = 1};
			class createSector {};
		}
	}
};

class CfgRemoteExec
{
        class Functions
        {
            file = "functions\SetUp";	
			//mode = 1;	//Only white listed function can be remoteExecuted  <---- DON'T KNOW WHAT "white listed function" ARE ?
            //BEAKS_fnc_createSector
            #include "functions\SetUp\createSectorExecution.hpp"
			class createSectorExecution {};		// <---- NOT SURE WHAT THIS DOES ?
        };
};

 

 

createSectorExecution.hpp

class BEAKS_fnc_createSector { jip = 0; allowedTargets = 2;}; //No JIP, Can only be remoteExecuted to the Server

fn_setUpSector.sqf

//waitUntil { time > 0 };

//Exit if we are not the server
if (!isServer) exitWith {};

//Create a plain old default sector
["myLoadingScreen", "this text does not display for some reason..."] call BIS_fnc_startLoadingScreen;

//Usage basic
_baseName = [position player,"Sector 1","S",nil,nil,EAST] call BEAKS_fnc_createSector;


"myLoadingScreen" call BIS_fnc_endLoadingScreen;	

fn_createSector.sqf

Quote

/*****
******
	Original file: fn_spawnSector.sqf
	Written by Larrow
	Sunday, 3 June 2018
	Originally posted @:https://forums.bohemia.net/forums/topic/181264-sector-module-scripting/?do=findComment&comment=3294957
******
	You are free to modifiy and distribute this file as long as this header is kept intact
******
	Description: Spawn a module sector
******
	0: _pos (Array, Object, Marker, Group, Location) - Position to spawn sector at

	//Anything from here on are optional parameters

	1: _name (String) - Name of sector as shown on map
	2: _designation (String) - Designation shown on both map and in sectors ui
	3: _sectorArea (Array, Object "Trigger" or "LocationArea_F") - Sectors trigger area in [ radius X, radius Y, direction, isRectangle ] see setTriggerArea OR an existing trigger or locationArea_F( with trigger attached, same as a default setup in the editor )
	4: _sides (Array) - Array of sides that can capture the sector, if [] used sides will be [east,west,resistance,civilian], if nil defaults to [east,west], not available through editor attributes and is usually defined by syncing side logics to the sector module
	5: _defaultOwner (Number, Side) - Initial owner of the sector when created, for no owner use either sideUnknown or -1
	6: _onOwnerChange (String) - Code as STRING that runs when a sector is captured, code is passed [ _sector, _owner, _oldOwner ] in _this, code is also run at sector initialisation _owner will be default owner and _oldOwner will be sideUnknown

	//Score award
	7: _scoreReward (Number) - Score given to side for capturing sector

	//Tasks and rewards
	8: _taskOwner (Number) - 0 = no task, 1 = everyone, 2 = default owner, 3 = all but default owner
	9: _taskTitle (String) - Task title, use %1 to insert sector name
	10: _taskDescription (String) - Task Description, use %1 to inser sector name, %2 to insert sector rewards ( vehicles and respawn positions, these will need to be created seperately and synced with a existing trigger that is passed in param 3 ), %3 for capture costs description

	//Capture limits and coef cost, these are the same as the attributes that can be seen when viewing a sectors attributes in the editor
	11: _ownerLimit (Number) - Range <0-1> that a side must be dominent to cpature sector
	12: _costInfantry (Number) - Ratio of how fast Infantry will capture area
	13: _costWheeled (Number) - Ratio of how fast Wheeled vehicles will capture area
	14: _costTracked (Number) - Ratio of how fast Tracked vehicles will capture area
	15: _costWater (Number) - Ratio of how fast Naval vehicles will capture area
	16: _costAir (Number) - Ratio of how fast Air vehicles will capture area
	17: _costPlayers (Number) - Ratio of how fast Players will capture area

	//Values not available through editor attributes
	18: _captureCoef (Number) - ?Some Time based coef added to scores
******
******/


//if we are not the server
if !( isServer ) exitWith {
	//Remote execute on the server
	_this remoteExec[ _fnc_scriptName, 2 ];
};

params [
	//Position to place sector
	[ "_pos", objNull, [ [], objNull, "", grpNull, locationNull ], [ 2, 3 ] ],
	//Name as shown on map
	[ "_name", "", [ "" ] ],
	//Designation as shown on map/sector ui icon
	[ "_designation", "", [ "" ] ],
	//Sector trigger area in [ radius X, radius Y, direction, isRectangle, radiusZ ] see setTriggerArea
	[ "_sectorArea", [ 50, 50, 0, false ], [ [], objNull ] ],
	//Sides competing for sector
	[ "_sides", [ east, west ], [ [] ] ],
	//Initial default owner, must be in competing sides
	[ "_defaultOwner", -1, [ 0, sideUnknown ] ],
	//Code as STRING that is run when sector changes ownership
	[ "_onOwnerChange", "true", [ "" ] ],
	//score awarded to capturing side
	[ "_scoreReward", 0, [ 0 ] ],
	//Sector task and rewards
	[ "_taskOwner", 0, [ 0 ] ],//0 - no task, 1 - everyone, 2 - default owner, 3 - all but default owner
	[ "_taskTitle", "", [ "" ] ],
	[ "_taskDescription", "", [ "" ] ],
	//Optional Sector capture coefs and costs
	[ "_ownerLimit", 0, [ 0 ] ],
	[ "_costInfantry", 1, [ 0 ] ],
	[ "_costWheeled", 1, [ 0 ] ],
	[ "_costTracked", 1, [ 0 ] ],
	[ "_costWater", 1, [ 0 ] ],
	[ "_costAir", 1, [ 0 ] ],
	[ "_costPlayers", 1, [ 0 ] ],
	//Not avaiable in editor attributes
	[ "_captureCoef", 0.05, [ 0 ] ]
];

_pos = _pos call BIS_fnc_position;
if ( _pos in [ [0,0,0], [] ] ) exitWith { "Creating Sector error: Bad position" call BIS_fnc_error };

if ( _defaultOwner isEqualType sideUnknown ) then {
	if ( _defaultOwner isEqualTo sideUnknown ) then {
		_defaultOwner = -1;
	}else{
		_defaultOwner = _defaultOwner call BIS_fnc_sideID;
	};
};

//If the user has passed a trigger OR location instead of a trigger area definition
if ( _sectorArea isEqualType objNull ) then {
	_sectorArea = switch ( typeOf _sectorArea ) do {
		case "EmptyDetector" : {
			_location = createGroup sideLogic createUnit [ "LocationArea_F", getPosATL _sectorArea, [], 0, "CAN_COLLIDE" ];
			_location synchronizeObjectsAdd[ _sectorArea ];
			str ( _location call BIS_fnc_netId );
		};
		case "LocationArea_F" : {
			str ( _sectorArea call BIS_fnc_netId );
		};
		default {
			[ 50, 50, 0, false ];
		};
	};
}else{
	//lets make sure area definition is correct
	_sectorArea params[
		[ "_radiusX", 50, [ 0 ] ],
		[ "_radiusY", 50, [ 0 ] ],
		[ "_dir", 0, [ 0 ] ],
		[ "_isRect", false, [ true ] ],
		[ "_radiusZ", -1 ]
	];

	_sectorArea = [ _radiusX, _radiusY, _dir, _isRect ];
};

//Create the sector logic
"ModuleSector_F" createUnit [ _pos, createGroup sideLogic, format[ "
	this setVariable [ 'name', '%1' ];
	this setVariable [ 'Designation', '%2' ];
	this setVariable [ 'OwnerLimit', '%4' ];
	this setVariable [ 'OnOwnerChange', %5 ];
	this setVariable [ 'CaptureCoef', '%6' ];
	this setVariable [ 'CostInfantry', '%7' ];
	this setVariable [ 'CostWheeled', '%8' ];
	this setVariable [ 'CostTracked', '%9' ];
	this setVariable [ 'CostWater', '%10' ];
	this setVariable [ 'CostAir', '%11' ];
	this setVariable [ 'CostPlayers', '%12' ];
	this setVariable [ 'DefaultOwner', '%13' ];
	this setVariable [ 'TaskOwner', '%14' ];
	this setVariable [ 'TaskTitle', %15 ];
	this setVariable [ 'taskDescription', %16 ];
    this setVariable [ 'ScoreReward', '%17' ];
	this setVariable [ 'Sides', %18 ];

	if ( %3 isEqualType '' ) then {
		this synchronizeObjectsAdd[ %3 call BIS_fnc_objectFromNetID ];
	}else{
		this setVariable [ 'objectArea', %3 ];
	};
",	_name, _designation, _sectorArea, _ownerLimit, str _onOwnerChange, _captureCoef, _costInfantry, _costWheeled, _costTracked, _costWater, _costAir, _costPlayers, _defaultOwner, _taskOwner, str _taskTitle, str _taskDescription, _scoreReward, _sides ]];

////////////////////// TESTING ////////////////////// 
hint format ["_pos: %1 \n _name: %2 \n _designation: %3 \n _sectorArea: %4 \n _sides: %5 \n _defaultOwner: %6", _pos, _name, 
	_designation, _sectorArea, _sides, _defaultOwner];

 

 

Share this post


Link to post
Share on other sites

Just a timing issue.

//description.ext

class CfgFunctions {
	class BEAKS
	{
		class SetUp
		{
			file = "functions\SetUp";
			class setUpSector {postInit = 1};
			class createSector {};
		}
	}
};

/*class CfgRemoteExec
{
		class Functions
		{
			//this is the WHITELIST any function mentioned in this section is whitelisted

			mode = 1;	//Only white listed function can be remoteExecuted

			//Include the class for BEAKS_fnc_createSector << the function to be whitelisted
			#include "functions\SetUp\createSectorExecution.hpp"

		};
};*/

No real changes here other than to explain what the whitelist is, also no need for file path you had placed in there.

There is no need for CfgRemoteExec if not wanted, I only added it to make entirely clear that this function should only ever be executed on the server.

//fn_setUpSector.sqf

//Exit if we are not the server
if (!isServer) exitWith {};

_nul = [] spawn {
	waitUntil { time > 0 };

	["myLoadingScreen"] call BIS_fnc_startLoadingScreen;

	//Usage basic
	[position player,"Sector 1","S",nil,nil,EAST] call BEAKS_fnc_createSector;

	"myLoadingScreen" call BIS_fnc_endLoadingScreen;
};

Otherwise all the other files you have shown stay the same.

Just a note that you have position player in there, which if on a dedicated server there will be no player. Although I expect you have it there just for testing.

 

Doing a postInit setup for this is kind of redundant to be honest. As this should only ever be created on the server, so you might as well use initServer.sqf with the code as per fn_setUpSector.sqf (of course not needing the check for isServer).

  • Like 1

Share this post


Link to post
Share on other sites

Thanks Larrow, this works.

 

So the waitUntil { time > 0 }; is what it controlling the timing. But timing of what exactly?

 

Correct, player position is just for testing.

 

 

 

Share this post


Link to post
Share on other sites
On 6/21/2018 at 12:35 AM, cklymowsky said:

So the waitUntil { time > 0 }; is what it controlling the timing. But timing of what exactly?

The timing of the module initialising through the module framework.

Don't know didn't look into to hard. Tried multiple event script entry points, CfgFunction with several flags for mission initialisation like BIS_fnc_init etc that all potentially have very slight timing differences but nothing seem to matter.

Most probably some timing to do with module framework and its base center, side and logic but didn't feel like tracking it down when just time > 0 seems to do the job.

 

If you do it like you previously showed (without the wait ), the module is actually created as you can see it in allMissionObjects "Logic" but it was just not initialising properly.

  • Like 3

Share this post


Link to post
Share on other sites
On 22/6/2018 at 2:28 PM, Larrow said:

The timing of the module initialising through the module framework.

Don't know didn't look into to hard. Tried multiple event script entry points, CfgFunction with several flags for mission initialisation like BIS_fnc_init etc that all potentially have very slight timing differences but nothing seem to matter.

Most probably some timing to do with module framework and its base center, side and logic but didn't feel like tracking it down when just time > 0 seems to do the job.

 

If you do it like you previously showed (without the wait ), the module is actually created as you can see it in allMissionObjects "Logic" but it was just not initialising properly.

 

Larrow, I wanted to also have Independent warring for sector control (All 3 factions) but it is not working as it throws an error "target at index 2 is undefined [ west, east, any]".

 

This is my code:

Spoiler

 


[
            flag1,
            "Claim Territory",
            "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_forceRespawn_ca.paa",
            "\a3\ui_f\data\IGUI\Cfg\holdactions\holdAction_forceRespawn_ca.paa",
            "true",
            "true",
            {},
            {},
            {
			
  params [ "_target", "_caller", "_id", "_args" ]; 
 
  [ 
 
   getPosATL _caller, 
 
   format["Territory %1", count( missionNamespace getVariable [ "BIS_fnc_moduleSector_sectors", [] ] ) ], 
 
   format[ "%1", count( missionNamespace getVariable [ "BIS_fnc_moduleSector_sectors", [] ] ) ], 
 
   [ 15, 30, 206, true ], 
 
   [ west, east, resistance ], 
 
   sideUnknown, 
 
   " 
    params[ '_sector', '_owner', '_oldOwner' ]; 
 
    if !( _owner isEqualTo sideUnknown ) then { 
     format[ '%1 captured by %2 from %3', _sector, _owner, _oldOwner,  ] remoteExec [ 'hint', _owner ]; 
    }; 
   " 
  ] call LARs_fnc_spawnSector; 
			
			},
            {},
            [],
            10,
            0,
            true,
            true
        ] call BIS_fnc_holdActionAdd;

 

 

 

 

I've also tried changing [ west, east, resistance ], to [ west, east, independent ], but the same error happens. The sector it is still created thou!

 

Do I need to modify your fn_spawnSector.sqf to be able to have all 3 factions?

 

PS: This is a holdAction but previously I used the addAction in your demo mission and had the same issue so it is not the holdAction conversion. 

Share this post


Link to post
Share on other sites
1 hour ago, LSValmont said:

Larrow, I wanted to also have Independent warring for sector control (All 3 factions) but it is not working as it throws an error "target at index 2 is undefined [ west, east, any]".

Good catch, I never tested all sides properly. Error is where certain sides (independent/resistance, civilian) when string-ified come back as GUER/CIV which mean absolutely nothing in script for Arma 3.

Updated download in original post with fix or can be downloaded here.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
Just now, Larrow said:

Good catch, I never tested all sides properly. Error is where certain sides (independent/resistance, civilian) when string-ified come back as GUER/CIV which mean absolutely nothing in script for Arma 3.

Updated download in original post with fix or can be downloaded here.

 

You are the best! Thanks!

Share this post


Link to post
Share on other sites
23 hours ago, Larrow said:

Good catch, I never tested all sides properly. Error is where certain sides (independent/resistance, civilian) when string-ified come back as GUER/CIV which mean absolutely nothing in script for Arma 3.

Updated download in original post with fix or can be downloaded here.

 

Adding this:

Spoiler

 

class CfgRemoteExec
{
        class Functions
        {
                mode = 1;    //Only white listed function can be remoteExecuted

                //Utility functions for demo mission
                class TAG_fnc_createSectorFromTrigger { jip = 0; allowedTargets = 2;};
                class TAG_fnc_createSectorFromLocation { jip = 0; allowedTargets = 2;};

                //LAR_fnc_spawnSector
                #include "LARs\spawnSector\functions\spawnSectorExecution.hpp"
        };
};

 

 

to description.ext seems to break the CBA functions called by other scripts such as: 

 

Spoiler

//this one executes the code within {} (which is our undercover_scriptfnc_switch_onfoot from above) if the player changes his weapon:
undercover_scriptevh_onFoot = ["weapon", {[_this select 0, _this select 1] call undercover_scriptfnc_switch_onfoot}] call CBA_fnc_addPlayerEventHandler;

 

After changing mode = 1 to mode = 2 (the default one) then the CBA CBA_fnc_addPlayerEventHandler works again but only once.

 

Do I need to add/change something else to class CfgRemoteExec to get all my other scripts to work again?

 

Thanks in advance!

Share this post


Link to post
Share on other sites
Just now, LSValmont said:

Do I need to add/change something else to class CfgRemoteExec to get all my other scripts to work again?

Just remove the CfgRemoteExec class completely. its not needed,

  • Thanks 1

Share this post


Link to post
Share on other sites

Hi Larrow,

 

I justed tested the VR mission in the editor and also with my own mission, nothing seems to happen, regardless which sector creation option I hit?

 

I have tried both with mods and without, no change. I use dev build 1.87.145170

 

Thanks for your help in advance!

Share this post


Link to post
Share on other sites

Hello

Firstly thank you guys for this topic and examles it helped me a lot. Thank you Larrow for your script.

Now I woul like to ask you for help. I used this script for creating sectors in my missions (game mode) WARMACHINE. Creating sector module by script after mission start doesn't work after update 1.86. (Worked well before 1.86) If you can tell me what changed in the moduleSector, or how to change the script to work again, I'll be glad. I spend one year by developing this missions. And now core mechanics doesn't work.
Thank You for your help.

 

Steps to reproduce:

In EDEN editor:
Place unit for player
Place object, set variable name: objectAlpha
save

place script <sector.sqf> into the mission files

sector.sqf:

//Create the sector logic
_pos = getPos objectAlpha;
sectorA = (createGroup sideLogic) createUnit ["ModuleSector_F",_pos,[],0,"NONE"];

//Default setting,  which are optional
sectorA setVariable ["CostAir","0.1"];
sectorA setVariable ["CostInfantry","0.1"];
sectorA setVariable ["CostPlayers","0.1"];
sectorA setVariable ["CostTracked","0.1"];
sectorA setVariable ["CostWater","0.1"];
sectorA setVariable ["CostWheeled","0.1"];
sectorA setVariable ["DefaultOwner","-1"]; //"-1" = None, "0"= West, "1" = East, "2"= independent 
sectorA setVariable ["Designation","A"];
sectorA setVariable ["Name","ALPHA"];
sectorA setVariable ["OnOwnerChange",""];
sectorA setVariable ["OwnerLimit","1"];
sectorA setVariable ["ScoreReward","0"];
sectorA setVariable ["TaskDescription","Capture sector ALPHA"];
sectorA setVariable ["TaskOwner","3"];
sectorA setVariable ["TaskTitle","ALPHA"];

//Set the sides for the sector
sectorA setVariable ["sides",[west, east]];

//Wait until sector is initialised
waitUntil {
!isNil { sectorA getVariable [ "finalized", nil ] } &&
{ !( sectorA getVariable [ "finalized", true ] ) }
};

//A size for the trigger
_trgSize = 50;
//Set the trigger size on the sector
sectorA setVariable [ "size", _trgSize ];
//Make the module update its trigger
[ sectorA, [], true, "area" ] call BIS_fnc_moduleSector;

//Unfortunately the sector has not been written to also update its marker so..
//Get the modules trigger
_trg = ( sectorA getVariable "areas" ) select 0;
//Get the triggers marker
_mrk = ( _trg getVariable "markers" ) select 0;
//Update the markers size
_mrk setMarkerSize [ _trgSize, _trgSize ];

Start mission
Run script: [] execVM "sector.sqf";

script stops at line 26 (//Wait until sector is initialised)

 

Links:

Feedback tracker

WarMachine missions

 

Thank You for your help.

 

 

Share this post


Link to post
Share on other sites
{ !( sectorA getVariable [ "finalized", true ] ) }

Why is this in {} brackets?

  • Thanks 1

Share this post


Link to post
Share on other sites

You mean to change it to:

//Wait until sector is initialised
waitUntil 
{
	(!isNil (sectorA getVariable ["finalized", nil])) && (!( sectorA getVariable [ "finalized", true ]))
};

Thank you for your reply. And thanks for WARLORDS, It's a great game mode.

Share this post


Link to post
Share on other sites

The whole condition is a bit strange to be honest :)

If you want to check if the variable "finalized" is indeed FALSE as you have it in the code now, it could look like this:

waitUntil {!(sectorA getVariable ["finalized", true])};

You don't need to wait for declaration of a variable when you're providing its default value.

  • Thanks 1

Share this post


Link to post
Share on other sites

Thank you. I will try it (hopefuly this night) and report back. 

Share this post


Link to post
Share on other sites

There has been a change to the initialisation of a module through the module framework. Now any modules created after time > 0 need the variable BIS_fnc_initModules_disableAutoActivation set on the module to be false.

Updated my previously posted function in the test mission to reflect this change.

_module setvariable [ 'BIS_fnc_initModules_disableAutoActivation', false ];

@ZeroG

 

  • Thanks 1

Share this post


Link to post
Share on other sites

Thank you Larrow. You are awsome. Your test mission is great example.

Here is how i solve it in my case. All credits goes to Larrow.

//CREATE NEW SECTOR
// pos-array, nameF-string, taskF-string, sideW=west, sideE=east // global variables created by another scripts

	"ModuleSector_F" createUnit [pos,createGroup sideLogic,format
	["
		sectorF=this; //to set variable name
		this setvariable ['BIS_fnc_initModules_disableAutoActivation',false];
		this setVariable ['name',nameF];
		this setVariable ['Designation','F'];
		this setVariable ['OwnerLimit','1'];
		this setVariable ['OnOwnerChange','[] call wrm_fnc_aiMove;']; //another custom function
		this setVariable ['CaptureCoef','0.05']; 	
		this setVariable ['CostInfantry','0.2'];
		this setVariable ['CostWheeled','0.2'];
		this setVariable ['CostTracked','0.2'];
		this setVariable ['CostWater','0.2'];
		this setVariable ['CostAir','0.2'];
		this setVariable ['CostPlayers','0.2'];
		this setVariable ['DefaultOwner','-1'];
		this setVariable ['TaskOwner','3'];
		this setVariable ['TaskTitle',nameF];
		this setVariable ['taskDescription',taskF];
		this setVariable ['ScoreReward','0'];
		this setVariable ['Sides',[sideE,sideW]];
		this setVariable ['objectArea',[50,50,0,false ]];
	"]];

 

Share this post


Link to post
Share on other sites

Hello, I tried using this script and whenever sectors are about to spawn I get the "bad position" error. I tried lots of different syntax but no dice.

Share this post


Link to post
Share on other sites

Sorry if I necro this post but is the more relevant to my problem.

 

It is enought to spawn sector modules on server in initserver or I have to call it on client?

 

 

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

×