diff --git a/main/navmeshes/co_daimos.nav b/main/navmeshes/co_daimos.nav index 4396f21b..87d6d32b 100644 Binary files a/main/navmeshes/co_daimos.nav and b/main/navmeshes/co_daimos.nav differ diff --git a/main/navmeshes/ns_ayumi.nav b/main/navmeshes/ns_ayumi.nav index a55c09f7..317914b4 100644 Binary files a/main/navmeshes/ns_ayumi.nav and b/main/navmeshes/ns_ayumi.nav differ diff --git a/main/navmeshes/ns_machina.nav b/main/navmeshes/ns_machina.nav index 8049374c..65f6d0f4 100644 Binary files a/main/navmeshes/ns_machina.nav and b/main/navmeshes/ns_machina.nav differ diff --git a/main/navmeshes/ns_nothing.nav b/main/navmeshes/ns_nothing.nav index e39f1b8a..a8690077 100644 Binary files a/main/navmeshes/ns_nothing.nav and b/main/navmeshes/ns_nothing.nav differ diff --git a/main/navmeshes/ns_tanith.nav b/main/navmeshes/ns_tanith.nav index b666b4a1..7dfba37b 100644 Binary files a/main/navmeshes/ns_tanith.nav and b/main/navmeshes/ns_tanith.nav differ diff --git a/main/nsbots.ini b/main/nsbots.ini index 2ba54365..025f46c9 100644 --- a/main/nsbots.ini +++ b/main/nsbots.ini @@ -16,7 +16,8 @@ BotFillTiming=1 # Chance the AI commander will try to relocate to an empty hive at match start # Value is a decimal between 0.0 and 1.0, with 0 being never and 1 being always -RelocationChance=0.1 +# Note that setting relocation chance to 0.0 will also disable ANY relocation at any time +RelocationChance=0.2 ### Skill Settings ### diff --git a/main/source/mod/AvHAIPlayer.cpp b/main/source/mod/AvHAIPlayer.cpp index 9d9e02f2..646b7a27 100644 --- a/main/source/mod/AvHAIPlayer.cpp +++ b/main/source/mod/AvHAIPlayer.cpp @@ -3403,7 +3403,16 @@ bool RegularMarineCombatThink(AvHAIPlayer* pBot) } else { - if (BotReloadWeapons(pBot)) { return true; } + float WeaponClipPercent = GetPlayerCurrentWeaponClipAmmo(pBot->Player) / GetPlayerCurrentWeaponMaxClipAmmo(pBot->Player); + + float ReloadWaitTime = (WeaponClipPercent < 0.2f) ? 3.0f : 5.0f; + + if (DesiredCombatWeapon == WEAPON_MARINE_HMG) { ReloadWaitTime *= 1.5f; } // Wait longer for HMG as we're more likely to be caught with our pants down + + if (TimeSinceLastSeenEnemy > ReloadWaitTime) + { + if (BotReloadWeapons(pBot)) { return true; } + } if (PlayerHasWeapon(pBot->Player, WEAPON_MARINE_GRENADE) || (PlayerHasWeapon(pBot->Player, WEAPON_MARINE_GL) && UTIL_GetPlayerPrimaryWeaponClipAmmo(pBot->Player) > 0)) { @@ -3542,7 +3551,14 @@ bool RegularMarineCombatThink(AvHAIPlayer* pBot) } else { - if (bCanReloadCurrentWeapon && !bEnemyIsRanged && DistToEnemy > sqrf(UTIL_MetresToGoldSrcUnits(10.0f))) + + float WeaponClipPercent = GetPlayerCurrentWeaponClipAmmo(pBot->Player) / GetPlayerCurrentWeaponMaxClipAmmo(pBot->Player); + + float ReloadWaitTime = (WeaponClipPercent < 0.2f) ? 3.0f : 5.0f; + + if (DesiredCombatWeapon == WEAPON_MARINE_HMG) { ReloadWaitTime *= 1.5f; } // Wait longer for HMG as we're more likely to be caught with our pants down + + if (bCanReloadCurrentWeapon && !bEnemyIsRanged && DistToEnemy > sqrf(UTIL_MetresToGoldSrcUnits(10.0f)) && TimeSinceLastSeenEnemy > ReloadWaitTime) { BotReloadWeapons(pBot); } @@ -3555,7 +3571,13 @@ bool RegularMarineCombatThink(AvHAIPlayer* pBot) return true; } - if (bCanReloadCurrentWeapon && DistToEnemy > sqrf(UTIL_MetresToGoldSrcUnits(10.0f)) && TimeSinceLastSeenEnemy > 2.0f) + float WeaponClipPercent = GetPlayerCurrentWeaponClipAmmo(pBot->Player) / GetPlayerCurrentWeaponMaxClipAmmo(pBot->Player); + + float ReloadWaitTime = (WeaponClipPercent < 0.2f) ? 3.0f : 5.0f; + + if (DesiredCombatWeapon == WEAPON_MARINE_HMG) { ReloadWaitTime *= 1.5f; } // Wait longer for HMG as we're more likely to be caught with our pants down + + if (bCanReloadCurrentWeapon && DistToEnemy > sqrf(UTIL_MetresToGoldSrcUnits(10.0f)) && TimeSinceLastSeenEnemy > ReloadWaitTime) { BotReloadWeapons(pBot); return true; @@ -7373,6 +7395,26 @@ void AIPlayerSetSecondaryAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) { AvHAIBuildableStructure ThisStructure = (*it); + if (ThisStructure.StructureType == STRUCTURE_ALIEN_RESTOWER) + { + const AvHAIResourceNode* ResNode = AITAC_GetResourceNodeFromEdict(ThisStructure.edict); + + if (!ResNode) { continue; } + + // Don't defend a res node if it's inside an enemy hive + if (!FNullEnt(ResNode->ParentHive) && ResNode->ParentHive->v.team != BotTeam) { continue; } + + DeployableSearchFilter EnemyStuffFilter; + EnemyStuffFilter.DeployableTeam = EnemyTeam; + EnemyStuffFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; + EnemyStuffFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; + EnemyStuffFilter.DeployableTypes = (STRUCTURE_MARINE_PHASEGATE | STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY); + EnemyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); + + // Don't defend res nodes if marines have built a base there, leads to bots throwing away their lives trying to save a doomed tower + if (AITAC_DeployableExistsAtLocation(ResNode->Location, &EnemyStuffFilter)) { continue; } + } + float ThisDist = vDist2D(pBot->Edict->v.origin, ThisStructure.edict->v.origin); int NumAttackers = AITAC_GetNumPlayersOnTeamWithLOS(EnemyTeam, ThisStructure.Location, UTIL_MetresToGoldSrcUnits(15.0f), nullptr); @@ -7415,6 +7457,8 @@ void AIPlayerSetSecondaryAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) } } + AITASK_ClearBotTask(pBot, &pBot->SecondaryBotTask); + } void AIPlayerSetWantsAndNeedsAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)