//========= Copyright Valve Corporation, All rights reserved. ============// // tf_bot_engineer_build_teleport_entrance.cpp // Engineer building a teleport entrance right outside of the spawn room // Michael Booth, May 2009 #include "cbase.h" #include "nav_mesh.h" #include "tf_player.h" #include "tf_obj.h" #include "tf_weapon_builder.h" #include "bot/tf_bot.h" #include "bot/behavior/engineer/tf_bot_engineer_build_teleport_entrance.h" #include "bot/behavior/engineer/tf_bot_engineer_move_to_build.h" #include "bot/behavior/tf_bot_get_ammo.h" extern ConVar tf_bot_path_lookahead_range; ConVar tf_bot_max_teleport_entrance_travel( "tf_bot_max_teleport_entrance_travel", "1500", FCVAR_CHEAT, "Don't plant teleport entrances farther than this travel distance from our spawn room" ); ConVar tf_bot_teleport_build_surface_normal_limit( "tf_bot_teleport_build_surface_normal_limit", "0.99", FCVAR_CHEAT, "If the ground normal Z component is less that this value, Engineer bots won't place their entrance teleporter" ); //--------------------------------------------------------------------------------------------- ActionResult< CTFBot > CTFBotEngineerBuildTeleportEntrance::OnStart( CTFBot *me, Action< CTFBot > *priorAction ) { return Continue(); } //--------------------------------------------------------------------------------------------- ActionResult< CTFBot > CTFBotEngineerBuildTeleportEntrance::Update( CTFBot *me, float interval ) { CTeamControlPoint *point = me->GetMyControlPoint(); if ( !point ) { // wait until a control point becomes available return Continue(); } CTFNavArea *myArea = me->GetLastKnownArea(); if ( !myArea ) { return Done( "No nav mesh!" ); } if ( myArea->GetIncursionDistance( me->GetTeamNumber() ) > tf_bot_max_teleport_entrance_travel.GetFloat() ) { return ChangeTo( new CTFBotEngineerMoveToBuild, "Too far from our spawn room to build teleporter entrance" ); } // make sure we go back to our resupply cabinet after planting the teleporter entrance before we move on if ( !me->IsAmmoFull() && CTFBotGetAmmo::IsPossible( me ) ) { return SuspendFor( new CTFBotGetAmmo, "Refilling ammo" ); } CBaseObject *myTeleportEntrance = me->GetObjectOfType( OBJ_TELEPORTER, MODE_TELEPORTER_ENTRANCE ); if ( myTeleportEntrance ) { // successfully built return ChangeTo( new CTFBotEngineerMoveToBuild, "Teleport entrance built" ); } // head towards the control point and build as soon as we can if ( !m_path.IsValid() ) { CTFBotPathCost cost( me, FASTEST_ROUTE ); m_path.Compute( me, point->GetAbsOrigin(), cost ); } m_path.Update( me ); // build CTFWeaponBase *myGun = me->GetActiveTFWeapon(); if ( myGun ) { CTFWeaponBuilder *builder = dynamic_cast< CTFWeaponBuilder * >( myGun ); if ( builder ) { // don't build on slopes - causes player blockages Vector forward; me->EyeVectors( &forward ); const float placementRange = 30.0f; forward *= placementRange; trace_t result; UTIL_TraceLine( me->WorldSpaceCenter() + Vector( forward.x, forward.y, 0.0f ), me->WorldSpaceCenter() + Vector( forward.x, forward.y, -200.0f ), MASK_PLAYERSOLID, me, COLLISION_GROUP_NONE, &result ); if ( builder->IsValidPlacement() && result.DidHit() && result.plane.normal.z > tf_bot_teleport_build_surface_normal_limit.GetFloat() ) { // place it down me->PressFireButton(); } } else { // switch to teleporter builder me->StartBuildingObjectOfType( OBJ_TELEPORTER, MODE_TELEPORTER_ENTRANCE ); } } return Continue(); } //--------------------------------------------------------------------------------------------- EventDesiredResult< CTFBot > CTFBotEngineerBuildTeleportEntrance::OnStuck( CTFBot *me ) { m_path.Invalidate(); return TryContinue(); }