Voir le sujet précédent ¤
Voir le sujet suivant
|
Auteur |
Message |
lylver
Héros
Inscrit le: 08 Avr 2005
Messages: 274
|
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 :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 :#include "ff_include"void main() { object oPC = OBJECT_SELF; 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 :#include "ff_include"void main(){ 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 & 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 :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() { if( GetLocalInt( OBJECT_SELF, "BUSY") ){ 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" ) ; if( ! GetIsObjectValid( stS. oCItem) && GetIsPC( stS. oSelf)){ 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); } } 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 :struct spell_data{ object oSelf ; int nSpId ; object oTgtObj ; location lTgtLoc ; int nClass ; object oCItem ; int nSSDC ; int nLevel ; int nMeta ; }; 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)); } 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 |
|
|
Sith Vicious
Grand Sage du Conseil
Inscrit le: 19 Oct 2005
Messages: 693
|
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 :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 :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 :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 |
|
|
lylver
Héros
Inscrit le: 08 Avr 2005
Messages: 274
|
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 |
|
|
Sith Vicious
Grand Sage du Conseil
Inscrit le: 19 Oct 2005
Messages: 693
|
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 |
|
|
lylver
Héros
Inscrit le: 08 Avr 2005
Messages: 274
|
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 |
|
|
Sith Vicious
Grand Sage du Conseil
Inscrit le: 19 Oct 2005
Messages: 693
|
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 |
|
|
Sith Vicious
Grand Sage du Conseil
Inscrit le: 19 Oct 2005
Messages: 693
|
Posté le : 24/03/2006 01:46:52 Sujet du message :
Doublon...
|
|
Revenir en haut |
|
|
lylver
Héros
Inscrit le: 08 Avr 2005
Messages: 274
|
Posté le : 24/03/2006 19:10:12 Sujet du message :
|
|
Revenir en haut |
|
|
ballestolive
Ecuyer
Inscrit le: 15 Nov 2005
Messages: 64
Localisation: A 35 KM Sud de Paris. |
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 :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 _________________ Coordinateur du projet LanceDragon VF un module pour NWN2. [http]
|
|
Revenir en haut |
|
|
|