Author Topic: persistant storage issue  (Read 353 times)

Legacy_Krevett

  • Full Member
  • ***
  • Posts: 203
  • Karma: +0/-0
persistant storage issue
« on: August 10, 2012, 02:07:02 pm »


               Hi guys! I'm trying to setup a client onenter and on exit script that track PC status for my module but I ran in a small issue.
If I enter, damage my PC and then save the database manually via a player tool there's no issue... But if I enter, damage my PC and then exit (letting the onclien exit script save data) I log back with full health ':pinched:'.

here are the scripts and functions:

OnClientEnter()

#include "inc_database"
void main()
{
object oPC = GetEnteringObject();
if (!GetIsDM(oPC) && NBDE_GetCampaignInt(DATA_NAME, "Newbie", oPC) == TRUE) DB_RestorePlayerStatus(oPC);
SetPlotFlag(oPC, FALSE);
SetImmortal(oPC, FALSE);
}

OnClientExit()

#include "inc_database"
void main()
{
object oPC = GetExitingObject();
DB_SavePCStatus(oPC);
}

The functions:

void DB_SavePCStatus(object oPC, string sDatabase = DATA_NAME)
{
int nHP;
int bDead;
int nLastrest;
int nFatigue;
int nIvresse;
int nMort;
int nTues;
int nHD;
float fCR;
string sNom;
location lLocation;
location lDeathloc;
location lLasttown;
if (!GetIsDM(oPC) || !GetIsDMPossessed(oPC))
nHP = GetCurrentHitPoints(oPC);
bDead = GetIsDead(oPC);
nLastrest = GetTotalHours() - GetLocalInt(oPC, "lastrest");
nFatigue = GetLocalInt(oPC, "fatigue");
nIvresse = GetLocalInt(oPC, "ivresse");
nMort = GetLocalInt(oPC, "NW_L_PLAYER_DIED");
nTues = GetLocalInt(oPC, "nombretues");
nHD = GetLocalInt(oPC, "HD");
fCR = GetLocalFloat(oPC, "CR");
sNom = GetLocalString(oPC, "nommeilleur");
lLocation = GetLocation(oPC);
lDeathloc = GetLocalLocation(oPC, "ls_death_loc");
lLasttown = GetLocalLocation(oPC, "ls_town_loc");
NBDE_SetCampaignInt(sDatabase, "Current_HP", nHP, oPC);
NBDE_SetCampaignInt(sDatabase, "Dead", bDead, oPC);
NBDE_SetCampaignInt(sDatabase, "Lastrest", nLastrest, oPC);
NBDE_SetCampaignInt(sDatabase, "Fatigue", nFatigue, oPC);
NBDE_SetCampaignInt(sDatabase, "Ivresse", nIvresse, oPC);
NBDE_SetCampaignInt(sDatabase, "Morts", nMort, oPC);
NBDE_SetCampaignInt(sDatabase, "Tues", nTues, oPC);
NBDE_SetCampaignInt(sDatabase, "Best_HD", nHD, oPC);
NBDE_SetCampaignFloat(sDatabase, "Best_CR", fCR, oPC);
NBDE_SetCampaignString(sDatabase, "Best_Nom", sNom, oPC);
NBDE_SetCampaignLocation(sDatabase, "Location", lLocation, oPC);
NBDE_SetCampaignLocation(sDatabase, "Deathloc", lDeathloc, oPC);
NBDE_SetCampaignLocation(sDatabase, "Lasttown", lLasttown, oPC);
ExportSingleCharacter(oPC);
}

void DB_RestorePlayerStatus(object oPC, string sDatabase = DATA_NAME)
{
object oArea = GetArea(oPC);
if (!GetIsObjectValid(oArea))
 {
 DelayCommand(0.1, DB_RestorePlayerStatus(oPC, sDatabase));
 return;
 }
int nHPmax = GetMaxHitPoints(oPC);
int nHP = NBDE_GetCampaignInt(sDatabase, "Current_HP", oPC);
int bDead = NBDE_GetCampaignInt(sDatabase, "Dead", oPC);
int nLastrest = GetTotalHours() - NBDE_GetCampaignInt(sDatabase, "Lastrest", oPC);
int nFatigue = NBDE_GetCampaignInt(sDatabase, "Fatigue", oPC);
int nIvresse = NBDE_GetCampaignInt(sDatabase, "Ivresse", oPC);
int nMort = NBDE_GetCampaignInt(sDatabase, "Morts", oPC);
int nTues = NBDE_GetCampaignInt(sDatabase, "Tues", oPC);
int nHD = NBDE_GetCampaignInt(sDatabase, "Best_HD", oPC);
float fCR = NBDE_GetCampaignFloat(sDatabase, "Best_CR", oPC);
string sNom = NBDE_GetCampaignString(sDatabase, "Best_Nom", oPC);
location lLocation = NBDE_GetCampaignLocation(sDatabase, "Location", oPC);
location lDeathloc = NBDE_GetCampaignLocation(sDatabase, "Deathloc", oPC);
location lLasttown =  NBDE_GetCampaignLocation(sDatabase, "Lasttown", oPC);
effect eEffect;
RebuildJournalQuestEntries(oPC);
DelayCommand(0.1, SetLocalInt(oPC, "lastrest", nLastrest));
SetLocalInt(oPC, "fatigue", nFatigue);
SetLocalInt(oPC, "ivresse", nIvresse);
SetLocalInt(oPC, "NW_L_PLAYER_DIED", nMort);
SetLocalInt(oPC, "nombretues", nTues);
SetLocalInt(oPC, "HD", nHD);
SetLocalFloat(oPC, "CR", fCR);
SetLocalString(oPC, "nommeilleur", sNom);
SetLocalLocation(oPC, "ls_death_loc", lDeathloc);
SetLocalLocation(oPC, "ls_town_loc", lLasttown);
if (nFatigue == 1)
 {
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_STRENGTH, 2));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 2));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 SendMessageToPC(oPC, "Vous vous sentez fatigue, un peu de repos serait profitable!");
 }
else if (nFatigue == 2)
 {
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_STRENGTH, 4));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 4));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 eEffect = ExtraordinaryEffect(EffectMovementSpeedDecrease(20));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 SendMessageToPC(oPC, "Vous vous sentez epuise, un peu de repos serait profitable!");
 }
else if (nFatigue == 3)
 {
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_STRENGTH, 6));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 6));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 eEffect = ExtraordinaryEffect(EffectMovementSpeedDecrease(40));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 SendMessageToPC(oPC, "Vous vous sentez a bout de forces, un peu de repos serait profitable!");
 }
if (GetIsObjectValid(GetAreaFromLocation(lLocation)))
 {
 AssignCommand(oPC, ClearAllActions());
 AssignCommand(oPC, ActionJumpToLocation(lLocation));
 }
if (nHP != nHPmax && bDead == FALSE) DelayCommand(0.1, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nHPmax - nHP, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_TWENTY), oPC));
if (bDead == TRUE)
 {
 SetLocalInt(oPC, "Auto_Dead", TRUE);
 DelayCommand(0.1, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), oPC));
 }
CheckIvresse(oPC);
SendMessageToPC(oPC, "Session restaurée!");
}

Note that I use nbde extensions and the database is Flushed via another script every minute...

I can't find what's going on as if the GetCurrentHP on client exit returns maxHP every time!
               
               

               


                     Modifié par Krevett, 10 août 2012 - 01:08 .
                     
                  


            

Legacy_acomputerdood

  • Sr. Member
  • ****
  • Posts: 378
  • Karma: +0/-0
persistant storage issue
« Reply #1 on: August 10, 2012, 02:25:53 pm »


               i think there's the case where when the onclientexit script fires, then the player doesn't actually exist anymore and therefore cannot have an inventory item to save the state to.


ahhh yes, here it is:

http://www.nwnlexico...odatabases.html

"- Since a player's health is only tracked when he rests/dies/resurrects, you probably want to add some code to periodically save a players status. Unfortunatelly the OnClientExit ScriptHook does not work for this, (the player object does not hold a valid location anymore,) so you need to come up with other solutions (i.e. periodic saves, save triggers in your world, etc)."
               
               

               


                     Modifié par acomputerdood, 10 août 2012 - 01:30 .
                     
                  


            

Legacy_Krevett

  • Full Member
  • ***
  • Posts: 203
  • Karma: +0/-0
persistant storage issue
« Reply #2 on: August 10, 2012, 03:16:11 pm »


               Ok thanks for the info... Slightly modified the system, now if I log back after a server reset all my PC infos are fully restored. But if I log out and then log back in without a server reset my PC's full hp are restored??? Has anyone ever encountered this problem?

Edit:
This is very strange only HP are not remembered if logging out and back in without a server reset... Everything else is restored!
What is even stranger is that HP are remembered when the server is reset!!!

I really don't understand where is the problem... (I don't use client exit anymore but the module is saved every minute, and PC status are saved upon resting, death, respawning, level up and area enter...)
               
               

               


                     Modifié par Krevett, 10 août 2012 - 03:52 .
                     
                  


            

Legacy_Krevett

  • Full Member
  • ***
  • Posts: 203
  • Karma: +0/-0
persistant storage issue
« Reply #3 on: August 10, 2012, 08:10:46 pm »


               Ok, here's what I've done for now but I still don't understand why it doesn't work without a server reset...

OnClientEnter

#include "inc_database"
void main()
{
object oPC = GetEnteringObject();
if (GetLocalInt(GetModule(), "PW") == TRUE && NBDE_GetCampaignInt(DATA_NAME, "ExistingPlayer", oPC) == TRUE && !GetIsDM(oPC))
 {
 SetPlotFlag(oPC, FALSE);
 SetImmortal(oPC, FALSE);
 DelayCommand(0.2, DB_RestorePlayerStatus(oPC));
 }
}

The "Save" function

void DB_SavePCStatus(object oPC, string sDatabase = DATA_NAME)
{
object oModule;
string sKey;
int nHP;
int bDead;
int nLastrest;
int nFatigue;
int nIvresse;
int nMort;
int nTues;
int nHD;
float fCR;
string sNom;
location lLocation;
location lDeathloc;
location lLasttown;
if (!GetIsDM(oPC) || !GetIsDMPossessed(oPC))
oModule = GetModule();
sKey = GetPCPlayerName(oPC) + GetName(oPC);
nHP = GetCurrentHitPoints(oPC);
bDead = GetIsDead(oPC);
nLastrest = GetTotalHours() - GetLocalInt(oPC, "lastrest");
nFatigue = GetLocalInt(oPC, "fatigue");
nIvresse = GetLocalInt(oPC, "ivresse");
nMort = GetLocalInt(oPC, "NW_L_PLAYER_DIED");
nTues = GetLocalInt(oPC, "nombretues");
nHD = GetLocalInt(oPC, "HD");
fCR = GetLocalFloat(oPC, "CR");
sNom = GetLocalString(oPC, "nommeilleur");
lLocation = GetLocation(oPC);
lDeathloc = GetLocalLocation(oPC, "ls_death_loc");
lLasttown = GetLocalLocation(oPC, "ls_town_loc");
SetLocalInt(oModule, sKey + "Present", TRUE);
SetLocalInt(oModule, sKey + "Current_HP", nHP);
SetLocalInt(oModule, sKey + "Dead", bDead);
NBDE_SetCampaignInt(sDatabase, "Current_HP", nHP, oPC);
NBDE_SetCampaignInt(sDatabase, "Dead", bDead, oPC);
NBDE_SetCampaignInt(sDatabase, "Lastrest", nLastrest, oPC);
NBDE_SetCampaignInt(sDatabase, "Fatigue", nFatigue, oPC);
NBDE_SetCampaignInt(sDatabase, "Ivresse", nIvresse, oPC);
NBDE_SetCampaignInt(sDatabase, "Morts", nMort, oPC);
NBDE_SetCampaignInt(sDatabase, "Tues", nTues, oPC);
NBDE_SetCampaignInt(sDatabase, "Best_HD", nHD, oPC);
NBDE_SetCampaignFloat(sDatabase, "Best_CR", fCR, oPC);
NBDE_SetCampaignString(sDatabase, "Best_Nom", sNom, oPC);
NBDE_SetCampaignLocation(sDatabase, "Location", lLocation, oPC);
NBDE_SetCampaignLocation(sDatabase, "Deathloc", lDeathloc, oPC);
NBDE_SetCampaignLocation(sDatabase, "Lasttown", lLasttown, oPC);
ExportSingleCharacter(oPC);
}

The "Restore" function

void DB_RestorePlayer(object oPC, string sDatabase = DATA_NAME)
{
int nHP;
int bDead;
int nHPmax = GetMaxHitPoints(oPC);
object oModule = GetModule();
string sKey = GetPCPlayerName(oPC) + GetName(oPC);
if (GetLocalInt(oModule, sKey + "Present") == TRUE)
 {
 nHP = GetLocalInt(oModule, sKey + "Current_HP");
 bDead = GetLocalInt(oModule, sKey + "Dead");
 }
else
 {
 nHP = NBDE_GetCampaignInt(sDatabase, "Current_HP", oPC);
 bDead = NBDE_GetCampaignInt(sDatabase, "Dead", oPC);
 }
int nLastrest = GetTotalHours() - NBDE_GetCampaignInt(sDatabase, "Lastrest", oPC);
int nFatigue = NBDE_GetCampaignInt(sDatabase, "Fatigue", oPC);
int nIvresse = NBDE_GetCampaignInt(sDatabase, "Ivresse", oPC);
int nMort = NBDE_GetCampaignInt(sDatabase, "Morts", oPC);
int nTues = NBDE_GetCampaignInt(sDatabase, "Tues", oPC);
int nHD = NBDE_GetCampaignInt(sDatabase, "Best_HD", oPC);
float fCR = NBDE_GetCampaignFloat(sDatabase, "Best_CR", oPC);
string sNom = NBDE_GetCampaignString(sDatabase, "Best_Nom", oPC);
location lLocation = NBDE_GetCampaignLocation(sDatabase, "Location", oPC);
location lDeathloc = NBDE_GetCampaignLocation(sDatabase, "Deathloc", oPC);
location lLasttown =  NBDE_GetCampaignLocation(sDatabase, "Lasttown", oPC);
effect eEffect;
RebuildJournalQuestEntries(oPC);
SetLocalInt(oPC, "lastrest", nLastrest);
SetLocalInt(oPC, "fatigue", nFatigue);
SetLocalInt(oPC, "ivresse", nIvresse);
SetLocalInt(oPC, "NW_L_PLAYER_DIED", nMort);
SetLocalInt(oPC, "nombretues", nTues);
SetLocalInt(oPC, "HD", nHD);
SetLocalFloat(oPC, "CR", fCR);
SetLocalString(oPC, "nommeilleur", sNom);
SetLocalLocation(oPC, "ls_death_loc", lDeathloc);
SetLocalLocation(oPC, "ls_town_loc", lLasttown);
if (nFatigue == 1)
 {
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_STRENGTH, 2));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 2));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 SendMessageToPC(oPC, "Vous vous sentez fatigue, un peu de repos serait profitable!");
 }
else if (nFatigue == 2)
 {
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_STRENGTH, 4));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 4));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 eEffect = ExtraordinaryEffect(EffectMovementSpeedDecrease(20));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 SendMessageToPC(oPC, "Vous vous sentez epuise, un peu de repos serait profitable!");
 }
else if (nFatigue == 3)
 {
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_STRENGTH, 6));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 eEffect = ExtraordinaryEffect(EffectAbilityDecrease(ABILITY_DEXTERITY, 6));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 eEffect = ExtraordinaryEffect(EffectMovementSpeedDecrease(40));
 ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oPC);
 SendMessageToPC(oPC, "Vous vous sentez a bout de forces, un peu de repos serait profitable!");
 }
if (GetIsObjectValid(GetAreaFromLocation(lLocation)))
 {
 AssignCommand(oPC, ClearAllActions());
 AssignCommand(oPC, ActionJumpToLocation(lLocation));
 }
if (nHP != nHPmax && bDead == FALSE) ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nHPmax - nHP, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_TWENTY), oPC);
else if (bDead == TRUE)
 {
 SetLocalInt(oPC, "Auto_Dead", TRUE);
 DelayCommand(0.1, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), oPC));
 }
CheckIvresse(oPC);
SendMessageToPC(oPC, "Session restaurée!");
}
////////////////////////////////////////////////////////////////////////////////
void DB_RestorePlayerStatus(object oPC, string sDatabase = DATA_NAME)
{
object oArea = GetArea(oPC);
if (!GetIsObjectValid(oArea)) DelayCommand(0.1, DB_RestorePlayerStatus(oPC, sDatabase));
else DB_RestorePlayer(oPC, sDatabase);
}

As mentionned earlier, the database is effectively flushed every minute (using NBDE by knat)

If anyone sees the issue in my scripts please I'm really getting dissapointed ':crying:'
               
               

               
            

Legacy_Krevett

  • Full Member
  • ***
  • Posts: 203
  • Karma: +0/-0
persistant storage issue
« Reply #4 on: August 10, 2012, 09:51:11 pm »


               Ok I found the problem!! It was a conflict with the Player status being saved in area on enter... Put a conditional to check if the player left and then reenter the serverr and it seems to work now '<img'>
               
               

               
            

Legacy_ffbj

  • Hero Member
  • *****
  • Posts: 1097
  • Karma: +0/-0
persistant storage issue
« Reply #5 on: August 11, 2012, 04:32:49 pm »


               Wel that's good.  In my fatigue method you get weaker as you have your script but you also get winded, (you can't run) tired and eventually you fall over from exhaustion.
               
               

               
            

Legacy_Krevett

  • Full Member
  • ***
  • Posts: 203
  • Karma: +0/-0
persistant storage issue
« Reply #6 on: August 12, 2012, 07:50:05 am »


               Well it's just a test module I mostly play LAN where I DM for four of my friends and I wanted to add persistance so that we could make sessions without losing crucial informations and restart the same module without having to redo everything from the start... Like the fatigue system there's still much scripts still in progress as I learn everyday (even when you think you're getting better and better at scripting you discover new trincks and optimisations...reopen old scripts and see how a sucker I was last year '<img'> )