cyco / WebFun

Reimplementation of the Desktop Adventures game engine for the web.
https://www.webfun.io
23 stars 0 forks source link

Zone 105: Ship return sequence plays twice #6

Open chillywillysoft opened 3 years ago

chillywillysoft commented 3 years ago

At some point I find and repair a little ship that takes me to a remote area of the map. When returning from the remote area to where I first found the ship, the ship flies onto the screen and makes a U-turn and Luke steps out but then Luke instantly disappears and then a duplicate ship flies onto the screen just like the first. Then Luke steps out for reals.

cyco commented 3 years ago

I think this must have been on zone 142 or 463. Does of one these two look familiar?

Zone 142

zone-142

Zone 463

zone-463

chillywillysoft commented 3 years ago

It's neither of those. The ship was smaller and in a little ditch. I'd like to be more helpful. I notice you guys made an asset editor and zone editor. Are those accessible from the webfun.io address?

chillywillysoft commented 3 years ago

I'd also like to help fix the bugs and get Indy running. I don't have much js/ts experience but I have some experience reverse engineering 16-bit Windows programs.

chillywillysoft commented 3 years ago

It's Zone 105.

cyco commented 3 years ago

That's awesome. Shall we tackle the bugs first?

Here's a screenshot of zone 105 for future reference.

zone-105

I managed to reproduce the issue with this test case zone-0x069.wftest.zip.

I fired up the script debugger (Activate debug mode, then click Debug Scripts from the debug menu) and the problem seems to be that action 11 is executed twice.

zone-105-debugger

This is actually by design. See https://github.com/cyco/WebFun/blob/master/src/engine/scenes/room-transition-scene.ts#L129 and https://github.com/cyco/WebFun/blob/master/src/engine/scenes/room-transition-scene.ts#L145

The scripts are supposed to be executed once the whole screen is black and then once again after the animation. I verified this behaviour in a custom zone in the original game. So unless I made a mistake there this is the desired behaviour. Right now I'm thinking that the original engine might stop script execution prematurely the first time around when a wait instruction is encountered. I'll try to find my sample zone and then we can verify if this is the case.


Thanks for your offer of helping out with indy. Reverse engineering 16bit NEs is exactly where I'm lacking experience. I couldn't even get Ghidra to display names for imported library functions :')

Screenshot 2021-06-30 at 09 53 44

Have you found the documentation yet (https://www.webfun.io/docs)? Its's still lacking but maybe we can extend it together.

Indy uses mostly the same on disk file format for all game data and I'm pretty sure I've got most of that covered (https://www.webfun.io/docs/appendix/deskadv.html). Right now the most pressing things are world generation and script execution.

I initially thought that world generation between yoda and indy would be mostly the same. The game first generates and abstract world map, then fills it with puzzles and zones with two interleaved strains. But I can't verify it due to the lack of a debugger on my part. Maybe take a look at https://github.com/cyco/WebFun/blob/master/src/engine/generation/world-generator.ts#L75 to see how worlds are generated for Yoda Stories.

I expect script execution in indy to be very similar to Yoda Stories. Maybe a bit fewer opcodes and some might be off, but that should be easy to verify.

cyco commented 3 years ago

Oh I missed your first comment there. Yes the asset editor is accessible from the website. You have to enable debug mode via the switch in the description text Screenshot 2021-06-30 at 10 31 03 and then choose Edit Current Data from the debug menu.

Screenshot 2021-06-30 at 10 32 22

The asset editor is quite clunky so beware :)

cyco commented 3 years ago

Alright, I found the file. construct.data.zip It's a DTA file that only holds enough zones & puzzles so the Yoda Stories Demo can use it to generate a new world successfully. I also added a few extra zones that inspect various aspects of the game engine, including script execution.

Loading this file in the Yoda Stories demo looks something like this

https://user-images.githubusercontent.com/697021/123936699-be3dae80-d995-11eb-952d-48404374a85a.mov

This is zone #135 in this DTA file with the following script

(defaction "Show instructions when computer is bumped"
   (and (bump 4 2 420)
        (progn
           (speak-npc 4 2 "This room counts how many times the \"enter-by-plane\" action is executed.\r\nYou should see two green dots.\r\n\r\nStep in the middle to reset the counter!"))))

(defaction "Setup registers once"
   (and (zone-not-initialized)
        (progn
           (set-counter 0)
           (set-random 1))))

(defaction "Reset registers when hero is in the center"
   (and (hero-is-at 4 4)
        (progn
           (set-counter 0)
           (set-random 1))))

(defaction  "Increase counter every time the enter-by-plane is executed and set another register to one to force an update of the tile"
   (and (enter-by-plane)
        (progn
           (add-to-counter 1)
           (set-random 1))))

(defaction "Display counter state 0 in center tile"
   (and (random-is 1)
        (counter-is 0)
        (progn
           (place-tile 4 4 0 214)
           (set-random 0))))

(defaction "Display counter state 1 in center tile"
   (and (random-is 1)
        (counter-is 1)
        (progn
           (place-tile 4 4 0 217)
           (set-random 0))))

(defaction "Display counter state 2 in center tile"
   (and (random-is 1)
        (counter-is 2)
        (progn
           (place-tile 4 4 0 218)
           (set-random 0))))

(defaction "Display counter state 3 in center tile"
   (and (random-is 1)
        (counter-is 3)
        (progn
           (place-tile 4 4 0 219)
           (set-random 0))))

(defaction "Display counter state 4 in center tile"
   (and (random-is 1)
        (counter-is 4)
        (progn
           (place-tile 4 4 0 220)
           (set-random 0))))

If you step through the video frame by frame, you can see that the script has already been executed once the first tile is shown (1 green dot). Then after the animation has finished another dot is added.

cyco commented 3 years ago

I dumped a save game with a whole world containing all the zones you mentioned in your bug reports. 0xc000, Desert, Small.wld.zip

My next step would be to load that up in the original game, solve the zone step by step and create new save games along the way. By checking the save games we can find out if all hotspots are set up correctly.

cyco commented 3 years ago

For this specific bug I'd be interested in the state of the hotspots on zone 104 after leaving, but before returning.

Edit: Actually, scratch that, we've already established that this bug is probably due to some specific detail of executing actions in the enter-by-plane phase.

cyco commented 3 years ago

I checked all instructions of the return animation action of the original zone in the test room I mentioned early. Removing them one-by-one I isolated move-hero-to. It looks like the original implementation does not execute enter-by-plane twice when that instruction is hit.

Here's an updated version that demonstrates the difference in webfun and the original implementation: construct.data.zip