The Dink Network

Reply to Re: Bad potion script?

If you don't have an account, just leave the password field blank.
Username:
Password:
Subject:
Antispam: Enter Dink Smallwood's last name (surname) below.
Formatting: :) :( ;( :P ;) :D >( : :s :O evil cat blood
Bold font Italic font hyperlink Code tags
Message:
 
 
December 30th 2009, 10:05 PM
custom_magicman.gif
magicman
Peasant They/Them Netherlands duck
Mmmm, pizza. 
My attempt at an explanation (it also explains some other possible game freezes):

When a script runs, it runs until it is done. If so, it's the *only* thing that happens. Just the script, nothing else. Not even, say, the Dink engine doing some of its magic like player input. Just the one script.

Butbutbut, you ask, I can walk around while all kinds of scripts are running. What about that?

Simply put, most scripts are over before you know it. For anything else there are the following pausing commands, which give the engine the possibility of dealing with other stuff.

These are a few DinkC commands that tell the Dink engine something like "You can do something else now, if you want". These are say_stop(), say_stop_xy(), wait(), wait_for_button(), move_stop(), and perhaps some others (choice menus, probably? Maybe show_bmp() and activate_bow() as well...). These commands stop running the script until it's ready to continue (text has been said, a certain amount of time has expired, etc). This is where the Dink engine can choose to continue running another script, do some of its own magic, or whatever else it is that it does.

The thing with suddenly stopping die() procedures in enemies is caused by the following two things:
- Actually killing the sprite is one of those other things that the engine can choose to do.
- Killing the sprite kills the script.

So what happens:
- Dink kills monster
- Engine runs die() procedure, and makes sure that the sprite is killed whenever the engine has the chance to do something.
- die() procedure has one of the previously mentioned pausing commands.
- Engine pauses the script, and does something else.
- Engine chooses to kill the sprite.
- Engine kills sprite, and thus the script.
- Engine can no longer continue running the die() procedure.

Commonly-used workaround:
Use script_attach(1000) or script_attach(0). This causes the script to not be on the sprite anymore, so it won't be killed when the engine kills the sprite. Alternatively, put it in its own file, and use spawn(). script_attach() will remove the script from the sprite, and spawn() will run it as an independent script, so it won't be killed when the engine kills off the sprite. Note that in this case &current_sprite can't be used either, because a script needs to be on a sprite to use that.

Another note: once the sprite gets killed, its sprite number has no meaning anymore. This means that you can't just use another variable (say, &crap), and give it the value of &current_sprite, and then use &crap. When I need some post-death animation, I create a clone of the recently deceased sprite, make the deceased sprite invisible, and play around with the clone.

Something similar happens with the touch() procedure:
- Dink touches sprite
- Engine detects Dink touching the sprite
- Engine runs touch() procedure (if touch_damage is -1, of course)
- touch() procedure has one of the previously mentioned pausing commands.
- Engine pauses the script, and does something else.
- Engine detects Dink touching the sprite
- goto 3.

(there's a neat trick that the buttonon() procedure will just trigger once, and also works for Dink-brain, not just mouse-brain).

And also why the game freezes if you don't have a wait() in a loop. This can actually be relaxed to guarantee having one of the pausing commands executed in the loop. If there's no pausing command between the label and the goto, the engine will be given no chance to do anything except running the code. The player experiences this as a gamefreeze.

Hope that clears things up. There's actually more logic to how the engine decides what to do, but I can't be bothered going into that now. Check out the FIFO part of FIFO and variables in DinkC.

EDIT: Whooooaaa, dude. That was quite the post >_>

EDIT2: Right, I feel like I haven't quite said everything I wanted to say. Sorry, dear readers.

About wait(): What it does is tell the Dink engine to "stop running this for at least this amount of milliseconds". If the engine encounters a wait(100), and then does non-pausing things for more than a tenth-second, the wait(100) will take more than a tenth-second. If the engine does non-pausing things for 75 milliseconds, it won't switch back. If it then does more non-pausing things for 75 milliseconds, it can continue. This is after 150 milliseconds, not 100.

Just to make a point that wait(&crap) can't be guaranteed to take &crap milliseconds, though it's quite hard to have it do non-pausing things for 75 milliseconds.