whiteboard/attack.cpp

Go to the documentation of this file.
00001 /* $Id: attack.cpp 53780 2012-04-05 11:04:20Z gabba $ */
00002 /*
00003  Copyright (C) 2010 - 2012 by Gabriel Morin <gabrielmorin (at) gmail (dot) com>
00004  Part of the Battle for Wesnoth Project http://www.wesnoth.org
00005 
00006  This program is free software; you can redistribute it and/or modify
00007  it under the terms of the GNU General Public License as published by
00008  the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010  This program is distributed in the hope that it will be useful,
00011  but WITHOUT ANY WARRANTY.
00012 
00013  See the COPYING file for more details.
00014  */
00015 
00016 /**
00017  * @file
00018  */
00019 
00020 #include "attack.hpp"
00021 
00022 #include "visitor.hpp"
00023 
00024 #include "arrow.hpp"
00025 #include "play_controller.hpp"
00026 #include "resources.hpp"
00027 #include "unit.hpp"
00028 #include "unit_map.hpp"
00029 
00030 namespace wb
00031 {
00032 
00033 std::ostream &operator<<(std::ostream &s, attack_ptr attack)
00034 {
00035     assert(attack);
00036     return attack->print(s);
00037 }
00038 
00039 std::ostream &operator<<(std::ostream &s, attack_const_ptr attack)
00040 {
00041     assert(attack);
00042     return attack->print(s);
00043 }
00044 
00045 std::ostream& attack::print(std::ostream& s) const
00046 {
00047     s << "Attack on (" << get_target_hex() << ") preceded by ";
00048     move::print(s);
00049     return s;
00050 }
00051 
00052 attack::attack(size_t team_index, bool hidden, unit& u, const map_location& target_hex, int weapon_choice, const pathfind::marked_route& route,
00053         arrow_ptr arrow, fake_unit_ptr fake_unit)
00054     : move(team_index, hidden, u, route, arrow, fake_unit),
00055     target_hex_(target_hex),
00056     weapon_choice_(weapon_choice),
00057     attack_movement_cost_(get_unit()->attacks()[weapon_choice_].movement_used()),
00058     temp_movement_subtracted_(0)
00059 {
00060     this->init();
00061 }
00062 
00063 attack::attack(config const& cfg, bool hidden)
00064     : move(cfg,hidden)
00065     , target_hex_(cfg.child("target_hex_")["x"],cfg.child("target_hex_")["y"])
00066     , weapon_choice_(cfg["weapon_choice_"].to_int(-1)) //default value: -1
00067     , attack_movement_cost_()
00068     , temp_movement_subtracted_(0)
00069 {
00070     // Validate target_hex
00071     if(!tiles_adjacent(target_hex_,get_dest_hex()))
00072         throw action::ctor_err("attack: Invalid target_hex_");
00073 
00074     // Validate weapon_choice_
00075     if(weapon_choice_ < 0 || weapon_choice_ >= static_cast<int>(get_unit()->attacks().size()))
00076         throw action::ctor_err("attack: Invalid weapon_choice_");
00077 
00078     // Construct attack_movement_cost_
00079     attack_movement_cost_ = get_unit()->attacks()[weapon_choice_].movement_used();
00080 
00081     this->init();
00082 }
00083 
00084 void attack::init()
00085 {
00086     resources::screen->invalidate(target_hex_);
00087 }
00088 
00089 attack::~attack()
00090 {
00091     invalidate();
00092 }
00093 
00094 void attack::accept(visitor& v)
00095 {
00096     v.visit(shared_from_this());
00097 }
00098 
00099 /* private */
00100 void attack::invalidate()
00101 {
00102     if(resources::screen)
00103     {
00104         //invalidate dest and target hex so attack indicator is properly cleared
00105         resources::screen->invalidate(get_dest_hex());
00106         resources::screen->invalidate(target_hex_);
00107     }
00108 }
00109 
00110 void attack::execute(bool& success, bool& complete)
00111 {
00112     if (!valid_) {
00113         success = false;
00114         //Setting complete to true signifies to side_actions to delete the planned action: nothing more to do with it.
00115         complete = true;
00116         return;
00117     }
00118 
00119     LOG_WB << "Executing: " << shared_from_this() << "\n";
00120 
00121     if (route_->steps.size() >= 2)
00122     {
00123         bool m_success, m_complete;
00124         move::execute(m_success,m_complete);
00125         if(!m_success) {
00126             //Move failed for some reason, so don't attack.
00127             success = false;
00128             complete = true;
00129             return;
00130         }
00131     }
00132 
00133     resources::controller->get_mouse_handler_base().attack_enemy(get_dest_hex(), get_target_hex(), weapon_choice_);
00134     complete = true;
00135 
00136     //check that attacking unit is still alive, if not, consider the attack a failure
00137     unit_map::const_iterator survivor = resources::units->find(get_dest_hex());
00138     if(!survivor.valid() || survivor->id() != unit_id_)
00139     {
00140         success = false;
00141     }
00142 
00143     success = true;
00144 }
00145 
00146 void attack::apply_temp_modifier(unit_map& unit_map)
00147 {
00148     move::apply_temp_modifier(unit_map);
00149     assert(get_unit());
00150     unit& unit = *get_unit();
00151     DBG_WB << unit.name() << " [" << unit.id()
00152                     << "] has " << unit.attacks_left() << " attacks, decreasing by one" << "\n";
00153     assert(unit.attacks_left() > 0);
00154     unit.set_attacks(unit.attacks_left() - 1);
00155 
00156     //Calculate movement to subtract
00157     temp_movement_subtracted_ = unit.movement_left() >= attack_movement_cost_ ? attack_movement_cost_ : 0 ;
00158     DBG_WB << "Attack: Changing movement points for unit " << unit.name() << " [" << unit.id()
00159                 << "] from " << unit.movement_left() << " to "
00160                 << unit.movement_left() - temp_movement_subtracted_ << ".\n";
00161     unit.set_movement(unit.movement_left() - temp_movement_subtracted_);
00162 
00163     //Update status of fake unit (not undone by remove_temp_modifiers)
00164     //@todo this contradicts the name "temp_modifiers"
00165     if (fake_unit_) { //Attacks that are not attack-moves don't have fake units
00166         fake_unit_->set_movement(unit.movement_left());
00167         fake_unit_->set_attacks(unit.attacks_left());
00168     }
00169 }
00170 
00171 void attack::remove_temp_modifier(unit_map& unit_map)
00172 {
00173     assert(get_unit());
00174     unit& unit = *get_unit();
00175     DBG_WB << unit.name() << " [" << unit.id()
00176                     << "] has " << unit.attacks_left() << " attacks, increasing by one" << "\n";
00177     unit.set_attacks(unit.attacks_left() + 1);
00178     DBG_WB << "Attack: Changing movement points for unit " << unit.name() << " [" << unit.id()
00179                 << "] from " << unit.movement_left() << " to "
00180                 << unit.movement_left() + temp_movement_subtracted_ << ".\n";
00181     unit.set_movement(unit.movement_left() + temp_movement_subtracted_);
00182     temp_movement_subtracted_ = 0;
00183     move::remove_temp_modifier(unit_map);
00184 }
00185 
00186 void attack::draw_hex(const map_location& hex)
00187 {
00188     if (hex == get_dest_hex() || hex == target_hex_) //draw attack indicator
00189     {
00190         //@todo: replace this by either the use of transparency + LAYER_ATTACK_INDICATOR,
00191         //or a dedicated layer
00192         const display::tdrawing_layer layer = display::LAYER_FOOTSTEPS;
00193 
00194         //calculate direction (valid for both hexes)
00195         std::string direction_text = map_location::write_direction(
00196                 get_dest_hex().get_relative_dir(target_hex_));
00197 
00198         if (hex == get_dest_hex()) //add symbol to attacker hex
00199         {
00200             int xpos = resources::screen->get_location_x(get_dest_hex());
00201             int ypos = resources::screen->get_location_y(get_dest_hex());
00202 
00203             resources::screen->drawing_buffer_add(layer, get_dest_hex(), xpos, ypos,
00204                     image::get_image("whiteboard/attack-indicator-src-" + direction_text + ".png", image::SCALED_TO_HEX));
00205         }
00206         else if (hex == target_hex_) //add symbol to defender hex
00207         {
00208             int xpos = resources::screen->get_location_x(target_hex_);
00209             int ypos = resources::screen->get_location_y(target_hex_);
00210 
00211             resources::screen->drawing_buffer_add(layer, target_hex_, xpos, ypos,
00212                     image::get_image("whiteboard/attack-indicator-dst-" + direction_text + ".png", image::SCALED_TO_HEX));
00213         }
00214     }
00215 }
00216 
00217 config attack::to_config() const
00218 {
00219     config final_cfg = move::to_config();
00220 
00221     final_cfg["type"] = "attack";
00222     final_cfg["weapon_choice_"] = weapon_choice_;
00223 //  final_cfg["attack_movement_cost_"] = attack_movement_cost_; //Unnecessary
00224 //  final_cfg["temp_movement_subtracted_"] = temp_movement_subtracted_; //Unnecessary
00225 
00226     config target_hex_cfg;
00227     target_hex_cfg["x"]=target_hex_.x;
00228     target_hex_cfg["y"]=target_hex_.y;
00229     final_cfg.add_child("target_hex_",target_hex_cfg);
00230 
00231     return final_cfg;
00232 }
00233 
00234 } // end namespace wb
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:43 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs