00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "character.h"
00023 #include <SDL.h>
00024 #include <sstream>
00025 #include <iostream>
00026 #include "body.h"
00027 #include "../team/macro.h"
00028 #include "move.h"
00029 #include "../game/game.h"
00030 #include "../game/game_mode.h"
00031 #include "../game/game_loop.h"
00032 #include "../game/time.h"
00033 #include "../game/config.h"
00034 #include "../graphic/text.h"
00035 #include "../graphic/font.h"
00036 #include "../include/action_handler.h"
00037 #include "../include/app.h"
00038 #include "../include/constant.h"
00039 #include "../interface/interface.h"
00040 #include "../interface/cursor.h"
00041 #include "../map/camera.h"
00042 #include "../map/map.h"
00043 #include "../map/water.h"
00044 #include "../network/network.h"
00045 #include "../network/randomsync.h"
00046 #include "../sound/jukebox.h"
00047 #include "../tool/debug.h"
00048 #include "../tool/random.h"
00049 #include "../tool/math_tools.h"
00050 #include "../weapon/suicide.h"
00051 #include "../weapon/crosshair.h"
00052 #include "../weapon/explosion.h"
00053
00054 const uint HAUT_FONT_MIX = 13;
00055
00056
00057 const uint ESPACE = 3;
00058 const uint do_nothing_timeout = 5000;
00059 const double MIN_SPEED_TO_FLY = 15.0;
00060
00061
00062 #ifdef DEBUG
00063
00064 #endif
00065 #ifdef ANIME_VITE
00066 const uint ANIM_PAUSE_MIN = 100;
00067 const uint ANIM_PAUSE_MAX = 150;
00068 #else
00069 const uint ANIM_PAUSE_MIN = 5*1000;
00070 const uint ANIM_PAUSE_MAX = 60*1000;
00071 #endif
00072
00073 #ifdef DEBUG
00074
00075 #endif
00076
00077
00078 const uint LARG_ENERGIE = 40;
00079 const uint HAUT_ENERGIE = 6;
00080
00081 Body * Character::GetBody() const
00082 {
00083 return body;
00084 }
00085
00086 void Character::SetBody(Body* char_body)
00087 {
00088 body = char_body;
00089 body->SetOwner(this);
00090 SetClothe("normal");
00091 SetMovement("walk");
00092
00093 SetDirection(randomSync.GetBool() ? Body::DIRECTION_LEFT : Body::DIRECTION_RIGHT);
00094 body->SetFrame(0);
00095 SetSize(body->GetSize());
00096 }
00097
00098 Character::Character (Team& my_team, const std::string &name, Body *char_body) :
00099 PhysicalObj("character"), m_team(my_team), bubble_engine(500)
00100 {
00101 SetCollisionModel(false, true, true);
00102
00103 assert(char_body);
00104 SetBody(char_body);
00105
00106 step_sound_played = true;
00107 pause_bouge_dg = 0;
00108 previous_strength = 0;
00109 channel_step = -1;
00110 hidden = false;
00111 do_nothing_time = 0;
00112 m_allow_negative_y = true;
00113 animation_time = Time::GetInstance()->Read() + randomObj.GetLong(ANIM_PAUSE_MIN,ANIM_PAUSE_MAX);
00114 prepare_shoot = false;
00115 back_jumping = false;
00116 death_explosion = true;
00117 firing_angle = 0.;
00118
00119
00120 damage_other_team = 0;
00121 damage_own_team = 0;
00122 max_damage = 0;
00123 current_total_damage = 0;
00124
00125
00126 disease_damage_per_turn = 0;
00127 disease_duration = 0;
00128
00129
00130 survivals = 0;
00131
00132 character_name = name;
00133
00134 ResetConstants();
00135
00136
00137 if (Config::GetInstance()->GetDisplayNameCharacter())
00138 name_text = new Text(character_name);
00139 else
00140 name_text = NULL;
00141
00142
00143 life_points = GameMode::GetInstance()->character.init_energy;
00144 energy_bar.InitVal (GameMode::GetInstance()->character.init_energy,
00145 0,
00146 GameMode::GetInstance()->character.init_energy);
00147 energy_bar.InitPos (0,0, LARG_ENERGIE, HAUT_ENERGIE);
00148 energy_bar.SetBorderColor( black_color );
00149 energy_bar.SetBackgroundColor( gray_color );
00150
00151 SetEnergy(GameMode::GetInstance()->character.init_energy);
00152 lost_energy = 0;
00153 MSG_DEBUG("character", "Load character %s", character_name.c_str());
00154 }
00155
00156 Character::Character (const Character& acharacter) : PhysicalObj(acharacter),
00157 m_team(acharacter.m_team),
00158 bubble_engine(250)
00159 {
00160 character_name = acharacter.character_name;
00161 step_sound_played = acharacter.step_sound_played;
00162 prepare_shoot = acharacter.prepare_shoot;
00163 back_jumping = acharacter.back_jumping;
00164 damage_other_team = acharacter.damage_other_team;
00165 damage_own_team = acharacter.damage_own_team;
00166 max_damage = acharacter.max_damage;
00167 death_explosion = acharacter.death_explosion;
00168 firing_angle = acharacter.firing_angle;
00169 current_total_damage = acharacter.current_total_damage;
00170 energy_bar = acharacter.energy_bar;
00171 survivals = acharacter.survivals;
00172 pause_bouge_dg = acharacter.pause_bouge_dg;
00173 do_nothing_time = acharacter.do_nothing_time;
00174 animation_time = acharacter.animation_time;
00175 lost_energy = acharacter.lost_energy;
00176 hidden = acharacter.hidden;
00177 channel_step = acharacter.channel_step ;
00178 previous_strength = acharacter.previous_strength;
00179 disease_damage_per_turn = acharacter.disease_damage_per_turn;
00180 disease_duration = acharacter.disease_duration;
00181
00182 if (acharacter.body)
00183 SetBody(new Body(acharacter.body));
00184 if(acharacter.name_text)
00185 name_text = new Text(*acharacter.name_text);
00186 }
00187
00188 Character::~Character()
00189 {
00190 MSG_DEBUG("character", "Unload character %s", character_name.c_str());
00191 if(body)
00192 delete body;
00193 if(name_text)
00194 delete name_text;
00195 body = NULL;
00196 name_text = NULL;
00197 }
00198
00199 void Character::SignalDrowning()
00200 {
00201 SetEnergy(0);
00202 SetMovement("drowned");
00203
00204 jukebox.Play (GetTeam().GetSoundProfile(),"sink");
00205 GameLoop::GetInstance()->SignalCharacterDeath (this);
00206 }
00207
00208
00209 void Character::SignalGhostState (bool was_dead)
00210 {
00211
00212 ActiveCharacter().MadeDamage(GetEnergy(), *this);
00213
00214 MSG_DEBUG("character", "ghost");
00215
00216
00217 if (!was_dead) GameLoop::GetInstance()->SignalCharacterDeath (this);
00218 }
00219
00220 void Character::SetDirection (Body::Direction_t nv_direction)
00221 {
00222 body->SetDirection(nv_direction);
00223 uint l,r,t,b;
00224 body->GetTestRect(l,r,t,b);
00225 SetTestRect(l,r,t,b);
00226 m_team.crosshair.Refresh(GetFiringAngle());
00227 }
00228
00229 void Character::DrawEnergyBar(int dy)
00230 {
00231 if( IsDead() )
00232 return;
00233
00234 energy_bar.DrawXY( Point2i( GetCenterX() - energy_bar.GetWidth() / 2, GetY() + dy)
00235 - camera.GetPosition() );
00236 }
00237
00238 void Character::DrawName (int dy) const
00239 {
00240 if(IsDead()) return;
00241
00242 const int x = GetCenterX();
00243 const int y = GetY()+dy;
00244
00245 if (Config::GetInstance()->GetDisplayNameCharacter())
00246 {
00247 name_text->DrawCenterTopOnMap(x,y);
00248 }
00249 }
00250
00251 void Character::SetEnergyDelta (int delta, bool do_report)
00252 {
00253
00254 if (IsDead()) return;
00255
00256
00257 if (do_report)
00258 ActiveCharacter().MadeDamage(-delta, *this);
00259
00260 uint saved_life_points = GetEnergy();
00261
00262
00263 SetEnergy(GetEnergy() + delta);
00264
00265 if(IsDead()) return;
00266
00267
00268 if (delta < 0) {
00269 lost_energy += (int)GetEnergy() - (int)saved_life_points;
00270
00271 if ( lost_energy > -33 )
00272 jukebox.Play (GetTeam().GetSoundProfile(), "injured_light");
00273 else if ( lost_energy > -66 )
00274 jukebox.Play (GetTeam().GetSoundProfile(), "injured_medium");
00275 else
00276 jukebox.Play (GetTeam().GetSoundProfile(), "injured_high");
00277 } else
00278 lost_energy = 0;
00279
00280
00281 if ( !IsActiveCharacter() && ActiveTeam().IsSameAs(m_team) )
00282 jukebox.Play (GetTeam().GetSoundProfile(), "friendly_fire");
00283 }
00284
00285 void Character::SetEnergy(int new_energy)
00286 {
00287 if(!network.IsLocal())
00288 {
00289 if( m_alive == DEAD && new_energy > 0)
00290 {
00291 printf("%s have been resurrected\n", GetName().c_str());
00292 m_alive = ALIVE;
00293 SetClothe("normal");
00294 SetMovement("walk");
00295 }
00296 }
00297
00298
00299 if(IsDead()) return;
00300
00301
00302 long energy = BorneLong((int)new_energy, 0,
00303 GameMode::GetInstance()->character.max_energy);
00304 life_points = energy;
00305 energy_bar.Actu (energy);
00306
00307
00308 if (GetEnergy() <= 0) Die();
00309 }
00310
00311 bool Character::GotInjured() const
00312 {
00313 return lost_energy < 0;
00314 }
00315
00316 void Character::DisableDeathExplosion()
00317 {
00318 death_explosion = false;
00319 }
00320
00321 void Character::Die()
00322 {
00323 assert (m_alive == ALIVE || m_alive == DROWNED);
00324
00325 MSG_DEBUG("character", "Dying");
00326
00327 if (m_alive != DROWNED)
00328 {
00329 m_alive = DEAD;
00330
00331 SetEnergy(0);
00332
00333 jukebox.Play(GetTeam().GetSoundProfile(),"death");
00334 SetClothe("dead");
00335 SetMovement("dead");
00336
00337 if(death_explosion)
00338 ApplyExplosion(GetCenter(), GameMode::GetInstance()->death_explosion_cfg);
00339 assert(IsDead());
00340
00341
00342 GameLoop::GetInstance()->SignalCharacterDeath (this);
00343 }
00344 }
00345
00346 bool Character::IsDiseased() const
00347 {
00348 return disease_duration > 0 && !IsDead();
00349 }
00350
00351 void Character::SetDiseaseDamage(const uint damage_per_turn, const uint duration)
00352 {
00353 disease_damage_per_turn = damage_per_turn;
00354 disease_duration = duration;
00355 }
00356
00357
00358 uint Character::GetDiseaseDamage() const
00359 {
00360 if (disease_damage_per_turn < static_cast<uint>(GetEnergy()))
00361 return disease_damage_per_turn;
00362 return GetEnergy() - 1;
00363 }
00364
00365 uint Character::GetDiseaseDuration() const
00366 {
00367 return disease_duration;
00368 }
00369
00370 void Character::DecDiseaseDuration()
00371 {
00372 if (disease_duration > 0) disease_duration--;
00373 else disease_damage_per_turn = 0;
00374 }
00375
00376 void Character::Draw()
00377 {
00378 if (hidden) return;
00379
00380
00381 if (IsGhost()) return;
00382
00383 bool dessine_perte = (lost_energy != 0);
00384 if ((&ActiveCharacter() == this
00385 && GameLoop::GetInstance()->ReadState() != GameLoop::END_TURN)
00386
00387 || IsDead()
00388 )
00389 dessine_perte = false;
00390
00391 if(GameLoop::GetInstance()->ReadState() == GameLoop::END_TURN && body->IsWalking())
00392 body->ResetWalk();
00393
00394 if(Time::GetInstance()->Read() > animation_time && &ActiveCharacter()!=this && !IsDead()
00395 && body->GetMovement().substr(0,9) != "animation"
00396 && body->GetClothe().substr(0,9) != "animation")
00397 {
00398 body->PlayAnimation();
00399 animation_time = Time::GetInstance()->Read() + body->GetMovementDuration() + randomObj.GetLong(ANIM_PAUSE_MIN,ANIM_PAUSE_MAX);
00400 }
00401
00402
00403 if(&ActiveCharacter() == this
00404 &&(body->GetMovement().substr(0,9) == "animation"
00405 || body->GetClothe().substr(0,9) == "animation"
00406 || body->GetClothe() == "black"))
00407 {
00408 SetClothe("normal");
00409 SetMovement("walk");
00410 }
00411
00412
00413 double n, a;
00414 GetSpeed(n, a);
00415 if(body->GetMovement() == "fly" && n < MIN_SPEED_TO_FLY)
00416 SetMovement("walk");
00417
00418
00419 Point2i pos = GetPosition();
00420
00421 if(prepare_shoot)
00422 {
00423 body->Build();
00424 if(body->GetMovement() != "weapon-" + ActiveTeam().GetWeapon().GetID() + "-begin-shoot")
00425 {
00426
00427 DoShoot();
00428 prepare_shoot = false;
00429 }
00430 }
00431
00432 body->Draw(pos);
00433
00434
00435 int dy = -ESPACE;
00436 bool est_ver_actif = (this == &ActiveCharacter());
00437 Config * config = Config::GetInstance();
00438 bool display_energy = config->GetDisplayEnergyCharacter();
00439 display_energy &= !est_ver_actif || (GameLoop::GetInstance()->ReadState() != GameLoop::PLAYING);
00440 display_energy |= dessine_perte;
00441 display_energy &= !IsDead();
00442 if (display_energy)
00443 {
00444 dy -= HAUT_ENERGIE;
00445 DrawEnergyBar (dy);
00446 dy -= ESPACE;
00447 }
00448
00449
00450 if (config->GetDisplayNameCharacter() && !est_ver_actif)
00451 {
00452 dy -= HAUT_FONT_MIX;
00453 DrawName (dy);
00454 dy -= ESPACE;
00455 }
00456
00457
00458 if (dessine_perte)
00459 {
00460 std::ostringstream ss;
00461 ss << lost_energy;
00462 dy -= HAUT_FONT_MIX;
00463 (*Font::GetInstance(Font::FONT_SMALL)).WriteCenterTop (
00464 GetPosition() - camera.GetPosition() + Point2i( GetWidth()/2, dy),
00465 ss.str(), white_color);
00466 }
00467
00468 }
00469
00470 void Character::Jump(double strength, double angle )
00471 {
00472 do_nothing_time = Time::GetInstance()->Read();
00473
00474 if (!CanJump() && ActiveTeam().IsLocal()) return;
00475
00476 SetMovement("jump");
00477
00478
00479 if (GetDirection() == Body::DIRECTION_LEFT) angle = InverseAngle(angle);
00480 SetSpeed (strength, angle);
00481 }
00482
00483 void Character::Jump()
00484 {
00485 MSG_DEBUG("character", "Jump");
00486 jukebox.Play (ActiveTeam().GetSoundProfile(), "jump");
00487 Jump(GameMode::GetInstance()->character.jump_strength,
00488 GameMode::GetInstance()->character.jump_angle);
00489 }
00490
00491 void Character::HighJump()
00492 {
00493 MSG_DEBUG("character", "HighJump");
00494 jukebox.Play (ActiveTeam().GetSoundProfile(), "superjump");
00495 Jump(GameMode::GetInstance()->character.super_jump_strength,
00496 GameMode::GetInstance()->character.super_jump_angle);
00497 }
00498
00499 void Character::BackJump()
00500 {
00501 MSG_DEBUG("character", "BackJump");
00502 back_jumping = true;
00503 jukebox.Play (ActiveTeam().GetSoundProfile(), "jump");
00504 Jump(GameMode::GetInstance()->character.back_jump_strength,
00505 GameMode::GetInstance()->character.back_jump_angle);
00506 }
00507
00508 void Character::PrepareShoot()
00509 {
00510 SetMovementOnce("weapon-" + ActiveTeam().GetWeapon().GetID() + "-begin-shoot");
00511 if(body->GetMovement() != "weapon-" + ActiveTeam().GetWeapon().GetID() + "-begin-shoot")
00512 {
00513
00514 DoShoot();
00515 }
00516 else
00517 prepare_shoot = true;
00518 }
00519
00520 void Character::DoShoot()
00521 {
00522 SetMovementOnce("weapon-" + ActiveTeam().GetWeapon().GetID() + "-end-shoot");
00523 ActiveTeam().AccessWeapon().Shoot();
00524 }
00525
00526 void Character::HandleShoot(Keyboard::Key_Event_t event_type)
00527 {
00528 if(prepare_shoot)
00529 return;
00530
00531 switch (event_type) {
00532 case Keyboard::KEY_PRESSED:
00533 if (ActiveTeam().GetWeapon().max_strength == 0)
00534 ActiveTeam().GetWeapon().NewActionShoot();
00535 else
00536 if ( (GameLoop::GetInstance()->ReadState() == GameLoop::PLAYING)
00537 && ActiveTeam().GetWeapon().IsReady() )
00538 ActiveTeam().AccessWeapon().InitLoading();
00539 break ;
00540
00541 case Keyboard::KEY_RELEASED:
00542 if (ActiveTeam().GetWeapon().IsLoading())
00543 ActiveTeam().GetWeapon().NewActionShoot();
00544 break ;
00545
00546 case Keyboard::KEY_REFRESH:
00547 if ( ActiveTeam().GetWeapon().IsLoading() )
00548 {
00549
00550 if (ActiveTeam().GetWeapon().ReadStrength() >=
00551 ActiveTeam().GetWeapon().max_strength)
00552 ActiveTeam().GetWeapon().NewActionShoot();
00553 else
00554 {
00555
00556 ActiveTeam().AccessWeapon().UpdateStrength();
00557 }
00558 }
00559 break ;
00560
00561 default:
00562 break ;
00563 }
00564 }
00565
00566 void Character::HandleKeyEvent(Action::Action_t action, Keyboard::Key_Event_t event_type)
00567 {
00568
00569 if (GameLoop::GetInstance()->ReadState() == GameLoop::END_TURN)
00570 return ;
00571
00572 if (ActiveCharacter().IsDead())
00573 return;
00574
00575 if (action == Action::ACTION_SHOOT)
00576 {
00577 HandleShoot(event_type);
00578 do_nothing_time = Time::GetInstance()->Read();
00579 CharacterCursor::GetInstance()->Hide();
00580 return;
00581 }
00582
00583 ActionHandler * action_handler = ActionHandler::GetInstance();
00584
00585 if(action <= Action::ACTION_NEXT_CHARACTER)
00586 {
00587 switch (event_type)
00588 {
00589 case Keyboard::KEY_REFRESH:
00590 switch (action) {
00591 case Action::ACTION_MOVE_LEFT:
00592 if(ActiveCharacter().IsImmobile())
00593 MoveCharacterLeft(ActiveCharacter());
00594 HideGameInterface();
00595 return;
00596 case Action::ACTION_MOVE_RIGHT:
00597 if(ActiveCharacter().IsImmobile())
00598 MoveCharacterRight(ActiveCharacter());
00599 HideGameInterface();
00600 return;
00601 default:
00602 break ;
00603 }
00604
00605 case Keyboard::KEY_PRESSED:
00606 switch (action)
00607 {
00608 case Action::ACTION_UP:
00609 HideGameInterface();
00610 if(ActiveCharacter().IsImmobile())
00611 {
00612 if (ActiveTeam().crosshair.enable)
00613 {
00614 do_nothing_time = Time::GetInstance()->Read();
00615 CharacterCursor::GetInstance()->Hide();
00616 action_handler->NewAction (new Action(Action::ACTION_UP));
00617 }
00618 }
00619 break ;
00620
00621 case Action::ACTION_DOWN:
00622 HideGameInterface();
00623 if(ActiveCharacter().IsImmobile())
00624 {
00625 if (ActiveTeam().crosshair.enable)
00626 {
00627 do_nothing_time = Time::GetInstance()->Read();
00628 CharacterCursor::GetInstance()->Hide();
00629 action_handler->NewAction (new Action(Action::ACTION_DOWN));
00630 }
00631 }
00632 break ;
00633 case Action::ACTION_MOVE_LEFT:
00634 case Action::ACTION_MOVE_RIGHT:
00635 HideGameInterface();
00636 InitMouvementDG(PAUSE_MOVEMENT);
00637 body->StartWalk();
00638 break;
00639
00640
00641
00642 case Action::ACTION_JUMP:
00643 HideGameInterface();
00644 if(ActiveCharacter().IsImmobile())
00645 action_handler->NewAction (new Action(Action::ACTION_JUMP));
00646 return ;
00647 case Action::ACTION_HIGH_JUMP:
00648 HideGameInterface();
00649 if(ActiveCharacter().IsImmobile())
00650 action_handler->NewAction (new Action(Action::ACTION_HIGH_JUMP));
00651 return ;
00652 case Action::ACTION_BACK_JUMP:
00653 HideGameInterface();
00654 if(ActiveCharacter().IsImmobile())
00655 action_handler->NewAction (new Action(Action::ACTION_BACK_JUMP));
00656 return ;
00657 default:
00658 break;
00659 }
00660 break;
00661
00662 case Keyboard::KEY_RELEASED:
00663 switch (action) {
00664 case Action::ACTION_MOVE_LEFT:
00665 case Action::ACTION_MOVE_RIGHT:
00666 body->StopWalk();
00667 SendCharacterPosition();
00668 break;
00669 default:
00670 break;
00671 }
00672 default: break;
00673 }
00674 }
00675 }
00676
00677 void Character::Refresh()
00678 {
00679 if (IsGhost()) return;
00680
00681 UpdatePosition ();
00682 Time * global_time = Time::GetInstance();
00683
00684 if(IsDiseased())
00685 {
00686 Point2i bubble_pos = GetPosition();
00687 if(GetDirection() == Body::DIRECTION_LEFT)
00688 bubble_pos.x += GetWidth();
00689 bubble_engine.AddPeriodic(bubble_pos, particle_ILL_BUBBLE, false,
00690 - M_PI_2 - (float)GetDirection() * M_PI_4, 20.0);
00691 }
00692
00693 if( IsActiveCharacter() && GameLoop::GetInstance()->ReadState() == GameLoop::PLAYING)
00694 {
00695 if(do_nothing_time + do_nothing_timeout < global_time->Read())
00696 CharacterCursor::GetInstance()->FollowActiveCharacter();
00697 }
00698
00699 if(body->IsWalking())
00700 {
00701
00702 uint frame_nbr = body->GetFrameCount();
00703 uint cur = body->GetFrame();
00704 frame_nbr /= 2;
00705 cur %= frame_nbr;
00706
00707 if(cur < frame_nbr / 2 && !step_sound_played)
00708 {
00709 step_sound_played = true;
00710 jukebox.Play (GetTeam().GetSoundProfile(),"step");
00711 }
00712
00713 if(cur > frame_nbr / 2)
00714 step_sound_played = false;
00715 }
00716
00717 if(back_jumping)
00718 {
00719 assert(&ActiveCharacter() == this);
00720 double rotation;
00721 static double speed_init = GameMode::GetInstance()->character.back_jump_strength *
00722 sin(GameMode::GetInstance()->character.back_jump_angle);
00723
00724 Point2d speed;
00725 GetSpeedXY(speed);
00726 rotation = -M_PI * speed.y / speed_init;
00727 body->SetRotation(rotation);
00728 }
00729 }
00730
00731
00732 void Character::PrepareTurn()
00733 {
00734 HandleMostDamage();
00735 lost_energy = 0;
00736 pause_bouge_dg = Time::GetInstance()->Read();
00737 }
00738
00739 const Team &Character::GetTeam() const
00740 {
00741 return m_team;
00742 }
00743
00744 bool Character::MouvementDG_Autorise() const
00745 {
00746 if (!IsImmobile() || IsFalling()) return false;
00747 return pause_bouge_dg < Time::GetInstance()->Read();
00748 }
00749
00750 bool Character::CanJump() const
00751 {
00752 return MouvementDG_Autorise();
00753 }
00754
00755 void Character::InitMouvementDG(uint pause)
00756 {
00757 do_nothing_time = Time::GetInstance()->Read();
00758 CharacterCursor::GetInstance()->Hide();
00759 step_sound_played = true;
00760 pause_bouge_dg = Time::GetInstance()->Read()+pause;
00761 }
00762
00763 bool Character::CanStillMoveDG(uint pause)
00764 {
00765 if(pause_bouge_dg+pause<Time::GetInstance()->Read())
00766 {
00767 pause_bouge_dg += pause;
00768 return true;
00769 }
00770 return false;
00771 }
00772
00773
00774 void Character::SignalCollision()
00775 {
00776
00777 if (IsDead()) return;
00778
00779 pause_bouge_dg = Time::GetInstance()->Read();
00780 back_jumping = false;
00781 double norme, degat;
00782 Point2d speed_vector;
00783 GameMode * game_mode = GameMode::GetInstance();
00784 SetMovement("walk");
00785 SetMovementOnce("soft-land");
00786
00787 GetSpeedXY (speed_vector);
00788 norme = speed_vector.Norm();
00789 if (norme > game_mode->safe_fall && speed_vector.y>0.0)
00790 {
00791 norme -= game_mode->safe_fall;
00792 degat = norme * game_mode->damage_per_fall_unit;
00793 SetEnergyDelta (-(int)degat);
00794 GameLoop::GetInstance()->SignalCharacterDamage(this);
00795 SetMovement("walk");
00796 SetMovementOnce("hard-land");
00797 }
00798 }
00799
00800 void Character::SignalExplosion()
00801 {
00802 if(IsDead()) return;
00803
00804 double n, a;
00805 GetSpeed(n, a);
00806 SetRebounding(true);
00807 if(n > MIN_SPEED_TO_FLY)
00808 SetMovement("fly");
00809 else
00810 {
00811 SetClotheOnce("black");
00812 SetMovementOnce("black");
00813 if(body->GetClothe() == "black"
00814 && body->GetMovement() != "black")
00815 std::cerr << "Error: the clothe \"black\" of the character " << GetName() << " is set, but the skin have no \"black\" movement !!!" << std::endl;
00816 }
00817
00818 if (IsActiveCharacter()) {
00819 ActiveTeam().AccessWeapon().Deselect();
00820
00821 ActiveTeam().AccessWeapon().Select();
00822
00823 GameLoop::GetInstance()->SignalCharacterDamage(this);
00824 }
00825 }
00826
00827 Body::Direction_t Character::GetDirection() const
00828 {
00829 return body->GetDirection();
00830 }
00831
00832
00833 void Character::StopPlaying()
00834 {
00835 if(IsDead()) return;
00836 SetClothe("normal");
00837 SetMovement("walk");
00838 body->ResetWalk();
00839 SetRebounding(true);
00840 }
00841
00842
00843 void Character::StartPlaying()
00844 {
00845 assert (!IsGhost());
00846 SetWeaponClothe();
00847 ActiveTeam().crosshair.Draw();
00848
00849 ShowGameInterface();
00850 m_team.crosshair.Refresh(GetFiringAngle());
00851 }
00852
00853 bool Character::IsActiveCharacter() const
00854 {
00855 return this == &ActiveCharacter();
00856 }
00857
00858
00859 const Point2i & Character::GetHandPosition() const {
00860 return body->GetHandPosition();
00861 }
00862
00863 double Character::GetFiringAngle() const {
00864 if (GetDirection() == Body::DIRECTION_LEFT)
00865 return InverseAngleRad(firing_angle);
00866 return firing_angle;
00867 }
00868
00869 double Character::GetAbsFiringAngle() const {
00870 return firing_angle;
00871 }
00872
00873 void Character::SetFiringAngle(double angle) {
00874
00875
00876
00877
00878 angle = BorneDouble(angle, -(ActiveTeam().GetWeapon().GetMaxAngle()),
00879 -(ActiveTeam().GetWeapon().GetMinAngle()));
00880 firing_angle = angle;
00881 m_team.crosshair.Refresh(GetFiringAngle());
00882 }
00883
00884 void Character::AddFiringAngle(double angle) {
00885 SetFiringAngle(firing_angle + angle);
00886 }
00887
00888 void Character::HandleMostDamage()
00889 {
00890 if (current_total_damage > max_damage)
00891 {
00892 max_damage = current_total_damage;
00893 }
00894 #ifdef DEBUG_STATS
00895 std::cerr << m_name << " most damage: " << max_damage << std::endl;
00896 #endif
00897 current_total_damage = 0;
00898 }
00899
00900 void Character::Hide() { hidden = true; }
00901 void Character::Show() { hidden = false; }
00902
00903 void Character::MadeDamage(const int Dmg, const Character &other)
00904 {
00905 if (m_team.IsSameAs(other.GetTeam()))
00906 {
00907 #ifdef DEBUG_STATS
00908 std::cerr << m_name << " damaged own team with " << Dmg << std::endl;
00909 #endif
00910 if (Character::IsSameAs(other))
00911 damage_own_team += Dmg;
00912 }
00913 else
00914 {
00915 #ifdef DEBUG_STATS
00916 std::cerr << m_name << " damaged other team with " << Dmg << std::endl;
00917 #endif
00918 damage_other_team += Dmg;
00919 }
00920
00921 current_total_damage += Dmg;
00922 }
00923
00924 void Character::SetWeaponClothe()
00925 {
00926 SetClothe("weapon-" + m_team.GetWeapon().GetID());
00927 if(body->GetClothe() != "weapon-" + m_team.GetWeapon().GetID())
00928 SetClothe("normal");
00929 }
00930
00931 void Character::SetMovement(std::string name)
00932 {
00933 if(IsDead()) return;
00934 MSG_DEBUG("body","Character %s -> SetMovement : %s",character_name.c_str(),name.c_str());
00935 body->SetMovement(name);
00936 uint l,r,t,b;
00937 body->GetTestRect(l,r,t,b);
00938 SetTestRect(l,r,t,b);
00939 }
00940
00941 void Character::SetMovementOnce(std::string name)
00942 {
00943 if(IsDead()) return;
00944 MSG_DEBUG("body","Character %s -> SetMovementOnce : %s",character_name.c_str(),name.c_str());
00945 body->SetMovementOnce(name);
00946 uint l,r,t,b;
00947 body->GetTestRect(l,r,t,b);
00948 SetTestRect(l,r,t,b);
00949 }
00950
00951 void Character::SetClothe(std::string name)
00952 {
00953 if(IsDead() && name!="dead") return;
00954 MSG_DEBUG("body","Character %s -> SetClothe : %s",character_name.c_str(),name.c_str());
00955 body->SetClothe(name);
00956 }
00957
00958 void Character::SetClotheOnce(std::string name)
00959 {
00960 if(IsDead()) return;
00961 MSG_DEBUG("body","Character %s -> SetClotheOnce : %s",character_name.c_str(),name.c_str());
00962 body->SetClotheOnce(name);
00963 }
00964
00965 uint Character::GetTeamIndex()
00966 {
00967 uint index = 0;
00968 teams_list.FindPlayingById( GetTeam().GetId(), index);
00969 return index;
00970 }
00971
00972 uint Character::GetCharacterIndex()
00973 {
00974 uint index = 0;
00975 for(Team::iterator it = m_team.begin();
00976 it != m_team.end() ; ++it, ++index )
00977 {
00978 if( &(*it) == this)
00979 return index;
00980 }
00981 assert(false);
00982 return 0;
00983 }