diff --git a/code/fgame/actor.h b/code/fgame/actor.h index 32ee76ef..7ba3602c 100644 --- a/code/fgame/actor.h +++ b/code/fgame/actor.h @@ -463,6 +463,8 @@ enum eActorState_Turret { ACTOR_STATE_TURRET_COVER_INSTEAD, ACTOR_STATE_TURRET_BECOME_COVER, ACTOR_STATE_TURRET_WAIT, + ACTOR_STATE_TURRET_SHOOT, // Added in 2.0 + ACTOR_STATE_TURRET_RETARGET_SUPPRESS, // Added in 2.0 ACTOR_STATE_TURRET_RETARGET_SNIPER_NODE, ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_SMALL, ACTOR_STATE_TURRET_RETARGET_PATH_EXACT, @@ -470,7 +472,8 @@ enum eActorState_Turret { ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_MEDIUM, ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_LARGE, ACTOR_STATE_TURRET_RETARGET_STEP_FACE_MEDIUM, - ACTOR_STATE_TURRET_RETARGET_STEP_FACE_LARGE + ACTOR_STATE_TURRET_RETARGET_STEP_FACE_LARGE, + ACTOR_STATE_TURRET_NUM_STATES }; // @@ -508,7 +511,7 @@ enum eActorState_Cover { // Pain think state // enum eActorState_Pain { - ACTOR_STATE_PAIN_START = ACTOR_STATE_PAIN, + ACTOR_STATE_PAIN_START = ACTOR_STATE_PAIN, ACTOR_STATE_PAIN_INITIAL = ACTOR_STATE_PAIN_START, ACTOR_STATE_PAIN_MAIN }; @@ -549,7 +552,7 @@ enum eActorState_BalconyKilled { // Weaponless think state // enum eActorState_WeaponLess { - ACTOR_STATE_WEAPONLESS_START = ACTOR_STATE_WEAPONLESS, + ACTOR_STATE_WEAPONLESS_START = ACTOR_STATE_WEAPONLESS, ACTOR_STATE_WEAPONLESS_NORMAL = ACTOR_STATE_WEAPONLESS_START, ACTOR_STATE_WEAPONLESS_GRENADE, ACTOR_STATE_WEAPONLESS_LOOP diff --git a/code/fgame/actor_turret.cpp b/code/fgame/actor_turret.cpp index 0be31402..4f9c06b0 100644 --- a/code/fgame/actor_turret.cpp +++ b/code/fgame/actor_turret.cpp @@ -41,7 +41,7 @@ void Actor::InitTurret(GlobalFuncs_t *func) bool Actor::Turret_IsRetargeting(void) const { - return m_State <= ACTOR_STATE_TURRET_RETARGET_STEP_FACE_LARGE; + return m_State > ACTOR_STATE_TURRET_SHOOT && m_State < ACTOR_STATE_TURRET_NUM_STATES; } bool Actor::Turret_DecideToSelectState(void) @@ -56,30 +56,33 @@ bool Actor::Turret_DecideToSelectState(void) case ACTOR_STATE_TURRET_GRENADE: case ACTOR_STATE_TURRET_TAKE_SNIPER_NODE: case ACTOR_STATE_TURRET_FAKE_ENEMY: + case ACTOR_STATE_TURRET_SHOOT: return false; } + return !Turret_IsRetargeting(); } void Actor::Turret_SelectState(void) { - vec2_t vDelta; float fDistSquared; + vec2_t vDelta; + if (!m_Enemy) { - TransitionState(ACTOR_STATE_TURRET_FAKE_ENEMY, rand() & 0x7FF + 250); + TransitionState(ACTOR_STATE_TURRET_FAKE_ENEMY, (rand() & 0x7FF) + 250); return; } VectorSub2D(origin, m_vHome, vDelta); fDistSquared = VectorLength2DSquared(vDelta); - if (m_State == ACTOR_STATE_TURRET_RUN_HOME && fDistSquared > m_fLeashSquared * 0.64 + 64.0) { + if (m_State == ACTOR_STATE_TURRET_RUN_HOME && fDistSquared > (m_fLeashSquared * 0.64 + 64.0)) { if (PathExists() && !PathComplete()) { return; } } else if (fDistSquared <= m_fLeashSquared * 1.21 + 256.0) { m_iRunHomeTime = 0; - } else if (m_iRunHomeTime == 0) { + } else if (!m_iRunHomeTime) { m_iRunHomeTime = level.inttime + (rand() & 0xFFF) + 1000; } else if (level.inttime >= m_iRunHomeTime) { m_iRunHomeTime = 0; @@ -88,68 +91,58 @@ void Actor::Turret_SelectState(void) SetPath(m_vHome, NULL, 0, NULL, 0.0); ShortenPathToAvoidSquadMates(); - if (PathExists() && !PathComplete()) { - TransitionState(ACTOR_STATE_TURRET_RUN_HOME, 0); - return; - } else { + if (!PathExists()) { Com_Printf( "^~^~^ (entnum %i, radnum %d, targetname '%s') cannot reach his leash home\n", entnum, radnum, targetname.c_str() ); + } else if (!PathComplete()) { + TransitionState(ACTOR_STATE_TURRET_RUN_HOME, 0); + return; } } VectorSub2D(origin, m_Enemy->origin, vDelta); fDistSquared = VectorLength2DSquared(vDelta); - if (m_State == ACTOR_STATE_TURRET_RUN_AWAY) { - if (m_fMinDistanceSquared * 2.25 > fDistSquared) { - return; - } + if (m_State == ACTOR_STATE_TURRET_RUN_AWAY && fDistSquared < m_fMinDistanceSquared * 2.25) { + return; } - if (m_fMinDistanceSquared > fDistSquared) { + if (fDistSquared < m_fMinDistanceSquared) { ClearPath(); TransitionState(ACTOR_STATE_TURRET_RUN_AWAY, 0); return; } if (fDistSquared > m_fMaxDistanceSquared) { - bool bSmthing = false; - if (m_Team == TEAM_GERMAN) { - if ((m_Enemy->origin - m_vHome).lengthSquared() >= Square(m_fLeash + m_fMaxDistance) && !CanSeeEnemy(200)) { - bSmthing = true; - } - } - if (bSmthing) { + if (m_Team == TEAM_GERMAN && (m_Enemy->origin - m_vHome).lengthSquared() >= Square(m_fLeash + m_fMaxDistance) + && !CanSeeEnemy(200)) { ClearPath(); TransitionState(ACTOR_STATE_TURRET_WAIT, 0); - } else { - if (m_State == ACTOR_STATE_TURRET_CHARGE) { - return; - } + } else if (m_State != ACTOR_STATE_TURRET_CHARGE) { ClearPath(); TransitionState(ACTOR_STATE_TURRET_CHARGE, 0); } - return; - } + } else { + if (DecideToThrowGrenade(m_vLastEnemyPos + m_Enemy->velocity, &m_vGrenadeVel, &m_eGrenadeMode, false)) { + SetDesiredYawDir(m_vGrenadeVel); - if (DecideToThrowGrenade(m_Enemy->velocity + m_vLastEnemyPos, &m_vGrenadeVel, &m_eGrenadeMode, false)) { - m_bNextForceStart = false; - SetDesiredYawDir(m_vGrenadeVel); + DesiredAnimation( + ANIM_MODE_NORMAL, + m_eGrenadeMode == AI_GREN_TOSS_ROLL ? STRING_ANIM_GRENADETOSS_SCR : STRING_ANIM_GRENADETHROW_SCR + ); + TransitionState(ACTOR_STATE_TURRET_GRENADE, 0); + return; + } - m_eNextAnimMode = ANIM_MODE_NORMAL; - m_csNextAnimString = - (m_eGrenadeMode == AI_GREN_TOSS_ROLL) ? STRING_ANIM_GRENADETOSS_SCR : STRING_ANIM_GRENADETHROW_SCR; - TransitionState(ACTOR_STATE_TURRET_GRENADE, 0); - return; - } - - if (m_State != ACTOR_STATE_TURRET_COMBAT && m_State != ACTOR_STATE_TURRET_SNIPER_NODE && m_State != ACTOR_STATE_TURRET_WAIT) { - ClearPath(); - TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); + if (m_State != ACTOR_STATE_TURRET_COMBAT && m_State != ACTOR_STATE_TURRET_SNIPER_NODE + && m_State != ACTOR_STATE_TURRET_WAIT && m_State != ACTOR_STATE_TURRET_SHOOT) { + ClearPath(); + TransitionState(ACTOR_STATE_TURRET_COMBAT); + } } } @@ -191,12 +184,8 @@ void Actor::Suspend_Turret(void) { if (!m_Enemy) { TransitionState(ACTOR_STATE_TURRET_COVER_INSTEAD, 0); - } else { - if (m_State <= ACTOR_STATE_TURRET_INTRO_AIM) { - SetEnemyPos(m_Enemy->origin); - AimAtEnemyBehavior(); - TransitionState(ACTOR_STATE_TURRET_RETARGET_SNIPER_NODE, 0); - } + } else if (m_State == ACTOR_STATE_TURRET_GRENADE || m_State == ACTOR_STATE_TURRET_INTRO_AIM) { + Turret_BeginRetarget(); } } @@ -209,29 +198,34 @@ void Actor::State_Turret_Combat(void) Turret_CheckRetarget(); return; } + if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) { SetPathWithLeash(m_vLastEnemyPos, NULL, 0); ShortenPathToAvoidSquadMates(); } + if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) { - FindPathNearWithLeash(m_vLastEnemyPos, 4.0 * m_fMinDistanceSquared); + FindPathNearWithLeash(m_vLastEnemyPos, m_fMinDistanceSquared * 4); if (!ShortenPathToAttack(0.0)) { ClearPath(); } ShortenPathToAvoidSquadMates(); } + if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) { m_pszDebugState = "combat->chill"; Turret_BeginRetarget(); - } else { - m_pszDebugState = "combat->move"; - if (!MovePathWithLeash()) { - m_pszDebugState = "combat->move->aim"; - Turret_BeginRetarget(); - } else { - Turret_CheckRetarget(); - } + return; } + + m_pszDebugState = "combat->move"; + if (!MovePathWithLeash()) { + m_pszDebugState = "combat->move->aim"; + Turret_BeginRetarget(); + return; + } + + Turret_CheckRetarget(); } void Actor::Turret_BeginRetarget(void) @@ -239,27 +233,25 @@ void Actor::Turret_BeginRetarget(void) SetEnemyPos(m_Enemy->origin); AimAtEnemyBehavior(); - TransitionState(ACTOR_STATE_TURRET_RETARGET_SNIPER_NODE, 0); + TransitionState(ACTOR_STATE_TURRET_RETARGET_SUPPRESS, 0); } void Actor::Turret_NextRetarget(void) { vec2_t vDelta; - float fDistSquared; m_State++; - - if (Turret_IsRetargeting()) { - m_iStateTime = level.inttime; + if (m_State < 122) { + TransitionState(m_State); return; } VectorSub2D(origin, m_vHome, vDelta); - fDistSquared = VectorLength2DSquared(vDelta); - if (fDistSquared >= m_fLeashSquared) { + if (VectorLength2DSquared(vDelta) >= m_fLeashSquared) { SetPath(m_vHome, NULL, 0, NULL, 0.0); ShortenPathToAvoidSquadMates(); + if (PathExists() && !PathComplete()) { TransitionState(ACTOR_STATE_TURRET_RUN_HOME, 0); State_Turret_RunHome(true); @@ -272,33 +264,35 @@ void Actor::Turret_NextRetarget(void) m_PotentialEnemies.FlagBadEnemy(m_Enemy); UpdateEnemy(-1); } + if (!m_Enemy) { Anim_Stand(); return; } + + TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); + State_Turret_Combat(); + } else if (CanSeeEnemy(200)) { + m_pszDebugState = "Retarget->Combat"; TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); State_Turret_Combat(); - } else { - if (CanSeeEnemy(200)) { - m_pszDebugState = "Retarget->Combat"; - TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); - State_Turret_Combat(); - } else { - TransitionState(ACTOR_STATE_TURRET_WAIT, 0); - State_Turret_Wait(); - } + TransitionState(ACTOR_STATE_TURRET_WAIT, 0); + State_Turret_Wait(); } } void Actor::Turret_SideStep(int iStepSize, vec3_t vDir) { AimAtEnemyBehavior(); - //v3 = iStepSize; StrafeToAttack(iStepSize, vDir); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((StrafeToAttack(-iStepSize, vDir), PathExists()) && !PathComplete() && PathAvoidsSquadMates())) { - TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); + + if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) { + StrafeToAttack(-iStepSize, vDir); + } + + if (PathExists() && !PathComplete() && PathAvoidsSquadMates()) { + TransitionState(ACTOR_STATE_TURRET_REACQUIRE); } else { Turret_NextRetarget(); } @@ -306,12 +300,69 @@ void Actor::Turret_SideStep(int iStepSize, vec3_t vDir) void Actor::State_Turret_Shoot(void) { - // FIXME: unimplemented + if (CanSeeEnemy(200) || FriendlyInLineOfFire(m_Enemy)) { + TransitionState(ACTOR_STATE_TURRET_COMBAT); + State_Turret_Combat(); + return; + } + + AimAtTargetPos(); + Anim_Suppress(); + + if (level.inttime >= m_iStateTime + 15000) { + Turret_SelectState(); + if (m_State == ACTOR_STATE_TURRET_SHOOT) { + Turret_BeginRetarget(); + } + } } void Actor::State_Turret_Retarget_Suppress(void) { - // FIXME: unimplemented + trace_t trace; + + if (rand() % 100 >= m_iSuppressChance) { + AimAtEnemyBehavior(); + Turret_NextRetarget(); + return; + } + + if (level.inttime >= m_iLastEnemyVisibleTime + 15000) { + AimAtEnemyBehavior(); + Turret_NextRetarget(); + return; + } + + if (FriendlyInLineOfFire(m_Enemy)) { + AimAtEnemyBehavior(); + Turret_NextRetarget(); + return; + } + + trace = G_Trace( + EyePosition(), + vec_zero, + vec_zero, + m_Enemy->EyePosition(), + this, + MASK_CANSEE, + qfalse, + "Actor::State_Turret_Retarget_Suppress" + ); + if (trace.fraction <= 0.5f) { + AimAtEnemyBehavior(); + Turret_NextRetarget(); + return; + } + + if (trace.fraction != 1.f && trace.plane.normal[2] >= 0.7f) { + AimAtEnemyBehavior(); + Turret_NextRetarget(); + return; + } + + TransitionState(ACTOR_STATE_TURRET_SHOOT); + State_Turret_Shoot(); } void Actor::State_Turret_Retarget_Sniper_Node(void) @@ -324,12 +375,12 @@ void Actor::State_Turret_Retarget_Sniper_Node(void) m_pCoverNode->Relinquish(); m_pCoverNode = NULL; } + pSniperNode = FindSniperNodeAndSetPath(&bTryAgain); if (pSniperNode) { m_pCoverNode = pSniperNode; pSniperNode->Claim(this); - TransitionState(ACTOR_STATE_TURRET_TAKE_SNIPER_NODE, 0); - + TransitionState(ACTOR_STATE_TURRET_TAKE_SNIPER_NODE); State_Turret_TakeSniperNode(); } else if (bTryAgain) { ContinueAnimation(); @@ -340,35 +391,34 @@ void Actor::State_Turret_Retarget_Sniper_Node(void) void Actor::State_Turret_Retarget_Step_Side_Small(void) { - int iRand; // esi - - iRand = (rand() & 64) - 32; - AimAtEnemyBehavior(); - StrafeToAttack(iRand, orientation[1]); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((Actor::StrafeToAttack(-iRand, orientation[1]), PathExists()) && !PathComplete() && PathAvoidsSquadMates() - )) { - TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); - } else { - Turret_NextRetarget(); - } + Turret_SideStep((rand() & 64) - 32, orientation[1]); } void Actor::State_Turret_Retarget_Path_Exact(void) { AimAtEnemyBehavior(); SetPathWithLeash(m_vLastEnemyPos, NULL, 0); - if (ShortenPathToAttack(128) && (ShortenPathToAvoidSquadMates(), PathExists())) { - TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); - } else { + + if (!ShortenPathToAttack(128)) { Turret_NextRetarget(); + return; } + + ShortenPathToAvoidSquadMates(); + + if (!PathExists()) { + Turret_NextRetarget(); + return; + } + + TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); } void Actor::State_Turret_Retarget_Path_Near(void) { AimAtEnemyBehavior(); FindPathNearWithLeash(m_vLastEnemyPos, m_fMinDistanceSquared); + if (ShortenPathToAttack(128)) { TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); } else { @@ -378,107 +428,59 @@ void Actor::State_Turret_Retarget_Path_Near(void) void Actor::State_Turret_Retarget_Step_Side_Medium(void) { - int iRand; // esi - - iRand = (rand() & 256) - 128; - AimAtEnemyBehavior(); - StrafeToAttack(iRand, orientation[1]); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((Actor::StrafeToAttack(-iRand, orientation[1]), PathExists()) && !PathComplete() && PathAvoidsSquadMates() - )) { - TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); - } else { - Turret_NextRetarget(); - } + Turret_SideStep((rand() & 256) - 128, orientation[1]); } void Actor::State_Turret_Retarget_Step_Side_Large(void) { - int iRand; // esi - - iRand = (rand() & 512) - 256; - AimAtEnemyBehavior(); - StrafeToAttack(iRand, orientation[1]); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((Actor::StrafeToAttack(-iRand, orientation[1]), PathExists()) && !PathComplete() && PathAvoidsSquadMates() - )) { - TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); - } else { - Turret_NextRetarget(); - } + Turret_SideStep((rand() & 512) - 256, orientation[1]); } void Actor::State_Turret_Retarget_Step_Face_Medium(void) { - int iRand; // esi - - iRand = (rand() & 256) - 128; - AimAtEnemyBehavior(); - StrafeToAttack(iRand, orientation[0]); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((Actor::StrafeToAttack(-iRand, orientation[0]), PathExists()) && !PathComplete() && PathAvoidsSquadMates() - )) { - TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); - } else { - Turret_NextRetarget(); - } + Turret_SideStep((rand() & 256) - 128, orientation[0]); } void Actor::State_Turret_Retarget_Step_Face_Large(void) { - int iRand; // esi - - iRand = (rand() & 512) - 256; - AimAtEnemyBehavior(); - StrafeToAttack(iRand, orientation[0]); - if ((PathExists() && !PathComplete() && PathAvoidsSquadMates()) - || ((Actor::StrafeToAttack(-iRand, orientation[0]), PathExists()) && !PathComplete() && PathAvoidsSquadMates() - )) { - TransitionState(ACTOR_STATE_TURRET_REACQUIRE, 0); - } else { - Turret_NextRetarget(); - } + Turret_SideStep((rand() & 512) - 256, orientation[0]); } void Actor::State_Turret_Reacquire(void) { - /*Sentient *v1; // ecx - float v2; // ST08_4 - float v3; // ST0C_4 - Sentient *v4; // ecx - float v5; // ST08_4 - float v6; // ST0C_4 - */ - if (PathExists() && !PathComplete()) { - if (CanMovePathWithLeash()) { - Anim_RunToInOpen(3); - FaceEnemyOrMotion(level.inttime - m_iStateTime); - } else { - Turret_BeginRetarget(); - } - } else { + if (!PathExists() || PathComplete()) { m_pszDebugState = "Retarget->Cheat"; SetEnemyPos(m_Enemy->origin); TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); State_Turret_Combat(); + return; + } + + if (CanMovePathWithLeash()) { + Anim_RunToInOpen(ANIM_MODE_PATH_GOAL); + FaceEnemyOrMotion(level.inttime - m_iStateTime); + } else { + Turret_BeginRetarget(); } } void Actor::State_Turret_TakeSniperNode(void) { - if (PathExists() && !PathComplete()) { - FaceMotion(); - Anim_RunToDanger(3); - } else { + if (!PathExists() || PathComplete()) { AimAtEnemyBehavior(); TransitionState(ACTOR_STATE_TURRET_SNIPER_NODE, 0); + return; } + + FaceMotion(); + Anim_RunToDanger(ANIM_MODE_PATH_GOAL); } void Actor::State_Turret_SniperNode(void) { AimAtTargetPos(); Anim_Sniper(); + if (Turret_CheckRetarget()) { m_pCoverNode->Relinquish(); m_pCoverNode->MarkTemporarilyBad(); @@ -490,6 +492,7 @@ bool Actor::State_Turret_RunHome(bool bAttackOnFail) { SetPath(m_vHome, NULL, 0, NULL, 0.0); ShortenPathToAvoidSquadMates(); + if (!PathExists() || PathComplete()) { Com_Printf( "^~^~^ (entnum %i, radnum %i, targetname '%s') cannot reach his leash home\n", @@ -502,11 +505,11 @@ bool Actor::State_Turret_RunHome(bool bAttackOnFail) State_Turret_Combat(); } return false; - } else { - FaceMotion(); - Anim_RunToInOpen(2); - return true; } + + FaceMotion(); + Anim_RunToInOpen(ANIM_MODE_PATH); + return true; } void Actor::State_Turret_RunAway(void) @@ -514,17 +517,20 @@ void Actor::State_Turret_RunAway(void) if (!PathExists() || PathComplete()) { FindPathAwayWithLeash(m_vLastEnemyPos, origin - m_Enemy->origin, 1.5 * m_fMinDistance); } + if (!PathExists() || PathComplete()) { m_pszDebugState = "runaway->combat"; State_Turret_Combat(); return; } + if (!CanMovePathWithLeash()) { m_pszDebugState = "runaway->leash->combat"; State_Turret_Combat(); return; } - Anim_RunAwayFiring(2); + + Anim_RunAwayFiring(ANIM_MODE_PATH); FaceEnemyOrMotion(level.inttime - m_iStateTime); } @@ -532,40 +538,39 @@ void Actor::State_Turret_Charge(void) { SetPathWithLeash(m_vLastEnemyPos, NULL, 0); ShortenPathToAvoidSquadMates(); + if (!PathExists()) { m_pszDebugState = "charge->near"; FindPathNearWithLeash(m_vLastEnemyPos, m_fMaxDistanceSquared); + if (!ShortenPathToAttack(0)) { ClearPath(); } } + if (!PathExists() || PathComplete() || !PathAvoidsSquadMates()) { ClearPath(); + if (CanSeeEnemy(500)) { m_pszDebugState = "charge->combat"; State_Turret_Combat(); return; } - m_bHasDesiredLookAngles = false; - m_pszDebugState = "charge->chill"; + + m_pszDebugState = "charge->chill"; + + ForwardLook(); Anim_Idle(); - if (m_Team != TEAM_AMERICAN) { - //v1 = &this->m_PotentialEnemies; - if (!m_PotentialEnemies.HasAlternateEnemy()) { - if (m_Enemy) { - Turret_CheckRetarget(); - } - return; - } + + if (m_Team == TEAM_AMERICAN || m_PotentialEnemies.HasAlternateEnemy()) { + m_PotentialEnemies.FlagBadEnemy(m_Enemy); + UpdateEnemy(-1); } - m_PotentialEnemies.FlagBadEnemy(m_Enemy); - UpdateEnemy(-1); + if (m_Enemy) { Turret_CheckRetarget(); } - return; - } - if (!MovePathWithLeash()) { + } else if (!MovePathWithLeash()) { m_pszDebugState = "charge->leash->combat"; TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); State_Turret_Combat(); @@ -582,6 +587,7 @@ void Actor::State_Turret_FakeEnemy(void) { AimAtTargetPos(); Anim_Aim(); + if (level.inttime >= m_iStateTime) { SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); } @@ -590,221 +596,226 @@ void Actor::State_Turret_FakeEnemy(void) void Actor::State_Turret_Wait(void) { PathNode *pNode; - if (CanSeeEnemy(500) || CanShootEnemy(500)) { - bool bSmth; - pNode = m_pCoverNode; - Cover_FindCover(true); - - if (m_pCoverNode) { - TransitionState(ACTOR_STATE_TURRET_BECOME_COVER, 0); - SetThink(THINKSTATE_ATTACK, THINK_COVER); - bSmth = true; - } else { - if (pNode) { - m_pCoverNode = pNode; - m_pCoverNode->Claim(this); - } - bSmth = false; - } - if (bSmth) { + if (CanSeeEnemy(500) || CanSeeEnemy(500)) { + if (Turret_TryToBecomeCoverGuy()) { m_pszDebugState = "Wait->CoverInstead"; ContinueAnimation(); } else { m_pszDebugState = "Wait->Combat"; - TransitionState(ACTOR_STATE_TURRET_COMBAT, 0); + TransitionState(ACTOR_STATE_TURRET_COMBAT); State_Turret_Combat(); } - } else { - if (level.inttime >= m_iLastFaceDecideTime + 1500) { - m_iLastFaceDecideTime = level.inttime + (rand() & 0x1FF); + return; + } - pNode = PathManager.FindCornerNodeForExactPath(this, m_Enemy, 0); + if (level.inttime >= m_iLastEnemyVisibleTime + 25000) { + m_vLastEnemyPos = m_Enemy->origin; + Turret_BeginRetarget(); + } - if (pNode) { - if (pNode->m_PathPos - origin != vec_zero) { - SetDesiredYawDir(pNode->m_PathPos - origin); - } - m_eDontFaceWallMode = 6; - } else { - AimAtTargetPos(); - DontFaceWall(); - } - } - if (m_eDontFaceWallMode > 8) { - Anim_Aim(); + if (level.inttime >= m_iLastFaceDecideTime + 1500) { + m_iLastFaceDecideTime = level.inttime + (rand() & 0x1FF); + + pNode = PathManager.FindCornerNodeForExactPath(this, m_Enemy, 0); + + if (pNode) { + SetDesiredYawDest(pNode->m_PathPos); + m_eDontFaceWallMode = 6; } else { - Anim_Stand(); + AimAtTargetPos(); + DontFaceWall(); } } + + if (m_eDontFaceWallMode == 7 || m_eDontFaceWallMode == 8) { + Anim_Stand(); + } else { + Anim_Aim(); + } } void Actor::Think_Turret(void) { - if (RequireThink()) { - UpdateEyeOrigin(); - NoPoint(); - UpdateEnemy(200); + if (!RequireThink()) { + return; + } - if (m_Enemy && m_State == ACTOR_STATE_TURRET_COVER_INSTEAD) { - if (!m_bTurretNoInitialCover && Turret_TryToBecomeCoverGuy()) { - m_pszDebugState = "CoverInstead"; - CheckUnregister(); - UpdateAngles(); - DoMove(); - UpdateBoneControllers(); - UpdateFootsteps(); - return; - } + UpdateEyeOrigin(); + NoPoint(); + UpdateEnemy(200); - m_bTurretNoInitialCover = false; + if (m_Enemy && m_State == ACTOR_STATE_TURRET_COVER_INSTEAD) { + if (!m_bTurretNoInitialCover && Turret_TryToBecomeCoverGuy()) { + m_pszDebugState = "CoverInstead"; - Turret_SelectState(); - - if (m_State == ACTOR_STATE_TURRET_COMBAT && !CanSeeEnemy(0)) { - Turret_BeginRetarget(); - } - - SetLeashHome(origin); - - if (level.inttime < m_iEnemyChangeTime + 200) { - if (AttackEntryAnimation()) { - m_bLockThinkState = true; - TransitionState(ACTOR_STATE_TURRET_INTRO_AIM, 0); - } - } + CheckUnregister(); + UpdateAngles(); + DoMove(); + UpdateBoneControllers(); + UpdateFootsteps(); + return; } - if (level.inttime > m_iStateTime + 3000) { - Turret_SelectState(); + m_bTurretNoInitialCover = false; + Turret_SelectState(); + + if (m_State == ACTOR_STATE_TURRET_COMBAT && !CanSeeEnemy(0)) { + Turret_BeginRetarget(); } - if (m_State == ACTOR_STATE_TURRET_INTRO_AIM) { - m_pszDebugState = "IntroAnim"; - AimAtTargetPos(); - ContinueAnimation(); - } else { - m_bLockThinkState = false; - if (!m_Enemy && m_State != ACTOR_STATE_TURRET_FAKE_ENEMY && m_State != ACTOR_STATE_TURRET_RUN_HOME) { - TransitionState(ACTOR_STATE_TURRET_FAKE_ENEMY, ((rand() + 250) & 0x7FF)); - } - if (!m_Enemy) { - if (m_State != ACTOR_STATE_TURRET_FAKE_ENEMY) { - if (m_State != ACTOR_STATE_TURRET_RUN_HOME || (origin - m_vHome).lengthXYSquared() <= 0.64f * m_fLeashSquared + 64.0f - || !State_Turret_RunHome(false)) { - m_pszDebugState = "Idle"; - SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); - IdleThink(); - } else { - m_pszDebugState = "Idle->RunHome"; - PostThink(true); - } - return; - } - } - if (m_Enemy && m_State == ACTOR_STATE_TURRET_FAKE_ENEMY) { - Turret_BeginRetarget(); - } + SetLeashHome(origin); - if (Turret_DecideToSelectState()) { - Turret_SelectState(); - } - - switch (m_State) { - case ACTOR_STATE_TURRET_COMBAT: - m_pszDebugState = "Combat"; - State_Turret_Combat(); - break; - case ACTOR_STATE_TURRET_REACQUIRE: - m_pszDebugState = "Reacquire"; - State_Turret_Reacquire(); - break; - case ACTOR_STATE_TURRET_TAKE_SNIPER_NODE: - m_pszDebugState = "TakeSniperNode"; - if (!PathExists() || PathComplete()) { - AimAtEnemyBehavior(); - TransitionState(ACTOR_STATE_TURRET_SNIPER_NODE, 0); - } else { - FaceMotion(); - Anim_RunToDanger(3); - } - break; - case ACTOR_STATE_TURRET_SNIPER_NODE: - m_pszDebugState = "SniperNode"; - State_Turret_SniperNode(); - break; - case ACTOR_STATE_TURRET_RUN_HOME: - m_pszDebugState = "RunHome"; - State_Turret_RunHome(true); - break; - case ACTOR_STATE_TURRET_RUN_AWAY: - m_pszDebugState = "RunAway"; - State_Turret_RunAway(); - break; - case ACTOR_STATE_TURRET_CHARGE: - m_pszDebugState = "Charge"; - State_Turret_Charge(); - break; - case ACTOR_STATE_TURRET_GRENADE: - m_pszDebugState = "Grenade"; - State_Turret_Grenade(); - break; - case ACTOR_STATE_TURRET_FAKE_ENEMY: - m_pszDebugState = "FakeEnemy"; - State_Turret_FakeEnemy(); - break; - case ACTOR_STATE_TURRET_BECOME_COVER: - m_pszDebugState = "BecomeCover"; - ContinueAnimation(); - break; - case ACTOR_STATE_TURRET_WAIT: - m_pszDebugState = "Wait"; - State_Turret_Wait(); - break; - case ACTOR_STATE_TURRET_RETARGET_SNIPER_NODE: - m_pszDebugState = "Retarget_Sniper_Node"; - State_Turret_Retarget_Sniper_Node(); - break; - case ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_SMALL: - m_pszDebugState = "Retarget_Step_Side_Small"; - State_Turret_Retarget_Step_Side_Small(); - break; - case ACTOR_STATE_TURRET_RETARGET_PATH_EXACT: - m_pszDebugState = "Retarget_Path_Exact"; - State_Turret_Retarget_Path_Exact(); - break; - case ACTOR_STATE_TURRET_RETARGET_PATH_NEAR: - m_pszDebugState = "Retarget_Path_Near"; - State_Turret_Retarget_Path_Near(); - break; - case ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_MEDIUM: - m_pszDebugState = "Retarget_Step_Side_Medium"; - State_Turret_Retarget_Step_Side_Medium(); - break; - case ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_LARGE: - m_pszDebugState = "Retarget_Step_Side_Large"; - State_Turret_Retarget_Step_Side_Large(); - break; - case ACTOR_STATE_TURRET_RETARGET_STEP_FACE_MEDIUM: - m_pszDebugState = "Retarget_Step_Face_Medium"; - State_Turret_Retarget_Step_Face_Medium(); - break; - case ACTOR_STATE_TURRET_RETARGET_STEP_FACE_LARGE: - m_pszDebugState = "Retarget_Step_Face_Large"; - State_Turret_Retarget_Step_Face_Large(); - break; - default: - Com_Printf("Actor::Think_Turret: invalid think state %i\n", m_State); - assert(!"invalid think state"); - break; - } - CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE); + if (level.inttime < m_iEnemyChangeTime + 200 && AttackEntryAnimation()) { + TransitionState(ACTOR_STATE_TURRET_INTRO_AIM); + m_bLockThinkState = true; } + } + + if (level.inttime > m_iStateTime + 3000) { + Turret_SelectState(); + } + + if (m_State == ACTOR_STATE_TURRET_INTRO_AIM) { + m_pszDebugState = "IntroAnim"; + AimAtTargetPos(); + ContinueAnimation(); + if (m_State == ACTOR_STATE_TURRET_WAIT) { PostThink(false); } else { PostThink(true); } + return; + } + + m_bLockThinkState = false; + + if (!m_Enemy && m_State != ACTOR_STATE_TURRET_FAKE_ENEMY && m_State != ACTOR_STATE_TURRET_RUN_HOME) { + TransitionState(ACTOR_STATE_TURRET_FAKE_ENEMY, (rand() + 250) & 0x7FF); + } + + if (!m_Enemy && m_State != ACTOR_STATE_TURRET_FAKE_ENEMY) { + if (m_State != ACTOR_STATE_TURRET_RUN_HOME + || (origin - m_vHome).lengthXYSquared() <= (m_fLeashSquared * 0.64f + 64.0f) + || !State_Turret_RunHome(false)) { + m_pszDebugState = "Idle"; + SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE); + IdleThink(); + } else { + m_pszDebugState = "Idle->RunHome"; + PostThink(true); + } + return; + } + + if (m_Enemy && m_State == ACTOR_STATE_TURRET_FAKE_ENEMY) { + Turret_BeginRetarget(); + } + + if (Turret_DecideToSelectState()) { + Turret_SelectState(); + } + + switch (m_State) { + case ACTOR_STATE_TURRET_COMBAT: + m_pszDebugState = "Combat"; + State_Turret_Combat(); + break; + case ACTOR_STATE_TURRET_REACQUIRE: + m_pszDebugState = "Reacquire"; + State_Turret_Reacquire(); + break; + case ACTOR_STATE_TURRET_TAKE_SNIPER_NODE: + m_pszDebugState = "TakeSniperNode"; + State_Turret_TakeSniperNode(); + break; + case ACTOR_STATE_TURRET_SNIPER_NODE: + m_pszDebugState = "SniperNode"; + State_Turret_SniperNode(); + break; + case ACTOR_STATE_TURRET_RUN_HOME: + m_pszDebugState = "RunHome"; + State_Turret_RunHome(true); + break; + case ACTOR_STATE_TURRET_RUN_AWAY: + m_pszDebugState = "RunAway"; + State_Turret_RunAway(); + break; + case ACTOR_STATE_TURRET_CHARGE: + m_pszDebugState = "Charge"; + State_Turret_Charge(); + break; + case ACTOR_STATE_TURRET_GRENADE: + m_pszDebugState = "Grenade"; + State_Turret_Grenade(); + break; + case ACTOR_STATE_TURRET_FAKE_ENEMY: + m_pszDebugState = "FakeEnemy"; + State_Turret_FakeEnemy(); + break; + case ACTOR_STATE_TURRET_BECOME_COVER: + m_pszDebugState = "BecomeCover"; + ContinueAnimation(); + break; + case ACTOR_STATE_TURRET_WAIT: + m_pszDebugState = "Wait"; + State_Turret_Wait(); + break; + case ACTOR_STATE_TURRET_SHOOT: + m_pszDebugState = "Shoot"; + State_Turret_Shoot(); + break; + case ACTOR_STATE_TURRET_RETARGET_SUPPRESS: + m_pszDebugState = "Retarget_Suppress"; + State_Turret_Retarget_Suppress(); + break; + case ACTOR_STATE_TURRET_RETARGET_SNIPER_NODE: + m_pszDebugState = "Retarget_Sniper_Node"; + State_Turret_Retarget_Sniper_Node(); + break; + case ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_SMALL: + m_pszDebugState = "Retarget_Step_Side_Small"; + State_Turret_Retarget_Step_Side_Small(); + break; + case ACTOR_STATE_TURRET_RETARGET_PATH_EXACT: + m_pszDebugState = "Retarget_Path_Exact"; + State_Turret_Retarget_Path_Exact(); + break; + case ACTOR_STATE_TURRET_RETARGET_PATH_NEAR: + m_pszDebugState = "Retarget_Path_Near"; + State_Turret_Retarget_Path_Near(); + break; + case ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_MEDIUM: + m_pszDebugState = "Retarget_Step_Side_Medium"; + State_Turret_Retarget_Step_Side_Medium(); + break; + case ACTOR_STATE_TURRET_RETARGET_STEP_SIDE_LARGE: + m_pszDebugState = "Retarget_Step_Side_Large"; + State_Turret_Retarget_Step_Side_Large(); + break; + case ACTOR_STATE_TURRET_RETARGET_STEP_FACE_MEDIUM: + m_pszDebugState = "Retarget_Step_Face_Medium"; + State_Turret_Retarget_Step_Face_Medium(); + break; + case ACTOR_STATE_TURRET_RETARGET_STEP_FACE_LARGE: + m_pszDebugState = "Retarget_Step_Face_Large"; + State_Turret_Retarget_Step_Face_Large(); + break; + default: + Com_Printf("Actor::Think_Turret: invalid think state %i\n", m_State); + assert(!"invalid think state"); + break; + } + + if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) { + CheckForTransition(THINKSTATE_BADPLACE, THINKLEVEL_IDLE); + } + + if (m_State == ACTOR_STATE_TURRET_WAIT) { + PostThink(false); + } else { + PostThink(true); } } @@ -812,35 +823,37 @@ void Actor::ReceiveAIEvent_Turret( vec3_t event_origin, int iType, Entity *originator, float fDistSquared, float fMaxDistSquared ) { - if (iType == AI_EVENT_WEAPON_IMPACT) { - if (m_Enemy && fDistSquared <= Square(128)) { - Turret_TryToBecomeCoverGuy(); - } - } else { + if (iType != AI_EVENT_WEAPON_IMPACT) { DefaultReceiveAIEvent(origin, iType, originator, fDistSquared, fMaxDistSquared); + } else if (m_Enemy && fDistSquared <= Square(128)) { + Turret_TryToBecomeCoverGuy(); } } bool Actor::Turret_TryToBecomeCoverGuy(void) { PathNode *pOldCover = m_pCoverNode; + Cover_FindCover(true); + if (m_pCoverNode) { TransitionState(ACTOR_STATE_TURRET_BECOME_COVER, 0); SetThink(THINKSTATE_ATTACK, THINK_COVER); return true; - } else { - if (pOldCover) { - m_pCoverNode = pOldCover; - m_pCoverNode->Claim(this); - } - return false; } + + if (pOldCover) { + m_pCoverNode = pOldCover; + m_pCoverNode->Claim(this); + } + + return false; } void Actor::FinishedAnimation_Turret(void) { - if (m_State <= ACTOR_STATE_TURRET_INTRO_AIM) { + if (m_State == ACTOR_STATE_TURRET_GRENADE || m_State == ACTOR_STATE_TURRET_INTRO_AIM + || m_State == ACTOR_STATE_TURRET_SHOOT) { Turret_SelectState(); } } @@ -855,7 +868,7 @@ void Actor::InterruptPoint_Turret(void) void Actor::PathnodeClaimRevoked_Turret(void) { - if (m_Enemy == NULL) { + if (!m_Enemy) { TransitionState(ACTOR_STATE_TURRET_COVER_INSTEAD, 0); } else { Turret_BeginRetarget();