Merge branch 'drawable_units'
This commit is contained in:
commit
f0fc9ff5c7
19 changed files with 419 additions and 315 deletions
|
@ -193,6 +193,8 @@
|
|||
<Unit filename="../../src/display.hpp" />
|
||||
<Unit filename="../../src/display_context.cpp" />
|
||||
<Unit filename="../../src/display_context.hpp" />
|
||||
<Unit filename="../../src/drawable_unit.cpp" />
|
||||
<Unit filename="../../src/drawable_unit.hpp" />
|
||||
<Unit filename="../../src/editor/action/action_base.hpp" />
|
||||
<Unit filename="../../src/editor/action/action.cpp" />
|
||||
<Unit filename="../../src/editor/action/action.hpp" />
|
||||
|
|
|
@ -231,6 +231,8 @@
|
|||
<Unit filename="..\..\src\display.hpp" />
|
||||
<Unit filename="..\..\src\display_context.cpp" />
|
||||
<Unit filename="..\..\src\display_context.hpp" />
|
||||
<Unit filename="..\..\src\drawable_unit.cpp" />
|
||||
<Unit filename="..\..\src\drawable_unit.hpp" />
|
||||
<Unit filename="..\..\src\editor\action\action.cpp" />
|
||||
<Unit filename="..\..\src\editor\action\action.hpp" />
|
||||
<Unit filename="..\..\src\editor\action\action_base.hpp" />
|
||||
|
|
|
@ -20060,6 +20060,14 @@
|
|||
RelativePath="..\..\src\display_context.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\drawable_unit.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\drawable_unit.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\events.cpp"
|
||||
>
|
||||
|
|
|
@ -700,6 +700,7 @@ set(wesnoth-main_SRC
|
|||
controller_base.cpp
|
||||
desktop_util.cpp
|
||||
dialogs.cpp
|
||||
drawable_unit.cpp
|
||||
editor/action/action.cpp
|
||||
editor/action/action_item.cpp
|
||||
editor/action/action_label.cpp
|
||||
|
|
|
@ -233,6 +233,7 @@ wesnoth_sources = Split("""
|
|||
controller_base.cpp
|
||||
desktop_util.cpp
|
||||
dialogs.cpp
|
||||
drawable_unit.cpp
|
||||
editor/action/action.cpp
|
||||
editor/action/action_unit.cpp
|
||||
editor/action/action_label.cpp
|
||||
|
|
|
@ -1288,37 +1288,5 @@ size_t move_unit_from_replay(const std::vector<map_location> &steps,
|
|||
return move_unit_internal(undo_stack, show_move, NULL, mover);
|
||||
}
|
||||
|
||||
bool unit_can_move(const unit &u)
|
||||
{
|
||||
const team ¤t_team = (*resources::teams)[u.side() - 1];
|
||||
|
||||
if(!u.attacks_left() && u.movement_left()==0)
|
||||
return false;
|
||||
|
||||
// Units with goto commands that have already done their gotos this turn
|
||||
// (i.e. don't have full movement left) should have red globes.
|
||||
if(u.has_moved() && u.has_goto()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
map_location locs[6];
|
||||
get_adjacent_tiles(u.get_location(), locs);
|
||||
for(int n = 0; n != 6; ++n) {
|
||||
if (resources::gameboard->map().on_board(locs[n])) {
|
||||
const unit_map::const_iterator i = resources::units->find(locs[n]);
|
||||
if (i.valid() && !i->incapacitated() &&
|
||||
current_team.is_enemy(i->side())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (u.movement_cost((resources::gameboard->map())[locs[n]]) <= u.movement_left()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}//namespace actions
|
||||
|
|
|
@ -114,13 +114,6 @@ size_t move_unit_from_replay(const std::vector<map_location> &steps,
|
|||
bool continued_move, bool skip_ally_sighted,
|
||||
bool show_move = true);
|
||||
|
||||
/**
|
||||
* Will return true iff the unit @a u has any possible moves
|
||||
* it can do (including attacking etc).
|
||||
*/
|
||||
bool unit_can_move(const unit &u);
|
||||
|
||||
|
||||
}//namespace actions
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "cursor.hpp"
|
||||
#include "drawable_unit.hpp"
|
||||
#include "display.hpp"
|
||||
#include "fake_unit_manager.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
|
@ -2553,7 +2554,7 @@ void display::draw_invalidated() {
|
|||
exclusive_unit_draw_requests_t::iterator request = exclusive_unit_draw_requests_.find(loc);
|
||||
if (u_it != dc_->units().end()
|
||||
&& (request == exclusive_unit_draw_requests_.end() || request->second == u_it->id()))
|
||||
u_it->redraw_unit();
|
||||
(static_cast<const drawable_unit*> (&*u_it))->redraw_unit();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -165,6 +165,8 @@ public:
|
|||
|
||||
void change_display_context(const display_context * dc);
|
||||
|
||||
const display_context & get_disp_context() { return *dc_; }
|
||||
|
||||
static Uint32 rgb(Uint8 red, Uint8 green, Uint8 blue)
|
||||
{ return 0xFF000000 | (red << 16) | (green << 8) | blue; }
|
||||
static Uint8 red(Uint32 color)
|
||||
|
|
|
@ -29,3 +29,41 @@ const unit * display_context::get_visible_unit(const map_location & loc, const t
|
|||
}
|
||||
return &*u;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return true iff the unit @a u has any possible moves
|
||||
* it can do (including attacking etc).
|
||||
*/
|
||||
|
||||
bool display_context::unit_can_move(const unit &u) const
|
||||
{
|
||||
if(!u.attacks_left() && u.movement_left()==0)
|
||||
return false;
|
||||
|
||||
// Units with goto commands that have already done their gotos this turn
|
||||
// (i.e. don't have full movement left) should have red globes.
|
||||
if(u.has_moved() && u.has_goto()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const team ¤t_team = teams()[u.side() - 1];
|
||||
|
||||
map_location locs[6];
|
||||
get_adjacent_tiles(u.get_location(), locs);
|
||||
for(int n = 0; n != 6; ++n) {
|
||||
if (map().on_board(locs[n])) {
|
||||
const unit_map::const_iterator i = units().find(locs[n]);
|
||||
if (i.valid() && !i->incapacitated() &&
|
||||
current_team.is_enemy(i->side())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (u.movement_cost(map()[locs[n]]) <= u.movement_left()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,16 @@ public:
|
|||
virtual const gamemap & map() const = 0;
|
||||
virtual const unit_map & units() const = 0;
|
||||
|
||||
// Needed for reports
|
||||
|
||||
const unit * get_visible_unit(const map_location &loc, const team ¤t_team, bool see_all = false) const;
|
||||
|
||||
// From actions:: namespace
|
||||
|
||||
bool unit_can_move(const unit & u) const;
|
||||
|
||||
// Dtor
|
||||
|
||||
virtual ~display_context() {}
|
||||
};
|
||||
|
||||
|
|
294
src/drawable_unit.cpp
Normal file
294
src/drawable_unit.cpp
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include "drawable_unit.hpp"
|
||||
|
||||
#include "display.hpp"
|
||||
#include "display_context.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "halo.hpp"
|
||||
#include "map.hpp"
|
||||
#include "team.hpp"
|
||||
#include "unit_animation.hpp"
|
||||
#include "unit_frame.hpp"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
void drawable_unit::redraw_unit () const
|
||||
{
|
||||
display &disp = *display::get_singleton();
|
||||
const gamemap &map = disp.get_map();
|
||||
|
||||
if ( hidden_ || disp.is_blindfolded() || !is_visible_to_team(disp.get_teams()[disp.viewing_team()],map, disp.show_everything()) )
|
||||
{
|
||||
clear_haloes();
|
||||
if(anim_) {
|
||||
anim_->update_last_draw_time();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!anim_) {
|
||||
set_standing();
|
||||
if (!anim_) return;
|
||||
}
|
||||
|
||||
if (refreshing_) return;
|
||||
refreshing_ = true;
|
||||
|
||||
anim_->update_last_draw_time();
|
||||
frame_parameters params;
|
||||
const t_translation::t_terrain terrain = map.get_terrain(loc_);
|
||||
const terrain_type& terrain_info = map.get_terrain_info(terrain);
|
||||
|
||||
// do not set to 0 so we can distinguish the flying from the "not on submerge terrain"
|
||||
// instead use -1.0 (as in "negative depth", it will be ignored by rendering)
|
||||
params.submerge= is_flying() ? -1.0 : terrain_info.unit_submerge();
|
||||
|
||||
if (invisible(loc_) &&
|
||||
params.highlight_ratio > 0.5) {
|
||||
params.highlight_ratio = 0.5;
|
||||
}
|
||||
if (loc_ == disp.selected_hex() && params.highlight_ratio == 1.0) {
|
||||
params.highlight_ratio = 1.5;
|
||||
}
|
||||
|
||||
int height_adjust = static_cast<int>(terrain_info.unit_height_adjust() * disp.get_zoom_factor());
|
||||
if (is_flying() && height_adjust < 0) {
|
||||
height_adjust = 0;
|
||||
}
|
||||
params.y -= height_adjust;
|
||||
params.halo_y -= height_adjust;
|
||||
|
||||
int red = 0,green = 0,blue = 0,tints = 0;
|
||||
double blend_ratio = 0;
|
||||
// Add future colored states here
|
||||
if(get_state(STATE_POISONED)) {
|
||||
green += 255;
|
||||
blend_ratio += 0.25;
|
||||
tints += 1;
|
||||
}
|
||||
if(get_state(STATE_SLOWED)) {
|
||||
red += 191;
|
||||
green += 191;
|
||||
blue += 255;
|
||||
blend_ratio += 0.25;
|
||||
tints += 1;
|
||||
}
|
||||
if(tints > 0) {
|
||||
params.blend_with = disp.rgb((red/tints),(green/tints),(blue/tints));
|
||||
params.blend_ratio = ((blend_ratio/tints));
|
||||
}
|
||||
|
||||
//hackish : see unit_frame::merge_parameters
|
||||
// we use image_mod on the primary image
|
||||
// and halo_mod on secondary images and all haloes
|
||||
params.image_mod = image_mods();
|
||||
params.halo_mod = TC_image_mods();
|
||||
params.image= absolute_image();
|
||||
|
||||
|
||||
if(get_state(STATE_PETRIFIED)) params.image_mod +="~GS()";
|
||||
params.primary_frame = t_true;
|
||||
|
||||
|
||||
const frame_parameters adjusted_params = anim_->get_current_params(params);
|
||||
|
||||
const map_location dst = loc_.get_direction(facing_);
|
||||
const int xsrc = disp.get_location_x(loc_);
|
||||
const int ysrc = disp.get_location_y(loc_);
|
||||
const int xdst = disp.get_location_x(dst);
|
||||
const int ydst = disp.get_location_y(dst);
|
||||
int d2 = disp.hex_size() / 2;
|
||||
|
||||
const int x = static_cast<int>(adjusted_params.offset * xdst + (1.0-adjusted_params.offset) * xsrc) + d2;
|
||||
const int y = static_cast<int>(adjusted_params.offset * ydst + (1.0-adjusted_params.offset) * ysrc) + d2;
|
||||
|
||||
if(unit_halo_ == halo::NO_HALO && !image_halo().empty()) {
|
||||
unit_halo_ = halo::add(0, 0, image_halo()+TC_image_mods(), map_location(-1, -1));
|
||||
}
|
||||
if(unit_halo_ != halo::NO_HALO && image_halo().empty()) {
|
||||
halo::remove(unit_halo_);
|
||||
unit_halo_ = halo::NO_HALO;
|
||||
} else if(unit_halo_ != halo::NO_HALO) {
|
||||
halo::set_location(unit_halo_, x, y - height_adjust);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// We draw bars only if wanted, visible on the map view
|
||||
bool draw_bars = draw_bars_ ;
|
||||
if (draw_bars) {
|
||||
const int d = disp.hex_size();
|
||||
SDL_Rect unit_rect = sdl::create_rect(xsrc, ysrc +adjusted_params.y, d, d);
|
||||
draw_bars = sdl::rects_overlap(unit_rect, disp.map_outside_area());
|
||||
}
|
||||
|
||||
surface ellipse_front(NULL);
|
||||
surface ellipse_back(NULL);
|
||||
int ellipse_floating = 0;
|
||||
// Always show the ellipse for selected units
|
||||
if(draw_bars && (preferences::show_side_colors() || disp.selected_hex() == loc_)) {
|
||||
if(adjusted_params.submerge > 0.0) {
|
||||
// The division by 2 seems to have no real meaning,
|
||||
// It just works fine with the current center of ellipse
|
||||
// and prevent a too large adjust if submerge = 1.0
|
||||
ellipse_floating = static_cast<int>(adjusted_params.submerge * disp.hex_size() / 2);
|
||||
}
|
||||
|
||||
std::string ellipse=image_ellipse();
|
||||
if(ellipse.empty()){
|
||||
ellipse="misc/ellipse";
|
||||
}
|
||||
|
||||
if(ellipse != "none") {
|
||||
// check if the unit has a ZoC or can recruit
|
||||
const char* const nozoc = emit_zoc_ ? "" : "nozoc-";
|
||||
const char* const leader = can_recruit() ? "leader-" : "";
|
||||
const char* const selected = disp.selected_hex() == loc_ ? "selected-" : "";
|
||||
|
||||
// Load the ellipse parts recolored to match team color
|
||||
char buf[100];
|
||||
std::string tc=team::get_side_color_index(side_);
|
||||
|
||||
snprintf(buf,sizeof(buf),"%s-%s%s%stop.png~RC(ellipse_red>%s)",ellipse.c_str(),leader,nozoc,selected,tc.c_str());
|
||||
ellipse_back.assign(image::get_image(image::locator(buf), image::SCALED_TO_ZOOM));
|
||||
snprintf(buf,sizeof(buf),"%s-%s%s%sbottom.png~RC(ellipse_red>%s)",ellipse.c_str(),leader,nozoc,selected,tc.c_str());
|
||||
ellipse_front.assign(image::get_image(image::locator(buf), image::SCALED_TO_ZOOM));
|
||||
}
|
||||
}
|
||||
|
||||
if (ellipse_back != NULL) {
|
||||
//disp.drawing_buffer_add(display::LAYER_UNIT_BG, loc,
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc_,
|
||||
xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_back);
|
||||
}
|
||||
|
||||
if (ellipse_front != NULL) {
|
||||
//disp.drawing_buffer_add(display::LAYER_UNIT_FG, loc,
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc_,
|
||||
xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_front);
|
||||
}
|
||||
if(draw_bars) {
|
||||
const image::locator* orb_img = NULL;
|
||||
/*static*/ const image::locator partmoved_orb(game_config::images::orb + "~RC(magenta>" +
|
||||
preferences::partial_color() + ")" );
|
||||
/*static*/ const image::locator moved_orb(game_config::images::orb + "~RC(magenta>" +
|
||||
preferences::moved_color() + ")" );
|
||||
/*static*/ const image::locator ally_orb(game_config::images::orb + "~RC(magenta>" +
|
||||
preferences::allied_color() + ")" );
|
||||
/*static*/ const image::locator enemy_orb(game_config::images::orb + "~RC(magenta>" +
|
||||
preferences::enemy_color() + ")" );
|
||||
/*static*/ const image::locator unmoved_orb(game_config::images::orb + "~RC(magenta>" +
|
||||
preferences::unmoved_color() + ")" );
|
||||
|
||||
const std::string* energy_file = &game_config::images::energy;
|
||||
|
||||
if(size_t(side()) != disp.viewing_team()+1) {
|
||||
if(disp.team_valid() &&
|
||||
disp.get_teams()[disp.viewing_team()].is_enemy(side())) {
|
||||
if (preferences::show_enemy_orb() && !get_state(STATE_PETRIFIED))
|
||||
orb_img = &enemy_orb;
|
||||
else
|
||||
orb_img = NULL;
|
||||
} else {
|
||||
if (preferences::show_allied_orb())
|
||||
orb_img = &ally_orb;
|
||||
else orb_img = NULL;
|
||||
}
|
||||
} else {
|
||||
if (preferences::show_moved_orb())
|
||||
orb_img = &moved_orb;
|
||||
else orb_img = NULL;
|
||||
|
||||
if(disp.playing_team() == disp.viewing_team() && !user_end_turn()) {
|
||||
if (movement_left() == total_movement()) {
|
||||
if (preferences::show_unmoved_orb())
|
||||
orb_img = &unmoved_orb;
|
||||
else orb_img = NULL;
|
||||
} else if ( disp.get_disp_context().unit_can_move(*this) ) {
|
||||
if (preferences::show_partial_orb())
|
||||
orb_img = &partmoved_orb;
|
||||
else orb_img = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (orb_img != NULL) {
|
||||
surface orb(image::get_image(*orb_img,image::SCALED_TO_ZOOM));
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
|
||||
loc_, xsrc, ysrc +adjusted_params.y, orb);
|
||||
}
|
||||
|
||||
double unit_energy = 0.0;
|
||||
if(max_hitpoints() > 0) {
|
||||
unit_energy = double(hitpoints())/double(max_hitpoints());
|
||||
}
|
||||
const int bar_shift = static_cast<int>(-5*disp.get_zoom_factor());
|
||||
const int hp_bar_height = static_cast<int>(max_hitpoints() * hp_bar_scaling_);
|
||||
|
||||
const fixed_t bar_alpha = (loc_ == disp.mouseover_hex() || loc_ == disp.selected_hex()) ? ftofxp(1.0): ftofxp(0.8);
|
||||
|
||||
disp.draw_bar(*energy_file, xsrc+bar_shift, ysrc +adjusted_params.y,
|
||||
loc_, hp_bar_height, unit_energy,hp_color(), bar_alpha);
|
||||
|
||||
if(experience() > 0 && can_advance()) {
|
||||
const double filled = double(experience())/double(max_experience());
|
||||
|
||||
const int xp_bar_height = static_cast<int>(max_experience() * xp_bar_scaling_ / std::max<int>(level_,1));
|
||||
|
||||
SDL_Color color=xp_color();
|
||||
disp.draw_bar(*energy_file, xsrc, ysrc +adjusted_params.y,
|
||||
loc_, xp_bar_height, filled, color, bar_alpha);
|
||||
}
|
||||
|
||||
if (can_recruit()) {
|
||||
surface crown(image::get_image(leader_crown(),image::SCALED_TO_ZOOM));
|
||||
if(!crown.null()) {
|
||||
//if(bar_alpha != ftofxp(1.0)) {
|
||||
// crown = adjust_surface_alpha(crown, bar_alpha);
|
||||
//}
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
|
||||
loc_, xsrc, ysrc +adjusted_params.y, crown);
|
||||
}
|
||||
}
|
||||
|
||||
for(std::vector<std::string>::const_iterator ov = overlays().begin(); ov != overlays().end(); ++ov) {
|
||||
const surface ov_img(image::get_image(*ov, image::SCALED_TO_ZOOM));
|
||||
if(ov_img != NULL) {
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
|
||||
loc_, xsrc, ysrc +adjusted_params.y, ov_img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Smooth unit movements from terrain of different elevation.
|
||||
// Do this separately from above so that the health bar doesn't go up and down.
|
||||
|
||||
const t_translation::t_terrain terrain_dst = map.get_terrain(dst);
|
||||
const terrain_type& terrain_dst_info = map.get_terrain_info(terrain_dst);
|
||||
|
||||
int height_adjust_unit = static_cast<int>((terrain_info.unit_height_adjust() * (1.0 - adjusted_params.offset) +
|
||||
terrain_dst_info.unit_height_adjust() * adjusted_params.offset) *
|
||||
disp.get_zoom_factor());
|
||||
if (is_flying() && height_adjust_unit < 0) {
|
||||
height_adjust_unit = 0;
|
||||
}
|
||||
params.y -= height_adjust_unit - height_adjust;
|
||||
params.halo_y -= height_adjust_unit - height_adjust;
|
||||
|
||||
anim_->redraw(params);
|
||||
refreshing_ = false;
|
||||
}
|
||||
|
41
src/drawable_unit.hpp
Normal file
41
src/drawable_unit.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* This wrapper class should be held by the display object when it needs to draw a unit.
|
||||
* The purpose of this is to improve encapsulation -- other parts of the engine like AI
|
||||
* don't need to be exposed to the unit drawing code, and encapsulation like this will
|
||||
* help us to reduce unnecessary includes.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef DRAWABLE_UNIT_H_INCLUDED
|
||||
#define DRAWABLE_UNIT_H_INCLUDED
|
||||
|
||||
#include "unit.hpp"
|
||||
|
||||
class display;
|
||||
class game_display;
|
||||
|
||||
class drawable_unit : protected unit //TODO: Get rid of inheritance and use composition instead.
|
||||
{ //IMO, it would be better for drawable unit to hold a unit reference, and be marked as a friend class.
|
||||
//But I don't want to rewrite the redraw() function right now.
|
||||
/** draw a unit. */
|
||||
void redraw_unit() const;
|
||||
|
||||
friend class display;
|
||||
friend class game_display;
|
||||
};
|
||||
#endif
|
|
@ -34,6 +34,7 @@ Growl_Delegate growl_obj;
|
|||
#endif
|
||||
|
||||
#include "cursor.hpp"
|
||||
#include "drawable_unit.hpp"
|
||||
#include "fake_unit.hpp"
|
||||
#include "fake_unit_manager.hpp"
|
||||
#include "game_board.hpp"
|
||||
|
@ -246,12 +247,12 @@ void game_display::draw_invalidated()
|
|||
halo::unrender(invalidated_);
|
||||
display::draw_invalidated();
|
||||
|
||||
BOOST_FOREACH(unit* temp_unit, fake_unit_man_->get_fake_unit_list_for_invalidation()) {
|
||||
BOOST_FOREACH(const unit* temp_unit, fake_unit_man_->get_fake_unit_list_for_invalidation()) {
|
||||
const map_location& loc = temp_unit->get_location();
|
||||
exclusive_unit_draw_requests_t::iterator request = exclusive_unit_draw_requests_.find(loc);
|
||||
if (invalidated_.find(loc) != invalidated_.end()
|
||||
&& (request == exclusive_unit_draw_requests_.end() || request->second == temp_unit->id()))
|
||||
temp_unit->redraw_unit();
|
||||
(static_cast<const drawable_unit*> (temp_unit))->redraw_unit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -810,7 +810,7 @@ namespace { // Helpers for menu_handler::end_turn()
|
|||
if ( un->side() == side_num ) {
|
||||
// @todo whiteboard should take into consideration units that have
|
||||
// a planned move but can still plan more movement in the same turn
|
||||
if ( actions::unit_can_move(*un) && !un->user_end_turn()
|
||||
if ( resources::gameboard->unit_can_move(*un) && !un->user_end_turn()
|
||||
&& !resources::whiteboard->unit_has_actions(&*un) )
|
||||
return true;
|
||||
}
|
||||
|
@ -825,7 +825,7 @@ namespace { // Helpers for menu_handler::end_turn()
|
|||
{
|
||||
for ( unit_map::const_iterator un = units.begin(); un != units.end(); ++un ) {
|
||||
if ( un->side() == side_num ) {
|
||||
if ( actions::unit_can_move(*un) && !un->has_moved() && !un->user_end_turn()
|
||||
if ( resources::gameboard->unit_can_move(*un) && !un->has_moved() && !un->user_end_turn()
|
||||
&& !resources::whiteboard->unit_has_actions(&*un) )
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1192,7 +1192,7 @@ bool mouse_handler::unit_in_cycle(unit_map::const_iterator it)
|
|||
return false;
|
||||
|
||||
if (it->side() != side_num_ || it->user_end_turn()
|
||||
|| gui().fogged(it->get_location()) || !actions::unit_can_move(*it))
|
||||
|| gui().fogged(it->get_location()) || !board_.unit_can_move(*it))
|
||||
return false;
|
||||
|
||||
if (current_team().is_enemy(int(gui().viewing_team()+1)) &&
|
||||
|
|
267
src/unit.cpp
267
src/unit.cpp
|
@ -1840,273 +1840,6 @@ void unit::set_facing(map_location::DIRECTION dir) const {
|
|||
// Else look at yourself (not available so continue to face the same direction)
|
||||
}
|
||||
|
||||
void unit::redraw_unit () const
|
||||
{
|
||||
display &disp = *display::get_singleton();
|
||||
const gamemap &map = disp.get_map();
|
||||
|
||||
if ( hidden_ || disp.is_blindfolded() || !is_visible_to_team(disp.get_teams()[disp.viewing_team()],map, disp.show_everything()) )
|
||||
{
|
||||
clear_haloes();
|
||||
if(anim_) {
|
||||
anim_->update_last_draw_time();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!anim_) {
|
||||
set_standing();
|
||||
if (!anim_) return;
|
||||
}
|
||||
|
||||
if (refreshing_) return;
|
||||
refreshing_ = true;
|
||||
|
||||
anim_->update_last_draw_time();
|
||||
frame_parameters params;
|
||||
const t_translation::t_terrain terrain = map.get_terrain(loc_);
|
||||
const terrain_type& terrain_info = map.get_terrain_info(terrain);
|
||||
|
||||
// do not set to 0 so we can distinguish the flying from the "not on submerge terrain"
|
||||
// instead use -1.0 (as in "negative depth", it will be ignored by rendering)
|
||||
params.submerge= is_flying() ? -1.0 : terrain_info.unit_submerge();
|
||||
|
||||
if (invisible(loc_) &&
|
||||
params.highlight_ratio > 0.5) {
|
||||
params.highlight_ratio = 0.5;
|
||||
}
|
||||
if (loc_ == disp.selected_hex() && params.highlight_ratio == 1.0) {
|
||||
params.highlight_ratio = 1.5;
|
||||
}
|
||||
|
||||
int height_adjust = static_cast<int>(terrain_info.unit_height_adjust() * disp.get_zoom_factor());
|
||||
if (is_flying() && height_adjust < 0) {
|
||||
height_adjust = 0;
|
||||
}
|
||||
params.y -= height_adjust;
|
||||
params.halo_y -= height_adjust;
|
||||
|
||||
int red = 0,green = 0,blue = 0,tints = 0;
|
||||
double blend_ratio = 0;
|
||||
// Add future colored states here
|
||||
if(get_state(STATE_POISONED)) {
|
||||
green += 255;
|
||||
blend_ratio += 0.25;
|
||||
tints += 1;
|
||||
}
|
||||
if(get_state(STATE_SLOWED)) {
|
||||
red += 191;
|
||||
green += 191;
|
||||
blue += 255;
|
||||
blend_ratio += 0.25;
|
||||
tints += 1;
|
||||
}
|
||||
if(tints > 0) {
|
||||
params.blend_with = disp.rgb((red/tints),(green/tints),(blue/tints));
|
||||
params.blend_ratio = ((blend_ratio/tints));
|
||||
}
|
||||
|
||||
//hackish : see unit_frame::merge_parameters
|
||||
// we use image_mod on the primary image
|
||||
// and halo_mod on secondary images and all haloes
|
||||
params.image_mod = image_mods();
|
||||
params.halo_mod = TC_image_mods();
|
||||
params.image= absolute_image();
|
||||
|
||||
|
||||
if(get_state(STATE_PETRIFIED)) params.image_mod +="~GS()";
|
||||
params.primary_frame = t_true;
|
||||
|
||||
|
||||
const frame_parameters adjusted_params = anim_->get_current_params(params);
|
||||
|
||||
const map_location dst = loc_.get_direction(facing_);
|
||||
const int xsrc = disp.get_location_x(loc_);
|
||||
const int ysrc = disp.get_location_y(loc_);
|
||||
const int xdst = disp.get_location_x(dst);
|
||||
const int ydst = disp.get_location_y(dst);
|
||||
int d2 = disp.hex_size() / 2;
|
||||
|
||||
const int x = static_cast<int>(adjusted_params.offset * xdst + (1.0-adjusted_params.offset) * xsrc) + d2;
|
||||
const int y = static_cast<int>(adjusted_params.offset * ydst + (1.0-adjusted_params.offset) * ysrc) + d2;
|
||||
|
||||
if(unit_halo_ == halo::NO_HALO && !image_halo().empty()) {
|
||||
unit_halo_ = halo::add(0, 0, image_halo()+TC_image_mods(), map_location(-1, -1));
|
||||
}
|
||||
if(unit_halo_ != halo::NO_HALO && image_halo().empty()) {
|
||||
halo::remove(unit_halo_);
|
||||
unit_halo_ = halo::NO_HALO;
|
||||
} else if(unit_halo_ != halo::NO_HALO) {
|
||||
halo::set_location(unit_halo_, x, y - height_adjust);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// We draw bars only if wanted, visible on the map view
|
||||
bool draw_bars = draw_bars_ ;
|
||||
if (draw_bars) {
|
||||
const int d = disp.hex_size();
|
||||
SDL_Rect unit_rect = sdl::create_rect(xsrc, ysrc +adjusted_params.y, d, d);
|
||||
draw_bars = sdl::rects_overlap(unit_rect, disp.map_outside_area());
|
||||
}
|
||||
|
||||
surface ellipse_front(NULL);
|
||||
surface ellipse_back(NULL);
|
||||
int ellipse_floating = 0;
|
||||
// Always show the ellipse for selected units
|
||||
if(draw_bars && (preferences::show_side_colors() || disp.selected_hex() == loc_)) {
|
||||
if(adjusted_params.submerge > 0.0) {
|
||||
// The division by 2 seems to have no real meaning,
|
||||
// It just works fine with the current center of ellipse
|
||||
// and prevent a too large adjust if submerge = 1.0
|
||||
ellipse_floating = static_cast<int>(adjusted_params.submerge * disp.hex_size() / 2);
|
||||
}
|
||||
|
||||
std::string ellipse=image_ellipse();
|
||||
if(ellipse.empty()){
|
||||
ellipse="misc/ellipse";
|
||||
}
|
||||
|
||||
if(ellipse != "none") {
|
||||
// check if the unit has a ZoC or can recruit
|
||||
const char* const nozoc = emit_zoc_ ? "" : "nozoc-";
|
||||
const char* const leader = can_recruit() ? "leader-" : "";
|
||||
const char* const selected = disp.selected_hex() == loc_ ? "selected-" : "";
|
||||
|
||||
// Load the ellipse parts recolored to match team color
|
||||
char buf[100];
|
||||
std::string tc=team::get_side_color_index(side_);
|
||||
|
||||
snprintf(buf,sizeof(buf),"%s-%s%s%stop.png~RC(ellipse_red>%s)",ellipse.c_str(),leader,nozoc,selected,tc.c_str());
|
||||
ellipse_back.assign(image::get_image(image::locator(buf), image::SCALED_TO_ZOOM));
|
||||
snprintf(buf,sizeof(buf),"%s-%s%s%sbottom.png~RC(ellipse_red>%s)",ellipse.c_str(),leader,nozoc,selected,tc.c_str());
|
||||
ellipse_front.assign(image::get_image(image::locator(buf), image::SCALED_TO_ZOOM));
|
||||
}
|
||||
}
|
||||
|
||||
if (ellipse_back != NULL) {
|
||||
//disp.drawing_buffer_add(display::LAYER_UNIT_BG, loc,
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc_,
|
||||
xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_back);
|
||||
}
|
||||
|
||||
if (ellipse_front != NULL) {
|
||||
//disp.drawing_buffer_add(display::LAYER_UNIT_FG, loc,
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc_,
|
||||
xsrc, ysrc +adjusted_params.y-ellipse_floating, ellipse_front);
|
||||
}
|
||||
if(draw_bars) {
|
||||
const image::locator* orb_img = NULL;
|
||||
/*static*/ const image::locator partmoved_orb(game_config::images::orb + "~RC(magenta>" +
|
||||
preferences::partial_color() + ")" );
|
||||
/*static*/ const image::locator moved_orb(game_config::images::orb + "~RC(magenta>" +
|
||||
preferences::moved_color() + ")" );
|
||||
/*static*/ const image::locator ally_orb(game_config::images::orb + "~RC(magenta>" +
|
||||
preferences::allied_color() + ")" );
|
||||
/*static*/ const image::locator enemy_orb(game_config::images::orb + "~RC(magenta>" +
|
||||
preferences::enemy_color() + ")" );
|
||||
/*static*/ const image::locator unmoved_orb(game_config::images::orb + "~RC(magenta>" +
|
||||
preferences::unmoved_color() + ")" );
|
||||
|
||||
const std::string* energy_file = &game_config::images::energy;
|
||||
|
||||
if(size_t(side()) != disp.viewing_team()+1) {
|
||||
if(disp.team_valid() &&
|
||||
disp.get_teams()[disp.viewing_team()].is_enemy(side())) {
|
||||
if (preferences::show_enemy_orb() && !get_state(STATE_PETRIFIED))
|
||||
orb_img = &enemy_orb;
|
||||
else
|
||||
orb_img = NULL;
|
||||
} else {
|
||||
if (preferences::show_allied_orb())
|
||||
orb_img = &ally_orb;
|
||||
else orb_img = NULL;
|
||||
}
|
||||
} else {
|
||||
if (preferences::show_moved_orb())
|
||||
orb_img = &moved_orb;
|
||||
else orb_img = NULL;
|
||||
|
||||
if(disp.playing_team() == disp.viewing_team() && !user_end_turn()) {
|
||||
if (movement_left() == total_movement()) {
|
||||
if (preferences::show_unmoved_orb())
|
||||
orb_img = &unmoved_orb;
|
||||
else orb_img = NULL;
|
||||
} else if ( actions::unit_can_move(*this) ) {
|
||||
if (preferences::show_partial_orb())
|
||||
orb_img = &partmoved_orb;
|
||||
else orb_img = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (orb_img != NULL) {
|
||||
surface orb(image::get_image(*orb_img,image::SCALED_TO_ZOOM));
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
|
||||
loc_, xsrc, ysrc +adjusted_params.y, orb);
|
||||
}
|
||||
|
||||
double unit_energy = 0.0;
|
||||
if(max_hitpoints() > 0) {
|
||||
unit_energy = double(hitpoints())/double(max_hitpoints());
|
||||
}
|
||||
const int bar_shift = static_cast<int>(-5*disp.get_zoom_factor());
|
||||
const int hp_bar_height = static_cast<int>(max_hitpoints() * hp_bar_scaling_);
|
||||
|
||||
const fixed_t bar_alpha = (loc_ == disp.mouseover_hex() || loc_ == disp.selected_hex()) ? ftofxp(1.0): ftofxp(0.8);
|
||||
|
||||
disp.draw_bar(*energy_file, xsrc+bar_shift, ysrc +adjusted_params.y,
|
||||
loc_, hp_bar_height, unit_energy,hp_color(), bar_alpha);
|
||||
|
||||
if(experience() > 0 && can_advance()) {
|
||||
const double filled = double(experience())/double(max_experience());
|
||||
|
||||
const int xp_bar_height = static_cast<int>(max_experience() * xp_bar_scaling_ / std::max<int>(level_,1));
|
||||
|
||||
SDL_Color color=xp_color();
|
||||
disp.draw_bar(*energy_file, xsrc, ysrc +adjusted_params.y,
|
||||
loc_, xp_bar_height, filled, color, bar_alpha);
|
||||
}
|
||||
|
||||
if (can_recruit()) {
|
||||
surface crown(image::get_image(leader_crown(),image::SCALED_TO_ZOOM));
|
||||
if(!crown.null()) {
|
||||
//if(bar_alpha != ftofxp(1.0)) {
|
||||
// crown = adjust_surface_alpha(crown, bar_alpha);
|
||||
//}
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
|
||||
loc_, xsrc, ysrc +adjusted_params.y, crown);
|
||||
}
|
||||
}
|
||||
|
||||
for(std::vector<std::string>::const_iterator ov = overlays().begin(); ov != overlays().end(); ++ov) {
|
||||
const surface ov_img(image::get_image(*ov, image::SCALED_TO_ZOOM));
|
||||
if(ov_img != NULL) {
|
||||
disp.drawing_buffer_add(display::LAYER_UNIT_BAR,
|
||||
loc_, xsrc, ysrc +adjusted_params.y, ov_img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Smooth unit movements from terrain of different elevation.
|
||||
// Do this separately from above so that the health bar doesn't go up and down.
|
||||
|
||||
const t_translation::t_terrain terrain_dst = map.get_terrain(dst);
|
||||
const terrain_type& terrain_dst_info = map.get_terrain_info(terrain_dst);
|
||||
|
||||
int height_adjust_unit = static_cast<int>((terrain_info.unit_height_adjust() * (1.0 - adjusted_params.offset) +
|
||||
terrain_dst_info.unit_height_adjust() * adjusted_params.offset) *
|
||||
disp.get_zoom_factor());
|
||||
if (is_flying() && height_adjust_unit < 0) {
|
||||
height_adjust_unit = 0;
|
||||
}
|
||||
params.y -= height_adjust_unit - height_adjust;
|
||||
params.halo_y -= height_adjust_unit - height_adjust;
|
||||
|
||||
anim_->redraw(params);
|
||||
refreshing_ = false;
|
||||
}
|
||||
|
||||
void unit::clear_haloes () const
|
||||
{
|
||||
if(unit_halo_ != halo::NO_HALO) {
|
||||
|
|
16
src/unit.hpp
16
src/unit.hpp
|
@ -248,8 +248,6 @@ public:
|
|||
/** A SDL surface, ready for display for place where we need a still-image of the unit. */
|
||||
const surface still_image(bool scaled = false) const;
|
||||
|
||||
/** draw a unit. */
|
||||
void redraw_unit() const;
|
||||
/** Clear unit_halo_ */
|
||||
void clear_haloes() const;
|
||||
|
||||
|
@ -420,7 +418,9 @@ private:
|
|||
void set_underlying_id();
|
||||
|
||||
config cfg_;
|
||||
protected:
|
||||
map_location loc_;
|
||||
private:
|
||||
|
||||
std::vector<std::string> advances_to_;
|
||||
const unit_type * type_;/// Never NULL. Adjusted for gender and variation.
|
||||
|
@ -436,7 +436,9 @@ private:
|
|||
int max_hit_points_;
|
||||
int experience_;
|
||||
int max_experience_;
|
||||
protected:
|
||||
int level_;
|
||||
private:
|
||||
int recall_cost_;
|
||||
bool canrecruit_;
|
||||
std::vector<std::string> recruit_list_;
|
||||
|
@ -445,7 +447,9 @@ private:
|
|||
std::string image_mods_;
|
||||
|
||||
bool unrenamable_;
|
||||
protected:
|
||||
int side_;
|
||||
private:
|
||||
const unit_race::GENDER gender_;
|
||||
|
||||
fixed_t alpha_;
|
||||
|
@ -469,16 +473,20 @@ private:
|
|||
config variables_;
|
||||
config events_;
|
||||
config filter_recall_;
|
||||
|
||||
protected:
|
||||
bool emit_zoc_;
|
||||
|
||||
mutable STATE state_; //animation state
|
||||
|
||||
private:
|
||||
std::vector<std::string> overlays_;
|
||||
|
||||
std::string role_;
|
||||
std::vector<attack_type> attacks_;
|
||||
protected:
|
||||
mutable map_location::DIRECTION facing_; //TODO: I think we actually consider this to be part of the gamestate, so it might be better if it's not mutable
|
||||
//But it's not easy to separate this guy from the animation code right now.
|
||||
private:
|
||||
std::vector<t_string> trait_names_;
|
||||
std::vector<t_string> trait_descriptions_;
|
||||
|
||||
|
@ -489,6 +497,7 @@ private:
|
|||
|
||||
utils::string_map modification_descriptions_;
|
||||
// Animations:
|
||||
protected:
|
||||
std::vector<unit_animation> animations_;
|
||||
|
||||
mutable boost::scoped_ptr<unit_animation> anim_;
|
||||
|
@ -503,6 +512,7 @@ private:
|
|||
mutable bool draw_bars_; // flag used for drawing / animation
|
||||
double hp_bar_scaling_, xp_bar_scaling_;
|
||||
|
||||
private:
|
||||
config modifications_;
|
||||
|
||||
/**
|
||||
|
|
|
@ -67,6 +67,7 @@ class unit_animation
|
|||
friend std::ostream& operator << (std::ostream& outstream, const unit_animation& u_animation);
|
||||
|
||||
friend class unit;
|
||||
friend class drawable_unit;
|
||||
|
||||
explicit unit_animation(const config &cfg, const std::string &frame_string = "");
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue