Call for Code Samples / WML Unit Tests
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.
Re: Call for Code Samples / WML Unit Tests
Note that in general I had from WML always expected behavior. I used lot of nested events and events inside units without any problems. The only one causing unexpected behavior (for me) was in the halo case, because event inside unit was created and (tryed to be) fired in same recruit event and WML engine looked like have an exception there.iceiceice wrote:Yeah so I worked slowly to the hard case, I only put the event in the unit in test 8 above. In that case it still works though.
Be aware English is not my first language and I could have explained bad myself using wrong or just invented words.
World Conquest II
World Conquest II
Re: Call for Code Samples / WML Unit Tests
Hmm so it looks like event inside unit is handled differently from event in normal wml.
The normal wml events are handled by action_wml code:
https://github.com/wesnoth/wesnoth/blob ... l.cpp#L754
The "event inside unit" syntax referred to on the wiki is handled in the constructor of unit:
https://github.com/wesnoth/wesnoth/blob ... t.cpp#L328
It looks a bit different.
Also there is no similar code for when units are made from a unit_type, so I guess that it in that case the [event] inside [unit] won't work at all.
I think I would advise to avoid [event] inside [unit] where possible since it uses a different code path and probably won't be as reliable.
Edit: For instance, it appears the the "name=remove" thing might not work there, since that code doesn't appear in the second code path.
In conclusion, just use events normally, imo, it will be less buggy.
The normal wml events are handled by action_wml code:
https://github.com/wesnoth/wesnoth/blob ... l.cpp#L754
The "event inside unit" syntax referred to on the wiki is handled in the constructor of unit:
https://github.com/wesnoth/wesnoth/blob ... t.cpp#L328
It looks a bit different.
Also there is no similar code for when units are made from a unit_type, so I guess that it in that case the [event] inside [unit] won't work at all.
I think I would advise to avoid [event] inside [unit] where possible since it uses a different code path and probably won't be as reliable.
Edit: For instance, it appears the the "name=remove" thing might not work there, since that code doesn't appear in the second code path.
Spoiler:
Re: Call for Code Samples / WML Unit Tests
I was quite imaginig something like thaticeiceice wrote:Hmm so it looks like event inside unit is handled differently from event in normal wml.
I will be carefull now I am advised, but for campaigns is far more clean and comfortable use events inside units rather than write events in every scenario "just in case some unit could need it"iceiceice wrote:I think I would advise to avoid [event] inside [unit] where possible since it uses a different code path and probably won't be as reliable.
Be aware English is not my first language and I could have explained bad myself using wrong or just invented words.
World Conquest II
World Conquest II
Re: Call for Code Samples / WML Unit Tests
Just posting again, so that you don't miss my repost with the spoiler:
From code inspection, it looks that currently there is a bug with modification events that will cause broken replays because they will not be fired, I assume it affects all versions.
Edit: Actually I guess that might only affect the "replay stop" button? Anyways I guess everyone knows that thing is quite buggy...
Edit: Okay, here's my impl of the feeding ability you posted. This is also committed, but if you want to suggest a change / post an alternative implementation feel free. For instance this doesn't test the delayed variables thing, I guess could add a version that adds according to the level.
I might separately debug the [event] inside [unit], but I'm done writing tests for today. I think the constructor of unit needs to add a line about the id of the unit for it to work but I haven't tested so I don't really know.
From code inspection, it looks that currently there is a bug with modification events that will cause broken replays because they will not be fired, I assume it affects all versions.
Edit: Actually I guess that might only affect the "replay stop" button? Anyways I guess everyone knows that thing is quite buggy...
Edit: Okay, here's my impl of the feeding ability you posted. This is also committed, but if you want to suggest a change / post an alternative implementation feel free. For instance this doesn't test the delayed variables thing, I guess could add a version that adds according to the level.
I might separately debug the [event] inside [unit], but I'm done writing tests for today. I think the constructor of unit needs to add a line about the id of the unit for it to work but I haven't tested so I don't really know.
Code: Select all
# This unit test defines a WML object based implementation of the "feeding" ability
# and checks that it works. What is being tested here, beyond what is tested in
# test_unit_map and other scenarios that test the attack pathway, is that
# - the die event works
# - objects attach to units by id correctly
# - abilities can be properly detected in filters
# - abilities which add other objects works
# - this impl of feeding works
#define STR_FEEDING
foo
#enddef
#define STR_FEEDING_EFFECT
bar
#enddef
#define STR_FEEDING_DESCRIPTION
baz
#enddef
#define TEST_FEEDING ID EXPECTED_INCREASE
[store_unit]
[filter]
id={ID}
[/filter]
variable=Killer
[/store_unit]
{VARIABLE victim_x $Killer.x}
{VARIABLE_OP victim_x sub 1}
{VARIABLE victim_y $Killer.y}
{VARIABLE victim_side 3}
{VARIABLE_OP victim_side sub $Killer.side|}
{VARIABLE Killer_start_hp $Killer.hitpoints}
[terrain_mask]
x,y=$victim_x|,$victim_y|
mask="Xv"
[/terrain_mask]
{UNIT $victim_side| "Elvish Archer" $victim_x| $victim_y| (hitpoints=1)}
[do_command]
[attack]
weapon = 0
defender_weapon = 0
[source]
x,y=$Killer.x|,$Killer.y|
[/source]
[destination]
x,y=$victim_x|,$victim_y|
[/destination]
[/attack]
[/do_command]
[store_unit]
[filter]
id={ID}
[/filter]
variable=Killer
[/store_unit]
{VARIABLE_OP Killer_start_hp add {EXPECTED_INCREASE}}
{ASSERT ({VARIABLE_CONDITIONAL Killer.hitpoints equals $Killer_start_hp})}
#enddef
{GENERIC_UNIT_TEST "feeding" (
[event]
id=ability_feeding_die
name=die
first_time_only=no
[filter]
[not]
[filter_wml]
[status]
not_living="yes"
[/status]
[/filter_wml]
[/not]
[/filter]
[filter_second]
ability=feeding
[/filter_second]
[unstore_unit]
variable=second_unit
{COLOR_HEAL}
text= {STR_FEEDING_EFFECT}
find_vacant=no
[/unstore_unit]
[object]
silent=yes
duration=forever
[filter]
x,y=$x2|,$y2|
[/filter]
[effect]
apply_to=hitpoints
increase_total=1
increase=1
[/effect]
[/object]
[/event]
[event]
name=start
[object]
id=feeding_object
silent=yes
[effect]
apply_to=new_ability
[abilities]
[dummy]
id=feeding
name= {STR_FEEDING}
female_name= {STR_FEEDING}
description= {STR_FEEDING_DESCRIPTION}
[/dummy]
[/abilities]
[/effect]
[filter]
id=bob
[/filter]
[/object]
[/event]
[event]
name=start
{TEST_FEEDING alice 0}
{TEST_FEEDING alice 0}
{TEST_FEEDING alice 0}
[end_turn]
[/end_turn]
[/event]
[event]
name = side 2 turn 1
{TEST_FEEDING bob 1}
{TEST_FEEDING bob 1}
{TEST_FEEDING bob 1}
[store_unit]
[filter]
id=bob
[/filter]
variable=Bob
[/store_unit]
{VARIABLE_OP Bob.experience add 50}
[unstore_unit]
variable=Bob
[/unstore_unit]
{TEST_FEEDING bob 1}
{TEST_FEEDING bob 1}
{TEST_FEEDING bob 1}
{RETURN ([true][/true])}
[/event]
)}