[Probleme] Sauvegarde des Sorts

Répondre
Partager Rechercher
Voici le script pour sauvegarder les sorts d'un joueur OnLine : LoadPCSpell à appeler dans le OnEnter du module et SavePCSpell dans votre sauvegarde des joueurs (typiquement OnHeartBeat du module) :

Code PHP:

// fichier Nwnx2
#include "aps_include"


// nombre total de sorts (version Nwn+SoU+HotU)
const int RF_SPELL_NUMBER 640;
// nom de la table Mysql sauvegardant ces données.
const string SPELL_TABLE "spell";

// Effectue des l'entree sur le module :
void LoadPCSpell(object oPC)
{
 
//* Assignation des sorts *//
   
if((GetLevelByClass(CLASS_TYPE_CLERIC,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_DRUID,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_SORCERER,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_WIZARD,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_PALADIN,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_RANGER,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_BARD,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_ARCANE_ARCHER,oPC) > 0))
    {
     
int i 0;
     
int iActualSpellTimesiSaveSpellTimesj;

     for(
i<= RF_SPELL_NUMBERi++)
     {
         
iActualSpellTimes GetHasSpell(i,oPC);

         if(
iActualSpellTimes 0)
         {
          
iSaveSpellTimes GetPersistentInt(oPC,"SPELL_STORE_"+IntToString(i),SPELL_TABLE);

          for(
0< (iActualSpellTimes iSaveSpellTimes); j++)
          {
            
DecrementRemainingSpellUses(oPC,i);
          }
         }
     }
    }
}

void SavePCSpell(object oPC)
{
    
//* Sauvegarde des sorts :
   
if((GetLevelByClass(CLASS_TYPE_CLERIC,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_DRUID,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_SORCERER,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_WIZARD,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_PALADIN,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_RANGER,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_BARD,oPC) > 0) ||
    (
GetLevelByClass(CLASS_TYPE_ARCANE_ARCHER,oPC) > 0))
    {
     
int i 0;
     
int iSpellTimes;

     for(
i<= RF_SPELL_NUMBERi++)
     {
        
DeletePersistentInt(oPC,"SPELL_STORE_"+IntToString(i),SPELL_TABLE);
        
iSpellTimes GetHasSpell(i,oPC);
        if(
iSpellTimes 0)
        {
         
SetPersistentInt(oPC,"SPELL_STORE_"+IntToString(i),iSpellTimes,10,SPELL_TABLE);
        }
     }
    }

Enjoy !

[edit] : Message édité pour plus de clarté (le problème ayant été résolu !)

PN
Une direction à explorer pourrait être un "routeur" de sorts qui permet à tes joeurs de n'utiliser leurs sorts que s'ils se sont reposés au moins une fois à l'entrée du jeu.

Cette solution n'est pas très satisfaisante d'un point de vue ergo, puisque tous les sorts semblent toujours être accessibles, mais quand même efficace en ce qui concerne le résultat, sans tomber dans une erreur TMI.
tiens, ca me fait penser qu'il faut que je poste un sort de NwN que je viens de rajouter, qui utilise une fonction qui repertorie tout les sorts... Regarde voir si y'a pas ce que tu cherche dedans ^^
Bon alors de toutes évidences c'est une boucle infinie.
Il n'y a que deux boucles dans ta fonction, or la plus grosse (for) ne me semble pas poser de problème.

Je dirais que l'erreur vient de là :
Code PHP:

while(GetHasSpell(i,oPC)){  DecrementRemainingSpellUses(oPC,i); } 

Peut-être que DecrementRemainingSpellUses ne prend pas effet tout de suite ? (comme le fait par exemple DestroyObject).
Je serais toi je choisirais la prudence :
Code PHP:

int nUses GetHasSpell(ioPC);
int j;
for(
j=0jnUsesj++)
    
DecrementRemainingSpellUses(oPCi); 
Cela dit, à en croire le sort d'eM, ta solution devrais marcher Enfin bon voilà, moi je vois que ça qui pourrais clocher.
en fait, a priori, GetHasSpell devrait être, a mon avis, sorti du while, avec une int pour le stocker, et decrementer l'int en question dans la boucle.

Ceci etant, je viens de poster le sort, et dedans, j'utilise donc ca :

Code PHP:

int DecrementAndCount(object oPC=OBJECT_SELF)
{
int nNumSpell 1700;
int nLevel nNbSpell ,nCount 0;

while (
nNumSpell 0)
    {
    
nNbSpell GetHasSpell(nNumSpell,oPC);
    while (
nNbSpell 0)
        {
        
nLevel GetInnateSpellLevel(nNumSpell);
        
DecrementRemainingSpellUses(oPC,nNumSpell);
        
nCount nCount nLevel;
        
nNbSpell--;
        }
    
nNumSpell--;
    }
return 
nCount;

evidemment, le but ici, c'est de decrementer tous les sorts, et de compter leur niveaux, mais tu devrait pouvoir l'adaptar facilement, je pense ^^
Merci, je vais essayer tout ça : j'avais pas pigé que GetHasSpell revoyait plus qu'un simple booléen, ça va aller bcp mieux avec une boucle for. Je posterai mon script une fois qu'il sera sans bugs.

PN

[edit]: et voila ! Merci à vous.
pour info : voila le bug qui fait rater une fonction qui pourtant aurait dû marcher :

A propos de GetHasSpell :
Citation :
Known Bugs
Patch 1.28 claims to have fixed problems regarding spontaneous casts, but reports indicate that this is not the case. If you can verify that it has been fixed, please use the link at the bottom of this topic to contact the maintainers of the Lexicon.

The number returned by this function is after each spell use, but it is not always decremented by one. Sometimes it is decremented by 5, 3, or 2.
Le script ne veux pas se compiler, il ne reconnais pas "GetPersistentInt".
Lorsque je me connecte, j'ai pas de sorts, je me repose et disco-reco, j'ai à nouveau pas de sorts
"et si le joueur avait bouffé tous ses sorts ?"

vos boucles ne prennent pas ca en compte puisqu'elles exluent tout int en dessous de 1... donc si le joueur a tout mangé, ce n'est pas enregistré.... enfin du moins dans le premier post de Nexus.


pour ceux qui utilisent le systeme de persistance par défaut de NWN (campaign), une petite précaution s'impose :

DestroyCampaignDatabase("SPELL_SAVE"+GetName(oPC));

comme dans ce qui suit :

Code PHP:

void SaveSpells(object oPC)
{
int n 0;
DestroyCampaignDatabase("SPELL_SAVE"+GetName(oPC));
for(
n<=640 n++)
    {
    if(
GetHasSpell(n,oPC)>=1)
        {
        
int iSpellTimes GetHasSpell(n,oPC);
        
SetCampaignInt("SPELL_SAVE"+GetName(oPC),IntToString(n),iSpellTimes,OBJECT_INVALID);
        }
    }
}

void LoadSpells(object oPC)
{
int x;
int n 0;
for(
<=640 n++)
    {
    
int iSpellTimes GetCampaignInt("SPELL_SAVE"+GetName(oPC),IntToString(n),OBJECT_INVALID);
    if(
GetHasSpell(n,oPC)>0)
        {
        for(
x=0x<(GetHasSpell(n,oPC)-iSpellTimes) ;x++)
            {
            
DecrementRemainingSpellUses(oPC,n);
            }
        }
    }

enfin, c'est une idée, va savoir si ca marche...
A mon avis, la persistance n'a pas forcément sa place dans la sauvegarde des sorts. Dans le sens ou si un joueur se connecte pour la premiere fois apres un reboot, tant pis pour sa gueule, il faudra qu'il se repose.

Une fois reposé, le serveur lui enregistre sa config de sorts.

A chaque fois qu'il fait un sort, celui ci est déduit de sa sauvegarde par une variable qui en remplace celle sauvegardée apres le repos.

Si il deconnecte puis reconnecte, il retrouvera ses sorts inchangés.

Le but du systeme de scripts que j'ai fait est d'empecher la deco reco abusive de certains lourdauds.

tu cree un include file :

Code PHP:

void SaveSpell(object oPCint nSpellID)
{
if(
GetIsPC(oPC)==TRUE)
    {
    
int nRemainingSpells GetHasSpell(nSpellID,oPC);
    
SetLocalInt(oPC,"SPELL"+IntToString(nSpellID),nRemainingSpells);
    }
}

void SaveAllSpells(object oPC)
{
int x;
int n 0;
SetLocalInt(oPC,"SortsRepos",FALSE);
SetLocalInt(oPC,"compteursauvsorts",0);
for(
<=650 n++)
    {
    
int nRemainingSpells GetHasSpell(n,oPC);
    if(
nRemainingSpells>0)
        {
        
SetLocalInt(oPC,"SPELL"+IntToString(n),nRemainingSpells);
        }
    }
}

void LoadSpells(object oPC)
{
SendMessageToPC(oPC,"Reconstruction par le serveur de la sauvegarde des sorts de "+GetName(oPC)+".");
int x;
int n 0;
for(
<=650 n++)
    {
    
int iSpellTimes GetLocalInt(oPC,"SPELL"+IntToString(n));
    
int iHasSpell GetHasSpell(n,oPC);
    if(
iSpellTimes==0)
        {
        while(
GetHasSpell(n,oPC)>0)
            {
            
DecrementRemainingSpellUses(oPC,n);
            }
        }
    if(
iHasSpell>iSpellTimes)
        {
        for(
x=0x<(iHasSpell-iSpellTimes) ;x++)
            {
            
DecrementRemainingSpellUses(oPC,n);
            }
        }
    }

puis sur chaque sort du mod tu fous la fonction SaveSpell(object oPC, int nSpellsID).

en gros, tu change ceci :

Code PHP:

void main()

en ceci :

Code PHP:

#include "nom_du_include_choisi"
void main()
{
    
SaveSpell(OBJECT_SELFGetSpellId());

// suite du script de sort... 

ensuite, sur ton onplayerrested, tu mets un declencheur de compteur, comme ceci :

Code PHP:

SetLocalInt(oPC,"SortsRepos",TRUE); 

puis sur le OnHeartBeat ceci, un compteur qui enregistrera les sorts juste apres la fin des repos :

Code PHP:

#include "nom_du_include_choisi"
void main()
{
if(
GetLocalInt(oPC,"SortsRepos")==TRUE)
            {
            
int iCounter GetLocalInt(oPC,"compteursauvsorts");
            
iCounter iCounter+1;
            if(
iCounter<=3)
                {
                
SetLocalInt(oPC,"compteursauvsorts",iCounter);
                }
            if(
iCounter>3)
                {
                
SaveAllSpells(oPC);
                
SendMessageToPC(oPC,"Constitution d'une sauvegarde des sorts de "+GetName(oPC)+" par le serveur.");
                }
            }

C'est long et fastidieux, mais le résultat en temps de calcul est quand meme plus leger que si tu faisais un OHB en permanence : Ca fait des gros coups de lag a chaque battement du coeur de module, et imagine si il y a 25 utilisateurs de sorts sur le serveur.

La fonction LoadSpells, juste sur le onenter, comme ceci, en se servant de tes conditions :

Code PHP:

#include "nom_du_include_choisi"
void main ()
{
if((
GetLevelByClass(CLASS_TYPE_CLERIC,oPC) > 0) ||
        (
GetLevelByClass(CLASS_TYPE_DRUID,oPC) > 0) ||
        (
GetLevelByClass(CLASS_TYPE_SORCERER,oPC) > 0) ||
        (
GetLevelByClass(CLASS_TYPE_WIZARD,oPC) > 0) ||
        (
GetLevelByClass(CLASS_TYPE_PALADIN,oPC) > 0) ||
        (
GetLevelByClass(CLASS_TYPE_RANGER,oPC) > 0) ||
        (
GetLevelByClass(CLASS_TYPE_BARD,oPC) > 0) ||
        (
GetLevelByClass(CLASS_TYPE_ARCANE_ARCHER,oPC) > 0))
            {
            
LoadSpells(oPC);
            }

Le serveur ne devrait avoir un coup de lag que a chaque connection de joueur utilisant de la magie, et le OHB du module est considérablement allégé.

Pour ceux qui sont curieux d'en voir le fonctionnement, passez sur mon module : FR - [CEP] - MARKHOR (persistant (rôle)).

Pour Info, j'ai créé un .erf qui contient le include et les sorts de NWN SOU et HOTU réédités pour qu'ils marchent avec ce systeme.

Mayk - _Kyam_

++++
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés