La Bibliothèque de Neverwinter Nights
Aide et informations diverses sur Neverwinter Nights ainsi que D&D3.
La date/heure actuelle est 23/11/2024 02:49:08


  Page 1 sur 1 ¤

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 : 19/03/2006 22:26:43 Sujet du message : Déco-reco : rétablir le nombre de sorts mémorisés

Prérequis : système de persistence externe, activation du spell-hooking
La soluce proposée utilise NWN-FF (adaptable à nwnx2) ou autre.

tn_mod_clienter.nss (partiel, OnModuleClientEnter)
NWScript :

//:: //
//:: Updated 2006-03-18 Lylver,
//:: comptage de sorts pour anti deco-reco
/* vos fonctions et include ici */
#include "ff_include"
void main()
{
  // ajout NWN-FF 16 Mars 2006
  ExecuteScript("ff_on_cl_enter", OBJECT_SELF);
  //
  object oPC = GetEnteringObject();
  // persistences sorts en memoire
  ExecuteScript("tn_pj_initspell",oPC);
  //
/* votre code ici */
  //
}
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.


tn_pj_initspell.nss (complet)
NWScript :

//:: //
//:: Created 2006-03-18 Lylver,
//:: comptage de sorts pour anti deco-reco
#include "ff_include"
void main()
{
  object oPC = OBJECT_SELF;
  // persistences sorts en memoire
  string sId = GetLocalString(oPC, "PWId");
  if( sId == "" ){
      int nLoopCount = GetLocalInt(oPC,"INITSPELL");
      SetLocalInt(oPC,"INITSPELL",++nLoopCount);
      if( nLoopCount < 10 ) DelayCommand(1.0,ExecuteScript("tn_pj_initspell",oPC));
      else WriteTimestampedLogEntry(GetName(oPC)+" probleme d'initialisation PWId pour initspell");
      return;
  }
  WriteTimestampedLogEntry(GetName(oPC)+" PWId correct");
  int nPlayerSpells,i,nSpellID,nIdCount;
  string sSQL = "SELECT COUNT(*) FROM PlayerSpells WHERE Id=" + sId ;
  string sNumber,sSpells;
  int iRes = SQLLocalExecAndFetchDirect(sSQL);
  nIdCount = SQLLocalEatDataInt();
  WriteTimestampedLogEntry(GetName(oPC)+" Id connue dans PlayersSpells : "+sId+" "+IntToString(nIdCount));
  if( nIdCount == 1 ){
      sSQL = "SELECT SpellUsedCount FROM PlayerSpells WHERE Id=" + sId ;
      iRes = SQLLocalExecAndFetchDirect(sSQL);
      nPlayerSpells = SQLLocalEatDataInt();
  } else {
      sSQL = "INSERT INTO PlayerSpells (Id) VALUES(" + sId + ")";
      SQLExecDirect(sSQL);
      nPlayerSpells = 0;
  }
  SetLocalInt(oPC,"SpellUsedCount",nPlayerSpells) ;
  for( i = 1 ; i <= nPlayerSpells ; i++){
      sSQL = "SELECT SpellID FROM PlayerSpellUsed WHERE Id=" + sId + " AND Number=" + IntToString(i) ;
      SQLExecDirect(sSQL);
      if( SQLLocalFetch() == SQL_SUCCESS ){
        nSpellID = SQLLocalEatDataInt();
      }
      DecrementRemainingSpellUses(oPC, nSpellID);
      sSpells = sSpells + IntToString(nSpellID) + " ";
  }
  WriteTimestampedLogEntry("Sorts utilise(s) par "+ GetName(oPC) + " : " + sSpells);
  //
}
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.


ff_buildtable.nss (partiel, fichier de déclaration/initialisation des tables NWN-FF)
NWScript :

//:: //
//:: Updated 2006-03-16 Lylver, ajout NWN-FF, admin lylver
//:: checked : leave everything, CNR could be useful
#include "ff_include"
void main(){

// ajout lylver 2006-03-18

SQLExecDirect("CREATE TABLE IF NOT EXISTS `PlayerSpells` ("+
  "`Id` smallint(5) unsigned NOT NULL default '0',"+
  "`SpellUsedCount` tinyint(4) unsigned NOT NULL default '0',"+
  "PRIMARY KEY (`Id`)"+
") TYPE=MyISAM");

SQLExecDirect("CREATE TABLE IF NOT EXISTS `PlayerSpellUsed` ("+
  "`Id` smallint(5) unsigned NOT NULL default '0',"+
  "`Number` tinyint(4) unsigned NOT NULL default '0',"+
  "`SpellID` smallint(6) NOT NULL default '0',"+
  "PRIMARY KEY (`Id`,`Number`)"+
") TYPE=MyISAM");

WriteTimestampedLogEntry("PlayerSpells &amp; PlayersSpellUsed crees");
}
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.


tn_mod_rest.nss (partiel, OnModuleRest)
NWScript :

//:: //
//:: Updated 2006-03-18 Lylver,
//:: comptage de sorts pour anti deco-reco
//:: //
//:: Updated 2006-03-16 Lylver, ajout NWN-FF
/* vos fonctions et include ici */
#include "ff_include"

void main()
{
    object oPC = GetLastPCRested() ;
    object oArea = GetArea(oPC);
    object oMod = GetModule() ;

/* section "debut du repos" */
    // debut du repos
  if (GetLastRestEventType() == REST_EVENTTYPE_REST_STARTED) {
  // ajout NWN-FF 16 Mars 2006
  ff_FlushData(oPC);
  //
/* votre code ici */
}


/* section "fin du repos" */
    // Repos effectif
    if (GetLastRestEventType() == REST_EVENTTYPE_REST_FINISHED) {
    // fonction comptage des sorts
    if( GetIsPC(oPC) ){
    // sort memorise, inscription database
      string sId = GetLocalString(oPC, "PWId");
      SetLocalInt(oPC,"SpellUsedCount",0) ;
      SQLExecDirect("UPDATE PlayerSpells SET SpellUsedCount=0 WHERE Id=" + sId);
      SQLExecDirect("DELETE FROM PlayerSpellUsed WHERE Id=" + sId);
    }
/* votre code ici */
}
/* fin section "fin du repos" */
/* autre code ici */
}
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.


tn_mod_spells.nss (script spell-hooking TNB2, partiel)
NWScript :

#include "ly_lib_spell"
#include "ff_include"

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" ) ; // utilitaire pour les logs



  if( !GetIsObjectValid(stS.oCItem) && GetIsPC(stS.oSelf)){
  // sort memorise, inscription database
      string sId = GetLocalString(stS.oSelf, "PWId");
      int nPlayerSpells = GetLocalInt(stS.oSelf,"SpellUsedCount") ;
      string sSQL;
      string sNumber = IntToString(++nPlayerSpells);
      SetLocalInt(stS.oSelf,"SpellUsedCount",nPlayerSpells) ;
      sSQL = "UPDATE PlayerSpells SET SpellUsedCount=" + sNumber + " WHERE Id=" + sId ;
      SQLExecDirect(sSQL) ;
      sSQL = "INSERT INTO PlayerSpellUsed (Id,Number,SpellID) VALUES(" +
        sId + "," + sNumber + "," + IntToString(stS.nSpId) +")";
      SQLExecDirect(sSQL);
  }


/* votre code ici */
}
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.


ly_lib_spell.nss (include pour gestion spell-hooking, secondaire)
NWScript :

//:: //
//:: Created Lylver 2005-09-16
//:: include pour sorts
//:: ly_lib_spell
//:: //
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));
}

// Uses Get2DAString + Cache
int GetSpellInnateLevel(int nSpell, object o2da)
{
  int nLevel = GetLocalInt(o2da,"spellsInnate"+IntToString(nSpell));
  if( nLevel == 0 ){
      nLevel = 1 + StringToInt(Get2DAString("spells","Innate",nSpell)) ;
      SetLocalInt(o2da,"spellsInnate"+IntToString(nSpell),nLevel);
  }
  return nLevel-1 ;
}

string GetSpellImmunityType(int nSpell, object o2da)
{
  string sImmunity = GetLocalString(o2da,"spellsImmunityType"+IntToString(nSpell));
  if( sImmunity == "" ){
      sImmunity = Get2DAString("spells","ImmunityType",nSpell) ;
      SetLocalString(o2da,"spellsImmunityType"+IntToString(nSpell),sImmunity);
  }
  return sImmunity ;
}
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.

_________________
TSLODOSS
TN Bouchon 2
NWN-FF
The DMFI
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
Sith Vicious
Grand Sage du Conseil
Inscrit le: 19 Oct 2005
Messages: 693
Répondre en citant
Posté le : 23/03/2006 15:00:41 Sujet du message :

Sans NWNX, et sans persistance over-reboot (considérant que c'est surtout pour éviter qu'un joueur se deco et revienne juste après avec tous ses sorts, et que des rebbots y en a pas toutes les 5 minutes), ça donne ça :

NWScript :

//script de spell-hooking du module :

#include "x2_inc_switches"

void main()
{
 
  int nSpell = GetSpellId();
  // retourne le niveau du lanceur
  int nLevel = GetCasterLevel(OBJECT_SELF);
  // retourne la classe du lanceur
  int nClass = GetLastSpellCastClass();
 
  int nSpellDC = GetSpellSaveDC();
 
  location lLoc = GetSpellTargetLocation();
 
  object oCible = GetSpellTargetObject();
  // si un objet lance le sort, cette fonction retourne l'objet en question
  object oItemUsed = GetSpellCastItem();


  if (oItemUsed == OBJECT_INVALID && GetIsPC(OBJECT_SELF) && nLevel > 0 && !GetIsDM(OBJECT_SELF))
  {
    object oMod = GetModule();
    string sName = /*IntToString(GetLocalInt(OBJE CT_SELF,"INDEX"));*/ GetName(OBJECT_SELF);
    int nList = GetLocalInt(oMod,"SPELLS"+sName);
    nList++;
    SetLocalInt(oMod,"SPELLLIST"+sName+IntToString(nList),nSpell);
    SetLocalInt(oMod,"SPELLS"+sName,nList);
  }
}

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.


NWScript :

//script OnClientEnter du module

//...//
//Sorts
        object oPC = GetEnteringObject();
        string sName = GetName(oPC); //IntToString(nIndex);
        int nCount = GetLocalInt(oMod,"SPELLS"+sName);
        int i;
        object oMod = GetModule();
        if (nCount>0)
        {
            int nSpell;
            for (i=1;i<=nCount;i++)
            {
                nSpell = GetLocalInt(oMod,"SPELLLIST"+sName+IntToString(i));
                DecrementRemainingSpellUses(oPC,nSpell);
            }
        }
//....///
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.


NWScript :

//script de repos du module

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

    if (nRestEvent == REST_EVENTTYPE_REST_FINISHED)
    {
        string sIndex = GetName(oPC);//IntToString(GetLocalInt(oPC, "INDEX"));
        int nCount = GetLocalInt(GetModule(),"SPELLS"+sIndex);
        if (nCount > 0)
        {
            int i = 0;
            object oMod = GetModule();
            string sRoot = "SPELLLIST"+sIndex;
            for (i;i<=nCount;i++)
            {
                DeleteLocalInt(oMod,sRoot+IntToString(i));
            }
            DeleteLocalInt(oMod,"SPELLS"+sIndex);
        }

    }
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 : 23/03/2006 16:53:10 Sujet du message :

Il faut pensez à tout le monde, bien vu
par contre, essaye d'améliorer ça :

"SPELLIST" + sName + IntToString(i)

pour utiliser une fonction du nom qui ne contienne pas de blancs, il y a potentiellement des problèmes.

=> Je pars chercher une fonction qui va bien

hop :
Code :

*/
//:: //////////////////////////////////////////////
//:: Created By: Knat
//:: Created On: 28.04.03
//:: Last Change: 14.06.03
//:: //////////////////////////////////////////////

// --------------------------- GLOBALS -----------------------------------

// needed to prevent DB hijacking
// this char is forbidden in PC names
// PCs with this delimiter in their name won't be able
// to manipulate player vaults (ID_FLAG = 2)
const string SECURE_DELIMITER = "#";

// everything not in here gets considered an illegal character
// - mixed up for additional security
const string HASH_INDEX = "#i!j$k%l{&M/n(o)p=q?r^Xs`Tu'v]AwBxCyDzE1F2-G3t;4I}5Y:J6_K7+Z[Lm9N\ l0kOjPhQ,gRfSeHdU8cVbWa.";

const int HASH_PRIME = 3021377;

// simple hash
// returns -1 if string contains illegal character
int hash(string sData)
{
int nLen = GetStringLength(sData);
int i, nHash, nChar;
for(i=0;i<nLen;i++)
{
nChar = FindSubString(HASH_INDEX, GetSubString(sData,i,1));
if(nChar == -1) return -1;
nHash = ((nHash<<5) ^ (nHash>>27)) ^ nChar;
}
return nHash % HASH_PRIME;
}

// return database ID from oTarget
int PINV_GetID(object oTarget, int nIDType = 0)
{
string sID;
switch(nIDType)
{
case 0 :
sID = "T" + SECURE_DELIMITER + GetTag(oTarget);
break;
case 1 :
sID = "U" + GetTag(GetArea(oTarget)) + SECURE_DELIMITER + IntToString(FloatToInt(GetPosition(oTarget).x * 10)) +
IntToString(FloatToInt(GetPosition(oTarget).y * 10));
break;
case 2 :
// reject player names containing secure delimiter
if(FindSubString(GetPCPlayerName(oTarget),SECURE_DELIMITER) != -1 || FindSubString(GetName(oTarget),SECURE_DELIMITER) != -1)
return -1;
sID = "P" + GetPCPlayerName(oTarget) + SECURE_DELIMITER + GetName(oTarget);
break;
}
return hash(sID);
}


C'est le cas n°2 qui convient le mieux
Suggestion de remplacement
"SPELLS" + IntToString(PINV_GetID(oPC,2)) + "_" + IntToString(i)
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
Sith Vicious
Grand Sage du Conseil
Inscrit le: 19 Oct 2005
Messages: 693
Répondre en citant
Posté le : 23/03/2006 17:18:58 Sujet du message :

Yup, merci !

J'avais pas vraiment pensé à ça, en fait perso j'utilise pas le nom mais un chiffre unique par joueur, donc ça colle, mais j'ai changé pour le poster.

Tiens juste un truc, le ^ dans

Citation :
nHash = ((nHash<<5) ^ (nHash>>27)) ^ nChar
c'est quoi ??
 
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 : 23/03/2006 18:33:57 Sujet du message :

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 :

Citation :

Bitwise Operators

These operators obtain results based on the logical relationships of individual bits within a binary counting system. Bitwise logic is also known as Boolean logic or Boolean mathematics.


Bitwise Operators

Symbol Operation
| OR
& AND
~ NOT
^ XOR (exclusive OR)
<< Shift Left
>> Shift Right
>>> Shift Right Zero Fill


The bitwise AND ("&") and bitwise OR ("|") are briefly detailed in the logical operators topic. Additional information on these operators appear below.



For our examples, let's use 8-bit binary numbers to practice. They are represented as 4 bits, a space, and the last four bits.

Example: 0001 1010 = 26


Bitwise 'OR' operator ("|"):
Will compare the bits of two numbers, and return a number with a 1 in every bit that has a 1 in either number. This is basically used to 'add' a bit to a number.

Example: 0001 1010 | 0001 0101 = 0001 1111


Bitwise 'AND' operator ("&"):
Will compare the bits of two numbers, and return a number with a 1 in every bit that has a 1 in both numbers. This is used to see if a bit exists in a number.

Example: 0001 1010 & 0000 1000 = 0000 1000


Bitwise 'NOT' operator ("~"):
Will compare the bits of two numbers, and return a number with 1s where neither number has a 1. This is used to subtract a bit from a number.

Example: 0001 1010 ~ 0100 0011 = 1010 0100


Bitwise 'XOR' operator ("^"):
Will compare the bits of two numbers, and return a number with a 1 in every bit that has a 1 in one number, but not the other. This is used to toggle a bit in a number.

Example: 0001 1010 ^ 0001 0000 = 0000 1010 and 0001 1010 ^ 0000 0100 = 0001 1110


Bitwise 'shift left' operator ("<<"):
Will take the bits of a number and move the 1s to the left a certain number of places. This is used to multiply by powers of 2.

Example: 0001 1010 << 2 = 0110 1000


Bitwise 'shift right' operator (">>"):
Will take the bits of a number and move the 1s to the right a certain number of places. This is used to divide by powers of 2.

Example: 0001 1010 >> 2 = 1000 0110


Bitwise 'shift right zero fill' operator (">>>"):
Will take the bits of a number and move the 1s to the right a certain number of places. The ones and zeros (bits) that pass the right bound of the byte are discarded, and the left side of the byte is padded with zeros (zero bits). This is used to divide by powers of 2.

Example: 0100 1111 >>> 2 = 0001 0011


Why on earth do I want to know this?
The trick to using bitwise arithmetic is to stop thinking of the numbers as numbers, but as groups of Yes/No flags. Each bit can represent a TRUE/FALSE value which you would check against.



To use this effectively, you would have some preset values like this:

int QUEST_ONE_DONE = 1;
int QUEST_TWO_DONE = 2;
int QUEST_THREE_DONE = 4;
int QUEST_FOUR_DONE = 8;



Notice that each value is a power of 2. This means it can be represented by a binary number with only a single 1 in place. That place value is the location for the 'flag' that represents a certain TRUE/FALSE value.



A practical example using the values set above.

I want to know if a PC has done a particular quest.
I want to eliminate the number of variables stored on the PC that depict the state of the quests.
I want a cleaner, more efficient way of checking the status of my quests.
I check a local int on the PC that I have called 'nQuestFlags' with the following line: // assumes the following code executes in one of the PC's
// events; if not use, the appropriate Get* function to retrieve
// the PC (in place of OBJECT_SELF)
int nQuestFlags = GetLocalInt(OBJECT_SELF, "nQuestFlags");
if (nQuestFlags & QUEST_TWO_DONE)
{
// he did the quest
}
else
{
// he did not do the quest
}

When the PC completes quest 3, I add the flag with this line: // again, assumes this executes in one of the PC's events
// as OBJECT_SELF refers to the PC
nQuestFlags = nQuestFlags | QUEST_THREE_DONE;
SetLocalInt(OBJECT_SELF, "nQuestFlags", nQuestFlags);

One final example to demonstrate the flexibility that bitwise operators and arithmatic provide appears below.

// prototype
void testQuest(int nQuests);
// pseudo-constants (bit flags)
int QUEST_ONE_DONE = 1;
int QUEST_TWO_DONE = 2;
int QUEST_THREE_DONE = 4;
int QUEST_FOUR_DONE = 8;

void main()
{
// demonstrate the flexibility of bitwise operations
int nQuest = 0;
// let's complete quest one
nQuest = nQuest | QUEST_ONE_DONE;
// let's now complete quest three
nQuest |= QUEST_THREE_DONE; // same as "nQuest = nQuest | QUEST_THREE_DONE;"
// what does the log print out?
testQuest(nQuest);
// examining the log, you would see
/*
Quest one complete
Quest three complete
*/
testQuest(QUEST_ONE_DONE | QUEST_TWO_DONE | QUEST_THREE_DONE | QUEST_FOUR_DONE);
// examining the log for the above statement, you would see
/*
Quest one complete
Quest two complete
Quest three complete
Quest four complete
*/
}

void testQuest(int nQuests)
{
// writes the completed quest to the log file
if (nQuests & QUEST_ONE_DONE)
PrintString("Quest one complete");
if (nQuests & QUEST_TWO_DONE)
PrintString("Quest two complete");
if (nQuests & QUEST_THREE_DONE)
PrintString("Quest three complete");
if (nQuests & QUEST_FOUR_DONE)
PrintString("Quest four complete");
}

Bitwise AND and OR in logical evaluations (if/then-type tests)

Instead of using the short-circuit logical evaluators and ("&&") and or ("||") you can use bitwise AND ("&") and OR ("|") in their place, assuming the default NWN values of TRUE ("1") and FALSE ("0") are used. Of course using these operators on statements that do not return a TRUE or FALSE will perform mathematical operations that will not give you the results you seek unless you are specifically trying to use bitwise arithmatic (see above).

// these two simple functions are used for demonstrating bitwise
// AND and OR
int LogicalTestOne(int iReturn)
{
PrintString("Test One Ran...");
return iReturn;
}

int LogicalTestTwo(int iReturn)
{
PrintString("Test Two Ran...");
return iReturn;
}

The following code sample uses the above defined functions and outputs to the log:

void main()
{
if (LogicalTestOne(1) & LogicalTestTwo(2))
{
PrintString("Both tests returned true.");
}
}



Examining the log, we find the following:

Test One Ran...
Test Two Ran...



But we expect to see "Both tests returned true." in the log file as well! What happened?



To understand this you need to understand what the values of 1 and 2 are and how the bitwise operator works. First the value of 1 in binary is 0001 and the value of 2 is 0010. The bitwise AND returns a 1 or a 0 if both positions of the comparitors are 1. in the case of 1 & 2 the result is 0:


0001
0010
----
0000


More bitwise fun comes with the | operator. What the OR operator does is return a 1 if either of the bits in the position are 1. So evaluating 0 | 2 results in:


0000
0010
----
0010


Which is 2. Now for the fun part, by definition 0 is FALSE and all other values resolve to NOT-FALSE or TRUE (even negative numbers; only 0 is FALSE). This can be evidenced by running the script with the values of 2 & 3:


0010
0011
----
0010


And 0010 is 2 which resolves to TRUE. The danger here occurs when you test numbers like 1 & 2:


0001
0010
----
0000


Or 3 & 4:


0011
0100
----
0000


Or 7 & 8:


0111
1000
----
0000


However, going back to my original note, IF you stick with the predefined values (as defined in nwscript.nss) of FALSE (0) and TRUE (1) you can safely exchange && with &. While it is true that the bitwise operators are different creatures than logical operators, informed developers can and do exchange them. The secret is understanding what they do.





--------------------------------------------------------------------------------
author: Ryan Hunt, editor: Charles Feduke, additional contributor(s): Joseph Berkley
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
Sith Vicious
Grand Sage du Conseil
Inscrit le: 19 Oct 2005
Messages: 693
Répondre en citant
Posté le : 24/03/2006 01:46:31 Sujet du message :

Ha ben merci !!

En revanche je suis pas sur de ce passage :

Citation :

Bitwise 'shift right' operator (">>"):
Will take the bits of a number and move the 1s to the right a certain number of places. This is used to divide by powers of 2.

Example: 0001 1010 >> 2 = 1000 0110


Bitwise 'shift right zero fill' operator (">>>"):
Will take the bits of a number and move the 1s to the right a certain number of places. The ones and zeros (bits) that pass the right bound of the byte are discarded, and the left side of the byte is padded with zeros (zero bits). This is used to divide by powers of 2.

Example: 0100 1111 >>> 2 = 0001 0011
Selon mes essais les deux instructions donnent la même chose (shift right zero fill)
Dernière édition par Sith Vicious le 24/03/2006 02:14:50; édité 1 fois
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
Sith Vicious
Grand Sage du Conseil
Inscrit le: 19 Oct 2005
Messages: 693
Répondre en citant
Posté le : 24/03/2006 01:46:52 Sujet du message :

Doublon...
 
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 : 24/03/2006 19:10:12 Sujet du message :

voici une meilleure fonction de hash, plus rapide à implémenter sur machine intel.
http://www.isthe.com:/chongo/tech/comp/fnv/
... vais me pencher dessus
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Ignorer l'utilisateur
 
ballestolive
Ecuyer
Inscrit le: 15 Nov 2005
Messages: 64
Localisation: A 35 KM Sud de Paris.
Répondre en citant
Posté le : 26/06/2008 18:16:38 Sujet du message :

Bonjour à tous,

j'ai un petit problème avec cette ligne du script de Sith Vicious:
NWScript :
if (nRestEvent == REST_EVENTTYPE_REST_FINISHED)
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.


Quelqu'un pourrait-il m'aider ??

Voici la réponse que me donne l'éditeur: ERREUR : INVALID DECLARATION TYPE.

Merci à vous tous Wink
_________________
Coordinateur du projet LanceDragon VF un module pour NWN2. [http]
 
Revenir en haut Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web du posteur Ignorer l'utilisateur
 
Montrer les messages depuis :
Page 1 sur 1 ¤


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 90.922ms