Jump to content

Scripting Woes


EiriktheScald

Recommended Posts

Eirik's script is as follows,

IF
!InParty(Myself)
Global("ESTalkedToWolf","GLOBAL",0) //ensures that it only plays once
AreaCheck("FW2800")
See([PC])
THEN
RESPONSE #100
	SetGlobal("ESTalkedToWolf","GLOBAL",1)
	PlaySound("esWolf")
	MoveViewObject(Myself,INSTANT)
	CreateCreature("WOLF01",1345.200,0) // Wolf
	ActionOverride("WOLF01",ChangeAIScript("None",RACE))
	DisplayString(Myself,@1)
	ActionOverride("WOLF01",MoveToPoint(1565.200))
	DisplayString(Myself,@2)
	ActionOverride("WOLF01",Attack("Eirik"))
END

IF
Dead("WOLF01") // Wolf
See([PC])
NumTimesTalkedTo(0)
THEN
RESPONSE #100
	StartDialogueNoSet([PC])
END

IF
!Dead("WOLF01") // Wolf
See("WOLF01")
Detect([PC])
THEN
RESPONSE #100
	AttackNoSound("WOLF01")
	Wait(1)
	Kill("WOLF01")
END

 

It plays the sound and even spawns the wolf. Eirik says both dialogs on cue; but then we all just stand there looking at each other. What an awkward moment! The wolf still standing where it was spawned. What's wrong with this script? :)

Link to comment

You are creating a creature, but in order for it to follow commands (and a script), it needs to have a DV. Wolves don't have them. There are a number of ways you can go about this.

 

You can copy a wolf over, assign it a new cre and DV, and maybe it's own script, or you can assign all wolves the same DV and include an area check for any assigned behavior. Tell me which you want to do, and I'll give you a few hints about doing it.

Link to comment

COPY_EXISTING ~wolf01.cre~ ~override/eswolf01.cre~
 WRITE_ASCII 0x280 ~eswolf~

 

CreateCreature("esWOLF01",[1345.200],0) // Wolf

ActionOverride("esWOLF",MoveToPoint([1565.200]))

 

CreatureCreature uses the resource reference/file name, but most scripting commands require the scripting name/death variable.

 

/edit

 

Too slow by half :)

Link to comment

No, which is why you're going to make a unique CRE and spawn that one instead of just a generic wolf. This one will have its own DV and everything, and since you're assigning sounds to it, you can even give it its own howl, if you like.

 

I'm doing this to create a messenger for Gavin's quest. Essentially, I'm just copying the CRE for a servant, renaming it, giving it a DV, a script, and a dialogue file, and that's about it. Then, when I want to spawn the messenger, I just spawn my custom CRE, and I don't have to worry about doing anything to every servant in BG.

 

This is from my tp2:

COPY_EXISTING ~_SERVAN.CRE~ ~override/B!MESNGR.CRE~
SAY NAME1 ~Temple Messenger~
SAY NAME2 ~Temple Messenger~
WRITE_ASCII 0x248 ~B!MESNGR~ #8 // override
WRITE_ASCII 0x2cc ~B!MESNGR~ #8 // dialogue
SAY INITIAL_MEETING ~[MALE GREETING 5] Hello there.~ [_GENMG05]
SAY DAMAGE ~[MALE TOWNSFOLK 5]~ [_VILLM05]
SAY DYING ~[MALE TOWNSFOLK 6]~ [_MTOWN06]
SAY SELECT_COMMON1 ~[MALE GREETING 5] Hello there.~ [_GENMG05]
SAY DIALOG_DEFAULT ~[MALE GREETING 5] Hello there.~ [_GENMG05]

 

A DV is a death variable. I don't know how it got that name. It's a label that identifies the actor as something that can carry out actions. That is what is used when you do See("DV"), Attack("DV"), !StateCheck("DV",STATE_SLEEPING), etc. About the only time you actually use the CRE name is during spawning.

Link to comment

OK--taking it slowly:

 

COPY_EXISTING ~_SERVAN.CRE~ ~override/B!MESNGR.CRE~

 

/* copies the CRE _servan.cre to the override directory and renames it b!mesngr.cre. I do this so that I don't have to make any changes to the original _servan.cre. When I spawn the messenger, I will spawn "B!MESNGR". */

 

SAY NAME1 ~Temple Messenger~

SAY NAME2 ~Temple Messenger~

 

/* Naming the CRE. This is what will show up in dialogue (for the first Name, I think), and when you hover the pointer over the cre (for the second Name, I think). In any case, you need both of them. */

 

WRITE_ASCII 0x248 ~B!MESNGR~ #8 // override

 

/* Assigns an override script to the creature I just created. The hex offset is 0x248, and the field is 8 characters long. */

 

WRITE_ASCII 0x2cc ~B!MESNGR~ #8 // dialogue

 

/* Assigns a dialogue file to the creature I just created. The hex offset is 0x2cc, and the field is 8 characters long. */

 

SAY INITIAL_MEETING ~[MALE GREETING 5] Hello there.~ [_GENMG05]

 

/* Assigns a sound for the first time it speaks. */

 

SAY DAMAGE ~[MALE TOWNSFOLK 5]~ [_VILLM05]

 

/* Assigns a sound for use if it takes damage. */

 

SAY DYING ~[MALE TOWNSFOLK 6]~ [_MTOWN06]

 

/* Assigns its last words, or in this case, a grunt. */

 

SAY SELECT_COMMON1 ~[MALE GREETING 5] Hello there.~ [_GENMG05]

 

/* Assigns a sound for if you click on it. */

 

SAY DIALOG_DEFAULT ~[MALE GREETING 5] Hello there.~ [_GENMG05]

 

/* When it speaks, it will use this sound. */

Link to comment
@Nythrun: esWolf01 is a creature file I create with a DV?

 

@berelinde: You lost me after the first three lines of code! Where are you assigning a DV?

 

[Edit:] Okay, looking at both of your examples, it must be

 

WRITE_ASCII 0x280

 

that assigns a DV. Correct?

 

Yes. This field is 32 bytes in length, so you may specifiy WRITE_ASCII 0x280 ~eswolf~ #32 (though it won't matter in this case). IEDSP is the offset encyclopedia, as always :)

 

eswolf01 would be a creature file that you make by renaming an existing creature, yes...much less work than building one from scratch :)

Link to comment

There are a few things still not ironed out.

 

Script

IF
!InParty(Myself)
Global("ESTalkedToWolf","GLOBAL",0) //ensures that it only plays once
AreaCheck("FW2800")
See([PC])
THEN
RESPONSE #100
	SetGlobal("ESTalkedToWolf","GLOBAL",1)
	PlaySound("esWolf")
	CreateCreature("esWOLF01",[1550.30],0) // Wolf
	MoveToOffset([0.5])
	Face(0)
	StartDialogueNoSet([PC])
	ActionOverride("eswolf",MoveToPoint([1785.200]))
	ActionOverride("eswolf",Face(0)
	Face(8)
	DisplayString(Myself,@2)
	ActionOverride("esWOLF",Attack("ESEIRIK"))
	Attack("esWOLF")
	Wait(1)
	Kill("esWOLF")
END

IF
Dead("esWOLF") // Wolf
See([PC])
NumTimesTalkedTo(1)
THEN
RESPONSE #100
	StartDialogueNoSet([PC])
END

 

Dialogue

BEGIN ~ESEIRIK~

// Encounter dialogue
IF ~NumTimesTalkedTo(0)~ THEN BEGIN esPCChat0.0
SAY @1
IF ~~ THEN EXIT
END

// Join dialogue
IF ~NumTimesTalkedTo(1)~ THEN BEGIN Chat1.0
SAY @5000
IF ~~ THEN REPLY @5001 GOTO Chat1.1
IF ~~ THEN REPLY @5002 GOTO Chat1.2
IF ~~ THEN REPLY @5003 GOTO Chat1.6
IF ~~ THEN REPLY @5004 GOTO Chat1.9
END

 

Everything works right up until 'DisplayString(Myself,@2)'. Nothing else happens.

Link to comment

How can you have any further action in a script block once you've had a dialogue begin?

 

I'd break down the first block and change the second.

 

IF
!InParty(Myself)
Global("ESTalkedToWolf","GLOBAL",0) //ensures that it only plays once
AreaCheck("FW2800")
See([PC])
THEN
RESPONSE #100
	SetGlobal("ESTalkedToWolf","GLOBAL",1)
	PlaySound("esWolf")
	CreateCreature("esWOLF01",[1550.30],0) // Wolf
	MoveToOffset([0.5])
	Face(0)
	StartDialogueNoSet([PC])
	ActionOverride("eswolf",MoveToPoint([1785.200]))
	ActionOverride("eswolf",Face(0)
	Face(8)
	DisplayString(Myself,@2)
	ActionOverride("esWOLF",Attack("ESEIRIK"))
	Attack("esWOLF")
	Wait(1)
	Kill("esWOLF")
END

IF
Dead("esWOLF") // Wolf
See([PC])
NumTimesTalkedTo(1)
THEN
RESPONSE #100
	StartDialogueNoSet([PC])
END

 

Here is some code that might work a little better, but I'm no expert on this kind of thing.

 

IF
!InParty(Myself)
Global("ESTalkedToWolf","GLOBAL",0) //ensures that it only plays once
AreaCheck("FW2800")
See([PC])
THEN
RESPONSE #100
	SetGlobal("ESTalkedToWolf","GLOBAL",1)
	PlaySound("esWolf")
	CreateCreature("esWOLF01",[1550.30],0) // Wolf
	MoveToOffset([0.5])
	Face(0)
	StartDialogueNoSet(Player1)
END

 

Your first block of dialogue would become:

BEGIN ~ESEIRIK~

// Encounter dialogue
IF ~NumTimesTalkedTo(0)~ THEN BEGIN esPCChat0.0
SAY @1
IF ~~ THEN DO ~SetGlobal("ESContinueMeeting","GLOBAL",1)~ EXIT
END

 

And now, you can pick up where you left off with the wolf:

 

IF
 Global("ESContinueMeeting","GLOBAL",1)
 !Dead("esWOLF") //that is your DV, right?
THEN
RESPONSE #100
	ActionOverride("esWOLF",MoveToPoint([1785.200]))
	ActionOverride("esWOLF",Face(0)) //You had a closing parenthesis missing, which might have caused some trouble, but you've got a long sequence of events here, and you might need to break it up some more.
	SetGlobal("ESContinueMeeting","GLOBAL",2)
END

IF
 Global("ESContinueMeeting","GLOBAL",2)
THEN
RESPONSE #100
	SetGlobal("ESContinueMeeting","GLOBAL",3)
	Face(8)
	DisplayString(Myself,@2)
	ActionOverride("esWOLF",Attack("ESEIRIK")) //Don't know if that's going to work. I've never tried targetting using a DV before.
	Attack("esWOLF")
	Wait(1)
	Kill("esWOLF")
END

 

I doubt this part gives you trouble.

IF
Dead("esWOLF") // Wolf
See([PC])
NumTimesTalkedToGT(0)
THEN
RESPONSE #100
	StartDialogueNoSet(Player1)
END

Link to comment

Finally, a working script! Thanks to all who helped. :) I'll post some screenshots later.

 

IF
!InParty(Myself)
Global("ESEncounterWolf","GLOBAL",0) //ensures that it only plays once
AreaCheck("FW2800")
See([PC])
THEN
RESPONSE #100
	SetGlobal("ESEncounterWolf","GLOBAL",1)
	PlaySound("esWolf")
	MoveToOffset([0.5])
MoveViewObject(Myself,INSTANT)
	FaceObject(Player1)
	StartDialogueNoSet(Player1)
END

IF
Global("ESEncounterWolf","GLOBAL",2)
THEN
RESPONSE #100
	SetGlobal("ESEncounterWolf","GLOBAL",3)
CreateCreature("esWOLF01",[1540.40],0) // Wolf
ActionOverride("esWOLF",MoveToPoint([1715.140]))
Wait(2)
ActionOverride("esWOLF",FaceObject("ESEIRIK"))
PlaySound("WOLFF03")
	FaceObject("esWOLF")
Wait(2)
	StartDialogueNoSet("esWOLF")
END

IF
Global("ESEncounterWolf","GLOBAL",4)
THEN
RESPONSE #100
RealSetGlobalTimer("ESWolfAttacks","GLOBAL",15)
	ActionOverride("esWOLF",Attack("ESEIRIK"))
AttackOneRound("esWOLF")
Continue()
END

IF
Dead("esWOLF") // Wolf
See([PC])
NumTimesTalkedTo(2)
THEN
RESPONSE #100
	FaceObject([PC])
	Wait(2)
	StartDialogueNoSet([PC])
END

IF
	GlobalTimerExpired("ESWolfAttacks","GLOBAL")
!Dead("esWOLF") // Wolf
See("esWOLF")
Detect([PC])
THEN
RESPONSE #100
	Kill("esWOLF")
END

 

And the dialog:

BEGIN ~ESEIRIK~

// Wolf encounter dialogue
IF ~NumTimesTalkedTo(0)~ THEN BEGIN Chat0.1
SAY @1
IF ~~ THEN DO ~SetGlobal("ESEncounterWolf","GLOBAL",2)~ EXIT
END

IF ~NumTimesTalkedTo(1)~ THEN BEGIN Chat0.2
SAY @2
IF ~~ THEN DO ~SetGlobal("ESEncounterWolf","GLOBAL",4)~ EXIT
END

// Join dialogue
IF ~NumTimesTalkedTo(2)~ THEN BEGIN Chat1.0
SAY @5000
IF ~~ THEN REPLY @5001 GOTO Chat1.1
IF ~~ THEN REPLY @5002 GOTO Chat1.2
IF ~~ THEN REPLY @5003 GOTO Chat1.6
IF ~~ THEN REPLY @5004 GOTO Chat1.9
END

Link to comment

As long as it's working for you.

 

Just a couple things: are you really having Eirik start dialogue with the wolf? How's that working out?

 

And you might want to change the StartDialogueNoSet([PC]) to StartDialogueNoSet(Player1). I don't imagine that [PC] is going to work out really well in multi-player mode. In general, if the engine can't figure out what to do, it chokes.

Link to comment
And you might want to change the StartDialogueNoSet([PC]) to StartDialogueNoSet(Player1). I don't imagine that [PC] is going to work out really well in multi-player mode. In general, if the engine can't figure out what to do, it chokes.
This will work fine. Specs are evaluated as the nearest visible object of type, so in this case, StartDialogueNoSet([2]) is going to pick the nearest actor of allegiance PC that is within visual range, is visible, and is alive (and since he has a See() trigger, there's always going to be a valid object).
Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...