[Epouvantail a grosbills] SAUVEGARDE DES SORTS

Répondre
Partager Rechercher
Suite au post de Nexus, et grâce à son script, voici ce que j'ai concocté :

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_

++++
Pourquoi ne pas mettre un petit DelayCommand sur l'évènement de fin de repos, au lieu de passer par le Heartbeat ?

Et pour les sorts, je conseille plutôt d'utiliser la fonction de HotU qui permet d'exécuter un script custom au début de chaque sort, au lieu de modifier les sorts un par un

Merci pour ce script très utile en tout cas
Salut Mayk ca faisais longtemps.

hm .. quelqu'un aurait utiliser cela avec les changement dont parle Taern ? ca c'est tres interessant ca puis vus que je compte utiliser d'autres sorts il est vrai que ca eviterais d'ouvrir tout ces scripts
Salut tous !

Yop Kadz ! C'est vrai que ca fait longtemps depuis arcantia ! Courage pour ton mod !

De rien Lys, c'est un plaisir *s'incline*

Pourquoi je ne me sers pas d'un DelayCommand est très simple... ! Vu que l'on envoie un petit message a la fin du repos au joueur, les malins comprendront que si ils se deconnectent juste avant, ils pourraient eviter la sauvegarde... Donc avec une variable locale, le résultat est que si ils deconnectent, le compteur reprend à la reconnection la ou il s'est arreté.

Le gros bill est toujours impressionné par les scripts, cela le calme et le rend RPisable...

Oui oui, je suis un vicieux...

Et de toute facon, meme si ils avaient pu eviter la sauvegarde, le script est fait de telle facon que si aucune sauvegarde n'a été effectuée, il reco avec aucun sort mémorisé.

Pour le spell hook, je ne m'en suis pas encore servi, ca viendra !

Azmathiel, lol tu t'es amusé a les compter ^^ !!!!

Moi ce qui m'importe, c'est que les GB ne passent pas au travers des mailles du filet et qu'ils en chient sans faire lagguer les autres joueurs. Après le reste....

Une modif intéressante serait d'eviter la sauvegarde aux non magiciens...

Merci pour vos réactions...

++++

Mayk _Kyam_
Ce qui risque de se passer est qu'à l'utilisation d'une potion ou d'un parchemin dont le personnage a le sort de mémorisé, cela le décrémente.

Qui a une idée pour empecher cela ?

+++
Mayk
Euh non ...
Si j'ai bien compris le script y a pas de risque... au pire si c'est un sort que le PJ possede il recollera la meme valeur que precedemment vu que son nombre de sort n'aura pas ete modifie...
Citation :
Provient du message de Garrath
Euh non ...
Si j'ai bien compris le script y a pas de risque... au pire si c'est un sort que le PJ possede il recollera la meme valeur que precedemment vu que son nombre de sort n'aura pas ete modifie...
Clair, où avais-je la tête ^^

Lol Azmath !
Citation :
Provient du message de Azmathiel
Bah pas la peine de compter: 651x3 + 3 petites régulières
C'est au max ca...
A priori il mets des variables seulement si il y a des sorts...

En passant peut etre qu'un petit DeleteLocalInt serait pas mal losque le GetHasSpell retourne 0 ...

Comme aussi un petit
Code PHP:

DeleteLocalInt(oPC,"SortsRepos"
pluto que la mettre a FALSE...
Apres reflexion doit y avoir moyen d'eviter le OHB

imaginons:
On garde une variable sur un PJ que lorsqu'un sort est utilise.
Au repos on supprime toutes ces variables.
Et a la reconnection on remets les sorts de façon a ce que la variables = le resultat du GetHasSpell

Le seul truc c quil faut pas mettre 0 quand le GetHasSpell = 0 mais -1

Ca donnerait un truc du style
Code PHP:

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

A mettre sur tous les sorts ou encore mieux dans le SpellHooking.

Ensuite sur un repos on fait un truc du style
Code PHP:

for(<=650 n++)
{
    
DeleteLocalInt(oPC,"SPELL"+IntToString(n));

et du coup a la reco d'un PJ il suffit juste de faire :
Code PHP:

void LoadSpells(object oPC)
{
SendMessageToPC(oPC,"Reconstruction par le serveur de la sauvegarde des sorts de "+GetName(oPC)+".");
int n 0;
 for(
<=650 n++)
 {
    
int iSpellTimes GetLocalInt(oPC,"SPELL"+IntToString(n));
    
// Attention si on a 0 c que la varaible locale n'existe pas donc rien a faire
    
if (iSpellTimes!=0)
    {
         if(
iSpellTimes==-1)
              
iSpellTimes 0;

         while(
GetHasSpell(n,oPC)>iSpellTimes)
         {
            
DecrementRemainingSpellUses(oPC,n);
         }
         
DeleteLocalInt(oPC,"SPELL"+IntToString(n));
    }
 }

Voila a mon avis en theorie ca doit marcher... ca evite le OHB a voir si en pratique c bon

En passant je comprends pas trop ce que tu faisais sur le LoadSpells avant
Citation :
if(iHasSpell>iSpellTimes)
{
for(x=0; x<(iHasSpell-iSpellTimes) ;x++)
{
DecrementRemainingSpellUses(oPC,n);
}
}
Car d'apres ce que j'ai pu comprendre le GetHasSpell peut te renvoyer 1 si tu as un sort X comme 5 (si tu as tj qu'un seul sort X)
Si a la reco, la variabe n'existe pas ou qu'elle est égale à zéro, le nombre de sorts est égal à un sur le LoadSpells. Je n'ai pas compris d'ou vient le bug, mais c'est ce qui se produisait lors des tests.

J'ai donc du scinder la fonction LoadSpells en deux :

un cas ou le nombre de sorts est supérieur ou égal à la variable enregistrée, que ce soit 1 ou 8 ou tout autre nombre posistif. C'est celle que tu montres dans ton quote.

L'autre est si la variable enregistrée est égale à zéro, que je place avant, par sécurité.

Quand je crée un script prenant en compte plusieurs paramètres, je scinde les parties de fonctions, pour qu'elles se lancent uniquement dans le cas que je veux. Comme cela on garde un contrôle sur les évènements en cas de bug. De plus, cela permet, si un bug il y a, de savoir exactement où ya blème.

Dans le script original, j'avais mis trois ou quatre conditions, et c'est vrai qu'ici cela semble redondant. Sauf que si la vatiable est égale zero ou n'existe pas, on est certain de chez certain que le joueur n'aura rien.

+++

Merci pour ta suggestion, je vais tester ca.
Scuez moi de vous interrompre .. mais comment cela marche pour éviter d'aller ouvrir tous les scripts de sorts et aller y mettre le void....

Pourriez pas faire juste un petite mise en forme avec un nom de sort pour faire l'exemple .. et j'irais cherchez les autres dans le 2da

Car j'ai pas trop compris le truc du spellhooking .. ou .. enfin c'est un peu chinois pour moi parfois
OK c assez simple en fait.
Avec le SpellHooking y a pas besoins d'aller modifier les sorts. J'explique.

Sur le OnModuleLoad (dans les evenements sur le module) rajouter la ligne
Code PHP:

SetLocalString(GetModule(), "X2_S_UD_SPELLSCRIPT""nom_script"); 

Ensuite creer le script "nom_script"
Code PHP:

#include "x2_inc_switches"

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

void main()
{
     
int nSpell=GetSpellId();
     
int nSpellDC=GetSpellSaveDC();
     
int nCastLevel=GetCasterLevel(OBJECT_SELF);

    
SaveSpell(OBJECT_SELFnSpell);


Alors c marrant a savoir, que OBJECT_SELF represente ici le caster tj.
Donc la, des qu'un sort sera lance, cela passera par ici et ensuite il lancera le sort normalement.

Sur le OnPlayerRest, il faut rajouter cela
Code PHP:

    object oPC GetLastPCRested();
    
int nRestType=GetLastRestEventType();

    if (
nRestType == REST_EVENTTYPE_REST_FINISHED)
   {
        
int n;
        for(
<=658 n++)
       {
            
DeleteLocalInt(oPC,"SPELL"+IntToString(n));
       }
   } 
Et sur le OnClientEnter du module j'ai mis cela :
Code PHP:

void LoadSpells(object oPC)
{
SendMessageToPC(oPC,"Reconstruction par le serveur de la sauvegarde des sorts de "+GetName(oPC)+".");
int n 0;
 for(
<=658 n++)
 {
    
int iSpellTimes GetLocalInt(oPC,"SPELL"+IntToString(n));
    
// Attention si on a 0 c que la varaible locale n'existe pas donc rien a faire
    
if (iSpellTimes!=0)
    {
         if(
iSpellTimes==-1)
              
iSpellTimes 0;

         while(
GetHasSpell(n,oPC)>iSpellTimes)
         {
            
DecrementRemainingSpellUses(oPC,n);
         }
    }
 }
}

void main()
{
    
object oPC GetEnteringObject();
    if (
GetIsPC(oPC))
    {
        
LoadSpells(oPC);
    }


Voila, simple efficace, rapide, et finis les bourrins de mage deco-reco et tout cela sans BD, et surtout sans OnHeartBeat ...
Merci a mayk pour le script de depart

[EDIT] Modification de 650 en 658.
[EDIT] Modification sur le repos. Merci à Tikem
[EDIT] Modification sur le OnClientEnter. Suppression du DeleteLocalInt qui ne sert a rien ici, d'autant plus que si le PJ se deco/reco 2 fois il repart avec tous ces sorts. Le DeleteLocalInt ne doit etre fait que par le repos!
merci pour le -1 !

Ca aide !

Et merci pour ton boulot !

+++

Je bosse sur des mercenaires a qui l'on peut demander de s'equiper d'une certaine manière et a qui l'on peut demander des réglages particuliers... du genre distance de poursuite, un peu comme dans fallout.

FR - [CEP] - MARKHOR
Questions :

La procédure énoncée par Garrath dans son avant dernier post est-elle la bonne pour faire fonctionner le système ?

Ya tous les scripts ?

La correction des 658 sorts à la place des 650 suffit juste de remplacer tous les 650 par des 658 ?

Vala, je demande parce que ce système m'interresse et je n'ai malheureusement pas le temps de faire des tests... Pis faudrait le mettre dans les scripts persistants ce système, il à l'air très très bien
Citation :
(bon la ca serait bien que cela se fasse a la fin du repos mais pas trouver)
Garrath cela ne serais pas ca que tu cherchais ?


REST_EVENTTYPE_REST_CANCELLED // repos anulé
REST_EVENTTYPE_REST_FINISHED // repos finit corectement
REST_EVENTTYPE_REST_INVALID // repos invalide
__________________
www.Kaegys.com
KaegysTV ma chaine YouTube
Un Dragon ne Meurt Jamais Seul.

TyKeM , Après les GBs réunis sur NWN, avoir fait du gros dps sur WoW, après avoir squatté le platine dans SC2 après le théory crafting de Diablo 3 je me lance sur KaegysTV YouTube
Répondre

Connectés sur ce fil

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