Bug bonus résiduels via déco/reco

Répondre
Partager Rechercher
Bonjour à tous,

Je me demandais si un système existait déjà pour contrer ce bug qui déséquilibre pas mal le jeu...

Cliquez ce bouton ou survolez le contenu pour afficher le spoiler
(déco/reco, on équipe d'autres objets que ceux précédemment équipés, et il y a cumul de bonus (précédents+nouveaux) pour la majeure partie des cas)


Merci de vos lumières
Sur le vault je crois pas qu'il y en ait mais c'est assez simple d'en faire un soi-même. J'avais fait un système comme ça pour Arkalym sans le tester et je crois qu'il est toujours en place (modifié très certainement). Libre à eux de mettre la version complète et corrigée en ligne.

Je ne me souviens plus exactement de comment l'exploit s'annule, je crois qu'il suffit de rééquiper l'objet. Si tu me donnes toutes les infos qu'il faut je devrais pouvoir remanier la version du script que j'ai pour tes besoins.
Salut Lv4 ^.^

J'avais songé à faire ça un peu brutalement:
Soit réserver 11 cases d'inventaire en permanence pour pouvoir faire un "déséquip/rééquip" x2 à la connexion du PJ (contraignant parce qu'on lui rend un peu la vie compliquée avec -11 emplacements, contrebalancé par les sacs mais tout de même...).
Ensuite un ami a tempéré mes ardeurs, en suggérant l'utilisation d'un coffre en zone inaccessible dans lequel on viendrait déposer/reprendre les objets.

En fait c'est à peu près comme ça que je voyais la correction du bug:
A chaque connexion d'un PJ on déséquipe / ré-équipe 2 fois les objets portés lors de la connexion (il me semble que déséquiper/ré-équiper une seule fois n'annule pas le résidu).
Après, comment exactement, et le plus sûrement possible, je n'ai pas encore commencé à mettre tout ça en .nss

Ca me semblait un peu archaïque comme façon de remédier à ce bug (bloquer des emplacements d'inventaire, déplacer les objets dans un coffre, risque de perte si crash serveur etc...).
Mais si c'est simple et efficace et qu'on n'ait plus ce genre de "déséquilibre" ma foi c'est super ^.^

Si tu as déjà bossé dessus ce serait un plaisir de jeter un oeil sur ton oeuvre Lv4 !
Tu pourrais faire simplement ça à la connexion du joueur:
Code PHP:

void ReEquipAll(object player)
{
    
object item;
    
AssignCommand(oPCClearAllActions());
    for (
018i++) // pour chaque item du joueur
    
{
        
item GetItemInSlot(iplayer);
        if (
item != OBJECT_INVALID)
        {
            
AssignCommand(oPCActionUnequipItem(item)); // déséquipe
            
AssignCommand(oPCActionEquipItem(itemi)); // rééquipe
        
}
    }

Ça devrait suffire. Après pour les cas particuliers où le joueur ne peut pas déséquiper son item (inventaire plein). je ne sais pas ce que ça fera, à toi de tester. Théoriquement comme on a encore la référence vers l'item au moment de l'ActionEquipItem, même s'il n'y a pas de place ça devrait le faire.

Mon travail sur l'autre version est un peu plus gros est plus compliqué... ça se basait sur des hash des items pour vérifier qu'à chaque equip/unequip il n'y avait pas de bonus qui se stack. Déséquiper/rééquiper le joueur c'est plus simple et plus propre. En plus je crois que ça gère que le cas des bonus aux caracs, tu peux le trouver [ici] (pendant un mois) si ça t'intéresse.
A priori, après première batterie de tests, il semblerait qu'il ne faille pas lancer le processus Equip/desequip trop tôt (avant même que le joueur n'ait le temps de voir les logs) sinon le cumul est toujours possible.

Je pousse les tests ce soir, comme c'est les vacances je vais avoir....
"un peu" de temps
Exécute le script lorsque le joueur équipe ou déséquipe un item. En le mettant dans un DelayCommand tu as toujours le risque que la fonction se perde dans les limbes. Ou peut-être sur le area_onenter, il est exécuté juste après le module_onenter. Attention dans les deux cas à ne le faire qu'une fois :)
Intéressant, mais alors une question me vient à l'esprit si je fais ça via le Onequip, quid de la situation en combat?

Si lorsqu'on déséquipe un combat se lance, l'armure ne pourra pas être ré-équipée.
Enfin, on parle d'un cas de figure qui serait plutôt rare je pense, m'enfin on ne sait jamais ^.^'

La solution du AreaEnter semble plus pertinente, le OnPCLoad/OnModuleEnter étant lourds d'exécutions en général...
Encore merci de tes conseils Lv4, je posterai le script final et fonctionnel une fois bien testé, sait-on jamais cela pourra sûrement servir à quelqu'un souhaitant alléger son système/le mettre en place
J'ai une solution fonctionnelle basée sur le Area_OnEnter, mais je n'ai pas pu faire tous les tests que je souhaitais encore (reste 25% à faire) à cause d'un fichu bug de crash chargement suite à la première déco/reco.

Dès que c'est solidement testé, je post tout ça !
A priori cela fonctionne bien.

En gros tout se base sur l'évènement On Area Enter et une créature en zone sûre (type zone DM, ou autre) qui servira de réservoir temporaire en cas d'inventaire plein.

En théorie, on ne devrait pas avoir de bugs, si vous voyez quoique ce soit n'hésitez pas à faire une remarque.

[Edit Bug potentiel] Au cas où le premier objet qu'on considère OK pour dupliquer/virer est un objet stackable > 1 unité, ça va bugger.
=> if(GetItemStackSize(oObjet)==1 && GetDroppableFlag(oObjet)==TRUE && etc. Devrait régler ce problème.

[Edit 2]Si vous utilisez ça sur le Area On Enter, mieux vaut prévoir une variable locale sur le PJ => il déco du serveur variable =1, il reco si variable =1 => on le passe au crible puis remise variable à 0.

Code PHP:

//Script à Mettre dans l'évènement On Area Enter
void BonusExploit(object oEntrant);
void copier(object oCopyobject oEntrantint CopyVar);
int Test_inventaire(object oEntrantint limite);

void main()
{
object oEntrant GetEnteringObject();

//####### Code Anti Bug de Cumul de bonus d'objets via déco/reco #######\\

 
FloatingTextStringOnCreature("Version Béta 4"oEntrant);//DEBUG vérification version script
 
 
object Creature_Inventaire=GetObjectByTag("creature_inventaire");//Une créature "réservoir" doit être placée dans une zone sûre au préalable.
 
string tag;
 
object oCopy;

if(
Test_inventaire(oEntrant127)&&GetIsPC(oEntrant))
 {
  
int boucle=0;
  
object oObjet=GetFirstItemInInventory(oEntrant);

   while(
GetIsObjectValid(oObjet)&&boucle==0)//Si l'objet est valide et que la boucle est active
   
{
    if(
GetItemStackSize(oObjet)==&& GetDroppableFlag(oObjet)==TRUE && GetPlotFlag(oObjet)==FALSE && // !Objets d'intrigue && Indroppables && Outils
        
GetTag(oObjet)!="Si vous avez du dmfi..." && GetTag(oObjet)!="D'autres objets spécifiques..." &&
      
GetTag(oObjet)!="du type journal..." && GetTag(oObjet)!="ou autres...que vous ne voulez pas voir déplacés de l'inventaire du PJ.")
     {
      
tag=GetTag(oObjet);//On prend le tag de l'objet qui sera copié
      
CopyItem(oObjetCreature_InventaireTRUE);//On copie l'objet qui va faire de la place, et on le met dans l'inventaire de la créature réservoir
      
oCopy GetItemPossessedBy(Creature_Inventairetag);//On défini l'objet copié pour le récupérer plus tard
      
SendMessageToPC(oEntrant"Objet "+GetName(oObjet)+" a été copié dans l'inventaire réservoir.");//DEBUG
      
DestroyObject(oObjet);//On le détruit
      
SendMessageToPC(oEntrant"Objet "+GetName(oObjet)+" a été détruit");//DEBUG
      
boucle=boucle+1;//On désactive la boucle
      
AssignCutsceneActionToObject(oEntrantClearAllActions());
      
DelayCommand(0.5BonusExploit(oEntrant));//Fonction anti bug bonus    
      
DelayCommand(0.5SendMessageToPC(oEntrant"Fonction AntiExploit."));//DEBUG
      
DelayCommand(0.8copier(oCopyoEntrantTRUE));//On redonne l'objet copié au joueur après avoir terminé la fonction anti bug bonus
      
DelayCommand(0.8SendMessageToPC(oEntrant," Objet "+GetName(oCopy)+" a été recopié"));//DEBUG
      
DelayCommand(0.9DestroyObject(oCopy));//On détruit l'objet copié dans l'inventaire réservoir
      
DelayCommand(0.9SendMessageToPC(oEntrant," Objet "+GetName(oCopy)+" détruit dans l'inventaire réservoir."));//DEBUG
    
}
   
oObjet=GetNextItemInInventory(oEntrant);
   
SendMessageToPC(oEntrant"Test sur objet suivant/Fin boucle.");//DEBUG
  
}
 }
else
//Si il y a suffisamment de place dans l'inventaire:
 

 
SendMessageToPC(oEntrant"L'inventaire est OK pour lancer le processus.");//DEBUG
 
AssignCutsceneActionToObject(oEntrantClearAllActions());
 
DelayCommand(0.1BonusExploit(oEntrant));    
 }    
if(
GetIsObjectValid(GetItemPossessedBy(Creature_Inventairetag)))//DEBUG sécurité : vérification de la présence de l'objet dans l'inventaire réservoir.
{
SendMessageToPC(oEntrant"DEBUG Objet "+tag+" valide dans inventaire réservoir. Fin script.");
}
}

void BonusExploit(object oEntrant)//Processus équip/ré-équip x2 nécessaire pour supprimer les cumuls
{
    
object item;
    
int i;
    for (
018i++) // pour chaque item du joueur
    
{
        
item GetItemInSlot(ioEntrant);
        if (
item != OBJECT_INVALID)
        {        
            
AssignCommand(oEntrantActionUnequipItem(item)); // déséquipe
            
AssignCommand(oEntrantActionEquipItem(itemi)); // rééquipe
            
SendMessageToPC(oEntrant,"DEBUG   "GetName(item)+" a été ré-équipé 1 fois.");
            
AssignCommand(oEntrantActionUnequipItem(item)); // déséquipe
            
AssignCommand(oEntrantActionEquipItem(itemi)); // rééquipe
            
SendMessageToPC(oEntrant,"DEBUG   "GetName(item)+" a été ré-équipé 2 fois.");
        }
    }

}

int Test_inventaire(object oEntrantint limite)
{

    
object oObjet GetFirstItemInInventory(oEntrant);
    
int total 0;
    
    while(
GetIsObjectValid(oObjet))
    {
        
total total 1;
    
        
oObjet GetNextItemInInventory(oEntrant);
    }
    
    if(
total>=limite)
    {
        return 
TRUE;
    }

    return 
FALSE;

}

void copier(object oCopyobject oEntrantint CopyVar)
{
CopyItem(oCopyoEntrantTRUE);

Je pense que tu pourrais mettre la vérification de l'inventaire plein + la recherche de l'objet à déplacer dans la même boucle. Ca évite d'en faire deux.
Code PHP:

object GetFistRemovableObject(object player)
{
    
int count 0;
    
object ret;
    
object obj GetFirstItemInInventory(player);
    while (
obj != OBJECT_INVALID)
    {
        if (++
count 126// on a dépassé la limite
            
return ret// on renvoie l'objet trouvé
        
if (ret == OBJECT_INVALID && GetItemStackSize(obj) == && GetDroppableFlag(obj) && !GetPlotFlag(obj) && OtherTests(obj))
            
ret obj// on affecte seulement si on en avait pas déjà un
        
obj GetNextItemInInventory(player);
    }
    return 
OBJECT_INVALID// si on sort ici c'est qu'on a la place
}

void main()
{
    
// ...
    
object obj GetFirstRemovableObject(player);
    if (
obj == OBJECT_INVALID// on a la place
    
{
        
// on effectue la manip direct
    
}
    else 
// pas la place mais obj == le premier item déplaçable
    
{
        
// on effectue d'abord la copie d'item dans le réservoir
    
}

Ce cas fail seulement lorsque le joueur n'a pas de place dans son inventaire (limite à 127) et qu'aucun de ses items ne remplit les conditions.

Une autre chose que je vois c'est que tu fais des DelayCommand(.5, bla); et avec ça tu n'es jamais sûr de les avoir dans l'ordre. Par exemple tu pourrais très bien redonner l'objet au joueur avant d'avoir fait ton antistack.
Il faudrait redonner l'objet une fois que tu es sûr d'avoir terminé.

Note aussi que CopyItem(...); renvoie l'objet copié donc tu n'es pas obligé de faire un GetItemPossessedBy sur le réservoir pour le retrouver !

Edit: Et tu utilises GetIsPC(object) sur la première condition et pas la seconde. Je pense que tu peux mettre ce test au tout début de ton script et couper si c'est pas bon:
Code PHP:

void main()
{
    
object player GetEnteringObject();
    if (!
GetIsPC(player))
        return;
    
// ... la suite

J'ai une version [ici] qui me paraît pas trop mal. J'ajouterais une dernière chose, il faudrait dans les autres tests, vérifier que l'objet que l'on retire éventuellement n'est pas un objet à inventaire (un sac), sinon je pense que les items qui sont dedans sont supprimés.

:)
J'ai fais deux trois petites modifs (deux fautes de frappes sur GetFirstRemovableObject, la déclaration de player/oEntrant dans CallItemBack et le double AssignCommand ne semblait pas fonctionner [AssignCommand(joueur, AssignCommand(CallItemBack[...]]), ça fonctionne bien mais j'ai une interrogation sur la boucle du :

Code PHP:

object GetFirstRemovableObject(object oEntrant)
{
        
int count 0;
        
object ret;
        
object obj GetFirstItemInInventory(oEntrant);
        while (
obj != OBJECT_INVALID)
        {
                if (++
count 126// on a dépassé la limite
                        
return ret// on renvoie l'objet trouvé
                        
SendMessageToPC(oEntrant"ret = "+GetName(ret));
                if (
ret == OBJECT_INVALID && GetItemStackSize(obj) == && GetDroppableFlag(obj) && !GetPlotFlag(obj))
                        
ret=obj// on affecte seulement si on en avait pas déjà un
                        
SendMessageToPC(oEntrant"ret = obj = "+GetName(ret));
                 
obj GetNextItemInInventory(oEntrant);
        }
        return 
OBJECT_INVALID// si on sort ici c'est qu'on a la place

L'objet qui va être supprimé/copié/rendu est retourné X fois (sur la totalité de la boucle en fait je pense^^)

Totalité du script:

Code PHP:

object GetFirstRemovableObject(object oEntrant);
void CallItemBack(object sourceobject item);
void DoAntiStack(object oEntrant);
 
void main()
{
        
object oEntrant GetEnteringObject();
        
        if (!
GetIsPC(oEntrant))
                return;
       
        
object obj GetFirstRemovableObject(oEntrant);
        if (
obj != OBJECT_INVALID// on n'a pas la place
        
{
                
object chest GetObjectByTag("chest");
                
object copy CopyItem(objchestTRUE);
                
DestroyObject(obj);
                
DoAntiStack(oEntrant);
                
//AssignCommand(oEntrant, CallItemBack(chest, copy)); // on ajoute le retour d'objet dans la file de commande du joueur comme ça c'est sûr qu'il l'a à la fin de l'antistack
                
DelayCommand(1.0CallItemBack(chestcopy));
        }
        else {
DoAntiStack(oEntrant);}
}
 
void DoAntiStack(object oEntrant)
{
        
int i;
        
object obj;
        for (
018i++) // pour chaque item du joueur
        
{
                
obj GetItemInSlot(ioEntrant);
                if (
obj != OBJECT_INVALID)
                {
                        
AssignCommand(oEntrantActionUnequipItem(obj)); // déséquipe
                        
AssignCommand(oEntrantActionEquipItem(obji)); // rééquipe
                        
AssignCommand(oEntrantActionUnequipItem(obj));
                        
AssignCommand(oEntrantActionEquipItem(obji));
                }
        }
}
 
void CallItemBack(object chestobject copy)
{
object oEntrant GetEnteringObject();
AssignCommand(chestActionGiveItem(copyoEntrant)); // utilise la fonction au lieu de copier l'item à nouveau
}
 
object GetFirstRemovableObject(object oEntrant)
{
        
int count 0;
        
object ret;
        
object obj GetFirstItemInInventory(oEntrant);
        while (
obj != OBJECT_INVALID)
        {
                if (++
count 126// on a dépassé la limite
                        
return ret// on renvoie l'objet trouvé
                        
SendMessageToPC(oEntrant"ret = "+GetName(ret));
                if (
ret == OBJECT_INVALID && GetItemStackSize(obj) == && GetDroppableFlag(obj) && !GetPlotFlag(obj))
                        
ret=obj// on affecte seulement si on en avait pas déjà un
                        
SendMessageToPC(oEntrant"ret = obj = "+GetName(ret));
                 
obj GetNextItemInInventory(oEntrant);
        }
        return 
OBJECT_INVALID// si on sort ici c'est qu'on a la place

Proposition pour la boucle :

Code PHP:

object GetFirstRemovableObject(object oEntrant)
{
        
int count 0;
        
object ret;
        
object obj GetFirstItemInInventory(oEntrant);
        while (
obj != OBJECT_INVALID)
        {
                if (++
count 126// on a dépassé la limite
                
{
                        return 
ret// on renvoie l'objet trouvé
                        
SendMessageToPC(oEntrant"ret = "+GetName(ret));
                }
                if (
GetItemStackSize(ret) > || !GetDroppableFlag(ret) || GetPlotFlag(ret) || GetHasInventory(ret))
                {
                        
ret=obj// Si "ret" est stackable>1 ou qu'il est indroppable ou qu'il est un objet d'intrigue ou que c'est un inventory bag
                        
SendMessageToPC(oEntrant"Ret ne rempli pas les conditions, on passe au suivant.");
                }
                 
obj GetNextItemInInventory(oEntrant);
        }
        return 
OBJECT_INVALID// si on sort ici c'est qu'on a la place

Je viens aussi de me rendre compte que si on a un inventory bag dans les premières positions dans l'inventaire, on va chercher dedans, prendre le premier objet valide dedans, et du coup on ne vide pas notre case au final ^^'
En fait l'objet n'est pas renvoyé X fois ? Je ne suis pas sûr de comprendre ta remarque.

Par contre la remarque sur les items à inventaire, oui. Je note que tu es passé à l'inverse de ce que je faisais, à savoir affecter ret à chaque objet qui ne remplit pas les conditions ? Dans mon idée on renvoie un item que l'on peut virer de l'inventaire.

Je vais bien commenter cette propal pour voir si on s'est bien compris.
Code PHP:

object GetFirstRemovableObject(object oEntrant)
{
    
int count 0;
    
object ret;
    
object obj GetFirstItemInInventory(oEntrant);
    while (
obj != OBJECT_INVALID)
    {
        if (++
count 126)
            
// le fait d'exécuter un return ici coupe le reste du script
            // on renvoie ret, qui est le premier item de l'inventaire à remplir les conditions
            
return ret;
        if (
ret == OBJECT_INVALID && !GetHasInventory(ret) && GetItemStackSize(ret) > && GetDroppableFlag(ret) && !GetPlotFlag(ret))
            
// si ret n'est pas déjà affecté, 
            // et que obj n'a pas d'inventaire, un stack de 1, est droppable et n'est pas de quête, alors on affecte
            
ret obj;
        
obj GetNextItemInInventory(oEntrant);
    }
    return 
OBJECT_INVALID;
    
    
// Donc si on a la place dans l'inventaire, on renvoie OBJECT_INVALID.
    // Si on n'a pas la place, on renvoie ret qui est le premier item de l'inventaire remplissant les conditions:
    // Pas d'inventaire, stack de 1, droppable, pas de quête

Ah ok effectivement là je comprends mieux ton code

Par contre il me semble qu'il faille mettre
Code PHP:

GetItemStackSize(ret) == 
pour justement n'avoir que les item non stackables et éviter les cas du type x-1, reste y, et pas de case libérée ?

Je n'ai toujours pas trouvé d'idée pour le problème des objets situés dans l'inventaire d'un item, assez ennuyant ce cas
Cliquez ce bouton ou survolez le contenu pour afficher le spoiler
Oui, en fait c'est un bug qu'on rencontre sur toute partie hébergée online.
Un joueur se connecte, se déconnecte, se reconnecte, équipe d'autres objets à la place des précédents (amulette, anneaux, ceinture, armure, etc, et la majorité des bonus se cumulent en général.
Donc par exemple tu vas équiper une arme qui fait +1D6 Magique, a la place de la précédente (qui faisait disons +1D8 feu) et bien tu te retrouves avec +1D8 feu +1D6 magique.

Dans le genre déséquilibre majeur, on fait pas mieux
Ok je viens de retester en remettant ta boucle, je confirme ce que j'avais remarqué :

On prends le premier item, il passe les conditions, et on l'affecte en tant que prochain item a scanner.
Donc du coup on passe au crible tous les items dans l'inventaire sans vraiment sortir de la boucle au premier objet valide rencontré.

Edit: Je m'étais mal exprimé, on n'a effectivement pas x fois le même objet qui revient, ce sont bien tous les objets qui y passent
Code PHP:

object GetFirstRemovableObject(object oEntrant

    
int count 0
    
object ret
    
object obj GetFirstItemInInventory(oEntrant); 
    while (
obj != OBJECT_INVALID
    { 
        if (++
count 126
            
// le fait d'exécuter un return ici coupe le reste du script 
            // on renvoie ret, qui est le premier item de l'inventaire à remplir les conditions 
            //return ret; 
            
SendMessageToPC(oEntrant"Ligne après le count++");//DEBUG
        
if (!GetHasInventory(obj) && GetItemStackSize(obj) == && GetDroppableFlag(obj) && !GetPlotFlag(obj)) 
        {
            
// si ret n'est pas déjà affecté,  
            // et que obj n'a pas d'inventaire, un stack de 1, est droppable et n'est pas de quête, alors on affecte 
            //ret = obj; 
            
return obj;
            
SendMessageToPC(oEntrant"Ligne après return obj; objet : "+GetName(obj));//DEBUG
            
}
        
obj GetNextItemInInventory(oEntrant); 
        
SendMessageToPC(oEntrant"Ligne après ECHEC affectation next;, objet : "+GetName(obj));//DEBUG
    

    return 
OBJECT_INVALID
Marche à merveille comme ça par contre

Il ne reste qu'à régler cette distinction item dans inventaire/item dans inventaire d'item, et on a un truc solide
Finalement il vaut mieux gérer ça via un item indroppable, plus léger, plus fiable.
Plutôt que d'avoir à gérer les items des inventory bags (la solution que je voyais était un peu lourde...).
Autant se réserver une case, avec un item qui peut servir à d'autres fins aussi.
(attention à ne pas se servir d'un item type stock variables locales artisanat ou autre hein..^^).
Question bête, pour résoudre ce type de problème pourquoi il ne suffirait pas de retirer et ré-équiper les objets dans les slots d'équipements ? Je ne comprend pas trop pourquoi vous voulez vider carrément les inventaires etc.
Où alors j'ai mal lu la solution choisie, ou alors j'ai pas compris le problème (que j'avoue ne jamais avoir rencontré)
On peut voir le problème différemment et laisser le joueur faire le travail.
Probablement comme C.Duk le dit.
Avec se script dans l’événement « équipé par le joueur ».
Code:
void main()
{
   object oPC      = GetPCItemLastEquippedBy();
   object oItem    = GetPCItemLastEquipped();
 
           int i = 1;
           object ItemEquip = GetItemInSlot(i,oPC);
           while(oItem != ItemEquip && i<19)                       
                       ItemEquip = GetItemInSlot(++i,oPC);                    
 
           string sTestSlot = "TestSlot"+IntToString(i);         
           if(GetLocalString(oPC,sTestSlot) == "")
           {                                              
                       AssignCommand(oPC,ActionUnequipItem(oItem));
                       AssignCommand(oPC,ActionEquipItem(oItem,i));                     
           }
           SetLocalString(oPC,"TestSlot"+IntToString(i),"ok");                  
}
Et pour être sûr de l’initialisation des variables locales, dans l’événement « fin de chargement du joueur ».


Code:
void main()
{
           object oPC = GetEnteringObject();
           if(GetIsPC(oPC))
           {
                       int i;
                       for(i=1;i<19;i++)
                       {
                                  DeleteLocalString(oPC,"TestSlot"+IntToString(i));
                       }
           }
}
Bien sûr à tester et à modifier mais en local pas de soucis.
Je veux avoir 1 case d'inventaire de libre pour éviter que le Joueur ne se retrouve avec son équipement à terre une fois le processus terminé.
Les effets cumulés sont annulés de manière certaine, uniquement lorsque mon code est placé dans un "évènement d'entré" léger : i.e l'area on enter.

Si il n'y a pas 1 case de libre, tous les objets équipés se retrouvent logiquement à terre.

Si je fais ça via le OnPCLoad les cumuls sont toujours là, et le Module On Enter est très chargé, je préfère éviter les aléas avec ce genre de bug.

Je préférai éviter l'évènement "On Equiped Item" pour éviter le spam du script qui est déjà bien fourni chez nous.
De plus, il ne suffit que de le lancer une fois à la reco pour être tranquille par la suite, donc pas besoin de passer via le "On Equiped Item", jusqu'à la prochaine déco/reco.
Il y a une erreur dans mes scripts.
Les "slot" sont numérotés de 0 à 17 et pas de 1 à18.
donc dans le premier script c'est :
int i = 0; et non int i = 1;
et
while(oItem != ItemEquip && i<18) et non while(oItem != ItemEquip && i<19)

dans le second c'est :
for(i=0;i<18;i++) et non for(i=1;i<19;i++)

Désolé mais je mange trop en ce moment et je somnole pas mal^^
Répondre

Connectés sur ce fil

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