unit drawing logic cleanup,

should fix various acceleration bugs and restore status bars during fight
This commit is contained in:
Jérémy Rosen 2007-05-12 10:33:21 +00:00
parent 2f9ee22ecd
commit e111e5d439
14 changed files with 360 additions and 319 deletions

View File

@ -92,7 +92,7 @@ bool can_recruit_on(const gamemap& map, const gamemap::location& leader, const g
std::string recruit_unit(const gamemap& map, int side,
unit_map& units, unit new_unit,
gamemap::location& recruit_location, display* disp, bool need_castle, bool full_movement)
gamemap::location& recruit_location, bool show, bool need_castle, bool full_movement)
{
const events::command_disabler disable_commands;
@ -145,32 +145,12 @@ std::string recruit_unit(const gamemap& map, int side,
}
new_unit.heal_all();
const bool show = disp != NULL && !disp->turbo() &&
!disp->fogged(recruit_location.x,recruit_location.y);
if(show) {
disp->draw(true,true);
}
units.add(new std::pair<gamemap::location,unit>(recruit_location,new_unit));
LOG_NG << "firing prerecruit event\n";
game_events::fire("prerecruit",recruit_location);
if(show) {
unit_map::iterator un = disp->get_units().find(recruit_location);
if( un !=disp->get_units().end()) {
un->second.set_hidden(true);
disp->scroll_to_tile(recruit_location.x,recruit_location.y,display::ONSCREEN);
un->second.set_hidden(false);
un->second.set_recruited(*disp,recruit_location);
while(!un->second.get_animation()->animation_finished()) {
disp->invalidate(recruit_location);
disp->draw();
events::pump();
disp->delay(10);
}
un->second.set_standing(*disp,recruit_location);
}
}
if(show)unit_display::unit_recruited(recruit_location);
LOG_NG << "firing recruit event\n";
game_events::fire("recruit",recruit_location);
@ -861,14 +841,34 @@ attack::attack(display& gui, const gamemap& map,
}
}
unit_display::unit_attack(gui_,units_,attacker_,defender_,
damage_defender_takes,
*a_stats_->weapon,d_stats_->weapon,
update_display_,abs_n_attack_);
if(update_display_) {
std::string float_text = "";
if(hits) {
if (a_stats_->poisons &&
!utils::string_bool(d_->second.get_state("poisoned"))) {
float_text = float_text + _("poisoned") + "\n";
}
if(a_stats_->slows && !utils::string_bool(d_->second.get_state("slowed"))) {
float_text = float_text + _("slowed") + "\n";
}
//if the defender is turned to stone, the fight stops immediately
static const std::string stone_string("stone");
if (a_stats_->stones) {
float_text = float_text + _("stone") + "\n";
}
}
unit_display::unit_attack(attacker_,defender_,
damage_defender_takes,
*a_stats_->weapon,d_stats_->weapon,
abs_n_attack_,float_text);
}
bool dies = d_->second.take_hit(damage_defender_takes);
LOG_NG << "defender took " << damage_defender_takes << (dies ? " and died" : "") << "\n";
if(dies) {
unit_display::unit_die(gui_,defender_,d_->second,a_stats_->weapon,d_stats_->weapon, &(a_->second));
unit_display::unit_die(defender_,d_->second,a_stats_->weapon,d_stats_->weapon, &(a_->second));
}
attack_stats.attack_result(hits ? (dies ? statistics::attack_context::KILLS : statistics::attack_context::HITS)
: statistics::attack_context::MISSES, attacker_damage_);
@ -989,17 +989,11 @@ attack::attack(display& gui, const gamemap& map,
} else if(hits) {
if (a_stats_->poisons &&
!utils::string_bool(d_->second.get_state("poisoned"))) {
if (update_display_){
gui_.float_label(d_->first,_("poisoned"),255,0,0);
}
d_->second.set_state("poisoned","yes");
LOG_NG << "defender poisoned\n";
}
if(a_stats_->slows && !utils::string_bool(d_->second.get_state("slowed"))) {
if (update_display_){
gui_.float_label(d_->first,_("slowed"),255,0,0);
}
d_->second.set_state("slowed","yes");
defender_damage_ = d_stats_->slow_damage;
LOG_NG << "defender slowed\n";
@ -1008,9 +1002,6 @@ attack::attack(display& gui, const gamemap& map,
//if the defender is turned to stone, the fight stops immediately
static const std::string stone_string("stone");
if (a_stats_->stones) {
if (update_display_){
gui_.float_label(d_->first,_("stone"),255,0,0);
}
d_->second.set_state("stoned","yes");
n_defends_ = 0;
n_attacks_ = 0;
@ -1076,14 +1067,33 @@ attack::attack(display& gui, const gamemap& map,
}
}
unit_display::unit_attack(gui_,units_,defender_,attacker_,
damage_attacker_takes,
*d_stats_->weapon,a_stats_->weapon,
update_display_,abs_n_defend_);
if(update_display_) {
std::string float_text = "";
if(hits) {
if (a_stats_->poisons &&
!utils::string_bool(d_->second.get_state("poisoned"))) {
float_text = float_text + _("poisoned") + "\n";
}
if(a_stats_->slows && !utils::string_bool(d_->second.get_state("slowed"))) {
float_text = float_text + _("slowed") + "\n";
}
//if the defender is turned to stone, the fight stops immediately
static const std::string stone_string("stone");
if (a_stats_->stones) {
float_text = float_text + _("stone") + "\n";
}
}
unit_display::unit_attack(defender_,attacker_,
damage_attacker_takes,
*d_stats_->weapon,a_stats_->weapon,
abs_n_defend_,float_text);
}
bool dies = a_->second.take_hit(damage_attacker_takes);
LOG_NG << "attacker took " << damage_attacker_takes << (dies ? " and died" : "") << "\n";
if(dies) {
unit_display::unit_die(gui_,attacker_,a_->second,a_stats_->weapon,d_stats_->weapon, &(d_->second));
unit_display::unit_die(attacker_,a_->second,a_stats_->weapon,d_stats_->weapon, &(d_->second));
}
if(ran_results == NULL) {
config cfg;
@ -1196,17 +1206,11 @@ attack::attack(display& gui, const gamemap& map,
} else if(hits) {
if (d_stats_->poisons &&
!utils::string_bool(a_->second.get_state("poisoned"))) {
if (update_display_){
gui_.float_label(a_->first,_("poisoned"),255,0,0);
}
a_->second.set_state("poisoned","yes");
LOG_NG << "attacker poisoned\n";
}
if(d_stats_->slows && !utils::string_bool(a_->second.get_state("slowed"))) {
if (update_display_){
gui_.float_label(a_->first,_("slowed"),255,0,0);
}
a_->second.set_state("slowed","yes");
attacker_damage_ = a_stats_->slow_damage;
LOG_NG << "attacker slowed\n";
@ -1216,9 +1220,6 @@ attack::attack(display& gui, const gamemap& map,
//if the attacker is turned to stone, the fight stops immediately
static const std::string stone_string("stone");
if (d_stats_->stones) {
if (update_display_){
gui_.float_label(a_->first,_("stone"),255,0,0);
}
a_->second.set_state("stoned","yes");
n_defends_ = 0;
n_attacks_ = 0;
@ -1477,80 +1478,17 @@ void calculate_healing(display& disp, const gamemap& map,
} else if(healing < neg_max) {
healing = neg_max;
}
if(healing == 0) {
continue;
}
if (disp.turbo() || recorder.is_skipping()
|| disp.fogged(i->first.x, i->first.y)
|| !update_display
|| (i->second.invisible(i->first,units,teams) &&
if ( !recorder.is_skipping()
&& update_display
&& !(i->second.invisible(i->first,units,teams) &&
teams[disp.viewing_team()].is_enemy(side))) {
// Simple path.
if (healing > 0)
i->second.heal(healing);
else if (healing < 0)
i->second.take_hit(-healing);
continue;
}
if (update_display){
// This is all the pretty stuff.
int start_time = INT_MAX;
disp.scroll_to_tile(i->first.x, i->first.y, display::ONSCREEN);
disp.select_hex(i->first);
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(i->first));
(*heal_anim_it)->second.set_healing(disp,(*heal_anim_it)->first,healing);
start_time = (*heal_anim_it)->second.get_animation()->get_begin_time();
}
if (healing < 0) {
i->second.set_poisoned(disp,i->first, -healing);
start_time = minimum<int>(start_time, i->second.get_animation()->get_begin_time());
// FIXME
sound::play_sound("poison.ogg");
disp.float_label(i->first, lexical_cast<std::string>(-healing), 255,0,0);
} else {
i->second.set_healed(disp,i->first, healing);
start_time = minimum<int>(start_time, i->second.get_animation()->get_begin_time());
sound::play_sound("heal.wav");
disp.float_label(i->first, lexical_cast<std::string>(healing), 0,255,0);
}
// restart all anims in a synchronized way
i->second.restart_animation(disp, start_time);
for(std::vector<unit_map::iterator>::iterator heal_reanim_it = healers.begin(); heal_reanim_it != healers.end(); ++heal_reanim_it) {
(*heal_reanim_it)->second.restart_animation(disp, start_time);
}
bool finished;
do {
finished = (i->second.get_animation()->animation_finished());
disp.invalidate(i->first);
for(std::vector<unit_map::iterator>::iterator heal_fanim_it = healers.begin(); heal_fanim_it != healers.end(); ++heal_fanim_it) {
finished &= (*heal_fanim_it)->second.get_animation()->animation_finished();
disp.invalidate((*heal_fanim_it)->first);
}
if (healing > 0) {
i->second.heal(1);
--healing;
} else if (healing < 0) {
i->second.take_hit(1);
++healing;
}
finished &= (!healing);
disp.draw();
events::pump();
disp.delay(10);
} while (!finished);
i->second.set_standing(disp,i->first);
for(std::vector<unit_map::iterator>::iterator heal_sanim_it = healers.begin(); heal_sanim_it != healers.end(); ++heal_sanim_it) {
(*heal_sanim_it)->second.set_standing(disp,(*heal_sanim_it)->first);
}
disp.update_display();
events::pump();
unit_display::unit_healing(i->second,i->first,healers,healing);
}
if (healing > 0)
i->second.heal(healing);
else if (healing < 0)
i->second.take_hit(-healing);
}
}
@ -1988,9 +1926,7 @@ size_t move_unit(display* disp, const game_data& gamedata,
//move the unit on the screen. Hide the unit in its current location, but don't actually
//remove it until the move is done, so that while the unit is moving status etc will
//still display the correct number of units.
if(disp != NULL) {
unit_display::move_unit(*disp,map,steps,ui->second,units,teams);
}
unit_display::move_unit(map,steps,ui->second,teams);
ui->second.set_movement(moves_left);
@ -1998,12 +1934,6 @@ size_t move_unit(display* disp, const game_data& gamedata,
p->first = steps.back();
units.add(p);
ui = units.find(p->first);
ui->second.set_standing(*disp,ui->first);
if(disp != NULL) {
disp->invalidate_unit();
disp->invalidate(steps.back());
disp->draw();
}
if(move_recorder != NULL) {
move_recorder->add_movement(steps.front(),steps.back());

View File

@ -50,8 +50,8 @@ bool can_recruit_on(const gamemap& map, const gamemap::location& leader, const g
//If the unit cannot be recruited, then a human-readable message
//describing why not will be returned. On success, the return string is empty
std::string recruit_unit(const gamemap& map, int team, unit_map& units,
unit u, gamemap::location& recruit_location,
display *disp=NULL, bool need_castle=true, bool full_movement=false);
unit u, gamemap::location& recruit_location,bool show=false,
bool need_castle=true, bool full_movement=false);
/* The battle_context class computes the statistics of a battle between an
* attacker and a defender unit.

View File

@ -482,13 +482,13 @@ gamemap::location ai_interface::move_unit_partial(location from, location to,
steps.push_back(to); //add the destination to the steps
if(show_move && unit_display::unit_visible_on_path(info_.disp,steps,
if(show_move && unit_display::unit_visible_on_path(steps,
u_it->second, info_.units,info_.teams)) {
info_.disp.scroll_to_tiles(from.x,from.y,to.x,to.y);
unit_map::iterator up = info_.units.find(u_it->first);
unit_display::move_unit(info_.disp,info_.map,steps,up->second,info_.units,info_.teams);
unit_display::move_unit(info_.map,steps,up->second,info_.teams);
}
}
}

View File

@ -168,7 +168,7 @@ void display::new_turn()
{
const time_of_day& tod = status_.get_time_of_day();
if(!turbo() && !first_turn_) {
if( !first_turn_) {
image::set_image_mask("");
const time_of_day& old_tod = status_.get_previous_time_of_day();
@ -177,8 +177,8 @@ void display::new_turn()
const surface old_mask(image::get_image(old_tod.image_mask,image::UNMASKED));
const surface new_mask(image::get_image(tod.image_mask,image::UNMASKED));
const int niterations = 10;
const int frame_time = 30;
const int niterations = (int)(10/turbo_speed());
const int frame_time = (int)(30/turbo_speed());
const int starting_ticks = SDL_GetTicks();
for(int i = 0; i != niterations; ++i) {
@ -582,7 +582,7 @@ void display::scroll_to_tile(int x, int y, SCROLL_TYPE scroll_type, bool check_f
int xmove = xpos - xpos_;
int ymove = ypos - ypos_;
if(scroll_type == WARP || turbo()) {
if(scroll_type == WARP ) {
scroll(xmove,ymove);
draw();
return;
@ -599,8 +599,8 @@ void display::scroll_to_tile(int x, int y, SCROLL_TYPE scroll_type, bool check_f
int t_prev = SDL_GetTicks();
// those values might need some fine-tuning:
const double accel_time = 0.3; // seconds
const double decel_time = 0.4; // seconds
const double accel_time = 0.3*turbo_speed(); // seconds
const double decel_time = 0.4*turbo_speed(); // seconds
double velocity = 0.0;
while (dist_moved < dist_total) {
@ -617,7 +617,7 @@ void display::scroll_to_tile(int x, int y, SCROLL_TYPE scroll_type, bool check_f
//std::cout << t << " " << hypot(x_old, y_old) << "\n";
double velocity_max = preferences::scroll_speed() * 80.0;
if (turbo()) velocity_max *= 4.0;
velocity_max *= turbo_speed();
double accel = velocity_max / accel_time;
double decel = velocity_max / decel_time;
@ -2345,19 +2345,15 @@ void display::set_playing_team(size_t team)
}
bool display::turbo() const
double display::turbo_speed() const
{
bool res = turbo_;
if(keys_[SDLK_LSHIFT] || keys_[SDLK_RSHIFT]) {
res = !res;
}
return res || screen_.faked();
}
double display::turbo_speed() const
{
if (turbo())
res |= screen_.faked();
if (res)
return turbo_speed_;
else
return 1.0;
@ -2365,23 +2361,10 @@ double display::turbo_speed() const
void display::set_turbo_speed(const double speed)
{
#if 0
// speed < 2 don't make sense
if (speed < 2)
return;
if (speed > 20)
turbo_speed_ = 20;
else
#endif
turbo_speed_ = speed;
}
//Delay routines: use these not SDL_Delay (for --nogui).
void display::non_turbo_delay() const
{
if (!turbo())
delay(10);
}
void display::delay(unsigned int milliseconds) const
{

View File

@ -325,14 +325,12 @@ public:
//functions to set/get whether 'turbo' mode is on. When turbo mode is on,
//everything moves much faster.
bool turbo() const;
void set_turbo(const bool turbo) { turbo_ = turbo; }
double turbo_speed() const;
void set_turbo_speed(const double speed);
//Delay routines: use these not SDL_Delay (for --nogui).
void non_turbo_delay() const;
void delay(unsigned int milliseconds) const;
//function which determines whether a grid should be overlayed on the

View File

@ -810,8 +810,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
game_map->x(), game_map->y());
wassert(route.steps.size() > 0);
}
unit_display::move_unit(*screen, *game_map, route.steps, dummy_unit,
*units, *teams);
unit_display::move_unit( *game_map, route.steps, dummy_unit, *teams);
src = dst;
}
@ -1349,11 +1348,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
if(game_map->on_board(loc)) {
loc = find_vacant_tile(*game_map,*units,loc);
const bool show = screen != NULL && !screen->fogged(loc.x,loc.y);
const bool animate = show && !screen->turbo() && cfg["animate"] != "";
if (show) {
screen->draw(true,true);
}
const bool animate = show && cfg["animate"] != "";
units->erase(loc);
units->add(new std::pair<gamemap::location,unit>(loc,new_unit));
@ -1366,17 +1361,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
unit_map::iterator un = units->find(loc);
if(animate) {
un->second.set_hidden(true);
screen->scroll_to_tile(loc.x,loc.y,display::ONSCREEN);
un->second.set_hidden(false);
un->second.set_recruited(*screen,un->first);
while(!un->second.get_animation()->animation_finished()) {
screen->invalidate(loc);
screen->draw();
events::pump();
screen->delay(10);
}
un->second.set_standing(*screen, un->first);
unit_display::unit_recruited(loc);
}
else if(show)
un->second.redraw_unit(*screen, loc);
@ -1423,7 +1408,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
gamemap::location loc = cfg_to_loc(cfg);
unit to_recruit(*u);
avail.erase(u); //erase before recruiting, since recruiting can fire more events
recruit_unit(*game_map,index+1,*units,to_recruit,loc,utils::string_bool(cfg["show"],true) ? NULL : screen,false,true);
recruit_unit(*game_map,index+1,*units,to_recruit,loc,utils::string_bool(cfg["show"],true),false,true);
unit_recalled = true;
break;
}
@ -1696,7 +1681,7 @@ bool event_handler::handle_event_command(const queued_event& event_info,
if(game_events::unit_matches_filter(un,cfg)) {
if(utils::string_bool(cfg["animate"])) {
screen->scroll_to_tile(un->first.x,un->first.y);
unit_display::unit_die(*screen,un->first,un->second);
unit_display::unit_die(un->first,un->second);
}
if(utils::string_bool(cfg["fire_event"])) {

View File

@ -990,7 +990,7 @@ namespace events{
action.starting_moves = u->second.movement_left();
unit_display::move_unit(*gui_,map_,route,u->second,units_,teams_);
unit_display::move_unit(map_,route,u->second,teams_);
std::pair<gamemap::location,unit> *up = units_.extract(u->first);
up->second.set_goto(gamemap::location());
up->second.set_movement(starting_moves);
@ -1112,7 +1112,7 @@ namespace events{
action.starting_moves = u->second.movement_left();
unit_display::move_unit(*gui_,map_,route,u->second,units_,teams_);
unit_display::move_unit(map_,route,u->second,teams_);
std::pair<gamemap::location,unit> *up = units_.extract(u->first);
up->second.set_goto(gamemap::location());
up->second.set_movement(starting_moves);

View File

@ -21,6 +21,7 @@
#include "replay.hpp"
#include "sound.hpp"
#include "variable.hpp"
#include "wassert.hpp"
#define LOG_NG LOG_STREAM(info, engine)
@ -43,6 +44,8 @@ play_controller::play_controller(const config& level, const game_data& gameinfo,
game_config::add_color_info(level);
init(video);
wassert(singleton_==NULL);
singleton_=this;
}
play_controller::~play_controller(){
@ -52,6 +55,7 @@ play_controller::~play_controller(){
delete events_manager_;
delete soundsources_manager_;
delete gui_;
singleton_=NULL;
}
void play_controller::init(CVideo& video){
@ -891,3 +895,5 @@ hotkey::ACTION_STATE play_controller::get_action_state(hotkey::HOTKEY_COMMAND co
return hotkey::ACTION_STATELESS;
}
}
play_controller* play_controller::singleton_ = NULL;

View File

@ -74,6 +74,8 @@ public:
virtual void play_side(const unsigned int team_num, bool save) = 0;
const int get_ticks();
display * get_display() { return gui_; }
static play_controller * get_singleton() { return singleton_; }
protected:
void handle_event(const SDL_Event& event);
@ -154,6 +156,7 @@ private:
void expand_wml_commands(std::vector<std::string>& items);
std::vector<wml_menu_item *> wml_commands_;
static play_controller* singleton_;
#define MAX_WML_COMMANDS 7
};

View File

@ -888,13 +888,13 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
rt->second.steps.push_back(dst);
if(!replayer.is_skipping() && unit_display::unit_visible_on_path(disp,rt->second.steps,u->second,units,teams)) {
if(!replayer.is_skipping() && unit_display::unit_visible_on_path(rt->second.steps,u->second,units,teams)) {
disp.scroll_to_tiles(src.x,src.y,dst.x,dst.y);
}
if(!replayer.is_skipping()) {
unit_display::move_unit(disp,map,rt->second.steps,u->second,units,teams);
unit_display::move_unit(map,rt->second.steps,u->second,teams);
}
else{
//unit location needs to be updated

View File

@ -1318,7 +1318,7 @@ void unit::read(const config& cfg)
healed_animations_.push_back(healed_animation(**healed_anim));
}
if(healed_animations_.empty()) {
healed_animations_.push_back(healed_animation(0,unit_frame(absolute_image(),240,"1.0","",display::rgb(255,255,255),"0:30,0.5:30,0:30,0.5:30,0:30,0.5:30,0:30,0.5:30")));
healed_animations_.push_back(healed_animation(0,unit_frame(absolute_image(),240,"1.0","",display::rgb(255,255,255),"0:30,0.5:30,0:30,0.5:30,0:30,0.5:30,0:30,0.5:30,0:30")));
// always have a healed animation
}
@ -1508,7 +1508,7 @@ void unit::set_standing(const display &disp,const gamemap::location& loc, bool w
void unit::set_defending(const display &disp,const gamemap::location& loc, int damage,const attack_type* attack,const attack_type* secondary_attack,int swing_num)
{
state_ = STATE_DEFENDING;
draw_bars_ = false;
draw_bars_ = true;
delete anim_;
@ -1551,7 +1551,7 @@ void unit::set_extra_anim(const display &disp,const gamemap::location& loc, std:
const unit_animation & unit::set_attacking(const display &disp,const gamemap::location& loc,int damage,const attack_type& type,const attack_type* secondary_attack,int swing_num)
{
state_ = STATE_ATTACKING;
draw_bars_ = false;
draw_bars_ = true;
delete anim_;
@ -1609,7 +1609,6 @@ void unit::set_recruited(const display &disp,const gamemap::location& loc)
delete anim_;
anim_ = new recruit_animation(recruiting_animation(disp,loc));
// add a fade in effect
anim_->start_animation(anim_->get_begin_time(), false, disp.turbo_speed());
frame_begin_time_ = anim_->get_begin_time() -1;
}
@ -1651,7 +1650,7 @@ void unit::set_teleporting(const display &disp,const gamemap::location& loc)
void unit::set_dying(const display &disp,const gamemap::location& loc,const attack_type* attack,const attack_type* secondary_attack)
{
state_ = STATE_DYING;
draw_bars_ = false;
draw_bars_ = true;
delete anim_;
@ -1675,7 +1674,7 @@ void unit::set_healing(const display &disp,const gamemap::location& loc,int heal
void unit::set_victorious(const display &disp,const gamemap::location& loc,const attack_type* attack,const attack_type* secondary_attack)
{
state_ = STATE_VICTORIOUS;
draw_bars_ = false;
draw_bars_ = true;
delete anim_;

View File

@ -27,51 +27,54 @@
#include "unit_display.hpp"
#include "util.hpp"
#include "wassert.hpp"
#include "play_controller.hpp"
#define LOG_DP LOG_STREAM(info, display)
static void teleport_unit_between(display& disp, const gamemap::location& a, const gamemap::location& b, unit& temp_unit)
static void teleport_unit_between( const gamemap::location& a, const gamemap::location& b, unit& temp_unit)
{
if(disp.update_locked() || disp.fogged(a.x,a.y) && disp.fogged(b.x,b.y)) {
display* disp = play_controller::get_singleton()->get_display();
if(!disp || disp->update_locked() || disp->fogged(a.x,a.y) && disp->fogged(b.x,b.y)) {
return;
}
temp_unit.set_teleporting(disp,a);
if (!disp.fogged(a.x, a.y)) { // teleport
disp.scroll_to_tile(a.x,a.y,display::ONSCREEN);
temp_unit.set_teleporting(*disp,a);
if (!disp->fogged(a.x, a.y)) { // teleport
disp->scroll_to_tile(a.x,a.y,display::ONSCREEN);
while(!temp_unit.get_animation()->animation_finished() && temp_unit.get_animation()->get_animation_time() < 0) {
disp.invalidate(a);
disp.place_temporary_unit(temp_unit, a);
disp.draw();
disp->invalidate(a);
disp->place_temporary_unit(temp_unit, a);
disp->draw();
events::pump();
disp.delay(10);
disp->delay(10);
}
}
if (!disp.fogged(b.x, b.y)) { // teleport
temp_unit.restart_animation(disp,0);
disp.scroll_to_tile(b.x,b.y,display::ONSCREEN);
if (!disp->fogged(b.x, b.y)) { // teleport
temp_unit.restart_animation(*disp,0);
disp->scroll_to_tile(b.x,b.y,display::ONSCREEN);
while(!temp_unit.get_animation()->animation_finished()) {
disp.invalidate(b);
disp.place_temporary_unit(temp_unit, b);
disp.draw();
disp->invalidate(b);
disp->place_temporary_unit(temp_unit, b);
disp->draw();
events::pump();
disp.delay(10);
disp->delay(10);
}
}
temp_unit.set_standing(disp,b);
disp.update_display();
temp_unit.set_standing(*disp,b);
disp->update_display();
events::pump();
}
static void move_unit_between(display& disp, const gamemap& map, const gamemap::location& a, const gamemap::location& b, unit& temp_unit)
static void move_unit_between( const gamemap& map, const gamemap::location& a, const gamemap::location& b, unit& temp_unit)
{
if(disp.update_locked() || disp.fogged(a.x,a.y) && disp.fogged(b.x,b.y)) {
display* disp = play_controller::get_singleton()->get_display();
if(!disp || disp->update_locked() || disp->fogged(a.x,a.y) && disp->fogged(b.x,b.y)) {
return;
}
const t_translation::t_letter dst_terrain = map.get_terrain(b);
const double acceleration = disp.turbo_speed();
const double acceleration = disp->turbo_speed();
gamemap::location src_adjacent[6];
get_adjacent_tiles(a, src_adjacent);
@ -79,22 +82,22 @@ static void move_unit_between(display& disp, const gamemap& map, const gamemap::
gamemap::location dst_adjacent[6];
get_adjacent_tiles(b, dst_adjacent);
const int total_mvt_time = (int)150 * temp_unit.movement_cost(dst_terrain)/acceleration;
const int total_mvt_time = 150 * (int)(temp_unit.movement_cost(dst_terrain)/acceleration);
const unsigned int start_time = SDL_GetTicks();
int mvt_time = 1;
disp.scroll_to_tiles(a.x,a.y,b.x,b.y,display::ONSCREEN);
disp->scroll_to_tiles(a.x,a.y,b.x,b.y,display::ONSCREEN);
while(mvt_time < total_mvt_time-1) { // one draw in each hex at least
disp.delay(10);
disp->delay(10);
mvt_time = SDL_GetTicks() -start_time;
if(mvt_time >=total_mvt_time) mvt_time = total_mvt_time -1;
double pos =double(mvt_time)/total_mvt_time;
const gamemap::location& ref_loc =pos<0.5?a:b;
if(pos >= 0.5) pos = pos -1;
temp_unit.set_walking(disp,ref_loc);
temp_unit.set_walking(*disp,ref_loc);
temp_unit.set_offset(pos);
disp.place_temporary_unit(temp_unit,ref_loc);
disp.draw();
disp->place_temporary_unit(temp_unit,ref_loc);
disp->draw();
events::pump();
}
@ -103,10 +106,12 @@ static void move_unit_between(display& disp, const gamemap& map, const gamemap::
namespace unit_display
{
bool unit_visible_on_path(display& disp, const std::vector<gamemap::location>& path, const unit& u, const unit_map& units, const std::vector<team>& teams)
bool unit_visible_on_path( const std::vector<gamemap::location>& path, const unit& u, const unit_map& units, const std::vector<team>& teams)
{
display* disp = play_controller::get_singleton()->get_display();
wassert(disp);
for(size_t i = 0; i+1 < path.size(); ++i) {
const bool invisible = teams[u.side()-1].is_enemy(int(disp.viewing_team()+1)) &&
const bool invisible = teams[u.side()-1].is_enemy(int(disp->viewing_team()+1)) &&
u.invisible(path[i],units,teams) &&
u.invisible(path[i+1],units,teams);
if(!invisible) {
@ -117,9 +122,12 @@ bool unit_visible_on_path(display& disp, const std::vector<gamemap::location>& p
return false;
}
void move_unit(display& disp, const gamemap& map, const std::vector<gamemap::location>& path, unit& u, const unit_map& units, const std::vector<team>& teams)
void move_unit( const gamemap& map, const std::vector<gamemap::location>& path, unit& u, const std::vector<team>& teams)
{
display* disp = play_controller::get_singleton()->get_display();
wassert(!path.empty());
wassert(disp);
const unit_map& units = disp->get_units();
bool previous_visible = false;
bool was_hidden = u.get_hidden();
@ -131,48 +139,49 @@ void move_unit(display& disp, const gamemap& map, const std::vector<gamemap::loc
for(size_t i = 0; i+1 < path.size(); ++i) {
temp_unit.set_facing(path[i].get_relative_dir(path[i+1]));
disp.remove_footstep(path[i]);
disp->remove_footstep(path[i]);
bool invisible = teams[temp_unit.side()-1].is_enemy(int(disp.viewing_team()+1)) &&
bool invisible = teams[temp_unit.side()-1].is_enemy(int(disp->viewing_team()+1)) &&
temp_unit.invisible(path[i],units,teams) &&
temp_unit.invisible(path[i+1],units,teams);
if(!invisible) {
if( !tiles_adjacent(path[i], path[i+1])) {
teleport_unit_between(disp,path[i],path[i+1],temp_unit);
teleport_unit_between(path[i],path[i+1],temp_unit);
} else {
move_unit_between(disp,map,path[i],path[i+1],temp_unit);
move_unit_between(map,path[i],path[i+1],temp_unit);
}
previous_visible = true;
} else if(previous_visible) {
gamemap::location arr[6];
disp.invalidate(path[i]);
disp->invalidate(path[i]);
get_adjacent_tiles(path[i], arr);
for (unsigned int i = 0; i < 6; i++) {
disp.invalidate(arr[i]);
disp->invalidate(arr[i]);
}
disp.draw();
disp->draw();
previous_visible = false;
} else {
previous_visible = false;
}
}
disp.remove_temporary_unit();
disp->remove_temporary_unit();
u.set_facing(path[path.size()-2].get_relative_dir(path[path.size()-1]));
u.set_standing(disp,path[path.size()-1]);
u.set_standing(*disp,path[path.size()-1]);
//make sure the entire path is cleaned properly
for(std::vector<gamemap::location>::const_iterator it = path.begin(); it != path.end(); ++it) {
disp.invalidate(*it);
disp->invalidate(*it);
}
u.set_hidden(was_hidden);
}
void unit_die(display& disp,const gamemap::location& loc, unit& loser,
void unit_die(const gamemap::location& loc, unit& loser,
const attack_type* attack,const attack_type* secondary_attack, unit* winner)
{
if(disp.update_locked() || disp.fogged(loc.x,loc.y) || preferences::show_combat() == false) {
display* disp = play_controller::get_singleton()->get_display();
if(!disp ||disp->update_locked() || disp->fogged(loc.x,loc.y) || preferences::show_combat() == false) {
return;
}
const std::string& die_sound = loser.die_sound();
@ -180,41 +189,44 @@ const attack_type* attack,const attack_type* secondary_attack, unit* winner)
sound::play_sound(die_sound);
}
loser.set_dying(disp,loc,attack,secondary_attack);
loser.set_dying(*disp,loc,attack,secondary_attack);
if(winner == NULL) { //test to see if there is no victor.
while(!loser.get_animation()->animation_finished()) {
disp.invalidate(loc);
disp.draw();
disp->invalidate(loc);
disp->draw();
events::pump();
disp.delay(10);
disp->delay(10);
}
return;
}
winner->set_victorious(disp,loc,attack,secondary_attack);
winner->set_victorious(*disp,loc,attack,secondary_attack);
int start_time = minimum<int>(loser.get_animation()->get_begin_time(),winner->get_animation()->get_begin_time());
winner->restart_animation(disp,start_time);
loser.restart_animation(disp,start_time);
winner->restart_animation(*disp,start_time);
loser.restart_animation(*disp,start_time);
while((!loser.get_animation()->animation_would_finish()) || ((!winner->get_animation()->animation_would_finish()))) {
disp.invalidate(loc);
disp.draw();
disp->invalidate(loc);
disp->draw();
events::pump();
disp.delay(10);
disp->delay(10);
}
}
static void unit_attack_ranged(display& disp, unit_map& units,
static void unit_attack_ranged(
const gamemap::location& a, const gamemap::location& b,
int damage, const attack_type& attack, const attack_type* secondary_attack,bool update_display, int swing)
int damage, const attack_type& attack, const attack_type* secondary_attack, int swing,std::string hit_text)
{
const bool hide = disp.update_locked() || disp.fogged(a.x,a.y) && disp.fogged(b.x,b.y)
|| preferences::show_combat() == false || (!update_display);
display* disp = play_controller::get_singleton()->get_display();
if(!disp) return;
const bool hide = disp->update_locked() || disp->fogged(a.x,a.y) && disp->fogged(b.x,b.y)
|| preferences::show_combat() == false ;
unit_map& units = disp->get_units();
log_scope("unit_attack_range");
const unit_map::iterator att = units.find(a);
@ -223,16 +235,20 @@ static void unit_attack_ranged(display& disp, unit_map& units,
const unit_map::iterator def = units.find(b);
wassert(def != units.end());
unit& defender = def->second;
bool def_was_hidden = def->second.get_hidden();
def->second.set_hidden(true);
unit defender = def->second;
disp->place_temporary_unit(defender,b);
defender.set_hidden(false);
const double acceleration = disp.turbo_speed();
const double acceleration = disp->turbo_speed();
// more damage shown for longer, but 1s at most for this factor
const double xsrc = disp.get_location_x(a);
const double ysrc = disp.get_location_y(a) - (attacker.is_flying() ? 0 : disp.get_map().get_terrain_info(disp.get_map().get_terrain(a)).unit_height_adjust());
const double xdst = disp.get_location_x(b);
const double ydst = disp.get_location_y(b) -( defender.is_flying() ? 0 : disp.get_map().get_terrain_info(disp.get_map().get_terrain(b)).unit_height_adjust());
const double xsrc = disp->get_location_x(a);
const double ysrc = disp->get_location_y(a) - (attacker.is_flying() ? 0 : disp->get_map().get_terrain_info(disp->get_map().get_terrain(a)).unit_height_adjust());
const double xdst = disp->get_location_x(b);
const double ydst = disp->get_location_y(b) -( defender.is_flying() ? 0 : disp->get_map().get_terrain_info(disp->get_map().get_terrain(b)).unit_height_adjust());
gamemap::location update_tiles[6];
get_adjacent_tiles(b,update_tiles);
@ -241,7 +257,7 @@ static void unit_attack_ranged(display& disp, unit_map& units,
// start leader and attacker animation, wait for attacker animation to end
unit_animation missile_animation = attacker.set_attacking(disp,a,damage,attack,secondary_attack,swing);
unit_animation missile_animation = attacker.set_attacking(*disp,a,damage,attack,secondary_attack,swing);
const gamemap::location leader_loc = under_leadership(units,a);
unit_map::iterator leader = units.end();
if(leader_loc.valid()){
@ -249,7 +265,7 @@ static void unit_attack_ranged(display& disp, unit_map& units,
leader = units.find(leader_loc);
wassert(leader != units.end());
leader->second.set_facing(leader_loc.get_relative_dir(a));
leader->second.set_leading(disp,leader_loc);
leader->second.set_leading(*disp,leader_loc);
}
int animation_time;
@ -279,15 +295,15 @@ static void unit_attack_ranged(display& disp, unit_map& units,
}
const bool vertical_dir = (a.x == b.x) ? true:false;
defender.set_defending(disp,b,damage,&attack,secondary_attack,swing);
defender.set_defending(*disp,b,damage,&attack,secondary_attack,swing);
// min of attacker, defender, missile and -200
int start_time = -200;
start_time = minimum<int>(start_time,defender.get_animation()->get_begin_time());
start_time = minimum<int>(start_time,missile_animation.get_begin_time());
start_time = minimum<int>(start_time,attacker.get_animation()->get_begin_time());
missile_animation.start_animation(start_time,false,acceleration);
defender.restart_animation(disp,start_time);
attacker.restart_animation(disp,start_time);
defender.restart_animation(*disp,start_time);
attacker.restart_animation(*disp,start_time);
animation_time = defender.get_animation()->get_animation_time();
bool sound_played = false ;
int missile_frame_halo = halo::NO_HALO;
@ -296,7 +312,8 @@ static void unit_attack_ranged(display& disp, unit_map& units,
!attacker.get_animation()->animation_would_finish() ||
!defender.get_animation()->animation_would_finish() ||
!missile_animation.animation_finished() ||
(leader_loc.valid() && !leader->second.get_animation()->animation_finished()))
(leader_loc.valid() && !leader->second.get_animation()->animation_finished()) ||
damage >0)
){
const unit_frame& missile_frame = missile_animation.get_current_frame();
double pos = missile_frame.offset(missile_animation.get_current_frame_time());
@ -304,21 +321,21 @@ static void unit_attack_ranged(display& disp, unit_map& units,
pos = double(animation_time -missile_animation.get_begin_time())/
double(missile_animation.get_end_time()-missile_animation.get_begin_time());
}
disp.invalidate(b);
disp.invalidate(a);
if(leader_loc.valid()) disp.invalidate(leader_loc);
disp->invalidate(b);
disp->invalidate(a);
if(leader_loc.valid()) disp->invalidate(leader_loc);
halo::remove(missile_halo);
halo::remove(missile_frame_halo);
missile_halo = halo::NO_HALO;
missile_frame_halo = halo::NO_HALO;
if(animation_time > missile_animation.get_begin_time() &&
animation_time < missile_animation.get_end_time() &&
(!disp.fogged(b.x,b.y) || !disp.fogged(a.x,a.y))) {
(!disp->fogged(b.x,b.y) || !disp->fogged(a.x,a.y))) {
const int posx = int(pos*xdst + (1.0-pos)*xsrc);
const int posy = int(pos*ydst + (1.0-pos)*ysrc);
image::locator missile_image= missile_frame.image();
const int d = disp.hex_size() / 2;
const int d = disp->hex_size() / 2;
if(vertical_dir) {
missile_image = missile_frame.image();
} else {
@ -346,47 +363,54 @@ static void unit_attack_ranged(display& disp, unit_map& units,
orientation);
}
if(damage > 0 && animation_time > 0 && !sound_played) {
if(!sound_played && animation_time > 0) {
sound_played = true;
sound::play_sound(def->second.get_hit_sound());
disp.float_label(b,lexical_cast<std::string>(damage),255,0,0);
disp.invalidate_unit();
std::string text ;
if(damage) text = lexical_cast<std::string>(damage);
if(!hit_text.empty()) text = text + "\n" + hit_text;
sound::play_sound(defender.get_hit_sound());
disp->float_label(b,text,255,0,0);
disp->invalidate_unit();
}
disp.draw();
if(damage > 0 && animation_time > 0) {
defender.take_hit(1);
damage--;
disp->invalidate_unit();
}
disp->draw();
events::pump();
missile_animation.update_last_draw_time();
disp.delay(10);
disp->delay(10);
// we use missile animation because it's the only one not reseted in the middle to go to standing
animation_time = missile_animation.get_animation_time();
}
// make sure get hit sound is always played and labels always displayed
if(damage > 0 && !hide && !sound_played) {
sound_played = true;
sound::play_sound(def->second.get_hit_sound());
disp.float_label(b,lexical_cast<std::string>(damage),255,0,0);
disp.invalidate_unit();
}
halo::remove(missile_halo);
missile_halo = halo::NO_HALO;
halo::remove(missile_frame_halo);
missile_frame_halo = halo::NO_HALO;
if(leader_loc.valid()) leader->second.set_standing(disp,leader_loc);
att->second.set_standing(disp,a);
def->second.set_standing(disp,b);
if(leader_loc.valid()) leader->second.set_standing(*disp,leader_loc);
att->second.set_standing(*disp,a);
def->second.set_standing(*disp,b);
def->second.set_hidden(def_was_hidden);
disp->remove_temporary_unit();
}
void unit_attack(display& disp, unit_map& units,
void unit_attack(
const gamemap::location& a, const gamemap::location& b, int damage,
const attack_type& attack, const attack_type* secondary_attack,
bool update_display, int swing)
int swing,std::string hit_text)
{
const bool hide = disp.update_locked() || disp.fogged(a.x,a.y) && disp.fogged(b.x,b.y)
|| preferences::show_combat() == false || (!update_display);
display* disp = play_controller::get_singleton()->get_display();
if(!disp) return;
unit_map& units = disp->get_units();
const bool hide = disp->update_locked() || disp->fogged(a.x,a.y) && disp->fogged(b.x,b.y)
|| preferences::show_combat() == false;
if(!hide) {
disp.scroll_to_tiles(a.x,a.y,b.x,b.y,display::ONSCREEN);
disp->scroll_to_tiles(a.x,a.y,b.x,b.y,display::ONSCREEN);
}
log_scope("unit_attack");
@ -397,24 +421,29 @@ void unit_attack(display& disp, unit_map& units,
const unit_map::iterator def = units.find(b);
wassert(def != units.end());
unit& defender = def->second;
att->second.set_facing(a.get_relative_dir(b));
def->second.set_facing(b.get_relative_dir(a));
if(attack.range_type() == attack_type::LONG_RANGE) {
unit_attack_ranged(disp, units, a, b, damage, attack,secondary_attack, update_display, swing);
unit_attack_ranged( a, b, damage, attack,secondary_attack, swing, hit_text);
return;
}
int start_time = 500;
int end_time = 0;
bool def_was_hidden = def->second.get_hidden();
def->second.set_hidden(true);
unit defender = def->second;
disp->place_temporary_unit(defender,b);
defender.set_hidden(false);
attacker.set_attacking(disp,a,damage,attack,secondary_attack,swing);
attacker.set_attacking(*disp,a,damage,attack,secondary_attack,swing);
start_time=minimum<int>(start_time,attacker.get_animation()->get_begin_time());
end_time=attacker.get_animation()->get_end_time();
defender.set_defending(disp,b,damage,&attack, secondary_attack, swing);
defender.set_defending(*disp,b,damage,&attack, secondary_attack, swing);
start_time=minimum<int>(start_time,defender.get_animation()->get_begin_time());
@ -425,7 +454,7 @@ void unit_attack(display& disp, unit_map& units,
leader = units.find(leader_loc);
wassert(leader != units.end());
leader->second.set_facing(leader_loc.get_relative_dir(a));
leader->second.set_leading(disp,leader_loc);
leader->second.set_leading(*disp,leader_loc);
start_time=minimum<int>(start_time,leader->second.get_animation()->get_begin_time());
}
@ -434,16 +463,17 @@ void unit_attack(display& disp, unit_map& units,
get_adjacent_tiles(b,update_tiles);
attacker.restart_animation(disp,start_time);
defender.restart_animation(disp,start_time);
if(leader_loc.valid()) leader->second.restart_animation(disp,start_time);
attacker.restart_animation(*disp,start_time);
defender.restart_animation(*disp,start_time);
if(leader_loc.valid()) leader->second.restart_animation(*disp,start_time);
int animation_time = start_time;
bool played_center = false;
bool sound_played = false;
while(!hide && (
!attacker.get_animation()->animation_would_finish() ||
!defender.get_animation()->animation_would_finish() ||
(leader_loc.valid() && !leader->second.get_animation()->animation_would_finish() ))
(leader_loc.valid() && !leader->second.get_animation()->animation_would_finish() ) ||
damage > 0)
){
double pos = 0.0;
@ -457,31 +487,134 @@ void unit_attack(display& disp, unit_map& units,
if(attacker.state() != unit::STATE_STANDING && pos > 0.0) {
attacker.set_offset(pos*0.6);
}
if(!played_center && animation_time >= 0) {
played_center=true;
if(damage > 0 && !hide) {
sound::play_sound(def->second.get_hit_sound());
disp.float_label(b,lexical_cast<std::string>(damage),255,0,0);
disp.invalidate_unit();
}
if(!sound_played && animation_time > 0) {
sound_played = true;
std::string text ;
if(damage) text = lexical_cast<std::string>(damage);
if(!hit_text.empty()) text = text + "\n" + hit_text;
sound::play_sound(defender.get_hit_sound());
disp->float_label(b,text,255,0,0);
disp->invalidate_unit();
}
disp.invalidate(b);
disp.invalidate(a);
if(leader_loc.valid()) disp.invalidate(leader_loc);
disp.draw();
if(damage > 0 && animation_time > 0) {
defender.take_hit(1);
damage--;
disp->invalidate_unit();
}
disp->invalidate(b);
disp->invalidate(a);
if(leader_loc.valid()) disp->invalidate(leader_loc);
disp->draw();
events::pump();
if(attacker.get_animation()->animation_finished()) {
attacker.set_offset(0.0);
}
disp.delay(10);
disp->delay(10);
animation_time = attacker.get_animation()->get_animation_time();
}
if(leader_loc.valid()) leader->second.set_standing(disp,leader_loc);
att->second.set_standing(disp,a);
def->second.set_standing(disp,b);
if(leader_loc.valid()) leader->second.set_standing(*disp,leader_loc);
att->second.set_standing(*disp,a);
def->second.set_standing(*disp,b);
def->second.set_hidden(def_was_hidden);
disp->remove_temporary_unit();
}
void unit_recruited(gamemap::location& loc)
{
display* disp = play_controller::get_singleton()->get_display();
if(!disp || disp->update_locked() ||disp->fogged(loc.x,loc.y)) 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.x,loc.y,display::ONSCREEN);
disp->draw();
u->second.set_recruited(*disp,loc);
u->second.set_hidden(false);
while(!u->second.get_animation()->animation_finished()) {
disp->invalidate(loc);
disp->draw();
events::pump();
disp->delay(10);
}
u->second.set_standing(*disp,loc);
}
void unit_healing(unit& healed_p,gamemap::location& healed_loc, std::vector<unit_map::iterator> healers, int healing)
{
display* disp = play_controller::get_singleton()->get_display();
if(!disp || disp->update_locked() || disp->fogged(healed_loc.x,healed_loc.y)) return;
if(healing==0) return;
// This is all the pretty stuff.
int start_time = INT_MAX;
disp->scroll_to_tile(healed_loc.x, healed_loc.y, display::ONSCREEN);
disp->select_hex(healed_loc);
unit healed = healed_p;
bool was_hidden = healed.get_hidden();
healed_p.set_hidden(true);
disp->place_temporary_unit(healed,healed_loc);
healed.set_hidden(false);
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));
(*heal_anim_it)->second.set_healing(*disp,(*heal_anim_it)->first,healing);
start_time = minimum<int>((*heal_anim_it)->second.get_animation()->get_begin_time(),start_time);
}
if (healing < 0) {
healed.set_poisoned(*disp,healed_loc, -healing);
start_time = minimum<int>(start_time, healed.get_animation()->get_begin_time());
// FIXME
sound::play_sound("poison.ogg");
disp->float_label(healed_loc, lexical_cast<std::string>(-healing), 255,0,0);
} else {
healed.set_healed(*disp,healed_loc, healing);
start_time = minimum<int>(start_time, healed.get_animation()->get_begin_time());
sound::play_sound("heal.wav");
disp->float_label(healed_loc, lexical_cast<std::string>(healing), 0,255,0);
}
disp->draw();
events::pump();
// restart all anims in a synchronized way
healed.restart_animation(*disp, start_time);
for(std::vector<unit_map::iterator>::iterator heal_reanim_it = healers.begin(); heal_reanim_it != healers.end(); ++heal_reanim_it) {
(*heal_reanim_it)->second.restart_animation(*disp, start_time);
}
bool finished;
do {
finished = (healed.get_animation()->animation_finished() && healing==0);
disp->invalidate(healed_loc);
for(std::vector<unit_map::iterator>::iterator heal_fanim_it = healers.begin(); heal_fanim_it != healers.end(); ++heal_fanim_it) {
finished &= (*heal_fanim_it)->second.get_animation()->animation_finished();
disp->invalidate((*heal_fanim_it)->first);
}
// TODO : adapt HP change speed to turbo_speed
if(healing > 0) {
healed.heal(1);
healing--;
} else if (healing < 0) {
healed.take_hit(1);
healing++;
}
disp->draw();
events::pump();
disp->delay(10);
} while (!finished);
healed_p.set_standing(*disp,healed_loc);
healed_p.set_hidden(was_hidden);
disp->remove_temporary_unit();
for(std::vector<unit_map::iterator>::iterator heal_sanim_it = healers.begin(); heal_sanim_it != healers.end(); ++heal_sanim_it) {
(*heal_sanim_it)->second.set_standing(*disp,(*heal_sanim_it)->first);
}
disp->update_display();
events::pump();
}
} // end unit display namespace

View File

@ -17,7 +17,6 @@
#include "map.hpp"
class attack_type;
class display;
class team;
class unit;
class unit_map;
@ -27,25 +26,30 @@ class unit_map;
///attacking, and dying
namespace unit_display
{
bool unit_visible_on_path(display& disp, const std::vector<gamemap::location>& path, const unit& u, const unit_map& units, const std::vector<team>& teams);
bool unit_visible_on_path( const std::vector<gamemap::location>& path, const unit& u, const unit_map& units, const std::vector<team>& teams);
///a function to display a unit moving along a given path
void move_unit(display& disp, const gamemap& map, const std::vector<gamemap::location>& path, unit& u, const unit_map& units, const std::vector<team>& teams);
void move_unit( const gamemap& map, const std::vector<gamemap::location>& path, unit& u, const std::vector<team>& teams);
///a function to show a unit fading out. Note that this only shows the effect, it doesn't
///actually kill the unit.
void unit_die(display& disp, const gamemap::location& loc, unit& u, const attack_type* attack=NULL, const attack_type*secondary_attack=NULL, unit * winner=NULL);
void unit_die( const gamemap::location& loc, unit& u, const attack_type* attack=NULL, const attack_type*secondary_attack=NULL, unit * winner=NULL);
///a function to make the unit on tile 'a' attack the unit on tile 'b'.
///the 'damage' will be subtracted from the unit's hitpoints, and a die effect will be
///displayed if the unit dies.
///true is returned if the defending unit is dead, and should be removed from the
///playing field.
void unit_attack(display& disp, unit_map& units,
void unit_attack(
const gamemap::location& a, const gamemap::location& b, int damage,
const attack_type& attack, const attack_type* secondary_attack,
bool update_display, int swing);
int swing,std::string hit_text);
void unit_recruited(gamemap::location& loc);
// set healer_loc to an invalid location if there are no healers
// this will use a poisoning anim if healing<0
void unit_healing(unit& healed,gamemap::location& healed_loc, std::vector<unit_map::iterator> healers, int healing);
}
#endif

View File

@ -731,7 +731,7 @@ unit_type::unit_type(const config& cfg, const movement_type_map& mv_types,
healed_animations_.push_back(healed_animation(**healed_anim));
}
if(healed_animations_.empty()) {
healed_animations_.push_back(healed_animation(0,unit_frame(image(),240,"1.0","",display::rgb(255,255,255),"0:30,0.5:30,0:30,0.5:30,0:30,0.5:30,0:30,0.5:30")));
healed_animations_.push_back(healed_animation(0,unit_frame(image(),240,"1.0","",display::rgb(255,255,255),"0:30,0.5:30,0:30,0.5:30,0:30,0.5:30,0:30,0.5:30,0:30")));
// always have a healed animation
}
expanded_cfg = unit_animation::prepare_animation(cfg,"poison_anim");