Author Topic: Converting IWD2 scripts for BG2: ToB: need help!  (Read 3431 times)

Offline vit mg

  • Planewalker
  • *****
  • Posts: 42
  • Gender: Male
    • AERIE team
Converting IWD2 scripts for BG2: ToB: need help!
« on: March 26, 2008, 05:19:44 AM »
Hello everyone!

My friends and I want to convert some scripts, written for IWD2 to use them in BG2 modding. But there is a lot of actions and triggers that exists in IWD2 but not in BG2.
Could somebody help us to find a way to right transformation?

Here is the one problem I would like you to solve me.
Trigger 0x4097 TimerActive(I:TimerID*) doesn't exist in the list of BG2 triggers.
I've got this code in IWD2:
Code: [Select]
IF
  !TimerActive(18)
  !See([ENEMY.0.GOBLIN],0)
  Global("Brogan_Leave","GLOBAL",0)
THEN
  RESPONSE #20
    FloatMessage(Myself,1666)
    StartRandomTimer(18,10,15)
    Continue()
  RESPONSE #20
    FloatMessage(Myself,1667)
    StartRandomTimer(18,10,15)
    Continue()
  RESPONSE #20
    FloatMessage(Myself,1668)
    StartRandomTimer(18,10,15)
    Continue()
  RESPONSE #20
    FloatMessage(Myself,1669)
    StartRandomTimer(18,10,15)
    Continue()
  RESPONSE #320
    Continue()
END
    To convert this for BG2 I've allready changed:
    ENEMY.0.GOBLIN with ENEMY.0.HOBGOBLIN // I don't khow what it means, but goblins do not exist in the list of creatures of BG2
    FloatMessage with DisplayStrngHead
    StartRandomTimer(18,10,15) with StartTimer(18,12) // 12 is a simple average of 10 and 15
    RESPONSE #320 whith RESPONSE #20 // 320% probability was an error I think

    I tried to replace !TimerActive(18) with TimerExpired(18) and now i've got this code in BG2:
Code: [Select]
IF
  TimerExpired(18)
  !See([ENEMY.0.HOBGOBLIN])
  Global("Brogan_Leave","GLOBAL",0)
THEN
  RESPONSE #20
    DisplayStringHead(Myself,1666)
    StartTimer(18,12)
    Continue()
  RESPONSE #20
    DisplayStringHead(Myself,1667)
    StartTimer(18,12)
    Continue()
  RESPONSE #20
    DisplayStringHead(Myself,1668)
    StartTimer(18,12)
    Continue()
  RESPONSE #20
    DisplayStringHead(Myself,1669)
    StartTimer(18,12)
    Continue()
  RESPONSE #20
    Continue()
END
It doesn't not work - the creature does not say anything.
(I think the reason is in that the TimerExpired(18) returns the true only if subtraction expired time from timer returns negative value but when this timer is not started the substraction value is zero or null so the trigger returts false.)
Could somebody tell me how to make this code working right way?
« Last Edit: March 26, 2008, 09:12:07 AM by vit mg »

Offline Kulyok

  • Global Moderator
  • Planewalker
  • *****
  • Posts: 6253
  • Gender: Female
  • The perfect moment is now.
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #1 on: March 26, 2008, 07:47:10 AM »
Just to add something: Badgert, another guy from Aerie.ru modding/translating community, asked me about this stuff recently, and I honestly answered I didn't know(because, well, I don't. If I were asked about NPC mods, I'd ramble to my heart's content, even if not all of it would be useful), but I did recommend him this Modding Q&A forum, as well as the Modding Q&A forum at G3, since they are the ultimate technical guys. So, um, let's uphold our reputation? :)

Offline devSin

  • Planewalker
  • *****
  • Posts: 1632
  • Gender: Male
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #2 on: March 26, 2008, 09:58:37 AM »
IF
OnCreation()
THEN
RESPONSE #100
StartTimer(18,12)
END

//The rest of your code here

Offline vit mg

  • Planewalker
  • *****
  • Posts: 42
  • Gender: Male
    • AERIE team
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #3 on: March 26, 2008, 11:39:43 AM »
Thank you ladies and gentlemen!

I tried append devSin's code before the mine. And, of course, it works. But only for the first time the creature meet PC and then creature don't say anything even after PC leave area and return again.
IESDP says that OnCreation() "returns true only if the active creature came into existance in the last script round. If this is in an area script this returns true when the player enters the area for the first time." Since my script is not area - I append it as Class script for the CRE file - I can't understand what "last script round" exactly means. Maybe you'll tell me what it means?

Like devSin did, I've tried to force my creature to do what I want with another trigger. So far as I understand, my creature speaks if it is idle, and I've used ActionListEmpty() trigger and the Delay trigger:
Code: [Select]
IF
  ActionListEmpty() //new added
  Delay(12) //new added
  See([PC])
  Global("Brogan_Leave","GLOBAL",0)
THEN
  RESPONSE #20
    DisplayStringHead(Myself,1666)
    Continue()
  RESPONSE #20
    DisplayStringHead(Myself,1667)
    Continue()
  RESPONSE #20
    DisplayStringHead(Myself,1668)
    Continue()
  RESPONSE #20
    DisplayStringHead(Myself,1669)
    Continue()
  RESPONSE #20
    Continue()
END
It works as I expected: creature speaks every 12 seconds all over the time when PC can see it.

But could somebody tell me how to make it work without Delay and ActionListEmpty in case I will not be able to use OnCreation and the creature must do anything else during speaking?
« Last Edit: March 26, 2008, 11:57:57 AM by vit mg »

Offline devSin

  • Planewalker
  • *****
  • Posts: 1632
  • Gender: Male
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #4 on: March 26, 2008, 12:57:58 PM »
It doesn't mean anything. OnCreation() will return true if this is A) the first time the script has been loaded for this object and B) no other actions in the script have been executed (i.e., whenever a script starts up, either by entering a new area, spawning a new creature, loading a saved game, etc., OnCreation() will be true until that object performs a scripted action from any of its available scripts).

I don't see anything wrong with your updated code. You could switch to using SetGlobalTimer() with !GlobalTimerNotExpired() rather than Delay(). ActionListEmpty() shouldn't keep the creature from doing anything once it's spoken, but it will prevent it from speaking if it's already doing anything; I don't see a problem with the behavior (it'd be dumb to stop whatever you're doing every 12 seconds just to give a DisplayStringHead()), but if you have a specific purpose for it, you can just get rid of ActionListEmpty() entirely.

Offline vit mg

  • Planewalker
  • *****
  • Posts: 42
  • Gender: Male
    • AERIE team
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #5 on: March 27, 2008, 04:24:46 AM »
Well, it looks like the solution was found. And now I've found out in was case OnCreation() returns true.

Thank you one more time! And I promise that I could ask here one more time too!

UPDATE:
Switching to using SetGlobalTimer() with !GlobalTimerNotExpired() seems like most useful solution:

Code: [Select]
IF
  !GlobalTimerNotExpired("18","LOCALS") // !TimerActive(18) replaced
  !See([ENEMY.0.HOBGOBLIN])
  Global("Brogan_Leave","GLOBAL",0)
THEN
  RESPONSE #20
    DisplayStringHead(Myself,1666)
    SetGlobalTimer("18","LOCALS",12) // StartRandomTimer(18,10,15) replaced
    Continue()
... the same code
END
« Last Edit: March 27, 2008, 08:39:00 AM by vit mg »

Offline devSin

  • Planewalker
  • *****
  • Posts: 1632
  • Gender: Male
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #6 on: March 27, 2008, 09:30:05 AM »
You'll want an actual variable name ("18" is kinda funky). StartTimer() is just a funky in-memory timer with a simple integer ID (and has a habit of breaking on me after a while), but GlobalTimer() is a real variable.

I don't think goblins in BG2 are given HOBGOBLIN race; you might just want to do [ENEMY] to pick out any hostiles unless there's some reason to prevent the string only when goblins are around.
« Last Edit: March 27, 2008, 09:32:28 AM by devSin »

Offline vit mg

  • Planewalker
  • *****
  • Posts: 42
  • Gender: Male
    • AERIE team
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #7 on: March 30, 2008, 05:16:51 AM »
Oh, thanks! Of course, I'll use my imagination more hard and take timer with not funky name :)

And what about goblins, i'm not sure what enemies my creature afraids. He says something like: "I think there are not any more goblins here..." But I don't know what creatures will spawn in that location in BG2 style. So I let HOBGOBLINS stay untill the situation will be clear. Maybe he doesn't afraid anyone exept goblins, even dragons. :)

Now I've got another question.
There is a IWD2 252 ChangeCurrentScript(S:Script*) script action.
It doesn't exist in BG2.
It used a lot in IWD2 sctipts to set a new script for the creature (as I think). Here the example:
Code: [Select]
IF
  Level(Myself,30)
THEN
  RESPONSE #100
    ChangeCurrentScript("00Monk30")
END

IF
  Level(Myself,29)
THEN
  RESPONSE #100
    ChangeCurrentScript("00Monk29")
END

... here goes the list of 28 similar actions that ends with

IF
  LevelGT(Myself,30)
THEN
  RESPONSE #100
    ChangeCurrentScript("")
    Continue()
END

I think, I have to replace all the ChangeCurrentScript actions with contents of named scripts (00Monk30, 00Monk29 and others). Like that:
Code: [Select]
IF
  Level(Myself,30)
THEN
  RESPONSE #100
    // here goes the first action of the 00Monk30 sctipt
END

IF
  Level(Myself,30)
THEN
  RESPONSE #100
    // here goes the second (tird etc) action of the 00Monk30 sctipt
END

IF
  Level(Myself,29)
THEN
  RESPONSE #100
    // here goes the first action of the 00Monk29 sctipt
END

IF
  Level(Myself,29)
THEN
  RESPONSE #100
    // here goes the second (tird etc) of the 00Monk29 sctipt
END

... here goes the list of 28 similar sctions that ends with

IF
  LevelGT(Myself,30)
THEN
  RESPONSE #100
    // I think this section not need at all
    Continue()
END

Tell me please, whether I make replacement right or wrong.

Offline devSin

  • Planewalker
  • *****
  • Posts: 1632
  • Gender: Male
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #8 on: March 30, 2008, 10:59:01 AM »
You can stick them all in one script if they're not too large, sure. You won't be able to do something like your second code block without additional triggers (remember, the engine finds the first true trigger, executes the actions, and then restarts processing from the top -- in the posted code, a Level 30 character would only ever run the first block).

BG2 has ChangeAIScript(), which allows you to set the script of the creature at the specified script level (ChangeAIScript("WTASIGHT",OVERRIDE) immediately switches to WTASIGHT in the override slot permanently). If the code you posted is just BIS's way of setting a level-dependent script when the creature is created, ChangeAIScript() should be safe.

Offline vit mg

  • Planewalker
  • *****
  • Posts: 42
  • Gender: Male
    • AERIE team
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #9 on: April 01, 2008, 07:14:11 AM »
Thanks a lot!
I was afraid to use ChangeAIScript because I did not understand how does it work. Now I see it fits very well.
And special thanks for the description of script running!

Can I proceed with asking? :)
Here is a small question (there is no descripnion of objects in IESDP, so I need to clear).

I've got the script action in IWD2:
Code: [Select]
MoveToObject(NearestPC)I don't know what NearescPC means, but i want to replace it for BG2 with SecondNearest, because IESDP says that Nearest returns the same as Myself.
So in BG2 I have:
Code: [Select]
MoveToObject(SecondNearest)
Tell me, please, is this replacement right?

Offline devSin

  • Planewalker
  • *****
  • Posts: 1632
  • Gender: Male
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #10 on: April 01, 2008, 08:02:51 AM »
MoveToObject([PC]) will cause the script runner to move to the nearest living visible PC. If no PCs are alive and visible (within visual range and can be seen normally by the script runner), then nothing happens.

Offline vit mg

  • Planewalker
  • *****
  • Posts: 42
  • Gender: Male
    • AERIE team
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #11 on: April 03, 2008, 04:35:25 AM »
Very well, now I've got a replacement for the MoveToObject(SecondNearest) command and I know how it works!
Thank you  very much, mr.devSin!

And I'm proceeding my annoyance :)

I've got no idea what to do with the NearSavedLocation trigger in this code in IWD2:
Code: [Select]
IF
  Global("RW_00AMVW050","LOCALS",0)
  !NearSavedLocation(5)
THEN
  RESPONSE #100
    SetGlobal("RW_00AMVW050","LOCALS",1)
    Continue()
END

IF
  !Global("RW_00AMVW050","LOCALS",0)
  NearSavedLocation(5)
THEN
  RESPONSE #100
    SetGlobal("RW_00AMVW050","LOCALS",0)
    NoAction()
END

IF
  !Global("RW_00AMVW050","LOCALS",0)
  Range([PC],40,LESS_THAN)
THEN
  RESPONSE #100
    MoveToPoint([-2.-2])
END

IF
  !TimerActive(19)
  Global("RW_00AMVW050","LOCALS",0)
  Range([PC],40,LESS_THAN)
THEN
  RESPONSE #100
    RandomWalk()
    StartRandomTimer(19,10,15)
END
This is a full code of the script file I have and I can't understand what this trigger used for...

Could you help me, please?
« Last Edit: April 03, 2008, 11:18:12 AM by vit mg »

Offline devSin

  • Planewalker
  • *****
  • Posts: 1632
  • Gender: Male
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #12 on: April 03, 2008, 11:07:36 AM »
Not much you'll be able to do with that. You could have a trigger point near the creature and change to a Range("TriggerPoint",5), but it's a lot of work.

The code isn't really essential; it's just basically letting the character wander around while not allowing them to get too far from their original point. In BG, they just stand still if they're always supposed to be in a certain place.

Offline SimDing0™

  • Back In Black
  • Global Moderator
  • Planewalker
  • *****
  • Posts: 3496
  • Gender: Male
  • Word Enhancer
Re: Converting IWD2 scripts for BG2: ToB: need help!
« Reply #13 on: April 03, 2008, 08:20:17 PM »
You can almost do "wander but not too far" in BG2.

Code: [Select]
IF
Global("StartPatrol","LOCALS",0)
THEN
RESPONSE #100
SetGlobal("StartPatrol","LOCALS",1)
SetGlobalTimer("Patrol","LOCALS",12)
SaveObjectLocation("LOCALS","DefaultLocation",Myself)
END

IF
GlobalTimerExpired("Patrol","LOCALS")
Global("StartPatrol","LOCALS",1)
THEN
RESPONSE #100
MoveToSavedLocationn("DefaultLocation","LOCALS")
SetGlobal("StartPatrol","LOCALS",0)
END

IF
GlobalTimerNotExpired("Patrol","LOCALS")
Global("StartPatrol","LOCALS",1)
THEN
RESPONSE #100
RandomWalkContinuous()
END

It depends on time rather than distance, so it probably still looks kind of fake, but whatever.

 

With Quick-Reply you can write a post when viewing a topic without loading a new page. You can still use bulletin board code and smileys as you would in a normal post.

Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.

Name: Email:
Verification:
Type the letters shown in the picture
Listen to the letters / Request another image
Type the letters shown in the picture:
What color is grass?:
What is the seventh word in this sentence?:
What is five minus two (use the full word)?: