fix the anim engine sometime choosing the default animation...

...when a valid user animation was available. Detected with drake
on-water anim, but could be triggered by anim animation. Also add a
security against force redraws between the end of a strike and the
next strike
This commit is contained in:
Jérémy Rosen 2009-10-09 20:46:38 +00:00
parent 01694d0f82
commit 2ab303050f
4 changed files with 99 additions and 47 deletions

View file

@ -546,4 +546,4 @@
image="units/drakes/fighter.png"
[/frame]
[/attack_anim]
[/unit_type]
[/unit_type]

View file

@ -999,6 +999,26 @@ void unit_animator::add_animation(unit* animated_unit,const std::string& event,
start_time_ = std::max<int>(start_time_,tmp.animation->get_begin_time());
animated_units_.push_back(tmp);
}
void unit_animator::add_animation(unit* animated_unit,const unit_animation* anim,
const map_location &src , bool with_bars,bool cycles,
const std::string text,const Uint32 text_color)
{
if(!animated_unit) return;
anim_elem tmp;
tmp.my_unit = animated_unit;
tmp.text = text;
tmp.text_color = text_color;
tmp.src = src;
tmp.with_bars= with_bars;
tmp.cycles = cycles;
tmp.animation = anim;
if(!tmp.animation) return;
start_time_ = std::max<int>(start_time_,tmp.animation->get_begin_time());
animated_units_.push_back(tmp);
}

View file

@ -33,7 +33,7 @@ class unit_animation
/** Shouldn't be used so only declared. */
unit_animation();
public:
typedef enum { MATCH_FAIL=-2 , DEFAULT_ANIM=-1} variation_type;
typedef enum { MATCH_FAIL=-10 , DEFAULT_ANIM=-9} variation_type;
typedef enum { HIT, MISS, KILL, INVALID} hit_type;
static const std::vector<std::string>& all_tag_names();
@ -141,6 +141,10 @@ class unit_animator
}
void add_animation(unit* animated_unit,const unit_animation * animation,
const map_location &src = map_location::null_location,
bool with_bars = false,bool cycles = false,
const std::string text="",const Uint32 text_color=0);
void add_animation(unit* animated_unit,const std::string& event,
const map_location &src = map_location::null_location,
const map_location &dst = map_location::null_location,

View file

@ -226,6 +226,7 @@ void move_unit(const std::vector<map_location>& path, unit& u,
disp->invalidate(path.back());
}
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)
@ -268,6 +269,7 @@ void unit_sheath_weapon(const map_location& primary_loc, unit* primary_unit,
if(secondary_unit) {
secondary_unit->set_standing();
}
reset_helpers(primary_unit,secondary_unit);
}
@ -288,6 +290,7 @@ void unit_die(const map_location& loc, unit& loser,
animator.start_animations();
animator.wait_for_end();
reset_helpers(winner,&loser);
events::mouse_handler* mousehandler = events::mouse_handler::get_singleton();
if (mousehandler) {
mousehandler->invalidate_reachmap();
@ -335,51 +338,52 @@ void unit_attack(
unit_ability_list leaders = attacker.get_abilities("leadership");
unit_ability_list helpers = defender.get_abilities("resistance");
{
std::string text ;
if(damage) text = lexical_cast<std::string>(damage);
if(!hit_text.empty()) {
text.insert(text.begin(),hit_text.size()/2,' ');
text = text + "\n" + hit_text;
}
std::string text_2 ;
if(drain && damage) text_2 = lexical_cast<std::string>(std::min<int>(damage,defender.hitpoints())/2);
if(!att_text.empty()) {
text_2.insert(text_2.begin(),att_text.size()/2,' ');
text_2 = text_2 + "\n" + att_text;
}
unit_animation::hit_type hit_type;
if(damage >= defender.hitpoints()) {
hit_type = unit_animation::KILL;
} else if(damage > 0) {
hit_type = unit_animation::HIT;
}else {
hit_type = unit_animation::MISS;
}
animator.add_animation(&attacker,"attack",att->first,def->first,damage,true,false,text_2,display::rgb(0,255,0),hit_type,&attack,secondary_attack,swing);
animator.add_animation(&defender,"defend",def->first,att->first,damage,true,false,text ,display::rgb(255,0,0),hit_type,&attack,secondary_attack,swing);
for (std::vector<std::pair<const config *, map_location> >::iterator itor = leaders.cfgs.begin(); itor != leaders.cfgs.end(); itor++) {
if(itor->second == a) continue;
if(itor->second == b) continue;
unit_map::iterator leader = units.find(itor->second);
assert(leader != units.end());
leader->second.set_facing(itor->second.get_relative_dir(a));
animator.add_animation(&leader->second,"leading",itor->second,att->first,damage,true,false,"",0,hit_type,&attack,secondary_attack,swing);
}
for (std::vector<std::pair<const config *, map_location> >::iterator itor = helpers.cfgs.begin(); itor != helpers.cfgs.end(); itor++) {
if(itor->second == a) continue;
if(itor->second == b) continue;
unit_map::iterator helper = units.find(itor->second);
assert(helper != units.end());
helper->second.set_facing(itor->second.get_relative_dir(b));
animator.add_animation(&helper->second,"resistance",itor->second,def->first,damage,true,false,"",0,hit_type,&attack,secondary_attack,swing);
}
std::string text ;
if(damage) text = lexical_cast<std::string>(damage);
if(!hit_text.empty()) {
text.insert(text.begin(),hit_text.size()/2,' ');
text = text + "\n" + hit_text;
}
std::string text_2 ;
if(drain && damage) text_2 = lexical_cast<std::string>(std::min<int>(damage,defender.hitpoints())/2);
if(!att_text.empty()) {
text_2.insert(text_2.begin(),att_text.size()/2,' ');
text_2 = text_2 + "\n" + att_text;
}
unit_animation::hit_type hit_type;
if(damage >= defender.hitpoints()) {
hit_type = unit_animation::KILL;
} else if(damage > 0) {
hit_type = unit_animation::HIT;
}else {
hit_type = unit_animation::MISS;
}
animator.add_animation(&attacker,"attack",att->first,def->first,damage,true,false,text_2,display::rgb(0,255,0),hit_type,&attack,secondary_attack,swing);
// note that we take an anim from the real unit, we'll use it later
const unit_animation * defender_anim = def->second.choose_animation(*disp,def->first,"defend",att->first,damage,hit_type,&attack,secondary_attack,swing);
animator.add_animation(&defender,defender_anim,def->first,true,false,text ,display::rgb(255,0,0));;
for (std::vector<std::pair<const config *, map_location> >::iterator itor = leaders.cfgs.begin(); itor != leaders.cfgs.end(); itor++) {
if(itor->second == a) continue;
if(itor->second == b) continue;
unit_map::iterator leader = units.find(itor->second);
assert(leader != units.end());
leader->second.set_facing(itor->second.get_relative_dir(a));
animator.add_animation(&leader->second,"leading",itor->second,att->first,damage,true,false,"",0,hit_type,&attack,secondary_attack,swing);
}
for (std::vector<std::pair<const config *, map_location> >::iterator itor = helpers.cfgs.begin(); itor != helpers.cfgs.end(); itor++) {
if(itor->second == a) continue;
if(itor->second == b) continue;
unit_map::iterator helper = units.find(itor->second);
assert(helper != units.end());
helper->second.set_facing(itor->second.get_relative_dir(b));
animator.add_animation(&helper->second,"resistance",itor->second,def->first,damage,true,false,"",0,hit_type,&attack,secondary_attack,swing);
}
animator.start_animations();
animator.wait_until(0);
int damage_left = damage;
@ -393,12 +397,36 @@ void unit_attack(
animator.wait_until(animator.get_animation_time_potential() +50);
}
animator.wait_for_end();
animator.set_all_standing();
// pass the animation back to the real unit
def->second.start_animation(animator.get_end_time(),defender_anim,true);
reset_helpers(&att->second,&def->second);
disp->remove_temporary_unit();
def->second.set_hidden(was_hidden);
def->second.set_standing();
}
// private helper function, set all helpers to default position
void reset_helpers(const unit *attacker,const unit *defender)
{
game_display* disp = game_display::get_singleton();
unit_map& units = disp->get_units();
if(attacker) {
unit_ability_list leaders = attacker->get_abilities("leadership");
for (std::vector<std::pair<const config *, map_location> >::iterator itor = leaders.cfgs.begin(); itor != leaders.cfgs.end(); itor++) {
unit_map::iterator leader = units.find(itor->second);
assert(leader != units.end());
leader->second.set_standing();
}
}
if(defender) {
unit_ability_list helpers = defender->get_abilities("resistance");
for (std::vector<std::pair<const config *, map_location> >::iterator itor = helpers.cfgs.begin(); itor != helpers.cfgs.end(); itor++) {
unit_map::iterator helper = units.find(itor->second);
assert(helper != units.end());
helper->second.set_standing();
}
}
}
void unit_recruited(const map_location& loc,const map_location& leader_loc)
{