I am probably missing something obvious, but I can't seem to make a floor trigger operated by the party only when facing a given direction (say, north.)
There are two problems to solve. 1) The party must not set the trigger when it steps on it facing anything but north. 2) If, while standing on the obj.trigger, the party turns to face north, the trigger should get, well, triggered. And of course, turning away from north should release the trigger. A basic obj.trigger instance triggers when stepped on, regardless of direction, and does nothing when the party turns while standing on it.
- Giving the obj.trigger instance a 'face' exvar doesn't prevent the trigger from acting when stepped on while facing the wrong direction.
- Giving it an on_turn exvar set to 'on_turn = floor_trigger' does not do anything. floor_trigger is the function that gets called when the trigger is stepped on, but clearly whatever happens on party turning, it doesn't involve checking the exvars of triggers.
- Modifying the obj.trigger archetype to add one line to it 'on_turn = floor_trigger,' does nothing most of the time and crashes DSB sometimes (when facing north (0)?)
- I have tried leaving the trigger as is and making it activate a function_caller object, but how do these even work? I do not know. And how would I get the activation to occur when the party turns? Can the function caller deactivate the trigger? would that be enough?
_ I have thought about putting a telporter on that tile as well, with a delay of one tick for its activation, that would teleport the party to the same tile, in the hopes of deactivating-reactivating the trigger, but I suspect that might lead to infinite telportation and, frankly, it shouldn't be that complicated.
I have spend several hours on this problem now, and I am no closer to a working solution. Any help would be appreciated.
(done) Directional trigger
Moderator: Sophia
Forum rules
Please read the Forum rules and policies before posting. You may
to help finance the hosting costs of this forum.
Please read the Forum rules and policies before posting. You may

- Sophia
- Concise and Honest
- Posts: 4307
- Joined: Thu Sep 12, 2002 9:50 pm
- Location: Nowhere in particular
- Contact:
Re: Directional trigger
Don't feel bad. It's actually a bit tricky, because there are two distinct events to concern ourselves with.Parallax wrote:I am probably missing something obvious, but I can't seem to make a floor trigger operated by the party only when facing a given direction (say, north.)
To solve this problem, you could simply put the the trigger itself on the NORTH instead of CENTER of the tile. This is as far as the problem needs to go with objects.Parallax wrote:The party must not set the trigger when it steps on it facing anything but north.
However, it won't yet completely solve our problems with the party, because there's still the second issue:
Normally, the on_turn event on the trigger sitting on the NORTH will be fired when the party turns north, but nothing will happen when the party turns away. This will thus not work with the standard triggers that need to support things like trigger counts and constant weight. However, this is how things like stairs that don't need such fancy features work. If a simple trigger is enough, something like this will suffice:Parallax wrote:If, while standing on the obj.trigger, the party turns to face north, the trigger should get, well, triggered. And of course, turning away from north should release the trigger
Code: Select all
function party_trigger(self, id, what)
-- If there is no triggering inst, it must be the party
if (what == nil) then
got_triggered(id, nil)
end
end
function party_turn(self, id)
got_triggered(id, nil)
end
If you want full-fledged triggers, things get (quite a bit) more complicated.
on_turn events (along with all other events) are associated with object archs, not exvars. So, this is just the wrong place for this kind of thing.Parallax wrote:Giving it an on_turn exvar set to 'on_turn = floor_trigger' does not do anything.
This is because on_turn takes a different parameter list than on_trigger. Its parameters are on_turn(self, id, dir); it does not take a triggering object because DSB only handles this by default when the party turns. On the other hand, on_trigger takes (self, id, what). So, the engine was taking the direction passed as an inst id of a triggering object. (inst id 0 is illegal, hence the crash on NORTH)Parallax wrote:Modifying the obj.trigger archetype to add one line to it 'on_turn = floor_trigger,' does nothing most of the time and crashes DSB sometimes (when facing north (0)?)
So, how to handle the more complicated triggers? Well, first, we'd better put the trigger back in the CENTER of the tile, because we'll handle things in our custom code rather than letting the engine do it.
Around line 362 of base/triggers.lua you'll find code like this:
Code: Select all
if (exvar[id].opby_party == true) then
return true
end
Code: Select all
if (exvar[id].opby_party == true) then
if (not exvar[id].opby_party_face) then
return true
end
local lev, x, y, face = dsb_party_coords()
if (face == exvar[id].opby_party_face) then
return true
end
end
Code: Select all
function trigger_turn(self, id, dir)
if (not exvar[id] or not exvar[id].opby_party_face) then
return nil
end
if (exvar[id].opby_party_face == dir) then
floor_trigger(self, id, nil)
elseif (exvar[id].opby_party_face == g_old_dir) then
local store_face = exvar[id].opby_party_face
exvar[id].opby_party_face = dir
floor_trigger_off(self, id, nil)
exvar[id].opby_party_face = store_face
end
end
You'll notice a couple of hacks in order to emulate the functionality of an off_trigger when we don't really have one. In order to make one of these hacks work we'll have to override sys_party_turn, too.
Code: Select all
function sys_party_turn(dir)
g_old_dir = dir
end
If this last chunk of code seems very complicated, well... that's because it is. Depending on how well it works, I may merge this into the base code, but I'm not sure, because I'm sure there are some issues I haven't spotted yet.
EDIT: After looking at this code a bit more, I've determined that if I'm going to be adding this to a new version, I could modify the core engine a bit to make this less hackish... I am probably going to add an off_turn event to eliminate most of the strangeness with the turn events. However, the idea behind being able to use a either a trigger on a specific direction (NORTH, SOUTH, etc. instead of CENTER) or an opby_party_face exvar on a centered trigger should remain the same.
- Parallax
- DMwiki contributor
- Posts: 424
- Joined: Mon Aug 28, 2006 7:56 pm
- Location: Back in New Jersey
Thank you for the in-depth explanation. I think I understand most of the lua code you wrote, although it would have taken me a very long time to figure it out and write it right on my own. I was really expecting "here's what you missed" followed by a 10-second solution involving the proper exvar.
I'm very much in favor of incorporating these changes, along with the new exvar opby_party_face, for the next version of DSB.
I am also not quite certain what you're doing here:
Why store opby_party_face, then override it, then call a function that cannot possibly know about it, then restore it? And even if it is, for some reason, necessary to overwrite opby_party_face before calling floor_trigger_off, can't we restore it simply by assigning it the value of g_old_dir, since that's where it started the loop? Surely floor_trigger_off is not going to turn the party, right?
Another thing is, in the beginning, you say to put the trigger on the NORTH (=0) side of the cell. But the only way for a floor trigger to get walked on is if the cell is open, in which case 0 is the direction of a corner (the northwestern one?) of the cell. I was under the impression that this was how you made triggers that got activated only if a character was standing on the proper subtile, but regardless of what direction the party is facing. I have not looked into subtile triggers at all so I could be completely wrong about that though, but I'm curious.
I'm very much in favor of incorporating these changes, along with the new exvar opby_party_face, for the next version of DSB.
I am also not quite certain what you're doing here:
Code: Select all
elseif (exvar[id].opby_party_face == g_old_dir) then
local store_face = exvar[id].opby_party_face
exvar[id].opby_party_face = dir
floor_trigger_off(self, id, nil)
exvar[id].opby_party_face = store_face
end
Another thing is, in the beginning, you say to put the trigger on the NORTH (=0) side of the cell. But the only way for a floor trigger to get walked on is if the cell is open, in which case 0 is the direction of a corner (the northwestern one?) of the cell. I was under the impression that this was how you made triggers that got activated only if a character was standing on the proper subtile, but regardless of what direction the party is facing. I have not looked into subtile triggers at all so I could be completely wrong about that though, but I'm curious.
- Sophia
- Concise and Honest
- Posts: 4307
- Joined: Thu Sep 12, 2002 9:50 pm
- Location: Nowhere in particular
- Contact:
I am too.Parallax wrote:I'm very much in favor of incorporating these changes, along with the new exvar opby_party_face, for the next version of DSB.

I've got an early version working and if I may say so it's quite nice. I've determined it's not that much additional work to allow the triggers to work in both ways, so that's what I'm going to allow-- you can either put the trigger on one side of the tile, or put it in the CENTER and set an opby_party_face, and in both cases, it'll do what you expect.
This is one of those ugly hacks.Parallax wrote:Why store opby_party_face, then override it, then call a function that cannot possibly know about it, then restore it?

The function does know about it, because it calls is_opby, and we modified is_opby up there. However, that version of is_opby tries to match the opby direction with the party's current direction: when they're moving off a trigger, that's the wrong direction. So, we have to tweak the opby direction.
I don't know. Truthfully, after all of the weird things you people have done to DSB, I try to not make assumptions like that.Parallax wrote:And even if it is, for some reason, necessary to overwrite opby_party_face before calling floor_trigger_off, can't we restore it simply by assigning it the value of g_old_dir, since that's where it started the loop? Surely floor_trigger_off is not going to turn the party, right?

Well, actually, it's both. DSB tiles have 5 subtile positions, numbered 0-4. Position 4 is always the CENTER. However, what exactly positions 0-3 mean varies depending on what code is handling it. For objects lying on an open tile, it's the corners. For objects on walls, it is the cardinal directions. However, it's really just a number-- 0-3. So, when you're putting a trigger on the NORTH side of a tile, yes, you're actually putting it in the NORTHWEST corner. When the party walks over the tile, though, the triggers executed are chosen based on their facing, which is based on the cardinal directions. This means that something on the NORTHWEST (corner 0) will be processed when the party is facing NORTH (direction 0).Parallax wrote:Another thing is, in the beginning, you say to put the trigger on the NORTH (=0) side of the cell. But the only way for a floor trigger to get walked on is if the cell is open, in which case 0 is the direction of a corner (the northwestern one?) of the cell.
In many cases, it's ok, as directional triggers will be opby either the party or an object, not both. You can use the system of corners for objects and the system of cardinal directions for the party, things in alcoves, and so on. Still, the weirdness this system can create is why I decided to support both directional triggers and the opby_party_face exvar.
No, though that would be pretty great, and could be done by some custom code.Parallax wrote:I was under the impression that this was how you made triggers that got activated only if a character was standing on the proper subtile, but regardless of what direction the party is facing. I have not looked into subtile triggers at all so I could be completely wrong about that though, but I'm curious.
I'll have to think about that one!

Right now, though, the game doesn't care about the content of the party when a trigger is operated by the party. The "direction" is determined by the party's facing.
- Parallax
- DMwiki contributor
- Posts: 424
- Joined: Mon Aug 28, 2006 7:56 pm
- Location: Back in New Jersey
That's nice, and it will keep it working somewhat smoothly with DDM, since I don't think there's going to be a DDM update anytime soon.Sophia wrote:I've got an early version working and if I may say so it's quite nice. I've determined it's not that much additional work to allow the triggers to work in both ways, so that's what I'm going to allow-- you can either put the trigger on one side of the tile, or put it in the CENTER and set an opby_party_face, and in both cases, it'll do what you expect.
We have done nothing that you have not allowed.Sophia wrote:Truthfully, after all of the weird things you people have done to DSB, I try to not make assumptions like that.

Parallax wrote:I was under the impression that this was how you made triggers that got activated only if a character was standing on the proper subtile, but regardless of what direction the party is facing. I have not looked into subtile triggers at all so I could be completely wrong about that though, but I'm curious.
Well, I went and serched for that topic in the DSB subforum, and I cannot find it. I found Remy's discussion of the directional trigger problem (shame on me, tsk tskSophia wrote:No, though that would be pretty great, and could be done by some custom code.
I'll have to think about that one!
Right now, though, the game doesn't care about the content of the party when a trigger is operated by the party. The "direction" is determined by the party's facing.

This leaves me with only one question: What is the function_caller object and how do you use it? OK, I guess that's two questions.
- Sophia
- Concise and Honest
- Posts: 4307
- Joined: Thu Sep 12, 2002 9:50 pm
- Location: Nowhere in particular
- Contact:
It calls Lua functions. (Ok, that's not very helpful)Parallax wrote:What is the function_caller object and how do you use it? OK, I guess that's two questions.
Truthfully, it has been somewhat deprecated by the "func" exvar, but if you want something to call functions in response to messages, it still may be useful. I think it could stand to be a bit better documented, though, as the interface isn't all that clear without reading through the code.
If you want to call the Lua function activate_func in response to a M_ACTIVATE, set it up like this:
Code: Select all
exvar[func_caller_id].m_a = "activate_func"
- Parallax
- DMwiki contributor
- Posts: 424
- Joined: Mon Aug 28, 2006 7:56 pm
- Location: Back in New Jersey
Thanks for the explanation. It would be great to have a manual, or at least some tutorials, on DSB.* Right now looking at the code is the best way to learn how DSB works, and that's not a very user-friendly way.**
*: No, I am not volunteering to write them.
**: I know you never claimed DSB was user-friendly. I can dream, can't I?
*: No, I am not volunteering to write them.
**: I know you never claimed DSB was user-friendly. I can dream, can't I?
