From 1eefedbc3657d79ead9e9a6301444ddaf2804dd8 Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Mon, 3 Aug 2020 23:39:57 +0200 Subject: [PATCH] Smoothed out turning of monsters/npc entities, they'll also reset paths when losing track of a target properly now. --- src/gs-entbase/server/baseentity.cpp | 1 + src/gs-entbase/server/basemonster.cpp | 87 ++++++++++++++++----- src/gs-entbase/server/basenpc.cpp | 9 ++- src/gs-entbase/server/scripted_sequence.cpp | 7 +- 4 files changed, 82 insertions(+), 22 deletions(-) diff --git a/src/gs-entbase/server/baseentity.cpp b/src/gs-entbase/server/baseentity.cpp index 7c179289..4e8fe776 100644 --- a/src/gs-entbase/server/baseentity.cpp +++ b/src/gs-entbase/server/baseentity.cpp @@ -33,6 +33,7 @@ CBaseEntity::SetFrame(float newFrame) return; frame = newFrame; + frame1time = 0.0f; SendFlags |= BASEFL_CHANGED_FRAME; } void diff --git a/src/gs-entbase/server/basemonster.cpp b/src/gs-entbase/server/basemonster.cpp index a749a5bb..37db4bce 100644 --- a/src/gs-entbase/server/basemonster.cpp +++ b/src/gs-entbase/server/basemonster.cpp @@ -65,6 +65,8 @@ enum MAL_ROGUE /* no allies, not even amongst themselves */ }; +.int m_iAlliance; + class CBaseMonster:CBaseEntity { vector oldnet_velocity; @@ -81,12 +83,12 @@ class CBaseMonster:CBaseEntity float m_flSequenceEnd; float m_flSequenceSpeed; vector m_vecSequenceAngle; + vector m_vecTurnAngle; /* attack/alliance system */ entity m_eEnemy; float m_flFOV; float m_flAttackThink; - int m_iAlliance; int m_iMState; vector m_vecLKPos; /* last-known pos */ @@ -111,6 +113,7 @@ class CBaseMonster:CBaseEntity /* see/hear subsystem */ float m_flSeeTime; virtual void(void) SeeThink; + virtual float(void) SeeFOV; /* attack system */ virtual void(void) AttackDraw; @@ -121,6 +124,7 @@ class CBaseMonster:CBaseEntity /* sequences */ virtual void(void) FreeState; + virtual void(void) FreeStateMoved; virtual void(void) ClearRoute; virtual void(void) CheckRoute; virtual void(void) WalkRoute; @@ -182,6 +186,25 @@ CBaseMonster::IdleNoise(void) } +int +CBaseMonster::IsFriend(int al) +{ + + if (m_iAlliance == MAL_ROGUE) + return FALSE; + else if (al == m_iAlliance) + return TRUE; + + return FALSE; +} + + +float +CBaseMonster::SeeFOV(void) +{ + return 90; +} + void CBaseMonster::SeeThink(void) { @@ -193,17 +216,19 @@ CBaseMonster::SeeThink(void) m_flSeeTime = time + 0.25f; - for (entity w = world; (w = find(w, ::classname, "player"));) { + for (entity w = world; (w = findfloat(w, ::takedamage, DAMAGE_YES));) { + if (IsFriend(w.m_iAlliance)) + continue; if (w.health <= 0) continue; /* first, is the potential enemy in our field of view? */ - makevectors(angles); + makevectors(v_angle); vector v = normalize(w.origin - origin); float flDot = v * v_forward; - if (flDot < 0.60) + if (flDot < SeeFOV()/180) continue; other = world; @@ -223,8 +248,10 @@ CBaseMonster::AttackThink(void) } /* reset */ - if (m_eEnemy && m_eEnemy.health <= 0) + if (m_eEnemy.solid == SOLID_CORPSE || (m_eEnemy && m_eEnemy.health <= 0)) { m_eEnemy = __NULL__; + ClearRoute(); + } /* do we have a clear shot? */ other = world; @@ -236,6 +263,7 @@ CBaseMonster::AttackThink(void) /* FIXME: This is unreliable, but unlikely that a player ever is here */ if (m_vecLKPos != [0,0,0]) { + ClearRoute(); NewRoute(m_vecLKPos); m_flSequenceSpeed = 140; m_vecLKPos = [0,0,0]; @@ -326,6 +354,15 @@ CBaseMonster::FreeState(void) } } +void +CBaseMonster::FreeStateMoved(void) +{ + vector new_origin; + new_origin = gettaginfo(this, 0); + SetOrigin(new_origin); + FreeState(); +} + void CBaseMonster::CheckRoute(void) { @@ -399,27 +436,39 @@ CBaseMonster::WalkRoute(void) endangles = vectoangles(m_eEnemy.origin - origin); /* TODO: lerp */ - input_angles[1] = endangles[1]; - return; - } - - if (m_iNodes && m_iMState == MONSTER_IDLE) { + m_vecTurnAngle[1] = endangles[1]; + } else if (m_iNodes && m_iMState == MONSTER_IDLE) { /* we're on our last node */ if (m_iCurNode < 0) { endangles = vectoangles(m_vecLastNode - origin); } else { endangles = vectoangles(m_pRoute[m_iCurNode].m_vecDest - origin); } - input_angles[1] = endangles[1]; + m_vecTurnAngle[1] = endangles[1]; input_movevalues = [m_flSequenceSpeed, 0, 0]; - } - - if (m_iMState == MONSTER_CHASING) { + } else if (m_iMState == MONSTER_CHASING) { /* we've got 'em in our sights, just need to walk closer */ endangles = vectoangles(m_eEnemy.origin - origin); input_movevalues = [140, 0, 0]; - input_angles[1] = endangles[1]; + m_vecTurnAngle[1] = endangles[1]; } + + /* functional */ + input_angles[1] = v_angle[1] = m_vecTurnAngle[1]; + + /* cosmetic */ + vector new_ang; + vector old_ang; + vector tmp; + makevectors(m_vecTurnAngle); + new_ang = v_forward; + makevectors(angles); + old_ang = v_forward; + + tmp[0] = Math_Lerp(old_ang[0], new_ang[0], frametime * 5); + tmp[1] = Math_Lerp(old_ang[1], new_ang[1], frametime * 5); + tmp[2] = Math_Lerp(old_ang[2], new_ang[2], frametime * 5); + angles = vectoangles(tmp); } void @@ -455,12 +504,12 @@ CBaseMonster::Physics(void) input_movevalues = [0,0,0]; input_impulse = 0; input_buttons = 0; - input_angles = angles = v_angle; + input_angles = v_angle; input_timelength = frametime; /* override whatever we did above with this */ if (m_iSequenceState == SEQUENCESTATE_ENDING) { - input_angles = angles = v_angle = m_vecSequenceAngle; + input_angles = v_angle = m_vecSequenceAngle; SetFrame(m_flSequenceEnd); } else if (movetype == MOVETYPE_WALK) { SeeThink(); @@ -495,6 +544,8 @@ CBaseMonster::Physics(void) think(); } } + + frame1time += frametime; } void @@ -574,6 +625,7 @@ CBaseMonster::Respawn(void) SendFlags = 0xff; style = MONSTER_IDLE; health = base_health; + m_eEnemy = __NULL__; SetAngles(v_angle); SetSolid(SOLID_SLIDEBOX); @@ -599,5 +651,4 @@ CBaseMonster::CBaseMonster(void) /* give us a 65 degree view cone */ m_flFOV = 1.0 / 65; - m_iAlliance = MAL_ROGUE; } diff --git a/src/gs-entbase/server/basenpc.cpp b/src/gs-entbase/server/basenpc.cpp index 6d60081d..c6c8831d 100644 --- a/src/gs-entbase/server/basenpc.cpp +++ b/src/gs-entbase/server/basenpc.cpp @@ -443,21 +443,22 @@ CBaseNPC::Physics(void) input_impulse = 0; input_buttons = 0; input_timelength = frametime; - input_angles = angles = v_angle; + input_angles = v_angle; /* override whatever we did above with this */ if (m_iSequenceState == SEQUENCESTATE_ENDING) { - input_angles = angles = v_angle = m_vecSequenceAngle; + input_angles = v_angle = m_vecSequenceAngle; SetFrame(m_flSequenceEnd); } else { if (style != MONSTER_DEAD) { + SeeThink(); AttackThink(); TalkPlayerGreet(); FollowChain(); if (m_eFollowing != world) { FollowPlayer(); - input_angles = angles = v_angle; + input_angles = v_angle; } else if (m_iFlags & MONSTER_FEAR) { PanicFrame(); } else { @@ -502,6 +503,8 @@ CBaseNPC::Physics(void) think(); } } + + frame1time += frametime; } void CBaseNPC::Respawn(void) diff --git a/src/gs-entbase/server/scripted_sequence.cpp b/src/gs-entbase/server/scripted_sequence.cpp index 888aaae5..dc99e232 100644 --- a/src/gs-entbase/server/scripted_sequence.cpp +++ b/src/gs-entbase/server/scripted_sequence.cpp @@ -198,7 +198,12 @@ scripted_sequence::Trigger(void) } f.m_iSequenceState = SEQUENCESTATE_ENDING; - f.think = CBaseMonster::FreeState; + + if (spawnflags & SSFL_NOSCRIPTMOVE) + f.think = CBaseMonster::FreeState; + else + f.think = CBaseMonster::FreeStateMoved; + dprint(sprintf("\tEnding: %f\n", f.nextthink)); }