Implement event priority
For any given event name, events execute in order of decreasing priority. Priority is a real number, and may be assigned via the `priority` attribute for the WML [event] tag, or through the Lua APIs: - wesnoth.game_events.add({priority = number}) - wesnoth.game_events.add_repeating(name, action, [priority]) Note that delayed variable substitution is not currently supported in the WML attribute.
This commit is contained in:
parent
9887d0ca26
commit
5ebc9a790a
17 changed files with 509 additions and 10 deletions
|
@ -126,6 +126,7 @@
|
|||
{SIMPLE_KEY filter_formula string}
|
||||
{DEFAULT_KEY first_time_only bool yes}
|
||||
{DEFAULT_KEY delayed_variable_substitution bool no}
|
||||
{DEFAULT_KEY priority s_real 0.0}
|
||||
|
||||
{FILTER_TAG "filter" unit ()}
|
||||
{FILTER_TAG "filter_second" unit ()}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#####
|
||||
# API(s) being tested: wesnoth.game_events.add
|
||||
##
|
||||
# Actions:
|
||||
# Use lua's game_events.add to attach a low-priority "new turn" event.
|
||||
# Use lua's game_events.add to attach a high-priority "new turn" event.
|
||||
##
|
||||
# Expected end state:
|
||||
# The test passes when high-priority event is triggered.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "events_test_lua_events_add_priority_vs_origin" (
|
||||
[event]
|
||||
name=preload
|
||||
[lua]
|
||||
code=<<
|
||||
wesnoth.game_events.add{
|
||||
id = 'low',
|
||||
name = 'start',
|
||||
priority = -1,
|
||||
action = unit_test.fail
|
||||
}
|
||||
wesnoth.game_events.add{
|
||||
id = 'high',
|
||||
name = 'start',
|
||||
priority = 1,
|
||||
action = unit_test.succeed
|
||||
};
|
||||
>>
|
||||
[/lua]
|
||||
[/event]
|
||||
)}
|
|
@ -0,0 +1,21 @@
|
|||
#####
|
||||
# API(s) being tested: wesnoth.game_events.add_repeating
|
||||
##
|
||||
# Actions:
|
||||
# Use lua's game_events.add_repeating to attach a low-priority "new turn" event.
|
||||
# Use lua's game_events.add_repeating to attach a high-priority "new turn" event.
|
||||
##
|
||||
# Expected end state:
|
||||
# The test passes when high-priority event is triggered.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "events_test_lua_events_add_repeating_priority_vs_origin" (
|
||||
[event]
|
||||
name=preload
|
||||
[lua]
|
||||
code=<<
|
||||
wesnoth.game_events.add_repeating('start', unit_test.fail, -1)
|
||||
wesnoth.game_events.add_repeating('start', unit_test.succeed, 1)
|
||||
>>
|
||||
[/lua]
|
||||
[/event]
|
||||
)}
|
|
@ -0,0 +1,28 @@
|
|||
#####
|
||||
# API(s) being tested: [event]priority=
|
||||
##
|
||||
# Actions:
|
||||
# Set X to 1 in the prestart event.
|
||||
# Add a low-priority start event handler.
|
||||
# In a new high-priority start event: Check if X is 1, Set X to 2.
|
||||
# In the added low-priority start event handler: Check if X is 2.
|
||||
##
|
||||
# Expected end state:
|
||||
# The test passes when the low-priority event is executed last.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "events_test_priority_vs_origin" (
|
||||
[event]
|
||||
name = prestart
|
||||
{VARIABLE X 1}
|
||||
[event]
|
||||
name = start
|
||||
{RETURN ({VARIABLE_CONDITIONAL X equals 2})}
|
||||
[/event]
|
||||
[event]
|
||||
name = start
|
||||
priority = 1
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals 1})}
|
||||
{VARIABLE X 2}
|
||||
[/event]
|
||||
[/event]
|
||||
)}
|
|
@ -0,0 +1,29 @@
|
|||
#####
|
||||
# API(s) being tested: [event]priority=
|
||||
##
|
||||
# Actions:
|
||||
# Set X to 1 in the prestart event.
|
||||
# In a start event handler with negative priority: Check if X is 1, Set X to 2.
|
||||
# In a start event handler with the same priority: Check if X is 2.
|
||||
##
|
||||
# Expected end state:
|
||||
# The test passes when the second event is executed last.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "events_test_same_priority" (
|
||||
[event]
|
||||
name = prestart
|
||||
{VARIABLE X 1}
|
||||
[event]
|
||||
name = start
|
||||
priority = -1
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals 1})}
|
||||
{VARIABLE X 2}
|
||||
[/event]
|
||||
[event]
|
||||
name = start
|
||||
priority = -1
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals 2})}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
[/event]
|
||||
)}
|
|
@ -0,0 +1,169 @@
|
|||
#####
|
||||
# API(s) being tested: [event]priority=
|
||||
##
|
||||
# Actions:
|
||||
# Use event handlers to append alphabet letters to X.
|
||||
# Each event handler increases Y by 1.
|
||||
# Each event handler checks the current value of X, Y vs expectation.
|
||||
##
|
||||
# Expected end state:
|
||||
# The test passes when X is `abcdefghijklmnopq` and Y is 17.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "events_test_multi_int" (
|
||||
[event]
|
||||
name = prestart
|
||||
{VARIABLE X "a"}
|
||||
{VARIABLE Y 1}
|
||||
[event]
|
||||
id = final-check
|
||||
name = start
|
||||
priority = -999999
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 17})}
|
||||
{RETURN ({VARIABLE_CONDITIONAL X equals abcdefghijklmnopq})}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-3
|
||||
name = start
|
||||
priority = 13
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 3})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abc})}
|
||||
{VARIABLE_OP X formula "'$X'..'d'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-5
|
||||
name = start
|
||||
priority = 8
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 5})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcde})}
|
||||
{VARIABLE_OP X formula "'$X'..'f'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-2
|
||||
name = start
|
||||
priority = 14
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 2})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals ab})}
|
||||
{VARIABLE_OP X formula "'$X'..'c'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-1
|
||||
name = start
|
||||
priority = 15
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 1})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals a})}
|
||||
{VARIABLE_OP X formula "'$X'..'b'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-4
|
||||
name = start
|
||||
priority = 12
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 4})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcd})}
|
||||
{VARIABLE_OP X formula "'$X'..'e'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-8
|
||||
name = start
|
||||
priority = 1
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 8})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefgh})}
|
||||
{VARIABLE_OP X formula "'$X'..'i'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-6
|
||||
name = start
|
||||
priority = 7
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 6})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdef})}
|
||||
{VARIABLE_OP X formula "'$X'..'g'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-9
|
||||
name = start
|
||||
priority = -2
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 9})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghi})}
|
||||
{VARIABLE_OP X formula "'$X'..'j'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-10
|
||||
name = start
|
||||
priority = -2
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 10})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghij})}
|
||||
{VARIABLE_OP X formula "'$X'..'k'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-7
|
||||
name = start
|
||||
priority = 7
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 7})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefg})}
|
||||
{VARIABLE_OP X formula "'$X'..'h'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-11
|
||||
name = start
|
||||
priority = -10
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 11})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijk})}
|
||||
{VARIABLE_OP X formula "'$X'..'l'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-12
|
||||
name = start
|
||||
priority = -11
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 12})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijkl})}
|
||||
{VARIABLE_OP X formula "'$X'..'m'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-14
|
||||
name = start
|
||||
priority = -2000
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 14})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijklmn})}
|
||||
{VARIABLE_OP X formula "'$X'..'o'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-16
|
||||
name = start
|
||||
priority = -800000
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 16})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijklmnop})}
|
||||
{VARIABLE_OP X formula "'$X'..'q'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-13
|
||||
name = start
|
||||
priority = -1000
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 13})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijklm})}
|
||||
{VARIABLE_OP X formula "'$X'..'n'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-15
|
||||
name = start
|
||||
priority = -40000
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 15})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijklmno})}
|
||||
{VARIABLE_OP X formula "'$X'..'p'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[/event]
|
||||
)}
|
|
@ -0,0 +1,171 @@
|
|||
#####
|
||||
# API(s) being tested: [event]priority=
|
||||
##
|
||||
# Actions:
|
||||
# Use event handlers to append alphabet letters to X.
|
||||
# Each event handler increases Y by 1.
|
||||
# Each event handler checks the current value of X, Y vs expectation.
|
||||
##
|
||||
# Expected end state:
|
||||
# The test passes when X is `abcdefghijklmnopq` and Y is 17.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "events_test_multi_float" (
|
||||
[event]
|
||||
name = prestart
|
||||
{VARIABLE X "a"}
|
||||
{VARIABLE Y 1}
|
||||
[event]
|
||||
id = final-check
|
||||
name = start
|
||||
priority = -999999
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 17})}
|
||||
{RETURN ({VARIABLE_CONDITIONAL X equals abcdefghijklmnopq})}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-3
|
||||
name = start
|
||||
priority = 4.1
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 3})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abc})}
|
||||
{VARIABLE_OP X formula "'$X'..'d'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-5
|
||||
name = start
|
||||
priority = 3.99999
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 5})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcde})}
|
||||
{VARIABLE_OP X formula "'$X'..'f'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-2
|
||||
name = start
|
||||
priority = 4.2
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 2})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals ab})}
|
||||
{VARIABLE_OP X formula "'$X'..'c'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-1
|
||||
name = start
|
||||
priority = 5
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 1})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals a})}
|
||||
{VARIABLE_OP X formula "'$X'..'b'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-4
|
||||
name = start
|
||||
priority = "$(4.0)"
|
||||
delayed_variable_substitution=no
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 4})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcd})}
|
||||
{VARIABLE_OP X formula "'$|X'..'e'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-8
|
||||
name = start
|
||||
priority = 1
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 8})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefgh})}
|
||||
{VARIABLE_OP X formula "'$X'..'i'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-6
|
||||
name = start
|
||||
priority = 1.5
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 6})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdef})}
|
||||
{VARIABLE_OP X formula "'$X'..'g'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-9
|
||||
name = start
|
||||
# Default to 0
|
||||
priority = "$X"
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 9})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghi})}
|
||||
{VARIABLE_OP X formula "'$X'..'j'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-10
|
||||
name = start
|
||||
priority = -2
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 10})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghij})}
|
||||
{VARIABLE_OP X formula "'$X'..'k'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-7
|
||||
name = start
|
||||
priority = 1.5
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 7})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefg})}
|
||||
{VARIABLE_OP X formula "'$X'..'h'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-11
|
||||
name = start
|
||||
priority = -3.5
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 11})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijk})}
|
||||
{VARIABLE_OP X formula "'$X'..'l'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-12
|
||||
name = start
|
||||
priority = -3.6
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 12})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijkl})}
|
||||
{VARIABLE_OP X formula "'$X'..'m'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-14
|
||||
name = start
|
||||
priority = -2000
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 14})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijklmn})}
|
||||
{VARIABLE_OP X formula "'$X'..'o'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-16
|
||||
name = start
|
||||
priority = -800000
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 16})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijklmnop})}
|
||||
{VARIABLE_OP X formula "'$X'..'q'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-13
|
||||
name = start
|
||||
priority = -1000
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 13})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijklm})}
|
||||
{VARIABLE_OP X formula "'$X'..'n'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[event]
|
||||
id = step-15
|
||||
name = start
|
||||
priority = -40000
|
||||
{ASSERT ({VARIABLE_CONDITIONAL Y equals 15})}
|
||||
{ASSERT ({VARIABLE_CONDITIONAL X equals abcdefghijklmno})}
|
||||
{VARIABLE_OP X formula "'$X'..'p'"}
|
||||
{VARIABLE_OP Y add 1}
|
||||
[/event]
|
||||
[/event]
|
||||
)}
|
|
@ -163,6 +163,7 @@ void event_handler::write_config(config &cfg, bool include_nonserializable) cons
|
|||
if(!types_.empty()) cfg["name"] = types_;
|
||||
if(!id_.empty()) cfg["id"] = id_;
|
||||
cfg["first_time_only"] = first_time_only_;
|
||||
cfg["priority"] = priority_;
|
||||
for(const auto& filter : filters_) {
|
||||
filter->serialize(cfg);
|
||||
}
|
||||
|
|
|
@ -94,6 +94,11 @@ public:
|
|||
return id_;
|
||||
}
|
||||
|
||||
const double& priority() const
|
||||
{
|
||||
return priority_;
|
||||
}
|
||||
|
||||
bool empty() const;
|
||||
|
||||
bool repeatable() const
|
||||
|
@ -111,6 +116,10 @@ public:
|
|||
first_time_only_ = !repeat;
|
||||
}
|
||||
|
||||
void set_priority(double priority)
|
||||
{
|
||||
priority_ = priority;
|
||||
}
|
||||
void set_menu_item(bool imi)
|
||||
{
|
||||
is_menu_item_ = imi;
|
||||
|
@ -149,6 +158,7 @@ private:
|
|||
*/
|
||||
bool has_preloaded_;
|
||||
int event_ref_;
|
||||
double priority_;
|
||||
config args_;
|
||||
std::vector<std::shared_ptr<event_filter>> filters_;
|
||||
std::string id_, types_;
|
||||
|
|
|
@ -67,14 +67,20 @@ namespace game_events
|
|||
/** Create an event handler. */
|
||||
void manager::add_event_handler_from_wml(const config& handler, game_lua_kernel& lk, bool is_menu_item)
|
||||
{
|
||||
auto new_handler = event_handlers_->add_event_handler(handler["name"], handler["id"], !handler["first_time_only"].to_bool(true), is_menu_item);
|
||||
auto new_handler = event_handlers_->add_event_handler(
|
||||
handler["name"],
|
||||
handler["id"],
|
||||
!handler["first_time_only"].to_bool(true),
|
||||
handler["priority"].to_double(0.),
|
||||
is_menu_item
|
||||
);
|
||||
if(new_handler.valid()) {
|
||||
new_handler->read_filters(handler);
|
||||
|
||||
// Strip out anything that's used by the event system itself.
|
||||
config args;
|
||||
for(const auto& [attr, val] : handler.attribute_range()) {
|
||||
if(attr == "id" || attr == "name" || attr == "first_time_only" || attr.compare(0, 6, "filter") == 0) {
|
||||
if(attr == "id" || attr == "name" || attr == "first_time_only" || attr == "priority" || attr.compare(0, 6, "filter") == 0) {
|
||||
continue;
|
||||
}
|
||||
args[attr] = val;
|
||||
|
@ -90,6 +96,7 @@ void manager::add_event_handler_from_wml(const config& handler, game_lua_kernel&
|
|||
<< (new_handler->names_raw().empty() ? "" : "'" + new_handler->names_raw() + "'")
|
||||
<< (new_handler->id().empty() ? "" : "{id=" + new_handler->id() + "}")
|
||||
<< (new_handler->repeatable() ? " (repeating" : " (first time only")
|
||||
<< "; priority " + std::to_string(new_handler->priority())
|
||||
<< (is_menu_item ? "; menu item)" : ")")
|
||||
<< " with the following actions:\n"
|
||||
<< args.debug();
|
||||
|
@ -98,9 +105,9 @@ void manager::add_event_handler_from_wml(const config& handler, game_lua_kernel&
|
|||
}
|
||||
}
|
||||
|
||||
pending_event_handler manager::add_event_handler_from_lua(const std::string& name, const std::string& id, bool repeat, bool is_menu_item)
|
||||
pending_event_handler manager::add_event_handler_from_lua(const std::string& name, const std::string& id, bool repeat, double priority, bool is_menu_item)
|
||||
{
|
||||
return event_handlers_->add_event_handler(name, id, repeat, is_menu_item);
|
||||
return event_handlers_->add_event_handler(name, id, repeat, priority, is_menu_item);
|
||||
}
|
||||
|
||||
/** Removes an event handler. */
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
/** Create an event handler from an [event] tag. */
|
||||
void add_event_handler_from_wml(const config& handler, game_lua_kernel& lk, bool is_menu_item = false);
|
||||
/** Create an empty event handler. Expects the caller to finish setting up the event. */
|
||||
pending_event_handler add_event_handler_from_lua(const std::string& name, const std::string& id, bool repeat = false, bool is_menu_item = false);
|
||||
pending_event_handler add_event_handler_from_lua(const std::string& name, const std::string& id, bool repeat = false, double priority = 0., bool is_menu_item = false);
|
||||
|
||||
/** Removes an event handler. */
|
||||
void remove_event_handler(const std::string& id);
|
||||
|
|
|
@ -75,6 +75,11 @@ std::string event_handlers::standardize_name(const std::string& name)
|
|||
return retval;
|
||||
}
|
||||
|
||||
bool event_handlers::cmp(const handler_ptr lhs, const handler_ptr rhs)
|
||||
{
|
||||
return lhs->priority() < rhs->priority();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read-only access to the handlers with fixed event names, by event name.
|
||||
*/
|
||||
|
@ -93,7 +98,7 @@ handler_list& event_handlers::get(const std::string& name)
|
|||
* An event with a nonempty ID will not be added if an event with that
|
||||
* ID already exists.
|
||||
*/
|
||||
pending_event_handler event_handlers::add_event_handler(const std::string& name, const std::string& id, bool repeat, bool is_menu_item)
|
||||
pending_event_handler event_handlers::add_event_handler(const std::string& name, const std::string& id, bool repeat, double priority, bool is_menu_item)
|
||||
{
|
||||
if(!id.empty()) {
|
||||
// Ignore this handler if there is already one with this ID.
|
||||
|
@ -119,6 +124,7 @@ pending_event_handler event_handlers::add_event_handler(const std::string& name,
|
|||
// Create a new handler.
|
||||
auto handler = std::make_shared<event_handler>(name, id);
|
||||
handler->set_menu_item(is_menu_item);
|
||||
handler->set_priority(priority);
|
||||
handler->set_repeatable(repeat);
|
||||
return {*this, handler};
|
||||
}
|
||||
|
@ -138,6 +144,7 @@ void event_handlers::finish_adding_event_handler(handler_ptr handler)
|
|||
// construct weak_ptrs from the shared one.
|
||||
DBG_EH << "inserting event handler for name=" << names << " with id=" << id;
|
||||
active_.emplace_back(handler);
|
||||
std::stable_sort(active_.rbegin(), active_.rend(), cmp);
|
||||
|
||||
// File by name.
|
||||
if(utils::might_contain_variables(names)) {
|
||||
|
|
|
@ -85,6 +85,9 @@ public:
|
|||
/** Utility to standardize the event names used in by_name_. */
|
||||
static std::string standardize_name(const std::string& name);
|
||||
|
||||
/** Compare function to sort event handlers by priority. */
|
||||
static bool cmp(const handler_ptr lhs, const handler_ptr rhs);
|
||||
|
||||
event_handlers()
|
||||
: active_()
|
||||
, by_name_()
|
||||
|
@ -114,7 +117,7 @@ public:
|
|||
handler_list& get(const std::string& name);
|
||||
|
||||
/** Adds an event handler. */
|
||||
pending_event_handler add_event_handler(const std::string& name, const std::string& id, bool repeat, bool is_menu_item = false);
|
||||
pending_event_handler add_event_handler(const std::string& name, const std::string& id, bool repeat, double priority = 0., bool is_menu_item = false);
|
||||
|
||||
/** Removes an event handler, identified by its ID. */
|
||||
void remove_event_handler(const std::string& id);
|
||||
|
|
|
@ -362,6 +362,7 @@ void wml_menu_item::update_command(const config& new_command)
|
|||
|
||||
command_["name"] = event_name_;
|
||||
command_["first_time_only"] = false;
|
||||
command_["priority"] = 0.;
|
||||
|
||||
// Register the event.
|
||||
LOG_NG << "Setting command for " << event_name_ << " to:\n" << command_;
|
||||
|
|
|
@ -3991,9 +3991,13 @@ static std::string read_event_name(lua_State* L, int idx)
|
|||
* id: Event ID
|
||||
* menu_item: True if this is a menu item (an ID is required); this means removing the menu item will automatically remove this event. Default false.
|
||||
* first_time_only: Whether this event should fire again after the first time; default true.
|
||||
* priority: Number that determines execution order. Events execute in order of decreasing priority, and secondarily in order of addition.
|
||||
* filter: Event filters as a config with filter tags, a table of the form {filter_type = filter_contents}, or a function
|
||||
* filter_args: Arbitrary data that will be passed to the filter, if it is a function. Ignored if the filter is specified as WML or a table.
|
||||
* content: The content of the event. This is a WML table passed verbatim into the event when it fires. If no function is specified, it will be interpreted as ActionWML.
|
||||
* action: The function to call when the event triggers. Defaults to wesnoth.wml_actions.command.
|
||||
*
|
||||
* Lua API: wesnoth.game_events.add
|
||||
*/
|
||||
int game_lua_kernel::intf_add_event(lua_State *L)
|
||||
{
|
||||
|
@ -4001,6 +4005,7 @@ int game_lua_kernel::intf_add_event(lua_State *L)
|
|||
using namespace std::literals;
|
||||
std::string name, id = luaW_table_get_def(L, 1, "id", ""s);
|
||||
bool repeat = !luaW_table_get_def(L, 1, "first_time_only", true), is_menu_item = luaW_table_get_def(L, 1, "menu_item", false);
|
||||
double priority = luaW_table_get_def(L, 1, "priority", 0.);
|
||||
if(luaW_tableget(L, 1, "name")) {
|
||||
name = read_event_name(L, -1);
|
||||
} else if(is_menu_item) {
|
||||
|
@ -4012,7 +4017,7 @@ int game_lua_kernel::intf_add_event(lua_State *L)
|
|||
if(id.empty() && name.empty()) {
|
||||
return luaL_argerror(L, 1, "either a name or id is required");
|
||||
}
|
||||
auto new_handler = man.add_event_handler_from_lua(name, id, repeat, is_menu_item);
|
||||
auto new_handler = man.add_event_handler_from_lua(name, id, repeat, priority, is_menu_item);
|
||||
if(new_handler.valid()) {
|
||||
bool has_lua_filter = false;
|
||||
new_handler->set_arguments(luaW_table_get_def(L, 1, "content", config{"__empty_lua_event", true}));
|
||||
|
@ -4071,6 +4076,10 @@ int game_lua_kernel::intf_add_event(lua_State *L)
|
|||
/** Add a new event handler
|
||||
* Arg 1: Event to handle, as a string or list of strings; or menu item ID if this is a menu item
|
||||
* Arg 2: The function to call when the event triggers
|
||||
*
|
||||
* Lua API:
|
||||
* - wesnoth.game_events.add_repeating
|
||||
* - wesnoth.game_events.add_menu
|
||||
*/
|
||||
template<bool is_menu_item>
|
||||
int game_lua_kernel::intf_add_event_simple(lua_State *L)
|
||||
|
@ -4078,6 +4087,7 @@ int game_lua_kernel::intf_add_event_simple(lua_State *L)
|
|||
game_events::manager & man = *game_state_.events_manager_;
|
||||
bool repeat = true;
|
||||
std::string name = read_event_name(L, 1), id;
|
||||
double priority = luaL_optnumber(L, 3, 0.);
|
||||
if(name.empty()) {
|
||||
return luaL_argerror(L, 1, "must not be empty");
|
||||
}
|
||||
|
@ -4085,7 +4095,7 @@ int game_lua_kernel::intf_add_event_simple(lua_State *L)
|
|||
id = name;
|
||||
name = "menu item " + name;
|
||||
}
|
||||
auto new_handler = man.add_event_handler_from_lua(name, id, repeat, is_menu_item);
|
||||
auto new_handler = man.add_event_handler_from_lua(name, id, repeat, priority, is_menu_item);
|
||||
if(new_handler.valid()) {
|
||||
// An event with empty arguments is not added, so set some dummy arguments
|
||||
new_handler->set_arguments(config{"__quick_lua_event", true});
|
||||
|
@ -4096,6 +4106,8 @@ int game_lua_kernel::intf_add_event_simple(lua_State *L)
|
|||
|
||||
/** Add a new event handler
|
||||
* Arg: A full event specification as a WML config
|
||||
*
|
||||
* WML API: [event]
|
||||
*/
|
||||
int game_lua_kernel::intf_add_event_wml(lua_State *L)
|
||||
{
|
||||
|
|
|
@ -39,6 +39,7 @@ function wesnoth.game_events.on_mouse_move(x, y) end
|
|||
---@field id string Event ID
|
||||
---@field menu_item boolean True if this is a menu item (an ID is required); this means removing the menu item will automatically remove this event. Default false.
|
||||
---@field first_time_only boolean Whether this event should fire again after the first time; default true.
|
||||
---@field priority number Events execute in order of decreasing priority, and secondarily in order of addition
|
||||
---@field filter WML|event_filter|fun(cfg:WML):boolean Event filters as a config with filter tags, a table of the form {filter_type = filter_contents}, or a function
|
||||
---@field filter_args WML Arbitrary data that will be passed to the filter, if it is a function. Ignored if the filter is specified as WML or a table.
|
||||
---@field content WML The content of the event. This is a WML table passed verbatim into the event when it fires. If no function is specified, it will be interpreted as ActionWML.
|
||||
|
@ -51,7 +52,8 @@ function wesnoth.game_events.add(opts) end
|
|||
---Add a repeating game event handler bound directly to a Lua function
|
||||
---@param name string|string[] The event or events to handle
|
||||
---@param action fun(WML) The function called when the event triggers
|
||||
function wesnoth.game_events.add_repeating(name, action) end
|
||||
---@param priority? number Events execute in order of decreasing priority, and secondarily in order of addition
|
||||
function wesnoth.game_events.add_repeating(name, action, priority) end
|
||||
|
||||
---Add a game event handler triggered from a menu item, bound directly to a Lua function
|
||||
---@param id string
|
||||
|
|
|
@ -445,6 +445,12 @@
|
|||
0 order_of_variable_events3
|
||||
0 premature_end_turn1
|
||||
2 premature_end_turn2
|
||||
0 events_test_priority_vs_origin
|
||||
0 events_test_same_priority
|
||||
0 events_test_multi_int
|
||||
0 events_test_multi_float
|
||||
0 events_test_lua_events_add_priority_vs_origin
|
||||
0 events_test_lua_events_add_repeating_priority_vs_origin
|
||||
0 kill_fires_events
|
||||
# Game mechanics
|
||||
0 heal
|
||||
|
|
Loading…
Add table
Reference in a new issue