La Bibliothèque de Neverwinter Nights
Aide et informations diverses sur Neverwinter Nights ainsi que D&D3.
La date/heure actuelle est 19/04/2024 16:07:36


  Page 2 sur 2 ¤ Aller à la page Précédente  1, 2

Voir le sujet précédent ¤ Voir le sujet suivant 
Auteur Message
lylver
Héros
Inscrit le: 08 Avr 2005
Messages: 274
Répondre en citant
Posté le : 02/01/2006 17:10:32 Sujet du message : Boutiques à la demande

Les boutiques, le grand bonheur des joueurs sur NWN ! Razz
Non sans déconner, beaucoup de joueurs jugent l'attrait d'un module à la richesse de ses boutiques. Qu'on soit d'accord ou pas sur ce qu'il faut mettre dedans : il faut penser que ces fameux endroits finissent par devenir un vrai casse-tête pour le gestionnaire/builder du module.
Comment assurez un peu de cohérence : que tout soit géré dans la palette.
Oui mais ... la palette personnalisée c'est lent.
Exact, certains travaillent sur le concept de boutiques "dynamiques" mais en attendant que ce soit au point ou publié, il faut bien commencer par le début : les boutiques à la demande.

Voici un premier jeu de script et plus loin le complément pour le GC (nettoyeur que j'ai publié dans les pages de ce forum) pour créer à la demande, pendant un dialogue, une boutique gérée dans la palette.

La méthode :
1) créer votre boutique dans la palette, avec la convention suivante : TAG en majuscule de 15 caractères au plus, le ResRef => la même chose mais en minuscule
2) Réserver dans votre module une zone 2x2 vide contenant un point de passage taggé "TN_SHOP"
3) le personnage vendeur (celà peut être autre chose qu'un personnage mais il devra être associé à un dialogue) doit être complémenté de variables locales pour retrouver les TAG des boutiques (TN_DYN_SHOPx)
4) Construisez le dialogue du vendeur et ajouter dans la branche finale donnant lieu à l'ouverture le script "shop_local_var" en "action conséquente"


Note : en positionnant dans une des branches de sélection une variable locale pour sélectionner le n° de la boutique on peut gérer du multiboutique.

Voici les scripts :
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :
//:: ////
//:: shop_local_var.nss
//:: Update Lylver 2005-10-02
//:: gestion multi-boutiques et prise en charge par le GC
//:: mettre un entier "TN_IDX_SHOP" de 0 a 9 (via le dialogue)
//:: sur le personnage gerant la boutique
//:: pour selectionner la boutique a ouvrir
//:: renseigner le personnage avec les tags des boutiques
//:: sous le forme de variables chaines
//:: TN_DYN_SHOPx (x de 0 a 9)
//:: il faut egalement mettre un script sur On Open Store et On Close Store
//:: pour indiquer l'etat d'occupation
//:: ////
//:: update Lylver 2005-09-25
//:: adaptation TN Bouchon
//:: Les Boutiques sont exclusivement dans la palette grace a cela, plus d'incoherence
//:: ni de double gestion.
//:: // convention de noms :
//:: 1) variable sur le PNJ : string TN_DYN_SHOP = TAG en majuscule
//:: 2) le resref de la boutique est forcement en minuscule, maximum 15 caracteres svp
//:: 15 caracteres, pas 16 Sad
//:: la boutique est cree sur demande dans la zone 0001 module_dynamic_shop
//:: certaines boutiques pourront beneficier d'un "shop_remove", a voir.
//:: ////
//:: // update Lylver 2005-07-22
//:: // suivant variable du PNJ
//:: ////
//:: // update Lylver 2005-06-12
//:: // creation de l'echoppe au besoin
//:: ////
/* shop_advanced
* dluan on mar 2003 */

//:: Update Lylver 2005-01-20
//:: inclue l'estimation
//:: +/-30%
#include "nw_i0_plot"
void main()
{
    object oPC = GetPCSpeaker();
    int iShop = GetLocalInt(OBJECT_SELF,"TN_IDX_SHOP") ;// 0 par defaut du coup
    string sShop = GetLocalString(OBJECT_SELF,"TN_DYN_SHOP"+IntToString(iShop)) ;
    object oShop = GetObjectByTag("TN_SHOP");
    object oStore = GetObjectByTag(sShop);
    if( GetIsObjectValid( oStore ) ){
      SendMessageToAllDMs(sShop+"");
    } else {
      SendMessageToAllDMs(sShop+"");
      oStore = CreateObject(OBJECT_TYPE_STORE, GetStringLowerCase(sShop), GetLocation(oShop));
      // indicateur pour le GC
      SetLocalObject(GetArea(OBJECT_SELF),"TN_DYN_SHOP"+IntToString(iShop),oStore);
      SendMessageToAllDMs("Debug : "+GetName(oStore)+"");
    }
    if (GetObjectType(oStore) == OBJECT_TYPE_STORE)
    {
        gplotAppraiseOpenStore(oStore, oPC);
    }
    else
    {
        ActionSpeakStringByStrRef(53090, TALKVOLUME_TALK);
    }
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Pour la sélection multiboutique : utiliser des scripts comme celui qui suit mis en "action conséquente" dans une branche de dialogue supplémentaire, déclenchée par un choix joueur.

Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :
//:: ////////////////////////////// /////////////////
//:: FileName shop_set_idx_00
//:: Created Lylver 2005-11-13
//:: ////////////////////////////// ////////////////
void main()
{
  SetLocalInt(OBJECT_SELF,"TN_IDX_SHOP",0) ; // marqueur boutique dyn.
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Voilà : bonne utilisation Cool
Cela devrait éviter les prises de têtes régulières sur les items qui sont modifiés au fur et à mesure : également dans le cas d'items standards le gain de place dans le module n'est pas négligeable : seul le resref est stocké, la description de l'item n'est faite qu'une fois.
De plus pour ceux qui connaissent ou qui ont un problème d'obésité pour leur module : cette technique permet de passer en hak les boutiques en même temps que les items par la suite (par contre il faut aller piocher les fichiers .utm dans <NWN path>\modules\temp0 : ne pas exporter !)

Les scripts qui suivent sont les compléments et mise à jour pour le système de nettoyage GC

Deux scripts à mettre sur la boutique en palette

Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :
//:: ////
//:: tn_onopen_store.nss
//:: Created Lylver 205-10-02
//:: OnOpenStore pour les boutiques dynamiques
//:: ////
void main()
{
  SetLocalInt(OBJECT_SELF,"BUSY",TRUE) ;
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :
//:: ////
//:: tn_onclose_stor.nss
//:: Created Lylver 205-10-02
//:: OnCloseStore pour les boutiques dynamiques
//:: ////
void main()
{
  DeleteLocalInt(OBJECT_SELF,"BUSY") ;
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Mise à jour d'un fichier include

Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :
//:: ////
//:: ly_lib_area.nss
//:: Update Lylver 2005-10-02
//:: gestion multi-boutiques et prise en charge par le GC
//:: mettre un entier "TN_IDX_SHOP" de 0 a 9 (via le dialogue)
//:: sur le personnage gerant la boutique
//:: pour selectionner la boutique a ouvrir
//:: renseigner le personnage avec les tags des boutiques
//:: sous le forme de variables chaines
//:: TN_DYN_SHOPx (x de 0 a 9)
//:: il faut egalement mettre un script sur On Open Store et On Close Store
//:: pour indiquer l'etat d'occupation
//:: ////
//:: Lylver 2005-01-12
//:: Include File for Area Cleaning
//::

int CheckPJInArea(object oArea) {
  object oObject = GetFirstObjectInArea(oArea) ;
  int nCount = 0 ;
  while (GetIsObjectValid(oObject)) {
      if (GetIsPC(oObject)) {
      nCount++ ;
      break ;
      }
      oObject = GetNextObjectInArea(oArea) ;
  }
  return nCount ;
}

int CheckPJetDMInArea(object oArea) {
  object oObject = GetFirstObjectInArea(oArea) ;
  int nCount = 0 ;
  while (GetIsObjectValid(oObject)) {
      if (GetIsPC(oObject) || GetIsDM(oObject) || GetIsDMPossessed(oObject)) {
      nCount++ ;
      break ;
      }
      oObject = GetNextObjectInArea(oArea) ;
  }
  return nCount ;
}

// * returns true if there is no player in the area
// * has to be ran from an object
// source xp2 module modifie
int NoPlayerInArea(object oArea) {
    object oFirst = GetFirstObjectInArea(oArea) ;
    if( GetIsPC(oFirst) || GetIsDM(oFirst) || GetIsDMPossessed(oFirst) ) return FALSE ;
    // pour le cas ou le seul objet est un PC
    if( !GetIsObjectValid(oFirst) ){
      SendMessageToAllDMs("Erreur : no valid object for GetFirstObjectInArea") ;
      return TRUE;
    }
    object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oFirst);
    return !GetIsObjectValid(oPC); // * no player in area
}

int CleanStore(object oArea) {
  object oShop ;
  int i, n=0;
  for( i=0 ; i<10 ; i++ ){ // max 10 boutiques (0 a 9)
      oShop = GetLocalObject( oArea, "TN_DYN_SHOP"+IntToString(i) ) ;
      if( GetIsObjectValid( oShop ) ){
        if( GetLocalInt( oShop,"BUSY" ) ){
            break ; // boutique accessible de plusieurs endroits
        } else {
            SendMessageToAllDMs("Dynamic Shop "+GetTag(oShop)+" destroyed");
            WriteTimestampedLogEntry("Dynamic Shop "+GetTag(oShop)+" destroyed");
            DestroyObject(oShop) ;
            n++ ;
        }
      }
  }
  return n;
}

int CleanBodyBag(object oArea, int nMax = 50) {
  int nCost = 0 ;
/*  if( CheckPJInArea(oArea) &gt; 0 ){
      SendMessageToAllDMs("Clea nBodyBag : PC is in Area") ;
      return nCost ;
  } // ne pas faire deux fonctions d'exploration de la zone imbriquee
*/
// Gestion par le OnEnter =&gt; cancel GC
  object oItem ;
  object oBag = GetFirstObjectInArea(oArea) ;
//  SendMessageToAllDMs("Clea nBodyBag : " + GetName(oBag) + GetTag(oBag) + GetResRef(oBag)) ;
  while (GetIsObjectValid(oBag)) {
      if( (GetObjectType(oBag) == OBJECT_TYPE_PLACEABLE) && (GetTag(oBag) == "BodyBag") ){
        nCost++ ; // incremente le nombre des objets effectivement traites
        oItem = GetFirstItemInInventory(oBag) ;
        while (oItem != OBJECT_INVALID) {
            nCost++ ;
            // SendMessageToAllDMs("Clea nBodyBagItem : " + GetName(oItem) + GetTag(oItem) + GetResRef(oItem)) ;
            DestroyObject(oItem) ;
            oItem = GetNextItemInInventory(oBag) ;
        } // while
        // DestroyObject(oBag,0.1) ; pas besoin : le moteur le fait, mais ou passent les BodyBags ?
      } // if
      oBag = GetNextObjectInArea(oArea) ;
      // SendMessageToAllDMs("Clea nBodyBag : " + GetName(oBag) + GetTag(oBag) + GetResRef(oBag)) ;
      // SendMessageToAllDMs("Clea nBodyBag : Total Traite" + IntToString(nCost)) ;
      if (nCost > nMax) { nCost = -1 * nCost ; break ;}
  } // while
  return nCost ;
}

int CleanPNJ(object oArea, int nMax = 50) {
  object oPnj = GetFirstObjectInArea(oArea) ;
  int nCost = 0 ;
  while (GetIsObjectValid(oPnj)) {
      if( GetIsEncounterCreature(oPnj) ){
        nCost++ ;
        DestroyObject(oPnj) ;
      } // if
      oPnj = GetNextObjectInArea(oArea) ;
      // SendMessageToAllDMs("Clea nPNJ : Total Traite" + IntToString(nCost)) ;
      if (nCost > nMax) { nCost = -1 * nCost ; break ;}
  } // while
  return nCost ;
}

int CleanItem(object oArea, int nMax = 50) {
  object oItem = GetFirstObjectInArea(oArea) ;
  object oLostItem = GetObjectByTag("CHEST_LOST_ITEM") ;
  int nCost = 0 ;
  while (GetIsObjectValid(oItem)) {
      if( GetObjectType(oItem) == OBJECT_TYPE_ITEM ){
        nCost++ ;
        CopyItem(oItem,oLostItem) ;
        DestroyObject(oItem) ;
      } // if
      oItem = GetNextObjectInArea(oArea) ;
      // SendMessageToAllDMs("Clea nItem : Total Traite" + IntToString(nCost)) ;
      if (nCost > nMax) { nCost = -1 * nCost ; break ;}
  } // while
  return nCost ;
}

// void main() {}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Le "main" GC

Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :
//:: ////
//:: ly_mod_area_gc.nss
//:: Update Lylver 2005-10-02
//:: gestion multi-boutiques et prise en charge par le GC
//:: ////
//:: Lylver 2005-04-28
//:: nouvelle fonction de test PJ dans zone
//:: GC main non affecte
//:: ////////////////////////////// //////
//:: Lylver 2005-03-08
//:: Copie des items perdus (abandonne)
//:: dans le coffre des objets trouves
//:: ////////////////////////////// //////
//:: Lylver 2005-01-12
//:: Module Garbage Collector
//:: Put on ModUserDef

#include "ly_lib_area"

void main() {
  object oMod = GetModule() ;
  int nBodyBag=0,nPNJ=0,nItemLost=0,bEmptyArea,nStore=0 ;
  int CleanP = GetLocalInt(oMod,"CLEANP") ;
  string sArea = "" ;
  object oArea = GetLocalObject(oMod,"CLEANQ") ;
  // SendMessageToAllDMs("GC : Hello ! I'm Here !") ;
  if (oArea != OBJECT_INVALID) { // j'ai une zone a traiter
      sArea = GetTag(oArea) ; // un run de nettoyage courant
      /* code */
      SendMessageToAllDMs("GC : operating on Area : " + GetName(oArea)) ;
      WriteTimestampedLogEntry("GC : operating on Area : " + GetName(oArea)) ;
      bEmptyArea = NoPlayerInArea(oArea) ;
      if( GetLocalInt(OBJECT_SELF,"PC_HERE") == 1 ){
        SendMessageToAllDMs("Warning GC : PC_HERE est a etat 1");
        WriteTimestampedLogEntry("Warning GC : PC_HERE est a etat 1");
      }
        // default cleaning : 50 items in one pass, return negative for 2nd check later
        // CleanBodyBag(object oArea, int nMax = 50)
      if( bEmptyArea ){ // si la zone est effectivement vide on nettoie
        nBodyBag = CleanBodyBag(oArea) ;
        nPNJ = CleanPNJ(oArea) ;
        nItemLost = CleanItem(oArea) ;
        nStore = CleanStore(oArea) ;
      } else { // mais si quelqu'un est la, on abandonne et on purge la queue
        DeleteLocalInt(oMod,"CLEANQ" + sArea) ;
        DeleteLocalObject(oMod,"CLEANQ") ;
        DelayCommand(6.0,SignalEvent(OBJECT_SELF, EventUserDefined(300))) ; // pas trop vite
        return ; // exit et recommence
      }
      // test si c'est fini (pas de code retour negatif
      if( (nBodyBag >= 0) && (nPNJ >= 0) && (nItemLost >=0) ){ // oui on prend la requete suivante
        DeleteLocalInt(oMod,"CLEANQ" + sArea) ;
        DeleteLocalObject(oMod,"CLEANQ") ;
        DelayCommand(6.0,SignalEvent(OBJECT_SELF, EventUserDefined(300))) ; // qu'on examine
        return ; // exit et recommence
      } else { // on termine rapidement
        SetLocalInt(oMod,"CLEANQ" + sArea, 29 + GetLocalInt(oMod,"CLEANQ" + sArea)) ; // passage + rapide
      }
  } else { // pas de zone en cours, alors on examine les requetes
      oArea = GetLocalObject(oMod,"CLEANR") ;
      if (oArea != OBJECT_INVALID) { // trouve qq chose a faire
        // SendMessageToAllDMs("GC : switching to Area : " + GetName(oArea)) ;
        sArea = GetTag(oArea) ; // gere la file d'attente
        SetLocalObject(oMod,"CLEANQ",oArea) ; // passe en clean courant
        SetLocalInt(oMod,"CLEANQ" + sArea, CleanP) ; // delai suivant
        // dependant de la plus longue des autres attentes en cours
        DeleteLocalInt(oMod,"CLEANR" + sArea) ;// libere le semaphore
        DeleteLocalObject(oMod,"CLEANR") ;
      } else { // meme si pas prise, il peut y avoir une demande de plus faible priorite
      // en boucle, on en tient compte en retestant plus vite apres reset priorite
        sArea = "" ;
        if( CleanP > 0 ){
            SetLocalInt(oMod,"CLEANQ", CleanP) ; // delai suivant
            DeleteLocalInt(oMod,"CLEANP") ; // reset priorite globale
        }
      }
      // else SendMessageToAllDMs("GC : Nothing to Do") ;
  }
  // on ne nettoie pas immediatement mais en fonction de la priorite de la requete
  // pour conserver une latence avant destruction des monstres 174s mini + 6s du a la purge
  float fDelay = 180.0 - 6.0 * IntToFloat((1+GetLocalInt(oMod,"CLEANQ"+sArea))) ; // 180 secondes maxi
  if (fDelay < 6.1) fDelay = 6.1 ; // pas trop vite pour la sortie de boucle des OnExit
  DelayCommand(fDelay, SignalEvent(OBJECT_SELF, EventUserDefined(300)));
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
lylver
Héros
Inscrit le: 08 Avr 2005
Messages: 274
Répondre en citant
Posté le : 06/01/2006 13:27:52 Sujet du message : Spell hooking

Après quelques mois de modifications, voici un exemple concret et consistant de spell-hooking.
vous trouverez ci-après le coeur du spell-hooking du TN Bouchon : je vous le propose car il a fallu un peu de méthode pour arriver à quelque chose qui soit suffisement clair, exempt de surprise (sorts qui bouclaient à l'infini).
Les sources complets sont là :
Exemple complet de spell-hooking
Comme l'indiquait Finipe dans la section tutoriel, j'active le spell hooking sur chaque zone du module.

Le script du OnModuleLoad
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :
//:Confused/
//:: tn_mod_def_load.nss
//:: Update Lylver 2005-09-16
//:: + spell hooking
//:Confused/

#include "x2_inc_switches"
#include "x2_inc_restsys"

void main()
{
//---------------------------- ------------------------------ --------------------
//                          S P E L L S C R I P T S
//---------------------------- ------------------------------ --------------------

//---------------------------- ------------------------------ --------------------
// Allows the module creator to specify a script that will be run before any spellscript is run
// You can call SetModuleOverrideSpellscript() at the end of the script specified by
// sScriptName. If you call this function this will prevent the original spellscript
// (and all craft item code) from being executed.
// If you do not add this line, the original spellscript and/or crafting code will
// run in addition to your script
//---------------------------- ------------------------------ --------------------
//void SetModuleOverrideSpellscript(s tring sScriptName);

// * activation du spell hooking
  SetLocalString(GetModule(), "X2_S_UD_SPELLSCRIPT", "tn_mod_spells");
//

}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Fichier d'include pour la définition d'une structure et outil de debug
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :
//:Confused/
//:: Created Lylver 2005-09-16
//:: include pour sorts
//:: ly_lib_spell
//:Confused/
struct spell_data{
  object oSelf ; // passer OBJECT_SELF
  int nSpId ; // GetSpellId(); returns the SPELL_* constant of the spell cast
  object oTgtObj ; // GetSpellTargetObject(); returns the targeted object of the spell, if valid
  location lTgtLoc ; // GetSpellTargetLocation(); returns the targeted location of the spell, if valid
  int nClass ; // GetLastSpellCastClass(); gets the class the PC cast the spell as
  object oCItem ; // GetSpellCastItem(); if an item cast the spell, this function gets that item
  int nSSDC ; // GetSpellSaveDC(); gets the DC required to save against the effects of the spell
  int nLevel ; // GetCasterLevel(OBJECT_SELF); gets the level the PC cast the spell as
  int nMeta ; // GetMetaMagicFeat(); Get the metamagic type (METAMAGIC_*) of the last spell cast by the caller
};

void dump_spell( struct spell_data stS, string sScript = "" ){
  WriteTimestampedLogEntry(sScript+" : "+
  "Spell ID : "+IntToString(stS.nSpId)+
  " Cible : "+GetName(stS.oTgtObj)+
  " Class nb : "+IntToString(stS.nClass)+
  " Item Name : "+GetName(stS.oCItem)+
  " Spell DC : "+IntToString(stS.nSSDC)+
  " Caster Level : "+IntToString(stS.nLevel)+
  " Metamagic : "+IntToString(stS.nMeta));
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Début du fichier de définition des fonctions associées aux sorts "hookés"
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :
//:Confused///
//:: Created 2005-12-27, Lylver
//:: compilation des fichiers de sorts
//:Confused///
#include "x2_inc_switches"
#include "ly_lib_spell"
#include "ly_lib_death" // lib pour carte de mort etc...
#include "ly_nw_i0_spells" // nw_io_spell refait
#include "ly_x0_i0_spells" // idem
#include "ly_x2_i0_spells" // idem
#include "x2_inc_spellhook"


//:Confused/////
//:: Updated 2005-10-05, Lylver
//:: Spell-Hooking, TN Bouchon
//:Confused///////////////////////// /////////////////////
//:: Update Lylver 2005-07-21
//:: duree corrigee : 1 heure/level au lieu 1 tour/level
//:Confused///////////////////////// /////////////////////
//:: Update Lylver 2005-07-21
//:: duree corrigee : 1 tour/level au lieu 1 round/level
//:: efficacite reduite : 3 + 1/4 level
//:: effet supplementaire : immunite a aveuglement (~ blind fighting)
//:: si jet de talent ecoute &gt;20
//:: en reflexion diminution save son : non implementee
//:Confused///////////////////////// /////////////////////
//:: Amplify
//:: x0_s0_amplify.nss
//:: Copyright (c) 2002 Bioware Corp.
//:Confused///////////////////////// ////////////////////
/*
    The caster or target is able to hear sounds better.
    Listen skill increases by 20.
    DURATION: 1 round/level
*/

//:Confused///////////////////////// ////////////////////
//:: Created By: Brent Knowles
//:: Created On: July 30, 2002
//:Confused///////////////////////// ////////////////////

void ly_s0_amplify(struct spell_data stS)
{
/*
  struct spell_data stS ;
  stS.oSelf = OBJECT_SELF;
  stS.nSpId = GetSpellId();
  stS.oTgtObj = GetSpellTargetObject();
  stS.lTgtLoc = GetSpellTargetLocation();
  stS.nClass = GetLastSpellCastClass();
  stS.oCItem = GetSpellCastItem();
  stS.nSSDC = GetSpellSaveDC();
  stS.nLevel = GetCasterLevel(OBJECT_SELF);
  stS.nMeta = GetMetaMagicFeat();
*/

/*
  Spellcast Hook Code
  Added 2003-06-23 by GeorgZ
  If you want to make changes to all spells,
  check x2_inc_spellhook.nss to find out more
*/

    if (!X2PreSpellCastCode())
    {
    // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
      SetModuleOverrideSpellScriptFinished();
      return;
    }
// End of Spell Cast Hook
    //Declare major variables
    object oTarget = stS.oTgtObj ;
    effect eVis = EffectVisualEffect(VFX_IMP_IMPROVE_ABILITY_SCORE);
    int nMetaMagic = stS.nMeta ;
    int nCasterLevel = stS.nLevel ;
    int nBonus = 3 + (nCasterLevel/4) ;
    effect eHide = EffectSkillIncrease(SKILL_LISTEN, nBonus );
    if( (d20() + GetSkillRank(SKILL_LISTEN,oTarget) + nBonus) > 20 ){
      eHide = EffectLinkEffects(EffectImmunity(IMMUNITY_TYPE_BLINDNESS),eHide);
    }
    effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
    effect eLink = EffectLinkEffects(eHide, eDur);

    int nDuration = nCasterLevel ; // * Duration 1 turn/level
    if (nMetaMagic == METAMAGIC_EXTEND) //Duration is +100%
    {
        nDuration = nDuration * 2;
    }

    //Fire spell cast at event for target
    SignalEvent(oTarget, EventSpellCastAt(stS.oSelf, SPELL_AMPLIFY, FALSE));
    //Apply VFX impact and bonus effects
    ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, HoursToSeconds(nDuration));
SetModuleOverrideSpellScriptFinished();
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Script principal
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :
//:Confused/////
//:: Updated 2005-12-25, Lylver
//:: ghostly visage, horrid wilting
//:: for future spell addition : see inside for the list
//:Confused/////
//:: Updated 2005-12-22, Lylver
//:: color spray, expeditious retreat
//:Confused/////
//:: Updated 2005-10-16, Lylver
//:: tests avec bilaes
//:Confused/////
//:: Updated 2005-10-04, Lylver
//:: timestop
//:Confused/////
//:: Updated 2005-09-27, Lylver
//:: restorations
//:Confused/
//:: Update Lylver 2005-09-24
//:: summons
//:: Update Lylver 2005-09-16
//:: + spell hooking tnb : chgt RAISE_DEAD
//:Confused/
//:Confused////////////////////
//:: created Lylver 2005-06-10
//:: spell-hooking main
//:: 1st purpose : scrolls DC for thieves
//:Confused////////////////////
/*
GetSpellId(); // returns the SPELL_* constant of the spell cast
GetSpellTargetObject(); // returns the targeted object of the spell, if valid
GetSpellTargetLocation(); // returns the targeted location of the spell, if valid
GetLastSpellCastClass(); // gets the class the PC cast the spell as
GetSpellCastItem(); // if an item cast the spell, this function gets that item
GetSpellSaveDC(); // gets the DC required to save against the effects of the spell
GetCasterLevel(OBJECT_SELF); // gets the level the PC cast the spell as
*/
/* ces includes sont dans ly_lib_sorts
#include "x2_inc_switches"
#include "ly_lib_spell"
#include "ly_lib_death"
#include "ly_nw_i0_spells"
#include "ly_x0_i0_spells"

#include "x2_inc_spellhook"
*/
#include "ly_lib_sorts"
// #include "ly_s0_firebrand" 2005-12-29
// #include "ly_s0_virtue" 2005-12-29
// #include "ly_s0_missstorm1" 2005-12-29
// #include "ly_s0_missstorm2" 2005-12-29
// #include "ly_s0_divpower" 2005-12-29
// #include "ly_s0_divfav" 2005-12-27
// #include "ly_s0_harm" 2005-12-29
// #include "ly_s3_summonelem" // it is an activate item
// #include "ly_s0_summon" 2005-12-29
// #include "ly_s0_lsrestor" 2005-12-29
// #include "ly_s0_restore" 2005-12-29
// #include "ly_s0_grrestore" 2005-12-29
// #include "ly_s0_remeffect" 2005-12-29
// #include "ly_s0_phankill" 2005-12-29
// #include "ly_s0_timestop" 2005-12-29
// #include "ly_s0_knock" 2005-12-29
// #include "ly_s0_findtrap" 2005-12-29
// #include "ly_s0_light" 2005-12-29
// #include "ly_s0_darkness" 2005-12-27
// #include "ly_s0_prgood" 2005-12-29
// #include "ly_s0_previl" 2005-12-29
// #include "ly_s0_clarity" 2005-12-27
// #include "ly_s0_rmvparal" 2005-12-29
// #include "ly_s0_curcrwn" 2005-12-27
// #include "ly_s0_curserw" 2005-12-27
// #include "ly_s0_truesee" 2005-12-29
// #include "ly_s0_amplify" 2005-12-27
// #include "ly_s0_clairadvo" 2005-12-27
// #include "ly_s0_flmstrike" 2005-12-29
// #include "ly_s0_hammgods" 2005-12-29
// #include "ly_s0_healcirc" 2005-12-29
// #include "ly_s0_shadshld" 2005-12-29
// #include "ly_s0_weird" 2005-12-29
// #include "ly_s0_magearm" 2005-12-29
// #include "ly_s0_colspray" 2005-12-27
// #include "ly_s0_healingkit" ------
// #include "ly_s0_exretreat" 2005-12-29
// #include "ly_s0_ghostvis" 2005-12-29
// #include "ly_s0_horrwilt" 2005-12-29
// #include "ly_s0_premo" 2005-12-29
// #include "ly_s0_stoneskn" 2005-12-29

void main()
{
  // Loop Lock
  if( GetLocalInt(OBJECT_SELF,"BUSY") ){
      // WriteTimestampedLogEntry("Spell Loop Lock");
      return ;
  } else {
      SetLocalInt(OBJECT_SELF,"BUSY",TRUE);
      object oSelf=OBJECT_SELF;
      DelayCommand(0.2,DeleteLocalInt(oSelf,"BUSY"));
  }
  //
  struct spell_data stS ;
  stS.oSelf = OBJECT_SELF;
  stS.nSpId = GetSpellId();
  stS.oTgtObj = GetSpellTargetObject();
  stS.lTgtLoc = GetSpellTargetLocation();
  stS.nClass = GetLastSpellCastClass();
  stS.oCItem = GetSpellCastItem();
  stS.nSSDC = GetSpellSaveDC();
  stS.nLevel = GetCasterLevel(OBJECT_SELF);
  stS.nMeta = GetMetaMagicFeat();

  dump_spell( stS, "tn_mod_spells" ) ;

  /* resoud un probleme de DC pour les sorts lances via parchemin pour les voleurs
      et introduit DC pour les parchemins au dessus du niveau du caster
  */

  if( GetIsObjectValid(stS.oCItem) &&
      GetIsPC(OBJECT_SELF) &&
    ( GetBaseItemType(stS.oCItem) == BASE_ITEM_SPELLSCROLL ) &&
    ( GetLastSpellCastClass() == CLASS_TYPE_INVALID ) ){
      int nProfane = GetLevelByClass(CLASS_TYPE_WIZARD)
        + GetLevelByClass(CLASS_TYPE_SORCERER)
        + GetLevelByClass(CLASS_TYPE_BARD)
        + GetLevelByClass(CLASS_TYPE_DRAGONDISCIPLE)
        + GetLevelByClass(CLASS_TYPE_PALEMASTER)
        + GetLevelByClass(CLASS_TYPE_ARCANE_ARCHER)
        + GetLevelByClass(CLASS_TYPE_HARPER)
        + GetLevelByClass(CLASS_TYPE_SHADOWDANCER) ;
      int nDivine = GetLevelByClass(CLASS_TYPE_CLERIC)
        + GetLevelByClass(CLASS_TYPE_DRUID)
        + GetLevelByClass(CLASS_TYPE_SHIFTER)
        + GetLevelByClass(CLASS_TYPE_PALADIN)
        + GetLevelByClass(CLASS_TYPE_HARPER)
        + GetLevelByClass(CLASS_TYPE_RANGER) ;
      int nTypeMagie = (nDivine > nProfane) ? nDivine : nProfane ;
      int nSkillUMD = d20() + GetSkillRank(SKILL_USE_MAGIC_DEVICE) + nTypeMagie ;
      int nDC_UMD = stS.nSSDC-10 + GetCasterLevel(OBJECT_SELF) ;
      if( stS.nSpId == SPELL_RAISE_DEAD ){ nDC_UMD = 2 ; }
      if( nDC_UMD > nSkillUMD ){
        SendMessageToPC(OBJECT_SELF,"Utilisation des Objets Magiques : Jet "
            +IntToString(nSkillUMD)+", DC = "+IntToString(nDC_UMD)+" * échec *");
        SetModuleOverrideSpellScriptFinished();
        return ;
      } else {
        SendMessageToPC(OBJECT_SELF,"Utilisation des Objets Magiques : Jet "
            +IntToString(nSkillUMD)+", DC = "+IntToString(nDC_UMD)+" * réussite *");
      }
  }
  if( GetIsObjectValid(stS.oCItem) ){
      string sItemTag = GetTag(stS.oCItem) ;
      if( sItemTag=="NW_IT_MEDKIT001" || sItemTag=="NW_IT_MEDKIT002" ||
          sItemTag=="NW_IT_MEDKIT003" || sItemTag=="NW_IT_MEDKIT004" )
      {
        ExecuteScript("tn_ctrl_medkit",stS.oSelf);
        return;
      }
  }
/* classic spell-hooking */

  switch (stS.nSpId) {
      case SPELL_FIREBRAND: ly_s0_firebrand(stS) ; break ;
      case SPELL_DIVINE_POWER: ly_s0_divpower(stS) ; break ;
      case SPELL_ISAACS_LESSER_MISSILE_STORM: ly_s0_missstorm1(stS) ; break ;
      case SPELL_ISAACS_GREATER_MISSILE_STORM: ly_s0_missstorm2(stS) ; break ;
      case SPELL_VIRTUE: ly_s0_virtue(stS) ; break ;
      case SPELL_DIVINE_FAVOR: ly_s0_divfav(stS) ; break ;
      case SPELL_HARM: ly_s0_harm(stS) ; break ;
//      case SPELL_ELEMENTAL_SUMMONING_ITEM: ly_s3_summonelem(stS) ; break ;
// it is an activate item
      case SPELL_SUMMON_CREATURE_I:
      case SPELL_SUMMON_CREATURE_II:
      case SPELL_SUMMON_CREATURE_III:
      case SPELL_SUMMON_CREATURE_IV:
      case SPELL_SUMMON_CREATURE_V:
      case SPELL_SUMMON_CREATURE_VI:
      case SPELL_SUMMON_CREATURE_VII:
      case SPELL_SUMMON_CREATURE_VIII:
      case SPELL_SUMMON_CREATURE_IX: ly_s0_summon(stS) ; break ;
      // begin 2005-09-27
      case SPELL_LESSER_RESTORATION: ly_s0_lsrestor(stS) ; break ;
      case SPELL_RESTORATION: ly_s0_restore(stS) ; break ;
      case SPELL_GREATER_RESTORATION: ly_s0_grrestore(stS) ; break ;
      case SPELL_NEUTRALIZE_POISON: ly_s0_remeffect(stS) ; break ;
      case SPELLABILITY_REMOVE_DISEASE:
      case SPELL_REMOVE_DISEASE: ly_s0_remeffect(stS) ; break ;
      case SPELL_PHANTASMAL_KILLER: ly_s0_phankill(stS) ; break ;
      // end 2005-09-27
      // begin 2005-10-04
      case SPELL_TIME_STOP: if( !GetIsDM(stS.oSelf) ) ly_s0_timestop(stS) ; break ;
      case SPELL_KNOCK: ly_s0_knock(stS) ; break ;
      case SPELL_FIND_TRAPS: ly_s0_findtrap(stS) ; break ;
      case SPELL_LIGHT: ly_s0_light(stS) ; break ;
      case SPELLABILITY_AS_DARKNESS:
      case SPELL_SHADOW_CONJURATION_DARKNESS:
      case 688: // Classe de prestige
      case SPELL_DARKNESS: ly_s0_darkness(stS) ; break ;
      case SPELL_PROTECTION_FROM_GOOD: ly_s0_prgood(stS) ; break ;
      case SPELL_PROTECTION_FROM_EVIL: ly_s0_previl(stS) ; break ;
      case SPELL_CLARITY: ly_s0_clarity(stS) ; break ;
      case SPELL_REMOVE_PARALYSIS: ly_s0_rmvparal(stS) ; break ;
      case SPELL_CURE_CRITICAL_WOUNDS: ly_s0_curcrwn(stS) ; break ;
      case SPELL_CURE_SERIOUS_WOUNDS: ly_s0_curserw(stS) ; break ;
      // end 2005-10-04
      // begin 2005-10-05
      case SPELL_TRUE_SEEING: ly_s0_truesee(stS) ; break ;
      case SPELL_AMPLIFY: ly_s0_amplify(stS) ; break ;
      case SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE: ly_s0_clairadvo(stS) ; break ;
      case SPELL_FLAME_STRIKE: ly_s0_flmstrike(stS) ; break ;
      case SPELL_HAMMER_OF_THE_GODS: ly_s0_hammgods(stS) ; break ;
      case SPELL_HEALING_CIRCLE: ly_s0_healcirc(stS) ; break ;
      case SPELL_SHADOW_SHIELD: ly_s0_shadshld(stS) ; break ;
      case SPELL_WEIRD: ly_s0_weird(stS) ; break ;
      // end 2005-10-05
      // begin 2005-11-23
      case SPELL_MAGE_ARMOR: ly_s0_magearm(stS) ; break ;
      // end 2005-11-23
      // begin 2005-12-22
      case SPELL_COLOR_SPRAY: ly_s0_colspray(stS) ; break ;
//      case SPELL_HEALINGKIT: ly_s0_healingkit(stS) ; break ;
      case SPELL_EXPEDITIOUS_RETREAT: ly_s0_exretreat(stS) ; break ;
      // end 2005-12-23
      case SPELL_GHOSTLY_VISAGE: ly_s0_ghostvis(stS) ; break ;
      case SPELL_HORRID_WILTING: ly_s0_horrwilt(stS) ; break ;
      case SPELL_PREMONITION: ly_s0_premo(stS) ; break ;
      case SPELL_STONESKIN: ly_s0_stoneskn(stS) ; break ;
      // end 2005-12-25
      case SPELL_SHIELD: ly_s0_shield(stS) ; break ;
      // end 2005-12-29
      case SPELL_ANIMATE_DEAD: ly_s0_animdead(stS) ; break ;
      case SPELL_ELEMENTAL_SHIELD: ly_s0_fireshld(stS) ; break ;
      case SPELL_ETHEREALNESS: ly_s0_ether(stS) ; break ;
      case SPELLABILITY_BG_BULLS_STRENGTH:
      case SPELL_BULLS_STRENGTH: ly_s0_bullstr(stS) ; break ;
      case SPELL_CALL_LIGHTNING: ly_s0_calllghtn(stS) ; break ;
      // end 2005-12-30
      case VFX_DUR_BIGBYS_GRASPING_HAND: ly_s0_bigby3(stS) ; break ;
      case VFX_DUR_BIGBYS_CRUSHING_HAND: ly_s0_bigby5(stS) ; break ;
      case SPELL_TENSERS_TRANSFORMATION: ly_s0_tenstrans(stS) ; break ;
      case SPELL_GATE: ly_s0_gate(stS) ; break ;
      case SPELL_EAGLE_SPLEDOR: ly_s0_eaglespl(stS) ; break ;
      case SPELL_CATS_GRACE: ly_s0_catgrace(stS) ; break ;
      case SPELL_CIRCLE_OF_DEATH: ly_s0_circdeath(stS) ; break ;
      // end 2005-12-31
      case SPELL_CREATE_UNDEAD: ly_s0_crundead(stS) ; break ;
      case SPELL_CREATE_GREATER_UNDEAD: ly_s0_crgrund(stS) ; break ;
      case SPELL_GREATER_STONESKIN: ly_s0_grstonesk(stS) ; break ;
      case SPELL_RAISE_DEAD: ly_s0_raisedead(stS) ; break ;
      case SPELL_RESURRECTION: ly_s0_resserec(stS) ; break ;
      // end 2006-01-01
  } // end switch statement
}
Le code a colorer syntaxiquement est trop long (plus de 10240 caractères) et risque de ne pas s'afficher du tout. Vous pouvez le voir en version colorée ici.


Voilà, j'espère que cela pourra servir de modèle à ceux qui hésitent à se lancer.
C'est déjà un peu optimisé mais on peut mieux faire, surtout du coté du codage des sorts modifiés.
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
lylver
Héros
Inscrit le: 08 Avr 2005
Messages: 274
Répondre en citant
Posté le : 03/04/2006 12:31:20 Sujet du message : GC etc mise à jour

Je reposte une version améliorée de mon nettoyeur.
Il s'occupe du :
- nettoyage des monstres (délai environ 3 minutes)
- rammassage des objets
- effacement des boutiques dynamiques (scripts joints)
En attendant de refaire une version fonctionnant différement (boucle onexit)
J'ai inclus depuis des commandes pour l'arrêter, le redémarrer, un contrôle de fonctionnement et surtout la gestion des "static spawns"

Bibliothèque de fonctions
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:: ////
//:: Update Lylver 2006-03-30
//:: nouveau systeme de nettoyage des boutiques
//:: //
//:: Update Lylver 2006-02-05
//:: nouvelle fonction qui remplace NoPlayerInArea
//:: =&gt; NbPlayerorDMInArea
//:: //
//:: Update Lylver 2006-01-14
//:: ajout et test d'une variable sur les items poses
//:: a meme la map : GCFALSE
//:: //
//:: Update Lylver 2006-01-14
//:: ajout et test d'une variable sur les creatures crees
//:: en dehors du systeme de Rencontres NWN : GCKILL
//:: //
//:: Update Lylver 2005-10-02
//:: gestion multi-boutiques et prise en charge par le GC
//:: mettre un entier "TN_IDX_SHOP" de 0 a 9 (via le dialogue)
//:: sur le personnage gerant la boutique
//:: pour selectionner la boutique a ouvrir
//:: renseigner le personnage avec les tags des boutiques
//:: sous le forme de variables chaines
//:: TN_DYN_SHOPx (x de 0 a 9)
//:: il faut egalement mettre un script sur On Open Store et On Close Store
//:: pour indiquer l'etat d'occupation
//:: //
//:: Lylver 2005-01-12
//:: Include File for Area Cleaning
//:: ly_lib_area.nss

int CheckPJInArea(object oArea) {
  object oObject = GetFirstObjectInArea(oArea) ;
  int nCount = 0 ;
  while (GetIsObjectValid(oObject)) {
      if (GetIsPC(oObject)) {
      nCount++ ;
      break ;
      }
      oObject = GetNextObjectInArea(oArea) ;
  }
  return nCount ;
}

int CheckPJetDMInArea(object oArea) {
  object oObject = GetFirstObjectInArea(oArea) ;
  int nCount = 0 ;
  while (GetIsObjectValid(oObject)) {
      if (GetIsPC(oObject) || GetIsDM(oObject) || GetIsDMPossessed(oObject)) {
      nCount++ ;
      break ;
      }
      oObject = GetNextObjectInArea(oArea) ;
  }
  return nCount ;
}

int NbPlayerorDMInArea(object oArea) {
  object oPC = GetFirstPC() ;
  int nCount = 0 ;
  while( GetIsObjectValid(oPC) ){
      if( GetArea(oPC) == oArea ){
      nCount++ ;
      break ;
      }
      oPC = GetNextPC() ;
  }
  return nCount ;
}

// * returns true if there is no player in the area
// * has to be ran from an object
// source xp2 module modifie
int NoPlayerInArea(object oArea) {
    object oFirst = GetFirstObjectInArea(oArea) ;
//    if( GetIsPC(oFirst) || GetIsDM(oFirst) || GetIsDMPossessed(oFirst) ) return FALSE ;
    if( GetIsPC(oFirst) ) return FALSE ;
    // pour le cas ou le seul objet est un PC
    if( !GetIsObjectValid(oFirst) ){
      SendMessageToAllDMs("Erreur : no valid object for GetFirstObjectInArea") ;
      return TRUE;
    }
    object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oFirst);
    return !GetIsObjectValid(oPC); // * no player in area
}

/*
int CleanStore(object oArea) {
  object oShop ;
  int i, n=0;
  for( i=0 ; i&lt;10 ; i++ ){ // max 10 boutiques (0 a 9)
      oShop = GetLocalObject( oArea, "TN_DYN_SHOP"+IntToS tring(i) ) ;
      if( GetIsObjectValid( oShop ) ){
        if( GetLocalInt( oShop,"BUSY" ) ){
            break ;  // boutique accessible de plusieurs endroits
        } else {
            // SendMessageToAllDMs("Dyna mic Shop "+GetTag(oShop)+" destroyed");
            // WriteTimestampedLogEntry(" ;Dynamic Shop "+GetTag(oShop)+" destroyed");
            DestroyObject(oShop) ;
            n++ ;
        }
      }
  }
  return n;
}
*/


int CleanModStore(object oArea) {
  int n=0;
  string sTag = GetLocalString(oArea,"ATAG");
  if( sTag == "" ) sTag = GetTag(oArea);
  object oStoreAreaWP = GetWaypointByTag("TN_SHOP");
  object oStoreArea = GetArea(oStoreAreaWP);
  object oShop = GetFirstObjectInArea(oStoreArea) ;
  while( GetIsObjectValid(oShop) ){
      if( GetObjectType(oShop) == OBJECT_TYPE_STORE ){
        if( GetLocalString(oShop,"ATAG") == sTag ){
            if( !GetLocalInt(oShop,"BUSY") ){
              // SendMessageToAllDMs("Dyna mic Shop "+GetTag(oShop)+" destroyed");
              // WriteTimestampedLogEntry(" ;Dynamic Shop "+GetTag(oShop)+" destroyed");
              DestroyObject(oShop) ;
              n++ ;
            }
        }
      }
      oShop = GetNextObjectInArea(oStoreArea) ;
  } // while
  return n;
}

int CleanBodyBag(object oArea, int nMax = 50) {
  int nCost = 0 ;
/*  if( CheckPJInArea(oArea) &gt; 0 ){
      SendMessageToAllDMs("Clea nBodyBag : PC is in Area") ;
      return nCost ;
  } // ne pas faire deux fonctions d'exploration de la zone imbriquee
*/
// Gestion par le OnEnter =&gt; cancel GC
  object oItem ;
  object oBag = GetFirstObjectInArea(oArea) ;
//  SendMessageToAllDMs("Clea nBodyBag : " + GetName(oBag) + GetTag(oBag) + GetResRef(oBag)) ;
  while (GetIsObjectValid(oBag)) {
      if( (GetObjectType(oBag) == OBJECT_TYPE_PLACEABLE) && (GetTag(oBag) == "BodyBag") ){
        nCost++ ; // incremente le nombre des objets effectivement traites
        oItem = GetFirstItemInInventory(oBag) ;
        while (oItem != OBJECT_INVALID) {
            nCost++ ;
            // SendMessageToAllDMs("Clea nBodyBagItem : " + GetName(oItem) + GetTag(oItem) + GetResRef(oItem)) ;
            DestroyObject(oItem) ;
            oItem = GetNextItemInInventory(oBag) ;
        } // while
        // DestroyObject(oBag,0.1) ; pas besoin : le moteur le fait, mais ou passent les BodyBags ?
      } // if
      oBag = GetNextObjectInArea(oArea) ;
      // SendMessageToAllDMs("Clea nBodyBag : " + GetName(oBag) + GetTag(oBag) + GetResRef(oBag)) ;
      // SendMessageToAllDMs("Clea nBodyBag : Total Traite" + IntToString(nCost)) ;
      if (nCost > nMax) { nCost = -1 * nCost ; break ;}
  } // while
  return nCost ;
}

int CleanPNJ(object oArea, int nMax = 50) {
  object oPnj = GetFirstObjectInArea(oArea) ;
  int nCost = 0 ;
  while (GetIsObjectValid(oPnj)) {
      if( GetIsEncounterCreature(oPnj) || GetLocalInt(oPnj,"GCKILL") ){
        nCost++ ;
        DestroyObject(oPnj) ;
      } // if
      oPnj = GetNextObjectInArea(oArea) ;
      // SendMessageToAllDMs("Clea nPNJ : Total Traite" + IntToString(nCost)) ;
      if (nCost > nMax) { nCost = -1 * nCost ; break ;}
  } // while
  return nCost ;
}

int CleanItem(object oArea, int nMax = 50) {
  object oItem = GetFirstObjectInArea(oArea) ;
  object oLostItem = GetObjectByTag("CHEST_LOST_ITEM") ;
  int nCost = 0 ;
  while (GetIsObjectValid(oItem)) {
      if( GetObjectType(oItem) == OBJECT_TYPE_ITEM ){
        if( !GetLocalInt(oItem,"GCFALSE") ){
            nCost++ ;
            CopyItem(oItem,oLostItem) ;
            DestroyObject(oItem) ;
        }
      } // if
      oItem = GetNextObjectInArea(oArea) ;
      // SendMessageToAllDMs("Clea nItem : Total Traite" + IntToString(nCost)) ;
      if (nCost > nMax) { nCost = -1 * nCost ; break ;}
  } // while
  return nCost ;
}

// void main() {}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Main GC
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:: ////
//:: Update Lylver 2006-03-30
//:: nouveau systeme de nettoyage des boutiques
//:Confused///
//:: Update Lylver 2006-03-26
//:: Controle presence d'un seul GC et auto-restart
//:Confused///
//:: Update Lylver 2006-02-05
//:: nouvelle fonction qui remplace NoPlayerInArea
//:: =&gt; NbPlayerorDMInArea
//:Confused///
//:: Update Lylver 2005-10-02
//:: gestion multi-boutiques et prise en charge par le GC
//:Confused///
//:: Lylver 2005-04-28
//:: nouvelle fonction de test PJ dans zone
//:: GC main non affecte
//:Confused///////////////////////// //////////
//:: Lylver 2005-03-08
//:: Copie des items perdus (abandonne)
//:: dans le coffre des objets trouves
//:Confused///////////////////////// //////////
//:: Lylver 2005-01-12
//:: Module Garbage Collector
//:: ly_mod_area_gc.nss

#include "ly_lib_area"

void main() {
  object oMod = GetModule() ;
  int nBodyBag=0,nPNJ=0,nItemLost=0,bEmptyArea,nStore=0 ;
  int CleanP = GetLocalInt(oMod,"CLEANP") ;
  int nGCGO = GetLocalInt(oMod,"GCGO");
  if( !nGCGO ){
      string sMesg = "GC Stopped (ly_mod_area_gc)";
      WriteTimestampedLogEntry(sMesg);
      // SendMessageToAllDMs(sMesg);
      return ;
  }
  if( nGCGO > 1 ){
      string sMesg = "Secondary GC Looping found or GC Dead : killed myself and launch the check.";
      WriteTimestampedLogEntry(sMesg);
      // SendMessageToAllDMs(sMesg);
      // 2006-03-26 : Check GC
      SignalEvent(oMod, EventUserDefined(301));
      return; // deux GC : erreur
  }
  SetLocalInt(oMod,"GCGO",nGCGO+2); // Loop Lock
  string sArea = "" ;
  object oArea = GetLocalObject(oMod,"CLEANQ") ;
  // SendMessageToAllDMs("GC : Hello ! I'm Here !") ;
  // WriteTimestampedLogEntry(" ;GC : Hello ! I'm Here !") ;
  if (oArea != OBJECT_INVALID) { // j'ai une zone a traiter
      sArea = GetTag(oArea) ; // un run de nettoyage courant
      /* code */
      // SendMessageToAllDMs("GC : operating on Area : " + GetTag(oArea) + " " + GetName(oArea)) ;
      WriteTimestampedLogEntry("GC : operating on Area : " + GetTag(oArea) + " " + GetName(oArea)) ;
      bEmptyArea = ( NbPlayerorDMInArea(oArea) == 0 ) ;
      if( GetLocalInt(oArea,"PC_HERE") == 1 ){
        string sMesg = "Warning GC : PC_HERE est a etat 1";
        SendMessageToAllDMs(sMesg);
        WriteTimestampedLogEntry(sMesg);
      }
        // default cleaning : 50 items in one pass, return negative for 2nd check later
        // CleanBodyBag(object oArea, int nMax = 50)
      if( bEmptyArea ){ // si la zone est effectivement vide on nettoie
        WriteTimestampedLogEntry("GC : BodyBag");
        nBodyBag = CleanBodyBag(oArea) ;
        WriteTimestampedLogEntry("BodyBag cleaned : "+IntToString(nBodyBag)+"\nGC : PNJ");
        nPNJ = CleanPNJ(oArea) ;
        WriteTimestampedLogEntry("PNJ cleaned : "+IntToString(nPNJ)+"\nGC : ItemLost");
        nItemLost = CleanItem(oArea) ;
        WriteTimestampedLogEntry("ItemLost moved : "+IntToString(nItemLost)+"\nGC : Store");
        nStore = CleanModStore(oArea) ; // nouveau clean des boutiques
        WriteTimestampedLogEntry("Store cleaned : "+IntToString(nStore));
      } else { // mais si quelqu'un est la, on abandonne et on purge la queue
        DeleteLocalInt(oMod,"CLEANQ" + sArea) ;
        DeleteLocalObject(oMod,"CLEANQ") ;
        if( GetLocalInt(oMod,"GCGO") != 0 ){
            SetLocalInt(oMod,"GCGO",nGCGO); // Unlock Loop
            // string sMesg = "GC : Restore nGCGO : "+IntToString(nGCGO);
            // SendMessageToAllDMs(sMesg);
            // WriteTimestampedLogEntry(sMesg );
        }
        DelayCommand(6.0,SignalEvent(oMod, EventUserDefined(300))) ; // pas trop vite
        return ; // exit et recommence
      }
      // test si c'est fini (pas de code retour negatif
      if( (nBodyBag >= 0) && (nPNJ >= 0) && (nItemLost >=0) ){ // oui on prend la requete suivante
        DeleteLocalInt(oMod,"CLEANQ" + sArea) ;
        DeleteLocalObject(oMod,"CLEANQ") ;
        if( GetLocalInt(oMod,"GCGO") != 0 ){
            SetLocalInt(oMod,"GCGO",nGCGO); // Unlock Loop
            // string sMesg = "GC : Restore nGCGO : "+IntToString(nGCGO);
            // SendMessageToAllDMs(sMesg);
            // WriteTimestampedLogEntry(sMesg );
        }
        DelayCommand(6.0,SignalEvent(oMod, EventUserDefined(300))) ; // qu'on examine
        return ; // exit et recommence
      } else { // on termine rapidement
        SetLocalInt(oMod,"CLEANQ" + sArea, 29 + GetLocalInt(oMod,"CLEANQ" + sArea)) ; // passage + rapide
      }
  } else { // pas de zone en cours, alors on examine les requetes
      // SendMessageToAllDMs("GC : Looking for job to do");
      oArea = GetLocalObject(oMod,"CLEANR") ;
      if (oArea != OBJECT_INVALID) { // trouve qq chose a faire
        // SendMessageToAllDMs("GC : switching to Area : " + GetTag(oArea) + " " + GetName(oArea)) ;
        sArea = GetTag(oArea) ; // gere la file d'attente
        SetLocalObject(oMod,"CLEANQ",oArea) ; // passe en clean courant
        SetLocalInt(oMod,"CLEANQ" + sArea, CleanP) ; // delai suivant
        // dependant de la plus longue des autres attentes en cours
        DeleteLocalInt(oMod,"CLEANR" + sArea) ;// libere le semaphore
        DeleteLocalObject(oMod,"CLEANR") ;
      } else { // meme si pas prise, il peut y avoir une demande de plus faible priorite
      // en boucle, on en tient compte en retestant plus vite apres reset priorite
        sArea = "" ;
        if( CleanP >= 0 ){
            SetLocalInt(oMod,"CLEANQ", CleanP) ; // delai suivant
            DeleteLocalInt(oMod,"CLEANP") ; // reset priorite globale
            // string sMesg = "GC : Priority : "+IntToString(CleanP);
            // SendMessageToAllDMs(sMesg);
            // WriteTimestampedLogEntry(sMesg );
        }
        // SendMessageToAllDMs("GC : Nothing to Do") ;
      }
  }
  // on ne nettoie pas immediatement mais en fonction de la priorite de la requete
  // pour conserver une latence avant destruction des monstres 174s mini + 6s du a la purge
  int nCount = 1 + GetLocalInt(oMod,"CLEANQ" + sArea);
  float fDelay = 180.0 - 6.0 * IntToFloat(nCount) ; // 180 secondes maxi
  if( fDelay < 6.1 ) fDelay = 6.1 ; // pas trop vite pour la sortie de boucle des OnExit
  if( GetLocalInt(oMod,"GCGO") != 0 ){
      SetLocalInt(oMod,"GCGO",nGCGO); // Unlock Loop
      // string sMesg = "GC : Restore nGCGO : "+IntToString(nGCGO);
      // SendMessageToAllDMs(sMesg);
      // WriteTimestampedLogEntry(sMesg );
  }
  // SendMessageToAllDMs("GC : Wait "+ IntToString(FloatToInt(fDelay) )+ " seconds &amp; Loop") ;
  DelayCommand(fDelay, SignalEvent(oMod, EventUserDefined(300)));
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Scripts de zone : On Enter
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:Confused/
//:: Updated 2006-03-16 Lylver, ajout NWN-FF
//:Confused/
//:: Update Lylver 2006-02-05
//:: nouvelle fonction qui remplace NoPlayerInArea
//:: =&gt; NbPlayerorDMInArea
//:: Lylver 2005-10-15
//:: Spell-hooking pour les PNJ
//:: Lylver 2005-09-13
//:: pour TN Bouchon II
//:: Lylver 2005-04-28
//:: nouvelle fonction de test PJ dans zone
//:: Lylver 2005-01-12
//:: Signal to Garbage Collector that PC are here
//:: Put OnEnter of Area
//:: Lylver 2005-02-07
//:: ly_onenter_area.nss

#include "ly_lib_area"
#include "x0_i0_walkway"

void main() {
  object oMod = GetModule() ;
  // ajout NWN-FF 16 Mars 2006
  int FFDB = GetLocalInt(oMod,"FFDB");
  if( FFDB ) ExecuteScript("ff_onenterarea", OBJECT_SELF);
  //
  object oPC = GetEnteringObject() ;
  object oArea = OBJECT_SELF ;
  string sArea = GetTag(oArea) ;
  // StaticSpawn
  if( !GetLocalInt(oArea,"PC_HERE") ) ExecuteScript("ly_static_spawn",oPC);
  SetLocalInt(oArea,"X2_L_WILD_MAGIC",1); // everybody wild magic =&gt; spell-hooking
  int bInteractive = GetIsPC(oPC) || GetIsDM(oPC) || GetIsDMPossessed(oPC) ;
  if( bInteractive ){
      WriteTimestampedLogEntry("Zone "+sArea+" OnEnter : "+GetName(oPC)) ;
      if( GetLocalInt(oArea,"NIVEAU_ZONE") == 0 ) WriteTimestampedLogEntry("Niveau_Zone 0 : a corriger") ;
  } else { // traitement des PNJs qui sortent de leur zone a la poursuite des PJs ou
  // par ceux qui patrouillent hors de vue des joueurs : duree de vie 180 secondes
      int nDestroy = GetLocalInt(oPC,"DESTROY") ;
      if( nDestroy != 0 ){
        if( NbPlayerorDMInArea(oArea) == 0 ){
            DestroyObject(oPC,IntToFloat(nDestroy)) ;
            WriteTimestampedLogEntry("Zone "+sArea+" OnEnter, no PJs : "+GetName(oPC)+" will be destroyed") ;
        }
      }
      return ;
  }
/*  if( GetIsDM(oPC) ){
      SendMessageToPC(oPC,"Nive au_Zone : "+IntToString(GetLocalInt (OBJECT_SELF,"NIVEAU_ZONE "))) ;
  }  */

  if( bInteractive ){
      if( GetLocalObject(oMod,"CLEANQ") == oArea ){ // check GC is in Area
        // SendMessageToAllDMs("OnEn ter : GC operating : Ordering Stop : " + sArea) ;
        // SendMessageToPC(GetEnteringObj ect(), "OnEnter : GC operating : Ordering Stop : " + sArea) ;
        DeleteLocalObject(oMod,"CLEANQ") ; // stop GC on Area
        DeleteLocalInt(oMod,"CLEANQ" + sArea) ; // counter also
      }
      if( GetLocalObject(oMod,"CLEANR") == oArea ){ // check GC called for Area
        // SendMessageToAllDMs("OnEn ter : GC called : cancelling " + sArea) ;
        // SendMessageToPC(GetEnteringObj ect(), "OnEnter : GC called : cancelling " + sArea) ;
        DeleteLocalObject(oMod,"CLEANR") ; // cancel GC call for Area
        SetLocalInt(oMod,"CLEANR" + sArea,-1) ; // demande d'arret
        // Note : -1 to reset zone counter done by ly_onexit_area, stoping hook-loop also
      }
      // variable de statut pour usage futur
      if( GetLocalInt(OBJECT_SELF,"PC_HERE") == 0){
        SetLocalInt(OBJECT_SELF,"PC_HERE",1) ;
        object oPnj = GetFirstObjectInArea(oArea) ;
        while( GetIsObjectValid(oPnj) ){
            if( GetLocalInt(oPnj,"WALK") ){
              AssignCommand(oPnj,WalkWayPoints()) ;
            }
            oPnj = GetNextObjectInArea(oArea) ;
        }
      }
  }
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Scripts de zone : On Exit
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:: ////
//:: Update Lylver 2006-02-05
//:: nouvelle fonction qui remplace NoPlayerInArea
//:: =&gt; NbPlayerorDMInArea
//:: Lylver 2005-09-13
//:: pour TN Bouchon II
//:: Lylver 2005-04-28
//:: nouvelle fonction de test PJ dans zone
//:: Lylver 2005-01-15
//:: OnExit Area
//:: GC et gestion des groupes de PJs
//:: Lylver 2005-02-07
//:: ly_onexit_area.nss

#include "ly_lib_area"
void main() {
  object oPC = GetExitingObject() ;
  string sArea = GetTag(OBJECT_SELF) ;
  int bInteractive = GetIsPC(oPC) || GetIsDM(oPC) || GetIsDMPossessed(oPC) ;
  if( bInteractive ){ ExecuteScript("ly_onexit_loop",OBJECT_SELF); } // sous-fonction pour le GC
  else { // traitement des PNJs qui sortent de leur zone a la poursuite des PJs ou
  // par ceux qui patrouillent hors de vue des joueurs : duree de vie 180 secondes
      if( GetIsEncounterCreature(oPC) && !GetIsObjectValid(GetMaster(oPC)) ){
      /* if( NoPlayerInArea(OBJECT_SELF) ){
            SetLocalInt(oPC,"DESTROY& quot;,180) ; // au cas ou la difference serait necessaire
        } else {
            SetLocalInt(oPC,"DESTROY& quot;,180) ;
        }      */

        SetLocalInt(oPC,"DESTROY",180) ;
        WriteTimestampedLogEntry("Zone "+sArea+" OnExit : "+GetName(oPC)+" marked for destroy") ;
      }
      return ;
  }
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Boucle d'attachement
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:Confused///
//:: Update Lylver 2006-02-05
//:: nouvelle fonction qui remplace NoPlayerInArea
//:: =&gt; NbPlayerorDMInArea
//:: Lylver 2005-09-13
//:: pour TN Bouchon II
//:: Lylver 2005-04-28
//:: nouvelle fonction de test PJ dans zone
//:: Lylver 2005-01-15
//:: OnExit Area
//:: Activation du GC : boucle d'attachement
//:: ly_onexit_loop.nss

#include "ly_lib_area"
void main()
{
  object oMod = GetModule() ;
  object oArea = OBJECT_SELF ;
  string sArea = GetTag(oArea) ;
  int nPJ;
  int CleanQ = GetLocalInt(oMod,"CLEANQ" + sArea) ;
  int CleanR = GetLocalInt(oMod,"CLEANR" + sArea) ;
  int CleanP = GetLocalInt(oMod,"CLEANP") ;
  if( CleanQ > 0 ){ // GC should be here
      if( GetLocalObject(oMod,"CLEANQ") == oArea ){ // GC ici : suppression de demande surnumeraire
        DeleteLocalInt(oMod,"CLEANR" + sArea) ; // reset a neutre
        if( GetLocalObject(oMod,"CLEANR") == oArea ){
            DeleteLocalObject(oMod,"CLEANR") ; // free GC [espere operation atomique]
        }
        // WriteTimestampedLogEntry(" ;Warning : GC OnExitLoop : "+sArea+" GC here : cancelling outnumbered request") ;
      } else { // cas d'erreur
        DeleteLocalInt(oMod,"CLEANQ" + sArea) ;
        // WriteTimestampedLogEntry(" ;Warning : GC OnExitLoop : "+sArea+" found area counter without object, resetting.") ;
      }
      return ; // GC is busy on our zone or repaired mismatch
  }
  if( CleanR < 0 ){ // traite l'annulation demandee
      DeleteLocalInt(oMod,"CLEANR" + sArea) ; // reset a neutre
      if( GetLocalObject(oMod,"CLEANR") == oArea ){
        DeleteLocalObject(oMod,"CLEANR") ; // free GC [espere operation atomique]
      }
      // SendMessageToPC(GetExitingObje ct(), "OnExit : GC called but ordered stop : " + sArea) ;
      CleanR = 0 ; // poursuit, test PJ plus loin
  }
  if( CleanR == 0 ){ // etat standard
//      nPJ = CheckPJInArea(OBJECT_SELF) ; fonction NoPlayerInArea 5* plus rapide
      if( NbPlayerorDMInArea(oArea) == 0){ // controle
        // raz variable de statut
        if( GetLocalInt(oArea,"PC_HERE") == 1) DeleteLocalInt(oArea,"PC_HERE") ;
//        if( nPJ &gt; 0 ) WriteTimestampedLogEntry(" ;Erreur : GC OnExitLoop Resultat CheckPJ et NoPlayer different");
      } else {
        // WriteTimestampedLogEntry(" ;Warning : GC OnExitLoop : PJ here, no hooking") ;
        return ; // pas de hooking : il y a du monde
      }
  }
  if( CleanR > 0 ){ // je suis deja passe ou alors un deuxieme PJ vient de sortir
      if( NbPlayerorDMInArea(oArea) == 0 ){ // controle
        // raz variable de statut
        if( GetLocalInt(oArea,"PC_HERE") == 1) DeleteLocalInt(oArea,"PC_HERE") ;
      } else { // stop ! : quelqu'un est la, pas besoin de nettoyer
        DeleteLocalInt(oMod,"CLEANR" + sArea) ; // reset a neutre
        if( GetLocalObject(oMod,"CLEANR") == oArea ){
            DeleteLocalObject(oMod,"CLEANR") ; // free GC [espere operation atomique]
        }
        // WriteTimestampedLogEntry(" ;Warning : GC OnExitLoop Stop Other Hooking") ;
        return ; // stop other running hooking : il y a du monde
      }
  }
  // Warning : overload
  if( CleanR > 300 ) WriteTimestampedLogEntry("Warning : GC OnExitLoop Slow Hooking") ;
  // hooking, ajout de prioritisation
  if( (GetLocalObject(oMod,"CLEANR") == OBJECT_INVALID) && (CleanR >= CleanP) ){ // semaphore vide
      SetLocalObject(oMod,"CLEANR", oArea) ; // signal GC [espere operation atomique]
      // WriteTimestampedLogEntry(" ;Warning : GC OnExitLoop "+sArea+" Hooking") ;
      return ; // yes I'm hooked !
  }
  if( GetLocalObject(oMod,"CLEANR") == oArea ){ // semaphore pris par moi-meme
      // WriteTimestampedLogEntry(" ;Warning : GC OnExitLoop "+sArea+" already hooked") ;
      return ; // yes I've been hooked !
  }
  // semaphore pas libre, increment compteur : accelere GC
  SetLocalInt(oMod,"CLEANR" + sArea,++CleanR) ;
  if( CleanR > CleanP ) SetLocalInt(oMod,"CLEANP",CleanR) ; // monte la priorite a soi-meme
  // pour prendre une option
  // WriteTimestampedLogEntry(" ;Warning : GC OnExitLoop "+sArea+" nb "+IntToString(CleanR)+&qu ot; Hooking failed : recheck in 6 secondes") ;
  // SendMessageToAllDMs("OnEx it : GC called : " + sArea + IntToString(CleanR)) ;
  DelayCommand(6.0,ExecuteScript("ly_onexit_loop", oArea)) ; // recheck in 6 seconds
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Script d'initialisation : au démarrage module
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:: ////
//:: Put OnModuleLoad Event Script
//:: Update Lylver 2005-09-19
//:: Garbage Collector : user event ID 300
//:: Updated Lylver 2006-02-05
//:: Debug for GC
//:: ////

void main()
{
  object oMod = GetModule();

/* Start the Garbage Collector */
  SetLocalInt(oMod,"GCGO",1);
  ExecuteScript("ly_mod_area_gc", oMod); // GC
//

  /* Start the export characters timer and turn counter */
  DelayCommand(600.0, SignalEvent(oMod, EventUserDefined(200)));
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Script Utilisateur : OnModuleUserDef
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:Confused/
//:: Updated 2006-03-25 Lylver
//:: GC autocheck &amp; restart, evt 200 -&gt; 301
//:Confused/
//:: Update Lylver 2005-09-13
//:: Garbage Collector
//:: Put OnModuleUserDef Event Script

void main(){
  object oMod = GetModule() ;
  //
  string sMesg;
  //
  switch (GetUserDefinedEventNumber()) {
      case 200:{ // 10 min timer
        DelayCommand(600.0, SignalEvent(oMod, EventUserDefined(200)));
        // 2006-03-26 : Check GC
        SignalEvent(oMod, EventUserDefined(301));
        //
      }
      case 300:{
        if( GetLocalInt(oMod,"GCGO") ){
            ExecuteScript("ly_mod_area_gc",oMod) ;
        } else {
            sMesg = "GC Stopped (tn_mod_userdef)";
            SendMessageToAllDMs(sMesg);
            WriteTimestampedLogEntry(sMesg);
        }
        break ;
      }
      case 301:{ // GC AutoRestart, verifie par evt 200
        if( GetLocalInt(oMod,"GCLOCK") ){
            sMesg = "GC Locked : no action";
            SendMessageToAllDMs(sMesg);
            WriteTimestampedLogEntry(sMesg);
            return ;
        }
        int CleanP = GetLocalInt(oMod,"CLEANP") ;
        if( GetLocalInt(oMod,"GCGO") && (CleanP < 90) ){
            sMesg = "GC check : OK, Running";
            SendMessageToAllDMs(sMesg);
            WriteTimestampedLogEntry(sMesg);
        } else {
            sMesg = "GC check : Stopped =&gt; Autorestart in 3min";
            SendMessageToAllDMs(sMesg);
            WriteTimestampedLogEntry(sMesg);
            DeleteLocalInt(oMod,"GCGO");
            SetLocalInt(oMod,"GCLOCK",TRUE);
            /* Start the Garbage Collector */
            DelayCommand(180.0, DeleteLocalInt(oMod,"GCLOCK"));
            DelayCommand(181.0, SetLocalInt(oMod,"GCGO",1));
            DelayCommand(182.0, ExecuteScript("ly_mod_area_gc",oMod)) ;
        }
        break ;
      }
  } /* switch */
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Amélioration des ressources utilisées par le module (créatures spawnées)
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:Confused///
//:: Updated Lylver 2006-01-12, test PJ
//:Confused/
//:: Update Lylver 2005-07-17
//:: Debug AI, check see/heard  (x0_inc_generic)
//:Confused///////////////////////// /////////////////////
//:: Default: End of Combat Round
//:: NW_C2_DEFAULT3
//:: Copyright (c) 2001 Bioware Corp.
//:Confused///////////////////////// ////////////////////
/*
    Calls the end of combat script every round
*/

//:Confused///////////////////////// ////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 16, 2001
//:Confused///////////////////////// ////////////////////

#include "NW_I0_GENERIC"
void main()
{
    if( !GetLocalInt(GetArea(OBJECT_SELF),"PC_HERE") ){
      AssignCommand(OBJECT_SELF,ClearAllActions(TRUE));
    }
    if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL))
    {
        DetermineSpecialBehavior();
    }
    else if(!GetSpawnInCondition(NW_FLAG_SET_WARNINGS))
    {
      DetermineCombatRound();
    }
    if(GetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT))
    {
        SignalEvent(OBJECT_SELF, EventUserDefined(1003));
    }
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Bibliothèque pour le "static spawn"
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:Confused///
//:: Updated 2006-04-16, Lylver
//:: pour permettre meme tag mais sur objet non creature
//:: //
//:: Created Lylver 2006-01-29, Lylver
//:: repris de Bouchon 6.67
//:Confused///
/***************************** ******/
/* fonction : SpawnNewCreature    */
/*            par Ynot            */
/* Spawn une creature a un endroit */
/***************************** ******/

void SpawnPNJ(string sTag, string sArea="",int iloc=1,int iAction=1, string sNewTag = "")
{
  string sResRef = GetStringLowerCase(sTag); // TAG en majuscule, ResRef en Minuscule
  if( sNewTag != "" ) sTag = sNewTag ;
  // cas standard : SP_&lt;ResRef&gt;_0&am p;lt;Loc&gt;
  int bNoMulti = (iAction != 0) ; // FALSE &lt;=&gt; autorise
  if( sArea == "" ){
      bNoMulti = TRUE ;
      if( sNewTag == "" ) sArea = sResRef ;
      else sArea = GetStringLowerCase(sNewTag) ;
  }
  // cas special, SP_&lt;Area&gt;_0& lt;Loc&gt;
  string sSpawnPoint = "SP_"+sArea+"_0"+ IntToString(iloc);
  object oSpawnPoint = GetWaypointByTag(sSpawnPoint) ;
  // deja spawne la ?
  if( bNoMulti &&
  (GetObjectType(GetNearestObjectByTag(sTag,oSpawnPoint)) == OBJECT_TYPE_CREATURE) ) return ;
  location lSpawn = GetLocation(oSpawnPoint) ;
  object oPNJ = CreateObject(OBJECT_TYPE_CREATURE, sResRef, lSpawn, FALSE, sNewTag);
  SetLocalInt(oPNJ,"GCKILL",TRUE) ; // nettoyage par GC
  switch( iAction ){
  case 8: ChangeToStandardFaction(oPNJ,STANDARD_FACTION_DEFENDER);break;
  case 7: ChangeToStandardFaction(oPNJ,STANDARD_FACTION_MERCHANT);break;
  case 6: AssignCommand(oPNJ, ActionAttack(GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC )));break;
  case 5: AssignCommand(oPNJ, ActionAttack(GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC,OBJECT_SELF ,1 ,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY )));break;
  case 4: AssignCommand(oPNJ, ActionForceFollowObject(GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC ),2.0) );break;
  case 3: AssignCommand(oPNJ, PlayAnimation (ANIMATION_LOOPING_CONJURE1,1.0,30.0 ));break;
  case 2: AssignCommand(oPNJ, ActionRandomWalk());break;
  case 1: default: break;
  }
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Le "static spawn" (éludé)
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:Confused///
//:: Created 2006-02-19, Lylver
//:: comme sur Armada : static spawn
//:Confused/
#include "ly_lib_pnj"
#include "ly_lib_item"
void main()
{
  object oPC = OBJECT_SELF ;
  object oArea = GetArea(oPC) ;
  string sAtag = GetLocalString(oArea,"ATAG") ;
  int bMesg = FALSE ;
  if( sAtag == "" ){
      sAtag = GetTag(oArea) ;
      if( sAtag != "" ) bMesg = TRUE ;
  }
  if( !GetIsPC(oPC) ) return ;
  string sPCID = GetPCID(oPC) ;
  int bSpawn = GetLocalInt(oArea,sPCID) ;
  int nDelay = GetLocalInt(oArea,"DELAI") ;
  if( nDelay == 0 ) nDelay = 24 ;
  if( !bSpawn ){
      SetLocalInt(oArea,sPCID,TRUE) ;
      DelayCommand(HoursToSeconds(nDelay),DeleteLocalInt(oArea,sPCID));
  }
  switch( StringToInt(sAtag) ){
      // Albion - Esterel : interieur Abbaye
      case 209 :{
        SpawnPNJ("PNJ_ADELME");
        break;
        }
      // CastelMort - Exterieur
      case 507 :{
        SpawnPNJ("PNJ_GUER_CHAOS","0507",1,1,"GUER_CHAOS1");
        SpawnPNJ("PNJ_GUER_CHAOS","0507",2,1,"GUER_CHAOS2");
        SpawnPNJ("PNJ_GUER_CHAOS","0507",3,1,"GUER_CHAOS3");
        SpawnPNJ("PNJ_GUER_CHAOS","0507",4,1,"GUER_CHAOS4");
        SpawnPNJ("PNJ_GUER_CHAOS","0507",5,1,"GUER_CHAOS5");
        SpawnPNJ("PNJ_GUER_CHAOS","0507",6,1,"GUER_CHAOS6");
        SpawnPNJ("GUERRIERCM","0507",7,1,"GUERRIERCM7");
        SpawnPNJ("GUERRIERCM","0507",8,1,"GUERRIERCM8");
        SpawnPNJ("GUERRIERCM","0507",9,1,"GUERRIERCM9");
        SpawnPNJ("GUERRIERCM","0507",10,1,"GUERRIERCM10");
        SpawnPNJ("GARDECM","0507",11,1,"GARDECM11");
        SpawnPNJ("GARDECM","0507",12,1,"GARDECM12");
        break;
      }
      // CastelMort - le bourg
      case 509 :{
        SpawnPNJ("GUERRIERCM","0509",1,1,"GUERRIERCM1");
        SpawnPNJ("GUERRIERCM","0509",2,1,"GUERRIERCM2");
        SpawnPNJ("GUERRIERCM","0509",3,1,"GUERRIERCM3");
        SpawnPNJ("GUERRIERCM","0509",4,1,"GUERRIERCM4");
        SpawnPNJ("GUERRIERCM","0509",5,1,"GUERRIERCM5");
        SpawnPNJ("GUERRIERCM","0509",6,1,"GUERRIERCM6");
        SpawnPNJ("GUERRIERCM","0509",7,1,"GUERRIERCM7");
        SpawnPNJ("GUERRIERCM","0509",8,1,"GUERRIERCM8");
        SpawnPNJ("GUERRIERCM","0509",9,1,"GUERRIERCM9");
        SpawnPNJ("GUERRIERCM","0509",10,1,"GUERRIERCM10");
        break;
      }
      // Castelmort - Son Palais
      case 519 :{
        SpawnPNJ("PNJ_ARGON");
        SpawnPNJ("PNJ_CALINE");
        SpawnPNJ("PNJ_BOUFFON_CM");
        SpawnPNJ("PNJ_CLARA");
        break;
      }
      // Le Bosquet Sacre
      case 916 :{
        SpawnPNJ("PNJ_BLODEUWEDD");
        break;
      }
      // Foret : le magasin magique
      case 918 :{
        SpawnPNJ("PNJ_LAXINE");
        SpawnPNJ("SOW_GARDEANIM","0918",1,7,"GLAXINE");
        break;
      }
      // Karak Varn - La Forge d'Asmundr
      case 1506 :{
        SpawnPNJ("SOW_PNJ_NEGAN");
        SpawnPNJ("PNJ_GENAR");
        SpawnPNJ("PNJ_ADELLA");
        SpawnPNJ("PNJ_HASHAN");
        break;
      }
      // Labyrinthe - 3
      case 1903 :{
        SpawnPNJ("TN_GOLEM_DEAMB","",1,1,"DEAMB03");
        if( !bSpawn ){
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1903",1,1,"GOLEMFLESH31");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1903",2,1,"GOLEMFLESH32");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1903",3,1,"GOLEMFLESH33");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1903",4,1,"GOLEMFLESH34");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1903",5,1,"GOLEMFLESH35");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1903",6,1,"GOLEMFLESH36");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1903",7,1,"GOLEMFLESH37");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1903",8,1,"GOLEMFLESH38");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1903",9,1,"GOLEMFLESH39");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_OS","1903",10,1,"GOLEM_OS310");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_OS","1903",11,1,"GOLEM_OS311");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_OS","1903",12,1,"GOLEM_OS312");
        }
        break;
      }
      // Labyrinthe - 4
      case 1904 :{
        SpawnPNJ("TN_GOLEM_DEAMB","",1,1,"DEAMB04");
        if( !bSpawn ){
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1904",1,1,"GOLEMFLESH41");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1904",2,1,"GOLEMFLESH42");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1904",3,1,"GOLEMFLESH43");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1904",4,1,"GOLEMFLESH44");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1904",5,1,"GOLEMFLESH45");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1904",6,1,"GOLEMFLESH46");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1904",9,1,"GOLEMFLESH49");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_CHAIR","1904",11,1,"GOLEMFLESH411");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_OS","1904",7,1,"GOLEM_OS47");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_OS","1904",8,1,"GOLEM_OS48");
            if( d3() != 1 ) SpawnPNJ("TN_GOLEM_OS","1904",10,1,"GOLEM_OS410");
        }
        break;
      }
      // Labyrinthe - 7
      case 1907 :{
        if( !bSpawn ){
            SpawnPNJ("SOW_MINOS_TYRAN","1907",1,1,"TYRAN1");
            SpawnPNJ("SOW_MINOS_TYRAN","1907",2,1,"TYRAN2");
        }
        break;
      }
      // Les Plaines arrides (camp bedouin)
      case 2601 :{
        SpawnPNJ("PNJ_GARD_ASOTEPH","2601",1,1,"GARDE_ASOTEPH1");
        SpawnPNJ("PNJ_GARD_ASOTEPH","2601",2,1,"GARDE_ASOTEPH2");
        SpawnPNJ("PNJ_F_BEDOUIN","2601",3,1,"F_BEDOUIN3");
        SpawnPNJ("PNJ_F_BEDOUIN","2601",4,1,"F_BEDOUIN4");
        SpawnPNJ("PNJ_F_BEDOUIN","2601",5,1,"F_BEDOUIN5");
        SpawnPNJ("PNJ_F_BEDOUIN","2601",6,1,"F_BEDOUIN6");
        SpawnPNJ("PNJ_H_BEDOUIN","2601",7,1,"H_BEDOUIN7");
        SpawnPNJ("PNJ_H_BEDOUIN","2601",8,1,"H_BEDOUIN8");
        SpawnPNJ("PNJ_H_BEDOUIN","2601",9,1,"H_BEDOUIN9");
        SpawnPNJ("PNJ_H_BEDOUIN","2601",10,1,"H_BEDOUIN10");
        SpawnPNJ("PNJ_H_BEDOUIN","2601",11,1,"H_BEDOUIN11");
        SpawnPNJ("PNJ_H_BEDOUIN","2601",12,1,"H_BEDOUIN12");
        break;
      }
      // Lhasa
      case 2614 :{
        SpawnPNJ("PNJ_CAPT_LHASA");
        SpawnPNJ("PNJ_CARD");
        SpawnPNJ("PNJ_GARDE_LHASA","2614",1,1,"GLHASA1");
        SpawnPNJ("PNJ_GARDE_LHASA","2614",2,1,"GLHASA2");
        SpawnPNJ("PNJ_GARDE_LHASA","2614",3,1,"GLHASA3");
        SpawnPNJ("PNJ_GARDE_LHASA","2614",4,1,"GLHASA4");
        SpawnPNJ("PNJ_GARDE_LHASA","2614",5,1,"GLHASA5");
        SpawnPNJ("PNJ_GARDE_LHASA","2614",6,1,"GLHASA6");
        SpawnPNJ("PNJ_GARDE_LHASA","2614",7,1,"GLHASA7");
        SpawnPNJ("PNJ_GARDE_LHASA","2614",8,1,"GLHASA8");
        break;
      }
      // Lhasa - Chez Micheline
      case 2615 :{
        SpawnPNJ("PNJ_MICHELINE");
        break;
      }
     
      case 2901 :{
        SpawnPNJ("PNJ_JACHO_ILE");
        break;
      }
      // Lyon - la ville
      case 3001 :{
        SpawnPNJ("PNJ_GARDEDELYON","3001",1,1,"PNJ_GARDEDELYON1");
        SpawnPNJ("PNJ_GARDEDELYON","3001",2,1,"PNJ_GARDEDELYON2");
        SpawnPNJ("PNJ_GARDEDELYON","3001",3,1,"PNJ_GARDEDELYON3");
        SpawnPNJ("PNJ_GARDEDELYON","3001",4,1,"PNJ_GARDEDELYON4");
        SpawnPNJ("PNJ_GARDEDELYON","3001",5,1,"PNJ_GARDEDELYON5");
        SpawnPNJ("BBS_SCRIBE_BP");
        SpawnPNJ("PNJ_ROBERT");
        SpawnPNJ("PNJ_BARAK");
        break;
      }
      case 0: default: bMesg = FALSE ;break;
  }
  if( bMesg ){
        string sMesg = "Zone : "+GetName(oArea)+"ATAG non positionne" ;
        WriteTimestampedLogEntry(sMesg);
        SendMessageToAllDMs(sMesg);
  }
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Les boutiques dynamiques
1) positionner le n° de la boutique
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:Confused///////////////////////// /////////////////////
//:: FileName shop_set_idx_01
//:: Created Lylver 2005-11-13
//:Confused///////////////////////// ////////////////////
void main()
{
  SetLocalInt(OBJECT_SELF,"TN_IDX_SHOP",1) ; // marqueur boutique dyn.
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Le script de gestion à mettre dans les dialogues pour ouvrir la boutique
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:: ////
//:: Update Lylver 2006-03-30
//:: nouveau systeme de nettoyage,
//:: utilisation de GetNearest et GetWaypoint (moins consommateur)
//:: ////
//:: Update Lylver 2005-10-02
//:: gestion multi-boutiques et prise en charge par le GC
//:: mettre un entier "TN_IDX_SHOP" de 0 a 9 (via le dialogue)
//:: sur le personnage gerant la boutique
//:: pour selectionner la boutique a ouvrir
//:: renseigner le personnage avec les tags des boutiques
//:: sous le forme de variables chaines
//:: TN_DYN_SHOPx (x de 0 a 9)
//:: il faut egalement mettre un script sur On Open Store et On Close Store
//:: pour indiquer l'etat d'occupation
//:Confused///
//:: update Lylver 2005-09-25
//:: adaptation TN Bouchon
//:: Les Boutiques sont exclusivement dans la palette grace a cela, plus d'incoherence
//:: ni de double gestion.
//:Confused/ convention de noms :
//:: 1) variable sur le PNJ : string TN_DYN_SHOP = TAG en majuscule
//:: 2) le resref de la boutique est forcement en minuscule, maximum 15 caracteres svp
//:: 15 caracteres, pas 16 Sad
//:: la boutique est cree sur demande dans la zone 0001 module_dynamic_shop
//:: certaines boutiques pourront beneficier d'un "shop_remove", a voir.
//:Confused///
//:Confused/ update Lylver 2005-07-22
//:Confused/ suivant variable du PNJ
//:Confused///
//:Confused/ update Lylver 2005-06-12
//:Confused/ creation de l'echoppe au besoin
//:Confused///
/* shop_advanced
* dluan on mar 2003 */

//:: Update Lylver 2005-01-20
//:: inclue l'estimation
//:: +/-30%
#include "nw_i0_plot"
void main()
{
    object oPC = GetPCSpeaker();
    int iStore = GetLocalInt(OBJECT_SELF,"TN_IDX_SHOP") ;// 0 par defaut du coup
    string sStore = GetLocalString(OBJECT_SELF,"TN_DYN_SHOP"+IntToString(iStore)) ;
    object oArea = GetArea(oPC);
    string sTag = GetLocalString(oArea,"ATAG");
    if( sTag == "" ) sTag = GetTag(oArea);
    object oShopAreaWP = GetWaypointByTag("TN_SHOP");
    object oStore = GetNearestObjectByTag(sStore,oShopAreaWP);
    if( GetIsObjectValid( oStore ) ){
     
    } else {
     
      oStore = CreateObject(OBJECT_TYPE_STORE, GetStringLowerCase(sStore), GetLocation(oShopAreaWP));
      // indicateur pour le GC
      // SetLocalObject(oArea,"TN_ DYN_SHOP"+IntToString(iSt ore),oStore); // obsolete
      SetLocalString(oStore,"ATAG",sTag); // pour CleanModStore
     
    }
    if (GetObjectType(oStore) == OBJECT_TYPE_STORE)
    {
        gplotAppraiseOpenStore(oStore, oPC);
    }
    else
    {
        ActionSpeakStringByStrRef(53090, TALKVOLUME_TALK);
    }
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


A mettre en script d'ouverture de la boutique
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:: ////
//:: Updated 2006-03-30, Lylver
//:Confused///
//:: Created Lylver 2005-10-02
//:: OnOpenStore pour les boutiques dynamiques
//:Confused///
void main()
{
  int nBusy = GetLocalInt(OBJECT_SELF,"BUSY");
  if( nBusy ){
      SetLocalInt(OBJECT_SELF,"BUSY",nBusy+1) ;
  }else{
      SetLocalInt(OBJECT_SELF,"BUSY",TRUE) ;
  }
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


A mettre en script de fermeture de la boutique
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:: ////
//:: Updated 2006-03-30, Lylver
//:Confused///
//:: Created Lylver 2005-10-02
//:: OnCloseStore pour les boutiques dynamiques
//:Confused///
void main()
{
  int nBusy = GetLocalInt(OBJECT_SELF,"BUSY");
  if( nBusy > 1 ){
      SetLocalInt(OBJECT_SELF,"BUSY",nBusy-1) ;
  }else{
      DeleteLocalInt(OBJECT_SELF,"BUSY") ;
  }
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


Scripts pour commande console ## dm_runscript dmstartgc
Ce message est un spoiler, et risque de vous informer de choses que vous auriez dû apprendre par vous même (fin d'un jeu, film, etc). À vos risques et périls (ludiques), vous pouvez le voir en cliquant sur cet avertissement.
Spoiler :
NWScript :

//:: ////
//:: Created Lylver 2006-02-05
//:: Debug for GC
//:: dmstartgc.nss
//:: ////
void main()
{
  object oMod = GetModule();
  string sMesg;
  if( GetLocalInt(oMod,"GCGO") ){
      sMesg = "GC already running : stop it first to clean";
      WriteTimestampedLogEntry(sMesg);
      SendMessageToAllDMs(sMesg);
      return ;
  }
  sMesg = "GC instructed to Start : please wait";
  WriteTimestampedLogEntry(sMesg);
  SendMessageToAllDMs(sMesg);
  if( GetLocalInt(oMod,"GCLOCK") ){
      sMesg = "GC Locked : unlock it first : exiting";
      WriteTimestampedLogEntry(sMesg);
      SendMessageToAllDMs(sMesg);
  } else {
      SetLocalInt(oMod,"GCGO",1);
      SignalEvent(oMod, EventUserDefined(300));
  }
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


## dm_runscript dmstopgc
NWScript :

//:: ////
//:: Created Lylver 2006-02-05
//:: Debug for GC
//:: dmstopgc.nss
//:: ! lock GC
//:: ////
void main()
{
  object oMod = GetModule();
  string sMesg = "GC instructed to Stop : please wait";
  WriteTimestampedLogEntry(sMesg);
  SendMessageToAllDMs(sMesg);
  DeleteLocalInt(oMod,"GCGO");
  SetLocalInt(oMod,"GCLOCK",TRUE);
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.


## dm_runscript dmunlockgc
NWScript :

//:: ////
//:: Created Lylver 2006-03-26
//:: Debug for GC
//:: dmunlockgc.nss
//:: ////
void main()
{
  object oMod = GetModule();
  string sMesg = "GC : unlocking";
  WriteTimestampedLogEntry(sMesg);
  SendMessageToAllDMs(sMesg);
  DeleteLocalInt(oMod,"GCLOCK");
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.



Edit : correction du static spawn
Dernière édition par lylver le 04/05/2006 16:25:07; édité 1 fois
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
Macadam
Grand Chevalier
Inscrit le: 07 Avr 2006
Messages: 132
Répondre en citant
Posté le : 11/04/2006 19:14:53 Sujet du message :

NWScript :

//fonction qui equipe la cape lorsqu'on la vet

void EquipCap (object oPC, object oItem);

//fonction qui desequipe la cape lorsqu'on l'enleve

void DesEquipCap (object oPC, object oItem);


//////////////////////////////
void EquipCap (object oPC, object oItem)
{
string sText;
string sTag = GetTag(oItem);
object oArmur=GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
int iOldApp = GetItemAppearance(oArmur, ITEM_APPR_TYPE_ARMOR_MODEL, ITEM_APPR_ARMOR_MODEL_NECK);
int iOldValue=0;
object oCape = GetItemInSlot(INVENTORY_SLOT_CLOAK, oPC);
AssignCommand(oPC, ClearAllActions());
if (sTag != GetTag(oCape)) return;
    if(iOldApp!=112)
        {
        //Mettre la cape
        iOldValue=112;
        sText = "*Met une cape*";
        }
      object oNewItem = CopyItemAndModify(oArmur, ITEM_APPR_TYPE_ARMOR_MODEL, ITEM_APPR_ARMOR_MODEL_NECK, iOldValue, TRUE);
    AssignCommand(oPC, ActionUnequipItem(oArmur));
    DestroyObject(oArmur, 0.1);
    DelayCommand(0.3,AssignCommand(oPC, ActionEquipItem(oNewItem, INVENTORY_SLOT_CHEST)));
    DelayCommand(0.5, AssignCommand(oPC, SpeakString(sText)));
}

////////////////////////////// /////
void DesEquipCap (object oPC, object oItem)
{
string sText;
string sTag = GetTag(oItem);
object oCape = GetItemInSlot(INVENTORY_SLOT_CLOAK, oPC);
object oArmur=GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
int iOldApp = GetItemAppearance(oArmur, ITEM_APPR_TYPE_ARMOR_MODEL, ITEM_APPR_ARMOR_MODEL_NECK);
int iOldValue=0;
if (sTag != GetTag(oCape)) return;
AssignCommand(oPC, ClearAllActions());
    if(iOldApp!=0)
        {
        //Enlever la cape
        iOldValue=0;
        sText = "*Enleve sa cape*";
        }
      object oNewItem = CopyItemAndModify(oArmur, ITEM_APPR_TYPE_ARMOR_MODEL, ITEM_APPR_ARMOR_MODEL_NECK, iOldValue, TRUE);
    AssignCommand(oPC, ActionUnequipItem(oArmur));
    DestroyObject(oArmur, 0.1);
    DelayCommand(0.3,AssignCommand(oPC, ActionEquipItem(oNewItem, INVENTORY_SLOT_CHEST)));
    DelayCommand(0.5, AssignCommand(oPC, SpeakString(sText)));
}


Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
Aladar
Chevalier
Inscrit le: 15 Déc 2004
Messages: 96
Localisation: Tours
Répondre en citant
Posté le : 26/08/2006 13:28:12 Sujet du message :

J'aime pas du tout le systeme de Biobio pour generer de l'or dans un contenant, alors j'ai fais cette petite fonction qui permet de mieux controler les drops de po dans les coffres, ça peut être utile. J'utilise un d100 que je multiplie par N pour obtenir le montant d'or à spawner, il est possible de determiner une somme minimum.

C'est adaptable à souhait puisque basé sur deux variables locales;
or (int) "nombre de d100 à lancer"
Min (int) "minimum d'or à droper"

NWScript :
//:: ////////////////////////////// ///////
//::  Genere de l'or dans un placeable
//:: ////////////////////////////// ///////
void GenGold(int n=1, int Min=1);

void GenGold(int n=1, int Min=1)
{
int n = GetLocalInt(OBJECT_SELF, "or"); // le nombre de d100 a lancer
int Min = GetLocalInt(OBJECT_SELF, "Min");// le minimum d'or a creer
int nGold = d100(1)*n;

if(nGold < Min) nGold = Min;
CreateItemOnObject("NW_IT_GOLD001", OBJECT_SELF, nGold);
}
Note : le code affiché ci-dessus n'est pas rendu tel qu'il devrait l'être réellement, en particulier des sauts de lignes sont automatiquement insérés pour éviter de casser la mise en page. En le copiant/collant, vous résoudrez ce problème.
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
Montrer les messages depuis :
Page 2 sur 2 ¤ Aller à la page Précédente  1, 2


Vous ne pouvez pas poster de nouveaux sujets dans ce forum
Vous ne pouvez pas répondre aux sujets dans ce forum
Vous ne pouvez pas éditer vos messages dans ce forum
Vous ne pouvez pas supprimer vos messages dans ce forum
Vous ne pouvez pas voter dans les sondages de ce forum


Sauter vers:
FAQ | Rechercher | Liste des Membres | Groupes d'utilisateurs | S'enregistrer | Profil | Se connecter pour vérifier ses messages privés | Connexion
Powered by phpBB 2.* [m] © 2001, 2002 phpBB Group
Theme rewritten in beautiful XHTML code by Baldurien.
Thème "La Bibliothèque de Neverwinter" crée par Kruger
Traduction par : phpBB-fr.com
Page generated in 256.538ms