Jump to content

Working Dayz Epoch Headless Client for Zed Spawn and FSM


Goober

Recommended Posts

To those interested in the overall architecture of the HC stuff:

 

1) Server listens for regular interval ping messages from HCs.

2) Server registers any HCs sending pings.  Server de-registers any HC that has stopped "pinging".  (HC has crashed, overloaded, etc...)

3) Client machines (the ones people play on) do not generate zombies by default any more.  Clients send "zombie generate" requests to server.

4) Server sends "zombie generate" request to random HC.  ( Choosing a random HC is a crude method of load balancing if you have more than one HC in operation. )

5) If no HCs in register, Server sends "zombie generate" request back to same Client.

 

All I did was hack Arma2 HC registration scripts (written by smarter coders than me ... and I give them recognition in the header comments) to DayZ zombie handling.

 

One of the pitfalls is failing to recognize that the request handling mechanisms have to be stateless and fast.  At any given moment, the Server, HC, and Client can be hit with hundreds of requests nearly simultaneously.  The general approach to that is to have the request receiving code simply spawn (not call) another function immediately to handle the request.  Hopefully this is straightforward and understandable.

 

Stateless is another matter.  The functions spawned by the request receiving code can make no assumptions.  You cannot just put all the message information in global variables because it could be overwritten at any moment by another request generation.  This means the request has to contain all the information necessary for proper zombie generation.  So the message information in the request has to be more than just "make zombie".  (This is complicated by the fact that the arma messaging system actually does use a form of global variable, so again fast code that copies the message into a local variable is necessary to maintain statelessness.)

 

Whew!

Link to comment
Share on other sites

 

There is error coming tho, from HC and have no clue how to fixit

 

"spawned building_spawnLoot"
Error in expression <ance"];
_obj = _this;




_type = toLower(typeOf _obj);


_config =  configFile >>>
  Error position: <typeOf _obj);


_config =  configFile >>>
  Error typeof: Type Array, expected Object
File z\addons\dayz_code\compile\building_spawnLoot.sqf, line 10

 

 

Hey KoTaS,

Did you happen to solve this problem?

Seems everything else is fine but this looks like it prevents loot from spawning.

Link to comment
Share on other sites

What i understand that this file is not compatible with new epoch 1.0.5.1 version.

 

HCdo_spawnRCV.sqf

private ["_type","_inVehicle","_onTheMove","_dateNow","_maxWildZombies","_age","_radius","_position","_nearbyplayers","_dayz_CurrentZombies","_dayz_maxGlobalZombies","_actors","_nearByObj","_handle","_looted","_cleared","_zombied","_config","_canLoot","_dis","_nearby","_nearbyCount"];


_type = _this select 0;
_inVehicle = _this select 1;
_onTheMove = _this select 2;
_dateNow = _this select 3;
_maxWildZombies = _this select 4;
_age = _this select 5;
_radius = _this select 6; 
_position = _this select 7;
_nearbyplayers = 0;
diag_log ("--HCdospawnRCV:" + str _this);


_dayz_CurrentZombies = 0;
_dayz_maxGlobalZombies = 0;


_actors = _position nearEntities ["CAManBase",_radius+200];
_dayz_maxGlobalZombies = dayz_maxGlobalZombiesInit;
{
if(isPlayer _x) then {
_dayz_maxGlobalZombies = _dayz_maxGlobalZombies + dayz_maxGlobalZombiesIncrease;
_nearbyplayers = _nearbyplayers + 1;
} else {
if (_x isKindof "zZombie_Base") then {


_dayz_CurrentZombies = _dayz_CurrentZombies + 1;
};
};
} foreach _actors;


_nearby = _position nearObjects ["building",_radius];
_nearbyCount = count _nearby;
if (_nearbyCount < 1) then
{
if (_dayz_CurrentZombies < (_maxWildZombies * _nearbyplayers ) and !_inVehicle)  then {
[_position] call wild_spawnZombiesHC;
diag_log "called wild_spawnZombiesHC:" + str _position;
};
} else {
{
_type = typeOf _x;
_config =  configFile >> "CfgBuildingLoot" >> _type;
_canLoot =  isClass (_config);


if(_canLoot) then {


_dis = _x distance _position;


if ((_dis < 120) and (_dis > 30) and !_inVehicle) then {
_looted = (_x getVariable ["looted",-0.1]);
_cleared = (_x getVariable ["cleared",true]);
_dateNow = (DateToNumber date);
_age = (_dateNow - _looted) * 525948;
if ((_age > 10) and (!_cleared)) then {
_nearByObj = nearestObjects [(getPosATL _x), ["WeaponHolder","WeaponHolderBase"],((sizeOf _type)+5)];
{deleteVehicle _x} forEach _nearByObj;
_x setVariable ["cleared",true,true];
_x setVariable ["looted",_dateNow,true];
};
if ((_age > 10) and (_cleared)) then {
_x setVariable ["looted",_dateNow,true];
diag_log "spawned building_spawnLoot";
_handle = [_x] spawn building_spawnLoot;
waitUntil{scriptDone _handle};
};
};


if (!_onTheMove) then {
if ((time - dayz_spawnWait) > dayz_spawnDelay) then {
if (({alive _x} count entities "zZombie_Base") < dayz_maxZeds) then {
if (_dayz_CurrentZombies < _dayz_maxGlobalZombies) then {
_zombied = (_x getVariable ["zombieSpawn",-0.1]);
_dateNow = (DateToNumber date);
_age = (_dateNow - _zombied) * 525948;
if (_age > 3) then {
_x setVariable ["zombieSpawn",_dateNow,true];
diag_log "called building_spawnZombiesHC";
[_x] call building_spawnZombiesHC;
}; 
} else {
dayz_spawnWait = time;
};
};
};
};
};
} forEach _nearby;
};

Error log

 

"spawned building_spawnLoot"
Error in expression <ance"];
_obj = _this;




_type = toLower(typeOf _obj);


_config =  configFile >>>
  Error position: <typeOf _obj);


_config =  configFile >>>
  Error typeof: Type Array, expected Object
File z\addons\dayz_code\compile\building_spawnLoot.sqf, line 10
Link to comment
Share on other sites

Also these two files are very different and i don't understand how to make it work again

 

Epoch 1.0.4.2  - building_spawnLoot.sqf

private ["_obj","_type","_config","_positions","_iPos","_nearBy","_itemType","_itemTypes","_lootChance","_weights","_cntWeights","_index","_itemTypesSmall","_positionsSmall"];
//_t1 = diag_tickTime;


_obj =  _this select 0;


// lower case to prevent issues with differing case for buildings from map to map.
_type = toLower(typeOf _obj);


//diag_log format["Spawning loot for: %1", _type];




_config =  configFile >> "CfgBuildingLoot" >> _type;
if (DZE_MissionLootTable) then {
_config = missionConfigFile >> "CfgBuildingLoot" >> _type;
};


_positions =  [] + getArray (_config >> "lootPos");
_itemTypes = [] + getArray (_config >> "itemType");
_lootChance = getNumber (_config >> "lootChance");


{
if ((random 1) < _lootChance) then {
_iPos = _obj modelToWorld _x;
_nearBy = nearestObjects [_iPos, ["ReammoBox","WeaponHolder","WeaponHolderBase"], 1];
if (count _nearBy == 0) then {
_index = dayz_CBLBase find _type;
//diag_log format["Found %2 at index: %1", _index,_type];
_weights = dayz_CBLChances select _index;
_cntWeights = count _weights;
_index = floor(random _cntWeights);
_index = _weights select _index;
_itemType = _itemTypes select _index;
[_itemType select 0, _itemType select 1 , _iPos, 0.0]  call spawn_loot;
//_obj setVariable ["created",(DateToNumber date),true];
};
};
} forEach _positions;


_itemTypesSmall = [] + getArray (_config >> "itemTypeSmall");
_positionsSmall =  [] + getArray (_config >> "lootPosSmall");
{
if ((random 1) < _lootChance) then {
_iPos = _obj modelToWorld _x;
_nearBy = nearestObjects [_iPos, ["ReammoBox","WeaponHolder","WeaponHolderBase"], 1];
if (count _nearBy == 0) then {
_index = dayzE_CBLSBase find _type;
//diag_log format["Found %2 at index: %1", _index,_type];
_weights = dayzE_CBLSChances select _index;
_cntWeights = count _weights;
_index = floor(random _cntWeights);
_index = _weights select _index;
_itemType = _itemTypesSmall select _index;
[_itemType select 0, _itemType select 1 , _iPos, 0.0] call spawn_loot_small;
//_obj setVariable ["created",(DateToNumber date),true];
};
};
} forEach _positionsSmall;
//["building_spawnLoot.sqf",(diag_tickTime - _t1)] call fnc_dump;

Epoch 1.0.5.1  - building_spawnLoot.sqf

/*        Created exclusively for ArmA2:OA - DayZMod
        Please request permission to use/alter/distribute from project leader (R4Z0R49)
Modified for DayZ Epoch by [VB]AWOL [email protected].
*/
private ["_lootChance"];
_obj = _this;


// lower case to prevent issues with differing case for buildings from map to map.
_type = toLower(typeOf _obj);


_config =  configFile >> "CfgBuildingLoot" >> _type;
if (DZE_MissionLootTable) then {
_config = missionConfigFile >> "CfgBuildingLoot" >> _type;
};


_pos = [] + getArray (_config >> "lootPos");
_itemTypes = [] + getArray (_config >> "lootType");
_lootChance = getNumber (_config >> "lootChance");


//_countPositions = count _pos;
_qty = 0; // effective quantity of spawned weaponholder
_lootSpawnBias = 67; //67 between 50 && 100. The lower it is, the lower chance some of the lootpiles will spawn




// shuffles an array
// parameters: array
// example: _myrandomarray = _myNormalArray call _ShuffleArray;
_ShuffleArray = {
private ["_ar","_rand_array","_rand"];
_ar = _this;
_rand_array = [];
while {count _ar > 0} do {
_rand = (count _ar);
_rand = floor (random _rand);
_rand_array set [count _rand_array, _ar select _rand];
_ar set [_rand, "randarray_del"];
_ar = _ar - ["randarray_del"];
};
_rand_array;
};
_positions = _pos call _ShuffleArray;


// bias for this building. The lower it is, the lower chance some of the lootpiles will spawn
_bias = 50 max _lootSpawnBias;
_bias = 100 min _bias;
_bias = (_bias + random(100 - _bias)) / 100;
//diag_log(format["BIAS:%1 LOOTCHANCE:%2", _bias, _lootChance]);


{
if (count _x == 3) then {
_rnd = (random 1) / _bias;
_iPos = _obj modelToWorld _x;
_nearBy = nearestObjects [_iPos, ["ReammoBox"], 2];


if (count _nearBy > 0) then {
_lootChance = _lootChance + 0.05;
};


if (dayz_currentWeaponHolders < dayz_maxMaxWeaponHolders) then {
if (_rnd <= _lootChance) then {
if (count _nearBy == 0) then {
_index = dayz_CBLBase find _type;
_weights = dayz_CBLChances select _index;
_cntWeights = count _weights;
_index = floor(random _cntWeights);
_index = _weights select _index;
_itemType = _itemTypes select _index;
[_itemType select 0, _itemType select 1 , _iPos, 0.0] call spawn_loot;
// diag_log (format["SpawnLoot: Pos: %1, LootType: %2/%3,",_iPos,_itemType select 0,_itemType select 1]);
dayz_currentWeaponHolders = dayz_currentWeaponHolders +1;
//loclout system
_obj setVariable ["looted",diag_tickTime + dayz_tickTimeOffset];
};
};
};
};
} count _positions;


// small loot
_posSmall =  [] + getArray (_config >> "lootPosSmall");
_itemTypesSmall = [] + getArray (_config >> "lootTypeSmall");


_positionsSmall = _posSmall call _ShuffleArray;


{
if (count _x == 3) then {
_rnd = (random 1) / _bias;
_iPos = _obj modelToWorld _x;
_nearBy = nearestObjects [_iPos, ["ReammoBox"], 2];


if (count _nearBy > 0) then {
_lootChance = _lootChance + 0.05;
};


if (dayz_currentWeaponHolders < dayz_maxMaxWeaponHolders) then {
if (_rnd <= _lootChance) then {
if (count _nearBy == 0) then {
_index = dayzE_CBLSBase find _type;
_weights = dayzE_CBLSChances select _index;
_cntWeights = count _weights;
_index = floor(random _cntWeights);
_index = _weights select _index;


//diag_log format["building_spawnLoot.sqf: %1", _itemTypesSmall];


_itemType = _itemTypesSmall select _index;
[_itemType select 0, _itemType select 1, _iPos, 0.0] call spawn_loot_small;
// diag_log (format["SpawnLoot: Pos: %1, LootType: %2/%3,",_iPos,_itemType select 0,_itemType select 1]);
dayz_currentWeaponHolders = dayz_currentWeaponHolders +1;
//loclout system
_obj setVariable ["looted",diag_tickTime + dayz_tickTimeOffset];
};
};
};
};
} count _positionsSmall;
Link to comment
Share on other sites

Okay figure how to make this working again 

Tested and working with  Epoch 1.0.5.1

 

Small problem does not work with loot system at all, cannot figure why. Here is error log

"spawned building_spawnLootHC"
Error in expression <hance"];
_obj = _this;


_type = toLower(typeOf _obj);


_config =  configFile >>>
  Error position: <typeOf _obj);


_config =  configFile >>>
  Error typeof: Type Array, expected Object
File mpmissions\__CUR_MP.Chernarus\addons\building_spawnLootHC.sqf, line 4

 

If anyone know how to fix this, please post it. Iam out of options here   :(

http://www.kotas.tk/DayZ_Epoch_11.Chernarus.zip

Link to comment
Share on other sites

Okay figure how to make this working again 

Tested and working with  Epoch 1.0.5.1

 

Small problem does not work with loot system at all, cannot figure why. Here is error log

"spawned building_spawnLootHC"
Error in expression <hance"];
_obj = _this;

... (some content deleted)

  Error typeof: Type Array, expected Object
File mpmissions\__CUR_MP.Chernarus\addons\building_spawnLootHC.sqf, line 4

 

If anyone know how to fix this, please post it. Iam out of options here   :(

http://www.kotas.tk/DayZ_Epoch_11.Chernarus.zip

 

Try changing:

 

_obj = _this;

 

to

 

_obj = _this select 0;

 

in your building_spawnLootHC.sqf.

 

This sets _obj to be the first value of the input array rather than being equal to the whole array. Computer programmers are weird people.  They like to start counting at zero.

Link to comment
Share on other sites

Very nice :) I will join in hopefully tomorrow.

What type of CPU usage are you getting from the HC?

When I messed with HC before it took ALOT of DZAI patrols to max out one non-HT core. I run 55-75% usage for 2 servers on 4 cores right now. I'm a little worried I might have to offload the HC on a VPS.

Link to comment
Share on other sites

Curious where HCdo_spawnRCV.sqf derived from... doesn't appear loot is running on the HC with these files. There is spawn_loot.sqf and spawn_loot_small.sqf that may need modified?

Also curious why not just call the things that are inside initHC in the HC's compiles.sqf. I'm going to do that with mine.

CEN: Anything beyond the limited scope of this thread he has hidden in his server file. I believe you would just need to create a public var and call it from the mission but will have to play around with it. People don't like sharing stuff :D

It would be cool to see an exmaple of the debug then most everything can be figured out from that.

Link to comment
Share on other sites

justchil,

 

HCdo_spawnRCV.sqf is basically a modified player_spawnCheck.sqf from dayz_code.pbo

 

Also, please make improvements like you suggest (initHC and HC compiles.sqf).  Some things I just bolted together while hacking this together originally.

 

If spawn_loot.sqf and spawn_loot_small.sqf needed to be changed, then I missed it.

EDIT: They don't need to be changed.  building_spawnLootHC.sqf calls them and passes a (player independent) position to them, so it is an intentional dive back into the base Dayz code.  Those sqfs are compiled as part of compilesHC.sqf.

 

Basically, in order to offload stuff from clients, I needed to replace anything that referred to the player with a reference back to the player's machine ID (for messaging) or position.  (Now if I could only get the DayZ coders to do the same in all the base code and reduce the number of overloading sqf files in the mission addons folder...)

Link to comment
Share on other sites

KoTaS is correct.  There is no hidden server side code.  Even though the server, HCs, and player client scripts are modified to make this work, everything is done openly through the mission file.

 

It was put in the server mods forum because it affects server code and there really wasn't another place for it.

 

It could be put into "@something" mod format, but ... well it just isn't (I don't have a simple reason).

Link to comment
Share on other sites

I got myself a dedicated server and bought a new OA account to experiment with this; and monkey like what monkey see.

Do we have permission to create derived work from this? If so, how should credits be credited?

Link to comment
Share on other sites

Do we have permission to create derived work from this? If so, how should credits be credited?

 

Derived work:  Of course!  Hack away!  I am hoping someone can use my proof of concept code and build something bigger and better with it.  More than one person on this thread is very interested in offloading all kinds of server functions onto HCs.

 

Credit:  I don't personally require anything, but common courtesy is to not strip out props located in file header comments or in code comments.  Treat the contributors the way you would want to be treated and you will minimize anyone whinging about credit.

Link to comment
Share on other sites

In the interest of openness I've created a github project for it at:

https://github.com/DavidFrendin/epoch-hc

The only thing I've done so far is rearranged the structure of the files to be a bit less intrusive (... and probably broke something in the process).

I hope you don't mind if I hijack this thread for some QnA's from time to time, or would you prefer IMs/other thread?

Link to comment
Share on other sites

David,

 

Good start.  Check my very first post in this thread and see whether you want to add some additional files or change the folder structure.

 

You aren't hijacking the thread if you ask questions related to the subject of the thread, so don't worry about it.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
×
×
  • Create New...