diff --git a/cl_dll/TheGate/scope.cpp b/cl_dll/TheGate/scope.cpp new file mode 100644 index 00000000..9b3da56e --- /dev/null +++ b/cl_dll/TheGate/scope.cpp @@ -0,0 +1,288 @@ +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" + +#include +#include + +#define SCOPE_SMALL 0 +#define SCOPE_MEDIUM 1 +#define SCOPE_LARGE 2 + +static int HUD_IsWidescreen(int iWidth, int iHeight) +{ + float ratio = iWidth / iHeight; + + return (ratio >= 1.77) ? 1 : 0; +} + +DECLARE_MESSAGE(m_Scope, Scope) + +int CHudScope::Init(void) +{ + HOOK_MESSAGE(Scope); + + // Make inactive. + m_iFlags &= ~HUD_ACTIVE; + + gHUD.AddHudElem(this); + + return 1; +}; + +void CHudScope::Reset(void) +{ + // Make inactive. + m_iFlags &= ~HUD_ACTIVE; +} + +int CHudScope::VidInit(void) +{ + for (int i = 0; i < SCOPE_HSPRITE_COUNT; i++) + m_scopes[i] = 0; + + m_ScopeSize = 0; + + int sw = ScreenWidth, sh = ScreenHeight; + + // + // Determine the ideal scope size to use. + // + + // Widescreen support. 1:77 + if (HUD_IsWidescreen(sw, sh)) + { + if (sh > 576) + { + if (sh > 800) + { + m_ScopeSize = SCOPE_LARGE; + } + else + { + m_ScopeSize = SCOPE_MEDIUM; + } + } + else + { + m_ScopeSize = SCOPE_SMALL; + } + } + // Normal display. 1:33 + else + { + if (sh > 600) + { + if (sh > 768) + { + m_ScopeSize = SCOPE_LARGE; + } + else + { + m_ScopeSize = SCOPE_MEDIUM; + } + } + else + { + m_ScopeSize = SCOPE_SMALL; + } + } + + // Make inactive. + m_iFlags &= ~HUD_ACTIVE; + + return 1; +}; + +int CHudScope::Draw(float flTime) +{ + if (!(m_iFlags & HUD_ACTIVE)) + return 1; + + int x, y, w, h; + + x = y = 0; + + if (!m_scopes[0]) + { + switch (m_ScopeSize) + { + default: + case SCOPE_SMALL: + m_scopes[0] = LoadSprite("sprites/scope/0.spr"); + break; + + case SCOPE_MEDIUM: + m_scopes[SCOPE_U_L] = LoadSprite("sprites/scope/800/U_L.spr"); + m_scopes[SCOPE_U_M_L] = LoadSprite("sprites/scope/800/U_M_L.spr"); + m_scopes[SCOPE_U_M_R] = LoadSprite("sprites/scope/800/U_M_R.spr"); + m_scopes[SCOPE_U_R] = LoadSprite("sprites/scope/800/U_R.spr"); + m_scopes[SCOPE_M_L] = LoadSprite("sprites/scope/800/M_L.spr"); + m_scopes[SCOPE_M_R] = LoadSprite("sprites/scope/800/M_R.spr"); + m_scopes[SCOPE_L_L] = LoadSprite("sprites/scope/800/L_L.spr"); + m_scopes[SCOPE_L_M_L] = LoadSprite("sprites/scope/800/L_M_L.spr"); + m_scopes[SCOPE_L_M_R] = LoadSprite("sprites/scope/800/L_M_R.spr"); + m_scopes[SCOPE_L_R] = LoadSprite("sprites/scope/800/L_R.spr"); + break; + + case SCOPE_LARGE: + m_scopes[SCOPE_U_L] = LoadSprite("sprites/scope/1024/U_L.spr"); + m_scopes[SCOPE_U_M_L] = LoadSprite("sprites/scope/1024/U_M_L.spr"); + m_scopes[SCOPE_U_M_R] = LoadSprite("sprites/scope/1024/U_M_R.spr"); + m_scopes[SCOPE_U_R] = LoadSprite("sprites/scope/1024/U_R.spr"); + m_scopes[SCOPE_M_L] = LoadSprite("sprites/scope/1024/M_L.spr"); + m_scopes[SCOPE_M_R] = LoadSprite("sprites/scope/1024/M_R.spr"); + m_scopes[SCOPE_L_L] = LoadSprite("sprites/scope/1024/L_L.spr"); + m_scopes[SCOPE_L_M_L] = LoadSprite("sprites/scope/1024/L_M_L.spr"); + m_scopes[SCOPE_L_M_R] = LoadSprite("sprites/scope/1024/L_M_R.spr"); + m_scopes[SCOPE_L_R] = LoadSprite("sprites/scope/1024/L_R.spr"); + break; + } + } + + w = SPR_Width(m_scopes[0], 0); + h = SPR_Height(m_scopes[0], 0); + + int r, g, b, a; + UnpackRGB(r, g, b, RGB_YELLOWISH); + + switch (m_ScopeSize) + { + default: + + // + // Small scope. + // + case SCOPE_SMALL: + // + // This uses one sprite. + // + + x = ScreenWidth / 2 - w; + y = ScreenHeight / 2 - h; + + //----------------------- + // Top left scope. + //----------------------- + SPR_Set(m_scopes[0], r, g, b); + SPR_DrawHoles(0, x, y, NULL); + + //----------------------- + // Top right scope. + //----------------------- + SPR_Set(m_scopes[0], r, g, b); + SPR_DrawHoles(1, x + w, y, NULL); + + //----------------------- + // Bottom right scope. + //----------------------- + SPR_Set(m_scopes[0], r, g, b); + SPR_DrawHoles(2, x + w, y + h, NULL); + + //----------------------- + // Bottom left scope. + //----------------------- + SPR_Set(m_scopes[0], r, g, b); + SPR_DrawHoles(3, x, y + h, NULL); + break; + + // + // Medium & Large scopes. + // + case SCOPE_MEDIUM: + case SCOPE_LARGE: + x = ScreenWidth / 2 - w * 2; + y = ScreenHeight / 2 - (h * 3) / 2; + + //----------------------- + // Upper part. + //----------------------- + SPR_Set(m_scopes[SCOPE_U_L], r, g, b); + SPR_DrawHoles(0, x, y, NULL); + + SPR_Set(m_scopes[SCOPE_U_M_L], r, g, b); + SPR_DrawHoles(0, x + w, y, NULL); + + SPR_Set(m_scopes[SCOPE_U_M_R], r, g, b); + SPR_DrawHoles(0, x + w * 2, y, NULL); + + SPR_Set(m_scopes[SCOPE_U_R], r, g, b); + SPR_DrawHoles(0, x + w * 3, y, NULL); + + //----------------------- + // Middle part. + //----------------------- + SPR_Set(m_scopes[SCOPE_M_L], r, g, b); + SPR_DrawHoles(0, x, y + h, NULL); + + SPR_Set(m_scopes[SCOPE_M_R], r, g, b); + SPR_DrawHoles(0, x + w * 3, y + h, NULL); + + //----------------------- + // Lower part. + //----------------------- + SPR_Set(m_scopes[SCOPE_L_L], r, g, b); + SPR_DrawHoles(0, x, y + h * 2, NULL); + + SPR_Set(m_scopes[SCOPE_L_M_L], r, g, b); + SPR_DrawHoles(0, x + w, y + h * 2, NULL); + + SPR_Set(m_scopes[SCOPE_L_M_R], r, g, b); + SPR_DrawHoles(0, x + w * 2, y + h * 2, NULL); + + SPR_Set(m_scopes[SCOPE_L_R], r, g, b); + SPR_DrawHoles(0, x + w * 3, y + h * 2, NULL); + break; + } + + r = g = b = 0; + a = 255; + + // Draw left bar. + gEngfuncs.pfnFillRGBABlend(0, 0, x + 1, ScreenHeight, r, g, b, a); + + // Draw right bar. + gEngfuncs.pfnFillRGBABlend(ScreenWidth - x - 1, 0, ScreenWidth, ScreenHeight, r, g, b, a); + + // Draw top bar. + gEngfuncs.pfnFillRGBABlend(0, 0, ScreenWidth, y + 1, r, g, b, a); + + // Draw bottom bar. + gEngfuncs.pfnFillRGBABlend(0, ScreenHeight - y - 1, ScreenWidth, ScreenHeight, r, g, b, a); + + return 1; +} + +int CHudScope::MsgFunc_Scope(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ(pbuf, iSize); + int fOn = READ_BYTE(); + + if (fOn) + { + // Make active. + m_iFlags |= HUD_ACTIVE; + } + else + { + // Make inactive. + m_iFlags &= ~HUD_ACTIVE; + } + + return 1; +} \ No newline at end of file diff --git a/cl_dll/ev_hldm.cpp b/cl_dll/ev_hldm.cpp index 9787a839..b3a06f5e 100644 --- a/cl_dll/ev_hldm.cpp +++ b/cl_dll/ev_hldm.cpp @@ -317,6 +317,7 @@ void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType ) case BULLET_MONSTER_MP5: case BULLET_PLAYER_BUCKSHOT: case BULLET_PLAYER_357: + case BULLET_PLAYER_SNIPER: default: // smoke and decal EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ) ); @@ -445,6 +446,7 @@ void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int EV_HLDM_DecalGunshot( &tr, iBulletType ); break; case BULLET_PLAYER_357: + case BULLET_PLAYER_SNIPER: EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); EV_HLDM_DecalGunshot( &tr, iBulletType ); break; @@ -1303,23 +1305,36 @@ void EV_FireCrossbow( event_args_t *args ) { int idx; vec3_t origin; + vec3_t angles; + vec3_t velocity; + + vec3_t vecSrc, vecAiming; + vec3_t up, right, forward; + float flSpread = 0.01; idx = args->entindex; VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) ); - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat( 0.95, 1.0 ), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) ); + AngleVectors( angles, forward, right, up ); - //Only play the weapon anims if I shot it. if( EV_IsLocal( idx ) ) { - if( args->iparam1 ) - gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 ); - else if ( args->iparam2 ) - gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 ); + // Add muzzle flash to current weapon model + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 0 ); V_PunchAxis( 0, -2.0 ); } + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) ); + + EV_GetGunPosition( args, vecSrc, origin ); + + VectorCopy( forward, vecAiming ); + + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_SNIPER, 0, 0, args->fparam1, args->fparam2 ); } //====================== // CROSSBOW END @@ -1331,15 +1346,13 @@ void EV_FireCrossbow( event_args_t *args ) enum rpg_e { RPG_IDLE = 0, - RPG_FIDGET, - RPG_RELOAD, // to reload - RPG_FIRE2, // to empty - RPG_HOLSTER1, // loaded - RPG_DRAW1, // loaded - RPG_HOLSTER2, // unloaded - RPG_DRAW_UL, // unloaded - RPG_IDLE_UL, // unloaded idle - RPG_FIDGET_UL // unloaded fidget + RPG_DRAW1, + RPG_AIMED, + RPG_LAUNCH, + RPG_DOWN_TO_UP, + RPG_UP_TO_DOWN, + RPG_RELOAD_AIMED, + RPG_RELOAD_IDLE }; void EV_FireRpg( event_args_t *args ) @@ -1351,12 +1364,11 @@ void EV_FireRpg( event_args_t *args ) VectorCopy( args->origin, origin ); gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, ATTN_NORM, 0, PITCH_NORM ); - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/glauncher.wav", 0.7, ATTN_NORM, 0, PITCH_NORM ); //Only play the weapon anims if I shot it. if( EV_IsLocal( idx ) ) { - gEngfuncs.pEventAPI->EV_WeaponAnimation( RPG_FIRE2, 1 ); + gEngfuncs.pEventAPI->EV_WeaponAnimation( RPG_LAUNCH, 0 ); V_PunchAxis( 0, -5.0 ); } diff --git a/cl_dll/ev_hldm.h b/cl_dll/ev_hldm.h index bff43b1e..d42b8f46 100644 --- a/cl_dll/ev_hldm.h +++ b/cl_dll/ev_hldm.h @@ -17,7 +17,7 @@ typedef enum BULLET_PLAYER_357, // python BULLET_PLAYER_BUCKSHOT, // shotgun BULLET_PLAYER_CROWBAR, // crowbar swipe - + BULLET_PLAYER_SNIPER, BULLET_MONSTER_9MM, BULLET_MONSTER_MP5, BULLET_MONSTER_12MM @@ -30,11 +30,10 @@ enum glock_e GLOCK_IDLE3, GLOCK_SHOOT, GLOCK_SHOOT_EMPTY, + GLOCK_RELOAD_EMPTY, GLOCK_RELOAD, - GLOCK_RELOAD_NOT_EMPTY, GLOCK_DRAW, - GLOCK_HOLSTER, - GLOCK_ADD_SILENCER + GLOCK_EMPTY_IDLE }; enum shotgun_e diff --git a/cl_dll/hud.cpp b/cl_dll/hud.cpp index 0f3b45bc..c8ff5c56 100644 --- a/cl_dll/hud.cpp +++ b/cl_dll/hud.cpp @@ -227,6 +227,7 @@ void CHud::Init( void ) m_AmmoSecondary.Init(); m_TextMessage.Init(); m_StatusIcons.Init(); + m_Scope.Init(); m_MOTD.Init(); m_Scoreboard.Init(); @@ -396,6 +397,7 @@ void CHud::VidInit( void ) m_AmmoSecondary.VidInit(); m_TextMessage.VidInit(); m_StatusIcons.VidInit(); + m_Scope.VidInit(); m_Scoreboard.VidInit(); m_MOTD.VidInit(); } diff --git a/cl_dll/hud.h b/cl_dll/hud.h index ec236003..da8dbc53 100644 --- a/cl_dll/hud.h +++ b/cl_dll/hud.h @@ -556,6 +556,39 @@ private: icon_sprite_t m_IconList[MAX_ICONSPRITES]; }; +// +//----------------------------------------------------- +// +class CHudScope : public CHudBase +{ +public: + virtual int Init( void ); + virtual int VidInit( void ); + virtual int Draw( float fTime ); + virtual void Reset( void ); + int MsgFunc_Scope( const char *pszName, int iSize, void *pbuf ); + +private: + enum + { + SCOPE_U_L = 0, // Up - Left + SCOPE_U_M_L, // Up - Middle - Left + SCOPE_U_M_R, // Up - Middle - Right + SCOPE_U_R, // Up - Right + SCOPE_M_L, // Middle - Left + SCOPE_M_R, // Middle - right + SCOPE_L_L, // Low - left + SCOPE_L_M_L, // Low - middle - left + SCOPE_L_M_R, // Low - middle - right + SCOPE_L_R, // Low - right + + SCOPE_HSPRITE_COUNT // <-- Must be the last. + }; + + HSPRITE m_scopes[SCOPE_HSPRITE_COUNT]; + int m_ScopeSize; +}; + // //----------------------------------------------------- // @@ -631,6 +664,7 @@ public: CHudAmmoSecondary m_AmmoSecondary; CHudTextMessage m_TextMessage; CHudStatusIcons m_StatusIcons; + CHudScope m_Scope; CHudScoreboard m_Scoreboard; CHudMOTD m_MOTD; diff --git a/dlls/TheGate/command.cpp b/dlls/TheGate/command.cpp new file mode 100644 index 00000000..439e31b4 --- /dev/null +++ b/dlls/TheGate/command.cpp @@ -0,0 +1,100 @@ +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "customentity.h" +#include "effects.h" +#include "weapons.h" + +class CTriggerCommand : public CPointEntity +{ +public: + void Spawn(void); + void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); + +private: + void PlayMP3(CBaseEntity* pClient, const char* song); +}; + +LINK_ENTITY_TO_CLASS(trigger_command, CTriggerCommand); + +void CTriggerCommand::Spawn(void) +{ + pev->solid = SOLID_NOT; + pev->movetype = MOVETYPE_NONE; + pev->effects = 0; + pev->frame = 0; +} + +void CTriggerCommand::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) +{ + if (!pActivator || !pActivator->IsNetClient()) + return; + + const char* command = STRING(pev->netname); + + if (!command || !*command) + return; + + // ALERT(at_console, "%s with command \"%s\"\n", STRING(pev->classname), command); + + char* str = NULL; + + if ((str = (char*)strstr(command, "playmp3")) != NULL) + { + int pchlen = 0; + int extlen = 3; // "mp3" excluding NULL terminator. + int ideallen = 0; + + char* pch = NULL, *lastpch = NULL; + char* song = NULL; + + pch = strtok(str, " ."); + + while (pch) + { + pchlen = strlen(pch); + ideallen = (pchlen <= extlen) ? pchlen : extlen; + + if (strncmp(pch, "mp3", sizeof(char) * ideallen) == 0) + { + pch = NULL; + } + else + { + lastpch = pch; + pch = strtok(NULL, " ."); + } + } + + song = lastpch; + + PlayMP3(pActivator, song); + } + + UTIL_Remove(this); +} + +void CTriggerCommand::PlayMP3(CBaseEntity* pClient, const char* song) +{ + ASSERT(pClient != NULL); + + char cmd[128]; + sprintf(cmd, "play media/%s.mp3\n", song); + + CLIENT_COMMAND(ENT(pClient->pev),cmd); +} diff --git a/dlls/TheGate/scientist2.cpp b/dlls/TheGate/scientist2.cpp new file mode 100644 index 00000000..2e0939e7 --- /dev/null +++ b/dlls/TheGate/scientist2.cpp @@ -0,0 +1,103 @@ +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* This source code contains proprietary and confidential information of +* Valve LLC and its suppliers. Access to this code is restricted to +* persons who have executed a written SDK license with Valve. Any access, +* use or distribution of this code by or to any unlicensed person is illegal. +* +****/ + +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" +#include "talkmonster.h" +#include "schedule.h" +#include "defaultai.h" +#include "scripted.h" +#include "animation.h" +#include "soundent.h" +#include "scientist.h" + +class CScientist2 : public CScientist +{ +public: + void Spawn(void); + void Precache(void); + + BOOL CanHeal(void) { return FALSE; } + + MONSTERSTATE GetIdealState(void); + + void DeathSound(void) {} + void PainSound(void) {} +}; + +LINK_ENTITY_TO_CLASS(monster_scientist2, CScientist2); + +void CScientist2::Spawn(void) +{ + Precache(); + + SET_MODEL(ENT(pev), "models/scientist2.mdl"); + UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); + + pev->solid = SOLID_SLIDEBOX; + pev->movetype = MOVETYPE_STEP; + m_bloodColor = BLOOD_COLOR_RED; + pev->health = gSkillData.scientistHealth; + pev->view_ofs = Vector(0, 0, 50);// position of the eyes relative to monster's origin. + m_flFieldOfView = VIEW_FIELD_WIDE; // NOTE: we need a wide field of view so scientists will notice player and say hello + m_MonsterState = MONSTERSTATE_NONE; + + // m_flDistTooFar = 256.0; + + m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_OPEN_DOORS | bits_CAP_AUTO_DOORS | bits_CAP_USE; + + // White hands + pev->skin = 0; + + if (pev->body == -1) + {// -1 chooses a random head + pev->body = RANDOM_LONG(0, NUM_SCIENTIST_HEADS - 1);// pick a head, any head + } + + MonsterInit(); + SetUse(&CScientist2::FollowerUse); +} + +void CScientist2::Precache(void) +{ + PRECACHE_MODEL("models/scientist2.mdl"); + + // every new scientist must call this, otherwise + // when a level is loaded, nobody will talk (time is reset to 0) + TalkInit(); + + CTalkMonster::Precache(); +} + +MONSTERSTATE CScientist2::GetIdealState(void) +{ + switch (m_MonsterState) + { + case MONSTERSTATE_ALERT: + case MONSTERSTATE_IDLE: + return CScientist::GetIdealState(); + + case MONSTERSTATE_COMBAT: + m_IdealMonsterState = MONSTERSTATE_ALERT; + return CScientist::GetIdealState(); + + default: + return CScientist::GetIdealState(); + } + + return CScientist::GetIdealState(); +} \ No newline at end of file diff --git a/dlls/cbase.cpp b/dlls/cbase.cpp index 62b4eaa1..b5e5ad78 100644 --- a/dlls/cbase.cpp +++ b/dlls/cbase.cpp @@ -135,6 +135,20 @@ int DispatchSpawn( edict_t *pent ) if( pEntity ) { + // + // The Gate: + // + // Prevent level shutting down due to engine limitation. + // + if( FStrEq( STRING( gpGlobals->mapname ), "gate18" ) ) + { + if( FStringNull( pEntity->pev->targetname ) ) + { + if( FClassnameIs( pEntity->pev, "monster_furniture" ) ) + return 0; + } + } + // Initialize these or entities who don't link to the world won't have anything in here pEntity->pev->absmin = pEntity->pev->origin - Vector( 1, 1, 1 ); pEntity->pev->absmax = pEntity->pev->origin + Vector( 1, 1, 1 ); diff --git a/dlls/combat.cpp b/dlls/combat.cpp index 3a59844f..e0dd8957 100644 --- a/dlls/combat.cpp +++ b/dlls/combat.cpp @@ -1535,6 +1535,9 @@ Vector CBaseEntity::FireBulletsPlayer( ULONG cShots, Vector vecSrc, Vector vecDi case BULLET_PLAYER_357: pEntity->TraceAttack( pevAttacker, gSkillData.plrDmg357, vecDir, &tr, DMG_BULLET ); break; + case BULLET_PLAYER_SNIPER: + pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgCrossbowClient, vecDir, &tr, DMG_BULLET ); + break; case BULLET_NONE: // FIX pEntity->TraceAttack( pevAttacker, 50, vecDir, &tr, DMG_CLUB ); TEXTURETYPE_PlaySound( &tr, vecSrc, vecEnd, iBulletType ); diff --git a/dlls/crossbow.cpp b/dlls/crossbow.cpp index d34ad25d..211266f4 100644 --- a/dlls/crossbow.cpp +++ b/dlls/crossbow.cpp @@ -236,6 +236,8 @@ void CCrossbowBolt::ExplodeThink( void ) } #endif +extern int gmsgScope; + enum crossbow_e { CROSSBOW_IDLE1 = 0, // full @@ -393,68 +395,50 @@ void CCrossbow::FireSniperBolt() void CCrossbow::FireBolt() { - TraceResult tr; + // don't fire underwater + if( m_pPlayer->pev->waterlevel == 3 ) + { + PlayEmptySound(); + m_flNextPrimaryAttack = 0.15; + return; + } if( m_iClip == 0 ) { PlayEmptySound(); + m_flNextPrimaryAttack = 0.15; return; } - m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; + m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME; + m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; m_iClip--; - int flags; -#if defined( CLIENT_WEAPONS ) - flags = FEV_NOTHOST; -#else - flags = 0; -#endif - - PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usCrossbow, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType], 0, 0 ); + m_pPlayer->pev->effects = (int)( m_pPlayer->pev->effects ) | EF_MUZZLEFLASH; // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); - Vector anglesAim = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle; - UTIL_MakeVectors( anglesAim ); + Vector vecSrc = m_pPlayer->GetGunPosition(); + Vector vecAiming = m_pPlayer->GetAutoaimVector( AUTOAIM_2DEGREES ); + Vector vecDir = m_pPlayer->FireBulletsPlayer( 1, vecSrc, vecAiming, Vector( 0, 0, 0 ), 8192, BULLET_PLAYER_SNIPER, 2, 0, m_pPlayer->pev, m_pPlayer->random_seed ); - anglesAim.x = -anglesAim.x; - Vector vecSrc = m_pPlayer->GetGunPosition() - gpGlobals->v_up * 2; - Vector vecDir = gpGlobals->v_forward; - -#ifndef CLIENT_DLL - CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate(); - pBolt->pev->origin = vecSrc; - pBolt->pev->angles = anglesAim; - pBolt->pev->owner = m_pPlayer->edict(); - - if( m_pPlayer->pev->waterlevel == 3 ) - { - pBolt->pev->velocity = vecDir * BOLT_WATER_VELOCITY; - pBolt->pev->speed = BOLT_WATER_VELOCITY; - } - else - { - pBolt->pev->velocity = vecDir * BOLT_AIR_VELOCITY; - pBolt->pev->speed = BOLT_AIR_VELOCITY; - } - pBolt->pev->avelocity.z = 10; + int flags; +#if defined( CLIENT_WEAPONS ) + flags = FEV_NOTHOST; +#else + flags = 0; #endif - if( !m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 ) - // HEV suit - indicate out of ammo condition - m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 ); + PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usCrossbow, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType], 0, 0 ); - m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.75; + m_flNextPrimaryAttack = GetNextAttackDelay( 2.2 ); - m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75; + if( m_flNextPrimaryAttack < UTIL_WeaponTimeBase() ) + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 2.2; - if( m_iClip != 0 ) - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5.0; - else - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.75; + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); } void CCrossbow::SecondaryAttack() @@ -470,6 +454,12 @@ void CCrossbow::SecondaryAttack() m_fInZoom = 1; } +#ifndef CLIENT_DLL + MESSAGE_BEGIN( MSG_ONE, gmsgScope, NULL, m_pPlayer->pev ); + WRITE_BYTE( m_fInZoom ); + MESSAGE_END(); +#endif + pev->nextthink = UTIL_WeaponTimeBase() + 0.1; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.0; } @@ -484,7 +474,7 @@ void CCrossbow::Reload( void ) SecondaryAttack(); } - if( DefaultReload( 5, CROSSBOW_RELOAD, 4.5 ) ) + if( DefaultReload( 5, CROSSBOW_RELOAD, 3.2 ) ) { EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_ITEM, "weapons/xbow_reload1.wav", RANDOM_FLOAT( 0.95, 1.0 ), ATTN_NORM, 0, 93 + RANDOM_LONG( 0, 0xF ) ); } @@ -501,29 +491,13 @@ void CCrossbow::WeaponIdle( void ) float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 ); if( flRand <= 0.75 ) { - if( m_iClip ) - { - SendWeaponAnim( CROSSBOW_IDLE1 ); - } - else - { - SendWeaponAnim( CROSSBOW_IDLE2 ); - } - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); + SendWeaponAnim( CROSSBOW_IDLE1 ); + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 121.0 / 15.0; } else { - if( m_iClip ) - { - SendWeaponAnim( CROSSBOW_FIDGET1 ); - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 90.0 / 30.0; - } - else - { - SendWeaponAnim( CROSSBOW_FIDGET2 ); - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 80.0 / 30.0; - } - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); + SendWeaponAnim( CROSSBOW_FIDGET1 ); + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 121.0 / 15.0; } } } diff --git a/dlls/handgrenade.cpp b/dlls/handgrenade.cpp index 063b2886..443a61a3 100644 --- a/dlls/handgrenade.cpp +++ b/dlls/handgrenade.cpp @@ -26,13 +26,14 @@ enum handgrenade_e { HANDGRENADE_IDLE = 0, - HANDGRENADE_FIDGET, + HANDGRENADE_DRAW, HANDGRENADE_PINPULL, - HANDGRENADE_THROW1, // toss - HANDGRENADE_THROW2, // medium - HANDGRENADE_THROW3, // hard HANDGRENADE_HOLSTER, - HANDGRENADE_DRAW + HANDGRENADE_THROW, + HANDGRENADE_EXPLODING_IDLE, + HANDGRENADE_EXPLODING_DRAW, + HANDGRENADE_EXPLODING_PINPULL, + HANDGRENADE_EXPLODING_THROW }; LINK_ENTITY_TO_CLASS( weapon_handgrenade, CHandGrenade ) @@ -152,18 +153,7 @@ void CHandGrenade::WeaponIdle( void ) CGrenade::ShootTimed( m_pPlayer->pev, vecSrc, vecThrow, time ); - if( flVel < 500 ) - { - SendWeaponAnim( HANDGRENADE_THROW1 ); - } - else if( flVel < 1000 ) - { - SendWeaponAnim( HANDGRENADE_THROW2 ); - } - else - { - SendWeaponAnim( HANDGRENADE_THROW3 ); - } + SendWeaponAnim( HANDGRENADE_THROW ); // player "shoot" animation m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); @@ -206,6 +196,9 @@ void CHandGrenade::WeaponIdle( void ) if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] ) { + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 31.0 / 10.0; + SendWeaponAnim( HANDGRENADE_IDLE ); + int iAnim; float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 ); if( flRand <= 0.75 ) diff --git a/dlls/hgrunt.cpp b/dlls/hgrunt.cpp index 7b0eaa2c..a6e1687a 100644 --- a/dlls/hgrunt.cpp +++ b/dlls/hgrunt.cpp @@ -267,6 +267,10 @@ int CHGrunt::IRelationship( CBaseEntity *pTarget ) return R_NM; } + if( FClassnameIs( pTarget->pev, "monster_houndeye" ) ) + { + return R_NO; + } return CSquadMonster::IRelationship( pTarget ); } diff --git a/dlls/houndeye.cpp b/dlls/houndeye.cpp index f35b0740..a86ec353 100644 --- a/dlls/houndeye.cpp +++ b/dlls/houndeye.cpp @@ -32,7 +32,7 @@ extern CGraph WorldGraph; // houndeye does 20 points of damage spread over a sphere 384 units in diameter, and each additional // squad member increases the BASE damage by 110%, per the spec. #define HOUNDEYE_MAX_SQUAD_SIZE 4 -#define HOUNDEYE_MAX_ATTACK_RADIUS 384 +#define HOUNDEYE_MAX_ATTACK_RADIUS 144 #define HOUNDEYE_SQUAD_BONUS (float)1.1 #define HOUNDEYE_EYE_FRAMES 4 // how many different switchable maps for the eye @@ -98,6 +98,7 @@ public: BOOL FCanActiveIdle( void ); Schedule_t *GetScheduleOfType( int Type ); Schedule_t *GetSchedule( void ); + int IRelationship(CBaseEntity *pTarget); int Save( CSave &save ); int Restore( CRestore &restore ); @@ -290,8 +291,17 @@ void CHoundeye::HandleAnimEvent( MonsterEvent_t *pEvent ) break; } case HOUND_AE_THUMP: - // emit the shockwaves - SonicAttack(); + { + // SOUND HERE! + CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.bullsquidDmgBite, DMG_SLASH ); + + if( pHurt ) + { + pHurt->pev->punchangle.x = 5; + pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_forward * 16; + pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_up * 2; + } + } break; case HOUND_AE_ANGERSOUND1: EMIT_SOUND( ENT( pev ), CHAN_VOICE, "houndeye/he_pain3.wav", 1, ATTN_NORM ); @@ -323,7 +333,7 @@ void CHoundeye::Spawn() pev->solid = SOLID_SLIDEBOX; pev->movetype = MOVETYPE_STEP; - m_bloodColor = BLOOD_COLOR_YELLOW; + m_bloodColor = BLOOD_COLOR_RED; pev->effects = 0; pev->health = gSkillData.houndeyeHealth; pev->yaw_speed = 5;//!!! should we put this in the monster's changeanim function since turn rates may vary with state/anim? @@ -1293,3 +1303,13 @@ Schedule_t *CHoundeye::GetSchedule( void ) return CSquadMonster::GetSchedule(); } + +int CHoundeye::IRelationship( CBaseEntity *pTarget ) +{ + if( FClassnameIs( pTarget->pev, "monster_human_grunt" ) || FClassnameIs( pTarget->pev, "monster_grunt_repel" ) ) + { + return R_NO; + } + + return CSquadMonster::IRelationship( pTarget ); +} diff --git a/dlls/mp5.cpp b/dlls/mp5.cpp index 7d05d5e1..a6fe3444 100644 --- a/dlls/mp5.cpp +++ b/dlls/mp5.cpp @@ -173,10 +173,6 @@ void CMP5::PrimaryAttack() #endif PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usMP5, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, 0, 0, 0, 0 ); - if( !m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0 ) - // HEV suit - indicate out of ammo condition - m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 ); - m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1; if( m_flNextPrimaryAttack < UTIL_WeaponTimeBase() ) @@ -230,10 +226,6 @@ void CMP5::SecondaryAttack( void ) m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5;// idle pretty soon after shooting. - - if( !m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] ) - // HEV suit - indicate out of ammo condition - m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 ); } void CMP5::Reload( void ) @@ -241,7 +233,7 @@ void CMP5::Reload( void ) if( m_pPlayer->ammo_9mm <= 0 ) return; - DefaultReload( MP5_MAX_CLIP, MP5_RELOAD, 1.5 ); + DefaultReload( MP5_MAX_CLIP, MP5_RELOAD, 2.5 ); } void CMP5::WeaponIdle( void ) diff --git a/dlls/player.cpp b/dlls/player.cpp index 2f097072..1100f225 100644 --- a/dlls/player.cpp +++ b/dlls/player.cpp @@ -115,6 +115,7 @@ TYPEDESCRIPTION CBasePlayer::m_playerSaveData[] = DEFINE_FIELD( CBasePlayer, m_pTank, FIELD_EHANDLE ), DEFINE_FIELD( CBasePlayer, m_iHideHUD, FIELD_INTEGER ), DEFINE_FIELD( CBasePlayer, m_iFOV, FIELD_INTEGER ), + DEFINE_FIELD( CBasePlayer, m_bUpdatePlayerModel, FIELD_BOOLEAN ), //DEFINE_FIELD( CBasePlayer, m_fDeadTime, FIELD_FLOAT ), // only used in multiplayer games //DEFINE_FIELD( CBasePlayer, m_fGameHUDInitialized, FIELD_INTEGER ), // only used in multiplayer games @@ -184,6 +185,8 @@ int gmsgTeamNames = 0; int gmsgStatusText = 0; int gmsgStatusValue = 0; +int gmsgScope = 0; + void LinkUserMessages( void ) { // Already taken care of? @@ -228,6 +231,8 @@ void LinkUserMessages( void ) gmsgStatusText = REG_USER_MSG( "StatusText", -1 ); gmsgStatusValue = REG_USER_MSG( "StatusValue", 3 ); + + gmsgScope = REG_USER_MSG( "Scope", 1 ); } LINK_ENTITY_TO_CLASS( player, CBasePlayer ) @@ -2499,6 +2504,12 @@ void CBasePlayer::PostThink() m_afButtonLast = pev->button; pt_end: + if( m_bUpdatePlayerModel ) + { + CLIENT_COMMAND( edict(), "model player\n" ); + + m_bUpdatePlayerModel = FALSE; + } #if defined( CLIENT_WEAPONS ) // Decay timers on weapons // go through all of the weapons and make a list of the ones to pack @@ -2775,6 +2786,8 @@ void CBasePlayer::Spawn( void ) m_flNextChatTime = gpGlobals->time; + m_bUpdatePlayerModel = FALSE; + g_pGameRules->PlayerSpawn( this ); } @@ -2898,6 +2911,8 @@ int CBasePlayer::Restore( CRestore &restore ) // Barring that, we clear it out here instead of using the incorrect restored time value. m_flNextAttack = UTIL_WeaponTimeBase(); #endif + m_bUpdatePlayerModel = TRUE; + return status; } diff --git a/dlls/player.h b/dlls/player.h index e75787ee..94a52295 100644 --- a/dlls/player.h +++ b/dlls/player.h @@ -308,6 +308,8 @@ public: char m_SbarString1[ SBAR_STRING_SIZE ]; float m_flNextChatTime; + + BOOL m_bUpdatePlayerModel; }; #define AUTOAIM_2DEGREES 0.0348994967025 diff --git a/dlls/rpg.cpp b/dlls/rpg.cpp index 1fec5cf1..a083a3b7 100644 --- a/dlls/rpg.cpp +++ b/dlls/rpg.cpp @@ -26,15 +26,13 @@ enum rpg_e { RPG_IDLE = 0, - RPG_FIDGET, - RPG_RELOAD, // to reload - RPG_FIRE2, // to empty - RPG_HOLSTER1, // loaded - RPG_DRAW1, // loaded - RPG_HOLSTER2, // unloaded - RPG_DRAW_UL, // unloaded - RPG_IDLE_UL, // unloaded idle - RPG_FIDGET_UL // unloaded fidget + RPG_DRAW1, + RPG_AIMED, + RPG_LAUNCH, + RPG_DOWN_TO_UP, + RPG_UP_TO_DOWN, + RPG_RELOAD_AIMED, + RPG_RELOAD_IDLE }; LINK_ENTITY_TO_CLASS( weapon_rpg, CRpg ) @@ -132,16 +130,16 @@ void CRpgRocket::Spawn( void ) pev->classname = MAKE_STRING( "rpg_rocket" ); SetThink( &CRpgRocket::IgniteThink ); - SetTouch( &CGrenade::ExplodeTouch ); + SetTouch( &CRpgRocket::ExplodeTouch ); - pev->angles.x -= 30; + pev->angles.x -= 1; UTIL_MakeVectors( pev->angles ); - pev->angles.x = -( pev->angles.x + 30 ); + pev->angles.x = -( pev->angles.x + 1 ); pev->velocity = gpGlobals->v_forward * 250; - pev->gravity = 0.5; + pev->gravity = 0.0; - pev->nextthink = gpGlobals->time + 0.4; + pev->nextthink = gpGlobals->time + 0.05; pev->dmg = gSkillData.plrDmgRPG; } @@ -194,8 +192,58 @@ void CRpgRocket::IgniteThink( void ) m_flIgniteTime = gpGlobals->time; - // set to follow laser spot - SetThink( &CRpgRocket::FollowThink ); + // Move in forward direction. Ignore guiding. + SetThink( &CRpgRocket::FlyThink ); + pev->nextthink = gpGlobals->time + 0.1; +} + +void CRpgRocket::FlyThink( void ) +{ + Vector vecTarget; + + UTIL_MakeAimVectors( pev->angles ); + + vecTarget = gpGlobals->v_forward; + + pev->angles = UTIL_VecToAngles( vecTarget ); + + // this acceleration and turning math is totally wrong, but it seems to respond well so don't change it. + float flSpeed = pev->velocity.Length(); + if( gpGlobals->time - m_flIgniteTime < 1.0 ) + { + pev->velocity = pev->velocity * 0.2 + vecTarget * ( flSpeed * 0.8 + 400 ); + if( pev->waterlevel == 3 ) + { + // go slow underwater + if( pev->velocity.Length() > 300 ) + { + pev->velocity = pev->velocity.Normalize() * 300; + } + UTIL_BubbleTrail( pev->origin - pev->velocity * 0.1, pev->origin, 4 ); + } + else + { + if( pev->velocity.Length() > 2000 ) + { + pev->velocity = pev->velocity.Normalize() * 2000; + } + } + } + else + { + if( pev->effects & EF_LIGHT ) + { + pev->effects = 0; + STOP_SOUND( ENT( pev ), CHAN_VOICE, "weapons/rocket1.wav" ); + } + pev->velocity = pev->velocity * 0.2 + vecTarget * flSpeed * 0.798; + if( pev->waterlevel == 0 && pev->velocity.Length() < 1500 ) + { + Detonate(); + } + } + // ALERT( at_console, "%.0f\n", flSpeed ); + pev->nextthink = gpGlobals->time + 0.1; } @@ -299,23 +347,8 @@ void CRpg::Reload( void ) m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5; - if( m_cActiveRockets && m_fSpotActive ) - { - // no reloading when there are active missiles tracking the designator. - // ward off future autoreload attempts by setting next attack time into the future for a bit. - return; - } - -#ifndef CLIENT_DLL - if( m_pSpot && m_fSpotActive ) - { - m_pSpot->Suspend( 2.1 ); - m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 2.1; - } -#endif - if( m_iClip == 0 ) - iResult = DefaultReload( RPG_MAX_CLIP, RPG_RELOAD, 2 ); + iResult = DefaultReload( RPG_MAX_CLIP, RPG_RELOAD_IDLE, 3.5 ); if( iResult ) m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); @@ -327,7 +360,7 @@ void CRpg::Spawn() m_iId = WEAPON_RPG; SET_MODEL( ENT( pev ), "models/w_rpg.mdl" ); - m_fSpotActive = 1; + m_fSpotActive = 0; #ifdef CLIENT_DLL if( bIsMultiplayer() ) @@ -394,22 +427,11 @@ int CRpg::AddToPlayer( CBasePlayer *pPlayer ) BOOL CRpg::Deploy() { - if( m_iClip == 0 ) - { - return DefaultDeploy( "models/v_rpg.mdl", "models/p_rpg.mdl", RPG_DRAW_UL, "rpg" ); - } - return DefaultDeploy( "models/v_rpg.mdl", "models/p_rpg.mdl", RPG_DRAW1, "rpg" ); } BOOL CRpg::CanHolster( void ) { - if( m_fSpotActive && m_cActiveRockets ) - { - // can't put away while guiding a missile. - return FALSE; - } - return TRUE; } @@ -418,16 +440,6 @@ void CRpg::Holster( int skiplocal /* = 0 */ ) m_fInReload = FALSE;// cancel any reload in progress. m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - - SendWeaponAnim( RPG_HOLSTER1 ); - -#ifndef CLIENT_DLL - if( m_pSpot ) - { - m_pSpot->Killed( NULL, GIB_NEVER ); - m_pSpot = NULL; - } -#endif } void CRpg::PrimaryAttack() @@ -471,27 +483,14 @@ void CRpg::PrimaryAttack() PlayEmptySound(); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.2; } - UpdateSpot(); } void CRpg::SecondaryAttack() { - m_fSpotActive = !m_fSpotActive; - -#ifndef CLIENT_DLL - if( !m_fSpotActive && m_pSpot ) - { - m_pSpot->Killed( NULL, GIB_NORMAL ); - m_pSpot = NULL; - } -#endif - m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.2; } void CRpg::WeaponIdle( void ) { - UpdateSpot(); - ResetEmptySound(); if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() ) @@ -499,28 +498,8 @@ void CRpg::WeaponIdle( void ) if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] ) { - int iAnim; - float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 ); - if( flRand <= 0.75 || m_fSpotActive ) - { - if( m_iClip == 0 ) - iAnim = RPG_IDLE_UL; - else - iAnim = RPG_IDLE; - - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 90.0 / 15.0; - } - else - { - if( m_iClip == 0 ) - iAnim = RPG_FIDGET_UL; - else - iAnim = RPG_FIDGET; - - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3.0; - } - - SendWeaponAnim( iAnim ); + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0 / 20.0; + SendWeaponAnim( RPG_IDLE ); } else { diff --git a/dlls/scientist.cpp b/dlls/scientist.cpp index 4e60c58e..39945b30 100644 --- a/dlls/scientist.cpp +++ b/dlls/scientist.cpp @@ -26,16 +26,7 @@ #include "scripted.h" #include "animation.h" #include "soundent.h" - -#define NUM_SCIENTIST_HEADS 4 // four heads available for scientist model - -enum -{ - HEAD_GLASSES = 0, - HEAD_EINSTEIN = 1, - HEAD_LUTHER = 2, - HEAD_SLICK = 3 -}; +#include "scientist.h" enum { @@ -68,55 +59,6 @@ enum //======================================================= // Scientist //======================================================= -class CScientist : public CTalkMonster -{ -public: - void Spawn( void ); - void Precache( void ); - - void SetYawSpeed( void ); - int Classify( void ); - void HandleAnimEvent( MonsterEvent_t *pEvent ); - void RunTask( Task_t *pTask ); - void StartTask( Task_t *pTask ); - int ObjectCaps( void ) { return CTalkMonster::ObjectCaps() | FCAP_IMPULSE_USE; } - int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ); - virtual int FriendNumber( int arrayNumber ); - void SetActivity( Activity newActivity ); - Activity GetStoppedActivity( void ); - int ISoundMask( void ); - void DeclineFollowing( void ); - - float CoverRadius( void ) { return 1200; } // Need more room for cover because scientists want to get far away! - BOOL DisregardEnemy( CBaseEntity *pEnemy ) { return !pEnemy->IsAlive() || ( gpGlobals->time - m_fearTime ) > 15; } - - BOOL CanHeal( void ); - void Heal( void ); - void Scream( void ); - - // Override these to set behavior - Schedule_t *GetScheduleOfType( int Type ); - Schedule_t *GetSchedule( void ); - MONSTERSTATE GetIdealState( void ); - - void DeathSound( void ); - void PainSound( void ); - - void TalkInit( void ); - - void Killed( entvars_t *pevAttacker, int iGib ); - - virtual int Save( CSave &save ); - virtual int Restore( CRestore &restore ); - static TYPEDESCRIPTION m_SaveData[]; - - CUSTOM_SCHEDULES - -private: - float m_painTime; - float m_healTime; - float m_fearTime; -}; LINK_ENTITY_TO_CLASS( monster_scientist, CScientist ) @@ -1082,20 +1024,6 @@ int CScientist::FriendNumber( int arrayNumber ) //========================================================= // Dead Scientist PROP //========================================================= -class CDeadScientist : public CBaseMonster -{ -public: - void Spawn( void ); - int Classify( void ) - { - return CLASS_HUMAN_PASSIVE; - } - - void KeyValue( KeyValueData *pkvd ); - int m_iPose;// which sequence to display - static char *m_szPoses[7]; -}; - char *CDeadScientist::m_szPoses[] = { "lying_on_back", @@ -1160,27 +1088,6 @@ void CDeadScientist::Spawn() //========================================================= // Sitting Scientist PROP //========================================================= -class CSittingScientist : public CScientist // kdb: changed from public CBaseMonster so he can speak -{ -public: - void Spawn( void ); - void Precache( void ); - - void EXPORT SittingThink( void ); - int Classify( void ); - virtual int Save( CSave &save ); - virtual int Restore( CRestore &restore ); - static TYPEDESCRIPTION m_SaveData[]; - - virtual void SetAnswerQuestion( CTalkMonster *pSpeaker ); - int FriendNumber( int arrayNumber ); - - int FIdleSpeak( void ); - int m_baseSequence; - int m_headTurn; - float m_flResponseDelay; -}; - LINK_ENTITY_TO_CLASS( monster_sitting_scientist, CSittingScientist ) TYPEDESCRIPTION CSittingScientist::m_SaveData[] = diff --git a/dlls/scientist.h b/dlls/scientist.h new file mode 100644 index 00000000..ea5c6330 --- /dev/null +++ b/dlls/scientist.h @@ -0,0 +1,119 @@ +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +#ifndef SCIENTIST_H +#define SCIENTIST_H + +#if defined ( THEGATE_DLL ) +#define NUM_SCIENTIST_HEADS 4 // four heads available for scientist model +enum { HEAD_GLASSES = 0, HEAD_EINSTEIN = 1, HEAD_LUTHER = 2, HEAD_SLICK = 3 }; + +//======================================================= +// Scientist +//======================================================= + +class CScientist : public CTalkMonster +{ +public: + void Spawn( void ); + void Precache( void ); + + void SetYawSpeed( void ); + int Classify ( void ); + void HandleAnimEvent( MonsterEvent_t *pEvent ); + void RunTask( Task_t *pTask ); + void StartTask( Task_t *pTask ); + int ObjectCaps( void ) { return CTalkMonster :: ObjectCaps() | FCAP_IMPULSE_USE; } + int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType); + virtual int FriendNumber( int arrayNumber ); + void SetActivity ( Activity newActivity ); + Activity GetStoppedActivity( void ); + int ISoundMask( void ); + void DeclineFollowing( void ); + + float CoverRadius( void ) { return 1200; } // Need more room for cover because scientists want to get far away! + BOOL DisregardEnemy( CBaseEntity *pEnemy ) { return !pEnemy->IsAlive() || (gpGlobals->time - m_fearTime) > 15; } + + BOOL CanHeal( void ); + void Heal( void ); + void Scream( void ); + + // Override these to set behavior + Schedule_t *GetScheduleOfType ( int Type ); + Schedule_t *GetSchedule ( void ); + MONSTERSTATE GetIdealState ( void ); + + void DeathSound( void ); + void PainSound( void ); + + void TalkInit( void ); + + void Killed( entvars_t *pevAttacker, int iGib ); + + virtual int Save( CSave &save ); + virtual int Restore( CRestore &restore ); + static TYPEDESCRIPTION m_SaveData[]; + + CUSTOM_SCHEDULES; + +private: + float m_painTime; + float m_healTime; + float m_fearTime; +}; + + +//========================================================= +// Dead Scientist PROP +//========================================================= +class CDeadScientist : public CBaseMonster +{ +public: + void Spawn(void); + int Classify(void) { return CLASS_HUMAN_PASSIVE; } + + void KeyValue(KeyValueData *pkvd); + int m_iPose;// which sequence to display + static char *m_szPoses[7]; +}; + +//========================================================= +// Sitting Scientist PROP +//========================================================= +class CSittingScientist : public CScientist // kdb: changed from public CBaseMonster so he can speak +{ +public: + void Spawn( void ); + void Precache( void ); + + void EXPORT SittingThink( void ); + int Classify ( void ); + virtual int Save( CSave &save ); + virtual int Restore( CRestore &restore ); + static TYPEDESCRIPTION m_SaveData[]; + + virtual void SetAnswerQuestion( CTalkMonster *pSpeaker ); + int FriendNumber( int arrayNumber ); + + int FIdleSpeak ( void ); + int m_baseSequence; + int m_headTurn; + float m_flResponseDelay; +}; + + +#endif // defined ( THEGATE_DLL ) + +#endif // SCIENTIST_H \ No newline at end of file diff --git a/dlls/scripted.cpp b/dlls/scripted.cpp index f3cf37c5..40d25cce 100644 --- a/dlls/scripted.cpp +++ b/dlls/scripted.cpp @@ -1157,11 +1157,23 @@ public: void Spawn( void ); void Die( void ); int Classify( void ); - virtual int ObjectCaps( void ) { return (CBaseMonster::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } + virtual int ObjectCaps( void ); }; LINK_ENTITY_TO_CLASS( monster_furniture, CFurniture ) +int CFurniture::ObjectCaps( void ) +{ + int caps = ( CBaseMonster::ObjectCaps() & ~FCAP_ACROSS_TRANSITION ); + + if( FStrEq( STRING( gpGlobals->mapname ), "gate18" ) ) + { + caps |= FCAP_DONT_SAVE; + } + + return caps; +} + //========================================================= // Furniture is killed //========================================================= diff --git a/dlls/triggers.cpp b/dlls/triggers.cpp index d7f9483c..3901b0f6 100644 --- a/dlls/triggers.cpp +++ b/dlls/triggers.cpp @@ -779,6 +779,20 @@ void CTargetCDAudio::Play( void ) void CTriggerHurt::Spawn( void ) { + // + // The Gate: + // + // Remove to prevent a crash. + // + if( FStrEq( STRING( gpGlobals->mapname ), "tombtest2" ) ) + { + if( !FStringNull( pev->targetname ) && FStrEq( STRING( pev->targetname ), "secondspikes" ) ) + { + UTIL_Remove( this ); + return; + } + } + InitTrigger(); SetTouch( &CBaseTrigger::HurtTouch ); diff --git a/dlls/weapons.cpp b/dlls/weapons.cpp index 3e2ef386..e7fd7845 100644 --- a/dlls/weapons.cpp +++ b/dlls/weapons.cpp @@ -169,6 +169,7 @@ void DecalGunshot( TraceResult *pTrace, int iBulletType ) case BULLET_MONSTER_MP5: case BULLET_PLAYER_BUCKSHOT: case BULLET_PLAYER_357: + case BULLET_PLAYER_SNIPER: default: // smoke and decal UTIL_GunshotDecalTrace( pTrace, DamageDecal( pEntity, DMG_BULLET ) ); diff --git a/dlls/weapons.h b/dlls/weapons.h index 5112254a..7700739b 100644 --- a/dlls/weapons.h +++ b/dlls/weapons.h @@ -174,7 +174,7 @@ typedef enum BULLET_PLAYER_357, // python BULLET_PLAYER_BUCKSHOT, // shotgun BULLET_PLAYER_CROWBAR, // crowbar swipe - + BULLET_PLAYER_SNIPER, BULLET_MONSTER_9MM, BULLET_MONSTER_MP5, BULLET_MONSTER_12MM @@ -710,6 +710,8 @@ public: static TYPEDESCRIPTION m_SaveData[]; void Spawn( void ); void Precache( void ); + + void EXPORT FlyThink( void ); void EXPORT FollowThink( void ); void EXPORT IgniteThink( void ); void EXPORT RocketTouch( CBaseEntity *pOther );