Boxdroppers and rapid destruction of multiple WCCs
Quote from Dewin on January 9, 2008, 5:21 amThought I'd post about this since it's a problem I encountered on my map and came up with a fix for.
Say you have a map that involves multiple weighted storage cubes, but only one box dropper.
Triggering the box dropper every time a cube gets destroyed can cause interesting things if two cubes get destroyed simultaneously or near-simultaneously. For instance, you might end up with two cubes stuck inside the dropper (instead of the usual one cube that is waiting for the next trigger), or something else. Either way, while you're likely to get one cube back, you're not likely to get all of them.
My solution was this:
1. Create a math_counter. Give it an initial value of -1, min and max of 0.
2. On the env_entity_maker part of the boxdropper (i.e. CP4P_dropper_boxmaker_1 if you are using CP4P prefabs), add an output for:
My output named: OnEntitySpawned
Target: name_of_math_counter
Target Input: add
Target Value: 13. Create a logic_compare. Set its Initial Value to 0 and Compare Value to the minimum number of boxes that should be existing at the time.
For its outputs, add:
My output named: OnLessThan
<<stuff to trigger your boxdropper here. For example (CP4P): CP4P_boxdropper_trigger=>Trigger>>4. On the math_counter, add:
OutValue => name_of_logic_compare => SetValue
with no parameter override5. Create a trigger_multiple covering the area around the box dropper. Set its Delay Before Reset to 4.
The only Flags that should be set are "Client". For its outputs, add
OnTrigger => name_of_logic_compare => Compare6. On any object that destroys a box, add the appropriate outputs to Subtract 1 from the math_counter.
If all works well, you'll have a box dropper that will replenish destroyed (or not yet spawned) boxes at a rate of 1 every 4 seconds until the requisite number has been made.
Notes:
1. Make sure there's space for all your boxes to be created, else you may clog the dropper.
2. It's important that the math_counter start at -1 instead of 0, since the boxdropper has always spawned one more box than is really available (the box that is 'waiting' at the bottom)
3. I tried doing this without the logic_compare using min/max values on the counter and SetHitMin/SetHitMax trickery. Don't try it, it doesn't work. If a counter has a max of 3 and a min of 2 with OnHitMin set to change min to -1, and has a current value of 3 and receives two Subtract(1) events simultaneously, the second will be clamped (thus keeping it at a value of 2, not 1) before the SetHitMin event fires, thus only one replacement box will be issued.
Thought I'd post about this since it's a problem I encountered on my map and came up with a fix for.
Say you have a map that involves multiple weighted storage cubes, but only one box dropper.
Triggering the box dropper every time a cube gets destroyed can cause interesting things if two cubes get destroyed simultaneously or near-simultaneously. For instance, you might end up with two cubes stuck inside the dropper (instead of the usual one cube that is waiting for the next trigger), or something else. Either way, while you're likely to get one cube back, you're not likely to get all of them.
My solution was this:
1. Create a math_counter. Give it an initial value of -1, min and max of 0.
2. On the env_entity_maker part of the boxdropper (i.e. CP4P_dropper_boxmaker_1 if you are using CP4P prefabs), add an output for:
My output named: OnEntitySpawned
Target: name_of_math_counter
Target Input: add
Target Value: 1
3. Create a logic_compare. Set its Initial Value to 0 and Compare Value to the minimum number of boxes that should be existing at the time.
For its outputs, add:
My output named: OnLessThan
<<stuff to trigger your boxdropper here. For example (CP4P): CP4P_boxdropper_trigger=>Trigger>>
4. On the math_counter, add:
OutValue => name_of_logic_compare => SetValue
with no parameter override
5. Create a trigger_multiple covering the area around the box dropper. Set its Delay Before Reset to 4.
The only Flags that should be set are "Client". For its outputs, add
OnTrigger => name_of_logic_compare => Compare
6. On any object that destroys a box, add the appropriate outputs to Subtract 1 from the math_counter.
If all works well, you'll have a box dropper that will replenish destroyed (or not yet spawned) boxes at a rate of 1 every 4 seconds until the requisite number has been made.
Notes:
1. Make sure there's space for all your boxes to be created, else you may clog the dropper.
2. It's important that the math_counter start at -1 instead of 0, since the boxdropper has always spawned one more box than is really available (the box that is 'waiting' at the bottom)
3. I tried doing this without the logic_compare using min/max values on the counter and SetHitMin/SetHitMax trickery. Don't try it, it doesn't work. If a counter has a max of 3 and a min of 2 with OnHitMin set to change min to -1, and has a current value of 3 and receives two Subtract(1) events simultaneously, the second will be clamped (thus keeping it at a value of 2, not 1) before the SetHitMin event fires, thus only one replacement box will be issued.
Quote from DaMaGepy on January 9, 2008, 3:04 pmI made a math counter too, and a timer. If there is 4 box and all destroyed at the same time, after every destruction it adds 1 to the counter and if a box created them removes 1. If its not 0 then it activates a timer that spawns a box every 2 sec until there are no boxes in the queue. Simple and safe.
I posted my map sources before, just check the map 03, the room with 5 button and 4 box and a box dropper before the last big room:
http://heroes.hardwired.hu/-/portal/damagepy_source.zip
I made a math counter too, and a timer. If there is 4 box and all destroyed at the same time, after every destruction it adds 1 to the counter and if a box created them removes 1. If its not 0 then it activates a timer that spawns a box every 2 sec until there are no boxes in the queue. Simple and safe.
I posted my map sources before, just check the map 03, the room with 5 button and 4 box and a box dropper before the last big room:
http://heroes.hardwired.hu/-/portal/damagepy_source.zip
Quote from Hunter on January 9, 2008, 7:56 pmSo you can use a trigger_multiple OR a logic_timer to accomplish this task. My question is, which is more efficient? Obviously, a logic_timer, being a point entity, takes up less space in the file, but it activates every few seconds as long as the map is loaded. To prevent that from happening, you could have triggers at the start and end of the puzzle that uses the dropper, but that would negate the file size advantage. I guess the more important thing is how much overhead is required by trigger collision detection. Anyone know anything about that?
So you can use a trigger_multiple OR a logic_timer to accomplish this task. My question is, which is more efficient? Obviously, a logic_timer, being a point entity, takes up less space in the file, but it activates every few seconds as long as the map is loaded. To prevent that from happening, you could have triggers at the start and end of the puzzle that uses the dropper, but that would negate the file size advantage. I guess the more important thing is how much overhead is required by trigger collision detection. Anyone know anything about that?
Quote from Dewin on January 9, 2008, 8:25 pmI prefer the trigger method myself, because I like to not generate the box until the player is near it. (The idea being that this will cause the player to actually *see* the box being generated, and it will draw their attention to it.)
The catch in this case is that the player might walk out of the trigger while it is still generating boxes... they might wait for 1, grab it and leave before the other two are generated. This doesn't permanently break anything (the trigger will still happily generate more as soon as the player comes back), but still is not perfect.
In reality, however, there is no need for a logic_timer at all even if you aren't using a trigger. Simply have your env_entity_maker run the compare event 4 seconds after it spawns the box, such that:
env_entity_maker OnEntitySpawned => math_counter Add 1 in 0.00
env_entity_maker OnEntitySpawned => logic_compare Compare in 4.00
math_counter Outvalue => logic_compare SetValue in 0.00
logic_compare OnLessThan => env_entity_maker Forcespawn in 0.00This gives you a loop where the env_entity_maker will effectively check to see if it should make a new box every 4 seconds (until it no longer needs to, at which point the loop is broken.). There's only two more things required to make it work:
1. a logic_auto (or similiar) to ForceSpawn the env_entity_maker to get the initial 'waiting' box spawned. (But you need this anyways), and
2. Call math_counter Subtract 1 any time a box is lost.The catch to doing it this way is you no longer have precise control over when boxes are released -- they'll be released as soon as they're required, instead of waiting for the player to be near the dropper. Well, it might be possible to get around this by disabling/enabling the entity_spawner... which would be the route to go if you had multiple boxdroppers and wanted the first one the player approached to give a box without having extra boxes....
Multiple boxes sharing one counter:
Same setup as before, but the math_counter's initial value is negative N, where N is the number of boxdroppers. (3 boxdroppers = -3)
logic_auto OnMapSpawn => env_entity_maker* ForceSpawn @ 0.00
logic_auto OnMapSpawn => env_entity_maker* Disable @ 0.01then a proximity trigger near each box dropper:
trigger_multiple OnTrigger => env_entity_maker* Disable @ 0.00
trigger_multiple OnTrigger => env_entity_maker_4 Enable @ 0.01
trigger_multiple OnTrigger => logic_compare Compaer @ 0.02
I prefer the trigger method myself, because I like to not generate the box until the player is near it. (The idea being that this will cause the player to actually *see* the box being generated, and it will draw their attention to it.)
The catch in this case is that the player might walk out of the trigger while it is still generating boxes... they might wait for 1, grab it and leave before the other two are generated. This doesn't permanently break anything (the trigger will still happily generate more as soon as the player comes back), but still is not perfect.
In reality, however, there is no need for a logic_timer at all even if you aren't using a trigger. Simply have your env_entity_maker run the compare event 4 seconds after it spawns the box, such that:
env_entity_maker OnEntitySpawned => math_counter Add 1 in 0.00
env_entity_maker OnEntitySpawned => logic_compare Compare in 4.00
math_counter Outvalue => logic_compare SetValue in 0.00
logic_compare OnLessThan => env_entity_maker Forcespawn in 0.00
This gives you a loop where the env_entity_maker will effectively check to see if it should make a new box every 4 seconds (until it no longer needs to, at which point the loop is broken.). There's only two more things required to make it work:
1. a logic_auto (or similiar) to ForceSpawn the env_entity_maker to get the initial 'waiting' box spawned. (But you need this anyways), and
2. Call math_counter Subtract 1 any time a box is lost.
The catch to doing it this way is you no longer have precise control over when boxes are released -- they'll be released as soon as they're required, instead of waiting for the player to be near the dropper. Well, it might be possible to get around this by disabling/enabling the entity_spawner... which would be the route to go if you had multiple boxdroppers and wanted the first one the player approached to give a box without having extra boxes....
Multiple boxes sharing one counter:
Same setup as before, but the math_counter's initial value is negative N, where N is the number of boxdroppers. (3 boxdroppers = -3)
logic_auto OnMapSpawn => env_entity_maker* ForceSpawn @ 0.00
logic_auto OnMapSpawn => env_entity_maker* Disable @ 0.01
then a proximity trigger near each box dropper:
trigger_multiple OnTrigger => env_entity_maker* Disable @ 0.00
trigger_multiple OnTrigger => env_entity_maker_4 Enable @ 0.01
trigger_multiple OnTrigger => logic_compare Compaer @ 0.02
Quote from username on January 9, 2008, 8:26 pmHunter wrote:So you can use a trigger_multiple OR a logic_timer to accomplish this task. My question is, which is more efficient? Obviously, a logic_timer, being a point entity, takes up less space in the file, but it activates every few seconds as long as the map is loaded. To prevent that from happening, you could have triggers at the start and end of the puzzle that uses the dropper, but that would negate the file size advantage. I guess the more important thing is how much overhead is required by trigger collision detection. Anyone know anything about that?The overhead is negligible, unless you're using hundreds of triggers in a small area. The only triggers checked are the ones that the player could see in their visleaf.
The overhead is negligible, unless you're using hundreds of triggers in a small area. The only triggers checked are the ones that the player could see in their visleaf.
Quote from msleeper on January 9, 2008, 8:26 pmHunter wrote:My question is, which is more efficient? Obviously, a logic_timer, being a point entity, takes up less space in the file, but it activates every few seconds as long as the map is loaded.This is more or less not entirely correct. The amount of file space difference between using a logic_timer or a trigger_multiple is completely negligible, we're talking less than 1 KB at absolute most for each entity.
As for what is more expensive in-game to operate and use, that is also a null issue. Handling logic entities doesn't even show up as a blip on a budget screen until you start getting into extreme amounts and/or calculations using them, which figuring out if a new WCC should be created isn't one of them. It takes more processing power for the engine to render a single WCC than it would to send 1,000 messages telling it to create a new one.
The logic_timer vs trigger_multiple comes down mostly to preference, and also partly to practice - how do you want your box dropper to work? Personally, I'd suggest not using logic_timer and use logic_relay, and having two logic_relays and a trigger_multiple:
- The first relay is fired at the beginning of the chain, when the cube is destroyed. The OnDestroyed or OnOutOfWorld or whatever Outputs you are using, fires a Trigger to this first relay. After a 1 or 2 second delay, it Outputs to the spawner to create a new cube and enables the trigger_multiple.
- The trigger_multiple sits at the bottom of the dropper. It does an OnStartTouch -> Trigger on the second relay.
- The second logic_relay, after 1 or 2 seconds, Disables the trigger_multiple and fires the Open animation for the box dropper door. After another 1 or 2 seconds, it fires the Close animation, and that's it.
This is more or less not entirely correct. The amount of file space difference between using a logic_timer or a trigger_multiple is completely negligible, we're talking less than 1 KB at absolute most for each entity.
As for what is more expensive in-game to operate and use, that is also a null issue. Handling logic entities doesn't even show up as a blip on a budget screen until you start getting into extreme amounts and/or calculations using them, which figuring out if a new WCC should be created isn't one of them. It takes more processing power for the engine to render a single WCC than it would to send 1,000 messages telling it to create a new one.
The logic_timer vs trigger_multiple comes down mostly to preference, and also partly to practice - how do you want your box dropper to work? Personally, I'd suggest not using logic_timer and use logic_relay, and having two logic_relays and a trigger_multiple:
- The first relay is fired at the beginning of the chain, when the cube is destroyed. The OnDestroyed or OnOutOfWorld or whatever Outputs you are using, fires a Trigger to this first relay. After a 1 or 2 second delay, it Outputs to the spawner to create a new cube and enables the trigger_multiple.
- The trigger_multiple sits at the bottom of the dropper. It does an OnStartTouch -> Trigger on the second relay.
- The second logic_relay, after 1 or 2 seconds, Disables the trigger_multiple and fires the Open animation for the box dropper door. After another 1 or 2 seconds, it fires the Close animation, and that's it.
Please do not Private Message me for assistance. Post a thread if you have questions or concerns.
If you need to contact the staff privately, contact the Global Moderators via Discord.
Quote from Hunter on January 10, 2008, 7:03 pmmsleeper wrote:This is more or less not entirely correct. The amount of file space difference between using a logic_timer or a trigger_multiple is completely negligible, we're talking less than 1 KB at absolute most for each entity.But there is a difference. Besides, I'm sure some idiot will manage to make a map where the triggers and logic are more costly than the physics and graphics, so it doesn't hurt to think about these things. (NB: I don't intend to be that idiot.)
Also, it looks like what you're describing is for a single box dropper, but it shouldn't be too hard to adapt those logic_relays to work with a multiple box dropper. Just throw in a math_counter and a few inputs and outputs to make sure there's only one box in the tube at a time, and there you go.
But there is a difference. Besides, I'm sure some idiot will manage to make a map where the triggers and logic are more costly than the physics and graphics, so it doesn't hurt to think about these things. (NB: I don't intend to be that idiot.)
Also, it looks like what you're describing is for a single box dropper, but it shouldn't be too hard to adapt those logic_relays to work with a multiple box dropper. Just throw in a math_counter and a few inputs and outputs to make sure there's only one box in the tube at a time, and there you go.
Quote from msleeper on January 10, 2008, 7:44 pmYou could have a sort of master logic_relay that sends commands to dropper-specific logic_relays.
You could have a sort of master logic_relay that sends commands to dropper-specific logic_relays.
Please do not Private Message me for assistance. Post a thread if you have questions or concerns.
If you need to contact the staff privately, contact the Global Moderators via Discord.
Quote from Hunter on January 10, 2008, 9:19 pmEh, sorry. When I said "multiple box droppers," I meant "multiple-box" droppers. As in, a single dropper that is designed to keep more than one box in play. Of course, there are probably situations where the reverse would be handy, but that's not what this thread is about.
Eh, sorry. When I said "multiple box droppers," I meant "multiple-box" droppers. As in, a single dropper that is designed to keep more than one box in play. Of course, there are probably situations where the reverse would be handy, but that's not what this thread is about.