Skip to content

Issues with storing variables on an item OnClientLeave

I'm trying to set up persistent saving for my module. Specifically, I'm trying to save the player's location and health value between resets.

I can't make any sense of this. Supposedly, the issue with OnClientLeave is fixed with EE:

"OnClientLeave event is now called before the creature is physically removed from the area, instead of after, to allow scripting to determine the creature’s position as it leaves."

"... if you add items or save local variables during this event be sure to call ExportSingleCharacter explicitly before the event end."

So, how come I can't get the game to save the local variables I set on an item in the player's inventory? Here's the code...

OnClientLeave

void main()
{
object oPC = GetExitingObject();
location myLocation = GetLocation(oPC);
object playerKey = GetItemPossessedBy(oPC, "PlayerKey");

int PCCount = GetLocalInt(oArea,"PCCount");
SetLocalInt(oArea,"PCCount",PCCount - 1);

if (GetIsObjectValid(playerKey))
{
SetLocalInt(playerKey, "missingHP", GetMaxHitPoints(oPC) - GetCurrentHitPoints(oPC)); // Store how much health we are missing. Damage me when I return.
SetLocalLocation(playerKey, "playerLocation", myLocation);
}

ExportSingleCharacter(oPC);
}

And naturally, I have code calling these variables OnClientEnter. They work when stored on the player, but I want to store it on an item for persistence over server resets. ExportSingleCharacter() should be updating/overwriting the player file (the server is server vault), and therefore the item "PlayerKey" as well, thus storing the updated information, no? But it clearly isn't, I can't seem to get this to work no matter what I do. I can update the player's information through any other event so it seems to be some issue with OnClientLeave. Any help would be appreciated.

Comments

  • SvirfPostingSvirfPosting Member Posts: 6
    I packed the same script into code ran by simply typing /save, and it works. Clearly the issue is that the game is not updating the player's key when they leave, but this is apparently not an issue with EE when used in conjunction with ExportSingleCharacter() which I'm doing, so... ???
  • meaglynmeaglyn Member Posts: 151
    When you say it's not working what do you mean? On your entry script is missingHP visible? How are you retrieving the location? Locations may not be valid across server resets since the area is in there as an object which could be different. You said it works if saving on the PC directly so maybe that's not it.

    Do you know the playerKey object is valid?

    You should probably take out the two oArea lines as those should just be in the area exit handler which will also run and are not needed here. Also oArea is not defined in the script you showed so it won't compile.

    Anyway just a couple of thoughts. Good luck. PW scripting is a lot of fun :)
  • SvirfPostingSvirfPosting Member Posts: 6
    ... I'm not sure why the script I pasted here doesn't show oArea being defined, it is in the real thing (idk, not getting enough coffee). Thanks for letting me know the area leave event will always fire, I didn't realize that. As for it not working, what I mean is the object tagged PlayerKey is not updating its variables despite me clearly telling it to in the script. This seems to be an issue related to OnClientLeave as it will work fine if called elsewhere (like from my script checking if the player types /save).

    For example, player types /save, these two lines are ran:
    SetLocalInt(playerKey, "missingHP", GetMaxHitPoints(oPC) - GetCurrentHitPoints(oPC)); // Store how much health we are missing. Damage me when I return.
    SetLocalLocation(playerKey, "playerLocation", myLocation);

    So when the player logs back in, even after a reset, their HP is down if they'd lost HP before logging off, and they appear in the location they were at last. It seems natural to me to want to update these variables when a player leaves (losing HP stops you cheesing mechanics, and people like to return to where they were last upon rejoining a server). But OnClientLeave just isn't cooperating with me despite me firing ExportSingleCharacter at the end of the event (which, as far as I can tell, should be force updating the key in their inventory, but it just... isn't). From what I've read what I'm looking to do shouldn't be possible pre-EE, but this is most definitely made in EE where it is explictly stated that it is possible to call the player's location during the OnClientLeave event, so I'm lost.
  • SvirfPostingSvirfPosting Member Posts: 6
    edited June 2021
    Last post was randomly deleted, retyping up a sec.
  • SvirfPostingSvirfPosting Member Posts: 6
    edited June 2021
    Uhh, okay, my post just randomly disappeared...

    oArea is defined in the actual script, I have no idea why it wasn't there in the block I posted, mustn't be getting enough coffee. Thanks for letting me know the area exit event always fires, I didn't know that, so the oArea stuff is indeed redundant. As for it not working, I mean the variables on the object tagged "PlayerKey" are not being updated despite my script explictly calling for that. When the player types /save, these two lines fire:

    SetLocalInt(playerKey, "missingHP", GetMaxHitPoints(oPC) - GetCurrentHitPoints(oPC)); // Store how much health we are missing. Damage me when I return.
    SetLocalLocation(playerKey, "playerLocation", myLocation);

    Now, when they log back on, even between resets, their location and current HP value is called. For whatever reason I cannot get these values to update during the OnClientLeave event, but I really want it to happen there as it's the most obvious time to store the player's details (stops them cheesing a fight, lets them return to exactly where they were when they last left etc). From what I've read, what I'm trying to do isn't possible pre-EE (issues with getting the player's location etc), but this is post-EE. And yeah, PlayerKey is definitely valid.

    On NWN Lexicon it says...

    "However, OnClientLeave event is still after the automatic server call to save the Character file. Therefore if you add items or save local variables during this event be sure to call ExportSingleCharacter explicitly before the event end."

    So, this would explain it if... I wasn't calling ExportSingleCharacter? Which I am, so I don't get why it won't work.
  • SvirfPostingSvirfPosting Member Posts: 6
    My crude solution for the time being is to update the players' key values on heartbeat for now. It seems a lot less optimal than simply updating these values when the player leaves, but modifying the player's inventory in the OnClientLeave event doesn't seem possible.
  • DazDaz Member Posts: 127
    Alas, OnClientLeave is too late for anything to get saved to the .bic file.
  • DJ_WoWDJ_WoW Member Posts: 51
    Gooday to ya,

    I run a pseudo-heartbeat with a DelayCommand calling a script that saves the location and current hit points and then calls itself to simulate the heartbeat. On client enter I read the location and saved hit points and damage the PC for the difference of saved hit points and current hit points and then initiate the DelayCommand script. I have not seen any lag on server. But I also do not have a lot of players.

    DJ-WoW
  • ForSeriousForSerious Member Posts: 466
    I know for sure that SetCampaignInt works for your use case, because that's how I'm doing it. You have to have some sort of unique name system in addition to it. I do not think that passing the player object into the last parameter works as expected.

    Have you tried using SKIN_SupportGetSkin(oPC); found in #include "x3_inc_skin"?
    If that doesn't work, I think you will have to switch to Campaign variables.
Sign In or Register to comment.