00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "global.hpp"
00016
00017 #include "color_range.hpp"
00018 #include "game_display.hpp"
00019 #include "game_config.hpp"
00020 #include "gettext.hpp"
00021 #include "log.hpp"
00022 #include "halo.hpp"
00023 #include "pathutils.hpp"
00024 #include "unit.hpp"
00025 #include "unit_animation.hpp"
00026 #include "unit_types.hpp"
00027 #include "util.hpp"
00028 #include "variable.hpp"
00029 #include "sound.hpp"
00030 #include "serialization/string_utils.hpp"
00031
00032 #include <algorithm>
00033 #include <climits>
00034 #include <cstdlib>
00035 #include <iostream>
00036
00037 config unit_animation::prepare_animation(const config &cfg,const std::string animation_tag)
00038 {
00039 config expanded_animations;
00040 std::vector<config> unexpanded_anims;
00041 {
00042
00043 config::const_child_itors all_anims = cfg.child_range(animation_tag);
00044 config::const_child_iterator current_anim;
00045 for(current_anim = all_anims.first; current_anim != all_anims.second ; current_anim++) {
00046 unexpanded_anims.push_back(**current_anim);
00047 }
00048 }
00049 while(!unexpanded_anims.empty()) {
00050
00051 const config analyzed_anim = unexpanded_anims.back();
00052 unexpanded_anims.pop_back();
00053 config::all_children_iterator child = analyzed_anim.ordered_begin();
00054 config expanded_anim;
00055 expanded_anim.values = analyzed_anim.values;
00056 while(child != analyzed_anim.ordered_end()) {
00057 if(*(*child).first == "if") {
00058 std::vector<config> to_add;
00059 config expanded_chunk = expanded_anim;
00060
00061 expanded_chunk.append(*(*child).second);
00062 to_add.push_back(expanded_chunk);
00063 child++;
00064 if(child != analyzed_anim.ordered_end() && *(*child).first == "else") {
00065 while(child != analyzed_anim.ordered_end() && *(*child).first == "else") {
00066 expanded_chunk = expanded_anim;
00067
00068 expanded_chunk.append(*(*child).second);
00069 to_add.push_back(expanded_chunk);
00070
00071 child++;
00072 }
00073
00074 } else {
00075
00076 to_add.push_back(expanded_anim);
00077 }
00078
00079 while(child != analyzed_anim.ordered_end()) {
00080 for(std::vector<config>::iterator itor= to_add.begin(); itor != to_add.end();itor++) {
00081 itor->add_child(*(*child).first,*(*child).second);
00082
00083 }
00084 child++;
00085 }
00086 unexpanded_anims.insert(unexpanded_anims.end(),to_add.begin(),to_add.end());
00087 } else {
00088
00089 expanded_anim.add_child(*(*child).first,*(*child).second);
00090 child++;
00091 if(child == analyzed_anim.ordered_end())
00092 expanded_animations.add_child(animation_tag,expanded_anim);
00093 }
00094 }
00095 }
00096 return expanded_animations;
00097 }
00098
00099 unit_animation::unit_animation(int start_time,
00100 const unit_frame & frame, const std::string& event, const int variation) :
00101 terrain_types_(),
00102 unit_filter_(),
00103 secondary_unit_filter_(),
00104 directions_(),
00105 frequency_(0),
00106 base_score_(variation),
00107 event_(utils::split(event)),
00108 value_(),
00109 primary_attack_filter_(),
00110 secondary_attack_filter_(),
00111 hits_(),
00112 swing_num_(),
00113 sub_anims_(),
00114 unit_anim_(start_time)
00115 {
00116 add_frame(frame.duration(),frame,!frame.does_not_change());
00117 }
00118
00119 unit_animation::unit_animation(const config& cfg,const std::string frame_string ) :
00120 terrain_types_(t_translation::read_list(cfg["terrain"])),
00121 unit_filter_(),
00122 secondary_unit_filter_(),
00123 directions_(),
00124 frequency_(0),
00125 base_score_(0),
00126 event_(),
00127 value_(),
00128 primary_attack_filter_(),
00129 secondary_attack_filter_(),
00130 hits_(),
00131 swing_num_(),
00132 sub_anims_(),
00133 unit_anim_(cfg,frame_string)
00134 {
00135
00136 config::child_map::const_iterator frame_itor =cfg.all_children().begin();
00137 for( ; frame_itor != cfg.all_children().end() ; frame_itor++) {
00138 if(frame_itor->first == frame_string) continue;
00139 if(frame_itor->first.find("_frame",frame_itor->first.size() -6 ) == std::string::npos) continue;
00140 sub_anims_[frame_itor->first] = particule(cfg,frame_itor->first.substr(0,frame_itor->first.size() -5));
00141 }
00142 event_ =utils::split(cfg["apply_to"]);
00143
00144 const std::vector<std::string>& my_directions = utils::split(cfg["direction"]);
00145 for(std::vector<std::string>::const_iterator i = my_directions.begin(); i != my_directions.end(); ++i) {
00146 const gamemap::location::DIRECTION d = gamemap::location::parse_direction(*i);
00147 directions_.push_back(d);
00148 }
00149 config::const_child_iterator itor;
00150 for(itor = cfg.child_range("filter").first; itor <cfg.child_range("filter").second;itor++) {
00151 unit_filter_.push_back(**itor);
00152 }
00153
00154 for(itor = cfg.child_range("unit_filter").first; itor <cfg.child_range("unit_filter").second;itor++) {
00155 unit_filter_.push_back(**itor);
00156 }
00157
00158 for(itor = cfg.child_range("secondary_unit_filter").first; itor <cfg.child_range("secondary_unit_filter").second;itor++) {
00159 secondary_unit_filter_.push_back(**itor);
00160 }
00161
00162 for(itor = cfg.child_range("filter_second").first; itor <cfg.child_range("filter_second").second;itor++) {
00163 secondary_unit_filter_.push_back(**itor);
00164 }
00165 frequency_ = atoi(cfg["frequency"].c_str());
00166
00167 std::vector<std::string> value_str = utils::split(cfg["value"]);
00168 std::vector<std::string>::iterator value;
00169 for(value=value_str.begin() ; value != value_str.end() ; value++) {
00170 value_.push_back(atoi(value->c_str()));
00171 }
00172
00173 std::vector<std::string> hits_str = utils::split(cfg["hits"]);
00174 std::vector<std::string>::iterator hit;
00175 for(hit=hits_str.begin() ; hit != hits_str.end() ; hit++) {
00176 if(*hit == "yes" || *hit == "hit") {
00177 hits_.push_back(HIT);
00178 }
00179 if(*hit == "no" || *hit == "miss") {
00180 hits_.push_back(MISS);
00181 }
00182 if(*hit == "yes" || *hit == "kill" ) {
00183 hits_.push_back(KILL);
00184 }
00185 }
00186 std::vector<std::string> swing_str = utils::split(cfg["swing"]);
00187 std::vector<std::string>::iterator swing;
00188 for(swing=swing_str.begin() ; swing != swing_str.end() ; swing++) {
00189 swing_num_.push_back(atoi(swing->c_str()));
00190 }
00191 for(itor = cfg.child_range("filter_attack").first; itor <cfg.child_range("filter_attack").second;itor++) {
00192 primary_attack_filter_.push_back(**itor);
00193 }
00194
00195 for(itor = cfg.child_range("attack_filter").first; itor <cfg.child_range("attack_filter").second;itor++) {
00196 primary_attack_filter_.push_back(**itor);
00197 }
00198 for(itor = cfg.child_range("filter_second_attack").first; itor <cfg.child_range("filter_second_attack").second;itor++) {
00199 secondary_attack_filter_.push_back(**itor);
00200 }
00201
00202 for(itor = cfg.child_range("secondary_attack_filter").first; itor <cfg.child_range("secondary_attack_filter").second;itor++) {
00203 secondary_attack_filter_.push_back(**itor);
00204 }
00205
00206 }
00207
00208 int unit_animation::matches(const game_display &disp,const gamemap::location& loc, const unit* my_unit,const std::string & event,const int value,hit_type hit,const attack_type* attack,const attack_type* second_attack, int swing_num) const
00209 {
00210 int result = base_score_;
00211 if(!event.empty()&&!event_.empty()) {
00212 if (std::find(event_.begin(),event_.end(),event)== event_.end()) {
00213 return MATCH_FAIL;
00214 } else {
00215 result ++;
00216 }
00217 }
00218 if(terrain_types_.empty() == false) {
00219 if(t_translation::terrain_matches(disp.get_map().get_terrain(loc), terrain_types_)) {
00220 result ++;
00221 } else {
00222 return MATCH_FAIL;
00223 }
00224 }
00225
00226 if(value_.empty() == false ) {
00227 if (std::find(value_.begin(),value_.end(),value)== value_.end()) {
00228 return MATCH_FAIL;
00229 } else {
00230 result ++;
00231 }
00232 }
00233 if(my_unit) {
00234 if(directions_.empty()== false) {
00235 if (std::find(directions_.begin(),directions_.end(),my_unit->facing())== directions_.end()) {
00236 return MATCH_FAIL;
00237 } else {
00238 result ++;
00239 }
00240 }
00241 std::vector<config>::const_iterator myitor;
00242 for(myitor = unit_filter_.begin(); myitor != unit_filter_.end(); myitor++) {
00243 if(!my_unit->matches_filter(&(*myitor),loc)) return MATCH_FAIL;
00244 result++;
00245 }
00246 if(!secondary_unit_filter_.empty()) {
00247 const gamemap::location facing_loc = loc.get_direction(my_unit->facing());
00248 unit_map::const_iterator unit;
00249 for(unit=disp.get_const_units().begin() ; unit != disp.get_const_units().end() ; unit++) {
00250 if(unit->first == facing_loc) {
00251 std::vector<config>::const_iterator second_itor;
00252 for(second_itor = secondary_unit_filter_.begin(); second_itor != secondary_unit_filter_.end(); second_itor++) {
00253 if(!unit->second.matches_filter(&(*second_itor),facing_loc)) return MATCH_FAIL;
00254 result++;
00255 }
00256
00257 break;
00258 }
00259 }
00260 if(unit == disp.get_const_units().end()) return MATCH_FAIL;
00261 }
00262
00263 } else if (!unit_filter_.empty()) return MATCH_FAIL;
00264 if(frequency_ && !(rand()%frequency_)) return MATCH_FAIL;
00265
00266
00267 if(hits_.empty() == false ) {
00268 if (std::find(hits_.begin(),hits_.end(),hit)== hits_.end()) {
00269 return MATCH_FAIL;
00270 } else {
00271 result ++;
00272 }
00273 }
00274 if(swing_num_.empty() == false ) {
00275 if (std::find(swing_num_.begin(),swing_num_.end(),swing_num)== swing_num_.end()) {
00276 return MATCH_FAIL;
00277 } else {
00278 result ++;
00279 }
00280 }
00281 if(!attack) {
00282 if(!primary_attack_filter_.empty())
00283 return MATCH_FAIL;
00284 }
00285 std::vector<config>::const_iterator myitor;
00286 for(myitor = primary_attack_filter_.begin(); myitor != primary_attack_filter_.end(); myitor++) {
00287 if(!attack->matches_filter(*myitor)) return MATCH_FAIL;
00288 result++;
00289 }
00290 if(!second_attack) {
00291 if(!secondary_attack_filter_.empty())
00292 return MATCH_FAIL;
00293 }
00294 for(myitor = secondary_attack_filter_.begin(); myitor != secondary_attack_filter_.end(); myitor++) {
00295 if(!second_attack->matches_filter(*myitor)) return MATCH_FAIL;
00296 result++;
00297 }
00298 return result;
00299
00300 }
00301
00302
00303 void unit_animation::fill_initial_animations( std::vector<unit_animation> & animations, const config & cfg)
00304 {
00305 const image::locator default_image = image::locator(cfg["image"]);
00306 std::vector<unit_animation> animation_base;
00307 std::vector<unit_animation>::const_iterator itor;
00308 add_anims(animations,cfg);
00309 for(itor = animations.begin(); itor != animations.end() ; itor++) {
00310 if (std::find(itor->event_.begin(),itor->event_.end(),"default")!= itor->event_.end()) {
00311 animation_base.push_back(*itor);
00312 animation_base.back().base_score_ = unit_animation::DEFAULT_ANIM;
00313 animation_base.back().event_.clear();
00314 }
00315 }
00316 if( animation_base.empty() )
00317 animation_base.push_back(unit_animation(0,frame_builder().image(default_image).duration(600),"",unit_animation::DEFAULT_ANIM));
00318
00319 animations.push_back(unit_animation(0,frame_builder().image(default_image).duration(1),"_disabled_",0));
00320 animations.push_back(unit_animation(0,frame_builder().image(default_image).duration(1).
00321 blend("0.0~0.3:100,0.3~0.0:200",display::rgb(255,255,255)),"_disabled_selected_",0));
00322 for(itor = animation_base.begin() ; itor != animation_base.end() ; itor++ ) {
00323 unit_animation tmp_anim = *itor;
00324
00325
00326 tmp_anim.unit_anim_.remove_frames_after(600);
00327 animations.push_back(tmp_anim);
00328
00329 tmp_anim = *itor;
00330 tmp_anim.event_ = utils::split("standing");
00331 animations.push_back(tmp_anim);
00332
00333 tmp_anim = *itor;
00334 tmp_anim.unit_anim_.override(0,"","0.0~0.3:100,0.3~0.0:200",display::rgb(255,255,255));
00335 tmp_anim.event_ = utils::split("selected");
00336 animations.push_back(tmp_anim);
00337
00338 tmp_anim = *itor;
00339 tmp_anim.unit_anim_.override(0,"0~1:600");
00340 tmp_anim.event_ = utils::split("recruited");
00341 tmp_anim.unit_anim_.remove_frames_after(600);
00342 animations.push_back(tmp_anim);
00343
00344 tmp_anim = *itor;
00345 tmp_anim.unit_anim_.override(0,"","1~0:600",display::rgb(255,255,255));
00346 tmp_anim.event_ = utils::split("levelin");
00347 tmp_anim.unit_anim_.remove_frames_after(600);
00348 animations.push_back(tmp_anim);
00349
00350 tmp_anim = *itor;
00351 tmp_anim.unit_anim_.override(0,"","0~1:600,1",display::rgb(255,255,255));
00352 tmp_anim.event_ = utils::split("levelout");
00353 tmp_anim.unit_anim_.remove_frames_after(600);
00354 animations.push_back(tmp_anim);
00355
00356 tmp_anim = *itor;
00357 tmp_anim.unit_anim_.override(0,"","",0,"0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,");
00358 tmp_anim.event_ = utils::split("movement");
00359 animations.push_back(tmp_anim);
00360
00361 tmp_anim = *itor;
00362 tmp_anim.unit_anim_.override(-150);
00363 tmp_anim.event_ = utils::split("defend");
00364 animations.push_back(tmp_anim);
00365
00366 tmp_anim = *itor;
00367 tmp_anim.unit_anim_.override(-150,"","",0,"0~0.6:150,0.6~0:150");
00368 tmp_anim.event_ = utils::split("attack");
00369 tmp_anim.primary_attack_filter_.push_back(config());
00370 tmp_anim.primary_attack_filter_.back()["range"] = "melee";
00371 animations.push_back(tmp_anim);
00372
00373 tmp_anim = *itor;
00374 tmp_anim.unit_anim_.override(-150);
00375 tmp_anim.event_ = utils::split("attack");
00376 tmp_anim.primary_attack_filter_.push_back(config());
00377 tmp_anim.primary_attack_filter_.back()["range"] = "ranged";
00378 animations.push_back(tmp_anim);
00379
00380 tmp_anim = *itor;
00381 tmp_anim.unit_anim_.override(0,"1~0:600");
00382 tmp_anim.unit_anim_.remove_frames_after(600);
00383 tmp_anim.event_ = utils::split("death");
00384 animations.push_back(tmp_anim);
00385 animations.back().sub_anims_["_death_sound"] = particule();
00386 animations.back().sub_anims_["_death_sound"].add_frame(1,frame_builder());
00387 animations.back().sub_anims_["_death_sound"].add_frame(1,frame_builder().sound(cfg["die_sound"]),true);
00388
00389
00390 tmp_anim = *itor;
00391 tmp_anim.unit_anim_.override(0,"1~0:150");
00392 tmp_anim.unit_anim_.remove_frames_after(150);
00393 tmp_anim.event_ = utils::split("pre_teleport");
00394 animations.push_back(tmp_anim);
00395
00396 tmp_anim = *itor;
00397 tmp_anim.unit_anim_.override(0,"0~1:150,1");
00398 tmp_anim.unit_anim_.remove_frames_after(150);
00399 tmp_anim.event_ = utils::split("post_teleport");
00400 animations.push_back(tmp_anim);
00401
00402 tmp_anim = *itor;
00403 tmp_anim.unit_anim_.override(0,"","0:30,0.5:30,0:30,0.5:30,0:30,0.5:30,0:30,0.5:30,0:30",display::rgb(255,255,255));
00404 tmp_anim.unit_anim_.remove_frames_after(300);
00405 tmp_anim.event_ = utils::split("healed");
00406 animations.push_back(tmp_anim);
00407 animations.back().sub_anims_["_healed_sound"] = particule();
00408 animations.back().sub_anims_["_healed_sound"].add_frame(1,frame_builder());
00409 animations.back().sub_anims_["_healed_sound"].add_frame(1,frame_builder().sound("heal.wav"),true);
00410
00411 tmp_anim = *itor;
00412 tmp_anim.unit_anim_.override(0,"","0:30,0.5:30,0:30,0.5:30,0:30,0.5:30,0:30,0.5:30,0:30",display::rgb(0,255,0));
00413 tmp_anim.unit_anim_.remove_frames_after(300);
00414 tmp_anim.event_ = utils::split("poisoned");
00415 animations.push_back(tmp_anim);
00416 animations.back().sub_anims_["_poison_sound"] = particule();
00417 animations.back().sub_anims_["_poison_sound"].add_frame(1,frame_builder());
00418 animations.back().sub_anims_["_poison_sound"].add_frame(1,frame_builder().sound("poison.ogg"),true);
00419
00420 }
00421
00422 }
00423 void unit_animation::add_anims( std::vector<unit_animation> & animations, const config & cfg)
00424 {
00425 config expanded_cfg;
00426 config::child_list::const_iterator anim_itor;
00427
00428 expanded_cfg = unit_animation::prepare_animation(cfg,"animation");
00429 const config::child_list& parsed_animations = expanded_cfg.get_children("animation");
00430 for(anim_itor = parsed_animations.begin(); anim_itor != parsed_animations.end(); ++anim_itor) {
00431 animations.push_back(unit_animation(**anim_itor));
00432 }
00433
00434
00435 expanded_cfg = unit_animation::prepare_animation(cfg,"leading_anim");
00436 const config::child_list& leading_anims = expanded_cfg.get_children("leading_anim");
00437 for(anim_itor = leading_anims.begin(); anim_itor != leading_anims.end(); ++anim_itor) {
00438 (**anim_itor)["apply_to"] ="leading";
00439 animations.push_back(unit_animation(**anim_itor));
00440 }
00441 expanded_cfg = unit_animation::prepare_animation(cfg,"recruit_anim");
00442 const config::child_list& recruit_anims = expanded_cfg.get_children("recruit_anim");
00443 for(anim_itor = recruit_anims.begin(); anim_itor != recruit_anims.end(); ++anim_itor) {
00444 (**anim_itor)["apply_to"] ="recruited";
00445 animations.push_back(unit_animation(**anim_itor));
00446 }
00447 expanded_cfg = unit_animation::prepare_animation(cfg,"standing_anim");
00448 const config::child_list& standing_anims = expanded_cfg.get_children("standing_anim");
00449 for(anim_itor = standing_anims.begin(); anim_itor != standing_anims.end(); ++anim_itor) {
00450 (**anim_itor)["apply_to"] ="standing,default";
00451 animations.push_back(unit_animation(**anim_itor));
00452 }
00453 expanded_cfg = unit_animation::prepare_animation(cfg,"idle_anim");
00454 const config::child_list& idle_anims = expanded_cfg.get_children("idle_anim");
00455 for(anim_itor = idle_anims.begin(); anim_itor != idle_anims.end(); ++anim_itor) {
00456 (**anim_itor)["apply_to"] ="idling";
00457 animations.push_back(unit_animation(**anim_itor));
00458 }
00459 expanded_cfg = unit_animation::prepare_animation(cfg,"levelin_anim");
00460 const config::child_list& levelin_anims = expanded_cfg.get_children("levelin_anim");
00461 for(anim_itor = levelin_anims.begin(); anim_itor != levelin_anims.end(); ++anim_itor) {
00462 (**anim_itor)["apply_to"] ="levelin";
00463 animations.push_back(unit_animation(**anim_itor));
00464 }
00465 expanded_cfg = unit_animation::prepare_animation(cfg,"levelout_anim");
00466 const config::child_list& levelout_anims = expanded_cfg.get_children("levelout_anim");
00467 for(anim_itor = levelout_anims.begin(); anim_itor != levelout_anims.end(); ++anim_itor) {
00468 (**anim_itor)["apply_to"] ="levelout";
00469 animations.push_back(unit_animation(**anim_itor));
00470 }
00471 expanded_cfg = unit_animation::prepare_animation(cfg,"healing_anim");
00472 const config::child_list& healing_anims = expanded_cfg.get_children("healing_anim");
00473 for(anim_itor = healing_anims.begin(); anim_itor != healing_anims.end(); ++anim_itor) {
00474 (**anim_itor)["apply_to"] ="healing";
00475 (**anim_itor)["value"]=(**anim_itor)["damage"];
00476 animations.push_back(unit_animation(**anim_itor));
00477 }
00478 expanded_cfg = unit_animation::prepare_animation(cfg,"healed_anim");
00479 const config::child_list& healed_anims = expanded_cfg.get_children("healed_anim");
00480 for(anim_itor = healed_anims.begin(); anim_itor != healed_anims.end(); ++anim_itor) {
00481 (**anim_itor)["apply_to"] ="healed";
00482 (**anim_itor)["value"]=(**anim_itor)["healing"];
00483 animations.push_back(unit_animation(**anim_itor));
00484 animations.back().sub_anims_["_healed_sound"] = particule();
00485 animations.back().sub_anims_["_healed_sound"].add_frame(1,frame_builder());
00486 animations.back().sub_anims_["_healed_sound"].add_frame(1,frame_builder().sound("heal.wav"),true);
00487 }
00488 expanded_cfg = unit_animation::prepare_animation(cfg,"poison_anim");
00489 const config::child_list& poison_anims = expanded_cfg.get_children("poison_anim");
00490 for(anim_itor = poison_anims.begin(); anim_itor != poison_anims.end(); ++anim_itor) {
00491 (**anim_itor)["apply_to"] ="poisoned";
00492 (**anim_itor)["value"]=(**anim_itor)["damage"];
00493 animations.push_back(unit_animation(**anim_itor));
00494 animations.back().sub_anims_["_poison_sound"] = particule();
00495 animations.back().sub_anims_["_poison_sound"].add_frame(1,frame_builder());
00496 animations.back().sub_anims_["_poison_sound"].add_frame(1,frame_builder().sound("poison.ogg"),true);
00497 }
00498 expanded_cfg = unit_animation::prepare_animation(cfg,"movement_anim");
00499 const config::child_list& movement_anims = expanded_cfg.get_children("movement_anim");
00500 for(anim_itor = movement_anims.begin(); anim_itor != movement_anims.end(); ++anim_itor) {
00501 if((**anim_itor)["offset"].empty() ) {
00502 (**anim_itor)["offset"] ="0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,0~1:150,";
00503
00504 }
00505 (**anim_itor)["apply_to"] ="movement";
00506 animations.push_back(unit_animation(**anim_itor));
00507 }
00508 expanded_cfg = unit_animation::prepare_animation(cfg,"defend");
00509 const config::child_list& defends = expanded_cfg.get_children("defend");
00510 for(anim_itor = defends.begin(); anim_itor != defends.end(); ++anim_itor) {
00511 (**anim_itor)["apply_to"] ="defend";
00512 if(!(**anim_itor)["damage"].empty()) {
00513 (**anim_itor)["value"]=(**anim_itor)["damage"];
00514 animations.push_back(unit_animation(**anim_itor));
00515 if(atoi((**anim_itor)["value"].c_str()) != 0) {
00516 animations.back().add_frame(100,frame_builder()
00517 .image(animations.back().get_last_frame().parameters(0).image)
00518 .duration(100)
00519 .blend("0.5:50,0.0:50",game_display::rgb(255,0,0)));
00520 }
00521 } else {
00522 (**anim_itor)["value"]="0";
00523 animations.push_back(unit_animation(**anim_itor));
00524 (**anim_itor)["value"]="";
00525 animations.push_back(unit_animation(**anim_itor));
00526 animations.back().add_frame(100,frame_builder()
00527 .image(animations.back().get_last_frame().parameters(0).image)
00528 .duration(100)
00529 .blend("0.5:50,0.0:50",game_display::rgb(255,0,0)));
00530 }
00531 }
00532 expanded_cfg = unit_animation::prepare_animation(cfg,"attack_anim");
00533 const config::child_list& attack_anims = expanded_cfg.get_children("attack_anim");
00534 for(config::child_list::const_iterator d = attack_anims.begin(); d != attack_anims.end(); ++d) {
00535 (**d)["apply_to"] ="attack";
00536 if((**d)["offset"].empty() && (**d).get_children("missile_frame").empty()) {
00537 (**d)["offset"] ="0~0.6,0.6~0";
00538 }
00539 if(!(**d).get_children("missile_frame").empty()) {
00540 if( (**d)["missile_offset"].empty())(**d)["missile_offset"] = "0~0.8";
00541 config tmp;
00542 tmp["duration"]="1";
00543 (**d).add_child("missile_frame",tmp);
00544 (**d).add_child_at("missile_frame",tmp,0);
00545 }
00546
00547 animations.push_back(unit_animation(**d));
00548 }
00549
00550 expanded_cfg = unit_animation::prepare_animation(cfg,"death");
00551 const config::child_list& deaths = expanded_cfg.get_children("death");
00552 for(anim_itor = deaths.begin(); anim_itor != deaths.end(); ++anim_itor) {
00553 (**anim_itor)["apply_to"] ="death";
00554 animations.push_back(unit_animation(**anim_itor));
00555 image::locator image_loc = animations.back().get_last_frame().parameters(0).image;
00556 animations.back().add_frame(600,frame_builder().image(image_loc).duration(600).highlight("1~0:600"));
00557 if(!cfg["die_sound"].empty()) {
00558 animations.back().sub_anims_["_death_sound"] = particule();
00559 animations.back().sub_anims_["_death_sound"].add_frame(1,frame_builder());
00560 animations.back().sub_anims_["_death_sound"].add_frame(1,frame_builder().sound(cfg["die_sound"]),true);
00561 }
00562 }
00563
00564 expanded_cfg = unit_animation::prepare_animation(cfg,"victory_anim");
00565 const config::child_list& victory_anims = expanded_cfg.get_children("victory_anim");
00566 for(anim_itor = victory_anims.begin(); anim_itor != victory_anims.end(); ++anim_itor) {
00567 (**anim_itor)["apply_to"] ="victory";
00568 animations.push_back(unit_animation(**anim_itor));
00569 }
00570
00571 expanded_cfg = unit_animation::prepare_animation(cfg,"extra_anim");
00572 const config::child_list& extra_anims = expanded_cfg.get_children("extra_anim");
00573 for(anim_itor = extra_anims.begin(); anim_itor != extra_anims.end(); ++anim_itor) {
00574 (**anim_itor)["apply_to"] =(**anim_itor)["flag"];
00575 animations.push_back(unit_animation(**anim_itor));
00576 }
00577 expanded_cfg = unit_animation::prepare_animation(cfg,"teleport_anim");
00578 const config::child_list& teleports = expanded_cfg.get_children("teleport_anim");
00579 for(anim_itor = teleports.begin(); anim_itor != teleports.end(); ++anim_itor) {
00580 (**anim_itor)["apply_to"] ="pre_teleport";
00581 animations.push_back(unit_animation(**anim_itor));
00582 animations.back().unit_anim_.remove_frames_after(0);
00583 (**anim_itor)["apply_to"] ="post_teleport";
00584 animations.push_back(unit_animation(**anim_itor));
00585 animations.back().unit_anim_.remove_frames_until(0);
00586 }
00587
00588 }
00589
00590 void unit_animation::particule::override( int start_time,const std::string highlight,const std::string blend_ratio ,Uint32 blend_color ,const std::string offset)
00591 {
00592 set_begin_time(start_time);
00593 if(!highlight.empty()) parameters_.highlight(highlight);
00594 if(!offset.empty()) parameters_.offset(offset);
00595 if(!blend_ratio.empty()) parameters_.blend(blend_ratio,blend_color);
00596
00597
00598 }
00599
00600 bool unit_animation::particule::need_update() const
00601 {
00602 if(animated<unit_frame>::need_update()) return true;
00603 if(get_current_frame().need_update()) return true;
00604 if(parameters_.need_update()) return true;
00605 return false;
00606 }
00607
00608 unit_animation::particule::particule(
00609 const config& cfg, const std::string frame_string ) :
00610 animated<unit_frame>(),
00611 accelerate(true),
00612 parameters_(cfg,frame_string),
00613 src_(),
00614 dst_(),
00615 halo_id_(0),
00616 last_frame_begin_time_(0)
00617 {
00618 config::const_child_itors range = cfg.child_range(frame_string+"frame");
00619 config::const_child_iterator itor;
00620 starting_frame_time_=INT_MAX;
00621 if(cfg[frame_string+"start_time"].empty() &&range.first != range.second) {
00622 for(itor = range.first; itor != range.second; itor++) {
00623 starting_frame_time_=minimum(starting_frame_time_,atoi((**itor)["begin"].c_str()));
00624 }
00625 } else {
00626 starting_frame_time_ = atoi(cfg[frame_string+"start_time"].c_str());
00627 }
00628
00629 for(; range.first != range.second; ++range.first) {
00630 unit_frame tmp_frame(**range.first);
00631 add_frame(tmp_frame.duration(),tmp_frame,!tmp_frame.does_not_change());
00632 }
00633 parameters_.duration(get_animation_duration());
00634 if(!parameters_.does_not_change() ) {
00635 force_change();
00636 }
00637 }
00638
00639 bool unit_animation::need_update() const
00640 {
00641 if(unit_anim_.need_update()) return true;
00642 std::map<std::string,particule>::const_iterator anim_itor =sub_anims_.begin();
00643 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00644 if(anim_itor->second.need_update()) return true;
00645 }
00646 return false;
00647 }
00648
00649 bool unit_animation::animation_finished() const
00650 {
00651 if(!unit_anim_.animation_finished()) return false;
00652 std::map<std::string,particule>::const_iterator anim_itor =sub_anims_.begin();
00653 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00654 if(!anim_itor->second.animation_finished()) return false;
00655 }
00656 return true;
00657 }
00658
00659 bool unit_animation::animation_finished_potential() const
00660 {
00661 if(!unit_anim_.animation_finished_potential()) return false;
00662 std::map<std::string,particule>::const_iterator anim_itor =sub_anims_.begin();
00663 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00664 if(!anim_itor->second.animation_finished_potential()) return false;
00665 }
00666 return true;
00667 }
00668
00669 void unit_animation::update_last_draw_time()
00670 {
00671 double acceleration = unit_anim_.accelerate ? game_display::get_singleton()->turbo_speed() : 1.0;
00672 unit_anim_.update_last_draw_time(acceleration);
00673 std::map<std::string,particule>::iterator anim_itor =sub_anims_.begin();
00674 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00675 anim_itor->second.update_last_draw_time(acceleration);
00676 }
00677 }
00678
00679 int unit_animation::get_end_time() const
00680 {
00681 int result = unit_anim_.get_end_time();
00682 std::map<std::string,particule>::const_iterator anim_itor =sub_anims_.end();
00683 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00684 result= minimum<int>(result,anim_itor->second.get_end_time());
00685 }
00686 return result;
00687 }
00688
00689 int unit_animation::get_begin_time() const
00690 {
00691 int result = unit_anim_.get_begin_time();
00692 std::map<std::string,particule>::const_iterator anim_itor =sub_anims_.begin();
00693 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00694 result= minimum<int>(result,anim_itor->second.get_begin_time());
00695 }
00696 return result;
00697 }
00698
00699 void unit_animation::start_animation(int start_time,const gamemap::location &src, const gamemap::location &dst, bool cycles, const std::string text, const Uint32 text_color,const bool accelerate)
00700 {
00701 unit_anim_.accelerate = accelerate;
00702 new_animation_frame();
00703 unit_anim_.start_animation(start_time, src, dst, cycles);
00704 if(!text.empty()) {
00705 particule crude_build;
00706 crude_build.add_frame(1,frame_builder());
00707 crude_build.add_frame(1,frame_builder().text(text,text_color),true);
00708 sub_anims_["_add_text"] = crude_build;
00709 }
00710 std::map<std::string,particule>::iterator anim_itor =sub_anims_.begin();
00711 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00712 anim_itor->second.accelerate = accelerate;
00713 anim_itor->second.start_animation(start_time,src,dst,cycles);
00714 }
00715 }
00716 void unit_animation::pause_animation()
00717 {
00718
00719 std::map<std::string,particule>::iterator anim_itor =sub_anims_.begin();
00720 unit_anim_.pause_animation();
00721 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00722 anim_itor->second.pause_animation();
00723 }
00724 }
00725 void unit_animation::restart_animation()
00726 {
00727
00728 std::map<std::string,particule>::iterator anim_itor =sub_anims_.begin();
00729 unit_anim_.restart_animation();
00730 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00731 anim_itor->second.restart_animation();
00732 }
00733 }
00734 void unit_animation::redraw(const frame_parameters& value)
00735 {
00736
00737 std::map<std::string,particule>::iterator anim_itor =sub_anims_.begin();
00738 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00739 anim_itor->second.redraw( value);
00740 }
00741 }
00742 void unit_animation::invalidate(const frame_parameters& value) const
00743 {
00744
00745 std::map<std::string,particule>::const_iterator anim_itor =sub_anims_.begin();
00746 unit_anim_.invalidate(value,true);
00747 for( ; anim_itor != sub_anims_.end() ; anim_itor++) {
00748 anim_itor->second.invalidate(value);
00749 }
00750 }
00751 void unit_animation::particule::redraw(const frame_parameters& value)
00752 {
00753 const unit_frame& current_frame= get_current_frame();
00754 const frame_parameters default_val = parameters_.parameters(get_animation_time() -get_begin_time());
00755 if(get_current_frame_begin_time() != last_frame_begin_time_ ) {
00756 last_frame_begin_time_ = get_current_frame_begin_time();
00757 current_frame.redraw(get_current_frame_time(),true,src_,dst_,&halo_id_,default_val,value);
00758 } else {
00759 current_frame.redraw(get_current_frame_time(),false,src_,dst_,&halo_id_,default_val,value);
00760 }
00761 }
00762 void unit_animation::particule::invalidate(const frame_parameters& value,const bool primary ) const
00763 {
00764 const unit_frame& current_frame= get_current_frame();
00765 const frame_parameters default_val = parameters_.parameters(get_animation_time() -get_begin_time());
00766 current_frame.invalidate(get_current_frame_time(),src_,dst_,default_val,value,primary);
00767 }
00768
00769 unit_animation::particule::~particule()
00770 {
00771 halo::remove(halo_id_);
00772 halo_id_ = halo::NO_HALO;
00773 }
00774
00775 void unit_animation::particule::start_animation(int start_time,
00776 const gamemap::location &src, const gamemap::location &dst,
00777 bool cycles)
00778 {
00779 halo::remove(halo_id_);
00780 halo_id_ = halo::NO_HALO;
00781 parameters_.duration(get_animation_duration());
00782 animated<unit_frame>::start_animation(start_time,cycles);
00783 last_frame_begin_time_ = get_begin_time() -1;
00784 if(src != gamemap::location::null_location || dst != gamemap::location::null_location) {
00785 src_ = src;
00786 dst_ = dst;
00787 }
00788 }
00789
00790 void unit_animator::add_animation(unit* animated_unit,const std::string& event,
00791 const gamemap::location &src , const int value,bool with_bars,bool cycles,
00792 const std::string text,const Uint32 text_color,
00793 const unit_animation::hit_type hit_type,
00794 const attack_type* attack, const attack_type* second_attack, int swing_num)
00795 {
00796 if(!animated_unit) return;
00797 anim_elem tmp;
00798 game_display*disp = game_display::get_singleton();
00799 tmp.my_unit = animated_unit;
00800 tmp.text = text;
00801 tmp.text_color = text_color;
00802 tmp.src = src;
00803 tmp.with_bars= with_bars;
00804 tmp.cycles = cycles;
00805 tmp.animation = animated_unit->choose_animation(*disp,src,event,value,hit_type,attack,second_attack,swing_num);
00806 if(!tmp.animation) return;
00807
00808
00809
00810 start_time_ = maximum<int>(start_time_,tmp.animation->get_begin_time());
00811 animated_units_.push_back(tmp);
00812 }
00813 void unit_animator::replace_anim_if_invalid(unit* animated_unit,const std::string& event,
00814 const gamemap::location &src , const int value,bool with_bars,bool cycles,
00815 const std::string text,const Uint32 text_color,
00816 const unit_animation::hit_type hit_type,
00817 const attack_type* attack, const attack_type* second_attack, int swing_num)
00818 {
00819 if(!animated_unit) return;
00820 game_display*disp = game_display::get_singleton();
00821 if(animated_unit->get_animation() &&
00822 !animated_unit->get_animation()->animation_finished_potential() &&
00823 animated_unit->get_animation()->matches(*disp,src,animated_unit,event,value,hit_type,attack,second_attack,swing_num) >unit_animation::MATCH_FAIL) {
00824 anim_elem tmp;
00825 tmp.my_unit = animated_unit;
00826 tmp.text = text;
00827 tmp.text_color = text_color;
00828 tmp.src = src;
00829 tmp.with_bars= with_bars;
00830 tmp.cycles = cycles;
00831 tmp.animation = NULL;
00832 animated_units_.push_back(tmp);
00833 }else {
00834 add_animation(animated_unit,event,src,value,with_bars,cycles,text,text_color,hit_type,attack,second_attack,swing_num);
00835 }
00836 }
00837 void unit_animator::start_animations()
00838 {
00839 int begin_time = INT_MAX;
00840 std::vector<anim_elem>::iterator anim;
00841 for(anim = animated_units_.begin(); anim != animated_units_.end();anim++) {
00842 if(anim->my_unit->get_animation()) {
00843 if(anim->animation) {
00844 begin_time = minimum<int>(begin_time,anim->animation->get_begin_time());
00845 } else {
00846 begin_time = minimum<int>(begin_time,anim->my_unit->get_animation()->get_begin_time());
00847 }
00848 }
00849 }
00850 for(anim = animated_units_.begin(); anim != animated_units_.end();anim++) {
00851 if(anim->animation) {
00852 anim->my_unit->start_animation(begin_time,anim->src, anim->animation,anim->with_bars, anim->cycles,anim->text,anim->text_color);
00853 anim->animation = NULL;
00854 }
00855
00856 }
00857 }
00858
00859 bool unit_animator::would_end() const
00860 {
00861 bool finished = true;
00862 for(std::vector<anim_elem>::const_iterator anim = animated_units_.begin(); anim != animated_units_.end();anim++) {
00863 finished &= anim->my_unit->get_animation()->animation_finished_potential();
00864 }
00865 return finished;
00866 }
00867 void unit_animator::wait_until(int animation_time) const
00868 {
00869 game_display*disp = game_display::get_singleton();
00870 double speed = disp->turbo_speed();
00871 int end_tick = animated_units_[0].my_unit->get_animation()->time_to_tick(animation_time);
00872 while (SDL_GetTicks() < (unsigned int)end_tick - 20/speed) {
00873 disp->draw();
00874 end_tick = animated_units_[0].my_unit->get_animation()->time_to_tick(animation_time);
00875 events::pump();
00876 disp->delay(maximum<int>(0,
00877 minimum<int>(10,
00878 static_cast<int>((animation_time - get_animation_time()) * speed))));
00879 }
00880 disp->delay(maximum<int>(0,end_tick - SDL_GetTicks() +5));
00881 new_animation_frame();
00882 }
00883 void unit_animator::wait_for_end() const
00884 {
00885 if (game_config::no_delay) return;
00886 bool finished = false;
00887 game_display*disp = game_display::get_singleton();
00888 while(!finished) {
00889 disp->draw();
00890 events::pump();
00891 disp->delay(10);
00892 finished = true;
00893 for(std::vector<anim_elem>::const_iterator anim = animated_units_.begin(); anim != animated_units_.end();anim++) {
00894 finished &= anim->my_unit->get_animation()->animation_finished_potential();
00895 }
00896 }
00897 }
00898 int unit_animator::get_animation_time() const{
00899 return animated_units_[0].my_unit->get_animation()->get_animation_time() ;
00900 }
00901
00902 int unit_animator::get_animation_time_potential() const{
00903 return animated_units_[0].my_unit->get_animation()->get_animation_time_potential() ;
00904 }
00905
00906 int unit_animator::get_end_time() const
00907 {
00908 int end_time = INT_MIN;
00909 for(std::vector<anim_elem>::const_iterator anim = animated_units_.begin(); anim != animated_units_.end();anim++) {
00910 if(anim->my_unit->get_animation()) {
00911 end_time = maximum<int>(end_time,anim->my_unit->get_animation()->get_end_time());
00912 }
00913 }
00914 return end_time;
00915 }
00916 void unit_animator::pause_animation()
00917 {
00918 for(std::vector<anim_elem>::iterator anim = animated_units_.begin(); anim != animated_units_.end();anim++) {
00919 if(anim->my_unit->get_animation()) {
00920 anim->my_unit->get_animation()->pause_animation();
00921 }
00922 }
00923 }
00924 void unit_animator::restart_animation()
00925 {
00926 for(std::vector<anim_elem>::iterator anim = animated_units_.begin(); anim != animated_units_.end();anim++) {
00927 if(anim->my_unit->get_animation()) {
00928 anim->my_unit->get_animation()->restart_animation();
00929 }
00930 }
00931 }