Jump to content

Scripts crashing the game.


Meira

Recommended Posts

A player reported that his game crashes few seconds after the party enters a new area added by my mod. Together we managed to narrow the cause down to the area script and these two blocks in it:

 

IF
AreaCheckObject("M#AR02","m#lorraine")
!Dead("m#lorraine")
THEN
RESPONSE #100
MoveGlobal("M#AR01","m#lorraine",[580.370])
END

 

and

 

IF
AreaCheckObject("M#AR02",Player1)
!AreaCheckObject("M#AR02","m#ygspm4")
!Dead("m#ygspm4")
THEN
RESPONSE #100
MoveGlobal("M#AR02","m#ygspm4",[200.790])
END

 

There are several similar blocks like the latter one of these two for other guards, but they don't seem to cause a crash. Removing the these two blocks allowed the game to proceed normally.

 

Furtemore, later in the game this block at the end of a dialogue (after OpenDoor()) causes a crash:

 

IF ~~ THEN BEGIN INSIDE18
 SAY @3162 /* @3162 = ~Thank you, <CHARNAME>. But enough of this, the battle awaits! There is a device in the sorcerer's laboratory that I need to use to release my son's soul from the gem.~ */ 
 IF ~~ THEN DO ~SetGlobal("M#LorraineMoved","GLOBAL",1)
	   CreateItem("m#clearf",1,0,0)
			 FillSlot(0)
			 ChangeAIScript("m#lorall",CLASS)
			 ChangeEnemyAlly(Myself,GOODBUTBLUE)
			 MoveToPointNoInterrupt([350.543])
			 OpenDoor("ExitDoor")
			 EscapeAreaMove("m#ar06",1243,895,3)~ EXIT
END

 

In my game these work without a hitch and crashes like this have never been reported before by any other player or tester. The player whose game crashes uses a mac.

 

Help? :)

Link to comment
Hmm, I only have V2 of Amber at the moment (and still haven't gotten around to playing it) but both m#ygspm4.cre and m#lor10.cre are corrupt (incorrect indices) in that way which will cause crashes on mac installations.

 

Okay, I don't understand the word 'indices', or why it only affects mac users, but how can I fix this or avoid creating 'incorrect indices' in the future? Is it enough if I just create new .cre files for those two?

 

Thanks for helping to solve the mystery, though. :)

Link to comment

Er, 0x2AC should always be 17: and there should always be 17 entries, preist0-6, Wizard 0-8 and Innate. Maybe you're thinking of Known Spells?

 

I could conceive of an algorithm for loading a CRE into memory that would have trouble if the slots table was before the things to put in them. We've already seen Mac crashes with unslotted items.

Link to comment
I could conceive of an algorithm for loading a CRE into memory that would have trouble if the slots table was before the things to put in them. We've already seen Mac crashes with unslotted items.
These crashes were related to the effects index for particular items. The order of the sections shouldn't matter at all (the engine already reorders everything when the files are loaded and flushed during saving).

 

If you remove the AreaCheckObject() calls, I suspect it'd work. They have a tendency to cause crashes in the Mac port. I don't know why the dialogue code you posted would crash; I don't see anything immediately suspect.

Link to comment

Since I'm the player that Meira is working with, I thought I'd give you a bit more information. There are eight blocks of code involved - one for each of "m#lorraine", "m#yclbm1", "m#ygspm1" thru "m#ygspm4", "m#ygsbm1" and "m#ygsbm2". The guard blocks are all similar. As devSin suspected, if the AreaObjectCheck() line is removed from each of the eight blocks, the game doesn't crash (it doesn't do what it's supposed to either, but at least it doesn't crash).

 

Now here's the interesting part. As long as a guard is alive when the party first enters area "M#AR02" then there is no need to remove the AreaObjectCheck() for that guard, even if he is subsequently killed (regardless of how the guard gets to area "M#AR02" - he can get there three different ways, and in all three the game does not crash). If a guard is killed in area "M#AR01" then the AreaObjectCheck() must be removed from that guard's block even though the block wouldn't have triggered had it been there, or it causes the game to crash. That leads me to suspect that the trigger is not working correctly on macs when the object has died in a different area. So for you experts out there, what exactly does dying do to the object, and is there any possibility that on a mac an object is removed from the saved game (loses its global status) when it dies?

 

I'm still testing Lorraine but she appears different. In her case the problem is more than just the AreaObjectCheck(). So long as I don't actually kill her in area "M#AR01", I can put the AreaObjectCheck() back in if I also change the action from MoveGlobal("M#AR01","m#lorraine",[580.370]) to something that doens't involve "m#lorraine". MoveGlobal("M#AR01","m#yclbm1",[580.370]) for example works and moves Ymmyrt's Lieutenant instead of Lorraine back to area "M#AR01" and doesn't cause the game to crash (though it leaves Lorraine in area "M#AR02" in place of the Lieutenant).

 

The second crash also involves Lorraine, and happens just as she goes thru the door, which makes me suspect the EscapeAreaMove("m#ar06",1243,895,3) line.

 

I'm not a member here, so I'm surprised that I'm allowed to post, but since you are working on my problem anyway, I figured that the extra info wouldn't hurt.

Link to comment
Guest Guest.1

Hey Guest, If you haven't, try flipping the stack order of the Dead & AreaObjectCheck triggers -- that is, put !Dead first. ``First'' is the top of the trigger list, top == closer to the IF than the THEN.

 

Now you can kill guards in AR01 without crashing in AR02.

 

Saddly, Lorraine doesn't work here because her state is incorrect when you `kill' her; check your save with NI: her state will be STATE_NORMAL but her HP will be -42 or whatever, some very unhealthy number. If you check the globals, her SPRITE_IS_DEAD will not have been set. Technically, this happens because she's a gay zombie ranger.

 

What I found more inane; manually setting her state to STATE_DEAD, and setting her SPRITE_IS_DEAD didn't `stick'. ;-( it seems the IE `fixes' this `error' on load of a save. Wonderful heuristics there.

 

Wait. I think I have confused myself -- it might have been in AR02 her state was unset causing !Dead to return as True. Too lazy to assert, sorry. Her state does go bad `somewhere' though.

 

 

Next: it would seem to be impossible to move her from AR04 tot AR06 once she moves from AR01 or AR02 to AR04. == it is the EscapeAreaMove action in her dialogue as you suspected.

 

Worse, NO move global action works in it's place. None. I tried all applicable actions listed in the IESDP reference for BG2TOB using each of Lorraine's dlg, the AR04 and AR06 objects: Spectacular failure in each case. Meaning: Amber *would* move from AR05 to AR04 (or AR06), Lorraine would *not* move from AR04 to AR06 (crash).

 

My solution: I have her DestroySelf rather than `Move' in AR04 via her dlg state 22 or 23, (whatever it is), then in the AR06 object's script Creates a fresh Lorraine, and sets her inventory, equipment, and locals, etc. This works fine. Kludge? Yup...

 

If I had my druthers, I'd go back and Fix Loraine's dialog graph's entry points to use AreaCheck triggers rather than locals, and remove her `globalness' in whole -- it serves little function.

Link to comment

Hey this is Meira's player again. It turns out that I have registered here before. Must have been quite a while ago since I haven't used this screen name on game forums in ages. Guest.1 - thanks for the suggestions. As far as Lorraine's state - she only gets to area "M#AR02" when she is still RED and most definitely alive. The problem is that she needs to be booted back to area "M#AR01" for her conversation to trigger correctly, and the MoveGlobal() that sends her back there crashes the game. The bad AreaObjectCheck() problem when you actually kill her can be fixed by inverting the !Dead() and the AreaObjectCheck() just as you suggested for the guards. So any idea why a live Lorraine can't be moved - either from "M#AR02" to "M#AR01" or from M#AR04" to M#AR06"? EscapeArea() does work, so it's only when she has a destination that the game crashes.

 

I'm not a modder. I am a programmer that has done a quick investigation into the IE engine so that I can continue an interesting game. So I have no clue as to what would keep an object from moving between areas. You modders out there must have run into this problem before. Any ideas?

Link to comment

Guest.1 - even if you switch the !Dead() and the AreaObjectCheck() triggers, it still crashes if you enter the gate and not everyone still alive follows you. If there is even one guard or Lorraine that does not follow, the the AreaObjectCheck() for that object returns false and the game crashes. It does fix the crashing due to dead guards though. And once Lorraine moves to "m#ar04", when the party enters "m#ar02", the AreaObjectCheck() trigger for Lorraine returns false and the game crashes.

 

Nythrun - It's not the MoveGlobal() itself in m#ar02.baf that's the problem, it's the MoveGlobal applied specifically to "m#lorraine" that crashes the game. I can MoveGlobal any of the guards without any problem. And Meira does an ActionOverride("m#lorraine", MakeGlobal()) immediately after creating her in "m#ar01.baf. And it can't be the coordinants because I can send a guard there. You have more tools than I have. Is there anything in the m#lorraine.cre file (that's not also in the guard files) that might cause the MoveGlobal() to fail for Lorraine but not the guards?

 

Then again it might not have anything to do with Lorraine, because the EscapeAreaMove that you sited at lines 88 and 97 of m#lorrai.baf works fine without any changes. Lorraine disappears from "m#ar01" and show up in "m#ar04" and the game does not crash.

 

I can't say what Guest.1 did, but I also tried replacing the EscapeAreaMove("m#ar06",1243,895,3) with a MoveBetweenAreas("m#ar06",[1243.895],3) in m#lorrai.d (I didn't find an m#npcnew.d file) and the game still crashes.

 

devSin - you said that AreaObjectChecks don't always work on macs - do you have any more info on why?

Link to comment

Thanks everyone for your input, especially Nythrum. Looks like the problem with Lorraine has nothing to do with her. The reason she can't be moved out of area "m#ar02" or "m#ar04" is the AreaCheckObject("m#ar02","m#lorraine) in m#ar02.baf and the !AreaCheckObject("m#ar04""m#lorraine") in m#ar04.baf which cause the game to crash on the next pass thru the script after Lorraine leaves the area.

 

So it looks like an AreaCheckObject() work around will fix all of the problems. Does anyone know how to make it work correctly on a mac? And kudos to devSin for good instincts.

 

For some reason, EscapeArea() doesn't crash the game. Just out of curiousity, does anyone know what it does differently when it executes?

Link to comment

Sorry, missed this earlier.

 

The problem with AreaCheckObject is either so trivial it would have already been fixed (a typo in trigger.ids) or very challenging to fix (there's an error in BGmain - means decompiling, searching, and writing a patch). Can't do that latter without a mac to test things on.

 

For workarounds, you can try something like commenting out all of the blocks in m#ar02.baf and m#ar04.baf that include AreaObjectCheck. This will leave m#04.baf empty and I forget if that will cause problems, so you might need to add a little dummy script like so

IF
 True()
THEN
 RESPONSE #100
NoAction ()
END

 

Probably doesn't matter though ;)

 

Then you'll need to open up m#lorrai.baf and add:

//  this comes from m#ar02.baf

IF
// shouldn't something else go here?
AreaCheck("M#AR02")
THEN
RESPONSE #100
ActionOverride(EscapeAreaMove("M#AR01",580,370,1))

// this comes from m#ar04.baf

IF
GlobalLT("M#AmberKidnap","GLOBAL",7)
Global("M#LorraineMoved","GLOBAL",0)
!AreaCheck("M#AR04")
THEN
RESPONSE #100
ActionOverride(EscapeAreaMove("M#AR04",530,610,10))
ActionOverride(SetGlobal("M#LorraineMoved","GLOBAL",1,))
END

I feel like there ought to be another conditional in the AreaCheck("M#AR02") block, but I didn't see one in the scripts during my lookover. Anyway, something like that would take care of Lorraine. Then you'll want to fix the guards by adding to m#yclbm1.baf :

// more from m#ar02.baf

IF
!Dead("m#yclbm1")
!InActiveArea("m#yclbm1")
OR (2)
AreaCheck("M#AR01")
AreaCheck("M#AR04")
THEN
RESPONSE #100
ActionOverride(MoveGlobal("M#AR02","m#yclbm1",[200.750]))
END

IF
!Dead("m#ygspm1")
!InActiveArea("m#ygspm1")
OR (2)
AreaCheck("M#AR01")
AreaCheck("M#AR04")
THEN
RESPONSE #100
ActionOverride(MoveGlobal("M#AR02","m#ygspm",[180.730]))
END

IF
!Dead("m#ygspm2")
!InActiveArea("m#ygspm2")
OR (2)
AreaCheck("M#AR01")
AreaCheck("M#AR04")
THEN
RESPONSE #100
ActionOverride(MoveGlobal("M#AR02","m#ygspm2",[220.770]))
END

IF
!Dead("m#ygspm3")
!InActiveArea("m#ygspm3")
OR (2)
AreaCheck("M#AR01")
AreaCheck("M#AR04")
THEN
RESPONSE #100
ActionOverride(MoveGlobal("M#AR02","m#ygspm3",[160.750]))
END

IF
!Dead("m#ygspm4")
!InActiveArea("m#ygspm4")
OR (2)
AreaCheck("M#AR01")
AreaCheck("M#AR04")
THEN
RESPONSE #100
ActionOverride(MoveGlobal("M#AR02","m#ygspm4",[220.790]))
END

IF
!Dead("m#ygsbm1")
!InActiveArea("m#ygsbm1")
OR (2)
AreaCheck("M#AR01")
AreaCheck("M#AR04")
THEN
RESPONSE #100
ActionOverride(MoveGlobal("M#AR02","m#ygsbm1",[140.770]))
END

IF
!Dead("m#ygsbm2"
!InActiveArea("m#ygsbm2")
OR (2)
AreaCheck("M#AR01")
AreaCheck("M#AR04")
THEN
RESPONSE #100
ActionOverride(MoveGlobal("M#AR02","m#ygsbm2",[180.810]))
END

 

Please note that these are improvised suggestions and not a tested patch :mad:

 

 

@Avenger:

 

I put up lorr17.cre from this mod up for download here. Initially I'd figured that both DLTCP and the mac port were having problems with 0x02a0 pointing to 0x00...but the mac evinces no dismay at the guard creatures (who are set up that way) and DLTCP does have problems with this creature. All the offsets look to be in order:

0x02a0->0x02d4 (known spells)

0x02a8->0x06a0 (spell mem info)

0x02b0->0x07b0 (memorized spells)

0x02b8->0x0840 (item slots)

0x02bc->0x0890 (item list)

0x02c4->0x0980 (effects)

and yet when loaded, part of the header is zeroed out. It confuses me, so please advise?

Link to comment
Guest Guest.1

@Nythrun

Just to make sure I'm following you Guest.1, if you don't mind:

 

Not at all!

 

I made quite a bunch of wild and vague claims without /any/ evidence, and threw some sarcastic assertions in there. Given the little context or explanation,there is little reason not to be incredulous. If you still have questions after this more detailed summery, I'd be happy to extrapolate on those particulars. Not to ignore your queries, but they largely don't connect with what I was testing.

 

details.

 

The (abstract) place I was `testing' the actions was for the `move crash' when Lorraine tries to go from AR04 to AR06 using her dlg.

 

I resolved the crash when moving from from AR02 to AR01 rayhatbss mentions by not letting the move *need* to happen. ( That is, I didn't resolve it! I merely simplified the ``problem'') If the player kills Lorraine in AR01 she doesn't move from AR01 to AR02, thus need not move from AR02 to anywhere. This is rather critical to the way I lurched and stumbled thru the quest.

 

This is currently my tweaked state 24, M#LORRAI.d.

IF ~~ THEN BEGIN 24
 SAY #111480
 IF ~~ THEN DO ~SetGlobal("M#LorraineMoved","GLOBAL",1)
CreateItem("m#clearf",1,0,0)
FillSlot(SLOT_AMULET)
ChangeAIScript("m#lorall",CLASS)
ChangeEnemyAlly(Myself,GOODBUTBLUE)
MoveToPointNoInterrupt([350.543])
OpenDoor("ExitDoor")
DestroySelf()
/* MoveBetweenAreas("M#AR06",[1190.928],3) */
/* MoveGlobal("M#AR06","m#lorraine",[1243.895]) */
/* MoveGlobalsTo("M#AR04","M#AR06",[1243.895]) */
/* EscapeAreaMove("m#ar06",1243,895,3) */
~ EXIT
END

 

Not too clever, eh?

 

I didn't test the ``Effect'' variation, it seemed spurious.

 

My Testing was very simple: I uncommented each line in turn, then compiled, opened BG2, loaded save, talked to Lorraine, bounced to this state, and crashed the game. oh, the DestroySelf() wasn't there, that was added latter, you see: it was my `solution'.

 

I also tried each of these from the AR06 script object, using ActionOverride where applicable, and AR04 script object similarly. All 12 tests failed. Fun.

I tried the actions on Amber, each worked, I was satisfied that they actions arn't broken entirely.

 

The points are valid, unless I'm dyslexic (false) 1243.895 is just easy to type, and also is valid.

 

I hope the narrow scope of my tests is clear now: I was just curious if Lorraine would move using another move global action from AR04 to AR06, as this was a problem preventing me from progressing in the plot. A cliff hanger and I wanted to watch the next episode.

 

Yea, this is the rest of the kludge.

 

In M#AR06.baf I prepended,

IF AreaCheckObject("M#AR06",Player1) G("MOVED_STUPID_LORRAINE",0)
THEN RESPONSE #100 
 SG("MOVED_STUPID_LORRAINE",1) 
 CreateCreatureObjectOffset("m#LORR17",Protagonist,[64.64])
END

This creates a ``fresh'' Lorraine, we destroyed her in AR04, so need a new one in AR06 ;-)

 

and M#lorrAI.baf I prepended:

IF AreaCheck("M#AR06") GlobalLT("M#Lorraine","Locals",5)
THEN RESPONSE #100
 SetGlobal("M#Lorraine","Locals",5)
 DestroyItem("minhp20")
 DestroyItem("minhp1")
 CreateItem("m#clearf",1,0,0)
 FillSlot(SLOT_AMULET)
 ChangeAIScript("m#lorall",CLASS)
 ChangeEnemyAlly(Myself,GOODBUTBLUE)
END

This sets her state `right', important, as otherwise she will attack charname, messing up plot coherency with mad skillz.

 

@rayhatbss, or other mac peeps: If you want to give this a try, note that it will work `ok' IF

+ you also false() out Lorraine's move block in AR02 bcs (or comment the whole thing out).

-- that this block crashes is ``normal'', it's got to go. Sorry I didn't make that clear before.

+ and do the !Dead / ACO() sort flip,

-- dead goes first, this is only for the guards, _not_ lorraine: she's `special'.

And in game:

+ and make _sure_ Lorraine doesn't escape to AR02; `kill' her in AR01,

-- use CTRL-Y a couple times (couple min-HP items she strips off), or attack her and her only, killing guards scares her.

+ Finally, cast a cleric cure/heal spell on her, so she gets up and takes off to AR04.

+ talk to her in AR04, it will `look' like she exited, except the game doesn't crash.

-- If you don' like DestroySelf(), EscapeArea() does the same thing with some fidgeting if the engine decides it would be really cool for a character to `exit' thru a brick wall.

+ go to AR06 and things should work Lorraine might be overpowered.

 

 

 

To get the files to edit, I'd use something like `mkdir FOO && weidu --out FOO M#LorrAI.bcs M#AR06.bcs M#LorrAI.dlg && edit FOO/*' if you don't use the shell and thus `edit' hasn't been set, use open -a bbedit FOO/*( or whatever editor you use, I like SubethaEdit and Mi (well, Japanese) for IE text ), then edit away! Really, you can be lazy here and not `edit' the bafs; highight one block copy it, then type `pbpaste | tr \\15 \\12 >> FOO/M#lorrAI.baf'' and then use history subbing to hit the other one, you know. `^lorrAi^AR06'? just get the other block to the paste board first ;-D note, The dlg can't be edited like this.

 

After that, `weidu --out override FOO/* && open BG2' -- or whatever BG2 TOB application is called, mine is simply `BG2' 'cause it's easy to type, `ln -s realy\ l stupid\ long\ name\(tm\) BG2' works too if you don't want to rename the `really stupid long name'.

 

Yup, no body asked, but Mac people (and windows people) in general tend to be kind of, well scared of the shell for some reason. The shell is FRIENDLY! well, sort uh, maybe?

 

AYE:

 

The Solution is not ideal, it's how I plowed thru the quest. really it's quite stupid, but hey, kludge that works, works. It really would be nice to know what exactly the problem is.

 

 

Yeah, and Nythrun, I'm not trying to confuse what you're saying there, that's all very good heuristics. I'd be happy for this`fix' to be proven convoluted and spurious while the real problem is issolated.

 

Also, you're memory is correct: empty scripts are fine; they are just... empty: try compiling one and looking with a hex editor or Vi at what `empty' is, good first step to writing a baf de/compiler, or if you're just plain curious, why not right?

 

However, empty baf response ( -- IF true() RESPONSE #42 /* empty! */ END) : /is/ a bad thing in some IE ( IWD ), but fine for BG2/TOB.

Link to comment

Guest.1 - the reason none of your move commands stopped the game from crashing was because it was the AreaCheckObject() on the subsequent pass thru the script that crashed the game. All of the move commands did what they were supposed to, then with Lorraine gone from the area, AreaCheckObject() was not satisfied which apparently crashes the game on the mac.

 

The AreaCheckObject() line in m#ar04.baf appears to be unneccessary. Simply removing that one line seemed to fix the problem with Lorraine in m#ar04. With that change everything seems to go fine.

 

As far as m#ar02, I'm in the process of testing Nythrum's suggested InActiveArea(). If it works that would fix the problem for both the guards and Lorraine.

Link to comment

Successful Test

 

Thanks to all who have contributed. The solution is simple, tested on a mac under a variety of scenarios and easy to implement. As devSin suspected, the problem was the various AreaCheckObject() triggers that Meira used in m#ar02.baf and m#ar04.baf. The solution came from the code that Nystrum suggested, but is simpler. Any AreaCheckObject() needs to be replaced by the equivalent InActiveArea().

 

In m#ar02.baf replace

 

AreaCheckObject("m#ar02","xxxxxx")

with

 

InActiveArea("xxxxxx")

where "xxxxxx" is replaced by the actual object name. Any leading ! stays.

 

In m#ar04.baf replace the

 

!AreaCheckObject("m#ar04","m#lorraine")

with

 

!InActiveArea("m#lorraine")

There are a total of nine replacements that need to be done - 8 in m#ar02.baf and 1 in m#ar04.baf. This solution has the advantage of preserving all of Meira's coding logic, while replacing the one bad command with a totally equivalent command that the mac doesn't choke on.

Link to comment

Archived

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

×
×
  • Create New...