diff --git a/regamedll/dlls/bmodels.cpp b/regamedll/dlls/bmodels.cpp index 47c27e14..a6c48b90 100644 --- a/regamedll/dlls/bmodels.cpp +++ b/regamedll/dlls/bmodels.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" -// BModelOrigin - calculates origin of a bmodel from absmin/size because all bmodel origins are 0 0 0 +// Calculates origin of a bmodel from absmin/size because all bmodel origins are 0 0 0 Vector VecBModelOrigin(entvars_t *pevBModel) { return pevBModel->absmin + (pevBModel->size * 0.5f); @@ -477,7 +477,7 @@ void CFuncRotating::Precache() } } -// Touch - will hurt others based on how fast the brush is spinning +// Will hurt others based on how fast the brush is spinning void CFuncRotating::HurtTouch(CBaseEntity *pOther) { entvars_t *pevOther = pOther->pev; @@ -494,7 +494,7 @@ void CFuncRotating::HurtTouch(CBaseEntity *pOther) pevOther->velocity = (pevOther->origin - VecBModelOrigin(pev)).Normalize() * pev->dmg; } -// RampPitchVol - ramp pitch and volume up to final values, based on difference +// Ramp pitch and volume up to final values, based on difference // between how fast we're going vs how fast we plan to go void CFuncRotating::RampPitchVol(BOOL fUp) { @@ -540,7 +540,7 @@ void CFuncRotating::RampPitchVol(BOOL fUp) EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseRunning), fvol, m_flAttenuation, (SND_CHANGE_PITCH | SND_CHANGE_VOL), pitch); } -// SpinUp - accelerates a non-moving func_rotating up to it's speed +// Accelerates a non-moving func_rotating up to it's speed void CFuncRotating::SpinUp() { // rotational velocity @@ -616,7 +616,7 @@ void CFuncRotating::Rotate() pev->nextthink = pev->ltime + 10; } -// Rotating Use - when a rotating brush is triggered +// When a rotating brush is triggered void CFuncRotating::RotatingUse(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) { // is this a brush that should accelerate and decelerate when turned on/off (fan)? @@ -662,7 +662,7 @@ void CFuncRotating::RotatingUse(CBaseEntity *pActivator, CBaseEntity *pCaller, U } } -// RotatingBlocked - An entity has blocked the brush +// An entity has blocked the brush void CFuncRotating::Blocked(CBaseEntity *pOther) { pOther->TakeDamage(pev, pev, pev->dmg, DMG_CRUSH); diff --git a/regamedll/dlls/bot/cs_bot.h b/regamedll/dlls/bot/cs_bot.h index 02011b62..6e0f1e23 100644 --- a/regamedll/dlls/bot/cs_bot.h +++ b/regamedll/dlls/bot/cs_bot.h @@ -729,7 +729,7 @@ private: float m_jumpCrouchTimestamp; // path navigation data - enum { MAX_PATH_LENGTH = 256 }; + enum { MAX_PATH_LENGTH = 256 }; struct ConnectInfo { CNavArea *area; // the area along the path @@ -1643,6 +1643,15 @@ public: cost += crouchPenalty * dist; } + // if this is a "walk" area, add penalty + if (area->GetAttributes() & NAV_WALK) + { + // these areas are kinda slow to move through + float_precision walkPenalty = (m_route == FASTEST_ROUTE) ? 2.5f : 1.5f; + + cost += walkPenalty * dist; + } + // if this is a "jump" area, add penalty if (area->GetAttributes() & NAV_JUMP) { diff --git a/regamedll/dlls/bot/cs_bot_chatter.cpp b/regamedll/dlls/bot/cs_bot_chatter.cpp index 3282f3c3..4158dfa2 100644 --- a/regamedll/dlls/bot/cs_bot_chatter.cpp +++ b/regamedll/dlls/bot/cs_bot_chatter.cpp @@ -838,24 +838,24 @@ bool BotStatement::IsValid() const { switch (m_condition[i]) { - case IS_IN_COMBAT: - { - if (!GetOwner()->IsAttacking()) - return false; - break; - } - /*case RADIO_SILENCE: - { - if (GetOwner()->GetChatter()->GetRadioSilenceDuration() < 10.0f) - return false; - break; - }*/ - case ENEMIES_REMAINING: - { - if (GetOwner()->GetEnemiesRemaining() == 0) - return false; - break; - } + case IS_IN_COMBAT: + { + if (!GetOwner()->IsAttacking()) + return false; + break; + } + /*case RADIO_SILENCE: + { + if (GetOwner()->GetChatter()->GetRadioSilenceDuration() < 10.0f) + return false; + break; + }*/ + case ENEMIES_REMAINING: + { + if (GetOwner()->GetEnemiesRemaining() == 0) + return false; + break; + } } } diff --git a/regamedll/dlls/bot/cs_bot_manager.cpp b/regamedll/dlls/bot/cs_bot_manager.cpp index 482c3038..664e14f6 100644 --- a/regamedll/dlls/bot/cs_bot_manager.cpp +++ b/regamedll/dlls/bot/cs_bot_manager.cpp @@ -270,6 +270,7 @@ void CCSBotManager::AddServerCommands() AddServerCommand("bot_nav_crouch"); AddServerCommand("bot_nav_jump"); AddServerCommand("bot_nav_precise"); + AddServerCommand("bot_nav_walk"); AddServerCommand("bot_nav_no_jump"); AddServerCommand("bot_nav_analyze"); AddServerCommand("bot_nav_strip"); @@ -525,6 +526,10 @@ void CCSBotManager::ServerCommand(const char *pcmd) { m_editCmd = EDIT_ATTRIB_PRECISE; } + else if (FStrEq(pcmd, "bot_nav_walk")) + { + m_editCmd = EDIT_ATTRIB_WALK; + } else if (FStrEq(pcmd, "bot_nav_no_jump")) { m_editCmd = EDIT_ATTRIB_NO_JUMP; diff --git a/regamedll/dlls/bot/cs_bot_pathfind.cpp b/regamedll/dlls/bot/cs_bot_pathfind.cpp index a170a4bb..0c2bda3c 100644 --- a/regamedll/dlls/bot/cs_bot_pathfind.cpp +++ b/regamedll/dlls/bot/cs_bot_pathfind.cpp @@ -288,23 +288,23 @@ bool CCSBot::UpdateLadderMovement() // check if somehow we totally missed the ladder switch (m_pathLadderState) { - case MOUNT_ASCENDING_LADDER: - case MOUNT_DESCENDING_LADDER: - case ASCEND_LADDER: - case DESCEND_LADDER: + case MOUNT_ASCENDING_LADDER: + case MOUNT_DESCENDING_LADDER: + case ASCEND_LADDER: + case DESCEND_LADDER: + { + const float farAway = 200.0f; + Vector2D d = (m_pathLadder->m_top - pev->origin).Make2D(); + if (d.IsLengthGreaterThan(farAway)) { - const float farAway = 200.0f; - Vector2D d = (m_pathLadder->m_top - pev->origin).Make2D(); - if (d.IsLengthGreaterThan(farAway)) - { - PrintIfWatched("Missed ladder\n"); - Jump(MUST_JUMP); - DestroyPath(); - Run(); - return false; - } - break; + PrintIfWatched("Missed ladder\n"); + Jump(MUST_JUMP); + DestroyPath(); + Run(); + return false; } + break; + } } m_areaEnteredTimestamp = gpGlobals->time; @@ -314,12 +314,68 @@ bool CCSBot::UpdateLadderMovement() switch (m_pathLadderState) { - case APPROACH_ASCENDING_LADDER: + case APPROACH_ASCENDING_LADDER: + { + bool approached = false; + Vector2D d(pev->origin.x - m_goalPosition.x, pev->origin.y - m_goalPosition.y); + + if (d.x * m_pathLadder->m_dirVector.x + d.y * m_pathLadder->m_dirVector.y < 0.0f) + { + Vector2D perp(-m_pathLadder->m_dirVector.y, m_pathLadder->m_dirVector.x); + + if (Q_abs(int64(d.x * perp.x + d.y * perp.y)) < tolerance && d.Length() < closeToGoal) + approached = true; + } + + // small radius will just slow them down a little for more accuracy in hitting their spot + const float walkRange = 50.0f; + if (d.IsLengthLessThan(walkRange)) + { + Walk(); + StandUp(); + } + + // TODO: Check that we are on the ladder we think we are + if (IsOnLadder()) + { + m_pathLadderState = ASCEND_LADDER; + PrintIfWatched("ASCEND_LADDER\n"); + + // find actual top in case m_pathLadder penetrates the ceiling + ComputeLadderEndpoint(true); + } + else if (approached) + { + // face the m_pathLadder + m_pathLadderState = FACE_ASCENDING_LADDER; + PrintIfWatched("FACE_ASCENDING_LADDER\n"); + } + else + { + // move toward ladder mount point + MoveTowardsPosition(&m_goalPosition); + } + break; + } + case APPROACH_DESCENDING_LADDER: + { + // fall check + if (GetFeetZ() <= m_pathLadder->m_bottom.z + HalfHumanHeight) + { + PrintIfWatched("Fell from ladder.\n"); + + m_pathLadderState = MOVE_TO_DESTINATION; + m_path[m_pathIndex].area->GetClosestPointOnArea(&m_pathLadder->m_bottom, &m_goalPosition); + + AddDirectionVector(&m_goalPosition, m_pathLadder->m_dir, HalfHumanWidth); + PrintIfWatched("MOVE_TO_DESTINATION\n"); + } + else { bool approached = false; Vector2D d(pev->origin.x - m_goalPosition.x, pev->origin.y - m_goalPosition.y); - if (d.x * m_pathLadder->m_dirVector.x + d.y * m_pathLadder->m_dirVector.y < 0.0f) + if (d.x * m_pathLadder->m_dirVector.x + d.y * m_pathLadder->m_dirVector.y > 0.0f) { Vector2D perp(-m_pathLadder->m_dirVector.y, m_pathLadder->m_dirVector.x); @@ -327,274 +383,218 @@ bool CCSBot::UpdateLadderMovement() approached = true; } - // small radius will just slow them down a little for more accuracy in hitting their spot - const float walkRange = 50.0f; - if (d.IsLengthLessThan(walkRange)) + // if approaching ladder from the side or "ahead", walk + if (m_pathLadder->m_topBehindArea != m_lastKnownArea) { - Walk(); - StandUp(); + const float walkRange = 150.0f; + if (!IsCrouching() && d.IsLengthLessThan(walkRange)) + Walk(); } // TODO: Check that we are on the ladder we think we are if (IsOnLadder()) { - m_pathLadderState = ASCEND_LADDER; - PrintIfWatched("ASCEND_LADDER\n"); + // we slipped onto the ladder - climb it + m_pathLadderState = DESCEND_LADDER; + Run(); + PrintIfWatched("DESCEND_LADDER\n"); - // find actual top in case m_pathLadder penetrates the ceiling - ComputeLadderEndpoint(true); + // find actual bottom in case m_pathLadder penetrates the floor + ComputeLadderEndpoint(false); } else if (approached) { - // face the m_pathLadder - m_pathLadderState = FACE_ASCENDING_LADDER; - PrintIfWatched("FACE_ASCENDING_LADDER\n"); + // face the ladder + m_pathLadderState = FACE_DESCENDING_LADDER; + PrintIfWatched("FACE_DESCENDING_LADDER\n"); } else { // move toward ladder mount point MoveTowardsPosition(&m_goalPosition); } - break; } - case APPROACH_DESCENDING_LADDER: + break; + } + case FACE_ASCENDING_LADDER: + { + // find yaw to directly aim at ladder + Vector to = m_pathLadder->m_bottom - pev->origin; + Vector idealAngle = UTIL_VecToAngles(to); + + const float angleTolerance = 5.0f; + if (AnglesAreEqual(pev->v_angle.y, idealAngle.y, angleTolerance)) { - // fall check - if (GetFeetZ() <= m_pathLadder->m_bottom.z + HalfHumanHeight) - { - PrintIfWatched("Fell from ladder.\n"); - - m_pathLadderState = MOVE_TO_DESTINATION; - m_path[m_pathIndex].area->GetClosestPointOnArea(&m_pathLadder->m_bottom, &m_goalPosition); - - AddDirectionVector(&m_goalPosition, m_pathLadder->m_dir, HalfHumanWidth); - PrintIfWatched("MOVE_TO_DESTINATION\n"); - } - else - { - bool approached = false; - Vector2D d(pev->origin.x - m_goalPosition.x, pev->origin.y - m_goalPosition.y); - - if (d.x * m_pathLadder->m_dirVector.x + d.y * m_pathLadder->m_dirVector.y > 0.0f) - { - Vector2D perp(-m_pathLadder->m_dirVector.y, m_pathLadder->m_dirVector.x); - - if (Q_abs(int64(d.x * perp.x + d.y * perp.y)) < tolerance && d.Length() < closeToGoal) - approached = true; - } - - // if approaching ladder from the side or "ahead", walk - if (m_pathLadder->m_topBehindArea != m_lastKnownArea) - { - const float walkRange = 150.0f; - if (!IsCrouching() && d.IsLengthLessThan(walkRange)) - Walk(); - } - - // TODO: Check that we are on the ladder we think we are - if (IsOnLadder()) - { - // we slipped onto the ladder - climb it - m_pathLadderState = DESCEND_LADDER; - Run(); - PrintIfWatched("DESCEND_LADDER\n"); - - // find actual bottom in case m_pathLadder penetrates the floor - ComputeLadderEndpoint(false); - } - else if (approached) - { - // face the ladder - m_pathLadderState = FACE_DESCENDING_LADDER; - PrintIfWatched("FACE_DESCENDING_LADDER\n"); - } - else - { - // move toward ladder mount point - MoveTowardsPosition(&m_goalPosition); - } - } - break; + // move toward ladder until we become "on" it + Run(); + ResetStuckMonitor(); + m_pathLadderState = MOUNT_ASCENDING_LADDER; + PrintIfWatched("MOUNT_ASCENDING_LADDER\n"); } - case FACE_ASCENDING_LADDER: + break; + } + case FACE_DESCENDING_LADDER: + { + // find yaw to directly aim at ladder + Vector to = m_pathLadder->m_top - pev->origin; + Vector idealAngle = UTIL_VecToAngles(to); + + const float angleTolerance = 5.0f; + if (AnglesAreEqual(pev->v_angle.y, idealAngle.y, angleTolerance)) { - // find yaw to directly aim at ladder - Vector to = m_pathLadder->m_bottom - pev->origin; - Vector idealAngle = UTIL_VecToAngles(to); - - const float angleTolerance = 5.0f; - if (AnglesAreEqual(pev->v_angle.y, idealAngle.y, angleTolerance)) - { - // move toward ladder until we become "on" it - Run(); - ResetStuckMonitor(); - m_pathLadderState = MOUNT_ASCENDING_LADDER; - PrintIfWatched("MOUNT_ASCENDING_LADDER\n"); - } - break; + // move toward ladder until we become "on" it + m_pathLadderState = MOUNT_DESCENDING_LADDER; + ResetStuckMonitor(); + PrintIfWatched("MOUNT_DESCENDING_LADDER\n"); } - case FACE_DESCENDING_LADDER: + break; + } + case MOUNT_ASCENDING_LADDER: + { + if (IsOnLadder()) { - // find yaw to directly aim at ladder - Vector to = m_pathLadder->m_top - pev->origin; - Vector idealAngle = UTIL_VecToAngles(to); + m_pathLadderState = ASCEND_LADDER; + PrintIfWatched("ASCEND_LADDER\n"); - const float angleTolerance = 5.0f; - if (AnglesAreEqual(pev->v_angle.y, idealAngle.y, angleTolerance)) - { - // move toward ladder until we become "on" it - m_pathLadderState = MOUNT_DESCENDING_LADDER; - ResetStuckMonitor(); - PrintIfWatched("MOUNT_DESCENDING_LADDER\n"); - } - break; + // find actual top in case m_pathLadder penetrates the ceiling + ComputeLadderEndpoint(true); } - case MOUNT_ASCENDING_LADDER: + + MoveForward(); + break; + } + case MOUNT_DESCENDING_LADDER: + { + // fall check + if (GetFeetZ() <= m_pathLadder->m_bottom.z + HalfHumanHeight) + { + PrintIfWatched("Fell from ladder.\n"); + + m_pathLadderState = MOVE_TO_DESTINATION; + m_path[m_pathIndex].area->GetClosestPointOnArea(&m_pathLadder->m_bottom, &m_goalPosition); + + AddDirectionVector(&m_goalPosition, m_pathLadder->m_dir, HalfHumanWidth); + PrintIfWatched("MOVE_TO_DESTINATION\n"); + } + else { if (IsOnLadder()) { - m_pathLadderState = ASCEND_LADDER; - PrintIfWatched("ASCEND_LADDER\n"); + m_pathLadderState = DESCEND_LADDER; + PrintIfWatched("DESCEND_LADDER\n"); - // find actual top in case m_pathLadder penetrates the ceiling - ComputeLadderEndpoint(true); + // find actual bottom in case m_pathLadder penetrates the floor + ComputeLadderEndpoint(false); } + // move toward ladder mount point MoveForward(); - break; } - case MOUNT_DESCENDING_LADDER: + break; + } + case ASCEND_LADDER: + { + // run, so we can make our dismount jump to the side, if necessary + Run(); + + // if our destination area requires us to crouch, do it + if (m_path[m_pathIndex].area->GetAttributes() & NAV_CROUCH) + Crouch(); + + // did we reach the top? + if (GetFeetZ() >= m_pathLadderEnd) { - // fall check - if (GetFeetZ() <= m_pathLadder->m_bottom.z + HalfHumanHeight) - { - PrintIfWatched("Fell from ladder.\n"); + // we reached the top - dismount + m_pathLadderState = DISMOUNT_ASCENDING_LADDER; + PrintIfWatched("DISMOUNT_ASCENDING_LADDER\n"); - m_pathLadderState = MOVE_TO_DESTINATION; - m_path[m_pathIndex].area->GetClosestPointOnArea(&m_pathLadder->m_bottom, &m_goalPosition); + if (m_path[m_pathIndex].area == m_pathLadder->m_topForwardArea) + m_pathLadderDismountDir = FORWARD; + else if (m_path[m_pathIndex].area == m_pathLadder->m_topLeftArea) + m_pathLadderDismountDir = LEFT; + else if (m_path[m_pathIndex].area == m_pathLadder->m_topRightArea) + m_pathLadderDismountDir = RIGHT; - AddDirectionVector(&m_goalPosition, m_pathLadder->m_dir, HalfHumanWidth); - PrintIfWatched("MOVE_TO_DESTINATION\n"); - } - else - { - if (IsOnLadder()) - { - m_pathLadderState = DESCEND_LADDER; - PrintIfWatched("DESCEND_LADDER\n"); - - // find actual bottom in case m_pathLadder penetrates the floor - ComputeLadderEndpoint(false); - } - - // move toward ladder mount point - MoveForward(); - } - break; + m_pathLadderDismountTimestamp = gpGlobals->time; } - case ASCEND_LADDER: + else if (!IsOnLadder()) { - // run, so we can make our dismount jump to the side, if necessary - Run(); - - // if our destination area requires us to crouch, do it - if (m_path[m_pathIndex].area->GetAttributes() & NAV_CROUCH) - Crouch(); - - // did we reach the top? - if (GetFeetZ() >= m_pathLadderEnd) - { - // we reached the top - dismount - m_pathLadderState = DISMOUNT_ASCENDING_LADDER; - PrintIfWatched("DISMOUNT_ASCENDING_LADDER\n"); - - if (m_path[m_pathIndex].area == m_pathLadder->m_topForwardArea) - m_pathLadderDismountDir = FORWARD; - else if (m_path[m_pathIndex].area == m_pathLadder->m_topLeftArea) - m_pathLadderDismountDir = LEFT; - else if (m_path[m_pathIndex].area == m_pathLadder->m_topRightArea) - m_pathLadderDismountDir = RIGHT; - - m_pathLadderDismountTimestamp = gpGlobals->time; - } - else if (!IsOnLadder()) - { - // we fall off the ladder, repath - DestroyPath(); - return false; - } - - // move up ladder - MoveForward(); - break; + // we fall off the ladder, repath + DestroyPath(); + return false; } - case DESCEND_LADDER: + + // move up ladder + MoveForward(); + break; + } + case DESCEND_LADDER: + { + Run(); + + float destHeight = m_pathLadderEnd + HalfHumanHeight; + if (!IsOnLadder() || GetFeetZ() <= destHeight) { - Run(); + // we reached the bottom, or we fell off - dismount + m_pathLadderState = MOVE_TO_DESTINATION; + m_path[m_pathIndex].area->GetClosestPointOnArea(&m_pathLadder->m_bottom, &m_goalPosition); - float destHeight = m_pathLadderEnd + HalfHumanHeight; - if (!IsOnLadder() || GetFeetZ() <= destHeight) - { - // we reached the bottom, or we fell off - dismount - m_pathLadderState = MOVE_TO_DESTINATION; - m_path[m_pathIndex].area->GetClosestPointOnArea(&m_pathLadder->m_bottom, &m_goalPosition); - - AddDirectionVector(&m_goalPosition, m_pathLadder->m_dir, HalfHumanWidth); - PrintIfWatched("MOVE_TO_DESTINATION\n"); - } - - // Move down ladder - MoveForward(); - break; + AddDirectionVector(&m_goalPosition, m_pathLadder->m_dir, HalfHumanWidth); + PrintIfWatched("MOVE_TO_DESTINATION\n"); } - case DISMOUNT_ASCENDING_LADDER: + + // Move down ladder + MoveForward(); + break; + } + case DISMOUNT_ASCENDING_LADDER: + { + if (gpGlobals->time - m_pathLadderDismountTimestamp >= 0.4f) { - if (gpGlobals->time - m_pathLadderDismountTimestamp >= 0.4f) - { - m_pathLadderState = MOVE_TO_DESTINATION; - m_path[m_pathIndex].area->GetClosestPointOnArea(&pev->origin, &m_goalPosition); - PrintIfWatched("MOVE_TO_DESTINATION\n"); - } - - // We should already be facing the dismount point - if (m_pathLadderFaceIn) - { - switch (m_pathLadderDismountDir) - { - case LEFT: StrafeLeft(); break; - case RIGHT: StrafeRight(); break; - case FORWARD: MoveForward(); break; - } - } - else - { - switch (m_pathLadderDismountDir) - { - case LEFT: StrafeRight(); break; - case RIGHT: StrafeLeft(); break; - case FORWARD: MoveBackward(); break; - } - } - break; + m_pathLadderState = MOVE_TO_DESTINATION; + m_path[m_pathIndex].area->GetClosestPointOnArea(&pev->origin, &m_goalPosition); + PrintIfWatched("MOVE_TO_DESTINATION\n"); } - case MOVE_TO_DESTINATION: + + // We should already be facing the dismount point + if (m_pathLadderFaceIn) { - if (m_path[m_pathIndex].area->Contains(&pev->origin)) + switch (m_pathLadderDismountDir) { - // successfully traversed ladder and reached destination area - // exit ladder state machine - PrintIfWatched("Ladder traversed.\n"); - m_pathLadder = nullptr; - - // incrememnt path index to next step beyond this ladder - SetPathIndex(m_pathIndex + 1); - - return false; + case LEFT: StrafeLeft(); break; + case RIGHT: StrafeRight(); break; + case FORWARD: MoveForward(); break; } - - MoveTowardsPosition(&m_goalPosition); - break; } + else + { + switch (m_pathLadderDismountDir) + { + case LEFT: StrafeRight(); break; + case RIGHT: StrafeLeft(); break; + case FORWARD: MoveBackward(); break; + } + } + break; + } + case MOVE_TO_DESTINATION: + { + if (m_path[m_pathIndex].area->Contains(&pev->origin)) + { + // successfully traversed ladder and reached destination area + // exit ladder state machine + PrintIfWatched("Ladder traversed.\n"); + m_pathLadder = nullptr; + + // incrememnt path index to next step beyond this ladder + SetPathIndex(m_pathIndex + 1); + + return false; + } + + MoveTowardsPosition(&m_goalPosition); + break; + } } return true; @@ -1352,9 +1352,10 @@ CCSBot::PathResult CCSBot::UpdatePathMovement(bool allowSpeedChange) SetPathIndex(newIndex); } - // Crouching if (!IsUsingLadder()) { + // Crouching + // if we are approaching a crouch area, crouch // if there are no crouch areas coming up, stand const float crouchRange = 50.0f; @@ -1388,6 +1389,29 @@ CCSBot::PathResult CCSBot::UpdatePathMovement(bool allowSpeedChange) StandUp(); } // end crouching logic + + // Walking + bool didWalk = false; + for (int i = prevIndex; i < m_pathLength; ++i) + { + const CNavArea *to = m_path[i].area; + + Vector close; + to->GetClosestPointOnArea(&pev->origin, &close); + + if ((close - pev->origin).Make2D().IsLengthGreaterThan(crouchRange)) + break; + + if (to->GetAttributes() & NAV_WALK) + { + Walk(); + didWalk = true; + break; + } + } + + if (!didWalk) + Run(); } // compute our forward facing angle diff --git a/regamedll/dlls/bot/cs_bot_radio.cpp b/regamedll/dlls/bot/cs_bot_radio.cpp index ae971f33..1a9cdc15 100644 --- a/regamedll/dlls/bot/cs_bot_radio.cpp +++ b/regamedll/dlls/bot/cs_bot_radio.cpp @@ -106,98 +106,98 @@ void CCSBot::RespondToRadioCommands() const float inhibitAutoFollowDuration = 60.0f; switch (m_lastRadioCommand) { - case EVENT_RADIO_REPORT_IN_TEAM: + case EVENT_RADIO_REPORT_IN_TEAM: + { + GetChatter()->ReportingIn(); + break; + } + case EVENT_RADIO_FOLLOW_ME: + case EVENT_RADIO_COVER_ME: + case EVENT_RADIO_STICK_TOGETHER_TEAM: + case EVENT_RADIO_REGROUP_TEAM: + { + if (!IsFollowing()) { - GetChatter()->ReportingIn(); - break; - } - case EVENT_RADIO_FOLLOW_ME: - case EVENT_RADIO_COVER_ME: - case EVENT_RADIO_STICK_TOGETHER_TEAM: - case EVENT_RADIO_REGROUP_TEAM: - { - if (!IsFollowing()) - { - Follow(m_radioSubject); - m_radioSubject->AllowAutoFollow(); - canDo = true; - } - break; - } - case EVENT_RADIO_ENEMY_SPOTTED: - case EVENT_RADIO_NEED_BACKUP: - case EVENT_RADIO_TAKING_FIRE: - { - if (!IsFollowing()) - { - Follow(m_radioSubject); - GetChatter()->Say("OnMyWay"); - m_radioSubject->AllowAutoFollow(); - canDo = false; - } - break; - } - case EVENT_RADIO_TEAM_FALL_BACK: - { - if (TryToRetreat()) - canDo = true; - break; - } - case EVENT_RADIO_HOLD_THIS_POSITION: - { - // find the leader's area - SetTask(HOLD_POSITION); - StopFollowing(); - m_radioSubject->InhibitAutoFollow(inhibitAutoFollowDuration); - Hide(TheNavAreaGrid.GetNearestNavArea(&m_radioPosition)); + Follow(m_radioSubject); + m_radioSubject->AllowAutoFollow(); canDo = true; - break; } - case EVENT_RADIO_GO_GO_GO: - case EVENT_RADIO_STORM_THE_FRONT: + break; + } + case EVENT_RADIO_ENEMY_SPOTTED: + case EVENT_RADIO_NEED_BACKUP: + case EVENT_RADIO_TAKING_FIRE: + { + if (!IsFollowing()) { - StopFollowing(); - Hunt(); + Follow(m_radioSubject); + GetChatter()->Say("OnMyWay"); + m_radioSubject->AllowAutoFollow(); + canDo = false; + } + break; + } + case EVENT_RADIO_TEAM_FALL_BACK: + { + if (TryToRetreat()) canDo = true; + break; + } + case EVENT_RADIO_HOLD_THIS_POSITION: + { + // find the leader's area + SetTask(HOLD_POSITION); + StopFollowing(); + m_radioSubject->InhibitAutoFollow(inhibitAutoFollowDuration); + Hide(TheNavAreaGrid.GetNearestNavArea(&m_radioPosition)); + canDo = true; + break; + } + case EVENT_RADIO_GO_GO_GO: + case EVENT_RADIO_STORM_THE_FRONT: + { + StopFollowing(); + Hunt(); + canDo = true; + m_radioSubject->InhibitAutoFollow(inhibitAutoFollowDuration); + break; + } + case EVENT_RADIO_GET_OUT_OF_THERE: + { + if (TheCSBots()->IsBombPlanted()) + { + EscapeFromBomb(); m_radioSubject->InhibitAutoFollow(inhibitAutoFollowDuration); - break; + canDo = true; } - case EVENT_RADIO_GET_OUT_OF_THERE: + break; + } + case EVENT_RADIO_SECTOR_CLEAR: + { + // if this is a defusal scenario, and the bomb is planted, + // and a human player cleared a bombsite, check it off our list too + if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_DEFUSE_BOMB) { - if (TheCSBots()->IsBombPlanted()) + if (m_iTeam == CT && TheCSBots()->IsBombPlanted()) { - EscapeFromBomb(); - m_radioSubject->InhibitAutoFollow(inhibitAutoFollowDuration); - canDo = true; - } - break; - } - case EVENT_RADIO_SECTOR_CLEAR: - { - // if this is a defusal scenario, and the bomb is planted, - // and a human player cleared a bombsite, check it off our list too - if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_DEFUSE_BOMB) - { - if (m_iTeam == CT && TheCSBots()->IsBombPlanted()) + const CCSBotManager::Zone *zone = TheCSBots()->GetClosestZone(m_radioSubject); + if (zone) { - const CCSBotManager::Zone *zone = TheCSBots()->GetClosestZone(m_radioSubject); - if (zone) - { - GetGameState()->ClearBombsite(zone->m_index); + GetGameState()->ClearBombsite(zone->m_index); - // if we are huting for the planted bomb, re-select bombsite - if (GetTask() == FIND_TICKING_BOMB) - Idle(); + // if we are huting for the planted bomb, re-select bombsite + if (GetTask() == FIND_TICKING_BOMB) + Idle(); - canDo = true; - } + canDo = true; } } - break; } - default: - // ignore all other radio commands for now - return; + break; + } + default: + // ignore all other radio commands for now + return; } if (canDo) diff --git a/regamedll/dlls/bot/cs_bot_update.cpp b/regamedll/dlls/bot/cs_bot_update.cpp index a362d2c0..e9c21e03 100644 --- a/regamedll/dlls/bot/cs_bot_update.cpp +++ b/regamedll/dlls/bot/cs_bot_update.cpp @@ -132,34 +132,34 @@ void CCSBot::Upkeep() switch (m_lookAtSpotState) { - case NOT_LOOKING_AT_SPOT: - { - // look ahead - SetLookAngles(m_lookAheadAngle, 0); - break; - } - case LOOK_TOWARDS_SPOT: - { - UpdateLookAt(); + case NOT_LOOKING_AT_SPOT: + { + // look ahead + SetLookAngles(m_lookAheadAngle, 0); + break; + } + case LOOK_TOWARDS_SPOT: + { + UpdateLookAt(); - if (IsLookingAtPosition(&m_lookAtSpot, m_lookAtSpotAngleTolerance)) - { - m_lookAtSpotState = LOOK_AT_SPOT; - m_lookAtSpotTimestamp = gpGlobals->time; - } - break; - } - case LOOK_AT_SPOT: + if (IsLookingAtPosition(&m_lookAtSpot, m_lookAtSpotAngleTolerance)) { - UpdateLookAt(); - - if (m_lookAtSpotDuration >= 0.0f && gpGlobals->time - m_lookAtSpotTimestamp > m_lookAtSpotDuration) - { - m_lookAtSpotState = NOT_LOOKING_AT_SPOT; - m_lookAtSpotDuration = 0.0f; - } - break; + m_lookAtSpotState = LOOK_AT_SPOT; + m_lookAtSpotTimestamp = gpGlobals->time; } + break; + } + case LOOK_AT_SPOT: + { + UpdateLookAt(); + + if (m_lookAtSpotDuration >= 0.0f && gpGlobals->time - m_lookAtSpotTimestamp > m_lookAtSpotDuration) + { + m_lookAtSpotState = NOT_LOOKING_AT_SPOT; + m_lookAtSpotDuration = 0.0f; + } + break; + } } float driftAmplitude = 2.0f; @@ -189,10 +189,10 @@ void CCSBot::Update() switch (m_processMode) { - case PROCESS_LEARN: UpdateLearnProcess(); return; - case PROCESS_ANALYZE_ALPHA: UpdateAnalyzeAlphaProcess(); return; - case PROCESS_ANALYZE_BETA: UpdateAnalyzeBetaProcess(); return; - case PROCESS_SAVE: UpdateSaveProcess(); return; + case PROCESS_LEARN: UpdateLearnProcess(); return; + case PROCESS_ANALYZE_ALPHA: UpdateAnalyzeAlphaProcess(); return; + case PROCESS_ANALYZE_BETA: UpdateAnalyzeBetaProcess(); return; + case PROCESS_SAVE: UpdateSaveProcess(); return; } // update our radio chatter @@ -312,11 +312,11 @@ void CCSBot::Update() { switch (m_blindMoveDir) { - case FORWARD: MoveForward(); break; - case RIGHT: StrafeRight(); break; - case BACKWARD: MoveBackward(); break; - case LEFT: StrafeLeft(); break; - default: Crouch(); break; + case FORWARD: MoveForward(); break; + case RIGHT: StrafeRight(); break; + case BACKWARD: MoveBackward(); break; + case LEFT: StrafeLeft(); break; + default: Crouch(); break; } } @@ -349,32 +349,32 @@ void CCSBot::Update() bool doAttack = false; switch (GetDisposition()) { - case IGNORE_ENEMIES: - { - // never attack - doAttack = false; - break; - } - case SELF_DEFENSE: - { - // attack if fired on - doAttack = IsPlayerLookingAtMe(threat); + case IGNORE_ENEMIES: + { + // never attack + doAttack = false; + break; + } + case SELF_DEFENSE: + { + // attack if fired on + doAttack = IsPlayerLookingAtMe(threat); - // attack if enemy very close - if (!doAttack) - { - const float selfDefenseRange = 750.0f; - doAttack = (pev->origin - threat->pev->origin).IsLengthLessThan(selfDefenseRange); - } - break; - } - case ENGAGE_AND_INVESTIGATE: - case OPPORTUNITY_FIRE: + // attack if enemy very close + if (!doAttack) { - // normal combat range - doAttack = true; - break; + const float selfDefenseRange = 750.0f; + doAttack = (pev->origin - threat->pev->origin).IsLengthLessThan(selfDefenseRange); } + break; + } + case ENGAGE_AND_INVESTIGATE: + case OPPORTUNITY_FIRE: + { + // normal combat range + doAttack = true; + break; + } } if (doAttack) @@ -596,52 +596,52 @@ void CCSBot::Update() // Scenario interrupts switch (TheCSBots()->GetScenario()) { - case CCSBotManager::SCENARIO_DEFUSE_BOMB: + case CCSBotManager::SCENARIO_DEFUSE_BOMB: + { + // flee if the bomb is ready to blow and we aren't defusing it or attacking and we know where the bomb is + // (aggressive players wait until its almost too late) + float gonnaBlowTime = 8.0f - (2.0f * GetProfile()->GetAggression()); + + // if we have a defuse kit, can wait longer + if (m_bHasDefuser) + gonnaBlowTime *= 0.66f; + + if (!IsEscapingFromBomb() // we aren't already escaping the bomb + && TheCSBots()->IsBombPlanted() // is the bomb planted + && GetGameState()->IsPlantedBombLocationKnown() // we know where the bomb is + && TheCSBots()->GetBombTimeLeft() < gonnaBlowTime // is the bomb about to explode + && !IsDefusingBomb() // we aren't defusing the bomb + && !IsAttacking()) // we aren't in the midst of a firefight { - // flee if the bomb is ready to blow and we aren't defusing it or attacking and we know where the bomb is - // (aggressive players wait until its almost too late) - float gonnaBlowTime = 8.0f - (2.0f * GetProfile()->GetAggression()); - - // if we have a defuse kit, can wait longer - if (m_bHasDefuser) - gonnaBlowTime *= 0.66f; - - if (!IsEscapingFromBomb() // we aren't already escaping the bomb - && TheCSBots()->IsBombPlanted() // is the bomb planted - && GetGameState()->IsPlantedBombLocationKnown() // we know where the bomb is - && TheCSBots()->GetBombTimeLeft() < gonnaBlowTime // is the bomb about to explode - && !IsDefusingBomb() // we aren't defusing the bomb - && !IsAttacking()) // we aren't in the midst of a firefight - { - EscapeFromBomb(); - break; - } + EscapeFromBomb(); break; } - case CCSBotManager::SCENARIO_RESCUE_HOSTAGES: + break; + } + case CCSBotManager::SCENARIO_RESCUE_HOSTAGES: + { + if (m_iTeam == CT) { - if (m_iTeam == CT) - { - UpdateHostageEscortCount(); - } - else - { - // Terrorists have imperfect information on status of hostages - CSGameState::ValidateStatusType status = GetGameState()->ValidateHostagePositions(); - - if (status & CSGameState::HOSTAGES_ALL_GONE) - { - GetChatter()->HostagesTaken(); - Idle(); - } - else if (status & CSGameState::HOSTAGE_GONE) - { - GetGameState()->HostageWasTaken(); - Idle(); - } - } - break; + UpdateHostageEscortCount(); } + else + { + // Terrorists have imperfect information on status of hostages + CSGameState::ValidateStatusType status = GetGameState()->ValidateHostagePositions(); + + if (status & CSGameState::HOSTAGES_ALL_GONE) + { + GetChatter()->HostagesTaken(); + Idle(); + } + else if (status & CSGameState::HOSTAGE_GONE) + { + GetGameState()->HostageWasTaken(); + Idle(); + } + } + break; + } } // Follow nearby humans if our co-op is high and we have nothing else to do diff --git a/regamedll/dlls/bot/cs_bot_vision.cpp b/regamedll/dlls/bot/cs_bot_vision.cpp index f11585c7..11a5ffe5 100644 --- a/regamedll/dlls/bot/cs_bot_vision.cpp +++ b/regamedll/dlls/bot/cs_bot_vision.cpp @@ -103,56 +103,56 @@ void CCSBot::UpdateLookAngles() // adjust pitch to look up/down ladder as we ascend/descend switch (m_pathLadderState) { - case APPROACH_ASCENDING_LADDER: - { - Vector to = m_goalPosition - pev->origin; - useYaw = idealYaw; + case APPROACH_ASCENDING_LADDER: + { + Vector to = m_goalPosition - pev->origin; + useYaw = idealYaw; - if (to.IsLengthLessThan(lookAlongLadderRange)) - usePitch = -ladderPitch; - break; - } - case APPROACH_DESCENDING_LADDER: - { - Vector to = m_goalPosition - pev->origin; - useYaw = idealYaw; + if (to.IsLengthLessThan(lookAlongLadderRange)) + usePitch = -ladderPitch; + break; + } + case APPROACH_DESCENDING_LADDER: + { + Vector to = m_goalPosition - pev->origin; + useYaw = idealYaw; - if (to.IsLengthLessThan(lookAlongLadderRange)) - usePitch = ladderPitch; - break; - } - case FACE_ASCENDING_LADDER: - { - useYaw = idealYaw; - usePitch = -ladderPitch; - break; - } - case FACE_DESCENDING_LADDER: - { - useYaw = idealYaw; + if (to.IsLengthLessThan(lookAlongLadderRange)) usePitch = ladderPitch; - break; - } - case MOUNT_ASCENDING_LADDER: - case ASCEND_LADDER: - { - useYaw = DirectionToAngle(faceDir) + StayOnLadderLine(this, m_pathLadder); - usePitch = -ladderPitch; - break; - } - case MOUNT_DESCENDING_LADDER: - case DESCEND_LADDER: - { - useYaw = DirectionToAngle(faceDir) + StayOnLadderLine(this, m_pathLadder); - usePitch = ladderPitch; - break; - } - case DISMOUNT_ASCENDING_LADDER: - case DISMOUNT_DESCENDING_LADDER: - { - useYaw = DirectionToAngle(faceDir); - break; - } + break; + } + case FACE_ASCENDING_LADDER: + { + useYaw = idealYaw; + usePitch = -ladderPitch; + break; + } + case FACE_DESCENDING_LADDER: + { + useYaw = idealYaw; + usePitch = ladderPitch; + break; + } + case MOUNT_ASCENDING_LADDER: + case ASCEND_LADDER: + { + useYaw = DirectionToAngle(faceDir) + StayOnLadderLine(this, m_pathLadder); + usePitch = -ladderPitch; + break; + } + case MOUNT_DESCENDING_LADDER: + case DESCEND_LADDER: + { + useYaw = DirectionToAngle(faceDir) + StayOnLadderLine(this, m_pathLadder); + usePitch = ladderPitch; + break; + } + case DISMOUNT_ASCENDING_LADDER: + case DISMOUNT_DESCENDING_LADDER: + { + useYaw = DirectionToAngle(faceDir); + break; + } } } diff --git a/regamedll/dlls/bot/cs_gamestate.cpp b/regamedll/dlls/bot/cs_gamestate.cpp index 141c66e6..48e1a3a8 100644 --- a/regamedll/dlls/bot/cs_gamestate.cpp +++ b/regamedll/dlls/bot/cs_gamestate.cpp @@ -246,27 +246,27 @@ const Vector *CSGameState::GetBombPosition() const { switch (m_bombState) { - case MOVING: - { - if (!m_lastSawBomber.HasStarted()) - return nullptr; - - return &m_bomberPos; - } - case LOOSE: - { - if (IsLooseBombLocationKnown()) - return &m_looseBombPos; - + case MOVING: + { + if (!m_lastSawBomber.HasStarted()) return nullptr; - } - case PLANTED: - { - if (IsPlantedBombLocationKnown()) - return &m_plantedBombPos; - return nullptr; - } + return &m_bomberPos; + } + case LOOSE: + { + if (IsLooseBombLocationKnown()) + return &m_looseBombPos; + + return nullptr; + } + case PLANTED: + { + if (IsPlantedBombLocationKnown()) + return &m_plantedBombPos; + + return nullptr; + } } return nullptr; @@ -477,7 +477,7 @@ CSGameState::ValidateStatusType CSGameState::ValidateHostagePositions() { HostageInfo *info = &m_hostage[i]; - if (!info->hostage) + if (!info->hostage) continue; // if we can see a hostage, update our knowledge of it diff --git a/regamedll/dlls/bot/states/cs_bot_fetch_bomb.cpp b/regamedll/dlls/bot/states/cs_bot_fetch_bomb.cpp index a2561842..e66031cf 100644 --- a/regamedll/dlls/bot/states/cs_bot_fetch_bomb.cpp +++ b/regamedll/dlls/bot/states/cs_bot_fetch_bomb.cpp @@ -39,7 +39,7 @@ void FetchBombState::OnUpdate(CCSBot *me) { if (me->IsCarryingBomb()) { - me->PrintIfWatched( "I picked up the bomb\n" ); + me->PrintIfWatched("I picked up the bomb\n"); me->Idle(); return; } diff --git a/regamedll/dlls/bot/states/cs_bot_hide.cpp b/regamedll/dlls/bot/states/cs_bot_hide.cpp index 678f0df8..049adca6 100644 --- a/regamedll/dlls/bot/states/cs_bot_hide.cpp +++ b/regamedll/dlls/bot/states/cs_bot_hide.cpp @@ -141,106 +141,106 @@ void HideState::OnUpdate(CCSBot *me) // Scenario logic switch (TheCSBots()->GetScenario()) { - case CCSBotManager::SCENARIO_DEFUSE_BOMB: + case CCSBotManager::SCENARIO_DEFUSE_BOMB: + { + if (me->m_iTeam == CT) { - if (me->m_iTeam == CT) + // if we are just holding position (due to a radio order) and the bomb has just planted, go defuse it + if (me->GetTask() == CCSBot::HOLD_POSITION && + TheCSBots()->IsBombPlanted() && + TheCSBots()->GetBombPlantTimestamp() > me->GetStateTimestamp()) { - // if we are just holding position (due to a radio order) and the bomb has just planted, go defuse it - if (me->GetTask() == CCSBot::HOLD_POSITION && - TheCSBots()->IsBombPlanted() && - TheCSBots()->GetBombPlantTimestamp() > me->GetStateTimestamp()) - { - me->Idle(); - return; - } - - // if we are guarding the defuser and he dies/gives up, stop hiding (to choose another defuser) - if (me->GetTask() == CCSBot::GUARD_BOMB_DEFUSER && !TheCSBots()->GetBombDefuser()) - { - me->Idle(); - return; - } - - // if we are guarding the loose bomb and it is picked up, stop hiding - if (me->GetTask() == CCSBot::GUARD_LOOSE_BOMB && !TheCSBots()->GetLooseBomb()) - { - me->GetChatter()->TheyPickedUpTheBomb(); - me->Idle(); - return; - } - - // if we are guarding a bombsite and the bomb is dropped and we hear about it, stop guarding - if (me->GetTask() == CCSBot::GUARD_BOMB_ZONE && me->GetGameState()->IsLooseBombLocationKnown()) - { - me->Idle(); - return; - } - - // if we are guarding (bombsite, initial encounter, etc) and the bomb is planted, go defuse it - if (me->IsDoingScenario() && me->GetTask() == CCSBot::GUARD_BOMB_ZONE && TheCSBots()->IsBombPlanted()) - { - me->Idle(); - return; - } - + me->Idle(); + return; } - // TERRORIST - else + + // if we are guarding the defuser and he dies/gives up, stop hiding (to choose another defuser) + if (me->GetTask() == CCSBot::GUARD_BOMB_DEFUSER && !TheCSBots()->GetBombDefuser()) { - // if we are near the ticking bomb and someone starts defusing it, attack! - if (TheCSBots()->GetBombDefuser()) - { - Vector toDefuser = TheCSBots()->GetBombDefuser()->pev->origin; - const float hearDefuseRange = 2000.0f; - if ((toDefuser - me->pev->origin).IsLengthLessThan(hearDefuseRange)) - { - // if we are nearby, attack, otherwise move to the bomb (which will cause us to attack when we see defuser) - if (me->CanSeePlantedBomb()) - { - me->Attack(TheCSBots()->GetBombDefuser()); - } - else - { - me->MoveTo(&toDefuser, FASTEST_ROUTE); - me->InhibitLookAround(10.0f); - } - - return; - } - } + me->Idle(); + return; } - break; + + // if we are guarding the loose bomb and it is picked up, stop hiding + if (me->GetTask() == CCSBot::GUARD_LOOSE_BOMB && !TheCSBots()->GetLooseBomb()) + { + me->GetChatter()->TheyPickedUpTheBomb(); + me->Idle(); + return; + } + + // if we are guarding a bombsite and the bomb is dropped and we hear about it, stop guarding + if (me->GetTask() == CCSBot::GUARD_BOMB_ZONE && me->GetGameState()->IsLooseBombLocationKnown()) + { + me->Idle(); + return; + } + + // if we are guarding (bombsite, initial encounter, etc) and the bomb is planted, go defuse it + if (me->IsDoingScenario() && me->GetTask() == CCSBot::GUARD_BOMB_ZONE && TheCSBots()->IsBombPlanted()) + { + me->Idle(); + return; + } + } - case CCSBotManager::SCENARIO_RESCUE_HOSTAGES: + // TERRORIST + else { - // if we're guarding the hostages and they all die or are taken, do something else - if (me->GetTask() == CCSBot::GUARD_HOSTAGES) + // if we are near the ticking bomb and someone starts defusing it, attack! + if (TheCSBots()->GetBombDefuser()) { - if (me->GetGameState()->AreAllHostagesBeingRescued() || me->GetGameState()->AreAllHostagesGone()) + Vector toDefuser = TheCSBots()->GetBombDefuser()->pev->origin; + const float hearDefuseRange = 2000.0f; + if ((toDefuser - me->pev->origin).IsLengthLessThan(hearDefuseRange)) { - me->Idle(); - return; - } - } - else if (me->GetTask() == CCSBot::GUARD_HOSTAGE_RESCUE_ZONE) - { - // if we stumble across a hostage, guard it - CHostage *pHostage = me->GetGameState()->GetNearestVisibleFreeHostage(); - if (pHostage) - { - // we see a free hostage, guard it - CNavArea *area = TheNavAreaGrid.GetNearestNavArea(&pHostage->pev->origin); - if (area) + // if we are nearby, attack, otherwise move to the bomb (which will cause us to attack when we see defuser) + if (me->CanSeePlantedBomb()) { - me->SetTask(CCSBot::GUARD_HOSTAGES); - me->Hide(area); - me->PrintIfWatched("I'm guarding hostages I found\n"); - // don't chatter here - he'll tell us when he's in his hiding spot - return; + me->Attack(TheCSBots()->GetBombDefuser()); } + else + { + me->MoveTo(&toDefuser, FASTEST_ROUTE); + me->InhibitLookAround(10.0f); + } + + return; } } } + break; + } + case CCSBotManager::SCENARIO_RESCUE_HOSTAGES: + { + // if we're guarding the hostages and they all die or are taken, do something else + if (me->GetTask() == CCSBot::GUARD_HOSTAGES) + { + if (me->GetGameState()->AreAllHostagesBeingRescued() || me->GetGameState()->AreAllHostagesGone()) + { + me->Idle(); + return; + } + } + else if (me->GetTask() == CCSBot::GUARD_HOSTAGE_RESCUE_ZONE) + { + // if we stumble across a hostage, guard it + CHostage *pHostage = me->GetGameState()->GetNearestVisibleFreeHostage(); + if (pHostage) + { + // we see a free hostage, guard it + CNavArea *area = TheNavAreaGrid.GetNearestNavArea(&pHostage->pev->origin); + if (area) + { + me->SetTask(CCSBot::GUARD_HOSTAGES); + me->Hide(area); + me->PrintIfWatched("I'm guarding hostages I found\n"); + // don't chatter here - he'll tell us when he's in his hiding spot + return; + } + } + } + } } bool isSettledInSniper = (me->IsSniper() && m_isAtSpot) ? true : false; diff --git a/regamedll/dlls/bot/states/cs_bot_idle.cpp b/regamedll/dlls/bot/states/cs_bot_idle.cpp index c0598577..cfa8fbcd 100644 --- a/regamedll/dlls/bot/states/cs_bot_idle.cpp +++ b/regamedll/dlls/bot/states/cs_bot_idle.cpp @@ -114,50 +114,236 @@ void IdleState::OnUpdate(CCSBot *me) // Scenario logic switch (TheCSBots()->GetScenario()) { - case CCSBotManager::SCENARIO_DEFUSE_BOMB: + case CCSBotManager::SCENARIO_DEFUSE_BOMB: + { + // if this is a bomb game and we have the bomb, go plant it + if (me->m_iTeam == TERRORIST) { - // if this is a bomb game and we have the bomb, go plant it - if (me->m_iTeam == TERRORIST) + if (me->GetGameState()->IsBombPlanted()) { - if (me->GetGameState()->IsBombPlanted()) + if (me->GetGameState()->GetPlantedBombsite() != CSGameState::UNKNOWN) { - if (me->GetGameState()->GetPlantedBombsite() != CSGameState::UNKNOWN) - { - // T's always know where the bomb is - go defend it - const CCSBotManager::Zone *zone = TheCSBots()->GetZone(me->GetGameState()->GetPlantedBombsite()); + // T's always know where the bomb is - go defend it + const CCSBotManager::Zone *zone = TheCSBots()->GetZone(me->GetGameState()->GetPlantedBombsite()); #ifdef REGAMEDLL_FIXES - if (zone) + if (zone) #endif + { + me->SetTask(CCSBot::GUARD_TICKING_BOMB); + + Place place = TheNavAreaGrid.GetPlace(&zone->m_center); + if (place != UNDEFINED_PLACE) { - me->SetTask(CCSBot::GUARD_TICKING_BOMB); - - Place place = TheNavAreaGrid.GetPlace(&zone->m_center); - if (place != UNDEFINED_PLACE) + // pick a random hiding spot in this place + const Vector *spot = FindRandomHidingSpot(me, place, me->IsSniper()); + if (spot) { - // pick a random hiding spot in this place - const Vector *spot = FindRandomHidingSpot(me, place, me->IsSniper()); - if (spot) - { - me->Hide(spot); - return; - } + me->Hide(spot); + return; } + } + + // hide nearby + me->Hide(TheNavAreaGrid.GetNearestNavArea(&zone->m_center)); + return; + } + } + else + { + // ask our teammates where the bomb is + me->GetChatter()->RequestBombLocation(); + + // we dont know where the bomb is - we must search the bombsites + int zoneIndex = me->GetGameState()->GetNextBombsiteToSearch(); + + // move to bombsite - if we reach it, we'll update its cleared status, causing us to select another + const Vector *pos = TheCSBots()->GetRandomPositionInZone(TheCSBots()->GetZone(zoneIndex)); + if (pos) + { + me->SetTask(CCSBot::FIND_TICKING_BOMB); + me->MoveTo(pos); + return; + } + } + } + else if (me->IsCarryingBomb()) + { + // if we're at a bomb site, plant the bomb + if (me->IsAtBombsite()) + { + // plant it + me->SetTask(CCSBot::PLANT_BOMB); + me->PlantBomb(); + + // radio to the team + me->GetChatter()->PlantingTheBomb(me->GetPlace()); + + return; + } + else if (TheCSBots()->IsTimeToPlantBomb()) + { + // move to the closest bomb site + const CCSBotManager::Zone *zone = TheCSBots()->GetClosestZone(me->GetLastKnownArea(), PathCost(me)); + if (zone) + { + // pick a random spot within the bomb zone + const Vector *pos = TheCSBots()->GetRandomPositionInZone(zone); + if (pos) + { + // move to bombsite + me->SetTask(CCSBot::PLANT_BOMB); + me->Run(); + me->MoveTo(pos); - // hide nearby - me->Hide(TheNavAreaGrid.GetNearestNavArea(&zone->m_center)); return; } } + } + } + else + { + // small chance of sniper camping on offense, if we aren't carrying the bomb + if (me->GetFriendsRemaining() && me->IsSniper() && RANDOM_FLOAT(0, 100.0f) < offenseSniperCampChance) + { + me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); + me->Hide(me->GetLastKnownArea(), RANDOM_FLOAT(10.0f, 30.0f), sniperHideRange); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + me->PrintIfWatched("Sniping!\n"); + return; + } + + // if the bomb is loose (on the ground), go get it + if (me->NoticeLooseBomb()) + { + me->FetchBomb(); + return; + } + + // if bomb has been planted, and we hear it, move to a hiding spot near the bomb and guard it + if (!me->IsRogue() && me->GetGameState()->IsBombPlanted() && me->GetGameState()->GetBombPosition()) + { + const Vector *bombPos = me->GetGameState()->GetBombPosition(); + + if (bombPos) + { + me->SetTask(CCSBot::GUARD_TICKING_BOMB); + me->Hide(TheNavAreaGrid.GetNavArea(bombPos)); + return; + } + } + } + } + // CT + else + { + if (me->GetGameState()->IsBombPlanted()) + { + // if the bomb has been planted, attempt to defuse it + const Vector *bombPos = me->GetGameState()->GetBombPosition(); + if (bombPos) + { + // if someone is defusing the bomb, guard them + if (TheCSBots()->GetBombDefuser()) + { + if (!me->IsRogue()) + { + me->SetTask(CCSBot::GUARD_BOMB_DEFUSER); + me->Hide(TheNavAreaGrid.GetNavArea(bombPos)); + return; + } + } + else if (me->IsDoingScenario()) + { + // move to the bomb and defuse it + me->SetTask(CCSBot::DEFUSE_BOMB); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + me->MoveTo(bombPos); + return; + } else { - // ask our teammates where the bomb is - me->GetChatter()->RequestBombLocation(); + // we're not allowed to defuse, guard the bomb zone + me->SetTask(CCSBot::GUARD_BOMB_ZONE); + me->Hide(TheNavAreaGrid.GetNavArea(bombPos)); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + return; + } + } + else if (me->GetGameState()->GetPlantedBombsite() != CSGameState::UNKNOWN) + { + // we know which bombsite, but not exactly where the bomb is, go there + const CCSBotManager::Zone *zone = TheCSBots()->GetZone(me->GetGameState()->GetPlantedBombsite()); + if (zone) + { + if (me->IsDoingScenario()) + { + me->SetTask(CCSBot::DEFUSE_BOMB); + me->MoveTo(&zone->m_center); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + return; + } + else + { + // we're not allowed to defuse, guard the bomb zone + me->SetTask(CCSBot::GUARD_BOMB_ZONE); + me->Hide(TheNavAreaGrid.GetNavArea(&zone->m_center)); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + return; + } + } + } + else + { + // we dont know where the bomb is - we must search the bombsites + // find closest un-cleared bombsite + const CCSBotManager::Zone *zone = nullptr; + float travelDistance = 9999999.9f; - // we dont know where the bomb is - we must search the bombsites + for (int z = 0; z < TheCSBots()->GetZoneCount(); z++) + { + if (TheCSBots()->GetZone(z)->m_areaCount == 0) + continue; + + // don't check bombsites that have been cleared + if (me->GetGameState()->IsBombsiteClear(z)) + continue; + + // just use the first overlapping nav area as a reasonable approximation + ShortestPathCost pathCost = ShortestPathCost(); + float_precision dist = NavAreaTravelDistance(me->GetLastKnownArea(), TheNavAreaGrid.GetNearestNavArea(&TheCSBots()->GetZone(z)->m_center), pathCost); + +#ifdef REGAMEDLL_FIXES + if (dist < 0.0f) + continue; +#endif + + if (dist < travelDistance) + { + zone = TheCSBots()->GetZone(z); + travelDistance = dist; + } + } + + if (zone) + { + const float farAwayRange = 2000.0f; + if (travelDistance > farAwayRange) + { + zone = nullptr; + } + } + + // if closest bombsite is "far away", pick one at random + if (!zone) + { int zoneIndex = me->GetGameState()->GetNextBombsiteToSearch(); + zone = TheCSBots()->GetZone(zoneIndex); + } - // move to bombsite - if we reach it, we'll update its cleared status, causing us to select another - const Vector *pos = TheCSBots()->GetRandomPositionInZone(TheCSBots()->GetZone(zoneIndex)); + // move to bombsite - if we reach it, we'll update its cleared status, causing us to select another + if (zone) + { + const Vector *pos = TheCSBots()->GetRandomPositionInZone(zone); if (pos) { me->SetTask(CCSBot::FIND_TICKING_BOMB); @@ -166,627 +352,441 @@ void IdleState::OnUpdate(CCSBot *me) } } } - else if (me->IsCarryingBomb()) - { - // if we're at a bomb site, plant the bomb - if (me->IsAtBombsite()) - { - // plant it - me->SetTask(CCSBot::PLANT_BOMB); - me->PlantBomb(); - // radio to the team - me->GetChatter()->PlantingTheBomb(me->GetPlace()); - - return; - } - else if (TheCSBots()->IsTimeToPlantBomb()) - { - // move to the closest bomb site - const CCSBotManager::Zone *zone = TheCSBots()->GetClosestZone(me->GetLastKnownArea(), PathCost(me)); - if (zone) - { - // pick a random spot within the bomb zone - const Vector *pos = TheCSBots()->GetRandomPositionInZone(zone); - if (pos) - { - // move to bombsite - me->SetTask(CCSBot::PLANT_BOMB); - me->Run(); - me->MoveTo(pos); - - return; - } - } - } - } - else - { - // small chance of sniper camping on offense, if we aren't carrying the bomb - if (me->GetFriendsRemaining() && me->IsSniper() && RANDOM_FLOAT(0, 100.0f) < offenseSniperCampChance) - { - me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); - me->Hide(me->GetLastKnownArea(), RANDOM_FLOAT(10.0f, 30.0f), sniperHideRange); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - me->PrintIfWatched("Sniping!\n"); - return; - } - - // if the bomb is loose (on the ground), go get it - if (me->NoticeLooseBomb()) - { - me->FetchBomb(); - return; - } - - // if bomb has been planted, and we hear it, move to a hiding spot near the bomb and guard it - if (!me->IsRogue() && me->GetGameState()->IsBombPlanted() && me->GetGameState()->GetBombPosition()) - { - const Vector *bombPos = me->GetGameState()->GetBombPosition(); - - if (bombPos) - { - me->SetTask(CCSBot::GUARD_TICKING_BOMB); - me->Hide(TheNavAreaGrid.GetNavArea(bombPos)); - return; - } - } - } + assert((0, "A CT bot doesn't know what to do while the bomb is planted!\n")); } - // CT - else + + // if we have a sniper rifle, we like to camp, whether rogue or not + if (me->IsSniper()) { - if (me->GetGameState()->IsBombPlanted()) + if (RANDOM_FLOAT(0, 100) <= defenseSniperCampChance) { - // if the bomb has been planted, attempt to defuse it - const Vector *bombPos = me->GetGameState()->GetBombPosition(); - if (bombPos) + CNavArea *snipingArea = nullptr; + + // if the bomb is loose, snipe near it + if (me->GetGameState()->IsLooseBombLocationKnown()) { - // if someone is defusing the bomb, guard them - if (TheCSBots()->GetBombDefuser()) - { - if (!me->IsRogue()) - { - me->SetTask(CCSBot::GUARD_BOMB_DEFUSER); - me->Hide(TheNavAreaGrid.GetNavArea(bombPos)); - return; - } - } - else if (me->IsDoingScenario()) - { - // move to the bomb and defuse it - me->SetTask(CCSBot::DEFUSE_BOMB); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - me->MoveTo(bombPos); - return; - } - else - { - // we're not allowed to defuse, guard the bomb zone - me->SetTask(CCSBot::GUARD_BOMB_ZONE); - me->Hide(TheNavAreaGrid.GetNavArea(bombPos)); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - return; - } - } - else if (me->GetGameState()->GetPlantedBombsite() != CSGameState::UNKNOWN) - { - // we know which bombsite, but not exactly where the bomb is, go there - const CCSBotManager::Zone *zone = TheCSBots()->GetZone(me->GetGameState()->GetPlantedBombsite()); - if (zone) - { - if (me->IsDoingScenario()) - { - me->SetTask(CCSBot::DEFUSE_BOMB); - me->MoveTo(&zone->m_center); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - return; - } - else - { - // we're not allowed to defuse, guard the bomb zone - me->SetTask(CCSBot::GUARD_BOMB_ZONE); - me->Hide(TheNavAreaGrid.GetNavArea(&zone->m_center)); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - return; - } - } + snipingArea = TheNavAreaGrid.GetNearestNavArea(me->GetGameState()->GetBombPosition()); + me->PrintIfWatched("Sniping near loose bomb\n"); } else { - // we dont know where the bomb is - we must search the bombsites - // find closest un-cleared bombsite - const CCSBotManager::Zone *zone = nullptr; - float travelDistance = 9999999.9f; - - for (int z = 0; z < TheCSBots()->GetZoneCount(); z++) - { - if (TheCSBots()->GetZone(z)->m_areaCount == 0) - continue; - - // don't check bombsites that have been cleared - if (me->GetGameState()->IsBombsiteClear(z)) - continue; - - // just use the first overlapping nav area as a reasonable approximation - ShortestPathCost pathCost = ShortestPathCost(); - float_precision dist = NavAreaTravelDistance(me->GetLastKnownArea(), TheNavAreaGrid.GetNearestNavArea(&TheCSBots()->GetZone(z)->m_center), pathCost); - -#ifdef REGAMEDLL_FIXES - if (dist < 0.0f) - continue; -#endif - - if (dist < travelDistance) - { - zone = TheCSBots()->GetZone(z); - travelDistance = dist; - } - } - - if (zone) - { - const float farAwayRange = 2000.0f; - if (travelDistance > farAwayRange) - { - zone = nullptr; - } - } - - // if closest bombsite is "far away", pick one at random - if (!zone) - { - int zoneIndex = me->GetGameState()->GetNextBombsiteToSearch(); - zone = TheCSBots()->GetZone(zoneIndex); - } - - // move to bombsite - if we reach it, we'll update its cleared status, causing us to select another - if (zone) - { - const Vector *pos = TheCSBots()->GetRandomPositionInZone(zone); - if (pos) - { - me->SetTask(CCSBot::FIND_TICKING_BOMB); - me->MoveTo(pos); - return; - } - } - } - - assert((0, "A CT bot doesn't know what to do while the bomb is planted!\n")); - } - - // if we have a sniper rifle, we like to camp, whether rogue or not - if (me->IsSniper()) - { - if (RANDOM_FLOAT(0, 100) <= defenseSniperCampChance) - { - CNavArea *snipingArea = nullptr; - - // if the bomb is loose, snipe near it - if (me->GetGameState()->IsLooseBombLocationKnown()) - { - snipingArea = TheNavAreaGrid.GetNearestNavArea(me->GetGameState()->GetBombPosition()); - me->PrintIfWatched("Sniping near loose bomb\n"); - } - else - { - // snipe bomb zone(s) - const CCSBotManager::Zone *zone = TheCSBots()->GetRandomZone(); - if (zone) - { - snipingArea = TheCSBots()->GetRandomAreaInZone(zone); - me->PrintIfWatched("Sniping near bombsite\n"); - } - } - - if (snipingArea) - { - me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); - me->Hide(snipingArea, -1.0f, sniperHideRange); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - return; - } - } - } - - // rogues just hunt, unless they want to snipe - // if the whole team has decided to rush, hunt - // if we know the bomb is dropped, hunt for enemies and the loose bomb - if (me->IsRogue() || TheCSBots()->IsDefenseRushing() || me->GetGameState()->IsLooseBombLocationKnown()) - { - me->Hunt(); - return; - } - - // the lower our morale gets, the more we want to camp the bomb zone(s) - // only decide to camp at the start of the round, or if we haven't seen anything for a long time - if (me->IsSafe() || me->HasNotSeenEnemyForLongTime()) - { - float guardBombsiteChance = -34.0f * me->GetMorale(); - - if (RANDOM_FLOAT(0.0f, 100.0f) < guardBombsiteChance) - { - float guardRange = 500.0f + 100.0f * (me->GetMorale() + 3); - - // guard bomb zone(s) + // snipe bomb zone(s) const CCSBotManager::Zone *zone = TheCSBots()->GetRandomZone(); if (zone) { - CNavArea *area = TheCSBots()->GetRandomAreaInZone(zone); - if (area) - { - me->PrintIfWatched("I'm guarding a bombsite\n"); - me->GetChatter()->AnnouncePlan("GoingToDefendBombsite", area->GetPlace()); - me->SetTask(CCSBot::GUARD_BOMB_ZONE); - me->Hide(area, -1.0, guardRange); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - return; - } + snipingArea = TheCSBots()->GetRandomAreaInZone(zone); + me->PrintIfWatched("Sniping near bombsite\n"); } } + + if (snipingArea) + { + me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); + me->Hide(snipingArea, -1.0f, sniperHideRange); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + return; + } } } - break; - } - case CCSBotManager::SCENARIO_ESCORT_VIP: - { - if (me->m_iTeam == TERRORIST) + + // rogues just hunt, unless they want to snipe + // if the whole team has decided to rush, hunt + // if we know the bomb is dropped, hunt for enemies and the loose bomb + if (me->IsRogue() || TheCSBots()->IsDefenseRushing() || me->GetGameState()->IsLooseBombLocationKnown()) { - // if we have a sniper rifle, we like to camp, whether rogue or not - if (me->IsSniper()) + me->Hunt(); + return; + } + + // the lower our morale gets, the more we want to camp the bomb zone(s) + // only decide to camp at the start of the round, or if we haven't seen anything for a long time + if (me->IsSafe() || me->HasNotSeenEnemyForLongTime()) + { + float guardBombsiteChance = -34.0f * me->GetMorale(); + + if (RANDOM_FLOAT(0.0f, 100.0f) < guardBombsiteChance) { - if (RANDOM_FLOAT(0, 100) <= defenseSniperCampChance) - { - // snipe escape zone(s) - const CCSBotManager::Zone *zone = TheCSBots()->GetRandomZone(); - if (zone) - { - CNavArea *area = TheCSBots()->GetRandomAreaInZone(zone); - if (area) - { - me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); - me->Hide(area, -1.0, sniperHideRange); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - me->PrintIfWatched("Sniping near escape zone\n"); - return; - } - } - } - } + float guardRange = 500.0f + 100.0f * (me->GetMorale() + 3); - // rogues just hunt, unless they want to snipe - // if the whole team has decided to rush, hunt - if (me->IsRogue() || TheCSBots()->IsDefenseRushing()) - break; - - // the lower our morale gets, the more we want to camp the escape zone(s) - float guardEscapeZoneChance = -34.0f * me->GetMorale(); - - if (RANDOM_FLOAT(0.0f, 100.0f) < guardEscapeZoneChance) - { - // guard escape zone(s) + // guard bomb zone(s) const CCSBotManager::Zone *zone = TheCSBots()->GetRandomZone(); if (zone) { CNavArea *area = TheCSBots()->GetRandomAreaInZone(zone); if (area) { - // guard the escape zone - stay closer if our morale is low - me->SetTask(CCSBot::GUARD_VIP_ESCAPE_ZONE); - me->PrintIfWatched("I'm guarding an escape zone\n"); - - float escapeGuardRange = 750.0f + 250.0f * (me->GetMorale() + 3); - me->Hide(area, -1.0, escapeGuardRange); + me->PrintIfWatched("I'm guarding a bombsite\n"); + me->GetChatter()->AnnouncePlan("GoingToDefendBombsite", area->GetPlace()); + me->SetTask(CCSBot::GUARD_BOMB_ZONE); + me->Hide(area, -1.0, guardRange); me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); return; } } } } - // CT - else + } + break; + } + case CCSBotManager::SCENARIO_ESCORT_VIP: + { + if (me->m_iTeam == TERRORIST) + { + // if we have a sniper rifle, we like to camp, whether rogue or not + if (me->IsSniper()) { - if (me->m_bIsVIP) + if (RANDOM_FLOAT(0, 100) <= defenseSniperCampChance) { - // if early in round, pick a random zone, otherwise pick closest zone - const float earlyTime = 20.0f; - const CCSBotManager::Zone *zone = nullptr; - - if (TheCSBots()->GetElapsedRoundTime() < earlyTime) - { - // pick random zone - zone = TheCSBots()->GetRandomZone(); - } - else - { - // pick closest zone - zone = TheCSBots()->GetClosestZone(me->GetLastKnownArea(), PathCost(me)); - } - + // snipe escape zone(s) + const CCSBotManager::Zone *zone = TheCSBots()->GetRandomZone(); if (zone) { - // pick a random spot within the escape zone - const Vector *pos = TheCSBots()->GetRandomPositionInZone(zone); - if (pos) + CNavArea *area = TheCSBots()->GetRandomAreaInZone(zone); + if (area) { - // move to escape zone - me->SetTask(CCSBot::VIP_ESCAPE); - me->Run(); - me->MoveTo(pos); - - // tell team to follow - const float repeatTime = 30.0f; - if (me->GetFriendsRemaining() && TheCSBots()->GetRadioMessageInterval(EVENT_RADIO_FOLLOW_ME, me->m_iTeam) > repeatTime) - me->SendRadioMessage(EVENT_RADIO_FOLLOW_ME); + me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); + me->Hide(area, -1.0, sniperHideRange); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + me->PrintIfWatched("Sniping near escape zone\n"); return; } } } - else + } + + // rogues just hunt, unless they want to snipe + // if the whole team has decided to rush, hunt + if (me->IsRogue() || TheCSBots()->IsDefenseRushing()) + break; + + // the lower our morale gets, the more we want to camp the escape zone(s) + float guardEscapeZoneChance = -34.0f * me->GetMorale(); + + if (RANDOM_FLOAT(0.0f, 100.0f) < guardEscapeZoneChance) + { + // guard escape zone(s) + const CCSBotManager::Zone *zone = TheCSBots()->GetRandomZone(); + if (zone) { - // small chance of sniper camping on offense, if we aren't VIP - if (me->GetFriendsRemaining() && me->IsSniper() && RANDOM_FLOAT(0, 100.0f) < offenseSniperCampChance) + CNavArea *area = TheCSBots()->GetRandomAreaInZone(zone); + if (area) { - me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); - me->Hide(me->GetLastKnownArea(), RANDOM_FLOAT(10.0f, 30.0f), sniperHideRange); + // guard the escape zone - stay closer if our morale is low + me->SetTask(CCSBot::GUARD_VIP_ESCAPE_ZONE); + me->PrintIfWatched("I'm guarding an escape zone\n"); + + float escapeGuardRange = 750.0f + 250.0f * (me->GetMorale() + 3); + me->Hide(area, -1.0, escapeGuardRange); me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - me->PrintIfWatched("Sniping!\n"); return; } } } - break; } - case CCSBotManager::SCENARIO_RESCUE_HOSTAGES: + // CT + else { - if (me->m_iTeam == TERRORIST) + if (me->m_bIsVIP) { - bool campHostages; + // if early in round, pick a random zone, otherwise pick closest zone + const float earlyTime = 20.0f; + const CCSBotManager::Zone *zone = nullptr; - // if we are in early game, camp the hostages - if (me->IsSafe()) + if (TheCSBots()->GetElapsedRoundTime() < earlyTime) { - campHostages = true; - } - else if (me->GetGameState()->HaveSomeHostagesBeenTaken() || me->GetGameState()->AreAllHostagesBeingRescued()) - { - campHostages = false; + // pick random zone + zone = TheCSBots()->GetRandomZone(); } else { - // later in the game, camp either hostages or escape zone - const float campZoneChance = 100.0f * (TheCSBots()->GetElapsedRoundTime() - me->GetSafeTime()) / 120.0f; - campHostages = (RANDOM_FLOAT(0, 100) > campZoneChance) ? true : false; + // pick closest zone + zone = TheCSBots()->GetClosestZone(me->GetLastKnownArea(), PathCost(me)); } - // if we have a sniper rifle, we like to camp, whether rogue or not - if (me->IsSniper()) + if (zone) { - if (RANDOM_FLOAT(0, 100) <= defenseSniperCampChance) + // pick a random spot within the escape zone + const Vector *pos = TheCSBots()->GetRandomPositionInZone(zone); + if (pos) { - const Vector *hostagePos = me->GetGameState()->GetRandomFreeHostagePosition(); - if (hostagePos && campHostages) + // move to escape zone + me->SetTask(CCSBot::VIP_ESCAPE); + me->Run(); + me->MoveTo(pos); + + // tell team to follow + const float repeatTime = 30.0f; + if (me->GetFriendsRemaining() && TheCSBots()->GetRadioMessageInterval(EVENT_RADIO_FOLLOW_ME, me->m_iTeam) > repeatTime) + me->SendRadioMessage(EVENT_RADIO_FOLLOW_ME); + return; + } + } + } + else + { + // small chance of sniper camping on offense, if we aren't VIP + if (me->GetFriendsRemaining() && me->IsSniper() && RANDOM_FLOAT(0, 100.0f) < offenseSniperCampChance) + { + me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); + me->Hide(me->GetLastKnownArea(), RANDOM_FLOAT(10.0f, 30.0f), sniperHideRange); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + me->PrintIfWatched("Sniping!\n"); + return; + } + } + } + break; + } + case CCSBotManager::SCENARIO_RESCUE_HOSTAGES: + { + if (me->m_iTeam == TERRORIST) + { + bool campHostages; + + // if we are in early game, camp the hostages + if (me->IsSafe()) + { + campHostages = true; + } + else if (me->GetGameState()->HaveSomeHostagesBeenTaken() || me->GetGameState()->AreAllHostagesBeingRescued()) + { + campHostages = false; + } + else + { + // later in the game, camp either hostages or escape zone + const float campZoneChance = 100.0f * (TheCSBots()->GetElapsedRoundTime() - me->GetSafeTime()) / 120.0f; + campHostages = (RANDOM_FLOAT(0, 100) > campZoneChance) ? true : false; + } + + // if we have a sniper rifle, we like to camp, whether rogue or not + if (me->IsSniper()) + { + if (RANDOM_FLOAT(0, 100) <= defenseSniperCampChance) + { + const Vector *hostagePos = me->GetGameState()->GetRandomFreeHostagePosition(); + if (hostagePos && campHostages) + { + me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); + me->PrintIfWatched("Sniping near hostages\n"); + me->Hide(TheNavAreaGrid.GetNearestNavArea(hostagePos), -1.0, sniperHideRange); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + return; + } + else + { + // camp the escape zone(s) + if (me->GuardRandomZone(sniperHideRange)) { me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); - me->PrintIfWatched("Sniping near hostages\n"); - me->Hide(TheNavAreaGrid.GetNearestNavArea(hostagePos), -1.0, sniperHideRange); + me->PrintIfWatched("Sniping near a rescue zone\n"); me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); return; } - else - { - // camp the escape zone(s) - if (me->GuardRandomZone(sniperHideRange)) - { - me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); - me->PrintIfWatched("Sniping near a rescue zone\n"); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - return; - } - } } } + } - // if safe time is up, and we stumble across a hostage, guard it - if (!me->IsSafe() && !me->IsRogue()) + // if safe time is up, and we stumble across a hostage, guard it + if (!me->IsSafe() && !me->IsRogue()) + { + CBaseEntity *pHostage = me->GetGameState()->GetNearestVisibleFreeHostage(); + if (pHostage) { - CBaseEntity *pHostage = me->GetGameState()->GetNearestVisibleFreeHostage(); - if (pHostage) + // we see a free hostage, guard it + CNavArea *area = TheNavAreaGrid.GetNearestNavArea(&pHostage->pev->origin); + if (area) { - // we see a free hostage, guard it - CNavArea *area = TheNavAreaGrid.GetNearestNavArea(&pHostage->pev->origin); - if (area) - { - me->SetTask(CCSBot::GUARD_HOSTAGES); - me->Hide(area); - me->PrintIfWatched("I'm guarding hostages I found\n"); - // don't chatter here - he'll tell us when he's in his hiding spot - return; - } + me->SetTask(CCSBot::GUARD_HOSTAGES); + me->Hide(area); + me->PrintIfWatched("I'm guarding hostages I found\n"); + // don't chatter here - he'll tell us when he's in his hiding spot + return; } } + } - // decide if we want to hunt, or guard - const float huntChance = 70.0f + 25.0f * me->GetMorale(); + // decide if we want to hunt, or guard + const float huntChance = 70.0f + 25.0f * me->GetMorale(); - // rogues just hunt, unless they want to snipe - // if the whole team has decided to rush, hunt - if (me->GetFriendsRemaining()) + // rogues just hunt, unless they want to snipe + // if the whole team has decided to rush, hunt + if (me->GetFriendsRemaining()) + { + if (me->IsRogue() || TheCSBots()->IsDefenseRushing() || RANDOM_FLOAT(0, 100) < huntChance) { - if (me->IsRogue() || TheCSBots()->IsDefenseRushing() || RANDOM_FLOAT(0, 100) < huntChance) + me->Hunt(); + return; + } + } + + // decide whether to camp the hostages or the escape zones + const Vector *hostagePos = me->GetGameState()->GetRandomFreeHostagePosition(); + if (hostagePos && campHostages) + { + CNavArea *area = TheNavAreaGrid.GetNearestNavArea(hostagePos); + if (area) + { + // guard the hostages - stay closer to hostages if our morale is low + me->SetTask(CCSBot::GUARD_HOSTAGES); + me->PrintIfWatched("I'm guarding hostages\n"); + + float hostageGuardRange = 750.0f + 250.0f * (me->GetMorale() + 3); + me->Hide(area, -1.0, hostageGuardRange); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + + if (RANDOM_FLOAT(0, 100) < 50) + me->GetChatter()->GuardingHostages(area->GetPlace(), IS_PLAN); + + return; + } + } + + // guard rescue zone(s) + if (me->GuardRandomZone()) + { + me->SetTask(CCSBot::GUARD_HOSTAGE_RESCUE_ZONE); + me->PrintIfWatched("I'm guarding a rescue zone\n"); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + me->GetChatter()->GuardingHostageEscapeZone(IS_PLAN); + return; + } + } + // CT + else + { + // only decide to do something else if we aren't already rescuing hostages + if (!me->GetHostageEscortCount()) + { + // small chance of sniper camping on offense + if (me->GetFriendsRemaining() && me->IsSniper() && RANDOM_FLOAT(0, 100.0f) < offenseSniperCampChance) + { + me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); + me->Hide(me->GetLastKnownArea(), RANDOM_FLOAT(10.0f, 30.0f), sniperHideRange); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + me->PrintIfWatched("Sniping!\n"); + return; + } + + if (me->GetFriendsRemaining() && !me->GetHostageEscortCount()) + { + // rogues just hunt, unless all friends are dead + // if we have friends left, we might go hunting instead of hostage rescuing + const float huntChance = 33.3f; + if (me->IsRogue() || RANDOM_FLOAT(0.0f, 100.0f) < huntChance) { me->Hunt(); return; } } - - // decide whether to camp the hostages or the escape zones - const Vector *hostagePos = me->GetGameState()->GetRandomFreeHostagePosition(); - if (hostagePos && campHostages) - { - CNavArea *area = TheNavAreaGrid.GetNearestNavArea(hostagePos); - if (area) - { - // guard the hostages - stay closer to hostages if our morale is low - me->SetTask(CCSBot::GUARD_HOSTAGES); - me->PrintIfWatched("I'm guarding hostages\n"); - - float hostageGuardRange = 750.0f + 250.0f * (me->GetMorale() + 3); - me->Hide(area, -1.0, hostageGuardRange); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - - if (RANDOM_FLOAT(0, 100) < 50) - me->GetChatter()->GuardingHostages(area->GetPlace(), IS_PLAN); - - return; - } - } - - // guard rescue zone(s) - if (me->GuardRandomZone()) - { - me->SetTask(CCSBot::GUARD_HOSTAGE_RESCUE_ZONE); - me->PrintIfWatched("I'm guarding a rescue zone\n"); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - me->GetChatter()->GuardingHostageEscapeZone(IS_PLAN); - return; - } } - // CT - else + + // look for free hostages - CT's have radar so they know where hostages are at all times + CHostage *pHostage = me->GetGameState()->GetNearestFreeHostage(); + + // if we are not allowed to do the scenario, guard the hostages to clear the area for the human(s) + if (!me->IsDoingScenario()) { - // only decide to do something else if we aren't already rescuing hostages - if (!me->GetHostageEscortCount()) - { - // small chance of sniper camping on offense - if (me->GetFriendsRemaining() && me->IsSniper() && RANDOM_FLOAT(0, 100.0f) < offenseSniperCampChance) - { - me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); - me->Hide(me->GetLastKnownArea(), RANDOM_FLOAT(10.0f, 30.0f), sniperHideRange); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - me->PrintIfWatched("Sniping!\n"); - return; - } - - if (me->GetFriendsRemaining() && !me->GetHostageEscortCount()) - { - // rogues just hunt, unless all friends are dead - // if we have friends left, we might go hunting instead of hostage rescuing - const float huntChance = 33.3f; - if (me->IsRogue() || RANDOM_FLOAT(0.0f, 100.0f) < huntChance) - { - me->Hunt(); - return; - } - } - } - - // look for free hostages - CT's have radar so they know where hostages are at all times - CHostage *pHostage = me->GetGameState()->GetNearestFreeHostage(); - - // if we are not allowed to do the scenario, guard the hostages to clear the area for the human(s) - if (!me->IsDoingScenario()) - { - if (pHostage) - { - CNavArea *area = TheNavAreaGrid.GetNearestNavArea(&pHostage->pev->origin); - if (area) - { - me->SetTask(CCSBot::GUARD_HOSTAGES); - me->Hide(area); - me->PrintIfWatched("I'm securing the hostages for a human to rescue\n"); - return; - } - } - - me->Hunt(); - return; - } - - bool fetchHostages = false; - bool rescueHostages = false; - const CCSBotManager::Zone *zone = nullptr; - me->SetGoalEntity(nullptr); - - // if we are escorting hostages, determine where to take them - if (me->GetHostageEscortCount()) - zone = TheCSBots()->GetClosestZone(me->GetLastKnownArea(), PathCost(me, FASTEST_ROUTE)); - - // if we are escorting hostages and there are more hostages to rescue, - // determine whether it's faster to rescue the ones we have, or go get the remaining ones if (pHostage) { - if (zone) + CNavArea *area = TheNavAreaGrid.GetNearestNavArea(&pHostage->pev->origin); + if (area) { - PathCost pathCost(me, FASTEST_ROUTE); - float toZone = NavAreaTravelDistance(me->GetLastKnownArea(), zone->m_area[0], pathCost); - float toHostage = NavAreaTravelDistance(me->GetLastKnownArea(), TheNavAreaGrid.GetNearestNavArea(&pHostage->pev->origin), pathCost); + me->SetTask(CCSBot::GUARD_HOSTAGES); + me->Hide(area); + me->PrintIfWatched("I'm securing the hostages for a human to rescue\n"); + return; + } + } - if (toHostage < 0.0f) - { - rescueHostages = true; - } - else - { - if (toZone < toHostage) - rescueHostages = true; - else - fetchHostages = true; - } + me->Hunt(); + return; + } + + bool fetchHostages = false; + bool rescueHostages = false; + const CCSBotManager::Zone *zone = nullptr; + me->SetGoalEntity(nullptr); + + // if we are escorting hostages, determine where to take them + if (me->GetHostageEscortCount()) + zone = TheCSBots()->GetClosestZone(me->GetLastKnownArea(), PathCost(me, FASTEST_ROUTE)); + + // if we are escorting hostages and there are more hostages to rescue, + // determine whether it's faster to rescue the ones we have, or go get the remaining ones + if (pHostage) + { + if (zone) + { + PathCost pathCost(me, FASTEST_ROUTE); + float toZone = NavAreaTravelDistance(me->GetLastKnownArea(), zone->m_area[0], pathCost); + float toHostage = NavAreaTravelDistance(me->GetLastKnownArea(), TheNavAreaGrid.GetNearestNavArea(&pHostage->pev->origin), pathCost); + + if (toHostage < 0.0f) + { + rescueHostages = true; } else { - fetchHostages = true; + if (toZone < toHostage) + rescueHostages = true; + else + fetchHostages = true; } } - else if (zone) + else { - rescueHostages = true; - } - - if (fetchHostages) - { - // go get hostages - me->SetTask(CCSBot::COLLECT_HOSTAGES); - me->Run(); - me->SetGoalEntity(pHostage); - me->ResetWaitForHostagePatience(); - - // if we already have some hostages, move to the others by the quickest route - RouteType route = (me->GetHostageEscortCount()) ? FASTEST_ROUTE : SAFEST_ROUTE; - me->MoveTo(&pHostage->pev->origin, route); - me->PrintIfWatched("I'm collecting hostages\n"); - return; - } - - if (rescueHostages) - { - me->SetTask(CCSBot::RESCUE_HOSTAGES); - me->Run(); - me->SetDisposition(CCSBot::SELF_DEFENSE); - me->MoveTo(TheCSBots()->GetRandomPositionInZone(zone), FASTEST_ROUTE); - me->PrintIfWatched("I'm rescuing hostages\n"); - me->GetChatter()->EscortingHostages(); - return; + fetchHostages = true; } } - break; - } - // deathmatch - default: - { - // sniping check - if (me->GetFriendsRemaining() && me->IsSniper() && RANDOM_FLOAT(0, 100.0f) < offenseSniperCampChance) + else if (zone) { - me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); - me->Hide(me->GetLastKnownArea(), RANDOM_FLOAT(10.0f, 30.0f), sniperHideRange); - me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); - me->PrintIfWatched("Sniping!\n"); + rescueHostages = true; + } + + if (fetchHostages) + { + // go get hostages + me->SetTask(CCSBot::COLLECT_HOSTAGES); + me->Run(); + me->SetGoalEntity(pHostage); + me->ResetWaitForHostagePatience(); + + // if we already have some hostages, move to the others by the quickest route + RouteType route = (me->GetHostageEscortCount()) ? FASTEST_ROUTE : SAFEST_ROUTE; + me->MoveTo(&pHostage->pev->origin, route); + me->PrintIfWatched("I'm collecting hostages\n"); + return; + } + + if (rescueHostages) + { + me->SetTask(CCSBot::RESCUE_HOSTAGES); + me->Run(); + me->SetDisposition(CCSBot::SELF_DEFENSE); + me->MoveTo(TheCSBots()->GetRandomPositionInZone(zone), FASTEST_ROUTE); + me->PrintIfWatched("I'm rescuing hostages\n"); + me->GetChatter()->EscortingHostages(); return; } - break; } + break; + } + // deathmatch + default: + { + // sniping check + if (me->GetFriendsRemaining() && me->IsSniper() && RANDOM_FLOAT(0, 100.0f) < offenseSniperCampChance) + { + me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); + me->Hide(me->GetLastKnownArea(), RANDOM_FLOAT(10.0f, 30.0f), sniperHideRange); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + me->PrintIfWatched("Sniping!\n"); + return; + } + break; + } } // if we have nothing special to do, go hunting for enemies diff --git a/regamedll/dlls/bot/states/cs_bot_move_to.cpp b/regamedll/dlls/bot/states/cs_bot_move_to.cpp index 02782006..6d63a481 100644 --- a/regamedll/dlls/bot/states/cs_bot_move_to.cpp +++ b/regamedll/dlls/bot/states/cs_bot_move_to.cpp @@ -44,15 +44,15 @@ void MoveToState::OnEnter(CCSBot *me) RouteType route; switch (me->GetTask()) { - case CCSBot::FIND_TICKING_BOMB: - case CCSBot::DEFUSE_BOMB: - case CCSBot::MOVE_TO_LAST_KNOWN_ENEMY_POSITION: - route = FASTEST_ROUTE; - break; + case CCSBot::FIND_TICKING_BOMB: + case CCSBot::DEFUSE_BOMB: + case CCSBot::MOVE_TO_LAST_KNOWN_ENEMY_POSITION: + route = FASTEST_ROUTE; + break; - default: - route = SAFEST_ROUTE; - break; + default: + route = SAFEST_ROUTE; + break; } // build path to, or nearly to, goal position @@ -84,181 +84,180 @@ void MoveToState::OnUpdate(CCSBot *me) // Scenario logic switch (TheCSBots()->GetScenario()) { - case CCSBotManager::SCENARIO_DEFUSE_BOMB: + case CCSBotManager::SCENARIO_DEFUSE_BOMB: + { + // if the bomb has been planted, find it + // NOTE: This task is used by both CT and T's to find the bomb + if (me->GetTask() == CCSBot::FIND_TICKING_BOMB) { - // if the bomb has been planted, find it - // NOTE: This task is used by both CT and T's to find the bomb - if (me->GetTask() == CCSBot::FIND_TICKING_BOMB) + if (!me->GetGameState()->IsBombPlanted()) { - if (!me->GetGameState()->IsBombPlanted()) - { - // the bomb is not planted - give up this task - me->Idle(); - return; - } + // the bomb is not planted - give up this task + me->Idle(); + return; + } - if (me->GetGameState()->GetPlantedBombsite() != CSGameState::UNKNOWN) - { - // we know where the bomb is planted, stop searching - me->Idle(); - return; - } + if (me->GetGameState()->GetPlantedBombsite() != CSGameState::UNKNOWN) + { + // we know where the bomb is planted, stop searching + me->Idle(); + return; + } - // check off bombsites that we explore or happen to stumble into - for (int z = 0; z < TheCSBots()->GetZoneCount(); z++) - { - // don't re-check zones - if (me->GetGameState()->IsBombsiteClear(z)) - continue; + // check off bombsites that we explore or happen to stumble into + for (int z = 0; z < TheCSBots()->GetZoneCount(); z++) + { + // don't re-check zones + if (me->GetGameState()->IsBombsiteClear(z)) + continue; - if (TheCSBots()->GetZone(z)->m_extent.Contains(&me->pev->origin)) + if (TheCSBots()->GetZone(z)->m_extent.Contains(&me->pev->origin)) + { + // note this bombsite is clear + me->GetGameState()->ClearBombsite(z); + + if (me->m_iTeam == CT) { - // note this bombsite is clear - me->GetGameState()->ClearBombsite(z); + // tell teammates this bombsite is clear + me->GetChatter()->BombsiteClear(z); + } - if (me->m_iTeam == CT) - { - // tell teammates this bombsite is clear - me->GetChatter()->BombsiteClear(z); - } + // find another zone to check + me->Idle(); + return; + } + } - // find another zone to check + // move to a bombsite + break; + } + else if (me->m_iTeam == CT) + { + if (me->GetGameState()->IsBombPlanted()) + { + switch (me->GetTask()) + { + case CCSBot::DEFUSE_BOMB: + { + // if we are trying to defuse the bomb, and someone has started defusing, guard them instead + if (me->CanSeePlantedBomb() && TheCSBots()->GetBombDefuser()) + { + me->GetChatter()->Say("CoveringFriend"); me->Idle(); return; } + break; } - - // move to a bombsite - break; - } - else if (me->m_iTeam == CT) - { - if (me->GetGameState()->IsBombPlanted()) + default: { - switch (me->GetTask()) - { - case CCSBot::DEFUSE_BOMB: - { - // if we are trying to defuse the bomb, and someone has started defusing, guard them instead - if (me->CanSeePlantedBomb() && TheCSBots()->GetBombDefuser()) - { - me->GetChatter()->Say("CoveringFriend"); - me->Idle(); - return; - } - - break; - } - default: - { - // we need to find the bomb - me->Idle(); - return; - } - } + // we need to find the bomb + me->Idle(); + return; + } } } - // TERRORIST - else - { - if (me->GetTask() == CCSBot::PLANT_BOMB) - { - if (me->GetFriendsRemaining()) - { - // if we are about to plant, radio for cover - if (!m_askedForCover) - { - const float nearPlantSite = 50.0f; - if (me->IsAtBombsite() && me->GetPathDistanceRemaining() < nearPlantSite) - { - // radio to the team - me->GetChatter()->PlantingTheBomb(me->GetPlace()); - m_askedForCover = true; - } - - // after we have started to move to the bombsite, tell team we're going to plant, and where - // don't do this if we have already radioed that we are starting to plant - if (!m_radioedPlan) - { - const float radioTime = 2.0f; - if (gpGlobals->time - me->GetStateTimestamp() > radioTime) - { - me->GetChatter()->GoingToPlantTheBomb(TheNavAreaGrid.GetPlace(&m_goalPosition)); - m_radioedPlan = true; - } - } - } - } - } - } - break; } - case CCSBotManager::SCENARIO_RESCUE_HOSTAGES: + // TERRORIST + else { - if (me->GetTask() == CCSBot::COLLECT_HOSTAGES) + if (me->GetTask() == CCSBot::PLANT_BOMB) { - // Since CT's have a radar, they can directly look at the actual hostage state - // check if someone else collected our hostage, or the hostage died or was rescued - CHostage *pHostage = me->GetGoalEntity(); - if (!pHostage || !pHostage->IsAlive() || pHostage->IsFollowingSomeone()) + if (me->GetFriendsRemaining()) { - me->Idle(); - return; - } - - // if our hostage has moved, repath - const float repathToleranceSq = 75.0f * 75.0f; - float error = (pHostage->pev->origin - m_goalPosition).LengthSquared(); - if (error > repathToleranceSq) - { - m_goalPosition = pHostage->pev->origin; - me->ComputePath(TheNavAreaGrid.GetNavArea(&m_goalPosition), &m_goalPosition, SAFEST_ROUTE); - } - - // TODO: Generalize ladder priorities over other tasks - if (!me->IsUsingLadder()) - { - Vector pos = pHostage->pev->origin + Vector(0, 0, HumanHeight * 0.75f); - Vector to = pos - me->pev->origin; - - // look at the hostage as we approach - const float watchHostageRange = 100.0f; - if (to.IsLengthLessThan(watchHostageRange)) + // if we are about to plant, radio for cover + if (!m_askedForCover) { - me->SetLookAt("Hostage", &pos, PRIORITY_LOW, 0.5f); - - // randomly move just a bit to avoid infinite use loops from bad hostage placement - NavRelativeDirType dir = (NavRelativeDirType)RANDOM_LONG(0, 3); - switch (dir) + const float nearPlantSite = 50.0f; + if (me->IsAtBombsite() && me->GetPathDistanceRemaining() < nearPlantSite) { - case LEFT: me->StrafeLeft(); break; - case RIGHT: me->StrafeRight(); break; - case FORWARD: me->MoveForward(); break; - case BACKWARD: me->MoveBackward(); break; + // radio to the team + me->GetChatter()->PlantingTheBomb(me->GetPlace()); + m_askedForCover = true; } - // check if we are close enough to the hostage to talk to him - const float useRange = MAX_PLAYER_USE_RADIUS - 14.0f; // shave off a fudge factor to make sure we're within range - if (to.IsLengthLessThan(useRange)) + // after we have started to move to the bombsite, tell team we're going to plant, and where + // don't do this if we have already radioed that we are starting to plant + if (!m_radioedPlan) { - me->UseEntity(me->GetGoalEntity()); - return; + const float radioTime = 2.0f; + if (gpGlobals->time - me->GetStateTimestamp() > radioTime) + { + me->GetChatter()->GoingToPlantTheBomb(TheNavAreaGrid.GetPlace(&m_goalPosition)); + m_radioedPlan = true; + } } } } } - else if (me->GetTask() == CCSBot::RESCUE_HOSTAGES) + } + break; + } + case CCSBotManager::SCENARIO_RESCUE_HOSTAGES: + { + if (me->GetTask() == CCSBot::COLLECT_HOSTAGES) + { + // Since CT's have a radar, they can directly look at the actual hostage state + // check if someone else collected our hostage, or the hostage died or was rescued + CHostage *pHostage = me->GetGoalEntity(); + if (!pHostage || !pHostage->IsAlive() || pHostage->IsFollowingSomeone()) { - // periodically check if we lost all our hostages - if (me->GetHostageEscortCount() == 0) + me->Idle(); + return; + } + + // if our hostage has moved, repath + const float repathToleranceSq = 75.0f * 75.0f; + float error = (pHostage->pev->origin - m_goalPosition).LengthSquared(); + if (error > repathToleranceSq) + { + m_goalPosition = pHostage->pev->origin; + me->ComputePath(TheNavAreaGrid.GetNavArea(&m_goalPosition), &m_goalPosition, SAFEST_ROUTE); + } + + // TODO: Generalize ladder priorities over other tasks + if (!me->IsUsingLadder()) + { + Vector pos = pHostage->pev->origin + Vector(0, 0, HumanHeight * 0.75f); + Vector to = pos - me->pev->origin; + + // look at the hostage as we approach + const float watchHostageRange = 100.0f; + if (to.IsLengthLessThan(watchHostageRange)) { - // lost our hostages - go get 'em - me->Idle(); - return; + me->SetLookAt("Hostage", &pos, PRIORITY_LOW, 0.5f); + + // randomly move just a bit to avoid infinite use loops from bad hostage placement + NavRelativeDirType dir = (NavRelativeDirType)RANDOM_LONG(0, 3); + switch (dir) + { + case LEFT: me->StrafeLeft(); break; + case RIGHT: me->StrafeRight(); break; + case FORWARD: me->MoveForward(); break; + case BACKWARD: me->MoveBackward(); break; + } + + // check if we are close enough to the hostage to talk to him + const float useRange = MAX_PLAYER_USE_RADIUS - 14.0f; // shave off a fudge factor to make sure we're within range + if (to.IsLengthLessThan(useRange)) + { + me->UseEntity(me->GetGoalEntity()); + return; + } } } - break; } + else if (me->GetTask() == CCSBot::RESCUE_HOSTAGES) + { + // periodically check if we lost all our hostages + if (me->GetHostageEscortCount() == 0) + { + // lost our hostages - go get 'em + me->Idle(); + return; + } + } + break; + } } if (me->UpdatePathMovement() != CCSBot::PROGRESSING) @@ -266,47 +265,47 @@ void MoveToState::OnUpdate(CCSBot *me) // reached destination switch (me->GetTask()) { - case CCSBot::PLANT_BOMB: + case CCSBot::PLANT_BOMB: + { + // if we are at bombsite with the bomb, plant it + if (me->IsAtBombsite() && me->IsCarryingBomb()) { - // if we are at bombsite with the bomb, plant it - if (me->IsAtBombsite() && me->IsCarryingBomb()) - { - me->PlantBomb(); - return; - } - break; + me->PlantBomb(); + return; } - case CCSBot::DEFUSE_BOMB: + break; + } + case CCSBot::DEFUSE_BOMB: + { + if (!me->IsActiveWeaponReloading()) { - if (!me->IsActiveWeaponReloading()) + // if we are near the bomb, defuse it (if we are reloading, don't try to defuse until we finish) + const Vector *bombPos = me->GetGameState()->GetBombPosition(); + if (bombPos) { - // if we are near the bomb, defuse it (if we are reloading, don't try to defuse until we finish) - const Vector *bombPos = me->GetGameState()->GetBombPosition(); - if (bombPos) - { - const float defuseRange = 100.0f; - Vector toBomb = *bombPos - me->pev->origin; - toBomb.z = bombPos->z - me->GetFeetZ(); + const float defuseRange = 100.0f; + Vector toBomb = *bombPos - me->pev->origin; + toBomb.z = bombPos->z - me->GetFeetZ(); - if (toBomb.IsLengthLessThan(defuseRange)) - { - me->DefuseBomb(); - return; - } + if (toBomb.IsLengthLessThan(defuseRange)) + { + me->DefuseBomb(); + return; } } - break; } - case CCSBot::MOVE_TO_LAST_KNOWN_ENEMY_POSITION: + break; + } + case CCSBot::MOVE_TO_LAST_KNOWN_ENEMY_POSITION: + { + CBaseEntity *pVictim = me->GetTaskEntity(); + if (pVictim && pVictim->IsAlive()) { - CBaseEntity *pVictim = me->GetTaskEntity(); - if (pVictim && pVictim->IsAlive()) - { - // if we got here and haven't re-acquired the enemy, we lost him - me->GetChatter()->Say("LostEnemy"); - } - break; + // if we got here and haven't re-acquired the enemy, we lost him + me->GetChatter()->Say("LostEnemy"); } + break; + } } // default behavior when destination is reached diff --git a/regamedll/dlls/combat.cpp b/regamedll/dlls/combat.cpp index 1ac1fb41..1e8e5769 100644 --- a/regamedll/dlls/combat.cpp +++ b/regamedll/dlls/combat.cpp @@ -293,7 +293,7 @@ void RadiusDamage(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker if (flAdjustedDamage < 0) flAdjustedDamage = 0; #endif - pEntity->TakeDamage(pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType); + pEntity->TakeDamage(pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType); } } } diff --git a/regamedll/dlls/doors.cpp b/regamedll/dlls/doors.cpp index dfe21b52..2b2e4598 100644 --- a/regamedll/dlls/doors.cpp +++ b/regamedll/dlls/doors.cpp @@ -969,7 +969,7 @@ void CMomentaryDoor::Spawn() if (pev->dmg == 0) pev->dmg = 2; - m_vecPosition1 = pev->origin; + m_vecPosition1 = pev->origin; // Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big m_vecPosition2 = m_vecPosition1 + (pev->movedir * (Q_fabs(float_precision(pev->movedir.x * (pev->size.x - 2))) + Q_fabs(float_precision(pev->movedir.y * (pev->size.y - 2))) + Q_fabs(float_precision(pev->movedir.z * (pev->size.z - 2))) - m_flLip)); diff --git a/regamedll/dlls/effects.cpp b/regamedll/dlls/effects.cpp index 21de24b1..0f56a80b 100644 --- a/regamedll/dlls/effects.cpp +++ b/regamedll/dlls/effects.cpp @@ -1003,7 +1003,7 @@ void CGlow::Spawn() if (m_maxFrame > 1.0f && pev->framerate != 0.0f) { - pev->nextthink = gpGlobals->time + 0.1f; + pev->nextthink = gpGlobals->time + 0.1f; } m_lastTime = gpGlobals->time; diff --git a/regamedll/dlls/explode.cpp b/regamedll/dlls/explode.cpp index 345cf7a7..0c484c84 100644 --- a/regamedll/dlls/explode.cpp +++ b/regamedll/dlls/explode.cpp @@ -103,7 +103,7 @@ void CEnvExplosion::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE vecSpot = pev->origin + Vector(0, 0, 8); - UTIL_TraceLine(vecSpot, vecSpot + Vector (0, 0, -40), ignore_monsters, ENT(pev), & tr); + UTIL_TraceLine(vecSpot, vecSpot + Vector(0, 0, -40), ignore_monsters, ENT(pev), &tr); // Pull out of the wall a bit if (tr.flFraction != 1.0f) @@ -112,7 +112,7 @@ void CEnvExplosion::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE } // draw decal - if (! (pev->spawnflags & SF_ENVEXPLOSION_NODECAL)) + if (!(pev->spawnflags & SF_ENVEXPLOSION_NODECAL)) { if (RANDOM_FLOAT(0, 1) < 0.5f) { diff --git a/regamedll/dlls/func_break.cpp b/regamedll/dlls/func_break.cpp index 6fcb8044..5fad6711 100644 --- a/regamedll/dlls/func_break.cpp +++ b/regamedll/dlls/func_break.cpp @@ -94,9 +94,9 @@ void CBreakable::Spawn() Precache(); if (pev->spawnflags & SF_BREAK_TRIGGER_ONLY) - pev->takedamage = DAMAGE_NO; + pev->takedamage = DAMAGE_NO; else - pev->takedamage = DAMAGE_YES; + pev->takedamage = DAMAGE_YES; m_flHealth = pev->health; pev->solid = SOLID_BSP; @@ -541,26 +541,25 @@ void CBreakable::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecD { switch (m_Material) { - case matComputer: + case matComputer: + { + UTIL_Sparks(ptr->vecEndPos); + + //random volume range + float flVolume = RANDOM_FLOAT(0.7 , 1.0); + switch (RANDOM_LONG(0, 1)) { - UTIL_Sparks(ptr->vecEndPos); - - //random volume range - float flVolume = RANDOM_FLOAT(0.7 , 1.0); - switch (RANDOM_LONG(0, 1)) - { - case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark5.wav", flVolume, ATTN_NORM); break; - case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark6.wav", flVolume, ATTN_NORM); break; - } - - break; + case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark5.wav", flVolume, ATTN_NORM); break; + case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark6.wav", flVolume, ATTN_NORM); break; } - case matUnbreakableGlass: - { - UTIL_Ricochet(ptr->vecEndPos, RANDOM_FLOAT(0.5, 1.5)); - break; - } + break; + } + case matUnbreakableGlass: + { + UTIL_Ricochet(ptr->vecEndPos, RANDOM_FLOAT(0.5, 1.5)); + break; + } } } diff --git a/regamedll/dlls/hostage/hostage.h b/regamedll/dlls/hostage/hostage.h index 18878fdd..fa5d324b 100644 --- a/regamedll/dlls/hostage/hostage.h +++ b/regamedll/dlls/hostage/hostage.h @@ -57,7 +57,7 @@ enum HostageChatterType HOSTAGE_CHATTER_PLEASE_RESCUE_ME, HOSTAGE_CHATTER_SEE_RESCUE_ZONE, HOSTAGE_CHATTER_IMPATIENT_FOR_RESCUE, - HOSTAGE_CHATTER_CTS_WIN , + HOSTAGE_CHATTER_CTS_WIN, HOSTAGE_CHATTER_TERRORISTS_WIN, HOSTAGE_CHATTER_RESCUED, HOSTAGE_CHATTER_WARN_NEARBY, diff --git a/regamedll/dlls/hostage/hostage_improv.cpp b/regamedll/dlls/hostage/hostage_improv.cpp index d4701a26..b45dbe32 100644 --- a/regamedll/dlls/hostage/hostage_improv.cpp +++ b/regamedll/dlls/hostage/hostage_improv.cpp @@ -155,7 +155,7 @@ void CHostageImprov::MoveTowards(const Vector &pos, float deltaT) Vector stepAhead = GetFeet() + farLookAheadRange * aheadRay; stepAhead.z += HumanHeight; - if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground, &normal )) + if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground, &normal)) { if (normal.z > 0.9f) jumped = DiscontinuityJump(ground, HOSTAGE_ONLY_JUMP_DOWN); diff --git a/regamedll/dlls/items.cpp b/regamedll/dlls/items.cpp index a72a5b8c..22335ea1 100644 --- a/regamedll/dlls/items.cpp +++ b/regamedll/dlls/items.cpp @@ -247,7 +247,7 @@ BOOL CItemBattery::MyTouch(CBasePlayer *pPlayer) pct--; char szcharge[64]; - Q_sprintf(szcharge,"!HEV_%1dP", pct); + Q_sprintf(szcharge, "!HEV_%1dP", pct); pPlayer->SetSuitUpdate(szcharge, SUIT_SENTENCE, SUIT_NEXT_IN_30SEC); return TRUE; diff --git a/regamedll/dlls/pathcorner.cpp b/regamedll/dlls/pathcorner.cpp index 9422d7f4..1bab256f 100644 --- a/regamedll/dlls/pathcorner.cpp +++ b/regamedll/dlls/pathcorner.cpp @@ -262,7 +262,7 @@ CPathTrack *CPathTrack::LookAhead(Vector *origin, float dist, int move) Vector dir = pcurrent->GetNext()->pev->origin - currentPos; float_precision length = dir.Length(); - if (!length && !ValidPath(pcurrent->GetNext()->GetNext(), move)) + if (!length && !ValidPath(pcurrent->GetNext()->GetNext(), move)) { // HACK: up against a dead end if (dist == originalDist) diff --git a/regamedll/dlls/plats.cpp b/regamedll/dlls/plats.cpp index 2fe31c98..c4b326b0 100644 --- a/regamedll/dlls/plats.cpp +++ b/regamedll/dlls/plats.cpp @@ -474,7 +474,7 @@ void CFuncPlatRot::SetupRotation() if (m_vecFinalAngle.x != 0) { CBaseToggle::AxisDir(pev); - m_start = pev->angles; + m_start = pev->angles; m_end = pev->angles + pev->movedir * m_vecFinalAngle.x; } else @@ -1328,9 +1328,15 @@ BOOL CFuncTrackTrain::OnControls(entvars_t *pevTest) local.y = -DotProduct(offset, gpGlobals->v_right); local.z = DotProduct(offset, gpGlobals->v_up); - if (local.x >= m_controlMins.x && local.y >= m_controlMins.y && local.z >= m_controlMins.z && - local.x <= m_controlMaxs.x && local.y <= m_controlMaxs.y && local.z <= m_controlMaxs.z) + if (local.x >= m_controlMins.x + && local.y >= m_controlMins.y + && local.z >= m_controlMins.z + && local.x <= m_controlMaxs.x + && local.y <= m_controlMaxs.y + && local.z <= m_controlMaxs.z) + { return TRUE; + } return FALSE; } @@ -1718,8 +1724,9 @@ TRAIN_CODE CFuncTrackChange::EvaluateTrain(CPathTrack *pcurrent) if (!pcurrent || !m_train) return TRAIN_SAFE; - if (m_train->m_ppath == pcurrent || (pcurrent->m_pprevious && m_train->m_ppath == pcurrent->m_pprevious) || - (pcurrent->m_pnext && m_train->m_ppath == pcurrent->m_pnext)) + if (m_train->m_ppath == pcurrent + || (pcurrent->m_pprevious && m_train->m_ppath == pcurrent->m_pprevious) + || (pcurrent->m_pnext && m_train->m_ppath == pcurrent->m_pnext)) { if (m_train->pev->speed != 0) return TRAIN_BLOCKING; diff --git a/regamedll/dlls/player.cpp b/regamedll/dlls/player.cpp index 8391a6fe..fd3251bc 100644 --- a/regamedll/dlls/player.cpp +++ b/regamedll/dlls/player.cpp @@ -110,7 +110,7 @@ const char *GetCSModelName(int item_id) case WEAPON_SCOUT: modelName = "models/w_scout.mdl"; break; case WEAPON_HEGRENADE: modelName = "models/w_hegrenade.mdl"; break; case WEAPON_XM1014: modelName = "models/w_xm1014.mdl"; break; - case WEAPON_C4: modelName = "models/w_backpack.mdl"; break; + case WEAPON_C4: modelName = "models/w_backpack.mdl"; break; case WEAPON_MAC10: modelName = "models/w_mac10.mdl"; break; case WEAPON_AUG: modelName = "models/w_aug.mdl"; break; case WEAPON_SMOKEGRENADE: modelName = "models/w_smokegrenade.mdl"; break; @@ -547,7 +547,7 @@ bool CBasePlayer::IsHittingShield(Vector &vecDirection, TraceResult *ptr) return false; if (ptr->iHitgroup == HITGROUP_SHIELD) - return true; + return true; if (m_bShieldDrawn) UTIL_MakeVectors(pev->angles); @@ -1228,7 +1228,7 @@ BOOL EXT_FUNC CBasePlayer::__API_HOOK(TakeDamage)(entvars_t *pevInflictor, entva return bTookDamage; } -void packPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo) +void PackPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo) { if (!pItem) return; @@ -1260,7 +1260,7 @@ void packPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo) } #ifdef REGAMEDLL_ADD -void packPlayerNade(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo) +void PackPlayerNade(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo) { if (!pItem) return; @@ -1282,16 +1282,9 @@ void packPlayerNade(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo) break; } - auto& ammoNades = pPlayer->m_rgAmmo[pItem->PrimaryAmmoIndex()]; - if (pItem->m_flStartThrow != 0) - { - if (ammoNades < 2) - return; - - ammoNades--; - } - else if (pItem->m_flReleaseThrow > 0 && ammoNades < 1) + if ((pPlayer->pev->button & IN_ATTACK) && pPlayer->m_rgAmmo[pItem->PrimaryAmmoIndex()] <= 0) { return; + } Vector vecAngles = pPlayer->pev->angles; Vector dir(Q_cos(vecAngles.y) * flOffset, Q_sin(vecAngles.y) * flOffset, 0.0f); @@ -1367,19 +1360,19 @@ void CBasePlayer::PackDeadPlayerItems() else if (pPlayerItem->iItemSlot() == GRENADE_SLOT) { if (AreRunningCZero()) - packPlayerItem(this, pPlayerItem, true); + PackPlayerItem(this, pPlayerItem, true); #ifdef REGAMEDLL_ADD else { switch ((int)nadedrops.value) { case 1: - packPlayerNade(this, pPlayerItem, true); + PackPlayerNade(this, pPlayerItem, true); break; case 2: { CBasePlayerItem *pNext = pPlayerItem->m_pNext; - packPlayerNade(this, pPlayerItem, true); + PackPlayerNade(this, pPlayerItem, true); pPlayerItem = pNext; continue; } @@ -1392,7 +1385,7 @@ void CBasePlayer::PackDeadPlayerItems() } } - packPlayerItem(this, pBestItem, bPackAmmo); + PackPlayerItem(this, pBestItem, bPackAmmo); } RemoveAllItems(TRUE); @@ -1950,6 +1943,10 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib) if ((pev->button & IN_ATTACK) && m_rgAmmo[pHEGrenade->m_iPrimaryAmmoType]) { CGrenade::ShootTimed2(pev, (pev->origin + pev->view_ofs), pev->angles, 1.5, m_iTeam, pHEGrenade->m_usCreateExplosion); + +#ifdef REGAMEDLL_FIXES + m_rgAmmo[m_pActiveItem->PrimaryAmmoIndex()]--; +#endif } break; } @@ -1958,6 +1955,10 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib) if ((pev->button & IN_ATTACK) && m_rgAmmo[((CBasePlayerWeapon *)m_pActiveItem)->m_iPrimaryAmmoType]) { CGrenade::ShootTimed(pev, (pev->origin + pev->view_ofs), pev->angles, 1.5); + +#ifdef REGAMEDLL_FIXES + m_rgAmmo[m_pActiveItem->PrimaryAmmoIndex()]--; +#endif } break; } @@ -1967,6 +1968,10 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib) if ((pev->button & IN_ATTACK) && m_rgAmmo[pSmoke->m_iPrimaryAmmoType]) { CGrenade::ShootSmokeGrenade(pev, (pev->origin + pev->view_ofs), pev->angles, 1.5, pSmoke->m_usCreateSmoke); + +#ifdef REGAMEDLL_FIXES + m_rgAmmo[m_pActiveItem->PrimaryAmmoIndex()]--; +#endif } break; } @@ -1997,7 +2002,9 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib) MESSAGE_END(); } else + { UTIL_ScreenFade(this, Vector(0, 0, 0), 3, 3, 255, (FFADE_OUT | FFADE_STAYOUT)); + } SetScoreboardAttributes(); @@ -2056,7 +2063,12 @@ void EXT_FUNC CBasePlayer::__API_HOOK(Killed)(entvars_t *pevAttacker, int iGib) break; } +#ifdef REGAMEDLL_FIXES + pev->angles.y = UTIL_VecToAngles(pev->velocity).y; +#else pev->angles.y = UTIL_VecToAngles(-pev->velocity).y; +#endif + pev->v_angle.y = pev->angles.y; m_iThrowDirection = THROW_NONE; @@ -4728,6 +4740,7 @@ void EXT_FUNC CBasePlayer::__API_HOOK(PostThink)() // NOTE: play on item channel because we play footstep landing on body channel EMIT_SOUND(ENT(pev), CHAN_ITEM, "common/bodysplat.wav", VOL_NORM, ATTN_NORM); } + #ifdef REGAMEDLL_FIXES if (flFallDamage >= 1.0f) #else diff --git a/regamedll/dlls/player.h b/regamedll/dlls/player.h index bec1301e..c4f4dbc7 100644 --- a/regamedll/dlls/player.h +++ b/regamedll/dlls/player.h @@ -939,7 +939,6 @@ Vector VecVelocityForDamage(float flDamage); int TrainSpeed(int iSpeed, int iMax); const char *GetWeaponName(entvars_t *pevInflictor, entvars_t *pKiller); void LogAttack(CBasePlayer *pAttacker, CBasePlayer *pVictim, int teamAttack, int healthHit, int armorHit, int newHealth, int newArmor, const char *killer_weapon_name); -void packPlayerItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, bool packAmmo); bool CanSeeUseable(CBasePlayer *me, CBaseEntity *entity); void FixPlayerCrouchStuck(edict_t *pPlayer); BOOL IsSpawnPointValid(CBaseEntity *pPlayer, CBaseEntity *pSpot); diff --git a/regamedll/dlls/singleplay_gamerules.cpp b/regamedll/dlls/singleplay_gamerules.cpp index 50a796fd..49155abb 100644 --- a/regamedll/dlls/singleplay_gamerules.cpp +++ b/regamedll/dlls/singleplay_gamerules.cpp @@ -148,7 +148,7 @@ edict_t *CHalfLifeRules::GetPlayerSpawnSpot(CBasePlayer *pPlayer) } pPlayer->pev->origin = pSpot->pev->origin + Vector(0, 0, 1); - pPlayer->pev->v_angle = g_vecZero; + pPlayer->pev->v_angle = g_vecZero; pPlayer->pev->velocity = g_vecZero; pPlayer->pev->angles = pSpot->pev->angles; pPlayer->pev->punchangle = g_vecZero; diff --git a/regamedll/dlls/skill.cpp b/regamedll/dlls/skill.cpp index a5e0e1bf..87fd4468 100644 --- a/regamedll/dlls/skill.cpp +++ b/regamedll/dlls/skill.cpp @@ -15,7 +15,7 @@ NOXREF float GetSkillCvar(char *pName) if (flValue <= 0.0f) { - ALERT(at_console, "\n\n** GetSkillCVar Got a zero for %s **\n\n",szBuffer); + ALERT(at_console, "\n\n** GetSkillCVar Got a zero for %s **\n\n", szBuffer); } return flValue; diff --git a/regamedll/dlls/sound.cpp b/regamedll/dlls/sound.cpp index 0554449f..7a921aef 100644 --- a/regamedll/dlls/sound.cpp +++ b/regamedll/dlls/sound.cpp @@ -1788,7 +1788,7 @@ float TEXTURETYPE_PlaySound(TraceResult *ptr, Vector vecSrc, Vector vecEnd, int { UTIL_Sparks(ptr->vecEndPos); - //random volume range + // random volume range float flVolume = RANDOM_FLOAT(0.7 , 1.0); switch (RANDOM_LONG(0, 1)) diff --git a/regamedll/dlls/weapons.h b/regamedll/dlls/weapons.h index 1f9dd73b..393abaeb 100644 --- a/regamedll/dlls/weapons.h +++ b/regamedll/dlls/weapons.h @@ -1127,8 +1127,8 @@ public: void EXPORT Smack(); void WeaponAnimation(int iAnimation); - int Stab(int fFirst); - int Swing(int fFirst); + BOOL Stab(BOOL fFirst); + BOOL Swing(BOOL fFirst); public: bool ShieldSecondaryFire(int iUpAnim, int iDownAnim); diff --git a/regamedll/dlls/wpn_shared/wpn_knife.cpp b/regamedll/dlls/wpn_shared/wpn_knife.cpp index f8ddcf29..efe309fd 100644 --- a/regamedll/dlls/wpn_shared/wpn_knife.cpp +++ b/regamedll/dlls/wpn_shared/wpn_knife.cpp @@ -248,9 +248,9 @@ void CKnife::WeaponIdle() SendWeaponAnim(KNIFE_IDLE, UseDecrement() != FALSE); } -int CKnife::Swing(int fFirst) +BOOL CKnife::Swing(BOOL fFirst) { - int fDidHit = FALSE; + BOOL fDidHit = FALSE; TraceResult tr; Vector vecSrc, vecEnd; @@ -422,9 +422,9 @@ int CKnife::Swing(int fFirst) return fDidHit; } -int CKnife::Stab(int fFirst) +BOOL CKnife::Stab(BOOL fFirst) { - int fDidHit = FALSE; + BOOL fDidHit = FALSE; TraceResult tr; Vector vecSrc, vecEnd; diff --git a/regamedll/game_shared/bot/nav.h b/regamedll/game_shared/bot/nav.h index fb82ccd9..b7c06367 100644 --- a/regamedll/game_shared/bot/nav.h +++ b/regamedll/game_shared/bot/nav.h @@ -69,6 +69,7 @@ enum NavAttributeType NAV_JUMP = 0x02, // must jump to traverse this area NAV_PRECISE = 0x04, // do not adjust for obstacles, just move along area NAV_NO_JUMP = 0x08, // inhibit discontinuity jumping + NAV_WALK = 0x10, // must not run through this area }; enum NavDirType diff --git a/regamedll/game_shared/bot/nav_area.cpp b/regamedll/game_shared/bot/nav_area.cpp index 92e6aec3..50f4445d 100644 --- a/regamedll/game_shared/bot/nav_area.cpp +++ b/regamedll/game_shared/bot/nav_area.cpp @@ -2338,6 +2338,7 @@ void CNavArea::Draw(byte red, byte green, byte blue, int duration) UTIL_DrawBeamPoints(nw, se, duration, red, green, blue); UTIL_DrawBeamPoints(ne, sw, duration, red, green, blue); } + if (GetAttributes() & NAV_PRECISE) { float size = 8.0f; @@ -2349,6 +2350,7 @@ void CNavArea::Draw(byte red, byte green, byte blue, int duration) Vector right(m_center.x + size, m_center.y, m_center.z + cv_bot_nav_zdraw.value); UTIL_DrawBeamPoints(left, right, duration, red, green, blue); } + if (GetAttributes() & NAV_NO_JUMP) { float size = 8.0f; @@ -2361,6 +2363,19 @@ void CNavArea::Draw(byte red, byte green, byte blue, int duration) UTIL_DrawBeamPoints(down, left, duration, red, green, blue); UTIL_DrawBeamPoints(left, up, duration, red, green, blue); } + + if (GetAttributes() & NAV_WALK) + { + float size = 8.0f; + Vector up(m_center.x - size, m_center.y - size, m_center.z + cv_bot_nav_zdraw.value); + Vector down(m_center.x + size, m_center.y + size, m_center.z + cv_bot_nav_zdraw.value); + Vector left(m_center.x - size, m_center.y + size, m_center.z + cv_bot_nav_zdraw.value); + Vector right(m_center.x + size, m_center.y - size, m_center.z + cv_bot_nav_zdraw.value); + UTIL_DrawBeamPoints(up, right, duration, red, green, blue); + UTIL_DrawBeamPoints(right, down, duration, red, green, blue); + UTIL_DrawBeamPoints(down, left, duration, red, green, blue); + UTIL_DrawBeamPoints(left, up, duration, red, green, blue); + } } // Draw selected corner for debugging @@ -3826,11 +3841,12 @@ void EditNavAreas(NavEditCmdType cmd) } else { - Q_sprintf(attrib, "%s%s%s%s", + Q_sprintf(attrib, "%s%s%s%s%s", (area->GetAttributes() & NAV_CROUCH) ? "CROUCH " : "", (area->GetAttributes() & NAV_JUMP) ? "JUMP " : "", (area->GetAttributes() & NAV_PRECISE) ? "PRECISE " : "", - (area->GetAttributes() & NAV_NO_JUMP) ? "NO_JUMP " : ""); + (area->GetAttributes() & NAV_NO_JUMP) ? "NO_JUMP " : "", + (area->GetAttributes() & NAV_WALK) ? "WALK " : ""); } Q_sprintf(buffer, "Area #%d %s %s\n", area->GetID(), locName, attrib); @@ -3853,36 +3869,36 @@ void EditNavAreas(NavEditCmdType cmd) switch (cmd) { - case EDIT_TOGGLE_PLACE_MODE: - EMIT_SOUND_DYN(ENT(pLocalPlayer->pev), CHAN_ITEM, "buttons/blip1.wav", 1, ATTN_NORM, 0, 100); - isPlaceMode = false; - return; + case EDIT_TOGGLE_PLACE_MODE: + EMIT_SOUND_DYN(ENT(pLocalPlayer->pev), CHAN_ITEM, "buttons/blip1.wav", 1, ATTN_NORM, 0, 100); + isPlaceMode = false; + return; - case EDIT_TOGGLE_PLACE_PAINTING: + case EDIT_TOGGLE_PLACE_PAINTING: + { + if (isPlacePainting) { - if (isPlacePainting) - { - isPlacePainting = false; - EMIT_SOUND_DYN(ENT(pLocalPlayer->pev), CHAN_ITEM, "buttons/latchunlocked2.wav", 1, ATTN_NORM, 0, 100); - } - else - { - isPlacePainting = true; - EMIT_SOUND_DYN(ENT(pLocalPlayer->pev), CHAN_ITEM, "buttons/lightswitch2.wav", 1, ATTN_NORM, 0, 100); - - // paint the initial area - area->SetPlace(TheCSBots()->GetNavPlace()); - } - break; + isPlacePainting = false; + EMIT_SOUND_DYN(ENT(pLocalPlayer->pev), CHAN_ITEM, "buttons/latchunlocked2.wav", 1, ATTN_NORM, 0, 100); } - case EDIT_PLACE_PICK: - EMIT_SOUND_DYN(ENT(pLocalPlayer->pev), CHAN_ITEM, "buttons/blip1.wav", 1, ATTN_NORM, 0, 100); - TheCSBots()->SetNavPlace(area->GetPlace()); - break; - case EDIT_PLACE_FLOODFILL: - PlaceFloodFillFunctor pff(area); - SearchSurroundingAreas(area, area->GetCenter(), pff); - break; + else + { + isPlacePainting = true; + EMIT_SOUND_DYN(ENT(pLocalPlayer->pev), CHAN_ITEM, "buttons/lightswitch2.wav", 1, ATTN_NORM, 0, 100); + + // paint the initial area + area->SetPlace(TheCSBots()->GetNavPlace()); + } + break; + } + case EDIT_PLACE_PICK: + EMIT_SOUND_DYN(ENT(pLocalPlayer->pev), CHAN_ITEM, "buttons/blip1.wav", 1, ATTN_NORM, 0, 100); + TheCSBots()->SetNavPlace(area->GetPlace()); + break; + case EDIT_PLACE_FLOODFILL: + PlaceFloodFillFunctor pff(area); + SearchSurroundingAreas(area, area->GetCenter(), pff); + break; } } else // normal editing mode @@ -3974,6 +3990,10 @@ void EditNavAreas(NavEditCmdType cmd) EMIT_SOUND_DYN(ENT(pLocalPlayer->pev), CHAN_ITEM, "buttons/bell1.wav", 1, ATTN_NORM, 0, 100); area->SetAttributes(area->GetAttributes() ^ NAV_PRECISE); break; + case EDIT_ATTRIB_WALK: + EMIT_SOUND_DYN(ENT(UTIL_GetLocalPlayer()->pev), CHAN_ITEM, "buttons/bell1.wav", 1, ATTN_NORM, 0, 100); + area->SetAttributes(area->GetAttributes() ^ NAV_WALK); + break; case EDIT_ATTRIB_NO_JUMP: EMIT_SOUND_DYN(ENT(pLocalPlayer->pev), CHAN_ITEM, "buttons/bell1.wav", 1, ATTN_NORM, 0, 100); area->SetAttributes(area->GetAttributes() ^ NAV_NO_JUMP); diff --git a/regamedll/game_shared/bot/nav_area.h b/regamedll/game_shared/bot/nav_area.h index a40d4387..4cb2532f 100644 --- a/regamedll/game_shared/bot/nav_area.h +++ b/regamedll/game_shared/bot/nav_area.h @@ -50,6 +50,7 @@ enum NavEditCmdType EDIT_ATTRIB_CROUCH, // toggle crouch attribute on current area EDIT_ATTRIB_JUMP, // toggle jump attribute on current area EDIT_ATTRIB_PRECISE, // toggle precise attribute on current area + EDIT_ATTRIB_WALK, // toggle walk attribute on current area EDIT_ATTRIB_NO_JUMP, // toggle inhibiting discontinuity jumping in current area EDIT_BEGIN_AREA, // begin creating a new nav area EDIT_END_AREA, // end creation of the new nav area diff --git a/regamedll/game_shared/bot/nav_file.cpp b/regamedll/game_shared/bot/nav_file.cpp index 667819e9..7c5ff78c 100644 --- a/regamedll/game_shared/bot/nav_file.cpp +++ b/regamedll/game_shared/bot/nav_file.cpp @@ -130,12 +130,13 @@ void CNavArea::Save(FILE *fp) const fprintf(fp, "v %f %f %f\n", m_extent.lo.x, m_extent.hi.y, m_swZ); static int base = 1; - fprintf(fp, "\n\ng %04dArea%s%s%s%s\n", m_id, + fprintf(fp, "\n\ng %04dArea%s%s%s%s%s\n", m_id, (GetAttributes() & NAV_CROUCH) ? "CROUCH" : "", (GetAttributes() & NAV_JUMP) ? "JUMP" : "", - (GetAttributes() & NAV_PRECISE) ? "PRECISE" : "", (GetAttributes() & NAV_NO_JUMP) ? "NO_JUMP" : ""); + (GetAttributes() & NAV_PRECISE) ? "PRECISE" : "", (GetAttributes() & NAV_NO_JUMP) ? "NO_JUMP" : "", + (GetAttributes() & NAV_WALK) ? "NAV_WALK" : ""); - fprintf(fp, "f %d %d %d %d\n\n", base, base + 1, base + 2, base + 3); - base += 4; + fprintf(fp, "f %d %d %d %d %d\n\n", base, base + 1, base + 2, base + 3, base + 4); + base += 5; } void CNavArea::Save(int fd, unsigned int version)