Question on "name=unit placed" events
Moderator: Forum Moderators
Forum rules
- Please use [code] BBCode tags in your posts for embedding WML snippets.
- To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
Question on "name=unit placed" events
I ran into a strange bug related to a "name=unit placed" event, and I could use some help understanding it. To give some context, I have a scenario where a player (side=1) controls a large number of walking corpses. At the end of the player's turn, any WCs that haven't moved have their side switched to an AI (side=2). The AI then moves them, and gives control back to the player at the end of its turn. I use a "unit placed" event to make sure any WCs created by plague while the AI is in control are immediately given back to the player.
Now for the bug: it seems like AFTER "side turn" and "turn refresh" for the AI's turn, the WCs are deleted and re-placed, which triggers the "unit placed" event. I am pretty confident that none of my custom events are doing this deletion. So, I'm wondering if there is any internal Wesnoth mechanism that might explain it? At first, I thought maybe they were being stored/unstored as part of the 'resting' mechanic. But then I realized that this was happening after "turn refresh", so that doesn't make sense.
I've attached a save if you want to see for yourself. Just load it and end turn immediately. You'll get a bunch of debug message for each step in this process.
Now for the bug: it seems like AFTER "side turn" and "turn refresh" for the AI's turn, the WCs are deleted and re-placed, which triggers the "unit placed" event. I am pretty confident that none of my custom events are doing this deletion. So, I'm wondering if there is any internal Wesnoth mechanism that might explain it? At first, I thought maybe they were being stored/unstored as part of the 'resting' mechanic. But then I realized that this was happening after "turn refresh", so that doesn't make sense.
I've attached a save if you want to see for yourself. Just load it and end turn immediately. You'll get a bunch of debug message for each step in this process.
- Attachments
-
- 2p - Monster Hunt Turn 4 DEBUGGING.gz
- (123.07 KiB) Downloaded 42 times
Re: Question on "name=unit placed" events
I am not going to download this file, but description sounds like unit id conflict.
Note that even if that is not the case, unit placed it allowed to trigger any time and it is your responsibility to filter if it should do something or not.
Note that even if that is not the case, unit placed it allowed to trigger any time and it is your responsibility to filter if it should do something or not.
Re: Question on "name=unit placed" events
None of the walking corpses have been given an id. I understand that I can control the event with a filter, and I have "solved" my current bug by doing just that. But the fact that this was an issue in the first place still does not make sense to me, and I'm trying to understand it better so I don't have issues with future bugs.
To better illustrate my point: I have removed ALL but 5 [event]s from the attached save. I have also simplified these 5 events as much as possible. The only actual action performed by any of these events is to display a [message] and change unit sides using [modify_unit]. The units are being deleted/re-placed after turn refresh, but before the AI makes any move. None of the 5 events match this timing. So like I said, I'm pretty confident I didn't write any WML that is deleting these units. I'm just trying to figure out what could be responsible.
Code: Select all
[event]
first_time_only=no
name="side_turn"
[message]
speaker=narrator
message="TESTING START TURN"
[/message]
[/event]
[event]
first_time_only=no
name="turn_refresh"
[message]
speaker=narrator
message="TESTING TURN REFRESH"
[/message]
[/event]
[event]
first_time_only=no
name="side_turn_end"
[if]
[variable]
equals="1"
name="side_number"
[/variable]
[then]
[message]
speaker=narrator
message="GIVE WALKING CORPSES TO AI..."
[/message]
[modify_unit]
side="2"
[filter]
type=Walking Corpse
side=1
[/filter]
[/modify_unit]
[/then]
[/if]
[/event]
[event]
first_time_only=no
name="side_turn_end"
[if]
[variable]
equals="2"
name="side_number"
[/variable]
[then]
[message]
speaker=narrator
message="GIVE WALKING CORPSES BACK TO PLAYER..."
[/message]
[modify_unit]
side="1"
[filter]
type=Walking Corpse
side=2
[/filter]
[/modify_unit]
[/then]
[/if]
[/event]
[event]
first_time_only=no
name="unit_placed"
[if]
[variable]
equals="2"
name="unit.side"
[/variable]
[and]
[variable]
name="unit.canrecruit"
not_equals=yes
[/variable]
[/and]
[then]
[message]
speaker=narrator
message="UNIT_PLACED EVENT TRIGGERED"
[/message]
[modify_unit]
side="1"
[filter]
x="$x1"
y="$y1"
[/filter]
[/modify_unit]
[/then]
[/if]
[/event]
- Attachments
-
- 2p - Monster Hunt Turn 4 DEBUGGING.gz
- (83.67 KiB) Downloaded 38 times
Re: Question on "name=unit placed" events
You can simplify side_turn_end to side_1_turn_end, side_2_turn_end.
Re: Question on "name=unit placed" events
Are you sure that
Also, are you sure that you even need
unit_placed
isn't firing when you give the units to the AI side? (So that they end up being given back immediately.)Also, are you sure that you even need
unit_placed
for this at all? I notice that the documentation for unit_placed
says, "This event is solely intended for special cases where no other event types suffice..." So it sounds like they are recommending that it be avoided if possible and used only as a last resort. I'm not sure why the documentation recommends this - possibly it is because the event is tricky to use, or perhaps because it is genuinely buggy in some cases. Wouldn't it be possible to avoid using unit_placed
by simply transferring all the AI units (including those that were created by plague) at the end of the AI's turn?Re: Question on "name=unit placed" events
It is probably just matter of timing, whether attack_end triggers too soon to transfer them.
Changing side at turn end removes chance from AI to kill the corpses.
Changing side at turn end removes chance from AI to kill the corpses.
Re: Question on "name=unit placed" events
True, but I don't think that explains the deletion of the units.
Yes, I'm quite sure. Using the debug statements I can watch each step of the process. At the end of the side 1 turn, I can see all the corpses switch to side 2. Then, at the start of the side 2 turn it pauses with another debug message and nothing changes. Then, I can watch 'resting' zombies get 2 healing, followed by the debug message at side 2 refresh. All the zombies are still on the map with side=2 at this point. AFTER the refresh event, all the zombies disappear from the map and are placed again (still side=2), one at a time. This triggers the "unit_placed" event each time, which I can watch using a debug message.
You're right, I don't actually need to use unit_placed, although the real scenario is a little more complicated than this example so I can't just modify side for every zombie at the end of the turn. I switched to using unit_placed because it simplified things. I'll note that despite the warning on the wiki, there is no indication that unit_placed itself is misbehaving. Units are in fact being placed, and it is triggering exactly as I would expect. The mystery is why those units are deleted/re-placed after turn refresh and without any obvious events to cause it.gnombat wrote: ↑March 17th, 2024, 8:02 pm Also, are you sure that you even needunit_placed
for this at all? I notice that the documentation forunit_placed
says, "This event is solely intended for special cases where no other event types suffice..." So it sounds like they are recommending that it be avoided if possible and used only as a last resort. I'm not sure why the documentation recommends this - possibly it is because the event is tricky to use, or perhaps because it is genuinely buggy in some cases. Wouldn't it be possible to avoid usingunit_placed
by simply transferring all the AI units (including those that were created by plague) at the end of the AI's turn?
I don't think it is a timing issue, as there are several events between when the zombies change sides, and when they disappear. I'm not sure what you mean re: attack_end?
- beetlenaut
- Developer
- Posts: 2828
- Joined: December 8th, 2007, 3:21 am
- Location: Washington State
- Contact:
Re: Question on "name=unit placed" events
I tried it, and I see what you mean. There is nothing in the code you showed us that could cause this problem though. I even tried these events in one of my scenarios to make sure there wasn't some sort of engine bug, and apparently there wasn't. They worked as expected, and no units got deleted. The problem is in another part of your code. If you zip up and post the whole add-on, I'm pretty sure someone will find it.
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
Re: Question on "name=unit placed" events
I've attached the entire scenario if you're curious, but I really don't want anyone to waste their time digging through it. It may be an issue in my code, but in the previously attached save I went and manually removed every single [event] except the 5 I posted in this thread. So if this unit deletion isn't happening in an event, what other tags should I be suspicious of? I also went and deleted all the menus from the attached save, since there's some logic there even if I wouldn't expect it to be executed. At this point, the save seems to be entirely map, side definitions, some default AI candidate actions, and a whole lot of units and variables. But no logic actually using those variables. Just those 5 harmless events.beetlenaut wrote: ↑March 18th, 2024, 5:07 pmI tried it, and I see what you mean. There is nothing in the code you showed us that could cause this problem though. I even tried these events in one of my scenarios to make sure there wasn't some sort of engine bug, and apparently there wasn't. They worked as expected, and no units got deleted. The problem is in another part of your code. If you zip up and post the whole add-on, I'm pretty sure someone will find it.
- Attachments
-
- 2p - Monster Hunt Turn 4 DEBUGGING.gz
- (66.75 KiB) Downloaded 27 times
-
- monster_hunt.zip
- (37.96 KiB) Downloaded 26 times
Re: Question on "name=unit placed" events
Upon testing this, it looks like it is in fact an internal Wesnoth mechanism triggering these events: the AI itself seems to be doing it (meaning the code which controls the AI).Limabean wrote: ↑March 17th, 2024, 4:00 am it seems like AFTER "side turn" and "turn refresh" for the AI's turn, the WCs are deleted and re-placed, which triggers the "unit placed" event. I am pretty confident that none of my custom events are doing this deletion. So, I'm wondering if there is any internal Wesnoth mechanism that might explain it?
The code is in data/ai/lua/battle_calcs.lua - see the comments in lines 1170, 1171, and 1186.
An easy way to reproduce this is:
- Add the following code to any scenario in any campaign (I used the first scenario of the WML Guide campaign, but I would guess pretty much any campaign/scenario would work).
Code: Select all
[event] name=unit_placed first_time_only=no [lua] code = << wesnoth.message(debug.traceback()) >> [/lua] [message] speaker=narrator message="unit_placed $unit.id $unit.x $unit.y" [/message] [/event]
- Play a few turns until a battle starts and some AI units are wounded. Then observe what happens on the AI's turn.
- beetlenaut
- Developer
- Posts: 2828
- Joined: December 8th, 2007, 3:21 am
- Location: Washington State
- Contact:
Re: Question on "name=unit placed" events
So part of the internal AI calculations removes a bunch of units for a millisecond, then puts them right back. I don't think unit_placed events should be triggered by that code. They will be triggered constantly at a time nobody expects. (See: this thread.) I would even say this is a bug, so it could be fixed before 1.18 is final.
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
Re: Question on "name=unit placed" events
Well, 1.18.0 has been tagged already, so I doubt the bug is going to be fixed before the release. (Maybe it could be fixed in 1.18.1 or a later bugfix release.)
I guess the safest thing is to do what Ravana suggested and just assume that the
I guess the safest thing is to do what Ravana suggested and just assume that the
unit_placed
event can trigger at any time, for any reason at all (or no apparent reason at all).Re: Question on "name=unit placed" events
Lua is taken from local file, it is not sent over network unless wrapped in [lua]. It is probably oos to change this behaviour in 1.18 when something reacts to unit placed.
Re: Question on "name=unit placed" events
Wow, that is awesome, thanks for taking the time to check this out. It was driving me crazy.gnombat wrote: ↑March 19th, 2024, 4:35 amUpon testing this, it looks like it is in fact an internal Wesnoth mechanism triggering these events: the AI itself seems to be doing it (meaning the code which controls the AI).Limabean wrote: ↑March 17th, 2024, 4:00 am it seems like AFTER "side turn" and "turn refresh" for the AI's turn, the WCs are deleted and re-placed, which triggers the "unit placed" event. I am pretty confident that none of my custom events are doing this deletion. So, I'm wondering if there is any internal Wesnoth mechanism that might explain it?
The code is in data/ai/lua/battle_calcs.lua - see the comments in lines 1170, 1171, and 1186.
An easy way to reproduce this is:
- Add the following code to any scenario in any campaign (I used the first scenario of the WML Guide campaign, but I would guess pretty much any campaign/scenario would work).
Code: Select all
[event] name=unit_placed first_time_only=no [lua] code = << wesnoth.message(debug.traceback()) >> [/lua] [message] speaker=narrator message="unit_placed $unit.id $unit.x $unit.y" [/message] [/event]
- Play a few turns until a battle starts and some AI units are wounded. Then observe what happens on the AI's turn.