Jump to content

ekroemer

Member
  • Posts

    426
  • Joined

  • Last visited

Posts posted by ekroemer

  1. Sorry, I only now saw the question.

    I never tried that but I don't think there's any serious Epoch related stuff in there.

    With regard to the scripting language, DZMS should work on anything that is Arma2.

    You may get a number of errors whenever a weapon or vehicle that has been explicitely added for Epoch is referenced, but that can be overcome by simply removing those things from the corresponding lists.

    Yuo could look in the DZMS forums if the problem has been addressed there. If it works for the original it'll work for my mod.

  2. Map radius doesn't do a thing - all locations are defined manually.

    I guess for your Taviana/Origins you should uncomment the lines

    // Taviana / Origins
    // DZMSHotSpotsStatLocs = DZMSHotSpotsTaviBase + DZMSHotSpotsTaviOrigins;
    // DZMSRoadBlocksStatLocs = DZMSRoadBlocksTaviBase + DZMSRoadBlocksTaviOrigins;

    in DZMSHotSpotsConfig.sqf.

    And I don't know what you mean by "in config i change map tavi to taviana". Sure you are in the correct thread?

     

  3. It seems I'm too daft to load my modified player_monitor.sqm.

    In MPMission's init.sqf I'm calling custom\compiles.sqf, that one has

    player_monitor = compile preprocessFileLineNumbers "custom\AntiAmmoCheat\player_monitor.sqf";

    and that one has

    diag_log ("player_monitor.sqf: calling modified version of player_monitor.fsm");
    _id = [] execFSM "custom\AntiAmmoCheat\player_monitor.fsm";

    But I don't even see the diag_log from player_monitor.sqf, let alone the from the sqm.

    What am I doing wrong?

     

    Edit: got it: player_monitor is not only defined in compiles.sqf but also directly in init.sqf.

     

    Edit2: now I get a 'you have an outdated version of Epoch' when connecting - obviously the game does not like changing player_monitor....

     

    Edit3: tried replacing player_monitor from scratch, works now and the full ammo information persists until the very end....but the DB write at disconnect still only has full mags.

    Reason: server_onPlayerDisconnect has

    		// prevent saving more than 20 magazine items
    		_magazines = [(magazines _playerObj),20] call array_reduceSize;
    
    		[_playerObj,_magazines,true,true,_isplayernearby] call server_playerSync;
    

    in it and (magazines _playerObj) just fetches the classnames, not the ammo stats.

    Changing that to

    		// prevent saving more than 20 magazine items
    		//_magazines = [(magazines _playerObj),20] call array_reduceSize;
    		if ( (count (magazines _playerObj)) > 20 ) then {
    		  _magazines = [(magazines _playerObj),20] call array_reduceSize;
    		  [_playerObj,_magazines,true,true,_isplayernearby] call server_playerSync;
    		} else {
    		  [_playerObj,dayz_Magazines,true,true,_isplayernearby] call server_playerSync;
    		};

    finally seems to do the trick.

     

     

     

  4. I have modified server_playerSync to

    	if (_isNewGear || _forceGear) then {
    		//diag_log ("gear..."); sleep 0.05;
    
    		// build an alternative _magazine potentially skipping mags with less than full ammo
    		_kr_magazines = [];
    		{ 
    		  diag_log ("_magazines entry: " +str(_x)); 
              if (typeName _x == "ARRAY") then {
    		    _actMagClass = (_x select 0);
    			_actAmmo = (_x select 1);
    			_maxAmmo = getNumber (configFile >> "CfgMagazines">> _actMagClass >> "count");
    		    _chanceToDelete = 1.0 - _actAmmo/_maxAmmo;
    			diag_log (str(_actMagClass)+", chance to delete: " + str(_chanceToDelete));
    		  } else {
    		    _actMagClass = _x;
    		    _chanceToDelete = 0;
    		  };
    		  if ( random 1 > _chanceToDelete ) then {
    	 	    _kr_magazines set [count _kr_magazines, _actMagClass];
    		  };
    		} forEach _magazines;
    		diag_log ("_magazines: " + str(_magazines));
    		diag_log ("_kr_magazines: " + str(_kr_magazines));
    
    		_playerGear = [weapons _character, _kr_magazines];
    

    and that piece of code does what it should.

    I've also changed player_monitor.sqm and player_spawn_2.sqf commenting out the lines dayz_Magazines = [];

     

    But still server_playerSync sometimes is called with a parameter _magazines not containing the ammo count...I have yet to find from where.

     

    Another question: where is the transfer from the player's main gear to backpack or other storage handled?

  5. I tested a bit in server_playerSync.sqf, changing

    	if (_isNewGear || _forceGear) then {
    		//diag_log ("gear..."); sleep 0.05;
    		_playerGear = [weapons _character,_magazines];

    to

    	private ["_kr_magazines", "_chanceToDelete"];
        if (_isNewGear || _forceGear) then {
    		//diag_log ("gear..."); sleep 0.05;
    		_kr_magazines = [];
    		{ 
    		  diag_log ("_magazines entry: " +str(_x)); 
              if (typeName _x == "ARRAY") then {
    		    _chanceToDelete = 1;
    		  } else {
    		    _chanceToDelete = 0;
    		  };
    		  if ( random 1 > _chanceToDelete ) then {
    	 	    _kr_magazines set [count _kr_magazines, _x];
    		  };
    		} forEach _magazines;
    		diag_log ("_magazines: " +str(_magazines));
    		diag_log ("_kr_magazines: " +str(_kr_magazines));
    
    		_playerGear = [weapons _character, _kr_magazines];
    

    Up to a point that did what I expected, namely deleting all magazines not completely filled from the array:

    18:41:53 "_magazines: ["ItemPainkiller","ItemPainkiller","FoodCanFrankBeans",["100Rnd_762x51_M240",40],["100Rnd_762x51_M240",92],"100Rnd_762x51_M240","ItemBandage","ItemBandage","ItemBandage","ItemBandage","ItemBandage","ItemBandage","ItemBandage","15Rnd_9x19_M9SD"]"
    18:41:53 "_kr_magazines: ["ItemPainkiller","ItemPainkiller","FoodCanFrankBeans","100Rnd_762x51_M240","ItemBandage","ItemBandage","ItemBandage","ItemBandage","ItemBandage","ItemBandage","ItemBandage","15Rnd_9x19_M9SD"]"
    

    and propagating the new set of gear nicely into the DB.

     

    But: after a while, be it after picking up something or logging off, the variables _magazines (that is a parameter to server_playerSync) reverted to

    "100Rnd_762x51_M240", "100Rnd_762x51_M240", "100Rnd_762x51_M240"

    instead of the

    ["100Rnd_762x51_M240",40],["100Rnd_762x51_M240",92],"100Rnd_762x51_M240"

    it had a moment before, while, of course, in-game the mags are still only partially filled. (Of course that fits right in with my earlier impression that the DB, when a player is still in-game, sometimes, but not always shows the correct ammo status.

     

    So the fault lies within the routine calling server_playerSync.

    Which function, other than server_onPlayerDisconnect (that is not the culprit) calls server_playerSync?

    Edit: found a call in dayz_code\system\player_monitor.fsm (Action to "Initialized"). Quite interestingly here the _magazineArray seems to be set up containing the correct ammo count.

    //Primary Mags
    for "_i" from 109 to 120 do 
    {
    	_control = 	_dialog displayCtrl _i;
    	_item = 	gearSlotData _control;
    	_val =		gearSlotAmmoCount _control;
    	_max = 		getNumber (configFile >> "CfgMagazines" >> _item >> "count");
    	if (_item != "") then {
    		if (_val != _max) then {
    			_magazineArray set [count _magazineArray,[_item,_val]];
    		} else {
    			_magazineArray set [count _magazineArray,_item];
    		};
    	};
    };
    

    So, when, where and why does that method fail or where is yet another call to server_playerSync?

     

    Edit2: Found another one, I think. dayz_code\system\player_spawn_2.sqf has a block

    	if (dayz_unsaved) then {
    		if ((time - dayz_lastSave) > DZE_SaveTime) then {
    			_dayzMags = if (!isNil "dayz_Magazines" && {typeName dayz_Magazines == "ARRAY"} && {count dayz_Magazines > 0}) then {dayz_Magazines} else {magazines player};
    			PVDZE_plr_Save = [player,_dayzMags,false,false];
    			publicVariableServer "PVDZE_plr_Save";
    			dayz_unsaved = false;
    			dayz_lastSave = time;
    			dayz_Magazines = [];
    		};
    	};

    Now I don't know for sure what player_spawn_2 does but it seems to care for a periodic player status update.

     

    Here's what I gleaned about the mechanisms involved:

    • server_playerSync writes player state to DB and is called with an argument _magazines
    • server_playerSync is linked via addPublicVariableEventHandler to a public variable PVDZE_plr_Save
    • the magazine part of this variable is defined (correctly) in player_monitor.fsm where, simultaneously a global variable dayz_Magazines is defined but emptied afterwards. (does not make 100% sense to use it and then to delete it)
    • there is also dayz_code\compile\player_gearSync.sqf which defines dayz_Magazines in the same way that player_monitor.fsm does

    The problem is the following:

    • while player_gearSync.sqf and player_monitor.fsm play nice and generate the correct magazine information,
    • server_playerSync does not use it because dayz_Magazines has been set to [].
    • Instead magazines player ist used and that generates only full mags.

     

    Looking at all occurrences of dayz_Magazines I don't understand why it is set to [].

    The only location where it is referenced without being set locally, before, is in player_spawn_2,sqf and there, imo, its value of [] results in information loss.

  6. Hi all,

     

    I fail to find a sqf command that will fetch me the capacity of a magazine, something like

    _classname = "100Rnd_762x51_M240";
    _maxRnd = GetAmmoCapacity(_classname);

    with a result of 100 in the _maxRnd variable.

    Surely there must be a way to do this without resorting to string analysis.

  7. I wouldn't dream of trying lowlevel changes ;-)

    But I think it will be possible to identify the entry ["30Rnd_556x45_Stanag",5] in server_playerSync's variables _playerGear and _playerBackp and to delete it there before it can be written to DB. Same for any object inventory.

    Of course I'd like to make this deletion dependent on the actual amount of ammo left in relation to the full amount - but that's a secondary problem.

    Regarding the backpack: here, I guess, the save-to-DB procedure is the same as for storage objects, storing only classname information. Nevertheless, in-game the round count is available: you can't refill a magazine by putting it into storage and getting it out, again without a server restart (that forces DB read instead of internal information use).

     

  8. I'm not sure where to post the feedback vbawol invited us to in http://epochmod.com/forum/index.php?/topic/37250-website-and-forum-migrated-and-updated/.

    • It seems one cannot copy&paste from forum posts anymore, I see this as a major drawback (even if I suspect that's a 'feature').
    • I don't like the nervous context sensitive behaviour either - just hover your mouse above the 'share this post' icon and you'll get the nicest flash on/off effects (at least with my connection, may be a performance issue).
    • The SW seems optimized for a 'Question'+'Answers' approach, not for ongoing discussions on a continous thread timeline. "Upvoting" a post to mark a particularly helpful contribution will lead to have this 'answer' sorted on top by default, thus severing any relations to prior posts that provide context. Imo 'sort by time' instead of 'sort by votes' should be default.
  9. That's a nice link :-)

    I think, when I've time (not before the weekend), I'll activate some of the diag_logs, e.g in server_playerSync

    		_playerGear = [weapons _character,_magazines];
    		//diag_log ("playerGear: " +str(_playerGear));

    and look at the format of _playerGear.

    Then I'll hopefully find some commands to dissect that thing.

  10. I know.

    I detailed that to show that your claim ["mag",5] meant 5 mags of type "mag" did not apply here.

    We concur that ammo count is not normally written into DB, but if you have a look at character_data for an in-game player you'll see that, sometimes, it is (but apparently never after logout).

    And, anyhow, the point is moot because I want to access the information in-game, not from the DB.

  11. That is correct for object_data.inventory, but I'm quite sure that in character_data multiple items in the players inventory (not backpack!) are listed separately, leading to substrings like

    ["mag", 3], ["mag", 1], "mag", "mag", "mag"

    describing 3 full and 2 partially filled mags of the same type.

     

    Thinking about it, the syntax for object_data.inventory isn't [["magA", numA], ["magB", numB]] either, but

    [["magA", "magB"],[numA, numB]].

     

    But be that as it may, fact is that in-game the information about rounds remaining in a partially used mag is present and thus there has to be a way of accessing it before it get's pressed into DB-format.

  12. That's right but imo no problem.

    Shamelessly citing myself (bah, the new forum SW seems to disallow copy&paste from posts?), http://epochmod.com/forum/index.php?/topic/2704-ammo-mags-refilling-after-relog/&do=findComment&comment=22276, while a player is in game the database record shows a rather involved syntax, e.g. ["100Rnd_762x54_PK",5] while a full mag simply appears as "100Rnd_762x54_PK" (no array).

    That means that in principle the ammo information is available.

    I expect (will test on weekend, if I have time) that the inventory array in the sqfs shows exactly this information, that is then discarded when writing to DB.

    I don't want to try to preserve the whole information - if that would be within my abilities it would have been done long ago.

    But it should be possible to code something that on average will have the same effect - random choice between full and no mag, the chance depending on the fill ratio

    E.g. a full 100rnd mag won't disappear ever, with 99rnds in it it has a 1% chance of not being saved to DB, with 1rnd the chance of disappearing would be 99%.

    To be clear: I'm only talking about manipulating the saving of the current in-game status to DB (relevant at the last writing time, for a character that's at logut). There'll be nothing changed in-game.

  13. Thanks!

    server_playerSync looks right for saving gear and backpack to DB, and server_updateObject.sqf:_object_inventory seems to handle object inventories.

    Now the 'only' thing one would have to do, would be to analyze the magazine variable (hopefully it's an array, not a string), identify elements signifying partially filled mags (assuming at this place this information is still present) and deleting them with a suitable probability RndLeft/RndMax.

    I'm still afraid that exceeds my scripting ability....any hint on how to get the number of rounds in a mag from it's classname?

     

     

  14. If I understand you correctly, the scripts that fill players' or objects' inventory at spawn time are flawed?

    Could you be more specific about where that happens?

    Also, while I've on occasion seen partially filled mag entries in the DB, I believe that has only been while the character was in-game. A logged off character seems to have full mag DB entries, only, so tweaking character setup won't be enough because the DB entry is already flawed.

  15. Hi there,

    imo one of the most annoying things with A2 Epoch is that you have infinite ammo. Just keep a single bullet in the mag before reload, re-log and all mags are full, again. The same holds for any storage: put partially filled mags in and after a restart the magical ammo fairy has come.

    That's a shame, especially on PvE servers where ammo should be a resource you have to scrounge for.

    So, is there a mod out to prevent this?

    Alternatively, what could be done about it. I could imagine a workaround that

    • would either delete a partially filled mag or, better
    • delete it with a probability of bullets_still_in_mag / mag_capacity
    • whenever a player logs out or
    • puts ammo into another storage.

    But this exceeds my scripting ability, especially

    • where to put this functionality (there'll be a OnPlayerLogout, but where to catch all mag transfer into other storage?)
    • how to get current state and capacity of all ammo items in the gear.

    Please tell me, someone has done this, already! ;)

  16. Raymix, as Zed is trying to define player skin by setting DZE_defaultSkin, do you know where this variable is referenced?

     

    If, for example,

    • we need to getVariable "humanity" after the player object has been set up (by player_monitor, right?)
    • and only then can define DZE_defaultSkin
    • but DZE_defaultSkin is already evaluated in player_monitor

    then changes made to it would not be processed.

     

    In that case changing DZE_defaultSkin won't be a feasible method and one would have to fallback to changing the skin later (something with player_morph?).

  17. DId you see specifically the bit of using spawn for the script to wait till player_monitor has finished its work?

     

    As far as I understand it from that post, everything called with execVM is basically started in a parallel thread that may well be still running when the ones started after have long finished.

  18. I think the problem is that the loadout.sqf is called early in init.sqf, aiming to change some DZE_* default variables.

     

    I suppose at this point 'player' has not been set up completely (him being dead and in need of a new character does not help), meaning his humanity has not yet been read from the DB and been added to the in-game entity 'player' via 'setvariable'. Thus the getvariable returns empty for 'humanity'.

     

    The custom loadoud scripts out there seem to aim for a UID based loadout, for this there seems to be a function: (getPlayerUID player).

     

    Other references:

     

    Here http://opendayz.net/threads/humanity-based-loadouts.10447/#post-90311 an ugly dll call is used to fetch the humanity from the DB.

     

    Here suspects the same issue I did above and a solution is proposed in the posts below. But then you had already posted there....and it does not cover skins.

     

    The location of the loadout.sqf call relative to the call to player_monitor seems crucial.

    I don't know when the changed DZE_* variables are referenced, so simply placing the loadout.sqf after player_monitor (before spawn selection) might be too late.

    Might calling player_monitor twice (the first time just to attach the humanity) work?

  19. Here are changes to fn_selfactions and origins_removeActions that allow you

    • to build more than one building of a type, e.g. 2 large garages and
    • to build without the need to have lower tier buildings before you can build higher levels.

     

    Excerpt from fn_selfactions.sqf:

    if(DZE_Origins_Building_System) then {
        if(isnil "s_player_build_origins_H1")    then {s_player_build_origins_H1 = -1;};
        if(isnil "s_player_build_origins_B1")    then {s_player_build_origins_B1 = -1;};
        if(isnil "s_player_build_origins_H2")    then {s_player_build_origins_H2 = -1;};
        if(isnil "s_player_build_origins_B2")    then {s_player_build_origins_B2 = -1;};
        if(isnil "s_player_build_origins_H3")    then {s_player_build_origins_H3 = -1;};
        if(isnil "s_player_build_origins_B3")    then {s_player_build_origins_B3 = -1;};
        if(isnil "s_player_build_origins_SG")    then {s_player_build_origins_SG = -1;};
        if(isnil "s_player_build_origins_LG")    then {s_player_build_origins_LG = -1;};
        if(isnil "s_player_build_origins_KING")  then {s_player_build_origins_KING = -1;};
        if(isnil "s_player_build_origins_SH")    then {s_player_build_origins_SH = -1;};
    
        if(isnil "s_player_origins_unlock") then {s_player_origins_unlock = -1;};
        if(isnil "s_player_origins_stronghold_doors") then {s_player_origins_stronghold_doors = -1;};
    
        _cursorTarget = cursorTarget;
        if (!isNull _cursorTarget) then {
            _typeOfCursorTarget = (typeOf _cursorTarget);
            if(_typeOfCursorTarget == DZE_Origins_Container ) then {
                if((player distance _cursorTarget) < DZE_Origins_Build_Distance) then {
    
                    private["_humanity","_houselevel","_humanityNeed","_actionText","_classname","_neededMaterials"];
    
                    _humanity = player getVariable["humanity",0];
    
                    {
                      _houselevel      = _x select 0;
                      _humanityNeed    = _x select 1;
                      _actionText      = _x select 2;
                      _classname       = _x select 3;
                      _neededMaterials = _x select 4;
    
                      if((_humanityNeed > 0 && _humanity >= _humanityNeed) || (_humanityNeed < 0 && _humanity <= _humanityNeed)) then {
    
                        if(_houselevel in ["H1"] ) then {
                          if(s_player_build_origins_H1 < 0) then {
                            s_player_build_origins_H1 = player addAction ["Build " + _actionText, "origins\player_build.sqf", [_cursorTarget, _houselevel, _classname, _neededMaterials, _actionText]];
                          };                     
                        };
                        if(_houselevel in ["H2"] ) then {
                          if(s_player_build_origins_H2 < 0) then {
                            s_player_build_origins_H2 = player addAction ["Build " + _actionText, "origins\player_build.sqf", [_cursorTarget, _houselevel, _classname, _neededMaterials, _actionText]];
                          };
                        };
                        if(_houselevel in ["H3"] ) then {
                          if(s_player_build_origins_H3 < 0) then {
                            s_player_build_origins_H3 = player addAction ["Build " + _actionText, "origins\player_build.sqf", [_cursorTarget, _houselevel, _classname, _neededMaterials, _actionText]];
                          };
                        };
                        if(_houselevel in ["B1"] ) then {
                          if(s_player_build_origins_B1 < 0) then {
                            s_player_build_origins_B1 = player addAction ["Build " + _actionText, "origins\player_build.sqf", [_cursorTarget, _houselevel, _classname, _neededMaterials, _actionText]];
                          };
                        };
                        if(_houselevel in ["B2"] ) then {
                          if(s_player_build_origins_B2 < 0) then {
                            s_player_build_origins_B2 = player addAction ["Build " + _actionText, "origins\player_build.sqf", [_cursorTarget, _houselevel, _classname, _neededMaterials, _actionText]];
                          };
                        };
                        if(_houselevel in ["B3"] ) then {
                          if(s_player_build_origins_B3 < 0) then {
                            s_player_build_origins_B3 = player addAction ["Build " + _actionText, "origins\player_build.sqf", [_cursorTarget, _houselevel, _classname, _neededMaterials, _actionText]];
                          };
                        };
                        if(_houselevel in ["SGH","SGB"] ) then {
                          if(s_player_build_origins_SG < 0) then {
                            s_player_build_origins_SG = player addAction ["Build " + _actionText, "origins\player_build.sqf", [_cursorTarget, _houselevel, _classname, _neededMaterials, _actionText]];
                          };
                        };
                        if(_houselevel in ["LGH","LGB"] ) then {
                          if(s_player_build_origins_LG < 0) then {
                            s_player_build_origins_LG = player addAction ["Build " + _actionText, "origins\player_build.sqf", [_cursorTarget, _houselevel, _classname, _neededMaterials, _actionText]];
                          };
                        };
                        if(_houselevel in ["KINGH","KINGB"] ) then {
                          if(s_player_build_origins_KING < 0) then {
                            s_player_build_origins_KING = player addAction ["Build " + _actionText, "origins\player_build.sqf", [_cursorTarget, _houselevel, _classname, _neededMaterials, _actionText]];
                          };
                        };
                        if(_houselevel in ["SHH","SHB"] ) then {
                          if(s_player_build_origins_SH < 0) then {
                            s_player_build_origins_SH = player addAction ["Build " + _actionText, "origins\player_build.sqf", [_cursorTarget, _houselevel, _classname, _neededMaterials, _actionText]];
                          };
                        };
    
                      };
    
                    } forEach DZE_Origins_Build_HousesGarages;
                } else {
                    [1] call origins_removeActions;
                };
            };
    
    

     

    The corresponding origins_removeActions.sqf:

    private["_type"];
    _type = _this select 0;
    if(_type == 0 || _type == 1) then {
    	player removeAction s_player_build_origins_H1;
    	s_player_build_origins_H1 = -1;
    	player removeAction s_player_build_origins_H2;
    	s_player_build_origins_H2 = -1;
    	player removeAction s_player_build_origins_H3;
    	s_player_build_origins_H3 = -1;
    	player removeAction s_player_build_origins_B1;
    	s_player_build_origins_B1 = -1;
    	player removeAction s_player_build_origins_B2;
    	s_player_build_origins_B2 = -1;
    	player removeAction s_player_build_origins_B3;
    	s_player_build_origins_B3 = -1;
    	player removeAction s_player_build_origins_SG;
    	s_player_build_origins_SG = -1;
    	player removeAction s_player_build_origins_LG;
    	s_player_build_origins_LG = -1;
    	player removeAction s_player_build_origins_KING;
    	s_player_build_origins_KING = -1;
    	player removeAction s_player_build_origins_SH;
    	s_player_build_origins_SH = -1;
    };
    if(_type == 0 || _type == 2) then {
    	player removeAction s_player_origins_unlock;
    	s_player_origins_unlock = -1;
    };
    if(_type == 0 || _type == 3) then {
    	player removeAction s_player_origins_stronghold_doors;
    	s_player_origins_stronghold_doors = -1;
    };
    sleep 2;
    true
    

×
×
  • Create New...