cmorgan Posted April 24, 2006 Share Posted April 24, 2006 Hello - Domi has been kind enough to allow me to apprentice code on a small section of her work. Most of the quest I have been able to research, ask generic confirmation questions on forums, or copy from others examples. Unfortunately, this one section is way beyond anything I have examples for: OUTLINE: 2 days after a previous encounter, Winski teleports onto the party wherever they are and initiates dialogue. Several options - the hard one to code is the "conflict" result: Winski summons 1 mephit for every partymember except player 1, and a killable but non-hostile Imp for the PC. Winski disappears, leaving the fighting to the summons - the Imp begins to cast a spell. If the Imp is killed, the spell stops, and the party talks about the encounter. If the Imp is not killed in time, Dynaheir (and if InParty("Minsc") are ("Dynaheir",DRYAD_TELEPORT) toast. REQUEST FOR ASSISTANCE: Encounter forced after a global timer expires, wherever the party is (triggered from which one of the _DYNAH .BCS?). Actor summoned onto party, dialogue, then IF ~~ DYQU5W5.1 SAY ~Here, creatures, get the dark woman for your master. Kill everyone, but her and the boy.~ IF ~~ THEN DO ~SetGlobal("DYQUImpAttack","GLOBAL",1) // I can add in here: ReallyForceSpell("WINSKI",DRYAD_TELEPORT)~ EXIT END I think I can use CreateCreatureObjectOffset("X#MEPHT1",Player1,[100.100]) started at neutral, then ActionOverride to Enemy and Move to Player1 after Winski exits to bring on the heat, but now comes the hard part -- >> as many mephits are summoned as there are party members - 1 and an Imp. Wow, how do I A. count players, B. subtract 1, and C. summon that variable # of .cres? >>Imp is not hostile OK, got that one - use the tp2 to set the allegiance to neutral - but how do I keep him neutral while being attacked? This is a "it's concentrating on casting, can't be intterrupted by party until killed" kind of thing. >>and one of the mephits protects the Imp. ?? The big one, and I have absolutely no clue as to what to research/learn to do this: The Imp casts (DisplayStringHead, probably one line every 5 sec,. possibly voiced lines) and if he is not killed by then - Dynaheir is taken away. The Imp's Spell: ~line1 line2 line3 line4 line5 line6 line7 line8 line9 line10 line11 line12~ then ONLY if the imp is not killed, do ReallyForceSpell("Dynaheir",DRYAD_TELEPORT) and InParty("Minsc") ReallyForceSpell("Minsc",DRYAD_TELEPORT) ELSE EXIT Any help on what to research/learn to do this, I would truly appreciate! I am hoping to have a first draft of the completed work for her by the time she gets back in May. Link to comment
cmorgan Posted April 26, 2006 Author Share Posted April 26, 2006 You remove the part of the script that causes the CRE to go hostile when attacked. It may look like this: IF AttackedBy([GOODCUTOFF],DEFAULT) Allegiance(Myself,NEUTRAL) THEN RESPONSE #100  Enemy() END are Echon's suggestion from PPG; Avenger_teambg suggests that it would be better to remove the Attack() actions. For the variable # myCre.cre, I may be able to come close to the requested result by IF ~~ THEN REPLY ~Well then, little example code snippet, let slip the Dogs of War!~ DO ~CreateCreatureObjectOffset("myNeutralCreature",Player1,[50.100]) SetGlobalVariable("NeutralCreatureCasts","GLOBAL",1)~ IF ~InParty(Player2)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[100.100])~ IF ~InParty(Player3)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[100.50])~ IF ~InParty(Player4)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[60.60])~ IF ~InParty(Player5)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[70.100])~ IF ~InParty(Player6)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[40.90])~ EXIT END I think the InParty checks should return true only if an NPC is in the slot, right? If I am on the right track, I still have to figure out how to do "The Imp casts (DisplayStringHead, probably one line every 5 sec,. possibly voiced lines) and if he is not killed by then - Dynaheir is taken away.". Link to comment
Grim Squeaker Posted April 26, 2006 Share Posted April 26, 2006 IF ~~ THEN REPLY ~Well then, little example code snippet, let slip the Dogs of War!~ DO ~CreateCreatureObjectOffset("myNeutralCreature",Player1,[50.100]) SetGlobalVariable("NeutralCreatureCasts","GLOBAL",1)~ IF ~InParty(Player2)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[100.100])~ IF ~InParty(Player3)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[100.50])~ IF ~InParty(Player4)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[60.60])~ IF ~InParty(Player5)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[70.100])~ IF ~InParty(Player6)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[40.90])~ EXIT END That doesn't make sense syntactically as you can't nest conditions like that. You could have something like: IF ~InParty(Player6)~ THEN REPLY ~stuff~ DO ~SetGlobalVariable("NeutralCreatureCasts","GLOBAL",1) CreateCreatureObjectOffset("myNeutralCreature",Player1,[50.100]) CreateCreatureObjectOffset("myHostileCreature",Player1,[100.100])~ CreateCreatureObjectOffset("myHostileCreature",Player1,[100.50])~ CreateCreatureObjectOffset("myHostileCreature",Player1,[60.60])~ CreateCreatureObjectOffset("myHostileCreature",Player1,[70.100])~ CreateCreatureObjectOffset("myHostileCreature",Player1,[40.90])~ EXIT IF ~InParty(Player5) !InParty(Player6) THEN REPLY ~stuff~ DO ~SetGlobalVariable("NeutralCreatureCasts","GLOBAL",1) CreateCreatureObjectOffset("myNeutralCreature",Player1,[50.100]) CreateCreatureObjectOffset("myHostileCreature",Player1,[100.100])~ CreateCreatureObjectOffset("myHostileCreature",Player1,[100.50])~ CreateCreatureObjectOffset("myHostileCreature",Player1,[60.60])~ CreateCreatureObjectOffset("myHostileCreature",Player1,[70.100])~ EXIT IF ~InParty(Player4) !InParty(Player5) !InParty(Player6) THEN REPLY ~stuff~ DO ~SetGlobalVariable("NeutralCreatureCasts","GLOBAL",1) CreateCreatureObjectOffset("myNeutralCreature",Player1,[50.100]) CreateCreatureObjectOffset("myHostileCreature",Player1,[100.100])~ CreateCreatureObjectOffset("myHostileCreature",Player1,[100.50])~ CreateCreatureObjectOffset("myHostileCreature",Player1,[60.60])~ EXIT ... Only one of these REPLY lines will turn up because of the conditions. Link to comment
cmorgan Posted April 26, 2006 Author Share Posted April 26, 2006 oh -- ok -- got it. What we are doing here is creating the largest contition, then backing it off one Player at a time. THANK YOU! Does my initial approach with nesting fail on regular dialog actions to; i.e. will IF ~~ DYQU5.2 SAY ~something~ ++ ~something~ + DYQU5.3 + ~Class(Player1, THIEF_ALL)~ + ~something~ DO ~SetGlobal("X","Y",#) EXTERN ~_someone~ DYQU5W5.1 + ~Class(Player1, BARD)~ + ~something~ DO ~SetGlobal("X","Y",#) EXTERN ~someone~ DYQU5W5.1 + ~Class(Player1, FIGHTER_ALL)~ + ~*something ~ EXTERN ~_WINSKI~ DYQU5W5.1 END work? Link to comment
Grim Squeaker Posted April 26, 2006 Share Posted April 26, 2006 Yeah of course that will work. But what you were trying to do was have an IF ~conditions~ DO ~stuff~ in the middle of a DO ~loads of stuff~, which is why I called it nesting (i.e. something nested within something else). In your new example you're just attaching conditions to player responses which is fine. Edit: Fuck, no you weren't. I've spotted a tilde I didn't see before. What you were doing was assuming that all of these... IF ~InParty(Player2)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[100.100])~ IF ~InParty(Player3)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[100.50])~ IF ~InParty(Player4)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[60.60])~ IF ~InParty(Player5)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[70.100])~ IF ~InParty(Player6)~ DO ~CreateCreatureObjectOffset("myHostileCreature",Player1,[40.90])~ ...would run if they are valid. They don't. Only the bottom-most valid one will run and it'll follow that line's transitions. Also, you didn't attach a transition to the ends of any them, so WeiDU wouldn't like it. Link to comment
cmorgan Posted April 26, 2006 Author Share Posted April 26, 2006 Yep, that is what I was assuming. I was saying I thought IF X begins then check for condition 1 if true then emit response 1 AND condition 2 if true then emit response 2 AND condition 3 if true then emit response 3 THEN go to Y. NOW, if I "grokked", then the way I should think is IF X begins then check for condition 3 if true then emit response 3 OUT to Y OR condition 2 if true then emit response 2 OUT to Y OR condition 1 if true then emit response 1 OUT to Y END where only one response is followed, evaluated from the last condition upwards. The Dialogue pattern above would have only one response, (e.g. FIGHTER_ALL based if Player1 was a fighter); the top line ++ ~something~ + DYQU5.3 wouldn't show up unless the class was not evaluated TRUE in condition check? Link to comment
Grim Squeaker Posted April 26, 2006 Share Posted April 26, 2006 Well. IF ~~ DYQU5.2 SAY ~something~ ++ ~something~ + DYQU5.3 + ~Class(Player1, THIEF_ALL)~ + ~something~ DO ~SetGlobal("X","Y",#) EXTERN ~_someone~ DYQU5W5.1 + ~Class(Player1, BARD)~ + ~something~ DO ~SetGlobal("X","Y",#) EXTERN ~someone~ DYQU5W5.1 + ~Class(Player1, FIGHTER_ALL)~ + ~*something ~ EXTERN ~_WINSKI~ DYQU5W5.1 END As this are player responses then all valid responses will be displayed e.g. if they are fighter, just the first one (without conditions) and last one. However, if they are a fighter/thief the first, the second and last options will be displayed. However: IF ~~ DYQU5.2 SAY ~something~ IF ~Class(Player1, THIEF_ALL)~ DO ~SetGlobal("X","Y",#) EXTERN ~_someone~ DYQU5W5.1 IF ~Class(Player1, BARD)~ DO ~SetGlobal("X","Y",#) EXTERN ~someone~ DYQU5W5.1 IF ~Class(Player1, FIGHTER_ALL)~ EXTERN ~_WINSKI~ DYQU5W5.1 END In this case we don't have player responses. We have straight EXTERN calls i.e. the player doesn't choose anything, it just automatically goes to the appropriate block. In this situation the first valid transition (bottom-up) is followed e.g. if they are fighter, its the FIGHTER_ALL one. If they are a thief, its the THIEF_ALL one. If they are a Fighter/Thief its the FIGHTER_ALL one as its first bottom-up. Link to comment
cmorgan Posted April 26, 2006 Author Share Posted April 26, 2006 Wicked cool. I think I understand. To confirm: IF ~Class(Player1, BARD)~ THEN REPLY ~something~ DO ~SetGlobal("X","Y",#)~ EXTERN ~_WINSKI~ DYQU5W5.1 equals if BARD then say "something" then SETGLOBAL then goto WINSKI and say "somethingelse" called by DYQU5W5.1 after the user hits return. IF ~Class(Player1, BARD)~ DO ~SetGlobal("X","Y",#)~ EXTERN ~_WINSKI~ DYQU5W5.1 equals if BARD then SETGLOBAL then goto WINSKI have him say "somethingelse" called by DYQU5W5.1 right away? I appreciate the help - just watch out, 'cause any minute now I'm going to break out into "The Rain in Spain falls Mainly on the Plain", with me in the role of Eliza! Link to comment
Grim Squeaker Posted April 26, 2006 Share Posted April 26, 2006 Yes thats it. Modders tend to use IF ~~ THEN GOTO type lines to branch dialogue based on variables or randomness without the player saying anything. A decent example of this are NPC initiated flirts in the Flirt Pack. We get a generic opening line and then there are a series of IF ~~ THEN GOTO lines based on the random trigger, so you get a random flirt without any player choices (or having a different start of the dialogue for each flirt). Link to comment
cmorgan Posted April 26, 2006 Author Share Posted April 26, 2006 Grim Squeaker, thank you - I'm a happy guy. One last unrelated question before I head out to play around with 61 StartTimer(I:ID*,I:Time*) and 269 DisplayStringHead(O:Object*,I:StrRef*) to see about the imp's spell -- I'll try some stuff out before asking more questions about that. Researching TakeItemReplace, I noticed you were exploring a workaround, swapping one amulet for another. If I leave off the Object, IF ~~ DO ~TakeItemReplace("X#DYJOR2.ITM","X#DYJOR1.ITM")~ will the default behavior be to swap the item out from any player holding the item, or must the object be specified? Link to comment
cmorgan Posted April 26, 2006 Author Share Posted April 26, 2006 OK, perhaps I need to back up a step. I have about 90% of this coded, but still must be missing something basic -- This is the top of a combined .D file I am testing. APPEND shouldn't need a BEGIN; but EXTEND_BOTTOM  ~_DRIZZT~ 10 IF ~Global("X#DynaJournal","GLOBAL",0)~ THEN DO ~SetGlobal("X#DynaJournal","GLOBAL",1)~ EXIT END APPEND ~_DRIZZT~ IF WEIGHT #4 ~!InParty("Dyanheir") !InMyArea("Dynaheir") Global("X#DynaJournal","GLOBAL",1) CombatCounter(0) !See([ENEMY]) See(Player1)~ THEN BEGIN DYQ0.0 SAY ~domi's text for drizzt here~ IF ~~ THEN DO ~GiveItemCreate("X#DYJOR1.ITM",Player1,1,1,0)~ IF ~InParty("Minsc")!Dead("Minsc")!StateCheck("Minsc",STATE_SLEEPING)~ EXTERN ~_BMINSC~ DYQ0.01 IF ~!InParty("Minsc")~ THEN REPLY ~Thank you. We will keep this with us until we find a scholar.~ EXIT END END //end append ~_DRIZZT~ X#DynaJournal=1  Item X#DYJOR1.ITM Returns parse errors at SAY ~domi's text for drizzt here~ IF ~~ THEN DO ~GiveItemCreate("X#DYJOR1.ITM",Player1,1,1,0)~ or if I write it SAY ~domi's text for drizzt here~ DO ~GiveItemCreate("X#DYJOR1.ITM",Player1,1,1,0)~ I have clean code from BG1NPC, Eranon, and TGCep1 side by side in ConTEXT, and I can't see the syntax differences. Can anyone point a newbie to the obvious? Link to comment
Grim Squeaker Posted April 27, 2006 Share Posted April 27, 2006 Right, you cannot do this: SAY ~domi's text for drizzt here~ DO ~GiveItemCreate("X#DYJOR1.ITM",Player1,1,1,0)~ We're not doing a CHAIN here so all DO ~~ lines must be attached to a transition line (i.e. a player response or an IF ~~ THEN line). IF ~~ THEN DO ~GiveItemCreate("X#DYJOR1.ITM",Player1,1,1,0)~ As I said before you cannot have an IF ~~ THEN line with no transition at the end. It has to go somewhere, whether it be EXTERNing, GOTOing or an EXIT. If you're intending that line to always play, it doesn't work like that as I covered above. Only one IF ~~ THEN line or player response (which is a type of IF ~~ THEN line) can be followed. Perhaps you meant: IF ~InParty("Minsc")!Dead("Minsc")!StateCheck("Minsc",STATE_SLEEPING)~ DO ~GiveItemCreate("X#DYJOR1.ITM",Player1,1,1,0)~ EXTERN ~_BMINSC~ DYQ0.01 IF ~!InParty("Minsc")~ THEN REPLY ~Thank you. We will keep this with us until we find a scholar.~ DO ~GiveItemCreate("X#DYJOR1.ITM",Player1,1,1,0)~ EXIT Link to comment
cmorgan Posted April 27, 2006 Author Share Posted April 27, 2006 Serves me right for reading line after line of CHAIN examples, then going back to regular work. Yes, your recoding was what I was aiming for: both conditions give the object; either Minsc replies or if Minsc is not in the party the player replies. Got that DO needs to be set into the reply lines with a transition at the end --If I am not in a CHAIN (or I_C_T variant based on CHAIN), I need to work within IF condition THEN BEGIN label (or if directly from a dialog sequence, IF nocondition label) IF condition SAY text (or skip the IF condition and begin with SAY) (no response from anyone = IF condition DO action TRANSITION) IF condition THEN REPLY text DO action TRANSITION END I am still missing something about what truly constitutes a proper transition -not the words to use, but how they operate- studying and copying aside, my brain wants to go back to if SAY ~text one and~ SAY ~text one continues here~ so it appears a linear form would work : SAY ~ ~ DO ~ ~ SAY ~ ~ REPLY ~ ~ EXIT That is what CHAIN seems to be doing; but it can't be. The initial SAY cannot have an action attached if there is no specific transition to the next line. I guess the transitions here are the jump to the next speaker? borrowing from/adding to another post in the tutorials: == KIDOJ ~We will go at once.~ DO ~ActionOverride("DCleric",EscapeArea()) AddJournalEntry(%Creating blah, blah, blah More blah stuff%,QUEST)~ == MYNPC ~InParty("Minsc")~ ~Come along now, big dude!~ END ++ ~Say text here~ EXIT END What are the transitions between KIDOJ, MYNPC, and Player1 response? Link to comment
Grim Squeaker Posted April 27, 2006 Share Posted April 27, 2006 Okay first of all: IF condition THEN BEGIN label (or if directly from a dialog sequence, IF nocondition label) IF condition SAY text (or skip the IF condition and begin with SAY) (no response from anyone = IF condition DO action TRANSITION) IF condition THEN REPLY text DO action TRANSITION END You can't have conditions on SAY lines. SAY ~text one and~ SAY ~text one continues here~ You can't have two consecutive SAY lines. The first one is SAY, any future ones are = e.g. SAY ~text one and~ = ~text one continues here~ Basically, what a CHAIN is a way to string together switch between dialogues. Here's a demonstration: CHAIN IF ~Global("G#Bob","GLOBAL",0)~ THEN G#BOB chainstate ~Hello, my name is Bob.~ DO ~SetGlobal("G#Bob","GLOBAL",1)~ == G#JIM ~Really? My name is Jim!~ == G#FRANK ~And mine is Frank!~ END ++ ~Yeah and my name is <CHARNAME>~ EXIT That is identical to doing this: APPEND G#BOB IF ~Global("G#Bob","GLOBAL",0)~ THEN BEGIN state1 SAY ~Hello, my name is Bob.~ IF ~~ THEN DO ~SetGlobal("G#Bob","GLOBAL",1)~ EXTERN G#JIM state2 END END APPEND G#JIM IF ~~ THEN BEGIN state2 SAY ~Really? My name is Jim!~ IF ~~ THEN EXTERN G#FRANK state3 END END APPEND G#FRANK IF ~~ THEN BEGIN state3 SAY ~And mine is Frank!~ ++ ~Yeah and my name is <CHARNAME>~ EXIT END END The reason CHAINs allow DO ~~ lines between the various bits of dialogue is to represnt what I have doing on in 'state1', the fact that between speakers you could have some actions. In your example: == KIDOJ ~We will go at once.~ DO ~ActionOverride("DCleric",EscapeArea()) AddJournalEntry(%Creating blah, blah, blah More blah stuff%,QUEST)~ == MYNPC ~InParty("Minsc")~ ~Come along now, big dude!~ END ++ ~Say text here~ EXIT END What I would call a 'transition line' is the bit that says: ++ ~Say text here~ EXIT The transition in that is the bit that says EXIT i.e. saying where to go if you choose that option. The bit that says... DO ~ActionOverride("DCleric",EscapeArea()) AddJournalEntry(%Creating blah, blah, blah More blah stuff%,QUEST)~ ...are actions which would be attached to a transition line were this not a CHAIN. They'd be like my 'SetGlobal("G#BoB","GLOBAL",1)' in 'state1' above. Hope that helps. Edit: Something to note in your example, however is the whitespace. Try not to think of this: == KIDOJ ~We will go at once.~ DO ~ActionOverride("DCleric",EscapeArea()) AddJournalEntry(%Creating blah, blah, blah More blah stuff%,QUEST)~ == MYNPC ~InParty("Minsc")~ ~Come along now, big dude!~ Try to think of it as this: == KIDOJ ~We will go at once.~ DO ~ActionOverride("DCleric",EscapeArea()) AddJournalEntry(%Creating blah, blah, blah More blah stuff%,QUEST)~ == MYNPC ~InParty("Minsc")~ ~Come along now, big dude!~ i.e. the actions are happening between the lines, rather than actually being attached to what the NPC is saying. Because WeiDU treats spaces and linebreaks the same way it doesn't make a difference, but its the way you picture that will help you. Link to comment
cmorgan Posted April 27, 2006 Author Share Posted April 27, 2006 Believe it or not, the lightning struck when you did the "whitespace" explanation-- light dawned, slapped head, and now I can go back through the examples. Thank you VERY much. I'll head back, reread the WeiDU, Dialogue, and Chain tutorials in light of this, and recode! Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.