diff --git a/dlls/CBaseEntity.cpp b/dlls/CBaseEntity.cpp index 73e1d79d..9e27e083 100644 --- a/dlls/CBaseEntity.cpp +++ b/dlls/CBaseEntity.cpp @@ -1250,6 +1250,9 @@ bool CBaseEntity::RunInventoryRules(CBaseEntity* ent) { void CBaseEntity::ParametricInterpolation(float flInterval) { + // A trace is done so that the client doesn't predict a projectile sliding across a wall + // (try removing this and firing the crossbow up towards a wall, it will start angling + // upward as it approaches the impact point). TraceResult tr; UTIL_TraceLine(pev->origin, pev->origin + pev->velocity, ignore_monsters, NULL, &tr); diff --git a/dlls/monster/CBarnacle.cpp b/dlls/monster/CBarnacle.cpp index 7312594a..63d58c41 100644 --- a/dlls/monster/CBarnacle.cpp +++ b/dlls/monster/CBarnacle.cpp @@ -335,7 +335,7 @@ void CBarnacle :: BarnacleThink ( void ) // ALERT( at_console, "tounge %f\n", m_flAltitude + m_flTongueAdj ); SetBoneController( 0, -(m_flAltitude + m_flTongueAdj) ); - StudioFrameAdvance( 0.1 ); + StudioFrameAdvance(); } //========================================================= @@ -365,7 +365,7 @@ void CBarnacle :: Killed( entvars_t *pevAttacker, int iGib ) SetActivity ( ACT_DIESIMPLE ); SetBoneController( 0, 0 ); - StudioFrameAdvance( 0.1 ); + StudioFrameAdvance(); pev->nextthink = gpGlobals->time + 0.1; SetThink ( &CBarnacle::WaitTillDead ); @@ -377,7 +377,7 @@ void CBarnacle :: WaitTillDead ( void ) { pev->nextthink = gpGlobals->time + 0.1; - float flInterval = StudioFrameAdvance( 0.1 ); + float flInterval = StudioFrameAdvance(); DispatchAnimEvents ( flInterval ); UpdateShockEffect(); diff --git a/dlls/monster/CBaseGrunt.cpp b/dlls/monster/CBaseGrunt.cpp index 62feaed2..25af4830 100644 --- a/dlls/monster/CBaseGrunt.cpp +++ b/dlls/monster/CBaseGrunt.cpp @@ -858,7 +858,7 @@ void CBaseGrunt::ShootRPG(Vector& vecShootOrigin, Vector& vecShootDir) { m_occludeTime = 0; } - if (!m_aimingRocket && !m_cAmmoLoaded || (m_occludeTime && gpGlobals->time - m_occludeTime > 2.0f)) { + if ((!m_aimingRocket && !m_cAmmoLoaded) || (m_occludeTime && gpGlobals->time - m_occludeTime > 2.0f)) { SetActivity(ACT_IDLE_ANGRY); TaskFail(); } @@ -2516,6 +2516,8 @@ Schedule_t *CBaseGrunt :: GetSchedule( void ) { // just landed pev->movetype = MOVETYPE_STEP; + pev->gravity = 0; + pev->friction = 0; return GetScheduleOfType(SCHED_GRUNT_REPEL_LAND); } else @@ -2858,7 +2860,7 @@ void CBaseRepel::RepelUse(CBaseEntity* pActivator, CBaseEntity* pCaller, USE_TYP // FLY movetype but with client interpolation pGrunt->pev->movetype = MOVETYPE_BOUNCE; pGrunt->pev->gravity = FLT_MIN; - pGrunt->pev->friction = 1.0f; + pGrunt->pev->friction = 2.0f; // don't fly away if landing on a slope pGrunt->pev->velocity = Vector(0, 0, RANDOM_FLOAT(-196, -128)); pGrunt->SetActivity(ACT_GLIDE); diff --git a/dlls/monster/CBaseMonster.cpp b/dlls/monster/CBaseMonster.cpp index be3064b8..1160e6c5 100644 --- a/dlls/monster/CBaseMonster.cpp +++ b/dlls/monster/CBaseMonster.cpp @@ -5229,7 +5229,10 @@ BOOL CBaseMonster::FScheduleDone(void) //========================================================= void CBaseMonster::ChangeSchedule(Schedule_t* pNewSchedule) { - ASSERT(pNewSchedule != NULL); + if (!pNewSchedule) { + ALERT(at_console, "Attempted to change to NULL schedule\n"); + return; + } m_pSchedule = pNewSchedule; m_iScheduleIndex = 0; @@ -5430,13 +5433,18 @@ void CBaseMonster::MaintainSchedule(void) { Task_t* pTask = GetTask(); ASSERT(pTask != NULL); - TaskBegin(); - #ifdef DEBUG_MONSTER - if (FClassnameIs(pev, DEBUG_MONSTER)) { - ALERT(at_console, " Start Task %s with data %f\n", GetTaskName(pTask->iTask), pTask->flData); + if (pTask) { + TaskBegin(); +#ifdef DEBUG_MONSTER + if (FClassnameIs(pev, DEBUG_MONSTER)) { + ALERT(at_console, " Start Task %s with data %f\n", GetTaskName(pTask->iTask), pTask->flData); + } +#endif + StartTask(pTask); + } + else { + ALERT(at_console, "Monster %s has NULL task\n", STRING(pev->classname)); } - #endif - StartTask(pTask); } // UNDONE: Twice?!!! @@ -5453,7 +5461,13 @@ void CBaseMonster::MaintainSchedule(void) { Task_t* pTask = GetTask(); ASSERT(pTask != NULL); - RunTask(pTask); + if (pTask) { + RunTask(pTask); + } + else { + ALERT(at_console, "Failed to run NULL task for %s (%s)\n", + STRING(pev->targetname), STRING(pev->classname)); + } } // UNDONE: We have to do this so that we have an animation set to blend to if RunTask changes the animation diff --git a/dlls/monster/CShockTrooper.cpp b/dlls/monster/CShockTrooper.cpp index a752e843..99579fc3 100644 --- a/dlls/monster/CShockTrooper.cpp +++ b/dlls/monster/CShockTrooper.cpp @@ -1907,6 +1907,8 @@ Schedule_t* CShockTrooper::GetSchedule() { // just landed pev->movetype = MOVETYPE_STEP; + pev->gravity = 0; + pev->friction = 0; return GetScheduleOfType(SCHED_GRUNT_REPEL_LAND); } else diff --git a/dlls/player/CBasePlayer.cpp b/dlls/player/CBasePlayer.cpp index 9b0c73b3..9f3135ac 100644 --- a/dlls/player/CBasePlayer.cpp +++ b/dlls/player/CBasePlayer.cpp @@ -4550,8 +4550,10 @@ void CBasePlayer :: UpdateClientData( void ) // Update all the items for ( int i = 0; i < MAX_ITEM_TYPES; i++ ) { - if ( m_rgpPlayerItems[i] ) // each item updates it's successors - ((CBasePlayerItem*)m_rgpPlayerItems[i].GetEntity())->UpdateClientData(this); + CBaseEntity* ent = m_rgpPlayerItems[i].GetEntity(); + CBasePlayerItem* item = ent ? ent->GetWeaponPtr() : NULL; + if (item) // each item updates it's successors + item->UpdateClientData(this); } // Cache and client weapon change diff --git a/dlls/util/eng_wrappers.cpp b/dlls/util/eng_wrappers.cpp index a7d85729..042c92da 100644 --- a/dlls/util/eng_wrappers.cpp +++ b/dlls/util/eng_wrappers.cpp @@ -337,8 +337,14 @@ void PRECACHE_MODEL_EXTRAS(const char* path, studiohdr_t* mdl) { if (opt[0] == '*') opt = opt.substr(1); // not sure why some models do this, it looks pointless. - // model sounds are loaded on demand, not precached - PRECACHE_GENERIC(STRING(ALLOC_STRING(normalize_path("sound/" + opt).c_str()))); + if (evt->event == 5004) { + // sound is loaded by the client on-demand + PRECACHE_GENERIC(STRING(ALLOC_STRING(normalize_path("sound/" + opt).c_str()))); + } + else { + // sound is played by the server + PRECACHE_SOUND_ENT(NULL, STRING(ALLOC_STRING(opt.c_str()))); + } } if (evt->event == 5001 || evt->event == 5011 || evt->event == 5021 || evt->event == 5031) { // muzzleflash sprite PRECACHE_GENERIC(STRING(ALLOC_STRING(normalize_path(opt).c_str()))); diff --git a/dlls/util/util.cpp b/dlls/util/util.cpp index 4600b075..f9a82e51 100644 --- a/dlls/util/util.cpp +++ b/dlls/util/util.cpp @@ -1147,10 +1147,10 @@ void UTIL_PlayGlobalMp3(const char* path, bool loop, edict_t* target) { // surround with ; to prevent multiple commands being joined when sent in the same frame(?) // this fixes music sometimes not loading/starting/stopping std::string mp3Path = normalize_path(UTIL_VarArgs("sound/%s", path)); - std::string mp3Command = UTIL_VarArgs(";mp3 %s %s;", (loop ? "loop" : "play"), mp3Path.c_str()); + std::string mp3Command = UTIL_VarArgs("mp3 %s %s", (loop ? "loop" : "play"), mp3Path.c_str()); MESSAGE_BEGIN(target ? MSG_ONE : MSG_ALL, SVC_STUFFTEXT, NULL, target); - WRITE_STRING(mp3Command.c_str()); + WRITE_STRING((mp3Command + "\n").c_str()); MESSAGE_END(); if (!target) { @@ -1160,16 +1160,15 @@ void UTIL_PlayGlobalMp3(const char* path, bool loop, edict_t* target) { } void UTIL_StopGlobalMp3(edict_t* target) { - const char* cmd = ";mp3 stop;"; MESSAGE_BEGIN(target ? MSG_ONE : MSG_ALL, SVC_STUFFTEXT, NULL, target); - WRITE_STRING(cmd); + WRITE_STRING("mp3 stop\n"); //WRITE_STRING(";cd fadeout;"); // blocked by cl_filterstuffcmd MESSAGE_END(); if (!target) { g_mp3Command = ""; - ALERT(at_console, "MP3 Command: '%s'\n", cmd); + ALERT(at_console, "MP3 Command: 'mp3 stop'\n"); } } @@ -2857,32 +2856,30 @@ Vector VecBModelOrigin(entvars_t* pevBModel) void PlayCDTrack(int iTrack) { - edict_t* pClient; - - // manually find the single player. - pClient = g_engfuncs.pfnPEntityOfEntIndex(1); - - // Can't play if the client is not connected! - if (!pClient) - return; - if (iTrack < -1 || iTrack > 30) { ALERT(at_console, "TriggerCDAudio - Track %d out of range\n"); return; } + std::string cdCommand = ""; + if (iTrack == -1) { - CLIENT_COMMAND(pClient, "cd stop\n"); + cdCommand = "cd stop"; + g_mp3Command = ""; } else { - char string[64]; - - snprintf(string, 64, "cd play %3d\n", iTrack); - CLIENT_COMMAND(pClient, string); + cdCommand = UTIL_VarArgs("cd play %d", iTrack); + g_mp3Command = cdCommand; // play for new joiners later } + + MESSAGE_BEGIN(MSG_ALL, SVC_STUFFTEXT); + WRITE_STRING((cdCommand + "\n").c_str()); + MESSAGE_END(); + + ALERT(at_console, "CD Command: '%s'\n", cdCommand.c_str()); } std::string sanitize_cvar_value(std::string val) { diff --git a/dlls/weapon/CRpg.cpp b/dlls/weapon/CRpg.cpp index 43dedff9..f4221259 100644 --- a/dlls/weapon/CRpg.cpp +++ b/dlls/weapon/CRpg.cpp @@ -290,7 +290,6 @@ void CRpgRocket :: FollowThink( void ) float bestDot = -1.0f; float bestDist = FLT_MAX; - Vector bestDir = vecTarget; // Examine all entities within a reasonable radius while ((pOther = UTIL_FindEntityByClassname( pOther, "laser_spot" )) != NULL)