Help : script de garde OnPerception

Répondre
Partager Rechercher
J'ai créé un script pour que des gardes qui voient un PJ avec une arme lui demande de la ranger, puis l'attaque s'il n'obéis pas.
Cependant, le script s'arrête à la première mise en garde...
Pouvez vous m'aider ???

Voici le script:
Code PHP:

object oWeapon1;
object oWeapon2;
int iWeapon1;
int iWeapon2;

void Avertissement(int iCompteurobject oCreature)
{
    
oWeapon1 GetItemInSlotINVENTORY_SLOT_RIGHTHANDoCreature);
    
oWeapon2 GetItemInSlotINVENTORY_SLOT_LEFTHANDoCreature);
    
iWeapon1 GetIsObjectValid(oWeapon1);
    
iWeapon2 GetIsObjectValid(oWeapon2);

    if (
iWeapon1 == TRUE || iWeapon2 == TRUE)
    {
        if (
iCompteur == 1)
        {
            
int rPhrase Random(3);

            if (
rPhrase == 1)
                
ActionSpeakString("Veuillez ranger vos armes s'il vous plait !");

            if (
rPhrase == 2)
                
ActionSpeakString("Les armes ne sont pas autorisees ici ! Veuillez les ranger");
        }

        if (
iCompteur == 2)
            
ActionSpeakString("Dernier avertissement, rangez vos armes !!!");

        if (
iCompteur ==3)
        {
            
ActionSpeakString("Vous aurez ete prevenu !");
            
ActionAttack(oCreatureFALSE);
        }

        
iCompteur iCompteur 1;
    }
    else
        
ActionSpeakString("Merci.");

}

void main()
{
    
ClearAllActions(FALSE);
    
object oCreature GetLastPerceived();
    
int iCreature GetIsPC(oCreature);

    if (
GetLastPerceptionSeen() == TRUE)
    {
        if (
iCreature == TRUE)
        {
            
int iCompteur 1;
            
Avertissement(iCompteuroCreature);
            
DelayCommand(5.0Avertissement(iCompteuroCreature));
            
DelayCommand(10.0Avertissement(iCompteuroCreature));
        }
    }

__________________
SidSilver... Harbar forever !
Tu met un random(3) mais tu n es que 2 phrase possible. tu devrais remplacer par random(2)+1 ou mettre une 3ieme phrase

Et ca ne marche pas car , qd tu lance ton delaycommand, tu le lance avec le parametre iCompteur=1 dans les 2 cas, car ton void Avertissement ne renvoie pas la valeur de iCompteur incrementer.
Il faudrai que ta fonction Avertissement soit recurssive.

Code PHP:

object oWeapon1;
object oWeapon2;
int iWeapon1;
int iWeapon2;

void Avertissement(int iCompteurobject oCreature)
{
    
oWeapon1 GetItemInSlotINVENTORY_SLOT_RIGHTHANDoCreature);
    
oWeapon2 GetItemInSlotINVENTORY_SLOT_LEFTHANDoCreature);
    
iWeapon1 GetIsObjectValid(oWeapon1);
    
iWeapon2 GetIsObjectValid(oWeapon2);

    if (
iWeapon1 == TRUE || iWeapon2 == TRUE)
    {
        if (
iCompteur == 1)
        {
            
int rPhrase Random(2)+1;

            if (
rPhrase == 1)
                
ActionSpeakString("Veuillez ranger vos armes s'il vous plait !");

            if (
rPhrase == 2)
                
ActionSpeakString("Les armes ne sont pas autorisees ici ! Veuillez les ranger");
            
           
DelayCommand(5.0Avertissement(iCompteur+1oCreature));  
       }

        if (
iCompteur == 2)
       {
            
ActionSpeakString("Dernier avertissement, rangez vos armes !!!");

           
DelayCommand(5.0Avertissement(iCompteur+1oCreature));  
       }
       if (
iCompteur ==3)
        {
            
ActionSpeakString("Vous aurez ete prevenu !");
            
ActionAttack(oCreatureFALSE);
        }
    }
    else
        
ActionSpeakString("Merci.");

}

void main()
{
    
ClearAllActions(FALSE);
    
object oCreature GetLastPerceived();
    
int iCreature GetIsPC(oCreature);

    if (
GetLastPerceptionSeen() == TRUE)
    {
        if (
iCreature == TRUE)
        {
            
int iCompteur 1;
            
Avertissement(iCompteuroCreature);
        }
    }

J espere ne pas avoir fait d erreur.
Voici donc la version finale, à laquelle j'ai intégré les fonctions de perception habituelles:

Code PHP:

#include "NW_I0_GENERIC"

object oWeapon1;
object oWeapon2;
int iWeapon1;
int iWeapon2;

void Avertissement(int iCompteurobject oCreature)
{
    
oWeapon1 GetItemInSlotINVENTORY_SLOT_RIGHTHANDoCreature);
    
oWeapon2 GetItemInSlotINVENTORY_SLOT_LEFTHANDoCreature);
    
iWeapon1 GetIsObjectValid(oWeapon1);
    
iWeapon2 GetIsObjectValid(oWeapon2);

    if (
iWeapon1 == TRUE || iWeapon2 == TRUE)
    {
        if (
iCompteur == 1)
        {
            
int rPhrase Random(2)+1;

            if (
rPhrase == 1)
                
ActionSpeakString("Veuillez ranger vos armes s'il vous plait !");

            if (
rPhrase == 2)
                
ActionSpeakString("Les armes ne sont pas autorisees ici ! Veuillez les ranger");

           
DelayCommand(10.0Avertissement(iCompteur+1oCreature));
       }

        if (
iCompteur == 2)
       {
            
ActionSpeakString("Dernier avertissement, rangez vos armes !!!");

           
DelayCommand(10.0Avertissement(iCompteur+1oCreature));
       }
       if (
iCompteur ==3)
        {
            
ActionSpeakString("Vous aurez ete prevenu !");
            
ActionAttack(oCreatureFALSE);
        }
    }
    else
        
ActionSpeakString("Merci.");

}

void main()
{
    
//This is the equivalent of a force conversation bubble, should only be used if you want an NPC
    //to say something while he is already engaged in combat.
    
if(GetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION) && GetIsPC(GetLastPerceived()) && GetLastPerceptionSeen())
    {
        
SpeakOneLinerConversation();
    }
    
//If the last perception event was hearing based or if someone vanished then go to search mode
    
if ((GetLastPerceptionVanished()) && GetIsEnemy(GetLastPerceived()))
    {
        
object oGone GetLastPerceived();
        if((
GetAttemptedAttackTarget() == GetLastPerceived() ||
           
GetAttemptedSpellTarget() == GetLastPerceived() ||
           
GetAttackTarget() == GetLastPerceived()) && GetArea(GetLastPerceived()) != GetArea(OBJECT_SELF))
        {
           
ClearAllActions();
           
DetermineCombatRound();
        }
    }
    
//Do not bother checking the last target seen if already fighting
    
else if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))
    {
        
//Check if the last percieved creature was actually seen
        
if(GetLastPerceptionSeen())
        {
            if(
GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL))
            {
                
DetermineSpecialBehavior();
            }
            else if(
GetIsEnemy(GetLastPerceived()))
            {
                if(!
GetHasEffect(EFFECT_TYPE_SLEEP))
                {
                    
SetFacingPoint(GetPosition(GetLastPerceived()));
                    
SpeakString("NW_I_WAS_ATTACKED"TALKVOLUME_SILENT_TALK);
                    
DetermineCombatRound();
                }
            }
            
//Linked up to the special conversation check to initiate a special one-off conversation
            //to get the PCs attention
            
else if(GetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION) && GetIsPC(GetLastPerceived()))
            {
                
ActionStartConversation(OBJECT_SELF);
            }
        }
    }
    if(
GetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT) && GetLastPerceptionSeen())
    {
        
SignalEvent(OBJECT_SELFEventUserDefined(1002));
    }

    
object oCreature GetLastPerceived();
    
int iCreature GetIsPC(oCreature);

    if (
GetLastPerceptionSeen() == TRUE)
    {
        if (
iCreature == TRUE)
        {
            
int iCompteur 1;
            
Avertissement(iCompteuroCreature);
        }
    }

__________________
SidSilver... Harbar forever !
Oui c'est très bien et c'est une excellente idée d'avoir utilisé une fonction récursive pour cela.
Mais une simple question de style (et puis un peu d'efficacité et de prudence aussi ): tu devrais enlever tous ces tests "== TRUE", ils alourdissent légèrement ton script, du point de vue lisibilité comme rapidité, et de plus ils représentent un petit risque avec certaines fonctions.
Ils ne sont absolument pas nécessaires et... la tradition veut qu'on ne les mette pas...
Une petite remarque d'optimisation sur ta fonction, qui risque de te sembler loufoque mais j'explique après:
Code PHP:

void Avertissement(int iCompteurobject oCreature)
{
    
// On cree un bloque pour limiter la portee des variables
    
{
        
oWeapon1 GetItemInSlotINVENTORY_SLOT_RIGHTHANDoCreature);
        
oWeapon2 GetItemInSlotINVENTORY_SLOT_LEFTHANDoCreature);
        
iWeapon1 GetIsObjectValid(oWeapon1);
        
iWeapon2 GetIsObjectValid(oWeapon2);

        if (
iWeapon1 == TRUE || iWeapon2 == TRUE)
        {
            if (
iCompteur == 1)
            {

                
int rPhrase Random(2)+1;

                if (
rPhrase == 1)
                    
ActionSpeakString("Veuillez ranger vos armes s'il vous plait !");

                if (
rPhrase == 2)
                    
ActionSpeakString("Les armes ne sont pas autorisees ici ! Veuillez les ranger");

            }

            if (
iCompteur == 2)
                
ActionSpeakString("Dernier avertissement, rangez vos armes !!!");

            if (
iCompteur ==3)
            {
                
ActionSpeakString("Vous aurez ete prevenu !");
                
ActionAttack(oCreatureFALSE);
                return; 
// interception du DelayCommand
            
}
        }
        else
        {
           
ActionSpeakString("Merci.");
           return; 
// interception du DelayCommand
        
}
    }
    
// on repouse le DelayCommand ici pour que les variables soient mortes
    
DelayCommand(10.0Avertissement(iCompteur+1oCreature));

Les variables vivantes au moment de son appel sont accessibles à l'intérieur d'un DelayCommand, pour rendre cela possible, l'état du script est sauvegardé en mémoire jusqu'à l'exécution de la commande retardée. Il s'agit donc de minimiser ce qu'il y a à sauvegarder, tu n'as pas besoin de passer oWeapon1, oWeapon2, iWeapon1, iWeapon2 qui sont obsolètes, donc mieux vaux les isoler à l'intérieur d'un bloque.

Une autre petite remarque, un switch est toujours plus rapide qu'une série de if. Puisqu'on y était hein ... Voilà, voilà...

Pom-pom, coupeur de cheveux en quatre.
Tu aurais comme même pu en profiter pour supprimer les "== TRUE" !!

Code PHP:

void Avertissement(int iCompteurobject oCreature)
{

        if (
GetIsObjectValid(GetItemInSlotINVENTORY_SLOT_RIGHTHANDoCreature)) || 
            
GetIsObjectValid(GetItemInSlotINVENTORY_SLOT_LEFTHANDoCreature)) )
        {
            switch( 
iCompteur )
            {
            case 
:
            
                switch( 
Random(2) )
                {
                
                case 
:
                    
ActionSpeakString("Veuillez ranger vos armes s'il vous plait !");
                    break;
                    
                case 
:
                    
ActionSpeakString("Les armes ne sont pas autorisees ici ! Veuillez les ranger");
                }
                
DelayCommand(10.0Avertissement(iCompteur+1oCreature));
                break;           



            case 
:

                
ActionSpeakString("Dernier avertissement, rangez vos armes !!!");
                
DelayCommand(10.0Avertissement(iCompteur+1oCreature));
                break;



            case 
:

                
ActionSpeakString("Vous aurez ete prevenu !");
                
ActionAttack(oCreatureFALSE);
                
            }
            
            

        }

        else

        {

           
ActionSpeakString("Merci.");          

        }

    }

}


void main()

{

    
//This is the equivalent of a force conversation bubble, should only be used if you want an NPC

    //to say something while he is already engaged in combat.

    
if(GetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION) && GetIsPC(GetLastPerceived()) && GetLastPerceptionSeen())

    {

        
SpeakOneLinerConversation();

    }

    
//If the last perception event was hearing based or if someone vanished then go to search mode

    
if ((GetLastPerceptionVanished()) && GetIsEnemy(GetLastPerceived()))

    {

        
object oGone GetLastPerceived();

        if((
GetAttemptedAttackTarget() == GetLastPerceived() ||

           
GetAttemptedSpellTarget() == GetLastPerceived() ||

           
GetAttackTarget() == GetLastPerceived()) && GetArea(GetLastPerceived()) != GetArea(OBJECT_SELF))

        {

           
ClearAllActions();

           
DetermineCombatRound();

        }

    }

    
//Do not bother checking the last target seen if already fighting

    
else if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))

    {

        
//Check if the last percieved creature was actually seen

        
if(GetLastPerceptionSeen())

        {

            if(
GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL))

            {

                
DetermineSpecialBehavior();

            }

            else if(
GetIsEnemy(GetLastPerceived()))

            {

                if(!
GetHasEffect(EFFECT_TYPE_SLEEP))

                {

                    
SetFacingPoint(GetPosition(GetLastPerceived()));

                    
SpeakString("NW_I_WAS_ATTACKED"TALKVOLUME_SILENT_TALK);

                    
DetermineCombatRound();

                }

            }

            
//Linked up to the special conversation check to initiate a special one-off conversation

            //to get the PCs attention

            
else if(GetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION) && GetIsPC(GetLastPerceived()))

            {

                
ActionStartConversation(OBJECT_SELF);

            }

        }

    }

    if(
GetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT) && GetLastPerceptionSeen())

    {

        
SignalEvent(OBJECT_SELFEventUserDefined(1002));

    }


    if (
GetLastPerceptionSeen() && GetIsPC(GetLastPerceived()))

    {

            
Avertissement(1oCreature);

    }


Voilà, c'est optimisé maintenant.
Citation :
tu devrais enlever tous ces tests "== TRUE", ils alourdissent légèrement ton script du point de vue lisibilité comme rapidité
La ok

Citation :
et de plus ils représentent un petit risque avec certaines fonctions.
Ah ? un exemple s'il te plait
"== TRUE" signifie en réalité en NWScript "== 1", or certaines fonctions ne renvoient pas 1 pour signifier la réussite, ex. :
Code PHP:

int GetHasSpell(
    
int nSpell,
    
object oCreature OBJECT_SELF
); 
renvoie le nombre de fois où ce sort peut-être lancé par oCreature.
Donc cette fonction si on fait "== TRUE" risque de renvoyer FALSE alors que le résultat attendu était bien sûr TRUE....

Les fonctions dangereuses sont rares, mais autant ne pas prendre de risques inutiles, alors même que cela alourdit le script...
Citation :
Tu aurais comme même pu en profiter pour supprimer les "== TRUE" !!
Houlà!

C'est vrai que de supprimer carrément les variables c'est encore le mieux.

Pom-pom, partisan du moindre effort au-delà du copier coller
Répondre

Connectés sur ce fil

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