Masteriser Neverwinter Nights (MNWN)
Prélude - Partie 2
Navigation dans la série :
Table des matières :
Vue du Module
5. Salles d'entraînement : Olgerd
Olgerd, croyez-le ou non, est une version modifiée du bon vieux
Pavel. Bien, son script onHeartBeat est m1q0apavel_1, et son évènement OnPerception
est m1q0apavel_2.
^^^^^^^^^^^^^^^^^^^^
Script: m1q0apavel_1
^^^^^^^^^^^^^^^^^^^^
void main()
{
object oPC =
GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,
PLAYER_CHAR_IS_PC,
OBJECT_SELF,
1,
CREATURE_TYPE_PERCEPTION,
PERCEPTION_SEEN);
if(GetLocalInt(
OBJECT_SELF,"NW_L_CallingOut") &&
GetIsObjectValid(oPC)
&&
IsInConversation(oPC) ==
FALSE &&
GetLocalInt(GetModule(),
"NW_PROLOGUE_PLOT") < 99 )
{
if(GetLocalInt(
OBJECT_SELF,"NW_L_HBCount") >
2)
{
SpeakOneLinerConversation();
SetLocalInt(
OBJECT_SELF,"NW_L_HBCount",
0);
}
else
{
SetLocalInt(
OBJECT_SELF,"NW_L_HBCount",
GetLocalInt
(OBJECT_SELF,
"NW_L_HBCount") + 1);
}
}
}
~~~~~~~~~~~~~~~~~~~~
En bref, à chaque heartbeat, Olgerd regarde qui est le
PJ le plus proche. Si le NW_L_CallOut d'Olgerd est à TRUE, et si le
PJ n'est pas en conversation, Olgerd dira une réplique d'une ligne
(one liner) (encore une fois, comme nous l'avons vu précédemment,
une vérification ultérieure ou une incrémentation du
NW_L_HBCount d'Olgerd est effectuée pour qu'Olgerd dise son one liner
tous les 3 heartbeats). (C'est ainsi que vous pouvez faire rapidement une
boîte magique si jamais vous le vouliez.) Ensuite on signale alentour
que l'on a été dérangé, des fois que ça
intéresse quelqu'un.
^^^^^^^^^^^^^^^^^^^^
Script: m1q0apavel_2
^^^^^^^^^^^^^^^^^^^^
void main()
{
if(GetIsPC(
GetLastPerceived()) &&
GetLocalInt(GetModule(),
"NW_PROLOGUE_PLOT") < 99)
{
SetLocalInt(OBJECT_SELF,
"NW_L_CallingOut",TRUE);
}
}
^^^^^^^^^^^^^^^^^^^^
Dans ce cas, à moins d'avoir NW_PROLOGUE_PLOT à 99 ou plus, NW_L_CallOut
prend la valeur TRUE. Plutôt simple. Le dialogue d'Olgerd est plutôt linéaire,
si vous avez suivi notre section sur Bim. Il vous conduit à travers un tutorial
sur les marchands, rien d'impressionnant. Cependant, en regardant attentivement
son dialogue, on trouve quelques petites choses sympas. Une information intéressante
concernant le dialogue d'Olgerd est qu'il interagit avec la porte "M0Q0_DOOR2"
pour vous laisser sortir de la pièce.
Le dialogue d'Olgerd nous fait aussi découvrir la fonction SetPanelButtonFlash.
Olgerd y fait appel lorqu'il nous montre comment accéder à notre inventaire.
L'aide Bioware pour cette fonction dit :
void SetPanelButtonFlash(
object oPlayer, int
nButton, int nEnableFlash)
Vos options pour le paramètre PANEL_BUTTON_* sont (au cas où vous
auriez besoin de le savoir) : _CHARACTER, _INVENTORY, _JOURNAL, _MAP, _OPTIONS,
_PLAYER_VERSUS_PLAYER, _REST, _SPELLS. Enfin, Olgerd nous montre comment créer
un objet en fonction de notre classe.
^^^^^^^^^^^^^^^^^^^^^^^^
Script: m1q0bolgred_item
^^^^^^^^^^^^^^^^^^^^^^^^
void main()
{
string sItemTemplate;
object oPC =
GetPCSpeaker();
if(GetLocalInt(
oPC,"NW_L_M1Q0Item1") ==
FALSE)
{
SetLocalInt(oPC,
"NW_L_M1Q0Item1",TRUE);
if(GetLevelByClass(
CLASS_TYPE_BARD,oPC) >
0 ||
GetLevelByClass(
CLASS_TYPE_DRUID,oPC) >
0 ||
GetLevelByClass(
CLASS_TYPE_ROGUE,oPC) >
0)
{
sItemTemplate =
"nw_aarcl002"; }
else if(
GetLevelByClass(CLASS_TYPE_SORCERER,
oPC) > 0 ||
GetLevelByClass(
CLASS_TYPE_WIZARD,oPC) >
0)
{
sItemTemplate =
"nw_mcloth009"; }
else if(
GetLevelByClass(CLASS_TYPE_MONK,
oPC) > 0)
{
sItemTemplate =
"nw_mcloth018";
}
else
{
sItemTemplate =
"nw_aarcl012"; }
object oItem =
CreateItemOnObject(sItemTemplate,
oPC);
SetIdentified(oItem,
TRUE);
}
}
^^^^^^^^^^^^^^^^^^^^^^^^
Ce script fonctionne avec la variable NW_L_M1Q0Item1 disposée
sur le PJ pour empêcher les PJs d'exploiter ce dialogue et d'obtenir une tonne
d'objets gratuitement. Ensuite le script regarde le GetLevelByClass pour voir
si le PJ a au moins le niveau 1 dans les différentes classes. La chaîne de
caractère variable sItemTemplate est alors définie en fonction de la classe
dans laquelle vous avez un niveau, puis elle est utilisée pour CreatItemOnObject
(l'"objet" est le PJ dans le cas présent). Juste pour aider un peu, l'objet
est automatiquement identifé pour nous.
6. Salles d'entraînement : Herban
Laissant Olgerd derrière vous, vous entrez dans une grande pièce
de la salle d'entraînement. Le premier PNJ que vous devriez rencontrer est
Herban. Les scripts d'Herban sont tous vides, ce qui est suffisamment intéressant.
Son comportement est en gros déterminé par son arbre de dialogue (m0q01a05herb),
donc si vous n'interagissez pas avec lui, il n'interagira pas avec vous. L'arbre
de dialogue d'Herban a quatre branches principales à partir de la racine...
décevant, puisque deux d'entre elles sont des one liners, mais les deux autres
cachent des dialogues plutôt étendus. Herban vous montre comment accéder au
menu radial et aux aptitudes spécifiques de classes. Plutôt linéaire.
7. Salles d'entraînement
: Dendy et ses mannequins d'entraînement
Après avoir parlé à Herban, vous devriez remarquer un mannequin
d'entraînement du côté (de l'autre côté de la pièce pour être précis) de l'endroit
où Dendy s'exerce. Dendy n'a que les scripts suivants de définis :
• OnDamaged : m1q0bdendy_5
• OnHeartBeat : m1q0bdendy_4
• OnPhysicalAttacked : m1q0bdendy_4
Reagardons le script de l'évènement HeartBeat, ok ?
^^^^^^^^^^^^^^^^^^^^
Script: m1q0bdendy_5
^^^^^^^^^^^^^^^^^^^^
void main()
{
object oAttacker =
GetLastAttacker();
if(GetWeaponRanged(
GetLastWeaponUsed(oAttacker)) ==
FALSE)
{
SetLocalInt(OBJECT_SELF,
"Generic_Surrender",1);
object oTarget =
GetFirstObjectInShape(SHAPE_SPHERE,
RADIUS_SIZE_HUGE,
GetLocation(
OBJECT_SELF));
while(GetIsObjectValid(
oTarget))
{
if(oTarget !=
OBJECT_SELF)
{
if(
GetIsEnemy(oTarget))
{
AdjustReputation(
oTarget, OBJECT_SELF,
50);
ClearPersonalReputation(
oTarget);
SetIsTemporaryFriend(
oTarget);
}
AssignCommand(
oTarget, ClearAllActions());
AssignCommand(
oTarget,ActionAttack(
OBJECT_INVALID));
}
oTarget =
GetNextObjectInShape(SHAPE_SPHERE,
RADIUS_SIZE_HUGE,
GetLocation(OBJECT_SELF));
}
ClearAllActions();
if(GetLocalInt(
GetModule(),"NW_G_M0Q01_FIGHTER_TEST")
> 0)
{
if(GetLevelByClass(
CLASS_TYPE_BARBARIAN,oAttacker) >
0 ||
GetLevelByClass(
CLASS_TYPE_BARD,oAttacker) >
0 ||
GetLevelByClass(
CLASS_TYPE_FIGHTER,oAttacker) >
0 ||
GetLevelByClass(
CLASS_TYPE_MONK,oAttacker) >
0 ||
GetLevelByClass(
CLASS_TYPE_PALADIN,oAttacker) >
0 ||
GetLevelByClass(
CLASS_TYPE_RANGER,oAttacker) >
0 )
{
SetLocalInt(
GetModule(),"NW_G_M1Q0BMelee",
TRUE);
if(
GetLocalInt(GetModule(),
"NW_G_M1Q0BRanged"))
{
SetLocalInt(
GetModule(),
"NW_G_M0Q01_FIGHTER_TEST",2);
}
}
else
{
SetLocalInt(
GetModule(),
"NW_G_M0Q01_NONFIGHTER_PASS2",TRUE);
}
}
SpeakOneLinerConversation();
}
}
^^^^^^^^^^^^^^^^^^^^
Ce script agit en fait lorsque vous blessez Dendy avec une arme
de mêlée. La première boucle while tourne sur tous les
objets dans une sphère de rayon RADIUS_SIZE_HUGE centrée sur
Dendy, et en gros annule les relations entre Dendy et ces objets, au cas où
votre attaque en ferait un ennemi. Ensuite si Herban vous avait demandé
d'effectuer le test des guerriers, la variable NW_G_M1Q0BMelee du module prend
la valeur TRUE. De plus, si la variable NW_G_M1Q0BRange du module vaut TRUE,
alors la vraiable NW_G_M0Q01_FIGHTER_TEST prend la valeur 2. L'autre possibilité
est que vous n'ayez pas à passer le test de guerrier, et dans ce cas,
NW_G_M0Q01_NONFIGHTER_PASS2 prend la valeur TRUE.
Dans tous les cas, si vous blessez Dendy, il dira un one liner de son arbre de dialogue :
un autre jukebox pour ceux d'entre vous à tendances violentes. Maintenant, jetons un oeil au dialogue de
Dendy : m0q01a05dend. Si la variable NW_G_M0Q01_FIGHTER_TEST vaut 1, vous entrez dans la branche du dialogue
qui peut vous mener à tester vos "compétences" sur Dendy. Il se mettra en mode parade(vous vous souvenez de
la ligne ActionUseSkill dans son évènement Heartbeat ? il fait la même chose ici). Notez comment ça marche :
le dialogue met Dendy en mode parade. Ensuit vous l'attaquez. Quand finalement vous le blessez, le script
onDamaged examiné ci-dessus rentre en action, supprimant tout problème relationnel entre lui et vous, et
menant à l'appel de SpeakOneLinerConversation. Ca siginifie que vous réentrez dans le dialogue (mais le
script onDamaged aura modifié certaines variables en fonction de vos caractéristiques). A la fin de ce
test, Dendy vous indique Hewwet.
Une remarque concernant le mannequin à proximité est nécessaire. En fait, dendy vous laisse
le choix de l'attaquer lui ou le manneaquin pour passer le test de combat. Le comportement du mannequin est
déterminé par deux scripts associés à trois évènements sur lui :
• OnDeath :
m0q0_chest_05_7
• OnPhysicalAttacked : patchnoattack
• OnSpellCastAt : patchnoattack
Le script m0q0_chest_05_7 fait en gros le même chose que
le script onDamaged de Dendy. Bien sûr, il n'y a aucun lien avec la
réputation ou autre, mais ça définit de la même
manière la variable utilisée pour déterminer si vous
avez ou non accompli le test, et fait dire à Dendy une conversation
one liner de même. L'autre script sur le mannequin est déroutant
:
^^^^^^^^^^^^^^^^^^^^^
Script: patchnoattack
^^^^^^^^^^^^^^^^^^^^^
void main()
{
object oPC =
GetLastAttacker();
SetIsTemporaryFriend(oPC,
OBJECT_SELF,FALSE,
0.001);
DelayCommand(0.001,
SetIsTemporaryEnemy(oPC));
}
^^^^^^^^^^^^^^^^^^^^^
Euh... ok, le script traite de la répitation et des amis et ennemis temporaires... bien.
Mais... le commentaire !
?? Avant que ce script ne soit ajouté, (le préfixe patch- indique que ce n'était pas
dans la première version du jeu, développement compris), les mannequins "attaquaient" en retour s'ils
étaient endommagés ? Je suis tenté de l'enlever, recompiler, et adminrer la scène...
^^^^^^^^^^^^^^^^^^^^^^^
Script: m0q01a01bimsck9
^^^^^^^^^^^^^^^^^^^^^^^
int StartingConditional()
{
object oPC =
GetLocalObject(OBJECT_SELF,
"NW_L_CurrentPC");
int bCondition =
GetLocalInt(OBJECT_SELF,
"NW_L_TALKLEVEL") == 4 &&
GetLocalInt(GetPCSpeaker(),
"NW_L_M1Q0Rested")
== FALSE;
return bCondition;
}
^^^^^^^^^^^^^^^^^^^^^^^
8. Salles d'entraînement : Hewwet et son
mannequin d'entraînement
Donc, vous avez parlé à Herban et passé le test de mêlée avec Dendy ou son mannequin.
Maintenant vous allez vers Hewwet pour vous exercer à utiliser une arme à distance. Hewwet n'a aucun
script associé à ses différents évènements. Encore une fois, l'interaction avec lui sera dirigée par
le dialogue. Le dialogue de Hewwet s'appelle m0q01a05heww. Il est très semblable, au moins en structure,
à celui de Dendy. il contient une branche avec un one-liner dans le milieu qui est utilisée lorsque vous
tirez sur (et touchez) le mannequin de trop près (juste un peu de piquant je pense). A la fin du test,
si vous n'avez pas encore passé le test de Dendy, il vous enverra vers lui.
Bon, vous ne pouvez pas tirer sur Hewwet comme vous pouviez attaquer Dendy, mais votre
test d'arme à distance requiert que vous touchiez la cible voisine. La cible... ah, c'est en réalité un
True Neutral Construct de niveau 1 (donc je suppose qu'elle pourrait s'animer et vous embrasser en retour).
Quoi qu'on en dise... cette cible que Bioware décrit comme "une simple cible d'archer" a les compétences
Weapon Proficiency (creature) et Darkvision ! A ce niveau là, je suis surpris qu'elle ne connaisse pas de
sorts ! Quoiqu'il en soit, le seul script associé à la cible se trouve dans son évènement onDamaged : le
script m0q0_archery_2. Le script est semblable à ce que fait le mannequin de Dendy avec son évènement
onDeath, mais, bien sûr, définit les variables du test des armes à distance. La cible a même un arbre
de dialogue, constitué d'un simple noeud qui dit "*Thunk*". Ah... le souci et l'intérêt de Bioware pour
les détails... c'est admirable.
Une dernière remarque à propos de Hewwet : il y a un support d'armes à côté de lui. Ce
support d'armes a un inventaire et l'inventaire est défini pour inclure un ensemble d'armes à distance,
donc si vous n'avez pas encore de fronde ou d'arbalète, servez-vous.
9. Salles d'entraînement : Erdan
Dans la même pièce que dendyn Hewwet et Herban, vous pouvez voir Erdan, s'entraînant dans
son armure dorée. Le comportement d'Erdan est déterminé par les scripts suivants :
• OnPerception : m1q0bstud_2
• OnUserDefined : m1q0bstud_d
Le script m1q0bstud_2 pour l'évènement onPerception vérifie seulement si l'objet perçu
est un PJ, et si c'est le cas, lance l'évènement User Defined #200 avec la ligne suivante (au cas où vous
n'auriez jamais vu comm