mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-13 18:32:11 +00:00
added support for defensive animations
This commit is contained in:
parent
8e3006652a
commit
79a5f2a21e
21
src/unit.cpp
21
src/unit.cpp
@ -801,15 +801,24 @@ const std::string& unit::image() const
|
||||
switch(state_) {
|
||||
case STATE_NORMAL: return type_->image();
|
||||
case STATE_DEFENDING_LONG:
|
||||
return type_->image_defensive(attack_type::LONG_RANGE);
|
||||
case STATE_DEFENDING_SHORT:
|
||||
return type_->image_defensive(attack_type::SHORT_RANGE);
|
||||
case STATE_DEFENDING_SHORT: {
|
||||
const attack_type::RANGE range = (state_ == STATE_DEFENDING_LONG) ? attack_type::LONG_RANGE : attack_type::SHORT_RANGE;
|
||||
const unit_animation* const anim = type_->defend_animation(getsHit_,range);
|
||||
if(anim != NULL) {
|
||||
const std::string* img = anim->get_frame(attackingMilliseconds_);
|
||||
if(img != NULL) {
|
||||
return *img;
|
||||
}
|
||||
}
|
||||
|
||||
return type_->image_defensive(range);
|
||||
}
|
||||
case STATE_ATTACKING: {
|
||||
if(attackType_ == NULL)
|
||||
return type_->image();
|
||||
|
||||
const std::string* const img =
|
||||
attackType_->get_frame(attackingMilliseconds_);
|
||||
attackType_->animation().get_frame(attackingMilliseconds_);
|
||||
|
||||
if(img == NULL)
|
||||
return type_->image_fighting(attackType_->range());
|
||||
@ -825,10 +834,12 @@ const std::string& unit::image() const
|
||||
}
|
||||
}
|
||||
|
||||
void unit::set_defending(bool newval, attack_type::RANGE range)
|
||||
void unit::set_defending(bool newval, bool hits, int ms, attack_type::RANGE range)
|
||||
{
|
||||
state_ = newval ? (range == attack_type::LONG_RANGE ? STATE_DEFENDING_LONG :
|
||||
STATE_DEFENDING_SHORT): STATE_NORMAL;
|
||||
attackingMilliseconds_ = ms;
|
||||
getsHit_ = hits;
|
||||
}
|
||||
|
||||
void unit::set_attacking(bool newval, const attack_type* type, int ms)
|
||||
|
@ -112,7 +112,7 @@ public:
|
||||
//(could be in the middle of an attack etc)
|
||||
const std::string& image() const;
|
||||
|
||||
void set_defending(bool newval,
|
||||
void set_defending(bool newval, bool hits=false, int ms=0,
|
||||
attack_type::RANGE range=attack_type::LONG_RANGE);
|
||||
void set_attacking(bool newval, const attack_type* type=NULL, int ms=0);
|
||||
|
||||
@ -150,6 +150,7 @@ private:
|
||||
STATE state_;
|
||||
const attack_type* attackType_;
|
||||
int attackingMilliseconds_;
|
||||
bool getsHit_;
|
||||
|
||||
int hitpoints_;
|
||||
int maxHitpoints_, backupMaxHitpoints_;
|
||||
|
@ -203,8 +203,6 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
||||
const unit_map::iterator att = units.find(a);
|
||||
const unit_map::iterator def = units.find(b);
|
||||
|
||||
def->second.set_defending(true,attack_type::LONG_RANGE);
|
||||
|
||||
const gamemap::location leader_loc = under_leadership(units,a);
|
||||
unit_map::iterator leader = units.end();
|
||||
if(leader_loc.valid()) {
|
||||
@ -215,8 +213,8 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
||||
|
||||
//the missile frames are based around the time when the missile impacts.
|
||||
//the 'real' frames are based around the time when the missile launches.
|
||||
const int first_missile = minimum<int>(-100,attack.get_first_frame(attack_type::MISSILE_FRAME));
|
||||
const int last_missile = attack.get_last_frame(attack_type::MISSILE_FRAME);
|
||||
const int first_missile = minimum<int>(-100,attack.animation().get_first_frame(unit_animation::MISSILE_FRAME));
|
||||
const int last_missile = attack.animation().get_last_frame(unit_animation::MISSILE_FRAME);
|
||||
|
||||
const int real_last_missile = last_missile - first_missile;
|
||||
const int missile_impact = -first_missile;
|
||||
@ -224,17 +222,17 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
||||
const int time_resolution = 20;
|
||||
const int acceleration = disp.turbo() ? 5:1;
|
||||
|
||||
const std::vector<attack_type::sfx>& sounds = attack.sound_effects();
|
||||
std::vector<attack_type::sfx>::const_iterator sfx_it = sounds.begin();
|
||||
const std::vector<unit_animation::sfx>& sounds = attack.animation().sound_effects();
|
||||
std::vector<unit_animation::sfx>::const_iterator sfx_it = sounds.begin();
|
||||
|
||||
const std::string& hit_sound = def->second.type().get_hit_sound();
|
||||
bool played_hit_sound = (hit_sound == "" || hit_sound == "null");
|
||||
const int play_hit_sound_at = 0;
|
||||
|
||||
const bool hits = damage > 0;
|
||||
const int begin_at = attack.get_first_frame();
|
||||
const int begin_at = attack.animation().get_first_frame();
|
||||
const int end_at = maximum((damage+1)*time_resolution+missile_impact,
|
||||
maximum(attack.get_last_frame(),real_last_missile));
|
||||
maximum(attack.animation().get_last_frame(),real_last_missile));
|
||||
|
||||
const double xsrc = disp.get_location_x(a);
|
||||
const double ysrc = disp.get_location_y(a);
|
||||
@ -246,8 +244,7 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
||||
|
||||
const bool vflip = b.y > a.y || b.y == a.y && is_even(a.x);
|
||||
const bool hflip = b.x < a.x;
|
||||
const attack_type::FRAME_DIRECTION dir =
|
||||
(a.x == b.x) ? attack_type::VERTICAL:attack_type::DIAGONAL;
|
||||
const unit_animation::FRAME_DIRECTION dir = (a.x == b.x) ? unit_animation::VERTICAL:unit_animation::DIAGONAL;
|
||||
|
||||
bool dead = false;
|
||||
const int drain_speed = 1*acceleration;
|
||||
@ -266,6 +263,8 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
||||
for(int i = begin_at; i < end_at; i += time_resolution*acceleration) {
|
||||
events::pump();
|
||||
|
||||
def->second.set_defending(true,hits,i - missile_impact,attack_type::LONG_RANGE);
|
||||
|
||||
//this is a while instead of an if, because there might be multiple
|
||||
//sounds playing simultaneously or close together
|
||||
while(!hide && sfx_it != sounds.end() && i >= sfx_it->time) {
|
||||
@ -284,7 +283,7 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
||||
|
||||
const std::string* new_halo = NULL;
|
||||
int new_halo_x = 0, new_halo_y = 0;
|
||||
const std::string* unit_image = attack.get_frame(i,NULL,attack_type::UNIT_FRAME,attack_type::VERTICAL,&new_halo,&new_halo_x,&new_halo_y);
|
||||
const std::string* unit_image = attack.animation().get_frame(i,NULL,unit_animation::UNIT_FRAME,unit_animation::VERTICAL,&new_halo,&new_halo_x,&new_halo_y);
|
||||
if(att->second.facing_left() == false) {
|
||||
new_halo_x *= -1;
|
||||
}
|
||||
@ -354,8 +353,8 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
||||
|
||||
const std::string* new_halo = NULL;
|
||||
int new_halo_x = 0, new_halo_y = 0;
|
||||
const std::string* missile_image = attack.get_frame(missile_frame,NULL,
|
||||
attack_type::MISSILE_FRAME,dir,&new_halo,&new_halo_x,&new_halo_y);
|
||||
const std::string* missile_image = attack.animation().get_frame(missile_frame,NULL,
|
||||
unit_animation::MISSILE_FRAME,dir,&new_halo,&new_halo_x,&new_halo_y);
|
||||
|
||||
if(att->second.facing_left() == false) {
|
||||
new_halo_x *= -1;
|
||||
@ -367,7 +366,7 @@ bool unit_attack_ranged(display& disp, unit_map& units, const gamemap& map,
|
||||
static const std::string default_missile(game_config::missile_n_image);
|
||||
static const std::string default_diag_missile(game_config::missile_ne_image);
|
||||
if(missile_image == NULL) {
|
||||
if(dir == attack_type::VERTICAL)
|
||||
if(dir == unit_animation::VERTICAL)
|
||||
missile_image = &default_missile;
|
||||
else
|
||||
missile_image = &default_diag_missile;
|
||||
@ -523,8 +522,8 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
|
||||
}
|
||||
|
||||
const bool hits = damage > 0;
|
||||
const std::vector<attack_type::sfx>& sounds = attack.sound_effects();
|
||||
std::vector<attack_type::sfx>::const_iterator sfx_it = sounds.begin();
|
||||
const std::vector<unit_animation::sfx>& sounds = attack.animation().sound_effects();
|
||||
std::vector<unit_animation::sfx>::const_iterator sfx_it = sounds.begin();
|
||||
|
||||
const std::string& hit_sound = def->second.type().get_hit_sound();
|
||||
bool played_hit_sound = (hit_sound == "" || hit_sound == "null");
|
||||
@ -544,9 +543,9 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
|
||||
leader->second.set_leading(true);
|
||||
}
|
||||
|
||||
const int begin_at = minimum<int>(-200,attack.get_first_frame());
|
||||
const int begin_at = minimum<int>(-200,attack.animation().get_first_frame());
|
||||
const int end_at = maximum<int>((damage+1)*time_resolution,
|
||||
maximum<int>(200,attack.get_last_frame()));
|
||||
maximum<int>(200,attack.animation().get_last_frame()));
|
||||
|
||||
const double xsrc = disp.get_location_x(a);
|
||||
const double ysrc = disp.get_location_y(a);
|
||||
@ -583,6 +582,8 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
|
||||
for(int i = begin_at; i < end_at; i += time_resolution*acceleration) {
|
||||
events::pump();
|
||||
|
||||
def->second.set_defending(true,hits,i,attack_type::SHORT_RANGE);
|
||||
|
||||
//this is a while instead of an if, because there might be multiple
|
||||
//sounds playing simultaneously or close together
|
||||
while(!hide && sfx_it != sounds.end() && i >= sfx_it->time) {
|
||||
@ -627,7 +628,6 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
|
||||
++flash_num;
|
||||
}
|
||||
|
||||
|
||||
disp.draw_tile(b.x,b.y,NULL,defender_alpha,defender_colour);
|
||||
if(leader_loc.valid()) {
|
||||
disp.draw_tile(leader_loc.x,leader_loc.y);
|
||||
@ -637,8 +637,8 @@ bool unit_attack(display& disp, unit_map& units, const gamemap& map,
|
||||
int new_halo_x = 0, new_halo_y = 0;
|
||||
|
||||
int xoffset = 0;
|
||||
const std::string* unit_image = attack.get_frame(i,&xoffset,attack_type::UNIT_FRAME,attack_type::VERTICAL,
|
||||
&new_halo_image,&new_halo_x,&new_halo_y);
|
||||
const std::string* unit_image = attack.animation().get_frame(i,&xoffset,unit_animation::UNIT_FRAME,unit_animation::VERTICAL,
|
||||
&new_halo_image,&new_halo_x,&new_halo_y);
|
||||
|
||||
if(!attacker.facing_left()) {
|
||||
xoffset *= -1;
|
||||
|
@ -28,28 +28,8 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
attack_type::attack_type(const config& cfg)
|
||||
unit_animation::unit_animation(const config& cfg)
|
||||
{
|
||||
name_ = cfg["name"];
|
||||
type_ = cfg["type"];
|
||||
special_ = cfg["special"];
|
||||
backstab_ = special_ == "backstab";
|
||||
icon_ = cfg["icon"];
|
||||
if(icon_.empty())
|
||||
icon_ = "attacks/" + name_ + ".png";
|
||||
|
||||
range_ = cfg["range"] == "long" ? LONG_RANGE : SHORT_RANGE;
|
||||
hexes_ = maximum<int>(1,atoi(cfg["hexes"].c_str()));
|
||||
damage_ = atol(cfg["damage"].c_str());
|
||||
num_attacks_ = atol(cfg["number"].c_str());
|
||||
|
||||
attack_weight_ = atof(cfg["attack_weight"].c_str());
|
||||
defense_weight_ = atof(cfg["defense_weight"].c_str());
|
||||
if ( ! attack_weight_ )
|
||||
attack_weight_ = 1.0;
|
||||
if ( ! defense_weight_ )
|
||||
defense_weight_ = 1.0;
|
||||
|
||||
config::const_child_itors range = cfg.child_range("frame");
|
||||
for(; range.first != range.second; ++range.first){
|
||||
const int beg = atoi((**range.first)["begin"].c_str());
|
||||
@ -97,6 +77,92 @@ attack_type::attack_type(const config& cfg)
|
||||
}
|
||||
}
|
||||
|
||||
int unit_animation::get_first_frame(unit_animation::FRAME_TYPE type) const
|
||||
{
|
||||
if(frames_[type].empty())
|
||||
return 0;
|
||||
else
|
||||
return minimum<int>(frames_[type].front().start,0);
|
||||
}
|
||||
|
||||
int unit_animation::get_last_frame(unit_animation::FRAME_TYPE type) const
|
||||
{
|
||||
if(frames_[type].empty())
|
||||
return 0;
|
||||
else
|
||||
return maximum<int>(frames_[type].back().end,0);
|
||||
}
|
||||
|
||||
const std::string* unit_animation::get_frame(int milliseconds, int* xoff,
|
||||
unit_animation::FRAME_TYPE type,
|
||||
unit_animation::FRAME_DIRECTION dir,
|
||||
const std::string** halo, int* halo_x, int* halo_y) const
|
||||
{
|
||||
for(std::vector<frame>::const_iterator i = frames_[type].begin();
|
||||
i != frames_[type].end(); ++i) {
|
||||
if(i->start > milliseconds)
|
||||
return NULL;
|
||||
|
||||
if(i->start <= milliseconds && i->end > milliseconds) {
|
||||
if(xoff != NULL) {
|
||||
*xoff = i->xoffset;
|
||||
}
|
||||
|
||||
if(halo != NULL) {
|
||||
if(i->halo.empty()) {
|
||||
*halo = NULL;
|
||||
} else {
|
||||
*halo = &i->halo;
|
||||
}
|
||||
|
||||
if(halo_x != NULL) {
|
||||
*halo_x = i->halo_x;
|
||||
}
|
||||
|
||||
if(halo_y != NULL) {
|
||||
*halo_y = i->halo_y;
|
||||
}
|
||||
}
|
||||
|
||||
if(dir == DIAGONAL && i->image_diagonal != "") {
|
||||
return &i->image_diagonal;
|
||||
} else {
|
||||
return &i->image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const std::vector<unit_animation::sfx>& unit_animation::sound_effects() const
|
||||
{
|
||||
return sfx_;
|
||||
}
|
||||
|
||||
attack_type::attack_type(const config& cfg) : animation_(cfg)
|
||||
{
|
||||
name_ = cfg["name"];
|
||||
type_ = cfg["type"];
|
||||
special_ = cfg["special"];
|
||||
backstab_ = special_ == "backstab";
|
||||
icon_ = cfg["icon"];
|
||||
if(icon_.empty())
|
||||
icon_ = "attacks/" + name_ + ".png";
|
||||
|
||||
range_ = cfg["range"] == "long" ? LONG_RANGE : SHORT_RANGE;
|
||||
hexes_ = maximum<int>(1,atoi(cfg["hexes"].c_str()));
|
||||
damage_ = atol(cfg["damage"].c_str());
|
||||
num_attacks_ = atol(cfg["number"].c_str());
|
||||
|
||||
attack_weight_ = atof(cfg["attack_weight"].c_str());
|
||||
defense_weight_ = atof(cfg["defense_weight"].c_str());
|
||||
if ( ! attack_weight_ )
|
||||
attack_weight_ = 1.0;
|
||||
if ( ! defense_weight_ )
|
||||
defense_weight_ = 1.0;
|
||||
}
|
||||
|
||||
const std::string& attack_type::name() const
|
||||
{
|
||||
return name_;
|
||||
@ -152,69 +218,6 @@ bool attack_type::backstab() const
|
||||
return backstab_;
|
||||
}
|
||||
|
||||
int attack_type::get_first_frame(attack_type::FRAME_TYPE type) const
|
||||
{
|
||||
if(frames_[type].empty())
|
||||
return 0;
|
||||
else
|
||||
return minimum<int>(frames_[type].front().start,0);
|
||||
}
|
||||
|
||||
int attack_type::get_last_frame(attack_type::FRAME_TYPE type) const
|
||||
{
|
||||
if(frames_[type].empty())
|
||||
return 0;
|
||||
else
|
||||
return maximum<int>(frames_[type].back().end,0);
|
||||
}
|
||||
|
||||
const std::string* attack_type::get_frame(int milliseconds, int* xoff,
|
||||
attack_type::FRAME_TYPE type,
|
||||
attack_type::FRAME_DIRECTION dir,
|
||||
const std::string** halo, int* halo_x, int* halo_y) const
|
||||
{
|
||||
for(std::vector<frame>::const_iterator i = frames_[type].begin();
|
||||
i != frames_[type].end(); ++i) {
|
||||
if(i->start > milliseconds)
|
||||
return NULL;
|
||||
|
||||
if(i->start <= milliseconds && i->end > milliseconds) {
|
||||
if(xoff != NULL) {
|
||||
*xoff = i->xoffset;
|
||||
}
|
||||
|
||||
if(halo != NULL) {
|
||||
if(i->halo.empty()) {
|
||||
*halo = NULL;
|
||||
} else {
|
||||
*halo = &i->halo;
|
||||
}
|
||||
|
||||
if(halo_x != NULL) {
|
||||
*halo_x = i->halo_x;
|
||||
}
|
||||
|
||||
if(halo_y != NULL) {
|
||||
*halo_y = i->halo_y;
|
||||
}
|
||||
}
|
||||
|
||||
if(dir == DIAGONAL && i->image_diagonal != "") {
|
||||
return &i->image_diagonal;
|
||||
} else {
|
||||
return &i->image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const std::vector<attack_type::sfx>& attack_type::sound_effects() const
|
||||
{
|
||||
return sfx_;
|
||||
}
|
||||
|
||||
bool attack_type::matches_filter(const config& cfg) const
|
||||
{
|
||||
const std::string& filter_range = cfg["range"];
|
||||
@ -549,6 +552,11 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
|
||||
}
|
||||
|
||||
can_advance_ = advances_to().empty() == false;
|
||||
|
||||
const config::child_list& defends = cfg_.get_children("defend");
|
||||
for(config::child_list::const_iterator d = defends.begin(); d != defends.end(); ++d) {
|
||||
defensive_animations_.push_back(defensive_animation(**d));
|
||||
}
|
||||
}
|
||||
|
||||
int unit_type::num_traits() const { return race_->num_traits(); }
|
||||
@ -868,6 +876,39 @@ const std::string& unit_type::race() const
|
||||
return race_->name();
|
||||
}
|
||||
|
||||
unit_type::defensive_animation::defensive_animation(const config& cfg) : hits(HIT_OR_MISS), range(SHORT_OR_LONG), animation(cfg)
|
||||
{
|
||||
const std::string& hits_str = cfg["hits"];
|
||||
if(hits_str.empty() == false) {
|
||||
hits = (hits_str == "yes") ? HIT : MISS;
|
||||
}
|
||||
|
||||
const std::string& range_str = cfg["range"];
|
||||
if(range_str.empty() == false) {
|
||||
range = (range_str == "short") ? SHORT : LONG;
|
||||
}
|
||||
}
|
||||
|
||||
bool unit_type::defensive_animation::matches(bool h, attack_type::RANGE r) const
|
||||
{
|
||||
if(hits == HIT && h == false || hits == MISS && h == true || range == SHORT && r == attack_type::LONG_RANGE || range == LONG && r == attack_type::SHORT_RANGE) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const unit_animation* unit_type::defend_animation(bool hits, attack_type::RANGE range) const
|
||||
{
|
||||
for(std::vector<defensive_animation>::const_iterator i = defensive_animations_.begin(); i != defensive_animations_.end(); ++i) {
|
||||
if(i->matches(hits,range)) {
|
||||
return &i->animation;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
game_data::game_data(const config& cfg)
|
||||
{
|
||||
static const std::vector<config*> dummy_traits;
|
||||
|
@ -21,26 +21,11 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//the 'attack type' is the type of attack, how many times it strikes,
|
||||
//and how much damage it does.
|
||||
class attack_type
|
||||
//a class to describe a unit's animation sequence
|
||||
class unit_animation
|
||||
{
|
||||
public:
|
||||
enum RANGE { SHORT_RANGE, LONG_RANGE };
|
||||
|
||||
attack_type(const config& cfg);
|
||||
const std::string& name() const;
|
||||
const std::string& type() const;
|
||||
const std::string& special() const;
|
||||
const std::string& icon() const;
|
||||
RANGE range() const;
|
||||
int hexes() const;
|
||||
int damage() const;
|
||||
int num_attacks() const;
|
||||
double attack_weight() const;
|
||||
double defense_weight() const;
|
||||
|
||||
bool backstab() const;
|
||||
unit_animation(const config& cfg);
|
||||
|
||||
enum FRAME_TYPE { UNIT_FRAME, MISSILE_FRAME };
|
||||
enum FRAME_DIRECTION { VERTICAL, DIAGONAL };
|
||||
@ -64,24 +49,7 @@ public:
|
||||
|
||||
const std::vector<sfx>& sound_effects() const;
|
||||
|
||||
bool matches_filter(const config& cfg) const;
|
||||
bool apply_modification(const config& cfg,std::string* description);
|
||||
private:
|
||||
std::string name_;
|
||||
std::string type_;
|
||||
std::string special_;
|
||||
std::string icon_;
|
||||
RANGE range_;
|
||||
int hexes_;
|
||||
int damage_;
|
||||
int num_attacks_;
|
||||
double attack_weight_;
|
||||
double defense_weight_;
|
||||
|
||||
//caches whether the unit can backstab. This is important
|
||||
//because the AI queries it alot.
|
||||
bool backstab_;
|
||||
|
||||
struct frame {
|
||||
frame(int i1, int i2, const std::string& img, const std::string& halo, int offset, int halo_x, int halo_y)
|
||||
: start(i1), end(i2), xoffset(offset), image(img), halo(halo), halo_x(halo_x), halo_y(halo_y)
|
||||
@ -106,6 +74,49 @@ private:
|
||||
std::vector<sfx> sfx_;
|
||||
};
|
||||
|
||||
//the 'attack type' is the type of attack, how many times it strikes,
|
||||
//and how much damage it does.
|
||||
class attack_type
|
||||
{
|
||||
public:
|
||||
enum RANGE { SHORT_RANGE, LONG_RANGE };
|
||||
|
||||
attack_type(const config& cfg);
|
||||
const std::string& name() const;
|
||||
const std::string& type() const;
|
||||
const std::string& special() const;
|
||||
const std::string& icon() const;
|
||||
RANGE range() const;
|
||||
int hexes() const;
|
||||
int damage() const;
|
||||
int num_attacks() const;
|
||||
double attack_weight() const;
|
||||
double defense_weight() const;
|
||||
|
||||
bool backstab() const;
|
||||
|
||||
const unit_animation& animation() const { return animation_; }
|
||||
|
||||
bool matches_filter(const config& cfg) const;
|
||||
bool apply_modification(const config& cfg,std::string* description);
|
||||
private:
|
||||
unit_animation animation_;
|
||||
std::string name_;
|
||||
std::string type_;
|
||||
std::string special_;
|
||||
std::string icon_;
|
||||
RANGE range_;
|
||||
int hexes_;
|
||||
int damage_;
|
||||
int num_attacks_;
|
||||
double attack_weight_;
|
||||
double defense_weight_;
|
||||
|
||||
//caches whether the unit can backstab. This is important
|
||||
//because the AI queries it alot.
|
||||
bool backstab_;
|
||||
};
|
||||
|
||||
class unit_movement_type;
|
||||
|
||||
//the 'unit movement type' is the basic size of the unit - flying, small land,
|
||||
@ -220,6 +231,8 @@ public:
|
||||
|
||||
const std::string& race() const;
|
||||
|
||||
const unit_animation* defend_animation(bool hits, attack_type::RANGE range) const;
|
||||
|
||||
private:
|
||||
const config& cfg_;
|
||||
|
||||
@ -244,6 +257,18 @@ private:
|
||||
const std::vector<config*>& possibleTraits_;
|
||||
|
||||
unit_race::GENDER gender_;
|
||||
|
||||
struct defensive_animation
|
||||
{
|
||||
defensive_animation(const config& cfg);
|
||||
bool matches(bool hits, attack_type::RANGE range) const;
|
||||
|
||||
enum { HIT, MISS, HIT_OR_MISS } hits;
|
||||
enum { SHORT, LONG, SHORT_OR_LONG } range;
|
||||
unit_animation animation;
|
||||
};
|
||||
|
||||
std::vector<defensive_animation> defensive_animations_;
|
||||
};
|
||||
|
||||
struct game_data
|
||||
|
Loading…
x
Reference in New Issue
Block a user