give to abilitie support of halo or overlay (#7856)
give abilities support of halo or overlay so that the unit benefits from a second halo or overlay when conditions are matched One of the things that bothers me is the permanent character of the halos of the Mage of Light and other units with the "illuminates" ability, which forces them to program only a permanent illumination applied only to the possessor of the ability. Adding the halo attribute to ability does not change anything about the behavior of the unit, but can be used in several cases: 1 allowing the use of ""illuminates" whose activity would be variable, in this case encoding the halo in [illuminates] ability and not in the unit_type allows to modulate the appearance of the halo under the same conditions 2. Applying illumination to adjacent units, I know it's pretty cheesy but a set developer might consider it easier if the hlo display follows the same logic. 3 The halo used to illustrate the possession in the unit of a special weapon used as leadership, the halo would be used to raise the possessor of the ability. for overlay, same logic for illustrate possession of a special weapon used as leadership, or influence on student with the "halo_image" attribute, it is now possible to give Sun Sylph units an illumination ability with an activity depending on the incarnate sun attack instead of giving the ability and the halo via obect and therefore allowing the player to have access to the description of the ability even when it is inactive.
This commit is contained in:
parent
7d40c5b9b2
commit
a17369597c
18 changed files with 195 additions and 15 deletions
2
changelog_entries/add_halo_overlay_abilities.md
Normal file
2
changelog_entries/add_halo_overlay_abilities.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
### WML Engine
|
||||
* add a halo/overlay_image and halo/overlay_image_self attribute to all abilities to be able to illustrate the activity of these abilities (illumination in mainline or initiative ability in Httt)
|
BIN
data/campaigns/Heir_To_The_Throne/images/misc/firststrike-1.png
Normal file
BIN
data/campaigns/Heir_To_The_Throne/images/misc/firststrike-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
data/campaigns/Heir_To_The_Throne/images/misc/firststrike-2.png
Normal file
BIN
data/campaigns/Heir_To_The_Throne/images/misc/firststrike-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
data/campaigns/Heir_To_The_Throne/images/misc/firststrike-3.png
Normal file
BIN
data/campaigns/Heir_To_The_Throne/images/misc/firststrike-3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
|
@ -8,6 +8,7 @@
|
|||
special_note=_"This unit’s grasp of melee tactics allows adjacent allies to strike the first blow even when defending."
|
||||
affect_self=no
|
||||
affect_allies=yes
|
||||
halo_image_self="misc/firststrike-1.png:100,misc/firststrike-2.png:100,misc/firststrike-3.png:100"
|
||||
[filter_opponent]
|
||||
[filter_weapon]
|
||||
range=melee
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
gender=female
|
||||
image=units/quenoth/sun_sylph/sun-sylph.png
|
||||
profile="portraits/quenoth/sun_sylph.webp"
|
||||
halo=halo/elven/shyde-stationary-halo[1~6].png:150
|
||||
hitpoints=42
|
||||
movement_type=quenoth_float
|
||||
movement=6
|
||||
|
@ -19,6 +20,7 @@
|
|||
usage=healer
|
||||
[abilities]
|
||||
{UTBS_ABILITY_HEALS}
|
||||
{ABILITY_SONG_VERSE_ILLUMINATES}
|
||||
[/abilities]
|
||||
description= _ "In times past, those who stepped beyond the boundary of the worlds of elf and faerie were called Sylphs, mystics with unparalleled knowledge of the secrets of the natural sphere. However, in the harsh new world, the path into the realm of the faerie became no longer a journey into the heart of nature, but a diverging path between light and darkness. Those elves who embrace the burning suns as the fulcrum of life and death learn also to harness their power, transforming into beings imbued with radiant fire. These Sun Sylphs very much embody the power that they wield: light that heals and protects, and flames that smolder with destruction."
|
||||
die_sound={SOUND_LIST:ELF_FEMALE_HIT}
|
||||
|
|
|
@ -296,14 +296,14 @@ _ "third verse"#enddef
|
|||
id = song_$unit.underlying_id|_$turn_number
|
||||
|
||||
[effect]
|
||||
apply_to = new_ability
|
||||
[abilities]
|
||||
{ABILITY_ILLUMINATES}
|
||||
[/abilities]
|
||||
[/effect]
|
||||
[effect]
|
||||
apply_to = halo
|
||||
halo = halo/illuminates-aura.png~CS(50,20,-70)
|
||||
apply_to=attack
|
||||
name=sun incarnate
|
||||
[set_specials]
|
||||
mode=append
|
||||
[dummy]
|
||||
id=sun_incarnate
|
||||
[/dummy]
|
||||
[/set_specials]
|
||||
[/effect]
|
||||
|
||||
duration = scenario
|
||||
|
@ -318,6 +318,29 @@ _ "third verse"#enddef
|
|||
[/event]
|
||||
#enddef
|
||||
|
||||
#define ABILITY_SONG_VERSE_ILLUMINATES
|
||||
# Canned definition of the Illuminates ability to be included in an
|
||||
# [abilities] clause.
|
||||
[illuminates]
|
||||
id=illumination_song_verse
|
||||
value=25
|
||||
max_value=25
|
||||
cumulative=no
|
||||
name= _ "third verse illuminates"
|
||||
female_name= _ "female^third verse illuminates"
|
||||
description= _ "When ability is active after sun incarnate attack, this unit illuminates the surrounding area, making lawful units fight better, and chaotic units fight worse.
|
||||
Any units adjacent to this unit will fight as if it were dusk when it is night, and as if it were day when it is dusk."
|
||||
special_note={INTERNAL:SPECIAL_NOTES_ILLUMINATES}
|
||||
affect_self=yes
|
||||
halo_image="halo/illuminates-aura.png~CS(50,20,-70)"
|
||||
[filter]
|
||||
[has_attack]
|
||||
special_id=sun_incarnate
|
||||
[/has_attack]
|
||||
[/filter]
|
||||
[/illuminates]
|
||||
#enddef
|
||||
|
||||
#define WEAPON_SPECIAL_ONCE_PER_TURN ATTACK_NAME
|
||||
[disable]
|
||||
id = once_per_turn
|
||||
|
|
|
@ -227,6 +227,8 @@ All adjacent lower-level units from the same side deal 25% more damage for each
|
|||
#define ABILITY_ILLUMINATES
|
||||
# Canned definition of the Illuminates ability to be included in an
|
||||
# [abilities] clause.
|
||||
#arg HALO
|
||||
""#endarg
|
||||
[illuminates]
|
||||
id=illumination
|
||||
value=25
|
||||
|
@ -239,6 +241,7 @@ All adjacent lower-level units from the same side deal 25% more damage for each
|
|||
Any units adjacent to this unit will fight as if it were dusk when it is night, and as if it were day when it is dusk."
|
||||
special_note={INTERNAL:SPECIAL_NOTES_ILLUMINATES}
|
||||
affect_self=yes
|
||||
halo_image={HALO}
|
||||
[/illuminates]
|
||||
#enddef
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
gender=male,female
|
||||
image="units/human-magi/white-cleric.png"
|
||||
profile="portraits/humans/mage-light.webp"
|
||||
halo=halo/illuminates-aura.png
|
||||
hitpoints=47
|
||||
movement_type=smallfoot
|
||||
movement=5
|
||||
|
@ -26,7 +25,7 @@ Following a strict code of piety and honor, these men and women work tirelessly
|
|||
die_sound={SOUND_LIST:HUMAN_OLD_DIE}
|
||||
{DEFENSE_ANIM "units/human-magi/white-cleric-defend.png" "units/human-magi/white-cleric.png" {SOUND_LIST:HUMAN_OLD_HIT} }
|
||||
[abilities]
|
||||
{ABILITY_ILLUMINATES}
|
||||
{ABILITY_ILLUMINATES HALO="halo/illuminates-aura.png"}
|
||||
{ABILITY_CURES}
|
||||
[/abilities]
|
||||
[resistance]
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
gender=female
|
||||
image="units/merfolk/diviner.png"
|
||||
profile=portraits/merfolk/priestess.webp
|
||||
halo=halo/illuminates-aura.png
|
||||
hitpoints=45
|
||||
[resistance]
|
||||
arcane=60
|
||||
|
@ -24,7 +23,7 @@
|
|||
die_sound=mermaid-die.ogg
|
||||
{DEFENSE_ANIM "units/merfolk/diviner-defend2.png" "units/merfolk/diviner-defend1.png" mermaid-hit.ogg }
|
||||
[abilities]
|
||||
{ABILITY_ILLUMINATES}
|
||||
{ABILITY_ILLUMINATES HALO="halo/illuminates-aura.png"}
|
||||
{ABILITY_CURES}
|
||||
[/abilities]
|
||||
[healing_anim]
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
{SIMPLE_KEY affect_enemies bool}
|
||||
{SIMPLE_KEY cumulative bool}
|
||||
{SIMPLE_KEY id string}
|
||||
{SIMPLE_KEY halo_image string}
|
||||
{SIMPLE_KEY halo_image_self string}
|
||||
{SIMPLE_KEY overlay_image string}
|
||||
{SIMPLE_KEY overlay_image_self string}
|
||||
|
||||
{FILTER_TAG "filter" unit ()}
|
||||
[tag]
|
||||
|
|
|
@ -219,7 +219,7 @@ Xu, Xu, Qxu, Qxu, Ql, Ql, Ql, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Gg, Gg, Gg, Gg, Gg
|
|||
[/modifications]
|
||||
[abilities]
|
||||
{ABILITY_SKIRMISHER}
|
||||
{ABILITY_ILLUMINATES}
|
||||
{ABILITY_ILLUMINATES HALO="halo/illuminates-aura.png"}
|
||||
[/abilities]
|
||||
[/unit]
|
||||
|
||||
|
|
|
@ -61,6 +61,25 @@ void move_action::write(config & cfg) const
|
|||
child["goto_y"] = goto_hex.wml_y();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset halo of adjacent units when undo move.
|
||||
*/
|
||||
static void reset_adjacent(bool& halo_adjacent, unit_map& units, const map_location& loc)
|
||||
{
|
||||
if(halo_adjacent){
|
||||
unit_map::iterator u = units.find(loc);
|
||||
const auto adjacent = get_adjacent_tiles(loc);
|
||||
for(unsigned i = 0; i < adjacent.size(); ++i) {
|
||||
const unit_map::const_iterator it = units.find(adjacent[i]);
|
||||
if (it == units.end() || it->incapacitated())
|
||||
continue;
|
||||
if ( &*it == &*u )
|
||||
continue;
|
||||
it->anim_comp().set_standing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undoes this action.
|
||||
* @return true on success; false on an error.
|
||||
|
@ -91,8 +110,17 @@ bool move_action::undo(int)
|
|||
|
||||
// Move the unit.
|
||||
unit_display::move_unit(rev_route, u.get_shared_ptr(), true, starting_dir);
|
||||
bool halo_adjacent = false;
|
||||
for (const config::any_child sp : u->abilities().all_children_range()){
|
||||
if(!(sp.cfg)["halo_image"].empty() && (sp.cfg).has_child("affect_adjacent")){
|
||||
halo_adjacent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
reset_adjacent(halo_adjacent, units, rev_route.front());
|
||||
units.move(u->get_location(), rev_route.back());
|
||||
unit::clear_status_caches();
|
||||
reset_adjacent(halo_adjacent, units, rev_route.back());
|
||||
|
||||
// Restore the unit's old state.
|
||||
u = units.find(rev_route.back());
|
||||
|
|
|
@ -476,6 +476,56 @@ bool unit::has_ability_type(const std::string& ability) const
|
|||
return !abilities_.child_range(ability).empty();
|
||||
}
|
||||
|
||||
//these two functions below are used in order to add to the unit
|
||||
//a second set of halo encoded in the abilities (like illuminates halo in [illuminates] ability for example)
|
||||
static void add_string_to_vector(std::vector<std::string>& image_list, const config& cfg, const std::string& attribute_name)
|
||||
{
|
||||
auto ret = std::find(image_list.begin(), image_list.end(), cfg[attribute_name].str());
|
||||
if(ret == image_list.end()){
|
||||
image_list.push_back(cfg[attribute_name].str());
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<std::string> unit::halo_or_icon_abilities(const std::string& image_type) const
|
||||
{
|
||||
std::vector<std::string> image_list;
|
||||
for (const config::any_child sp : abilities_.all_children_range()){
|
||||
bool is_active = ability_active(sp.key, sp.cfg, loc_);
|
||||
//Add halo/overlay to owner of ability if active and affect_self is true.
|
||||
if( !(sp.cfg)[image_type + "_image"].str().empty() && is_active && ability_affects_self(sp.key, sp.cfg, loc_)){
|
||||
add_string_to_vector(image_list, sp.cfg,image_type + "_image");
|
||||
}
|
||||
//Add halo/overlay to owner of ability who affect adjacent only if active.
|
||||
if(!(sp.cfg)[image_type + "_image_self"].str().empty() && is_active){
|
||||
add_string_to_vector(image_list, sp.cfg, image_type + "_image_self");
|
||||
}
|
||||
}
|
||||
|
||||
const unit_map& units = get_unit_map();
|
||||
|
||||
//Add halo/overlay to unit under abilities owned by adjacent who has [affect_adjacent]
|
||||
//if condition matched
|
||||
const auto adjacent = get_adjacent_tiles(loc_);
|
||||
for(unsigned i = 0; i < adjacent.size(); ++i) {
|
||||
const unit_map::const_iterator it = units.find(adjacent[i]);
|
||||
if (it == units.end() || it->incapacitated())
|
||||
continue;
|
||||
if ( &*it == this )
|
||||
continue;
|
||||
for(const config::any_child j : it->abilities_.all_children_range()) {
|
||||
if(!(j.cfg)[image_type + "_image"].str().empty() && affects_side(j.cfg, side(), it->side()) && it->ability_active(j.key, j.cfg, adjacent[i]) && ability_affects_adjacent(j.key, j.cfg, i, loc_, *it))
|
||||
{
|
||||
add_string_to_vector(image_list, j.cfg, image_type + "_image");
|
||||
}
|
||||
}
|
||||
}
|
||||
//rearranges vector alphabetically when its size equals or exceeds two.
|
||||
if(image_list.size() >= 2){
|
||||
std::sort(image_list.begin(), image_list.end());
|
||||
}
|
||||
return image_list;
|
||||
}
|
||||
|
||||
void attack_type::add_formula_context(wfl::map_formula_callable& callable) const
|
||||
{
|
||||
if(unit_const_ptr & att = is_attacker_ ? self_ : other_) {
|
||||
|
|
|
@ -148,6 +148,8 @@ void unit_animation_component::refresh()
|
|||
void unit_animation_component::clear_haloes ()
|
||||
{
|
||||
unit_halo_.reset();
|
||||
abil_halos_.clear();
|
||||
abil_halos_ref_.clear();
|
||||
if(anim_ ) anim_->clear_haloes();
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,9 @@ public:
|
|||
frame_begin_time_(0),
|
||||
draw_bars_(false),
|
||||
refreshing_(false),
|
||||
unit_halo_() {}
|
||||
unit_halo_(),
|
||||
abil_halos_(),
|
||||
abil_halos_ref_() {}
|
||||
|
||||
/** Copy construct a unit animation component, for use when copy constructing a unit. */
|
||||
unit_animation_component(unit & my_unit, const unit_animation_component & o) :
|
||||
|
@ -56,7 +58,9 @@ public:
|
|||
frame_begin_time_(o.frame_begin_time_),
|
||||
draw_bars_(o.draw_bars_),
|
||||
refreshing_(o.refreshing_),
|
||||
unit_halo_() {}
|
||||
unit_halo_(),
|
||||
abil_halos_(),
|
||||
abil_halos_ref_() {}
|
||||
|
||||
/** Chooses an appropriate animation from the list of known animations. */
|
||||
const unit_animation* choose_animation(
|
||||
|
@ -134,4 +138,8 @@ private:
|
|||
|
||||
/** handle to the halo of this unit */
|
||||
halo::handle unit_halo_;
|
||||
/** handle to the abilities halos of this unit */
|
||||
std::vector<halo::handle> abil_halos_;
|
||||
/** vector used to check that halo_abilities vector isn't modified between each read */
|
||||
std::vector<std::string> abil_halos_ref_;
|
||||
};
|
||||
|
|
|
@ -389,6 +389,13 @@ void unit_drawer::redraw_unit(const unit& u) const
|
|||
}
|
||||
};
|
||||
|
||||
const std::vector<std::string> overlays_abilities = u.overlays_abilities();
|
||||
for(const std::string& ov : overlays_abilities) {
|
||||
if(texture tex = image::get_texture(ov)) {
|
||||
textures.push_back(std::move(tex));
|
||||
}
|
||||
};
|
||||
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, [=,
|
||||
textures = std::move(textures),
|
||||
adj_y = adjusted_params.y,
|
||||
|
@ -462,6 +469,45 @@ void unit_drawer::redraw_unit(const unit& u) const
|
|||
halo_man.set_location(ac.unit_halo_, halo_x, halo_y);
|
||||
}
|
||||
|
||||
const std::vector<std::string> halos_abilities = u.halo_abilities();
|
||||
bool has_abil_halo = !ac.abil_halos_.empty() && ac.abil_halos_.front()->valid();
|
||||
if(!has_abil_halo && !halos_abilities.empty()) {
|
||||
for(const std::string& halo_ab : halos_abilities){
|
||||
halo::handle abil_halo = halo_man.add(
|
||||
halo_x, halo_y,
|
||||
halo_ab + u.TC_image_mods(),
|
||||
map_location(-1, -1)
|
||||
);
|
||||
if(abil_halo->valid()){
|
||||
ac.abil_halos_.push_back(abil_halo);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(has_abil_halo && (ac.abil_halos_ref_ != halos_abilities || halos_abilities.empty())){
|
||||
for(halo::handle& abil_halo : ac.abil_halos_){
|
||||
halo_man.remove(abil_halo);
|
||||
}
|
||||
ac.abil_halos_.clear();
|
||||
if(!halos_abilities.empty()){
|
||||
for(const std::string& halo_ab : halos_abilities){
|
||||
halo::handle abil_halo = halo_man.add(
|
||||
halo_x, halo_y,
|
||||
halo_ab + u.TC_image_mods(),
|
||||
map_location(-1, -1)
|
||||
);
|
||||
if(abil_halo->valid()){
|
||||
ac.abil_halos_.push_back(abil_halo);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(has_abil_halo){
|
||||
for(halo::handle& abil_halo : ac.abil_halos_){
|
||||
halo_man.set_location(abil_halo, halo_x, halo_y);
|
||||
}
|
||||
}
|
||||
|
||||
ac.abil_halos_ref_ = halos_abilities;
|
||||
|
||||
ac.anim_->redraw(params, halo_man);
|
||||
ac.refreshing_ = false;
|
||||
}
|
||||
|
|
|
@ -1559,6 +1559,14 @@ public:
|
|||
return halo_.value_or("");
|
||||
}
|
||||
|
||||
const std::vector<std::string> halo_or_icon_abilities(const std::string& image_type) const;
|
||||
|
||||
/** Get the [halo] abilities halo image(s). */
|
||||
const std::vector<std::string> halo_abilities() const
|
||||
{
|
||||
return halo_or_icon_abilities("halo");
|
||||
}
|
||||
|
||||
/** Set the unit's halo image. */
|
||||
void set_image_halo(const std::string& halo);
|
||||
|
||||
|
@ -1602,6 +1610,11 @@ public:
|
|||
return overlays_;
|
||||
}
|
||||
|
||||
/** Get the [overlay] ability overlay images. */
|
||||
const std::vector<std::string> overlays_abilities() const
|
||||
{
|
||||
return halo_or_icon_abilities("overlay");
|
||||
}
|
||||
/**
|
||||
* Color for this unit's *current* hitpoints.
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue