Exploiting 'x_relay's for scriptless timers...
Moderator: Sophia
Forum rules
Please read the Forum rules and policies before posting.
Please read the Forum rules and policies before posting.
Exploiting 'x_relay's for scriptless timers...
While making the editor, I've been 'testing' it's usability by trying to recreate the original DM dungeon. While I'm not hugely worried about accuracy (there's already a DSB DM dungeon available, why make another?), I've been trying to at least get the mechanics working.
From what I've read, the 'x_relay' arch was created so that porting FTL's dungeons through RTSB could be simplified. Because of that, and it's supposed 'limited use in from-scratch DSB dungeons', I've tried to avoid using it as much as possible. But there are a couple of cases when I've found it useful.
Most triggers* in DSB work in a specific way - when they are 'operated', they fire a message at a target (both the message and the target(s) are specified by exvars). How a trigger gets operated is dictated by various exvars (the 'opby's, but 'air' and 'air_only' fall into this group as well), though most deal with something the player does.
'x_relay's are different in that they are operated by messages**, which means they can do some nifty things that triggers normally can't. I've found them useful in two situations in particular.
The first is in sending multiple messages of different types*** (such as different message values or different delays). For example, if you want the player to push a button to activate a teleporter, then want the teleporter to deactivate after a short delay, you can use an 'x_relay'.
When the button is operated, it fires an M_ACTIVATE message to both the x_relay and the teleporter. The 'x_relay' has it's exvars set to fire a M_DEACTIVATE with a delay of 10 at the teleporter. The result is that when the button is pressed, the teleporter activates and the relay is operated, firing it's own message (M_DEACTIVATE) with a 10 tick delay, shutting the teleporter back down.
The second case is if you want to start a message loop; because an 'x_relay' is operated by messages, it can operate itself, setting up a loop. This is useful if you want a continuous operation - such as a door that goes up and down over and over, and the player has to race beneath it.
To set this up, we'd create a door and an 'x_relay', as well as a floor trigger for our "starter". The floor trigger fires an M_ACTIVATE message at the x_relay to initiate the loop. The x_relay is set to fire a M_TOGGLE message at both itself and the door, with a delay of 6. So, when the floor trigger message arrives, it fires those messages - after 6 ticks, the door toggles, and the x_relay is operated again, firing two new messages.
* - Triggers include lots of things in DSB; almost every wall decoration I tested is, in fact, a trigger in disguise. That isn't true with floor decorations, but the invisible floor trigger can be used with anything on top of it.
** - The one message that doesn't work with 'x_relay's is M_DEACTIVATE. This shuts down the x_relay without it operating. Of course, if it's in a messaging loop, it'll recieve an M_TOGGLE message later and reactivate.
*** - This can be duplicated with two triggers being operated at the same time, such as two floor triggers on the same tile or two buttons overlapping on a wall. I don't like this method, because it's harder to see what's going on by just looking at it in the editor (you'd have to select the tile to see it has two buttons or triggers), but it's useful if you need to fire a M_DEACTIVATE message first, since that would normally shut an 'x_relay' down. If you do it this way, be sure to silence one of the triggers (if they make a noise), since two will cause a wierd "echo".
I should note that I'm unsure how stable the message looping is; that is, I don't know what would happen if you had lots of these going on, and the message queue gets over-crowded. I know there are certain archtypes that use looping (like monster generators), but I'm unclear of the actual mechanics of how DSB decides to pay attention to them (do generators work on levels the player is not located?).
Obviously, the best way to accomplish this sort of thing is with scripting, but as I was trying to avoid that, I thought I'd point these out. (I did say the editor could recreate the original DM dungeon without scripting, after all, and I know some people are going to try to do just that sort of thing).
From what I've read, the 'x_relay' arch was created so that porting FTL's dungeons through RTSB could be simplified. Because of that, and it's supposed 'limited use in from-scratch DSB dungeons', I've tried to avoid using it as much as possible. But there are a couple of cases when I've found it useful.
Most triggers* in DSB work in a specific way - when they are 'operated', they fire a message at a target (both the message and the target(s) are specified by exvars). How a trigger gets operated is dictated by various exvars (the 'opby's, but 'air' and 'air_only' fall into this group as well), though most deal with something the player does.
'x_relay's are different in that they are operated by messages**, which means they can do some nifty things that triggers normally can't. I've found them useful in two situations in particular.
The first is in sending multiple messages of different types*** (such as different message values or different delays). For example, if you want the player to push a button to activate a teleporter, then want the teleporter to deactivate after a short delay, you can use an 'x_relay'.
When the button is operated, it fires an M_ACTIVATE message to both the x_relay and the teleporter. The 'x_relay' has it's exvars set to fire a M_DEACTIVATE with a delay of 10 at the teleporter. The result is that when the button is pressed, the teleporter activates and the relay is operated, firing it's own message (M_DEACTIVATE) with a 10 tick delay, shutting the teleporter back down.
The second case is if you want to start a message loop; because an 'x_relay' is operated by messages, it can operate itself, setting up a loop. This is useful if you want a continuous operation - such as a door that goes up and down over and over, and the player has to race beneath it.
To set this up, we'd create a door and an 'x_relay', as well as a floor trigger for our "starter". The floor trigger fires an M_ACTIVATE message at the x_relay to initiate the loop. The x_relay is set to fire a M_TOGGLE message at both itself and the door, with a delay of 6. So, when the floor trigger message arrives, it fires those messages - after 6 ticks, the door toggles, and the x_relay is operated again, firing two new messages.
* - Triggers include lots of things in DSB; almost every wall decoration I tested is, in fact, a trigger in disguise. That isn't true with floor decorations, but the invisible floor trigger can be used with anything on top of it.
** - The one message that doesn't work with 'x_relay's is M_DEACTIVATE. This shuts down the x_relay without it operating. Of course, if it's in a messaging loop, it'll recieve an M_TOGGLE message later and reactivate.
*** - This can be duplicated with two triggers being operated at the same time, such as two floor triggers on the same tile or two buttons overlapping on a wall. I don't like this method, because it's harder to see what's going on by just looking at it in the editor (you'd have to select the tile to see it has two buttons or triggers), but it's useful if you need to fire a M_DEACTIVATE message first, since that would normally shut an 'x_relay' down. If you do it this way, be sure to silence one of the triggers (if they make a noise), since two will cause a wierd "echo".
I should note that I'm unsure how stable the message looping is; that is, I don't know what would happen if you had lots of these going on, and the message queue gets over-crowded. I know there are certain archtypes that use looping (like monster generators), but I'm unclear of the actual mechanics of how DSB decides to pay attention to them (do generators work on levels the player is not located?).
Obviously, the best way to accomplish this sort of thing is with scripting, but as I was trying to avoid that, I thought I'd point these out. (I did say the editor could recreate the original DM dungeon without scripting, after all, and I know some people are going to try to do just that sort of thing).
- Sophia
- Concise and Honest
- Posts: 4240
- Joined: Thu Sep 12, 2002 9:50 pm
- Location: Nowhere in particular
- Contact:
Re: Exploiting 'x_relay's for scriptless timers...
I'm going to be totally blunt: I don't like "x_relay." I feel it should not be used in new dungeons. (That is, dungeons created specifically for DSB, rather than converted from DM/CSB/RTC/whatever) The x_ in front of its name is there because it's a hack, and sticking an x_ in front of the name seemed a good way to set it apart.
My intention in DSB was to get away from the "apples and teleporters" school of thought, though. There's nothing inherently wrong with it-- it's just that the dungeon turns into a twisted mess of esoteric hacks very, very quickly.
The fact remains, though-- right now, there are still some good uses for "x_relay." I think the solution would be to come up with a more "DSB-spirted" way of doing it, though, rather than using lots of "x_relay" insts.
So something like:
would send a M_ACTIVATE to targ_1 immediately, and send a M_DEACTIVATE to targ_2 after 12 ticks.
(This doesn't work in DSB 0.20, but it will in DSB 0.21 unless we find something significantly wrong with this idea)
I may have to give this one more thought!
To answer the second question, monster generators will work whenever activated. Original DM did a lot of suppression of timers and such for levels the party wasn't on, in order to save the already overtasked CPU; this concern doesn't apply to DSB so timers generated by a dsb_msg will run no matter where in the dungeon their associated instance is.
You're pretty much correct. It was actually created to emulate RTC's WALLITEM_RELAY. RTC, like original DM, has no scripting ability, so to create any sort of complicated effects, complex chains of triggers, relays, etc., are needed. Both of the uses of "x_relay" you've described below are used quite commonly in RTC dungeons for creating the very effects you described.RemyR wrote:From what I've read, the 'x_relay' arch was created so that porting FTL's dungeons through RTSB could be simplified. Because of that, and it's supposed 'limited use in from-scratch DSB dungeons', I've tried to avoid using it as much as possible. But there are a couple of cases when I've found it useful.
My intention in DSB was to get away from the "apples and teleporters" school of thought, though. There's nothing inherently wrong with it-- it's just that the dungeon turns into a twisted mess of esoteric hacks very, very quickly.
The fact remains, though-- right now, there are still some good uses for "x_relay." I think the solution would be to come up with a more "DSB-spirted" way of doing it, though, rather than using lots of "x_relay" insts.
It seems like changing the base code to support a message type and a delay that are also stored as tables just like the targets would be a simpler, more direct approach, and eliminate the need for an "x_relay" here.RemyR wrote:The first is in sending multiple messages of different types (such as different message values or different delays). For example, if you want the player to push a button to activate a teleporter, then want the teleporter to deactivate after a short delay, you can use an 'x_relay'.
So something like:
Code: Select all
target = { targ_1, targ 2}
msg = { M_ACTIVATE, M_DEACTIVATE }
delay = { 0, 12 }
(This doesn't work in DSB 0.20, but it will in DSB 0.21 unless we find something significantly wrong with this idea)
This one is a bit trickier. Objects in DSB can handle messages however the designer chooses, of course, so the door itself could be made to re-activate itself as needed, but, that's not the most generic solution, and it also requires custom code-- not that that's a problem, as most DSB dungeons will, but for something this simple, it seems like there should be an easy, elegant way. A recurring exvar comes to mind, but, of course, there'd have to be a way to stop that loop, too... that's also a problem with "x_relay," mind you.RemyR wrote:The second case is if you want to start a message loop; because an 'x_relay' is operated by messages, it can operate itself, setting up a loop. This is useful if you want a continuous operation - such as a door that goes up and down over and over, and the player has to race beneath it.
I may have to give this one more thought!
It's perfectly stable. DSB dynamically resizes the message queue as needed, so its length is limited only by available memory.RemyR wrote:I should note that I'm unsure how stable the message looping is; that is, I don't know what would happen if you had lots of these going on, and the message queue gets over-crowded. I know there are certain archtypes that use looping (like monster generators), but I'm unclear of the actual mechanics of how DSB decides to pay attention to them (do generators work on levels the player is not located?).
To answer the second question, monster generators will work whenever activated. Original DM did a lot of suppression of timers and such for levels the party wasn't on, in order to save the already overtasked CPU; this concern doesn't apply to DSB so timers generated by a dsb_msg will run no matter where in the dungeon their associated instance is.
I think x_relay and x_counter are ugly, because they involve using a dungeon instance to control the behavior of other instances, instead of using a script.
But their good point is that they provide a point and click way of designing mechanism, that gets well with the design of an editor.
The good point of x_relay, is that to kill a message loop, you just need to destroy the relay, and it can save some time writing control scripts.
The good point of x_counter, is that it provides an all-made counter, and a lot of riddles actually need counting something.
As for implementing a "recurring" message, I have a proposal :
In combination with the above multiple message design, the addition of :
M_TRIGGER : force execution of got_triggered for target instance
M_UNTRIGGER : force execution of got_untriggered for target instance
Add a mechanical exvar :
is_mute (or whatever), if this exvar is set to true, the instance won't send any further message (disables the execution of "got_triggered" and "got_untriggered")
M_MUTE sets is_mute to true
M_UNMUTE sets is mute to nil
It allows to control a loop, and to interrupt it without destroying the instance.
There might be some subtleties to take care of
( e.g. a constant_weight pad, receiving a M_MUTE message would be forever activated with the current design...)
But that's the downside (or is it of lua : if people want to do bad things with the engine, they can.
But their good point is that they provide a point and click way of designing mechanism, that gets well with the design of an editor.
The good point of x_relay, is that to kill a message loop, you just need to destroy the relay, and it can save some time writing control scripts.
The good point of x_counter, is that it provides an all-made counter, and a lot of riddles actually need counting something.
As for implementing a "recurring" message, I have a proposal :
In combination with the above multiple message design, the addition of :
M_TRIGGER : force execution of got_triggered for target instance
M_UNTRIGGER : force execution of got_untriggered for target instance
Add a mechanical exvar :
is_mute (or whatever), if this exvar is set to true, the instance won't send any further message (disables the execution of "got_triggered" and "got_untriggered")
M_MUTE sets is_mute to true
M_UNMUTE sets is mute to nil
It allows to control a loop, and to interrupt it without destroying the instance.
There might be some subtleties to take care of
( e.g. a constant_weight pad, receiving a M_MUTE message would be forever activated with the current design...)
But that's the downside (or is it of lua : if people want to do bad things with the engine, they can.
What Is Your Quest ?
- Parallax
- DMwiki contributor
- Posts: 424
- Joined: Mon Aug 28, 2006 7:56 pm
- Location: Back in New Jersey
I have been wondering about a general porblem that fits well in the x_relay discussion, so I'll submit it here.
Let's take Sophia' example of the exvars as tables.
Let's also assume that both targets are the same, and what we want to do is to activate the target for a limited but significant time dt.
If the activation mechanism is triggered once, at time t1, then triggered again before its first expiration, at time t2<t1+dt, what happens?
What I might want for it to happen might be that the timer is reset so that the target remains activated all the way to t2+dt. In practice, however, that does not work. The timeline is as follows:
t1: activation, the target is activated. A deactivation message is scheduled for t1+dt.
t2: activation again, nothing happens since the target is already active. A deactivation message is sent for t2+dt.
t1+dt: deactivation message reaches the target. Target deactivated.
t2+dt: second deactivation has no effect.
In other words, everything happens as if the second activation never took place. My question is, how would you modify this system so that the second activation 'cancels' the first deactivation? I think I had this discussion once with Sophia in FC, but the answer at the time involved unique flags for messages and I have no idea I would implement it.
Let's take Sophia' example of the exvars as tables.
Let's also assume that both targets are the same, and what we want to do is to activate the target for a limited but significant time dt.
If the activation mechanism is triggered once, at time t1, then triggered again before its first expiration, at time t2<t1+dt, what happens?
What I might want for it to happen might be that the timer is reset so that the target remains activated all the way to t2+dt. In practice, however, that does not work. The timeline is as follows:
t1: activation, the target is activated. A deactivation message is scheduled for t1+dt.
t2: activation again, nothing happens since the target is already active. A deactivation message is sent for t2+dt.
t1+dt: deactivation message reaches the target. Target deactivated.
t2+dt: second deactivation has no effect.
In other words, everything happens as if the second activation never took place. My question is, how would you modify this system so that the second activation 'cancels' the first deactivation? I think I had this discussion once with Sophia in FC, but the answer at the time involved unique flags for messages and I have no idea I would implement it.
- Sophia
- Concise and Honest
- Posts: 4240
- Joined: Thu Sep 12, 2002 9:50 pm
- Location: Nowhere in particular
- Contact:
Well, that works once.Joramund wrote:The good point of x_relay, is that to kill a message loop, you just need to destroy the relay, and it can save some time writing control scripts.
Destroying the relay isn't the best solution if you want to be able to turn the loop on and off at will.
True, but also remember that there is a count exvar provided for most simpler applications of this.Joramund wrote:The good point of x_counter, is that it provides an all-made counter, and a lot of riddles actually need counting something.
Not bad, though, practically speaking, I wonder how well it'd work with opbys and such... it's definitely something to think about, though.Joramund wrote:M_TRIGGER : force execution of got_triggered for target instance
M_UNTRIGGER : force execution of got_untriggered for target instance
I'd implement some kind of activation counting system:Parallax wrote:What I might want for it to happen might be that the timer is reset so that the target remains activated all the way to t2+dt. In practice, however, that does not work. The timeline is as follows:
t1: activation, the target is activated. A deactivation message is scheduled for t1+dt.
t2: activation again, nothing happens since the target is already active. A deactivation message is sent for t2+dt.
t1+dt: deactivation message reaches the target. Target deactivated.
t2+dt: second deactivation has no effect.
t1: activation, the target is activated. A deactivation message is scheduled for t1+dt. The activation count is increased to 1.
t2: activation again, nothing happens, but the count is increased to 2.
t1+dt: deactivation message reaches the target. The count is reduced to 1.
t2+dt: second deactivation reduces the count back to 0, and the target is deactivated.
For many objects, this behavior is not desirable, as they should switch on and off on the first message they get regardless of any superfluous messages, so I'm not going to change the base code for everything-- it might be a worthwhile option if it can be folded in without making the system (very much) uglier, though.
I actually tried to write a script to do this (sort of), but I got stuck on a particular question. if thisIt seems like changing the base code to support a message type and a delay that are also stored as tables just like the targets would be a simpler, more direct approach, and eliminate the need for an "x_relay" here.
Code: Select all
target = {targ_1, targ_2}
msg = M_TOGGLE
delay = 0
Code: Select all
target = {targ_1, targ_2}
msg = {M_TOGGLE, M_TOGGLE}
delay = {0, 0}
Code: Select all
target = {targ_1, targ_2}
msg = M_TOGGLE
delay = {0, 12}
Code: Select all
target = targ_1
msg - M_TOGGLE
delay = {0, 12}
Now that I think about it, my script for got_triggered never ignores a tabled 'delay' . What breaks it is if there are tables in both 'target' and 'delay' and their number of elements aren't the same. This:
Code: Select all
target = {targ_1, targ_2, targ_3}
msg = M_TOGGLE
delay = {0, 12}
I'm planning on removing the 'x_counter' from the editor's Archtype Library, for the same reason I don't use a 'translate_dungeon' call at the end of generated code: it leads to un-DSB ways of doing things (both can, of course, be added by the designer).True, but also remember that there is a count exvar provided for most simpler applications of this.
That worries me, too, because you'd need a new variable to tell the instance it can only be triggered by it's 'opby's, it can only be triggered by 'M_TRIGGER's, or both.Not bad, though, practically speaking, I wonder how well it'd work with opbys and such... it's definitely something to think about, though.
Here's why: let's say you have two pads (Pad_1, and Pad_2) and a door (Door). Pad_1 gets stepped on - it triggers, firing an M_UNMUTE at itself (I'll explain why in a moment) first, an M_TOGGLE at Door, and an M_TRIGGER at itself with a delay (we'll say 10). 10 ticks later, it's supposed to receive M_TRIGGER and repeat those messages.
But what happens if the player steps on Pad_1 again? Another loop starts. Let's say they do it 5 ticks into the first loop. Now, Door is recieving M_TOGGLEs every 5 ticks. If they step on it again (and again), the Door is going to go haywire (I once did this with an 'x_relay' loop).
So, we need a way to disable Pad_1 from being triggered by it's opbys, without killing it with disable_self (which eliminates it's target exvar, rendering it useless). We also have to not totally disable it (with dsb_disable), because it still needs to react to M_TRIGGER. So we 'switch' it to M_TRIGGER_ONLY_MODE mode when it gets triggered. That's another message that must be included with got_triggered.
Now, the player makes it by Door, and steps on Pad_2. Pad_2 fires an M_MUTE at Pad_1 to stop it looping, and also fires a message to put it in OPBY_ONLY_MODE, because it'll still have M_TRIGGERs in the Message Queue. This also lets the Player go back and step on Pad_1, starting the loop again. That's why it needs to M_UNMUTE itself, by the way.
I scripted (though, it remains untested) a very simple msg_generator archtype, that basically functions like a monster_generator except that it calls dsb_msg instead of dsb_spawn. Well, actually it calls got_triggered, since that includes all the nifty code for multiple targets and such, but it's basically the same idea. The nice part about it is that I could have expanded it to include an 'mcounter' - so that you could specify the number of times it loops, and it can be deactivated with a simple M_DEACTIVATE message. It doesn't have the 'x_relay' problem of not being able to use this message, since it doesn't ever fire it's exvar.msg at itself.
Unfortunately, it doesn't encapsulate the ability of being triggered by messages in triggers, but it also doesn't require what I found ugly about 'x_relay' in the first place - the hackish need to send messages to itself (the M_TRIGGER method still needs this - as well as a few other messages that need to passed around).
- Sophia
- Concise and Honest
- Posts: 4240
- Joined: Thu Sep 12, 2002 9:50 pm
- Location: Nowhere in particular
- Contact:
As I have it implemented now, it will send two messages:RemyR wrote:I have to wonder what this:Code: Select all
target = {targ_1, targ_2} msg = M_TOGGLE delay = {0, 12}
should do.
M_TOGGLE to targ_1 after no delay, and M_TOGGLE to targ_2 after a delay of 12.
I don't think there's really any problem with not handling this intelligently because there's not really an intelligent way to handle it.RemyR wrote:What breaks it is if there are tables in both 'target' and 'delay' and their number of elements aren't the same.
My implementation expects that if target is a table, then delay and msg will also be tables of the same length, or a single argument, which is taken as shorthand for a table of equal size of all the same thing. (For example, in this case, { M_TOGGLE, M_TOGGLE })
I think that's reasonable enough.
Actually, it's even stickier than that. Your version assumes that M_TRIGGER has a sane handling of the tc exvar, and I'm not even sure how that should work. If M_TRIGGER raises the trigger count, the situation can get very sticky very fast for the designer. If it doesn't, then-- well, what then? Does every M_TRIGGER assume an immediate untrigger afterwards? Or does it just trigger and not affect the trigger count, which makes things a bit weird if the party is standing on the trigger! How should this affect constant weight?RemyR wrote:let's say you have two pads (Pad_1, and Pad_2) and a door (Door). Pad_1 gets stepped on - it triggers, firing an M_UNMUTE at itself (I'll explain why in a moment) first, an M_TOGGLE at Door, and an M_TRIGGER at itself with a delay (we'll say 10). 10 ticks later, it's supposed to receive M_TRIGGER and repeat those messages.
But what happens if the player steps on Pad_1 again? Another loop starts.
It starts to make "x_relay" seem sane, really!
I wouldn't file this one away as inherently bad.RemyR wrote:the hackish need to send messages to itself
Doors send themselves messages to continue to go up or down. Clouds send themselves messages to disappear or reduce in size. There are uses for it. In this case, though, you're probably right-- there has to be a better way. Your "msg_generator" seems like it might be something a bit more 'DSBish' but still offering a similar functionality.
I like this idea of a msg generator.
With enough parameters, it would provide an "encapsulated" control script, very good for an editor.
Even with the ability to script and copy&paste in Lua, I think a few simple thing should be doable in the editor,
and stuff like the counters in DM or CSB should have a reasonable way of being reproduced.
msg_generator should definetely start sending messages when activated, and stop at once when deactivated. It should not be able to enter into multiple loops like x_relay can do... unless the designer want it of course.
In order to be useful, such a generator need a lot of control variables :
- [ target, msg, delay ] to define one "run"
- [ count, interval, disable_self ... ]
- running (to track if the generator is running and shouldn't start another thread), run_count (to keep track of the number of runs, in case one wants to restart the generator with the same parameters later in the game)
etc.
EDIT : also, I don't exactly know how things are timed in dsb...
- what happens if I call a function in dungeon.lua just after dsb_party_place() and this function calls dsb_msg_chain or something like that, to make timed events ?
- what is the cleanest way to make a series of "absolutely-timed" events in a dungeon ?
With enough parameters, it would provide an "encapsulated" control script, very good for an editor.
Even with the ability to script and copy&paste in Lua, I think a few simple thing should be doable in the editor,
and stuff like the counters in DM or CSB should have a reasonable way of being reproduced.
msg_generator should definetely start sending messages when activated, and stop at once when deactivated. It should not be able to enter into multiple loops like x_relay can do... unless the designer want it of course.
In order to be useful, such a generator need a lot of control variables :
- [ target, msg, delay ] to define one "run"
- [ count, interval, disable_self ... ]
- running (to track if the generator is running and shouldn't start another thread), run_count (to keep track of the number of runs, in case one wants to restart the generator with the same parameters later in the game)
etc.
EDIT : also, I don't exactly know how things are timed in dsb...
- what happens if I call a function in dungeon.lua just after dsb_party_place() and this function calls dsb_msg_chain or something like that, to make timed events ?
- what is the cleanest way to make a series of "absolutely-timed" events in a dungeon ?
What Is Your Quest ?
Well, currently the 'msg_generator' is broken - I think this is actually another issue (and I'll start another thread in a moment), but to get through a few of your suggestions...
then added champions to the party, and it worked just fine. You could, in fact, use multiple 'dsb_party_place's to move the party around during creation, but I really couldn't fathom why (this might be useful to do later - if, for example, you had an 'Event Screen' where the player could choose his starting place in the dungeon - but that's rather pointless during the compiling of the dungeon).
I'd do it with a global variable and override 'sys_tick', but I'm pretty cavalier about overriding base functions to get things to work. I also don't know how well that would work, since I just realized I don't know if sys_tick starts "ticking" when you first enter the dungeon, or when DSB first loads the dungeon, which might be bad. (I think the proper way would be with an archtype that has a message handler for, say M_NEXTTICK - or, even better, your own Message Values - and have a trigger at the dungeon's starting square that sends out a series of M_NEXTTICKs (or, your own message values) to it, with the proper delays, but I don't know if those get saved with a savegame).
And, back up to Sophia:
Well, because I just have the msg_generator call got_triggered, it uses target, msg, delay, count, and disable_self automatically. I'm not sure what 'interval' is, but if you mean the time between got_triggered calls, it uses the 'regen' exvar. Which means that 'regen' and 'delay' will stack, which might not be what you want. Techncally, it uses the GF_INACTIVE flag to determine whether it can operate, so that multiple messages don't start multiple loops (I'll bring this up in the other thread).In order to be useful, such a generator need a lot of control variables :
- [ target, msg, delay ] to define one "run"
- [ count, interval, disable_self ... ]
- running...
You can do a dsb_party_place whenever you feel like, as long as the 'place' you put the party exists - that is, the level has been created. The editor used to place the party right after it generated the level they were starting on, then spawned all the instances (and made 'dsb_msg_chain' calls) and exvars,what happens if I call a function in dungeon.lua just after dsb_party_place() and this function calls dsb_msg_chain or something like that, to make timed events ?
then added champions to the party, and it worked just fine. You could, in fact, use multiple 'dsb_party_place's to move the party around during creation, but I really couldn't fathom why (this might be useful to do later - if, for example, you had an 'Event Screen' where the player could choose his starting place in the dungeon - but that's rather pointless during the compiling of the dungeon).
That depends on how you define "clean".- what is the cleanest way to make a series of "absolutely-timed" events in a dungeon ?
I'd do it with a global variable and override 'sys_tick', but I'm pretty cavalier about overriding base functions to get things to work. I also don't know how well that would work, since I just realized I don't know if sys_tick starts "ticking" when you first enter the dungeon, or when DSB first loads the dungeon, which might be bad. (I think the proper way would be with an archtype that has a message handler for, say M_NEXTTICK - or, even better, your own Message Values - and have a trigger at the dungeon's starting square that sends out a series of M_NEXTTICKs (or, your own message values) to it, with the proper delays, but I don't know if those get saved with a savegame).
And, back up to Sophia:
I should rephrase - I don't like the fact that the designer has to make instances send themselves messages to get a particular function to work correctly. That, to me, says you're better off designing something to handle that particular function. Doors, clouds, and even my msg_generator send themselves messages - but it's not something you have to "add" to get functionality, it's encapsulated within the archtypes themselves.I wouldn't file this one away as inherently bad.
- Sophia
- Concise and Honest
- Posts: 4240
- Joined: Thu Sep 12, 2002 9:50 pm
- Location: Nowhere in particular
- Contact:
As it happens, it also depends on how you define "absolute."RemyR wrote:That depends on how you define "clean".- what is the cleanest way to make a series of "absolutely-timed" events in a dungeon ?
By default, DSB ticks along at 5 ticks per second, but, just like DM, it also generates an extra tick whenever the party takes a step. So, if the party is dashing along at a pretty good speed, there may be more than 5 ticks generated in a second.
They do. The only things in the message queue that don't get retained in a savegame are calls to dsb_delay_func, mostly because I don't have any clue how to save a reference to an arbitrary Lua function.RemyR wrote:but I don't know if those get saved with a savegame
So, if I want to make an event happen, for exemple after rougly 10 minutes of game time,
I just have to make a dsb_msg(10*60*7,id,msg,data,[sender]) ?
There is no problem with saving a function this way :
Any function can be attached to a message handler
BTW, I don't think having a "savegame-leak" (dsb_delay_func) function is a good idea.
I just have to make a dsb_msg(10*60*7,id,msg,data,[sender]) ?
There is no problem with saving a function this way :
Any function can be attached to a message handler
BTW, I don't think having a "savegame-leak" (dsb_delay_func) function is a good idea.
What Is Your Quest ?
- Sophia
- Concise and Honest
- Posts: 4240
- Joined: Thu Sep 12, 2002 9:50 pm
- Location: Nowhere in particular
- Contact:
That might be close if the party is dashing around a lot.Joramund wrote:So, if I want to make an event happen, for exemple after rougly 10 minutes of game time,
I just have to make a dsb_msg(10*60*7,id,msg,data,[sender]) ?
10*60*5 would be a better formula if they're just standing still.
Sometimes it's nice to have. In particular, dsb_delay_func timers continue to run even while the game is locked (it is thus impossible to save, eliminating the problem), so they're very useful for "cut scenes." For example, the fusing Chaos animation is handled by a series of dsb_delay_funcs.Joramund wrote:BTW, I don't think having a "savegame-leak" (dsb_delay_func) function is a good idea.