Some cleanup of attack_type usage for enable_shared_from_this safety
- Call shared_from_this() instead of taking the address - Don't use raw pointers to attack_type - Change some cases of attack_type objects that weren't owned by a shared_ptr (either owned by another object or allocated directly on the stack) List of files that currently call attack_type constructors: - game_events/conditional_wml.cpp - gui/dialogs/unit_attack.cpp - scripting/lua_unit_attacks.cpp - units/types.cpp - units/unit.cpp Each of these has been individually considered and made safe for use with enable_shared_from_this. (Most of them already were safe.)
This commit is contained in:
parent
2ca105e146
commit
fcc0da5bd4
19 changed files with 108 additions and 104 deletions
|
@ -67,7 +67,7 @@ static lg::log_domain log_config("config");
|
|||
battle_context_unit_stats::battle_context_unit_stats(const unit &u,
|
||||
const map_location& u_loc, int u_attack_num, bool attacking,
|
||||
const unit &opp, const map_location& opp_loc,
|
||||
const attack_type *opp_weapon, const unit_map& units) :
|
||||
const_attack_ptr opp_weapon, const unit_map& units) :
|
||||
weapon(nullptr),
|
||||
attack_num(u_attack_num),
|
||||
is_attacker(attacking),
|
||||
|
@ -100,7 +100,7 @@ battle_context_unit_stats::battle_context_unit_stats(const unit &u,
|
|||
{
|
||||
// Get the current state of the unit.
|
||||
if (attack_num >= 0) {
|
||||
weapon = &u.attacks()[attack_num];
|
||||
weapon = u.attacks()[attack_num].shared_from_this();
|
||||
}
|
||||
if(u.hitpoints() < 0) {
|
||||
LOG_CF << "Unit with " << u.hitpoints() << " hitpoints found, set to 0 for damage calculations\n";
|
||||
|
@ -204,9 +204,9 @@ battle_context_unit_stats::battle_context_unit_stats(const unit &u,
|
|||
}
|
||||
|
||||
battle_context_unit_stats::battle_context_unit_stats(const unit_type* u_type,
|
||||
const attack_type* att_weapon, bool attacking,
|
||||
const_attack_ptr att_weapon, bool attacking,
|
||||
const unit_type* opp_type,
|
||||
const attack_type* opp_weapon,
|
||||
const_attack_ptr opp_weapon,
|
||||
unsigned int opp_terrain_defense,
|
||||
int lawful_bonus) :
|
||||
weapon(att_weapon),
|
||||
|
@ -332,7 +332,7 @@ battle_context::battle_context(const unit_map& units,
|
|||
const unit &defender = *units.find(defender_loc);
|
||||
const double harm_weight = 1.0 - aggression;
|
||||
|
||||
if (attacker_weapon == -1 && attacker.attacks().size() == 1 && attacker.attacks()[0].attack_weight() > 0 && !(&attacker.attacks()[0])->get_special_bool("disable", true))
|
||||
if (attacker_weapon == -1 && attacker.attacks().size() == 1 && attacker.attacks()[0].attack_weight() > 0 && !attacker.attacks()[0].get_special_bool("disable", true))
|
||||
attacker_weapon = 0;
|
||||
|
||||
if (attacker_weapon == -1) {
|
||||
|
@ -346,17 +346,17 @@ battle_context::battle_context(const unit_map& units,
|
|||
|
||||
// If those didn't have to generate statistics, do so now.
|
||||
if (!attacker_stats_) {
|
||||
const attack_type *adef = nullptr;
|
||||
const attack_type *ddef = nullptr;
|
||||
const_attack_ptr adef = nullptr;
|
||||
const_attack_ptr ddef = nullptr;
|
||||
if (attacker_weapon >= 0) {
|
||||
VALIDATE(attacker_weapon < static_cast<int>(attacker.attacks().size()),
|
||||
_("An invalid attacker weapon got selected."));
|
||||
adef = &attacker.attacks()[attacker_weapon];
|
||||
adef = attacker.attacks()[attacker_weapon].shared_from_this();
|
||||
}
|
||||
if (defender_weapon >= 0) {
|
||||
VALIDATE(defender_weapon < static_cast<int>(defender.attacks().size()),
|
||||
_("An invalid defender weapon got selected."));
|
||||
ddef = &defender.attacks()[defender_weapon];
|
||||
ddef = defender.attacks()[defender_weapon].shared_from_this();
|
||||
}
|
||||
assert(!defender_stats_ && !attacker_combatant_ && !defender_combatant_);
|
||||
attacker_stats_ = new battle_context_unit_stats(attacker, attacker_loc, attacker_weapon,
|
||||
|
@ -493,7 +493,7 @@ int battle_context::choose_attacker_weapon(const unit &attacker,
|
|||
if (choices.size() == 1) {
|
||||
*defender_weapon = choose_defender_weapon(attacker, defender, choices[0], units,
|
||||
attacker_loc, defender_loc, prev_def);
|
||||
const attack_type *def_weapon = *defender_weapon >= 0 ? &defender.attacks()[*defender_weapon] : nullptr;
|
||||
const_attack_ptr def_weapon = *defender_weapon >= 0 ? defender.attacks()[*defender_weapon].shared_from_this() : nullptr;
|
||||
attacker_stats_ = new battle_context_unit_stats(attacker, attacker_loc, choices[0],
|
||||
true, defender, defender_loc, def_weapon, units);
|
||||
if (attacker_stats_->disable) {
|
||||
|
@ -503,7 +503,7 @@ int battle_context::choose_attacker_weapon(const unit &attacker,
|
|||
}
|
||||
const attack_type &att = attacker.attacks()[choices[0]];
|
||||
defender_stats_ = new battle_context_unit_stats(defender, defender_loc, *defender_weapon, false,
|
||||
attacker, attacker_loc, &att, units);
|
||||
attacker, attacker_loc, att.shared_from_this(), units);
|
||||
return choices[0];
|
||||
}
|
||||
|
||||
|
@ -517,9 +517,9 @@ int battle_context::choose_attacker_weapon(const unit &attacker,
|
|||
attacker_loc, defender_loc, prev_def);
|
||||
// If that didn't simulate, do so now.
|
||||
if (!attacker_combatant_) {
|
||||
const attack_type *def = nullptr;
|
||||
const_attack_ptr def = nullptr;
|
||||
if (def_weapon >= 0) {
|
||||
def = &defender.attacks()[def_weapon];
|
||||
def = defender.attacks()[def_weapon].shared_from_this();
|
||||
}
|
||||
attacker_stats_ = new battle_context_unit_stats(attacker, attacker_loc, choices[i],
|
||||
true, defender, defender_loc, def, units);
|
||||
|
@ -529,7 +529,7 @@ int battle_context::choose_attacker_weapon(const unit &attacker,
|
|||
continue;
|
||||
}
|
||||
defender_stats_ = new battle_context_unit_stats(defender, defender_loc, def_weapon, false,
|
||||
attacker, attacker_loc, &att, units);
|
||||
attacker, attacker_loc, att.shared_from_this(), units);
|
||||
attacker_combatant_ = new combatant(*attacker_stats_);
|
||||
defender_combatant_ = new combatant(*defender_stats_, prev_def);
|
||||
attacker_combatant_->fight(*defender_combatant_);
|
||||
|
@ -599,7 +599,7 @@ int battle_context::choose_defender_weapon(const unit &attacker,
|
|||
return -1;
|
||||
if (choices.size() == 1) {
|
||||
const battle_context_unit_stats def_stats(defender, defender_loc,
|
||||
choices[0], false, attacker, attacker_loc, &att, units);
|
||||
choices[0], false, attacker, attacker_loc, att.shared_from_this(), units);
|
||||
return (def_stats.disable) ? -1 : choices[0];
|
||||
}
|
||||
|
||||
|
@ -616,7 +616,7 @@ int battle_context::choose_defender_weapon(const unit &attacker,
|
|||
const attack_type &def = defender.attacks()[choices[i]];
|
||||
if (def.defense_weight() >= max_weight) {
|
||||
const battle_context_unit_stats def_stats(defender, defender_loc,
|
||||
choices[i], false, attacker, attacker_loc, &att, units);
|
||||
choices[i], false, attacker, attacker_loc, att.shared_from_this(), units);
|
||||
if (def_stats.disable) continue;
|
||||
max_weight = def.defense_weight();
|
||||
int rating = static_cast<int>(def_stats.num_blows * def_stats.damage *
|
||||
|
@ -632,9 +632,9 @@ int battle_context::choose_defender_weapon(const unit &attacker,
|
|||
for (i = 0; i < choices.size(); ++i) {
|
||||
const attack_type &def = defender.attacks()[choices[i]];
|
||||
battle_context_unit_stats *att_stats = new battle_context_unit_stats(attacker, attacker_loc, attacker_weapon,
|
||||
true, defender, defender_loc, &def, units);
|
||||
true, defender, defender_loc, def.shared_from_this(), units);
|
||||
battle_context_unit_stats *def_stats = new battle_context_unit_stats(defender, defender_loc, choices[i], false,
|
||||
attacker, attacker_loc, &att, units);
|
||||
attacker, attacker_loc, att.shared_from_this(), units);
|
||||
if (def_stats->disable) {
|
||||
delete att_stats;
|
||||
delete def_stats;
|
||||
|
@ -878,11 +878,11 @@ namespace {
|
|||
// Fix pointer to weapons
|
||||
const_cast<battle_context_unit_stats*>(a_stats_)->weapon =
|
||||
a_.valid() && a_.weapon_ >= 0
|
||||
? &a_.get_unit().attacks()[a_.weapon_] : nullptr;
|
||||
? a_.get_unit().attacks()[a_.weapon_].shared_from_this() : nullptr;
|
||||
|
||||
const_cast<battle_context_unit_stats*>(d_stats_)->weapon =
|
||||
d_.valid() && d_.weapon_ >= 0
|
||||
? &d_.get_unit().attacks()[d_.weapon_] : nullptr;
|
||||
? d_.get_unit().attacks()[d_.weapon_].shared_from_this() : nullptr;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ inline unsigned swarm_blows(unsigned min_blows, unsigned max_blows, unsigned hp,
|
|||
/** Structure describing the statistics of a unit involved in the battle. */
|
||||
struct battle_context_unit_stats
|
||||
{
|
||||
const attack_type *weapon; /**< The weapon used by the unit to attack the opponent, or nullptr if there is none. */
|
||||
const_attack_ptr weapon; /**< The weapon used by the unit to attack the opponent, or nullptr if there is none. */
|
||||
int attack_num; /**< Index into unit->attacks() or -1 for none. */
|
||||
bool is_attacker; /**< True if the unit is the attacker. */
|
||||
bool is_poisoned; /**< True if the unit is poisoned at the beginning of the battle. */
|
||||
|
@ -85,13 +85,13 @@ struct battle_context_unit_stats
|
|||
battle_context_unit_stats(const unit &u, const map_location& u_loc,
|
||||
int u_attack_num, bool attacking,
|
||||
const unit &opp, const map_location& opp_loc,
|
||||
const attack_type *opp_weapon,
|
||||
const_attack_ptr opp_weapon,
|
||||
const unit_map& units);
|
||||
|
||||
/** Used by AI for combat analysis */
|
||||
battle_context_unit_stats(const unit_type* u_type,
|
||||
const attack_type* att_weapon, bool attacking,
|
||||
const unit_type* opp_type, const attack_type* opp_weapon,
|
||||
const_attack_ptr att_weapon, bool attacking,
|
||||
const unit_type* opp_type, const_attack_ptr opp_weapon,
|
||||
unsigned int opp_terrain_defense,
|
||||
int lawful_bonus = 0);
|
||||
|
||||
|
|
|
@ -1056,7 +1056,7 @@ struct attack_simulation {
|
|||
|
||||
attack_simulation(const unit_type* attacker, const unit_type* defender,
|
||||
double attacker_defense, double defender_defense,
|
||||
const attack_type* att_weapon, const attack_type* def_weapon,
|
||||
const_attack_ptr att_weapon, const_attack_ptr def_weapon,
|
||||
int average_lawful_bonus) :
|
||||
attacker_type(attacker),
|
||||
defender_type(defender),
|
||||
|
@ -1133,7 +1133,7 @@ void recruitment::simulate_attack(
|
|||
std::shared_ptr<attack_simulation> simulation(new attack_simulation(
|
||||
attacker, defender,
|
||||
attacker_defense, defender_defense,
|
||||
&att_weapon, &def_weapon, average_lawful_bonus_));
|
||||
att_weapon.shared_from_this(), def_weapon.shared_from_this(), average_lawful_bonus_));
|
||||
if (!best_def_response || simulation->better_result(best_def_response.get(), true)) {
|
||||
best_def_response = simulation;
|
||||
}
|
||||
|
@ -1144,7 +1144,7 @@ void recruitment::simulate_attack(
|
|||
best_def_response.reset(new attack_simulation(
|
||||
attacker, defender,
|
||||
attacker_defense, defender_defense,
|
||||
&att_weapon, nullptr, average_lawful_bonus_));
|
||||
att_weapon.shared_from_this(), nullptr, average_lawful_bonus_));
|
||||
}
|
||||
if (!best_att_attack || best_def_response->better_result(best_att_attack.get(), false)) {
|
||||
best_att_attack = best_def_response;
|
||||
|
|
|
@ -66,33 +66,33 @@ void location_callable::serialize_to_string(std::string& str) const
|
|||
variant attack_type_callable::get_value(const std::string& key) const
|
||||
{
|
||||
if(key == "id" || key == "name") {
|
||||
return variant(att_.id());
|
||||
return variant(att_->id());
|
||||
} else if(key == "description") {
|
||||
return variant(att_.name());
|
||||
return variant(att_->name());
|
||||
} else if(key == "type") {
|
||||
return variant(att_.type());
|
||||
return variant(att_->type());
|
||||
} else if(key == "icon") {
|
||||
return variant(att_.icon());
|
||||
return variant(att_->icon());
|
||||
} else if(key == "range") {
|
||||
return variant(att_.range());
|
||||
return variant(att_->range());
|
||||
} else if(key == "damage") {
|
||||
return variant(att_.damage());
|
||||
return variant(att_->damage());
|
||||
} else if(key == "number_of_attacks" || key == "number" || key == "num_attacks" || key == "attacks") {
|
||||
return variant(att_.num_attacks());
|
||||
return variant(att_->num_attacks());
|
||||
} else if(key == "attack_weight") {
|
||||
return variant(att_.attack_weight(), variant::DECIMAL_VARIANT);
|
||||
return variant(att_->attack_weight(), variant::DECIMAL_VARIANT);
|
||||
} else if(key == "defense_weight") {
|
||||
return variant(att_.defense_weight(), variant::DECIMAL_VARIANT);
|
||||
return variant(att_->defense_weight(), variant::DECIMAL_VARIANT);
|
||||
} else if(key == "accuracy") {
|
||||
return variant(att_.accuracy());
|
||||
return variant(att_->accuracy());
|
||||
} else if(key == "parry") {
|
||||
return variant(att_.parry());
|
||||
return variant(att_->parry());
|
||||
} else if(key == "movement_used") {
|
||||
return variant(att_.movement_used());
|
||||
return variant(att_->movement_used());
|
||||
} else if(key == "specials" || key == "special") {
|
||||
std::vector<variant> res;
|
||||
|
||||
for(const auto& special : att_.specials().all_children_range()) {
|
||||
for(const auto& special : att_->specials().all_children_range()) {
|
||||
if(!special.cfg["id"].empty()) {
|
||||
res.emplace_back(special.cfg["id"].str());
|
||||
}
|
||||
|
@ -127,27 +127,27 @@ int attack_type_callable::do_compare(const formula_callable* callable) const
|
|||
return formula_callable::do_compare(callable);
|
||||
}
|
||||
|
||||
if(att_.damage() != att_callable->att_.damage()) {
|
||||
return att_.damage() - att_callable->att_.damage();
|
||||
if(att_->damage() != att_callable->att_->damage()) {
|
||||
return att_->damage() - att_callable->att_->damage();
|
||||
}
|
||||
|
||||
if(att_.num_attacks() != att_callable->att_.num_attacks()) {
|
||||
return att_.num_attacks() - att_callable->att_.num_attacks();
|
||||
if(att_->num_attacks() != att_callable->att_->num_attacks()) {
|
||||
return att_->num_attacks() - att_callable->att_->num_attacks();
|
||||
}
|
||||
|
||||
if(att_.id() != att_callable->att_.id()) {
|
||||
return att_.id().compare(att_callable->att_.id());
|
||||
if(att_->id() != att_callable->att_->id()) {
|
||||
return att_->id().compare(att_callable->att_->id());
|
||||
}
|
||||
|
||||
if(att_.type() != att_callable->att_.type()) {
|
||||
return att_.type().compare(att_callable->att_.type());
|
||||
if(att_->type() != att_callable->att_->type()) {
|
||||
return att_->type().compare(att_callable->att_->type());
|
||||
}
|
||||
|
||||
if(att_.range() != att_callable->att_.range()) {
|
||||
return att_.range().compare(att_callable->att_.range());
|
||||
if(att_->range() != att_callable->att_->range()) {
|
||||
return att_->range().compare(att_callable->att_->range());
|
||||
}
|
||||
|
||||
return att_.weapon_specials().compare(att_callable->att_.weapon_specials());
|
||||
return att_->weapon_specials().compare(att_callable->att_->weapon_specials());
|
||||
}
|
||||
|
||||
variant unit_callable::get_value(const std::string& key) const
|
||||
|
|
|
@ -83,7 +83,7 @@ private:
|
|||
class attack_type_callable : public formula_callable
|
||||
{
|
||||
public:
|
||||
explicit attack_type_callable(const attack_type& attack) : att_(attack)
|
||||
explicit attack_type_callable(const attack_type& attack) : att_(attack.shared_from_this())
|
||||
{
|
||||
type_ = ATTACK_TYPE_C;
|
||||
}
|
||||
|
@ -93,10 +93,10 @@ public:
|
|||
|
||||
int do_compare(const formula_callable* callable) const override;
|
||||
|
||||
const attack_type& get_attack_type() const { return att_; }
|
||||
const attack_type& get_attack_type() const { return *att_; }
|
||||
|
||||
private:
|
||||
const attack_type att_;
|
||||
const_attack_ptr att_;
|
||||
};
|
||||
|
||||
class unit_callable : public formula_callable
|
||||
|
|
|
@ -213,8 +213,10 @@ bool matches_special_filter(const config &cfg, const vconfig& filter)
|
|||
// better to not execute the event (so the problem is more obvious)
|
||||
return false;
|
||||
}
|
||||
const attack_type attack(cfg);
|
||||
return attack.matches_filter(filter.get_parsed_config());
|
||||
// Though it may seem wasteful to put this on the heap, it's necessary.
|
||||
// matches_filter() could potentially call a WFL formula, which would call shared_from_this().
|
||||
auto attack = std::make_shared<const attack_type>(cfg);
|
||||
return attack->matches_filter(filter.get_parsed_config());
|
||||
}
|
||||
|
||||
} // end namespace game_events
|
||||
|
|
|
@ -126,7 +126,7 @@ void attack_predictions::set_data(window& window, const combatant_data& attacker
|
|||
ss.str("");
|
||||
|
||||
// Set specials context (for safety, it should not have changed normally).
|
||||
const attack_type* weapon = attacker.stats_.weapon;
|
||||
const_attack_ptr weapon = attacker.stats_.weapon;
|
||||
weapon->set_specials_context(attacker.unit_.get_location(), defender.unit_.get_location(), attacker.stats_.is_attacker, defender.stats_.weapon);
|
||||
|
||||
// Get damage modifiers.
|
||||
|
|
|
@ -109,8 +109,9 @@ void unit_attack::pre_show(window& window)
|
|||
listbox& weapon_list = find_widget<listbox>(&window, "weapon_list", false);
|
||||
window.keyboard_capture(&weapon_list);
|
||||
|
||||
const config empty;
|
||||
const attack_type no_weapon(empty);
|
||||
// Possible TODO: If a "blank weapon" is generally useful, add it as a static member in attack_type.
|
||||
static const config empty;
|
||||
static const_attack_ptr no_weapon(new attack_type(empty));
|
||||
|
||||
for(const auto & weapon : weapons_) {
|
||||
const battle_context_unit_stats& attacker = weapon.get_attacker_stats();
|
||||
|
@ -119,7 +120,7 @@ void unit_attack::pre_show(window& window)
|
|||
const attack_type& attacker_weapon =
|
||||
*attacker.weapon;
|
||||
const attack_type& defender_weapon = defender.weapon ?
|
||||
*defender.weapon : no_weapon;
|
||||
*defender.weapon : *no_weapon;
|
||||
|
||||
// Don't show if the atacker's weapon has at least one active "disable" special.
|
||||
if(attacker_weapon.get_special_bool("disable")) {
|
||||
|
|
|
@ -434,7 +434,7 @@ static int impl_add_animation(lua_State* L)
|
|||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
anim.add_animation(&u, which, u.get_location(), dest, v1, bars, text, color, hits, primary.get(), secondary.get(), v2);
|
||||
anim.add_animation(&u, which, u.get_location(), dest, v1, bars, text, color, hits, primary, secondary, v2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -679,7 +679,7 @@ std::string attack_type::weapon_specials(bool only_active, bool is_backstab) con
|
|||
void attack_type::set_specials_context(const map_location& unit_loc,
|
||||
const map_location& other_loc,
|
||||
bool attacking,
|
||||
const attack_type *other_attack) const
|
||||
const_attack_ptr other_attack) const
|
||||
{
|
||||
self_loc_ = unit_loc;
|
||||
other_loc_ = other_loc;
|
||||
|
@ -808,7 +808,7 @@ namespace { // Helpers for attack_type::special_active()
|
|||
static bool special_unit_matches(const unit_map::const_iterator & un_it,
|
||||
const unit_map::const_iterator & u2,
|
||||
const map_location & loc,
|
||||
const attack_type * weapon,
|
||||
const_attack_ptr weapon,
|
||||
const config & filter,
|
||||
const bool for_listing,
|
||||
const std::string & child_tag)
|
||||
|
@ -909,11 +909,11 @@ bool attack_type::special_active(const config& special, AFFECTS whom,
|
|||
unit_map::const_iterator & def = is_attacker_ ? other : self;
|
||||
const map_location & att_loc = is_attacker_ ? self_loc_ : other_loc_;
|
||||
const map_location & def_loc = is_attacker_ ? other_loc_ : self_loc_;
|
||||
const attack_type * att_weapon = is_attacker_ ? this : other_attack_;
|
||||
const attack_type * def_weapon = is_attacker_ ? other_attack_ : this;
|
||||
const_attack_ptr att_weapon = is_attacker_ ? shared_from_this() : other_attack_;
|
||||
const_attack_ptr def_weapon = is_attacker_ ? other_attack_ : shared_from_this();
|
||||
|
||||
// Filter the units involved.
|
||||
if (!special_unit_matches(self, other, self_loc_, this, special, is_for_listing_, "filter_self"))
|
||||
if (!special_unit_matches(self, other, self_loc_, shared_from_this(), special, is_for_listing_, "filter_self"))
|
||||
return false;
|
||||
if (!special_unit_matches(other, self, other_loc_, other_attack_, special, is_for_listing_, "filter_opponent"))
|
||||
return false;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
*/
|
||||
|
||||
#include "units/animation.hpp"
|
||||
|
||||
|
@ -374,8 +374,8 @@ unit_animation::unit_animation(const config& cfg,const std::string& frame_string
|
|||
}
|
||||
|
||||
int unit_animation::matches(const display& disp, const map_location& loc, const map_location& second_loc,
|
||||
const unit* my_unit, const std::string& event, const int value, hit_type hit, const attack_type* attack,
|
||||
const attack_type* second_attack, int value2) const
|
||||
const unit* my_unit, const std::string& event, const int value, hit_type hit, const_attack_ptr attack,
|
||||
const_attack_ptr second_attack, int value2) const
|
||||
{
|
||||
int result = base_score_;
|
||||
|
||||
|
@ -1301,8 +1301,8 @@ void unit_animator::add_animation(const unit* animated_unit
|
|||
, const std::string& text
|
||||
, const color_t text_color
|
||||
, const unit_animation::hit_type hit_type
|
||||
, const attack_type* attack
|
||||
, const attack_type* second_attack
|
||||
, const_attack_ptr attack
|
||||
, const_attack_ptr second_attack
|
||||
, int value2)
|
||||
{
|
||||
if(!animated_unit) return;
|
||||
|
@ -1355,8 +1355,8 @@ void unit_animator::replace_anim_if_invalid(const unit* animated_unit
|
|||
, const std::string& text
|
||||
, const color_t text_color
|
||||
, const unit_animation::hit_type hit_type
|
||||
, const attack_type* attack
|
||||
, const attack_type* second_attack
|
||||
, const_attack_ptr attack
|
||||
, const_attack_ptr second_attack
|
||||
, int value2)
|
||||
{
|
||||
if(!animated_unit) return;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
*/
|
||||
#ifndef UNIT_ANIMATION_H_INCLUDED
|
||||
#define UNIT_ANIMATION_H_INCLUDED
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
|||
#include "units/ptr.hpp"
|
||||
#include "utils/make_enum.hpp"
|
||||
|
||||
class attack_type;
|
||||
class display;
|
||||
class unit;
|
||||
|
||||
|
@ -43,7 +42,7 @@ public:
|
|||
static void fill_initial_animations(std::vector<unit_animation>& animations, const config& cfg);
|
||||
static void add_anims(std::vector<unit_animation>& animations, const config& cfg);
|
||||
|
||||
int matches(const display& disp, const map_location& loc, const map_location& second_loc, const unit* my_unit, const std::string& event = "", const int value = 0, hit_type hit = hit_type::INVALID, const attack_type* attack = nullptr, const attack_type* second_attack = nullptr, int value2 = 0) const;
|
||||
int matches(const display& disp, const map_location& loc, const map_location& second_loc, const unit* my_unit, const std::string& event = "", const int value = 0, hit_type hit = hit_type::INVALID, const_attack_ptr attack = nullptr, const_attack_ptr second_attack = nullptr, int value2 = 0) const;
|
||||
|
||||
const unit_frame& get_last_frame() const
|
||||
{
|
||||
|
@ -208,8 +207,8 @@ public:
|
|||
, const color_t text_color = {0,0,0}
|
||||
, const unit_animation::hit_type hit_type =
|
||||
unit_animation::hit_type::INVALID
|
||||
, const attack_type* attack = nullptr
|
||||
, const attack_type* second_attack = nullptr
|
||||
, const_attack_ptr attack = nullptr
|
||||
, const_attack_ptr second_attack = nullptr
|
||||
, int value2 = 0);
|
||||
|
||||
void replace_anim_if_invalid(const unit* animated_unit
|
||||
|
@ -221,8 +220,8 @@ public:
|
|||
, const std::string& text = ""
|
||||
, const color_t text_color = {0,0,0}
|
||||
, const unit_animation::hit_type hit_type = unit_animation::hit_type::INVALID
|
||||
, const attack_type* attack = nullptr
|
||||
, const attack_type* second_attack = nullptr
|
||||
, const_attack_ptr attack = nullptr
|
||||
, const_attack_ptr second_attack = nullptr
|
||||
, int value2 = 0);
|
||||
void start_animations();
|
||||
void pause_animation();
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
const unit_animation* unit_animation_component::choose_animation(const display& disp, const map_location& loc,const std::string& event,
|
||||
const map_location& second_loc,const int value,const unit_animation::hit_type hit,
|
||||
const attack_type* attack, const attack_type* second_attack, int swing_num)
|
||||
const_attack_ptr attack, const_attack_ptr second_attack, int swing_num)
|
||||
{
|
||||
// Select one of the matching animations at random
|
||||
std::vector<const unit_animation*> options;
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
const map_location& second_loc = map_location::null_location(),
|
||||
const int damage=0,
|
||||
const unit_animation::hit_type hit_type = unit_animation::hit_type::INVALID,
|
||||
const attack_type* attack=nullptr,const attack_type* second_attack = nullptr,
|
||||
const_attack_ptr attack=nullptr,const_attack_ptr second_attack = nullptr,
|
||||
int swing_num =0);
|
||||
|
||||
/** Sets the animation state to standing. */
|
||||
|
|
|
@ -71,10 +71,6 @@ attack_type::attack_type(const config& cfg) :
|
|||
}
|
||||
}
|
||||
|
||||
attack_type::~attack_type()
|
||||
{
|
||||
}
|
||||
|
||||
std::string attack_type::accuracy_parry_description() const
|
||||
{
|
||||
if(accuracy_ == 0 && parry_ == 0) {
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <boost/smart_ptr/intrusive_ptr.hpp>
|
||||
#include <boost/dynamic_bitset_fwd.hpp>
|
||||
|
||||
#include "units/ptr.hpp" // for attack_ptr
|
||||
|
||||
class unit_ability_list;
|
||||
|
||||
//the 'attack type' is the type of attack, how many times it strikes,
|
||||
|
@ -35,8 +37,6 @@ class attack_type : public std::enable_shared_from_this<attack_type>
|
|||
public:
|
||||
|
||||
explicit attack_type(const config& cfg);
|
||||
/** Default implementation, but defined out-of-line for efficiency reasons. */
|
||||
~attack_type();
|
||||
const t_string& name() const { return description_; }
|
||||
const std::string& id() const { return id_; }
|
||||
const std::string& type() const { return type_; }
|
||||
|
@ -74,7 +74,7 @@ public:
|
|||
std::vector<std::pair<t_string, t_string> > special_tooltips(boost::dynamic_bitset<>* active_list = nullptr) const;
|
||||
std::string weapon_specials(bool only_active=false, bool is_backstab=false) const;
|
||||
void set_specials_context(const map_location& unit_loc, const map_location& other_loc,
|
||||
bool attacking, const attack_type *other_attack) const;
|
||||
bool attacking, const_attack_ptr other_attack) const;
|
||||
void set_specials_context(const map_location& loc, bool attacking = true) const;
|
||||
void set_specials_context_for_listing() const;
|
||||
|
||||
|
@ -108,7 +108,7 @@ private:
|
|||
// considered active.
|
||||
mutable map_location self_loc_, other_loc_;
|
||||
mutable bool is_attacker_;
|
||||
mutable const attack_type* other_attack_;
|
||||
mutable const_attack_ptr other_attack_;
|
||||
mutable bool is_for_listing_ = false;
|
||||
|
||||
t_string description_;
|
||||
|
@ -128,8 +128,6 @@ private:
|
|||
config specials_;
|
||||
};
|
||||
|
||||
using attack_ptr = std::shared_ptr<attack_type>;
|
||||
using const_attack_ptr = std::shared_ptr<const attack_type>;
|
||||
using attack_list = std::vector<attack_ptr>;
|
||||
using attack_itors = boost::iterator_range<boost::indirect_iterator<attack_list::iterator>>;
|
||||
using const_attack_itors = boost::iterator_range<boost::indirect_iterator<attack_list::const_iterator>>;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define UNIT_PTR_H_INCLUDED
|
||||
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <memory>
|
||||
|
||||
class unit;
|
||||
|
||||
|
@ -29,4 +30,11 @@ void intrusive_ptr_release(const unit *);
|
|||
typedef boost::intrusive_ptr<unit> unit_ptr;
|
||||
typedef boost::intrusive_ptr<const unit> unit_const_ptr;
|
||||
|
||||
// And attacks too!
|
||||
|
||||
class attack_type;
|
||||
|
||||
using attack_ptr = std::shared_ptr<attack_type>;
|
||||
using const_attack_ptr = std::shared_ptr<const attack_type>;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -498,7 +498,7 @@ void move_unit(const std::vector<map_location>& path, unit_ptr u,
|
|||
void reset_helpers(const unit *attacker,const unit *defender);
|
||||
|
||||
void unit_draw_weapon(const map_location& loc, unit& attacker,
|
||||
const attack_type* attack,const attack_type* secondary_attack, const map_location& defender_loc,unit* defender)
|
||||
const_attack_ptr attack,const_attack_ptr secondary_attack, const map_location& defender_loc,unit* defender)
|
||||
{
|
||||
display* disp = display::get_singleton();
|
||||
if(!disp ||disp->video().update_locked() || disp->video().faked() || disp->fogged(loc) || preferences::show_combat() == false) {
|
||||
|
@ -516,7 +516,7 @@ void unit_draw_weapon(const map_location& loc, unit& attacker,
|
|||
|
||||
|
||||
void unit_sheath_weapon(const map_location& primary_loc, unit* primary_unit,
|
||||
const attack_type* primary_attack,const attack_type* secondary_attack, const map_location& secondary_loc,unit* secondary_unit)
|
||||
const_attack_ptr primary_attack,const_attack_ptr secondary_attack, const map_location& secondary_loc,unit* secondary_unit)
|
||||
{
|
||||
display* disp = display::get_singleton();
|
||||
if(!disp ||disp->video().update_locked() || disp->video().faked() || disp->fogged(primary_loc) || preferences::show_combat() == false) {
|
||||
|
@ -546,7 +546,7 @@ void unit_sheath_weapon(const map_location& primary_loc, unit* primary_unit,
|
|||
|
||||
|
||||
void unit_die(const map_location& loc, unit& loser,
|
||||
const attack_type* attack,const attack_type* secondary_attack, const map_location& winner_loc,unit* winner)
|
||||
const_attack_ptr attack,const_attack_ptr secondary_attack, const map_location& winner_loc,unit* winner)
|
||||
{
|
||||
display* disp = display::get_singleton();
|
||||
if(!disp ||disp->video().update_locked() || disp->video().faked() || disp->fogged(loc) || preferences::show_combat() == false) {
|
||||
|
@ -571,7 +571,7 @@ void unit_die(const map_location& loc, unit& loser,
|
|||
|
||||
void unit_attack(display * disp, game_board & board,
|
||||
const map_location& a, const map_location& b, int damage,
|
||||
const attack_type& attack, const attack_type* secondary_attack,
|
||||
const attack_type& attack, const_attack_ptr secondary_attack,
|
||||
int swing,const std::string& hit_text,int drain_amount,const std::string& att_text, const std::vector<std::string>* extra_hit_sounds)
|
||||
{
|
||||
if(!disp ||disp->video().update_locked() || disp->video().faked() ||
|
||||
|
@ -618,12 +618,12 @@ void unit_attack(display * disp, game_board & board,
|
|||
animator.add_animation(&attacker, "attack", att->get_location(),
|
||||
def->get_location(), damage, true, text_2,
|
||||
(drain_amount >= 0) ? color_t(0,255,0) : color_t(255,0,0),
|
||||
hit_type, &attack, secondary_attack, swing);
|
||||
hit_type, attack.shared_from_this(), secondary_attack, swing);
|
||||
|
||||
// note that we take an anim from the real unit, we'll use it later
|
||||
const unit_animation *defender_anim = def->anim_comp().choose_animation(*disp,
|
||||
def->get_location(), "defend", att->get_location(), damage,
|
||||
hit_type, &attack, secondary_attack, swing);
|
||||
hit_type, attack.shared_from_this(), secondary_attack, swing);
|
||||
animator.add_animation(&defender, defender_anim, def->get_location(),
|
||||
true, text , {255,0,0});
|
||||
|
||||
|
@ -635,7 +635,7 @@ void unit_attack(display * disp, game_board & board,
|
|||
leader->set_facing(ability.second.get_relative_dir(a));
|
||||
animator.add_animation(&*leader, "leading", ability.second,
|
||||
att->get_location(), damage, true, "", {0,0,0},
|
||||
hit_type, &attack, secondary_attack, swing);
|
||||
hit_type, attack.shared_from_this(), secondary_attack, swing);
|
||||
}
|
||||
for (const unit_ability & ability : helpers) {
|
||||
if(ability.second == a) continue;
|
||||
|
@ -645,7 +645,7 @@ void unit_attack(display * disp, game_board & board,
|
|||
helper->set_facing(ability.second.get_relative_dir(b));
|
||||
animator.add_animation(&*helper, "resistance", ability.second,
|
||||
def->get_location(), damage, true, "", {0,0,0},
|
||||
hit_type, &attack, secondary_attack, swing);
|
||||
hit_type, attack.shared_from_this(), secondary_attack, swing);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -89,13 +89,13 @@ void move_unit(const std::vector<map_location>& path, unit_ptr u,
|
|||
* Play a pre-fight animation
|
||||
* First unit is the attacker, second unit the defender
|
||||
*/
|
||||
void unit_draw_weapon( const map_location& loc, unit& u, const attack_type* attack=nullptr, const attack_type*secondary_attack=nullptr,const map_location& defender_loc = map_location::null_location(), unit * defender=nullptr);
|
||||
void unit_draw_weapon( const map_location& loc, unit& u, const_attack_ptr attack=nullptr, const_attack_ptr secondary_attack=nullptr,const map_location& defender_loc = map_location::null_location(), unit * defender=nullptr);
|
||||
|
||||
/**
|
||||
* Play a post-fight animation
|
||||
* Both unit can be set to null, only valid units will play their animation
|
||||
*/
|
||||
void unit_sheath_weapon( const map_location& loc, unit* u=nullptr, const attack_type* attack=nullptr, const attack_type*secondary_attack=nullptr,const map_location& defender_loc = map_location::null_location(), unit * defender=nullptr);
|
||||
void unit_sheath_weapon( const map_location& loc, unit* u=nullptr, const_attack_ptr attack=nullptr, const_attack_ptr secondary_attack=nullptr,const map_location& defender_loc = map_location::null_location(), unit * defender=nullptr);
|
||||
|
||||
/**
|
||||
* Show a unit fading out.
|
||||
|
@ -103,7 +103,7 @@ void unit_sheath_weapon( const map_location& loc, unit* u=nullptr, const attack_
|
|||
* Note: this only shows the effect, it doesn't actually kill the unit.
|
||||
*/
|
||||
void unit_die( const map_location& loc, unit& u,
|
||||
const attack_type* attack=nullptr, const attack_type* secondary_attack=nullptr,
|
||||
const_attack_ptr attack=nullptr, const_attack_ptr secondary_attack=nullptr,
|
||||
const map_location& winner_loc=map_location::null_location(),
|
||||
unit* winner=nullptr);
|
||||
|
||||
|
@ -119,7 +119,7 @@ void unit_sheath_weapon( const map_location& loc, unit* u=nullptr, const attack_
|
|||
*/
|
||||
void unit_attack(display * disp, game_board & board, //TODO: Would be nice if this could be purely a display function and defer damage dealing to its caller
|
||||
const map_location& a, const map_location& b, int damage,
|
||||
const attack_type& attack, const attack_type* secondary_attack,
|
||||
const attack_type& attack, const_attack_ptr secondary_attack,
|
||||
int swing, const std::string& hit_text, int drain_amount, const std::string& att_text, const std::vector<std::string>* extra_hit_sounds=nullptr);
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue