/* $Id: tombot.cpp,v 1.10 2005/10/16 17:53:05 pohlt Exp $ */ #include "tombot.hpp" #include "avatar.hpp" #include "global.hpp" #include "event.hpp" #include "vector.hpp" #include "flag.hpp" #include "random.hpp" TomBot::TomBot() : m_event( Event::EMPTY ), m_moveCounter( 0 ), m_groundedCounter( 0 ), m_airborneCounter( 0 ) { m_ID = TOM_BOT; } void TomBot::aimAtClosestAvatar( bool& targetFound, real& dist, real& diffAngle, bool& lineOfSight ) { real minDist2 = 1e+30; Vector dr; std::vector visObj = m_avatar->getVisibleObjects(); Avatar* target = NULL; const Uint8 ownID = m_avatar->getPlayer()->getPlayerOrTeamID(); for( unsigned int i = 0; i < visObj.size(); i++ ) { if( visObj[i]->isAvatar() ) { Avatar* avatar = dynamic_cast( visObj[i] ); if ( avatar && avatar->getPlayer()->getPlayerOrTeamID() != ownID && ! avatar->getBonusPack().hasBonus( BONUS_SHIELD )) { const real dist2 = (m_avatar->getPos() - avatar->getPos()).abs2(); if( dist2 < minDist2 ) { dr = m_avatar->getPos() - avatar->getPos(); minDist2 = dist2; target = avatar; } } } } LOG( 5 ) INFO( "TomBot::aimAtClosestAvatar: dx: %f; dy: %f\n", dr.x, dr.y ); if( ! target ) { LOG( 5 ) INFO( "TomBot::aimAtClosestAvatar: no target found\n" ); targetFound = false; return; } dr += (m_avatar->getVel() - target->getVel()) * (dr.abs()/27.0); m_event.removeAction( Event::LEFT | Event::RIGHT ); if( dr.x > 20.0 ) m_event.addAction( Event::LEFT ); if( dr.x < -20.0 ) m_event.addAction( Event::RIGHT ); const real targetAngle = ATAN2_REAL( FABS_REAL( dr.x ), dr.y ) / M_PI * 180.0, aimingAngle = m_avatar->getAimingAngle(); targetFound = true; diffAngle = FABS_REAL( aimingAngle - targetAngle ); dist = SQRT_REAL( minDist2 ); LOG( 5 ) INFO( "TomBot::aimAtClosestAvatar: targetAngle: %f; aimingAngle: %f\n", targetAngle, aimingAngle ); m_event.removeAction( Event::UP | Event::DOWN ); if( aimingAngle > targetAngle ) { LOG( 5 ) INFO( "TomBot::aimAtClosestAvatar: aiming up\n" ); m_event.addAction( Event::UP ); } else if( aimingAngle < targetAngle ) { LOG( 5 ) INFO( "TomBot::aimAtClosestAvatar: aiming down\n" ); m_event.addAction( Event::DOWN ); } /* // stop shooting to turn around if( (dr.x > 0.0 && m_avatar->isFacingRight()) || (dr.x < -0.0 && ! m_avatar->isFacingRight()) ) return 1e+30; */ int dummy; /* setting and removing the collision rectangle causes async m_avatar->removeCollRect(); target->removeCollRect(); lineOfSight = m_avatar->m_worldPointer->getMap()->testLinePassable( m_avatar->getIntPositionX() , m_avatar->getIntPositionY()+m_avatar->getWeaponPivotDY(), target->getIntPositionX(), target->getIntPositionY()+target->getWeaponPivotDY(), dummy, dummy, dummy, dummy, Flags::INDESTRUCTIBLE ); m_avatar->setCollRect(); target->setCollRect(); */ lineOfSight = m_avatar->m_worldPointer->getMap()->testLinePassable( m_avatar->getIntPosX(), m_avatar->getIntPosY()+m_avatar->getWeaponPivotDY(), target ->getIntPosX(), target ->getIntPosY()+target ->getWeaponPivotDY(), dummy, dummy, dummy, dummy, Flags::OBSTACLE_EARTH ); } void TomBot::update() { bool targetFound, lineOfSight; real dist, diffAngle; aimAtClosestAvatar( targetFound, dist, diffAngle, lineOfSight); const bool shoot = targetFound && lineOfSight && (diffAngle*dist < 1000.0); if( ! targetFound && ! m_avatar->isMovingAny() ) { m_event.removeAction( Event::DIG | Event::JUMP | Event::LEFT | Event::RIGHT ); m_event.addAction( localRnd.getUint32() % 2 ? Event::LEFT : Event::RIGHT ); } Vector position = m_avatar->getPos(); if ( position == m_lastPosition ) { if( m_moveCounter > 15 ) { // start from beginning LOG( 5 ) INFO( "TomBot::update: start from beginning\n" ); m_event.removeAction( Event::JUMP | Event::LEFT | Event::RIGHT ); m_event.addAction( localRnd.getUint32() % 2 ? Event::LEFT : Event::RIGHT ); m_moveCounter = 0; } if( m_moveCounter > 10 ) { // try jumping LOG( 5 ) INFO( "TomBot::update: try jumping\n" ); m_event.removeAction( Event::DIG ); m_event.addAction( Event::JUMP ); } if ( m_moveCounter > 5 ) { // try digging LOG( 5 ) INFO( "TomBot::update: try digging\n" ); m_event.addAction( Event::DIG ); } m_moveCounter++; } else { m_event.removeAction( Event::DIG ); m_lastPosition = position; m_moveCounter = 0; } if( m_avatar->isGrounded() ) { m_groundedCounter++; m_airborneCounter = 0; } else { m_airborneCounter++; m_groundedCounter = 0; } if( m_groundedCounter >= 75 ) { m_event.addAction( Event::JUMP ); } if( m_airborneCounter >= 50 ) { m_event.removeAction( Event::JUMP ); } // shoot whenever possible if( shoot ) { if ( getActiveWeapon()->isReloading() || getActiveWeapon()->isCharging() ) { Uint32 nextWeapon = getActiveWeaponIndex() + 1; if( nextWeapon > 5 ) nextWeapon = 0; m_event.setWeapon( nextWeapon+1 ); } else { m_event.addAction( Event::SHOOT ); } } else m_event.removeAction( Event::SHOOT ); // respawn if dead if ( ! m_avatar->isLiving() ) { LOG( 5 ) INFO( "TomBot: respawn\n" ); m_event.addAction( Event::SPAWN ); } else m_event.removeAction( Event::SPAWN ); }