unit_display.cpp

Go to the documentation of this file.
00001 /* $Id: unit_display.cpp 54055 2012-05-01 04:00:58Z brilliand $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
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 /** @file */
00017 
00018 #include "global.hpp"
00019 #include "unit_display.hpp"
00020 
00021 #include "foreach.hpp"
00022 #include "game_preferences.hpp"
00023 #include "game_events.hpp"
00024 #include "log.hpp"
00025 #include "mouse_events.hpp"
00026 #include "resources.hpp"
00027 #include "terrain_filter.hpp"
00028 
00029 
00030 #define LOG_DP LOG_STREAM(info, display)
00031 
00032 static void teleport_unit_between( const map_location& a, const map_location& b, unit& temp_unit)
00033 {
00034     display* disp = display::get_singleton();
00035     if(!disp || disp->video().update_locked() || disp->video().faked() || (disp->fogged(a) && disp->fogged(b))) {
00036         return;
00037     }
00038     disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.0,false);
00039 
00040     temp_unit.set_location(a);
00041     if (!disp->fogged(a)) { // teleport
00042         disp->invalidate(temp_unit.get_location());
00043         temp_unit.set_facing(a.get_relative_dir(b));
00044         unit_animator animator;
00045         animator.add_animation(&temp_unit,"pre_teleport",a);
00046         animator.start_animations();
00047         animator.wait_for_end();
00048     }
00049 
00050     temp_unit.set_location(b);
00051     if (!disp->fogged(b)) { // teleport
00052         disp->invalidate(temp_unit.get_location());
00053         temp_unit.set_facing(a.get_relative_dir(b));
00054         disp->scroll_to_tiles(b,a,game_display::ONSCREEN,true,0.0,false);
00055         unit_animator animator;
00056         animator.add_animation(&temp_unit,"post_teleport",b);
00057         animator.start_animations();
00058         animator.wait_for_end();
00059     }
00060 
00061     temp_unit.set_standing();
00062     disp->update_display();
00063     events::pump();
00064 }
00065 
00066 static void move_unit_between(const map_location& a, const map_location& b, unit& temp_unit,unsigned int step_num,unsigned int step_left)
00067 {
00068     display* disp = display::get_singleton();
00069     if(!disp || disp->video().update_locked() || disp->video().faked() || (disp->fogged(a) && disp->fogged(b))) {
00070         return;
00071     }
00072 
00073     temp_unit.set_location(a);
00074     disp->invalidate(temp_unit.get_location());
00075     temp_unit.set_facing(a.get_relative_dir(b));
00076     unit_animator animator;
00077     animator.replace_anim_if_invalid(&temp_unit,"movement",a,b,step_num,
00078             false,"",0,unit_animation::INVALID,NULL,NULL,step_left);
00079     animator.start_animations();
00080         animator.pause_animation();
00081     disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.0,false);
00082         animator.restart_animation();
00083 
00084     // useless now, previous short draw() just did one
00085     // new_animation_frame();
00086 
00087     int target_time = animator.get_animation_time_potential();
00088 
00089         // target_time must be short to avoid jumpy move
00090         // std::cout << "target time: " << target_time << "\n";
00091     // we round it to the next multile of 200
00092     target_time += 200;
00093     target_time -= target_time%200;
00094 
00095     // This code causes backwards teleport because the time > 200 causes offset > 1.0
00096     // which will not match with the following -1.0
00097     // if(  target_time - animator.get_animation_time_potential() < 100 ) target_time +=200;
00098 
00099     animator.wait_until(target_time);
00100         // debug code, see unit_frame::redraw()
00101         // std::cout << "   end\n";
00102     map_location arr[6];
00103     get_adjacent_tiles(a, arr);
00104     unsigned int i;
00105     for (i = 0; i < 6; ++i) {
00106         disp->invalidate(arr[i]);
00107     }
00108     get_adjacent_tiles(b, arr);
00109     for (i = 0; i < 6; ++i) {
00110         disp->invalidate(arr[i]);
00111     }
00112 }
00113 
00114 namespace unit_display
00115 {
00116 
00117 void move_unit(const std::vector<map_location>& path, unit& u,
00118         const std::vector<team>& teams, bool animate,
00119         map_location::DIRECTION dir)
00120 {
00121     game_display* disp = game_display::get_singleton();
00122     assert(!path.empty());
00123     assert(disp);
00124     if(!disp || disp->video().update_locked() || disp->video().faked())
00125         return;
00126     // One hex path (strange), nothing to do
00127     if(path.size() == 1)
00128         return;
00129     if(dir == map_location::NDIRECTIONS)
00130         dir = path[path.size()-2].get_relative_dir(path.back());
00131     // Don't animate, only set facing and redraw path ends
00132     if(!animate) {
00133         u.set_facing(dir);
00134         disp->invalidate(path.front());
00135         disp->invalidate(path.back());
00136         return;
00137     }
00138 
00139     bool was_hidden = u.get_hidden();
00140     // Original unit is usually hidden (but still on map, so count is correct)
00141     game_display::fake_unit temp_unit(u);
00142     u.set_hidden(true);
00143     temp_unit.set_standing(false);
00144     temp_unit.set_hidden(false);
00145     temp_unit.place_on_game_display(disp);
00146 
00147     move_unit_start(path, temp_unit, teams[temp_unit.side()-1]);
00148 
00149     for(size_t i = 0; i+1 < path.size(); ++i) {
00150         move_unit_step(path, i, temp_unit, teams[temp_unit.side()-1]);
00151     }
00152 
00153     move_unit_finish(path, temp_unit);
00154 
00155     temp_unit.remove_from_game_display();
00156 
00157     u.set_facing(dir);
00158     u.set_hidden(was_hidden);
00159 }
00160 
00161 void move_unit_start(const std::vector<map_location>& path, unit& temp_unit,
00162         const team& tm)
00163 {
00164     game_display* disp = game_display::get_singleton();
00165     assert(!path.empty());
00166     assert(disp);
00167     if(!disp || disp->video().update_locked() || disp->video().faked())
00168         return;
00169     // One hex path (strange), nothing to do
00170     if(path.size() == 1)
00171         return;
00172 
00173     bool invisible = tm.is_enemy(int(disp->viewing_team()+1)) &&
00174         temp_unit.invisible(path[0]);
00175     if(!invisible) {
00176         // Scroll to the path, but only if it fully fits on screen.
00177         // If it does not fit we might be able to do a better scroll later.
00178         disp->scroll_to_tiles(path, game_display::ONSCREEN, true, true,0.0,false);
00179     }
00180     // We need to clear big invalidation before the move and have a smooth animation
00181     // (mainly black stripes and invalidation after canceling atatck dialog)
00182     // Two draw calls are needed to also redraw the previously invalidated hexes
00183     // We use update=false because we don't need delay here (no time wasted)
00184     // and no screen refresh (will be done by last 3rd draw() and it optimizes
00185     // the double blitting done by these invalidations)
00186     disp->draw(false);
00187     disp->draw(false);
00188 
00189     // The last draw() was still slow, and its initial new_animation_frame() call
00190     // is now old, so we do another draw() to get a fresh one
00191     // TODO: replace that by a new_animation_frame() before starting anims
00192     //       don't forget to change the previous draw(false) to true
00193     disp->draw(true);
00194 
00195     // extra immobile mvt anim for take-off
00196     temp_unit.set_location(path[0]);
00197     disp->invalidate(temp_unit.get_location());
00198     temp_unit.set_facing(path[0].get_relative_dir(path[1]));
00199 
00200     unit_animator animator;
00201     animator.add_animation(&temp_unit,"pre_movement",path[0],path[1]);
00202     animator.start_animations();
00203     animator.wait_for_end();
00204 }
00205 
00206 void move_unit_step(const std::vector<map_location>& path, size_t i,
00207         unit& temp_unit, const team& tm)
00208 {
00209     game_display* disp = game_display::get_singleton();
00210     assert(path.size() > i+1);
00211     assert(disp);
00212     if(!disp || disp->video().update_locked() || disp->video().faked())
00213         return;
00214     // already reached end of path - this should never happen
00215     if(path.size() <= i+1)
00216         return;
00217 
00218     bool invisible = tm.is_enemy(int(disp->viewing_team()+1)) &&
00219             temp_unit.invisible(path[i]) &&
00220             temp_unit.invisible(path[i+1]);
00221     if(invisible)
00222         return;
00223 
00224     if (!disp->tile_fully_on_screen(path[i]) || !disp->tile_fully_on_screen(path[i+1])) {
00225         // prevent the unit from disappearing if we scroll here with i == 0
00226         temp_unit.set_location(path[i]);
00227         disp->invalidate(temp_unit.get_location());
00228         // scroll in as much of the remaining path as possible
00229         std::vector<map_location> remaining_path;
00230         for(size_t j = i; j < path.size(); ++j) {
00231             remaining_path.push_back(path[j]);
00232         }
00233         temp_unit.get_animation()->pause_animation();
00234         disp->scroll_to_tiles(remaining_path,
00235                     game_display::ONSCREEN, true,false,0.0,false);
00236         temp_unit.get_animation()->restart_animation();
00237     }
00238 
00239     if(tiles_adjacent(path[i], path[i+1])) {
00240         move_unit_between(path[i],path[i+1],temp_unit,i,path.size()-2-i);
00241     } else if (path[i] != path[i+1]) {
00242         teleport_unit_between(path[i],path[i+1],temp_unit);
00243     } else {
00244         // no move needed
00245     }
00246 }
00247 
00248 void move_unit_finish(const std::vector<map_location>& path, unit& temp_unit)
00249 {
00250     game_display* disp = game_display::get_singleton();
00251     assert(!path.empty());
00252     assert(disp);
00253     if(!disp || disp->video().update_locked() || disp->video().faked())
00254         return;
00255     // One hex path (strange), nothing to do
00256     if(path.size() == 1)
00257         return;
00258 
00259     temp_unit.set_location(path[path.size() - 1]);
00260     temp_unit.set_facing(path[path.size()-2].get_relative_dir(path[path.size()-1]));
00261 
00262     unit_animator animator;
00263     animator.add_animation(&temp_unit,"post_movement",path[path.size()-1],map_location::null_location);
00264     animator.start_animations();
00265     animator.wait_for_end();
00266 
00267     events::mouse_handler* mousehandler = events::mouse_handler::get_singleton();
00268     if (mousehandler) {
00269         mousehandler->invalidate_reachmap();
00270     }
00271 
00272     disp->invalidate(path.front());
00273     disp->invalidate(path.back());
00274 }
00275 
00276 void reset_helpers(const unit *attacker,const unit *defender);
00277 
00278 void unit_draw_weapon(const map_location& loc, unit& attacker,
00279         const attack_type* attack,const attack_type* secondary_attack, const map_location& defender_loc,unit* defender)
00280 {
00281     display* disp = display::get_singleton();
00282     if(!disp ||disp->video().update_locked() || disp->video().faked() || disp->fogged(loc) || preferences::show_combat() == false) {
00283         return;
00284     }
00285     unit_animator animator;
00286     animator.add_animation(&attacker,"draw_weapon",loc,defender_loc,0,false,"",0,unit_animation::HIT,attack,secondary_attack,0);
00287     animator.add_animation(defender,"draw_weapon",defender_loc,loc,0,false,"",0,unit_animation::MISS,secondary_attack,attack,0);
00288     animator.start_animations();
00289     animator.wait_for_end();
00290 
00291 }
00292 
00293 
00294 void unit_sheath_weapon(const map_location& primary_loc, unit* primary_unit,
00295         const attack_type* primary_attack,const attack_type* secondary_attack, const map_location& secondary_loc,unit* secondary_unit)
00296 {
00297     display* disp = display::get_singleton();
00298     if(!disp ||disp->video().update_locked() || disp->video().faked() || disp->fogged(primary_loc) || preferences::show_combat() == false) {
00299         return;
00300     }
00301     unit_animator animator;
00302     if(primary_unit) {
00303         animator.add_animation(primary_unit,"sheath_weapon",primary_loc,secondary_loc,0,false,"",0,unit_animation::INVALID,primary_attack,secondary_attack,0);
00304     }
00305     if(secondary_unit) {
00306         animator.add_animation(secondary_unit,"sheath_weapon",secondary_loc,primary_loc,0,false,"",0,unit_animation::INVALID,secondary_attack,primary_attack,0);
00307     }
00308 
00309     if(primary_unit || secondary_unit) {
00310         animator.start_animations();
00311         animator.wait_for_end();
00312     }
00313     if(primary_unit) {
00314         primary_unit->set_standing();
00315     }
00316     if(secondary_unit) {
00317         secondary_unit->set_standing();
00318     }
00319     reset_helpers(primary_unit,secondary_unit);
00320 
00321 }
00322 
00323 
00324 void unit_die(const map_location& loc, unit& loser,
00325         const attack_type* attack,const attack_type* secondary_attack, const map_location& winner_loc,unit* winner)
00326 {
00327     display* disp = display::get_singleton();
00328     if(!disp ||disp->video().update_locked() || disp->video().faked() || disp->fogged(loc) || preferences::show_combat() == false) {
00329         return;
00330     }
00331     unit_animator animator;
00332     // hide the hp/xp bars of the loser (useless and prevent bars around an erased unit)
00333     animator.add_animation(&loser,"death",loc,winner_loc,0,false,"",0,unit_animation::KILL,attack,secondary_attack,0);
00334     // but show the bars of the winner (avoid blinking and show its xp gain)
00335     animator.add_animation(winner,"victory",winner_loc,loc,0,true,"",0,
00336             unit_animation::KILL,secondary_attack,attack,0);
00337     animator.start_animations();
00338     animator.wait_for_end();
00339 
00340     reset_helpers(winner,&loser);
00341     events::mouse_handler* mousehandler = events::mouse_handler::get_singleton();
00342     if (mousehandler) {
00343         mousehandler->invalidate_reachmap();
00344     }
00345 }
00346 
00347 
00348 void unit_attack(
00349                  const map_location& a, const map_location& b, int damage,
00350                  const attack_type& attack, const attack_type* secondary_attack,
00351           int swing,std::string hit_text,int drain_amount,std::string att_text)
00352 {
00353     display* disp = display::get_singleton();
00354     if(!disp ||disp->video().update_locked() || disp->video().faked() ||
00355             (disp->fogged(a) && disp->fogged(b)) || preferences::show_combat() == false) {
00356         return;
00357     }
00358     unit_map& units = disp->get_units();
00359     disp->select_hex(map_location::null_location);
00360 
00361     // scroll such that there is at least half a hex spacing around fighters
00362     disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.5,false);
00363 
00364     log_scope("unit_attack");
00365 
00366     const unit_map::iterator att = units.find(a);
00367     assert(att != units.end());
00368     unit& attacker = *att;
00369 
00370     const unit_map::iterator def = units.find(b);
00371     assert(def != units.end());
00372     unit &defender = *def;
00373     int def_hitpoints = defender.hitpoints();
00374 
00375     att->set_facing(a.get_relative_dir(b));
00376     def->set_facing(b.get_relative_dir(a));
00377     defender.set_facing(b.get_relative_dir(a));
00378 
00379 
00380     unit_animator animator;
00381     unit_ability_list leaders = attacker.get_abilities("leadership");
00382     unit_ability_list helpers = defender.get_abilities("resistance");
00383 
00384     std::string text ;
00385     if(damage) text = lexical_cast<std::string>(damage);
00386     if(!hit_text.empty()) {
00387         text.insert(text.begin(),hit_text.size()/2,' ');
00388         text = text + "\n" + hit_text;
00389     }
00390 
00391     std::string text_2 ;
00392     if(drain_amount) text_2 = lexical_cast<std::string>(drain_amount > 0 ? drain_amount : -drain_amount);
00393     if(!att_text.empty()) {
00394         text_2.insert(text_2.begin(),att_text.size()/2,' ');
00395         text_2 = text_2 + "\n" + att_text;
00396     }
00397 
00398     unit_animation::hit_type hit_type;
00399     if(damage >= defender.hitpoints()) {
00400         hit_type = unit_animation::KILL;
00401     } else if(damage > 0) {
00402         hit_type = unit_animation::HIT;
00403     }else {
00404         hit_type = unit_animation::MISS;
00405     }
00406     animator.add_animation(&attacker, "attack", att->get_location(),
00407         def->get_location(), damage, true,  text_2,
00408         (drain_amount >= 0) ? display::rgb(0, 255, 0) : display::rgb(255, 0, 0),
00409         hit_type, &attack, secondary_attack, swing);
00410 
00411     // note that we take an anim from the real unit, we'll use it later
00412     const unit_animation *defender_anim = def->choose_animation(*disp,
00413         def->get_location(), "defend", att->get_location(), damage,
00414         hit_type, &attack, secondary_attack, swing);
00415     animator.add_animation(&defender, defender_anim, def->get_location(),
00416         true,  text , display::rgb(255, 0, 0));
00417 
00418     for (std::vector<std::pair<const config *, map_location> >::iterator itor = leaders.cfgs.begin(); itor != leaders.cfgs.end(); ++itor) {
00419         if(itor->second == a) continue;
00420         if(itor->second == b) continue;
00421         unit_map::iterator leader = units.find(itor->second);
00422         assert(leader != units.end());
00423         leader->set_facing(itor->second.get_relative_dir(a));
00424         animator.add_animation(&*leader, "leading", itor->second,
00425             att->get_location(), damage, true,  "", 0,
00426             hit_type, &attack, secondary_attack, swing);
00427     }
00428     for (std::vector<std::pair<const config *, map_location> >::iterator itor = helpers.cfgs.begin(); itor != helpers.cfgs.end(); ++itor) {
00429         if(itor->second == a) continue;
00430         if(itor->second == b) continue;
00431         unit_map::iterator helper = units.find(itor->second);
00432         assert(helper != units.end());
00433         helper->set_facing(itor->second.get_relative_dir(b));
00434         animator.add_animation(&*helper, "resistance", itor->second,
00435             def->get_location(), damage, true,  "", 0,
00436             hit_type, &attack, secondary_attack, swing);
00437     }
00438 
00439 
00440     animator.start_animations();
00441     animator.wait_until(0);
00442     int damage_left = damage;
00443     while(damage_left > 0 && !animator.would_end()) {
00444         int step_left = (animator.get_end_time() - animator.get_animation_time() )/50;
00445         if(step_left < 1) step_left = 1;
00446         int removed_hp =  damage_left/step_left ;
00447         if(removed_hp < 1) removed_hp = 1;
00448         defender.take_hit(removed_hp);
00449         damage_left -= removed_hp;
00450         animator.wait_until(animator.get_animation_time_potential() +50);
00451     }
00452     animator.wait_for_end();
00453     // pass the animation back to the real unit
00454     def->start_animation(animator.get_end_time(), defender_anim, true);
00455     reset_helpers(&*att, &*def);
00456     def->set_hitpoints(def_hitpoints);
00457 }
00458 
00459 // private helper function, set all helpers to default position
00460 void reset_helpers(const unit *attacker,const unit *defender)
00461 {
00462     display* disp = display::get_singleton();
00463     unit_map& units = disp->get_units();
00464     if(attacker) {
00465         unit_ability_list leaders = attacker->get_abilities("leadership");
00466         for (std::vector<std::pair<const config *, map_location> >::iterator itor = leaders.cfgs.begin(); itor != leaders.cfgs.end(); ++itor) {
00467             unit_map::iterator leader = units.find(itor->second);
00468             assert(leader != units.end());
00469             leader->set_standing();
00470         }
00471     }
00472 
00473     if(defender) {
00474         unit_ability_list helpers = defender->get_abilities("resistance");
00475         for (std::vector<std::pair<const config *, map_location> >::iterator itor = helpers.cfgs.begin(); itor != helpers.cfgs.end(); ++itor) {
00476             unit_map::iterator helper = units.find(itor->second);
00477             assert(helper != units.end());
00478             helper->set_standing();
00479         }
00480     }
00481 }
00482 
00483 void unit_recruited(const map_location& loc,const map_location& leader_loc)
00484 {
00485     game_display* disp = game_display::get_singleton();
00486     if(!disp || disp->video().update_locked() || disp->video().faked() ||disp->fogged(loc)) return;
00487     unit_map::iterator u = disp->get_units().find(loc);
00488     if(u == disp->get_units().end()) return;
00489     u->set_hidden(true);
00490 
00491     unit_animator animator;
00492     if(leader_loc != map_location::null_location) {
00493         unit_map::iterator leader = disp->get_units().find(leader_loc);
00494         if(leader == disp->get_units().end()) return;
00495         disp->scroll_to_tiles(loc,leader_loc,game_display::ONSCREEN,true,0.0,false);
00496         leader->set_facing(leader_loc.get_relative_dir(loc));
00497         animator.add_animation(&*leader, "recruiting", leader_loc, loc, 0, true);
00498     } else {
00499         disp->scroll_to_tile(loc,game_display::ONSCREEN,true,false);
00500     }
00501 
00502     disp->draw();
00503     u->set_hidden(false);
00504     animator.add_animation(&*u, "recruited", loc, leader_loc);
00505     animator.start_animations();
00506     animator.wait_for_end();
00507     animator.set_all_standing();
00508     if (loc==disp->mouseover_hex()) disp->invalidate_unit();
00509 }
00510 
00511 void unit_healing(unit &healed, const map_location &healed_loc,
00512     const std::vector<unit *> &healers, int healing)
00513 {
00514     game_display* disp = game_display::get_singleton();
00515     if(!disp || disp->video().update_locked() || disp->video().faked() || disp->fogged(healed_loc)) return;
00516     if(healing==0) return;
00517     // This is all the pretty stuff.
00518     disp->scroll_to_tile(healed_loc, game_display::ONSCREEN,true,false);
00519     disp->display_unit_hex(healed_loc);
00520     unit_animator animator;
00521 
00522     foreach (unit *h, healers) {
00523         h->set_facing(h->get_location().get_relative_dir(healed_loc));
00524         animator.add_animation(h, "healing", h->get_location(),
00525             healed_loc, healing);
00526     }
00527     if (healing < 0) {
00528         animator.add_animation(&healed,"poisoned",healed_loc,map_location::null_location,-healing,false,lexical_cast<std::string>(-healing), display::rgb(255,0,0));
00529     } else {
00530         animator.add_animation(&healed,"healed",healed_loc,map_location::null_location,healing,false,lexical_cast<std::string>(healing), display::rgb(0,255,0));
00531     }
00532     animator.start_animations();
00533     animator.wait_for_end();
00534     animator.set_all_standing();
00535 
00536 }
00537 
00538 void wml_animation_internal(unit_animator &animator, const vconfig &cfg, const map_location &default_location = map_location::null_location);
00539 
00540 void wml_animation(const vconfig &cfg, const map_location &default_location)
00541 {
00542     game_display &disp = *resources::screen;
00543     if (disp.video().update_locked() || disp.video().faked()) return;
00544     unit_animator animator;
00545     wml_animation_internal(animator, cfg, default_location);
00546     animator.start_animations();
00547     animator.wait_for_end();
00548     animator.set_all_standing();
00549 }
00550 
00551 void wml_animation_internal(unit_animator &animator, const vconfig &cfg, const map_location &default_location)
00552 {
00553     unit_map::iterator u = resources::units->find(default_location);
00554 
00555     // Search for a valid unit filter,
00556     // and if we have one, look for the matching unit
00557     vconfig filter = cfg.child("filter");
00558     if(!filter.null()) {
00559         for (u = resources::units->begin(); u != resources::units->end(); ++u) {
00560             if (game_events::unit_matches_filter(*u, filter))
00561                 break;
00562         }
00563     }
00564 
00565     // We have found a unit that matches the filter
00566     if (u.valid() && !resources::screen->fogged(u->get_location()))
00567     {
00568         attack_type *primary = NULL;
00569         attack_type *secondary = NULL;
00570         Uint32 text_color;
00571         unit_animation::hit_type hits=  unit_animation::INVALID;
00572         std::vector<attack_type> attacks = u->attacks();
00573         std::vector<attack_type>::iterator itor;
00574 
00575         filter = cfg.child("primary_attack");
00576         if(!filter.null()) {
00577             for(itor = attacks.begin(); itor != attacks.end(); ++itor){
00578                 if(itor->matches_filter(filter.get_parsed_config())) {
00579                     primary = &*itor;
00580                     break;
00581                 }
00582             }
00583         }
00584 
00585         filter = cfg.child("secondary_attack");
00586         if(!filter.null()) {
00587             for(itor = attacks.begin(); itor != attacks.end(); ++itor){
00588                 if(itor->matches_filter(filter.get_parsed_config())) {
00589                     secondary = &*itor;
00590                     break;
00591                 }
00592             }
00593         }
00594 
00595         if(cfg["hits"] == "yes" || cfg["hits"] == "hit") {
00596             hits = unit_animation::HIT;
00597         }
00598         if(cfg["hits"] == "no" || cfg["hits"] == "miss") {
00599             hits = unit_animation::MISS;
00600         }
00601         if( cfg["hits"] == "kill" ) {
00602             hits = unit_animation::KILL;
00603         }
00604         if(cfg["red"].empty() && cfg["green"].empty() && cfg["blue"].empty()) {
00605             text_color = display::rgb(0xff,0xff,0xff);
00606         } else {
00607             text_color = display::rgb(cfg["red"], cfg["green"], cfg["blue"]);
00608         }
00609         resources::screen->scroll_to_tile(u->get_location(), game_display::ONSCREEN, true, false);
00610         vconfig t_filter = cfg.child("facing");
00611         map_location secondary_loc = map_location::null_location;
00612         if(!t_filter.empty()) {
00613             terrain_filter filter(t_filter, *resources::units);
00614             std::set<map_location> locs;
00615             filter.get_locations(locs);
00616             if (!locs.empty() && u->get_location() != *locs.begin()) {
00617                 map_location::DIRECTION dir =u->get_location().get_relative_dir(*locs.begin());
00618                 u->set_facing(dir);
00619                 secondary_loc = u->get_location().get_direction(dir);
00620             }
00621         }
00622         animator.add_animation(&*u, cfg["flag"], u->get_location(),
00623             secondary_loc, cfg["value"], cfg["with_bars"].to_bool(),
00624             cfg["text"], text_color, hits, primary, secondary,
00625             cfg["value_second"]);
00626     }
00627     const vconfig::child_list sub_anims = cfg.get_children("animate");
00628     vconfig::child_list::const_iterator anim_itor;
00629     for(anim_itor = sub_anims.begin(); anim_itor != sub_anims.end();++anim_itor) {
00630         wml_animation_internal(animator, *anim_itor);
00631     }
00632 
00633 }
00634 } // end unit_display namespace
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

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