new animation type: recruiting (c++ part only)
This commit is contained in:
parent
6c7d19f0b4
commit
be7769eda1
8 changed files with 65 additions and 38 deletions
|
@ -13,6 +13,8 @@ Version 1.7.0-svn:
|
|||
* The ~RC() image functor does not accept the special palette switch
|
||||
~RC(palette1=palette2) syntax anymore. ~PAL(palette1>palette2) should
|
||||
be used instead
|
||||
* New type of animation : "recruiting" used by leaders when recruiting
|
||||
units
|
||||
* New portrait for Orc Grunt, Dwarf Fighter (alternative), Goblin Spearman
|
||||
Ogre/Young Ogre, Trapper
|
||||
* Language and i18n:
|
||||
|
|
|
@ -191,7 +191,7 @@ std::string recruit_unit(const gamemap& map, const int side, unit_map& units,
|
|||
}
|
||||
const unit_map::iterator new_unit_itor = units.find(recruit_location);
|
||||
if(new_unit_itor != units.end()) new_unit_itor->second.set_hidden(false);
|
||||
if(show)unit_display::unit_recruited(recruit_location);
|
||||
if(show)unit_display::unit_recruited(recruit_location,u->first);
|
||||
if (is_recall)
|
||||
{
|
||||
LOG_NG << "firing recall event\n";
|
||||
|
@ -1179,9 +1179,9 @@ attack::attack(game_display& gui, const gamemap& map,
|
|||
|
||||
refresh_bc();
|
||||
if(!a_.valid()) {
|
||||
unit_display::unit_die(d_.iter_->first, d_.get_unit(), NULL, d_stats_->weapon, NULL);
|
||||
unit_display::unit_die(d_.iter_->first, d_.get_unit(), NULL, d_stats_->weapon);
|
||||
} else {
|
||||
unit_display::unit_die(d_.iter_->first, d_.get_unit(),a_stats_->weapon,d_stats_->weapon, &(a_.get_unit()));
|
||||
unit_display::unit_die(d_.iter_->first, d_.get_unit(),a_stats_->weapon,d_stats_->weapon,a_.iter_->first, &(a_.get_unit()));
|
||||
}
|
||||
|
||||
DELAY_END_LEVEL(delayed_exception, game_events::fire("die",death_loc,attacker_loc, dat));
|
||||
|
@ -1449,9 +1449,9 @@ attack::attack(game_display& gui, const gamemap& map,
|
|||
|
||||
refresh_bc();
|
||||
if(!d_.valid()) {
|
||||
unit_display::unit_die(a_.loc_, a_.get_unit(),a_stats_->weapon, NULL, NULL);
|
||||
unit_display::unit_die(a_.loc_, a_.get_unit(),a_stats_->weapon);
|
||||
} else {
|
||||
unit_display::unit_die(a_.loc_, a_.get_unit(),a_stats_->weapon,d_stats_->weapon, &(d_.get_unit()));
|
||||
unit_display::unit_die(a_.loc_, a_.get_unit(),a_stats_->weapon,d_stats_->weapon,d_.loc_, &(d_.get_unit()));
|
||||
}
|
||||
|
||||
DELAY_END_LEVEL(delayed_exception, game_events::fire("die",death_loc,defender_loc,dat));
|
||||
|
|
|
@ -2827,13 +2827,15 @@ const t_string& unit::modification_description(const std::string& type) const
|
|||
|
||||
|
||||
|
||||
const unit_animation* unit::choose_animation(const game_display& disp, const map_location& loc,const std::string& event,const int value,const unit_animation::hit_type hit,const attack_type* attack,const attack_type* second_attack, int swing_num) const
|
||||
const unit_animation* unit::choose_animation(const game_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
|
||||
{
|
||||
// Select one of the matching animations at random
|
||||
std::vector<const unit_animation*> options;
|
||||
int max_val = unit_animation::MATCH_FAIL;
|
||||
for(std::vector<unit_animation>::const_iterator i = animations_.begin(); i != animations_.end(); ++i) {
|
||||
int matching = i->matches(disp,loc,this,event,value,hit,attack,second_attack,swing_num);
|
||||
int matching = i->matches(disp,loc,second_loc,this,event,value,hit,attack,second_attack,swing_num);
|
||||
if(matching > unit_animation::MATCH_FAIL && matching == max_val) {
|
||||
options.push_back(&*i);
|
||||
} else if(matching > max_val) {
|
||||
|
|
|
@ -278,7 +278,13 @@ public:
|
|||
unit_type::ALIGNMENT alignment() const { return alignment_; }
|
||||
const unit_race* race() const { return race_; }
|
||||
|
||||
const unit_animation* choose_animation(const game_display& disp, const map_location& loc,const std::string& event,const int damage=0,const unit_animation::hit_type hit_type = unit_animation::INVALID,const attack_type* attack=NULL,const attack_type* second_attack = NULL, int swing_num =0) const;
|
||||
const unit_animation* choose_animation(const game_display& disp,
|
||||
const map_location& loc, const std::string& event,
|
||||
const map_location& second_loc = map_location::null_location,
|
||||
const int damage=0,
|
||||
const unit_animation::hit_type hit_type = unit_animation::INVALID,
|
||||
const attack_type* attack=NULL,const attack_type* second_attack = NULL,
|
||||
int swing_num =0) const;
|
||||
|
||||
bool get_ability_bool(const std::string& ability, const map_location& loc) const;
|
||||
unit_ability_list get_abilities(const std::string& ability, const map_location& loc) const;
|
||||
|
|
|
@ -201,7 +201,7 @@ unit_animation::unit_animation(const config& cfg,const std::string frame_string
|
|||
|
||||
}
|
||||
|
||||
int unit_animation::matches(const game_display &disp,const map_location& 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 swing_num) const
|
||||
int unit_animation::matches(const game_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 swing_num) const
|
||||
{
|
||||
int result = base_score_;
|
||||
if(!event.empty()&&!event_.empty()) {
|
||||
|
@ -240,13 +240,12 @@ int unit_animation::matches(const game_display &disp,const map_location& loc, co
|
|||
result++;
|
||||
}
|
||||
if(!secondary_unit_filter_.empty()) {
|
||||
const map_location facing_loc = loc.get_direction(my_unit->facing());
|
||||
unit_map::const_iterator unit;
|
||||
for(unit=disp.get_const_units().begin() ; unit != disp.get_const_units().end() ; unit++) {
|
||||
if(unit->first == facing_loc) {
|
||||
if(unit->first == second_loc) {
|
||||
std::vector<config>::const_iterator second_itor;
|
||||
for(second_itor = secondary_unit_filter_.begin(); second_itor != secondary_unit_filter_.end(); second_itor++) {
|
||||
if(!unit->second.matches_filter(&(*second_itor),facing_loc)) return MATCH_FAIL;
|
||||
if(!unit->second.matches_filter(&(*second_itor),second_loc)) return MATCH_FAIL;
|
||||
result++;
|
||||
}
|
||||
|
||||
|
@ -854,7 +853,8 @@ void unit_animation::particule::start_animation(int start_time, bool cycles)
|
|||
}
|
||||
|
||||
void unit_animator::add_animation(unit* animated_unit,const std::string& event,
|
||||
const map_location &src , const int value,bool with_bars,bool cycles,
|
||||
const map_location &src , const map_location &dst ,
|
||||
const int value,bool with_bars,bool cycles,
|
||||
const std::string text,const Uint32 text_color,
|
||||
const unit_animation::hit_type hit_type,
|
||||
const attack_type* attack, const attack_type* second_attack, int swing_num)
|
||||
|
@ -868,7 +868,7 @@ void unit_animator::add_animation(unit* animated_unit,const std::string& event,
|
|||
tmp.src = src;
|
||||
tmp.with_bars= with_bars;
|
||||
tmp.cycles = cycles;
|
||||
tmp.animation = animated_unit->choose_animation(*disp,src,event,value,hit_type,attack,second_attack,swing_num);
|
||||
tmp.animation = animated_unit->choose_animation(*disp,src,event,dst,value,hit_type,attack,second_attack,swing_num);
|
||||
if(!tmp.animation) return;
|
||||
|
||||
|
||||
|
@ -877,7 +877,8 @@ void unit_animator::add_animation(unit* animated_unit,const std::string& event,
|
|||
animated_units_.push_back(tmp);
|
||||
}
|
||||
void unit_animator::replace_anim_if_invalid(unit* animated_unit,const std::string& event,
|
||||
const map_location &src , const int value,bool with_bars,bool cycles,
|
||||
const map_location &src , const map_location & dst,
|
||||
const int value,bool with_bars,bool cycles,
|
||||
const std::string text,const Uint32 text_color,
|
||||
const unit_animation::hit_type hit_type,
|
||||
const attack_type* attack, const attack_type* second_attack, int swing_num)
|
||||
|
@ -886,7 +887,7 @@ void unit_animator::replace_anim_if_invalid(unit* animated_unit,const std::strin
|
|||
game_display*disp = game_display::get_singleton();
|
||||
if(animated_unit->get_animation() &&
|
||||
!animated_unit->get_animation()->animation_finished_potential() &&
|
||||
animated_unit->get_animation()->matches(*disp,src,animated_unit,event,value,hit_type,attack,second_attack,swing_num) >unit_animation::MATCH_FAIL) {
|
||||
animated_unit->get_animation()->matches(*disp,src,dst,animated_unit,event,value,hit_type,attack,second_attack,swing_num) >unit_animation::MATCH_FAIL) {
|
||||
anim_elem tmp;
|
||||
tmp.my_unit = animated_unit;
|
||||
tmp.text = text;
|
||||
|
@ -897,7 +898,7 @@ void unit_animator::replace_anim_if_invalid(unit* animated_unit,const std::strin
|
|||
tmp.animation = NULL;
|
||||
animated_units_.push_back(tmp);
|
||||
}else {
|
||||
add_animation(animated_unit,event,src,value,with_bars,cycles,text,text_color,hit_type,attack,second_attack,swing_num);
|
||||
add_animation(animated_unit,event,src,dst,value,with_bars,cycles,text,text_color,hit_type,attack,second_attack,swing_num);
|
||||
}
|
||||
}
|
||||
void unit_animator::start_animations()
|
||||
|
|
|
@ -38,7 +38,7 @@ class unit_animation
|
|||
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 game_display &disp,const map_location& loc,const unit* my_unit,const std::string & event="",const int value=0,hit_type hit=INVALID,const attack_type* attack=NULL,const attack_type* second_attack = NULL, int swing_num =0) const;
|
||||
int matches(const game_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=INVALID,const attack_type* attack=NULL,const attack_type* second_attack = NULL, int swing_num =0) const;
|
||||
|
||||
|
||||
const unit_frame& get_last_frame() const{ return unit_anim_.get_last_frame() ; };
|
||||
|
@ -130,6 +130,7 @@ class unit_animator
|
|||
|
||||
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,
|
||||
const int value=0,bool with_bars = false,bool cycles = false,
|
||||
const std::string text="",const Uint32 text_color=0,
|
||||
const unit_animation::hit_type hit_type = unit_animation::INVALID,
|
||||
|
@ -137,6 +138,7 @@ class unit_animator
|
|||
int swing_num =0);
|
||||
void replace_anim_if_invalid(unit* animated_unit,const std::string& event,
|
||||
const map_location &src = map_location::null_location,
|
||||
const map_location &dst = map_location::null_location,
|
||||
const int value=0,bool with_bars = false,bool cycles = false,
|
||||
const std::string text="",const Uint32 text_color=0,
|
||||
const unit_animation::hit_type hit_type = unit_animation::INVALID,
|
||||
|
|
|
@ -67,7 +67,7 @@ static void move_unit_between(const map_location& a, const map_location& b, unit
|
|||
disp->place_temporary_unit(temp_unit,a);
|
||||
temp_unit.set_facing(a.get_relative_dir(b));
|
||||
unit_animator animator;
|
||||
animator.replace_anim_if_invalid(&temp_unit,"movement",a);
|
||||
animator.replace_anim_if_invalid(&temp_unit,"movement",a,b);
|
||||
animator.start_animations();
|
||||
animator.pause_animation();
|
||||
disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.0,false);
|
||||
|
@ -207,7 +207,7 @@ void move_unit(const std::vector<map_location>& path, unit& u, const std::vector
|
|||
}
|
||||
|
||||
void unit_die(const map_location& loc, unit& loser,
|
||||
const attack_type* attack,const attack_type* secondary_attack, unit* winner)
|
||||
const attack_type* attack,const attack_type* secondary_attack, const map_location& winner_loc,unit* winner)
|
||||
{
|
||||
game_display* disp = game_display::get_singleton();
|
||||
if(!disp ||disp->video().update_locked() || disp->fogged(loc) || preferences::show_combat() == false) {
|
||||
|
@ -215,9 +215,9 @@ void unit_die(const map_location& loc, unit& loser,
|
|||
}
|
||||
unit_animator animator;
|
||||
// hide the hp/xp bars of the loser (useless and prevent bars around an erased unit)
|
||||
animator.add_animation(&loser,"death",loc,0,false,false,"",0,unit_animation::KILL,attack,secondary_attack,0);
|
||||
animator.add_animation(&loser,"death",loc,winner_loc,0,false,false,"",0,unit_animation::KILL,attack,secondary_attack,0);
|
||||
// but show the bars of the winner (avoid blinking and show its xp gain)
|
||||
animator.add_animation(winner,"victory",loc.get_direction(loser.facing()),0,true,false,"",0,
|
||||
animator.add_animation(winner,"victory",winner_loc,loc,0,true,false,"",0,
|
||||
unit_animation::KILL,secondary_attack,attack,0);
|
||||
animator.start_animations();
|
||||
animator.wait_for_end();
|
||||
|
@ -292,8 +292,8 @@ void unit_attack(
|
|||
}else {
|
||||
hit_type = unit_animation::MISS;
|
||||
}
|
||||
animator.add_animation(&attacker,"attack",att->first,damage,true,false,text_2,display::rgb(0,255,0),hit_type,&attack,secondary_attack,swing);
|
||||
animator.add_animation(&defender,"defend",def->first,damage,true,false,text ,display::rgb(255,0,0),hit_type,&attack,secondary_attack,swing);
|
||||
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;
|
||||
|
@ -301,7 +301,7 @@ void unit_attack(
|
|||
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,damage,true,false,"",0,hit_type,&attack,secondary_attack,swing);
|
||||
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;
|
||||
|
@ -309,7 +309,7 @@ void unit_attack(
|
|||
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,damage,true,false,"",0,hit_type,&attack,secondary_attack,swing);
|
||||
animator.add_animation(&helper->second,"resistance",itor->second,def->first,damage,true,false,"",0,hit_type,&attack,secondary_attack,swing);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -335,20 +335,29 @@ void unit_attack(
|
|||
}
|
||||
|
||||
|
||||
void unit_recruited(map_location& loc)
|
||||
void unit_recruited(const map_location& loc,const map_location& leader_loc)
|
||||
{
|
||||
game_display* disp = game_display::get_singleton();
|
||||
if(!disp || disp->video().update_locked() ||disp->fogged(loc)) return;
|
||||
unit_map::iterator u = disp->get_units().find(loc);
|
||||
if(u == disp->get_units().end()) return;
|
||||
|
||||
u->second.set_hidden(true);
|
||||
disp->scroll_to_tile(loc,game_display::ONSCREEN,true,false);
|
||||
|
||||
unit_animator animator;
|
||||
if(leader_loc != map_location::null_location) {
|
||||
unit_map::iterator leader = disp->get_units().find(leader_loc);
|
||||
if(leader == disp->get_units().end()) return;
|
||||
disp->scroll_to_tiles(loc,leader_loc,game_display::ONSCREEN,true,0.0,false);
|
||||
leader->second.set_facing(leader_loc.get_relative_dir(loc));
|
||||
animator.add_animation(&leader->second,"recruiting",leader_loc,loc);
|
||||
} else {
|
||||
disp->scroll_to_tile(loc,game_display::ONSCREEN,true,false);
|
||||
}
|
||||
|
||||
disp->draw();
|
||||
u->second.set_hidden(false);
|
||||
u->second.set_facing(static_cast<map_location::DIRECTION>(rand()%map_location::NDIRECTIONS));
|
||||
unit_animator animator;
|
||||
animator.add_animation(&u->second,"recruited",loc);
|
||||
animator.add_animation(&u->second,"recruited",loc,leader_loc);
|
||||
animator.start_animations();
|
||||
animator.wait_for_end();
|
||||
animator.set_all_standing();
|
||||
|
@ -367,12 +376,12 @@ void unit_healing(unit& healed,map_location& healed_loc, std::vector<unit_map::i
|
|||
|
||||
for(std::vector<unit_map::iterator>::iterator heal_anim_it = healers.begin(); heal_anim_it != healers.end(); ++heal_anim_it) {
|
||||
(*heal_anim_it)->second.set_facing((*heal_anim_it)->first.get_relative_dir(healed_loc));
|
||||
animator.add_animation(&(*heal_anim_it)->second,"healing",(*heal_anim_it)->first,healing);
|
||||
animator.add_animation(&(*heal_anim_it)->second,"healing",(*heal_anim_it)->first,healed_loc,healing);
|
||||
}
|
||||
if (healing < 0) {
|
||||
animator.add_animation(&healed,"poisoned",healed_loc,-healing,false,false,lexical_cast<std::string>(-healing), display::rgb(255,0,0));
|
||||
animator.add_animation(&healed,"poisoned",healed_loc,map_location::null_location,-healing,false,false,lexical_cast<std::string>(-healing), display::rgb(255,0,0));
|
||||
} else {
|
||||
animator.add_animation(&healed,"healed",healed_loc,healing,false,false,lexical_cast<std::string>(healing), display::rgb(0,255,0));
|
||||
animator.add_animation(&healed,"healed",healed_loc,map_location::null_location,healing,false,false,lexical_cast<std::string>(healing), display::rgb(0,255,0));
|
||||
}
|
||||
animator.start_animations();
|
||||
animator.wait_for_end();
|
||||
|
@ -450,15 +459,18 @@ void wml_animation_internal(unit_animator & animator,const vconfig &cfg, const g
|
|||
}
|
||||
disp->scroll_to_tile(u->first, game_display::ONSCREEN,true,false);
|
||||
vconfig t_filter = cfg.child("facing");
|
||||
map_location secondary_loc = map_location::null_location;
|
||||
if(!t_filter.empty()) {
|
||||
terrain_filter filter(t_filter,map,game_status,units);
|
||||
std::set<map_location> locs;
|
||||
filter.get_locations(locs);
|
||||
if(!locs.empty()) {
|
||||
u->second.set_facing(u->first.get_relative_dir(*locs.begin()));
|
||||
map_location::DIRECTION dir =u->first.get_relative_dir(*locs.begin());
|
||||
u->second.set_facing(dir);
|
||||
secondary_loc = u->first.get_direction(dir);
|
||||
}
|
||||
}
|
||||
animator.add_animation(&u->second,cfg["flag"],u->first,lexical_cast_default<int>(cfg["value"]),utils::string_bool(cfg["with_bars"]),
|
||||
animator.add_animation(&u->second,cfg["flag"],u->first,secondary_loc,lexical_cast_default<int>(cfg["value"]),utils::string_bool(cfg["with_bars"]),
|
||||
false,cfg["text"],text_color, hits,primary,secondary,0);
|
||||
}
|
||||
const vconfig::child_list sub_anims = cfg.get_children("animate");
|
||||
|
|
|
@ -46,7 +46,7 @@ void move_unit(const std::vector<map_location>& path, unit& u, const std::vector
|
|||
*
|
||||
* 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=NULL, const attack_type*secondary_attack=NULL, unit * winner=NULL);
|
||||
void unit_die( const map_location& loc, unit& u, const attack_type* attack=NULL, const attack_type*secondary_attack=NULL,const map_location& winner_loc = map_location::null_location, unit * winner=NULL);
|
||||
|
||||
/**
|
||||
* Make the unit on tile 'a' attack the unit on tile 'b'.
|
||||
|
@ -61,7 +61,9 @@ void unit_attack(
|
|||
const map_location& a, const map_location& b, int damage,
|
||||
const attack_type& attack, const attack_type* secondary_attack,
|
||||
int swing,std::string hit_text,bool drain,std::string att_text);
|
||||
void unit_recruited(map_location& loc);
|
||||
|
||||
|
||||
void unit_recruited(const map_location& loc,const map_location& leader_loc=map_location::null_location);
|
||||
|
||||
/**
|
||||
* Set healer_loc to an invalid location if there are no healers.
|
||||
|
|
Loading…
Add table
Reference in a new issue