Browse Source

Merge @malortie's patches for The Gate.

thegate
Night Owl 8 years ago
parent
commit
89eb528c16
  1. 288
      cl_dll/TheGate/scope.cpp
  2. 48
      cl_dll/ev_hldm.cpp
  3. 7
      cl_dll/ev_hldm.h
  4. 2
      cl_dll/hud.cpp
  5. 34
      cl_dll/hud.h
  6. 100
      dlls/TheGate/command.cpp
  7. 103
      dlls/TheGate/scientist2.cpp
  8. 14
      dlls/cbase.cpp
  9. 3
      dlls/combat.cpp
  10. 100
      dlls/crossbow.cpp
  11. 27
      dlls/handgrenade.cpp
  12. 4
      dlls/hgrunt.cpp
  13. 28
      dlls/houndeye.cpp
  14. 10
      dlls/mp5.cpp
  15. 15
      dlls/player.cpp
  16. 2
      dlls/player.h
  17. 157
      dlls/rpg.cpp
  18. 95
      dlls/scientist.cpp
  19. 119
      dlls/scientist.h
  20. 14
      dlls/scripted.cpp
  21. 14
      dlls/triggers.cpp
  22. 1
      dlls/weapons.cpp
  23. 4
      dlls/weapons.h

288
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 <string.h>
#include <stdio.h>
#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;
}

48
cl_dll/ev_hldm.cpp

@ -317,6 +317,7 @@ void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType )
case BULLET_MONSTER_MP5: case BULLET_MONSTER_MP5:
case BULLET_PLAYER_BUCKSHOT: case BULLET_PLAYER_BUCKSHOT:
case BULLET_PLAYER_357: case BULLET_PLAYER_357:
case BULLET_PLAYER_SNIPER:
default: default:
// smoke and decal // smoke and decal
EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ) ); 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 ); EV_HLDM_DecalGunshot( &tr, iBulletType );
break; break;
case BULLET_PLAYER_357: case BULLET_PLAYER_357:
case BULLET_PLAYER_SNIPER:
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType ); EV_HLDM_DecalGunshot( &tr, iBulletType );
break; break;
@ -1303,23 +1305,36 @@ void EV_FireCrossbow( event_args_t *args )
{ {
int idx; int idx;
vec3_t origin; 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; idx = args->entindex;
VectorCopy( args->origin, origin ); 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 ) ); AngleVectors( angles, forward, right, up );
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 ) );
//Only play the weapon anims if I shot it.
if( EV_IsLocal( idx ) ) if( EV_IsLocal( idx ) )
{ {
if( args->iparam1 ) // Add muzzle flash to current weapon model
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 ); EV_MuzzleFlash();
else if ( args->iparam2 ) gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 0 );
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 );
V_PunchAxis( 0, -2.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 // CROSSBOW END
@ -1331,15 +1346,13 @@ void EV_FireCrossbow( event_args_t *args )
enum rpg_e enum rpg_e
{ {
RPG_IDLE = 0, RPG_IDLE = 0,
RPG_FIDGET, RPG_DRAW1,
RPG_RELOAD, // to reload RPG_AIMED,
RPG_FIRE2, // to empty RPG_LAUNCH,
RPG_HOLSTER1, // loaded RPG_DOWN_TO_UP,
RPG_DRAW1, // loaded RPG_UP_TO_DOWN,
RPG_HOLSTER2, // unloaded RPG_RELOAD_AIMED,
RPG_DRAW_UL, // unloaded RPG_RELOAD_IDLE
RPG_IDLE_UL, // unloaded idle
RPG_FIDGET_UL // unloaded fidget
}; };
void EV_FireRpg( event_args_t *args ) void EV_FireRpg( event_args_t *args )
@ -1351,12 +1364,11 @@ void EV_FireRpg( event_args_t *args )
VectorCopy( args->origin, origin ); 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_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. //Only play the weapon anims if I shot it.
if( EV_IsLocal( idx ) ) if( EV_IsLocal( idx ) )
{ {
gEngfuncs.pEventAPI->EV_WeaponAnimation( RPG_FIRE2, 1 ); gEngfuncs.pEventAPI->EV_WeaponAnimation( RPG_LAUNCH, 0 );
V_PunchAxis( 0, -5.0 ); V_PunchAxis( 0, -5.0 );
} }

7
cl_dll/ev_hldm.h

@ -17,7 +17,7 @@ typedef enum
BULLET_PLAYER_357, // python BULLET_PLAYER_357, // python
BULLET_PLAYER_BUCKSHOT, // shotgun BULLET_PLAYER_BUCKSHOT, // shotgun
BULLET_PLAYER_CROWBAR, // crowbar swipe BULLET_PLAYER_CROWBAR, // crowbar swipe
BULLET_PLAYER_SNIPER,
BULLET_MONSTER_9MM, BULLET_MONSTER_9MM,
BULLET_MONSTER_MP5, BULLET_MONSTER_MP5,
BULLET_MONSTER_12MM BULLET_MONSTER_12MM
@ -30,11 +30,10 @@ enum glock_e
GLOCK_IDLE3, GLOCK_IDLE3,
GLOCK_SHOOT, GLOCK_SHOOT,
GLOCK_SHOOT_EMPTY, GLOCK_SHOOT_EMPTY,
GLOCK_RELOAD_EMPTY,
GLOCK_RELOAD, GLOCK_RELOAD,
GLOCK_RELOAD_NOT_EMPTY,
GLOCK_DRAW, GLOCK_DRAW,
GLOCK_HOLSTER, GLOCK_EMPTY_IDLE
GLOCK_ADD_SILENCER
}; };
enum shotgun_e enum shotgun_e

2
cl_dll/hud.cpp

@ -227,6 +227,7 @@ void CHud::Init( void )
m_AmmoSecondary.Init(); m_AmmoSecondary.Init();
m_TextMessage.Init(); m_TextMessage.Init();
m_StatusIcons.Init(); m_StatusIcons.Init();
m_Scope.Init();
m_MOTD.Init(); m_MOTD.Init();
m_Scoreboard.Init(); m_Scoreboard.Init();
@ -396,6 +397,7 @@ void CHud::VidInit( void )
m_AmmoSecondary.VidInit(); m_AmmoSecondary.VidInit();
m_TextMessage.VidInit(); m_TextMessage.VidInit();
m_StatusIcons.VidInit(); m_StatusIcons.VidInit();
m_Scope.VidInit();
m_Scoreboard.VidInit(); m_Scoreboard.VidInit();
m_MOTD.VidInit(); m_MOTD.VidInit();
} }

34
cl_dll/hud.h

@ -556,6 +556,39 @@ private:
icon_sprite_t m_IconList[MAX_ICONSPRITES]; 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; CHudAmmoSecondary m_AmmoSecondary;
CHudTextMessage m_TextMessage; CHudTextMessage m_TextMessage;
CHudStatusIcons m_StatusIcons; CHudStatusIcons m_StatusIcons;
CHudScope m_Scope;
CHudScoreboard m_Scoreboard; CHudScoreboard m_Scoreboard;
CHudMOTD m_MOTD; CHudMOTD m_MOTD;

100
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);
}

103
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();
}

14
dlls/cbase.cpp

@ -135,6 +135,20 @@ int DispatchSpawn( edict_t *pent )
if( pEntity ) 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 // 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->absmin = pEntity->pev->origin - Vector( 1, 1, 1 );
pEntity->pev->absmax = pEntity->pev->origin + Vector( 1, 1, 1 ); pEntity->pev->absmax = pEntity->pev->origin + Vector( 1, 1, 1 );

3
dlls/combat.cpp

@ -1535,6 +1535,9 @@ Vector CBaseEntity::FireBulletsPlayer( ULONG cShots, Vector vecSrc, Vector vecDi
case BULLET_PLAYER_357: case BULLET_PLAYER_357:
pEntity->TraceAttack( pevAttacker, gSkillData.plrDmg357, vecDir, &tr, DMG_BULLET ); pEntity->TraceAttack( pevAttacker, gSkillData.plrDmg357, vecDir, &tr, DMG_BULLET );
break; break;
case BULLET_PLAYER_SNIPER:
pEntity->TraceAttack( pevAttacker, gSkillData.plrDmgCrossbowClient, vecDir, &tr, DMG_BULLET );
break;
case BULLET_NONE: // FIX case BULLET_NONE: // FIX
pEntity->TraceAttack( pevAttacker, 50, vecDir, &tr, DMG_CLUB ); pEntity->TraceAttack( pevAttacker, 50, vecDir, &tr, DMG_CLUB );
TEXTURETYPE_PlaySound( &tr, vecSrc, vecEnd, iBulletType ); TEXTURETYPE_PlaySound( &tr, vecSrc, vecEnd, iBulletType );

100
dlls/crossbow.cpp

@ -236,6 +236,8 @@ void CCrossbowBolt::ExplodeThink( void )
} }
#endif #endif
extern int gmsgScope;
enum crossbow_e enum crossbow_e
{ {
CROSSBOW_IDLE1 = 0, // full CROSSBOW_IDLE1 = 0, // full
@ -393,68 +395,50 @@ void CCrossbow::FireSniperBolt()
void CCrossbow::FireBolt() 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 ) if( m_iClip == 0 )
{ {
PlayEmptySound(); PlayEmptySound();
m_flNextPrimaryAttack = 0.15;
return; return;
} }
m_pPlayer->m_iWeaponVolume = QUIET_GUN_VOLUME; m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
m_iClip--; m_iClip--;
int flags; m_pPlayer->pev->effects = (int)( m_pPlayer->pev->effects ) | EF_MUZZLEFLASH;
#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 );
// player "shoot" animation // player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
Vector anglesAim = m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle; Vector vecSrc = m_pPlayer->GetGunPosition();
UTIL_MakeVectors( anglesAim ); 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; int flags;
Vector vecSrc = m_pPlayer->GetGunPosition() - gpGlobals->v_up * 2; #if defined( CLIENT_WEAPONS )
Vector vecDir = gpGlobals->v_forward; flags = FEV_NOTHOST;
#else
#ifndef CLIENT_DLL flags = 0;
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;
#endif #endif
if( !m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 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 );
// HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 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() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5.0;
else
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.75;
} }
void CCrossbow::SecondaryAttack() void CCrossbow::SecondaryAttack()
@ -470,6 +454,12 @@ void CCrossbow::SecondaryAttack()
m_fInZoom = 1; 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; pev->nextthink = UTIL_WeaponTimeBase() + 0.1;
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.0; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.0;
} }
@ -484,7 +474,7 @@ void CCrossbow::Reload( void )
SecondaryAttack(); 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 ) ); 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 ); float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
if( flRand <= 0.75 ) if( flRand <= 0.75 )
{ {
if( m_iClip ) SendWeaponAnim( CROSSBOW_IDLE1 );
{ m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 121.0 / 15.0;
SendWeaponAnim( CROSSBOW_IDLE1 );
}
else
{
SendWeaponAnim( CROSSBOW_IDLE2 );
}
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
} }
else else
{ {
if( m_iClip ) SendWeaponAnim( CROSSBOW_FIDGET1 );
{ m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 121.0 / 15.0;
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 );
} }
} }
} }

27
dlls/handgrenade.cpp

@ -26,13 +26,14 @@
enum handgrenade_e enum handgrenade_e
{ {
HANDGRENADE_IDLE = 0, HANDGRENADE_IDLE = 0,
HANDGRENADE_FIDGET, HANDGRENADE_DRAW,
HANDGRENADE_PINPULL, HANDGRENADE_PINPULL,
HANDGRENADE_THROW1, // toss
HANDGRENADE_THROW2, // medium
HANDGRENADE_THROW3, // hard
HANDGRENADE_HOLSTER, 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 ) LINK_ENTITY_TO_CLASS( weapon_handgrenade, CHandGrenade )
@ -152,18 +153,7 @@ void CHandGrenade::WeaponIdle( void )
CGrenade::ShootTimed( m_pPlayer->pev, vecSrc, vecThrow, time ); CGrenade::ShootTimed( m_pPlayer->pev, vecSrc, vecThrow, time );
if( flVel < 500 ) SendWeaponAnim( HANDGRENADE_THROW );
{
SendWeaponAnim( HANDGRENADE_THROW1 );
}
else if( flVel < 1000 )
{
SendWeaponAnim( HANDGRENADE_THROW2 );
}
else
{
SendWeaponAnim( HANDGRENADE_THROW3 );
}
// player "shoot" animation // player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
@ -206,6 +196,9 @@ void CHandGrenade::WeaponIdle( void )
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] ) if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{ {
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 31.0 / 10.0;
SendWeaponAnim( HANDGRENADE_IDLE );
int iAnim; int iAnim;
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 ); float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 );
if( flRand <= 0.75 ) if( flRand <= 0.75 )

4
dlls/hgrunt.cpp

@ -267,6 +267,10 @@ int CHGrunt::IRelationship( CBaseEntity *pTarget )
return R_NM; return R_NM;
} }
if( FClassnameIs( pTarget->pev, "monster_houndeye" ) )
{
return R_NO;
}
return CSquadMonster::IRelationship( pTarget ); return CSquadMonster::IRelationship( pTarget );
} }

28
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 // 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. // squad member increases the BASE damage by 110%, per the spec.
#define HOUNDEYE_MAX_SQUAD_SIZE 4 #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_SQUAD_BONUS (float)1.1
#define HOUNDEYE_EYE_FRAMES 4 // how many different switchable maps for the eye #define HOUNDEYE_EYE_FRAMES 4 // how many different switchable maps for the eye
@ -98,6 +98,7 @@ public:
BOOL FCanActiveIdle( void ); BOOL FCanActiveIdle( void );
Schedule_t *GetScheduleOfType( int Type ); Schedule_t *GetScheduleOfType( int Type );
Schedule_t *GetSchedule( void ); Schedule_t *GetSchedule( void );
int IRelationship(CBaseEntity *pTarget);
int Save( CSave &save ); int Save( CSave &save );
int Restore( CRestore &restore ); int Restore( CRestore &restore );
@ -290,8 +291,17 @@ void CHoundeye::HandleAnimEvent( MonsterEvent_t *pEvent )
break; break;
} }
case HOUND_AE_THUMP: 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; break;
case HOUND_AE_ANGERSOUND1: case HOUND_AE_ANGERSOUND1:
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "houndeye/he_pain3.wav", 1, ATTN_NORM ); 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->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP; pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_YELLOW; m_bloodColor = BLOOD_COLOR_RED;
pev->effects = 0; pev->effects = 0;
pev->health = gSkillData.houndeyeHealth; 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? 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(); 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 );
}

10
dlls/mp5.cpp

@ -173,10 +173,6 @@ void CMP5::PrimaryAttack()
#endif #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 ); 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; m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1;
if( m_flNextPrimaryAttack < UTIL_WeaponTimeBase() ) if( m_flNextPrimaryAttack < UTIL_WeaponTimeBase() )
@ -230,10 +226,6 @@ void CMP5::SecondaryAttack( void )
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1; m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 1;
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 5;// idle pretty soon after shooting. 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 ) void CMP5::Reload( void )
@ -241,7 +233,7 @@ void CMP5::Reload( void )
if( m_pPlayer->ammo_9mm <= 0 ) if( m_pPlayer->ammo_9mm <= 0 )
return; return;
DefaultReload( MP5_MAX_CLIP, MP5_RELOAD, 1.5 ); DefaultReload( MP5_MAX_CLIP, MP5_RELOAD, 2.5 );
} }
void CMP5::WeaponIdle( void ) void CMP5::WeaponIdle( void )

15
dlls/player.cpp

@ -115,6 +115,7 @@ TYPEDESCRIPTION CBasePlayer::m_playerSaveData[] =
DEFINE_FIELD( CBasePlayer, m_pTank, FIELD_EHANDLE ), DEFINE_FIELD( CBasePlayer, m_pTank, FIELD_EHANDLE ),
DEFINE_FIELD( CBasePlayer, m_iHideHUD, FIELD_INTEGER ), DEFINE_FIELD( CBasePlayer, m_iHideHUD, FIELD_INTEGER ),
DEFINE_FIELD( CBasePlayer, m_iFOV, 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_fDeadTime, FIELD_FLOAT ), // only used in multiplayer games
//DEFINE_FIELD( CBasePlayer, m_fGameHUDInitialized, FIELD_INTEGER ), // 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 gmsgStatusText = 0;
int gmsgStatusValue = 0; int gmsgStatusValue = 0;
int gmsgScope = 0;
void LinkUserMessages( void ) void LinkUserMessages( void )
{ {
// Already taken care of? // Already taken care of?
@ -228,6 +231,8 @@ void LinkUserMessages( void )
gmsgStatusText = REG_USER_MSG( "StatusText", -1 ); gmsgStatusText = REG_USER_MSG( "StatusText", -1 );
gmsgStatusValue = REG_USER_MSG( "StatusValue", 3 ); gmsgStatusValue = REG_USER_MSG( "StatusValue", 3 );
gmsgScope = REG_USER_MSG( "Scope", 1 );
} }
LINK_ENTITY_TO_CLASS( player, CBasePlayer ) LINK_ENTITY_TO_CLASS( player, CBasePlayer )
@ -2499,6 +2504,12 @@ void CBasePlayer::PostThink()
m_afButtonLast = pev->button; m_afButtonLast = pev->button;
pt_end: pt_end:
if( m_bUpdatePlayerModel )
{
CLIENT_COMMAND( edict(), "model player\n" );
m_bUpdatePlayerModel = FALSE;
}
#if defined( CLIENT_WEAPONS ) #if defined( CLIENT_WEAPONS )
// Decay timers on weapons // Decay timers on weapons
// go through all of the weapons and make a list of the ones to pack // 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_flNextChatTime = gpGlobals->time;
m_bUpdatePlayerModel = FALSE;
g_pGameRules->PlayerSpawn( this ); 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. // Barring that, we clear it out here instead of using the incorrect restored time value.
m_flNextAttack = UTIL_WeaponTimeBase(); m_flNextAttack = UTIL_WeaponTimeBase();
#endif #endif
m_bUpdatePlayerModel = TRUE;
return status; return status;
} }

2
dlls/player.h

@ -308,6 +308,8 @@ public:
char m_SbarString1[ SBAR_STRING_SIZE ]; char m_SbarString1[ SBAR_STRING_SIZE ];
float m_flNextChatTime; float m_flNextChatTime;
BOOL m_bUpdatePlayerModel;
}; };
#define AUTOAIM_2DEGREES 0.0348994967025 #define AUTOAIM_2DEGREES 0.0348994967025

157
dlls/rpg.cpp

@ -26,15 +26,13 @@
enum rpg_e enum rpg_e
{ {
RPG_IDLE = 0, RPG_IDLE = 0,
RPG_FIDGET, RPG_DRAW1,
RPG_RELOAD, // to reload RPG_AIMED,
RPG_FIRE2, // to empty RPG_LAUNCH,
RPG_HOLSTER1, // loaded RPG_DOWN_TO_UP,
RPG_DRAW1, // loaded RPG_UP_TO_DOWN,
RPG_HOLSTER2, // unloaded RPG_RELOAD_AIMED,
RPG_DRAW_UL, // unloaded RPG_RELOAD_IDLE
RPG_IDLE_UL, // unloaded idle
RPG_FIDGET_UL // unloaded fidget
}; };
LINK_ENTITY_TO_CLASS( weapon_rpg, CRpg ) LINK_ENTITY_TO_CLASS( weapon_rpg, CRpg )
@ -132,16 +130,16 @@ void CRpgRocket::Spawn( void )
pev->classname = MAKE_STRING( "rpg_rocket" ); pev->classname = MAKE_STRING( "rpg_rocket" );
SetThink( &CRpgRocket::IgniteThink ); SetThink( &CRpgRocket::IgniteThink );
SetTouch( &CGrenade::ExplodeTouch ); SetTouch( &CRpgRocket::ExplodeTouch );
pev->angles.x -= 30; pev->angles.x -= 1;
UTIL_MakeVectors( pev->angles ); 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->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; pev->dmg = gSkillData.plrDmgRPG;
} }
@ -194,8 +192,58 @@ void CRpgRocket::IgniteThink( void )
m_flIgniteTime = gpGlobals->time; m_flIgniteTime = gpGlobals->time;
// set to follow laser spot // Move in forward direction. Ignore guiding.
SetThink( &CRpgRocket::FollowThink ); 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; pev->nextthink = gpGlobals->time + 0.1;
} }
@ -299,23 +347,8 @@ void CRpg::Reload( void )
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5; 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 ) if( m_iClip == 0 )
iResult = DefaultReload( RPG_MAX_CLIP, RPG_RELOAD, 2 ); iResult = DefaultReload( RPG_MAX_CLIP, RPG_RELOAD_IDLE, 3.5 );
if( iResult ) if( iResult )
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 ); m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + UTIL_SharedRandomFloat( m_pPlayer->random_seed, 10, 15 );
@ -327,7 +360,7 @@ void CRpg::Spawn()
m_iId = WEAPON_RPG; m_iId = WEAPON_RPG;
SET_MODEL( ENT( pev ), "models/w_rpg.mdl" ); SET_MODEL( ENT( pev ), "models/w_rpg.mdl" );
m_fSpotActive = 1; m_fSpotActive = 0;
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
if( bIsMultiplayer() ) if( bIsMultiplayer() )
@ -394,22 +427,11 @@ int CRpg::AddToPlayer( CBasePlayer *pPlayer )
BOOL CRpg::Deploy() 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" ); return DefaultDeploy( "models/v_rpg.mdl", "models/p_rpg.mdl", RPG_DRAW1, "rpg" );
} }
BOOL CRpg::CanHolster( void ) BOOL CRpg::CanHolster( void )
{ {
if( m_fSpotActive && m_cActiveRockets )
{
// can't put away while guiding a missile.
return FALSE;
}
return TRUE; return TRUE;
} }
@ -418,16 +440,6 @@ void CRpg::Holster( int skiplocal /* = 0 */ )
m_fInReload = FALSE;// cancel any reload in progress. m_fInReload = FALSE;// cancel any reload in progress.
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; 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() void CRpg::PrimaryAttack()
@ -471,27 +483,14 @@ void CRpg::PrimaryAttack()
PlayEmptySound(); PlayEmptySound();
m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.2; m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.2;
} }
UpdateSpot();
} }
void CRpg::SecondaryAttack() 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 ) void CRpg::WeaponIdle( void )
{ {
UpdateSpot();
ResetEmptySound(); ResetEmptySound();
if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() ) if( m_flTimeWeaponIdle > UTIL_WeaponTimeBase() )
@ -499,28 +498,8 @@ void CRpg::WeaponIdle( void )
if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] ) if( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] )
{ {
int iAnim; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0 / 20.0;
float flRand = UTIL_SharedRandomFloat( m_pPlayer->random_seed, 0, 1 ); SendWeaponAnim( RPG_IDLE );
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 );
} }
else else
{ {

95
dlls/scientist.cpp

@ -26,16 +26,7 @@
#include "scripted.h" #include "scripted.h"
#include "animation.h" #include "animation.h"
#include "soundent.h" #include "soundent.h"
#include "scientist.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
};
enum enum
{ {
@ -68,55 +59,6 @@ enum
//======================================================= //=======================================================
// Scientist // 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 ) LINK_ENTITY_TO_CLASS( monster_scientist, CScientist )
@ -1082,20 +1024,6 @@ int CScientist::FriendNumber( int arrayNumber )
//========================================================= //=========================================================
// Dead Scientist PROP // 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[] = char *CDeadScientist::m_szPoses[] =
{ {
"lying_on_back", "lying_on_back",
@ -1160,27 +1088,6 @@ void CDeadScientist::Spawn()
//========================================================= //=========================================================
// Sitting Scientist PROP // 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 ) LINK_ENTITY_TO_CLASS( monster_sitting_scientist, CSittingScientist )
TYPEDESCRIPTION CSittingScientist::m_SaveData[] = TYPEDESCRIPTION CSittingScientist::m_SaveData[] =

119
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

14
dlls/scripted.cpp

@ -1157,11 +1157,23 @@ public:
void Spawn( void ); void Spawn( void );
void Die( void ); void Die( void );
int Classify( 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 ) 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 // Furniture is killed
//========================================================= //=========================================================

14
dlls/triggers.cpp

@ -779,6 +779,20 @@ void CTargetCDAudio::Play( void )
void CTriggerHurt::Spawn( 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(); InitTrigger();
SetTouch( &CBaseTrigger::HurtTouch ); SetTouch( &CBaseTrigger::HurtTouch );

1
dlls/weapons.cpp

@ -169,6 +169,7 @@ void DecalGunshot( TraceResult *pTrace, int iBulletType )
case BULLET_MONSTER_MP5: case BULLET_MONSTER_MP5:
case BULLET_PLAYER_BUCKSHOT: case BULLET_PLAYER_BUCKSHOT:
case BULLET_PLAYER_357: case BULLET_PLAYER_357:
case BULLET_PLAYER_SNIPER:
default: default:
// smoke and decal // smoke and decal
UTIL_GunshotDecalTrace( pTrace, DamageDecal( pEntity, DMG_BULLET ) ); UTIL_GunshotDecalTrace( pTrace, DamageDecal( pEntity, DMG_BULLET ) );

4
dlls/weapons.h

@ -174,7 +174,7 @@ typedef enum
BULLET_PLAYER_357, // python BULLET_PLAYER_357, // python
BULLET_PLAYER_BUCKSHOT, // shotgun BULLET_PLAYER_BUCKSHOT, // shotgun
BULLET_PLAYER_CROWBAR, // crowbar swipe BULLET_PLAYER_CROWBAR, // crowbar swipe
BULLET_PLAYER_SNIPER,
BULLET_MONSTER_9MM, BULLET_MONSTER_9MM,
BULLET_MONSTER_MP5, BULLET_MONSTER_MP5,
BULLET_MONSTER_12MM BULLET_MONSTER_12MM
@ -710,6 +710,8 @@ public:
static TYPEDESCRIPTION m_SaveData[]; static TYPEDESCRIPTION m_SaveData[];
void Spawn( void ); void Spawn( void );
void Precache( void ); void Precache( void );
void EXPORT FlyThink( void );
void EXPORT FollowThink( void ); void EXPORT FollowThink( void );
void EXPORT IgniteThink( void ); void EXPORT IgniteThink( void );
void EXPORT RocketTouch( CBaseEntity *pOther ); void EXPORT RocketTouch( CBaseEntity *pOther );

Loading…
Cancel
Save