//============================================================================== // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //============================================================================== //============================================================================== // File: cComputerSoldier.cpp // Project: Shooting Star // Author: Jarmo Hekkanen // Copyrights (c) 2003 2ndPoint ry (www.2ndpoint.fi) //------------------------------------------------------------------------------ // Revision history //============================================================================== //============================================================================== // Includes #include "cComputerSoldier.hpp" #include "Debug.hpp" #include "cWorld.hpp" #include "cOwnable.hpp" #include "cWeapon.hpp" #include //------------------------------------------------------------------------------ // Namespaces using namespace ShootingStar; //============================================================================== //! Constructor cComputerSoldier::cComputerSoldier (PlayerRef player1, PlayerRef player2): cSoldier ("enemy"), mState (State_Patrol), mpTarget (NULL), mTargetLos (false), mPlayer1 (player1), mPlayer2 (player2), mReport (REPORT_DELAY) { SetMaxArmor (0); //SetMaxHealth (50); }; //! Destructor cComputerSoldier::~cComputerSoldier (void) { // Empty }; //! Updating interface void cComputerSoldier::Update (Uint32 deltaTime) { bool report = false; /*if ( mReport < deltaTime ) { report = true; mReport = REPORT_DELAY; } else mReport -= deltaTime; */ switch ( mState ) { case State_Patrol: /*if ( report ) dbgInfo () << GetID () << " Patrolling\n";*/ if ( mPlayer1.IsValid () && mPlayer1->IsAlive () ) { bool los = !cWorld::GetInstance ().CollidesWithWalls (GetPosition (), mPlayer1->GetPosition ()); if ( los ) { cVector2f aimLine = mPlayer1->GetPosition () - GetPosition (); float distance = aimLine.GetLenght (); if ( distance < 500.0f ) { mState = State_Attack; mpTarget = mPlayer1; break; } } } if ( mPlayer2.IsValid () && mPlayer2->IsAlive () ) { bool los = !cWorld::GetInstance ().CollidesWithWalls (GetPosition (), mPlayer2->GetPosition ()); if ( los ) { cVector2f aimLine = mPlayer2->GetPosition () - GetPosition (); float distance = aimLine.GetLenght (); if ( distance < 500.0f ) { mState = State_Attack; mpTarget = mPlayer2; break; } } } ReleaseTrigger (); StopWalking (); break; case State_Attack: { if ( mpTarget == NULL ) { mState = State_Patrol; break; } /*if ( report ) dbgInfo () << GetID () << " Attacking, target: " << mpTarget->GetID () << '\n';*/ if ( !mpTarget->IsAlive () ) { //dbgInfo () << GetID () << " Target is dead: " << mpTarget->GetID () << '\n'; mpTarget = NULL; mState = State_Patrol; break; } cVector2f aimLine = mpTarget->GetPosition () - GetPosition (); mTargetLos = !cWorld::GetInstance ().CollidesWithWalls (GetPosition (), mpTarget->GetPosition ()); float distance = aimLine.GetLenght (); float angle; aimLine.NormalizeSelf (); if ( aimLine.mY > 0.0f ) angle = R2D (acos (aimLine.mX)); else angle = R2D (acos (aimLine.mX)) * -1.0f; TurnTo (angle); if ( distance < 100.0f && mTargetLos ) WalkBackward (); else if ( distance < 300.0f && mTargetLos ) StopWalking (); else if ( distance > 320.0f || !mTargetLos ) WalkForward (); cWeapon *pWeapon = GetCurrentWeapon (); if ( distance < 400.0f && mTargetLos && pWeapon != NULL && pWeapon->GetState () == cWeapon::State_Ready ) PullTrigger (); else ReleaseTrigger (); break; } default: // This should never happen dbg::sentinel (DBG_HERE); break; } // Call base update cSoldier::Update (deltaTime); } void cComputerSoldier::OnHurt (int amount, const cVector2f &direction, ObjectID attacker) { // Call base cSoldier::OnHurt (amount, direction, attacker); if ( attacker == GetID () || attacker == 0 ) return; // dbgInfo () << GetID () << " Under attack, attacker: " << attacker << '\n'; cWorld &world = cWorld::GetInstance (); // Get the attacker object cObject *pObject = world.GetObject (attacker); if ( pObject == NULL ) return; // Check if attacker is ownable (bullet etc.) cOwnable *pOwnable = dynamic_cast (pObject); if ( pOwnable != NULL ) { // We want to attack owner (player) not the bullet pObject = world.GetObject (pOwnable->GetOwner ()); if ( pObject == NULL ) return; } if ( mpTarget != NULL ) { if ( mpTarget->GetID () == pObject->GetID () ) return; if ( dynamic_cast(mpTarget) != NULL && mTargetLos ) return; } // Check if attacker is soldier cSoldier *pSoldier = dynamic_cast (pObject); if ( pSoldier != NULL ) { // It's our new target mpTarget = pSoldier; // Attack!!!! mState = State_Attack; // dbgInfo () << GetID () << " Attacking, target " << mpTarget->GetID () << '\n'; } // Attacker is not soldier, do nothing } //============================================================================== // EOF //==============================================================================