Voir le sujet précédent ¤
Voir le sujet suivant
|
Auteur |
Message |
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14066
Localisation: Quadran Alpha |
Posté le : 03/10/2002 23:29:09 Sujet du message : [Ressources] Vos scripts
Ce sujet a pour but de préparer une probable section Scripts , voilà : ici, vous pouvez ajouter vos propres scripts. Pour cela, utilisez la balise [ code ] (sans espace) des forums.
Je commence avec mon script de téléportation entre zones :
Code :
void TeleportObject( string sZone, string sWayPont )
{
object oPlayer = GetPCSpeaker();
object oArea = GetObjectByTag( sZone );
float fOrientation = GetFacing( oPlayer );
vector vPosition = GetPosition( GetObjectByTag( sWayPont ) );
location lWhereToGo = Location( oArea, vPosition, fOrientation );
AssignCommand( oPlayer, JumpToLocation( lWhereToGo ) );
}
Explications :
TeleportObject( string sZone, string sWayPont )
- sZone correspond au tag de la zone où il faut se téléporter.
- sWayPoint correspond à un tag de Waypoint où le personnage atterira.
Vous pouvez aussi ajouter un argument : object oPlayer et zapper la ligne : object oPlayer = GetPCSpeaker(); vu que je me sers de ce script essentiellement pour une téléportation par dialogue. (très pratique pour tester un module)
- object oArea = GetObjectByTag( sZone ) : on obtiens l'objet zone.
- float fOrientation = GetFacing( oPlayer ) : ceci est nécessaire pour la fonction Location. Même si on peut mettre 0.0 comme valeur par défaut.
- vector vPosition = GetPosition( GetObjectByTag( sWayPont ) ) : on crée un vecteur en fonction du Waypoint, cela nous permet de ne pas atterir n'importe où dans la zone : imaginez les dégats si la téléportation menait sur un mur ! (nota: le personnage serait inscruté dans le mur)
- location lWhereToGo = Location( oArea, vPosition, fOrientation ) : on stocke la location d'arrivée.
- AssignCommand( oPlayer, JumpToLocation( lWhereToGo ) ) : on se téléporte.
Edit:
pensez aussi à ceci : [http]_________________ #nwnights-fr @ irc.darkmyst.org TitanQuest-FR
Dernière édition par Baldurien le 03/10/2002 23:36:49; édité 1 fois
|
|
Revenir en haut |
|
|
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14066
Localisation: Quadran Alpha |
Posté le : 03/10/2002 23:35:44 Sujet du message : Ne pas créer à l'infini des objets
Code :
#include "NW_I0_TOOL"
void main()
{
if ( CheckPartyForItem( GetFirstPC(), "itmMiscClair" ) == FALSE )
{
CreateItemOnObject( "itmmiscclair", GetFirstPC() );
}
}
Lorsque vous commencez une partie, il peut être interessant de donner des objets: par exemple un livre , une sorte de journal des quêtes.
Cependant, lorsque vous sauvegardez le personnage, que vous refaites le module : paf! ça recrée l'objet. Ce qui, vous en conviendrez est fort peu sympathique (imaginez un objet de gros bill crée à l'infini...)
Vous devez pour cela avoir le tag de l'item, le blueprint d'une item, et le tag d'un joueur. (note: le 1.25 devrait faire apparaître la fonction GetResRef)
Notez bien : ici ce script ne teste QUE le premier joueur. Vous devrez surement passer par une boucle pour les autres joueurs. _________________ #nwnights-fr @ irc.darkmyst.org TitanQuest-FR
|
|
Revenir en haut |
|
|
Cassin
Papa-poule(t) & poissard intemporel
Inscrit le: 16 Sep 2002
Messages: 7471
Localisation: 6 bis rue de la Couveuse, Poulailler 39b |
Posté le : 14/10/2002 13:21:38 Sujet du message :
Cet exemple s'applique à un PNJ pour qu'il "attaque" un arbre pour donner l'illusion qu'il le coupe, mais avec quelques modifs on peut appliquer ce qu'on veut comme effet.
Le but étant que le bûcheron arrête son boulot quand le joueur approche, afin de pouvoir lui parler, et qu'il recommence à couper l'arbre après son départ.
D'abord, créer un PNJ, si possible avec une hache .
Pour un bô narbre, j'ai pris le tileset forest et comme les arbres sont des tiles qu'on ne peut pas "tagger", j'ai posé dessus un "InvisibleObject" que le bûcheron attaquera.
Autour du PNJ, créer un trigger qui délimitera la zone dans laquelle le joueur pénétrera et arrêtera en même temps le boulot du bûcheron.
Voilà les scripts à mettre :
Sur le Trigger :
- dans OnEnter :
Code :
void main()
{
object oPC;
oPC=GetEnteringObject();
SetLocalInt(oPC,"InZone",1);
}
- Dans OnExit :
Code :
void main()
{
object oPC;
oPC = GetExitingObject();
SetLocalInt(oPC,"InZone",0);
}
Sur le PNJ :
Dans OnPerception :
Code :
void main()
{
if(GetIsPC(GetLastPerceived()))
{
SignalEvent(OBJECT_SELF,EventUserDefined(200));
}
}
- Dans OnUserDefined :
Code :
void main()
{
object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC );
switch(GetUserDefinedEventNumber())
{
case 200:
{
if(!IsInConversation(OBJECT_SELF) && GetLocalInt(oPC,"InZone") == 0)
{
ActionAttack(GetNearestObjectByTag("InvisibleObject"));
DelayCommand(12.0,ClearAllActions());
DelayCommand(24.0,SignalEvent(OBJECT_SELF,EventUserDefined(200)));
}
else
{
DelayCommand(12.0,SignalEvent(OBJECT_SELF,EventUserDefined(200)));
}
}
}
}
Voilà !
PS : il est à noter qu'on ne peut pas parler au PNJ tant qu'il ne s'est pas mit en "mode repos" (dans mon cas, il repose sa hache sur son épaule). Si le PNJ renvoie la phrase "object is busy", il suffit d'attendre un peu que son attitude ou sa posture change pour pouvoir lui parler. _________________ Aventure ! Camaraderie ! Et acier sur acier ! Les ingrédients légendaires ! Hein Bouh ?
http://cassin1306.spaces.live.com
|
|
Revenir en haut |
|
|
Cassin
Papa-poule(t) & poissard intemporel
Inscrit le: 16 Sep 2002
Messages: 7471
Localisation: 6 bis rue de la Couveuse, Poulailler 39b |
Posté le : 14/10/2002 16:04:34 Sujet du message : Invoquer et désinvoquer un PNJ avec FXs ;)
Dans mon module lorsque le joueur clique sur un autel il fait apparaître un esprit dans un déluge de tonnerre et de feu
Voilà donc comment :
- bon, d'abord évidemment il faut commencer par créer le PNJ en question et noter son tag (ici : esprit)
- poser ensuite un waypoint, là où la créature apparaîtra. Ici il est noté WP_esprit
- ensuite, créer l'autel (ou autre placeable hein ) et le rendre Useable (Utilisable en VF)
- dans le OnUsed du placeable, mettre le script suivant :
Code :object oPC = GetLastUsedBy();
void main()
{
effect eVis = EffectVisualEffect(VFX_DUR_GHOSTLY_VISAGE);
location lLoc = GetLocation(GetNearestObjectByTag("WP_Esprit"));
object oEsprit = CreateObject(OBJECT_TYPE_CREATURE,"esprit",lLoc,TRUE);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,EffectVisualEffect(VFX_FNF_SUMMON_GATE),lLoc);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eVis,oEsprit);
}
Pour varier les effets, vous pouvez changer le VFX_FNF_SUMMON_GATE par autre chose, pour voir la liste, tapez VFX_FNF_SUMMON dans l'onglet "Constants" de l'éditeur de script. Cela va de l'effet d'invocation de monstre I à III en passant par les Celestials ...
- ensuite pour moi le PNJ devait déclencher une conversation, j'ai donc mis ce script dans son OnPerception :
Code :void main()
{
ActionStartConversation(GetLastPerceived(), "esprit",TRUE);
}
mais c'est évidemment facultatif si vous ne voulez pas le faire parler !
- A la fin de la conversation, dans les deux cases de "other files" ("autres fichiers" en VF) j'ai mis ce dernier script :
Code :#include "NW_I0_Plot"
void main()
{
effect eVis = EffectVisualEffect(VFX_IMP_UNSUMMON);
ApplyEffectToObject(DURATION_TYPE_INSTANT,eVis,OBJECT_SELF);
DestroyObject(OBJECT_SELF,0.5f);
PlayOldTheme();
}
encore une fois ici on peut faire varier l'effet...
A noter que j'ai tiré ça de la campagne solo, fin du chapitre 1, juste avant d'entrer dans le fort de Heaum, il y a un PNJ qui apparaît lorsqu'on traverse le pont.
Là le PNJ apparaissait suite au passage sur un trigger, pour ça il suffit de changer dans le premier script le object oPC = GetLastUsedBy(); par un object oPC = GetLastEntered(); et de placer le script dans le OnEnter du trigger.
Ne pas oublier non plus de placer un DestroyObject(OBJECT_SELF); à la fin du script afin de détruire le trigger, sinon le PNJ apparaîtra chaque fois que vous le traverserez (mais c'est peut-être ce que vous voulez faire aussi ).
Voilà ! _________________ Aventure ! Camaraderie ! Et acier sur acier ! Les ingrédients légendaires ! Hein Bouh ?
http://cassin1306.spaces.live.com
|
|
Revenir en haut |
|
|
Cassin
Papa-poule(t) & poissard intemporel
Inscrit le: 16 Sep 2002
Messages: 7471
Localisation: 6 bis rue de la Couveuse, Poulailler 39b |
Posté le : 14/10/2002 16:16:59 Sujet du message : Les tokens adaptés au français, par Jedaï
Dernière édition par Cassin le 12/05/2003 08:54:52; édité 2 fois
|
|
Revenir en haut |
|
|
Cassin
Papa-poule(t) & poissard intemporel
Inscrit le: 16 Sep 2002
Messages: 7471
Localisation: 6 bis rue de la Couveuse, Poulailler 39b |
Posté le : 14/10/2002 19:24:02 Sujet du message : Script de respawn
Bon attention on s'accroche là, c'est du gros morceau !
(tout d'abord merci à Jedaï (encore lui ) et à Tyn' pour m'avoir grandement aidé sur ce #%£$*% de script ! )
Donc comme le titre l'indique c'est un script de respawn. Ben oui, je trouve pas ça très réaliste que le joueur fonce de le tas et meure 36 fois en réssucitant de suite pour avoir à l'usure le vilain méchant en face. Alors voilà ce que je propose dans mon module :
- le joueur est dans un Monastère et reçoit pour mission de retrouver une arme magique dans la forêt proche. Bon. Tant qu'il n'a pas trouvé l'arme, il peut crever autant de fois, à son respawn il est téléporté au temple du monastère avec 1PV et il doit aller voir le guerrisseur avant de repartir à l'assaut.
- une fois l'arme trouvée, le monastère est sensé être détruit, et donc le joueur ne peut plus être téléporté au temple. Et c'est là que ça devient intéressant : si le joueur meurt et respawn, hop!, un pt de constit en moins. Et oui, carrément ! Ca a le mérite de faire réfléchir et à plus utiliser le bouton Save Game / Load Game que Respawn...
(et ça colle plus à une règle de AD&D qui disait qu'on ne pouvait être réssucité qu'autant de fois qu'on avait de pts de constit).
Alors avant tout, créez 10 "objets de créature" de type "peau de créature" ayant chacun comme propriété une pénalité d'un pt de constit' et de blueprint "constit1" ; "constit2" ; "constit3' etc...
(donc l'objet "constit1" avec une pénalité d'un point, l'objet "constit2" avec une pénalité de 2 pts etc... )
SURTOUT n'oubliez pas de cocher la case "Identifié", sinon ça ne marchera pas ! (on ne peut pas utiliser un objet non-identifié !)
Voici donc le script :
Code :#include "nw_i0_plot"
void main()
{
object oRespawner = GetLastRespawnButtonPresser();
ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectResurrection(),oRespawner);
if (!GetLocalInt(GetModule(), "get_armeMGK") == 0) // ici on vérifie si l'arme magique a bien été trouvée
{
string sDestTag = "RespawnPoint"; // ça c'est le tag du waypoint de téléportation, situé dans le temple ; si vous le changez, pensez aussi à le modifier ici...
if (GetIsObjectValid(GetObjectByTag(sDestTag)))
{
if (sDestTag == "RespawnPoint") // ... et ici aussi
{
object oPriest = GetObjectByTag("NW_DEATH_CLERIC");
AssignCommand(oPriest, DelayCommand(2.1, PlayVoiceChat(VOICE_CHAT_TALKTOME, oPriest)));
SetLocalLocation(oRespawner, "NW_L_I_DIED_HERE", GetLocation(GetLastRespawnButtonPresser()));
SetLocalInt(oRespawner, "NW_L_I_DIED", 1);
SetLocalObject(oPriest, "NW_L_LASTDIED", GetLastRespawnButtonPresser());
}
object oSpawnPoint = GetObjectByTag(sDestTag);
SetLocalInt (oRespawner, "mort", 1);
AssignCommand(oRespawner,JumpToLocation(GetLocation(oSpawnPoint)));
// * mak
}
}
else
{
//Respawn après : résurrect sur place mise en place des token -1 constits :
object oRez = GetLastRespawnButtonPresser();
ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(GetMaxHitPoints(oRespawner)), oRespawner);
RemoveEffects(oRespawner); // ces 2 lignes soignent le joueur de tous ses maux, chose que le script ne faisait pas en le ramenant dans le temple.
int nNbRez = GetLocalInt(oRez, "nNbRez");
nNbRez++;
if (nNbRez <=10)
{
DestroyObject(GetItemInSlot(INVENTORY_SLOT_CARMOUR, oRez));
object oPenRez = CreateItemOnObject("constit"+IntToString(nNbRez), oRez);
AssignCommand(oRez, ActionEquipItem(oPenRez, INVENTORY_SLOT_CARMOUR));
SetLocalInt(oRez, "nNbRez", nNbRez);
}
}
}
Donc pensez surtout à bien nommer les BLUEPRINTS (et pas les tags) de vos objets de constit correctement, ainsi que le WP du temple si vous en mettez un...
J'espère que ceci vous aidera et vous évitera d'y passer des jours comme moi ! _________________ Aventure ! Camaraderie ! Et acier sur acier ! Les ingrédients légendaires ! Hein Bouh ?
http://cassin1306.spaces.live.com
|
|
Revenir en haut |
|
|
Baldurien
L'homme qui chutait sur le macadam
Inscrit le: 12 Sep 2002
Messages: 14066
Localisation: Quadran Alpha |
Posté le : 20/10/2002 18:35:42 Sujet du message :
Code :
// Effet special: fx: VFX_*, time : en seconde, type de dommage DAMAGE_TYPE_*
struct FX
{
int fx;
float time;
int damage;
int damageType;
int damageMin;
int damageMax;
};
// Creer un portail:
// - oCaller : personne appelant le portail
// - lUserItemLoc : location ou creet le portail
// - Structure Portail
object CreatePortail( object oCaller, location lUserItemLoc, struct FX cBeam, struct FX cAura, int iType = 0 );
object CreatePortail( object oCaller, location lUserItemLoc, struct FX cBeam, struct FX cAura, int iType = 0 )
{
int bCanCreate = TRUE;
object oPortail = OBJECT_INVALID;
/////////////////////////////////////////////////////
/* Partie a modifier selon le type d'action voulue */
if ( iType == 0 &&
GetIsPC( oCaller ) &&
GetLocalInt( GetModule(), "bal_portail_used_by_" + GetPCPlayerName( oCaller ) )
== TRUE )
{
FloatingTextStringOnCreature( GetPCPlayerName( oCaller ) + " : vous avez deja ouvert un portail.", oCaller, FALSE );
bCanCreate = FALSE;
}
/* Partie a modifier selon le type d'action voulue */
/////////////////////////////////////////////////////
if ( bCanCreate == TRUE )
{
effect eEffect = EffectVisualEffect( VFX_DUR_ELEMENTAL_SHIELD );
effect eEffect2 = EffectVisualEffect( cAura.fx );
ApplyEffectAtLocation( DURATION_TYPE_TEMPORARY, eEffect, lUserItemLoc, 3.0);
oPortail = CreateObject( OBJECT_TYPE_PLACEABLE, "teleport_portail", lUserItemLoc, FALSE );
ApplyEffectAtLocation( DURATION_TYPE_TEMPORARY, eEffect2, lUserItemLoc, cAura.time );
effect eLightning = EffectBeam( cBeam.fx, oPortail, BODY_NODE_CHEST );
float fDelay = 0.2;
object oTarget = GetFirstObjectInShape( SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lUserItemLoc, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_ITEM | OBJECT_TYPE_PLACEABLE );
int iDamageRange = abs( cBeam.damageMax - cBeam.damageMin );
effect eDamage;
while ( GetIsObjectValid( oTarget ) )
{
if ( oTarget != oPortail )
{
DelayCommand(fDelay, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, eLightning, oTarget, cBeam.time ) );
if ( cBeam.damage == TRUE && iDamageRange > 0 )
{
eDamage = EffectDamage( ( cBeam.damageMin + Random( iDamageRange ) + 1 ), cBeam.damageType );
DelayCommand( 0.0, ApplyEffectToObject( DURATION_TYPE_INSTANT, eDamage, oTarget ) );
}
}
fDelay = fDelay + 0.1f;
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lUserItemLoc, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_ITEM | OBJECT_TYPE_PLACEABLE );
}
/* Type de portails
0. portail prive de teleportation
*/
/////////////////////////////////////////////////////
/* Partie a modifier selon le type d'action voulue */
if ( iType == 0 && GetIsPC( oCaller ) )
{
SetLocalInt( oPortail , "bal_portail_type", iType );
SetLocalString( oPortail, "bal_portail_user", GetPCPlayerName( oCaller ) );
SetLocalInt( GetModule(), "bal_portail_used_by_" + GetPCPlayerName( oCaller ), 1 );
}
/* Partie a modifier selon le type d'action voulue */
/////////////////////////////////////////////////////
}
return oPortail;
}
Un script que j'ai crée: le but est de créer un portail qui a pour blueprint teleport_portail. Ceci va en plus de créer le portail dégager des effets spéciaux histoire d'en mettre plein la vue. Ces effets spéciaux peuvent aussi mettre plein de dégâts aux créatures environnant le portail.
Je l'explique:
Code :
struct FX
{
int fx;
float time;
int damage;
int damageType;
int damageMin;
int damageMax;
};
Cette structure va nous permettre de définir un effet spécial, elle va nous simplifier la vie: au lieu de faire des noms de variable pas sympa du tout, on pourra faire appel à par exemple beam.time, ce qui est plus sympa quand même.
fx : il s'agit d'un entier représentant une des constantes VFX_*.
time : flottant représentant la durée de l'effet
damage : entier (ou booléen) représentant si oui (TRUE) ou non (FALSE) le portail dommagera les différentes choses (créatures, placeables, objets) qui traînent dans le coin.
damageType : type de dommage. Basiquement représenté par une constante DAMAGE_TYPE_*
damageMin, damageMax : dommage minimum et maximum. Et oui, on utilise pas les fonctions d20
Code :
object CreatePortail( object oCaller, location lUserItemLoc, struct FX cBeam, struct FX cAura, int iType = 0 )
oCaller: personne qui appelle le portail.
lUserItemLoc : l'endroit où va se 'poser' le portail. Basiquement: GetItemActivatedTargetLocation(); s'il s'agit d'une item créant le portail.
cBeam : représente le rayon (par exemple: électrique) qui 'touchera' chacun des objets présant dans la zone. Ici, cBeam.fx doit être une constante VFX_BEAM_*
cAura : lorsque le portail apparaît on crée une aura (sans effets sur les objets) : par exemple, une aura de 'froid' sur un portail menant vers les plaines hivernales. etc. Basiquement, ça doit être une constante VFX_DUR_AURA_*
iType : type de portail. Si vous désirez faire un portail menant vers l'enfer, alors il serait bon d'envoyer quelque démons, ceci vous permet d'ajouter des suppléments à la fonction
La fonction renvoie par défaut le portail crée, ou un OBJECT_INVALID en cas de pépin.
Code :
/////////////////////////////////////////////////////
/* Partie a modifier selon le type d'action voulue */
if ( iType == 0 &&
GetIsPC( oCaller ) &&
GetLocalInt( GetModule(), "bal_portail_used_by_" + GetPCPlayerName( oCaller ) )
== TRUE )
{
FloatingTextStringOnCreature( GetPCPlayerName( oCaller ) + " : vous avez deja ouvert un portail.", oCaller, FALSE );
bCanCreate = FALSE;
}
/* Partie a modifier selon le type d'action voulue */
/////////////////////////////////////////////////////
Cette partie consiste basiquement à vérifier par exemple l'existance du portail et éviter qu'il soit recrée. Si vous donnez a valeur FALSE à bCanCreate alors rien ne se produira.
Code :
/////////////////////////////////////////////////////
/* Partie a modifier selon le type d'action voulue */
if ( iType == 0 && GetIsPC( oCaller ) )
{
SetLocalInt( oPortail , "bal_portail_type", iType );
SetLocalString( oPortail, "bal_portail_user", GetPCPlayerName( oCaller ) );
SetLocalInt( GetModule(), "bal_portail_used_by_" + GetPCPlayerName( oCaller ), 1 );
}
/* Partie a modifier selon le type d'action voulue */
/////////////////////////////////////////////////////
C'est ici que cela se passe: en fonction du type, vous pouvez décider d'envoyer des démons, de personaliser le portail etc !
Enjoy ! _________________ #nwnights-fr @ irc.darkmyst.org TitanQuest-FR
|
|
Revenir en haut |
|
|
elthair
Novice
Inscrit le: 22 Oct 2002
Messages: 12
Localisation: RP |
Posté le : 22/10/2002 16:41:15 Sujet du message : Lien de portails
Un petit script amusant qui lie deux portails entre eux dans un module avec peu de contrainte, une cle peut-etre requise...
Utilisation:
creer un blueprint de portail avec un dialogue du style "voulez emprunter ce portail?
oui.............execution du script
non............sortie
Nommer ses portails sous cette forme: NomdePortail_A et Nomdeportail_B
et c'est tout... le lien vers la cible se fait tout seul...
Un script, un modele de portail et juste le tag a changer...
Code :
------------------------------------------------------------------
//besoin pour les fonctions de tests sur l'inventaire
#include "nw_i0_tool"
void main()
{
//def du perso qui cause au portail
object oClicker = GetPCSpeaker();
//def du portail cible
object oTarget;
//test pour savoir si une cle speciale est demandee
int iKeyRequired = GetLockKeyRequired(OBJECT_SELF);
//recuperation du nom de cette fameuse cle
string sKeyRequiredTag = GetLockKeyTag(OBJECT_SELF);
//recuperation du tag du portail
string sSourceName = GetTag(OBJECT_SELF);
//on compte sa longueur
int iSourceNameLength = GetStringLength( sSourceName );
//on recupere le dernier caractere du nom
string sLastCharacter = GetStringRight( sSourceName, 1 );
//def du nouveau dernier caractere
string sNewLastCharacter ;
//recuperation du nom moins le dernier caractere
string sSourceNameBegining = GetStringLeft( sSourceName, iSourceNameLength -1 );
//test sur le dernier caractere, si A alors devient B et reciproquement
if ( sLastCharacter == "A" ){ sNewLastCharacter = "B";}
if ( sLastCharacter == "B" ){ sNewLastCharacter = "A";}
//la cible du portail devient le debut du nom + le nouveau dernier caractere
oTarget = GetObjectByTag(sSourceNameBegining + sNewLastCharacter);
// affichage de transition
SetAreaTransitionBMP(AREA_TRANSITION_RANDOM);
//si la cle est requise, test pour savoir si l'equipe l'a
if (iKeyRequired == TRUE ){
if (CheckPartyForItem(oClicker, sKeyRequiredTag))
{
// si oui alors on saute vers la cible
AssignCommand(oClicker,JumpToObject(oTarget));
}
else
{
//si non texte...
SpeakString("Vous n'avez pas la bonne cle.");
}}
else { AssignCommand(oClicker,JumpToObject(oTarget));}
} _________________ Elthair,
J'epanche donc j'essuie
|
|
Revenir en haut |
|
|
Pof From Hell
Ecuyer
Inscrit le: 22 Oct 2002
Messages: 58
Localisation: Ba ....l'enfer.... |
Posté le : 04/12/2002 19:52:21 Sujet du message :
je voulais creer un script qui applique un effet sur un NPC qui es en train d'etre detrui....
mais comme l'effet s'applique sur le NPC ...ba quand il disparait ...l'effet aussi disparait ..
donc pas cool
alors j'ai fais ce petit script que j'ai place dans action consequentes dans un dialogue....et ca marche ...et c'est zolie !!!
voila
Code :
// Pour faire disparaitre un NPC //
// avec un effet qui persiste //
// meme si le NPC a disparu //
///////////////////////////////////
void main()
{
//On definit l'objet qui va disparaitre = oNPC,
object oNPC = GetObjectByTag("Ange001");
//On crée l'objet invisible sur lequel on va appliquer l'effet,
//il apparait a l'endroit ou est le NPC,
object oTarget = CreateObject(OBJECT_TYPE_PLACEABLE,"effetdeladestruc",GetLocation(oNPC));
//On determine l'effet a appliquer sur l'objet invisible,
effect eEffet = EffectVisualEffect(VFX_IMP_DEATH_L);
//On defini l'objet sur lequel va etre applique l'effet,
object oInvisible = GetNearestObjectByTag("EffetdelaDestructiondelAnge");
//ATTENTION: il y a un DelayCommand de 0.15, il est necessaire,
//car si le delai est inferieur a 0.15 ou s'il n'y a pas de delai,
//l'objet invisible n'a pas le temps d'apparaitre,
//donc l'effet ne peut etre applique,
//On applique l'effet a l'objet invisible,
DelayCommand(0.15,ApplyEffectToObject(DURATION_TYPE_INSTANT,eEffet,oInvisible));
//On fait disparaitre le NPC (c'est un ange dans mon exemple !!!),
DelayCommand(0.15,DestroyObject(oNPC));
//On detruit l'objet invisible qui ne sert plus a rien,
DelayCommand(10.0,DestroyObject(oInvisible));
//Et voila !!!
}
bon comme je débute en script....je pense que tout le monde savais ce script.....mais comme j'ai lutter pendant 3 heures ba chuis content donc voila
mais si qq'un trouve plus simple ..ou autre chose ...ba il peut me le dire
tcho _________________ I'm a Cowboy From Hell !!!
|
|
Revenir en haut |
|
|
Nordehialen
Acolyte
Inscrit le: 22 Jan 2003
Messages: 37
|
Posté le : 25/01/2003 12:45:25 Sujet du message :
Voilà un script pour conditionner le repos dans le module "onreste"
Il a été fait Par Jedaï et ...... pour MOA
Et Merci encore à toi....
" On dort obligatoirement dans une auberge et que si on achète la clef de la chambre SAUF si on a un Kit de Survie, dans ce cas on dort partout"
Code :void main()
{
object oPC = GetLastPCRested();
string sArea = GetTag(GetArea(oPC));
if (sArea == "Tag De L'Auberge1")
{
if( ! GetIsObjectValid(GetItemPossessedBy(oPC, "Tag de la clé1")))
{
AssignCommand(oPC, ClearAllActions());
SendMessageToPC(oPC, "Vous ne pouvez pas dormir à l'auberge sans payer votre chambre !");
}
}
else if (sArea == "Tag De L'Auberge2")
{
if( ! GetIsObjectValid(GetItemPossessedBy(oPC, "Tag de la clé2")))
{
AssignCommand(oPC, ClearAllActions());
SendMessageToPC(oPC, "Vous ne pouvez pas dormir à l'auberge sans payer votre chambre !");
}
}
else if (sArea == "Tag De L'Auberge3")
{
if( ! GetIsObjectValid(GetItemPossessedBy(oPC, "Tag de la clé3")))
{
AssignCommand(oPC, ClearAllActions());
SendMessageToPC(oPC, "Vous ne pouvez pas dormir à l'auberge sans payer votre chambre !");
}
}
else
{
if( ! GetIsObjectValid(GetItemPossessedBy(oPC, "Tag du kit")))
{
AssignCommand(oPC, ClearAllActions());
SendMessageToPC(oPC, "Vous ne pouvez pas dormir à la belle étoile sans sac de couchage !");
}
}
} _________________ Une drow loyale bonne, difficile à croire et pourtant...
|
|
Revenir en haut |
|
|
Serguai
Grand Chevalier
Inscrit le: 07 Déc 2002
Messages: 104
|
Posté le : 16/02/2003 20:19:00 Sujet du message : Des pnj qui ne sont pas au même endroit le jour ou la nuit
Voilà donc un petit système de scripts pour que vos PNJ je soient pas au même endroit le jour et la nuit.
Une petite explication sur le fonctionnement:
Il vous faut remplacer les scripts onheartbeat et onspawn des pnj en question par ceux que je vous propose. Ensuite très simple vous n'avez que 4 waypoints a créer:
- Dans le lieu où le pnj se trouve le jour il vous faut un tag EXIT_tagdupnj (endroit ou le pnj s'en ira le soir), et un tag DAY_tagdupnj (endroit ou il apparait le jour)
- Dans le lieu où le pnj se trouve la nuit il vous faut un tag EXIT_tagdupnj (endroit ou le pnj s'en ira le matin), et un tag NIGHT_tagdupnj (endroit ou il apparait la nuit).
Dans les scripts vous n'avez qu'une chose à spécifier, c'est dans le onspawn les zones de jour qu'il faut lister dans la condition (c'est important pour initialiser les variables à chaque respawn).
Si vous ne voulez pas encombrer la condition, vous pouvez toujours choisir de faire autant de onspawn que de ville en extérieur... ou trouver une autre amélioration. Je suis ouvert à toute suggestion
Pour celà, jetez un coup d'oeil au commentaire.
Voilà le premier script, celui du OnHeartBeat:
La portion de code que j'ai rajouté au OnHeartBeat normal se trouve a la fin (attention, c'est important que ca se trouve a la fin !).
Code ://::///////////////////////////////////////////////
//:: Heartbeat personnalise
//:: RAV_ANIMHB
//:://////////////////////////////////////////////
/*
Animations personnalisees
*/
//:://////////////////////////////////////////////
//:: Created By: Serge GANDOLPHE
//:: Created On: 13 fevrier 2003
//:://////////////////////////////////////////////
#include "NW_I0_GENERIC"
#include "nw_i0_plot"
void main()
{
//if(!GetIsInCombat() && !IsInConversation(OBJECT_SELF))
// ActionRandomWalk();
if(GetSpawnInCondition(NW_FLAG_FAST_BUFF_ENEMY))
{
if(TalentAdvancedBuff(40.0))
{
SetSpawnInCondition(NW_FLAG_FAST_BUFF_ENEMY, FALSE);
return;
}
}
if(GetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING))
{
int nDay = FALSE;
if(GetIsDay() || GetIsDawn())
{
nDay = TRUE;
}
if(GetLocalInt(OBJECT_SELF, "NW_GENERIC_DAY_NIGHT") != nDay)
{
if(nDay == TRUE)
{
SetLocalInt(OBJECT_SELF, "NW_GENERIC_DAY_NIGHT", TRUE);
}
else
{
SetLocalInt(OBJECT_SELF, "NW_GENERIC_DAY_NIGHT", FALSE);
}
WalkWayPoints();
}
}
if(!GetHasEffect(EFFECT_TYPE_SLEEP))
{
if(!GetIsPostOrWalking())
{
if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))
{
if(!GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN)))
{
if(!GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL) && !IsInConversation(OBJECT_SELF))
{
if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS) || GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN))
{
PlayMobileAmbientAnimations();
}
else if(GetIsEncounterCreature() &&
!GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN)))
{
PlayMobileAmbientAnimations();
}
else if(GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS) &&
!GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN)))
{
PlayImmobileAmbientAnimations();
}
}
else
{
DetermineSpecialBehavior();
}
}
else
{
//DetermineCombatRound();
}
}
}
}
else
{
if(GetSpawnInCondition(NW_FLAG_SLEEPING_AT_NIGHT))
{
effect eVis = EffectVisualEffect(VFX_IMP_SLEEP);
if(d10() > 6)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, OBJECT_SELF);
}
}
}
if(GetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT))
{
SignalEvent(OBJECT_SELF, EventUserDefined(1001));
}
//Ca se passe ici
/*Le jour le pnj se ballade dans le village et a la tombee de la nuit il rentre chez lui*/
if(GetLocalInt(OBJECT_SELF,"isoutside"))
{
if((GetIsNight() || GetIsDusk()) && !GetLocalInt(OBJECT_SELF,"movedinside")){
SetLocalInt(OBJECT_SELF,"isoutside", FALSE);
SetLocalInt(OBJECT_SELF,"movedoutside",FALSE);
SetLocalInt(OBJECT_SELF,"movedinside",TRUE);
ClearAllActions(TRUE);
EscapeArea(FALSE,"EXIT_"+GetTag(OBJECT_SELF));
object OPnj = CreateObject(OBJECT_TYPE_CREATURE,GetResRef(OBJECT_SELF),GetLocation(GetWaypointByTag("NIGHT_"+GetTag(OBJECT_SELF))));
DestroyObject(OBJECT_SELF,10.0f);//Pour etre certain de ne pas avoir de clones
}
}
else{
if((GetIsDay() || GetIsDawn()) && !GetLocalInt(OBJECT_SELF,"movedoutside")){
SetLocalInt(OBJECT_SELF,"isoutside", TRUE);
SetLocalInt(OBJECT_SELF,"movedoutside",TRUE);
SetLocalInt(OBJECT_SELF,"movedinside",FALSE);
ClearAllActions(TRUE);
EscapeArea(FALSE,"EXIT_"+GetTag(OBJECT_SELF));
object OPnj = CreateObject(OBJECT_TYPE_CREATURE,GetResRef(OBJECT_SELF),GetLocation(GetWaypointByTag("DAY_"+GetTag(OBJECT_SELF))));
DestroyObject(OBJECT_SELF,10.0f);
}
}
}
Voilà le code OnSpawn
Code ://::///////////////////////////////////////////////
//:: Default: On Spawn In
//:: rav_os_commoner
//:: Par Serge GANDOLPHE
//:://////////////////////////////////////////////
/*
Determines the course of action to be taken
after having just been spawned in
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 25, 2001
//:://////////////////////////////////////////////
#include "NW_O2_CONINCLUDE"
#include "NW_I0_GENERIC"
void main()
{
//Ici il faut lister vos zones de JOUR!!!!
//Remplacez simplement zone1 et zone2 par les tags de vos zones et rajoutez autant de || areaTag =="zonex" que vous avez de zones de jour
string areaTag = GetTag(GetArea(OBJECT_SELF));
if(areaTag =="zone1" || areaTag =="zone2" ){
SetLocalInt(OBJECT_SELF,"isoutside", TRUE);
SetLocalInt(OBJECT_SELF,"movedoutside",TRUE);
SetLocalInt(OBJECT_SELF,"movedinside",FALSE);
}
else{
SetLocalInt(OBJECT_SELF,"isoutside", FALSE);
SetLocalInt(OBJECT_SELF,"movedoutside",FALSE);
SetLocalInt(OBJECT_SELF,"movedinside",TRUE);
}
// OPTIONAL BEHAVIORS (Comment In or Out to Activate ) ****************************************************************************
//SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION);
//SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION);
// This causes the creature to say a special greeting in their conversation file
// upon Perceiving the player. Attach the [NW_D2_GenCheck.nss] script to the desired
// greeting in order to designate it. As the creature is actually saying this to
// himself, don't attach any player responses to the greeting.
//SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET);
// This will set the listening pattern on the NPC to attack when allies call
//SetSpawnInCondition(NW_FLAG_STEALTH);
// If the NPC has stealth and they are a rogue go into stealth mode
//SetSpawnInCondition(NW_FLAG_SEARCH);
// If the NPC has Search go into Search Mode
//SetSpawnInCondition(NW_FLAG_SET_WARNINGS);
// This will set the NPC to give a warning to non-enemies before attacking
//SetSpawnInCondition(NW_FLAG_SLEEP);
//Creatures that spawn in during the night will be asleep.
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
//SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
//NOTE that these animations will play automatically for Encounter Creatures.
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
// CUSTOM USER DEFINED EVENTS
/*
The following settings will allow the user to fire one of the blank user defined events in the NW_D2_DefaultD. Like the
On Spawn In script this script is meant to be customized by the end user to allow for unique behaviors. The user defined
events user 1000 - 1010
*/
//SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1001
//SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1002
//SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1005
//SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1006
//SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1008
//SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1003
//SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1004
//SetSpawnInCondition(NW_FLAG_DEATH_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1007
// DEFAULT GENERIC BEHAVIOR (DO NOT TOUCH) *****************************************************************************************
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
// combat.
GenerateNPCTreasure(); //* Use this to create a small amount of treasure on the creature
}
Concernant les animations: Au début du OnHeartBeat j'ai mis un ActionRandomWalk que vous pouvez évidemment modifier selon l'action que vous souhaitez que votre pnj effectue.
Vous pouvez tout simplement l'enlever si vous voulez que le pnj soit immobile.
Vous pouvez toujours décommenter certains SetSpawnInCondition du OnSpawn si vous voulez affecter un comportement spécial a votre PNJ (ca marche comme avant, cf les commentaires en anglais qui sont ceux d'origine).
Pour toutes questions, remarque ou améliorations (je le modifierai peut être encore), postez sur le Thread intitulé " Une ville vivante"
Je précise que j'ai testé ce système et que ca ne ralentit pas plus que la normale.
|
|
Revenir en haut |
|
|
Lavok
Légende vivante
Inscrit le: 22 Oct 2002
Messages: 434
Localisation: Sphère planaire |
Posté le : 22/02/2003 10:33:08 Sujet du message : Mannequin d'entraînnement
Un script un peu long mais très simple quand je compare aux autres ici :
Code :
#include "nw_i0_tool"
void main()
{
object oRigolo = GetLastDamager();
//oRigolo est celui qui a touché le mannequin.
object oGlups = OBJECT_SELF;
//oGlups, c'est le mannequin.
effect eBoum = EffectVisualEffect(VFX_FNF_SCREEN_SHAKE);
//eBoum est un effet de tremblement d'écran qui est facultatif.
int nDamage = GetTotalDamageDealt();
//nDamage est le nombre de points de dommages qu'a reçu le mannequin.
if (GetIsPC(oRigolo))
//Ici, on vérifie que oRigolo est bien un joueur.
{
if(nDamage > 99)
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 100 ou plus.
{
SendMessageToPC(oRigolo, "Tricheur !");
//On ne peut décement pas faire autant de dommages en un coup !
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(TRUE), oRigolo));
//Bref, on tue le tricheur sans sommations !
}
else
{
if(nDamage > 59)
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 60 ou plus.
{
RewardPartyXP(20, oRigolo);
//On offre 20 xp au joueur.
SendMessageToPC(oRigolo, "CHAMPION DU MONDE !!!");
//Un petit message au joueur...
ApplyEffectToObject(DURATION_TYPE_INSTANT, eBoum, oGlups);
DelayCommand(2.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eBoum, oGlups));
DelayCommand(4.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eBoum, oGlups));
//L'effet de tremblement. On peut le supprimer sans aucun problème.
}
else
{
if(nDamage > 49)
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 50 ou plus.
{
RewardPartyXP(10, oRigolo);
//On offre 10 xp au joueur.
SendMessageToPC(oRigolo, "CHAMPION !");
//Un petit message au joueur...
ApplyEffectToObject(DURATION_TYPE_INSTANT, eBoum, oGlups);
//L'effet de tremblement. On peut le supprimer sans aucun problème.
}
else
{
if(nDamage > 39)
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 40 ou plus.
{
RewardPartyXP(8, oRigolo);
//On offre 8 xp au joueur.
SendMessageToPC(oRigolo, "Champion !");
//Un petit message au joueur...
}
else
{
if(nDamage > 29)
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 30 ou plus.
{
RewardPartyXP(6, oRigolo);
//On offre 6 xp au joueur.
SendMessageToPC(oRigolo, "Des muscles d'acier !");
//Un petit message au joueur...
}
else
{
if(nDamage > 19)
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 20 ou plus.
{
RewardPartyXP(4, oRigolo);
//On offre 4 xp au joueur.
SendMessageToPC(oRigolo, "Quelle force !");
//Un petit message au joueur...
}
else
{
if(nDamage > 14)
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 15 ou plus.
{
RewardPartyXP(3, oRigolo);
//On offre 3 xp au joueur.
SendMessageToPC(oRigolo, "Impressionant !");
//Un petit message au joueur...
}
else
{
if(nDamage > 9)
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 10 ou plus.
{
RewardPartyXP(2, oRigolo);
//On offre 2 xp au joueur.
SendMessageToPC(oRigolo, "Pas mal !");
//Un petit message au joueur...
}
else
{
if(nDamage > 4)
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 5 ou plus.
{
RewardPartyXP(1, oRigolo);
//On offre 1 xp au joueur.
SendMessageToPC(oRigolo, "Bof !");
//Un petit message au joueur...
}
else
{
if(nDamage > 2)
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 3 ou plus.
{
SendMessageToPC(oRigolo, "Pas terrible !");
//Un petit message au joueur...
}
else
//Ce qui suit entre accolades est ce qui se passera si nDamage vaut 1 ou 2.
{
SendMessageToPC(oRigolo, "Mauviette !");
//Un petit message au joueur...
}
}
}
}
}
}
}
}
}
}
}
else
//Ce qui suit entre accolades est ce qui se passera si oRigolo n'est pas un joueur.
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nDamage), oGlups);
//On guérit le mannequin des dommages qu'il vient de recevoir( cela n'arrive donc que si une autre créature attaque le mannequin ).
}
}
Je ne pense pas qu'il y ait besoin d'énormément d'explications : il suffit de mettre le script dans le OnDamaged ET le OnDeath du mannequin ( avec des scripts empêchant une contre-attaque bien sûr ). Attention ! Surtout ne pas mettre "intrigue" au mannequin, sinon le script ne fonctionnera pas. Je conseille de mettre aux alentours de 200 points de vie au mannequin car c'est une source très facile d'xp( si on le rend invincible, les joueurs de votre module risquent de laisser leur personnage s'entraînner indéfiniment !). Le mannequin doit être idéalement immunisé contre les sorts et tout ce qui ne sont pas des dommages physiques. Il est bien évident que les valeurs ( d'xp ou de dommages minimum ) et les messages envoyés au joueur sont très facilement modifiables. De même, ceux qui n'aiment pas l'effet de tremblement en cas de gros dommages peuvent l'enlever.
PS : Merci à Jedaï pour l'idée du "GetTotalDamageDealt()" ( c'était pour une cible mais c'est la même chose pour un mannequin )
EDIT : Attention ! Quand je parle de mannequin c'est en tant que créature avec une apparence de mannequin et pas en tant que plaçable !
EDIT2 : Je précise le script qui empêche la contre-attaque :
Code :
void main()
{
object oPC = GetLastAttacker();
SetIsTemporaryFriend(oPC,OBJECT_SELF,FALSE,0.001);
DelayCommand(0.001,SetIsTemporaryEnemy(oPC));
}
A placer sur le 'OnPhysicalAttacked' et le 'OnSpellCastAt' du mannequin. Tous les autres événements que je n'ai pas encore cités sont vides. Le mannequin est immobile. _________________ ToB : Une seule chose semble certaine : tant que le trône de sang de Bhaal restera vide, le chaos règnera.
Moi : Une seule chose semble certaine : tant que la tête de singe de Bush restera vide, le chaos règnera.
|
|
Revenir en haut |
|
|
Albator003
Invité
|
Posté le : 25/04/2003 12:16:38 Sujet du message :
désoler Cassin me suis planter sur mon envoie j'ai mis citation au lieux de nwn Script...delete mon post si tu peux
Bijour a tous
bien pour cela crée un placable (logique) et donner lui un tag et cocher la case intrigue. Apres ça crée une arme perso à laquel vous atribuerai un tag. Une fois que c'ets fais mettez ce script sur le On Damaged du placable
Code ://://////////////////////////////////////////////
//:: FileName : Placable destructible que par une arme
//://///////////////////////////////////////////
//://///////////////////////////////////////////
//:: Created By: Albator003
//:: Created On:
//://///////////////////////////////////////////
void main()
{
object oPJ = GetLastDamager(); // On prend le dernier joueur qui attaque le placable
if(GetTag(GetLastWeaponUsed(oPJ)) == ("Tag de l'arme perso")) // On regarde si il possde l'arme pour dtruire le placable dans ce cas il la possde
{
effect eCasse = EffectVisualEffect(VFX_IMP_DEATH,VFX_FNF_LOS_EVIL_30); //Quelques effets visuelles pour que ce soit un peu plus beau
effect eCasse1 = EffectVisualEffect(VFX_IMP_LIGHTNING_M,VFX_DUR_WEB_MASS); //idem
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eCasse, GetLocation(OBJECT_SELF)); //Execution des effet pour le cas ou il possede l'arme
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eCasse1, GetLocation(OBJECT_SELF)); // Idem
DestroyObject(GetObjectByTag("Tag de votre placable")); //On detruit le placable
}
{
if(GetTag(GetLastWeaponUsed(oPJ)) != ("Tag de l'arme perso")) // On regarde si le joueur a l'arme (ici il ne la pas)
ActionSpeakString("*Vous touchez l'autel mais n'y faite aucune égratignure*"); // On lui signal que c'est pas la peine de s'acharner dessus lol
}
}
encore sry
|
|
Revenir en haut |
|
|
Cassin
Papa-poule(t) & poissard intemporel
Inscrit le: 16 Sep 2002
Messages: 7471
Localisation: 6 bis rue de la Couveuse, Poulailler 39b |
Posté le : 12/05/2003 08:47:30 Sujet du message :
|
|
Revenir en haut |
|
|
Tuyen
Demi-dieu
Inscrit le: 23 Nov 2002
Messages: 460
Localisation: Chez moi |
Posté le : 16/05/2003 01:30:01 Sujet du message :
Lisez les instructions en commentaires sur le script tutu_transe pour savoir comment faire pour utilisez la transe dans vos modules comme dans FF9
Code ://::///////////////////////////////////////////////
//:: Name tutu_transe
//:: FileName
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*mettez ce script sous le nom de "tutu_transe" dans votre liste de scripts du module
Modifier le script NW_C2_DEFAULT3 ( c'est le script de fin de round ). Ensuite creez
une arme quelconque et donnez lui le tag de trance_01, trance_02 ou trance_99. Lorsque
vous utiliserez une de ces armes dans votre module, au bout d'un certain nombre de combats,
votre perso va entrer en transe et devenir beaucoup plus fort. Cette periode dure un court
instant et apres il perd beaucoup plus de puissance qu'avant la transe. Cette periode
des effets secondaires dure 90sec (modifiable).
Je me suis inspire d'un script deja poste sur NW Vault :
http://nwvault.ign.com/Files/scripts/data/1040734959970.shtml
A noter que lorsque le PJ quitte un combat pendant la transe, lorsqu'il rencontrera
de nouveau un ennemi il reviendra a l'etat de transe, tandis que les effets de la
contretranse sont predefinis.
*/
//:://////////////////////////////////////////////
//:: Created By: Marvin Kosh
//:: Modified By: Tuyen
//:://////////////////////////////////////////////
void main()
{
// ***********************DEFINITION DES VARIABLES***************************
object oTranse = OBJECT_SELF;
int iTemps = GetLocalInt(oTranse, "temps");
// Definir le nombre de Hit Point max et actuel du perso
int iMaxHP = GetMaxHitPoints(oTranse);
int iCurHP = GetCurrentHitPoints(oTranse);
string sWeapon = GetTag(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTranse));
// Definir le type de transe
int iTranceProcess = StringToInt(GetSubString(sWeapon, 7, 2));
// Definir les dialogues d'entree et de sortie de transe
string sTranceStart = "*Transe!*";
string sTranceEnd = "Vous sentez les effets de la transe vous quitter.";
// Definir la duree du temps de transe et de contretranse
float fEffectDur = 10.0;//Ne pas changer cette valeur
float fSideEffectDur = 90.0; /*Changez cette valeur si vous voulez que
les effets negatifs durent plus longtemps*/
// Definir les effets de transe et de contretranse
effect TranceEffect1;
effect TranceEffect2;
effect TranceEffect3;
effect TranceEffect4;
effect TranceSideEffect1;
effect TranceSideEffect2;
effect TranceSideEffect3;
/* Definir les effets pour chaque type de transe : Chaque cas correspond a
un type de transe different. Vous pouvez creer des transes qui ameliorent
les capacites de combat ou plutot ceux de magie, et aussi modifier leurs
puissances. Pour cela utiliser les fonctions de type 'Effect***' et ajouter
cases entre case 1 et case 99 ne pas oublier de les declater en haut si vous
voulez ajoutez plus de 4 effets pour un type de transe. */
switch(iTranceProcess)
{
case 1:
TranceEffect1 = EffectAbilityIncrease(ABILITY_STRENGTH, 10);
TranceEffect2 = EffectHaste();
TranceEffect3 = EffectVisualEffect(VFX_FNF_LOS_HOLY_30, FALSE);
TranceEffect4 = EffectVisualEffect(VFX_DUR_PROTECTION_GOOD_MAJOR, FALSE);
break;
case 2:
TranceEffect1 = EffectSpellResistanceIncrease(25);
TranceEffect2 = EffectDamageReduction(10, DAMAGE_POWER_PLUS_TWO, 100);
TranceEffect3 = EffectVisualEffect(VFX_IMP_HARM, FALSE);
TranceEffect4 = EffectVisualEffect(VFX_DUR_SANCTUARY, FALSE);
break;
case 99:
TranceEffect1 = EffectDamageIncrease(DAMAGE_BONUS_2d6, DAMAGE_TYPE_NEGATIVE);
TranceEffect2 = EffectAttackIncrease(10, ATTACK_BONUS_MISC);
TranceEffect3 = EffectVisualEffect(VFX_DUR_PROTECTION_EVIL_MAJOR, FALSE);
TranceEffect4 = EffectVisualEffect(VFX_DUR_PROTECTION_ELEMENTS, FALSE);
break;
}
// Definir les effets de contretranse pour chaque type de transe
switch (iTranceProcess)
{
case 1:
TranceSideEffect1 = EffectAbilityDecrease(ABILITY_STRENGTH, 14);
TranceSideEffect2 = EffectSlow();
TranceSideEffect3 = EffectVisualEffect(VFX_IMP_DISPEL, FALSE);
break;
case 2:
TranceSideEffect1 = EffectSpellResistanceDecrease(25);
TranceSideEffect2 = EffectDispelMagicAll(20);
TranceSideEffect3 = EffectVisualEffect(VFX_IMP_DISPEL, FALSE);
break;
case 99:
TranceSideEffect1 = EffectVisualEffect(VFX_IMP_DEATH, FALSE);
TranceSideEffect2 = EffectSkillDecrease (SKILL_ALL_SKILLS, 20);
TranceSideEffect3 = EffectVisualEffect(VFX_FNF_PWKILL, FALSE);
break;
}
//************** C'EST LA QUE LES CHOSES SERIEUSES COMMENCENT **************
//Incrementation de la variable temps d'un point
iTemps = iTemps + 1;
SetLocalInt(oTranse, "temps", iTemps);
//Enlevez les commentaires de la ligne ci-dessous pour avoir le decompte des rounds
//FloatingTextStringOnCreature(IntToString(iTemps), oTranse, FALSE);
//Pendant 40 rounds, il ne se passe rien
//A partir du 40ieme round et jusqu'au 47ieme round, le perso entre en transe
if ((iTemps == 40) && (GetIsInCombat(oTranse)==TRUE))
{
FloatingTextStringOnCreature(sTranceStart, oTranse, FALSE);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, TranceEffect3, oTranse, fEffectDur);
}
//Application de divers effets
if ((iTemps >= 40) && (iTemps < 47) && (GetIsInCombat(oTranse)==TRUE))
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, TranceEffect1, oTranse, fEffectDur);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, TranceEffect2, oTranse, fEffectDur);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, TranceEffect4, oTranse, fEffectDur);
}
//Au 47ieme round, c'est la fin de la transe, le perso se trouve sous des effets de
//contretranse, qui le rabaissent. Ces effets durent
if (iTemps == 47)
{
SendMessageToPC(oTranse, sTranceEnd);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, TranceSideEffect1, oTranse, fSideEffectDur);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, TranceSideEffect2, oTranse, fSideEffectDur);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, TranceSideEffect3, oTranse, fSideEffectDur);
}
//Lorsque le compteur atteint 55, le remettre a 0
if (iTemps == 55)
{
iTemps = 0;
}
SetLocalInt(oTranse, "temps", iTemps);
}
Et modifier le fichier nw_c2_default3 ( pour cela taper son nom lors de l'ouverture d'un script )
Code ://::///////////////////////////////////////////////
//:: Default: End of Combat Round
//:: NW_C2_DEFAULT3
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Calls the end of combat script every round
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Modified By : Marvin Kosh
//:: Implemente dans ce module par : Votre serviteur Tuyen (o_o)
//:: Created On: Oct 16, 2001
//:://////////////////////////////////////////////
#include "NW_I0_GENERIC"
void main()
{
// Modifications pour la transe
// Definir le dernier ennemi( soit le PC, soit un autre NPC )
object oTarget = GetLastAttacker();
// definir l'armer principale utilisee ( main droie )
object oMainWeapon =(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget));
// definir le tag de l'arme en tant que string
string sTag = GetTag(oMainWeapon);
// verifie si le tag commence par "transe_"
// si c'est le cas lancer le script "tutu_transe" sur le dernier ennemi
if (GetSubString(sTag, 0, 7) == "trance_")
ExecuteScript("tutu_transe", oTarget);
// Fin des modifications
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));
}
}
Edit de finipe : j'ai ajouté un tout petit espace au début de tes def de variables, parce que le /* faussait le tout et mettait des trucs en commentaires
|
|
Revenir en haut |
|
|
Tyrion
Ecuyer
Inscrit le: 23 Fév 2003
Messages: 43
|
Posté le : 19/05/2003 09:22:37 Sujet du message :
Voila maintenant quelques semaines que je travaille sur un système de prison automatique et en rajoutant un cote assez rp, suite a quelques problèmes rencontrés lors de mes testes, j'ai perdu un peu de temps donc ce que je voulais rajouter (comme option pour le système) ne sont pas encore inclus.
Le système nécessite aucun DMs, il est entièrement configurable et facilement.
Ce que le système fait :
- lorsqu'un joueur Tue un autre joueur, il teleporte le tueur en prison
- il dépouille le joueur de ses objets lui mettant une tunique de bagnard
- il sort le PJ emprisonner 30 mn après son arrivée dans la prison(peut être réglé par vos soins)
- il prévient le taulard du temps qu'il lui reste avant de sortir
- il restitue tous les items au PJ
- il prévient tous les joueurs présent sur le serveur d'un envoie en prison ou d'une sortie ^^
Ce qu'il fera dans les prochaines versions : (enfin je l'espère)
- emprisonne le tueur qu'au bout de x crimes
- possibilité de sortir un PJ manuellement en coupant l chrono de tempo et rendant les objets
- j'attends vos idées ^^
Ce qui peu être mis en œuvre :
- une clef peu être posséder par les DMs pour mettre en prison manuellement
- cette même clef peu être possède par les joueurs (a définir dans le script) car sinon la clef est détruit si elle se trouve sur quelqu'un d'autre (et oui sa éviterai les petits malin qui les dupliquerais sur les serveurs autorisant les persos locaux
Voila pour la présentation.
Le système est dispo a ICI.
Merci de me dire ce que vous en penser, les bugs, ou vos idées d'amélioration. (et meme de l'aide : )
*sent la mort des PKs arriver*
Merci a elchwang (pour son aide)
|
|
Revenir en haut |
|
|
Albator003
Invité
|
Posté le : 31/07/2003 18:01:36 Sujet du message : Poubelle portable
Apres le téléphone portable la poubelle portable
Apres quelque jour de reflexion voila ce que j'ai mis au point : un poubelle portative je m'explique.
tout dabord :
un contenant qui a lallure d'un coffre que je donne au PJ qui entre dans mon module.
Un livre qui sert de mode d'emploie et d'action pour ma poubelle (a detruire les item contenu dans linventaire du contenant.
Ce system peut etre utiliser dans les module ou il y a pas mal de dropitem.
Pour inciter les joueur a rendre nos terre plus belle chaque item detruit leur donne une somme d'argent (reglable a vous de choisir)
bien voila la théorie maintenant les script
Ps je ne detail pas les script c'es tassez simple a comprendre
Crée un contenant
Crée un livre dans ces propriété mettez lui lancer sort;pouvoir unique sur soi meme (utilisation illimité)
A mettre sur le OnActivateitem du module :
Code :
void main()
{
object oPC;
if (!GetIsPC(GetItemActivatedTarget())
|| GetIsInCombat(GetItemActivator())
){
SendMessageToPC(GetItemActivator(), "Vous ne pouvez pas utiliser cet objet maintenant !");
return;}
object oTarget;
oPC = GetItemActivator();
oTarget = oPC;
AssignCommand(oTarget, ActionStartConversation(oPC, "nomdudial"));
}
Crée un dialogue portant le meme nom que vous avez appeler dans le script au dessus ici "nomdudial". Crée un dialogue genre voulez vous detruire les objet - Oui ou NOn
sur le OUi vous allez a action conséquente et vous mettez ce script
Code :
void main()
{
object oPoubelle = GetObjectByTag("Tag de votre contenant");
object oPC = GetItemPossessor(oPoubelle);
object oObject = GetFirstItemInInventory(oPoubelle);
int nGold = 20; //a vous de choisir combien vous voulez donné
while(GetIsObjectValid(oObject)==TRUE)
{
DestroyObject(oObject);
oObject = GetNextItemInInventory(oPoubelle);
GiveGoldToCreature(oPC, nGold);
}
}
Voila c'est pas bien compliquer et ca peux etre utile.
...Vous aussi faite parti du comité des eboueurs !!
|
|
Revenir en haut |
|
|
lendraste
Grand Maître Chanteur du Conseil
Inscrit le: 20 Fév 2003
Messages: 1403
Localisation: Quelque part ailleurs |
Posté le : 21/08/2003 08:05:41 Sujet du message : Multi-canaux privés de discussion sur NWN
Suite à une discussion sur un autre forum, j'ai réalisé une bibliothèque de script et proposé une solution pour créer des canaux de discussion dans NWN. C'est à l'état de prototype. Je retranscris ici les différents post qui composent le sujet, mais je vous renvoie au sujet d'origine pour toute nouvelle information qui pourrait apparaître. Ce sujet fait doublon avec la News de Gorkk.
------------------------------------
Chose promise, chose due. Voici le prototype du système de canaux privé multiple. Il est primitif et pas vraiment optimisé (autrment dit j'ai peur que ca rame un peu avec beaucoup de joueurs, mais ça reste à tester et cela peut être amélioré). Je l'ai pas beaucoup commenté également, mais je n'ai guère le temps de faire mieux pour le moment.
Voici donc ce qu'il faut faire pour l'installer. L'élement principal est une bibliothèque de script que voici et que j'appelle "lib_lrvmessqueue" :
Code :
/*******************************************************************************
** Module : Loreval Message Queue (prototype) **
** Sous-Module : Systeme multi-canaux **
**----------------------------------------------------------------------------**
** Auteur : Lendraste **
** Version : 0.1b **
** Date de creation : 14/08/2003 **
** Date de modification : 16/08/2003 **
** Compatibilites : NWN 1.29+, SOU 1.30 **
**----------------------------------------------------------------------------**
** Module permettant la creation et la gestion de canaux et de liste de dif- **
** fusion de message. Ce systeme s'appuie sur la presence d'un PNJ Listener **
**----------------------------------------------------------------------------**
** Historique **
** 14/08/2003 (v0.1b) : composition de la bibliotheque **
** 16/08/2003 (v0.1b) : premiere diffusion **
*******************************************************************************/
// -----------------------
// Bibliothèques a inclure
// -----------------------
// --- Pas de bibliotheque ---
// --------------------------
// Déclaration des constantes
// --------------------------
string LMQ_PREFIXE="LMQ_";
string LMQ_CSUFFIX="_COUNT";
// -------------------------
// Prototypage des fonctions
// -------------------------
// --- Fonctions d'informations de base ---
int LMQ_IsChan(string sChanName);
int LMQ_IsChanCreator(object oPC, string sChanName);
int LMQ_IsChanMember(object oPC, string sChanName);
object LMQ_GetChanCreator(string sChanName);
object LMQ_GetChanMember(string sChanName, string sMember);
string LMQ_UserList(string sChanName);
// --- Fonctions d'actions primitives ---
int LMQ_AddToChannel(object oJoiner, string sChanName);
int LMQ_CreateChannel(object oCreator, string sChanName);
int LMQ_RemoveFromChannel(object oMember, string sChanName);
// --- Fonctions d'actions de haut niveau ---
int LMQ_JoinChannel(object oJoiner, string sChanName);
int LMQ_KickUser(string sChanName, string sUserName);
// --- Fonctions liees a la composition et la diffusion des messages ---
void LMQ_PushMessageOnChan(string sChanName, string sMessage, object oOwner=OBJECT_INVALID);
string LMQ_ComposeMessage(string sChanName, string sMessage, object oSender=OBJECT_INVALID);
void LMQ_SendMessage(object oDest, string sChanName, string sMessage, object oSender=OBJECT_INVALID);
// --- Fonctions liees au PNJ/Listener
void LMQ_CommandInterpretor(int nListenPN, object oOwner);
void LMQ_InitiateListener(object oListener);
// ------------------------
// Definition des fonctions
// ------------------------
/******************************************
* Fonction : LMQ_IsChan *
*-----------------------------------------*
* Cette fonction permet de savoir si le *
* canal specifie existe *
*-----------------------------------------*
* Entree : *
* sChanName : nom du canal a tester *
*-----------------------------------------*
* Sortie : *
* TRUE/FALSE indiquant si le canal exis-*
* te ou non. *
*******************************************/
int LMQ_IsChan(string sChanName)
{
// --- Recuperation du compteur suppose de membre du canal nomme ---
int nCount=GetLocalInt(GetModule(), LMQ_PREFIXE+sChanName+LMQ_CSUFFIX);
if (nCount>0)
{
// -- Compte superieur a 0 signifiant qu'il y a au moins un membre, le canal existe --
return TRUE;
}
else
{
// -- Compte egal a 0 signifiant que le compteur n'existe pas ou qu'il n'y a pas de membre, le canal n'existe pas --
return FALSE;
}
}
/******************************************
* Fonction : LMQ_IsChanMember *
*-----------------------------------------*
* Cette fonction permet de savoir si le *
* membre specifie appartient au canal *
*-----------------------------------------*
* Entree : *
* oPC : le membre a tester *
* sChanName : nom du canal a tester *
*-----------------------------------------*
* Sortie : *
* TRUE/FALSE indiquant si le membre fait*
* bien partie du canal *
*******************************************/
int LMQ_IsChanMember(object oPC, string sChanName)
{
// --- Test si le canal existe ---
if (LMQ_IsChan(sChanName))
{
// --- Recupere dans la liste le membre qui porterait le meme nom ---
object oMember=LMQ_GetChanMember(sChanName, GetName(oPC));
// --- Test si cette recherche a ete fructueuse
if (GetIsObjectValid(oMember))
{
// -- La cle CD et le nom de joueur sont-ils identiques ? --
if ((GetPCPublicCDKey(oPC)==GetPCPublicCDKey(oMember)) && (GetPCPlayerName(oPC)==GetPCPlayerName(oMember)))
{
// -- C'est bien un membre de la liste du canal --
return TRUE;
}
else
{
// -- Il n'est pas membre --
return FALSE;
}
}
else
{
// -- aucun membre ne porte le meme nom, celui la n'est donc pas membre --
return FALSE;
}
}
else
{
// -- Le canal n'existe pas, donc pas de membre --
return FALSE;
}
}
/******************************************
* Fonction : LMQ_IsChanCreator *
*-----------------------------------------*
* Cette fonction permet de savoir si le *
* membre specifie est le createur du canal*
*-----------------------------------------*
* Entree : *
* oPC : le membre a tester *
* sChanName : nom du canal a tester *
*-----------------------------------------*
* Sortie : *
* TRUE/FALSE indiquant si le membre fait*
* bien partie du canal *
*******************************************/
int LMQ_IsChanCreator(object oPC, string sChanName)
{
// --- Test si le canal existe ---
if (LMQ_IsChan(sChanName))
{
// --- Recupere le premier membre du canal ---
object oMember=LMQ_GetChanCreator(sChanName);
// -- La cle CD et le nom de joueur et le nom du personnage sont-ils identiques ? --
if ((GetName(oPC)==GetName(oMember)) && (GetPCPublicCDKey(oPC)==GetPCPublicCDKey(oMember)) && (GetPCPlayerName(oPC)==GetPCPlayerName(oMember)))
{
// C'est le cas, ce premier membre identifie est donc bien le createur
return TRUE;
}
else
{
// -- aucun membre ne porte le meme nom, celui la n'est donc pas membre --
return FALSE;
}
}
else
{
// -- Le canal n'existe pas, donc pas de membre --
return FALSE;
}
}
/******************************************
* Fonction : LMQ_GetChanMember *
*-----------------------------------------*
* Cette fonction renvoie le premier membre*
* d'un canal dont le nom est identique a *
* celui specifie *
*-----------------------------------------*
* Entree : *
* sChanName : nom du canal a tester *
* sMember : nom du personnage a chercher*
*-----------------------------------------*
* Sortie : *
* un objet representant le membre ou *
* OBJECT_INVALID *
*******************************************/
object LMQ_GetChanMember(string sChanName, string sMember)
{
if (LMQ_IsChan(sChanName))
{
int nCount=GetLocalInt(GetModule(), LMQ_PREFIXE+sChanName+LMQ_CSUFFIX);
int bFound=FALSE;
object oTmp;
while ((nCount>0) && (!bFound))
{
oTmp=GetLocalObject(GetModule(), LMQ_PREFIXE+sChanName+IntToString(nCount));
if (GetName(oTmp)==sMember)
{
bFound=TRUE;
}
else
{
nCount--;
}
}
if (bFound)
{
return oTmp;
}
else
{
return OBJECT_INVALID;
}
}
else
{
return OBJECT_INVALID;
}
}
/******************************************
* Fonction : LMQ_GetChanCreator *
*-----------------------------------------*
* Cette fonction renvoie le premier membre*
* d'un canal specifie *
*-----------------------------------------*
* Entree : *
* sChanName : nom du canal a tester *
*-----------------------------------------*
* Sortie : *
* un objet representant le createur ou *
* OBJECT_INVALID pour le cas ou le canal*
* n'existe pas. Un canal existant a tou-*
* jours au moins un membre : le createur*
*******************************************/
object LMQ_GetChanCreator(string sChanName)
{
if (LMQ_IsChan(sChanName))
{
return GetLocalObject(GetModule(), LMQ_PREFIXE+sChanName+"1");
}
else
{
return OBJECT_INVALID;
}
}
/******************************************
* Fonction : LMQ_AddToChannel *
*-----------------------------------------*
* Cette fonction ajoute la creature speci-*
* a la suite de la liste des membres du *
* canal specifie *
*-----------------------------------------*
* Entree : *
* oJoiner : creature a ajouter *
* sChanName : nom du canal cible *
*-----------------------------------------*
* Sortie : *
* toujours TRUE *
*******************************************/
int LMQ_AddToChannel(object oJoiner, string sChanName)
{
int nCount=GetLocalInt(GetModule(), LMQ_PREFIXE+sChanName+LMQ_CSUFFIX);
nCount++;
SetLocalObject(GetModule(), LMQ_PREFIXE+sChanName+IntToString(nCount), oJoiner);
SetLocalInt(GetModule(), LMQ_PREFIXE+sChanName+LMQ_CSUFFIX, nCount);
return TRUE;
}
/******************************************
* Fonction : LMQ_CreateChannel *
*-----------------------------------------*
* Cette fonction cree le premier membre *
* d'un canal et le compteur associe *
*-----------------------------------------*
* Entree : *
* oCreator : membre createur *
* sChanName : nom du canal cible *
*-----------------------------------------*
* Sortie : *
* toujours TRUE *
*******************************************/
int LMQ_CreateChannel(object oCreator, string sChanName)
{
object oModule=GetModule();
SetLocalInt(oModule, LMQ_PREFIXE+sChanName+LMQ_CSUFFIX, 1);
SetLocalObject(oModule, LMQ_PREFIXE+sChanName+"1", oCreator);
return TRUE;
}
/******************************************
* Fonction : LMQ_RemoveFromChannel *
*-----------------------------------------*
* Cette fonction supprime un membre speci-*
* fie du canal specifie *
*-----------------------------------------*
* Entree : *
* oMember : membre a supprimer *
* sChanName : nom du canal cible *
*-----------------------------------------*
* Sortie : *
* renvoie TRUE si le membre est supprime*
* sinon renvoie FALSE *
*******************************************/
int LMQ_RemoveFromChannel(object oMember, string sChanName)
{
int nCount=GetLocalInt(GetModule(), LMQ_PREFIXE+sChanName+LMQ_CSUFFIX);
object oModule=GetModule();
int nC;
object oTmp;
int bFound=FALSE;
for (nC=1;nC<=nCount;nC++)
{
oTmp=GetLocalObject(oModule, LMQ_PREFIXE+sChanName+IntToString(nC));
if (!bFound)
{
if ((GetName(oMember)==GetName(oTmp)) && (GetPCPlayerName(oMember)==GetPCPlayerName(oTmp)) && (GetPCPublicCDKey(oMember)==GetPCPublicCDKey(oTmp)))
{
bFound=TRUE;
}
}
if (bFound)
{
if (nC<nCount)
{
SetLocalObject(oModule, LMQ_PREFIXE+sChanName+IntToString(nC), GetLocalObject(oModule, LMQ_PREFIXE+sChanName+IntToString(nC+1)));
}
}
}
if (bFound)
{
DeleteLocalObject(oModule, LMQ_PREFIXE+sChanName+IntToString(nCount));
nCount--;
if (nCount>0)
{
SetLocalInt(oModule, LMQ_PREFIXE+sChanName+LMQ_CSUFFIX, nCount);
}
else
{
DeleteLocalInt(oModule, LMQ_PREFIXE+sChanName+LMQ_CSUFFIX);
}
return TRUE;
}
else
{
return FALSE;
}
}
/******************************************
* Fonction : LMQ_JoinChannel *
*-----------------------------------------*
* Cette fonction se charge d'ajouter un *
* membre a un canal apres quelques test *
* prealable *
*-----------------------------------------*
* Entree : *
* oJoiner : creature a ajouter *
* sChanName : nom du canal cible *
*-----------------------------------------*
* Sortie : *
* TRUE si le membre est ajoute *
* FALSE dans les autres cas *
*******************************************/
int LMQ_JoinChannel(object oJoiner, string sChanName)
{
if (GetIsPC(oJoiner))
{
if (LMQ_IsChan(sChanName))
{
if (!LMQ_IsChanMember(oJoiner, sChanName))
{
return LMQ_AddToChannel(oJoiner, sChanName);
}
else
{
return FALSE;
}
}
else
{
return FALSE;
}
}
else
{
return FALSE;
}
}
/******************************************
* Fonction : LMQ_KickUser *
*-----------------------------------------*
* Cette fonction kick un utilisateur de la*
* liste des membres du canal specifie *
*-----------------------------------------*
* Entree : *
* sChanName : nom du canal cible *
* sUserName : nom du membre *
*-----------------------------------------*
* Sortie : *
* TRUE si le membre est kicke *
* FALSE dans les autres cas *
*******************************************/
int LMQ_KickUser(string sChanName, string sUserName)
{
object oMember=LMQ_GetChanMember(sChanName, sUserName);
if (GetIsPC(oMember))
{
return LMQ_RemoveFromChannel(oMember, sChanName);
}
else
{
return FALSE;
}
}
/******************************************
* Fonction : LMQ_UserList *
*-----------------------------------------*
* Cette fonction cree un message compor- *
* tant la liste des membres du canal donne*
*-----------------------------------------*
* Entree : *
* sChanName : nom du canal cible *
*-----------------------------------------*
* Sortie : *
* chaine de caractere contenant la liste*
* des membres *
*******************************************/
string LMQ_UserList(string sChanName)
{
string sTmp="";
object oMember;
object oModule=GetModule();
int nCount=GetLocalInt(GetModule(), LMQ_PREFIXE+sChanName+LMQ_CSUFFIX);
int nC;
for (nC=1;nC<=nCount;nC++)
{
oMember=GetLocalObject(oModule, LMQ_PREFIXE+sChanName+IntToString(nC));
sTmp=sTmp+GetName(oMember);
if (nC==1)
{
sTmp=sTmp+"*";
}
if (nC<nCount)
{
sTmp=sTmp+", ";
}
}
return sTmp;
}
/******************************************
* Fonction : LMQ_PutMessageOnChan *
*-----------------------------------------*
* Cette fonction distribue un message a *
* tous les membres d'un canal *
*-----------------------------------------*
* Entree : *
* sChanName : nom du canal cible *
* sMessage : contenu du message *
* oOwner : envoyeur du message *
*-----------------------------------------*
* Si le oOwner est omis, le message sera *
* considere comme un message systeme *
*******************************************/
void LMQ_PushMessageOnChan(string sChanName, string sMessage, object oOwner=OBJECT_INVALID)
{
object oTmp;
int nCount=GetLocalInt(GetModule(), LMQ_PREFIXE+sChanName+LMQ_CSUFFIX);
string sToSend=LMQ_ComposeMessage(sChanName, sMessage, oOwner);
while (nCount>0)
{
oTmp=GetLocalObject(GetModule(), LMQ_PREFIXE+sChanName+IntToString(nCount));
if (GetIsPC(oTmp))
{
SendMessageToPC(oTmp, sToSend);
}
nCount--;
}
}
/******************************************
* Fonction : LMQ_ComposeMessage *
*-----------------------------------------*
* Cette fonction compose un message pour *
* envoie sur un canal donne. Elle se char-*
* ge egalement de composer les messages *
* d'erreur ou les messages automatiques *
* du systeme *
*-----------------------------------------*
* Entree : *
* sChanName : nom du canal cible *
* sMessage : contenu du message *
* oSender : envoyeur du message *
*-----------------------------------------*
* Sortie : *
* La chaine complete du message *
*-----------------------------------------*
* Si oSender est invalide, le message est *
* automatiquement de type "systeme" *
* "!OK" est le nom de canal a employer *
* pour creer un message individuel d'in- *
* formation. *
* "!KO" est le nom de canal a employer *
* pour creer un message individuel d'er- *
* reur *
*******************************************/
string LMQ_ComposeMessage(string sChanName, string sMessage, object oSender=OBJECT_INVALID)
{
string sHeader;
string sToSend;
if (sChanName=="!OK")
{
sHeader+=">> ";
}
else if (sChanName=="!KO")
{
sHeader+="!! ";
}
else
{
if (GetIsObjectValid(oSender))
{
sHeader="["+sChanName+" : "+GetName(oSender)+"] ";
}
else
{
sHeader="["+sChanName+"]";
}
}
if (GetIsObjectValid(oSender))
{
sToSend=sHeader+sMessage;
}
else
{
sToSend=sHeader+"<"+sMessage+">";
}
return sToSend;
}
/******************************************
* Fonction : LMQ_SendMessage *
*-----------------------------------------*
* Cette fonction envoie un message a un *
* unique destinataire *
*-----------------------------------------*
* Entree : *
* oDest : le destinataire du message *
* sChanName : nom du canal relatif *
* sMessage : contenu du message *
* oOwner : envoyeur du message *
*-----------------------------------------*
* Si le oOwner est omis, le message sera *
* considere comme un message systeme *
*******************************************/
void LMQ_SendMessage(object oDest, string sChanName, string sMessage, object oSender=OBJECT_INVALID)
{
string sToSend=LMQ_ComposeMessage(sChanName, sMessage, oSender);
SendMessageToPC(oDest, sToSend);
}
/******************************************
* Fonction : LMQ_CommandInterpretor *
*-----------------------------------------*
* Cette fonction gere les Patterns captes *
* par le listener et execute les commandes*
* correspondante *
*-----------------------------------------*
* Entree : *
* nListenPN : numero de pattern capte *
* oOwner : proprietaire du Listener *
*******************************************/
void LMQ_CommandInterpretor(int nListenPN, object oOwner)
{
switch (nListenPN)
{
case 3000 : // --- Envoie d'un message ---
{
string sChanName=GetMatchedSubstring(1);
if (LMQ_IsChan(sChanName))
{
if (LMQ_IsChanMember(oOwner, sChanName))
{
string sMessage=GetMatchedSubstring(3);
LMQ_PushMessageOnChan(sChanName, sMessage, oOwner);
}
else
{
LMQ_SendMessage(oOwner, "!KO", "Vous n'etes pas membre de ce canal");
}
}
else
{
LMQ_SendMessage(oOwner, "!KO", "Le canal n'existe pas");
}
}break;
case 3001 : // --- Creation d'un canal ---
{
string sChanName=GetMatchedSubstring(2);
if (LMQ_IsChan(sChanName))
{
LMQ_SendMessage(oOwner, "!KO", "Le canal existe deja");
}
else
{
LMQ_CreateChannel(oOwner, sChanName);
LMQ_SendMessage(oOwner, "!OK", "Canal '" + sChanName + "' cree");
}
}break;
case 3002 : // --- Se joindre a un canal ---
{
string sChanName=GetMatchedSubstring(2);
if (!LMQ_IsChan(sChanName))
{
LMQ_SendMessage(oOwner, "!KO", "Le canal n'existe pas");
}
else
{
if (LMQ_JoinChannel(oOwner, sChanName))
{
LMQ_SendMessage(oOwner, "!OK", "Vous rejoignez le canal '" + sChanName + "'");
LMQ_PushMessageOnChan(sChanName, "L'utilisateur '"+GetName(oOwner)+"' a rejoins le canal");
}
else
{
LMQ_SendMessage(oOwner, "!KO", "Vous n'avez pas reussi a joindre le canal '" + sChanName + "'");
}
}
}break;
case 3003 : // --- Kicker un user d'un canal ---
{
string sChanName=GetMatchedSubstring(6);
if (!LMQ_IsChan(sChanName))
{
LMQ_SendMessage(oOwner, "!KO", "Le canal n'existe pas");
}
else
{
if (LMQ_IsChanCreator(oOwner, sChanName))
{
string sUserName=GetMatchedSubstring(3);
if (LMQ_KickUser(sChanName, sUserName))
{
LMQ_PushMessageOnChan(sChanName, "L'utilisateur '"+sUserName+"' a ete kicke du canal");
}
else
{
LMQ_SendMessage(oOwner, "!KO", "Impossible de banir l'utilisateur '"+sUserName+"'");
}
}
else
{
LMQ_SendMessage(oOwner, "!KO", "Vous n'avez pas le droit de kicker sur ce canal");
}
}
}break;
case 3004 : // --- Quitter un canal ---
{
string sChanName=GetMatchedSubstring(2);
if (!LMQ_IsChan(sChanName))
{
LMQ_SendMessage(oOwner, "!KO", "Le canal n'existe pas");
}
else
{
if (LMQ_RemoveFromChannel(oOwner, sChanName))
{
LMQ_PushMessageOnChan(sChanName, "L'utilisateur '"+GetName(oOwner)+"' a quitte le canal");
LMQ_SendMessage(oOwner, "!OK", "Vous avez quitte le canal'"+sChanName+"'");
}
else
{
LMQ_SendMessage(oOwner, "!KO", "Vous n'avez pas reussi a quitte le canal'"+sChanName+"'");
}
}
}break;
case 3005 : // --- Lister les membres d'un canal ---
{
string sChanName=GetMatchedSubstring(2);
if (!LMQ_IsChan(sChanName))
{
LMQ_SendMessage(oOwner, "!KO", "Le canal n'existe pas");
}
else
{
if (LMQ_IsChanMember(oOwner, sChanName))
{
string sList=LMQ_UserList(sChanName);
LMQ_SendMessage(oOwner, "!OK", "Liste des membres du canal '"+sChanName+"' : "+sList);
}
else
{
LMQ_SendMessage(oOwner, "!KO", "Vous n'avez pas le droit de lister ce canal, vous n'en etes pas membre");
}
}
}break;
}
}
/******************************************
* Fonction : LMQ_InitiateListener *
*-----------------------------------------*
* Cette fonction initialise la liste des *
* Patterns captes par le Listener donne *
*-----------------------------------------*
* Entree : *
* oListener : le Listener *
*******************************************/
void LMQ_InitiateListener(object oListener)
{
SetListenPattern(oListener, "!***w**", 3000);
SetListenPattern(oListener, "?cchan*w**", 3001);
SetListenPattern(oListener, "?jchan*w**", 3002);
SetListenPattern(oListener, "?kchan*w'**'*w**", 3003);
SetListenPattern(oListener, "?qchan*w**", 3004);
SetListenPattern(oListener, "?lchan*w**", 3005);
}
// --- Commenter pour la compilation dfinitive
//void main() {}
Cette bibliothèque, une fois créée est utilisée par 2 scripts qui devront être placé sur un PNJ dédié appelé Listener (ou ecouteur). J'ai gargé le nom "ecouteur" en ResRef, mais il suffit de peu pour que le Listener s'appelle autrement. Je conseille bien sur de faire le Listener invisible et invulnérable. Il est possible qu'il faille aussi lui ajouter quelque caractéristiques, mais ce n'est pas mon propos. Pour créer ce Listener, il faudra invoquer le morceaux de code suivant :
Code :
object oListener=CreateObject(OBJECT_TYPE_CREATURE, "ecouteur", GetLocation(oObj)); // -- Creation du Listener --
SetLocalObject(oListener, "MYPC", oObj); // -- Etablissement du lien Listener-PC --
SetLocalObject(oObj, "MYLISTENER", oListener); // -- Etablissement du lien PC-Listener --
AssignCommand(oListener, ActionForceFollowObject(oObj, 5.0)); // -- Passer en mode ForceFollow --
Dans ce code oObj désigne un PJ. Pour être sûr que tout PJ disposera de son Listener personnel, il faut utiliser ce code à l'entrée du module par un PJ.
Maintenant, sur le Listener, seuls 2 évènements sont indispensables (je ne saurais trop conseiller d'éliminer tous les scripts par défaut de Bioware sur ce PNJ).
Il nécessite un OnSpawn :
Code :
#include "lib_lrvmessqueue"
void main()
{
LMQ_InitiateListener(OBJECT_SELF); // -- Initialisation des patterns d'ecoute --
SetListening(OBJECT_SELF, TRUE); // -- Activation du mode d'ecoute --
}
Et un OnConversation :
Code :
#include "lib_lrvmessqueue"
void main()
{
object oSpeaker=GetLastSpeaker(); // -- Recupere la derniere creature entendue --
if (GetIsPC(oSpeaker)) // -- verifie qu'il s'agit d'un PC --
{
object oOwner=GetLocalObject(OBJECT_SELF, "MYPC");
if (GetPCPublicCDKey(oOwner)==GetPCPublicCDKey(oSpeaker)) // -- verifie qu'il s'agit de SON PC --
{
int nLP=GetListenPatternNumber(); // -- recupere le numero de pattern capte --
LMQ_CommandInterpretor(nLP, oSpeaker); // -- transmet l'info au central de commande --
}
}
}
Une fois ceci fait, le mode d'emploi est relativement simple. Les commandes peuvent bien sûr être customisée à loisirs. On peut les prononcer à haute voix (elle serotn alors visible par les autres joueurs à l'écran) ou bien les dire sur le canal DM et dans ce cas personne ne les vera sauf les DMs s'ils regardent leur canal. A noter d'ailleurs que je n'ai ps fait de canal DM spécifique dans ce système (ca mériterait de figurer au rangs des améliorations).
Voici la liste des commandes :
?cchan <nom_canal> : pour créer un canal.
?jchan <nom_canal> : pour se joindre à un canal existant
?qchan <nom_canal> : pour quitter un canal dont on est membre
?kchan '<nom_personnage>' <nom_canal> : pour kicker un personnage d'un canal dont on est le createur.
?lchan <nom_canal> : pour lister les membres d'un canal dont on est membre. Celui qui porte une * est le créateur.
!<nom_canal> <message> : pour écrire un message aux membres d'un canal.
<nom_canal> doit être un nom en un seul mot. L'utilisation d'espace est proscrite.
<nom_personnage> dans la commande de kick est placé entre quote. C'est important car il faut donner le nom complet du membre a kicker et ce dernier comporte parfois des espaces (entre le nom et le prénom par exemple)
<message> peut comporter autant de caractère et d'espace que vous voulez et être de n'importe quelle forme, cela n'a pas d'importance.
Je reste à disposition sur ce sujet pour parler des problèmes ou des améliorations. Je compte le laisser à l'état de prototype un bon moment encore, car j'ai d'autres priorités.
-----------------------------------------------
En fait, ayant moi-même vécu quelques déboires avec le OnClientEnter, je ne fais pratiquement plus d'opération sur le PJ à ce moment, mais sur OnEnter de toutes mes zones. Ma technique consiste juste à remplir une variable lors du OnClientEnter pour indiquer que le PJ vient d'entrer, par la suite, quelle que soit la zone sur laquelle il est introduit, on teste la variable et on effectue le code.
Je pense tout simplement qu'au moment d'un OnClientEnter, le personnage n'est pas encore présent dans une zone ce qui fait que les opération visant à le localiser ou à créer quelque chose à ses côté échouent. Voici la façon dont je gère cela.
A mettre dans le OnClientEnter :
Code :
void main()
{
object oPC=GetEnteringObject();
if (GetIsPC(oPC))
{
SetLocalInt(oPC, "FIRST", TRUE);
}
}
et ceci sur le OnEnter de toutes les zones ou un PJ est susceptible d'apparaître à la connexion :
Code :
void main()
{
object oObj=GetEnteringObject();
if (GetIsPC(oObj))
{
if (GetLocalInt(oObj, "FIRST"))
{
DeleteLocalInt(oObj, "FIRST");
object oListener=CreateObject(OBJECT_TYPE_CREATURE, "ecouteur", GetLocation(oObj)); // -- Creation du Listener --
SetLocalObject(oListener, "MYPC", oObj); // -- Etablissement du lien Listener-PC --
SetLocalObject(oObj, "MYLISTENER", oListener); // -- Etablissement du lien PC-Listener --
AssignCommand(oListener, ActionForceFollowObject(oObj, 5.0)); // -- Passer en mode ForceFollow --
}
}
}
Je sais que c'est bourrin, mais le jour où j'ai rencontré je n'ai jamais cherché à creuser le problème, je l'ai contourné vite fait, et oublié. Ceci est ce qu'il y avait dans mon module de test, ca devrait donc fonctionner. J'aurai du le dire plus tôt. Désolé.
------------------------------------
Toujours pour aider les développeurs à fignoler cet outils voici quelques observations que j'ai pu faire :
1 - Le mode MD semble poser un problème au Listener. En effet, tant que le Listener n'a pas entendu le MD au moins une fois alors qu'il était visible et tangible, il est incapable de percevoir le MD. Ce bug (qui je pense est un bug de NWN) me tient depuis la 1.23 ce qui est véritablement prise de tête. Car cette situation se produit après chaque changement de zone de la part du MD (du moins en utilisant le "chooser"). Donc après chaque changement de zone, le MD doit se rendre visible, parler un coup et il peut se rendre de nouveau invisible, le Listener l'entendra normalement. Si quelqu'un entrevoit une solution pour contourner cette difficulté, je suis preneur.
2 - Le Listener peut demeurer visible pour le MJ, en revanche, il faut le rendrre totalement invisible pour les PNJs et aussi les Créatures (histoire que celle-ci ne le prenne pas pour cible. Or l'invisibilité n'est pas du tout la panacée. Il existe un sort bien plus efficace pour ça, c'est le Sanctuaire. L'effet sanctuaire rend totalement invisible et indécelable pour toute créature hostile celui qui en bénéficie. Si l'efficacité du sort de base Sanctuaire dépend d'un Jet de Protection (la barre peut être placée suffisamment haut pour que personne ne le réussisse) il existe un autre effet, depuis la 1.30 qui est, quant à lui, infaillible. C'est EffectEthereal . D'après ce que j'en sais, cet effet est aussi puissant que l'invisibilité de DM (en revanche, il ne rend pas intangible contrairement à ce que son nom peut laisser penser). L'astuce pour paraître invisible pour toute créature est donc d'appartenir à une faction spécialement conçue pour être hostile à tout le monde. Je rappelle à toute fin utile qu'un certaine proximité permet toujours de voir les créatures invisibles. Une créature sous cette effet là peut-être sous le nez d'un personnage sans être vu.
Cet effet est doublement avantageux car l'avatar MD n'étant hostile à personne, ce dernier pourra voir les Listeners.
3 - Parmis les caractéristiques de ce Listener, prévoyez de lui donner la vitesse de déplacement MD et de lui accorder la portée de perception maximale. Pour être encore plus sur de sa discrétion, vous pouvez lui accorder l'apparence "invisible", comme ça, même si son effet ethéré prend fin par accident, il restera relativement discret (visible avec TAB ou en passant le curseur sur lui). Accordez lui aussi le mode de déplacement discret avec un score défiant toute concurrence.
4 - La téléportation du MD vers une autre zone est semble-t-il un véritable handicap. En fait, c'est comme si l'avatar MD était détruit puis recréé. Cela réinitialise, bien sûr, la validité de la perception du MD comme expliqué au point 1 mais supprime également l'action ForceFollow implanté sur le PNJ. Il faut donc prévoir un cas de figure pour ça... Le OnHeartBeat semble le meilleur évènement pour le Listener pour lui permettre de vérifier si l'avatar qu'il suit est toujours prêt de lui. Si cela ne semble pas indispensable pour le PJ, ca l'est pour l'avatar MD. Afin d'éviter que tous les Listener n'exploite un OnHeartbeat, il serait bon de faire 2 Listener différents. Un pour les joueurs et un pour le MD avec quelques pouvoir en plus pour ne pas perdre de vu son MD. Une seconde difficulté se pose lorsque le MD s'incarne dans un PNJ, à ce moment l'Avatar cesse d'exister et le Listener est paumé . Donc il faut prévoir le coup de la disparition du MD dans un PNJ afin qu'il conserve son Listener. A noter qu'incarné dans un PNJ, le MD deviendra hostile à son Listener et donc celui-ci disparaitra de sa vue.
Voilà ce qui m'est venu à l'esprit en réfléchissant aux améliorations à prévoir.
J'essaierai de coller d'autres observations au fur et à mesure qu'elles me viennent. _________________ Lendraste de Loreval
Qui cherche la Vérité cherche celui qui la détient, car elle n'existe pas à l'état naturel.
La cité des mensonges - 1
|
|
Revenir en haut |
|
|
finipe
Grand Sage du Conseil
Inscrit le: 11 Fév 2003
Messages: 519
Localisation: Nantes |
Posté le : 17/11/2003 08:00:15 Sujet du message : Potion frelatée
Un script tout bête que j'ai fait pour simuler une potion frelatée, avec 6 effets aléatoires bénéfiques ou pas.
Il faut créer un objet magique avec en propriétés "Pouvoir unique, sur soi uniquement [utilisation unique]", et puis une jolie description du genre "La potion est présentée dans une bouteille opaque étiquetée avec soin à la main : impossible de discerner la couleur du liquide, mais son emballage est irréprochable !". L'objet devra avoir comme tag "PotionFrelatee".
Sur le OnActivate du module, ajouter le script suivant :
NWScript :void main() { object oPlayer = GetItemActivator(); object oItem = GetItemActivated(); if( GetTag ( oItem) == "PotionFrelatee") { switch ( d6()) { case 1: AssignCommand( oPlayer, ActionPlayAnimation( ANIMATION_FIREFORGET_DRINK)); DelayCommand( 1.2, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectDisease( DISEASE_SHAKES), oPlayer, 90.0)); DelayCommand( 1.3, SendMessageToPC( oPlayer, "")); DelayCommand( 1.4, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectKnockdown(), oPlayer, 6.0)); break; case 2: AssignCommand( oPlayer, ActionPlayAnimation( ANIMATION_FIREFORGET_DRINK)); DelayCommand( 1.2, ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectVisualEffect( VFX_IMP_REDUCE_ABILITY_SCORE), oPlayer)); DelayCommand( 1.3, SendMessageToPC( oPlayer, "")); DelayCommand( 1.4, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectAbilityDecrease( ABILITY_CONSTITUTION, 2), oPlayer, 60.0)); break; case 3: AssignCommand( oPlayer, ActionPlayAnimation( ANIMATION_FIREFORGET_DRINK)); SendMessageToPC( oPlayer, "Vous ne ressentez rien, aucun effet notable."); break; case 4: AssignCommand( oPlayer, ActionPlayAnimation( ANIMATION_FIREFORGET_DRINK)); DelayCommand( 1.2, ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectVisualEffect( VFX_IMP_MAGICAL_VISION), oPlayer)); DelayCommand( 1.3, SendMessageToPC( oPlayer, "")); DelayCommand( 1.4, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectSavingThrowIncrease( SAVING_THROW_ALL, 2), oPlayer, 60.0)); break; case 5: AssignCommand( oPlayer, ActionPlayAnimation( ANIMATION_FIREFORGET_DRINK)); DelayCommand( 1.2, ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectVisualEffect( VFX_IMP_IMPROVE_ABILITY_SCORE), oPlayer)); DelayCommand( 1.3, SendMessageToPC( oPlayer, "")); DelayCommand( 1.4, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectAbilityIncrease( ABILITY_CONSTITUTION, 2), oPlayer, 120.0)); DelayCommand( 1.4, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectAbilityIncrease( ABILITY_STRENGTH, 2), oPlayer, 120.0)); break; case 6: AssignCommand( oPlayer, ActionPlayAnimation( ANIMATION_FIREFORGET_DRINK)); DelayCommand( 1.2, ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectVisualEffect( VFX_IMP_HEALING_S), oPlayer)); DelayCommand( 1.2, SendMessageToPC( oPlayer, "")); DelayCommand( 1.3, ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectHeal( 10), oPlayer)); DelayCommand( 1.4, ApplyEffectToObject( DURATION_TYPE_INSTANT, EffectVisualEffect( VFX_IMP_ELEMENTAL_PROTECTION), oPlayer)); DelayCommand( 1.5, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, EffectRegenerate( 2, 10.0), oPlayer, 120.0)); 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.
Voilà, il est bien sûr possible d'ajouter autant d'effet que l'on veut pour plus de possibilités _________________ » Le Tref & l'Aucube : Histoire, misanthropie & zoologie léonine
» 1626, le Gant & l'Epée : intrigues & duels sous le règne de Louis XIII
|
|
Revenir en haut |
|
|
Klemmth
Seigneur
Inscrit le: 26 Juin 2004
Messages: 176
Localisation: france |
Posté le : 26/06/2004 11:51:50 Sujet du message :
Voila un tout petit script (mon premier) qui permet, à partir d'un objet de créer un portail puis de s'y téléporter de n'importe où, même si on a changé de zone.
Auparavant, j'ai crée un objet que j'ai appelé "Teleporteur", et où j'ai mis "Pouvoir unique sur soi uniquement ( avec utilisation illimitée )" dans les propriétés. Cet objet a pour tag "teleporteur", et pour blueprint "hen_dae1qt001". J'ai aussi fait "editer copier" sur le "recall_portail" du jeu sans rien changer.
Ce script est à àjouter dans le onActivateItem du module.
Bon je crois que c'est tout, place au script.
NWScript :void main() { object oItem = GetItemActivated(); string sItem = GetTag( oItem ); object oPlayer = GetItemActivator(); if ( sItem == "tag_item_teleporteur" ) { if ( GetLocalInt( oItem, "DejaCree" ) != 1 ) { effect eEffect = EffectVisualEffect( VFX_FNF_MYSTICAL_EXPLOSION ); location lPortail = GetLocation( oPlayer ); CreateObject( OBJECT_TYPE_PLACEABLE, "resref_du_portail_de_teleportation", lPortail, FALSE, "portail_teleportation" ); ApplyEffectAtLocation( DURATION_TYPE_INSTANT, eEffect, lPortail, 0.0 ); SetLocalInt( oItem, "DejaCree", 1); } else { object oPortail = GetObjectByTag( "portail_teleportation" ); effect eEffect = EffectVisualEffect( VFX_IMP_DUST_EXPLOSION ); location lPlayer = GetLocation( oPlayer ); location lPortail = GetLocation( oPortail ); ApplyEffectAtLocation( DURATION_TYPE_INSTANT, eEffect, lPlayer, 0.0 ); AssignCommand( oPlayer, JumpToObject( oPortail ) ); ApplyEffectAtLocation( DURATION_TYPE_INSTANT, eEffect, lPortail, 0.0 ); DestroyObject( oPortail, 4.0 ); SetLocalInt( oItem, "DejaCree", 0 ); } } } 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 |
|
|
PinMaster
Ecuyer
Inscrit le: 30 Sep 2004
Messages: 49
Localisation: Non loin de Marseille... |
Posté le : 13/09/2005 07:28:20 Sujet du message : [Système] Panneau d'affichage et scribe (SPEC BBS 2.0)
Je viend ici pour vous informer de la finalisation du système BBS de mon cru... le SPEC BBS 2.0B et M (Bioware / MySQL).
Bref, vous pourrez trouver leurs liens et quelques informations sur son évolution sur le site NWN-Système ( ici)...
Voici la description de ce système (en copier/coller):
Citation :Voici le tout nouveau système de panneau d'affichage, il est inspiré du BBS (Bulletin Board System V1.1) de Serban Oprescu. Mais aujourd'hui, il n'a plus beaucoup de chose en rapport.
La modification se porte essentiellement sur la gestion du panneau d'affichage. Vous pourrez ainsi trouver différentes rubriques comme :
-> Communiqué de l'empereur
-> Messages divers
-> Avis de recherche
-> Achat et vente d'objet
-> Rapport de bug
-> Coin MD pour le paramétrage
Petite nouveauté en plus, les Plumes et les encriers utilisables sont basés sur un système de charge d'item. Le gros avantage réside dans le fait que l'on peu créé autant d'tiem que l'on souhaite sans pour autant toucher au code du BBS. Pour cela, il suffit de crée un item type Plume ou Encirer, de définir le nombre de charges, le prix de vente et le TAG (SPEC_ENCRIER pour tout type d'encrier, SPEC_PLUMES pour tout type de plumes)... le tour est joué, rien de plus rien de moins... il suffit juste d'utiliser Aurora pour la création d'item. Donc aucune connaissance en script ne sera nécessaire.
Vous trouverez ces systèmes aux liens ci-dessous :
-> Version Bioware : Cliquez-ici
-> Version MySQL : Cliquez-ici_________________ Module en développement : Pandorn Nouvel Age
Système de Pandorn diffusé : Cliquez-ici
|
|
Revenir en haut |
|
|
lylver
Héros
Inscrit le: 08 Avr 2005
Messages: 274
|
Posté le : 20/09/2005 12:39:40 Sujet du message : complément BBS
modification et ajouts au système BBS de PinMaster, version database NWN je précise, indiqué ci-dessus.
Il s'agit d'ajouter des éléments de persistence pour :
- gérer la continuité de la date/heure du module
- réduire les problèmes de latence lors des accès aux commandes [Set/Get]Campaign[Int/String] du système de database NWN
1) Vous aurez besoin de définir dans un petit coin de votre module 4 points de passages avec les tags suivants : DBI_READ, DBS_READ, DBI_FIFO, DBS_FIFO.
Il serviront à stocker en variables locales des entiers et des chaînes de caractères.
2) Il vous faudra aussi modifier vos scripts de modules suivants :
Mod_OnModLoad, Mod_OnHeartBeat, Mod_OnUsrDefined, Mod_OnActvtItem.
3) Créér également un objet avec lancer un sort/pouvoir unique sur soi[utilisation unique] avec le Tag "RESTARTTN" (c'est changeable dans Mod_OnActvtItem si vous voulez autre chose)
pour le redémmarrage propre du module et mettez le nom de fichier de votre module au bon endroit dans Mod_OnUsrDefined (StartNewModule())
Précautions d'emploi : le cache est en mode FIFO, avec un "pacing" d'écriture que j'ai réglé à 0.5sec avec un DelayCommand. Les essais que j'ai fait me montre que les données sont stables après environ 15 secondes. Donc pour les cas de paranoïa, j'ai inclus un "restarter" pour le module, on pourrait sur le même modèle créer un "stop_module".
Sinon un peu de patience après le départ de tout le monde et vous pouvez couper sans risque.
J'ai enlevé les morceaux de scripts qui n'ont pas de rapport avec le BBS.
Voici les différents fichiers supplémentaires :
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 :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 :const int DO_CACHE = TRUE; const int DO_WCACHE = TRUE; struct MemDB{ string sDB ; object oChi ; object oChs ; object oDbi ; object oDbs ; string sVar ; int nValue ; string sValue ; }; int GCacheInt( struct MemDB stDB) { int nCache = GetLocalInt( stDB. oChi, stDB. sDB+ stDB. sVar); if( nCache == 0) { nCache = GetCampaignInt( stDB. sDB, stDB. sVar); SetLocalInt( stDB. oChi, stDB. sDB+ stDB. sVar, nCache); } return nCache; } void SCacheInt( struct MemDB stDB) { int nCache = GetLocalInt( stDB. oChi, stDB. sDB+ stDB. sVar); if( ( nCache != stDB. nValue) || ( stDB. nValue == 0) ){ object oMod = GetModule() ; int bWCACHE = DO_WCACHE && ! GetLocalInt( oMod, "REBOOT") ; SetLocalInt( stDB. oChi, stDB. sDB+ stDB. sVar, stDB. nValue); if( bWCACHE ){ int nModWCounter = 1+ GetLocalInt( stDB. oDbi, "WDBICNT") ; SetLocalInt( stDB. oDbi, "WDBICNT", nModWCounter); SetLocalString( stDB. oDbi, "IDBCACHE"+ IntToString( nModWCounter), stDB. sDB); SetLocalString( stDB. oDbi, "IVARCACHE"+ IntToString( nModWCounter), stDB. sVar); SetLocalInt( stDB. oDbi, "IVALUECACHE"+ IntToString( nModWCounter), stDB. nValue); } else{ SetCampaignInt( stDB. sDB, stDB. sVar, stDB. nValue); } } } string GCacheString( struct MemDB stDB) { string sCache = GetLocalString( stDB. oChs, stDB. sDB+ stDB. sVar); if( sCache == "") { sCache = GetCampaignString( stDB. sDB, stDB. sVar); SetLocalString( stDB. oChs, stDB. sDB+ stDB. sVar, sCache); } return sCache; } void SCacheString( struct MemDB stDB) { string sCache = GetLocalString( stDB. oChs, stDB. sDB+ stDB. sVar); if( ( sCache != stDB. sValue) || ( stDB. sValue == "") ){ object oMod = GetModule() ; int bWCACHE = DO_WCACHE && ! GetLocalInt( oMod, "REBOOT") ; SetLocalString( stDB. oChs, stDB. sDB+ stDB. sVar, stDB. sValue); if( bWCACHE ){ int nModWCounter = 1+ GetLocalInt( stDB. oDbs, "WDBSCNT") ; SetLocalInt( stDB. oDbs, "WDBSCNT", nModWCounter); SetLocalString( stDB. oDbs, "SDBCACHE"+ IntToString( nModWCounter), stDB. sDB); SetLocalString( stDB. oDbs, "SVARCACHE"+ IntToString( nModWCounter), stDB. sVar); SetLocalString( stDB. oDbs, "SVALUECACHE"+ IntToString( nModWCounter), stDB. sValue); WriteTimestampedLogEntry( "SCacheString : "+ "WDBSCNT"+ "_"+ IntToString( nModWCounter)+ " "+ "SDBCACHE"+ IntToString( nModWCounter)+ "_"+ stDB. sDB+ " "+ "SVARCACHE"+ IntToString( nModWCounter)+ "_"+ stDB. sVar+ " "+ "SVALUECACHE"+ IntToString( nModWCounter)+ "_"+ stDB. sValue); } else{ SetCampaignString( stDB. sDB, stDB. sVar, stDB. sValue); } } } 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.
Attention : celui là est une version modifiée de celui de MrPin
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 :#include "bbs_lib_item"void bbs_do_board_stats(); void bbs_initiate( object oBBS); int bbs_can_show( int WhichEntry); void bbs_change_page( int PageChange); void bbs_select_entry( int WhichEntry); void bbs_add_notice( object oBBS, string sPoster, string sTitle, string sMessage, string sDate, string sBBStag = ""); void bbs_do_board_stats() { object oMod= GetModule(); struct MemDB dDB; dDB. sDB = "DB_BBS"; dDB. oChi = GetLocalObject( oMod, "DBI_READ"); dDB. oChs = GetLocalObject( oMod, "DBS_READ"); dDB. oDbi = GetLocalObject( oMod, "DBI_FIFO"); dDB. oDbs = GetLocalObject( oMod, "DBS_FIFO"); dDB. sVar = ""; dDB. nValue = 0; dDB. sValue = ""; object oBBS = GetLocalObject( GetModule(), "BBS_" + GetTag( OBJECT_SELF)); int PageSize = GetLocalInt( oBBS, "PageSize"); dDB. sVar = GetTag( oBBS)+ "#C" + GetLocalString( oBBS, "BBS_TYPE") ; int TotalItems = GCacheInt( dDB); int PageIndex = GetLocalInt( oBBS, "PageIndex") + 1; SetCustomToken( 3671, IntToString( TotalItems)); if ( TotalItems == 0) { PageIndex = 0;} SetCustomToken( 3672, IntToString( PageIndex)); SetCustomToken( 3673, IntToString(( TotalItems + PageSize - 1) / PageSize)); } void bbs_initiate( object oBBS) { string sBBS = "BBS_" + GetTag( oBBS); object myBBS = GetLocalObject( GetModule(), sBBS); if (! GetIsObjectValid( myBBS)) { SetLocalObject( GetModule(), sBBS, oBBS); myBBS = oBBS; SetLocalInt( myBBS, "MaxItems", 100); SetLocalInt( myBBS, "PageSize", 5); } } int bbs_can_show( int WhichEntry) { object oMod= GetModule(); struct MemDB dDB; dDB. sDB = "DB_BBS"; dDB. oChi = GetLocalObject( oMod, "DBI_READ"); dDB. oChs = GetLocalObject( oMod, "DBS_READ"); dDB. oDbi = GetLocalObject( oMod, "DBI_FIFO"); dDB. oDbs = GetLocalObject( oMod, "DBS_FIFO"); dDB. sVar = ""; dDB. nValue = 0; dDB. sValue = ""; object oBBS = GetLocalObject( GetModule(), "BBS_" + GetTag( OBJECT_SELF)); int PageSize = GetLocalInt( oBBS, "PageSize"); int nSpot = GetLocalInt( oBBS, "PageIndex") * PageSize + WhichEntry; dDB. sVar = GetTag( oBBS)+ "#C" + GetLocalString( oBBS, "BBS_TYPE") ; if( nSpot <= GCacheInt( dDB) && WhichEntry <= PageSize) { return TRUE;} return FALSE; } void bbs_change_page( int PageFlip) { object oMod= GetModule(); struct MemDB dDB; dDB. sDB = "DB_BBS"; dDB. oChi = GetLocalObject( oMod, "DBI_READ"); dDB. oChs = GetLocalObject( oMod, "DBS_READ"); dDB. oDbi = GetLocalObject( oMod, "DBI_FIFO"); dDB. oDbs = GetLocalObject( oMod, "DBS_FIFO"); dDB. sVar = ""; dDB. nValue = 0; dDB. sValue = ""; object oBBS = GetLocalObject( GetModule(), "BBS_" + GetTag( OBJECT_SELF)); string sType = GetLocalString( oBBS, "BBS_TYPE"); int PageSize = GetLocalInt( oBBS, "PageSize"); dDB. sVar = GetTag( oBBS)+ "#C" + sType ; int TotalItems = GCacheInt( dDB); int MaxItems = GetLocalInt( oBBS, "MaxItems"); dDB. sVar = GetTag( oBBS)+ "#L" + sType ; int LatestItem = GCacheInt( dDB); int PageIndex = GetLocalInt( oBBS, "PageIndex") + 1 * PageFlip; if ( PageIndex < 0) { PageIndex = 0;} SetLocalInt( oBBS, "PageIndex", PageIndex); string sInfo; int iLoop; int iNotice; for ( iLoop = 0; iLoop < PageSize; iLoop++) { iNotice = LatestItem - PageIndex * PageSize - iLoop; if ( iNotice < 1) { iNotice = MaxItems + iNotice;} dDB. sVar = GetTag( oBBS)+ "#T" + sType + IntToString( iNotice) ; sInfo = GCacheString( dDB); SetCustomToken( 3680 + iLoop, sInfo); dDB. sVar = GetTag( oBBS)+ "#P" + sType + IntToString( iNotice) ; sInfo = GCacheString( dDB); if ((( PageIndex * PageSize + iLoop + 2) > TotalItems) || ( iLoop == PageSize - 1)){ sInfo = sInfo + "\n "; } SetCustomToken( 3690 + iLoop, sInfo); } bbs_do_board_stats(); SetCustomToken( 3674, ""); SetCustomToken( 3675, ""); SetCustomToken( 3676, ""); SetCustomToken( 3677, ""); SetCustomToken( 3678, ""); } void bbs_select_entry( int WhichEntry) { object oMod= GetModule(); struct MemDB dDB; dDB. sDB = "DB_BBS"; dDB. oChi = GetLocalObject( oMod, "DBI_READ"); dDB. oChs = GetLocalObject( oMod, "DBS_READ"); dDB. oDbi = GetLocalObject( oMod, "DBI_FIFO"); dDB. oDbs = GetLocalObject( oMod, "DBS_FIFO"); dDB. sVar = ""; dDB. nValue = 0; dDB. sValue = ""; object oBBS = GetLocalObject( GetModule(), "BBS_" + GetTag( OBJECT_SELF)); string sType = GetLocalString( oBBS, "BBS_TYPE"); int PageSize = GetLocalInt( oBBS, "PageSize"); int MaxItems = GetLocalInt( oBBS, "MaxItems"); dDB. sVar = GetTag( oBBS)+ "#L" + sType ; int LatestItem = GCacheInt( dDB); int PageIndex = GetLocalInt( oBBS, "PageIndex"); int iNotice = LatestItem - PageIndex * PageSize - WhichEntry + 1; if ( iNotice < 1) { iNotice = MaxItems + iNotice;} string sNotice = IntToString( iNotice); bbs_do_board_stats(); dDB. sVar = GetTag( oBBS)+ "#T" + sType + sNotice ; SetCustomToken( 3674, "\n\n" + GCacheString( dDB) + "\nPar: "); dDB. sVar = GetTag( oBBS)+ "#P" + sType + sNotice ; SetCustomToken( 3675, GCacheString( dDB)); SetCustomToken( 3676, " Le: "); dDB. sVar = GetTag( oBBS)+ "#D" + sType + sNotice ; SetCustomToken( 3677, GCacheString( dDB)); dDB. sVar = GetTag( oBBS)+ "#M" + sType + sNotice ; SetCustomToken( 3678, "\n" + GCacheString( dDB)); } void bbs_add_notice( object oBBS, string sPoster, string sTitle, string sMessage, string sDate, string sBBStag = "") { object oMod= GetModule(); struct MemDB dDB; dDB. sDB = "DB_BBS"; dDB. oChi = GetLocalObject( oMod, "DBI_READ"); dDB. oChs = GetLocalObject( oMod, "DBS_READ"); dDB. oDbi = GetLocalObject( oMod, "DBI_FIFO"); dDB. oDbs = GetLocalObject( oMod, "DBS_FIFO"); dDB. sVar = ""; dDB. nValue = 0; dDB. sValue = ""; if ( sBBStag != "") { oBBS = GetObjectByTag( sBBStag);} bbs_initiate( oBBS); oBBS = GetLocalObject( oMod, "BBS_" + GetTag( oBBS)); if ( sDate == "") { sDate = IntToString( GetTimeMinute()); if ( GetStringLength( sDate) == 1) { sDate = "0" + sDate;} sDate = IntToString( GetCalendarMonth()) + "/" + IntToString( GetCalendarDay()) + "/" + IntToString( GetCalendarYear()) + " " + IntToString( GetTimeHour()) + ":" + sDate; } string sType = GetLocalString( oBBS, "BBS_TYPE"); int MaxItems = GetLocalInt( oBBS, "MaxItems"); dDB. sVar = GetTag( oBBS)+ "#C" + sType ; int TotalItems = GCacheInt( dDB) ; int nSpot = TotalItems + 1; if ( nSpot > MaxItems) { dDB. sVar = GetTag( oBBS)+ "#L" + sType ; nSpot = GCacheInt( dDB) + 1 ; if ( nSpot > MaxItems) nSpot = nSpot - MaxItems; } dDB. sVar = GetTag( oBBS)+ "#P" + sType + IntToString( nSpot) ; dDB. sValue = sPoster ; SCacheString( dDB) ; dDB. sVar = GetTag( oBBS)+ "#D" + sType + IntToString( nSpot) ; dDB. sValue = sDate ; SCacheString( dDB) ; dDB. sVar = GetTag( oBBS)+ "#T" + sType + IntToString( nSpot) ; dDB. sValue = sTitle ; SCacheString( dDB) ; dDB. sVar = GetTag( oBBS)+ "#M" + sType + IntToString( nSpot) ; dDB. sValue = sMessage ; SCacheString( dDB) ; dDB. sVar = GetTag( oBBS)+ "#L" + sType ; dDB. nValue = nSpot ; SCacheInt( dDB) ; if ( MaxItems > TotalItems){ dDB. sVar = GetTag( oBBS)+ "#C" + sType ; dDB. nValue = TotalItems + 1 ; SCacheInt( dDB) ; } string sQuote = GetSubString( GetStringByStrRef( 464), 13, 1); } 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 :#include "x2_inc_switches"#include "x2_inc_restsys"#include "ly_lib_time"#include "bbs_lib_item"void main() { object oMod = GetModule() ; DelayCommand( 600.0, SignalEvent( OBJECT_SELF, EventUserDefined( 200))); object oDBI= GetObjectByTag( "DBI_FIFO"); object oDBS= GetObjectByTag( "DBS_FIFO"); object oCacheI= GetObjectByTag( "DBI_READ"); object oCacheS= GetObjectByTag( "DBS_READ"); if( GetIsObjectValid( oDBI) ){ WriteTimestampedLogEntry( "Successul get of DBI_FIFO object"); SetLocalObject( oMod, "DBI_FIFO", oDBI); } else { WriteTimestampedLogEntry( "Fatal Error : unable to get DBI_FIFO object"); EndGame( ""); } if( GetIsObjectValid( oDBS) ){ WriteTimestampedLogEntry( "Successul get of DBS_FIFO object"); SetLocalObject( oMod, "DBS_FIFO", oDBI); } else { WriteTimestampedLogEntry( "Fatal Error : unable to get DBS_FIFO object"); EndGame( ""); } if( GetIsObjectValid( oCacheI) ){ WriteTimestampedLogEntry( "Successul get of DBI_READ object"); SetLocalObject( oMod, "DBI_READ", oCacheI); } else { WriteTimestampedLogEntry( "Fatal Error : unable to get DBI_READ object"); EndGame( ""); } if( GetIsObjectValid( oCacheS) ){ WriteTimestampedLogEntry( "Successul get of DBS_READ object"); SetLocalObject( oMod, "DBS_READ", oCacheS); } else { WriteTimestampedLogEntry( "Fatal Error : unable to get DBS_READ object"); EndGame( ""); } struct MemDB dDB; dDB. sDB = "DATE_MODULE"; dDB. oChi = GetLocalObject( oMod, "DBI_READ"); dDB. oChs = GetLocalObject( oMod, "DBS_READ"); dDB. oDbi = GetLocalObject( oMod, "DBI_FIFO"); dDB. oDbs = GetLocalObject( oMod, "DBS_FIFO"); dDB. sVar = ""; dDB. nValue = 0; dDB. sValue = ""; int nCTY = GetCalendarYear() ; int nCTM = GetCalendarMonth() ; int nCTD = GetCalendarDay() ; int nTH = GetTimeHour(); int nTM = GetTimeMinute(); int nTS = GetTimeSecond(); int nAbsolDay = ly_day() ; int nCTime = ly_time() ; int iTM = GetCampaignInt( "DATE_MODULE", "MINUTE") ; int iTH = GetCampaignInt( "DATE_MODULE", "HEURE") ; int iCTD = GetCampaignInt( "DATE_MODULE", "JOUR") ; int iCTM = GetCampaignInt( "DATE_MODULE", "MOIS") ; int iCTY = GetCampaignInt( "DATE_MODULE", "ANNEE") ; int iRBOOT = GetCampaignInt( "DATE_MODULE", "NREBOOT") ; int iTOUR = GetCampaignInt( "DATE_MODULE", "NTOUR") ; if( iRBOOT== 0 ) { iTM = nTM; iTH = nTH ; iCTD = nCTD ; iCTM = nCTM ; iCTY = nCTY ; } DestroyCampaignDatabase( "DATE_MODULE"); dDB. sVar = "MINUTE" ; dDB. nValue = iTM ; SCacheInt( dDB) ; dDB. sVar = "HEURE" ; dDB. nValue = iTH ; SCacheInt( dDB) ; dDB. sVar = "JOUR" ; dDB. nValue = iCTD ; SCacheInt( dDB) ; dDB. sVar = "MOIS" ; dDB. nValue = iCTM ; SCacheInt( dDB) ; dDB. sVar = "ANNEE" ; dDB. nValue = iCTY ; SCacheInt( dDB) ; dDB. sVar = "NTOUR" ; dDB. nValue = iTOUR ; SCacheInt( dDB) ; dDB. sVar = "NREBOOT" ; dDB. nValue = iRBOOT+ 1 ; SCacheInt( dDB) ; SetTime( iTH, iTM, 0, 0) ; SetCalendar( iCTY, iCTM, iCTD) ; int iAbsolDay = ly_day() ; int iCTime = ly_time() ; WriteTimestampedLogEntry( "Module TN bouchon 2, version du 16-09-2005 et +"); WriteTimestampedLogEntry( ""+ IntToString( iRBOOT+ 1)); WriteTimestampedLogEntry( ""+ IntToString( iTOUR)); WriteTimestampedLogEntry( ""); WriteTimestampedLogEntry( ""); WriteTimestampedLogEntry( ""); WriteTimestampedLogEntry( "Date RP : lancement du monde le "+ IntToString( nCTD)+ " "+ IntToString( nCTM)+ " "+ IntToString( nCTY)); WriteTimestampedLogEntry( "Date RP : actuellement nous sommes le "+ IntToString( iCTD)+ " "+ IntToString( iCTM)+ " "+ IntToString( iCTY)); WriteTimestampedLogEntry( "Heure RP : il est "+ IntToString( iTH)+ ":"+ IntToString( iTM)); SetLocalInt( oMod, "StartDay", iAbsolDay) ; SetLocalInt( oMod, "StartTime", iCTime) ; } 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 :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 :#include "ly_lib_time"#include "bbs_lib_item"void main(){ object oMod = GetModule() ; switch ( GetUserDefinedEventNumber()) { case 200:{ DelayCommand( 600.0, SignalEvent( OBJECT_SELF, EventUserDefined( 200))); struct MemDB dDB; dDB. sDB = "DATE_MODULE"; dDB. oChi = GetLocalObject( oMod, "DBI_READ"); dDB. oChs = GetLocalObject( oMod, "DBS_READ"); dDB. oDbi = GetLocalObject( oMod, "DBI_FIFO"); dDB. oDbs = GetLocalObject( oMod, "DBS_FIFO"); dDB. sVar = ""; dDB. nValue = 0; dDB. sValue = ""; int iCTY = GetCalendarYear() ; int iCTM = GetCalendarMonth() ; int iCTD = GetCalendarDay() ; int iTH = GetTimeHour(); int iTM = GetTimeMinute(); int iTS = GetTimeSecond(); int iCDay = ly_day() ; int iCTime = ly_time() ; dDB. sVar = "NTOUR"; int iTOUR = GCacheInt( dDB) ; dDB. sVar = "MINUTE" ; dDB. nValue = iTM ; SCacheInt( dDB) ; dDB. sVar = "HEURE" ; dDB. nValue = iTH ; SCacheInt( dDB) ; dDB. sVar = "JOUR" ; dDB. nValue = iCTD ; SCacheInt( dDB) ; dDB. sVar = "MOIS" ; dDB. nValue = iCTM ; SCacheInt( dDB) ; dDB. sVar = "ANNEE" ; dDB. nValue = iCTY ; SCacheInt( dDB) ; dDB. sVar = "NTOUR" ; dDB. nValue = iTOUR+ 1 ; SCacheInt( dDB) ; ExportAllCharacters(); break; } case 600:{ ExecuteScript( "bbs_mod_dbcache", OBJECT_SELF) ; break ; } case 601:{ ExecuteScript( "bbs_mod_dbcachi", OBJECT_SELF) ; break ; } case 602:{ ExecuteScript( "bbs_mod_dbcachs", OBJECT_SELF) ; break ; } case 604:{ if( GetLocalInt( OBJECT_SELF, "DBIFLUSHED") && GetLocalInt( OBJECT_SELF, "DBSFLUSHED") ){ SendMessageToAllDMs( "DB Flush : completed."); WriteTimestampedLogEntry( "DB Flush : completed."); StartNewModule( "tnbouchon1609") ; } else{ SendMessageToAllDMs( "Waiting for DB Flush to complete..."); WriteTimestampedLogEntry( "Waiting for DB Flush to complete..."); DelayCommand( 2.0, SignalEvent( OBJECT_SELF, EventUserDefined( 604))); } 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.
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 :void main() { object oItem = GetItemActivated(); string sItemTag = GetTag( oItem); string sItemName = GetName( oItem); object oActivator = GetItemActivator(); object oTarget = GetItemActivatedTarget(); string sTargetTag = GetTag( GetItemActivatedTarget()); location lTargetLoc = GetItemActivatedTargetLocation(); object oMod = GetModule(); if( GetTag( oItem)== "RESTARTTN") { location lTarget = GetLocation( oTarget); effect eVis = EffectVisualEffect( VFX_FNF_TIME_STOP); effect eTime = EffectTimeStop(); SetLocalInt( oMod, "REBOOT", TRUE); SignalEvent( oMod, EventUserDefined( 200)); DelayCommand( 4.0 , SignalEvent( oMod, EventUserDefined( 600))) ; SignalEvent( oActivator, EventSpellCastAt( oActivator, SPELL_TIME_STOP, FALSE)); DelayCommand( 0.75, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, eTime, oActivator, 3.0)); object oPC= GetFirstPC() ; while( GetIsObjectValid( oPC) ){ ApplyEffectAtLocation( DURATION_TYPE_INSTANT, eVis, GetLocation( oPC)); SendMessageToPC( oPC, "REBOOT A CHAUD DU MODULE"); oPC = GetNextPC() ; } SignalEvent( oMod, EventUserDefined( 604)) ; 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.
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 :#include "bbs_lib_item"void main() { object oMod= GetModule(); struct MemDB dDB; dDB. sDB = ""; dDB. oChi = GetLocalObject( oMod, "DBI_READ"); dDB. oChs = GetLocalObject( oMod, "DBS_READ"); dDB. oDbi = GetLocalObject( oMod, "DBI_FIFO"); dDB. oDbs = GetLocalObject( oMod, "DBS_FIFO"); dDB. sVar = ""; dDB. nValue = 0; dDB. sValue = ""; int nModFCounter = GetLocalInt( dDB. oDbi, "FDBICNT") ; int nModWCounter = GetLocalInt( dDB. oDbi, "WDBICNT") ; if( nModWCounter > nModFCounter ){ SignalEvent( oMod, EventUserDefined( 601)); } else{ if( nModWCounter < nModFCounter ){ WriteTimestampedLogEntry( "DBI Cache Flush Error"); } else{ if( nModFCounter > 10000 ){ DeleteLocalInt( dDB. oDbi, "FDBICNT"); DeleteLocalInt( dDB. oDbi, "WDBICNT"); } } if( GetLocalInt( oMod, "REBOOT") ){ SetLocalInt( oMod, "DBIFLUSHED", TRUE); } } nModFCounter = GetLocalInt( dDB. oDbs, "FDBSCNT") ; nModWCounter = GetLocalInt( dDB. oDbs, "WDBSCNT") ; if( nModWCounter > nModFCounter ){ SignalEvent( oMod, EventUserDefined( 602)); } else{ if( nModWCounter < nModFCounter ){ WriteTimestampedLogEntry( "DBS Cache Flush Error"); } else{ if( nModFCounter > 10000 ){ DeleteLocalInt( dDB. oDbs, "FDBSCNT"); DeleteLocalInt( dDB. oDbs, "WDBSCNT"); } } if( GetLocalInt( oMod, "REBOOT") ){ SetLocalInt( oMod, "DBSFLUSHED", 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 :#include "bbs_lib_item"void main() { object oMod= GetModule(); struct MemDB dDB; dDB. sDB = ""; dDB. oChi = GetLocalObject( oMod, "DBI_READ"); dDB. oChs = GetLocalObject( oMod, "DBS_READ"); dDB. oDbi = GetLocalObject( oMod, "DBI_FIFO"); dDB. oDbs = GetLocalObject( oMod, "DBS_FIFO"); dDB. sVar = ""; dDB. nValue = 0; dDB. sValue = ""; int nModFCounter = GetLocalInt( dDB. oDbi, "FDBICNT") ; int nModWCounter = GetLocalInt( dDB. oDbi, "WDBICNT") ; if( nModWCounter > nModFCounter ){ nModFCounter++ ; SetLocalInt( dDB. oDbi, "FDBICNT", nModFCounter) ; string sDBCache = GetLocalString( dDB. oDbi, "IDBCACHE"+ IntToString( nModFCounter)) ; string sVARCache = GetLocalString( dDB. oDbi, "IVARCACHE"+ IntToString( nModFCounter)) ; int nVALUECache = GetLocalInt( dDB. oDbi, "IVALUECACHE"+ IntToString( nModFCounter)) ; DeleteLocalString( dDB. oDbi, "IDBCACHE"+ IntToString( nModFCounter)) ; DeleteLocalString( dDB. oDbi, "IVARCACHE"+ IntToString( nModFCounter)) ; DeleteLocalInt( dDB. oDbi, "IVALUECACHE"+ IntToString( nModFCounter)) ; SetCampaignInt( sDBCache, sVARCache, nVALUECache); if( nModWCounter != nModFCounter ){ if( GetLocalInt( oMod, "REBOOT") ){ SignalEvent( oMod, EventUserDefined( 601)); } else{ DelayCommand( 0.5, SignalEvent( oMod, EventUserDefined( 601))); } } else{ if( GetLocalInt( oMod, "REBOOT") ){ SetLocalInt( oMod, "DBIFLUSHED", 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 :#include "bbs_lib_item"void main() { object oMod= GetModule(); struct MemDB dDB; dDB. sDB = ""; dDB. oChi = GetLocalObject( oMod, "DBI_READ"); dDB. oChs = GetLocalObject( oMod, "DBS_READ"); dDB. oDbi = GetLocalObject( oMod, "DBI_FIFO"); dDB. oDbs = GetLocalObject( oMod, "DBS_FIFO"); dDB. sVar = ""; dDB. nValue = 0; dDB. sValue = ""; int nModFCounter = GetLocalInt( dDB. oDbs, "FDBSCNT") ; int nModWCounter = GetLocalInt( dDB. oDbs, "WDBSCNT") ; if( nModWCounter > nModFCounter ){ nModFCounter++ ; SetLocalInt( dDB. oDbs, "FDBSCNT", nModFCounter) ; string sDBCache = GetLocalString( dDB. oDbs, "SDBCACHE"+ IntToString( nModFCounter)) ; string sVARCache = GetLocalString( dDB. oDbs, "SVARCACHE"+ IntToString( nModFCounter)) ; string sVALUECache = GetLocalString( dDB. oDbs, "SVALUECACHE"+ IntToString( nModFCounter)) ; DeleteLocalString( dDB. oDbs, "SDBCACHE"+ IntToString( nModFCounter)) ; DeleteLocalString( dDB. oDbs, "SVARCACHE"+ IntToString( nModFCounter)) ; DeleteLocalString( dDB. oDbs, "SVALUECACHE"+ IntToString( nModFCounter)) ; SetCampaignString( sDBCache, sVARCache, sVALUECache); if( nModWCounter != nModFCounter ){ if( GetLocalInt( oMod, "REBOOT") ){ SignalEvent( oMod, EventUserDefined( 602)); } else{ DelayCommand( 0.5, SignalEvent( oMod, EventUserDefined( 602))); } } else{ if( GetLocalInt( oMod, "REBOOT") ){ SetLocalInt( oMod, "DBSFLUSHED", 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 :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.
Dernière édition par lylver le 06/04/2006 08:59:17; édité 2 fois
|
|
Revenir en haut |
|
|
BenGorre
Légende vivante
Inscrit le: 12 Fév 2004
Messages: 301
|
Posté le : 27/09/2005 17:07:38 Sujet du message :
Voici mon script pour enlever un effet visuel permanent qu'on a appliqué avant par script:
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.
Je pense qu'il sera utile a beaucoup de gens. Ce script permet d'ameliorer les haks qui utilise des vfx pour mettre des cornes, des yeux brillants et autres. _________________ La mort n'est rien seul le fait de mourir est terrible
Henry Fielding 1745
Le serveur Filandre a été stoppé pour le moment, je on travail à la conversion vers NWN2.
|
|
Revenir en haut |
|
|
Black Knight
Grand Maître Chanteur du Conseil
Inscrit le: 27 Oct 2005
Messages: 1031
Localisation: Fin fond du trou du cul du monde |
Posté le : 31/10/2005 13:19:56 Sujet du message :
Il a plein de personne (je pense) qui souhaiterais faire un "Black Smith"
# Qu'est ce qu'un BLACK SMITH ?
C'est un personnage qui sert de "marchand de creation". Donc faire par exemple un armure a votre gouts!
# Petit conseil
Prenez tout votre temps. Les scripts sont super simple mais faire tout monsieur Black Smith c'est super long (j'ai du mettre 2 semaines)
# Preparation
Faite deja un Waypoint la ou les joueurs ne pourrons pas voir l'objet (je vous expliquerais) et ou il ne peuvent surtout pas le prendre. (tag : WP_Craft)
Faite une armure lourde tagger = ArmureLourde et en Ref = armurel_craft
# Le Dialogue
Deja il faut créer un dialogue (le dialogue que je vais vous faire est de base!):
Rouge : Black smith
Bleue : PJ
Gris : Lien
Dialogue : (ne fait pour l'instant pas gaff au dialogue lisez le juste tout vous sera explique ensuite)
- Bienvenue que voulez vous créer ?
-- Une armure
--- Quel genere d'armure ?
---- Armure Lourde
----- Votre item coute : <CUSTOM2000>
------ [CONTINUER]
------- Que voulez vous ajoute ?
-------- Un bonnus d'armure
--------- De combien voulez vous ?
---------- +1
----------- J'ai ajuster ce que vous avez demendé
------ Créer l'objet
----- J'ai ajuster ce que vous avez demendé
------ Votre item coute : <CUSTOM2000>
Bon voila le dialogue.Nous allons evite les premiere lignes et nous allons regarde de plus pres la ligne : Armure Lourde
Ici vous devez ajoute ce petit script :
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.
Ce script vous permet :
1 => de creer l'objet (armure lourde) au Waypoint que je vous ai dit de creer
2 => D'enregistrer sur une local son nom avec comme base "Item"
La prochaine ligne est : Votre item coute : <CUSTOM2000>
Ici vous allez mettre le script suivant :
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.
Ce script vous permet :
1) De dire combien l'objet coute grace a custom 2000
Apres prochaine phrase : Un bonnus d'armure
(Ce script est a mettre dans le Condition de la phrase!
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.
Ce script vous permet :
1) D'evite a ce que le joueur puisse mettre plusieur bonnus d'armure (ce ne sera pas cumulable sinon (et de plus l'item coutera plus chere!))
Prochaine phrase : +1
Script a mettre :
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.
Ce script vous permet :
1) De mettre l'armure demendé en armure +1
AU CAS OU : si le joueur c'est tromper vous pouvez mettre une phrase "Retour" mais attention ne pas oublier de mettre a LocalInt a 0 !! Sinon le joueur se retrouvera "un peut idiot" si il voulez mettre +1 a la CA
Apres : J'ai ajuster ce que vous avez demendé
Vous mettez ce script :
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.
Ce script vous permet de :
1)Examiner l'objet en question (moi je doit avoir un bug sa ne s'examine pas, pourquoi ? il y a un bug ? si vous le trouvez merci de me le dire svp !)
Prochaine phrase : Créer l'objet
vous mettez ce script :
NWScript :void main() { object oPC = GetPCSpeaker(); DestroyObject( GetLocalObject( oPC, "Item")); int iGold = GetGold( oPC); int iPiece = GetGoldPieceValue( GetLocalObject( oPC, "Item")); if( iGold < iPiece) { FloatingTextStringOnCreature( "IMPOSSIBLE : Vous n'avez pas assez d'argent. Crafting arreter !\n(Votre or : "+ IntToString( iGold)+ "\nCoute : "+ IntToString( iPiece)+ "\nVous avez besoin de : "+ IntToString( abs( iPiece- iGold))+ ")", oPC); } else{ CopyItem( GetLocalObject( oPC, "Item"), oPC); TakeGoldFromCreature( GetGoldPieceValue( GetLocalObject( oPC, "Item")), oPC); } DeleteLocalObject( oPC, "Item"); SetLocalInt( oPC, "Armure", 0); } 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 script vous permet :
1) De detruire l'objet (regarde la suite pour plus d'expliquation)
2) De voir si le PJ a assez d'argent, si oui il creer l'objet en prenant l'argent necessaire
3) De detruire la LocalObject "Item"
4) De remettre le bonnus d'armure a 0 (la LocalInt "Armure")
Si le joueur souhaite tout stopper vous rajouter une phrase "Annuler" au moment ou le PNJ dit "Votre item coute : <CUSTOM2000>"
a mettre ceci comme script a l'interrieur :
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.
Ce script vous permet :
1) de detruire l'item
2) de detruire la LocalInt "Armure"
3) de detruire la LocalObject "Item"
# Info
-Un objet sera crée au Waypoint que je vous ai demendé de créer, ceci et pour que le blacksmith ajoute les proprietes dessus et dise cb il coute. Apres il a juste a faire une copie de celui ci et de detruire l'item.
-la LocalObject "Item" sert a ajoute TOUT sans faire des immences script, Black smith prend le tag de l'objet et le met dans une localobject, apres il ajuste tout sur cette local.
-Et une derniere chose je vous ai mis aussi la localobject pour que vous puissez faire des ccopier coller ! Voila les 2 phrase a copier coller en tant que lien :
Votre item coute : <CUSTOM2000>
J'ai ajuster ce que vous avez demendé
Apres dans les action des phrase commes Armure leger, Casque etc.. vous devez creer un Casque (par exemple) et remplace ce script :
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.
par celui la :
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.
Voila si vous avez des questions je suis dispo si vous savez comment resoudre mon probleme d'examination de l'objet je suis dispo aussi ! Allez bonne chance a vous (et oui vous devez faire TOUT le reste vous comprenez maintenant pk les 2 semaines loool)
|
|
Revenir en haut |
|
|
Black Knight
Grand Maître Chanteur du Conseil
Inscrit le: 27 Oct 2005
Messages: 1031
Localisation: Fin fond du trou du cul du monde |
Posté le : 02/11/2005 15:07:17 Sujet du message :
J'ai trouve mon p'tit bug pour l'examination, apparament sa serait du a cause d'une phrase direct :s voila comment il doit se presente :
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.
Voila ceci fera l'affaire
|
|
Revenir en haut |
|
|
|