00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "body.h"
00022 #include <sstream>
00023 #include <iostream>
00024 #include <map>
00025 #include "clothe.h"
00026 #include "member.h"
00027 #include "../team/teams_list.h"
00028 #include "../game/time.h"
00029 #include "../tool/debug.h"
00030 #include "../tool/random.h"
00031 #include "../tool/resource_manager.h"
00032 #include "../tool/xml_document.h"
00033 #include "../particles/body_member.h"
00034 #include "../particles/teleport_member.h"
00035
00036 Body::Body(xmlpp::Element* xml, Profile* res)
00037 {
00038 need_rebuild = true;
00039 current_clothe = NULL;
00040 current_mvt = NULL;
00041 walk_events = 0;
00042 animation_number = 0;
00043 direction = DIRECTION_RIGHT;
00044 main_rotation_rad = 0;
00045
00046
00047 xmlpp::Node::NodeList nodes = xml -> get_children("sprite");
00048 xmlpp::Node::NodeList::iterator it=nodes.begin();
00049
00050 while(it != nodes.end())
00051 {
00052 xmlpp::Element *elem = dynamic_cast<xmlpp::Element*> (*it);
00053 std::string name;
00054 XmlReader::ReadStringAttr( elem, "name", name);
00055
00056 Member* member = new Member(elem, res);
00057 if(members_lst.find(name) != members_lst.end())
00058 std::cerr << "Warning !! The member \""<< name << "\" is defined twice in the xml file" << std::endl;
00059 else
00060 members_lst[name] = member;
00061
00062 it++;
00063 }
00064
00065
00066 weapon_member = new WeaponMember();
00067 members_lst["weapon"] = weapon_member;
00068
00069
00070 xmlpp::Node::NodeList nodes2 = xml -> get_children("clothe");
00071 xmlpp::Node::NodeList::iterator it2=nodes2.begin();
00072
00073 while(it2 != nodes2.end())
00074 {
00075 xmlpp::Element *elem = dynamic_cast<xmlpp::Element*> (*it2);
00076 std::string name;
00077 XmlReader::ReadStringAttr( elem, "name", name);
00078
00079 Clothe* clothe = new Clothe(elem, members_lst);
00080 if (clothes_lst.find(name) != clothes_lst.end())
00081 std::cerr << "Warning !! The clothe \""<< name << "\" is defined twice in the xml file" << std::endl;
00082 else
00083 clothes_lst[name] = clothe;
00084
00085 it2++;
00086 }
00087
00088
00089 xmlpp::Node::NodeList nodes4 = xml -> get_children("alias");
00090 xmlpp::Node::NodeList::iterator it4=nodes4.begin();
00091 std::map<std::string, std::string> mvt_alias;
00092 while(it4 != nodes4.end())
00093 {
00094 xmlpp::Element *elem = dynamic_cast<xmlpp::Element*> (*it4);
00095 std::string mvt, corresp;
00096 XmlReader::ReadStringAttr( elem, "movement", mvt);
00097 XmlReader::ReadStringAttr( elem, "correspond_to", corresp);
00098 mvt_alias.insert(std::make_pair(mvt,corresp));
00099 it4++;
00100 }
00101
00102
00103 xmlpp::Node::NodeList nodes3 = xml -> get_children("movement");
00104 xmlpp::Node::NodeList::iterator it3=nodes3.begin();
00105
00106 while(it3 != nodes3.end())
00107 {
00108 xmlpp::Element *elem = dynamic_cast<xmlpp::Element*> (*it3);
00109 std::string name;
00110 XmlReader::ReadStringAttr( elem, "name", name);
00111 if(strncmp(name.c_str(),"animation", 9)==0)
00112 animation_number++;
00113
00114 Movement* mvt = new Movement(elem);
00115 if(mvt_lst.find(name) != mvt_lst.end())
00116 std::cerr << "Warning !! The movement \""<< name << "\" is defined twice in the xml file" << std::endl;
00117 else
00118 mvt_lst[name] = mvt;
00119
00120 for(std::map<std::string, std::string>::iterator it = mvt_alias.begin();
00121 it != mvt_alias.end(); ++it)
00122 if(it->second == name)
00123 {
00124 Movement* mvt = new Movement(elem);
00125 mvt->type = it->first;
00126 mvt_lst[it->first] = mvt;
00127 }
00128 it3++;
00129 }
00130 }
00131
00132 Body::Body(Body *_body)
00133 {
00134 need_rebuild = true;
00135 current_clothe = NULL;
00136 current_mvt = NULL;
00137 walk_events = 0;
00138 animation_number = _body->animation_number;
00139 direction = DIRECTION_RIGHT;
00140 main_rotation_rad = 0;
00141
00142
00143 weapon_member = new WeaponMember();
00144 members_lst["weapon"] = weapon_member;
00145
00146
00147 std::map<std::string, Member*>::iterator it1 = _body->members_lst.begin();
00148 while(it1 != _body->members_lst.end())
00149 if(it1->second->name != "weapon")
00150 {
00151 std::pair<std::string,Member*> p;
00152 p.first = it1->first;
00153 p.second = new Member(it1->second);
00154 members_lst.insert(p);
00155 it1++;
00156 }
00157 else
00158 it1++;
00159
00160
00161 std::map<std::string, Clothe*>::iterator it2 = _body->clothes_lst.begin();
00162 while(it2 != _body->clothes_lst.end())
00163 {
00164 std::pair<std::string,Clothe*> p;
00165 p.first = it2->first;
00166 p.second = new Clothe(it2->second, members_lst);
00167 clothes_lst.insert(p);
00168 it2++;
00169 }
00170
00171
00172 std::map<std::string, Movement*>::iterator it3 = _body->mvt_lst.begin();
00173 while(it3 != _body->mvt_lst.end())
00174 {
00175 std::pair<std::string,Movement*> p;
00176 p.first = it3->first;
00177 p.second = it3->second;
00178 mvt_lst.insert(p);
00179 it3++;
00180 }
00181 }
00182
00183 Body::~Body()
00184 {
00185
00186
00187 std::map<std::string, Member*>::iterator it = members_lst.begin();
00188 while(it != members_lst.end())
00189 {
00190 delete it->second;
00191 it++;
00192 }
00193
00194
00195 std::map<std::string, Clothe*>::iterator it2 = clothes_lst.begin();
00196 while(it2 != clothes_lst.end())
00197 {
00198 delete it2->second;
00199 it2++;
00200 }
00201
00202 members_lst.clear();
00203 clothes_lst.clear();
00204 mvt_lst.clear();
00205 }
00206
00207 void Body::ResetMovement()
00208 {
00209 for(int layer=0;layer < (int)current_clothe->layers.size() ;layer++)
00210 current_clothe->layers[layer]->ResetMovement();
00211 }
00212
00213 void Body::ApplyMovement(Movement* mvt, uint frame)
00214 {
00215
00216
00217
00218 std::vector<junction>::iterator member = squel_lst.begin();
00219 for(;member != squel_lst.end();
00220 member++)
00221 {
00222 assert( frame < mvt->frames.size() );
00223 if(mvt->frames[frame].find(member->member->type) != mvt->frames[frame].end())
00224 {
00225
00226 member_mvt mb_mvt = mvt->frames[frame].find(member->member->type)->second;
00227 if(mb_mvt.follow_crosshair && ActiveCharacter().body == this && ActiveTeam().AccessWeapon().UseCrossHair())
00228 {
00229
00230 double angle = owner->GetFiringAngle();
00231 if(angle < 0)
00232 angle += 2 * M_PI;
00233 if(ActiveCharacter().GetDirection() == DIRECTION_LEFT)
00234 angle = M_PI - angle;
00235
00236 mb_mvt.SetAngle(mb_mvt.GetAngle() + angle);
00237 }
00238
00239 if(mb_mvt.follow_half_crosshair && ActiveCharacter().body == this && ActiveTeam().AccessWeapon().UseCrossHair())
00240 {
00241
00242 double angle_rad = owner->GetFiringAngle();
00243 if(ActiveCharacter().GetDirection() == DIRECTION_RIGHT)
00244 angle_rad /= 2;
00245 else
00246 if(angle_rad > M_PI_2)
00247 angle_rad = M_PI_2 - angle_rad / 2;
00248 else
00249 angle_rad = -M_PI_2 - angle_rad / 2;
00250
00251
00252
00253 if(angle_rad < 0)
00254 angle_rad += 2 * M_PI;
00255
00256 mb_mvt.SetAngle(mb_mvt.GetAngle() + angle_rad);
00257 }
00258
00259 if(mb_mvt.follow_speed)
00260 {
00261
00262 double angle_rad = (owner->GetSpeedAngle());
00263 if(angle_rad < 0)
00264 angle_rad += 2 * M_PI;
00265 if(owner->GetDirection() == DIRECTION_LEFT)
00266 angle_rad = M_PI - angle_rad;
00267
00268 mb_mvt.SetAngle(mb_mvt.GetAngle() + angle_rad);
00269 }
00270
00271 if(mb_mvt.follow_direction)
00272 {
00273
00274 if(owner->GetDirection() == DIRECTION_LEFT)
00275 mb_mvt.SetAngle(mb_mvt.GetAngle() + M_PI);
00276 }
00277
00278
00279 member->member->ApplyMovement(mb_mvt, squel_lst);
00280 }
00281 }
00282 }
00283
00284 void Body::ApplySqueleton()
00285 {
00286
00287 std::vector<junction>::iterator member = squel_lst.begin();
00288
00289 member->member->pos = Point2f(0,0);
00290 member->member->SetAngle(0);
00291 member++;
00292
00293 for(;member != squel_lst.end();
00294 member++)
00295 {
00296
00297 member->member->ApplySqueleton(member->parent);
00298 }
00299 }
00300
00301 void Body::Build()
00302 {
00303
00304 unsigned int last_frame = current_frame;
00305 if(walk_events > 0 || current_mvt->type!="walk")
00306 if(Time::GetInstance()->Read() > last_refresh + current_mvt->speed)
00307 {
00308 current_frame += (Time::GetInstance()->Read()-last_refresh) / current_mvt->speed;
00309 last_refresh += ((Time::GetInstance()->Read()-last_refresh) / current_mvt->speed) * current_mvt->speed;
00310
00311 if(current_frame >= current_mvt->frames.size())
00312 {
00313 if(play_once_clothe_sauv)
00314 SetClothe(play_once_clothe_sauv->name);
00315 if(play_once_mvt_sauv)
00316 {
00317 SetMovement(play_once_mvt_sauv->type);
00318 current_frame = play_once_frame_sauv;
00319 }
00320 }
00321 current_frame %= current_mvt->frames.size();
00322 }
00323
00324 need_rebuild |= (last_frame != current_frame);
00325 need_rebuild |= current_mvt->always_moving;
00326
00327 if(!need_rebuild)
00328 return;
00329
00330 ResetMovement();
00331 ApplySqueleton();
00332 ApplyMovement(current_mvt, current_frame);
00333
00334
00335
00336 for(int layer=0;layer < (int)current_clothe->layers.size() ;layer++)
00337 if(current_clothe->layers[layer]->name != "weapon")
00338 current_clothe->layers[layer]->RotateSprite();
00339
00340
00341 member_mvt body_mvt;
00342 float y_max = 0;
00343 for(int lay=0;lay < (int)current_clothe->layers.size() ;lay++)
00344 if(current_clothe->layers[lay]->name != "weapon")
00345 {
00346 Member* member = current_clothe->layers[lay];
00347 if(member->pos.y + member->spr->GetHeightMax() + member->spr->GetRotationPoint().y > y_max
00348 && !member->go_through_ground)
00349 y_max = member->pos.y + member->spr->GetHeightMax() + member->spr->GetRotationPoint().y;
00350 }
00351 body_mvt.pos.y = (float)GetSize().y - y_max + current_mvt->test_bottom;
00352 body_mvt.pos.x = GetSize().x / 2.0 - squel_lst.front().member->spr->GetWidth() / 2.0;
00353 body_mvt.SetAngle(main_rotation_rad);
00354 squel_lst.front().member->ApplyMovement(body_mvt, squel_lst);
00355
00356 need_rebuild = false;
00357 }
00358
00359 void Body::Draw(const Point2i& _pos)
00360 {
00361 Build();
00362
00363
00364 if(direction == DIRECTION_RIGHT)
00365 weapon_pos = Point2i((int)weapon_member->pos.x,(int)weapon_member->pos.y);
00366 else
00367 weapon_pos = Point2i(GetSize().x - (int)weapon_member->pos.x,(int)weapon_member->pos.y);
00368 weapon_pos += _pos;
00369
00370
00371 for(int layer=0;layer < (int)current_clothe->layers.size() ;layer++)
00372 current_clothe->layers[layer]->Draw(_pos, _pos.x + GetSize().x/2, int(direction));
00373 }
00374
00375 void Body::AddChildMembers(Member* parent)
00376 {
00377
00378
00379 for(std::map<std::string, v_attached>::iterator child = parent->attached_members.begin();
00380 child != parent->attached_members.end();
00381 child++)
00382 {
00383
00384 for(uint lay = 0; lay < current_clothe->layers.size(); lay++)
00385 {
00386 if(current_clothe->layers[lay]->type == child->first)
00387 {
00388
00389 junction body;
00390 body.member = current_clothe->layers[lay];
00391 body.parent = parent;
00392 squel_lst.push_back(body);
00393
00394
00395 AddChildMembers(current_clothe->layers[lay]);
00396 }
00397 }
00398 }
00399 }
00400
00401 void Body::BuildSqueleton()
00402 {
00403
00404
00405 squel_lst.clear();
00406
00407
00408 for(uint lay = 0; lay < current_clothe->layers.size(); lay++)
00409 if(current_clothe->layers[lay]->type == "body")
00410 {
00411 junction body;
00412 body.member = current_clothe->layers[lay];
00413 body.parent = NULL;
00414 squel_lst.push_back(body);
00415 break;
00416 }
00417
00418 if(squel_lst.size() == 0)
00419 {
00420 std::cerr << "Unable to find the \"body\" member in the current clothe" << std::endl;
00421 assert(false);
00422 }
00423
00424 AddChildMembers(squel_lst.front().member);
00425 }
00426
00427 void Body::SetClothe(std::string name)
00428 {
00429 MSG_DEBUG("body", " %s use clothe %s", owner->GetName().c_str(), name.c_str());
00430 if(current_clothe && current_clothe->name == name) return;
00431
00432 if(clothes_lst.find(name) != clothes_lst.end())
00433 {
00434 current_clothe = clothes_lst.find(name)->second;
00435 BuildSqueleton();
00436 main_rotation_rad = 0;
00437 need_rebuild = true;
00438 }
00439 else
00440 MSG_DEBUG("body","Clothe not found");
00441
00442
00443 play_once_clothe_sauv = NULL;
00444
00445 assert(current_clothe != NULL);
00446 }
00447
00448 void Body::SetMovement(std::string name)
00449 {
00450 MSG_DEBUG("body", " %s use movement %s", owner->GetName().c_str(), name.c_str());
00451 if(current_mvt && current_mvt->type == name) return;
00452
00453
00454 if(current_clothe && current_clothe->name == "black") return;
00455
00456 if(mvt_lst.find(name) != mvt_lst.end())
00457 {
00458 current_mvt = mvt_lst.find(name)->second;
00459 current_frame = 0;
00460 last_refresh = Time::GetInstance()->Read();
00461 main_rotation_rad = 0;
00462 need_rebuild = true;
00463 }
00464 else
00465 MSG_DEBUG("body","Movement not found");
00466
00467 play_once_mvt_sauv = NULL;
00468
00469 assert(current_mvt != NULL);
00470 }
00471
00472 void Body::PlayAnimation()
00473 {
00474 std::ostringstream name;
00475 name << "animation" << randomObj.GetLong(0, animation_number - 1);
00476 SetClotheOnce(name.str());
00477 SetMovementOnce(name.str());
00478 }
00479
00480 void Body::SetClotheOnce(std::string name)
00481 {
00482 MSG_DEBUG("body", " %s use clothe %s once", owner->GetName().c_str(), name.c_str());
00483 if(current_clothe && current_clothe->name == name) return;
00484
00485 if(clothes_lst.find(name) != clothes_lst.end())
00486 {
00487 if(!play_once_clothe_sauv)
00488 play_once_clothe_sauv = current_clothe;
00489 current_clothe = clothes_lst.find(name)->second;
00490 BuildSqueleton();
00491 main_rotation_rad = 0;
00492 need_rebuild = true;
00493 }
00494 else
00495 MSG_DEBUG("body","Clothe not found");
00496
00497 assert(current_clothe != NULL);
00498 }
00499
00500 void Body::SetMovementOnce(std::string name)
00501 {
00502 MSG_DEBUG("body", " %s use movement %s once", owner->GetName().c_str(), name.c_str());
00503 if(current_mvt && current_mvt->type == name) return;
00504
00505
00506 if(current_clothe && current_clothe->name == "black" && name != "black") return;
00507
00508 if(mvt_lst.find(name) != mvt_lst.end())
00509 {
00510 if(!play_once_mvt_sauv)
00511 {
00512 play_once_mvt_sauv = current_mvt;
00513 play_once_frame_sauv = current_frame;
00514 }
00515
00516 current_mvt = mvt_lst.find(name)->second;
00517 current_frame = 0;
00518 last_refresh = Time::GetInstance()->Read();
00519 main_rotation_rad = 0;
00520 need_rebuild = true;
00521 }
00522 else
00523 MSG_DEBUG("body","Movement not found");
00524
00525 assert(current_mvt != NULL);
00526 }
00527
00528 void Body::GetTestRect(uint &l, uint&r, uint &t, uint &b)
00529 {
00530 if(direction == DIRECTION_RIGHT)
00531 {
00532 l = current_mvt->test_left;
00533 r = current_mvt->test_right;
00534 }
00535 else
00536 {
00537 r = current_mvt->test_left;
00538 l = current_mvt->test_right;
00539 }
00540 t = current_mvt->test_top;
00541 b = current_mvt->test_bottom;
00542 }
00543
00544 void Body::SetDirection(Direction_t dir)
00545 {
00546 direction=dir;
00547 }
00548
00549 const Body::Direction_t &Body::GetDirection() const
00550 {
00551 return direction;
00552 }
00553
00554 const Point2i &Body::GetHandPosition() const
00555 {
00556 return weapon_pos;
00557 }
00558
00559 void Body::StartWalk()
00560 {
00561
00562
00563
00564
00565 walk_events++;
00566 if(walk_events == 1)
00567 last_refresh = Time::GetInstance()->Read();
00568 }
00569
00570 void Body::StopWalk()
00571 {
00572 if(walk_events > 0)
00573 walk_events--;
00574 if(current_mvt->type == "walk")
00575 SetFrame(0);
00576 }
00577
00578 void Body::ResetWalk()
00579 {
00580 walk_events = 0;
00581 }
00582
00583 uint Body::GetMovementDuration()
00584 {
00585 return current_mvt->frames.size() * current_mvt->speed;
00586 }
00587
00588 uint Body::GetFrameCount()
00589 {
00590 return current_mvt->frames.size();
00591 }
00592
00593 void Body::SetFrame(uint no)
00594 {
00595 assert(no < current_mvt->frames.size());
00596 current_frame = no;
00597 need_rebuild = true;
00598 }
00599
00600 void Body::MakeParticles(const Point2i& pos)
00601 {
00602 Build();
00603
00604 for(int layer=0;layer < (int)current_clothe->layers.size() ;layer++)
00605 if(current_clothe->layers[layer]->type != "weapon")
00606 ParticleEngine::AddNow(new BodyMemberParticle(current_clothe->layers[layer]->spr,
00607 current_clothe->layers[layer]->GetPos()+pos));
00608 }
00609
00610 void Body::MakeTeleportParticles(const Point2i& pos, const Point2i& dst)
00611 {
00612 Build();
00613
00614 for(int layer=0;layer < (int)current_clothe->layers.size() ;layer++)
00615 if(current_clothe->layers[layer]->type != "weapon")
00616 {
00617 ParticleEngine::AddNow(new TeleportMemberParticle(current_clothe->layers[layer]->spr,
00618 current_clothe->layers[layer]->GetPos()+pos,
00619 current_clothe->layers[layer]->GetPos()+dst,
00620 int(direction)));
00621 }
00622 }
00623
00624 void Body::SetRotation(double angle)
00625 {
00626 MSG_DEBUG("body", "%s -> new angle: %i", owner->GetName().c_str(), angle);
00627 main_rotation_rad = angle;
00628 need_rebuild = true;
00629 }
00630
00631 const std::string& Body::GetMovement() { return current_mvt->type; }
00632 const std::string& Body::GetClothe() { return current_clothe->name; }