diff --git a/neo/doom3/game/bots/Bot.cpp b/neo/doom3/game/bots/Bot.cpp index 1a164236..97692590 100644 --- a/neo/doom3/game/bots/Bot.cpp +++ b/neo/doom3/game/bots/Bot.cpp @@ -30,6 +30,19 @@ static bool BotDirectPathIsClear( int passEntityNum, const idVec3& from, const i return trace.fraction >= 0.95f; } +static idAngles BotTurnTowardAngles( const idAngles& currentAngles, const idAngles& desiredAngles, float maxTurn ) +{ + idAngles result = currentAngles; + for( int i = 0; i < 2; i++ ) + { + float delta = idMath::AngleDelta( desiredAngles[i], currentAngles[i] ); + delta = idMath::ClampFloat( -maxTurn, maxTurn, delta ); + result[i] = idMath::AngleMod( currentAngles[i] + delta ); + } + result[ROLL] = 0.0f; + return result; +} + static idVec3 bot_stuckOrigin[MAX_CLIENTS]; static float bot_stuckTime[MAX_CLIENTS]; static bool bot_stuckInit[MAX_CLIENTS]; @@ -226,6 +239,7 @@ rvmBot::Think void rvmBot::BotMoveToGoalOrigin(idVec3 goalOrigin) { idVec3 moveDir = goalOrigin - GetPhysics()->GetOrigin(); + const float goalDist = moveDir.Length(); // Usercmd forward/right movement is horizontal. Feeding pitch or a view-origin // z delta into the movement vector makes the bot under-steer, drift, or push @@ -239,6 +253,40 @@ void rvmBot::BotMoveToGoalOrigin(idVec3 goalOrigin) } else { + if( bs.enemy < 0 && goalDist > 96.0f ) + { + if( bs.move_wander_time < Bot_Time() ) + { + bs.move_wander_time = Bot_Time() + idMath::FRandRange( 0.75f, 1.8f ); + bs.move_wander_side = rvmBotUtil::crandom(); + if( idMath::Fabs( bs.move_wander_side ) < 0.35f ) + { + bs.move_wander_side = bs.move_wander_side < 0.0f ? -0.35f : 0.35f; + } + } + + idVec3 forwardDir = moveDir; + forwardDir.Normalize(); + idVec3 sideDir( -forwardDir[1], forwardDir[0], 0.0f ); + const float wanderScale = idMath::ClampFloat( 0.0f, 64.0f, goalDist * 0.18f ); + idVec3 wanderedDir = moveDir + sideDir * ( wanderScale * bs.move_wander_side ); + wanderedDir[2] = 0.0f; + + idVec3 testDir = wanderedDir; + if( testDir.Normalize() > 0.0f ) + { + idVec3 testEnd = GetPhysics()->GetOrigin() + testDir * 56.0f; + if( BotDirectPathIsClear( entityNumber, GetPhysics()->GetOrigin() + idVec3( 0.0f, 0.0f, 24.0f ), testEnd + idVec3( 0.0f, 0.0f, 24.0f ) ) ) + { + moveDir = wanderedDir; + } + else + { + bs.move_wander_side = -bs.move_wander_side; + } + } + } + bs.botinput.dir = moveDir; bs.botinput.dir.Normalize(); bs.botinput.speed = pm_runspeed.GetInteger(); @@ -252,7 +300,8 @@ void rvmBot::BotMoveToGoalOrigin(idVec3 goalOrigin) } else if( moveDir.LengthSqr() > Square( 1.0f ) ) { - bs.botinput.viewangles = idAngles( 0.0f, moveDir.ToYaw(), 0.0f ); + const idAngles desiredAngles( 0.0f, moveDir.ToYaw(), 0.0f ); + bs.botinput.viewangles = BotTurnTowardAngles( viewAngles, desiredAngles, 22.0f ); bs.viewangles = bs.botinput.viewangles; } else diff --git a/neo/doom3/game/bots/Bot.h b/neo/doom3/game/bots/Bot.h index 99edb072..a877b03c 100644 --- a/neo/doom3/game/bots/Bot.h +++ b/neo/doom3/game/bots/Bot.h @@ -765,6 +765,8 @@ struct bot_state_t attackcrouch_time = 0; attackstrafe_time = 0; attackjump_time = 0; + move_wander_time = 0; + move_wander_side = 0.0f; firethrottleshoot_time = 0; chase_time = 0; thinktime = 0; @@ -799,6 +801,8 @@ struct bot_state_t float attackcrouch_time; float attackstrafe_time; float attackchase_time; + float move_wander_time; + float move_wander_side; float firethrottlewait_time; float firethrottleshoot_time; float nbg_time; //nearby goal time diff --git a/neo/doom3/game/bots/BotAI.cpp b/neo/doom3/game/bots/BotAI.cpp index 42ad45c2..2c7bae16 100644 --- a/neo/doom3/game/bots/BotAI.cpp +++ b/neo/doom3/game/bots/BotAI.cpp @@ -335,9 +335,11 @@ void rvmBot::BotChooseWeapon(bot_state_t* bs) if (bs->weaponnum != newweaponnum) { bs->weaponchange_time = Bot_Time(); + bs->botinput.lastWeaponNum = -1; } bs->weaponnum = newweaponnum; bs->botinput.weapon = bs->weaponnum; + SelectWeapon(bs->weaponnum, false); } diff --git a/neo/doom3/game/bots/Bot_goal.cpp b/neo/doom3/game/bots/Bot_goal.cpp index 241620aa..1176f59c 100644 --- a/neo/doom3/game/bots/Bot_goal.cpp +++ b/neo/doom3/game/bots/Bot_goal.cpp @@ -413,23 +413,13 @@ static const char* Bot_ItemWeightAlias( const char* classname ) static const itemWeightAlias_t aliases[] = { - { "weapon_machinegun_mp", "weapon_machinegun" }, - { "weapon_shotgun_mp", "weapon_shotgun" }, - { "weapon_rocketlauncher_mp", "weapon_rocketlauncher" }, - { "weapon_plasmagun_mp", "weapon_plasmagun" }, - { "weapon_bfg_mp", "weapon_bfg" }, { "weapon_grenadelauncher", "weapon_rocketlauncher" }, - { "weapon_grenadelauncher_mp", "weapon_rocketlauncher" }, { "weapon_lightning", "weapon_plasmagun" }, - { "weapon_lightning_mp", "weapon_plasmagun" }, { "weapon_railgun", "weapon_rocketlauncher" }, - { "weapon_railgun_mp", "weapon_rocketlauncher" }, { "weapon_fists", "weapon_pistol" }, { "weapon_grapplinghook", "weapon_chainsaw" }, { "weapon_nailgun", "weapon_chaingun" }, - { "weapon_nailgun_mp", "weapon_chaingun" }, { "weapon_prox_launcher", "weapon_rocketlauncher" }, - { "weapon_prox_launcher_mp", "weapon_rocketlauncher" }, { "team_redobelisk", "item_armor_shard" }, { "team_blueobelisk", "item_armor_shard" }, diff --git a/neo/doom3/game/gamesys/GameTypeInfo.h b/neo/doom3/game/gamesys/GameTypeInfo.h index cb65211d..3b41c5e6 100644 --- a/neo/doom3/game/gamesys/GameTypeInfo.h +++ b/neo/doom3/game/gamesys/GameTypeInfo.h @@ -8464,6 +8464,8 @@ static classVariableInfo_t bot_state_t_typeInfo[] = { { "float", "attackcrouch_time", (intptr_t)(&((bot_state_t *)0)->attackcrouch_time), sizeof( ((bot_state_t *)0)->attackcrouch_time ) }, { "float", "attackstrafe_time", (intptr_t)(&((bot_state_t *)0)->attackstrafe_time), sizeof( ((bot_state_t *)0)->attackstrafe_time ) }, { "float", "attackchase_time", (intptr_t)(&((bot_state_t *)0)->attackchase_time), sizeof( ((bot_state_t *)0)->attackchase_time ) }, + { "float", "move_wander_time", (intptr_t)(&((bot_state_t *)0)->move_wander_time), sizeof( ((bot_state_t *)0)->move_wander_time ) }, + { "float", "move_wander_side", (intptr_t)(&((bot_state_t *)0)->move_wander_side), sizeof( ((bot_state_t *)0)->move_wander_side ) }, { "float", "firethrottlewait_time", (intptr_t)(&((bot_state_t *)0)->firethrottlewait_time), sizeof( ((bot_state_t *)0)->firethrottlewait_time ) }, { "float", "firethrottleshoot_time", (intptr_t)(&((bot_state_t *)0)->firethrottleshoot_time), sizeof( ((bot_state_t *)0)->firethrottleshoot_time ) }, { "float", "nbg_time", (intptr_t)(&((bot_state_t *)0)->nbg_time), sizeof( ((bot_state_t *)0)->nbg_time ) },