GetInventoryDisturbType() et Escamotage

Répondre
Partager Rechercher
Bonjour tout le monde !
J'ai encore une colle


la fonction GetInventoryDisturbType() permet de renvoyer le type de modification de l'inventaire lorsqu'on le place sur l'évènement "script déclenché par la modification de l'inventaire" (le OnDisturb)

- INVENTORY_DISTURB_TYPE_STOLEN
L'objet est volé dans l'inventaire

- INVENTORY_DISTURB_TYPE_REMOVED
l'objet est enlevé dans l'inventaire

- INVENTORY_DISTURB_TYPE_ADDED
l'objet est ajouté dans l'inventaire


Hors quand je fais des tests (afin de faire script pour que des gardes pas loin puissent éventuellement repérer le vol) je me rend compte que quand le vol est réussi (donc que l'objet sur lequel on a mis le script est une créature), le script mis sur l'event OnDisturb ne se lance pas. En fait, il ne se lance que quand le vol est découvert par le PNJ

voici mon code

Code PHP:

void main()
{
object oTarget GetLastDisturbed();
int iTypeDisturb GetInventoryDisturbType();
if (
iTypeDisturb == INVENTORY_DISTURB_TYPE_STOLEN
               
AssignCommand (oTargetSpeakString("SHOUT_DISTURBED"TALKVOLUME_SILENT_SHOUT));

Le PJ lance un cri silencieux et tous les gardes à côté effectuent un test pour pouvoir remarquer le vol..

Quellqu'un aurait-il une info que j'aurais loupée ? Une piste ?
Citation :
Publié par KorTeX
Bonjour tout le monde !
J'ai encore une colle


la fonction GetInventoryDisturbType() permet de renvoyer le type de modification de l'inventaire lorsqu'on le place sur l'évènement "script déclenché par la modification de l'inventaire" (le OnDisturb)

- INVENTORY_DISTURB_TYPE_STOLEN
L'objet est volé dans l'inventaire

- INVENTORY_DISTURB_TYPE_REMOVED
l'objet est enlevé dans l'inventaire

- INVENTORY_DISTURB_TYPE_ADDED
l'objet est ajouté dans l'inventaire


Hors quand je fais des tests (afin de faire script pour que des gardes pas loin puissent éventuellement repérer le vol) je me rend compte que quand le vol est réussi (donc que l'objet sur lequel on a mis le script est une créature), le script mis sur l'event OnDisturb ne se lance pas. En fait, il ne se lance que quand le vol est découvert par le PNJ

voici mon code

Code PHP:

void main()
{
object oTarget GetLastDisturbed();
int iTypeDisturb GetInventoryDisturbType();
if (
iTypeDisturb == INVENTORY_DISTURB_TYPE_STOLEN
               
AssignCommand (oTargetSpeakString("SHOUT_DISTURBED"TALKVOLUME_SILENT_SHOUT));

Le PJ lance un cri silencieux et tous les gardes à côté effectuent un test pour pouvoir remarquer le vol..

Quellqu'un aurait-il une info que j'aurais loupée ? Une piste ?
C est pas plutot le contenant qui doit lancer le cri ?
non ce n'est pas le contenant c'est plus simple pour récupérer le voleur

et de toute façon le cri n'est pas lancé si le joueur vole un objet sur une créature
Citation :
En fait, il ne se lance que quand le vol est découvert par le PNJ
Jusque là, je dirais que c'est normal, non ?

Tu veux que l'entourage du PNJ puisse remarquer le vol, c'est ça ?
Citation :
Publié par Deyonara
Jusque là, je dirais que c'est normal, non ?

Tu veux que l'entourage du PNJ puisse remarquer le vol, c'est ça ?

et bien oui, je pensias que l'event OnDisturb se lançait quand l'inventaire était modifié, et que INVENTORY_DISTURB_TYPE_STOLENétait renvoyé quand l'objet était volé
L'évènement module se lance par contre, ça j'en suis certain. Sinon tu peux toujours réécrire un système de vol à la tir mais c'est un peu plus long. En résumé : Rendre la skill non-utilisable(flag sur le 2da), ajout d'une action dans le menu contextuel(modification d'ui, contextmenu.xml) et enfin programmation du script personnalisé.
Citation :
Publié par Anthraxcite
L'évènement module se lance par contre, ça j'en suis certain. Sinon tu peux toujours réécrire un système de vol à la tir mais c'est un peu plus long. En résumé : Rendre la skill non-utilisable(flag sur le 2da), ajout d'une action dans le menu contextuel(modification d'ui, contextmenu.xml) et enfin programmation du script personnalisé.
C'est un peu trop compliqué pour ce que je veux faire
Ce qui est bizarre, c'est que l'event se lance parfaitement dans le cas d'une modification de l'inventaire d'un placeable..
La manière la plus propre autre que celle proposée plus haut me semble la suivante :

Dans l'évènement d'acquisition d'un item.
Code:
void main()
{
	object oAcquiredBy = GetModuleItemAcquiredBy();
	object oAcquiredFrom = GetModuleItemAcquiredFrom();
	object oItemAcquired = GetModuleItemAcquired();
	if(!GetIsPC(oAcquiredFrom) && GetIsPC(oAcquiredBy) && GetStolenFlag(oItemAcquired))
	{
		SignalEvent(oAcquiredFrom,EventUserDefined(XXXX));
	}	
}
Donc l'envoie d'un event sur le personnage non qui gérera le vol ou non selon qu'il a le script adéquat, selon le PNJ on peut également choisir une réaction différente. Là ça gère uniquement le fait qu'un PJ vole un PNJ, si j'ai bien lu entre les lignes c'est ça que tu souhaites. Maintenant tu peux aussi tout gérer dans ce script mais je trouverai ça plutôt moche^^.
je pensais pour ma part que GetStolenFlag était une variable placée sur l'objet pour signaler que cet objet devait être vendu au marché noir et qu'elle n'était pas automatiquement placée en ce qui concernent les objet réellement volés
On se sert de ce marqueur pour les coffres crochetés qui devraient avoir un propriétaire. Les échoppes rachetant les objets volés existent aussi grâce à ce marqueur.

N'embête pas trop les roublards avec des scripts qui les empêcheraient d'être des roublards, quand même, hein. ^^
Citation :
Publié par Deyonara
Jusque là, je dirais que c'est normal, non ?
Bin pas trop non. Si le script ne se lance pas à chaque modification de l'inventaire je trouve ça foireux
Dans tous les cas il ne se lance que si le jeu a décidé que le vol a été remarqué

Citation :
Publié par Deyonara
On se sert de ce marqueur pour les coffres crochetés qui devraient avoir un propriétaire. Les échoppes rachetant les objets volés existent aussi grâce à ce marqueur.
oui donc rien à voir avec le GetInventoryDisturbType()
Du coup ce serait pas un bug ?

Citation :
Publié par Deyonara
N'embête pas trop les roublards avec des scripts qui les empêcheraient d'être des roublards, quand même, hein. ^^
J'utilise les règle DD 3.5 et applique un peu de réalisme : un garde peut voir un joueur faire du vol à la tire ; et s'il est sous les ordres de supérieurs qui respectent les consignes de Tyr, doit l'en empêcher

et pi j'embête qui je veux
Ca a peut-être changé dans nwn2 mais dans le 1, une fois qu'on vole un objet il prend automatiquement ce flag. Si on ne tient compte que des objets pris sur PNJs par des PJs et qu'on vérifie le flag en plus on peut être pratiquement certain qu'il s'agit d'un vol à la tir.
Citation :
Publié par Anthraxcite
Ca a peut-être changé dans nwn2 mais dans le 1, une fois qu'on vole un objet il prend automatiquement ce flag. Si on ne tient compte que des objets pris sur PNJs par des PJs et qu'on vérifie le flag en plus on peut être pratiquement certain qu'il s'agit d'un vol à la tir.
ah tiens je n'ai pas vérifié si c'était automatique et d'ailleurs tu as raison on peut le faire de façon automatique ça serait mieux
(j'avais peur de le faire car dans le cas d'une animation le PNJ contrôlé par un DM ne pourrait pas donner d'objet aux joueurs sans que le flag ne se mette mais on va pouvoir gérer ça )

[Edit] j'ai parlé/écrit trop tôt.. dans ce cas là, même si un joueur donne l'objet à un autre joueur, ou bien le ramasse par terre, cela va lancer le script, et donc ne va pas fonctionner seulement pour les vols comme je le voudrais

et je ne vois pas de contrôle assez efficace pour l'empêcher
Au contraire !

De ce que j'ai retenu de "GetItemAcquiredFrom()" dans NWN1, c'est qu'il renverra la valeur OBJECT_INVALID, si l'objet a été récupéré du sol, ou d'une fenêtre d'échange de joueur. Si la fonction renvoie un autre joueur, c'est qu'il y a eu un vol.

La chose à prendre en compte c'est dans le cas où un script fait transiter un objet directement d'un inventaire à un autre. Auquel cas je te suggère de mettre une variable locale pour signaler un transfert "autorisé", que tu enlèves dans le script de l'évènement "OnItemAcquired" du module.

Exemple dans ton "OnItemAcquired" :
Code PHP:

object oAcquiredFrom GetItemAcquiredFrom();
 
object oItem GetModuleItemAcquired();

 
// Si l'objet a été acquis de manière légale :
 
if(GetObjecType(oAcquiredFrom)!=OBJECT_TYPE_CREATURE ||
    
GetLocalInt(oItem,"HAS_NOT_BEEN_STOLEN")==1)
 {
     
// Blablabla, c'est chuper cool, notre objet est légal.
 

Pour les plaçables, tu peux aussi bien utiliser une commande toute bête. Si le plaçable appartient à quelqu'un, et qu'un joueur l'ouvre, tu rajoutes ça dans l'évènement "OnOpen" :
Code PHP:

object oLoop GetFirstItemInInventory(OBJECT_SELF);
 while(
oLoop!=OBJECT_INVALID)
 {
     
SetStolenFlag(oLoop,TRUE);
     
oLoop GetNextItemInInventory(OBJECT_SELF);
 } 
et ça dans l'évènement "OnClosed" :
Code PHP:

object oLoop GetFirstItemInInventory(OBJECT_SELF);
 while(
oLoop!=OBJECT_INVALID)
 {
     
SetStolenFlag(oLoop,FALSE);
     
oLoop GetNextItemInInventory(OBJECT_SELF); 
et justement pour les placeables les scripts balancés sur l'event "modification de l'inventaire" sont lancés quelque soit l'event
Sur les créatures non
bon et bien cela fonctionne bien dans l'event du module OnAcquire

Le cri est lancé, les gardes autour font bien leur jet de dés; donc tout va bien
Le système permettant de rendre plus réaliste les vols, pas de les empêcher (et pi entre 2 joueurs m'en fiche pas mal )




alors les roublards : c'est fait
les lanceurs de sorts : c'est fait
les guerriers : c'est fait...

manque les moines.... qu'est ce que je vais bien pouvoir leur faire ??
Salutation KorteX, Humm tu dis que cela fonctionne, mais quel procédé as tu employé pour que..

As tu utilisé celui de Deyonara ?

merci d'avance..
Citation :
Publié par nosfe_
Salutation KorteX, Humm tu dis que cela fonctionne, mais quel procédé as tu employé pour que..

As tu utilisé celui de Deyonara ?

merci d'avance..

ah vi pardon
je mettrai mes codes ce soir


en gros, avant de mettre ici les détails, lorsque le personnage tente de voler un PNJ :

LE PNJ EST DECOUVERT
le jeu décide de lui même si le pnj voit ou non sa tentative d'escamotage (ça j'arrive pas à l'enlever) et seulement dans ce cas le script OnDisturb est lancé. Du coup dans le OnDisturb, je place un script qui fait que le PNJ crie "au voleur", et soit s'enfuit, soit il attaque le joueur. Quant au joueur il lance une phrase "inaudible" (par les joueurs) pour signaler qu'il s'est fait repéré. Les gardes qui l'entendent l'attaquent après l'avoir insulté ( )

LE PNJ N'EST PAS DECOUVERT
Je place une variable sur tous les PNJs pouvant se faire voler.
Sur le script d'acquisition des objets du module, si l'objet acquis provient d'une créature ayant cette variable, le joueur lance une autre phrase "inaudible". Dans ce cas là, tous les gardes qui entendent cette phrase font un test pour voir s'ils ont remarqué l'escamotage (1) . S'ils le voient les gardes l'attaquent après avoir lancé une autre insulte


Dans le cas où le pnj est découvert et qu'il prend l'objet quand même, les deux phrases sont lancées, mais ce n'est pas grave car les gardes l'attaquent quand même



(1) le test pour voir si l'escamotage est découvert est basé sur les rège DD 3.5

on lance 1d20 et on ajoute sa perception, contre 1d20+ la compétence escamotage du voleur (+2 si le joueur a 5 ou plus en bluff).
j'ai rajouté une difficulté pour la distance (10m => +1, 15m => +2 , et 20m => +3 )
si les jets sont égaux, on regarde les rangs dans les compétences respectives et le plus fort gagne. Si les rangs sont égaux, on refait le jet
bon en retard mais vieux motard que jamais comme on dit !
Vous remarquerez que les cris lancés n'ont rien à voir avec la réalité (I_WAS_DISTURBED, etc... ).. Après avoir réfléchis sur 36 façon de transmettre l'identité du voleur aux autres PNJs qui inter agissent avec l'acte criminel, j'ai décidé de le faire crier par le joueur... c'est plus simple pour le récupérer (GetLastSpeaker() ) et je n'ai pas pris la peine de les modifier


donc voici la fonction que j'utilise pour voir si le vol est détecté

Code PHP:

int GetDetectVol (object oVoleurobject oTargetgard)
{
int iDetect FALSE;
int iSpot GetSkillRank (SKILL_SPOToTargetgard) + GetAbilityModifier (ABILITY_WISDOMoTargetgard); // détection + SAG
int iPickPocket GetSkillRank (SKILL_SLEIGHT_OF_HANDoVoleur) + GetAbilityModifier (ABILITY_DEXTERITYoTargetgard); // escamotage + DEX
if (GetSkillRank (SKILL_BLUFFoVoleur) >= 5iPickPocket iPickPocket 2// +2 si le voleur à un rang 5 en bluff

// modificateurs selon la distance
float fDist GetDistanceBetween (oVoleuroTargetgard);
if (
fDist 20.0fiSpot iSpot -3;
else if (
fDist 15.0fiSpot iSpot 2;
else if (
fDist 10.0fiSpot iSpot 1;

iint iJetVoleur d20()+iPickPocket;
int iJetgard d20()+iSpot;

if (
iJetVoleur iJetgardiDetect TRUE;
else if (
iJetVoleur == iJetgard
    {
    if (
GetSkillRank (SKILL_SLEIGHT_OF_HANDoVoleur) > GetSkillRank (SKILL_SPOToTargetgard)) iDetect TRUE //si les jets sont identiques, le meilleur rang gagne
    
else if (GetSkillRank (SKILL_SLEIGHT_OF_HANDoVoleur) == GetSkillRank (SKILL_SPOToTargetgard)) iDetect GetStealthDetect (oVoleuroTargetgard); // si les rangs sont identiques on refait un jet
    
}
return 
iDetect

le code que j'ai mis dans le OnAcquire du module, je regarde la variable STEAL sur le PNJ

Code PHP:

object oItem GetModuleItemAcquired();
object oGive GetModuleItemAcquiredFrom ();
if (
GetLocalInt (oGive"STEAL") == TRUE)
    {
    
object oTake GetModuleItemAcquiredBy ();
    
// si le passant détecte le vol, il réagira et criera au voleur
    
AssignCommand (oTakeSpeakString("SHOUT_DISTURB"TALKVOLUME_SILENT_TALK));
    } 

Le code mis dans le OnDisturb du PNJ qui se fait voler.
Ce code n'étant lancé que s'il détecte le vol, il n'y a pas de test effectué

Code PHP:

    AssignCommand (oTargetSpeakString("I_WAS_DISTURBED"TALKVOLUME_SILENT_TALK));
    
AssignCommand (oTargetSpeakString("I_WAS_DISTURBED"));
    
int irand Random (3);
        {
        if (
irand == 0)AssignCommand (OBJECT_SELFSpeakString("AU VOLEUR ! AU VOLEUR !"));
        else if (
irand == 1)AssignCommand (OBJECT_SELF,SpeakString("Saleté de...  ! AU VOLEUR !"));
        else if (
irand == 2)AssignCommand (OBJECT_SELF,SpeakString("mais... Hey ! vous ! AU VOLEUR !"));
        
irand Random (6);
        
AssignCommand (OBJECT_SELF,ClearAllActions());
        if  (
irand == 4AssignCommand (OBJECT_SELF,ActionAttack(oTarget));
        else  
AssignCommand (OBJECT_SELF,ActionMoveAwayFromObject(oTargetTRUE));
        } 

le code que j'ai mis sur les garde, dans l'event OnDial
Code PHP:

void main()
{
int nHeard GetListenPatternNumber();
object oSpeaker GetLastSpeaker();
if (
nHeard == -1)
    {
    
BeginConversation();
    }
else
    {
    
object oVoleur
    
int iRand;
    if(
GetIsObjectValid(oSpeaker))
    {
        switch(
nHeard)
        {
        
// un vol détecté ou attaque
        
case 1:
            {
            if(!
GetIsEnemy (oSpeaker))
                {
                
oVoleur GetLocalObject (oSpeaker"voleur");
                
iRand Random (4);
                if (
iRand == 0SpeakString ("Au nom de Torm !");
                else if (
iRand == 1SpeakString ("Tu vas voir sale bouseux!");
                else if (
iRand == 2SpeakString ("Hey toi là bas !");
                else if (
iRand == 3SpeakString ("Tu vas le payer !");
                
ClearAllActions();
                
ActionAttack (oVoleur);
                }
            break;
            }
        
// vol non détecté
        
case 2:
            {
            
oVoleur GetLocalObject (oSpeaker"voleur");
            if ((!
GetIsEnemy (oSpeaker))&&(GetDetectVol (oVoleurOBJECT_SELF)))
                {
                
iRand Random (4);
                if (
iRand == 0SpeakString ("Au nom de Torm ! Sale voleur !");
                else if (
iRand == 1SpeakString ("Toi là bas ! Tu vas voir sale bouseux!");
                else if (
iRand == 2SpeakString ("Hey toi là bas ! Arrête ! ");
                else if (
iRand == 3SpeakString ("Au nom de Lomann ! Arrête toi !");
                
ClearAllActions();
                
ActionAttack (oVoleur);
                }
            break;
            }
        
// une attaque
        
case 3:
            {
            if (!
GetIsEnemy (oSpeaker))
                {
                
iRand Random (4);
                if (
iRand == 0SpeakString ("Au nom de Torm !");
                else if (
iRand == 1SpeakString ("Tu vas voir sale bouseux!");
                else if (
iRand == 2SpeakString ("A moi la garde !");
                else if (
iRand == 3SpeakString ("Tu vas le payer !");
                
ClearAllActions();
                
ActionAttack (oVoleur);
                }
            break;
            }    
        }
    }
    }

et j'ai rajouté ça dans leur script de Spawn, afin qu'ils détectent les cris

Code PHP:

 SetListenPattern(OBJECT_SELF"I_WAS_DISTURBED",1); // vol détecté
    
SetListenPattern(OBJECT_SELF"SHOUT_DISTURBED",2); // vol non détecté
    
SetListenPattern(OBJECT_SELF"NW_I_WAS_ATTACKED",3); // une attaque
    
    
SetListening(OBJECT_SELF,TRUE); 
La fonction "GetDetectVol()" était toute cassée, j'y ai mis quelques pansements :
Code PHP:

int GetDetectVol(object oVoleurobject oTargetgard)
{
    
int iDetect FALSE;
    
int iSpot GetSkillRank(SKILL_SPOT,oTargetgard);
    
int iPickPocket GetSkillRank(SKILL_SLEIGHT_OF_HAND,oVoleur);
    if(
GetSkillRank(SKILL_BLUFF,oVoleur)>=5)
        
iPickPocket += 2// +2 si le voleur à un rang 5 en bluff

    // modificateurs selon la distance
    
float fDist GetDistanceBetween(oVoleur,oTargetgard);
    if(
fDist>20.0)
        
iSpot -= 3;
    else if (
fDist>15.0)
        
iSpot -= 2;
    else if (
fDist>10.0)
        
iSpot -= 1;

    
// Il me semble que GetSkillRank() prend déjà en
    // compte les modificateurs des caractéristiques.
    
int iJetVoleur d20()+iPickPocket/*+GetAbilityModifier(ABILITY_DEXTERITY,oVoleur)*/;
    
int iJetgard d20()+iSpot/*+GetAbilityModifier(ABILITY_WISDOM,oTargetgard)*/;

    if(
iJetVoleur<iJetgard)
        
iDetect TRUE;
    else if(
iJetVoleur==iJetgard
    {
        
// si les jets sont identiques, le meilleur rang gagne
        
if(iPickPocket<iSpot)
            
iDetect TRUE;
        
// si les rangs sont identiques on refait un jet
        
else if(iPickPocket==iSpot)
            
iDetect GetDetectVol(oVoleur,oTargetgard);
    }
    return 
iDetect;

Pour ton garde, un simple if/else peut faire l'affaire :
Code PHP:

void main()
{
    
int nHeard GetListenPatternNumber();
    
object oSpeaker GetLastSpeaker();
    if(
nHeard==-1)
        
BeginConversation();
    else if(
nHeard>&& nHeard<4)
    {
        
oVoleur GetLocalObject(oSpeaker,"voleur");
        
int iRand Random (4);
        
string sString;
        
// un vol détecté ou attaque
        
if(nHeard==|| nHeard==3):
        {
            
sString "Au nom de Torm !";
            if(
iRand==1)
                
sString "Tu vas voir sale bouseux!";
            else if(
iRand==2)
                
sString "Hey toi là bas !";
            else if(
iRand==3)
                
sString "Tu vas le payer !";
            
SpeakString(sString);
            
ClearAllActions();
            
ActionAttack(oVoleur);
        }
        
// vol non détecté
        
else if(nHeard==&& GetDetectVol(oVoleur,OBJECT_SELF)==TRUE)
        {
            
sString "Au nom de Torm ! Sale voleur !";
            if(
iRand==1)
                
sString "Toi là bas ! Tu vas voir sale bouseux!";
            else if(
iRand==2)
                
sString "Hey toi là bas ! Arrête ! ";
            else if(
iRand==3)
                
sString "Au nom de Lomann ! Arrête toi !";
            
SpeakString(sString);
            
ClearAllActions();
            
ActionAttack(oVoleur);
        }
    }

Par contre il va falloir te mettre d'accord avec toi-même pour mettre le joueur en variable (mieux à mon sens) ou faire du joueur celui qui lance la phrase. ^^
Citation :
Publié par Deyonara
La fonction "GetDetectVol()" était toute cassée, j'y ai mis quelques pansements :
merki je l'ai bidouillé afin qu'elle soit mieux pour tout le monde en fait, car je sauvegarde les vols sur des base de données, et au départ j'avais fait un test de détection et non pas de voleur..
et vue l'heure, je me suis emmelé les pinceaux

Et je ne savais pas que ça prenait en compte les modificateurs des caractéristiques associées


Citation :
Publié par Deyonara
Pour ton garde, un simple if/else peut faire l'affaire :
J'ai pris encore des codes de mes codes et ça me paraissait plus simple pour les relire.. j'ai pas mal d'autres choses (contrôle de joueurs recherchés par la garde, faits marquant, etc... )

Et je préfère différencier l'attaque du vol dans ce qu'ils disent (ce qui n'est pas le cas pour le moment )


Citation :
Publié par Deyonara
Par contre il va falloir te mettre d'accord avec toi-même pour mettre le joueur en variable (mieux à mon sens) ou faire du joueur celui qui lance la phrase. ^^
C'est un reste de mon indécision..
Il suffit d'enlever les oVoleur = GetLocalObject(oSpeaker,"voleur"); des codes sur le OnDial des gardiens
Par contre je tiens à dire qu'il faut sur le OnDial du gardien une exclusion

Code PHP:

 if GetIsEnemy (oSpeaker) return ; 

sinon le garde va dire des choses à chaque round et à chaque fois qu'un garde attaquera. Quand il y a 4 gardes, ça risque d'être marrant mais assez vite saoûlant
Répondre

Connectés sur ce fil

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