mirror of
https://github.com/wesnoth/wesnoth
synced 2025-04-28 18:43:17 +00:00
unit drawing logic cleanup,
should fix various acceleration bugs and restore status bars during fight
This commit is contained in:
parent
2f9ee22ecd
commit
e111e5d439
190
src/actions.cpp
190
src/actions.cpp
@ -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());
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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"])) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
};
|
||||
|
@ -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
|
||||
|
11
src/unit.cpp
11
src/unit.cpp
@ -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_;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user