Moved modified HL SDK to trunk

This commit is contained in:
Scott Ehlert
2006-08-27 02:22:59 +00:00
parent 28c4ea4fec
commit 30235e05e5
900 changed files with 344676 additions and 0 deletions

127
hlsdk/dmc/dlls/Makefile Normal file
View File

@ -0,0 +1,127 @@
#
# Half-Life DMC SDK 2.3 dmc_i386.so Makefile for x86 Linux
#
# October 2002 by Leon Hartwig (hartwig@valvesoftware.com)
#
DLLNAME=dmc
ARCH=i386
#make sure this is the correct compiler for your system
CC=gcc
DLL_SRCDIR=.
ENGINE_SRCDIR=../../engine
COMMON_SRCDIR=../../common
PM_SHARED_SRCDIR=../pm_shared
GAME_SHARED_SRCDIR=../../game_shared
DLL_OBJDIR=$(DLL_SRCDIR)/obj
PM_SHARED_OBJDIR=$(DLL_OBJDIR)/pm_shared
GAME_SHARED_OBJDIR=$(DLL_OBJDIR)/game_shared
BASE_CFLAGS= -Dstricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_vsnprintf=vsnprintf\
-DCLIENT_WEAPONS
#safe optimization
CFLAGS=$(BASE_CFLAGS) -Wall -Wno-non-virtual-dtor -Wno-invalid-offsetof -Werror -m486 -O1
C_FLAGS=$(BASE_CFLAGS) -Wall -Werror -m486 -O1
#full optimization
#CFLAGS=$(BASE_CFLAGS) -Wall -Wno-non-virtual-dtor -Wno-invalid-offsetof -Werror -O1 -m486 -ffast-math -funroll-loops \
-fomit-frame-pointer -fexpensive-optimizations \
-malign-loops=2 -malign-jumps=2 -malign-functions=2
#use these when debugging
#CFLAGS=$(BASE_CFLAGS) -g
INCLUDEDIRS=-I. -I$(ENGINE_SRCDIR) -I$(COMMON_SRCDIR) -I$(PM_SHARED_SRCDIR) -I$(GAME_SHARED_SRCDIR)
LDFLAGS=
SHLIBEXT=so
SHLIBCFLAGS=-fPIC
SHLIBLDFLAGS=-shared
DO_CC=$(CC) $(CFLAGS) $(SHLIBCFLAGS) $(INCLUDEDIRS) -o $@ -c $<
DO_C=$(CC) $(C_FLAGS) $(SHLIBCFLAGS) $(INCLUDEDIRS) -o $@ -c $<
#############################################################################
# SETUP AND BUILD
# GAME
#############################################################################
$(DLL_OBJDIR)/%.o: $(DLL_SRCDIR)/%.cpp
$(DO_CC)
$(GAME_SHARED_OBJDIR)/%.o: $(GAME_SHARED_SRCDIR)/%.cpp
$(DO_CC)
$(PM_SHARED_OBJDIR)/%.o: $(PM_SHARED_SRCDIR)/%.c
$(DO_C)
OBJ = \
$(DLL_OBJDIR)/animating.o \
$(DLL_OBJDIR)/animation.o \
$(DLL_OBJDIR)/bmodels.o \
$(DLL_OBJDIR)/buttons.o \
$(DLL_OBJDIR)/cbase.o \
$(DLL_OBJDIR)/client.o \
$(DLL_OBJDIR)/combat.o \
$(DLL_OBJDIR)/doors.o \
$(DLL_OBJDIR)/effects.o \
$(DLL_OBJDIR)/explode.o \
$(DLL_OBJDIR)/func_break.o \
$(DLL_OBJDIR)/game.o \
$(DLL_OBJDIR)/gamerules.o \
$(DLL_OBJDIR)/globals.o \
$(DLL_OBJDIR)/h_ai.o \
$(DLL_OBJDIR)/h_export.o \
$(DLL_OBJDIR)/lights.o \
$(DLL_OBJDIR)/maprules.o \
$(DLL_OBJDIR)/monsters.o \
$(DLL_OBJDIR)/monsterstate.o \
$(DLL_OBJDIR)/multiplay_gamerules.o \
$(DLL_OBJDIR)/nodes.o \
$(DLL_OBJDIR)/observer.o \
$(DLL_OBJDIR)/pathcorner.o \
$(DLL_OBJDIR)/plane.o \
$(DLL_OBJDIR)/plats.o \
$(DLL_OBJDIR)/player.o \
$(DLL_OBJDIR)/quake_gun.o \
$(DLL_OBJDIR)/quake_items.o \
$(DLL_OBJDIR)/quake_nail.o \
$(DLL_OBJDIR)/quake_player.o \
$(DLL_OBJDIR)/quake_rocket.o \
$(DLL_OBJDIR)/quake_weapons_all.o \
$(DLL_OBJDIR)/schedule.o \
$(DLL_OBJDIR)/singleplay_gamerules.o \
$(DLL_OBJDIR)/skill.o \
$(DLL_OBJDIR)/sound.o \
$(DLL_OBJDIR)/spectator.o \
$(DLL_OBJDIR)/subs.o \
$(DLL_OBJDIR)/teamplay_gamerules.o \
$(DLL_OBJDIR)/triggers.o \
$(DLL_OBJDIR)/util.o \
$(DLL_OBJDIR)/weapons.o \
$(DLL_OBJDIR)/world.o \
$(PM_SHARED_OBJDIR)/pm_shared.o \
$(PM_SHARED_OBJDIR)/pm_math.o \
$(PM_SHARED_OBJDIR)/pm_debug.o \
$(GAME_SHARED_OBJDIR)/voice_gamemgr.o
$(DLLNAME)_$(ARCH).$(SHLIBEXT) : neat $(OBJ)
$(CC) $(CFLAGS) $(SHLIBLDFLAGS) $(LDFLAGS) -o $@ $(OBJ)
neat:
-mkdir -p $(DLL_OBJDIR)
-mkdir -p $(GAME_SHARED_OBJDIR)
-mkdir -p $(PM_SHARED_OBJDIR)
clean:
-rm -f $(OBJ)
-rm -f $(DLLNAME)_$(ARCH).$(SHLIBEXT)
spotless: clean
-rm -rf $(GAME_SHARED_OBJDIR)
-rm -rf $(PM_SHARED_OBJDIR)
-rm -rf $(DLL_OBJDIR)

109
hlsdk/dmc/dlls/activity.h Normal file
View File

@ -0,0 +1,109 @@
/***
*
* 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.
*
****/
#ifndef ACTIVITY_H
#define ACTIVITY_H
typedef enum {
ACT_RESET = 0, // Set m_Activity to this invalid value to force a reset to m_IdealActivity
ACT_IDLE = 1,
ACT_GUARD,
ACT_WALK,
ACT_RUN,
ACT_FLY, // Fly (and flap if appropriate)
ACT_SWIM,
ACT_HOP, // vertical jump
ACT_LEAP, // long forward jump
ACT_FALL,
ACT_LAND,
ACT_STRAFE_LEFT,
ACT_STRAFE_RIGHT,
ACT_ROLL_LEFT, // tuck and roll, left
ACT_ROLL_RIGHT, // tuck and roll, right
ACT_TURN_LEFT, // turn quickly left (stationary)
ACT_TURN_RIGHT, // turn quickly right (stationary)
ACT_CROUCH, // the act of crouching down from a standing position
ACT_CROUCHIDLE, // holding body in crouched position (loops)
ACT_STAND, // the act of standing from a crouched position
ACT_USE,
ACT_SIGNAL1,
ACT_SIGNAL2,
ACT_SIGNAL3,
ACT_TWITCH,
ACT_COWER,
ACT_SMALL_FLINCH,
ACT_BIG_FLINCH,
ACT_RANGE_ATTACK1,
ACT_RANGE_ATTACK2,
ACT_MELEE_ATTACK1,
ACT_MELEE_ATTACK2,
ACT_RELOAD,
ACT_ARM, // pull out gun, for instance
ACT_DISARM, // reholster gun
ACT_EAT, // monster chowing on a large food item (loop)
ACT_DIESIMPLE,
ACT_DIEBACKWARD,
ACT_DIEFORWARD,
ACT_DIEVIOLENT,
ACT_BARNACLE_HIT, // barnacle tongue hits a monster
ACT_BARNACLE_PULL, // barnacle is lifting the monster ( loop )
ACT_BARNACLE_CHOMP, // barnacle latches on to the monster
ACT_BARNACLE_CHEW, // barnacle is holding the monster in its mouth ( loop )
ACT_SLEEP,
ACT_INSPECT_FLOOR, // for active idles, look at something on or near the floor
ACT_INSPECT_WALL, // for active idles, look at something directly ahead of you ( doesn't HAVE to be a wall or on a wall )
ACT_IDLE_ANGRY, // alternate idle animation in which the monster is clearly agitated. (loop)
ACT_WALK_HURT, // limp (loop)
ACT_RUN_HURT, // limp (loop)
ACT_HOVER, // Idle while in flight
ACT_GLIDE, // Fly (don't flap)
ACT_FLY_LEFT, // Turn left in flight
ACT_FLY_RIGHT, // Turn right in flight
ACT_DETECT_SCENT, // this means the monster smells a scent carried by the air
ACT_SNIFF, // this is the act of actually sniffing an item in front of the monster
ACT_BITE, // some large monsters can eat small things in one bite. This plays one time, EAT loops.
ACT_THREAT_DISPLAY, // without attacking, monster demonstrates that it is angry. (Yell, stick out chest, etc )
ACT_FEAR_DISPLAY, // monster just saw something that it is afraid of
ACT_EXCITED, // for some reason, monster is excited. Sees something he really likes to eat, or whatever.
ACT_SPECIAL_ATTACK1, // very monster specific special attacks.
ACT_SPECIAL_ATTACK2,
ACT_COMBAT_IDLE, // agitated idle.
ACT_WALK_SCARED,
ACT_RUN_SCARED,
ACT_VICTORY_DANCE, // killed a player, do a victory dance.
ACT_DIE_HEADSHOT, // die, hit in head.
ACT_DIE_CHESTSHOT, // die, hit in chest
ACT_DIE_GUTSHOT, // die, hit in gut
ACT_DIE_BACKSHOT, // die, hit in back
ACT_FLINCH_HEAD,
ACT_FLINCH_CHEST,
ACT_FLINCH_STOMACH,
ACT_FLINCH_LEFTARM,
ACT_FLINCH_RIGHTARM,
ACT_FLINCH_LEFTLEG,
ACT_FLINCH_RIGHTLEG,
} Activity;
typedef struct {
int type;
char *name;
} activity_map_t;
extern activity_map_t activity_map[];
#endif //ACTIVITY_H

View File

@ -0,0 +1,97 @@
/***
*
* 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.
*
****/
#define _A( a ) { a, #a }
activity_map_t activity_map[] =
{
_A( ACT_IDLE ),
_A( ACT_GUARD ),
_A( ACT_WALK ),
_A( ACT_RUN ),
_A( ACT_FLY ),
_A( ACT_SWIM ),
_A( ACT_HOP ),
_A( ACT_LEAP ),
_A( ACT_FALL ),
_A( ACT_LAND ),
_A( ACT_STRAFE_LEFT ),
_A( ACT_STRAFE_RIGHT ),
_A( ACT_ROLL_LEFT ),
_A( ACT_ROLL_RIGHT ),
_A( ACT_TURN_LEFT ),
_A( ACT_TURN_RIGHT ),
_A( ACT_CROUCH ),
_A( ACT_CROUCHIDLE ),
_A( ACT_STAND ),
_A( ACT_USE ),
_A( ACT_SIGNAL1 ),
_A( ACT_SIGNAL2 ),
_A( ACT_SIGNAL3 ),
_A( ACT_TWITCH ),
_A( ACT_COWER ),
_A( ACT_SMALL_FLINCH ),
_A( ACT_BIG_FLINCH ),
_A( ACT_RANGE_ATTACK1 ),
_A( ACT_RANGE_ATTACK2 ),
_A( ACT_MELEE_ATTACK1 ),
_A( ACT_MELEE_ATTACK2 ),
_A( ACT_RELOAD ),
_A( ACT_ARM ),
_A( ACT_DISARM ),
_A( ACT_EAT ),
_A( ACT_DIESIMPLE ),
_A( ACT_DIEBACKWARD ),
_A( ACT_DIEFORWARD ),
_A( ACT_DIEVIOLENT ),
_A( ACT_BARNACLE_HIT ),
_A( ACT_BARNACLE_PULL ),
_A( ACT_BARNACLE_CHOMP ),
_A( ACT_BARNACLE_CHEW ),
_A( ACT_SLEEP ),
_A( ACT_INSPECT_FLOOR ),
_A( ACT_INSPECT_WALL ),
_A( ACT_IDLE_ANGRY ),
_A( ACT_WALK_HURT ),
_A( ACT_RUN_HURT ),
_A( ACT_HOVER ),
_A( ACT_GLIDE ),
_A( ACT_FLY_LEFT ),
_A( ACT_FLY_RIGHT ),
_A( ACT_DETECT_SCENT ),
_A( ACT_SNIFF ),
_A( ACT_BITE ),
_A( ACT_THREAT_DISPLAY ),
_A( ACT_FEAR_DISPLAY ),
_A( ACT_EXCITED ),
_A( ACT_SPECIAL_ATTACK1 ),
_A( ACT_SPECIAL_ATTACK2 ),
_A( ACT_COMBAT_IDLE ),
_A( ACT_WALK_SCARED ),
_A( ACT_RUN_SCARED ),
_A( ACT_VICTORY_DANCE ),
_A( ACT_DIE_HEADSHOT ),
_A( ACT_DIE_CHESTSHOT ),
_A( ACT_DIE_GUTSHOT ),
_A( ACT_DIE_BACKSHOT ),
_A( ACT_FLINCH_HEAD ),
_A( ACT_FLINCH_CHEST ),
_A( ACT_FLINCH_STOMACH ),
_A( ACT_FLINCH_LEFTARM ),
_A( ACT_FLINCH_RIGHTARM ),
_A( ACT_FLINCH_LEFTLEG ),
_A( ACT_FLINCH_RIGHTLEG ),
{ 0, NULL }
};

View File

@ -0,0 +1,313 @@
/***
*
* 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.
*
****/
/*
===== monsters.cpp ========================================================
Monster-related utility code
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "animation.h"
#include "saverestore.h"
TYPEDESCRIPTION CBaseAnimating::m_SaveData[] =
{
DEFINE_FIELD( CBaseMonster, m_flFrameRate, FIELD_FLOAT ),
DEFINE_FIELD( CBaseMonster, m_flGroundSpeed, FIELD_FLOAT ),
DEFINE_FIELD( CBaseMonster, m_flLastEventCheck, FIELD_TIME ),
DEFINE_FIELD( CBaseMonster, m_fSequenceFinished, FIELD_BOOLEAN ),
DEFINE_FIELD( CBaseMonster, m_fSequenceLoops, FIELD_BOOLEAN ),
};
IMPLEMENT_SAVERESTORE( CBaseAnimating, CBaseDelay );
//=========================================================
// StudioFrameAdvance - advance the animation frame up to the current time
// if an flInterval is passed in, only advance animation that number of seconds
//=========================================================
float CBaseAnimating :: StudioFrameAdvance ( float flInterval )
{
if (flInterval == 0.0)
{
flInterval = (gpGlobals->time - pev->animtime);
if (flInterval <= 0.001)
{
pev->animtime = gpGlobals->time;
return 0.0;
}
}
if (! pev->animtime)
flInterval = 0.0;
pev->frame += flInterval * m_flFrameRate * pev->framerate;
pev->animtime = gpGlobals->time;
if (pev->frame < 0.0 || pev->frame >= 256.0)
{
if (m_fSequenceLoops)
pev->frame -= (int)(pev->frame / 256.0) * 256.0;
else
pev->frame = (pev->frame < 0.0) ? 0 : 255;
m_fSequenceFinished = TRUE; // just in case it wasn't caught in GetEvents
}
return flInterval;
}
//=========================================================
// LookupActivity
//=========================================================
int CBaseAnimating :: LookupActivity ( int activity )
{
ASSERT( activity != 0 );
void *pmodel = GET_MODEL_PTR( ENT(pev) );
return ::LookupActivity( pmodel, pev, activity );
}
//=========================================================
// LookupActivityHeaviest
//
// Get activity with highest 'weight'
//
//=========================================================
int CBaseAnimating :: LookupActivityHeaviest ( int activity )
{
void *pmodel = GET_MODEL_PTR( ENT(pev) );
return ::LookupActivityHeaviest( pmodel, pev, activity );
}
//=========================================================
//=========================================================
int CBaseAnimating :: LookupSequence ( const char *label )
{
void *pmodel = GET_MODEL_PTR( ENT(pev) );
return ::LookupSequence( pmodel, label );
}
//=========================================================
//=========================================================
void CBaseAnimating :: ResetSequenceInfo ( )
{
void *pmodel = GET_MODEL_PTR( ENT(pev) );
GetSequenceInfo( pmodel, pev, &m_flFrameRate, &m_flGroundSpeed );
m_fSequenceLoops = ((GetSequenceFlags() & STUDIO_LOOPING) != 0);
pev->animtime = gpGlobals->time;
pev->framerate = 1.0;
m_fSequenceFinished = FALSE;
m_flLastEventCheck = gpGlobals->time;
}
//=========================================================
//=========================================================
BOOL CBaseAnimating :: GetSequenceFlags( )
{
void *pmodel = GET_MODEL_PTR( ENT(pev) );
return ::GetSequenceFlags( pmodel, pev );
}
//=========================================================
// DispatchAnimEvents
//=========================================================
void CBaseAnimating :: DispatchAnimEvents ( float flInterval )
{
MonsterEvent_t event;
void *pmodel = GET_MODEL_PTR( ENT(pev) );
if ( !pmodel )
{
ALERT( at_aiconsole, "Gibbed monster is thinking!\n" );
return;
}
// FIXME: I have to do this or some events get missed, and this is probably causing the problem below
flInterval = 0.1;
// FIX: this still sometimes hits events twice
float flStart = pev->frame + (m_flLastEventCheck - pev->animtime) * m_flFrameRate * pev->framerate;
float flEnd = pev->frame + flInterval * m_flFrameRate * pev->framerate;
m_flLastEventCheck = pev->animtime + flInterval;
m_fSequenceFinished = FALSE;
if (flEnd >= 256 || flEnd <= 0.0)
m_fSequenceFinished = TRUE;
int index = 0;
while ( (index = GetAnimationEvent( pmodel, pev, &event, flStart, flEnd, index ) ) != 0 )
{
HandleAnimEvent( &event );
}
}
//=========================================================
//=========================================================
float CBaseAnimating :: SetBoneController ( int iController, float flValue )
{
void *pmodel = GET_MODEL_PTR( ENT(pev) );
return SetController( pmodel, pev, iController, flValue );
}
//=========================================================
//=========================================================
void CBaseAnimating :: InitBoneControllers ( void )
{
void *pmodel = GET_MODEL_PTR( ENT(pev) );
SetController( pmodel, pev, 0, 0.0 );
SetController( pmodel, pev, 1, 0.0 );
SetController( pmodel, pev, 2, 0.0 );
SetController( pmodel, pev, 3, 0.0 );
}
//=========================================================
//=========================================================
float CBaseAnimating :: SetBlending ( int iBlender, float flValue )
{
void *pmodel = GET_MODEL_PTR( ENT(pev) );
return ::SetBlending( pmodel, pev, iBlender, flValue );
}
//=========================================================
//=========================================================
void CBaseAnimating :: GetBonePosition ( int iBone, Vector &origin, Vector &angles )
{
GET_BONE_POSITION( ENT(pev), iBone, origin, angles );
}
//=========================================================
//=========================================================
void CBaseAnimating :: GetAttachment ( int iAttachment, Vector &origin, Vector &angles )
{
GET_ATTACHMENT( ENT(pev), iAttachment, origin, angles );
}
//=========================================================
//=========================================================
int CBaseAnimating :: FindTransition( int iEndingSequence, int iGoalSequence, int *piDir )
{
void *pmodel = GET_MODEL_PTR( ENT(pev) );
if (piDir == NULL)
{
int iDir;
int sequence = ::FindTransition( pmodel, iEndingSequence, iGoalSequence, &iDir );
if (iDir != 1)
return -1;
else
return sequence;
}
return ::FindTransition( pmodel, iEndingSequence, iGoalSequence, piDir );
}
//=========================================================
//=========================================================
void CBaseAnimating :: GetAutomovement( Vector &origin, Vector &angles, float flInterval )
{
}
void CBaseAnimating :: SetBodygroup( int iGroup, int iValue )
{
::SetBodygroup( GET_MODEL_PTR( ENT(pev) ), pev, iGroup, iValue );
}
int CBaseAnimating :: GetBodygroup( int iGroup )
{
return ::GetBodygroup( GET_MODEL_PTR( ENT(pev) ), pev, iGroup );
}
int CBaseAnimating :: ExtractBbox( int sequence, float *mins, float *maxs )
{
return ::ExtractBbox( GET_MODEL_PTR( ENT(pev) ), sequence, mins, maxs );
}
//=========================================================
//=========================================================
void CBaseAnimating :: SetSequenceBox( void )
{
Vector mins, maxs;
// Get sequence bbox
if ( ExtractBbox( pev->sequence, mins, maxs ) )
{
// expand box for rotation
// find min / max for rotations
float yaw = pev->angles.y * (M_PI / 180.0);
Vector xvector, yvector;
xvector.x = cos(yaw);
xvector.y = sin(yaw);
yvector.x = -sin(yaw);
yvector.y = cos(yaw);
Vector bounds[2];
bounds[0] = mins;
bounds[1] = maxs;
Vector rmin( 9999, 9999, 9999 );
Vector rmax( -9999, -9999, -9999 );
Vector base, transformed;
for (int i = 0; i <= 1; i++ )
{
base.x = bounds[i].x;
for ( int j = 0; j <= 1; j++ )
{
base.y = bounds[j].y;
for ( int k = 0; k <= 1; k++ )
{
base.z = bounds[k].z;
// transform the point
transformed.x = xvector.x*base.x + yvector.x*base.y;
transformed.y = xvector.y*base.x + yvector.y*base.y;
transformed.z = base.z;
for ( int l = 0; l < 3; l++ )
{
if (transformed[l] < rmin[l])
rmin[l] = transformed[l];
if (transformed[l] > rmax[l])
rmax[l] = transformed[l];
}
}
}
}
rmin.z = 0;
rmax.z = rmin.z + 1;
UTIL_SetSize( pev, rmin, rmax );
}
}

View File

@ -0,0 +1,535 @@
/***
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined _MSC_VER && _MSC_VER >= 1400
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#pragma warning(disable: 4996) // deprecated functions
#endif
typedef bool BOOL;
// hack into header files that we can ship
typedef int qboolean;
typedef unsigned char byte;
#include "../utils/common/mathlib.h"
#include "const.h"
#include "progdefs.h"
#include "edict.h"
#include "eiface.h"
#include "studio.h"
#include "../engine/studio.h"
#ifndef ACTIVITY_H
#include "activity.h"
#endif
#include "activitymap.h"
#ifndef ANIMATION_H
#include "animation.h"
#endif
#ifndef SCRIPTEVENT_H
#include "scriptevent.h"
#endif
#ifndef ENGINECALLBACK_H
#include "enginecallback.h"
#endif
extern globalvars_t *gpGlobals;
#ifdef _MSC_VER
#pragma warning( disable : 4244 )
#endif
int ExtractBbox( void *pmodel, int sequence, float *mins, float *maxs )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if (! pstudiohdr)
return 0;
mstudioseqdesc_t *pseqdesc;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
mins[0] = pseqdesc[ sequence ].bbmin[0];
mins[1] = pseqdesc[ sequence ].bbmin[1];
mins[2] = pseqdesc[ sequence ].bbmin[2];
maxs[0] = pseqdesc[ sequence ].bbmax[0];
maxs[1] = pseqdesc[ sequence ].bbmax[1];
maxs[2] = pseqdesc[ sequence ].bbmax[2];
return 1;
}
int LookupActivity( void *pmodel, entvars_t *pev, int activity )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if (! pstudiohdr)
return 0;
mstudioseqdesc_t *pseqdesc;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
int weighttotal = 0;
int seq = ACTIVITY_NOT_AVAILABLE;
for (int i = 0; i < pstudiohdr->numseq; i++)
{
if (pseqdesc[i].activity == activity)
{
weighttotal += pseqdesc[i].actweight;
if (!weighttotal || RANDOM_LONG(0,weighttotal-1) < pseqdesc[i].actweight)
seq = i;
}
}
return seq;
}
int LookupActivityHeaviest( void *pmodel, entvars_t *pev, int activity )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if ( !pstudiohdr )
return 0;
mstudioseqdesc_t *pseqdesc;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
int weight = 0;
int seq = ACTIVITY_NOT_AVAILABLE;
for (int i = 0; i < pstudiohdr->numseq; i++)
{
if (pseqdesc[i].activity == activity)
{
if ( pseqdesc[i].actweight > weight )
{
weight = pseqdesc[i].actweight;
seq = i;
}
}
}
return seq;
}
void GetEyePosition ( void *pmodel, float *vecEyePosition )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if ( !pstudiohdr )
{
ALERT ( at_console, "GetEyePosition() Can't get pstudiohdr ptr!\n" );
return;
}
VectorCopy ( pstudiohdr->eyeposition, vecEyePosition );
}
int LookupSequence( void *pmodel, const char *label )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if (! pstudiohdr)
return 0;
mstudioseqdesc_t *pseqdesc;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
for (int i = 0; i < pstudiohdr->numseq; i++)
{
if (stricmp( pseqdesc[i].label, label ) == 0)
return i;
}
return -1;
}
int IsSoundEvent( int eventNumber )
{
if ( eventNumber == SCRIPT_EVENT_SOUND || eventNumber == SCRIPT_EVENT_SOUND_VOICE )
return 1;
return 0;
}
void SequencePrecache( void *pmodel, const char *pSequenceName )
{
int index = LookupSequence( pmodel, pSequenceName );
if ( index >= 0 )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if ( !pstudiohdr || index >= pstudiohdr->numseq )
return;
mstudioseqdesc_t *pseqdesc;
mstudioevent_t *pevent;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + index;
pevent = (mstudioevent_t *)((byte *)pstudiohdr + pseqdesc->eventindex);
for (int i = 0; i < pseqdesc->numevents; i++)
{
// Don't send client-side events to the server AI
if ( pevent[i].event >= EVENT_CLIENT )
continue;
// UNDONE: Add a callback to check to see if a sound is precached yet and don't allocate a copy
// of it's name if it is.
if ( IsSoundEvent( pevent[i].event ) )
{
if ( !strlen(pevent[i].options) )
{
ALERT( at_error, "Bad sound event %d in sequence %s :: %s (sound is \"%s\")\n", pevent[i].event, pstudiohdr->name, pSequenceName, pevent[i].options );
}
PRECACHE_SOUND( (char *)(gpGlobals->pStringBase + ALLOC_STRING(pevent[i].options) ) );
}
}
}
}
void GetSequenceInfo( void *pmodel, entvars_t *pev, float *pflFrameRate, float *pflGroundSpeed )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if (! pstudiohdr)
return;
mstudioseqdesc_t *pseqdesc;
if (pev->sequence >= pstudiohdr->numseq)
{
*pflFrameRate = 0.0;
*pflGroundSpeed = 0.0;
return;
}
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence;
if (pseqdesc->numframes > 1)
{
*pflFrameRate = 256 * pseqdesc->fps / (pseqdesc->numframes - 1);
*pflGroundSpeed = sqrt( pseqdesc->linearmovement[0]*pseqdesc->linearmovement[0]+ pseqdesc->linearmovement[1]*pseqdesc->linearmovement[1]+ pseqdesc->linearmovement[2]*pseqdesc->linearmovement[2] );
*pflGroundSpeed = *pflGroundSpeed * pseqdesc->fps / (pseqdesc->numframes - 1);
}
else
{
*pflFrameRate = 256.0;
*pflGroundSpeed = 0.0;
}
}
int GetSequenceFlags( void *pmodel, entvars_t *pev )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if ( !pstudiohdr || pev->sequence >= pstudiohdr->numseq )
return 0;
mstudioseqdesc_t *pseqdesc;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence;
return pseqdesc->flags;
}
int GetAnimationEvent( void *pmodel, entvars_t *pev, MonsterEvent_t *pMonsterEvent, float flStart, float flEnd, int index )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if ( !pstudiohdr || pev->sequence >= pstudiohdr->numseq || !pMonsterEvent )
return 0;
mstudioseqdesc_t *pseqdesc;
mstudioevent_t *pevent;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence;
pevent = (mstudioevent_t *)((byte *)pstudiohdr + pseqdesc->eventindex);
if (pseqdesc->numevents == 0 || index > pseqdesc->numevents )
return 0;
if (pseqdesc->numframes > 1)
{
flStart *= (pseqdesc->numframes - 1) / 256.0;
flEnd *= (pseqdesc->numframes - 1) / 256.0;
}
else
{
flStart = 0;
flEnd = 1.0;
}
for (; index < pseqdesc->numevents; index++)
{
// Don't send client-side events to the server AI
if ( pevent[index].event >= EVENT_CLIENT )
continue;
if ( (pevent[index].frame >= flStart && pevent[index].frame < flEnd) ||
((pseqdesc->flags & STUDIO_LOOPING) && flEnd >= pseqdesc->numframes - 1 && pevent[index].frame < flEnd - pseqdesc->numframes + 1) )
{
pMonsterEvent->event = pevent[index].event;
pMonsterEvent->options = pevent[index].options;
return index + 1;
}
}
return 0;
}
float SetController( void *pmodel, entvars_t *pev, int iController, float flValue )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if (! pstudiohdr)
return flValue;
mstudiobonecontroller_t *pbonecontroller = (mstudiobonecontroller_t *)((byte *)pstudiohdr + pstudiohdr->bonecontrollerindex);
int i = 0;
// find first controller that matches the index
for (i = 0; i < pstudiohdr->numbonecontrollers; i++, pbonecontroller++)
{
if (pbonecontroller->index == iController)
break;
}
if (i >= pstudiohdr->numbonecontrollers)
return flValue;
// wrap 0..360 if it's a rotational controller
if (pbonecontroller->type & (STUDIO_XR | STUDIO_YR | STUDIO_ZR))
{
// ugly hack, invert value if end < start
if (pbonecontroller->end < pbonecontroller->start)
flValue = -flValue;
// does the controller not wrap?
if (pbonecontroller->start + 359.0 >= pbonecontroller->end)
{
if (flValue > ((pbonecontroller->start + pbonecontroller->end) / 2.0) + 180)
flValue = flValue - 360;
if (flValue < ((pbonecontroller->start + pbonecontroller->end) / 2.0) - 180)
flValue = flValue + 360;
}
else
{
if (flValue > 360)
flValue = flValue - (int)(flValue / 360.0) * 360.0;
else if (flValue < 0)
flValue = flValue + (int)((flValue / -360.0) + 1) * 360.0;
}
}
int setting = static_cast<int>(255 * (flValue - pbonecontroller->start) / (pbonecontroller->end - pbonecontroller->start));
if (setting < 0) setting = 0;
if (setting > 255) setting = 255;
pev->controller[iController] = setting;
return setting * (1.0 / 255.0) * (pbonecontroller->end - pbonecontroller->start) + pbonecontroller->start;
}
float SetBlending( void *pmodel, entvars_t *pev, int iBlender, float flValue )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if (! pstudiohdr)
return flValue;
mstudioseqdesc_t *pseqdesc;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence;
if (pseqdesc->blendtype[iBlender] == 0)
return flValue;
if (pseqdesc->blendtype[iBlender] & (STUDIO_XR | STUDIO_YR | STUDIO_ZR))
{
// ugly hack, invert value if end < start
if (pseqdesc->blendend[iBlender] < pseqdesc->blendstart[iBlender])
flValue = -flValue;
// does the controller not wrap?
if (pseqdesc->blendstart[iBlender] + 359.0 >= pseqdesc->blendend[iBlender])
{
if (flValue > ((pseqdesc->blendstart[iBlender] + pseqdesc->blendend[iBlender]) / 2.0) + 180)
flValue = flValue - 360;
if (flValue < ((pseqdesc->blendstart[iBlender] + pseqdesc->blendend[iBlender]) / 2.0) - 180)
flValue = flValue + 360;
}
}
int setting = static_cast<int>(255 * (flValue - pseqdesc->blendstart[iBlender]) / (pseqdesc->blendend[iBlender] - pseqdesc->blendstart[iBlender]));
if (setting < 0) setting = 0;
if (setting > 255) setting = 255;
pev->blending[iBlender] = setting;
return setting * (1.0 / 255.0) * (pseqdesc->blendend[iBlender] - pseqdesc->blendstart[iBlender]) + pseqdesc->blendstart[iBlender];
}
int FindTransition( void *pmodel, int iEndingAnim, int iGoalAnim, int *piDir )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if (! pstudiohdr)
return iGoalAnim;
mstudioseqdesc_t *pseqdesc;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
// bail if we're going to or from a node 0
if (pseqdesc[iEndingAnim].entrynode == 0 || pseqdesc[iGoalAnim].entrynode == 0)
{
return iGoalAnim;
}
int iEndNode;
// ALERT( at_console, "from %d to %d: ", pEndNode->iEndNode, pGoalNode->iStartNode );
if (*piDir > 0)
{
iEndNode = pseqdesc[iEndingAnim].exitnode;
}
else
{
iEndNode = pseqdesc[iEndingAnim].entrynode;
}
if (iEndNode == pseqdesc[iGoalAnim].entrynode)
{
*piDir = 1;
return iGoalAnim;
}
byte *pTransition = ((byte *)pstudiohdr + pstudiohdr->transitionindex);
int iInternNode = pTransition[(iEndNode-1)*pstudiohdr->numtransitions + (pseqdesc[iGoalAnim].entrynode-1)];
if (iInternNode == 0)
return iGoalAnim;
int i;
// look for someone going
for (i = 0; i < pstudiohdr->numseq; i++)
{
if (pseqdesc[i].entrynode == iEndNode && pseqdesc[i].exitnode == iInternNode)
{
*piDir = 1;
return i;
}
if (pseqdesc[i].nodeflags)
{
if (pseqdesc[i].exitnode == iEndNode && pseqdesc[i].entrynode == iInternNode)
{
*piDir = -1;
return i;
}
}
}
ALERT( at_console, "error in transition graph" );
return iGoalAnim;
}
void SetBodygroup( void *pmodel, entvars_t *pev, int iGroup, int iValue )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if (! pstudiohdr)
return;
if (iGroup > pstudiohdr->numbodyparts)
return;
mstudiobodyparts_t *pbodypart = (mstudiobodyparts_t *)((byte *)pstudiohdr + pstudiohdr->bodypartindex) + iGroup;
if (iValue >= pbodypart->nummodels)
return;
int iCurrent = (pev->body / pbodypart->base) % pbodypart->nummodels;
pev->body = (pev->body - (iCurrent * pbodypart->base) + (iValue * pbodypart->base));
}
int GetBodygroup( void *pmodel, entvars_t *pev, int iGroup )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if (! pstudiohdr)
return 0;
if (iGroup > pstudiohdr->numbodyparts)
return 0;
mstudiobodyparts_t *pbodypart = (mstudiobodyparts_t *)((byte *)pstudiohdr + pstudiohdr->bodypartindex) + iGroup;
if (pbodypart->nummodels <= 1)
return 0;
int iCurrent = (pev->body / pbodypart->base) % pbodypart->nummodels;
return iCurrent;
}

View File

@ -0,0 +1,47 @@
/***
*
* 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.
*
****/
#ifndef ANIMATION_H
#define ANIMATION_H
#define ACTIVITY_NOT_AVAILABLE -1
#ifndef MONSTEREVENT_H
#include "monsterevent.h"
#endif
extern int IsSoundEvent( int eventNumber );
int LookupActivity( void *pmodel, entvars_t *pev, int activity );
int LookupActivityHeaviest( void *pmodel, entvars_t *pev, int activity );
int LookupSequence( void *pmodel, const char *label );
void GetSequenceInfo( void *pmodel, entvars_t *pev, float *pflFrameRate, float *pflGroundSpeed );
int GetSequenceFlags( void *pmodel, entvars_t *pev );
int LookupAnimationEvents( void *pmodel, entvars_t *pev, float flStart, float flEnd );
float SetController( void *pmodel, entvars_t *pev, int iController, float flValue );
float SetBlending( void *pmodel, entvars_t *pev, int iBlender, float flValue );
void GetEyePosition( void *pmodel, float *vecEyePosition );
void SequencePrecache( void *pmodel, const char *pSequenceName );
int FindTransition( void *pmodel, int iEndingAnim, int iGoalAnim, int *piDir );
void SetBodygroup( void *pmodel, entvars_t *pev, int iGroup, int iValue );
int GetBodygroup( void *pmodel, entvars_t *pev, int iGroup );
int GetAnimationEvent( void *pmodel, entvars_t *pev, MonsterEvent_t *pMonsterEvent, float flStart, float flEnd, int index );
int ExtractBbox( void *pmodel, int sequence, float *mins, float *maxs );
// From /engine/studio.h
#define STUDIO_LOOPING 0x0001
#endif //ANIMATION_H

View File

@ -0,0 +1,339 @@
/***
*
* 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.
*
* 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.
*
****/
#ifndef BASEMONSTER_H
#define BASEMONSTER_H
//
// generic Monster
//
class CBaseMonster : public CBaseToggle
{
private:
int m_afConditions;
public:
typedef enum
{
SCRIPT_PLAYING = 0, // Playing the sequence
SCRIPT_WAIT, // Waiting on everyone in the script to be ready
SCRIPT_CLEANUP, // Cancelling the script / cleaning up
SCRIPT_WALK_TO_MARK,
SCRIPT_RUN_TO_MARK,
} SCRIPTSTATE;
// these fields have been added in the process of reworking the state machine. (sjb)
EHANDLE m_hEnemy; // the entity that the monster is fighting.
EHANDLE m_hTargetEnt; // the entity that the monster is trying to reach
EHANDLE m_hOldEnemy[ MAX_OLD_ENEMIES ];
Vector m_vecOldEnemy[ MAX_OLD_ENEMIES ];
float m_flFieldOfView;// width of monster's field of view ( dot product )
float m_flWaitFinished;// if we're told to wait, this is the time that the wait will be over.
float m_flMoveWaitFinished;
Activity m_Activity;// what the monster is doing (animation)
Activity m_IdealActivity;// monster should switch to this activity
int m_LastHitGroup; // the last body region that took damage
MONSTERSTATE m_MonsterState;// monster's current state
MONSTERSTATE m_IdealMonsterState;// monster should change to this state
int m_iTaskStatus;
Schedule_t *m_pSchedule;
int m_iScheduleIndex;
WayPoint_t m_Route[ ROUTE_SIZE ]; // Positions of movement
int m_movementGoal; // Goal that defines route
int m_iRouteIndex; // index into m_Route[]
float m_moveWaitTime; // How long I should wait for something to move
Vector m_vecMoveGoal; // kept around for node graph moves, so we know our ultimate goal
Activity m_movementActivity; // When moving, set this activity
int m_iAudibleList; // first index of a linked list of sounds that the monster can hear.
int m_afSoundTypes;
Vector m_vecLastPosition;// monster sometimes wants to return to where it started after an operation.
int m_iHintNode; // this is the hint node that the monster is moving towards or performing active idle on.
int m_afMemory;
int m_iMaxHealth;// keeps track of monster's maximum health value (for re-healing, etc)
Vector m_vecEnemyLKP;// last known position of enemy. (enemy's origin)
int m_cAmmoLoaded; // how much ammo is in the weapon (used to trigger reload anim sequences)
int m_afCapability;// tells us what a monster can/can't do.
float m_flNextAttack; // cannot attack again until this time
int m_bitsDamageType; // what types of damage has monster (player) taken
BYTE m_rgbTimeBasedDamage[CDMG_TIMEBASED];
int m_lastDamageAmount;// how much damage did monster (player) last take
// time based damage counters, decr. 1 per 2 seconds
int m_bloodColor; // color of blood particless
int m_failSchedule; // Schedule type to choose if current schedule fails
float m_flHungryTime;// set this is a future time to stop the monster from eating for a while.
float m_flDistTooFar; // if enemy farther away than this, bits_COND_ENEMY_TOOFAR set in CheckEnemy
float m_flDistLook; // distance monster sees (Default 2048)
int m_iTriggerCondition;// for scripted AI, this is the condition that will cause the activation of the monster's TriggerTarget
string_t m_iszTriggerTarget;// name of target that should be fired.
Vector m_HackedGunPos; // HACK until we can query end of gun
// Scripted sequence Info
SCRIPTSTATE m_scriptState; // internal cinematic state
CCineMonster *m_pCine;
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
void KeyValue( KeyValueData *pkvd );
// monster use function
void EXPORT MonsterUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT CorpseUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
// overrideable Monster member functions
virtual int BloodColor( void ) { return m_bloodColor; }
virtual CBaseMonster *MyMonsterPointer( void ) { return this; }
virtual void Look ( int iDistance );// basic sight function for monsters
virtual void RunAI ( void );// core ai function!
void Listen ( void );
virtual BOOL IsAlive( void ) { return (pev->deadflag != DEAD_DEAD); }
virtual BOOL ShouldFadeOnDeath( void );
// Basic Monster AI functions
virtual float ChangeYaw ( int speed );
float VecToYaw( Vector vecDir );
float FlYawDiff ( void );
float DamageForce( float damage );
// stuff written for new state machine
virtual void MonsterThink( void );
void EXPORT CallMonsterThink( void ) { this->MonsterThink(); }
virtual int IRelationship ( CBaseEntity *pTarget );
virtual void MonsterInit ( void );
virtual void MonsterInitDead( void ); // Call after animation/pose is set up
virtual void BecomeDead( void );
void EXPORT CorpseFallThink( void );
void EXPORT MonsterInitThink ( void );
virtual void StartMonster ( void );
virtual CBaseEntity* BestVisibleEnemy ( void );// finds best visible enemy for attack
virtual BOOL FInViewCone ( CBaseEntity *pEntity );// see if pEntity is in monster's view cone
virtual BOOL FInViewCone ( Vector *pOrigin );// see if given location is in monster's view cone
virtual void HandleAnimEvent( MonsterEvent_t *pEvent );
virtual int CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, CBaseEntity *pTarget, float *pflDist );// check validity of a straight move through space
virtual void Move( float flInterval = 0.1 );
virtual void MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval );
virtual BOOL ShouldAdvanceRoute( float flWaypointDist );
virtual Activity GetStoppedActivity( void ) { return ACT_IDLE; }
virtual void Stop( void ) { m_IdealActivity = GetStoppedActivity(); }
// This will stop animation until you call ResetSequenceInfo() at some point in the future
inline void StopAnimation( void ) { pev->framerate = 0; }
// these functions will survey conditions and set appropriate conditions bits for attack types.
virtual BOOL CheckRangeAttack1( float flDot, float flDist );
virtual BOOL CheckRangeAttack2( float flDot, float flDist );
virtual BOOL CheckMeleeAttack1( float flDot, float flDist );
virtual BOOL CheckMeleeAttack2( float flDot, float flDist );
BOOL FHaveSchedule( void );
BOOL FScheduleValid ( void );
void ClearSchedule( void );
BOOL FScheduleDone ( void );
void ChangeSchedule ( Schedule_t *pNewSchedule );
void NextScheduledTask ( void );
Schedule_t *ScheduleInList( const char *pName, Schedule_t **pList, int listCount );
virtual Schedule_t *ScheduleFromName( const char *pName );
static Schedule_t *m_scheduleList[];
void MaintainSchedule ( void );
virtual void StartTask ( Task_t *pTask );
virtual void RunTask ( Task_t *pTask );
virtual Schedule_t *GetScheduleOfType( int Type );
virtual Schedule_t *GetSchedule( void );
virtual void ScheduleChange( void ) {}
// virtual int CanPlaySequence( void ) { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); }
virtual int CanPlaySequence( BOOL fDisregardState, int interruptLevel );
virtual int CanPlaySentence( BOOL fDisregardState ) { return IsAlive(); }
virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation );
virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener );
virtual void SentenceStop( void );
Task_t *GetTask ( void );
virtual MONSTERSTATE GetIdealState ( void );
virtual void SetActivity ( Activity NewActivity );
void SetSequenceByName ( char *szSequence );
void SetState ( MONSTERSTATE State );
virtual void ReportAIState( void );
void CheckAttacks ( CBaseEntity *pTarget, float flDist );
virtual int CheckEnemy ( CBaseEntity *pEnemy );
void PushEnemy( CBaseEntity *pEnemy, Vector &vecLastKnownPos );
BOOL PopEnemy( void );
BOOL FGetNodeRoute ( Vector vecDest );
inline void TaskComplete( void ) { if ( !HasConditions(bits_COND_TASK_FAILED) ) m_iTaskStatus = TASKSTATUS_COMPLETE; }
void MovementComplete( void );
inline void TaskFail( void ) { SetConditions(bits_COND_TASK_FAILED); }
inline void TaskBegin( void ) { m_iTaskStatus = TASKSTATUS_RUNNING; }
int TaskIsRunning( void );
inline int TaskIsComplete( void ) { return (m_iTaskStatus == TASKSTATUS_COMPLETE); }
inline int MovementIsComplete( void ) { return (m_movementGoal == MOVEGOAL_NONE); }
int IScheduleFlags ( void );
BOOL FRefreshRoute( void );
BOOL FRouteClear ( void );
void RouteSimplify( CBaseEntity *pTargetEnt );
void AdvanceRoute ( float distance );
virtual BOOL FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, CBaseEntity *pTargetEnt, Vector *pApex );
void MakeIdealYaw( Vector vecTarget );
virtual void SetYawSpeed ( void ) { return; };// allows different yaw_speeds for each activity
BOOL BuildRoute ( const Vector &vecGoal, int iMoveFlag, CBaseEntity *pTarget );
virtual BOOL BuildNearestRoute ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist );
int RouteClassify( int iMoveFlag );
void InsertWaypoint ( Vector vecLocation, int afMoveFlags );
BOOL FindLateralCover ( const Vector &vecThreat, const Vector &vecViewOffset );
virtual BOOL FindCover ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist );
virtual BOOL FValidateCover ( const Vector &vecCoverLocation ) { return TRUE; };
virtual float CoverRadius( void ) { return 784; } // Default cover radius
virtual BOOL FCanCheckAttacks ( void );
virtual void CheckAmmo( void ) { return; };
virtual int IgnoreConditions ( void );
inline void SetConditions( int iConditions ) { m_afConditions |= iConditions; }
inline void ClearConditions( int iConditions ) { m_afConditions &= ~iConditions; }
inline BOOL HasConditions( int iConditions ) { if ( m_afConditions & iConditions ) return TRUE; return FALSE; }
inline BOOL HasAllConditions( int iConditions ) { if ( (m_afConditions & iConditions) == iConditions ) return TRUE; return FALSE; }
virtual BOOL FValidateHintType( short sHint );
int FindHintNode ( void );
virtual BOOL FCanActiveIdle ( void );
void SetTurnActivity ( void );
float FLSoundVolume ( CSound *pSound );
BOOL MoveToNode( Activity movementAct, float waitTime, const Vector &goal );
BOOL MoveToTarget( Activity movementAct, float waitTime );
BOOL MoveToLocation( Activity movementAct, float waitTime, const Vector &goal );
BOOL MoveToEnemy( Activity movementAct, float waitTime );
// Returns the time when the door will be open
float OpenDoorAndWait( entvars_t *pevDoor );
virtual int ISoundMask( void );
virtual CSound* PBestSound ( void );
virtual CSound* PBestScent ( void );
virtual float HearingSensitivity( void ) { return 1.0; };
BOOL FBecomeProne ( void );
virtual void BarnacleVictimBitten( entvars_t *pevBarnacle );
virtual void BarnacleVictimReleased( void );
void SetEyePosition ( void );
BOOL FShouldEat( void );// see if a monster is 'hungry'
void Eat ( float flFullDuration );// make the monster 'full' for a while.
CBaseEntity *CheckTraceHullAttack( float flDist, int iDamage, int iDmgType );
BOOL FacingIdeal( void );
BOOL FCheckAITrigger( void );// checks and, if necessary, fires the monster's trigger target.
BOOL NoFriendlyFire( void );
BOOL BBoxFlat( void );
// PrescheduleThink
virtual void PrescheduleThink( void ) { return; };
BOOL GetEnemy ( void );
void MakeDamageBloodDecal ( int cCount, float flNoise, TraceResult *ptr, const Vector &vecDir );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
// combat functions
float UpdateTarget ( entvars_t *pevTarget );
virtual Activity GetDeathActivity ( void );
Activity GetSmallFlinchActivity( void );
virtual void Killed( entvars_t *pevAttacker, int iGib );
virtual void GibMonster( void );
BOOL ShouldGibMonster( int iGib );
void CallGibMonster( void );
virtual BOOL HasHumanGibs( void );
virtual BOOL HasAlienGibs( void );
virtual void FadeMonster( void ); // Called instead of GibMonster() when gibs are disabled
Vector ShootAtEnemy( const Vector &shootOrigin );
virtual Vector BodyTarget( const Vector &posSrc ) { return Center( ) * 0.75 + EyePosition() * 0.25; }; // position to shoot at
virtual Vector GetGunPosition( void );
virtual int TakeHealth( float flHealth, int bitsDamageType );
virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
int DeadTakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
void RadiusDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType );
void RadiusDamage(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType );
virtual int IsMoving( void ) { return m_movementGoal != MOVEGOAL_NONE; }
void RouteClear( void );
void RouteNew( void );
virtual void DeathSound ( void ) { return; };
virtual void AlertSound ( void ) { return; };
virtual void IdleSound ( void ) { return; };
virtual void PainSound ( void ) { return; };
virtual void StopFollowing( BOOL clearSchedule ) {}
inline void Remember( int iMemory ) { m_afMemory |= iMemory; }
inline void Forget( int iMemory ) { m_afMemory &= ~iMemory; }
inline BOOL HasMemory( int iMemory ) { if ( m_afMemory & iMemory ) return TRUE; return FALSE; }
inline BOOL HasAllMemories( int iMemory ) { if ( (m_afMemory & iMemory) == iMemory ) return TRUE; return FALSE; }
BOOL ExitScriptedSequence( );
BOOL CineCleanup( );
CBaseEntity* DropItem ( char *pszItemName, const Vector &vecPos, const Vector &vecAng );// drop an item.
};
#endif // BASEMONSTER_H

958
hlsdk/dmc/dlls/bmodels.cpp Normal file
View File

@ -0,0 +1,958 @@
/***
*
* 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.
*
****/
/*
===== bmodels.cpp ========================================================
spawn, think, and use functions for entities that use brush models
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "doors.h"
extern DLL_GLOBAL Vector g_vecAttackDir;
#define SF_BRUSH_ACCDCC 16// brush should accelerate and decelerate when toggled
#define SF_BRUSH_HURT 32// rotating brush that inflicts pain based on rotation speed
#define SF_ROTATING_NOT_SOLID 64 // some special rotating objects are not solid.
// covering cheesy noise1, noise2, & noise3 fields so they make more sense (for rotating fans)
#define noiseStart noise1
#define noiseStop noise2
#define noiseRunning noise3
#define SF_PENDULUM_SWING 2 // spawnflag that makes a pendulum a rope swing.
//
// BModelOrigin - calculates origin of a bmodel from absmin/size because all bmodel origins are 0 0 0
//
Vector VecBModelOrigin( entvars_t* pevBModel )
{
return pevBModel->absmin + ( pevBModel->size * 0.5 );
}
// =================== FUNC_WALL ==============================================
/*QUAKED func_wall (0 .5 .8) ?
This is just a solid wall if not inhibited
*/
class CFuncWall : public CBaseEntity
{
public:
void Spawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
// Bmodels don't go across transitions
virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
};
LINK_ENTITY_TO_CLASS( func_wall, CFuncWall );
void CFuncWall :: Spawn( void )
{
pev->angles = g_vecZero;
pev->movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything
pev->solid = SOLID_BSP;
SET_MODEL( ENT(pev), STRING(pev->model) );
// If it can't move/go away, it's really part of the world
pev->flags |= FL_WORLDBRUSH;
}
void CFuncWall :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( ShouldToggle( useType, (int)(pev->frame)) )
pev->frame = 1 - pev->frame;
}
#define SF_WALL_START_OFF 0x0001
class CFuncWallToggle : public CFuncWall
{
public:
void Spawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void TurnOff( void );
void TurnOn( void );
BOOL IsOn( void );
};
LINK_ENTITY_TO_CLASS( func_wall_toggle, CFuncWallToggle );
void CFuncWallToggle :: Spawn( void )
{
CFuncWall::Spawn();
if ( pev->spawnflags & SF_WALL_START_OFF )
TurnOff();
}
void CFuncWallToggle :: TurnOff( void )
{
pev->solid = SOLID_NOT;
pev->effects |= EF_NODRAW;
UTIL_SetOrigin( pev, pev->origin );
}
void CFuncWallToggle :: TurnOn( void )
{
pev->solid = SOLID_BSP;
pev->effects &= ~EF_NODRAW;
UTIL_SetOrigin( pev, pev->origin );
}
BOOL CFuncWallToggle :: IsOn( void )
{
if ( pev->solid == SOLID_NOT )
return FALSE;
return TRUE;
}
void CFuncWallToggle :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
int status = IsOn();
if ( ShouldToggle( useType, status ) )
{
if ( status )
TurnOff();
else
TurnOn();
}
}
#define SF_CONVEYOR_VISUAL 0x0001
#define SF_CONVEYOR_NOTSOLID 0x0002
class CFuncConveyor : public CFuncWall
{
public:
void Spawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void UpdateSpeed( float speed );
};
LINK_ENTITY_TO_CLASS( func_conveyor, CFuncConveyor );
void CFuncConveyor :: Spawn( void )
{
SetMovedir( pev );
CFuncWall::Spawn();
if ( !(pev->spawnflags & SF_CONVEYOR_VISUAL) )
SetBits( pev->flags, FL_CONVEYOR );
// HACKHACK - This is to allow for some special effects
if ( pev->spawnflags & SF_CONVEYOR_NOTSOLID )
{
pev->solid = SOLID_NOT;
pev->skin = 0; // Don't want the engine thinking we've got special contents on this brush
}
if ( pev->speed == 0 )
pev->speed = 100;
UpdateSpeed( pev->speed );
}
// HACKHACK -- This is ugly, but encode the speed in the rendercolor to avoid adding more data to the network stream
void CFuncConveyor :: UpdateSpeed( float speed )
{
// Encode it as an integer with 4 fractional bits
int speedCode = (int)(fabs(speed) * 16.0);
if ( speed < 0 )
pev->rendercolor.x = 1;
else
pev->rendercolor.x = 0;
pev->rendercolor.y = (speedCode >> 8);
pev->rendercolor.z = (speedCode & 0xFF);
}
void CFuncConveyor :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
pev->speed = -pev->speed;
UpdateSpeed( pev->speed );
}
// =================== FUNC_ILLUSIONARY ==============================================
/*QUAKED func_illusionary (0 .5 .8) ?
A simple entity that looks solid but lets you walk through it.
*/
class CFuncIllusionary : public CBaseToggle
{
public:
void Spawn( void );
void EXPORT SloshTouch( CBaseEntity *pOther );
void KeyValue( KeyValueData *pkvd );
virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
};
LINK_ENTITY_TO_CLASS( func_illusionary, CFuncIllusionary );
void CFuncIllusionary :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "skin"))//skin is used for content type
{
pev->skin = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CBaseToggle::KeyValue( pkvd );
}
void CFuncIllusionary :: Spawn( void )
{
pev->angles = g_vecZero;
pev->movetype = MOVETYPE_NONE;
pev->solid = SOLID_NOT;// always solid_not
SET_MODEL( ENT(pev), STRING(pev->model) );
// I'd rather eat the network bandwidth of this than figure out how to save/restore
// these entities after they have been moved to the client, or respawn them ala Quake
// Perhaps we can do this in deathmatch only.
// MAKE_STATIC(ENT(pev));
}
// -------------------------------------------------------------------------------
//
// Monster only clip brush
//
// This brush will be solid for any entity who has the FL_MONSTERCLIP flag set
// in pev->flags
//
// otherwise it will be invisible and not solid. This can be used to keep
// specific monsters out of certain areas
//
// -------------------------------------------------------------------------------
class CFuncMonsterClip : public CFuncWall
{
public:
void Spawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) {} // Clear out func_wall's use function
};
LINK_ENTITY_TO_CLASS( func_monsterclip, CFuncMonsterClip );
void CFuncMonsterClip::Spawn( void )
{
CFuncWall::Spawn();
if ( CVAR_GET_FLOAT("showtriggers") == 0 )
pev->effects = EF_NODRAW;
pev->flags |= FL_MONSTERCLIP;
}
// =================== FUNC_ROTATING ==============================================
class CFuncRotating : public CBaseEntity
{
public:
// basic functions
void Spawn( void );
void Precache( void );
void EXPORT SpinUp ( void );
void EXPORT SpinDown ( void );
void KeyValue( KeyValueData* pkvd);
void EXPORT HurtTouch ( CBaseEntity *pOther );
void EXPORT RotatingUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT Rotate( void );
void RampPitchVol (int fUp );
void Blocked( CBaseEntity *pOther );
virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
float m_flFanFriction;
float m_flAttenuation;
float m_flVolume;
float m_pitch;
int m_sounds;
};
TYPEDESCRIPTION CFuncRotating::m_SaveData[] =
{
DEFINE_FIELD( CFuncRotating, m_flFanFriction, FIELD_FLOAT ),
DEFINE_FIELD( CFuncRotating, m_flAttenuation, FIELD_FLOAT ),
DEFINE_FIELD( CFuncRotating, m_flVolume, FIELD_FLOAT ),
DEFINE_FIELD( CFuncRotating, m_pitch, FIELD_FLOAT ),
DEFINE_FIELD( CFuncRotating, m_sounds, FIELD_INTEGER )
};
IMPLEMENT_SAVERESTORE( CFuncRotating, CBaseEntity );
LINK_ENTITY_TO_CLASS( func_rotating, CFuncRotating );
void CFuncRotating :: KeyValue( KeyValueData* pkvd)
{
if (FStrEq(pkvd->szKeyName, "fanfriction"))
{
m_flFanFriction = atof(pkvd->szValue)/100;
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "Volume"))
{
m_flVolume = atof(pkvd->szValue)/10.0;
if (m_flVolume > 1.0)
m_flVolume = 1.0;
if (m_flVolume < 0.0)
m_flVolume = 0.0;
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "spawnorigin"))
{
Vector tmp;
UTIL_StringToVector( (float *)tmp, pkvd->szValue );
if ( tmp != g_vecZero )
pev->origin = tmp;
}
else if (FStrEq(pkvd->szKeyName, "sounds"))
{
m_sounds = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CBaseEntity::KeyValue( pkvd );
}
/*QUAKED func_rotating (0 .5 .8) ? START_ON REVERSE X_AXIS Y_AXIS
You need to have an origin brush as part of this entity. The
center of that brush will be
the point around which it is rotated. It will rotate around the Z
axis by default. You can
check either the X_AXIS or Y_AXIS box to change that.
"speed" determines how fast it moves; default value is 100.
"dmg" damage to inflict when blocked (2 default)
REVERSE will cause the it to rotate in the opposite direction.
*/
void CFuncRotating :: Spawn( )
{
// set final pitch. Must not be PITCH_NORM, since we
// plan on pitch shifting later.
m_pitch = PITCH_NORM - 1;
// maintain compatibility with previous maps
if (m_flVolume == 0.0)
m_flVolume = 1.0;
// if the designer didn't set a sound attenuation, default to one.
m_flAttenuation = ATTN_NORM;
if ( FBitSet ( pev->spawnflags, SF_BRUSH_ROTATE_SMALLRADIUS) )
{
m_flAttenuation = ATTN_IDLE;
}
else if ( FBitSet ( pev->spawnflags, SF_BRUSH_ROTATE_MEDIUMRADIUS) )
{
m_flAttenuation = ATTN_STATIC;
}
else if ( FBitSet ( pev->spawnflags, SF_BRUSH_ROTATE_LARGERADIUS) )
{
m_flAttenuation = ATTN_NORM;
}
// prevent divide by zero if level designer forgets friction!
if ( m_flFanFriction == 0 )
{
m_flFanFriction = 1;
}
if ( FBitSet(pev->spawnflags, SF_BRUSH_ROTATE_Z_AXIS) )
pev->movedir = Vector(0,0,1);
else if ( FBitSet(pev->spawnflags, SF_BRUSH_ROTATE_X_AXIS) )
pev->movedir = Vector(1,0,0);
else
pev->movedir = Vector(0,1,0); // y-axis
// check for reverse rotation
if ( FBitSet(pev->spawnflags, SF_BRUSH_ROTATE_BACKWARDS) )
pev->movedir = pev->movedir * -1;
// some rotating objects like fake volumetric lights will not be solid.
if ( FBitSet(pev->spawnflags, SF_ROTATING_NOT_SOLID) )
{
pev->solid = SOLID_NOT;
pev->skin = CONTENTS_EMPTY;
pev->movetype = MOVETYPE_PUSH;
}
else
{
pev->solid = SOLID_BSP;
pev->movetype = MOVETYPE_PUSH;
}
UTIL_SetOrigin(pev, pev->origin);
SET_MODEL( ENT(pev), STRING(pev->model) );
SetUse( &CFuncRotating::RotatingUse );
// did level designer forget to assign speed?
if (pev->speed <= 0)
pev->speed = 0;
// Removed this per level designers request. -- JAY
// if (pev->dmg == 0)
// pev->dmg = 2;
// instant-use brush?
if ( FBitSet( pev->spawnflags, SF_BRUSH_ROTATE_INSTANT) )
{
SetThink( &CBaseEntity::SUB_CallUseToggle );
pev->nextthink = pev->ltime + 1.5; // leave a magic delay for client to start up
}
// can this brush inflict pain?
if ( FBitSet (pev->spawnflags, SF_BRUSH_HURT) )
{
SetTouch( &CFuncRotating::HurtTouch );
}
Precache( );
}
void CFuncRotating :: Precache( void )
{
char* szSoundFile = (char*) STRING(pev->message);
// set up fan sounds
if (!FStringNull( pev->message ) && strlen( szSoundFile ) > 0)
{
// if a path is set for a wave, use it
PRECACHE_SOUND(szSoundFile);
pev->noiseRunning = ALLOC_STRING(szSoundFile);
} else
{
// otherwise use preset sound
switch (m_sounds)
{
case 1:
PRECACHE_SOUND ("fans/fan1.wav");
pev->noiseRunning = ALLOC_STRING("fans/fan1.wav");
break;
case 2:
PRECACHE_SOUND ("fans/fan2.wav");
pev->noiseRunning = ALLOC_STRING("fans/fan2.wav");
break;
case 3:
PRECACHE_SOUND ("fans/fan3.wav");
pev->noiseRunning = ALLOC_STRING("fans/fan3.wav");
break;
case 4:
PRECACHE_SOUND ("fans/fan4.wav");
pev->noiseRunning = ALLOC_STRING("fans/fan4.wav");
break;
case 5:
PRECACHE_SOUND ("fans/fan5.wav");
pev->noiseRunning = ALLOC_STRING("fans/fan5.wav");
break;
case 0:
default:
if (!FStringNull( pev->message ) && strlen( szSoundFile ) > 0)
{
PRECACHE_SOUND(szSoundFile);
pev->noiseRunning = ALLOC_STRING(szSoundFile);
break;
} else
{
pev->noiseRunning = ALLOC_STRING("common/null.wav");
break;
}
}
}
if (pev->avelocity != g_vecZero )
{
// if fan was spinning, and we went through transition or save/restore,
// make sure we restart the sound. 1.5 sec delay is magic number. KDB
SetThink ( &CFuncRotating::SpinUp );
pev->nextthink = pev->ltime + 1.5;
}
}
//
// Touch - will hurt others based on how fast the brush is spinning
//
void CFuncRotating :: HurtTouch ( CBaseEntity *pOther )
{
entvars_t *pevOther = pOther->pev;
// we can't hurt this thing, so we're not concerned with it
if ( !pevOther->takedamage )
return;
// calculate damage based on rotation speed
pev->dmg = pev->avelocity.Length() / 10;
pOther->TakeDamage( pev, pev, pev->dmg, DMG_CRUSH);
pevOther->velocity = (pevOther->origin - VecBModelOrigin(pev) ).Normalize() * pev->dmg;
}
//
// RampPitchVol - ramp pitch and volume up to final values, based on difference
// between how fast we're going vs how fast we plan to go
//
#define FANPITCHMIN 30
#define FANPITCHMAX 100
void CFuncRotating :: RampPitchVol (int fUp)
{
Vector vecAVel = pev->avelocity;
vec_t vecCur;
vec_t vecFinal;
float fpct;
float fvol;
float fpitch;
int pitch;
// get current angular velocity
vecCur = abs(vecAVel.x != 0 ? static_cast<int>(vecAVel.x) : static_cast<int>(vecAVel.y != 0 ? vecAVel.y : vecAVel.z));
// get target angular velocity
vecFinal = (pev->movedir.x != 0 ? pev->movedir.x : (pev->movedir.y != 0 ? pev->movedir.y : pev->movedir.z));
vecFinal *= pev->speed;
vecFinal = abs(static_cast<int>(vecFinal));
// calc volume and pitch as % of final vol and pitch
fpct = vecCur / vecFinal;
// if (fUp)
// fvol = m_flVolume * (0.5 + fpct/2.0); // spinup volume ramps up from 50% max vol
// else
fvol = m_flVolume * fpct; // slowdown volume ramps down to 0
fpitch = FANPITCHMIN + (FANPITCHMAX - FANPITCHMIN) * fpct;
pitch = (int) fpitch;
if (pitch == PITCH_NORM)
pitch = PITCH_NORM-1;
// change the fan's vol and pitch
EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseRunning),
fvol, m_flAttenuation, SND_CHANGE_PITCH | SND_CHANGE_VOL, pitch);
}
//
// SpinUp - accelerates a non-moving func_rotating up to it's speed
//
void CFuncRotating :: SpinUp( void )
{
Vector vecAVel;//rotational velocity
pev->nextthink = pev->ltime + 0.1;
pev->avelocity = pev->avelocity + ( pev->movedir * ( pev->speed * m_flFanFriction ) );
vecAVel = pev->avelocity;// cache entity's rotational velocity
// if we've met or exceeded target speed, set target speed and stop thinking
if ( abs(static_cast<int>(vecAVel.x)) >= abs(static_cast<int>(pev->movedir.x * pev->speed)) &&
abs(static_cast<int>(vecAVel.y)) >= abs(static_cast<int>(pev->movedir.y * pev->speed)) &&
abs(static_cast<int>(vecAVel.z)) >= abs(static_cast<int>(pev->movedir.z * pev->speed)) )
{
pev->avelocity = pev->movedir * pev->speed;// set speed in case we overshot
EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseRunning),
m_flVolume, m_flAttenuation, SND_CHANGE_PITCH | SND_CHANGE_VOL, FANPITCHMAX);
SetThink( &CFuncRotating::Rotate );
Rotate();
}
else
{
RampPitchVol(TRUE);
}
}
//
// SpinDown - decelerates a moving func_rotating to a standstill.
//
void CFuncRotating :: SpinDown( void )
{
Vector vecAVel;//rotational velocity
vec_t vecdir;
pev->nextthink = pev->ltime + 0.1;
pev->avelocity = pev->avelocity - ( pev->movedir * ( pev->speed * m_flFanFriction ) );//spin down slower than spinup
vecAVel = pev->avelocity;// cache entity's rotational velocity
if (pev->movedir.x != 0)
vecdir = pev->movedir.x;
else if (pev->movedir.y != 0)
vecdir = pev->movedir.y;
else
vecdir = pev->movedir.z;
// if we've met or exceeded target speed, set target speed and stop thinking
// (note: must check for movedir > 0 or < 0)
if (((vecdir > 0) && (vecAVel.x <= 0 && vecAVel.y <= 0 && vecAVel.z <= 0)) ||
((vecdir < 0) && (vecAVel.x >= 0 && vecAVel.y >= 0 && vecAVel.z >= 0)))
{
pev->avelocity = g_vecZero;// set speed in case we overshot
// stop sound, we're done
EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseRunning /* Stop */),
0, 0, SND_STOP, static_cast<int>(m_pitch));
SetThink( &CFuncRotating::Rotate );
Rotate();
}
else
{
RampPitchVol(FALSE);
}
}
void CFuncRotating :: Rotate( void )
{
pev->nextthink = pev->ltime + 10;
}
//=========================================================
// Rotating Use - when a rotating brush is triggered
//=========================================================
void CFuncRotating :: RotatingUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
// is this a brush that should accelerate and decelerate when turned on/off (fan)?
if ( FBitSet ( pev->spawnflags, SF_BRUSH_ACCDCC ) )
{
// fan is spinning, so stop it.
if ( pev->avelocity != g_vecZero )
{
SetThink ( &CFuncRotating::SpinDown );
//EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, (char *)STRING(pev->noiseStop),
// m_flVolume, m_flAttenuation, 0, m_pitch);
pev->nextthink = pev->ltime + 0.1;
}
else// fan is not moving, so start it
{
SetThink ( &CFuncRotating::SpinUp );
EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseRunning),
0.01, m_flAttenuation, 0, FANPITCHMIN);
pev->nextthink = pev->ltime + 0.1;
}
}
else if ( !FBitSet ( pev->spawnflags, SF_BRUSH_ACCDCC ) )//this is a normal start/stop brush.
{
if ( pev->avelocity != g_vecZero )
{
// play stopping sound here
SetThink ( &CFuncRotating::SpinDown );
// EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, (char *)STRING(pev->noiseStop),
// m_flVolume, m_flAttenuation, 0, m_pitch);
pev->nextthink = pev->ltime + 0.1;
// pev->avelocity = g_vecZero;
}
else
{
EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseRunning),
m_flVolume, m_flAttenuation, 0, FANPITCHMAX);
pev->avelocity = pev->movedir * pev->speed;
SetThink( &CFuncRotating::Rotate );
Rotate();
}
}
}
//
// RotatingBlocked - An entity has blocked the brush
//
void CFuncRotating :: Blocked( CBaseEntity *pOther )
{
pOther->TakeDamage( pev, pev, pev->dmg, DMG_CRUSH);
}
//#endif
class CPendulum : public CBaseEntity
{
public:
void Spawn ( void );
void KeyValue( KeyValueData *pkvd );
void EXPORT Swing( void );
void EXPORT PendulumUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT Stop( void );
void Touch( CBaseEntity *pOther );
void EXPORT RopeTouch ( CBaseEntity *pOther );// this touch func makes the pendulum a rope
virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
void Blocked( CBaseEntity *pOther );
static TYPEDESCRIPTION m_SaveData[];
float m_accel; // Acceleration
float m_distance; //
float m_time;
float m_damp;
float m_maxSpeed;
float m_dampSpeed;
vec3_t m_center;
vec3_t m_start;
};
LINK_ENTITY_TO_CLASS( func_pendulum, CPendulum );
TYPEDESCRIPTION CPendulum::m_SaveData[] =
{
DEFINE_FIELD( CPendulum, m_accel, FIELD_FLOAT ),
DEFINE_FIELD( CPendulum, m_distance, FIELD_FLOAT ),
DEFINE_FIELD( CPendulum, m_time, FIELD_TIME ),
DEFINE_FIELD( CPendulum, m_damp, FIELD_FLOAT ),
DEFINE_FIELD( CPendulum, m_maxSpeed, FIELD_FLOAT ),
DEFINE_FIELD( CPendulum, m_dampSpeed, FIELD_FLOAT ),
DEFINE_FIELD( CPendulum, m_center, FIELD_VECTOR ),
DEFINE_FIELD( CPendulum, m_start, FIELD_VECTOR ),
};
IMPLEMENT_SAVERESTORE( CPendulum, CBaseEntity );
void CPendulum :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "distance"))
{
m_distance = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "damp"))
{
m_damp = atof(pkvd->szValue) * 0.001;
pkvd->fHandled = TRUE;
}
else
CBaseEntity::KeyValue( pkvd );
}
void CPendulum :: Spawn( void )
{
// set the axis of rotation
CBaseToggle :: AxisDir( pev );
if ( FBitSet (pev->spawnflags, SF_DOOR_PASSABLE) )
pev->solid = SOLID_NOT;
else
pev->solid = SOLID_BSP;
pev->movetype = MOVETYPE_PUSH;
UTIL_SetOrigin(pev, pev->origin);
SET_MODEL(ENT(pev), STRING(pev->model) );
if ( m_distance == 0 )
return;
if (pev->speed == 0)
pev->speed = 100;
m_accel = (pev->speed * pev->speed) / (2 * fabs(m_distance)); // Calculate constant acceleration from speed and distance
m_maxSpeed = pev->speed;
m_start = pev->angles;
m_center = pev->angles + (m_distance * 0.5) * pev->movedir;
if ( FBitSet( pev->spawnflags, SF_BRUSH_ROTATE_INSTANT) )
{
SetThink( &CBaseEntity::SUB_CallUseToggle );
pev->nextthink = gpGlobals->time + 0.1;
}
pev->speed = 0;
SetUse( &CPendulum::PendulumUse );
if ( FBitSet( pev->spawnflags, SF_PENDULUM_SWING ) )
{
SetTouch ( &CPendulum::RopeTouch );
}
}
void CPendulum :: PendulumUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( pev->speed ) // Pendulum is moving, stop it and auto-return if necessary
{
if ( FBitSet( pev->spawnflags, SF_PENDULUM_AUTO_RETURN ) )
{
float delta;
delta = CBaseToggle :: AxisDelta( pev->spawnflags, pev->angles, m_start );
pev->avelocity = m_maxSpeed * pev->movedir;
pev->nextthink = pev->ltime + (delta / m_maxSpeed);
SetThink( &CPendulum::Stop );
}
else
{
pev->speed = 0; // Dead stop
SetThink( NULL );
pev->avelocity = g_vecZero;
}
}
else
{
pev->nextthink = pev->ltime + 0.1; // Start the pendulum moving
m_time = gpGlobals->time; // Save time to calculate dt
SetThink( &CPendulum::Swing );
m_dampSpeed = m_maxSpeed;
}
}
void CPendulum :: Stop( void )
{
pev->angles = m_start;
pev->speed = 0;
SetThink( NULL );
pev->avelocity = g_vecZero;
}
void CPendulum::Blocked( CBaseEntity *pOther )
{
m_time = gpGlobals->time;
}
void CPendulum :: Swing( void )
{
float delta, dt;
delta = CBaseToggle :: AxisDelta( pev->spawnflags, pev->angles, m_center );
dt = gpGlobals->time - m_time; // How much time has passed?
m_time = gpGlobals->time; // Remember the last time called
if ( delta > 0 && m_accel > 0 )
pev->speed -= m_accel * dt; // Integrate velocity
else
pev->speed += m_accel * dt;
if ( pev->speed > m_maxSpeed )
pev->speed = m_maxSpeed;
else if ( pev->speed < -m_maxSpeed )
pev->speed = -m_maxSpeed;
// scale the destdelta vector by the time spent traveling to get velocity
pev->avelocity = pev->speed * pev->movedir;
// Call this again
pev->nextthink = pev->ltime + 0.1;
if ( m_damp )
{
m_dampSpeed -= m_damp * m_dampSpeed * dt;
if ( m_dampSpeed < 30.0 )
{
pev->angles = m_center;
pev->speed = 0;
SetThink( NULL );
pev->avelocity = g_vecZero;
}
else if ( pev->speed > m_dampSpeed )
pev->speed = m_dampSpeed;
else if ( pev->speed < -m_dampSpeed )
pev->speed = -m_dampSpeed;
}
}
void CPendulum :: Touch ( CBaseEntity *pOther )
{
entvars_t *pevOther = pOther->pev;
if ( pev->dmg <= 0 )
return;
// we can't hurt this thing, so we're not concerned with it
if ( !pevOther->takedamage )
return;
// calculate damage based on rotation speed
float damage = pev->dmg * pev->speed * 0.01;
if ( damage < 0 )
damage = -damage;
pOther->TakeDamage( pev, pev, damage, DMG_CRUSH );
pevOther->velocity = (pevOther->origin - VecBModelOrigin(pev) ).Normalize() * damage;
}
void CPendulum :: RopeTouch ( CBaseEntity *pOther )
{
entvars_t *pevOther = pOther->pev;
if ( !pOther->IsPlayer() )
{// not a player!
ALERT ( at_console, "Not a client\n" );
return;
}
if ( ENT(pevOther) == pev->enemy )
{// this player already on the rope.
return;
}
pev->enemy = pOther->edict();
pevOther->velocity = g_vecZero;
pevOther->movetype = MOVETYPE_NONE;
}

1276
hlsdk/dmc/dlls/buttons.cpp Normal file

File diff suppressed because it is too large Load Diff

767
hlsdk/dmc/dlls/cbase.cpp Normal file
View File

@ -0,0 +1,767 @@
/***
*
* 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 "extdll.h"
#include "util.h"
#include "cbase.h"
#include "saverestore.h"
#include "client.h"
#include "decals.h"
#include "gamerules.h"
#include "game.h"
extern "C" void PM_Move ( struct playermove_s *ppmove, int server );
extern "C" void PM_Init ( struct playermove_s *ppmove );
extern "C" char PM_FindTextureType( char *name );
void EntvarsKeyvalue( entvars_t *pev, KeyValueData *pkvd );
extern Vector VecBModelOrigin( entvars_t* pevBModel );
extern DLL_GLOBAL Vector g_vecAttackDir;
extern DLL_GLOBAL int g_iSkillLevel;
static DLL_FUNCTIONS gFunctionTable =
{
GameDLLInit, //pfnGameInit
DispatchSpawn, //pfnSpawn
DispatchThink, //pfnThink
DispatchUse, //pfnUse
DispatchTouch, //pfnTouch
DispatchBlocked, //pfnBlocked
DispatchKeyValue, //pfnKeyValue
DispatchSave, //pfnSave
DispatchRestore, //pfnRestore
DispatchObjectCollsionBox, //pfnAbsBox
SaveWriteFields, //pfnSaveWriteFields
SaveReadFields, //pfnSaveReadFields
SaveGlobalState, //pfnSaveGlobalState
RestoreGlobalState, //pfnRestoreGlobalState
ResetGlobalState, //pfnResetGlobalState
ClientConnect, //pfnClientConnect
ClientDisconnect, //pfnClientDisconnect
ClientKill, //pfnClientKill
ClientPutInServer, //pfnClientPutInServer
ClientCommand, //pfnClientCommand
ClientUserInfoChanged, //pfnClientUserInfoChanged
ServerActivate, //pfnServerActivate
ServerDeactivate, //pfnServerDeactivate
PlayerPreThink, //pfnPlayerPreThink
PlayerPostThink, //pfnPlayerPostThink
StartFrame, //pfnStartFrame
ParmsNewLevel, //pfnParmsNewLevel
ParmsChangeLevel, //pfnParmsChangeLevel
GetGameDescription, //pfnGetGameDescription Returns string describing current .dll game.
PlayerCustomization, //pfnPlayerCustomization Notifies .dll of new customization for player.
SpectatorConnect, //pfnSpectatorConnect Called when spectator joins server
SpectatorDisconnect, //pfnSpectatorDisconnect Called when spectator leaves the server
SpectatorThink, //pfnSpectatorThink Called when spectator sends a command packet (usercmd_t)
Sys_Error, //pfnSys_Error Called when engine has encountered an error
PM_Move, //pfnPM_Move
PM_Init, //pfnPM_Init Server version of player movement initialization
PM_FindTextureType, //pfnPM_FindTextureType
SetupVisibility, //pfnSetupVisibility Set up PVS and PAS for networking for this client
UpdateClientData, //pfnUpdateClientData Set up data sent only to specific client
AddToFullPack, //pfnAddToFullPack
CreateBaseline, //pfnCreateBaseline Tweak entity baseline for network encoding, allows setup of player baselines, too.
RegisterEncoders, //pfnRegisterEncoders Callbacks for network encoding
GetWeaponData, //pfnGetWeaponData
CmdStart, //pfnCmdStart
CmdEnd, //pfnCmdEnd
ConnectionlessPacket, //pfnConnectionlessPacket
GetHullBounds, //pfnGetHullBounds
CreateInstancedBaselines, //pfnCreateInstancedBaselines
InconsistentFile, //pfnInconsistentFile
AllowLagCompensation, //pfnAllowLagCompensation
};
static void SetObjectCollisionBox( entvars_t *pev );
int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion )
{
if ( !pFunctionTable || interfaceVersion != INTERFACE_VERSION )
{
return FALSE;
}
memcpy( pFunctionTable, &gFunctionTable, sizeof( DLL_FUNCTIONS ) );
return TRUE;
}
int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion )
{
if ( !pFunctionTable || *interfaceVersion != INTERFACE_VERSION )
{
// Tell engine what version we had, so it can figure out who is out of date.
*interfaceVersion = INTERFACE_VERSION;
return FALSE;
}
memcpy( pFunctionTable, &gFunctionTable, sizeof( DLL_FUNCTIONS ) );
return TRUE;
}
int DispatchSpawn( edict_t *pent )
{
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent);
if (pEntity)
{
// 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);
pEntity->Spawn();
// Try to get the pointer again, in case the spawn function deleted the entity.
// UNDONE: Spawn() should really return a code to ask that the entity be deleted, but
// that would touch too much code for me to do that right now.
pEntity = (CBaseEntity *)GET_PRIVATE(pent);
if ( pEntity )
{
if ( g_pGameRules && !g_pGameRules->IsAllowedToSpawn( pEntity ) )
return -1; // return that this entity should be deleted
if ( pEntity->pev->flags & FL_KILLME )
return -1;
}
// Handle global stuff here
if ( pEntity && pEntity->pev->globalname )
{
const globalentity_t *pGlobal = gGlobalState.EntityFromTable( pEntity->pev->globalname );
if ( pGlobal )
{
// Already dead? delete
if ( pGlobal->state == GLOBAL_DEAD )
return -1;
else if ( !FStrEq( STRING(gpGlobals->mapname), pGlobal->levelName ) )
pEntity->MakeDormant(); // Hasn't been moved to this level yet, wait but stay alive
// In this level & not dead, continue on as normal
}
else
{
// Spawned entities default to 'On'
gGlobalState.EntityAdd( pEntity->pev->globalname, gpGlobals->mapname, GLOBAL_ON );
// ALERT( at_console, "Added global entity %s (%s)\n", STRING(pEntity->pev->classname), STRING(pEntity->pev->globalname) );
}
}
}
return 0;
}
void DispatchKeyValue( edict_t *pentKeyvalue, KeyValueData *pkvd )
{
if ( !pkvd || !pentKeyvalue )
return;
EntvarsKeyvalue( VARS(pentKeyvalue), pkvd );
// If the key was an entity variable, or there's no class set yet, don't look for the object, it may
// not exist yet.
if ( pkvd->fHandled || pkvd->szClassName == NULL )
return;
// Get the actualy entity object
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pentKeyvalue);
if ( !pEntity )
return;
pEntity->KeyValue( pkvd );
}
// HACKHACK -- this is a hack to keep the node graph entity from "touching" things (like triggers)
// while it builds the graph
BOOL gTouchDisabled = FALSE;
void DispatchTouch( edict_t *pentTouched, edict_t *pentOther )
{
if ( gTouchDisabled )
return;
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pentTouched);
CBaseEntity *pOther = (CBaseEntity *)GET_PRIVATE( pentOther );
if ( pEntity && pOther && ! ((pEntity->pev->flags | pOther->pev->flags) & FL_KILLME) )
pEntity->Touch( pOther );
}
void DispatchUse( edict_t *pentUsed, edict_t *pentOther )
{
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pentUsed);
CBaseEntity *pOther = (CBaseEntity *)GET_PRIVATE(pentOther);
if (pEntity && !(pEntity->pev->flags & FL_KILLME) )
pEntity->Use( pOther, pOther, USE_TOGGLE, 0 );
}
void DispatchThink( edict_t *pent )
{
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent);
if (pEntity)
{
if ( FBitSet( pEntity->pev->flags, FL_DORMANT ) )
ALERT( at_error, "Dormant entity %s is thinking!!\n", STRING(pEntity->pev->classname) );
pEntity->Think();
}
}
void DispatchBlocked( edict_t *pentBlocked, edict_t *pentOther )
{
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE( pentBlocked );
CBaseEntity *pOther = (CBaseEntity *)GET_PRIVATE( pentOther );
if (pEntity)
pEntity->Blocked( pOther );
}
void DispatchSave( edict_t *pent, SAVERESTOREDATA *pSaveData )
{
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent);
if ( pEntity && pSaveData )
{
ENTITYTABLE *pTable = &pSaveData->pTable[ pSaveData->currentIndex ];
if ( pTable->pent != pent )
ALERT( at_error, "ENTITY TABLE OR INDEX IS WRONG!!!!\n" );
if ( pEntity->ObjectCaps() & FCAP_DONT_SAVE )
return;
// These don't use ltime & nextthink as times really, but we'll fudge around it.
if ( pEntity->pev->movetype == MOVETYPE_PUSH )
{
float delta = pEntity->pev->nextthink - pEntity->pev->ltime;
pEntity->pev->ltime = gpGlobals->time;
pEntity->pev->nextthink = pEntity->pev->ltime + delta;
}
pTable->location = pSaveData->size; // Remember entity position for file I/O
pTable->classname = pEntity->pev->classname; // Remember entity class for respawn
CSave saveHelper( pSaveData );
pEntity->Save( saveHelper );
pTable->size = pSaveData->size - pTable->location; // Size of entity block is data size written to block
}
}
// Find the matching global entity. Spit out an error if the designer made entities of
// different classes with the same global name
CBaseEntity *FindGlobalEntity( string_t classname, string_t globalname )
{
edict_t *pent = FIND_ENTITY_BY_STRING( NULL, "globalname", STRING(globalname) );
CBaseEntity *pReturn = CBaseEntity::Instance( pent );
if ( pReturn )
{
if ( !FClassnameIs( pReturn->pev, STRING(classname) ) )
{
ALERT( at_console, "Global entity found %s, wrong class %s\n", STRING(globalname), STRING(pReturn->pev->classname) );
pReturn = NULL;
}
}
return pReturn;
}
int DispatchRestore( edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity )
{
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent);
if ( pEntity && pSaveData )
{
entvars_t tmpVars;
Vector oldOffset;
CRestore restoreHelper( pSaveData );
if ( globalEntity )
{
CRestore tmpRestore( pSaveData );
tmpRestore.PrecacheMode( 0 );
tmpRestore.ReadEntVars( "ENTVARS", &tmpVars );
// HACKHACK - reset the save pointers, we're going to restore for real this time
pSaveData->size = pSaveData->pTable[pSaveData->currentIndex].location;
pSaveData->pCurrentData = pSaveData->pBaseData + pSaveData->size;
// -------------------
const globalentity_t *pGlobal = gGlobalState.EntityFromTable( tmpVars.globalname );
// Don't overlay any instance of the global that isn't the latest
// pSaveData->szCurrentMapName is the level this entity is coming from
// pGlobla->levelName is the last level the global entity was active in.
// If they aren't the same, then this global update is out of date.
if ( !FStrEq( pSaveData->szCurrentMapName, pGlobal->levelName ) )
return 0;
// Compute the new global offset
oldOffset = pSaveData->vecLandmarkOffset;
CBaseEntity *pNewEntity = FindGlobalEntity( tmpVars.classname, tmpVars.globalname );
if ( pNewEntity )
{
// ALERT( at_console, "Overlay %s with %s\n", STRING(pNewEntity->pev->classname), STRING(tmpVars.classname) );
// Tell the restore code we're overlaying a global entity from another level
restoreHelper.SetGlobalMode( 1 ); // Don't overwrite global fields
pSaveData->vecLandmarkOffset = (pSaveData->vecLandmarkOffset - pNewEntity->pev->mins) + tmpVars.mins;
pEntity = pNewEntity;// we're going to restore this data OVER the old entity
pent = ENT( pEntity->pev );
// Update the global table to say that the global definition of this entity should come from this level
gGlobalState.EntityUpdate( pEntity->pev->globalname, gpGlobals->mapname );
}
else
{
// This entity will be freed automatically by the engine. If we don't do a restore on a matching entity (below)
// or call EntityUpdate() to move it to this level, we haven't changed global state at all.
return 0;
}
}
if ( pEntity->ObjectCaps() & FCAP_MUST_SPAWN )
{
pEntity->Restore( restoreHelper );
pEntity->Spawn();
}
else
{
pEntity->Restore( restoreHelper );
pEntity->Precache( );
}
// Again, could be deleted, get the pointer again.
pEntity = (CBaseEntity *)GET_PRIVATE(pent);
#if 0
if ( pEntity && pEntity->pev->globalname && globalEntity )
{
ALERT( at_console, "Global %s is %s\n", STRING(pEntity->pev->globalname), STRING(pEntity->pev->model) );
}
#endif
// Is this an overriding global entity (coming over the transition), or one restoring in a level
if ( globalEntity )
{
// ALERT( at_console, "After: %f %f %f %s\n", pEntity->pev->origin.x, pEntity->pev->origin.y, pEntity->pev->origin.z, STRING(pEntity->pev->model) );
pSaveData->vecLandmarkOffset = oldOffset;
if ( pEntity )
{
UTIL_SetOrigin( pEntity->pev, pEntity->pev->origin );
pEntity->OverrideReset();
}
}
else if ( pEntity && pEntity->pev->globalname )
{
const globalentity_t *pGlobal = gGlobalState.EntityFromTable( pEntity->pev->globalname );
if ( pGlobal )
{
// Already dead? delete
if ( pGlobal->state == GLOBAL_DEAD )
return -1;
else if ( !FStrEq( STRING(gpGlobals->mapname), pGlobal->levelName ) )
{
pEntity->MakeDormant(); // Hasn't been moved to this level yet, wait but stay alive
}
// In this level & not dead, continue on as normal
}
else
{
ALERT( at_error, "Global Entity %s (%s) not in table!!!\n", STRING(pEntity->pev->globalname), STRING(pEntity->pev->classname) );
// Spawned entities default to 'On'
gGlobalState.EntityAdd( pEntity->pev->globalname, gpGlobals->mapname, GLOBAL_ON );
}
}
}
return 0;
}
void DispatchObjectCollsionBox( edict_t *pent )
{
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent);
if (pEntity)
{
pEntity->SetObjectCollisionBox();
}
else
SetObjectCollisionBox( &pent->v );
}
void SaveWriteFields( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount )
{
CSave saveHelper( pSaveData );
saveHelper.WriteFields( pname, pBaseData, pFields, fieldCount );
}
void SaveReadFields( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount )
{
CRestore restoreHelper( pSaveData );
restoreHelper.ReadFields( pname, pBaseData, pFields, fieldCount );
}
edict_t * EHANDLE::Get( void )
{
if (m_pent)
{
if (m_pent->serialnumber == m_serialnumber)
return m_pent;
else
return NULL;
}
return NULL;
};
edict_t * EHANDLE::Set( edict_t *pent )
{
m_pent = pent;
if (pent)
m_serialnumber = m_pent->serialnumber;
return pent;
};
EHANDLE :: operator CBaseEntity *()
{
return (CBaseEntity *)GET_PRIVATE( Get( ) );
};
CBaseEntity * EHANDLE :: operator = (CBaseEntity *pEntity)
{
if (pEntity)
{
m_pent = ENT( pEntity->pev );
if (m_pent)
m_serialnumber = m_pent->serialnumber;
}
else
{
m_pent = NULL;
m_serialnumber = 0;
}
return pEntity;
}
EHANDLE :: operator int ()
{
return Get() != NULL;
}
CBaseEntity * EHANDLE :: operator -> ()
{
return (CBaseEntity *)GET_PRIVATE( Get( ) );
}
// give health
int CBaseEntity :: TakeHealth( float flHealth, int bitsDamageType )
{
if (!pev->takedamage)
return 0;
// heal
if ( pev->health >= pev->max_health )
return 0;
pev->health += flHealth;
if (pev->health > pev->max_health)
pev->health = pev->max_health;
return 1;
}
// inflict damage on this entity. bitsDamageType indicates type of damage inflicted, ie: DMG_CRUSH
int CBaseEntity :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType )
{
Vector vecTemp;
if (!pev->takedamage)
return 0;
// UNDONE: some entity types may be immune or resistant to some bitsDamageType
// if Attacker == Inflictor, the attack was a melee or other instant-hit attack.
// (that is, no actual entity projectile was involved in the attack so use the shooter's origin).
if ( pevAttacker == pevInflictor )
{
vecTemp = pevAttacker->origin - ( VecBModelOrigin(pev) );
}
else
// an actual missile was involved.
{
vecTemp = pevInflictor->origin - ( VecBModelOrigin(pev) );
}
// this global is still used for glass and other non-monster killables, along with decals.
g_vecAttackDir = vecTemp.Normalize();
// save damage based on the target's armor level
// figure momentum add (don't let hurt brushes or other triggers move player)
if ((!FNullEnt(pevInflictor)) && (pev->movetype == MOVETYPE_WALK || pev->movetype == MOVETYPE_STEP) && (pevAttacker->solid != SOLID_TRIGGER) )
{
Vector vecDir = pev->origin - (pevInflictor->absmin + pevInflictor->absmax) * 0.5;
vecDir = vecDir.Normalize();
float flForce = flDamage * ((32 * 32 * 72.0) / (pev->size.x * pev->size.y * pev->size.z)) * 5;
if (flForce > 1000.0)
flForce = 1000.0;
pev->velocity = pev->velocity + vecDir * flForce;
}
// do the damage
pev->health -= flDamage;
if (pev->health <= 0)
{
Killed( pevAttacker, GIB_NORMAL );
return 0;
}
return 1;
}
void CBaseEntity :: Killed( entvars_t *pevAttacker, int iGib )
{
pev->takedamage = DAMAGE_NO;
pev->deadflag = DEAD_DEAD;
UTIL_Remove( this );
}
CBaseEntity *CBaseEntity::GetNextTarget( void )
{
if ( FStringNull( pev->target ) )
return NULL;
edict_t *pTarget = FIND_ENTITY_BY_TARGETNAME ( NULL, STRING(pev->target) );
if ( FNullEnt(pTarget) )
return NULL;
return Instance( pTarget );
}
// Global Savedata for Delay
TYPEDESCRIPTION CBaseEntity::m_SaveData[] =
{
DEFINE_FIELD( CBaseEntity, m_pGoalEnt, FIELD_CLASSPTR ),
DEFINE_FIELD( CBaseEntity, m_pfnThink, FIELD_FUNCTION ), // UNDONE: Build table of these!!!
DEFINE_FIELD( CBaseEntity, m_pfnTouch, FIELD_FUNCTION ),
DEFINE_FIELD( CBaseEntity, m_pfnUse, FIELD_FUNCTION ),
DEFINE_FIELD( CBaseEntity, m_pfnBlocked, FIELD_FUNCTION ),
};
int CBaseEntity::Save( CSave &save )
{
if ( save.WriteEntVars( "ENTVARS", pev ) )
return save.WriteFields( "BASE", this, m_SaveData, ARRAYSIZE(m_SaveData) );
return 0;
}
int CBaseEntity::Restore( CRestore &restore )
{
int status;
status = restore.ReadEntVars( "ENTVARS", pev );
if ( status )
status = restore.ReadFields( "BASE", this, m_SaveData, ARRAYSIZE(m_SaveData) );
if ( pev->modelindex != 0 && !FStringNull(pev->model) )
{
Vector mins, maxs;
mins = pev->mins; // Set model is about to destroy these
maxs = pev->maxs;
PRECACHE_MODEL( (char *)STRING(pev->model) );
SET_MODEL(ENT(pev), STRING(pev->model));
UTIL_SetSize(pev, mins, maxs); // Reset them
}
return status;
}
// Initialize absmin & absmax to the appropriate box
void SetObjectCollisionBox( entvars_t *pev )
{
if ( (pev->solid == SOLID_BSP) &&
(pev->angles.x || pev->angles.y|| pev->angles.z) )
{ // expand for rotation
float max, v;
int i;
max = 0;
for (i=0 ; i<3 ; i++)
{
v = fabs( pev->mins[i]);
if (v > max)
max = v;
v = fabs( pev->maxs[i]);
if (v > max)
max = v;
}
for (i=0 ; i<3 ; i++)
{
pev->absmin[i] = pev->origin[i] - max;
pev->absmax[i] = pev->origin[i] + max;
}
}
else
{
pev->absmin = pev->origin + pev->mins;
pev->absmax = pev->origin + pev->maxs;
}
pev->absmin.x -= 1;
pev->absmin.y -= 1;
pev->absmin.z -= 1;
pev->absmax.x += 1;
pev->absmax.y += 1;
pev->absmax.z += 1;
}
void CBaseEntity::SetObjectCollisionBox( void )
{
::SetObjectCollisionBox( pev );
}
int CBaseEntity :: Intersects( CBaseEntity *pOther )
{
if ( pOther->pev->absmin.x > pev->absmax.x ||
pOther->pev->absmin.y > pev->absmax.y ||
pOther->pev->absmin.z > pev->absmax.z ||
pOther->pev->absmax.x < pev->absmin.x ||
pOther->pev->absmax.y < pev->absmin.y ||
pOther->pev->absmax.z < pev->absmin.z )
return 0;
return 1;
}
void CBaseEntity :: MakeDormant( void )
{
SetBits( pev->flags, FL_DORMANT );
// Don't touch
pev->solid = SOLID_NOT;
// Don't move
pev->movetype = MOVETYPE_NONE;
// Don't draw
SetBits( pev->effects, EF_NODRAW );
// Don't think
pev->nextthink = 0;
// Relink
UTIL_SetOrigin( pev, pev->origin );
}
int CBaseEntity :: IsDormant( void )
{
return FBitSet( pev->flags, FL_DORMANT );
}
BOOL CBaseEntity :: IsInWorld( void )
{
// position
if (pev->origin.x >= 4096) return FALSE;
if (pev->origin.y >= 4096) return FALSE;
if (pev->origin.z >= 4096) return FALSE;
if (pev->origin.x <= -4096) return FALSE;
if (pev->origin.y <= -4096) return FALSE;
if (pev->origin.z <= -4096) return FALSE;
// speed
if (pev->velocity.x >= 2000) return FALSE;
if (pev->velocity.y >= 2000) return FALSE;
if (pev->velocity.z >= 2000) return FALSE;
if (pev->velocity.x <= -2000) return FALSE;
if (pev->velocity.y <= -2000) return FALSE;
if (pev->velocity.z <= -2000) return FALSE;
return TRUE;
}
int CBaseEntity::ShouldToggle( USE_TYPE useType, BOOL currentState )
{
if ( useType != USE_TOGGLE && useType != USE_SET )
{
if ( (currentState && useType == USE_ON) || (!currentState && useType == USE_OFF) )
return 0;
}
return 1;
}
int CBaseEntity :: DamageDecal( int bitsDamageType )
{
if ( pev->rendermode == kRenderTransAlpha )
return -1;
if ( pev->rendermode != kRenderNormal )
return DECAL_BPROOF1;
return DECAL_GUNSHOT1 + RANDOM_LONG(0,4);
}
// NOTE: szName must be a pointer to constant memory, e.g. "monster_class" because the entity
// will keep a pointer to it after this call.
CBaseEntity * CBaseEntity::Create( char *szName, const Vector &vecOrigin, const Vector &vecAngles, edict_t *pentOwner )
{
edict_t *pent;
CBaseEntity *pEntity;
pent = CREATE_NAMED_ENTITY( MAKE_STRING( szName ));
if ( FNullEnt( pent ) )
{
ALERT ( at_console, "NULL Ent in Create!\n" );
return NULL;
}
pEntity = Instance( pent );
pEntity->pev->owner = pentOwner;
pEntity->pev->origin = vecOrigin;
pEntity->pev->angles = vecAngles;
DispatchSpawn( pEntity->edict() );
return pEntity;
}

801
hlsdk/dmc/dlls/cbase.h Normal file
View File

@ -0,0 +1,801 @@
/***
*
* 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.
*
****/
/*
Class Hierachy
CBaseEntity
CBaseDelay
CBaseToggle
CBaseItem
CBaseMonster
CBaseCycler
CBasePlayer
CBaseGroup
*/
#define MAX_PATH_SIZE 10 // max number of nodes available for a path.
// These are caps bits to indicate what an object's capabilities (currently used for save/restore and level transitions)
#define FCAP_CUSTOMSAVE 0x00000001
#define FCAP_ACROSS_TRANSITION 0x00000002 // should transfer between transitions
#define FCAP_MUST_SPAWN 0x00000004 // Spawn after restore
#define FCAP_DONT_SAVE 0x80000000 // Don't save this
#define FCAP_IMPULSE_USE 0x00000008 // can be used by the player
#define FCAP_CONTINUOUS_USE 0x00000010 // can be used by the player
#define FCAP_ONOFF_USE 0x00000020 // can be used by the player
#define FCAP_DIRECTIONAL_USE 0x00000040 // Player sends +/- 1 when using (currently only tracktrains)
#define FCAP_MASTER 0x00000080 // Can be used to "master" other entities (like multisource)
// UNDONE: This will ignore transition volumes (trigger_transition), but not the PVS!!!
#define FCAP_FORCE_TRANSITION 0x00000080 // ALWAYS goes across transitions
#include "saverestore.h"
#include "schedule.h"
#ifndef MONSTEREVENT_H
#include "monsterevent.h"
#endif
// C functions for external declarations that call the appropriate C++ methods
#ifdef _WIN32
#define EXPORT _declspec( dllexport )
#else
#define EXPORT /* */
#endif
extern "C" EXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
extern "C" EXPORT int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
extern int DispatchSpawn( edict_t *pent );
extern void DispatchKeyValue( edict_t *pentKeyvalue, KeyValueData *pkvd );
extern void DispatchTouch( edict_t *pentTouched, edict_t *pentOther );
extern void DispatchUse( edict_t *pentUsed, edict_t *pentOther );
extern void DispatchThink( edict_t *pent );
extern void DispatchBlocked( edict_t *pentBlocked, edict_t *pentOther );
extern void DispatchSave( edict_t *pent, SAVERESTOREDATA *pSaveData );
extern int DispatchRestore( edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity );
extern void DispatchObjectCollsionBox( edict_t *pent );
extern void SaveWriteFields( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
extern void SaveReadFields( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
extern void SaveGlobalState( SAVERESTOREDATA *pSaveData );
extern void RestoreGlobalState( SAVERESTOREDATA *pSaveData );
extern void ResetGlobalState( void );
typedef enum { USE_OFF = 0, USE_ON = 1, USE_SET = 2, USE_TOGGLE = 3 } USE_TYPE;
extern void FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
typedef void (CBaseEntity::*BASEPTR)(void);
typedef void (CBaseEntity::*ENTITYFUNCPTR)(CBaseEntity *pOther );
typedef void (CBaseEntity::*USEPTR)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
// For CLASSIFY
#define CLASS_NONE 0
#define CLASS_MACHINE 1
#define CLASS_PLAYER 2
#define CLASS_HUMAN_PASSIVE 3
#define CLASS_HUMAN_MILITARY 4
#define CLASS_ALIEN_MILITARY 5
#define CLASS_ALIEN_PASSIVE 6
#define CLASS_ALIEN_MONSTER 7
#define CLASS_ALIEN_PREY 8
#define CLASS_ALIEN_PREDATOR 9
#define CLASS_INSECT 10
#define CLASS_PLAYER_ALLY 11
#define CLASS_PLAYER_BIOWEAPON 12 // hornets and snarks.launched by players
#define CLASS_ALIEN_BIOWEAPON 13 // hornets and snarks.launched by the alien menace
#define CLASS_BARNACLE 99 // special because no one pays attention to it, and it eats a wide cross-section of creatures.
class CBaseEntity;
class CBaseMonster;
class CBasePlayerItem;
class CSquadMonster;
#define SF_NORESPAWN ( 1 << 30 )// !!!set this bit on guns and stuff that should never respawn.
//
// EHANDLE. Safe way to point to CBaseEntities who may die between frames
//
class EHANDLE
{
private:
edict_t *m_pent;
int m_serialnumber;
public:
edict_t *Get( void );
edict_t *Set( edict_t *pent );
operator int ();
operator CBaseEntity *();
CBaseEntity * operator = (CBaseEntity *pEntity);
CBaseEntity * operator ->();
};
//
// Base Entity. All entity types derive from this
//
class CBaseEntity
{
public:
// Constructor. Set engine to use C/C++ callback functions
// pointers to engine data
entvars_t *pev; // Don't need to save/restore this pointer, the engine resets it
// path corners
CBaseEntity *m_pGoalEnt;// path corner we are heading towards
CBaseEntity *m_pLink;// used for temporary link-list operations.
// initialization functions
virtual void Spawn( void ) { return; }
virtual void Precache( void ) { return; }
virtual void KeyValue( KeyValueData* pkvd) { pkvd->fHandled = FALSE; }
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
virtual int ObjectCaps( void ) { return FCAP_ACROSS_TRANSITION; }
virtual void Activate( void ) {}
// Setup the object->object collision box (pev->mins / pev->maxs is the object->world collision box)
virtual void SetObjectCollisionBox( void );
// Classify - returns the type of group (i.e, "houndeye", or "human military" so that monsters with different classnames
// still realize that they are teammates. (overridden for monsters that form groups)
virtual int Classify ( void ) { return CLASS_NONE; };
virtual void DeathNotice ( entvars_t *pevChild ) {}// monster maker children use this to tell the monster maker that they have died.
static TYPEDESCRIPTION m_SaveData[];
virtual void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
virtual int TakeHealth( float flHealth, int bitsDamageType );
virtual void Killed( entvars_t *pevAttacker, int iGib );
virtual int BloodColor( void ) { return DONT_BLEED; }
virtual void TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType );
virtual BOOL IsTriggered( CBaseEntity *pActivator ) {return TRUE;}
virtual CBaseMonster *MyMonsterPointer( void ) { return NULL;}
virtual CSquadMonster *MySquadMonsterPointer( void ) { return NULL;}
virtual int GetToggleState( void ) { return TS_AT_TOP; }
virtual void AddPoints( int score, BOOL bAllowNegativeScore ) {}
virtual void AddPointsToTeam( int score, BOOL bAllowNegativeScore ) {}
virtual BOOL AddPlayerItem( CBasePlayerItem *pItem ) { return 0; }
virtual BOOL RemovePlayerItem( CBasePlayerItem *pItem ) { return 0; }
virtual int GiveAmmo( int iAmount, char *szName, int iMax ) { return -1; };
virtual float GetDelay( void ) { return 0; }
virtual int IsMoving( void ) { return pev->velocity != g_vecZero; }
virtual void OverrideReset( void ) {}
virtual int DamageDecal( int bitsDamageType );
// This is ONLY used by the node graph to test movement through a door
virtual void SetToggleState( int state ) {}
virtual void StartSneaking( void ) {}
virtual void StopSneaking( void ) {}
virtual BOOL OnControls( entvars_t *onpev ) { return FALSE; }
virtual BOOL IsSneaking( void ) { return FALSE; }
virtual BOOL IsAlive( void ) { return (pev->deadflag == DEAD_NO) && pev->health > 0; }
virtual BOOL IsBSPModel( void ) { return pev->solid == SOLID_BSP || pev->movetype == MOVETYPE_PUSHSTEP; }
virtual BOOL ReflectGauss( void ) { return ( IsBSPModel() && !pev->takedamage ); }
virtual BOOL HasTarget( string_t targetname ) { return FStrEq(STRING(targetname), STRING(pev->targetname) ); }
virtual BOOL IsInWorld( void );
virtual BOOL IsPlayer( void ) { return FALSE; }
virtual BOOL IsNetClient( void ) { return FALSE; }
virtual const char *TeamID( void ) { return ""; }
// virtual void SetActivator( CBaseEntity *pActivator ) {}
virtual CBaseEntity *GetNextTarget( void );
// fundamental callbacks
void (CBaseEntity ::*m_pfnThink)(void);
void (CBaseEntity ::*m_pfnTouch)( CBaseEntity *pOther );
void (CBaseEntity ::*m_pfnUse)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void (CBaseEntity ::*m_pfnBlocked)( CBaseEntity *pOther );
virtual void Think( void ) { if (m_pfnThink) (this->*m_pfnThink)(); };
virtual void Touch( CBaseEntity *pOther ) { if (m_pfnTouch) (this->*m_pfnTouch)( pOther ); };
virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if (m_pfnUse)
(this->*m_pfnUse)( pActivator, pCaller, useType, value );
}
virtual void Blocked( CBaseEntity *pOther ) { if (m_pfnBlocked) (this->*m_pfnBlocked)( pOther ); };
// allow engine to allocate instance data
void *operator new( size_t stAllocateBlock, entvars_t *newpev )
{
return (void *)ALLOC_PRIVATE(ENT(newpev), stAllocateBlock);
};
// don't use this.
#if defined(_MSC_VER) && _MSC_VER >= 1200 // only build this code if MSVC++ 6.0 or higher
void operator delete(void *pMem, entvars_t *pev)
{
pev->flags |= FL_KILLME;
};
#endif
void UpdateOnRemove( void );
// common member functions
void EXPORT SUB_Remove( void );
void EXPORT SUB_DoNothing( void );
void EXPORT SUB_StartFadeOut ( void );
void EXPORT SUB_FadeOut ( void );
void EXPORT SUB_CallUseToggle( void ) { this->Use( this, this, USE_TOGGLE, 0 ); }
int ShouldToggle( USE_TYPE useType, BOOL currentState );
void FireBullets( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq = 4, int iDamage = 0, entvars_t *pevAttacker = NULL );
virtual CBaseEntity *Respawn( void ) { return NULL; }
void SUB_UseTargets( CBaseEntity *pActivator, USE_TYPE useType, float value );
// Do the bounding boxes of these two intersect?
int Intersects( CBaseEntity *pOther );
void MakeDormant( void );
int IsDormant( void );
BOOL IsLockedByMaster( void ) { return FALSE; }
static CBaseEntity *Instance( edict_t *pent )
{
if ( !pent )
pent = ENT(0);
CBaseEntity *pEnt = (CBaseEntity *)GET_PRIVATE(pent);
return pEnt;
}
static CBaseEntity *Instance( entvars_t *instpev ) { return Instance( ENT( instpev ) ); }
static CBaseEntity *Instance( int inst_eoffset) { return Instance( ENT( inst_eoffset) ); }
CBaseMonster *GetMonsterPointer( entvars_t *pevMonster )
{
CBaseEntity *pEntity = Instance( pevMonster );
if ( pEntity )
return pEntity->MyMonsterPointer();
return NULL;
}
CBaseMonster *GetMonsterPointer( edict_t *pentMonster )
{
CBaseEntity *pEntity = Instance( pentMonster );
if ( pEntity )
return pEntity->MyMonsterPointer();
return NULL;
}
// Ugly code to lookup all functions to make sure they are exported when set.
#ifdef _DEBUG
void FunctionCheck( void *pFunction, char *name )
{
#ifdef _WIN32
if (pFunction && !NAME_FOR_FUNCTION((unsigned long)(pFunction)) )
ALERT( at_error, "No EXPORT: %s:%s (%08lx)\n", STRING(pev->classname), name, (unsigned long)pFunction );
#endif // _WIN32
}
BASEPTR ThinkSet( BASEPTR func, char *name )
{
m_pfnThink = func;
FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnThink)))), name );
return func;
}
ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, char *name )
{
m_pfnTouch = func;
FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnTouch)))), name );
return func;
}
USEPTR UseSet( USEPTR func, char *name )
{
m_pfnUse = func;
FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnUse)))), name );
return func;
}
ENTITYFUNCPTR BlockedSet( ENTITYFUNCPTR func, char *name )
{
m_pfnBlocked = func;
FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnBlocked)))), name );
return func;
}
#endif
// virtual functions used by a few classes
// used by monsters that are created by the MonsterMaker
virtual void UpdateOwner( void ) { return; };
//
static CBaseEntity *Create( char *szName, const Vector &vecOrigin, const Vector &vecAngles, edict_t *pentOwner = NULL );
virtual BOOL FBecomeProne( void ) {return FALSE;};
edict_t *edict() { return ENT( pev ); };
EOFFSET eoffset( ) { return OFFSET( pev ); };
int entindex( ) { return ENTINDEX( edict() ); };
virtual Vector Center( ) { return (pev->absmax + pev->absmin) * 0.5; }; // center point of entity
virtual Vector EyePosition( ) { return pev->origin + pev->view_ofs; }; // position of eyes
virtual Vector EarPosition( ) { return pev->origin + pev->view_ofs; }; // position of ears
virtual Vector BodyTarget( const Vector &posSrc ) { return Center( ); }; // position to shoot at
virtual int Illumination( ) { return GETENTITYILLUM( ENT( pev ) ); };
virtual BOOL FVisible ( CBaseEntity *pEntity );
virtual BOOL FVisible ( const Vector &vecOrigin );
// QUAKECLASSIC
BOOL m_bAxHitMe;
void Spawn_Telefog( Vector vecOrg, CBaseEntity *pOther );
Vector m_vecTeleAngles;
};
// Ugly technique to override base member functions
// Normally it's illegal to cast a pointer to a member function of a derived class to a pointer to a
// member function of a base class. static_cast is a sleezy way around that problem.
#ifdef _DEBUG
#define SetThink( a ) ThinkSet( static_cast <void (CBaseEntity::*)(void)> (a), #a )
#define SetTouch( a ) TouchSet( static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a), #a )
#define SetUse( a ) UseSet( static_cast <void (CBaseEntity::*)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )> (a), #a )
#define SetBlocked( a ) BlockedSet( static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a), #a )
#else
#define SetThink( a ) m_pfnThink = static_cast <void (CBaseEntity::*)(void)> (a)
#define SetTouch( a ) m_pfnTouch = static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a)
#define SetUse( a ) m_pfnUse = static_cast <void (CBaseEntity::*)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )> (a)
#define SetBlocked( a ) m_pfnBlocked = static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a)
#endif
class CPointEntity : public CBaseEntity
{
public:
void Spawn( void );
virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
private:
};
typedef struct locksounds // sounds that doors and buttons make when locked/unlocked
{
string_t sLockedSound; // sound a door makes when it's locked
string_t sLockedSentence; // sentence group played when door is locked
string_t sUnlockedSound; // sound a door makes when it's unlocked
string_t sUnlockedSentence; // sentence group played when door is unlocked
int iLockedSentence; // which sentence in sentence group to play next
int iUnlockedSentence; // which sentence in sentence group to play next
float flwaitSound; // time delay between playing consecutive 'locked/unlocked' sounds
float flwaitSentence; // time delay between playing consecutive sentences
BYTE bEOFLocked; // true if hit end of list of locked sentences
BYTE bEOFUnlocked; // true if hit end of list of unlocked sentences
} locksound_t;
void PlayLockSounds(entvars_t *pev, locksound_t *pls, int flocked, int fbutton);
//
// MultiSouce
//
#define MAX_MULTI_TARGETS 16 // maximum number of targets a single multi_manager entity may be assigned.
#define MS_MAX_TARGETS 32
class CMultiSource : public CPointEntity
{
public:
void Spawn( );
void KeyValue( KeyValueData *pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
int ObjectCaps( void ) { return (CPointEntity::ObjectCaps() | FCAP_MASTER); }
BOOL IsTriggered( CBaseEntity *pActivator );
void EXPORT Register( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
EHANDLE m_rgEntities[MS_MAX_TARGETS];
int m_rgTriggered[MS_MAX_TARGETS];
int m_iTotal;
string_t m_globalstate;
};
//
// generic Delay entity.
//
class CBaseDelay : public CBaseEntity
{
public:
float m_flDelay;
int m_iszKillTarget;
virtual void KeyValue( KeyValueData* pkvd);
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
// common member functions
void SUB_UseTargets( CBaseEntity *pActivator, USE_TYPE useType, float value );
void EXPORT DelayThink( void );
};
class CBaseAnimating : public CBaseDelay
{
public:
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
// Basic Monster Animation functions
float StudioFrameAdvance( float flInterval = 0.0 ); // accumulate animation frame time from last time called until now
int GetSequenceFlags( void );
int LookupActivity ( int activity );
int LookupActivityHeaviest ( int activity );
int LookupSequence ( const char *label );
void ResetSequenceInfo ( );
void DispatchAnimEvents ( float flFutureInterval = 0.1 ); // Handle events that have happend since last time called up until X seconds into the future
virtual void HandleAnimEvent( MonsterEvent_t *pEvent ) { return; };
float SetBoneController ( int iController, float flValue );
void InitBoneControllers ( void );
float SetBlending ( int iBlender, float flValue );
void GetBonePosition ( int iBone, Vector &origin, Vector &angles );
void GetAutomovement( Vector &origin, Vector &angles, float flInterval = 0.1 );
int FindTransition( int iEndingSequence, int iGoalSequence, int *piDir );
void GetAttachment ( int iAttachment, Vector &origin, Vector &angles );
void SetBodygroup( int iGroup, int iValue );
int GetBodygroup( int iGroup );
int ExtractBbox( int sequence, float *mins, float *maxs );
void SetSequenceBox( void );
// animation needs
float m_flFrameRate; // computed FPS for current sequence
float m_flGroundSpeed; // computed linear movement rate for current sequence
float m_flLastEventCheck; // last time the event list was checked
BOOL m_fSequenceFinished;// flag set when StudioAdvanceFrame moves across a frame boundry
BOOL m_fSequenceLoops; // true if the sequence loops
};
//
// generic Toggle entity.
//
#define SF_ITEM_USE_ONLY 256 // ITEM_USE_ONLY = BUTTON_USE_ONLY = DOOR_USE_ONLY!!!
class CBaseToggle : public CBaseAnimating
{
public:
void KeyValue( KeyValueData *pkvd );
TOGGLE_STATE m_toggle_state;
float m_flActivateFinished;//like attack_finished, but for doors
float m_flMoveDistance;// how far a door should slide or rotate
float m_flWait;
float m_flLip;
float m_flTWidth;// for plats
float m_flTLength;// for plats
Vector m_vecPosition1;
Vector m_vecPosition2;
Vector m_vecAngle1;
Vector m_vecAngle2;
int m_cTriggersLeft; // trigger_counter only, # of activations remaining
float m_flHeight;
EHANDLE m_hActivator;
void (CBaseToggle::*m_pfnCallWhenMoveDone)(void);
Vector m_vecFinalDest;
Vector m_vecFinalAngle;
int m_bitsDamageInflict; // DMG_ damage type that the door or tigger does
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
virtual int GetToggleState( void ) { return m_toggle_state; }
virtual float GetDelay( void ) { return m_flWait; }
// common member functions
void LinearMove( Vector vecDest, float flSpeed );
void EXPORT LinearMoveDone( void );
void AngularMove( Vector vecDestAngle, float flSpeed );
void EXPORT AngularMoveDone( void );
BOOL IsLockedByMaster( void );
static float AxisValue( int flags, const Vector &angles );
static void AxisDir( entvars_t *pev );
static float AxisDelta( int flags, const Vector &angle1, const Vector &angle2 );
string_t m_sMaster; // If this button has a master switch, this is the targetname.
// A master switch must be of the multisource type. If all
// of the switches in the multisource have been triggered, then
// the button will be allowed to operate. Otherwise, it will be
// deactivated.
};
#define SetMoveDone( a ) m_pfnCallWhenMoveDone = static_cast <void (CBaseToggle::*)(void)> (a)
// people gib if their health is <= this at the time of death
#define GIB_HEALTH_VALUE -30
#define ROUTE_SIZE 8 // how many waypoints a monster can store at one time
#define MAX_OLD_ENEMIES 4 // how many old enemies to remember
#define bits_CAP_DUCK ( 1 << 0 )// crouch
#define bits_CAP_JUMP ( 1 << 1 )// jump/leap
#define bits_CAP_STRAFE ( 1 << 2 )// strafe ( walk/run sideways)
#define bits_CAP_SQUAD ( 1 << 3 )// can form squads
#define bits_CAP_SWIM ( 1 << 4 )// proficiently navigate in water
#define bits_CAP_CLIMB ( 1 << 5 )// climb ladders/ropes
#define bits_CAP_USE ( 1 << 6 )// open doors/push buttons/pull levers
#define bits_CAP_HEAR ( 1 << 7 )// can hear forced sounds
#define bits_CAP_AUTO_DOORS ( 1 << 8 )// can trigger auto doors
#define bits_CAP_OPEN_DOORS ( 1 << 9 )// can open manual doors
#define bits_CAP_TURN_HEAD ( 1 << 10)// can turn head, always bone controller 0
#define bits_CAP_RANGE_ATTACK1 ( 1 << 11)// can do a range attack 1
#define bits_CAP_RANGE_ATTACK2 ( 1 << 12)// can do a range attack 2
#define bits_CAP_MELEE_ATTACK1 ( 1 << 13)// can do a melee attack 1
#define bits_CAP_MELEE_ATTACK2 ( 1 << 14)// can do a melee attack 2
#define bits_CAP_FLY ( 1 << 15)// can fly, move all around
#define bits_CAP_DOORS_GROUP (bits_CAP_USE | bits_CAP_AUTO_DOORS | bits_CAP_OPEN_DOORS)
// used by suit voice to indicate damage sustained and repaired type to player
// instant damage
#define DMG_GENERIC 0 // generic damage was done
#define DMG_CRUSH (1 << 0) // crushed by falling or moving object
#define DMG_BULLET (1 << 1) // shot
#define DMG_SLASH (1 << 2) // cut, clawed, stabbed
#define DMG_BURN (1 << 3) // heat burned
#define DMG_FREEZE (1 << 4) // frozen
#define DMG_FALL (1 << 5) // fell too far
#define DMG_BLAST (1 << 6) // explosive blast damage
#define DMG_CLUB (1 << 7) // crowbar, punch, headbutt
#define DMG_SHOCK (1 << 8) // electric shock
#define DMG_SONIC (1 << 9) // sound pulse shockwave
#define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam
#define DMG_NEVERGIB (1 << 12) // with this bit OR'd in, no damage type will be able to gib victims upon death
#define DMG_ALWAYSGIB (1 << 13) // with this bit OR'd in, any damage type can be made to gib victims upon death.
#define DMG_DROWN (1 << 14) // Drowning
// time-based damage
#define DMG_TIMEBASED (~(0x3fff)) // mask for time-based damage
#define DMG_PARALYZE (1 << 15) // slows affected creature down
#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad
#define DMG_POISON (1 << 17) // blood poisioning
#define DMG_RADIATION (1 << 18) // radiation exposure
#define DMG_DROWNRECOVER (1 << 19) // drowning recovery
#define DMG_ACID (1 << 20) // toxic chemicals or acid burns
#define DMG_SLOWBURN (1 << 21) // in an oven
#define DMG_SLOWFREEZE (1 << 22) // in a subzero freezer
#define DMG_MORTAR (1 << 23) // Hit by air raid (done to distinguish grenade from mortar)
#define DMG_IGNORE_MAXHEALTH (1<< 24) // Used by TakeHealth only. Ignores the player's max health when healing.
// these are the damage types that are allowed to gib corpses
#define DMG_GIB_CORPSE ( DMG_CRUSH | DMG_FALL | DMG_BLAST | DMG_SONIC | DMG_CLUB )
// these are the damage types that have client hud art
#define DMG_SHOWNHUD (DMG_POISON | DMG_ACID | DMG_FREEZE | DMG_SLOWFREEZE | DMG_DROWN | DMG_BURN | DMG_SLOWBURN | DMG_NERVEGAS | DMG_RADIATION | DMG_SHOCK)
// NOTE: tweak these values based on gameplay feedback:
#define PARALYZE_DURATION 2 // number of 2 second intervals to take damage
#define PARALYZE_DAMAGE 1.0 // damage to take each 2 second interval
#define NERVEGAS_DURATION 2
#define NERVEGAS_DAMAGE 5.0
#define POISON_DURATION 5
#define POISON_DAMAGE 2.0
#define RADIATION_DURATION 2
#define RADIATION_DAMAGE 1.0
#define ACID_DURATION 2
#define ACID_DAMAGE 5.0
#define SLOWBURN_DURATION 2
#define SLOWBURN_DAMAGE 1.0
#define SLOWFREEZE_DURATION 2
#define SLOWFREEZE_DAMAGE 1.0
#define itbd_Paralyze 0
#define itbd_NerveGas 1
#define itbd_Poison 2
#define itbd_Radiation 3
#define itbd_DrownRecover 4
#define itbd_Acid 5
#define itbd_SlowBurn 6
#define itbd_SlowFreeze 7
#define CDMG_TIMEBASED 8
// when calling KILLED(), a value that governs gib behavior is expected to be
// one of these three values
#define GIB_NORMAL 0// gib if entity was overkilled
#define GIB_NEVER 1// never gib, no matter how much death damage is done ( freezing, etc )
#define GIB_ALWAYS 2// always gib ( Houndeye Shock, Barnacle Bite )
class CBaseMonster;
class CCineMonster;
class CSound;
#include "basemonster.h"
char *ButtonSound( int sound ); // get string of button sound number
//
// Generic Button
//
class CBaseButton : public CBaseToggle
{
public:
void Spawn( void );
virtual void Precache( void );
void RotSpawn( void );
virtual void KeyValue( KeyValueData* pkvd);
void ButtonActivate( );
void SparkSoundCache( void );
void EXPORT ButtonShot( void );
void EXPORT ButtonTouch( CBaseEntity *pOther );
void EXPORT ButtonSpark ( void );
void EXPORT TriggerAndWait( void );
void EXPORT ButtonReturn( void );
void EXPORT ButtonBackHome( void );
void EXPORT ButtonUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
enum BUTTON_CODE { BUTTON_NOTHING, BUTTON_ACTIVATE, BUTTON_RETURN };
BUTTON_CODE ButtonResponseToTouch( void );
static TYPEDESCRIPTION m_SaveData[];
// Buttons that don't take damage can be IMPULSE used
virtual int ObjectCaps( void ) { return (CBaseToggle:: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | (pev->takedamage?0:FCAP_IMPULSE_USE); }
BOOL m_fStayPushed; // button stays pushed in until touched again?
BOOL m_fRotating; // a rotating button? default is a sliding button.
string_t m_strChangeTarget; // if this field is not null, this is an index into the engine string array.
// when this button is touched, it's target entity's TARGET field will be set
// to the button's ChangeTarget. This allows you to make a func_train switch paths, etc.
locksound_t m_ls; // door lock sounds
BYTE m_bLockedSound; // ordinals from entity selection
BYTE m_bLockedSentence;
BYTE m_bUnlockedSound;
BYTE m_bUnlockedSentence;
int m_sounds;
};
//
// Weapons
//
#define BAD_WEAPON 0x00007FFF
//
// Converts a entvars_t * to a class pointer
// It will allocate the class and entity if necessary
//
template <class T> T * GetClassPtr( T *a )
{
entvars_t *pev = (entvars_t *)a;
// allocate entity if necessary
if (pev == NULL)
pev = VARS(CREATE_ENTITY());
// get the private data
a = (T *)GET_PRIVATE(ENT(pev));
if (a == NULL)
{
// allocate private data
a = new(pev) T;
a->pev = pev;
}
return a;
}
/*
bit_PUSHBRUSH_DATA | bit_TOGGLE_DATA
bit_MONSTER_DATA
bit_DELAY_DATA
bit_TOGGLE_DATA | bit_DELAY_DATA | bit_MONSTER_DATA
bit_PLAYER_DATA | bit_MONSTER_DATA
bit_MONSTER_DATA | CYCLER_DATA
bit_LIGHT_DATA
path_corner_data
bit_MONSTER_DATA | wildcard_data
bit_MONSTER_DATA | bit_GROUP_DATA
boid_flock_data
boid_data
CYCLER_DATA
bit_ITEM_DATA
bit_ITEM_DATA | func_hud_data
bit_TOGGLE_DATA | bit_ITEM_DATA
EOFFSET
env_sound_data
env_sound_data
push_trigger_data
*/
#define TRACER_FREQ 4 // Tracers fire every 4 bullets
typedef struct _SelAmmo
{
BYTE Ammo1Type;
BYTE Ammo1;
BYTE Ammo2Type;
BYTE Ammo2;
} SelAmmo;
// this moved here from world.cpp, to allow classes to be derived from it
//=======================
// CWorld
//
// This spawns first when each level begins.
//=======================
class CWorld : public CBaseEntity
{
public:
void Spawn( void );
void Precache( void );
void KeyValue( KeyValueData *pkvd );
};
class CClientFog : public CBaseEntity
{
public:
void Spawn( void );
void KeyValue( KeyValueData *pkvd );
float m_iStartDist;
float m_iEndDist;
};
// QUAKECLASSIC
extern char *g_szDeathType;

46
hlsdk/dmc/dlls/cdll_dll.h Normal file
View File

@ -0,0 +1,46 @@
/***
*
* 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.
*
****/
//
// cdll_dll.h
// this file is included by both the game-dll and the client-dll,
#ifndef CDLL_DLL_H
#define CDLL_DLL_H
#define MAX_WEAPONS 257 // ???
#define MAX_WEAPON_SLOTS 9 // hud item selection slots
#define MAX_ITEM_TYPES 6 // hud item selection slots
#define MAX_ITEMS 5 // hard coded item types
#define HIDEHUD_WEAPONS ( 1<<0 )
#define HIDEHUD_FLASHLIGHT ( 1<<1 )
#define HIDEHUD_ALL ( 1<<2 )
#define HIDEHUD_HEALTH ( 1<<3 )
#define MAX_AMMO_TYPES 32 // ???
#define MAX_AMMO_SLOTS 32 // not really slots
#define HUD_PRINTNOTIFY 1
#define HUD_PRINTCONSOLE 2
#define HUD_PRINTTALK 3
#define HUD_PRINTCENTER 4
#define WEAPON_SUIT 31
#endif

1711
hlsdk/dmc/dlls/client.cpp Normal file

File diff suppressed because it is too large Load Diff

65
hlsdk/dmc/dlls/client.h Normal file
View File

@ -0,0 +1,65 @@
/***
*
* 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.
*
****/
#ifndef CLIENT_H
#define CLIENT_H
extern void respawn( entvars_t* pev, BOOL fCopyCorpse );
extern BOOL ClientConnect( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] );
extern void ClientDisconnect( edict_t *pEntity );
extern void ClientKill( edict_t *pEntity );
extern void ClientPutInServer( edict_t *pEntity );
extern void ClientCommand( edict_t *pEntity );
extern void ClientUserInfoChanged( edict_t *pEntity, char *infobuffer );
extern void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax );
extern void ServerDeactivate( void );
extern void StartFrame( void );
extern void PlayerPostThink( edict_t *pEntity );
extern void PlayerPreThink( edict_t *pEntity );
extern void ParmsNewLevel( void );
extern void ParmsChangeLevel( void );
extern void ClientPrecache( void );
extern const char *GetGameDescription( void );
extern void PlayerCustomization( edict_t *pEntity, customization_t *pCust );
extern void SpectatorConnect ( edict_t *pEntity );
extern void SpectatorDisconnect ( edict_t *pEntity );
extern void SpectatorThink ( edict_t *pEntity );
extern void Sys_Error( const char *error_string );
extern void SetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas );
extern void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd );
extern int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet );
extern void CreateBaseline( int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs );
extern void RegisterEncoders( void );
extern int GetWeaponData( struct edict_s *player, struct weapon_data_s *info );
extern void CmdStart( const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed );
extern void CmdEnd ( const edict_t *player );
extern int ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
extern int GetHullBounds( int hullnumber, float *mins, float *maxs );
extern void CreateInstancedBaselines ( void );
extern int InconsistentFile( const edict_t *player, const char *filename, char *disconnect_message );
extern int AllowLagCompensation( void );
#endif // CLIENT_H

1099
hlsdk/dmc/dlls/combat.cpp Normal file

File diff suppressed because it is too large Load Diff

75
hlsdk/dmc/dlls/decals.h Normal file
View File

@ -0,0 +1,75 @@
/***
*
* 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.
*
****/
#ifndef DECALS_H
#define DECALS_H
//
// Dynamic Decals
//
enum decal_e
{
DECAL_GUNSHOT1 = 0,
DECAL_GUNSHOT2,
DECAL_GUNSHOT3,
DECAL_GUNSHOT4,
DECAL_GUNSHOT5,
DECAL_LAMBDA1,
DECAL_LAMBDA2,
DECAL_LAMBDA3,
DECAL_LAMBDA4,
DECAL_LAMBDA5,
DECAL_LAMBDA6,
DECAL_SCORCH1,
DECAL_SCORCH2,
DECAL_BLOOD1,
DECAL_BLOOD2,
DECAL_BLOOD3,
DECAL_BLOOD4,
DECAL_BLOOD5,
DECAL_BLOOD6,
DECAL_YBLOOD1,
DECAL_YBLOOD2,
DECAL_YBLOOD3,
DECAL_YBLOOD4,
DECAL_YBLOOD5,
DECAL_YBLOOD6,
DECAL_GLASSBREAK1,
DECAL_GLASSBREAK2,
DECAL_GLASSBREAK3,
DECAL_BIGSHOT1,
DECAL_BIGSHOT2,
DECAL_BIGSHOT3,
DECAL_BIGSHOT4,
DECAL_BIGSHOT5,
DECAL_SPIT1,
DECAL_SPIT2,
DECAL_BPROOF1, // Bulletproof glass decal
DECAL_GARGSTOMP1, // Gargantua stomp crack
DECAL_SMALLSCORCH1, // Small scorch mark
DECAL_SMALLSCORCH2, // Small scorch mark
DECAL_SMALLSCORCH3, // Small scorch mark
DECAL_MOMMABIRTH, // Big momma birth splatter
DECAL_MOMMASPLAT,
};
typedef struct
{
char *name;
int index;
} DLL_DECALLIST;
extern DLL_DECALLIST gDecals[];
#endif // DECALS_H

View File

@ -0,0 +1,240 @@
/***
*
* 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.
*
* 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.
*
****/
//=========================================================
// Default behaviors.
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "schedule.h"
#include "defaultai.h"
#include "nodes.h"
#include "scripted.h"
Schedule_t *CBaseMonster::m_scheduleList[] =
{
};
Schedule_t *CBaseMonster::ScheduleFromName( const char *pName )
{
return ScheduleInList( pName, m_scheduleList, ARRAYSIZE(m_scheduleList) );
}
Schedule_t *CBaseMonster :: ScheduleInList( const char *pName, Schedule_t **pList, int listCount )
{
int i;
if ( !pName )
{
ALERT( at_console, "%s set to unnamed schedule!\n", STRING(pev->classname) );
return NULL;
}
for ( i = 0; i < listCount; i++ )
{
if ( !pList[i]->pName )
{
ALERT( at_console, "Unnamed schedule!\n" );
continue;
}
if ( stricmp( pName, pList[i]->pName ) == 0 )
return pList[i];
}
return NULL;
}
//=========================================================
// GetScheduleOfType - returns a pointer to one of the
// monster's available schedules of the indicated type.
//=========================================================
Schedule_t* CBaseMonster :: GetScheduleOfType ( int Type )
{
// ALERT ( at_console, "Sched Type:%d\n", Type );
switch ( Type )
{
// This is the schedule for scripted sequences AND scripted AI
case SCHED_AISCRIPT:
{
ASSERT( m_pCine != NULL );
if ( !m_pCine )
{
ALERT( at_aiconsole, "Script failed for %s\n", STRING(pev->classname) );
CineCleanup();
return GetScheduleOfType( SCHED_IDLE_STAND );
}
// else
// ALERT( at_aiconsole, "Starting script %s for %s\n", STRING( m_pCine->m_iszPlay ), STRING(pev->classname) );
switch ( m_pCine->m_fMoveTo )
{
case 0:
case 4:
return slWaitScript;
case 1:
return slWalkToScript;
case 2:
return slRunToScript;
case 5:
return slFaceScript;
}
break;
}
case SCHED_IDLE_STAND:
{
if ( RANDOM_LONG(0,14) == 0 && FCanActiveIdle() )
{
return &slActiveIdle[ 0 ];
}
return &slIdleStand[ 0 ];
}
case SCHED_IDLE_WALK:
{
return &slIdleWalk[ 0 ];
}
case SCHED_WAIT_TRIGGER:
{
return &slIdleTrigger[ 0 ];
}
case SCHED_WAKE_ANGRY:
{
return &slWakeAngry[ 0 ];
}
case SCHED_ALERT_FACE:
{
return &slAlertFace[ 0 ];
}
case SCHED_ALERT_STAND:
{
return &slAlertStand[ 0 ];
}
case SCHED_COMBAT_STAND:
{
return &slCombatStand[ 0 ];
}
case SCHED_COMBAT_FACE:
{
return &slCombatFace[ 0 ];
}
case SCHED_CHASE_ENEMY:
{
return &slChaseEnemy[ 0 ];
}
case SCHED_CHASE_ENEMY_FAILED:
{
return &slFail[ 0 ];
}
case SCHED_SMALL_FLINCH:
{
return &slSmallFlinch[ 0 ];
}
case SCHED_ALERT_SMALL_FLINCH:
{
return &slAlertSmallFlinch[ 0 ];
}
case SCHED_RELOAD:
{
return &slReload[ 0 ];
}
case SCHED_ARM_WEAPON:
{
return &slArmWeapon[ 0 ];
}
case SCHED_STANDOFF:
{
return &slStandoff[ 0 ];
}
case SCHED_RANGE_ATTACK1:
{
return &slRangeAttack1[ 0 ];
}
case SCHED_RANGE_ATTACK2:
{
return &slRangeAttack2[ 0 ];
}
case SCHED_MELEE_ATTACK1:
{
return &slPrimaryMeleeAttack[ 0 ];
}
case SCHED_MELEE_ATTACK2:
{
return &slSecondaryMeleeAttack[ 0 ];
}
case SCHED_SPECIAL_ATTACK1:
{
return &slSpecialAttack1[ 0 ];
}
case SCHED_SPECIAL_ATTACK2:
{
return &slSpecialAttack2[ 0 ];
}
case SCHED_TAKE_COVER_FROM_BEST_SOUND:
{
return &slTakeCoverFromBestSound[ 0 ];
}
case SCHED_TAKE_COVER_FROM_ENEMY:
{
return &slTakeCoverFromEnemy[ 0 ];
}
case SCHED_COWER:
{
return &slCower[ 0 ];
}
case SCHED_AMBUSH:
{
return &slAmbush[ 0 ];
}
case SCHED_BARNACLE_VICTIM_GRAB:
{
return &slBarnacleVictimGrab[ 0 ];
}
case SCHED_BARNACLE_VICTIM_CHOMP:
{
return &slBarnacleVictimChomp[ 0 ];
}
case SCHED_INVESTIGATE_SOUND:
{
return &slInvestigateSound[ 0 ];
}
case SCHED_DIE:
{
return &slDie[ 0 ];
}
case SCHED_TAKE_COVER_FROM_ORIGIN:
{
return &slTakeCoverFromOrigin[ 0 ];
}
case SCHED_VICTORY_DANCE:
{
return &slVictoryDance[ 0 ];
}
case SCHED_FAIL:
{
return slFail;
}
default:
{
ALERT ( at_console, "GetScheduleOfType()\nNo CASE for Schedule Type %d!\n", Type );
return &slIdleStand[ 0 ];
break;
}
}
return NULL;
}

View File

@ -0,0 +1,98 @@
/***
*
* 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.
*
* 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.
*
****/
#ifndef DEFAULTAI_H
#define DEFAULTAI_H
//=========================================================
// Failed
//=========================================================
extern Schedule_t slFail[];
//=========================================================
// Idle Schedules
//=========================================================
extern Schedule_t slIdleStand[];
extern Schedule_t slIdleTrigger[];
extern Schedule_t slIdleWalk[];
//=========================================================
// Wake Schedules
//=========================================================
extern Schedule_t slWakeAngry[];
//=========================================================
// AlertTurn Schedules
//=========================================================
extern Schedule_t slAlertFace[];
//=========================================================
// AlertIdle Schedules
//=========================================================
extern Schedule_t slAlertStand[];
//=========================================================
// CombatIdle Schedule
//=========================================================
extern Schedule_t slCombatStand[];
//=========================================================
// CombatFace Schedule
//=========================================================
extern Schedule_t slCombatFace[];
//=========================================================
// reload schedule
//=========================================================
extern Schedule_t slReload[];
//=========================================================
// Attack Schedules
//=========================================================
extern Schedule_t slRangeAttack1[];
extern Schedule_t slRangeAttack2[];
extern Schedule_t slTakeCoverFromBestSound[];
// primary melee attack
extern Schedule_t slMeleeAttack[];
// Chase enemy schedule
extern Schedule_t slChaseEnemy[];
//=========================================================
// small flinch, used when a relatively minor bit of damage
// is inflicted.
//=========================================================
extern Schedule_t slSmallFlinch[];
//=========================================================
// Die!
//=========================================================
extern Schedule_t slDie[];
//=========================================================
// Universal Error Schedule
//=========================================================
extern Schedule_t slError[];
//=========================================================
// Scripted sequences
//=========================================================
extern Schedule_t slWalkToScript[];
extern Schedule_t slRunToScript[];
extern Schedule_t slWaitScript[];
#endif // DEFAULTAI_H

5
hlsdk/dmc/dlls/dmc.def Normal file
View File

@ -0,0 +1,5 @@
LIBRARY dmc
EXPORTS
GiveFnptrsToDll @1
SECTIONS
.data READ WRITE

15
hlsdk/dmc/dlls/dmcgl.def Normal file
View File

@ -0,0 +1,15 @@
LIBRARY dmcgl
EXPORTS
GiveFnptrsToDll @1
GetEntityInterfaces @2
SetChangeParms @3
SetNewParms @4
ClientKill @5
PutClientInServer @6
PlayerPreThink @7
PlayerPostThink @8
ClientConnect @9
ClientDisconnect @10
StartFrame @11
SECTIONS
.data READ WRITE

1093
hlsdk/dmc/dlls/doors.cpp Normal file

File diff suppressed because it is too large Load Diff

33
hlsdk/dmc/dlls/doors.h Normal file
View File

@ -0,0 +1,33 @@
/***
*
* 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.
*
****/
#ifndef DOORS_H
#define DOORS_H
// doors
#define SF_DOOR_ROTATE_Y 0
#define SF_DOOR_START_OPEN 1
#define SF_DOOR_ROTATE_BACKWARDS 2
#define SF_DOOR_PASSABLE 8
#define SF_DOOR_ONEWAY 16
#define SF_DOOR_NO_AUTO_RETURN 32
#define SF_DOOR_ROTATE_Z 64
#define SF_DOOR_ROTATE_X 128
#define SF_DOOR_USE_ONLY 256 // door must be opened by player's use button.
#define SF_DOOR_NOMONSTERS 512 // Monster can't open
#define SF_DOOR_SILENT 0x80000000
#endif //DOORS_H

2268
hlsdk/dmc/dlls/effects.cpp Normal file

File diff suppressed because it is too large Load Diff

209
hlsdk/dmc/dlls/effects.h Normal file
View File

@ -0,0 +1,209 @@
/***
*
* 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.
*
****/
#ifndef EFFECTS_H
#define EFFECTS_H
#define SF_BEAM_STARTON 0x0001
#define SF_BEAM_TOGGLE 0x0002
#define SF_BEAM_RANDOM 0x0004
#define SF_BEAM_RING 0x0008
#define SF_BEAM_SPARKSTART 0x0010
#define SF_BEAM_SPARKEND 0x0020
#define SF_BEAM_DECALS 0x0040
#define SF_BEAM_SHADEIN 0x0080
#define SF_BEAM_SHADEOUT 0x0100
#define SF_BEAM_TEMPORARY 0x8000
#define SF_SPRITE_STARTON 0x0001
#define SF_SPRITE_ONCE 0x0002
#define SF_SPRITE_TEMPORARY 0x8000
class CSprite : public CPointEntity
{
public:
void Spawn( void );
void Precache( void );
int ObjectCaps( void )
{
int flags = 0;
if ( pev->spawnflags & SF_SPRITE_TEMPORARY )
flags = FCAP_DONT_SAVE;
return (CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags;
}
void EXPORT AnimateThink( void );
void EXPORT ExpandThink( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void Animate( float frames );
void Expand( float scaleSpeed, float fadeSpeed );
void SpriteInit( const char *pSpriteName, const Vector &origin );
inline void SetAttachment( edict_t *pEntity, int attachment )
{
if ( pEntity )
{
pev->skin = ENTINDEX(pEntity);
pev->body = attachment;
pev->aiment = pEntity;
pev->movetype = MOVETYPE_FOLLOW;
}
}
void TurnOff( void );
void TurnOn( void );
inline float Frames( void ) { return m_maxFrame; }
inline void SetTransparency( int rendermode, int r, int g, int b, int a, int fx )
{
pev->rendermode = rendermode;
pev->rendercolor.x = r;
pev->rendercolor.y = g;
pev->rendercolor.z = b;
pev->renderamt = a;
pev->renderfx = fx;
}
inline void SetTexture( int spriteIndex ) { pev->modelindex = spriteIndex; }
inline void SetScale( float scale ) { pev->scale = scale; }
inline void SetColor( int r, int g, int b ) { pev->rendercolor.x = r; pev->rendercolor.y = g; pev->rendercolor.z = b; }
inline void SetBrightness( int brightness ) { pev->renderamt = brightness; }
inline void AnimateAndDie( float framerate )
{
SetThink(&CSprite::AnimateUntilDead);
pev->framerate = framerate;
pev->dmgtime = gpGlobals->time + (m_maxFrame / framerate);
pev->nextthink = gpGlobals->time;
}
void EXPORT AnimateUntilDead( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
static CSprite *SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate );
private:
float m_lastTime;
float m_maxFrame;
};
class CBeam : public CBaseEntity
{
public:
void Spawn( void );
void Precache( void );
int ObjectCaps( void )
{
int flags = 0;
if ( pev->spawnflags & SF_BEAM_TEMPORARY )
flags = FCAP_DONT_SAVE;
return (CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags;
}
void EXPORT TriggerTouch( CBaseEntity *pOther );
// These functions are here to show the way beams are encoded as entities.
// Encoding beams as entities simplifies their management in the client/server architecture
inline void SetType( int type ) { pev->rendermode = (pev->rendermode & 0xF0) | (type&0x0F); }
inline void SetFlags( int flags ) { pev->rendermode = (pev->rendermode & 0x0F) | (flags&0xF0); }
inline void SetStartPos( const Vector& pos ) { pev->origin = pos; }
inline void SetEndPos( const Vector& pos ) { pev->angles = pos; }
void SetStartEntity( int entityIndex );
void SetEndEntity( int entityIndex );
inline void SetStartAttachment( int attachment ) { pev->sequence = (pev->sequence & 0x0FFF) | ((attachment&0xF)<<12); }
inline void SetEndAttachment( int attachment ) { pev->skin = (pev->skin & 0x0FFF) | ((attachment&0xF)<<12); }
inline void SetTexture( int spriteIndex ) { pev->modelindex = spriteIndex; }
inline void SetWidth( int width ) { pev->scale = width; }
inline void SetNoise( int amplitude ) { pev->body = amplitude; }
inline void SetColor( int r, int g, int b ) { pev->rendercolor.x = r; pev->rendercolor.y = g; pev->rendercolor.z = b; }
inline void SetBrightness( int brightness ) { pev->renderamt = brightness; }
inline void SetFrame( float frame ) { pev->frame = frame; }
inline void SetScrollRate( int speed ) { pev->animtime = speed; }
inline int GetType( void ) { return pev->rendermode & 0x0F; }
inline int GetFlags( void ) { return pev->rendermode & 0xF0; }
inline int GetStartEntity( void ) { return pev->sequence & 0xFFF; }
inline int GetEndEntity( void ) { return pev->skin & 0xFFF; }
const Vector &GetStartPos( void );
const Vector &GetEndPos( void );
Vector Center( void ) { return (GetStartPos() + GetEndPos()) * 0.5; }; // center point of beam
inline int GetTexture( void ) { return pev->modelindex; }
inline int GetWidth( void ) { return static_cast<int>(pev->scale); }
inline int GetNoise( void ) { return pev->body; }
// inline void GetColor( int r, int g, int b ) { pev->rendercolor.x = r; pev->rendercolor.y = g; pev->rendercolor.z = b; }
inline int GetBrightness( void ) { return static_cast<int>(pev->renderamt); }
inline int GetFrame( void ) { return static_cast<int>(pev->frame); }
inline int GetScrollRate( void ) { return static_cast<int>(pev->animtime); }
// Call after you change start/end positions
void RelinkBeam( void );
// void SetObjectCollisionBox( void );
void DoSparks( const Vector &start, const Vector &end );
CBaseEntity *RandomTargetname( const char *szName );
void BeamDamage( TraceResult *ptr );
// Init after BeamCreate()
void BeamInit( const char *pSpriteName, int width );
void PointsInit( const Vector &start, const Vector &end );
void PointEntInit( const Vector &start, int endIndex );
void EntsInit( int startIndex, int endIndex );
void HoseInit( const Vector &start, const Vector &direction );
static CBeam *BeamCreate( const char *pSpriteName, int width );
inline void LiveForTime( float time ) { SetThink(&CBaseEntity::SUB_Remove); pev->nextthink = gpGlobals->time + time; }
inline void BeamDamageInstant( TraceResult *ptr, float damage )
{
pev->dmg = damage;
pev->dmgtime = gpGlobals->time - 1;
BeamDamage(ptr);
}
};
#define SF_MESSAGE_ONCE 0x0001 // Fade in, not out
#define SF_MESSAGE_ALL 0x0002 // Send to all clients
class CLaser : public CBeam
{
public:
void Spawn( void );
void Precache( void );
void KeyValue( KeyValueData *pkvd );
void TurnOn( void );
void TurnOff( void );
int IsOn( void );
void FireAtPoint( TraceResult &point );
void EXPORT StrikeThink( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
CSprite *m_pSprite;
int m_iszSpriteName;
Vector m_firePosition;
};
#endif //EFFECTS_H

View File

@ -0,0 +1,165 @@
/***
*
* 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.
*
****/
#ifndef ENGINECALLBACK_H
#define ENGINECALLBACK_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "event_flags.h"
// Fix warning in MSVC8
#undef SERVER_EXECUTE
// Must be provided by user of this code
extern enginefuncs_t g_engfuncs;
// The actual engine callbacks
#define GETPLAYERUSERID (*g_engfuncs.pfnGetPlayerUserId)
#define PRECACHE_MODEL (*g_engfuncs.pfnPrecacheModel)
#define PRECACHE_SOUND (*g_engfuncs.pfnPrecacheSound)
#define PRECACHE_GENERIC (*g_engfuncs.pfnPrecacheGeneric)
#define SET_MODEL (*g_engfuncs.pfnSetModel)
#define MODEL_INDEX (*g_engfuncs.pfnModelIndex)
#define MODEL_FRAMES (*g_engfuncs.pfnModelFrames)
#define SET_SIZE (*g_engfuncs.pfnSetSize)
#define CHANGE_LEVEL (*g_engfuncs.pfnChangeLevel)
#define GET_SPAWN_PARMS (*g_engfuncs.pfnGetSpawnParms)
#define SAVE_SPAWN_PARMS (*g_engfuncs.pfnSaveSpawnParms)
#define VEC_TO_YAW (*g_engfuncs.pfnVecToYaw)
#define VEC_TO_ANGLES (*g_engfuncs.pfnVecToAngles)
#define MOVE_TO_ORIGIN (*g_engfuncs.pfnMoveToOrigin)
#define oldCHANGE_YAW (*g_engfuncs.pfnChangeYaw)
#define CHANGE_PITCH (*g_engfuncs.pfnChangePitch)
#define MAKE_VECTORS (*g_engfuncs.pfnMakeVectors)
#define CREATE_ENTITY (*g_engfuncs.pfnCreateEntity)
#define REMOVE_ENTITY (*g_engfuncs.pfnRemoveEntity)
#define CREATE_NAMED_ENTITY (*g_engfuncs.pfnCreateNamedEntity)
#define MAKE_STATIC (*g_engfuncs.pfnMakeStatic)
#define ENT_IS_ON_FLOOR (*g_engfuncs.pfnEntIsOnFloor)
#define DROP_TO_FLOOR (*g_engfuncs.pfnDropToFloor)
#define WALK_MOVE (*g_engfuncs.pfnWalkMove)
#define SET_ORIGIN (*g_engfuncs.pfnSetOrigin)
#define EMIT_SOUND_DYN2 (*g_engfuncs.pfnEmitSound)
#define BUILD_SOUND_MSG (*g_engfuncs.pfnBuildSoundMsg)
#define TRACE_LINE (*g_engfuncs.pfnTraceLine)
#define TRACE_TOSS (*g_engfuncs.pfnTraceToss)
#define TRACE_MONSTER_HULL (*g_engfuncs.pfnTraceMonsterHull)
#define TRACE_HULL (*g_engfuncs.pfnTraceHull)
#define GET_AIM_VECTOR (*g_engfuncs.pfnGetAimVector)
#define SERVER_COMMAND (*g_engfuncs.pfnServerCommand)
#define SERVER_EXECUTE (*g_engfuncs.pfnServerExecute)
#define CLIENT_COMMAND (*g_engfuncs.pfnClientCommand)
#define PARTICLE_EFFECT (*g_engfuncs.pfnParticleEffect)
#define LIGHT_STYLE (*g_engfuncs.pfnLightStyle)
#define DECAL_INDEX (*g_engfuncs.pfnDecalIndex)
#define POINT_CONTENTS (*g_engfuncs.pfnPointContents)
#define CRC32_INIT (*g_engfuncs.pfnCRC32_Init)
#define CRC32_PROCESS_BUFFER (*g_engfuncs.pfnCRC32_ProcessBuffer)
#define CRC32_PROCESS_BYTE (*g_engfuncs.pfnCRC32_ProcessByte)
#define CRC32_FINAL (*g_engfuncs.pfnCRC32_Final)
#define RANDOM_LONG (*g_engfuncs.pfnRandomLong)
#define RANDOM_FLOAT (*g_engfuncs.pfnRandomFloat)
#define GETPLAYERAUTHID (*g_engfuncs.pfnGetPlayerAuthId)
inline void MESSAGE_BEGIN( int msg_dest, int msg_type, const float *pOrigin = NULL, edict_t *ed = NULL ) {
(*g_engfuncs.pfnMessageBegin)(msg_dest, msg_type, pOrigin, ed);
}
#define MESSAGE_END (*g_engfuncs.pfnMessageEnd)
#define WRITE_BYTE (*g_engfuncs.pfnWriteByte)
#define WRITE_CHAR (*g_engfuncs.pfnWriteChar)
#define WRITE_SHORT (*g_engfuncs.pfnWriteShort)
#define WRITE_LONG (*g_engfuncs.pfnWriteLong)
#define WRITE_ANGLE (*g_engfuncs.pfnWriteAngle)
#define WRITE_COORD (*g_engfuncs.pfnWriteCoord)
#define WRITE_STRING (*g_engfuncs.pfnWriteString)
#define WRITE_ENTITY (*g_engfuncs.pfnWriteEntity)
#define CVAR_REGISTER (*g_engfuncs.pfnCVarRegister)
#define CVAR_GET_FLOAT (*g_engfuncs.pfnCVarGetFloat)
#define CVAR_GET_STRING (*g_engfuncs.pfnCVarGetString)
#define CVAR_SET_FLOAT (*g_engfuncs.pfnCVarSetFloat)
#define CVAR_SET_STRING (*g_engfuncs.pfnCVarSetString)
#define CVAR_GET_POINTER (*g_engfuncs.pfnCVarGetPointer)
#define ALERT (*g_engfuncs.pfnAlertMessage)
#define ENGINE_FPRINTF (*g_engfuncs.pfnEngineFprintf)
#define ALLOC_PRIVATE (*g_engfuncs.pfnPvAllocEntPrivateData)
inline void *GET_PRIVATE( edict_t *pent )
{
if ( pent )
return pent->pvPrivateData;
return NULL;
}
#define FREE_PRIVATE (*g_engfuncs.pfnFreeEntPrivateData)
//#define STRING (*g_engfuncs.pfnSzFromIndex)
#define ALLOC_STRING (*g_engfuncs.pfnAllocString)
#define FIND_ENTITY_BY_STRING (*g_engfuncs.pfnFindEntityByString)
#define GETENTITYILLUM (*g_engfuncs.pfnGetEntityIllum)
#define FIND_ENTITY_IN_SPHERE (*g_engfuncs.pfnFindEntityInSphere)
#define FIND_CLIENT_IN_PVS (*g_engfuncs.pfnFindClientInPVS)
#define EMIT_AMBIENT_SOUND (*g_engfuncs.pfnEmitAmbientSound)
#define GET_MODEL_PTR (*g_engfuncs.pfnGetModelPtr)
#define REG_USER_MSG (*g_engfuncs.pfnRegUserMsg)
#define GET_BONE_POSITION (*g_engfuncs.pfnGetBonePosition)
#define FUNCTION_FROM_NAME (*g_engfuncs.pfnFunctionFromName)
#define NAME_FOR_FUNCTION (*g_engfuncs.pfnNameForFunction)
#define TRACE_TEXTURE (*g_engfuncs.pfnTraceTexture)
#define CLIENT_PRINTF (*g_engfuncs.pfnClientPrintf)
#define CMD_ARGS (*g_engfuncs.pfnCmd_Args)
#define CMD_ARGC (*g_engfuncs.pfnCmd_Argc)
#define CMD_ARGV (*g_engfuncs.pfnCmd_Argv)
#define GET_ATTACHMENT (*g_engfuncs.pfnGetAttachment)
#define SET_VIEW (*g_engfuncs.pfnSetView)
#define SET_CROSSHAIRANGLE (*g_engfuncs.pfnCrosshairAngle)
#define LOAD_FILE_FOR_ME (*g_engfuncs.pfnLoadFileForMe)
#define FREE_FILE (*g_engfuncs.pfnFreeFile)
#define COMPARE_FILE_TIME (*g_engfuncs.pfnCompareFileTime)
#define GET_GAME_DIR (*g_engfuncs.pfnGetGameDir)
#define IS_MAP_VALID (*g_engfuncs.pfnIsMapValid)
#define NUMBER_OF_ENTITIES (*g_engfuncs.pfnNumberOfEntities)
#define IS_DEDICATED_SERVER (*g_engfuncs.pfnIsDedicatedServer)
#define PRECACHE_EVENT (*g_engfuncs.pfnPrecacheEvent)
#define PLAYBACK_EVENT_FULL (*g_engfuncs.pfnPlaybackEvent)
#define ENGINE_SET_PVS (*g_engfuncs.pfnSetFatPVS)
#define ENGINE_SET_PAS (*g_engfuncs.pfnSetFatPAS)
#define ENGINE_CHECK_VISIBILITY (*g_engfuncs.pfnCheckVisibility)
#define DELTA_SET ( *g_engfuncs.pfnDeltaSetField )
#define DELTA_UNSET ( *g_engfuncs.pfnDeltaUnsetField )
#define DELTA_ADDENCODER ( *g_engfuncs.pfnDeltaAddEncoder )
#define ENGINE_CURRENT_PLAYER ( *g_engfuncs.pfnGetCurrentPlayer )
#define ENGINE_CANSKIP ( *g_engfuncs.pfnCanSkipPlayer )
#define DELTA_FINDFIELD ( *g_engfuncs.pfnDeltaFindField )
#define DELTA_SETBYINDEX ( *g_engfuncs.pfnDeltaSetFieldByIndex )
#define DELTA_UNSETBYINDEX ( *g_engfuncs.pfnDeltaUnsetFieldByIndex )
#define ENGINE_GETPHYSINFO ( *g_engfuncs.pfnGetPhysicsInfoString )
#define ENGINE_SETGROUPMASK ( *g_engfuncs.pfnSetGroupMask )
#define ENGINE_INSTANCE_BASELINE ( *g_engfuncs.pfnCreateInstancedBaseline )
#define ENGINE_FORCE_UNMODIFIED ( *g_engfuncs.pfnForceUnmodified )
#define PLAYER_CNX_STATS ( *g_engfuncs.pfnGetPlayerStats )
#endif //ENGINECALLBACK_H

273
hlsdk/dmc/dlls/explode.cpp Normal file
View File

@ -0,0 +1,273 @@
/***
*
* 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.
*
****/
/*
===== explode.cpp ========================================================
Explosion-related code
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "decals.h"
#include "explode.h"
// Spark Shower
class CShower : public CBaseEntity
{
void Spawn( void );
void Think( void );
void Touch( CBaseEntity *pOther );
int ObjectCaps( void ) { return FCAP_DONT_SAVE; }
};
LINK_ENTITY_TO_CLASS( spark_shower, CShower );
void CShower::Spawn( void )
{
pev->velocity = RANDOM_FLOAT( 200, 300 ) * pev->angles;
pev->velocity.x += RANDOM_FLOAT(-100.f,100.f);
pev->velocity.y += RANDOM_FLOAT(-100.f,100.f);
if ( pev->velocity.z >= 0 )
pev->velocity.z += 200;
else
pev->velocity.z -= 200;
pev->movetype = MOVETYPE_BOUNCE;
pev->gravity = 0.5;
pev->nextthink = gpGlobals->time + 0.1;
pev->solid = SOLID_NOT;
SET_MODEL( edict(), "models/grenade.mdl"); // Need a model, just use the grenade, we don't draw it anyway
UTIL_SetSize(pev, g_vecZero, g_vecZero );
pev->effects |= EF_NODRAW;
pev->speed = RANDOM_FLOAT( 0.5, 1.5 );
pev->angles = g_vecZero;
}
void CShower::Think( void )
{
UTIL_Sparks( pev->origin );
pev->speed -= 0.1;
if ( pev->speed > 0 )
pev->nextthink = gpGlobals->time + 0.1;
else
UTIL_Remove( this );
pev->flags &= ~FL_ONGROUND;
}
void CShower::Touch( CBaseEntity *pOther )
{
if ( pev->flags & FL_ONGROUND )
pev->velocity = pev->velocity * 0.1;
else
pev->velocity = pev->velocity * 0.6;
if ( (pev->velocity.x*pev->velocity.x+pev->velocity.y*pev->velocity.y) < 10.0 )
pev->speed = 0;
}
class CEnvExplosion : public CBaseMonster
{
public:
void Spawn( );
void EXPORT Smoke ( void );
void KeyValue( KeyValueData *pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
int m_iMagnitude;// how large is the fireball? how much damage?
int m_spriteScale; // what's the exact fireball sprite scale?
};
TYPEDESCRIPTION CEnvExplosion::m_SaveData[] =
{
DEFINE_FIELD( CEnvExplosion, m_iMagnitude, FIELD_INTEGER ),
DEFINE_FIELD( CEnvExplosion, m_spriteScale, FIELD_INTEGER ),
};
IMPLEMENT_SAVERESTORE( CEnvExplosion, CBaseMonster );
LINK_ENTITY_TO_CLASS( env_explosion, CEnvExplosion );
void CEnvExplosion::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "iMagnitude"))
{
m_iMagnitude = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CBaseEntity::KeyValue( pkvd );
}
void CEnvExplosion::Spawn( void )
{
pev->solid = SOLID_NOT;
pev->effects = EF_NODRAW;
pev->movetype = MOVETYPE_NONE;
/*
if ( m_iMagnitude > 250 )
{
m_iMagnitude = 250;
}
*/
float flSpriteScale;
flSpriteScale = ( m_iMagnitude - 50) * 0.6;
/*
if ( flSpriteScale > 50 )
{
flSpriteScale = 50;
}
*/
if ( flSpriteScale < 10 )
{
flSpriteScale = 10;
}
m_spriteScale = (int)flSpriteScale;
}
void CEnvExplosion::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
TraceResult tr;
pev->model = iStringNull;//invisible
pev->solid = SOLID_NOT;// intangible
Vector vecSpot;// trace starts here!
vecSpot = pev->origin + Vector ( 0 , 0 , 8 );
UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -40 ), ignore_monsters, ENT(pev), & tr);
// Pull out of the wall a bit
if ( tr.flFraction != 1.0 )
{
pev->origin = tr.vecEndPos + (tr.vecPlaneNormal * (m_iMagnitude - 24) * 0.6);
}
else
{
pev->origin = pev->origin;
}
// draw decal
if (! ( pev->spawnflags & SF_ENVEXPLOSION_NODECAL))
{
if ( RANDOM_FLOAT( 0 , 1 ) < 0.5 )
{
UTIL_DecalTrace( &tr, DECAL_SCORCH1 );
}
else
{
UTIL_DecalTrace( &tr, DECAL_SCORCH2 );
}
}
// draw fireball
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NOFIREBALL ) )
{
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_EXPLOSION);
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_SHORT( g_sModelIndexFireball );
WRITE_BYTE( (BYTE)m_spriteScale ); // scale * 10
WRITE_BYTE( 15 ); // framerate
WRITE_BYTE( TE_EXPLFLAG_NONE );
MESSAGE_END();
}
else
{
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_EXPLOSION);
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_SHORT( g_sModelIndexFireball );
WRITE_BYTE( 0 ); // no sprite
WRITE_BYTE( 15 ); // framerate
WRITE_BYTE( TE_EXPLFLAG_NONE );
MESSAGE_END();
}
// do damage
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NODAMAGE ) )
{
RadiusDamage ( pev, pev, m_iMagnitude, CLASS_NONE, DMG_BLAST );
}
SetThink( &CEnvExplosion::Smoke );
pev->nextthink = gpGlobals->time + 0.3;
// draw sparks
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NOSPARKS ) )
{
int sparkCount = RANDOM_LONG(0,3);
for ( int i = 0; i < sparkCount; i++ )
{
Create( "spark_shower", pev->origin, tr.vecPlaneNormal, NULL );
}
}
}
void CEnvExplosion::Smoke( void )
{
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NOSMOKE ) )
{
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_SMOKE );
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_SHORT( g_sModelIndexSmoke );
WRITE_BYTE( (BYTE)m_spriteScale ); // scale * 10
WRITE_BYTE( 12 ); // framerate
MESSAGE_END();
}
if ( !(pev->spawnflags & SF_ENVEXPLOSION_REPEATABLE) )
{
UTIL_Remove( this );
}
}
// HACKHACK -- create one of these and fake a keyvalue to get the right explosion setup
void ExplosionCreate( const Vector &center, const Vector &angles, edict_t *pOwner, int magnitude, BOOL doDamage )
{
KeyValueData kvd;
char buf[128];
CBaseEntity *pExplosion = CBaseEntity::Create( "env_explosion", center, angles, pOwner );
sprintf( buf, "%3d", magnitude );
kvd.szKeyName = "iMagnitude";
kvd.szValue = buf;
pExplosion->KeyValue( &kvd );
if ( !doDamage )
pExplosion->pev->spawnflags |= SF_ENVEXPLOSION_NODAMAGE;
pExplosion->Spawn();
pExplosion->Use( NULL, NULL, USE_TOGGLE, 0 );
}

32
hlsdk/dmc/dlls/explode.h Normal file
View File

@ -0,0 +1,32 @@
/***
*
* 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.
*
****/
#ifndef EXPLODE_H
#define EXPLODE_H
#define SF_ENVEXPLOSION_NODAMAGE ( 1 << 0 ) // when set, ENV_EXPLOSION will not actually inflict damage
#define SF_ENVEXPLOSION_REPEATABLE ( 1 << 1 ) // can this entity be refired?
#define SF_ENVEXPLOSION_NOFIREBALL ( 1 << 2 ) // don't draw the fireball
#define SF_ENVEXPLOSION_NOSMOKE ( 1 << 3 ) // don't draw the smoke
#define SF_ENVEXPLOSION_NODECAL ( 1 << 4 ) // don't make a scorch mark
#define SF_ENVEXPLOSION_NOSPARKS ( 1 << 5 ) // don't make a scorch mark
extern DLL_GLOBAL short g_sModelIndexFireball;
extern DLL_GLOBAL short g_sModelIndexSmoke;
extern void ExplosionCreate( const Vector &center, const Vector &angles, edict_t *pOwner, int magnitude, BOOL doDamage );
#endif //EXPLODE_H

107
hlsdk/dmc/dlls/extdll.h Normal file
View File

@ -0,0 +1,107 @@
/***
*
* 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.
*
****/
#ifndef EXTDLL_H
#define EXTDLL_H
//
// Global header file for extension DLLs
//
// Allow "DEBUG" in addition to default "_DEBUG"
#ifdef _DEBUG
#define DEBUG 1
#endif
// Silence certain warnings
#ifdef _MSC_VER
#pragma warning(disable : 4244) // int or float down-conversion
#pragma warning(disable : 4305) // int or float data truncation
#pragma warning(disable : 4201) // nameless struct/union
#pragma warning(disable : 4514) // unreferenced inline function removed
#pragma warning(disable : 4100) // unreferenced formal parameter
#if _MSC_VER >= 1400
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#pragma warning(disable: 4996) // deprecated functions
#endif
#endif
#ifdef _WIN32
// Prevent tons of unused windows definitions
#define WIN32_LEAN_AND_MEAN
#define NOWINRES
#define NOSERVICE
#define NOMCX
#define NOIME
#include "windows.h"
#else // _WIN32
#define FALSE 0
#define TRUE (!FALSE)
typedef unsigned long ULONG;
typedef unsigned char BYTE;
typedef int BOOL;
#define MAX_PATH PATH_MAX
#include <limits.h>
#include <stdarg.h>
#include <ctype.h>
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#define itoa(a,b,c) sprintf(b, "%d", a)
#define _snprintf snprintf
#define _vsnprintf vsnprintf
#endif //_WIN32
// Misc C-runtime library headers
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
// Header file containing definition of globalvars_t and entvars_t
typedef int func_t; //
typedef int string_t; // from engine's pr_comp.h;
typedef float vec_t; // needed before including progdefs.h
// Vector class
#include "vector.h"
// Defining it as a (bogus) struct helps enforce type-checking
#define vec3_t Vector
// Shared engine/DLL constants
#include "const.h"
#include "progdefs.h"
#include "edict.h"
// Shared header describing protocol between engine and DLLs
#include "eiface.h"
// Shared header between the client DLL and the game DLLs
#include "cdll_dll.h"
#endif //EXTDLL_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
/***
*
* 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.
*
****/
#ifndef FUNC_BREAK_H
#define FUNC_BREAK_H
typedef enum { expRandom, expDirected} Explosions;
typedef enum { matGlass = 0, matWood, matMetal, matFlesh, matCinderBlock, matCeilingTile, matComputer, matUnbreakableGlass, matRocks, matNone, matLastMaterial } Materials;
#define NUM_SHARDS 6 // this many shards spawned when breakable objects break;
class CBreakable : public CBaseDelay
{
public:
// basic functions
void Spawn( void );
void Precache( void );
void KeyValue( KeyValueData* pkvd);
void EXPORT BreakTouch( CBaseEntity *pOther );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void DamageSound( void );
// breakables use an overridden takedamage
virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
// To spark when hit
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType );
BOOL IsBreakable( void );
BOOL SparkWhenHit( void );
int DamageDecal( int bitsDamageType );
void EXPORT Die( void );
virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION); }
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
inline BOOL Explodable( void ) { return ExplosionMagnitude() > 0; }
inline int ExplosionMagnitude( void ) { return pev->impulse; }
inline void ExplosionSetMagnitude( int magnitude ) { pev->impulse = magnitude; }
static void MaterialSoundPrecache( Materials precacheMaterial );
static void MaterialSoundRandom( edict_t *pEdict, Materials soundMaterial, float volume );
static const char **MaterialSoundList( Materials precacheMaterial, int &soundCount );
static const char *pSoundsWood[];
static const char *pSoundsFlesh[];
static const char *pSoundsGlass[];
static const char *pSoundsMetal[];
static const char *pSoundsConcrete[];
static const char *pSpawnObjects[];
static TYPEDESCRIPTION m_SaveData[];
Materials m_Material;
Explosions m_Explosion;
int m_idShard;
float m_angle;
int m_iszGibModel;
int m_iszSpawnObject;
};
#endif // FUNC_BREAK_H

892
hlsdk/dmc/dlls/game.cpp Normal file
View File

@ -0,0 +1,892 @@
/***
*
* 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 "extdll.h"
#include "eiface.h"
#include "util.h"
#include "game.h"
// QUAKECLASSIC
cvar_t rj = {"rj", "0"};
cvar_t displaysoundlist = {"displaysoundlist","0"};
// multiplayer server rules
cvar_t fragsleft = {"mp_fragsleft","0", FCVAR_SERVER | FCVAR_UNLOGGED }; // Don't spam console/log files/users with this changing
cvar_t timeleft = {"mp_timeleft","0" , FCVAR_SERVER | FCVAR_UNLOGGED }; // " "
// multiplayer server rules
cvar_t teamplay = {"mp_teamplay","0", FCVAR_SERVER };
cvar_t fraglimit = {"mp_fraglimit","0", FCVAR_SERVER };
cvar_t timelimit = {"mp_timelimit","0", FCVAR_SERVER };
cvar_t friendlyfire= {"mp_friendlyfire","0", FCVAR_SERVER };
cvar_t falldamage = {"mp_falldamage","0", FCVAR_SERVER };
cvar_t weaponstay = {"mp_weaponstay","1", FCVAR_SERVER };
cvar_t forcerespawn= {"mp_forcerespawn","1", FCVAR_SERVER };
cvar_t flashlight = {"mp_flashlight","0", FCVAR_SERVER };
cvar_t aimcrosshair= {"mp_autocrosshair","1", FCVAR_SERVER };
cvar_t decalfrequency = {"decalfrequency","30", FCVAR_SERVER };
cvar_t teamlist = {"mp_teamlist","hgrunt;scientist", FCVAR_SERVER };
cvar_t teamoverride = {"mp_teamoverride","1" };
cvar_t defaultteam = {"mp_defaultteam","0" };
cvar_t allowmonsters={"mp_allowmonsters","0", FCVAR_SERVER };
cvar_t mp_chattime = {"mp_chattime","10", FCVAR_SERVER };
cvar_t *g_psv_gravity = NULL;
cvar_t *g_psv_aim = NULL;
cvar_t *g_footsteps = NULL;
//CVARS FOR SKILL LEVEL SETTINGS
// Agrunt
cvar_t sk_agrunt_health1 = {"sk_agrunt_health1","0"};
cvar_t sk_agrunt_health2 = {"sk_agrunt_health2","0"};
cvar_t sk_agrunt_health3 = {"sk_agrunt_health3","0"};
cvar_t sk_agrunt_dmg_punch1 = {"sk_agrunt_dmg_punch1","0"};
cvar_t sk_agrunt_dmg_punch2 = {"sk_agrunt_dmg_punch2","0"};
cvar_t sk_agrunt_dmg_punch3 = {"sk_agrunt_dmg_punch3","0"};
// Apache
cvar_t sk_apache_health1 = {"sk_apache_health1","0"};
cvar_t sk_apache_health2 = {"sk_apache_health2","0"};
cvar_t sk_apache_health3 = {"sk_apache_health3","0"};
// Barney
cvar_t sk_barney_health1 = {"sk_barney_health1","0"};
cvar_t sk_barney_health2 = {"sk_barney_health2","0"};
cvar_t sk_barney_health3 = {"sk_barney_health3","0"};
// Bullsquid
cvar_t sk_bullsquid_health1 = {"sk_bullsquid_health1","0"};
cvar_t sk_bullsquid_health2 = {"sk_bullsquid_health2","0"};
cvar_t sk_bullsquid_health3 = {"sk_bullsquid_health3","0"};
cvar_t sk_bullsquid_dmg_bite1 = {"sk_bullsquid_dmg_bite1","0"};
cvar_t sk_bullsquid_dmg_bite2 = {"sk_bullsquid_dmg_bite2","0"};
cvar_t sk_bullsquid_dmg_bite3 = {"sk_bullsquid_dmg_bite3","0"};
cvar_t sk_bullsquid_dmg_whip1 = {"sk_bullsquid_dmg_whip1","0"};
cvar_t sk_bullsquid_dmg_whip2 = {"sk_bullsquid_dmg_whip2","0"};
cvar_t sk_bullsquid_dmg_whip3 = {"sk_bullsquid_dmg_whip3","0"};
cvar_t sk_bullsquid_dmg_spit1 = {"sk_bullsquid_dmg_spit1","0"};
cvar_t sk_bullsquid_dmg_spit2 = {"sk_bullsquid_dmg_spit2","0"};
cvar_t sk_bullsquid_dmg_spit3 = {"sk_bullsquid_dmg_spit3","0"};
// Big Momma
cvar_t sk_bigmomma_health_factor1 = {"sk_bigmomma_health_factor1","1.0"};
cvar_t sk_bigmomma_health_factor2 = {"sk_bigmomma_health_factor2","1.0"};
cvar_t sk_bigmomma_health_factor3 = {"sk_bigmomma_health_factor3","1.0"};
cvar_t sk_bigmomma_dmg_slash1 = {"sk_bigmomma_dmg_slash1","50"};
cvar_t sk_bigmomma_dmg_slash2 = {"sk_bigmomma_dmg_slash2","50"};
cvar_t sk_bigmomma_dmg_slash3 = {"sk_bigmomma_dmg_slash3","50"};
cvar_t sk_bigmomma_dmg_blast1 = {"sk_bigmomma_dmg_blast1","100"};
cvar_t sk_bigmomma_dmg_blast2 = {"sk_bigmomma_dmg_blast2","100"};
cvar_t sk_bigmomma_dmg_blast3 = {"sk_bigmomma_dmg_blast3","100"};
cvar_t sk_bigmomma_radius_blast1 = {"sk_bigmomma_radius_blast1","250"};
cvar_t sk_bigmomma_radius_blast2 = {"sk_bigmomma_radius_blast2","250"};
cvar_t sk_bigmomma_radius_blast3 = {"sk_bigmomma_radius_blast3","250"};
// Gargantua
cvar_t sk_gargantua_health1 = {"sk_gargantua_health1","0"};
cvar_t sk_gargantua_health2 = {"sk_gargantua_health2","0"};
cvar_t sk_gargantua_health3 = {"sk_gargantua_health3","0"};
cvar_t sk_gargantua_dmg_slash1 = {"sk_gargantua_dmg_slash1","0"};
cvar_t sk_gargantua_dmg_slash2 = {"sk_gargantua_dmg_slash2","0"};
cvar_t sk_gargantua_dmg_slash3 = {"sk_gargantua_dmg_slash3","0"};
cvar_t sk_gargantua_dmg_fire1 = {"sk_gargantua_dmg_fire1","0"};
cvar_t sk_gargantua_dmg_fire2 = {"sk_gargantua_dmg_fire2","0"};
cvar_t sk_gargantua_dmg_fire3 = {"sk_gargantua_dmg_fire3","0"};
cvar_t sk_gargantua_dmg_stomp1 = {"sk_gargantua_dmg_stomp1","0"};
cvar_t sk_gargantua_dmg_stomp2 = {"sk_gargantua_dmg_stomp2","0"};
cvar_t sk_gargantua_dmg_stomp3 = {"sk_gargantua_dmg_stomp3","0"};
// Hassassin
cvar_t sk_hassassin_health1 = {"sk_hassassin_health1","0"};
cvar_t sk_hassassin_health2 = {"sk_hassassin_health2","0"};
cvar_t sk_hassassin_health3 = {"sk_hassassin_health3","0"};
// Headcrab
cvar_t sk_headcrab_health1 = {"sk_headcrab_health1","0"};
cvar_t sk_headcrab_health2 = {"sk_headcrab_health2","0"};
cvar_t sk_headcrab_health3 = {"sk_headcrab_health3","0"};
cvar_t sk_headcrab_dmg_bite1 = {"sk_headcrab_dmg_bite1","0"};
cvar_t sk_headcrab_dmg_bite2 = {"sk_headcrab_dmg_bite2","0"};
cvar_t sk_headcrab_dmg_bite3 = {"sk_headcrab_dmg_bite3","0"};
// Hgrunt
cvar_t sk_hgrunt_health1 = {"sk_hgrunt_health1","0"};
cvar_t sk_hgrunt_health2 = {"sk_hgrunt_health2","0"};
cvar_t sk_hgrunt_health3 = {"sk_hgrunt_health3","0"};
cvar_t sk_hgrunt_kick1 = {"sk_hgrunt_kick1","0"};
cvar_t sk_hgrunt_kick2 = {"sk_hgrunt_kick2","0"};
cvar_t sk_hgrunt_kick3 = {"sk_hgrunt_kick3","0"};
cvar_t sk_hgrunt_pellets1 = {"sk_hgrunt_pellets1","0"};
cvar_t sk_hgrunt_pellets2 = {"sk_hgrunt_pellets2","0"};
cvar_t sk_hgrunt_pellets3 = {"sk_hgrunt_pellets3","0"};
cvar_t sk_hgrunt_gspeed1 = {"sk_hgrunt_gspeed1","0"};
cvar_t sk_hgrunt_gspeed2 = {"sk_hgrunt_gspeed2","0"};
cvar_t sk_hgrunt_gspeed3 = {"sk_hgrunt_gspeed3","0"};
// Houndeye
cvar_t sk_houndeye_health1 = {"sk_houndeye_health1","0"};
cvar_t sk_houndeye_health2 = {"sk_houndeye_health2","0"};
cvar_t sk_houndeye_health3 = {"sk_houndeye_health3","0"};
cvar_t sk_houndeye_dmg_blast1 = {"sk_houndeye_dmg_blast1","0"};
cvar_t sk_houndeye_dmg_blast2 = {"sk_houndeye_dmg_blast2","0"};
cvar_t sk_houndeye_dmg_blast3 = {"sk_houndeye_dmg_blast3","0"};
// ISlave
cvar_t sk_islave_health1 = {"sk_islave_health1","0"};
cvar_t sk_islave_health2 = {"sk_islave_health2","0"};
cvar_t sk_islave_health3 = {"sk_islave_health3","0"};
cvar_t sk_islave_dmg_claw1 = {"sk_islave_dmg_claw1","0"};
cvar_t sk_islave_dmg_claw2 = {"sk_islave_dmg_claw2","0"};
cvar_t sk_islave_dmg_claw3 = {"sk_islave_dmg_claw3","0"};
cvar_t sk_islave_dmg_clawrake1 = {"sk_islave_dmg_clawrake1","0"};
cvar_t sk_islave_dmg_clawrake2 = {"sk_islave_dmg_clawrake2","0"};
cvar_t sk_islave_dmg_clawrake3 = {"sk_islave_dmg_clawrake3","0"};
cvar_t sk_islave_dmg_zap1 = {"sk_islave_dmg_zap1","0"};
cvar_t sk_islave_dmg_zap2 = {"sk_islave_dmg_zap2","0"};
cvar_t sk_islave_dmg_zap3 = {"sk_islave_dmg_zap3","0"};
// Icthyosaur
cvar_t sk_ichthyosaur_health1 = {"sk_ichthyosaur_health1","0"};
cvar_t sk_ichthyosaur_health2 = {"sk_ichthyosaur_health2","0"};
cvar_t sk_ichthyosaur_health3 = {"sk_ichthyosaur_health3","0"};
cvar_t sk_ichthyosaur_shake1 = {"sk_ichthyosaur_shake1","0"};
cvar_t sk_ichthyosaur_shake2 = {"sk_ichthyosaur_shake2","0"};
cvar_t sk_ichthyosaur_shake3 = {"sk_ichthyosaur_shake3","0"};
// Leech
cvar_t sk_leech_health1 = {"sk_leech_health1","0"};
cvar_t sk_leech_health2 = {"sk_leech_health2","0"};
cvar_t sk_leech_health3 = {"sk_leech_health3","0"};
cvar_t sk_leech_dmg_bite1 = {"sk_leech_dmg_bite1","0"};
cvar_t sk_leech_dmg_bite2 = {"sk_leech_dmg_bite2","0"};
cvar_t sk_leech_dmg_bite3 = {"sk_leech_dmg_bite3","0"};
// Controller
cvar_t sk_controller_health1 = {"sk_controller_health1","0"};
cvar_t sk_controller_health2 = {"sk_controller_health2","0"};
cvar_t sk_controller_health3 = {"sk_controller_health3","0"};
cvar_t sk_controller_dmgzap1 = {"sk_controller_dmgzap1","0"};
cvar_t sk_controller_dmgzap2 = {"sk_controller_dmgzap2","0"};
cvar_t sk_controller_dmgzap3 = {"sk_controller_dmgzap3","0"};
cvar_t sk_controller_speedball1 = {"sk_controller_speedball1","0"};
cvar_t sk_controller_speedball2 = {"sk_controller_speedball2","0"};
cvar_t sk_controller_speedball3 = {"sk_controller_speedball3","0"};
cvar_t sk_controller_dmgball1 = {"sk_controller_dmgball1","0"};
cvar_t sk_controller_dmgball2 = {"sk_controller_dmgball2","0"};
cvar_t sk_controller_dmgball3 = {"sk_controller_dmgball3","0"};
// Nihilanth
cvar_t sk_nihilanth_health1 = {"sk_nihilanth_health1","0"};
cvar_t sk_nihilanth_health2 = {"sk_nihilanth_health2","0"};
cvar_t sk_nihilanth_health3 = {"sk_nihilanth_health3","0"};
cvar_t sk_nihilanth_zap1 = {"sk_nihilanth_zap1","0"};
cvar_t sk_nihilanth_zap2 = {"sk_nihilanth_zap2","0"};
cvar_t sk_nihilanth_zap3 = {"sk_nihilanth_zap3","0"};
// Scientist
cvar_t sk_scientist_health1 = {"sk_scientist_health1","0"};
cvar_t sk_scientist_health2 = {"sk_scientist_health2","0"};
cvar_t sk_scientist_health3 = {"sk_scientist_health3","0"};
// Snark
cvar_t sk_snark_health1 = {"sk_snark_health1","0"};
cvar_t sk_snark_health2 = {"sk_snark_health2","0"};
cvar_t sk_snark_health3 = {"sk_snark_health3","0"};
cvar_t sk_snark_dmg_bite1 = {"sk_snark_dmg_bite1","0"};
cvar_t sk_snark_dmg_bite2 = {"sk_snark_dmg_bite2","0"};
cvar_t sk_snark_dmg_bite3 = {"sk_snark_dmg_bite3","0"};
cvar_t sk_snark_dmg_pop1 = {"sk_snark_dmg_pop1","0"};
cvar_t sk_snark_dmg_pop2 = {"sk_snark_dmg_pop2","0"};
cvar_t sk_snark_dmg_pop3 = {"sk_snark_dmg_pop3","0"};
// Zombie
cvar_t sk_zombie_health1 = {"sk_zombie_health1","0"};
cvar_t sk_zombie_health2 = {"sk_zombie_health2","0"};
cvar_t sk_zombie_health3 = {"sk_zombie_health3","0"};
cvar_t sk_zombie_dmg_one_slash1 = {"sk_zombie_dmg_one_slash1","0"};
cvar_t sk_zombie_dmg_one_slash2 = {"sk_zombie_dmg_one_slash2","0"};
cvar_t sk_zombie_dmg_one_slash3 = {"sk_zombie_dmg_one_slash3","0"};
cvar_t sk_zombie_dmg_both_slash1 = {"sk_zombie_dmg_both_slash1","0"};
cvar_t sk_zombie_dmg_both_slash2 = {"sk_zombie_dmg_both_slash2","0"};
cvar_t sk_zombie_dmg_both_slash3 = {"sk_zombie_dmg_both_slash3","0"};
//Turret
cvar_t sk_turret_health1 = {"sk_turret_health1","0"};
cvar_t sk_turret_health2 = {"sk_turret_health2","0"};
cvar_t sk_turret_health3 = {"sk_turret_health3","0"};
// MiniTurret
cvar_t sk_miniturret_health1 = {"sk_miniturret_health1","0"};
cvar_t sk_miniturret_health2 = {"sk_miniturret_health2","0"};
cvar_t sk_miniturret_health3 = {"sk_miniturret_health3","0"};
// Sentry Turret
cvar_t sk_sentry_health1 = {"sk_sentry_health1","0"};
cvar_t sk_sentry_health2 = {"sk_sentry_health2","0"};
cvar_t sk_sentry_health3 = {"sk_sentry_health3","0"};
// PLAYER WEAPONS
// Crowbar whack
cvar_t sk_plr_crowbar1 = {"sk_plr_crowbar1","0"};
cvar_t sk_plr_crowbar2 = {"sk_plr_crowbar2","0"};
cvar_t sk_plr_crowbar3 = {"sk_plr_crowbar3","0"};
// Glock Round
cvar_t sk_plr_9mm_bullet1 = {"sk_plr_9mm_bullet1","0"};
cvar_t sk_plr_9mm_bullet2 = {"sk_plr_9mm_bullet2","0"};
cvar_t sk_plr_9mm_bullet3 = {"sk_plr_9mm_bullet3","0"};
// 357 Round
cvar_t sk_plr_357_bullet1 = {"sk_plr_357_bullet1","0"};
cvar_t sk_plr_357_bullet2 = {"sk_plr_357_bullet2","0"};
cvar_t sk_plr_357_bullet3 = {"sk_plr_357_bullet3","0"};
// MP5 Round
cvar_t sk_plr_9mmAR_bullet1 = {"sk_plr_9mmAR_bullet1","0"};
cvar_t sk_plr_9mmAR_bullet2 = {"sk_plr_9mmAR_bullet2","0"};
cvar_t sk_plr_9mmAR_bullet3 = {"sk_plr_9mmAR_bullet3","0"};
// M203 grenade
cvar_t sk_plr_9mmAR_grenade1 = {"sk_plr_9mmAR_grenade1","0"};
cvar_t sk_plr_9mmAR_grenade2 = {"sk_plr_9mmAR_grenade2","0"};
cvar_t sk_plr_9mmAR_grenade3 = {"sk_plr_9mmAR_grenade3","0"};
// Shotgun buckshot
cvar_t sk_plr_buckshot1 = {"sk_plr_buckshot1","0"};
cvar_t sk_plr_buckshot2 = {"sk_plr_buckshot2","0"};
cvar_t sk_plr_buckshot3 = {"sk_plr_buckshot3","0"};
// Crossbow
cvar_t sk_plr_xbow_bolt_client1 = {"sk_plr_xbow_bolt_client1","0"};
cvar_t sk_plr_xbow_bolt_client2 = {"sk_plr_xbow_bolt_client2","0"};
cvar_t sk_plr_xbow_bolt_client3 = {"sk_plr_xbow_bolt_client3","0"};
cvar_t sk_plr_xbow_bolt_monster1 = {"sk_plr_xbow_bolt_monster1","0"};
cvar_t sk_plr_xbow_bolt_monster2 = {"sk_plr_xbow_bolt_monster2","0"};
cvar_t sk_plr_xbow_bolt_monster3 = {"sk_plr_xbow_bolt_monster3","0"};
// RPG
cvar_t sk_plr_rpg1 = {"sk_plr_rpg1","0"};
cvar_t sk_plr_rpg2 = {"sk_plr_rpg2","0"};
cvar_t sk_plr_rpg3 = {"sk_plr_rpg3","0"};
// Zero Point Generator
cvar_t sk_plr_gauss1 = {"sk_plr_gauss1","0"};
cvar_t sk_plr_gauss2 = {"sk_plr_gauss2","0"};
cvar_t sk_plr_gauss3 = {"sk_plr_gauss3","0"};
// Tau Cannon
cvar_t sk_plr_egon_narrow1 = {"sk_plr_egon_narrow1","0"};
cvar_t sk_plr_egon_narrow2 = {"sk_plr_egon_narrow2","0"};
cvar_t sk_plr_egon_narrow3 = {"sk_plr_egon_narrow3","0"};
cvar_t sk_plr_egon_wide1 = {"sk_plr_egon_wide1","0"};
cvar_t sk_plr_egon_wide2 = {"sk_plr_egon_wide2","0"};
cvar_t sk_plr_egon_wide3 = {"sk_plr_egon_wide3","0"};
// Hand Grendade
cvar_t sk_plr_hand_grenade1 = {"sk_plr_hand_grenade1","0"};
cvar_t sk_plr_hand_grenade2 = {"sk_plr_hand_grenade2","0"};
cvar_t sk_plr_hand_grenade3 = {"sk_plr_hand_grenade3","0"};
// Satchel Charge
cvar_t sk_plr_satchel1 = {"sk_plr_satchel1","0"};
cvar_t sk_plr_satchel2 = {"sk_plr_satchel2","0"};
cvar_t sk_plr_satchel3 = {"sk_plr_satchel3","0"};
// Tripmine
cvar_t sk_plr_tripmine1 = {"sk_plr_tripmine1","0"};
cvar_t sk_plr_tripmine2 = {"sk_plr_tripmine2","0"};
cvar_t sk_plr_tripmine3 = {"sk_plr_tripmine3","0"};
// WORLD WEAPONS
cvar_t sk_12mm_bullet1 = {"sk_12mm_bullet1","0"};
cvar_t sk_12mm_bullet2 = {"sk_12mm_bullet2","0"};
cvar_t sk_12mm_bullet3 = {"sk_12mm_bullet3","0"};
cvar_t sk_9mmAR_bullet1 = {"sk_9mmAR_bullet1","0"};
cvar_t sk_9mmAR_bullet2 = {"sk_9mmAR_bullet2","0"};
cvar_t sk_9mmAR_bullet3 = {"sk_9mmAR_bullet3","0"};
cvar_t sk_9mm_bullet1 = {"sk_9mm_bullet1","0"};
cvar_t sk_9mm_bullet2 = {"sk_9mm_bullet2","0"};
cvar_t sk_9mm_bullet3 = {"sk_9mm_bullet3","0"};
// HORNET
cvar_t sk_hornet_dmg1 = {"sk_hornet_dmg1","0"};
cvar_t sk_hornet_dmg2 = {"sk_hornet_dmg2","0"};
cvar_t sk_hornet_dmg3 = {"sk_hornet_dmg3","0"};
// HEALTH/CHARGE
cvar_t sk_suitcharger1 = { "sk_suitcharger1","0" };
cvar_t sk_suitcharger2 = { "sk_suitcharger2","0" };
cvar_t sk_suitcharger3 = { "sk_suitcharger3","0" };
cvar_t sk_battery1 = { "sk_battery1","0" };
cvar_t sk_battery2 = { "sk_battery2","0" };
cvar_t sk_battery3 = { "sk_battery3","0" };
cvar_t sk_healthcharger1 = { "sk_healthcharger1","0" };
cvar_t sk_healthcharger2 = { "sk_healthcharger2","0" };
cvar_t sk_healthcharger3 = { "sk_healthcharger3","0" };
cvar_t sk_healthkit1 = { "sk_healthkit1","0" };
cvar_t sk_healthkit2 = { "sk_healthkit2","0" };
cvar_t sk_healthkit3 = { "sk_healthkit3","0" };
cvar_t sk_scientist_heal1 = { "sk_scientist_heal1","0" };
cvar_t sk_scientist_heal2 = { "sk_scientist_heal2","0" };
cvar_t sk_scientist_heal3 = { "sk_scientist_heal3","0" };
// monster damage adjusters
cvar_t sk_monster_head1 = { "sk_monster_head1","2" };
cvar_t sk_monster_head2 = { "sk_monster_head2","2" };
cvar_t sk_monster_head3 = { "sk_monster_head3","2" };
cvar_t sk_monster_chest1 = { "sk_monster_chest1","1" };
cvar_t sk_monster_chest2 = { "sk_monster_chest2","1" };
cvar_t sk_monster_chest3 = { "sk_monster_chest3","1" };
cvar_t sk_monster_stomach1 = { "sk_monster_stomach1","1" };
cvar_t sk_monster_stomach2 = { "sk_monster_stomach2","1" };
cvar_t sk_monster_stomach3 = { "sk_monster_stomach3","1" };
cvar_t sk_monster_arm1 = { "sk_monster_arm1","1" };
cvar_t sk_monster_arm2 = { "sk_monster_arm2","1" };
cvar_t sk_monster_arm3 = { "sk_monster_arm3","1" };
cvar_t sk_monster_leg1 = { "sk_monster_leg1","1" };
cvar_t sk_monster_leg2 = { "sk_monster_leg2","1" };
cvar_t sk_monster_leg3 = { "sk_monster_leg3","1" };
// player damage adjusters
cvar_t sk_player_head1 = { "sk_player_head1","2" };
cvar_t sk_player_head2 = { "sk_player_head2","2" };
cvar_t sk_player_head3 = { "sk_player_head3","2" };
cvar_t sk_player_chest1 = { "sk_player_chest1","1" };
cvar_t sk_player_chest2 = { "sk_player_chest2","1" };
cvar_t sk_player_chest3 = { "sk_player_chest3","1" };
cvar_t sk_player_stomach1 = { "sk_player_stomach1","1" };
cvar_t sk_player_stomach2 = { "sk_player_stomach2","1" };
cvar_t sk_player_stomach3 = { "sk_player_stomach3","1" };
cvar_t sk_player_arm1 = { "sk_player_arm1","1" };
cvar_t sk_player_arm2 = { "sk_player_arm2","1" };
cvar_t sk_player_arm3 = { "sk_player_arm3","1" };
cvar_t sk_player_leg1 = { "sk_player_leg1","1" };
cvar_t sk_player_leg2 = { "sk_player_leg2","1" };
cvar_t sk_player_leg3 = { "sk_player_leg3","1" };
// END Cvars for Skill Level settings
// Register your console variables here
// This gets called one time when the game is initialied
void GameDLLInit( void )
{
// Register cvars here:
g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" );
g_psv_aim = CVAR_GET_POINTER( "sv_aim" );
g_footsteps = CVAR_GET_POINTER( "mp_footsteps" );
// QUAKECLASSIC
CVAR_REGISTER (&rj);
CVAR_REGISTER (&displaysoundlist);
CVAR_REGISTER (&teamplay);
CVAR_REGISTER (&fraglimit);
CVAR_REGISTER (&timelimit);
CVAR_REGISTER (&fragsleft);
CVAR_REGISTER (&timeleft);
CVAR_REGISTER (&friendlyfire);
CVAR_REGISTER (&falldamage);
CVAR_REGISTER (&weaponstay);
CVAR_REGISTER (&forcerespawn);
CVAR_REGISTER (&flashlight);
CVAR_REGISTER (&aimcrosshair);
CVAR_REGISTER (&decalfrequency);
CVAR_REGISTER (&teamlist);
CVAR_REGISTER (&teamoverride);
CVAR_REGISTER (&defaultteam);
CVAR_REGISTER (&allowmonsters);
CVAR_REGISTER (&mp_chattime);
// REGISTER CVARS FOR SKILL LEVEL STUFF
// Agrunt
CVAR_REGISTER ( &sk_agrunt_health1 );// {"sk_agrunt_health1","0"};
CVAR_REGISTER ( &sk_agrunt_health2 );// {"sk_agrunt_health2","0"};
CVAR_REGISTER ( &sk_agrunt_health3 );// {"sk_agrunt_health3","0"};
CVAR_REGISTER ( &sk_agrunt_dmg_punch1 );// {"sk_agrunt_dmg_punch1","0"};
CVAR_REGISTER ( &sk_agrunt_dmg_punch2 );// {"sk_agrunt_dmg_punch2","0"};
CVAR_REGISTER ( &sk_agrunt_dmg_punch3 );// {"sk_agrunt_dmg_punch3","0"};
// Apache
CVAR_REGISTER ( &sk_apache_health1 );// {"sk_apache_health1","0"};
CVAR_REGISTER ( &sk_apache_health2 );// {"sk_apache_health2","0"};
CVAR_REGISTER ( &sk_apache_health3 );// {"sk_apache_health3","0"};
// Barney
CVAR_REGISTER ( &sk_barney_health1 );// {"sk_barney_health1","0"};
CVAR_REGISTER ( &sk_barney_health2 );// {"sk_barney_health2","0"};
CVAR_REGISTER ( &sk_barney_health3 );// {"sk_barney_health3","0"};
// Bullsquid
CVAR_REGISTER ( &sk_bullsquid_health1 );// {"sk_bullsquid_health1","0"};
CVAR_REGISTER ( &sk_bullsquid_health2 );// {"sk_bullsquid_health2","0"};
CVAR_REGISTER ( &sk_bullsquid_health3 );// {"sk_bullsquid_health3","0"};
CVAR_REGISTER ( &sk_bullsquid_dmg_bite1 );// {"sk_bullsquid_dmg_bite1","0"};
CVAR_REGISTER ( &sk_bullsquid_dmg_bite2 );// {"sk_bullsquid_dmg_bite2","0"};
CVAR_REGISTER ( &sk_bullsquid_dmg_bite3 );// {"sk_bullsquid_dmg_bite3","0"};
CVAR_REGISTER ( &sk_bullsquid_dmg_whip1 );// {"sk_bullsquid_dmg_whip1","0"};
CVAR_REGISTER ( &sk_bullsquid_dmg_whip2 );// {"sk_bullsquid_dmg_whip2","0"};
CVAR_REGISTER ( &sk_bullsquid_dmg_whip3 );// {"sk_bullsquid_dmg_whip3","0"};
CVAR_REGISTER ( &sk_bullsquid_dmg_spit1 );// {"sk_bullsquid_dmg_spit1","0"};
CVAR_REGISTER ( &sk_bullsquid_dmg_spit2 );// {"sk_bullsquid_dmg_spit2","0"};
CVAR_REGISTER ( &sk_bullsquid_dmg_spit3 );// {"sk_bullsquid_dmg_spit3","0"};
CVAR_REGISTER ( &sk_bigmomma_health_factor1 );// {"sk_bigmomma_health_factor1","1.0"};
CVAR_REGISTER ( &sk_bigmomma_health_factor2 );// {"sk_bigmomma_health_factor2","1.0"};
CVAR_REGISTER ( &sk_bigmomma_health_factor3 );// {"sk_bigmomma_health_factor3","1.0"};
CVAR_REGISTER ( &sk_bigmomma_dmg_slash1 );// {"sk_bigmomma_dmg_slash1","50"};
CVAR_REGISTER ( &sk_bigmomma_dmg_slash2 );// {"sk_bigmomma_dmg_slash2","50"};
CVAR_REGISTER ( &sk_bigmomma_dmg_slash3 );// {"sk_bigmomma_dmg_slash3","50"};
CVAR_REGISTER ( &sk_bigmomma_dmg_blast1 );// {"sk_bigmomma_dmg_blast1","100"};
CVAR_REGISTER ( &sk_bigmomma_dmg_blast2 );// {"sk_bigmomma_dmg_blast2","100"};
CVAR_REGISTER ( &sk_bigmomma_dmg_blast3 );// {"sk_bigmomma_dmg_blast3","100"};
CVAR_REGISTER ( &sk_bigmomma_radius_blast1 );// {"sk_bigmomma_radius_blast1","250"};
CVAR_REGISTER ( &sk_bigmomma_radius_blast2 );// {"sk_bigmomma_radius_blast2","250"};
CVAR_REGISTER ( &sk_bigmomma_radius_blast3 );// {"sk_bigmomma_radius_blast3","250"};
// Gargantua
CVAR_REGISTER ( &sk_gargantua_health1 );// {"sk_gargantua_health1","0"};
CVAR_REGISTER ( &sk_gargantua_health2 );// {"sk_gargantua_health2","0"};
CVAR_REGISTER ( &sk_gargantua_health3 );// {"sk_gargantua_health3","0"};
CVAR_REGISTER ( &sk_gargantua_dmg_slash1 );// {"sk_gargantua_dmg_slash1","0"};
CVAR_REGISTER ( &sk_gargantua_dmg_slash2 );// {"sk_gargantua_dmg_slash2","0"};
CVAR_REGISTER ( &sk_gargantua_dmg_slash3 );// {"sk_gargantua_dmg_slash3","0"};
CVAR_REGISTER ( &sk_gargantua_dmg_fire1 );// {"sk_gargantua_dmg_fire1","0"};
CVAR_REGISTER ( &sk_gargantua_dmg_fire2 );// {"sk_gargantua_dmg_fire2","0"};
CVAR_REGISTER ( &sk_gargantua_dmg_fire3 );// {"sk_gargantua_dmg_fire3","0"};
CVAR_REGISTER ( &sk_gargantua_dmg_stomp1 );// {"sk_gargantua_dmg_stomp1","0"};
CVAR_REGISTER ( &sk_gargantua_dmg_stomp2 );// {"sk_gargantua_dmg_stomp2","0"};
CVAR_REGISTER ( &sk_gargantua_dmg_stomp3 );// {"sk_gargantua_dmg_stomp3","0"};
// Hassassin
CVAR_REGISTER ( &sk_hassassin_health1 );// {"sk_hassassin_health1","0"};
CVAR_REGISTER ( &sk_hassassin_health2 );// {"sk_hassassin_health2","0"};
CVAR_REGISTER ( &sk_hassassin_health3 );// {"sk_hassassin_health3","0"};
// Headcrab
CVAR_REGISTER ( &sk_headcrab_health1 );// {"sk_headcrab_health1","0"};
CVAR_REGISTER ( &sk_headcrab_health2 );// {"sk_headcrab_health2","0"};
CVAR_REGISTER ( &sk_headcrab_health3 );// {"sk_headcrab_health3","0"};
CVAR_REGISTER ( &sk_headcrab_dmg_bite1 );// {"sk_headcrab_dmg_bite1","0"};
CVAR_REGISTER ( &sk_headcrab_dmg_bite2 );// {"sk_headcrab_dmg_bite2","0"};
CVAR_REGISTER ( &sk_headcrab_dmg_bite3 );// {"sk_headcrab_dmg_bite3","0"};
// Hgrunt
CVAR_REGISTER ( &sk_hgrunt_health1 );// {"sk_hgrunt_health1","0"};
CVAR_REGISTER ( &sk_hgrunt_health2 );// {"sk_hgrunt_health2","0"};
CVAR_REGISTER ( &sk_hgrunt_health3 );// {"sk_hgrunt_health3","0"};
CVAR_REGISTER ( &sk_hgrunt_kick1 );// {"sk_hgrunt_kick1","0"};
CVAR_REGISTER ( &sk_hgrunt_kick2 );// {"sk_hgrunt_kick2","0"};
CVAR_REGISTER ( &sk_hgrunt_kick3 );// {"sk_hgrunt_kick3","0"};
CVAR_REGISTER ( &sk_hgrunt_pellets1 );
CVAR_REGISTER ( &sk_hgrunt_pellets2 );
CVAR_REGISTER ( &sk_hgrunt_pellets3 );
CVAR_REGISTER ( &sk_hgrunt_gspeed1 );
CVAR_REGISTER ( &sk_hgrunt_gspeed2 );
CVAR_REGISTER ( &sk_hgrunt_gspeed3 );
// Houndeye
CVAR_REGISTER ( &sk_houndeye_health1 );// {"sk_houndeye_health1","0"};
CVAR_REGISTER ( &sk_houndeye_health2 );// {"sk_houndeye_health2","0"};
CVAR_REGISTER ( &sk_houndeye_health3 );// {"sk_houndeye_health3","0"};
CVAR_REGISTER ( &sk_houndeye_dmg_blast1 );// {"sk_houndeye_dmg_blast1","0"};
CVAR_REGISTER ( &sk_houndeye_dmg_blast2 );// {"sk_houndeye_dmg_blast2","0"};
CVAR_REGISTER ( &sk_houndeye_dmg_blast3 );// {"sk_houndeye_dmg_blast3","0"};
// ISlave
CVAR_REGISTER ( &sk_islave_health1 );// {"sk_islave_health1","0"};
CVAR_REGISTER ( &sk_islave_health2 );// {"sk_islave_health2","0"};
CVAR_REGISTER ( &sk_islave_health3 );// {"sk_islave_health3","0"};
CVAR_REGISTER ( &sk_islave_dmg_claw1 );// {"sk_islave_dmg_claw1","0"};
CVAR_REGISTER ( &sk_islave_dmg_claw2 );// {"sk_islave_dmg_claw2","0"};
CVAR_REGISTER ( &sk_islave_dmg_claw3 );// {"sk_islave_dmg_claw3","0"};
CVAR_REGISTER ( &sk_islave_dmg_clawrake1 );// {"sk_islave_dmg_clawrake1","0"};
CVAR_REGISTER ( &sk_islave_dmg_clawrake2 );// {"sk_islave_dmg_clawrake2","0"};
CVAR_REGISTER ( &sk_islave_dmg_clawrake3 );// {"sk_islave_dmg_clawrake3","0"};
CVAR_REGISTER ( &sk_islave_dmg_zap1 );// {"sk_islave_dmg_zap1","0"};
CVAR_REGISTER ( &sk_islave_dmg_zap2 );// {"sk_islave_dmg_zap2","0"};
CVAR_REGISTER ( &sk_islave_dmg_zap3 );// {"sk_islave_dmg_zap3","0"};
// Icthyosaur
CVAR_REGISTER ( &sk_ichthyosaur_health1 );// {"sk_ichthyosaur_health1","0"};
CVAR_REGISTER ( &sk_ichthyosaur_health2 );// {"sk_ichthyosaur_health2","0"};
CVAR_REGISTER ( &sk_ichthyosaur_health3 );// {"sk_ichthyosaur_health3","0"};
CVAR_REGISTER ( &sk_ichthyosaur_shake1 );// {"sk_ichthyosaur_health3","0"};
CVAR_REGISTER ( &sk_ichthyosaur_shake2 );// {"sk_ichthyosaur_health3","0"};
CVAR_REGISTER ( &sk_ichthyosaur_shake3 );// {"sk_ichthyosaur_health3","0"};
// Leech
CVAR_REGISTER ( &sk_leech_health1 );// {"sk_leech_health1","0"};
CVAR_REGISTER ( &sk_leech_health2 );// {"sk_leech_health2","0"};
CVAR_REGISTER ( &sk_leech_health3 );// {"sk_leech_health3","0"};
CVAR_REGISTER ( &sk_leech_dmg_bite1 );// {"sk_leech_dmg_bite1","0"};
CVAR_REGISTER ( &sk_leech_dmg_bite2 );// {"sk_leech_dmg_bite2","0"};
CVAR_REGISTER ( &sk_leech_dmg_bite3 );// {"sk_leech_dmg_bite3","0"};
// Controller
CVAR_REGISTER ( &sk_controller_health1 );
CVAR_REGISTER ( &sk_controller_health2 );
CVAR_REGISTER ( &sk_controller_health3 );
CVAR_REGISTER ( &sk_controller_dmgzap1 );
CVAR_REGISTER ( &sk_controller_dmgzap2 );
CVAR_REGISTER ( &sk_controller_dmgzap3 );
CVAR_REGISTER ( &sk_controller_speedball1 );
CVAR_REGISTER ( &sk_controller_speedball2 );
CVAR_REGISTER ( &sk_controller_speedball3 );
CVAR_REGISTER ( &sk_controller_dmgball1 );
CVAR_REGISTER ( &sk_controller_dmgball2 );
CVAR_REGISTER ( &sk_controller_dmgball3 );
// Nihilanth
CVAR_REGISTER ( &sk_nihilanth_health1 );// {"sk_nihilanth_health1","0"};
CVAR_REGISTER ( &sk_nihilanth_health2 );// {"sk_nihilanth_health2","0"};
CVAR_REGISTER ( &sk_nihilanth_health3 );// {"sk_nihilanth_health3","0"};
CVAR_REGISTER ( &sk_nihilanth_zap1 );
CVAR_REGISTER ( &sk_nihilanth_zap2 );
CVAR_REGISTER ( &sk_nihilanth_zap3 );
// Scientist
CVAR_REGISTER ( &sk_scientist_health1 );// {"sk_scientist_health1","0"};
CVAR_REGISTER ( &sk_scientist_health2 );// {"sk_scientist_health2","0"};
CVAR_REGISTER ( &sk_scientist_health3 );// {"sk_scientist_health3","0"};
// Snark
CVAR_REGISTER ( &sk_snark_health1 );// {"sk_snark_health1","0"};
CVAR_REGISTER ( &sk_snark_health2 );// {"sk_snark_health2","0"};
CVAR_REGISTER ( &sk_snark_health3 );// {"sk_snark_health3","0"};
CVAR_REGISTER ( &sk_snark_dmg_bite1 );// {"sk_snark_dmg_bite1","0"};
CVAR_REGISTER ( &sk_snark_dmg_bite2 );// {"sk_snark_dmg_bite2","0"};
CVAR_REGISTER ( &sk_snark_dmg_bite3 );// {"sk_snark_dmg_bite3","0"};
CVAR_REGISTER ( &sk_snark_dmg_pop1 );// {"sk_snark_dmg_pop1","0"};
CVAR_REGISTER ( &sk_snark_dmg_pop2 );// {"sk_snark_dmg_pop2","0"};
CVAR_REGISTER ( &sk_snark_dmg_pop3 );// {"sk_snark_dmg_pop3","0"};
// Zombie
CVAR_REGISTER ( &sk_zombie_health1 );// {"sk_zombie_health1","0"};
CVAR_REGISTER ( &sk_zombie_health2 );// {"sk_zombie_health3","0"};
CVAR_REGISTER ( &sk_zombie_health3 );// {"sk_zombie_health3","0"};
CVAR_REGISTER ( &sk_zombie_dmg_one_slash1 );// {"sk_zombie_dmg_one_slash1","0"};
CVAR_REGISTER ( &sk_zombie_dmg_one_slash2 );// {"sk_zombie_dmg_one_slash2","0"};
CVAR_REGISTER ( &sk_zombie_dmg_one_slash3 );// {"sk_zombie_dmg_one_slash3","0"};
CVAR_REGISTER ( &sk_zombie_dmg_both_slash1 );// {"sk_zombie_dmg_both_slash1","0"};
CVAR_REGISTER ( &sk_zombie_dmg_both_slash2 );// {"sk_zombie_dmg_both_slash2","0"};
CVAR_REGISTER ( &sk_zombie_dmg_both_slash3 );// {"sk_zombie_dmg_both_slash3","0"};
//Turret
CVAR_REGISTER ( &sk_turret_health1 );// {"sk_turret_health1","0"};
CVAR_REGISTER ( &sk_turret_health2 );// {"sk_turret_health2","0"};
CVAR_REGISTER ( &sk_turret_health3 );// {"sk_turret_health3","0"};
// MiniTurret
CVAR_REGISTER ( &sk_miniturret_health1 );// {"sk_miniturret_health1","0"};
CVAR_REGISTER ( &sk_miniturret_health2 );// {"sk_miniturret_health2","0"};
CVAR_REGISTER ( &sk_miniturret_health3 );// {"sk_miniturret_health3","0"};
// Sentry Turret
CVAR_REGISTER ( &sk_sentry_health1 );// {"sk_sentry_health1","0"};
CVAR_REGISTER ( &sk_sentry_health2 );// {"sk_sentry_health2","0"};
CVAR_REGISTER ( &sk_sentry_health3 );// {"sk_sentry_health3","0"};
// PLAYER WEAPONS
// Crowbar whack
CVAR_REGISTER ( &sk_plr_crowbar1 );// {"sk_plr_crowbar1","0"};
CVAR_REGISTER ( &sk_plr_crowbar2 );// {"sk_plr_crowbar2","0"};
CVAR_REGISTER ( &sk_plr_crowbar3 );// {"sk_plr_crowbar3","0"};
// Glock Round
CVAR_REGISTER ( &sk_plr_9mm_bullet1 );// {"sk_plr_9mm_bullet1","0"};
CVAR_REGISTER ( &sk_plr_9mm_bullet2 );// {"sk_plr_9mm_bullet2","0"};
CVAR_REGISTER ( &sk_plr_9mm_bullet3 );// {"sk_plr_9mm_bullet3","0"};
// 357 Round
CVAR_REGISTER ( &sk_plr_357_bullet1 );// {"sk_plr_357_bullet1","0"};
CVAR_REGISTER ( &sk_plr_357_bullet2 );// {"sk_plr_357_bullet2","0"};
CVAR_REGISTER ( &sk_plr_357_bullet3 );// {"sk_plr_357_bullet3","0"};
// MP5 Round
CVAR_REGISTER ( &sk_plr_9mmAR_bullet1 );// {"sk_plr_9mmAR_bullet1","0"};
CVAR_REGISTER ( &sk_plr_9mmAR_bullet2 );// {"sk_plr_9mmAR_bullet2","0"};
CVAR_REGISTER ( &sk_plr_9mmAR_bullet3 );// {"sk_plr_9mmAR_bullet3","0"};
// M203 grenade
CVAR_REGISTER ( &sk_plr_9mmAR_grenade1 );// {"sk_plr_9mmAR_grenade1","0"};
CVAR_REGISTER ( &sk_plr_9mmAR_grenade2 );// {"sk_plr_9mmAR_grenade2","0"};
CVAR_REGISTER ( &sk_plr_9mmAR_grenade3 );// {"sk_plr_9mmAR_grenade3","0"};
// Shotgun buckshot
CVAR_REGISTER ( &sk_plr_buckshot1 );// {"sk_plr_buckshot1","0"};
CVAR_REGISTER ( &sk_plr_buckshot2 );// {"sk_plr_buckshot2","0"};
CVAR_REGISTER ( &sk_plr_buckshot3 );// {"sk_plr_buckshot3","0"};
// Crossbow
CVAR_REGISTER ( &sk_plr_xbow_bolt_monster1 );// {"sk_plr_xbow_bolt1","0"};
CVAR_REGISTER ( &sk_plr_xbow_bolt_monster2 );// {"sk_plr_xbow_bolt2","0"};
CVAR_REGISTER ( &sk_plr_xbow_bolt_monster3 );// {"sk_plr_xbow_bolt3","0"};
CVAR_REGISTER ( &sk_plr_xbow_bolt_client1 );// {"sk_plr_xbow_bolt1","0"};
CVAR_REGISTER ( &sk_plr_xbow_bolt_client2 );// {"sk_plr_xbow_bolt2","0"};
CVAR_REGISTER ( &sk_plr_xbow_bolt_client3 );// {"sk_plr_xbow_bolt3","0"};
// RPG
CVAR_REGISTER ( &sk_plr_rpg1 );// {"sk_plr_rpg1","0"};
CVAR_REGISTER ( &sk_plr_rpg2 );// {"sk_plr_rpg2","0"};
CVAR_REGISTER ( &sk_plr_rpg3 );// {"sk_plr_rpg3","0"};
// Gauss Gun
CVAR_REGISTER ( &sk_plr_gauss1 );// {"sk_plr_gauss1","0"};
CVAR_REGISTER ( &sk_plr_gauss2 );// {"sk_plr_gauss2","0"};
CVAR_REGISTER ( &sk_plr_gauss3 );// {"sk_plr_gauss3","0"};
// Egon Gun
CVAR_REGISTER ( &sk_plr_egon_narrow1 );// {"sk_plr_egon_narrow1","0"};
CVAR_REGISTER ( &sk_plr_egon_narrow2 );// {"sk_plr_egon_narrow2","0"};
CVAR_REGISTER ( &sk_plr_egon_narrow3 );// {"sk_plr_egon_narrow3","0"};
CVAR_REGISTER ( &sk_plr_egon_wide1 );// {"sk_plr_egon_wide1","0"};
CVAR_REGISTER ( &sk_plr_egon_wide2 );// {"sk_plr_egon_wide2","0"};
CVAR_REGISTER ( &sk_plr_egon_wide3 );// {"sk_plr_egon_wide3","0"};
// Hand Grendade
CVAR_REGISTER ( &sk_plr_hand_grenade1 );// {"sk_plr_hand_grenade1","0"};
CVAR_REGISTER ( &sk_plr_hand_grenade2 );// {"sk_plr_hand_grenade2","0"};
CVAR_REGISTER ( &sk_plr_hand_grenade3 );// {"sk_plr_hand_grenade3","0"};
// Satchel Charge
CVAR_REGISTER ( &sk_plr_satchel1 );// {"sk_plr_satchel1","0"};
CVAR_REGISTER ( &sk_plr_satchel2 );// {"sk_plr_satchel2","0"};
CVAR_REGISTER ( &sk_plr_satchel3 );// {"sk_plr_satchel3","0"};
// Tripmine
CVAR_REGISTER ( &sk_plr_tripmine1 );// {"sk_plr_tripmine1","0"};
CVAR_REGISTER ( &sk_plr_tripmine2 );// {"sk_plr_tripmine2","0"};
CVAR_REGISTER ( &sk_plr_tripmine3 );// {"sk_plr_tripmine3","0"};
// WORLD WEAPONS
CVAR_REGISTER ( &sk_12mm_bullet1 );// {"sk_12mm_bullet1","0"};
CVAR_REGISTER ( &sk_12mm_bullet2 );// {"sk_12mm_bullet2","0"};
CVAR_REGISTER ( &sk_12mm_bullet3 );// {"sk_12mm_bullet3","0"};
CVAR_REGISTER ( &sk_9mmAR_bullet1 );// {"sk_9mm_bullet1","0"};
CVAR_REGISTER ( &sk_9mmAR_bullet2 );// {"sk_9mm_bullet1","0"};
CVAR_REGISTER ( &sk_9mmAR_bullet3 );// {"sk_9mm_bullet1","0"};
CVAR_REGISTER ( &sk_9mm_bullet1 );// {"sk_9mm_bullet1","0"};
CVAR_REGISTER ( &sk_9mm_bullet2 );// {"sk_9mm_bullet2","0"};
CVAR_REGISTER ( &sk_9mm_bullet3 );// {"sk_9mm_bullet3","0"};
// HORNET
CVAR_REGISTER ( &sk_hornet_dmg1 );// {"sk_hornet_dmg1","0"};
CVAR_REGISTER ( &sk_hornet_dmg2 );// {"sk_hornet_dmg2","0"};
CVAR_REGISTER ( &sk_hornet_dmg3 );// {"sk_hornet_dmg3","0"};
// HEALTH/SUIT CHARGE DISTRIBUTION
CVAR_REGISTER ( &sk_suitcharger1 );
CVAR_REGISTER ( &sk_suitcharger2 );
CVAR_REGISTER ( &sk_suitcharger3 );
CVAR_REGISTER ( &sk_battery1 );
CVAR_REGISTER ( &sk_battery2 );
CVAR_REGISTER ( &sk_battery3 );
CVAR_REGISTER ( &sk_healthcharger1 );
CVAR_REGISTER ( &sk_healthcharger2 );
CVAR_REGISTER ( &sk_healthcharger3 );
CVAR_REGISTER ( &sk_healthkit1 );
CVAR_REGISTER ( &sk_healthkit2 );
CVAR_REGISTER ( &sk_healthkit3 );
CVAR_REGISTER ( &sk_scientist_heal1 );
CVAR_REGISTER ( &sk_scientist_heal2 );
CVAR_REGISTER ( &sk_scientist_heal3 );
// monster damage adjusters
CVAR_REGISTER ( &sk_monster_head1 );
CVAR_REGISTER ( &sk_monster_head2 );
CVAR_REGISTER ( &sk_monster_head3 );
CVAR_REGISTER ( &sk_monster_chest1 );
CVAR_REGISTER ( &sk_monster_chest2 );
CVAR_REGISTER ( &sk_monster_chest3 );
CVAR_REGISTER ( &sk_monster_stomach1 );
CVAR_REGISTER ( &sk_monster_stomach2 );
CVAR_REGISTER ( &sk_monster_stomach3 );
CVAR_REGISTER ( &sk_monster_arm1 );
CVAR_REGISTER ( &sk_monster_arm2 );
CVAR_REGISTER ( &sk_monster_arm3 );
CVAR_REGISTER ( &sk_monster_leg1 );
CVAR_REGISTER ( &sk_monster_leg2 );
CVAR_REGISTER ( &sk_monster_leg3 );
// player damage adjusters
CVAR_REGISTER ( &sk_player_head1 );
CVAR_REGISTER ( &sk_player_head2 );
CVAR_REGISTER ( &sk_player_head3 );
CVAR_REGISTER ( &sk_player_chest1 );
CVAR_REGISTER ( &sk_player_chest2 );
CVAR_REGISTER ( &sk_player_chest3 );
CVAR_REGISTER ( &sk_player_stomach1 );
CVAR_REGISTER ( &sk_player_stomach2 );
CVAR_REGISTER ( &sk_player_stomach3 );
CVAR_REGISTER ( &sk_player_arm1 );
CVAR_REGISTER ( &sk_player_arm2 );
CVAR_REGISTER ( &sk_player_arm3 );
CVAR_REGISTER ( &sk_player_leg1 );
CVAR_REGISTER ( &sk_player_leg2 );
CVAR_REGISTER ( &sk_player_leg3 );
// END REGISTER CVARS FOR SKILL LEVEL STUFF
SERVER_COMMAND( "exec skill.cfg\n" );
}

46
hlsdk/dmc/dlls/game.h Normal file
View File

@ -0,0 +1,46 @@
/***
*
* 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.
*
****/
#ifndef GAME_H
#define GAME_H
extern void GameDLLInit( void );
extern cvar_t displaysoundlist;
extern cvar_t mapcyclefile;
extern cvar_t servercfgfile;
extern cvar_t lservercfgfile;
// multiplayer server rules
extern cvar_t fraglimit;
extern cvar_t timelimit;
extern cvar_t friendlyfir;
extern cvar_t falldamage;
extern cvar_t weaponstay;
extern cvar_t forcerespaw;
extern cvar_t flashlight;
extern cvar_t aimcrosshair;
extern cvar_t decalfrequency;
extern cvar_t teamlist;
extern cvar_t teamoverride;
extern cvar_t defaultteam;
// Engine Cvars
extern cvar_t *g_psv_gravity;
extern cvar_t *g_psv_aim;
extern cvar_t *g_footsteps;
#endif // GAME_H

View File

@ -0,0 +1,179 @@
/***
*
* 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.
*
****/
//=========================================================
// GameRules.cpp
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "teamplay_gamerules.h"
extern Vector g_vecTeleMins[ MAX_TELES ];
extern Vector g_vecTeleMaxs[ MAX_TELES ];
extern int g_iTeleNum;
#include "skill.h"
extern edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer );
DLL_GLOBAL CGameRules* g_pGameRules = NULL;
extern DLL_GLOBAL BOOL g_fGameOver;
extern int gmsgDeathMsg; // client dll messages
extern int gmsgScoreInfo;
extern int gmsgMOTD;
//=========================================================
//=========================================================
BOOL CGameRules::CanHaveAmmo( CBasePlayer *pPlayer, const char *pszAmmoName, int iMaxCarry )
{
int iAmmoIndex;
if ( pszAmmoName )
{
iAmmoIndex = pPlayer->GetAmmoIndex( pszAmmoName );
if ( iAmmoIndex > -1 )
{
if ( pPlayer->AmmoInventory( iAmmoIndex ) < iMaxCarry )
{
// player has room for more of this type of ammo
return TRUE;
}
}
}
return FALSE;
}
//=========================================================
//=========================================================
edict_t *CGameRules :: GetPlayerSpawnSpot( CBasePlayer *pPlayer )
{
edict_t *pentSpawnSpot = EntSelectSpawnPoint( pPlayer );
pPlayer->pev->origin = VARS(pentSpawnSpot)->origin + Vector(0,0,1);
pPlayer->pev->v_angle = g_vecZero;
pPlayer->pev->velocity = g_vecZero;
pPlayer->pev->angles = VARS(pentSpawnSpot)->angles;
pPlayer->pev->punchangle = g_vecZero;
pPlayer->pev->fixangle = TRUE;
return pentSpawnSpot;
}
//=========================================================
//=========================================================
BOOL CGameRules::CanHavePlayerItem( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon )
{
if ( pWeapon->pszAmmo1() )
{
if ( !CanHaveAmmo( pPlayer, pWeapon->pszAmmo1(), pWeapon->iMaxAmmo1() ) )
{
// we can't carry anymore ammo for this gun. We can only
// have the gun if we aren't already carrying one of this type
if ( pPlayer->HasPlayerItem( pWeapon ) )
{
return FALSE;
}
}
}
else
{
// weapon doesn't use ammo, don't take another if you already have it.
if ( pPlayer->HasPlayerItem( pWeapon ) )
{
return FALSE;
}
}
// note: will fall through to here if GetItemInfo doesn't fill the struct!
return TRUE;
}
//=========================================================
// load the SkillData struct with the proper values based on the skill level.
//=========================================================
void CGameRules::RefreshSkillData ( void )
{
int iSkill;
iSkill = (int)CVAR_GET_FLOAT("skill");
if ( iSkill < 1 )
{
iSkill = 1;
}
else if ( iSkill > 3 )
{
iSkill = 3;
}
gSkillData.iSkillLevel = iSkill;
}
//=========================================================
// instantiate the proper game rules object
//=========================================================
CGameRules *InstallGameRules( void )
{
SERVER_COMMAND( "exec game.cfg\n" );
SERVER_EXECUTE( );
//Clear all the teleporters
for ( int i = 0; i < MAX_TELES; i++ )
{
g_vecTeleMins[ i ].x = 0.0;
g_vecTeleMins[ i ].y = 0.0;
g_vecTeleMins[ i ].z = 0.0;
g_vecTeleMaxs[ i ].x = 0.0;
g_vecTeleMaxs[ i ].y = 0.0;
g_vecTeleMaxs[ i ].z = 0.0;
}
g_iTeleNum = 0;
if ( !gpGlobals->deathmatch )
{
// generic half-life
return new CHalfLifeRules;
}
else
{
if ( CVAR_GET_FLOAT( "mp_teamplay" ) > 0 )
{
// teamplay
return new CHalfLifeTeamplay;
}
if ((int)gpGlobals->deathmatch == 1)
{
// vanilla deathmatch
return new CHalfLifeMultiplay;
}
else
{
// vanilla deathmatch??
return new CHalfLifeMultiplay;
}
}
}

370
hlsdk/dmc/dlls/gamerules.h Normal file
View File

@ -0,0 +1,370 @@
/***
*
* 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.
*
****/
//=========================================================
// GameRules
//=========================================================
//#include "weapons.h"
//#include "items.h"
class CBasePlayerItem;
class CBasePlayer;
class CItem;
class CBasePlayerAmmo;
// weapon respawning return codes
enum
{
GR_NONE = 0,
GR_WEAPON_RESPAWN_YES,
GR_WEAPON_RESPAWN_NO,
GR_AMMO_RESPAWN_YES,
GR_AMMO_RESPAWN_NO,
GR_ITEM_RESPAWN_YES,
GR_ITEM_RESPAWN_NO,
GR_PLR_DROP_GUN_ALL,
GR_PLR_DROP_GUN_ACTIVE,
GR_PLR_DROP_GUN_NO,
GR_PLR_DROP_AMMO_ALL,
GR_PLR_DROP_AMMO_ACTIVE,
GR_PLR_DROP_AMMO_NO,
};
// Player relationship return codes
enum
{
GR_NOTTEAMMATE = 0,
GR_TEAMMATE,
GR_ENEMY,
GR_ALLY,
GR_NEUTRAL,
};
class CGameRules
{
public:
virtual void RefreshSkillData( void );// fill skill data struct with proper values
virtual void Think( void ) = 0;// GR_Think - runs every server frame, should handle any timer tasks, periodic events, etc.
virtual BOOL IsAllowedToSpawn( CBaseEntity *pEntity ) = 0; // Can this item spawn (eg monsters don't spawn in deathmatch).
virtual BOOL FAllowFlashlight( void ) = 0;// Are players allowed to switch on their flashlight?
virtual BOOL FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon ) = 0;// should the player switch to this weapon?
virtual BOOL GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon ) = 0;// I can't use this weapon anymore, get me the next best one.
// Functions to verify the single/multiplayer status of a game
virtual BOOL IsMultiplayer( void ) = 0;// is this a multiplayer game? (either coop or deathmatch)
virtual BOOL IsDeathmatch( void ) = 0;//is this a deathmatch game?
virtual BOOL IsTeamplay( void ) { return FALSE; };// is this deathmatch game being played with team rules?
virtual BOOL IsCoOp( void ) = 0;// is this a coop game?
virtual const char *GetGameDescription( void ) { return "DMC"; } // this is the game name that gets seen in the server browser
// Client connection/disconnection
virtual BOOL ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] ) = 0;// a client just connected to the server (player hasn't spawned yet)
virtual void InitHUD( CBasePlayer *pl ) = 0; // the client dll is ready for updating
virtual void ClientDisconnected( edict_t *pClient ) = 0;// a client just disconnected from the server
virtual void UpdateGameMode( CBasePlayer *pPlayer ) {} // the client needs to be informed of the current game mode
// Client damage rules
virtual float FlPlayerFallDamage( CBasePlayer *pPlayer ) = 0;// this client just hit the ground after a fall. How much damage?
virtual BOOL FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker ) {return TRUE;};// can this player take damage from this attacker?
virtual BOOL ShouldAutoAim( CBasePlayer *pPlayer, edict_t *target ) { return TRUE; }
// Client spawn/respawn control
virtual void PlayerSpawn( CBasePlayer *pPlayer ) = 0;// called by CBasePlayer::Spawn just before releasing player into the game
virtual void PlayerThink( CBasePlayer *pPlayer ) = 0; // called by CBasePlayer::PreThink every frame, before physics are run and after keys are accepted
virtual BOOL FPlayerCanRespawn( CBasePlayer *pPlayer ) = 0;// is this player allowed to respawn now?
virtual float FlPlayerSpawnTime( CBasePlayer *pPlayer ) = 0;// When in the future will this player be able to spawn?
virtual edict_t *GetPlayerSpawnSpot( CBasePlayer *pPlayer );// Place this player on their spawnspot and face them the proper direction.
virtual BOOL AllowAutoTargetCrosshair( void ) { return TRUE; };
virtual BOOL ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) { return FALSE; }; // handles the user commands; returns TRUE if command handled properly
virtual void ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer ) {} // the player has changed userinfo; can change it now
// Client kills/scoring
virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ) = 0;// how many points do I award whoever kills this player?
virtual void PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor ) = 0;// Called each time a player dies
virtual void DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor )= 0;// Call this from within a GameRules class to report an obituary.
// Weapon retrieval
virtual BOOL CanHavePlayerItem( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon );// The player is touching an CBasePlayerItem, do I give it to him?
virtual void PlayerGotWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon ) = 0;// Called each time a player picks up a weapon from the ground
// Weapon spawn/respawn control
virtual int WeaponShouldRespawn( CBasePlayerItem *pWeapon ) = 0;// should this weapon respawn?
virtual float FlWeaponRespawnTime( CBasePlayerItem *pWeapon ) = 0;// when may this weapon respawn?
virtual float FlWeaponTryRespawn( CBasePlayerItem *pWeapon ) = 0; // can i respawn now, and if not, when should i try again?
virtual Vector VecWeaponRespawnSpot( CBasePlayerItem *pWeapon ) = 0;// where in the world should this weapon respawn?
// Item retrieval
virtual BOOL CanHaveItem( CBasePlayer *pPlayer, CItem *pItem ) = 0;// is this player allowed to take this item?
virtual void PlayerGotItem( CBasePlayer *pPlayer, CItem *pItem ) = 0;// call each time a player picks up an item (battery, healthkit, longjump)
// Item spawn/respawn control
virtual int ItemShouldRespawn( CItem *pItem ) = 0;// Should this item respawn?
virtual float FlItemRespawnTime( CItem *pItem ) = 0;// when may this item respawn?
virtual Vector VecItemRespawnSpot( CItem *pItem ) = 0;// where in the world should this item respawn?
// Ammo retrieval
virtual BOOL CanHaveAmmo( CBasePlayer *pPlayer, const char *pszAmmoName, int iMaxCarry );// can this player take more of this ammo?
virtual void PlayerGotAmmo( CBasePlayer *pPlayer, char *szName, int iCount ) = 0;// called each time a player picks up some ammo in the world
// Ammo spawn/respawn control
virtual int AmmoShouldRespawn( CBasePlayerAmmo *pAmmo ) = 0;// should this ammo item respawn?
virtual float FlAmmoRespawnTime( CBasePlayerAmmo *pAmmo ) = 0;// when should this ammo item respawn?
virtual Vector VecAmmoRespawnSpot( CBasePlayerAmmo *pAmmo ) = 0;// where in the world should this ammo item respawn?
// by default, everything spawns
// Healthcharger respawn control
virtual float FlHealthChargerRechargeTime( void ) = 0;// how long until a depleted HealthCharger recharges itself?
virtual float FlHEVChargerRechargeTime( void ) { return 0; }// how long until a depleted HealthCharger recharges itself?
// What happens to a dead player's weapons
virtual int DeadPlayerWeapons( CBasePlayer *pPlayer ) = 0;// what do I do with a player's weapons when he's killed?
// What happens to a dead player's ammo
virtual int DeadPlayerAmmo( CBasePlayer *pPlayer ) = 0;// Do I drop ammo when the player dies? How much?
// Teamplay stuff
virtual const char *GetTeamID( CBaseEntity *pEntity ) = 0;// what team is this entity on?
virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ) = 0;// What is the player's relationship with this entity?
virtual int GetTeamIndex( const char *pTeamName ) { return -1; }
virtual const char *GetIndexedTeamName( int teamIndex ) { return ""; }
virtual BOOL IsValidTeam( const char *pTeamName ) { return TRUE; }
virtual void ChangePlayerTeam( CBasePlayer *pPlayer, const char *pTeamName, BOOL bKill, BOOL bGib ) {}
virtual const char *SetDefaultPlayerTeam( CBasePlayer *pPlayer ) { return ""; }
// Sounds
virtual BOOL PlayTextureSounds( void ) { return TRUE; }
virtual BOOL PlayFootstepSounds( CBasePlayer *pl, float fvol ) { return TRUE; }
// Monsters
virtual BOOL FAllowMonsters( void ) = 0;//are monsters allowed
// Immediately end a multiplayer game
virtual void EndMultiplayerGame( void ) {}
};
extern CGameRules *InstallGameRules( void );
//=========================================================
// CHalfLifeRules - rules for the single player Half-Life
// game.
//=========================================================
class CHalfLifeRules : public CGameRules
{
public:
CHalfLifeRules ( void );
// GR_Think
virtual void Think( void );
virtual BOOL IsAllowedToSpawn( CBaseEntity *pEntity );
virtual BOOL FAllowFlashlight( void ) { return TRUE; };
virtual BOOL FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon );
virtual BOOL GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon );
// Functions to verify the single/multiplayer status of a game
virtual BOOL IsMultiplayer( void );
virtual BOOL IsDeathmatch( void );
virtual BOOL IsCoOp( void );
// Client connection/disconnection
virtual BOOL ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] );
virtual void InitHUD( CBasePlayer *pl ); // the client dll is ready for updating
virtual void ClientDisconnected( edict_t *pClient );
// Client damage rules
virtual float FlPlayerFallDamage( CBasePlayer *pPlayer );
// Client spawn/respawn control
virtual void PlayerSpawn( CBasePlayer *pPlayer );
virtual void PlayerThink( CBasePlayer *pPlayer );
virtual BOOL FPlayerCanRespawn( CBasePlayer *pPlayer );
virtual float FlPlayerSpawnTime( CBasePlayer *pPlayer );
virtual BOOL AllowAutoTargetCrosshair( void );
// Client kills/scoring
virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled );
virtual void PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor );
virtual void DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor );
// Weapon retrieval
virtual void PlayerGotWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon );
// Weapon spawn/respawn control
virtual int WeaponShouldRespawn( CBasePlayerItem *pWeapon );
virtual float FlWeaponRespawnTime( CBasePlayerItem *pWeapon );
virtual float FlWeaponTryRespawn( CBasePlayerItem *pWeapon );
virtual Vector VecWeaponRespawnSpot( CBasePlayerItem *pWeapon );
// Item retrieval
virtual BOOL CanHaveItem( CBasePlayer *pPlayer, CItem *pItem );
virtual void PlayerGotItem( CBasePlayer *pPlayer, CItem *pItem );
// Item spawn/respawn control
virtual int ItemShouldRespawn( CItem *pItem );
virtual float FlItemRespawnTime( CItem *pItem );
virtual Vector VecItemRespawnSpot( CItem *pItem );
// Ammo retrieval
virtual void PlayerGotAmmo( CBasePlayer *pPlayer, char *szName, int iCount );
// Ammo spawn/respawn control
virtual int AmmoShouldRespawn( CBasePlayerAmmo *pAmmo );
virtual float FlAmmoRespawnTime( CBasePlayerAmmo *pAmmo );
virtual Vector VecAmmoRespawnSpot( CBasePlayerAmmo *pAmmo );
// Healthcharger respawn control
virtual float FlHealthChargerRechargeTime( void );
// What happens to a dead player's weapons
virtual int DeadPlayerWeapons( CBasePlayer *pPlayer );
// What happens to a dead player's ammo
virtual int DeadPlayerAmmo( CBasePlayer *pPlayer );
// Monsters
virtual BOOL FAllowMonsters( void );
// Teamplay stuff
virtual const char *GetTeamID( CBaseEntity *pEntity ) {return "";};
virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget );
};
#include "voice_gamemgr.h"
//=========================================================
// CHalfLifeMultiplay - rules for the basic half life multiplayer
// competition
//=========================================================
class CHalfLifeMultiplay : public CGameRules
{
public:
CHalfLifeMultiplay();
virtual BOOL ClientCommand( CBasePlayer *pPlayer, const char *pcmd );
// GR_Think
virtual void Think( void );
virtual void RefreshSkillData( void );
virtual BOOL IsAllowedToSpawn( CBaseEntity *pEntity );
virtual BOOL FAllowFlashlight( void );
virtual BOOL FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon );
virtual BOOL GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon );
// Functions to verify the single/multiplayer status of a game
virtual BOOL IsMultiplayer( void );
virtual BOOL IsDeathmatch( void );
virtual BOOL IsCoOp( void );
// Client connection/disconnection
// If ClientConnected returns FALSE, the connection is rejected and the user is provided the reason specified in
// svRejectReason
// Only the client's name and remote address are provided to the dll for verification.
virtual BOOL ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] );
virtual void InitHUD( CBasePlayer *pl ); // the client dll is ready for updating
virtual void ClientDisconnected( edict_t *pClient );
virtual void UpdateGameMode( CBasePlayer *pPlayer ); // the client needs to be informed of the current game mode
// Client damage rules
virtual float FlPlayerFallDamage( CBasePlayer *pPlayer );
virtual BOOL FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker );
// Client spawn/respawn control
virtual void PlayerSpawn( CBasePlayer *pPlayer );
virtual void PlayerThink( CBasePlayer *pPlayer );
virtual BOOL FPlayerCanRespawn( CBasePlayer *pPlayer );
virtual float FlPlayerSpawnTime( CBasePlayer *pPlayer );
virtual edict_t *GetPlayerSpawnSpot( CBasePlayer *pPlayer );
virtual BOOL AllowAutoTargetCrosshair( void );
// Client kills/scoring
virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled );
virtual void PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor );
virtual void DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor );
// Weapon retrieval
virtual void PlayerGotWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon );
virtual BOOL CanHavePlayerItem( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon );// The player is touching an CBasePlayerItem, do I give it to him?
// Weapon spawn/respawn control
virtual int WeaponShouldRespawn( CBasePlayerItem *pWeapon );
virtual float FlWeaponRespawnTime( CBasePlayerItem *pWeapon );
virtual float FlWeaponTryRespawn( CBasePlayerItem *pWeapon );
virtual Vector VecWeaponRespawnSpot( CBasePlayerItem *pWeapon );
// Item retrieval
virtual BOOL CanHaveItem( CBasePlayer *pPlayer, CItem *pItem );
virtual void PlayerGotItem( CBasePlayer *pPlayer, CItem *pItem );
// Item spawn/respawn control
virtual int ItemShouldRespawn( CItem *pItem );
virtual float FlItemRespawnTime( CItem *pItem );
virtual Vector VecItemRespawnSpot( CItem *pItem );
// Ammo retrieval
virtual void PlayerGotAmmo( CBasePlayer *pPlayer, char *szName, int iCount );
// Ammo spawn/respawn control
virtual int AmmoShouldRespawn( CBasePlayerAmmo *pAmmo );
virtual float FlAmmoRespawnTime( CBasePlayerAmmo *pAmmo );
virtual Vector VecAmmoRespawnSpot( CBasePlayerAmmo *pAmmo );
// Healthcharger respawn control
virtual float FlHealthChargerRechargeTime( void );
virtual float FlHEVChargerRechargeTime( void );
// What happens to a dead player's weapons
virtual int DeadPlayerWeapons( CBasePlayer *pPlayer );
// What happens to a dead player's ammo
virtual int DeadPlayerAmmo( CBasePlayer *pPlayer );
// Teamplay stuff
virtual const char *GetTeamID( CBaseEntity *pEntity ) {return "";}
virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget );
virtual BOOL PlayTextureSounds( void ) { return FALSE; }
virtual BOOL PlayFootstepSounds( CBasePlayer *pl, float fvol );
// Monsters
virtual BOOL FAllowMonsters( void );
// Immediately end a multiplayer game
virtual void EndMultiplayerGame( void ) { GoToIntermission(); }
CVoiceGameMgr m_VoiceGameMgr;
protected:
virtual void ChangeLevel( void );
virtual void GoToIntermission( void );
float m_flIntermissionEndTime;
float m_flIntermissionStartTime;
BOOL m_iEndIntermissionButtonHit;
void SendMOTDToClient( edict_t *client );
float m_flGameEndTime;
virtual void ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer );
};
extern DLL_GLOBAL CGameRules* g_pGameRules;

View File

@ -0,0 +1,39 @@
/***
*
* 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.
*
****/
/*
===== globals.cpp ========================================================
DLL-wide global variable definitions.
They're all defined here, for convenient centralization.
Source files that need them should "extern ..." declare each
variable, to better document what globals they care about.
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "soundent.h"
DLL_GLOBAL ULONG g_ulFrameCount;
DLL_GLOBAL ULONG g_ulModelIndexEyes;
DLL_GLOBAL ULONG g_ulModelIndexPlayer;
DLL_GLOBAL Vector g_vecAttackDir;
DLL_GLOBAL int g_iSkillLevel;
DLL_GLOBAL int gDisplayTitle;
DLL_GLOBAL BOOL g_fGameOver;
DLL_GLOBAL const Vector g_vecZero = Vector(0,0,0);
DLL_GLOBAL int g_Language;

198
hlsdk/dmc/dlls/h_ai.cpp Normal file
View File

@ -0,0 +1,198 @@
/***
*
* 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.
*
****/
/*
h_ai.cpp - halflife specific ai code
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#define NUM_LATERAL_CHECKS 13 // how many checks are made on each side of a monster looking for lateral cover
#define NUM_LATERAL_LOS_CHECKS 6 // how many checks are made on each side of a monster looking for lateral cover
//float flRandom = RANDOM_FLOAT(0,1);
DLL_GLOBAL BOOL g_fDrawLines = FALSE;
//=========================================================
//
// AI UTILITY FUNCTIONS
//
// !!!UNDONE - move CBaseMonster functions to monsters.cpp
//=========================================================
//=========================================================
// FBoxVisible - a more accurate ( and slower ) version
// of FVisible.
//
// !!!UNDONE - make this CBaseMonster?
//=========================================================
BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget, Vector &vecTargetOrigin, float flSize )
{
// don't look through water
if ((pevLooker->waterlevel != 3 && pevTarget->waterlevel == 3)
|| (pevLooker->waterlevel == 3 && pevTarget->waterlevel == 0))
return FALSE;
TraceResult tr;
Vector vecLookerOrigin = pevLooker->origin + pevLooker->view_ofs;//look through the monster's 'eyes'
for (int i = 0; i < 5; i++)
{
Vector vecTarget = pevTarget->origin;
vecTarget.x += RANDOM_FLOAT( pevTarget->mins.x + flSize, pevTarget->maxs.x - flSize);
vecTarget.y += RANDOM_FLOAT( pevTarget->mins.y + flSize, pevTarget->maxs.y - flSize);
vecTarget.z += RANDOM_FLOAT( pevTarget->mins.z + flSize, pevTarget->maxs.z - flSize);
UTIL_TraceLine(vecLookerOrigin, vecTarget, ignore_monsters, ignore_glass, ENT(pevLooker)/*pentIgnore*/, &tr);
if (tr.flFraction == 1.0)
{
vecTargetOrigin = vecTarget;
return TRUE;// line of sight is valid.
}
}
return FALSE;// Line of sight is not established
}
//
// VecCheckToss - returns the velocity at which an object should be lobbed from vecspot1 to land near vecspot2.
// returns g_vecZero if toss is not feasible.
//
Vector VecCheckToss ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flGravityAdj )
{
TraceResult tr;
Vector vecMidPoint;// halfway point between Spot1 and Spot2
Vector vecApex;// highest point
Vector vecScale;
Vector vecGrenadeVel;
Vector vecTemp;
float flGravity = CVAR_GET_FLOAT( "sv_gravity" ) * flGravityAdj;
if (vecSpot2.z - vecSpot1.z > 500)
{
// to high, fail
return g_vecZero;
}
UTIL_MakeVectors (pev->angles);
// toss a little bit to the left or right, not right down on the enemy's bean (head).
vecSpot2 = vecSpot2 + gpGlobals->v_right * ( RANDOM_FLOAT(-8,8) + RANDOM_FLOAT(-16,16) );
vecSpot2 = vecSpot2 + gpGlobals->v_forward * ( RANDOM_FLOAT(-8,8) + RANDOM_FLOAT(-16,16) );
// calculate the midpoint and apex of the 'triangle'
// UNDONE: normalize any Z position differences between spot1 and spot2 so that triangle is always RIGHT
// How much time does it take to get there?
// get a rough idea of how high it can be thrown
vecMidPoint = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5;
UTIL_TraceLine(vecMidPoint, vecMidPoint + Vector(0,0,500), ignore_monsters, ENT(pev), &tr);
vecMidPoint = tr.vecEndPos;
// (subtract 15 so the grenade doesn't hit the ceiling)
vecMidPoint.z -= 15;
if (vecMidPoint.z < vecSpot1.z || vecMidPoint.z < vecSpot2.z)
{
// to not enough space, fail
return g_vecZero;
}
// How high should the grenade travel to reach the apex
float distance1 = (vecMidPoint.z - vecSpot1.z);
float distance2 = (vecMidPoint.z - vecSpot2.z);
// How long will it take for the grenade to travel this distance
float time1 = sqrt( distance1 / (0.5 * flGravity) );
float time2 = sqrt( distance2 / (0.5 * flGravity) );
if (time1 < 0.1)
{
// too close
return g_vecZero;
}
// how hard to throw sideways to get there in time.
vecGrenadeVel = (vecSpot2 - vecSpot1) / (time1 + time2);
// how hard upwards to reach the apex at the right time.
vecGrenadeVel.z = flGravity * time1;
// find the apex
vecApex = vecSpot1 + vecGrenadeVel * time1;
vecApex.z = vecMidPoint.z;
UTIL_TraceLine(vecSpot1, vecApex, dont_ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0)
{
// fail!
return g_vecZero;
}
// UNDONE: either ignore monsters or change it to not care if we hit our enemy
UTIL_TraceLine(vecSpot2, vecApex, ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0)
{
// fail!
return g_vecZero;
}
return vecGrenadeVel;
}
//
// VecCheckThrow - returns the velocity vector at which an object should be thrown from vecspot1 to hit vecspot2.
// returns g_vecZero if throw is not feasible.
//
Vector VecCheckThrow ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj )
{
float flGravity = CVAR_GET_FLOAT( "sv_gravity" ) * flGravityAdj;
Vector vecGrenadeVel = (vecSpot2 - vecSpot1);
// throw at a constant time
float time = vecGrenadeVel.Length( ) / flSpeed;
vecGrenadeVel = vecGrenadeVel * (1.0 / time);
// adjust upward toss to compensate for gravity loss
vecGrenadeVel.z += flGravity * time * 0.5;
Vector vecApex = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5;
vecApex.z += 0.5 * flGravity * (time * 0.5) * (time * 0.5);
TraceResult tr;
UTIL_TraceLine(vecSpot1, vecApex, dont_ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0)
{
// fail!
return g_vecZero;
}
UTIL_TraceLine(vecSpot2, vecApex, ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0)
{
// fail!
return g_vecZero;
}
return vecGrenadeVel;
}

View File

@ -0,0 +1,69 @@
/***
*
* 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.
*
****/
/*
===== h_export.cpp ========================================================
Entity classes exported by Halflife.
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
// Holds engine functionality callbacks
enginefuncs_t g_engfuncs;
globalvars_t *gpGlobals;
#ifdef _WIN32
// Required DLL entry point
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
}
return TRUE;
}
void DLLEXPORT GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals )
{
memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t));
gpGlobals = pGlobals;
}
#else
extern "C" {
void GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals )
{
memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t));
gpGlobals = pGlobals;
}
}
#endif

337
hlsdk/dmc/dlls/items.cpp Normal file
View File

@ -0,0 +1,337 @@
/***
*
* 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.
*
****/
/*
===== items.cpp ========================================================
functions governing the selection/use of weapons for players
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "weapons.h"
#include "player.h"
#include "skill.h"
#include "items.h"
#include "gamerules.h"
extern int gmsgItemPickup;
class CWorldItem : public CBaseEntity
{
public:
void KeyValue(KeyValueData *pkvd );
void Spawn( void );
int m_iType;
};
LINK_ENTITY_TO_CLASS(world_items, CWorldItem);
void CWorldItem::KeyValue(KeyValueData *pkvd)
{
if (FStrEq(pkvd->szKeyName, "type"))
{
m_iType = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CBaseEntity::KeyValue( pkvd );
}
void CWorldItem::Spawn( void )
{
CBaseEntity *pEntity = NULL;
switch (m_iType)
{
case 44: // ITEM_BATTERY:
pEntity = CBaseEntity::Create( "item_battery", pev->origin, pev->angles );
break;
case 42: // ITEM_ANTIDOTE:
pEntity = CBaseEntity::Create( "item_antidote", pev->origin, pev->angles );
break;
case 43: // ITEM_SECURITY:
pEntity = CBaseEntity::Create( "item_security", pev->origin, pev->angles );
break;
case 45: // ITEM_SUIT:
pEntity = CBaseEntity::Create( "item_suit", pev->origin, pev->angles );
break;
}
if (!pEntity)
{
ALERT( at_console, "unable to create world_item %d\n", m_iType );
}
else
{
pEntity->pev->target = pev->target;
pEntity->pev->targetname = pev->targetname;
pEntity->pev->spawnflags = pev->spawnflags;
}
REMOVE_ENTITY(edict());
}
void CItem::Spawn( void )
{
pev->movetype = MOVETYPE_TOSS;
pev->solid = SOLID_TRIGGER;
UTIL_SetOrigin( pev, pev->origin );
UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 16));
SetTouch(&CItem::ItemTouch);
if (DROP_TO_FLOOR(ENT(pev)) == 0)
{
ALERT(at_error, "Item %s fell out of level at %f,%f,%f", STRING( pev->classname ), pev->origin.x, pev->origin.y, pev->origin.z);
UTIL_Remove( this );
return;
}
}
extern int gEvilImpulse101;
void CItem::ItemTouch( CBaseEntity *pOther )
{
// if it's not a player, ignore
if ( !pOther->IsPlayer() )
{
return;
}
CBasePlayer *pPlayer = (CBasePlayer *)pOther;
// ok, a player is touching this item, but can he have it?
if ( !g_pGameRules->CanHaveItem( pPlayer, this ) )
{
// no? Ignore the touch.
return;
}
if (MyTouch( pPlayer ))
{
SUB_UseTargets( pOther, USE_TOGGLE, 0 );
SetTouch( NULL );
// player grabbed the item.
g_pGameRules->PlayerGotItem( pPlayer, this );
if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_YES )
{
Respawn();
}
else
{
UTIL_Remove( this );
}
}
else if (gEvilImpulse101)
{
UTIL_Remove( this );
}
}
CBaseEntity* CItem::Respawn( void )
{
SetTouch( NULL );
pev->effects |= EF_NODRAW;
UTIL_SetOrigin( pev, g_pGameRules->VecItemRespawnSpot( this ) );// blip to whereever you should respawn.
SetThink ( &CItem::Materialize );
pev->nextthink = g_pGameRules->FlItemRespawnTime( this );
return this;
}
void CItem::Materialize( void )
{
if ( pev->effects & EF_NODRAW )
{
// changing from invisible state to visible.
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "items/suitchargeok1.wav", 1, ATTN_NORM, 0, 150 );
pev->effects &= ~EF_NODRAW;
pev->effects |= EF_MUZZLEFLASH;
}
SetTouch( &CItem::ItemTouch );
}
#define SF_SUIT_SHORTLOGON 0x0001
class CItemSuit : public CItem
{
void Spawn( void )
{
Precache( );
SET_MODEL(ENT(pev), "models/w_suit.mdl");
CItem::Spawn( );
}
void Precache( void )
{
PRECACHE_MODEL ("models/w_suit.mdl");
}
BOOL MyTouch( CBasePlayer *pPlayer )
{
if ( pPlayer->pev->weapons & (1<<WEAPON_SUIT) )
return FALSE;
if ( pev->spawnflags & SF_SUIT_SHORTLOGON )
EMIT_SOUND_SUIT(pPlayer->edict(), "!HEV_A0"); // short version of suit logon,
else
EMIT_SOUND_SUIT(pPlayer->edict(), "!HEV_AAx"); // long version of suit logon
pPlayer->pev->weapons |= (1<<WEAPON_SUIT);
return TRUE;
}
};
LINK_ENTITY_TO_CLASS(item_suit, CItemSuit);
class CItemBattery : public CItem
{
void Spawn( void )
{
Precache( );
SET_MODEL(ENT(pev), "models/w_battery.mdl");
CItem::Spawn( );
}
void Precache( void )
{
PRECACHE_MODEL ("models/w_battery.mdl");
PRECACHE_SOUND( "items/gunpickup2.wav" );
}
BOOL MyTouch( CBasePlayer *pPlayer )
{
if ((pPlayer->pev->armorvalue < MAX_NORMAL_BATTERY) &&
(pPlayer->pev->weapons & (1<<WEAPON_SUIT)))
{
int pct;
char szcharge[64];
pPlayer->pev->armorvalue += gSkillData.batteryCapacity;
pPlayer->pev->armorvalue = min(pPlayer->pev->armorvalue, MAX_NORMAL_BATTERY);
EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM );
MESSAGE_BEGIN( MSG_ONE, gmsgItemPickup, NULL, pPlayer->pev );
WRITE_STRING( STRING(pev->classname) );
MESSAGE_END();
// Suit reports new power level
// For some reason this wasn't working in release build -- round it.
pct = (int)( (float)(pPlayer->pev->armorvalue * 100.0) * (1.0/MAX_NORMAL_BATTERY) + 0.5);
pct = (pct / 5);
if (pct > 0)
pct--;
sprintf( szcharge,"!HEV_%1dP", pct );
//EMIT_SOUND_SUIT(ENT(pev), szcharge);
pPlayer->SetSuitUpdate(szcharge, FALSE, SUIT_NEXT_IN_30SEC);
return TRUE;
}
return FALSE;
}
};
LINK_ENTITY_TO_CLASS(item_battery, CItemBattery);
class CItemAntidote : public CItem
{
void Spawn( void )
{
Precache( );
SET_MODEL(ENT(pev), "models/w_antidote.mdl");
CItem::Spawn( );
}
void Precache( void )
{
PRECACHE_MODEL ("models/w_antidote.mdl");
}
BOOL MyTouch( CBasePlayer *pPlayer )
{
pPlayer->SetSuitUpdate("!HEV_DET4", FALSE, SUIT_NEXT_IN_1MIN);
pPlayer->m_rgItems[ITEM_ANTIDOTE] += 1;
return TRUE;
}
};
LINK_ENTITY_TO_CLASS(item_antidote, CItemAntidote);
class CItemSecurity : public CItem
{
void Spawn( void )
{
Precache( );
SET_MODEL(ENT(pev), "models/w_security.mdl");
CItem::Spawn( );
}
void Precache( void )
{
PRECACHE_MODEL ("models/w_security.mdl");
}
BOOL MyTouch( CBasePlayer *pPlayer )
{
pPlayer->m_rgItems[ITEM_SECURITY] += 1;
return TRUE;
}
};
LINK_ENTITY_TO_CLASS(item_security, CItemSecurity);
class CItemLongJump : public CItem
{
void Spawn( void )
{
Precache( );
SET_MODEL(ENT(pev), "models/w_longjump.mdl");
CItem::Spawn( );
}
void Precache( void )
{
PRECACHE_MODEL ("models/w_longjump.mdl");
}
BOOL MyTouch( CBasePlayer *pPlayer )
{
if ( pPlayer->m_fLongJump )
{
return FALSE;
}
if ( ( pPlayer->pev->weapons & (1<<WEAPON_SUIT) ) )
{
pPlayer->m_fLongJump = TRUE;// player now has longjump module
g_engfuncs.pfnSetPhysicsKeyValue( pPlayer->edict(), "slj", "1" );
MESSAGE_BEGIN( MSG_ONE, gmsgItemPickup, NULL, pPlayer->pev );
WRITE_STRING( STRING(pev->classname) );
MESSAGE_END();
EMIT_SOUND_SUIT( pPlayer->edict(), "!HEV_A1" ); // Play the longjump sound UNDONE: Kelly? correct sound?
return TRUE;
}
return FALSE;
}
};
LINK_ENTITY_TO_CLASS( item_longjump, CItemLongJump );

29
hlsdk/dmc/dlls/items.h Normal file
View File

@ -0,0 +1,29 @@
/***
*
* 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.
*
****/
#ifndef ITEMS_H
#define ITEMS_H
class CItem : public CBaseEntity
{
public:
void Spawn( void );
CBaseEntity* Respawn( void );
void EXPORT ItemTouch( CBaseEntity *pOther );
void EXPORT Materialize( void );
virtual BOOL MyTouch( CBasePlayer *pPlayer ) { return FALSE; };
};
#endif // ITEMS_H

199
hlsdk/dmc/dlls/lights.cpp Normal file
View File

@ -0,0 +1,199 @@
/***
*
* 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.
*
****/
/*
===== lights.cpp ========================================================
spawn and think functions for editor-placed lights
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
class CLight : public CPointEntity
{
public:
virtual void KeyValue( KeyValueData* pkvd );
virtual void Spawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
private:
int m_iStyle;
int m_iszPattern;
};
LINK_ENTITY_TO_CLASS( light, CLight );
TYPEDESCRIPTION CLight::m_SaveData[] =
{
DEFINE_FIELD( CLight, m_iStyle, FIELD_INTEGER ),
DEFINE_FIELD( CLight, m_iszPattern, FIELD_STRING ),
};
IMPLEMENT_SAVERESTORE( CLight, CPointEntity );
//
// Cache user-entity-field values until spawn is called.
//
void CLight :: KeyValue( KeyValueData* pkvd)
{
if (FStrEq(pkvd->szKeyName, "style"))
{
m_iStyle = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "pitch"))
{
pev->angles.x = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "pattern"))
{
m_iszPattern = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else
{
CPointEntity::KeyValue( pkvd );
}
}
/*QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) LIGHT_START_OFF
Non-displayed light.
Default light value is 300
Default style is 0
If targeted, it will toggle between on or off.
*/
void CLight :: Spawn( void )
{
if (FStringNull(pev->targetname))
{ // inert light
REMOVE_ENTITY(ENT(pev));
return;
}
if (m_iStyle >= 32)
{
// CHANGE_METHOD(ENT(pev), em_use, light_use);
if (FBitSet(pev->spawnflags, SF_LIGHT_START_OFF))
LIGHT_STYLE(m_iStyle, "a");
else if (m_iszPattern)
LIGHT_STYLE(m_iStyle, (char *)STRING( m_iszPattern ));
else
LIGHT_STYLE(m_iStyle, "m");
}
}
void CLight :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if (m_iStyle >= 32)
{
if ( !ShouldToggle( useType, !FBitSet(pev->spawnflags, SF_LIGHT_START_OFF) ) )
return;
if (FBitSet(pev->spawnflags, SF_LIGHT_START_OFF))
{
if (m_iszPattern)
LIGHT_STYLE(m_iStyle, (char *)STRING( m_iszPattern ));
else
LIGHT_STYLE(m_iStyle, "m");
ClearBits(pev->spawnflags, SF_LIGHT_START_OFF);
}
else
{
LIGHT_STYLE(m_iStyle, "a");
SetBits(pev->spawnflags, SF_LIGHT_START_OFF);
}
}
}
//
// shut up spawn functions for new spotlights
//
LINK_ENTITY_TO_CLASS( light_spot, CLight );
class CEnvLight : public CLight
{
public:
void KeyValue( KeyValueData* pkvd );
void Spawn( void );
};
LINK_ENTITY_TO_CLASS( light_environment, CEnvLight );
void CEnvLight::KeyValue( KeyValueData* pkvd )
{
if (FStrEq(pkvd->szKeyName, "_light"))
{
int r, g, b, v, j;
char szColor[64];
j = sscanf( pkvd->szValue, "%d %d %d %d\n", &r, &g, &b, &v );
if (j == 1)
{
g = b = r;
}
else if (j == 4)
{
r = r * (v / 255);
g = g * (v / 255);
b = b * (v / 255);
}
// simulate qrad direct, ambient,and gamma adjustments, as well as engine scaling
r = static_cast<int>(powf( r / 114.0f, 0.6f ) * 264);
g = static_cast<int>(powf( g / 114.0f, 0.6f ) * 264);
b = static_cast<int>(powf( b / 114.0f, 0.6f ) * 264);
pkvd->fHandled = TRUE;
sprintf( szColor, "%d", r );
CVAR_SET_STRING( "sv_skycolor_r", szColor );
sprintf( szColor, "%d", g );
CVAR_SET_STRING( "sv_skycolor_g", szColor );
sprintf( szColor, "%d", b );
CVAR_SET_STRING( "sv_skycolor_b", szColor );
}
else
{
CLight::KeyValue( pkvd );
}
}
void CEnvLight :: Spawn( void )
{
char szVector[64];
UTIL_MakeAimVectors( pev->angles );
sprintf( szVector, "%f", gpGlobals->v_forward.x );
CVAR_SET_STRING( "sv_skyvec_x", szVector );
sprintf( szVector, "%f", gpGlobals->v_forward.y );
CVAR_SET_STRING( "sv_skyvec_y", szVector );
sprintf( szVector, "%f", gpGlobals->v_forward.z );
CVAR_SET_STRING( "sv_skyvec_z", szVector );
CLight::Spawn( );
}

918
hlsdk/dmc/dlls/maprules.cpp Normal file
View File

@ -0,0 +1,918 @@
/***
*
* 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.
*
****/
// -------------------------------------------
//
// maprules.cpp
//
// This module contains entities for implementing/changing game
// rules dynamically within each map (.BSP)
//
// -------------------------------------------
#include "extdll.h"
#include "eiface.h"
#include "util.h"
#include "gamerules.h"
#include "maprules.h"
#include "cbase.h"
#include "player.h"
class CRuleEntity : public CBaseEntity
{
public:
void Spawn( void );
void KeyValue( KeyValueData *pkvd );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
void SetMaster( int iszMaster ) { m_iszMaster = iszMaster; }
protected:
BOOL CanFireForActivator( CBaseEntity *pActivator );
private:
string_t m_iszMaster;
};
TYPEDESCRIPTION CRuleEntity::m_SaveData[] =
{
DEFINE_FIELD( CRuleEntity, m_iszMaster, FIELD_STRING),
};
IMPLEMENT_SAVERESTORE( CRuleEntity, CBaseEntity );
void CRuleEntity::Spawn( void )
{
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NONE;
pev->effects = EF_NODRAW;
}
void CRuleEntity::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "master"))
{
SetMaster( ALLOC_STRING(pkvd->szValue) );
pkvd->fHandled = TRUE;
}
else
CBaseEntity::KeyValue( pkvd );
}
BOOL CRuleEntity::CanFireForActivator( CBaseEntity *pActivator )
{
if ( m_iszMaster )
{
if ( UTIL_IsMasterTriggered( m_iszMaster, pActivator ) )
return TRUE;
else
return FALSE;
}
return TRUE;
}
//
// CRulePointEntity -- base class for all rule "point" entities (not brushes)
//
class CRulePointEntity : public CRuleEntity
{
public:
void Spawn( void );
};
void CRulePointEntity::Spawn( void )
{
CRuleEntity::Spawn();
pev->frame = 0;
pev->model = 0;
}
//
// CRuleBrushEntity -- base class for all rule "brush" entities (not brushes)
// Default behavior is to set up like a trigger, invisible, but keep the model for volume testing
//
class CRuleBrushEntity : public CRuleEntity
{
public:
void Spawn( void );
private:
};
void CRuleBrushEntity::Spawn( void )
{
SET_MODEL( edict(), STRING(pev->model) );
CRuleEntity::Spawn();
}
// CGameScore / game_score -- award points to player / team
// Points +/- total
// Flag: Allow negative scores SF_SCORE_NEGATIVE
// Flag: Award points to team in teamplay SF_SCORE_TEAM
#define SF_SCORE_NEGATIVE 0x0001
#define SF_SCORE_TEAM 0x0002
class CGameScore : public CRulePointEntity
{
public:
void Spawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void KeyValue( KeyValueData *pkvd );
inline int Points( void ) { return static_cast<int>(pev->frags); }
inline BOOL AllowNegativeScore( void ) { return pev->spawnflags & SF_SCORE_NEGATIVE; }
inline BOOL AwardToTeam( void ) { return pev->spawnflags & SF_SCORE_TEAM; }
inline void SetPoints( int points ) { pev->frags = points; }
private:
};
LINK_ENTITY_TO_CLASS( game_score, CGameScore );
void CGameScore::Spawn( void )
{
CRulePointEntity::Spawn();
}
void CGameScore::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "points"))
{
SetPoints( atoi(pkvd->szValue) );
pkvd->fHandled = TRUE;
}
else
CRulePointEntity::KeyValue( pkvd );
}
void CGameScore::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
// Only players can use this
if ( pActivator->IsPlayer() )
{
if ( AwardToTeam() )
{
pActivator->AddPointsToTeam( Points(), AllowNegativeScore() );
}
else
{
pActivator->AddPoints( Points(), AllowNegativeScore() );
}
}
}
// CGameEnd / game_end -- Ends the game in MP
class CGameEnd : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
private:
};
LINK_ENTITY_TO_CLASS( game_end, CGameEnd );
void CGameEnd::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
g_pGameRules->EndMultiplayerGame();
}
//
// CGameText / game_text -- NON-Localized HUD Message (use env_message to display a titles.txt message)
// Flag: All players SF_ENVTEXT_ALLPLAYERS
//
#define SF_ENVTEXT_ALLPLAYERS 0x0001
class CGameText : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void KeyValue( KeyValueData *pkvd );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
inline BOOL MessageToAll( void ) { return (pev->spawnflags & SF_ENVTEXT_ALLPLAYERS); }
inline void MessageSet( const char *pMessage ) { pev->message = ALLOC_STRING(pMessage); }
inline const char *MessageGet( void ) { return STRING(pev->message); }
private:
hudtextparms_t m_textParms;
};
LINK_ENTITY_TO_CLASS( game_text, CGameText );
// Save parms as a block. Will break save/restore if the structure changes, but this entity didn't ship with Half-Life, so
// it can't impact saved Half-Life games.
TYPEDESCRIPTION CGameText::m_SaveData[] =
{
DEFINE_ARRAY( CGameText, m_textParms, FIELD_CHARACTER, sizeof(hudtextparms_t) ),
};
IMPLEMENT_SAVERESTORE( CGameText, CRulePointEntity );
void CGameText::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "channel"))
{
m_textParms.channel = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "x"))
{
m_textParms.x = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "y"))
{
m_textParms.y = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "effect"))
{
m_textParms.effect = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "color"))
{
int color[4];
UTIL_StringToIntArray( color, 4, pkvd->szValue );
m_textParms.r1 = color[0];
m_textParms.g1 = color[1];
m_textParms.b1 = color[2];
m_textParms.a1 = color[3];
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "color2"))
{
int color[4];
UTIL_StringToIntArray( color, 4, pkvd->szValue );
m_textParms.r2 = color[0];
m_textParms.g2 = color[1];
m_textParms.b2 = color[2];
m_textParms.a2 = color[3];
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fadein"))
{
m_textParms.fadeinTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fadeout"))
{
m_textParms.fadeoutTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "holdtime"))
{
m_textParms.holdTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fxtime"))
{
m_textParms.fxTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else
CRulePointEntity::KeyValue( pkvd );
}
void CGameText::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
if ( MessageToAll() )
{
UTIL_HudMessageAll( m_textParms, MessageGet() );
}
else
{
if ( pActivator->IsNetClient() )
{
UTIL_HudMessage( pActivator, m_textParms, MessageGet() );
}
}
}
//
// CGameTeamMaster / game_team_master -- "Masters" like multisource, but based on the team of the activator
// Only allows mastered entity to fire if the team matches my team
//
// team index (pulled from server team list "mp_teamlist"
// Flag: Remove on Fire
// Flag: Any team until set? -- Any team can use this until the team is set (otherwise no teams can use it)
//
#define SF_TEAMMASTER_FIREONCE 0x0001
#define SF_TEAMMASTER_ANYTEAM 0x0002
class CGameTeamMaster : public CRulePointEntity
{
public:
void KeyValue( KeyValueData *pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
int ObjectCaps( void ) { return CRulePointEntity:: ObjectCaps() | FCAP_MASTER; }
BOOL IsTriggered( CBaseEntity *pActivator );
const char *TeamID( void );
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_TEAMMASTER_FIREONCE) ? TRUE : FALSE; }
inline BOOL AnyTeam( void ) { return (pev->spawnflags & SF_TEAMMASTER_ANYTEAM) ? TRUE : FALSE; }
private:
BOOL TeamMatch( CBaseEntity *pActivator );
int m_teamIndex;
USE_TYPE triggerType;
};
LINK_ENTITY_TO_CLASS( game_team_master, CGameTeamMaster );
void CGameTeamMaster::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "teamindex"))
{
m_teamIndex = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "triggerstate"))
{
int type = atoi( pkvd->szValue );
switch( type )
{
case 0:
triggerType = USE_OFF;
break;
case 2:
triggerType = USE_TOGGLE;
break;
default:
triggerType = USE_ON;
break;
}
pkvd->fHandled = TRUE;
}
else
CRulePointEntity::KeyValue( pkvd );
}
void CGameTeamMaster::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
if ( useType == USE_SET )
{
if ( value < 0 )
{
m_teamIndex = -1;
}
else
{
m_teamIndex = g_pGameRules->GetTeamIndex( pActivator->TeamID() );
}
return;
}
if ( TeamMatch( pActivator ) )
{
SUB_UseTargets( pActivator, triggerType, value );
if ( RemoveOnFire() )
UTIL_Remove( this );
}
}
BOOL CGameTeamMaster::IsTriggered( CBaseEntity *pActivator )
{
return TeamMatch( pActivator );
}
const char *CGameTeamMaster::TeamID( void )
{
if ( m_teamIndex < 0 ) // Currently set to "no team"
return "";
return g_pGameRules->GetIndexedTeamName( m_teamIndex ); // UNDONE: Fill this in with the team from the "teamlist"
}
BOOL CGameTeamMaster::TeamMatch( CBaseEntity *pActivator )
{
if ( m_teamIndex < 0 && AnyTeam() )
return TRUE;
if ( !pActivator )
return FALSE;
return UTIL_TeamsMatch( pActivator->TeamID(), TeamID() );
}
//
// CGameTeamSet / game_team_set -- Changes the team of the entity it targets to the activator's team
// Flag: Fire once
// Flag: Clear team -- Sets the team to "NONE" instead of activator
#define SF_TEAMSET_FIREONCE 0x0001
#define SF_TEAMSET_CLEARTEAM 0x0002
class CGameTeamSet : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_TEAMSET_FIREONCE) ? TRUE : FALSE; }
inline BOOL ShouldClearTeam( void ) { return (pev->spawnflags & SF_TEAMSET_CLEARTEAM) ? TRUE : FALSE; }
private:
};
LINK_ENTITY_TO_CLASS( game_team_set, CGameTeamSet );
void CGameTeamSet::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
if ( ShouldClearTeam() )
{
SUB_UseTargets( pActivator, USE_SET, -1 );
}
else
{
SUB_UseTargets( pActivator, USE_SET, 0 );
}
if ( RemoveOnFire() )
{
UTIL_Remove( this );
}
}
//
// CGamePlayerZone / game_player_zone -- players in the zone fire my target when I'm fired
//
// Needs master?
class CGamePlayerZone : public CRuleBrushEntity
{
public:
void KeyValue( KeyValueData *pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
private:
string_t m_iszInTarget;
string_t m_iszOutTarget;
string_t m_iszInCount;
string_t m_iszOutCount;
};
LINK_ENTITY_TO_CLASS( game_zone_player, CGamePlayerZone );
TYPEDESCRIPTION CGamePlayerZone::m_SaveData[] =
{
DEFINE_FIELD( CGamePlayerZone, m_iszInTarget, FIELD_STRING ),
DEFINE_FIELD( CGamePlayerZone, m_iszOutTarget, FIELD_STRING ),
DEFINE_FIELD( CGamePlayerZone, m_iszInCount, FIELD_STRING ),
DEFINE_FIELD( CGamePlayerZone, m_iszOutCount, FIELD_STRING ),
};
IMPLEMENT_SAVERESTORE( CGamePlayerZone, CRuleBrushEntity );
void CGamePlayerZone::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "intarget"))
{
m_iszInTarget = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "outtarget"))
{
m_iszOutTarget = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "incount"))
{
m_iszInCount = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "outcount"))
{
m_iszOutCount = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else
CRuleBrushEntity::KeyValue( pkvd );
}
void CGamePlayerZone::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
int playersInCount = 0;
int playersOutCount = 0;
if ( !CanFireForActivator( pActivator ) )
return;
CBaseEntity *pPlayer = NULL;
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
pPlayer = UTIL_PlayerByIndex( i );
if ( pPlayer )
{
TraceResult trace;
int hullNumber;
hullNumber = human_hull;
if ( pPlayer->pev->flags & FL_DUCKING )
{
hullNumber = head_hull;
}
UTIL_TraceModel( pPlayer->pev->origin, pPlayer->pev->origin, hullNumber, edict(), &trace );
if ( trace.fStartSolid )
{
playersInCount++;
if ( m_iszInTarget )
{
FireTargets( STRING(m_iszInTarget), pPlayer, pActivator, useType, value );
}
}
else
{
playersOutCount++;
if ( m_iszOutTarget )
{
FireTargets( STRING(m_iszOutTarget), pPlayer, pActivator, useType, value );
}
}
}
}
if ( m_iszInCount )
{
FireTargets( STRING(m_iszInCount), pActivator, this, USE_SET, playersInCount );
}
if ( m_iszOutCount )
{
FireTargets( STRING(m_iszOutCount), pActivator, this, USE_SET, playersOutCount );
}
}
//
// CGamePlayerHurt / game_player_hurt -- Damages the player who fires it
// Flag: Fire once
#define SF_PKILL_FIREONCE 0x0001
class CGamePlayerHurt : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_PKILL_FIREONCE) ? TRUE : FALSE; }
private:
};
LINK_ENTITY_TO_CLASS( game_player_hurt, CGamePlayerHurt );
void CGamePlayerHurt::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
if ( pActivator->IsPlayer() )
{
if ( pev->dmg < 0 )
pActivator->TakeHealth( -pev->dmg, DMG_GENERIC );
else
pActivator->TakeDamage( pev, pev, pev->dmg, DMG_GENERIC );
}
SUB_UseTargets( pActivator, useType, value );
if ( RemoveOnFire() )
{
UTIL_Remove( this );
}
}
//
// CGameCounter / game_counter -- Counts events and fires target
// Flag: Fire once
// Flag: Reset on Fire
#define SF_GAMECOUNT_FIREONCE 0x0001
#define SF_GAMECOUNT_RESET 0x0002
class CGameCounter : public CRulePointEntity
{
public:
void Spawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_GAMECOUNT_FIREONCE) ? TRUE : FALSE; }
inline BOOL ResetOnFire( void ) { return (pev->spawnflags & SF_GAMECOUNT_RESET) ? TRUE : FALSE; }
inline void CountUp( void ) { pev->frags++; }
inline void CountDown( void ) { pev->frags--; }
inline void ResetCount( void ) { pev->frags = pev->dmg; }
inline int CountValue( void ) { return static_cast<int>(pev->frags); }
inline int LimitValue( void ) { return static_cast<int>(pev->health); }
inline BOOL HitLimit( void ) { return CountValue() == LimitValue(); }
private:
inline void SetCountValue( int value ) { pev->frags = value; }
inline void SetInitialValue( int value ) { pev->dmg = value; }
};
LINK_ENTITY_TO_CLASS( game_counter, CGameCounter );
void CGameCounter::Spawn( void )
{
// Save off the initial count
SetInitialValue( CountValue() );
CRulePointEntity::Spawn();
}
void CGameCounter::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
switch( useType )
{
case USE_ON:
case USE_TOGGLE:
CountUp();
break;
case USE_OFF:
CountDown();
break;
case USE_SET:
SetCountValue( (int)value );
break;
}
if ( HitLimit() )
{
SUB_UseTargets( pActivator, USE_TOGGLE, 0 );
if ( RemoveOnFire() )
{
UTIL_Remove( this );
}
if ( ResetOnFire() )
{
ResetCount();
}
}
}
//
// CGameCounterSet / game_counter_set -- Sets the counter's value
// Flag: Fire once
#define SF_GAMECOUNTSET_FIREONCE 0x0001
class CGameCounterSet : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_GAMECOUNTSET_FIREONCE) ? TRUE : FALSE; }
private:
};
LINK_ENTITY_TO_CLASS( game_counter_set, CGameCounterSet );
void CGameCounterSet::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
SUB_UseTargets( pActivator, USE_SET, pev->frags );
if ( RemoveOnFire() )
{
UTIL_Remove( this );
}
}
//
// CGamePlayerEquip / game_playerequip -- Sets the default player equipment
// Flag: USE Only
#define SF_PLAYEREQUIP_USEONLY 0x0001
#define MAX_EQUIP 32
class CGamePlayerEquip : public CRulePointEntity
{
public:
void KeyValue( KeyValueData *pkvd );
void Touch( CBaseEntity *pOther );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
inline BOOL UseOnly( void ) { return (pev->spawnflags & SF_PLAYEREQUIP_USEONLY) ? TRUE : FALSE; }
private:
void EquipPlayer( CBaseEntity *pPlayer );
string_t m_weaponNames[MAX_EQUIP];
int m_weaponCount[MAX_EQUIP];
};
LINK_ENTITY_TO_CLASS( game_player_equip, CGamePlayerEquip );
void CGamePlayerEquip::KeyValue( KeyValueData *pkvd )
{
CRulePointEntity::KeyValue( pkvd );
if ( !pkvd->fHandled )
{
for ( int i = 0; i < MAX_EQUIP; i++ )
{
if ( !m_weaponNames[i] )
{
char tmp[128];
UTIL_StripToken( pkvd->szKeyName, tmp );
m_weaponNames[i] = ALLOC_STRING(tmp);
m_weaponCount[i] = atoi(pkvd->szValue);
m_weaponCount[i] = max(1,m_weaponCount[i]);
pkvd->fHandled = TRUE;
break;
}
}
}
}
void CGamePlayerEquip::Touch( CBaseEntity *pOther )
{
if ( !CanFireForActivator( pOther ) )
return;
if ( UseOnly() )
return;
EquipPlayer( pOther );
}
void CGamePlayerEquip::EquipPlayer( CBaseEntity *pEntity )
{
CBasePlayer *pPlayer = NULL;
if ( pEntity->IsPlayer() )
{
pPlayer = (CBasePlayer *)pEntity;
}
if ( !pPlayer )
return;
for ( int i = 0; i < MAX_EQUIP; i++ )
{
if ( !m_weaponNames[i] )
break;
for ( int j = 0; j < m_weaponCount[i]; j++ )
{
pPlayer->GiveNamedItem( STRING(m_weaponNames[i]) );
}
}
}
void CGamePlayerEquip::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
EquipPlayer( pActivator );
}
//
// CGamePlayerTeam / game_player_team -- Changes the team of the player who fired it
// Flag: Fire once
// Flag: Kill Player
// Flag: Gib Player
#define SF_PTEAM_FIREONCE 0x0001
#define SF_PTEAM_KILL 0x0002
#define SF_PTEAM_GIB 0x0004
class CGamePlayerTeam : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
private:
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_PTEAM_FIREONCE) ? TRUE : FALSE; }
inline BOOL ShouldKillPlayer( void ) { return (pev->spawnflags & SF_PTEAM_KILL) ? TRUE : FALSE; }
inline BOOL ShouldGibPlayer( void ) { return (pev->spawnflags & SF_PTEAM_GIB) ? TRUE : FALSE; }
const char *TargetTeamName( const char *pszTargetName );
};
LINK_ENTITY_TO_CLASS( game_player_team, CGamePlayerTeam );
const char *CGamePlayerTeam::TargetTeamName( const char *pszTargetName )
{
CBaseEntity *pTeamEntity = NULL;
while ((pTeamEntity = UTIL_FindEntityByTargetname( pTeamEntity, pszTargetName )) != NULL)
{
if ( FClassnameIs( pTeamEntity->pev, "game_team_master" ) )
return pTeamEntity->TeamID();
}
return NULL;
}
void CGamePlayerTeam::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
if ( pActivator->IsPlayer() )
{
const char *pszTargetTeam = TargetTeamName( STRING(pev->target) );
if ( pszTargetTeam )
{
CBasePlayer *pPlayer = (CBasePlayer *)pActivator;
g_pGameRules->ChangePlayerTeam( pPlayer, pszTargetTeam, ShouldKillPlayer(), ShouldGibPlayer() );
}
}
if ( RemoveOnFire() )
{
UTIL_Remove( this );
}
}

22
hlsdk/dmc/dlls/maprules.h Normal file
View File

@ -0,0 +1,22 @@
/***
*
* 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.
*
****/
#ifndef MAPRULES_H
#define MAPRULES_H
#endif // MAPRULES_H

View File

@ -0,0 +1,34 @@
/***
*
* 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.
*
****/
#ifndef MONSTEREVENT_H
#define MONSTEREVENT_H
typedef struct
{
int event;
char *options;
} MonsterEvent_t;
#define EVENT_SPECIFIC 0
#define EVENT_SCRIPTED 1000
#define EVENT_SHARED 2000
#define EVENT_CLIENT 5000
#define MONSTER_EVENT_BODYDROP_LIGHT 2001
#define MONSTER_EVENT_BODYDROP_HEAVY 2002
#define MONSTER_EVENT_SWISHSOUND 2010
#endif // MONSTEREVENT_H

134
hlsdk/dmc/dlls/monsters.cpp Normal file
View File

@ -0,0 +1,134 @@
/***
*
* 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.
*
* 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.
*
****/
/*
===== monsters.cpp ========================================================
Monster-related utility code
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "nodes.h"
#include "monsters.h"
CBaseEntity* CBaseMonster :: CheckTraceHullAttack( float flDist, int iDamage, int iDmgType ) { return NULL; }
void CBaseMonster :: Eat ( float flFullDuration ) { }
BOOL CBaseMonster :: FShouldEat ( void ) { return TRUE; }
void CBaseMonster :: BarnacleVictimBitten ( entvars_t *pevBarnacle ) { }
void CBaseMonster :: BarnacleVictimReleased ( void ) { }
void CBaseMonster :: Listen ( void ) { }
float CBaseMonster :: FLSoundVolume ( CSound *pSound ) { return 0.0; }
BOOL CBaseMonster :: FValidateHintType ( short sHint ) { return FALSE; }
void CBaseMonster :: Look ( int iDistance ) { }
int CBaseMonster :: ISoundMask ( void ) { return 0; }
CSound* CBaseMonster :: PBestSound ( void ) { return NULL; }
CSound* CBaseMonster :: PBestScent ( void ) { return NULL; }
void CBaseMonster :: MonsterThink ( void ) { }
void CBaseMonster :: MonsterUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { }
int CBaseMonster :: IgnoreConditions ( void ) { return 0; }
void CBaseMonster :: RouteClear ( void ) { }
void CBaseMonster :: RouteNew ( void ) { }
BOOL CBaseMonster :: FRouteClear ( void ) { return FALSE; }
BOOL CBaseMonster :: FRefreshRoute ( void ) { return 0; }
BOOL CBaseMonster::MoveToEnemy( Activity movementAct, float waitTime ) { return FALSE; }
BOOL CBaseMonster::MoveToLocation( Activity movementAct, float waitTime, const Vector &goal ) { return FALSE; }
BOOL CBaseMonster::MoveToTarget( Activity movementAct, float waitTime ) { return FALSE; }
BOOL CBaseMonster::MoveToNode( Activity movementAct, float waitTime, const Vector &goal ) { return FALSE; }
int ShouldSimplify( int routeType ) { return TRUE; }
void CBaseMonster :: RouteSimplify( CBaseEntity *pTargetEnt ) { }
BOOL CBaseMonster :: FBecomeProne ( void ) { return TRUE; }
BOOL CBaseMonster :: CheckRangeAttack1 ( float flDot, float flDist ) { return FALSE; }
BOOL CBaseMonster :: CheckRangeAttack2 ( float flDot, float flDist ) { return FALSE; }
BOOL CBaseMonster :: CheckMeleeAttack1 ( float flDot, float flDist ) { return FALSE; }
BOOL CBaseMonster :: CheckMeleeAttack2 ( float flDot, float flDist ) { return FALSE; }
void CBaseMonster :: CheckAttacks ( CBaseEntity *pTarget, float flDist ) { }
BOOL CBaseMonster :: FCanCheckAttacks ( void ) { return FALSE; }
int CBaseMonster :: CheckEnemy ( CBaseEntity *pEnemy ) { return 0; }
void CBaseMonster :: PushEnemy( CBaseEntity *pEnemy, Vector &vecLastKnownPos ) { }
BOOL CBaseMonster :: PopEnemy( ) { return FALSE; }
void CBaseMonster :: SetActivity ( Activity NewActivity ) { }
void CBaseMonster :: SetSequenceByName ( char *szSequence ) { }
int CBaseMonster :: CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, CBaseEntity *pTarget, float *pflDist ) { return 0; }
float CBaseMonster :: OpenDoorAndWait( entvars_t *pevDoor ) { return 0.0; }
void CBaseMonster :: AdvanceRoute ( float distance ) { }
int CBaseMonster :: RouteClassify( int iMoveFlag ) { return 0; }
BOOL CBaseMonster :: BuildRoute ( const Vector &vecGoal, int iMoveFlag, CBaseEntity *pTarget ) { return FALSE; }
void CBaseMonster :: InsertWaypoint ( Vector vecLocation, int afMoveFlags ) { }
BOOL CBaseMonster :: FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, CBaseEntity *pTargetEnt, Vector *pApex ) { return FALSE; }
void CBaseMonster :: Move ( float flInterval ) { }
BOOL CBaseMonster:: ShouldAdvanceRoute( float flWaypointDist ) { return FALSE; }
void CBaseMonster::MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval ) { }
void CBaseMonster :: MonsterInit ( void ) { }
void CBaseMonster :: MonsterInitThink ( void ) { }
void CBaseMonster :: StartMonster ( void ) { }
void CBaseMonster :: MovementComplete( void ) { }
int CBaseMonster::TaskIsRunning( void ) { return 0; }
int CBaseMonster::IRelationship ( CBaseEntity *pTarget ) { return 0; }
BOOL CBaseMonster :: FindCover ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist ) { return FALSE; }
BOOL CBaseMonster :: BuildNearestRoute ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist ) { return FALSE; }
CBaseEntity *CBaseMonster :: BestVisibleEnemy ( void ) { return NULL; }
BOOL CBaseMonster :: FInViewCone ( CBaseEntity *pEntity ) { return FALSE; }
BOOL CBaseMonster :: FInViewCone ( Vector *pOrigin ) { return FALSE; }
BOOL CBaseEntity :: FVisible ( CBaseEntity *pEntity ) { return FALSE; }
BOOL CBaseEntity :: FVisible ( const Vector &vecOrigin ) { return FALSE; }
void CBaseMonster :: MakeIdealYaw( Vector vecTarget ) { }
float CBaseMonster::FlYawDiff ( void ) { return 0.0; }
float CBaseMonster::ChangeYaw ( int yawSpeed ) { return 0; }
float CBaseMonster::VecToYaw ( Vector vecDir ) { return 0.0; }
void CBaseMonster :: SetEyePosition ( void ) { }
void CBaseMonster :: HandleAnimEvent( MonsterEvent_t *pEvent ) { }
Vector CBaseMonster :: GetGunPosition( void ) { return g_vecZero; }
void CBaseEntity::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker ) { }
BOOL CBaseMonster :: FGetNodeRoute ( Vector vecDest ) { return TRUE; }
int CBaseMonster :: FindHintNode ( void ) { return NO_NODE; }
void CBaseMonster::ReportAIState( void ) { }
void CBaseMonster :: KeyValue( KeyValueData *pkvd ) { }
BOOL CBaseMonster :: FCheckAITrigger ( void ) { return FALSE; }
int CBaseMonster :: CanPlaySequence( BOOL fDisregardMonsterState, int interruptLevel ) { return FALSE; }
BOOL CBaseMonster :: FindLateralCover ( const Vector &vecThreat, const Vector &vecViewOffset ) { return FALSE; }
Vector CBaseMonster :: ShootAtEnemy( const Vector &shootOrigin ) { return g_vecZero; }
BOOL CBaseMonster :: FacingIdeal( void ) { return FALSE; }
BOOL CBaseMonster :: FCanActiveIdle ( void ) { return FALSE; }
void CBaseMonster::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ) { }
void CBaseMonster::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ) { }
void CBaseMonster::SentenceStop( void ) { }
void CBaseMonster::CorpseFallThink( void ) { }
void CBaseMonster :: MonsterInitDead( void ) { }
BOOL CBaseMonster :: BBoxFlat ( void ) { return TRUE; }
BOOL CBaseMonster :: GetEnemy ( void ) { return FALSE; }
void CBaseMonster :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
CBaseEntity* CBaseMonster :: DropItem ( char *pszItemName, const Vector &vecPos, const Vector &vecAng ) { return NULL; }
BOOL CBaseMonster :: ShouldFadeOnDeath( void ) { return FALSE; }
void CBaseMonster::FadeMonster( void ) { }
BOOL CBaseMonster :: HasHumanGibs( void ) { return TRUE; }
BOOL CBaseMonster :: HasAlienGibs( void ) { return FALSE; }
MONSTERSTATE CBaseMonster :: GetIdealState ( void ) { return MONSTERSTATE_ALERT; }
Schedule_t* CBaseMonster :: GetScheduleOfType ( int Type ) { return NULL; }
Schedule_t *CBaseMonster :: GetSchedule ( void ) { return NULL; }
void CBaseMonster :: RunTask ( Task_t *pTask ) { }
void CBaseMonster :: StartTask ( Task_t *pTask ) { }
Schedule_t *CBaseMonster::ScheduleFromName( const char *pName ) { return NULL;}
void CBaseMonster::BecomeDead( void ) {}
void CBaseMonster :: RunAI ( void ) {}
void CBaseMonster :: Killed( entvars_t *pevAttacker, int iGib ) {}
int CBaseMonster :: TakeHealth (float flHealth, int bitsDamageType) { return 0; }
int CBaseMonster::Restore( class CRestore & ) { return 1; }
int CBaseMonster::Save( class CSave & ) { return 1; }

183
hlsdk/dmc/dlls/monsters.h Normal file
View File

@ -0,0 +1,183 @@
/***
*
* 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.
*
* 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.
*
****/
#ifndef MONSTERS_H
#include "skill.h"
#define MONSTERS_H
/*
===== monsters.h ========================================================
Header file for monster-related utility code
*/
// CHECKLOCALMOVE result types
#define LOCALMOVE_INVALID 0 // move is not possible
#define LOCALMOVE_INVALID_DONT_TRIANGULATE 1 // move is not possible, don't try to triangulate
#define LOCALMOVE_VALID 2 // move is possible
// Hit Group standards
#define HITGROUP_GENERIC 0
#define HITGROUP_HEAD 1
#define HITGROUP_CHEST 2
#define HITGROUP_STOMACH 3
#define HITGROUP_LEFTARM 4
#define HITGROUP_RIGHTARM 5
#define HITGROUP_LEFTLEG 6
#define HITGROUP_RIGHTLEG 7
// Monster Spawnflags
#define SF_MONSTER_WAIT_TILL_SEEN 1// spawnflag that makes monsters wait until player can see them before attacking.
#define SF_MONSTER_GAG 2 // no idle noises from this monster
#define SF_MONSTER_HITMONSTERCLIP 4
// 8
#define SF_MONSTER_PRISONER 16 // monster won't attack anyone, no one will attacke him.
// 32
// 64
#define SF_MONSTER_WAIT_FOR_SCRIPT 128 //spawnflag that makes monsters wait to check for attacking until the script is done or they've been attacked
#define SF_MONSTER_PREDISASTER 256 //this is a predisaster scientist or barney. Influences how they speak.
#define SF_MONSTER_FADECORPSE 512 // Fade out corpse after death
#define SF_MONSTER_FALL_TO_GROUND 0x80000000
// specialty spawnflags
#define SF_MONSTER_TURRET_AUTOACTIVATE 32
#define SF_MONSTER_TURRET_STARTINACTIVE 64
#define SF_MONSTER_WAIT_UNTIL_PROVOKED 64 // don't attack the player unless provoked
// MoveToOrigin stuff
#define MOVE_START_TURN_DIST 64 // when this far away from moveGoal, start turning to face next goal
#define MOVE_STUCK_DIST 32 // if a monster can't step this far, it is stuck.
// MoveToOrigin stuff
#define MOVE_NORMAL 0// normal move in the direction monster is facing
#define MOVE_STRAFE 1// moves in direction specified, no matter which way monster is facing
// spawn flags 256 and above are already taken by the engine
extern void UTIL_MoveToOrigin( edict_t* pent, const Vector &vecGoal, float flDist, int iMoveType );
Vector VecCheckToss ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flGravityAdj = 1.0 );
Vector VecCheckThrow ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj = 1.0 );
extern DLL_GLOBAL Vector g_vecAttackDir;
extern DLL_GLOBAL CONSTANT float g_flMeleeRange;
extern DLL_GLOBAL CONSTANT float g_flMediumRange;
extern DLL_GLOBAL CONSTANT float g_flLongRange;
extern void EjectBrass (const Vector &vecOrigin, const Vector &vecVelocity, float rotation, int model, int soundtype );
extern void ExplodeModel( const Vector &vecOrigin, float speed, int model, int count );
BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget );
BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget, Vector &vecTargetOrigin, float flSize = 0.0 );
// monster to monster relationship types
#define R_AL -2 // (ALLY) pals. Good alternative to R_NO when applicable.
#define R_FR -1// (FEAR)will run
#define R_NO 0// (NO RELATIONSHIP) disregard
#define R_DL 1// (DISLIKE) will attack
#define R_HT 2// (HATE)will attack this character instead of any visible DISLIKEd characters
#define R_NM 3// (NEMESIS) A monster Will ALWAYS attack its nemsis, no matter what
// these bits represent the monster's memory
#define MEMORY_CLEAR 0
#define bits_MEMORY_PROVOKED ( 1 << 0 )// right now only used for houndeyes.
#define bits_MEMORY_INCOVER ( 1 << 1 )// monster knows it is in a covered position.
#define bits_MEMORY_SUSPICIOUS ( 1 << 2 )// Ally is suspicious of the player, and will move to provoked more easily
#define bits_MEMORY_PATH_FINISHED ( 1 << 3 )// Finished monster path (just used by big momma for now)
#define bits_MEMORY_ON_PATH ( 1 << 4 )// Moving on a path
#define bits_MEMORY_MOVE_FAILED ( 1 << 5 )// Movement has already failed
#define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched
#define bits_MEMORY_KILLED ( 1 << 7 )// HACKHACK -- remember that I've already called my Killed()
#define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // Monster-specific memory
#define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // Monster-specific memory
#define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // Monster-specific memory
#define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // Monster-specific memory
// trigger conditions for scripted AI
// these MUST match the CHOICES interface in halflife.fgd for the base monster
enum
{
AITRIGGER_NONE = 0,
AITRIGGER_SEEPLAYER_ANGRY_AT_PLAYER,
AITRIGGER_TAKEDAMAGE,
AITRIGGER_HALFHEALTH,
AITRIGGER_DEATH,
AITRIGGER_SQUADMEMBERDIE,
AITRIGGER_SQUADLEADERDIE,
AITRIGGER_HEARWORLD,
AITRIGGER_HEARPLAYER,
AITRIGGER_HEARCOMBAT,
AITRIGGER_SEEPLAYER_UNCONDITIONAL,
AITRIGGER_SEEPLAYER_NOT_IN_COMBAT,
};
/*
0 : "No Trigger"
1 : "See Player"
2 : "Take Damage"
3 : "50% Health Remaining"
4 : "Death"
5 : "Squad Member Dead"
6 : "Squad Leader Dead"
7 : "Hear World"
8 : "Hear Player"
9 : "Hear Combat"
*/
//
// A gib is a chunk of a body, or a piece of wood/metal/rocks/etc.
//
class CGib : public CBaseEntity
{
public:
void Spawn( const char *szGibModel );
void EXPORT BounceGibTouch ( CBaseEntity *pOther );
void EXPORT StickyGibTouch ( CBaseEntity *pOther );
void EXPORT WaitTillLand( void );
void LimitVelocity( void );
virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DONT_SAVE; }
static void SpawnHeadGib( entvars_t *pevVictim );
static void SpawnRandomGibs( entvars_t *pevVictim, int cGibs, int human );
static void SpawnStickyGibs( entvars_t *pevVictim, Vector vecOrigin, int cGibs );
int m_bloodColor;
int m_cBloodDecals;
int m_material;
float m_lifeTime;
};
#define CUSTOM_SCHEDULES\
virtual Schedule_t *ScheduleFromName( const char *pName );\
static Schedule_t *m_scheduleList[];
#define DEFINE_CUSTOM_SCHEDULES(derivedClass)\
Schedule_t *derivedClass::m_scheduleList[] =
#define IMPLEMENT_CUSTOM_SCHEDULES(derivedClass, baseClass)\
Schedule_t *derivedClass::ScheduleFromName( const char *pName )\
{\
Schedule_t *pSchedule = ScheduleInList( pName, m_scheduleList, ARRAYSIZE(m_scheduleList) );\
if ( !pSchedule )\
return baseClass::ScheduleFromName(pName);\
return pSchedule;\
}
#endif //MONSTERS_H

View File

@ -0,0 +1,28 @@
/***
*
* 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.
*
* 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.
*
****/
//=========================================================
// monsterstate.cpp - base class monster functions for
// controlling core AI.
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "nodes.h"
#include "monsters.h"
#include "animation.h"
#include "saverestore.h"
void CBaseMonster :: SetState ( MONSTERSTATE State ) { };

View File

@ -0,0 +1,469 @@
# Microsoft Developer Studio Project File - Name="dmc" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=dmc - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "dmc.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "dmc.mak" CFG="dmc - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "dmc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "dmc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "dmc - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir ".\Release"
# PROP BASE Intermediate_Dir ".\Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\Releasedmc"
# PROP Intermediate_Dir ".\Releasedmc"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /MT /W3 /Zi /O2 /I "..\..\..\engine" /I "..\..\..\common" /I "." /I "..\..\..\game_shared" /I "..\..\dlls" /I "..\..\pm_shared" /I "..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "QUIVER" /D "VOXEL" /D "QUAKE2" /D "VALVE_DLL" /Fr /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /debug /machine:I386 /def:"..\dmc.def"
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "dmc - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir ".\dmc___Win"
# PROP BASE Intermediate_Dir ".\dmc___Win"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\Debugdmc"
# PROP Intermediate_Dir ".\Debugdmc"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /MTd /W3 /Gm /ZI /Od /I "." /I "..\..\..\game_shared" /I "..\..\dlls" /I "..\..\..\engine" /I "..\..\..\common" /I "..\..\pm_shared" /I "..\..\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "QUIVER" /D "VOXEL" /D "QUAKE2" /D "VALVE_DLL" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /i "..\..\engine" /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# ADD LINK32 user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /def:"..\dmc.def"
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "dmc - Win32 Release"
# Name "dmc - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
# Begin Group "Shared Weapons"
# PROP Default_Filter "*.cpp"
# Begin Source File
SOURCE=..\quake_gun.cpp
# End Source File
# Begin Source File
SOURCE=..\quake_weapons_all.cpp
# End Source File
# End Group
# Begin Source File
SOURCE=..\animating.cpp
# End Source File
# Begin Source File
SOURCE=..\animation.cpp
# End Source File
# Begin Source File
SOURCE=..\bmodels.cpp
# End Source File
# Begin Source File
SOURCE=..\buttons.cpp
# End Source File
# Begin Source File
SOURCE=..\cbase.cpp
# End Source File
# Begin Source File
SOURCE=..\client.cpp
# End Source File
# Begin Source File
SOURCE=..\combat.cpp
# End Source File
# Begin Source File
SOURCE=..\doors.cpp
# End Source File
# Begin Source File
SOURCE=..\effects.cpp
# End Source File
# Begin Source File
SOURCE=..\explode.cpp
# End Source File
# Begin Source File
SOURCE=..\func_break.cpp
# End Source File
# Begin Source File
SOURCE=..\game.cpp
# End Source File
# Begin Source File
SOURCE=..\gamerules.cpp
# End Source File
# Begin Source File
SOURCE=..\globals.cpp
# End Source File
# Begin Source File
SOURCE=..\h_ai.cpp
# End Source File
# Begin Source File
SOURCE=..\h_export.cpp
# End Source File
# Begin Source File
SOURCE=..\lights.cpp
# End Source File
# Begin Source File
SOURCE=..\maprules.cpp
# End Source File
# Begin Source File
SOURCE=..\monsters.cpp
# End Source File
# Begin Source File
SOURCE=..\monsterstate.cpp
# End Source File
# Begin Source File
SOURCE=..\multiplay_gamerules.cpp
# End Source File
# Begin Source File
SOURCE=..\nodes.cpp
# End Source File
# Begin Source File
SOURCE=..\observer.cpp
# End Source File
# Begin Source File
SOURCE=..\pathcorner.cpp
# End Source File
# Begin Source File
SOURCE=..\plane.cpp
# End Source File
# Begin Source File
SOURCE=..\plats.cpp
# End Source File
# Begin Source File
SOURCE=..\player.cpp
# End Source File
# Begin Source File
SOURCE=..\..\pm_shared\pm_debug.c
# End Source File
# Begin Source File
SOURCE=..\..\pm_shared\pm_math.c
# End Source File
# Begin Source File
SOURCE=..\..\pm_shared\pm_shared.c
# End Source File
# Begin Source File
SOURCE=..\quake_items.cpp
# End Source File
# Begin Source File
SOURCE=..\quake_nail.cpp
# End Source File
# Begin Source File
SOURCE=..\quake_player.cpp
# End Source File
# Begin Source File
SOURCE=..\quake_rocket.cpp
# End Source File
# Begin Source File
SOURCE=..\schedule.cpp
# End Source File
# Begin Source File
SOURCE=..\singleplay_gamerules.cpp
# End Source File
# Begin Source File
SOURCE=..\skill.cpp
# End Source File
# Begin Source File
SOURCE=..\sound.cpp
# End Source File
# Begin Source File
SOURCE=..\spectator.cpp
# End Source File
# Begin Source File
SOURCE=..\subs.cpp
# End Source File
# Begin Source File
SOURCE=..\teamplay_gamerules.cpp
# End Source File
# Begin Source File
SOURCE=..\triggers.cpp
# End Source File
# Begin Source File
SOURCE=..\util.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\game_shared\voice_gamemgr.cpp
# End Source File
# Begin Source File
SOURCE=..\weapons.cpp
# End Source File
# Begin Source File
SOURCE=..\world.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=..\activity.h
# End Source File
# Begin Source File
SOURCE=..\activitymap.h
# End Source File
# Begin Source File
SOURCE=..\animation.h
# End Source File
# Begin Source File
SOURCE=..\basemonster.h
# End Source File
# Begin Source File
SOURCE=..\cbase.h
# End Source File
# Begin Source File
SOURCE=..\cdll_dll.h
# End Source File
# Begin Source File
SOURCE=..\client.h
# End Source File
# Begin Source File
SOURCE=..\decals.h
# End Source File
# Begin Source File
SOURCE=..\defaultai.h
# End Source File
# Begin Source File
SOURCE=..\doors.h
# End Source File
# Begin Source File
SOURCE=..\effects.h
# End Source File
# Begin Source File
SOURCE=..\enginecallback.h
# End Source File
# Begin Source File
SOURCE=..\explode.h
# End Source File
# Begin Source File
SOURCE=..\extdll.h
# End Source File
# Begin Source File
SOURCE=..\func_break.h
# End Source File
# Begin Source File
SOURCE=..\gamerules.h
# End Source File
# Begin Source File
SOURCE=..\items.h
# End Source File
# Begin Source File
SOURCE=..\monsterevent.h
# End Source File
# Begin Source File
SOURCE=..\monsters.h
# End Source File
# Begin Source File
SOURCE=..\nodes.h
# End Source File
# Begin Source File
SOURCE=..\plane.h
# End Source File
# Begin Source File
SOURCE=..\player.h
# End Source File
# Begin Source File
SOURCE=..\..\pm_shared\pm_debug.h
# End Source File
# Begin Source File
SOURCE=..\..\pm_shared\pm_defs.h
# End Source File
# Begin Source File
SOURCE=..\..\pm_shared\pm_info.h
# End Source File
# Begin Source File
SOURCE=..\..\pm_shared\pm_materials.h
# End Source File
# Begin Source File
SOURCE=..\..\pm_shared\pm_movevars.h
# End Source File
# Begin Source File
SOURCE=..\..\pm_shared\pm_shared.h
# End Source File
# Begin Source File
SOURCE=..\quake_gun.h
# End Source File
# Begin Source File
SOURCE=..\saverestore.h
# End Source File
# Begin Source File
SOURCE=..\schedule.h
# End Source File
# Begin Source File
SOURCE=..\scripted.h
# End Source File
# Begin Source File
SOURCE=..\scriptevent.h
# End Source File
# Begin Source File
SOURCE=..\skill.h
# End Source File
# Begin Source File
SOURCE=..\soundent.h
# End Source File
# Begin Source File
SOURCE=..\spectator.h
# End Source File
# Begin Source File
SOURCE=..\teamplay_gamerules.h
# End Source File
# Begin Source File
SOURCE=..\trains.h
# End Source File
# Begin Source File
SOURCE=..\util.h
# End Source File
# Begin Source File
SOURCE=..\vector.h
# End Source File
# Begin Source File
SOURCE=..\..\..\game_shared\voice_gamemgr.h
# End Source File
# Begin Source File
SOURCE=..\weapons.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3648
hlsdk/dmc/dlls/nodes.cpp Normal file

File diff suppressed because it is too large Load Diff

374
hlsdk/dmc/dlls/nodes.h Normal file
View File

@ -0,0 +1,374 @@
/***
*
* 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.
*
* 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.
*
****/
//=========================================================
// nodes.h
//=========================================================
//=========================================================
// DEFINE
//=========================================================
#define MAX_STACK_NODES 100
#define NO_NODE -1
#define MAX_NODE_HULLS 4
#define bits_NODE_LAND ( 1 << 0 ) // Land node, so nudge if necessary.
#define bits_NODE_AIR ( 1 << 1 ) // Air node, don't nudge.
#define bits_NODE_WATER ( 1 << 2 ) // Water node, don't nudge.
#define bits_NODE_GROUP_REALM (bits_NODE_LAND | bits_NODE_AIR | bits_NODE_WATER)
//=========================================================
// Instance of a node.
//=========================================================
class CNode
{
public:
Vector m_vecOrigin;// location of this node in space
Vector m_vecOriginPeek; // location of this node (LAND nodes are NODE_HEIGHT higher).
BYTE m_Region[3]; // Which of 256 regions do each of the coordinate belong?
int m_afNodeInfo;// bits that tell us more about this location
int m_cNumLinks; // how many links this node has
int m_iFirstLink;// index of this node's first link in the link pool.
// Where to start looking in the compressed routing table (offset into m_pRouteInfo).
// (4 hull sizes -- smallest to largest + fly/swim), and secondly, door capability.
//
int m_pNextBestNode[MAX_NODE_HULLS][2];
// Used in finding the shortest path. m_fClosestSoFar is -1 if not visited.
// Then it is the distance to the source. If another path uses this node
// and has a closer distance, then m_iPreviousNode is also updated.
//
float m_flClosestSoFar; // Used in finding the shortest path.
int m_iPreviousNode;
short m_sHintType;// there is something interesting in the world at this node's position
short m_sHintActivity;// there is something interesting in the world at this node's position
float m_flHintYaw;// monster on this node should face this yaw to face the hint.
};
//=========================================================
// CLink - A link between 2 nodes
//=========================================================
#define bits_LINK_SMALL_HULL ( 1 << 0 )// headcrab box can fit through this connection
#define bits_LINK_HUMAN_HULL ( 1 << 1 )// player box can fit through this connection
#define bits_LINK_LARGE_HULL ( 1 << 2 )// big box can fit through this connection
#define bits_LINK_FLY_HULL ( 1 << 3 )// a flying big box can fit through this connection
#define bits_LINK_DISABLED ( 1 << 4 )// link is not valid when the set
#define NODE_SMALL_HULL 0
#define NODE_HUMAN_HULL 1
#define NODE_LARGE_HULL 2
#define NODE_FLY_HULL 3
class CLink
{
public:
int m_iSrcNode;// the node that 'owns' this link ( keeps us from having to make reverse lookups )
int m_iDestNode;// the node on the other end of the link.
entvars_t *m_pLinkEnt;// the entity that blocks this connection (doors, etc)
// m_szLinkEntModelname is not necessarily NULL terminated (so we can store it in a more alignment-friendly 4 bytes)
char m_szLinkEntModelname[ 4 ];// the unique name of the brush model that blocks the connection (this is kept for save/restore)
int m_afLinkInfo;// information about this link
float m_flWeight;// length of the link line segment
};
typedef struct
{
int m_SortedBy[3];
int m_CheckedEvent;
} DIST_INFO;
typedef struct
{
Vector v;
short n; // Nearest node or -1 if no node found.
} CACHE_ENTRY;
//=========================================================
// CGraph
//=========================================================
#define GRAPH_VERSION (int)16// !!!increment this whever graph/node/link classes change, to obsolesce older disk files.
class CGraph
{
public:
// the graph has two flags, and should not be accessed unless both flags are TRUE!
BOOL m_fGraphPresent;// is the graph in memory?
BOOL m_fGraphPointersSet;// are the entity pointers for the graph all set?
BOOL m_fRoutingComplete; // are the optimal routes computed, yet?
CNode *m_pNodes;// pointer to the memory block that contains all node info
CLink *m_pLinkPool;// big list of all node connections
char *m_pRouteInfo; // compressed routing information the nodes use.
int m_cNodes;// total number of nodes
int m_cLinks;// total number of links
int m_nRouteInfo; // size of m_pRouteInfo in bytes.
// Tables for making nearest node lookup faster. SortedBy provided nodes in a
// order of a particular coordinate. Instead of doing a binary search, RangeStart
// and RangeEnd let you get to the part of SortedBy that you are interested in.
//
// Once you have a point of interest, the only way you'll find a closer point is
// if at least one of the coordinates is closer than the ones you have now. So we
// search each range. After the search is exhausted, we know we have the closest
// node.
//
#define CACHE_SIZE 128
#define NUM_RANGES 256
DIST_INFO *m_di; // This is m_cNodes long, but the entries don't correspond to CNode entries.
int m_RangeStart[3][NUM_RANGES];
int m_RangeEnd[3][NUM_RANGES];
float m_flShortest;
int m_iNearest;
int m_minX, m_minY, m_minZ, m_maxX, m_maxY, m_maxZ;
int m_minBoxX, m_minBoxY, m_minBoxZ, m_maxBoxX, m_maxBoxY, m_maxBoxZ;
int m_CheckedCounter;
float m_RegionMin[3], m_RegionMax[3]; // The range of nodes.
CACHE_ENTRY m_Cache[CACHE_SIZE];
int m_HashPrimes[16];
short *m_pHashLinks;
int m_nHashLinks;
// kinda sleazy. In order to allow variety in active idles for monster groups in a room with more than one node,
// we keep track of the last node we searched from and store it here. Subsequent searches by other monsters will pick
// up where the last search stopped.
int m_iLastActiveIdleSearch;
// another such system used to track the search for cover nodes, helps greatly with two monsters trying to get to the same node.
int m_iLastCoverSearch;
// functions to create the graph
int LinkVisibleNodes ( CLink *pLinkPool, FILE *file, int *piBadNode );
int RejectInlineLinks ( CLink *pLinkPool, FILE *file );
int FindShortestPath ( int *piPath, int iStart, int iDest, int iHull, int afCapMask);
int FindNearestNode ( const Vector &vecOrigin, CBaseEntity *pEntity );
int FindNearestNode ( const Vector &vecOrigin, int afNodeTypes );
//int FindNearestLink ( const Vector &vecTestPoint, int *piNearestLink, BOOL *pfAlongLine );
float PathLength( int iStart, int iDest, int iHull, int afCapMask );
int NextNodeInRoute( int iCurrentNode, int iDest, int iHull, int iCap );
enum NODEQUERY { NODEGRAPH_DYNAMIC, NODEGRAPH_STATIC };
// A static query means we're asking about the possiblity of handling this entity at ANY time
// A dynamic query means we're asking about it RIGHT NOW. So we should query the current state
int HandleLinkEnt ( int iNode, entvars_t *pevLinkEnt, int afCapMask, NODEQUERY queryType );
entvars_t* LinkEntForLink ( CLink *pLink, CNode *pNode );
void ShowNodeConnections ( int iNode );
void InitGraph( void );
int AllocNodes ( void );
int CheckNODFile(char *szMapName);
int FLoadGraph(char *szMapName);
int FSaveGraph(char *szMapName);
int FSetGraphPointers(void);
void CheckNode(Vector vecOrigin, int iNode);
void BuildRegionTables(void);
void ComputeStaticRoutingTables(void);
void TestRoutingTables(void);
void HashInsert(int iSrcNode, int iDestNode, int iKey);
void HashSearch(int iSrcNode, int iDestNode, int &iKey);
void HashChoosePrimes(int TableSize);
void BuildLinkLookups(void);
void SortNodes(void);
int HullIndex( const CBaseEntity *pEntity ); // what hull the monster uses
int NodeType( const CBaseEntity *pEntity ); // what node type the monster uses
inline int CapIndex( int afCapMask )
{
if (afCapMask & (bits_CAP_OPEN_DOORS | bits_CAP_AUTO_DOORS | bits_CAP_USE))
return 1;
return 0;
}
inline CNode &Node( int i )
{
#ifdef _DEBUG
if ( !m_pNodes || i < 0 || i > m_cNodes )
ALERT( at_error, "Bad Node!\n" );
#endif
return m_pNodes[i];
}
inline CLink &Link( int i )
{
#ifdef _DEBUG
if ( !m_pLinkPool || i < 0 || i > m_cLinks )
ALERT( at_error, "Bad link!\n" );
#endif
return m_pLinkPool[i];
}
inline CLink &NodeLink( int iNode, int iLink )
{
return Link( Node( iNode ).m_iFirstLink + iLink );
}
inline CLink &NodeLink( const CNode &node, int iLink )
{
return Link( node.m_iFirstLink + iLink );
}
inline int INodeLink ( int iNode, int iLink )
{
return NodeLink( iNode, iLink ).m_iDestNode;
}
#if 0
inline CNode &SourceNode( int iNode, int iLink )
{
return Node( NodeLink( iNode, iLink ).m_iSrcNode );
}
inline CNode &DestNode( int iNode, int iLink )
{
return Node( NodeLink( iNode, iLink ).m_iDestNode );
}
inline CNode *PNodeLink ( int iNode, int iLink )
{
return &DestNode( iNode, iLink );
}
#endif
};
//=========================================================
// Nodes start out as ents in the level. The node graph
// is built, then these ents are discarded.
//=========================================================
class CNodeEnt : public CBaseEntity
{
void Spawn( void );
void KeyValue( KeyValueData *pkvd );
virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
short m_sHintType;
short m_sHintActivity;
};
//=========================================================
// CStack - last in, first out.
//=========================================================
class CStack
{
public:
CStack( void );
void Push( int value );
int Pop( void );
int Top( void );
int Empty( void ) { return m_level==0; }
int Size( void ) { return m_level; }
void CopyToArray ( int *piArray );
private:
int m_stack[ MAX_STACK_NODES ];
int m_level;
};
//=========================================================
// CQueue - first in, first out.
//=========================================================
class CQueue
{
public:
CQueue( void );// constructor
inline int Full ( void ) { return ( m_cSize == MAX_STACK_NODES ); }
inline int Empty ( void ) { return ( m_cSize == 0 ); }
//inline int Tail ( void ) { return ( m_queue[ m_tail ] ); }
inline int Size ( void ) { return ( m_cSize ); }
void Insert( int, float );
int Remove( float & );
private:
int m_cSize;
struct tag_QUEUE_NODE
{
int Id;
float Priority;
} m_queue[ MAX_STACK_NODES ];
int m_head;
int m_tail;
};
//=========================================================
// CQueuePriority - Priority queue (smallest item out first).
//
//=========================================================
class CQueuePriority
{
public:
CQueuePriority( void );// constructor
inline int Full ( void ) { return ( m_cSize == MAX_STACK_NODES ); }
inline int Empty ( void ) { return ( m_cSize == 0 ); }
//inline int Tail ( float & ) { return ( m_queue[ m_tail ].Id ); }
inline int Size ( void ) { return ( m_cSize ); }
void Insert( int, float );
int Remove( float &);
private:
int m_cSize;
struct tag_HEAP_NODE
{
int Id;
float Priority;
} m_heap[ MAX_STACK_NODES ];
void Heap_SiftDown(int);
void Heap_SiftUp(void);
};
//=========================================================
// hints - these MUST coincide with the HINTS listed under
// info_node in the FGD file!
//=========================================================
enum
{
HINT_NONE = 0,
HINT_WORLD_DOOR,
HINT_WORLD_WINDOW,
HINT_WORLD_BUTTON,
HINT_WORLD_MACHINERY,
HINT_WORLD_LEDGE,
HINT_WORLD_LIGHT_SOURCE,
HINT_WORLD_HEAT_SOURCE,
HINT_WORLD_BLINKING_LIGHT,
HINT_WORLD_BRIGHT_COLORS,
HINT_WORLD_HUMAN_BLOOD,
HINT_WORLD_ALIEN_BLOOD,
HINT_TACTICAL_EXIT = 100,
HINT_TACTICAL_VANTAGE,
HINT_TACTICAL_AMBUSH,
HINT_STUKA_PERCH = 300,
HINT_STUKA_LANDING,
};
extern CGraph WorldGraph;

142
hlsdk/dmc/dlls/observer.cpp Normal file
View File

@ -0,0 +1,142 @@
//=========== (C) Copyright 1996-2002, Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Functionality for the observer chase camera
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "pm_shared.h"
// Find the next client in the game for this player to spectate
void CBasePlayer::Observer_FindNextPlayer()
{
// MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching
// only a subset of the players. e.g. Make it check the target's team.
CBaseEntity *client = m_hObserverTarget;
while ( (client = (CBaseEntity*)UTIL_FindEntityByClassname( client, "player" )) != m_hObserverTarget )
{
if ( !client )
continue;
if ( !client->pev )
continue;
if ( client == this )
continue;
// Add checks on target here.
m_hObserverTarget = client;
break;
}
// Did we find a target?
if ( m_hObserverTarget )
{
// Store the target in pev so the physics DLL can get to it
if (pev->iuser1 != OBS_ROAMING)
pev->iuser2 = ENTINDEX( m_hObserverTarget->edict() );
// Move to the target
UTIL_SetOrigin( pev, m_hObserverTarget->pev->origin );
ALERT( at_console, "Now Tracking %s\n", STRING( m_hObserverTarget->pev->classname ) );
}
else
{
ALERT( at_console, "No observer targets.\n" );
}
}
// Handle buttons in observer mode
void CBasePlayer::Observer_HandleButtons()
{
// Slow down mouse clicks
if ( m_flNextObserverInput > gpGlobals->time )
return;
// Jump changes from modes: Chase to Roaming
if ( m_afButtonPressed & IN_JUMP )
{
if ( pev->iuser1 == OBS_CHASE_LOCKED )
Observer_SetMode( OBS_CHASE_FREE );
else if ( pev->iuser1 == OBS_CHASE_FREE )
Observer_SetMode( OBS_ROAMING );
else if ( pev->iuser1 == OBS_ROAMING )
Observer_SetMode( OBS_IN_EYE );
else if ( pev->iuser1 == OBS_IN_EYE )
Observer_SetMode( OBS_MAP_FREE );
else if ( pev->iuser1 == OBS_MAP_FREE )
Observer_SetMode( OBS_MAP_CHASE );
else
Observer_SetMode( OBS_CHASE_FREE ); // don't use OBS_CHASE_LOCKED anymore
m_flNextObserverInput = gpGlobals->time + 0.2;
}
// Attack moves to the next player
if ( m_afButtonPressed & IN_ATTACK )
{
Observer_FindNextPlayer();
m_flNextObserverInput = gpGlobals->time + 0.2;
}
}
// Attempt to change the observer mode
void CBasePlayer::Observer_SetMode( int iMode )
{
// Just abort if we're changing to the mode we're already in
if ( iMode == pev->iuser1 )
return;
// is valid mode ?
if ( iMode < OBS_CHASE_LOCKED || iMode > OBS_MAP_CHASE )
iMode = OBS_IN_EYE; // now it is
// if we are not roaming, we need a valid target to track
if ( (iMode != OBS_ROAMING) && (m_hObserverTarget == 0) )
{
Observer_FindNextPlayer();
// if we didn't find a valid target switch to roaming
if (m_hObserverTarget == 0)
{
ClientPrint( pev, HUD_PRINTCENTER, "#Spec_NoTarget" );
iMode = OBS_ROAMING;
}
}
// set spectator mode
pev->iuser1 = iMode;
// set target if not roaming
if (iMode == OBS_ROAMING)
pev->iuser2 = 0;
else
pev->iuser2 = ENTINDEX( m_hObserverTarget->edict() );
// print spepctaor mode on client screen
char modemsg[16];
sprintf(modemsg,"#Spec_Mode%i", iMode);
ClientPrint( pev, HUD_PRINTCENTER, modemsg );
}

View File

@ -0,0 +1,428 @@
/***
*
* 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.
*
****/
//
// ========================== PATH_CORNER ===========================
//
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "trains.h"
#include "saverestore.h"
class CPathCorner : public CPointEntity
{
public:
void Spawn( );
void KeyValue( KeyValueData* pkvd );
float GetDelay( void ) { return m_flWait; }
// void Touch( CBaseEntity *pOther );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
private:
float m_flWait;
};
LINK_ENTITY_TO_CLASS( path_corner, CPathCorner );
// Global Savedata for Delay
TYPEDESCRIPTION CPathCorner::m_SaveData[] =
{
DEFINE_FIELD( CPathCorner, m_flWait, FIELD_FLOAT ),
};
IMPLEMENT_SAVERESTORE( CPathCorner, CPointEntity );
//
// Cache user-entity-field values until spawn is called.
//
void CPathCorner :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "wait"))
{
m_flWait = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CPointEntity::KeyValue( pkvd );
}
void CPathCorner :: Spawn( )
{
ASSERTSZ(!FStringNull(pev->targetname), "path_corner without a targetname");
}
#if 0
void CPathCorner :: Touch( CBaseEntity *pOther )
{
entvars_t* pevToucher = pOther->pev;
if ( FBitSet ( pevToucher->flags, FL_MONSTER ) )
{// monsters don't navigate path corners based on touch anymore
return;
}
// If OTHER isn't explicitly looking for this path_corner, bail out
if ( pOther->m_pGoalEnt != this )
{
return;
}
// If OTHER has an enemy, this touch is incidental, ignore
if ( !FNullEnt(pevToucher->enemy) )
{
return; // fighting, not following a path
}
// UNDONE: support non-zero flWait
/*
if (m_flWait != 0)
ALERT(at_warning, "Non-zero path-cornder waits NYI");
*/
// Find the next "stop" on the path, make it the goal of the "toucher".
if (FStringNull(pev->target))
{
ALERT(at_warning, "PathCornerTouch: no next stop specified");
}
pOther->m_pGoalEnt = CBaseEntity::Instance( FIND_ENTITY_BY_TARGETNAME ( NULL, STRING(pev->target) ) );
// If "next spot" was not found (does not exist - level design error)
if ( !pOther->m_pGoalEnt )
{
ALERT(at_console, "PathCornerTouch--%s couldn't find next stop in path: %s", STRING(pev->classname), STRING(pev->target));
return;
}
// Turn towards the next stop in the path.
pevToucher->ideal_yaw = UTIL_VecToYaw ( pOther->m_pGoalEnt->pev->origin - pevToucher->origin );
}
#endif
TYPEDESCRIPTION CPathTrack::m_SaveData[] =
{
DEFINE_FIELD( CPathTrack, m_length, FIELD_FLOAT ),
DEFINE_FIELD( CPathTrack, m_pnext, FIELD_CLASSPTR ),
DEFINE_FIELD( CPathTrack, m_paltpath, FIELD_CLASSPTR ),
DEFINE_FIELD( CPathTrack, m_pprevious, FIELD_CLASSPTR ),
DEFINE_FIELD( CPathTrack, m_altName, FIELD_STRING ),
};
IMPLEMENT_SAVERESTORE( CPathTrack, CBaseEntity );
LINK_ENTITY_TO_CLASS( path_track, CPathTrack );
//
// Cache user-entity-field values until spawn is called.
//
void CPathTrack :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "altpath"))
{
m_altName = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CPointEntity::KeyValue( pkvd );
}
void CPathTrack :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
int on;
// Use toggles between two paths
if ( m_paltpath )
{
on = !FBitSet( pev->spawnflags, SF_PATH_ALTERNATE );
if ( ShouldToggle( useType, on ) )
{
if ( on )
SetBits( pev->spawnflags, SF_PATH_ALTERNATE );
else
ClearBits( pev->spawnflags, SF_PATH_ALTERNATE );
}
}
else // Use toggles between enabled/disabled
{
on = !FBitSet( pev->spawnflags, SF_PATH_DISABLED );
if ( ShouldToggle( useType, on ) )
{
if ( on )
SetBits( pev->spawnflags, SF_PATH_DISABLED );
else
ClearBits( pev->spawnflags, SF_PATH_DISABLED );
}
}
}
void CPathTrack :: Link( void )
{
edict_t *pentTarget;
if ( !FStringNull(pev->target) )
{
pentTarget = FIND_ENTITY_BY_TARGETNAME( NULL, STRING(pev->target) );
if ( !FNullEnt(pentTarget) )
{
m_pnext = CPathTrack::Instance( pentTarget );
if ( m_pnext ) // If no next pointer, this is the end of a path
{
m_pnext->SetPrevious( this );
}
}
else
ALERT( at_console, "Dead end link %s\n", STRING(pev->target) );
}
// Find "alternate" path
if ( m_altName )
{
pentTarget = FIND_ENTITY_BY_TARGETNAME( NULL, STRING(m_altName) );
if ( !FNullEnt(pentTarget) )
{
m_paltpath = CPathTrack::Instance( pentTarget );
if ( m_paltpath ) // If no next pointer, this is the end of a path
{
m_paltpath->SetPrevious( this );
}
}
}
}
void CPathTrack :: Spawn( void )
{
pev->solid = SOLID_TRIGGER;
UTIL_SetSize(pev, Vector(-8, -8, -8), Vector(8, 8, 8));
m_pnext = NULL;
m_pprevious = NULL;
// DEBUGGING CODE
#if PATH_SPARKLE_DEBUG
SetThink( Sparkle );
pev->nextthink = gpGlobals->time + 0.5;
#endif
}
void CPathTrack::Activate( void )
{
if ( !FStringNull( pev->targetname ) ) // Link to next, and back-link
Link();
}
CPathTrack *CPathTrack :: ValidPath( CPathTrack *ppath, int testFlag )
{
if ( !ppath )
return NULL;
if ( testFlag && FBitSet( ppath->pev->spawnflags, SF_PATH_DISABLED ) )
return NULL;
return ppath;
}
void CPathTrack :: Project( CPathTrack *pstart, CPathTrack *pend, Vector *origin, float dist )
{
if ( pstart && pend )
{
Vector dir = (pend->pev->origin - pstart->pev->origin);
dir = dir.Normalize();
*origin = pend->pev->origin + dir * dist;
}
}
CPathTrack *CPathTrack::GetNext( void )
{
if ( m_paltpath && FBitSet( pev->spawnflags, SF_PATH_ALTERNATE ) && !FBitSet( pev->spawnflags, SF_PATH_ALTREVERSE ) )
return m_paltpath;
return m_pnext;
}
CPathTrack *CPathTrack::GetPrevious( void )
{
if ( m_paltpath && FBitSet( pev->spawnflags, SF_PATH_ALTERNATE ) && FBitSet( pev->spawnflags, SF_PATH_ALTREVERSE ) )
return m_paltpath;
return m_pprevious;
}
void CPathTrack::SetPrevious( CPathTrack *pprev )
{
// Only set previous if this isn't my alternate path
if ( pprev && !FStrEq( STRING(pprev->pev->targetname), STRING(m_altName) ) )
m_pprevious = pprev;
}
// Assumes this is ALWAYS enabled
CPathTrack *CPathTrack :: LookAhead( Vector *origin, float dist, int move )
{
CPathTrack *pcurrent;
float originalDist = dist;
pcurrent = this;
Vector currentPos = *origin;
if ( dist < 0 ) // Travelling backwards through path
{
dist = -dist;
while ( dist > 0 )
{
Vector dir = pcurrent->pev->origin - currentPos;
float length = dir.Length();
if ( !length )
{
if ( !ValidPath(pcurrent->GetPrevious(), move) ) // If there is no previous node, or it's disabled, return now.
{
if ( !move )
Project( pcurrent->GetNext(), pcurrent, origin, dist );
return NULL;
}
pcurrent = pcurrent->GetPrevious();
}
else if ( length > dist ) // enough left in this path to move
{
*origin = currentPos + (dir * (dist / length));
return pcurrent;
}
else
{
dist -= length;
currentPos = pcurrent->pev->origin;
*origin = currentPos;
if ( !ValidPath(pcurrent->GetPrevious(), move) ) // If there is no previous node, or it's disabled, return now.
return NULL;
pcurrent = pcurrent->GetPrevious();
}
}
*origin = currentPos;
return pcurrent;
}
else
{
while ( dist > 0 )
{
if ( !ValidPath(pcurrent->GetNext(), move) ) // If there is no next node, or it's disabled, return now.
{
if ( !move )
Project( pcurrent->GetPrevious(), pcurrent, origin, dist );
return NULL;
}
Vector dir = pcurrent->GetNext()->pev->origin - currentPos;
float length = dir.Length();
if ( !length && !ValidPath( pcurrent->GetNext()->GetNext(), move ) )
{
if ( dist == originalDist ) // HACK -- up against a dead end
return NULL;
return pcurrent;
}
if ( length > dist ) // enough left in this path to move
{
*origin = currentPos + (dir * (dist / length));
return pcurrent;
}
else
{
dist -= length;
currentPos = pcurrent->GetNext()->pev->origin;
pcurrent = pcurrent->GetNext();
*origin = currentPos;
}
}
*origin = currentPos;
}
return pcurrent;
}
// Assumes this is ALWAYS enabled
CPathTrack *CPathTrack :: Nearest( Vector origin )
{
int deadCount;
float minDist, dist;
Vector delta;
CPathTrack *ppath, *pnearest;
delta = origin - pev->origin;
delta.z = 0;
minDist = delta.Length();
pnearest = this;
ppath = GetNext();
// Hey, I could use the old 2 racing pointers solution to this, but I'm lazy :)
deadCount = 0;
while ( ppath && ppath != this )
{
deadCount++;
if ( deadCount > 9999 )
{
ALERT( at_error, "Bad sequence of path_tracks from %s", STRING(pev->targetname) );
return NULL;
}
delta = origin - ppath->pev->origin;
delta.z = 0;
dist = delta.Length();
if ( dist < minDist )
{
minDist = dist;
pnearest = ppath;
}
ppath = ppath->GetNext();
}
return pnearest;
}
CPathTrack *CPathTrack::Instance( edict_t *pent )
{
if ( FClassnameIs( pent, "path_track" ) )
return (CPathTrack *)GET_PRIVATE(pent);
return NULL;
}
// DEBUGGING CODE
#if PATH_SPARKLE_DEBUG
void CPathTrack :: Sparkle( void )
{
pev->nextthink = gpGlobals->time + 0.2;
if ( FBitSet( pev->spawnflags, SF_PATH_DISABLED ) )
UTIL_ParticleEffect(pev->origin, Vector(0,0,100), 210, 10);
else
UTIL_ParticleEffect(pev->origin, Vector(0,0,100), 84, 10);
}
#endif

60
hlsdk/dmc/dlls/plane.cpp Normal file
View File

@ -0,0 +1,60 @@
/***
*
* 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 "extdll.h"
#include "plane.h"
//=========================================================
// Plane
//=========================================================
CPlane :: CPlane ( void )
{
m_fInitialized = FALSE;
}
//=========================================================
// InitializePlane - Takes a normal for the plane and a
// point on the plane and
//=========================================================
void CPlane :: InitializePlane ( const Vector &vecNormal, const Vector &vecPoint )
{
m_vecNormal = vecNormal;
m_flDist = DotProduct ( m_vecNormal, vecPoint );
m_fInitialized = TRUE;
}
//=========================================================
// PointInFront - determines whether the given vector is
// in front of the plane.
//=========================================================
BOOL CPlane :: PointInFront ( const Vector &vecPoint )
{
float flFace;
if ( !m_fInitialized )
{
return FALSE;
}
flFace = DotProduct ( m_vecNormal, vecPoint ) - m_flDist;
if ( flFace >= 0 )
{
return TRUE;
}
return FALSE;
}

43
hlsdk/dmc/dlls/plane.h Normal file
View File

@ -0,0 +1,43 @@
/***
*
* 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.
*
****/
#ifndef PLANE_H
#define PLANE_H
//=========================================================
// Plane
//=========================================================
class CPlane
{
public:
CPlane ( void );
//=========================================================
// InitializePlane - Takes a normal for the plane and a
// point on the plane and
//=========================================================
void InitializePlane ( const Vector &vecNormal, const Vector &vecPoint );
//=========================================================
// PointInFront - determines whether the given vector is
// in front of the plane.
//=========================================================
BOOL PointInFront ( const Vector &vecPoint );
Vector m_vecNormal;
float m_flDist;
BOOL m_fInitialized;
};
#endif // PLANE_H

2285
hlsdk/dmc/dlls/plats.cpp Normal file

File diff suppressed because it is too large Load Diff

4880
hlsdk/dmc/dlls/player.cpp Normal file

File diff suppressed because it is too large Load Diff

436
hlsdk/dmc/dlls/player.h Normal file
View File

@ -0,0 +1,436 @@
/***
*
* 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.
*
****/
#ifndef PLAYER_H
#define PLAYER_H
#define PLAYER_FATAL_FALL_SPEED 1024// approx 60 feet
#define PLAYER_MAX_SAFE_FALL_SPEED 580// approx 20 feet
#define DAMAGE_FOR_FALL_SPEED (float) 100 / ( PLAYER_FATAL_FALL_SPEED - PLAYER_MAX_SAFE_FALL_SPEED )// damage per unit per second.
#define PLAYER_MIN_BOUNCE_SPEED 200
#define PLAYER_FALL_PUNCH_THRESHHOLD (float)350 // won't punch player's screen/make scrape noise unless player falling at least this fast.
//
// Player PHYSICS FLAGS bits
//
#define PFLAG_ONLADDER ( 1<<0 )
#define PFLAG_ONSWING ( 1<<0 )
#define PFLAG_ONTRAIN ( 1<<1 )
#define PFLAG_ONBARNACLE ( 1<<2 )
#define PFLAG_DUCKING ( 1<<3 ) // In the process of ducking, but totally squatted yet
#define PFLAG_USING ( 1<<4 ) // Using a continuous entity
#define PFLAG_OBSERVER ( 1<<5 ) // player is locked in stationary cam mode. Spectators can move, observers can't.
//
// generic player
//
//-----------------------------------------------------
//This is Half-Life player entity
//-----------------------------------------------------
#define CSUITPLAYLIST 4 // max of 4 suit sentences queued up at any time
#define SUIT_GROUP TRUE
#define SUIT_SENTENCE FALSE
#define SUIT_REPEAT_OK 0
#define SUIT_NEXT_IN_30SEC 30
#define SUIT_NEXT_IN_1MIN 60
#define SUIT_NEXT_IN_5MIN 300
#define SUIT_NEXT_IN_10MIN 600
#define SUIT_NEXT_IN_30MIN 1800
#define SUIT_NEXT_IN_1HOUR 3600
#define CSUITNOREPEAT 32
#define SOUND_FLASHLIGHT_ON "items/flashlight1.wav"
#define SOUND_FLASHLIGHT_OFF "items/flashlight1.wav"
#define TEAM_NAME_LENGTH 16
typedef enum
{
PLAYER_IDLE,
PLAYER_WALK,
PLAYER_JUMP,
PLAYER_SUPERJUMP,
PLAYER_DIE,
PLAYER_ATTACK1,
} PLAYER_ANIM;
#define MAX_ID_RANGE 2048
#define SBAR_STRING_SIZE 128
enum sbar_data
{
SBAR_ID_TARGETNAME = 1,
SBAR_ID_TARGETHEALTH,
SBAR_ID_TARGETARMOR,
SBAR_ID_TARGETTEAM,
SBAR_END,
};
#define PLAYER_MAX_SPEED 300
class CBasePlayer : public CBaseMonster
{
public:
int random_seed; // See that is shared between client & server for shared weapons code
int m_iPlayerSound;// the index of the sound list slot reserved for this player
int m_iTargetVolume;// ideal sound volume.
int m_iWeaponVolume;// how loud the player's weapon is right now.
int m_iExtraSoundTypes;// additional classification for this weapon's sound
int m_iWeaponFlash;// brightness of the weapon flash
float m_flStopExtraSoundTime;
float m_flFlashLightTime; // Time until next battery draw/Recharge
int m_iFlashBattery; // Flashlight Battery Draw
int m_afButtonLast;
int m_afButtonPressed;
int m_afButtonReleased;
edict_t *m_pentSndLast; // last sound entity to modify player room type
float m_flSndRoomtype; // last roomtype set by sound entity
float m_flSndRange; // dist from player to sound entity
float m_flFallVelocity;
int m_rgItems[MAX_ITEMS];
int m_fKnownItem; // True when a new item needs to be added
int m_fNewAmmo; // True when a new item has been added
unsigned int m_afPhysicsFlags; // physics flags - set when 'normal' physics should be revisited or overriden
float m_fNextSuicideTime; // the time after which the player can next use the suicide command
// these are time-sensitive things that we keep track of
float m_flTimeStepSound; // when the last stepping sound was made
float m_flTimeWeaponIdle; // when to play another weapon idle animation.
float m_flSwimTime; // how long player has been underwater
float m_flDuckTime; // how long we've been ducking
float m_flWallJumpTime; // how long until next walljump
float m_flSuitUpdate; // when to play next suit update
int m_rgSuitPlayList[CSUITPLAYLIST];// next sentencenum to play for suit update
int m_iSuitPlayNext; // next sentence slot for queue storage;
int m_rgiSuitNoRepeat[CSUITNOREPEAT]; // suit sentence no repeat list
float m_rgflSuitNoRepeatTime[CSUITNOREPEAT]; // how long to wait before allowing repeat
int m_lastDamageAmount; // Last damage taken
float m_tbdPrev; // Time-based damage timer
float m_flgeigerRange; // range to nearest radiation source
float m_flgeigerDelay; // delay per update of range msg to client
int m_igeigerRangePrev;
int m_iStepLeft; // alternate left/right foot stepping sound
char m_szTextureName[CBTEXTURENAMEMAX]; // current texture name we're standing on
char m_chTextureType; // current texture type
int m_idrowndmg; // track drowning damage taken
int m_idrownrestored; // track drowning damage restored
int m_bitsHUDDamage; // Damage bits for the current fame. These get sent to
// the hude via the DAMAGE message
BOOL m_fInitHUD; // True when deferred HUD restart msg needs to be sent
BOOL m_fGameHUDInitialized;
int m_iTrain; // Train control position
BOOL m_fWeapon; // Set this to FALSE to force a reset of the current weapon HUD info
EHANDLE m_pTank; // the tank which the player is currently controlling, NULL if no tank
float m_fDeadTime; // the time at which the player died (used in PlayerDeathThink())
BOOL m_fNoPlayerSound; // a debugging feature. Player makes no sound if this is true.
BOOL m_fLongJump; // does this player have the longjump module?
float m_tSneaking;
int m_iUpdateTime; // stores the number of frame ticks before sending HUD update messages
int m_iClientHealth; // the health currently known by the client. If this changes, send a new
int m_iClientBattery; // the Battery currently known by the client. If this changes, send a new
int m_iHideHUD; // the players hud weapon info is to be hidden
int m_iClientHideHUD;
int m_iFOV; // field of view
int m_iClientFOV; // client's known FOV
// usable player items
CBasePlayerItem *m_rgpPlayerItems[MAX_ITEM_TYPES];
CBasePlayerItem *m_pActiveItem;
CBasePlayerItem *m_pClientActiveItem; // client version of the active item
CBasePlayerItem *m_pLastItem;
// shared ammo slots
int m_rgAmmo[MAX_AMMO_SLOTS];
int m_rgAmmoLast[MAX_AMMO_SLOTS];
Vector m_vecAutoAim;
BOOL m_fOnTarget;
int m_iDeaths;
float m_iRespawnFrames; // used in PlayerDeathThink() to make sure players can always respawn
int m_lastx, m_lasty; // These are the previous update's crosshair angles, DON"T SAVE/RESTORE
int m_nCustomSprayFrames;// Custom clan logo frames for this player
float m_flNextDecalTime;// next time this player can spray a decal
char m_szTeamName[TEAM_NAME_LENGTH];
virtual void Spawn( void );
// virtual void Think( void );
virtual void Jump( void );
virtual void Duck( void );
virtual void PreThink( void );
virtual void PostThink( void );
virtual Vector GetGunPosition( void );
virtual int TakeHealth( float flHealth, int bitsDamageType );
virtual void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
virtual void Killed( entvars_t *pevAttacker, int iGib );
virtual Vector BodyTarget( const Vector &posSrc ) { return Center( ) + pev->view_ofs * RANDOM_FLOAT( 0.5, 1.1 ); }; // position to shoot at
virtual void StartSneaking( void ) { m_tSneaking = gpGlobals->time - 1; }
virtual void StopSneaking( void ) { m_tSneaking = gpGlobals->time + 30; }
virtual BOOL IsSneaking( void ) { return m_tSneaking <= gpGlobals->time; }
virtual BOOL IsAlive( void ) { return (pev->deadflag == DEAD_NO) && pev->health > 0; }
virtual BOOL ShouldFadeOnDeath( void ) { return FALSE; }
virtual BOOL IsPlayer( void ) { return TRUE; } // Spectators should return FALSE for this, they aren't "players" as far as game logic is concerned
virtual BOOL IsNetClient( void ) { return TRUE; } // Bots should return FALSE for this, they can't receive NET messages
// Spectators should return TRUE for this
virtual const char *TeamID( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
void RenewItems(void);
void RemoveAllItems( BOOL removeSuit );
BOOL SwitchWeapon( CBasePlayerItem *pWeapon );
// JOHN: sends custom messages if player HUD data has changed (eg health, ammo)
virtual void UpdateClientData( void );
static TYPEDESCRIPTION m_playerSaveData[];
// Player is moved across the transition by other means
virtual int ObjectCaps( void ) { return CBaseMonster :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
virtual void Precache( void );
BOOL IsOnLadder( void );
BOOL FlashlightIsOn( void );
void FlashlightTurnOn( void );
void FlashlightTurnOff( void );
void DeathSound ( void );
int Classify ( void );
void SetAnimation( PLAYER_ANIM playerAnim );
void SetWeaponAnimType( const char *szExtention );
char m_szAnimExtention[32];
// custom player functions
virtual void ImpulseCommands( void );
void CheatImpulseCommands( int iImpulse );
void StartDeathCam( void );
void StartObserver( Vector vecPosition, Vector vecViewAngle );
void AddPoints( int score, BOOL bAllowNegativeScore );
void AddPointsToTeam( int score, BOOL bAllowNegativeScore );
BOOL AddPlayerItem( CBasePlayerItem *pItem );
BOOL RemovePlayerItem( CBasePlayerItem *pItem );
void DropPlayerItem ( char *pszItemName );
BOOL HasPlayerItem( CBasePlayerItem *pCheckItem );
BOOL HasNamedPlayerItem( const char *pszItemName );
BOOL HasWeapons( void );// do I have ANY weapons?
void SelectPrevItem( int iItem );
void SelectNextItem( int iItem );
void SelectLastItem(void);
void SelectItem(const char *pstr);
void ItemPreFrame( void );
void ItemPostFrame( void );
void GiveNamedItem( const char *szName );
void EnableControl(BOOL fControl);
int GiveAmmo( int iAmount, char *szName, int iMax );
void SendAmmoUpdate(void);
void WaterMove( void );
void EXPORT PlayerDeathThink( void );
void PlayerUse( void );
void CheckSuitUpdate();
void SetSuitUpdate(char *name, int fgroup, int iNoRepeat);
void UpdateGeigerCounter( void );
void CheckTimeBasedDamage( void );
void UpdateStepSound( void );
void PlayStepSound(int step, float fvol);
BOOL FBecomeProne ( void );
void BarnacleVictimBitten ( entvars_t *pevBarnacle );
void BarnacleVictimReleased ( void );
static int GetAmmoIndex(const char *psz);
int AmmoInventory( int iAmmoIndex );
int Illumination( void );
void ResetAutoaim( void );
Vector GetAutoaimVector( float flDelta );
Vector AutoaimDeflection( Vector &vecSrc, float flDist, float flDelta );
void ForceClientDllUpdate( void ); // Forces all client .dll specific data to be resent to client.
void DeathMessage( entvars_t *pevKiller );
void SetCustomDecalFrames( int nFrames );
int GetCustomDecalFrames( void );
// Observer camera
void Observer_FindNextPlayer();
void Observer_HandleButtons();
void Observer_SetMode( int iMode );
EHANDLE m_hObserverTarget;
float m_flNextObserverInput;
int IsObserver() { return pev->iuser1; };
// QUAKECLASSIC
// Player
void Pain( CBaseEntity *pAttacker );
float m_flPainSoundFinished;
BOOL m_bHadFirstSpawn; // used to handle the MOTD
// Weapon selection
int W_BestWeapon( void );
void W_SetCurrentAmmo( int sendanim = 1 );
BOOL W_CheckNoAmmo( void );
void W_ChangeWeapon( int iWeaponNumber );
void W_CycleWeaponCommand( void );
void W_CycleWeaponReverseCommand( void );
// Weapon functionality
void Q_FireBullets(int iShots, Vector vecDir, Vector vecSpread);
void LightningDamage( Vector p1, Vector p2, CBaseEntity *pAttacker, float flDamage,Vector vecDir);
// Weapons
void W_Attack( int iQuadSound );
void W_FireAxe( void );
void W_FireShotgun( int QuadSound );
void W_FireSuperShotgun( int QuadSound );
void W_FireRocket( int QuadSound );
void W_FireLightning( int QuadSound );
void W_FireGrenade( int QuadSound );
void W_FireSuperSpikes( int QuadSound );
void W_FireSpikes( int QuadSound );
// Ammunition
void CheckAmmo( void );
int *m_pCurrentAmmo; // Always points to one of the four ammo counts below
int m_iAmmoRockets;
int m_iAmmoCells;
int m_iAmmoShells;
int m_iAmmoNails;
// Backpacks
void DropBackpack( void );
// Weapons
void Deathmatch_Weapon(int iOldWeapon, int iNewWeapon);
int m_iQuakeWeapon;
int m_iClientQuakeWeapon; // The last status of the m_iQuakeWeapon sent to the client.
int m_iQuakeItems;
int m_iClientQuakeItems; // The last status of the m_iQuakeItems sent to the client.
int m_iWeaponSwitch;
int m_iBackpackSwitch;
int m_iAutoWepSwitch;
// Weapon Data
float m_flAxeFire;
float m_flLightningTime;
int m_iNailOffset;
float m_flNextQuadSound;
// Powerups
float m_flSuperDamageFinished;
float m_flInvincibleFinished;
float m_flInvisibleFinished;
float m_flRadsuitFinished;
void PowerUpThink( void ); //Checks powerup timers and hadles their effects
char m_chOldModel[64]; //Save the player's model here
bool m_bPlayedQuadSound;
bool m_bPlayedEnvSound;
bool m_bPlayedInvSound;
bool m_bPlayedProtectSound;
BOOL m_bLostInvincSound;
BOOL m_bLostInvisSound;
BOOL m_bLostSuperSound;
BOOL m_bLostRadSound;
float m_fInvincSound;
float m_fSuperSound;
void InitStatusBar( void );
void UpdateStatusBar( void );
int m_izSBarState[ SBAR_END ];
float m_flNextSBarUpdateTime;
float m_flStatusBarDisappearDelay;
char m_SbarString0[ SBAR_STRING_SIZE ];
char m_SbarString1[ SBAR_STRING_SIZE ];
unsigned short m_usShotgunSingle;
unsigned short m_usShotgunDouble;
unsigned short m_usAxe;
unsigned short m_usAxeSwing;
unsigned short m_usRocket;
unsigned short m_usGrenade;
unsigned short m_usLightning;
unsigned short m_usSpike;
unsigned short m_usSuperSpike;
};
#define AUTOAIM_2DEGREES 0.0348994967025
#define AUTOAIM_5DEGREES 0.08715574274766
#define AUTOAIM_8DEGREES 0.1391731009601
#define AUTOAIM_10DEGREES 0.1736481776669
// QUAKECLASSIC
#define Q_SMALL_PUNCHANGLE_KICK -2
#define Q_BIG_PUNCHANGLE_KICK -4
#define IT_AXE (1 << 0)
#define IT_SHOTGUN (1 << 1)
#define IT_SUPER_SHOTGUN (1 << 2)
#define IT_NAILGUN (1 << 3)
#define IT_SUPER_NAILGUN (1 << 4)
#define IT_GRENADE_LAUNCHER (1 << 5)
#define IT_ROCKET_LAUNCHER (1 << 6)
#define IT_LIGHTNING (1 << 7)
#define IT_EXTRA_WEAPON (1 << 8)
#define IT_SHELLS (1 << 9)
#define IT_NAILS (1 << 10)
#define IT_ROCKETS (1 << 11)
#define IT_CELLS (1 << 12)
#define IT_ARMOR1 (1 << 13)
#define IT_ARMOR2 (1 << 14)
#define IT_ARMOR3 (1 << 15)
#define IT_SUPERHEALTH (1 << 16)
#define IT_KEY1 (1 << 17)
#define IT_KEY2 (1 << 18)
#define IT_INVISIBILITY (1 << 19)
#define IT_INVULNERABILITY (1 << 20)
#define IT_SUIT (1 << 21)
#define IT_QUAD (1 << 22)
extern int gmsgHudText;
extern BOOL gInitHUD;
#define MAX_TELES 256
#endif // PLAYER_H

View File

@ -0,0 +1,174 @@
/***
*
* 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.
*
****/
/*
===== quake_gun.cpp ========================================================
This is a half-life weapon that fires every one of the quake weapons.
It's automatically given to all players.
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "quake_gun.h"
LINK_ENTITY_TO_CLASS( weapon_quakegun, CQuakeGun );
//===========================================================
void CQuakeGun::Spawn( )
{
Precache( );
SET_MODEL(ENT(pev), "models/v_crowbar.mdl");
m_iDefaultAmmo = GLOCK_DEFAULT_GIVE;
FallInit();
}
void CQuakeGun::Precache( void )
{
PRECACHE_MODEL("models/v_crowbar.mdl");
PRECACHE_MODEL("models/p_9mmhandgun.mdl");
}
int CQuakeGun::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = NULL;
p->iMaxAmmo1 = -1;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = -1;
p->iSlot = 1;
p->iPosition = 1;
p->iFlags = 0;
p->iId = m_iId = WEAPON_GLOCK;
p->iWeight = GLOCK_WEIGHT;
return 1;
}
void CQuakeGun::DestroyEffect( void )
{
#ifndef CLIENT_DLL
if ( m_pBeam )
{
UTIL_Remove( m_pBeam );
m_pBeam = NULL;
}
#endif
}
void CQuakeGun::CreateEffect( void )
{
#ifndef CLIENT_DLL
DestroyEffect();
m_pBeam = CBeam::BeamCreate( "sprites/laserbeam.spr", 40 );
m_pBeam->PointEntInit( pev->origin, m_pPlayer->entindex() );
m_pBeam->SetBrightness( 100 );
m_pBeam->SetEndAttachment( 1 );
m_pBeam->pev->spawnflags |= SF_BEAM_TEMPORARY; // Flag these to be destroyed on save/restore or level transition
m_pBeam->pev->flags |= FL_SKIPLOCALHOST;
m_pBeam->pev->owner = m_pPlayer->edict();
m_pBeam->SetScrollRate( 110 );
m_pBeam->SetNoise( 5 );
#endif
}
void CQuakeGun::UpdateEffect( void )
{
#if !defined( CLIENT_DLL )
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
Vector vecAiming = gpGlobals->v_forward;
Vector vecSrc = m_pPlayer->GetGunPosition( );
Vector vecDest = vecSrc + vecAiming * 2048;
edict_t *pentIgnore;
TraceResult tr;
pentIgnore = m_pPlayer->edict();
Vector tmpSrc = vecSrc + gpGlobals->v_up * -8 + gpGlobals->v_right * 3;
// ALERT( at_console, "." );
UTIL_TraceLine( vecSrc, vecDest, dont_ignore_monsters, pentIgnore, &tr );
if (tr.fAllSolid)
return;
if ( !m_pBeam )
{
CreateEffect();
}
m_pBeam->SetStartPos( tr.vecEndPos );
#endif
}
#if !defined( CLIENT_DLL )
BOOL CQuakeGun::Deploy( )
{
m_pPlayer->pev->viewmodel = MAKE_STRING("models/v_crowbar.mdl");
m_pPlayer->pev->weaponmodel = MAKE_STRING("models/p_9mmhandgun.mdl");
strcpy( m_pPlayer->m_szAnimExtention, "onehanded" );
#ifdef CLIENT_DLL
g_flLightTime = 0.0;
#endif
SendWeaponAnim( 0 );
return TRUE;
}
#endif
// Plays quad sound if needed
int CQuakeGun::SuperDamageSound()
{
if ( m_pPlayer->m_iQuakeItems & IT_QUAD )
{
if ( m_pPlayer->m_flNextQuadSound < gpGlobals->time)
{
m_pPlayer->m_flNextQuadSound = gpGlobals->time + 1;
return 1;
}
}
return 0;
}
// Firing the Quakegun forces the player to fire the appropriate weapon
void CQuakeGun::PrimaryAttack( void )
{
int iQuadSound = 0;
iQuadSound = SuperDamageSound();
m_pPlayer->W_Attack( iQuadSound );
#if !defined( CLIENT_DLL )
if ( m_pPlayer->m_iQuakeWeapon == IT_LIGHTNING && m_pPlayer->pev->deadflag == DEAD_NO )
UpdateEffect();
#endif
m_bPlayedIdleAnim = FALSE;
}

View File

@ -0,0 +1,44 @@
/***
*
* 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.
*
****/
/*
===== quake_gun.h ========================================================
This is a half-life weapon that fires every one of the quake weapons.
It's automatically given to all players.
*/
#include "effects.h"
class CQuakeGun : public CBasePlayerWeapon
{
public:
void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 1; }
int GetItemInfo(ItemInfo *p);
int SuperDamageSound( void );
void PrimaryAttack( void );
BOOL Deploy( void );
void UpdateEffect( void );
void CreateEffect ( void );
void DestroyEffect ( void );
CBeam *m_pBeam;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,122 @@
//=========== (C) Copyright 1996-2002, Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Quake nail entity
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "weapons.h"
#include "decals.h"
#include "gamerules.h"
LINK_ENTITY_TO_CLASS( quake_nail, CQuakeNail );
//=========================================================
CQuakeNail *CQuakeNail::CreateNail( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner )
{
CQuakeNail *pNail = GetClassPtr( (CQuakeNail *)NULL );
UTIL_SetOrigin( pNail->pev, vecOrigin );
pNail->pev->velocity = vecAngles * 1000;
pNail->pev->angles = UTIL_VecToAngles(vecAngles);
pNail->pev->owner = pOwner->edict();
pNail->Spawn();
pNail->pev->classname = MAKE_STRING("spike");
// don't send to clients.
pNail->pev->effects |= EF_NODRAW;
return pNail;
}
CQuakeNail *CQuakeNail::CreateSuperNail( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner )
{
CQuakeNail *pNail = CreateNail( vecOrigin, vecAngles, pOwner );
pNail->pev->classname = MAKE_STRING("superspike");
// Super nails simply do more damage
pNail->pev->dmg = 18;
return pNail;
}
//=========================================================
void CQuakeNail::Spawn( void )
{
Precache();
// Setup
pev->movetype = MOVETYPE_FLYMISSILE;
pev->solid = SOLID_BBOX;
// Safety removal
pev->nextthink = gpGlobals->time + 6;
SetThink( &CBaseEntity::SUB_Remove );
// Touch
SetTouch( &CQuakeNail::NailTouch );
// Model
SET_MODEL( ENT(pev), "models/spike.mdl" );
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
UTIL_SetOrigin( pev, pev->origin );
// Damage
pev->dmg = 9;
}
//=========================================================
void CQuakeNail::NailTouch( CBaseEntity *pOther )
{
if (pOther->pev->solid == SOLID_TRIGGER)
return;
// Remove if we've hit skybrush
if ( UTIL_PointContents(pev->origin) == CONTENT_SKY )
{
UTIL_Remove( this );
return;
}
// Hit something that bleeds
if (pOther->pev->takedamage)
{
CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner);
if ( g_pGameRules->PlayerRelationship( pOther, pOwner ) != GR_TEAMMATE )
SpawnBlood( pev->origin, pOther->BloodColor(), pev->dmg );
pOther->TakeDamage( pev, pOwner->pev, pev->dmg, DMG_GENERIC );
}
else
{
if ( pOther->pev->solid == SOLID_BSP || pOther->pev->movetype == MOVETYPE_PUSHSTEP )
{
TraceResult tr;
tr.vecEndPos = pev->origin;
tr.pHit = pOther->edict();
//Arent we doing this client side?
//UTIL_GunshotDecalTrace( &tr, DECAL_GUNSHOT1 + RANDOM_LONG( 0, 4 ) );
}
}
UTIL_Remove( this );
}

View File

@ -0,0 +1,250 @@
/***
*
* 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.
*
****/
/*
===== quake_player.cpp ========================================================
Quake Classic player functionality.
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "gamerules.h"
#include "hltv.h"
extern entvars_t *g_pevLastInflictor;
extern int gmsgStatusText;
extern int gmsgStatusValue;
extern DLL_GLOBAL Vector g_vecAttackDir;
/*************************************
STATUS BAR
*************************************/
// Initialise the player's status bar
void CBasePlayer::InitStatusBar()
{
m_flStatusBarDisappearDelay = 0;
m_SbarString1[0] = m_SbarString0[0] = 0;
}
void CBasePlayer::UpdateStatusBar()
{
int newSBarState[ SBAR_END ];
memset( newSBarState, 0, sizeof(newSBarState) );
// Find an ID Target
TraceResult tr;
UTIL_MakeVectors( pev->v_angle + pev->punchangle );
Vector vecSrc = EyePosition();
Vector vecEnd = vecSrc + (gpGlobals->v_forward * MAX_ID_RANGE);
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, edict(), &tr);
if (tr.flFraction != 1.0)
{
if ( !FNullEnt( tr.pHit ) )
{
CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit );
if ( pEntity->Classify() == CLASS_PLAYER )
{
newSBarState[ SBAR_ID_TARGETNAME ] = ENTINDEX( pEntity->edict() );
newSBarState[ SBAR_ID_TARGETTEAM ] = FALSE;
m_flStatusBarDisappearDelay = gpGlobals->time + 1.0;
}
}
else if ( m_flStatusBarDisappearDelay > gpGlobals->time )
{
// hold the values for a short amount of time after viewing the object
newSBarState[ SBAR_ID_TARGETNAME ] = m_izSBarState[ SBAR_ID_TARGETNAME ];
newSBarState[ SBAR_ID_TARGETHEALTH ] = m_izSBarState[ SBAR_ID_TARGETHEALTH ];
newSBarState[ SBAR_ID_TARGETARMOR ] = m_izSBarState[ SBAR_ID_TARGETARMOR ];
newSBarState[ SBAR_ID_TARGETTEAM ] = m_izSBarState[ SBAR_ID_TARGETTEAM ];
}
}
// Check values and send if they don't match
for (int i = 1; i < SBAR_END; i++)
{
if ( newSBarState[i] != m_izSBarState[i] )
{
MESSAGE_BEGIN( MSG_ONE, gmsgStatusValue, NULL, pev );
WRITE_BYTE( i );
WRITE_SHORT( newSBarState[i] );
MESSAGE_END();
m_izSBarState[i] = newSBarState[i];
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Player has taken some damage. This is now using the Quake functionality.
//-----------------------------------------------------------------------------
int CBasePlayer::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
{
if ( (pev->takedamage == DAMAGE_NO) || (IsAlive() == FALSE) )
return 0;
//We are wearing the suit and we want to be hurt by lava or slime
if ( m_iQuakeItems & IT_SUIT )
{
if ( bitsDamageType & DMG_BURN || bitsDamageType & DMG_ACID )
return 0;
}
CBaseEntity *pAttacker = CBaseEntity::Instance(pevAttacker);
// keep track of amount of damage last sustained
m_lastDamageAmount = static_cast<int>(flDamage);
// check for quad damage powerup on the attacker
if (pAttacker->IsPlayer())
{
if ( ((CBasePlayer*)pAttacker)->m_flSuperDamageFinished > gpGlobals->time )
{
if (gpGlobals->deathmatch == 4)
flDamage *= 8;
else
flDamage *= 4;
}
}
// team play damage avoidance
if ( g_pGameRules->PlayerRelationship( this, pAttacker ) == GR_TEAMMATE )
{
// Teamplay 3 you can still hurt yourself
if ( CVAR_GET_FLOAT( "mp_teamplay" ) == 3 && pAttacker != this )
return 0;
// Teamplay 1 can't hurt any teammates, including yourself
if ( CVAR_GET_FLOAT( "mp_teamplay" ) == 1 )
return 0;
// Teamplay 2 you can still hurt teammates
}
// save damage based on the target's armor level
float flSave = ceil(pev->armortype * flDamage);
if (flSave >= pev->armorvalue)
{
flSave = pev->armorvalue;
pev->armortype = 0; // lost all armor
m_iQuakeItems &= ~(IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3);
}
pev->armorvalue -= flSave;
float flTake = ceil(flDamage - flSave);
// add to the damage total for clients, which will be sent as a single message at the end of the frame
pev->dmg_take = pev->dmg_take + flTake;
pev->dmg_inflictor = ENT(pevInflictor);
Vector vecTemp;
if ( pevAttacker == pevInflictor )
{
vecTemp = pevAttacker->origin - ( VecBModelOrigin(pev) );
}
else
// an actual missile was involved.
{
vecTemp = pevInflictor->origin - ( VecBModelOrigin(pev) );
}
// this global is still used for glass and other non-monster killables, along with decals.
g_vecAttackDir = vecTemp.Normalize();
// figure momentum add
if ( (pevInflictor) && (pev->movetype == MOVETYPE_WALK) && !( FBitSet (bitsDamageType, DMG_BURN) ) && !( FBitSet (bitsDamageType, DMG_ACID) ) )
{
Vector vecPush = (pev->origin - (pevInflictor->absmin + pevInflictor->absmax) * 0.5).Normalize();
// Set kickback for smaller weapons
// Read: only if it's not yourself doing the damage
if ( (flDamage < 60) && pAttacker->IsPlayer() && (pAttacker != this) )
pev->velocity = pev->velocity + vecPush * flDamage * 11;
else
{
// Otherwise, these rules apply to rockets and grenades
// for blast velocity
if ( pAttacker == this )
{
if ( m_iQuakeWeapon != IT_LIGHTNING )
pev->velocity = pev->velocity + vecPush * flDamage * 8;
}
else
pev->velocity = pev->velocity + vecPush * flDamage * 8;
}
// Rocket Jump modifiers
int iRocketJumpModifier = (int)CVAR_GET_FLOAT("rj");
if ( (iRocketJumpModifier > 1) && (pAttacker == this) && m_iQuakeWeapon == ( IT_ROCKET_LAUNCHER | IT_GRENADE_LAUNCHER ) )
pev->velocity = pev->velocity + vecPush * flDamage * iRocketJumpModifier;
}
// check for godmode or invincibility
if (pev->flags & FL_GODMODE)
return 0;
if (m_flInvincibleFinished > gpGlobals->time)
{
if (m_fInvincSound < gpGlobals->time)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
m_fInvincSound = gpGlobals->time + 2;
}
return 0;
}
// do the damage
pev->health -= (int)flTake;
// tell director about it
MESSAGE_BEGIN( MSG_SPEC, SVC_DIRECTOR );
WRITE_BYTE ( 9 ); // command length in bytes
WRITE_BYTE ( DRC_CMD_EVENT ); // take damage event
WRITE_SHORT( ENTINDEX(this->edict()) ); // index number of primary entity
WRITE_SHORT( ENTINDEX(ENT(pevInflictor)) ); // index number of secondary entity
WRITE_LONG( 5 ); // eventflags (priority and flags)
MESSAGE_END();
// react to the damage
m_bitsDamageType |= bitsDamageType; // Save this so we can report it to the client
m_bitsHUDDamage = -1; // make sure the damage bits get resent
if ( pev->health <= 0 )
{
g_pevLastInflictor = pevInflictor;
Killed( pevAttacker, GIB_NORMAL );
g_pevLastInflictor = NULL;
return 0;
}
// play pain sound
Pain( pAttacker );
return static_cast<int>(flTake);
}

View File

@ -0,0 +1,191 @@
//=========== (C) Copyright 1996-2002, Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Quake rocket entity
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "weapons.h"
#define GRENADE_TRAIL 1
#define ROCKET_TRAIL 2
extern unsigned short g_sTrail;
extern unsigned short g_sExplosion;
LINK_ENTITY_TO_CLASS( quake_rocket, CQuakeRocket );
//=========================================================
CQuakeRocket *CQuakeRocket::CreateRocket( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner )
{
CQuakeRocket *pRocket = GetClassPtr( (CQuakeRocket *)NULL );
UTIL_SetOrigin( pRocket->pev, vecOrigin );
SET_MODEL(ENT(pRocket->pev), "models/rocket.mdl");
pRocket->Spawn();
pRocket->pev->classname = MAKE_STRING("missile");
pRocket->pev->owner = pOwner->edict();
// Setup
pRocket->pev->movetype = MOVETYPE_FLYMISSILE;
pRocket->pev->solid = SOLID_BBOX;
// Velocity
pRocket->pev->velocity = vecAngles * 1000;
pRocket->pev->angles = UTIL_VecToAngles( vecAngles );
// Touch
pRocket->SetTouch( &CQuakeRocket::RocketTouch );
// Safety Remove
pRocket->pev->nextthink = gpGlobals->time + 5;
pRocket->SetThink( &CBaseEntity::SUB_Remove );
// Effects
// pRocket->pev->effects |= EF_LIGHT;
PLAYBACK_EVENT_FULL (FEV_GLOBAL, pRocket->edict(), g_sTrail, 0.0,
(float *)&pRocket->pev->origin, (float *)&pRocket->pev->angles, 0.7, 0.0, pRocket->entindex(), ROCKET_TRAIL, 0, 0);
return pRocket;
}
//=========================================================
CQuakeRocket *CQuakeRocket::CreateGrenade( Vector vecOrigin, Vector vecVelocity, CBaseEntity *pOwner )
{
CQuakeRocket *pRocket = GetClassPtr( (CQuakeRocket *)NULL );
UTIL_SetOrigin( pRocket->pev, vecOrigin );
SET_MODEL(ENT(pRocket->pev), "models/grenade.mdl");
pRocket->Spawn();
pRocket->pev->classname = MAKE_STRING("grenade");
pRocket->pev->owner = pOwner->edict();
// Setup
pRocket->pev->movetype = MOVETYPE_BOUNCE;
pRocket->pev->solid = SOLID_BBOX;
pRocket->pev->avelocity = Vector(300,300,300);
// Velocity
pRocket->pev->velocity = vecVelocity;
pRocket->pev->angles = UTIL_VecToAngles(vecVelocity);
pRocket->pev->friction = 0.5;
// Touch
pRocket->SetTouch( &CQuakeRocket::GrenadeTouch );
// set newmis duration
if ( gpGlobals->deathmatch == 4 )
{
pRocket->m_flAttackFinished = gpGlobals->time + 1.1; // What's this used for?
if (pOwner)
pOwner->TakeDamage( pOwner->pev, pOwner->pev, 10, DMG_GENERIC );
}
pRocket->pev->nextthink = gpGlobals->time + 2.5;
pRocket->SetThink( &CQuakeRocket::GrenadeExplode );
PLAYBACK_EVENT_FULL (FEV_GLOBAL, pRocket->edict(), g_sTrail, 0.0,
(float *)&g_vecZero, (float *)&g_vecZero, 0.7, 0.0, pRocket->entindex(), GRENADE_TRAIL, 0, 0);
return pRocket;
}
//=========================================================
void CQuakeRocket::Spawn( void )
{
Precache();
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
UTIL_SetOrigin( pev, pev->origin );
}
//=========================================================
void CQuakeRocket::Precache( void )
{
m_iTrail = PRECACHE_MODEL("sprites/smoke.spr");
}
//=========================================================
void CQuakeRocket::RocketTouch ( CBaseEntity *pOther )
{
// Remove if we've hit skybrush
if ( UTIL_PointContents(pev->origin) == CONTENT_SKY )
{
UTIL_Remove( this );
return;
}
// Do touch damage
float flDmg = RANDOM_FLOAT( 100, 120 );
CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner);
if (pOther->pev->health)
pOther->TakeDamage( pev, pOwner->pev, flDmg, DMG_BULLET );
// Don't do radius damage to the other, because all the damage was done in the impact
Q_RadiusDamage(this, pOwner, 120, pOther);
// Finish and remove
Explode();
}
//=========================================================
void CQuakeRocket::GrenadeTouch( CBaseEntity *pOther )
{
if (pOther->pev->takedamage == DAMAGE_AIM)
{
GrenadeExplode();
return;
}
if (pev->flags & FL_ONGROUND)
{
// add a bit of static friction
pev->velocity = pev->velocity * 0.75;
if (pev->velocity.Length() <= 20)
{
pev->avelocity = g_vecZero;
}
}
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
if (pev->velocity == g_vecZero)
pev->avelocity = g_vecZero;
}
//=========================================================
void CQuakeRocket::GrenadeExplode()
{
CBaseEntity *pOwner = CBaseEntity::Instance(pev->owner);
Q_RadiusDamage(this, pOwner, 120, NULL);
// Finish and remove
Explode();
}
//=========================================================
void CQuakeRocket::Explode()
{
//We use the angles field to send the rocket velocity.
PLAYBACK_EVENT_FULL( FEV_GLOBAL, edict(), g_sExplosion, 0.0, (float *)&pev->origin, (float *)&pev->velocity, 0.0, 0.0, 0, 0, 0, 0 );
UTIL_Remove( this );
}

View File

@ -0,0 +1,996 @@
/***
*
* 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.
*
****/
/*
===== quake_weapons.cpp ========================================================
Quake weaponry
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "quake_gun.h"
char gszQ_DeathType[128];
DLL_GLOBAL short g_sModelIndexNail;
#ifdef CLIENT_DLL
#include "cl_entity.h"
struct cl_entity_s *GetViewEntity( void );
extern float g_flLightTime;
#endif
// called by worldspawn
void QuakeClassicPrecache( void )
{
// Weapon sounds
PRECACHE_SOUND("weapons/ax1.wav");
PRECACHE_SOUND("player/axhit2.wav");
PRECACHE_SOUND("player/axhitbod.wav");
PRECACHE_SOUND("weapons/r_exp3.wav"); // new rocket explosion
PRECACHE_SOUND("weapons/rocket1i.wav");// spike gun
PRECACHE_SOUND("weapons/sgun1.wav");
PRECACHE_SOUND("weapons/lhit.wav");
PRECACHE_SOUND("weapons/guncock.wav"); // player shotgun
PRECACHE_SOUND("weapons/ric1.wav"); // ricochet (used in c code)
PRECACHE_SOUND("weapons/ric2.wav"); // ricochet (used in c code)
PRECACHE_SOUND("weapons/ric3.wav"); // ricochet (used in c code)
PRECACHE_SOUND("weapons/spike2.wav"); // super spikes
PRECACHE_SOUND("weapons/tink1.wav"); // spikes tink (used in c code)
PRECACHE_SOUND("weapons/grenade.wav"); // grenade launcher
PRECACHE_SOUND("weapons/bounce.wav"); // grenade bounce
PRECACHE_SOUND("weapons/shotgn2.wav"); // super shotgun
PRECACHE_SOUND("weapons/lstart.wav"); // lightning start
// Weapon models
PRECACHE_MODEL("models/v_crowbar.mdl");
PRECACHE_MODEL("models/v_shot.mdl");
PRECACHE_MODEL("models/v_shot2.mdl");
PRECACHE_MODEL("models/v_nail.mdl");
PRECACHE_MODEL("models/v_nail2.mdl");
PRECACHE_MODEL("models/v_rock.mdl");
PRECACHE_MODEL("models/v_rock2.mdl");
PRECACHE_MODEL("models/v_light.mdl");
// Weapon player models
PRECACHE_MODEL("models/p_crowbar.mdl");
PRECACHE_MODEL("models/p_rock2.mdl");
PRECACHE_MODEL("models/p_rock.mdl");
PRECACHE_MODEL("models/p_shot2.mdl");
PRECACHE_MODEL("models/p_nail.mdl");
PRECACHE_MODEL("models/p_nail2.mdl");
PRECACHE_MODEL("models/p_light.mdl");
PRECACHE_MODEL("models/p_shot.mdl");
// Weapon effect models
PRECACHE_MODEL("models/rocket.mdl"); // rocket
PRECACHE_MODEL("models/grenade.mdl"); // grenade
g_sModelIndexNail = PRECACHE_MODEL("models/spike.mdl");
g_sModelIndexLaser = PRECACHE_MODEL("sprites/laserbeam.spr");
PRECACHE_MODEL("sprites/smoke.spr");
// Powerup models
// Powerup sounds
PRECACHE_SOUND("items/damage3.wav");
PRECACHE_SOUND("items/sight1.wav");
// Teleport sounds
PRECACHE_SOUND("misc/r_tele1.wav");
PRECACHE_SOUND("misc/r_tele2.wav");
PRECACHE_SOUND("misc/r_tele3.wav");
PRECACHE_SOUND("misc/r_tele4.wav");
PRECACHE_SOUND("misc/r_tele5.wav");
// Misc
PRECACHE_SOUND("weapons/lock4.wav");
PRECACHE_SOUND("weapons/pkup.wav");
PRECACHE_SOUND("items/itembk2.wav");
PRECACHE_MODEL("models/backpack.mdl");
}
//================================================================================================
// WEAPON SELECTION
//================================================================================================
// Return the ID of the best weapon being carried by the player
int CBasePlayer::W_BestWeapon()
{
if (pev->waterlevel <= 1 && m_iAmmoCells >= 1 && (m_iQuakeItems & IT_LIGHTNING) )
return IT_LIGHTNING;
else if(m_iAmmoNails >= 2 && (m_iQuakeItems & IT_SUPER_NAILGUN) )
return IT_SUPER_NAILGUN;
else if(m_iAmmoShells >= 2 && (m_iQuakeItems & IT_SUPER_SHOTGUN) )
return IT_SUPER_SHOTGUN;
else if(m_iAmmoNails >= 1 && (m_iQuakeItems & IT_NAILGUN) )
return IT_NAILGUN;
else if(m_iAmmoShells >= 1 && (m_iQuakeItems & IT_SHOTGUN) )
return IT_SHOTGUN;
return IT_AXE;
}
// Weapon setup after weapon switch
void CBasePlayer::W_SetCurrentAmmo( int sendanim /* = 1 */ )
{
m_iQuakeItems &= ~(IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS);
int iszViewModel = 0;
char *viewmodel = "";
int iszWeaponModel = 0;
char *szAnimExt = NULL;
// Find out what weapon the player's using
if (m_iQuakeWeapon == IT_AXE)
{
m_pCurrentAmmo = NULL;
viewmodel = "models/v_crowbar.mdl";
iszViewModel = MAKE_STRING(viewmodel);
szAnimExt = "crowbar";
iszWeaponModel = MAKE_STRING("models/p_crowbar.mdl");
}
else if (m_iQuakeWeapon == IT_SHOTGUN)
{
m_pCurrentAmmo = &m_iAmmoShells;
viewmodel = "models/v_shot.mdl";
iszViewModel = MAKE_STRING(viewmodel);
iszWeaponModel = MAKE_STRING("models/p_shot.mdl");
m_iQuakeItems |= IT_SHELLS;
szAnimExt = "shotgun";
}
else if (m_iQuakeWeapon == IT_SUPER_SHOTGUN)
{
m_pCurrentAmmo = &m_iAmmoShells;
viewmodel = "models/v_shot2.mdl";
iszViewModel = MAKE_STRING(viewmodel);
iszWeaponModel = MAKE_STRING("models/p_shot2.mdl");
m_iQuakeItems |= IT_SHELLS;
szAnimExt = "shotgun";
}
else if (m_iQuakeWeapon == IT_NAILGUN)
{
m_pCurrentAmmo = &m_iAmmoNails;
viewmodel = "models/v_nail.mdl";
iszViewModel = MAKE_STRING(viewmodel);
iszWeaponModel = MAKE_STRING("models/p_nail.mdl");
m_iQuakeItems |= IT_NAILS;
szAnimExt = "mp5";
}
else if (m_iQuakeWeapon == IT_SUPER_NAILGUN)
{
m_pCurrentAmmo = &m_iAmmoNails;
viewmodel = "models/v_nail2.mdl";
iszViewModel = MAKE_STRING(viewmodel);
iszWeaponModel = MAKE_STRING("models/p_nail2.mdl");
m_iQuakeItems |= IT_NAILS;
szAnimExt = "mp5";
}
else if (m_iQuakeWeapon == IT_GRENADE_LAUNCHER)
{
m_pCurrentAmmo = &m_iAmmoRockets;
viewmodel = "models/v_rock.mdl";
iszViewModel = MAKE_STRING(viewmodel);
m_iQuakeItems |= IT_ROCKETS;
iszWeaponModel = MAKE_STRING("models/p_rock.mdl");
szAnimExt = "gauss";
}
else if (m_iQuakeWeapon == IT_ROCKET_LAUNCHER)
{
m_pCurrentAmmo = &m_iAmmoRockets;
viewmodel = "models/v_rock2.mdl";
iszViewModel = MAKE_STRING(viewmodel);
m_iQuakeItems |= IT_ROCKETS;
iszWeaponModel = MAKE_STRING("models/p_rock2.mdl");
szAnimExt = "gauss";
}
else if (m_iQuakeWeapon == IT_LIGHTNING)
{
m_pCurrentAmmo = &m_iAmmoCells;
viewmodel = "models/v_light.mdl";
iszViewModel = MAKE_STRING(viewmodel);
iszWeaponModel = MAKE_STRING("models/p_light.mdl");
m_iQuakeItems |= IT_CELLS;
szAnimExt = "gauss";
}
else
{
m_pCurrentAmmo = NULL;
}
#if !defined( CLIENT_DLL )
pev->viewmodel = iszViewModel;
pev->weaponmodel = iszWeaponModel;
strcpy( m_szAnimExtention, szAnimExt );
#else
{
int HUD_GetModelIndex( char *modelname );
pev->viewmodel = HUD_GetModelIndex( viewmodel );
cl_entity_t *view;
view = GetViewEntity();
//Adrian - The actual "magic" is done in the
//Studio drawing code.
if ( m_iQuakeItems & IT_INVISIBILITY )
{
if( view )
{
view->curstate.renderfx = kRenderFxGlowShell;
view->curstate.renderamt = 5;
view->curstate.rendercolor.r = 125;
view->curstate.rendercolor.g = 125;
view->curstate.rendercolor.b = 125;
}
}
else
{
if ( m_iQuakeItems & IT_INVULNERABILITY )
{
if( view )
{
view->curstate.renderfx = kRenderFxGlowShell;
view->curstate.renderamt = 15;
view->curstate.rendercolor.r = 255;
view->curstate.rendercolor.g = 125;
view->curstate.rendercolor.b = 125;
}
}
else if ( m_iQuakeItems & IT_QUAD )
{
if( view )
{
view->curstate.renderfx = kRenderFxGlowShell;
view->curstate.renderamt = 15;
view->curstate.rendercolor.r = 125;
view->curstate.rendercolor.g = 125;
view->curstate.rendercolor.b = 255;
}
}
else if ( m_iQuakeItems & ( IT_INVULNERABILITY | IT_QUAD ) )
{
if( view )
{
view->curstate.renderfx = kRenderFxGlowShell;
view->curstate.renderamt = 15;
view->curstate.rendercolor.r = 255;
view->curstate.rendercolor.g = 125;
view->curstate.rendercolor.b = 255;
}
}
else
view->curstate.renderfx = kRenderFxNone; // Clear it.
}
}
#endif
}
// Return TRUE if the weapon still has ammo
BOOL CBasePlayer::W_CheckNoAmmo()
{
if ( m_pCurrentAmmo && *m_pCurrentAmmo > 0 )
return TRUE;
if ( m_iQuakeWeapon == IT_AXE )
return TRUE;
if ( m_iQuakeWeapon == IT_LIGHTNING )
{
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usLightning, 0, (float *)&pev->origin, (float *)&pev->angles, 0.0, 0.0, 0, 1, 0, 0 );
if ( m_pActiveItem )
((CQuakeGun*)m_pActiveItem)->DestroyEffect();
}
m_iQuakeWeapon = W_BestWeapon();
W_SetCurrentAmmo();
return FALSE;
}
// Change to the specified weapon
void CBasePlayer::W_ChangeWeapon( int iWeaponNumber )
{
if ( m_iQuakeWeapon == IT_LIGHTNING )
{
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usLightning, 0, (float *)&pev->origin, (float *)&pev->angles, 0.0, 0.0, 0, 1, 0, 0 );
if ( m_pActiveItem )
((CQuakeGun*)m_pActiveItem)->DestroyEffect();
}
int iWeapon = 0;
BOOL bHaveAmmo = TRUE;
if (iWeaponNumber == 1)
{
iWeapon = IT_AXE;
}
else if (iWeaponNumber == 2)
{
iWeapon = IT_SHOTGUN;
if (m_iAmmoShells < 1)
bHaveAmmo = FALSE;
}
else if (iWeaponNumber == 3)
{
iWeapon = IT_SUPER_SHOTGUN;
if (m_iAmmoShells < 2)
bHaveAmmo = FALSE;
}
else if (iWeaponNumber == 4)
{
iWeapon = IT_NAILGUN;
if (m_iAmmoNails < 1)
bHaveAmmo = FALSE;
}
else if (iWeaponNumber == 5)
{
iWeapon = IT_SUPER_NAILGUN;
if (m_iAmmoNails < 2)
bHaveAmmo = FALSE;
}
else if (iWeaponNumber == 6)
{
iWeapon = IT_GRENADE_LAUNCHER;
if (m_iAmmoRockets < 1)
bHaveAmmo = FALSE;
}
else if (iWeaponNumber == 7)
{
iWeapon = IT_ROCKET_LAUNCHER;
if (m_iAmmoRockets < 1)
bHaveAmmo = FALSE;
}
else if (iWeaponNumber == 8)
{
iWeapon = IT_LIGHTNING;
if (m_iAmmoCells < 1)
bHaveAmmo = FALSE;
}
// Have the weapon?
if ( !(m_iQuakeItems & iWeapon) )
{
ClientPrint( pev, HUD_PRINTCONSOLE, "#No_Weapon" );
return;
}
// Have ammo for it?
if ( !bHaveAmmo )
{
ClientPrint( pev, HUD_PRINTCONSOLE, "#No_Ammo" );
return;
}
// Set weapon, update ammo
m_iQuakeWeapon = iWeapon;
W_SetCurrentAmmo();
#ifdef CLIENT_DLL
g_flLightTime = 0.0;
#endif
}
// Go to the next weapon with ammo
void CBasePlayer::W_CycleWeaponCommand( void )
{
while (1)
{
BOOL bHaveAmmo = TRUE;
if (m_iQuakeWeapon == IT_LIGHTNING)
{
m_iQuakeWeapon = IT_EXTRA_WEAPON;
}
else if (m_iQuakeWeapon == IT_EXTRA_WEAPON)
{
m_iQuakeWeapon = IT_AXE;
}
else if (m_iQuakeWeapon == IT_AXE)
{
m_iQuakeWeapon = IT_SHOTGUN;
if (m_iAmmoShells < 1)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_SHOTGUN)
{
m_iQuakeWeapon = IT_SUPER_SHOTGUN;
if (m_iAmmoShells < 2)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_SUPER_SHOTGUN)
{
m_iQuakeWeapon = IT_NAILGUN;
if (m_iAmmoNails < 1)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_NAILGUN)
{
m_iQuakeWeapon = IT_SUPER_NAILGUN;
if (m_iAmmoNails < 2)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_SUPER_NAILGUN)
{
m_iQuakeWeapon = IT_GRENADE_LAUNCHER;
if (m_iAmmoRockets < 1)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_GRENADE_LAUNCHER)
{
m_iQuakeWeapon = IT_ROCKET_LAUNCHER;
if (m_iAmmoRockets < 1)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_ROCKET_LAUNCHER)
{
m_iQuakeWeapon = IT_LIGHTNING;
if (m_iAmmoCells < 1)
bHaveAmmo = FALSE;
}
if ( (m_iQuakeItems & m_iQuakeWeapon) && bHaveAmmo )
{
W_SetCurrentAmmo();
return;
}
}
}
// Go to the prev weapon with ammo
void CBasePlayer::W_CycleWeaponReverseCommand()
{
while (1)
{
BOOL bHaveAmmo = TRUE;
if (m_iQuakeWeapon == IT_EXTRA_WEAPON)
{
m_iQuakeWeapon = IT_LIGHTNING;
}
else if (m_iQuakeWeapon == IT_LIGHTNING)
{
m_iQuakeWeapon = IT_ROCKET_LAUNCHER;
if (m_iAmmoRockets < 1)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_ROCKET_LAUNCHER)
{
m_iQuakeWeapon = IT_GRENADE_LAUNCHER;
if (m_iAmmoRockets < 1)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_GRENADE_LAUNCHER)
{
m_iQuakeWeapon = IT_SUPER_NAILGUN;
if (m_iAmmoNails < 2)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_SUPER_NAILGUN)
{
m_iQuakeWeapon = IT_NAILGUN;
if (m_iAmmoNails < 1)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_NAILGUN)
{
m_iQuakeWeapon = IT_SUPER_SHOTGUN;
if (m_iAmmoShells < 2)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_SUPER_SHOTGUN)
{
m_iQuakeWeapon = IT_SHOTGUN;
if (m_iAmmoShells < 1)
bHaveAmmo = FALSE;
}
else if (m_iQuakeWeapon == IT_SHOTGUN)
{
m_iQuakeWeapon = IT_AXE;
}
else if (m_iQuakeWeapon == IT_AXE)
{
m_iQuakeWeapon = IT_EXTRA_WEAPON;
}
else if (m_iQuakeWeapon == IT_EXTRA_WEAPON)
{
m_iQuakeWeapon = IT_LIGHTNING;
if (m_iAmmoCells < 1)
bHaveAmmo = FALSE;
}
if ( (m_iQuakeItems & m_iQuakeWeapon) && bHaveAmmo )
{
W_SetCurrentAmmo();
return;
}
}
}
//================================================================================================
// WEAPON FUNCTIONS
//================================================================================================
// Returns true if the inflictor can directly damage the target. Used for explosions and melee attacks.
float Q_CanDamage(CBaseEntity *pTarget, CBaseEntity *pInflictor)
{
TraceResult trace;
// bmodels need special checking because their origin is 0,0,0
if (pTarget->pev->movetype == MOVETYPE_PUSH)
{
UTIL_TraceLine( pInflictor->pev->origin, 0.5 * (pTarget->pev->absmin + pTarget->pev->absmax), ignore_monsters, NULL, &trace );
if (trace.flFraction == 1)
return TRUE;
CBaseEntity *pEntity = CBaseEntity::Instance(trace.pHit);
if (pEntity == pTarget)
return TRUE;
return FALSE;
}
UTIL_TraceLine( pInflictor->pev->origin, pTarget->pev->origin, ignore_monsters, NULL, &trace );
if (trace.flFraction == 1)
return TRUE;
UTIL_TraceLine( pInflictor->pev->origin, pTarget->pev->origin + Vector(15,15,0), ignore_monsters, NULL, &trace );
if (trace.flFraction == 1)
return TRUE;
UTIL_TraceLine( pInflictor->pev->origin, pTarget->pev->origin + Vector(-15,-15,0), ignore_monsters, NULL, &trace );
if (trace.flFraction == 1)
return TRUE;
UTIL_TraceLine( pInflictor->pev->origin, pTarget->pev->origin + Vector(-15,15,0), ignore_monsters, NULL, &trace );
if (trace.flFraction == 1)
return TRUE;
UTIL_TraceLine( pInflictor->pev->origin, pTarget->pev->origin + Vector(15,-15,0), ignore_monsters, NULL, &trace );
if (trace.flFraction == 1)
return TRUE;
return FALSE;
}
// Quake Bullet firing
void CBasePlayer::Q_FireBullets(int iShots, Vector vecDir, Vector vecSpread)
{
TraceResult trace;
UTIL_MakeVectors(pev->v_angle);
Vector vecSrc = pev->origin + (gpGlobals->v_forward * 10);
vecSrc.z = pev->absmin.z + (pev->size.z * 0.7);
ClearMultiDamage();
while ( iShots > 0 )
{
Vector vecPath = vecDir + ( RANDOM_FLOAT( -1, 1 ) * vecSpread.x * gpGlobals->v_right ) + ( RANDOM_FLOAT( -1, 1 ) * vecSpread.y * gpGlobals->v_up );
Vector vecEnd = vecSrc + ( vecPath * 2048 );
UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT(pev), &trace );
if (trace.flFraction != 1.0)
{
CBaseEntity *pEntity = CBaseEntity::Instance(trace.pHit);
if (pEntity && pEntity->pev->takedamage && pEntity->IsPlayer() )
{
pEntity->TraceAttack(pev, 4, vecPath, &trace, DMG_BULLET);
//AddMultiDamage(pev, pEntity, 4, DMG_BULLET);
}
else if ( pEntity && pEntity->pev->takedamage )
{
pEntity->TakeDamage( pev, pev, 4, DMG_BULLET );
}
}
iShots--;
}
ApplyMultiDamage( pev, pev );
}
#if !defined( CLIENT_DLL )
// Quake Radius damage
void Q_RadiusDamage( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, CBaseEntity *pIgnore )
{
CBaseEntity *pEnt = NULL;
while ( (pEnt = UTIL_FindEntityInSphere( pEnt, pInflictor->pev->origin, flDamage+40 )) != NULL )
{
if (pEnt != pIgnore)
{
if (pEnt->pev->takedamage)
{
Vector vecOrg = pEnt->pev->origin + ((pEnt->pev->mins + pEnt->pev->maxs) * 0.5);
float flPoints = 0.5 * (pInflictor->pev->origin - vecOrg).Length();
if (flPoints < 0)
flPoints = 0;
flPoints = flDamage - flPoints;
if (pEnt == pAttacker)
flPoints = flPoints * 0.5;
if (flPoints > 0)
{
if ( Q_CanDamage( pEnt, pInflictor ) )
pEnt->TakeDamage( pInflictor->pev, pAttacker->pev, flPoints, DMG_GENERIC );
}
}
}
}
}
#endif
// Lightning hit a target
void LightningHit(CBaseEntity *pTarget, CBaseEntity *pAttacker, Vector vecHitPos, float flDamage, TraceResult *ptr, Vector vecDir )
{
#ifndef CLIENT_DLL
SpawnBlood( vecHitPos, BLOOD_COLOR_RED, flDamage * 1.5 );
if ( g_pGameRules->PlayerRelationship( pTarget, pAttacker ) != GR_TEAMMATE )
{
pTarget->TakeDamage( pAttacker->pev, pAttacker->pev, flDamage, DMG_GENERIC );
pTarget->TraceBleed( flDamage, vecDir, ptr, DMG_BULLET ); // have to use DMG_BULLET or it wont spawn.
}
#endif
}
// Lightning Damage
void CBasePlayer::LightningDamage( Vector p1, Vector p2, CBaseEntity *pAttacker, float flDamage, Vector vecDir)
{
#if !defined( CLIENT_DLL )
TraceResult trace;
Vector vecThru = (p2 - p1).Normalize();
vecThru.x = 0 - vecThru.y;
vecThru.y = vecThru.x;
vecThru.z = 0;
vecThru = vecThru * 16;
CBaseEntity *pEntity1 = NULL;
CBaseEntity *pEntity2 = NULL;
// Hit first target?
UTIL_TraceLine( p1, p2, dont_ignore_monsters, ENT(pev), &trace );
CBaseEntity *pEntity = CBaseEntity::Instance(trace.pHit);
if (pEntity && pEntity->pev->takedamage)
{
LightningHit(pEntity, pAttacker, trace.vecEndPos, flDamage, &trace, vecDir );
}
pEntity1 = pEntity;
// Hit second target?
UTIL_TraceLine( p1 + vecThru, p2 + vecThru, dont_ignore_monsters, ENT(pev), &trace );
pEntity = CBaseEntity::Instance(trace.pHit);
if (pEntity && pEntity != pEntity1 && pEntity->pev->takedamage)
{
LightningHit(pEntity, pAttacker, trace.vecEndPos, flDamage, &trace, vecDir );
}
pEntity2 = pEntity;
// Hit third target?
UTIL_TraceLine( p1 - vecThru, p2 - vecThru, dont_ignore_monsters, ENT(pev), &trace );
pEntity = CBaseEntity::Instance(trace.pHit);
if (pEntity && pEntity != pEntity1 && pEntity != pEntity2 && pEntity->pev->takedamage)
{
LightningHit(pEntity, pAttacker, trace.vecEndPos, flDamage, &trace, vecDir );
}
#endif
}
//================================================================================================
// WEAPON FIRING
//================================================================================================
// Axe
void CBasePlayer::W_FireAxe()
{
TraceResult trace;
Vector vecSrc = pev->origin + Vector(0, 0, 16);
// Swing forward 64 units
UTIL_MakeVectors(pev->v_angle);
UTIL_TraceLine( vecSrc, vecSrc + (gpGlobals->v_forward * 64), dont_ignore_monsters, ENT(pev), &trace );
if (trace.flFraction == 1.0)
return;
Vector vecOrg = trace.vecEndPos - gpGlobals->v_forward * 4;
CBaseEntity *pEntity = CBaseEntity::Instance(trace.pHit);
if (pEntity && pEntity->pev->takedamage)
{
pEntity->m_bAxHitMe = TRUE;
int iDmg = 20;
if (gpGlobals->deathmatch > 3)
iDmg = 75;
pEntity->TakeDamage( pev, pev, iDmg, DMG_GENERIC );
#ifndef CLIENT_DLL
if ( g_pGameRules->PlayerRelationship( this, pEntity ) != GR_TEAMMATE )
SpawnBlood( vecOrg, BLOOD_COLOR_RED, iDmg * 4 ); // Make a lot of Blood!
#endif
}
}
// Single barrel shotgun
void CBasePlayer::W_FireShotgun( int iQuadSound )
{
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usShotgunSingle, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iQuadSound, 0, 0, 0 );
if (gpGlobals->deathmatch != 4 )
*m_pCurrentAmmo -= 1;
Vector vecDir = GetAutoaimVector( AUTOAIM_5DEGREES );
Q_FireBullets(6, vecDir, Vector(0.04, 0.04, 0) );
}
// Double barrel shotgun
void CBasePlayer::W_FireSuperShotgun( int iQuadSound )
{
if (*m_pCurrentAmmo == 1)
{
W_FireShotgun( iQuadSound );
return;
}
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usShotgunDouble, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iQuadSound, 0, 0, 0 );
if (gpGlobals->deathmatch != 4 )
*m_pCurrentAmmo -= 2;
Vector vecDir = GetAutoaimVector( AUTOAIM_5DEGREES );
Q_FireBullets(14, vecDir, Vector(0.14, 0.08, 0) );
};
// Rocket launcher
void CBasePlayer::W_FireRocket( int iQuadSound )
{
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usRocket, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iQuadSound, 0, 0, 0 );
if (gpGlobals->deathmatch != 4 )
*m_pCurrentAmmo -= 1;
// Create the rocket
UTIL_MakeVectors( pev->v_angle );
Vector vecOrg = pev->origin + (gpGlobals->v_forward * 8) + Vector(0,0,16);
Vector vecDir = GetAutoaimVector( AUTOAIM_5DEGREES );
CQuakeRocket::CreateRocket( vecOrg, vecDir, this );
}
// Grenade launcher
void CBasePlayer::W_FireGrenade( int iQuadSound )
{
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usGrenade, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iQuadSound, 0, 0, 0 );
if (gpGlobals->deathmatch != 4 )
*m_pCurrentAmmo -= 1;
// Get initial velocity
UTIL_MakeVectors( pev->v_angle );
Vector vecVelocity;
if ( pev->v_angle.x )
{
vecVelocity = gpGlobals->v_forward * 600 + gpGlobals->v_up * 200 + RANDOM_FLOAT(-1,1) * gpGlobals->v_right * 10 + RANDOM_FLOAT(-1,1) * gpGlobals->v_up * 10;
}
else
{
vecVelocity = GetAutoaimVector( AUTOAIM_5DEGREES );
vecVelocity = vecVelocity * 600;
vecVelocity.z = 200;
}
// Create the grenade
CQuakeRocket::CreateGrenade( pev->origin, vecVelocity, this );
}
// Lightning Gun
void CBasePlayer::W_FireLightning( int iQuadSound )
{
if (*m_pCurrentAmmo < 1)
{
//This should already be IT_LIGHTNING but what the heck.
if ( m_iQuakeWeapon == IT_LIGHTNING )
{
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usLightning, 0, (float *)&pev->origin, (float *)&pev->angles, 0.0, 0.0, 0, 1, 0, 0 );
if ( m_pActiveItem )
((CQuakeGun*)m_pActiveItem)->DestroyEffect();
}
m_iQuakeWeapon = W_BestWeapon ();
W_SetCurrentAmmo();
return;
}
bool playsound = false;
// Make lightning sound every 0.6 seconds
if ( m_flLightningTime <= gpGlobals->time )
{
playsound = true;
m_flLightningTime = gpGlobals->time + 0.6;
}
// explode if under water
if (pev->waterlevel > 1)
{
if ( (gpGlobals->deathmatch > 3) && (RANDOM_FLOAT(0, 1) <= 0.5) )
{
strcpy( gszQ_DeathType, "selfwater" );
TakeDamage( pev, pev, 4000, DMG_GENERIC );
}
else
{
float flCellsBurnt = *m_pCurrentAmmo;
*m_pCurrentAmmo = 0;
W_SetCurrentAmmo();
#if !defined( CLIENT_DLL )
Q_RadiusDamage( this, this, 35 * flCellsBurnt, NULL );
#endif
return;
}
}
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usLightning, 0, (float *)&pev->origin, (float *)&pev->angles, 0.0, 0.0, iQuadSound, 0, playsound, 0 );
#if !defined( CLIENT_DLL )
if (gpGlobals->deathmatch != 4 )
*m_pCurrentAmmo -= 1;
// Lightning bolt effect
TraceResult trace;
Vector vecOrg = pev->origin + Vector(0,0,16);
UTIL_MakeVectors( pev->v_angle );
UTIL_TraceLine( vecOrg, vecOrg + (gpGlobals->v_forward * 600), ignore_monsters, ENT(pev), &trace );
Vector vecDir = gpGlobals->v_forward + ( 0.001 * gpGlobals->v_right ) + ( 0.001 * gpGlobals->v_up );
// Do damage
LightningDamage(pev->origin, trace.vecEndPos + (gpGlobals->v_forward * 4), this, 30, vecDir );
#endif
}
// Super Nailgun
void CBasePlayer::W_FireSuperSpikes( int iQuadSound )
{
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usSuperSpike, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iQuadSound, 0, m_iNailOffset > 0.0 ? 1 : 0, 0 );
if (gpGlobals->deathmatch != 4 )
*m_pCurrentAmmo -= 2;
m_flNextAttack = UTIL_WeaponTimeBase() + 0.1;
// Fire the Nail
Vector vecDir = GetAutoaimVector( AUTOAIM_5DEGREES );
CQuakeNail::CreateSuperNail( pev->origin + Vector(0,0,16), vecDir, this );
}
// Nailgun
void CBasePlayer::W_FireSpikes( int iQuadSound )
{
// If we're wielding the Super nailgun and we've got ammo for it, fire Super nails
if (*m_pCurrentAmmo >= 2 && m_iQuakeWeapon == IT_SUPER_NAILGUN)
{
W_FireSuperSpikes( iQuadSound );
return;
}
// Swap to next best weapon if this one just ran out
if (*m_pCurrentAmmo < 1)
{
m_iQuakeWeapon = W_BestWeapon ();
W_SetCurrentAmmo();
return;
}
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usSpike, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iQuadSound, 0, m_iNailOffset > 0.0 ? 1 : 0, 0 );
// Fire left then right
if (m_iNailOffset == 2)
m_iNailOffset = -2;
else
m_iNailOffset = 2;
if (gpGlobals->deathmatch != 4 )
*m_pCurrentAmmo -= 1;
m_flNextAttack = UTIL_WeaponTimeBase() + 0.1;
// Fire the nail
UTIL_MakeVectors( pev->v_angle );
Vector vecDir = GetAutoaimVector( AUTOAIM_5DEGREES );
CQuakeNail::CreateNail( pev->origin + Vector(0,0,10) + (gpGlobals->v_right * m_iNailOffset), vecDir, this );
}
//===============================================================================
// PLAYER WEAPON USE
//===============================================================================
void CBasePlayer::W_Attack( int iQuadSound )
{
// Out of ammo?
if ( !W_CheckNoAmmo() )
return;
if ( m_iQuakeWeapon != IT_LIGHTNING )
((CBasePlayerWeapon*)m_pActiveItem)->SendWeaponAnim( 1, 1 );
if (m_iQuakeWeapon == IT_AXE)
{
m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usAxeSwing, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iQuadSound, 0, 0, 0 );
// Delay attack for 0.3
m_flAxeFire = gpGlobals->time + 0.3;
PLAYBACK_EVENT_FULL( FEV_NOTHOST, edict(), m_usAxe, 0.3, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, iQuadSound, 0, 0, 0 );
}
else if (m_iQuakeWeapon == IT_SHOTGUN)
{
m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
W_FireShotgun( iQuadSound );
}
else if (m_iQuakeWeapon == IT_SUPER_SHOTGUN)
{
m_flNextAttack = UTIL_WeaponTimeBase() + 0.7;
W_FireSuperShotgun( iQuadSound );
}
else if (m_iQuakeWeapon == IT_NAILGUN)
{
m_flNextAttack = UTIL_WeaponTimeBase() + 0.1;
W_FireSpikes( iQuadSound );
}
else if (m_iQuakeWeapon == IT_SUPER_NAILGUN)
{
m_flNextAttack = UTIL_WeaponTimeBase() + 0.1;
W_FireSpikes( iQuadSound );
}
else if (m_iQuakeWeapon == IT_GRENADE_LAUNCHER)
{
m_flNextAttack = UTIL_WeaponTimeBase() + 0.6;
W_FireGrenade( iQuadSound );
}
else if (m_iQuakeWeapon == IT_ROCKET_LAUNCHER)
{
m_flNextAttack = UTIL_WeaponTimeBase() + 0.8;
W_FireRocket( iQuadSound );
}
else if (m_iQuakeWeapon == IT_LIGHTNING)
{
m_flNextAttack = UTIL_WeaponTimeBase() + 0.1;
// Play the lightning start sound if gun just started firing
if (m_afButtonPressed & IN_ATTACK)
EMIT_SOUND(ENT(pev), CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
W_FireLightning( iQuadSound );
}
// Make player attack
if ( pev->health >= 0 )
SetAnimation( PLAYER_ATTACK1 );
}

View File

@ -0,0 +1,177 @@
/***
*
* 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.
*
****/
// Implementation in UTIL.CPP
#ifndef SAVERESTORE_H
#define SAVERESTORE_H
class CBaseEntity;
class CSaveRestoreBuffer
{
public:
CSaveRestoreBuffer( void );
CSaveRestoreBuffer( SAVERESTOREDATA *pdata );
virtual ~CSaveRestoreBuffer( void );
int EntityIndex( entvars_t *pevLookup );
int EntityIndex( edict_t *pentLookup );
int EntityIndex( EOFFSET eoLookup );
int EntityIndex( CBaseEntity *pEntity );
int EntityFlags( int entityIndex, int flags ) { return EntityFlagsSet( entityIndex, 0 ); }
int EntityFlagsSet( int entityIndex, int flags );
edict_t *EntityFromIndex( int entityIndex );
unsigned short TokenHash( const char *pszToken );
protected:
SAVERESTOREDATA *m_pdata;
void BufferRewind( int size );
unsigned int HashString( const char *pszToken );
private:
// effc++ rule 11
void operator=(CSaveRestoreBuffer&);
CSaveRestoreBuffer(const CSaveRestoreBuffer&);
};
class CSave : public CSaveRestoreBuffer
{
public:
CSave( SAVERESTOREDATA *pdata ) : CSaveRestoreBuffer( pdata ) {};
void WriteShort( const char *pname, const short *value, int count );
void WriteInt( const char *pname, const int *value, int count ); // Save an int
void WriteFloat( const char *pname, const float *value, int count ); // Save a float
void WriteTime( const char *pname, const float *value, int count ); // Save a float (timevalue)
void WriteData( const char *pname, int size, const char *pdata ); // Save a binary data block
void WriteString( const char *pname, const char *pstring ); // Save a null-terminated string
void WriteString( const char *pname, const int *stringId, int count ); // Save a null-terminated string (engine string)
void WriteVector( const char *pname, const Vector &value ); // Save a vector
void WriteVector( const char *pname, const float *value, int count ); // Save a vector
void WritePositionVector( const char *pname, const Vector &value ); // Offset for landmark if necessary
void WritePositionVector( const char *pname, const float *value, int count ); // array of pos vectors
void WriteFunction( const char *pname, const int *value, int count ); // Save a function pointer
int WriteEntVars( const char *pname, entvars_t *pev ); // Save entvars_t (entvars_t)
int WriteFields( const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
private:
int DataEmpty( const char *pdata, int size );
void BufferField( const char *pname, int size, const char *pdata );
void BufferString( char *pdata, int len );
void BufferData( const char *pdata, int size );
void BufferHeader( const char *pname, int size );
};
typedef struct
{
unsigned short size;
unsigned short token;
char *pData;
} HEADER;
class CRestore : public CSaveRestoreBuffer
{
public:
CRestore( SAVERESTOREDATA *pdata ) : CSaveRestoreBuffer( pdata ), m_global(0), m_precache(TRUE) { }
int ReadEntVars( const char *pname, entvars_t *pev ); // entvars_t
int ReadFields( const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
int ReadField( void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount, int startField, int size, char *pName, void *pData );
int ReadInt( void );
short ReadShort( void );
int ReadNamedInt( const char *pName );
char *ReadNamedString( const char *pName );
int Empty( void ) { return (m_pdata == NULL) || ((m_pdata->pCurrentData-m_pdata->pBaseData)>=m_pdata->bufferSize); }
inline void SetGlobalMode( int global ) { m_global = global; }
void PrecacheMode( BOOL mode ) { m_precache = mode; }
private:
char *BufferPointer( void );
void BufferReadBytes( char *pOutput, int size );
void BufferSkipBytes( int bytes );
int BufferSkipZString( void );
int BufferCheckZString( const char *string );
void BufferReadHeader( HEADER *pheader );
int m_global; // Restoring a global entity?
BOOL m_precache;
};
#define MAX_ENTITYARRAY 64
//#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
#define IMPLEMENT_SAVERESTORE(derivedClass,baseClass) \
int derivedClass::Save( CSave &save )\
{\
if ( !baseClass::Save(save) )\
return 0;\
return save.WriteFields( #derivedClass, this, m_SaveData, ARRAYSIZE(m_SaveData) );\
}\
int derivedClass::Restore( CRestore &restore )\
{\
if ( !baseClass::Restore(restore) )\
return 0;\
return restore.ReadFields( #derivedClass, this, m_SaveData, ARRAYSIZE(m_SaveData) );\
}
typedef enum { GLOBAL_OFF = 0, GLOBAL_ON = 1, GLOBAL_DEAD = 2 } GLOBALESTATE;
typedef struct globalentity_s globalentity_t;
struct globalentity_s
{
char name[64];
char levelName[32];
GLOBALESTATE state;
globalentity_t *pNext;
};
class CGlobalState
{
public:
CGlobalState();
void Reset( void );
void ClearStates( void );
void EntityAdd( string_t globalname, string_t mapName, GLOBALESTATE state );
void EntitySetState( string_t globalname, GLOBALESTATE state );
void EntityUpdate( string_t globalname, string_t mapname );
const globalentity_t *EntityFromTable( string_t globalname );
GLOBALESTATE EntityGetState( string_t globalname );
int EntityInTable( string_t globalname ) { return (Find( globalname ) != NULL) ? 1 : 0; }
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
//#ifdef _DEBUG
void DumpGlobals( void );
//#endif
private:
globalentity_t *Find( string_t globalname );
globalentity_t *m_pList;
int m_listCount;
// effc++ rule 11
void operator=(CGlobalState&);
CGlobalState(const CGlobalState&);
};
extern CGlobalState gGlobalState;
#endif //SAVERESTORE_H

View File

@ -0,0 +1,39 @@
/***
*
* 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.
*
* 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.
*
****/
//=========================================================
// schedule.cpp - functions and data pertaining to the
// monsters' AI scheduling system.
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "animation.h"
#include "scripted.h"
#include "nodes.h"
#include "defaultai.h"
extern CGraph WorldGraph;
BOOL CBaseMonster :: FHaveSchedule( void ) { return FALSE; };
void CBaseMonster :: ClearSchedule( void ) { };
BOOL CBaseMonster :: FScheduleDone ( void ) { return FALSE; };
void CBaseMonster :: ChangeSchedule ( Schedule_t *pNewSchedule ) { };
void CBaseMonster :: NextScheduledTask ( void ) { };
int CBaseMonster :: IScheduleFlags ( void ) { return 0; };
BOOL CBaseMonster :: FScheduleValid ( void ) { return FALSE; };
void CBaseMonster :: MaintainSchedule ( void ) { };
void CBaseMonster :: SetTurnActivity ( void ) { };
Task_t *CBaseMonster :: GetTask ( void ) { return NULL; };

290
hlsdk/dmc/dlls/schedule.h Normal file
View File

@ -0,0 +1,290 @@
/***
*
* 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.
*
* 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.
*
****/
//=========================================================
// Scheduling
//=========================================================
#ifndef SCHEDULE_H
#define SCHEDULE_H
#define TASKSTATUS_NEW 0 // Just started
#define TASKSTATUS_RUNNING 1 // Running task & movement
#define TASKSTATUS_RUNNING_MOVEMENT 2 // Just running movement
#define TASKSTATUS_RUNNING_TASK 3 // Just running task
#define TASKSTATUS_COMPLETE 4 // Completed, get next task
//=========================================================
// These are the schedule types
//=========================================================
typedef enum
{
SCHED_NONE = 0,
SCHED_IDLE_STAND,
SCHED_IDLE_WALK,
SCHED_WAKE_ANGRY,
SCHED_WAKE_CALLED,
SCHED_ALERT_FACE,
SCHED_ALERT_SMALL_FLINCH,
SCHED_ALERT_BIG_FLINCH,
SCHED_ALERT_STAND,
SCHED_INVESTIGATE_SOUND,
SCHED_COMBAT_FACE,
SCHED_COMBAT_STAND,
SCHED_CHASE_ENEMY,
SCHED_CHASE_ENEMY_FAILED,
SCHED_VICTORY_DANCE,
SCHED_TARGET_FACE,
SCHED_TARGET_CHASE,
SCHED_SMALL_FLINCH,
SCHED_TAKE_COVER_FROM_ENEMY,
SCHED_TAKE_COVER_FROM_BEST_SOUND,
SCHED_TAKE_COVER_FROM_ORIGIN,
SCHED_COWER, // usually a last resort!
SCHED_MELEE_ATTACK1,
SCHED_MELEE_ATTACK2,
SCHED_RANGE_ATTACK1,
SCHED_RANGE_ATTACK2,
SCHED_SPECIAL_ATTACK1,
SCHED_SPECIAL_ATTACK2,
SCHED_STANDOFF,
SCHED_ARM_WEAPON,
SCHED_RELOAD,
SCHED_GUARD,
SCHED_AMBUSH,
SCHED_DIE,
SCHED_WAIT_TRIGGER,
SCHED_FOLLOW,
SCHED_SLEEP,
SCHED_WAKE,
SCHED_BARNACLE_VICTIM_GRAB,
SCHED_BARNACLE_VICTIM_CHOMP,
SCHED_AISCRIPT,
SCHED_FAIL,
LAST_COMMON_SCHEDULE // Leave this at the bottom
} SCHEDULE_TYPE;
//=========================================================
// These are the shared tasks
//=========================================================
typedef enum
{
TASK_INVALID = 0,
TASK_WAIT,
TASK_WAIT_FACE_ENEMY,
TASK_WAIT_PVS,
TASK_SUGGEST_STATE,
TASK_WALK_TO_TARGET,
TASK_RUN_TO_TARGET,
TASK_MOVE_TO_TARGET_RANGE,
TASK_GET_PATH_TO_ENEMY,
TASK_GET_PATH_TO_ENEMY_LKP,
TASK_GET_PATH_TO_ENEMY_CORPSE,
TASK_GET_PATH_TO_LEADER,
TASK_GET_PATH_TO_SPOT,
TASK_GET_PATH_TO_TARGET,
TASK_GET_PATH_TO_HINTNODE,
TASK_GET_PATH_TO_LASTPOSITION,
TASK_GET_PATH_TO_BESTSOUND,
TASK_GET_PATH_TO_BESTSCENT,
TASK_RUN_PATH,
TASK_WALK_PATH,
TASK_STRAFE_PATH,
TASK_CLEAR_MOVE_WAIT,
TASK_STORE_LASTPOSITION,
TASK_CLEAR_LASTPOSITION,
TASK_PLAY_ACTIVE_IDLE,
TASK_FIND_HINTNODE,
TASK_CLEAR_HINTNODE,
TASK_SMALL_FLINCH,
TASK_FACE_IDEAL,
TASK_FACE_ROUTE,
TASK_FACE_ENEMY,
TASK_FACE_HINTNODE,
TASK_FACE_TARGET,
TASK_FACE_LASTPOSITION,
TASK_RANGE_ATTACK1,
TASK_RANGE_ATTACK2,
TASK_MELEE_ATTACK1,
TASK_MELEE_ATTACK2,
TASK_RELOAD,
TASK_RANGE_ATTACK1_NOTURN,
TASK_RANGE_ATTACK2_NOTURN,
TASK_MELEE_ATTACK1_NOTURN,
TASK_MELEE_ATTACK2_NOTURN,
TASK_RELOAD_NOTURN,
TASK_SPECIAL_ATTACK1,
TASK_SPECIAL_ATTACK2,
TASK_CROUCH,
TASK_STAND,
TASK_GUARD,
TASK_STEP_LEFT,
TASK_STEP_RIGHT,
TASK_STEP_FORWARD,
TASK_STEP_BACK,
TASK_DODGE_LEFT,
TASK_DODGE_RIGHT,
TASK_SOUND_ANGRY,
TASK_SOUND_DEATH,
TASK_SET_ACTIVITY,
TASK_SET_SCHEDULE,
TASK_SET_FAIL_SCHEDULE,
TASK_CLEAR_FAIL_SCHEDULE,
TASK_PLAY_SEQUENCE,
TASK_PLAY_SEQUENCE_FACE_ENEMY,
TASK_PLAY_SEQUENCE_FACE_TARGET,
TASK_SOUND_IDLE,
TASK_SOUND_WAKE,
TASK_SOUND_PAIN,
TASK_SOUND_DIE,
TASK_FIND_COVER_FROM_BEST_SOUND,// tries lateral cover first, then node cover
TASK_FIND_COVER_FROM_ENEMY,// tries lateral cover first, then node cover
TASK_FIND_LATERAL_COVER_FROM_ENEMY,
TASK_FIND_NODE_COVER_FROM_ENEMY,
TASK_FIND_NEAR_NODE_COVER_FROM_ENEMY,// data for this one is the MAXIMUM acceptable distance to the cover.
TASK_FIND_FAR_NODE_COVER_FROM_ENEMY,// data for this one is there MINIMUM aceptable distance to the cover.
TASK_FIND_COVER_FROM_ORIGIN,
TASK_EAT,
TASK_DIE,
TASK_WAIT_FOR_SCRIPT,
TASK_PLAY_SCRIPT,
TASK_ENABLE_SCRIPT,
TASK_PLANT_ON_SCRIPT,
TASK_FACE_SCRIPT,
TASK_WAIT_RANDOM,
TASK_WAIT_INDEFINITE,
TASK_STOP_MOVING,
TASK_TURN_LEFT,
TASK_TURN_RIGHT,
TASK_REMEMBER,
TASK_FORGET,
TASK_WAIT_FOR_MOVEMENT, // wait until MovementIsComplete()
LAST_COMMON_TASK, // LEAVE THIS AT THE BOTTOM!! (sjb)
} SHARED_TASKS;
// These go in the flData member of the TASK_WALK_TO_TARGET, TASK_RUN_TO_TARGET
enum
{
TARGET_MOVE_NORMAL = 0,
TARGET_MOVE_SCRIPTED = 1,
};
// A goal should be used for a task that requires several schedules to complete.
// The goal index should indicate which schedule (ordinally) the monster is running.
// That way, when tasks fail, the AI can make decisions based on the context of the
// current goal and sequence rather than just the current schedule.
enum
{
GOAL_ATTACK_ENEMY,
GOAL_MOVE,
GOAL_TAKE_COVER,
GOAL_MOVE_TARGET,
GOAL_EAT,
};
// an array of tasks is a task list
// an array of schedules is a schedule list
struct Task_t
{
int iTask;
float flData;
};
struct Schedule_t
{
Task_t *pTasklist;
int cTasks;
int iInterruptMask;// a bit mask of conditions that can interrupt this schedule
// a more specific mask that indicates which TYPES of sounds will interrupt the schedule in the
// event that the schedule is broken by COND_HEAR_SOUND
int iSoundMask;
const char *pName;
};
// an array of waypoints makes up the monster's route.
// !!!LATER- this declaration doesn't belong in this file.
struct WayPoint_t
{
Vector vecLocation;
int iType;
};
// these MoveFlag values are assigned to a WayPoint's TYPE in order to demonstrate the
// type of movement the monster should use to get there.
#define bits_MF_TO_TARGETENT ( 1 << 0 ) // local move to targetent.
#define bits_MF_TO_ENEMY ( 1 << 1 ) // local move to enemy
#define bits_MF_TO_COVER ( 1 << 2 ) // local move to a hiding place
#define bits_MF_TO_DETOUR ( 1 << 3 ) // local move to detour point.
#define bits_MF_TO_PATHCORNER ( 1 << 4 ) // local move to a path corner
#define bits_MF_TO_NODE ( 1 << 5 ) // local move to a node
#define bits_MF_TO_LOCATION ( 1 << 6 ) // local move to an arbitrary point
#define bits_MF_IS_GOAL ( 1 << 7 ) // this waypoint is the goal of the whole move.
#define bits_MF_DONT_SIMPLIFY ( 1 << 8 ) // Don't let the route code simplify this waypoint
// If you define any flags that aren't _TO_ flags, add them here so we can mask
// them off when doing compares.
#define bits_MF_NOT_TO_MASK (bits_MF_IS_GOAL | bits_MF_DONT_SIMPLIFY)
#define MOVEGOAL_NONE (0)
#define MOVEGOAL_TARGETENT (bits_MF_TO_TARGETENT)
#define MOVEGOAL_ENEMY (bits_MF_TO_ENEMY)
#define MOVEGOAL_PATHCORNER (bits_MF_TO_PATHCORNER)
#define MOVEGOAL_LOCATION (bits_MF_TO_LOCATION)
#define MOVEGOAL_NODE (bits_MF_TO_NODE)
// these bits represent conditions that may befall the monster, of which some are allowed
// to interrupt certain schedules.
#define bits_COND_NO_AMMO_LOADED ( 1 << 0 ) // weapon needs to be reloaded!
#define bits_COND_SEE_HATE ( 1 << 1 ) // see something that you hate
#define bits_COND_SEE_FEAR ( 1 << 2 ) // see something that you are afraid of
#define bits_COND_SEE_DISLIKE ( 1 << 3 ) // see something that you dislike
#define bits_COND_SEE_ENEMY ( 1 << 4 ) // target entity is in full view.
#define bits_COND_ENEMY_OCCLUDED ( 1 << 5 ) // target entity occluded by the world
#define bits_COND_SMELL_FOOD ( 1 << 6 )
#define bits_COND_ENEMY_TOOFAR ( 1 << 7 )
#define bits_COND_LIGHT_DAMAGE ( 1 << 8 ) // hurt a little
#define bits_COND_HEAVY_DAMAGE ( 1 << 9 ) // hurt a lot
#define bits_COND_CAN_RANGE_ATTACK1 ( 1 << 10)
#define bits_COND_CAN_MELEE_ATTACK1 ( 1 << 11)
#define bits_COND_CAN_RANGE_ATTACK2 ( 1 << 12)
#define bits_COND_CAN_MELEE_ATTACK2 ( 1 << 13)
// #define bits_COND_CAN_RANGE_ATTACK3 ( 1 << 14)
#define bits_COND_PROVOKED ( 1 << 15)
#define bits_COND_NEW_ENEMY ( 1 << 16)
#define bits_COND_HEAR_SOUND ( 1 << 17) // there is an interesting sound
#define bits_COND_SMELL ( 1 << 18) // there is an interesting scent
#define bits_COND_ENEMY_FACING_ME ( 1 << 19) // enemy is facing me
#define bits_COND_ENEMY_DEAD ( 1 << 20) // enemy was killed. If you get this in combat, try to find another enemy. If you get it in alert, victory dance.
#define bits_COND_SEE_CLIENT ( 1 << 21) // see a client
#define bits_COND_SEE_NEMESIS ( 1 << 22) // see my nemesis
#define bits_COND_SPECIAL1 ( 1 << 28) // Defined by individual monster
#define bits_COND_SPECIAL2 ( 1 << 29) // Defined by individual monster
#define bits_COND_TASK_FAILED ( 1 << 30)
#define bits_COND_SCHEDULE_DONE ( 1 << 31)
#define bits_COND_ALL_SPECIAL (bits_COND_SPECIAL1 | bits_COND_SPECIAL2)
#define bits_COND_CAN_ATTACK (bits_COND_CAN_RANGE_ATTACK1 | bits_COND_CAN_MELEE_ATTACK1 | bits_COND_CAN_RANGE_ATTACK2 | bits_COND_CAN_MELEE_ATTACK2)
#endif // SCHEDULE_H

1260
hlsdk/dmc/dlls/scripted.cpp Normal file

File diff suppressed because it is too large Load Diff

107
hlsdk/dmc/dlls/scripted.h Normal file
View File

@ -0,0 +1,107 @@
/***
*
* 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.
*
* 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.
*
****/
#ifndef SCRIPTED_H
#define SCRIPTED_H
#ifndef SCRIPTEVENT_H
#include "scriptevent.h"
#endif
#define SF_SCRIPT_WAITTILLSEEN 1
#define SF_SCRIPT_EXITAGITATED 2
#define SF_SCRIPT_REPEATABLE 4
#define SF_SCRIPT_LEAVECORPSE 8
//#define SF_SCRIPT_INTERPOLATE 16 // don't use, old bug
#define SF_SCRIPT_NOINTERRUPT 32
#define SF_SCRIPT_OVERRIDESTATE 64
#define SF_SCRIPT_NOSCRIPTMOVEMENT 128
#define SCRIPT_BREAK_CONDITIONS (bits_COND_LIGHT_DAMAGE|bits_COND_HEAVY_DAMAGE)
enum SS_INTERRUPT
{
SS_INTERRUPT_IDLE = 0,
SS_INTERRUPT_BY_NAME,
SS_INTERRUPT_AI,
};
// when a monster finishes an AI scripted sequence, we can choose
// a schedule to place them in. These defines are the aliases to
// resolve worldcraft input to real schedules (sjb)
#define SCRIPT_FINISHSCHED_DEFAULT 0
#define SCRIPT_FINISHSCHED_AMBUSH 1
class CCineMonster : public CBaseMonster
{
public:
void Spawn( void );
virtual void KeyValue( KeyValueData *pkvd );
virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual void Blocked( CBaseEntity *pOther );
virtual void Touch( CBaseEntity *pOther );
virtual int ObjectCaps( void ) { return (CBaseMonster :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION); }
virtual void Activate( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
// void EXPORT CineSpawnThink( void );
void EXPORT CineThink( void );
void Pain( void );
void Die( void );
void DelayStart( int state );
BOOL FindEntity( void );
virtual void PossessEntity( void );
void ReleaseEntity( CBaseMonster *pEntity );
void CancelScript( void );
virtual BOOL StartSequence( CBaseMonster *pTarget, int iszSeq, BOOL completeOnEmpty );
virtual BOOL FCanOverrideState ( void );
void SequenceDone ( CBaseMonster *pMonster );
virtual void FixScriptMonsterSchedule( CBaseMonster *pMonster );
BOOL CanInterrupt( void );
void AllowInterrupt( BOOL fAllow );
int IgnoreConditions( void );
int m_iszIdle; // string index for idle animation
int m_iszPlay; // string index for scripted animation
int m_iszEntity; // entity that is wanted for this script
int m_fMoveTo;
int m_iFinishSchedule;
float m_flRadius; // range to search
float m_flRepeat; // repeat rate
int m_iDelay;
float m_startTime;
int m_saved_movetype;
int m_saved_solid;
int m_saved_effects;
// Vector m_vecOrigOrigin;
BOOL m_interruptable;
};
class CCineAI : public CCineMonster
{
BOOL StartSequence( CBaseMonster *pTarget, int iszSeq, BOOL completeOnEmpty );
void PossessEntity( void );
BOOL FCanOverrideState ( void );
virtual void FixScriptMonsterSchedule( CBaseMonster *pMonster );
};
#endif //SCRIPTED_H

View File

@ -0,0 +1,29 @@
/***
*
* 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.
*
****/
#ifndef SCRIPTEVENT_H
#define SCRIPTEVENT_H
#define SCRIPT_EVENT_DEAD 1000 // character is now dead
#define SCRIPT_EVENT_NOINTERRUPT 1001 // does not allow interrupt
#define SCRIPT_EVENT_CANINTERRUPT 1002 // will allow interrupt
#define SCRIPT_EVENT_FIREEVENT 1003 // event now fires
#define SCRIPT_EVENT_SOUND 1004 // Play named wave file (on CHAN_BODY)
#define SCRIPT_EVENT_SENTENCE 1005 // Play named sentence
#define SCRIPT_EVENT_INAIR 1006 // Leave the character in air at the end of the sequence (don't find the floor)
#define SCRIPT_EVENT_ENDANIMATION 1007 // Set the animation by name after the sequence completes
#define SCRIPT_EVENT_SOUND_VOICE 1008 // Play named wave file (on CHAN_VOICE)
#define SCRIPT_EVENT_SENTENCE_RND1 1009 // Play sentence group 25% of the time
#define SCRIPT_EVENT_NOT_DEAD 1010 // Bring back to life (for life/death sequences)
#endif //SCRIPTEVENT_H

View File

@ -0,0 +1,336 @@
/***
*
* 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.
*
****/
//
// teamplay_gamerules.cpp
//
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "skill.h"
#include "items.h"
extern DLL_GLOBAL CGameRules *g_pGameRules;
extern DLL_GLOBAL BOOL g_fGameOver;
extern int gmsgDeathMsg; // client dll messages
extern int gmsgScoreInfo;
extern int gmsgMOTD;
//=========================================================
//=========================================================
CHalfLifeRules::CHalfLifeRules( void )
{
RefreshSkillData();
}
//=========================================================
//=========================================================
void CHalfLifeRules::Think ( void )
{
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules::IsMultiplayer( void )
{
return FALSE;
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules::IsDeathmatch ( void )
{
return FALSE;
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules::IsCoOp( void )
{
return FALSE;
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon )
{
if ( !pPlayer->m_pActiveItem )
{
// player doesn't have an active item!
return TRUE;
}
if ( !pPlayer->m_pActiveItem->CanHolster() )
{
return FALSE;
}
return TRUE;
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules :: GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon )
{
return FALSE;
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules :: ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] )
{
return TRUE;
}
void CHalfLifeRules :: InitHUD( CBasePlayer *pl )
{
}
//=========================================================
//=========================================================
void CHalfLifeRules :: ClientDisconnected( edict_t *pClient )
{
}
//=========================================================
//=========================================================
float CHalfLifeRules::FlPlayerFallDamage( CBasePlayer *pPlayer )
{
// subtract off the speed at which a player is allowed to fall without being hurt,
// so damage will be based on speed beyond that, not the entire fall
pPlayer->m_flFallVelocity -= PLAYER_MAX_SAFE_FALL_SPEED;
return pPlayer->m_flFallVelocity * DAMAGE_FOR_FALL_SPEED;
}
//=========================================================
//=========================================================
void CHalfLifeRules :: PlayerSpawn( CBasePlayer *pPlayer )
{
// Start with init ammoload
pPlayer->m_iAmmoShells = 25;
// Start with shotgun and axe
pPlayer->GiveNamedItem( "weapon_quakegun" );
pPlayer->m_iQuakeItems |= (IT_SHOTGUN | IT_AXE);
pPlayer->m_iQuakeWeapon = pPlayer->W_BestWeapon();
pPlayer->W_SetCurrentAmmo();
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules :: AllowAutoTargetCrosshair( void )
{
return ( g_iSkillLevel == SKILL_EASY );
}
//=========================================================
//=========================================================
void CHalfLifeRules :: PlayerThink( CBasePlayer *pPlayer )
{
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules :: FPlayerCanRespawn( CBasePlayer *pPlayer )
{
return TRUE;
}
//=========================================================
//=========================================================
float CHalfLifeRules :: FlPlayerSpawnTime( CBasePlayer *pPlayer )
{
return gpGlobals->time;//now!
}
//=========================================================
// IPointsForKill - how many points awarded to anyone
// that kills this player?
//=========================================================
int CHalfLifeRules :: IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled )
{
return 1;
}
//=========================================================
// PlayerKilled - someone/something killed this player
//=========================================================
void CHalfLifeRules :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor )
{
}
//=========================================================
// Deathnotice
//=========================================================
void CHalfLifeRules::DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor )
{
}
//=========================================================
// PlayerGotWeapon - player has grabbed a weapon that was
// sitting in the world
//=========================================================
void CHalfLifeRules :: PlayerGotWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pWeapon )
{
}
//=========================================================
// FlWeaponRespawnTime - what is the time in the future
// at which this weapon may spawn?
//=========================================================
float CHalfLifeRules :: FlWeaponRespawnTime( CBasePlayerItem *pWeapon )
{
return -1;
}
//=========================================================
// FlWeaponRespawnTime - Returns 0 if the weapon can respawn
// now, otherwise it returns the time at which it can try
// to spawn again.
//=========================================================
float CHalfLifeRules :: FlWeaponTryRespawn( CBasePlayerItem *pWeapon )
{
return 0;
}
//=========================================================
// VecWeaponRespawnSpot - where should this weapon spawn?
// Some game variations may choose to randomize spawn locations
//=========================================================
Vector CHalfLifeRules :: VecWeaponRespawnSpot( CBasePlayerItem *pWeapon )
{
return pWeapon->pev->origin;
}
//=========================================================
// WeaponShouldRespawn - any conditions inhibiting the
// respawning of this weapon?
//=========================================================
int CHalfLifeRules :: WeaponShouldRespawn( CBasePlayerItem *pWeapon )
{
return GR_WEAPON_RESPAWN_NO;
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules::CanHaveItem( CBasePlayer *pPlayer, CItem *pItem )
{
return TRUE;
}
//=========================================================
//=========================================================
void CHalfLifeRules::PlayerGotItem( CBasePlayer *pPlayer, CItem *pItem )
{
}
//=========================================================
//=========================================================
int CHalfLifeRules::ItemShouldRespawn( CItem *pItem )
{
return GR_ITEM_RESPAWN_NO;
}
//=========================================================
// At what time in the future may this Item respawn?
//=========================================================
float CHalfLifeRules::FlItemRespawnTime( CItem *pItem )
{
return -1;
}
//=========================================================
// Where should this item respawn?
// Some game variations may choose to randomize spawn locations
//=========================================================
Vector CHalfLifeRules::VecItemRespawnSpot( CItem *pItem )
{
return pItem->pev->origin;
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules::IsAllowedToSpawn( CBaseEntity *pEntity )
{
return TRUE;
}
//=========================================================
//=========================================================
void CHalfLifeRules::PlayerGotAmmo( CBasePlayer *pPlayer, char *szName, int iCount )
{
}
//=========================================================
//=========================================================
int CHalfLifeRules::AmmoShouldRespawn( CBasePlayerAmmo *pAmmo )
{
return GR_AMMO_RESPAWN_NO;
}
//=========================================================
//=========================================================
float CHalfLifeRules::FlAmmoRespawnTime( CBasePlayerAmmo *pAmmo )
{
return -1;
}
//=========================================================
//=========================================================
Vector CHalfLifeRules::VecAmmoRespawnSpot( CBasePlayerAmmo *pAmmo )
{
return pAmmo->pev->origin;
}
//=========================================================
//=========================================================
float CHalfLifeRules::FlHealthChargerRechargeTime( void )
{
return 0;// don't recharge
}
//=========================================================
//=========================================================
int CHalfLifeRules::DeadPlayerWeapons( CBasePlayer *pPlayer )
{
return GR_PLR_DROP_GUN_NO;
}
//=========================================================
//=========================================================
int CHalfLifeRules::DeadPlayerAmmo( CBasePlayer *pPlayer )
{
return GR_PLR_DROP_AMMO_NO;
}
//=========================================================
//=========================================================
int CHalfLifeRules::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget )
{
// why would a single player in half life need this?
return GR_NOTTEAMMATE;
}
//=========================================================
//=========================================================
BOOL CHalfLifeRules :: FAllowMonsters( void )
{
return TRUE;
}

47
hlsdk/dmc/dlls/skill.cpp Normal file
View File

@ -0,0 +1,47 @@
/***
*
* 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.
*
****/
//=========================================================
// skill.cpp - code for skill level concerns
//=========================================================
#include "extdll.h"
#include "util.h"
#include "skill.h"
skilldata_t gSkillData;
//=========================================================
// take the name of a cvar, tack a digit for the skill level
// on, and return the value.of that Cvar
//=========================================================
float GetSkillCvar( char *pName )
{
int iCount;
float flValue;
char szBuffer[ 64 ];
iCount = sprintf( szBuffer, "%s%d",pName, gSkillData.iSkillLevel );
flValue = CVAR_GET_FLOAT ( szBuffer );
if ( flValue <= 0 )
{
ALERT ( at_console, "\n\n** GetSkillCVar Got a zero for %s **\n\n", szBuffer );
}
return flValue;
}

147
hlsdk/dmc/dlls/skill.h Normal file
View File

@ -0,0 +1,147 @@
/***
*
* 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.
*
****/
//=========================================================
// skill.h - skill level concerns
//=========================================================
struct skilldata_t
{
int iSkillLevel; // game skill level
// Monster Health & Damage
float agruntHealth;
float agruntDmgPunch;
float apacheHealth;
float barneyHealth;
float bigmommaHealthFactor; // Multiply each node's health by this
float bigmommaDmgSlash; // melee attack damage
float bigmommaDmgBlast; // mortar attack damage
float bigmommaRadiusBlast; // mortar attack radius
float bullsquidHealth;
float bullsquidDmgBite;
float bullsquidDmgWhip;
float bullsquidDmgSpit;
float gargantuaHealth;
float gargantuaDmgSlash;
float gargantuaDmgFire;
float gargantuaDmgStomp;
float hassassinHealth;
float headcrabHealth;
float headcrabDmgBite;
float hgruntHealth;
float hgruntDmgKick;
float hgruntShotgunPellets;
float hgruntGrenadeSpeed;
float houndeyeHealth;
float houndeyeDmgBlast;
float slaveHealth;
float slaveDmgClaw;
float slaveDmgClawrake;
float slaveDmgZap;
float ichthyosaurHealth;
float ichthyosaurDmgShake;
float leechHealth;
float leechDmgBite;
float controllerHealth;
float controllerDmgZap;
float controllerSpeedBall;
float controllerDmgBall;
float nihilanthHealth;
float nihilanthZap;
float scientistHealth;
float snarkHealth;
float snarkDmgBite;
float snarkDmgPop;
float zombieHealth;
float zombieDmgOneSlash;
float zombieDmgBothSlash;
float turretHealth;
float miniturretHealth;
float sentryHealth;
// Player Weapons
float plrDmgCrowbar;
float plrDmg9MM;
float plrDmg357;
float plrDmgMP5;
float plrDmgM203Grenade;
float plrDmgBuckshot;
float plrDmgCrossbowClient;
float plrDmgCrossbowMonster;
float plrDmgRPG;
float plrDmgGauss;
float plrDmgEgonNarrow;
float plrDmgEgonWide;
float plrDmgHornet;
float plrDmgHandGrenade;
float plrDmgSatchel;
float plrDmgTripmine;
// weapons shared by monsters
float monDmg9MM;
float monDmgMP5;
float monDmg12MM;
float monDmgHornet;
// health/suit charge
float suitchargerCapacity;
float batteryCapacity;
float healthchargerCapacity;
float healthkitCapacity;
float scientistHeal;
// monster damage adj
float monHead;
float monChest;
float monStomach;
float monLeg;
float monArm;
// player damage adj
float plrHead;
float plrChest;
float plrStomach;
float plrLeg;
float plrArm;
};
extern DLL_GLOBAL skilldata_t gSkillData;
float GetSkillCvar( char *pName );
extern DLL_GLOBAL int g_iSkillLevel;
#define SKILL_EASY 1
#define SKILL_MEDIUM 2
#define SKILL_HARD 3

1967
hlsdk/dmc/dlls/sound.cpp Normal file

File diff suppressed because it is too large Load Diff

379
hlsdk/dmc/dlls/soundent.cpp Normal file
View File

@ -0,0 +1,379 @@
/***
*
* 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 "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "soundent.h"
LINK_ENTITY_TO_CLASS( soundent, CSoundEnt );
CSoundEnt *pSoundEnt;
//=========================================================
// CSound - Clear - zeros all fields for a sound
//=========================================================
void CSound :: Clear ( void )
{
m_vecOrigin = g_vecZero;
m_iType = 0;
m_iVolume = 0;
m_flExpireTime = 0;
m_iNext = SOUNDLIST_EMPTY;
m_iNextAudible = 0;
}
//=========================================================
// Reset - clears the volume, origin, and type for a sound,
// but doesn't expire or unlink it.
//=========================================================
void CSound :: Reset ( void )
{
m_vecOrigin = g_vecZero;
m_iType = 0;
m_iVolume = 0;
m_iNext = SOUNDLIST_EMPTY;
}
//=========================================================
// FIsSound - returns TRUE if the sound is an Audible sound
//=========================================================
BOOL CSound :: FIsSound ( void )
{
if ( m_iType & ( bits_SOUND_COMBAT | bits_SOUND_WORLD | bits_SOUND_PLAYER | bits_SOUND_DANGER ) )
{
return TRUE;
}
return FALSE;
}
//=========================================================
// FIsScent - returns TRUE if the sound is actually a scent
//=========================================================
BOOL CSound :: FIsScent ( void )
{
if ( m_iType & ( bits_SOUND_CARCASS | bits_SOUND_MEAT | bits_SOUND_GARBAGE ) )
{
return TRUE;
}
return FALSE;
}
//=========================================================
// Spawn
//=========================================================
void CSoundEnt :: Spawn( void )
{
pev->solid = SOLID_NOT;
Initialize();
pev->nextthink = gpGlobals->time + 1;
}
//=========================================================
// Think - at interval, the entire active sound list is checked
// for sounds that have ExpireTimes less than or equal
// to the current world time, and these sounds are deallocated.
//=========================================================
void CSoundEnt :: Think ( void )
{
int iSound;
int iPreviousSound;
pev->nextthink = gpGlobals->time + 0.3;// how often to check the sound list.
iPreviousSound = SOUNDLIST_EMPTY;
iSound = m_iActiveSound;
while ( iSound != SOUNDLIST_EMPTY )
{
if ( m_SoundPool[ iSound ].m_flExpireTime <= gpGlobals->time && m_SoundPool[ iSound ].m_flExpireTime != SOUND_NEVER_EXPIRE )
{
int iNext = m_SoundPool[ iSound ].m_iNext;
// move this sound back into the free list
FreeSound( iSound, iPreviousSound );
iSound = iNext;
}
else
{
iPreviousSound = iSound;
iSound = m_SoundPool[ iSound ].m_iNext;
}
}
if ( m_fShowReport )
{
ALERT ( at_aiconsole, "Soundlist: %d / %d (%d)\n", ISoundsInList( SOUNDLISTTYPE_ACTIVE ),ISoundsInList( SOUNDLISTTYPE_FREE ), ISoundsInList( SOUNDLISTTYPE_ACTIVE ) - m_cLastActiveSounds );
m_cLastActiveSounds = ISoundsInList ( SOUNDLISTTYPE_ACTIVE );
}
}
//=========================================================
// Precache - dummy function
//=========================================================
void CSoundEnt :: Precache ( void )
{
}
//=========================================================
// FreeSound - clears the passed active sound and moves it
// to the top of the free list. TAKE CARE to only call this
// function for sounds in the Active list!!
//=========================================================
void CSoundEnt :: FreeSound ( int iSound, int iPrevious )
{
if ( !pSoundEnt )
{
// no sound ent!
return;
}
if ( iPrevious != SOUNDLIST_EMPTY )
{
// iSound is not the head of the active list, so
// must fix the index for the Previous sound
// pSoundEnt->m_SoundPool[ iPrevious ].m_iNext = m_SoundPool[ iSound ].m_iNext;
pSoundEnt->m_SoundPool[ iPrevious ].m_iNext = pSoundEnt->m_SoundPool[ iSound ].m_iNext;
}
else
{
// the sound we're freeing IS the head of the active list.
pSoundEnt->m_iActiveSound = pSoundEnt->m_SoundPool [ iSound ].m_iNext;
}
// make iSound the head of the Free list.
pSoundEnt->m_SoundPool[ iSound ].m_iNext = pSoundEnt->m_iFreeSound;
pSoundEnt->m_iFreeSound = iSound;
}
//=========================================================
// IAllocSound - moves a sound from the Free list to the
// Active list returns the index of the alloc'd sound
//=========================================================
int CSoundEnt :: IAllocSound( void )
{
int iNewSound;
if ( m_iFreeSound == SOUNDLIST_EMPTY )
{
// no free sound!
ALERT ( at_console, "Free Sound List is full!\n" );
return SOUNDLIST_EMPTY;
}
// there is at least one sound available, so move it to the
// Active sound list, and return its SoundPool index.
iNewSound = m_iFreeSound;// copy the index of the next free sound
m_iFreeSound = m_SoundPool[ m_iFreeSound ].m_iNext;// move the index down into the free list.
m_SoundPool[ iNewSound ].m_iNext = m_iActiveSound;// point the new sound at the top of the active list.
m_iActiveSound = iNewSound;// now make the new sound the top of the active list. You're done.
return iNewSound;
}
//=========================================================
// InsertSound - Allocates a free sound and fills it with
// sound info.
//=========================================================
void CSoundEnt :: InsertSound ( int iType, const Vector &vecOrigin, int iVolume, float flDuration )
{
int iThisSound;
if ( !pSoundEnt )
{
// no sound ent!
return;
}
iThisSound = pSoundEnt->IAllocSound();
if ( iThisSound == SOUNDLIST_EMPTY )
{
ALERT ( at_console, "Could not AllocSound() for InsertSound() (DLL)\n" );
return;
}
pSoundEnt->m_SoundPool[ iThisSound ].m_vecOrigin = vecOrigin;
pSoundEnt->m_SoundPool[ iThisSound ].m_iType = iType;
pSoundEnt->m_SoundPool[ iThisSound ].m_iVolume = iVolume;
pSoundEnt->m_SoundPool[ iThisSound ].m_flExpireTime = gpGlobals->time + flDuration;
}
//=========================================================
// Initialize - clears all sounds and moves them into the
// free sound list.
//=========================================================
void CSoundEnt :: Initialize ( void )
{
int i;
int iSound;
m_cLastActiveSounds = 0;
m_iFreeSound = 0;
m_iActiveSound = SOUNDLIST_EMPTY;
for ( i = 0 ; i < MAX_WORLD_SOUNDS ; i++ )
{// clear all sounds, and link them into the free sound list.
m_SoundPool[ i ].Clear();
m_SoundPool[ i ].m_iNext = i + 1;
}
m_SoundPool[ i - 1 ].m_iNext = SOUNDLIST_EMPTY;// terminate the list here.
// now reserve enough sounds for each client
for ( i = 0 ; i < gpGlobals->maxClients ; i++ )
{
iSound = pSoundEnt->IAllocSound();
if ( iSound == SOUNDLIST_EMPTY )
{
ALERT ( at_console, "Could not AllocSound() for Client Reserve! (DLL)\n" );
return;
}
pSoundEnt->m_SoundPool[ iSound ].m_flExpireTime = SOUND_NEVER_EXPIRE;
}
if ( CVAR_GET_FLOAT("displaysoundlist") == 1 )
{
m_fShowReport = TRUE;
}
else
{
m_fShowReport = FALSE;
}
}
//=========================================================
// ISoundsInList - returns the number of sounds in the desired
// sound list.
//=========================================================
int CSoundEnt :: ISoundsInList ( int iListType )
{
int i;
int iThisSound = 0;
if ( iListType == SOUNDLISTTYPE_FREE )
{
iThisSound = m_iFreeSound;
}
else if ( iListType == SOUNDLISTTYPE_ACTIVE )
{
iThisSound = m_iActiveSound;
}
else
{
ALERT ( at_console, "Unknown Sound List Type!\n" );
}
if ( iThisSound == SOUNDLIST_EMPTY )
{
return 0;
}
i = 0;
while ( iThisSound != SOUNDLIST_EMPTY )
{
i++;
iThisSound = m_SoundPool[ iThisSound ].m_iNext;
}
return i;
}
//=========================================================
// ActiveList - returns the head of the active sound list
//=========================================================
int CSoundEnt :: ActiveList ( void )
{
if ( !pSoundEnt )
{
return SOUNDLIST_EMPTY;
}
return pSoundEnt->m_iActiveSound;
}
//=========================================================
// FreeList - returns the head of the free sound list
//=========================================================
int CSoundEnt :: FreeList ( void )
{
if ( !pSoundEnt )
{
return SOUNDLIST_EMPTY;
}
return pSoundEnt->m_iFreeSound;
}
//=========================================================
// SoundPointerForIndex - returns a pointer to the instance
// of CSound at index's position in the sound pool.
//=========================================================
CSound* CSoundEnt :: SoundPointerForIndex( int iIndex )
{
if ( !pSoundEnt )
{
return NULL;
}
if ( iIndex > ( MAX_WORLD_SOUNDS - 1 ) )
{
ALERT ( at_console, "SoundPointerForIndex() - Index too large!\n" );
return NULL;
}
if ( iIndex < 0 )
{
ALERT ( at_console, "SoundPointerForIndex() - Index < 0!\n" );
return NULL;
}
return &pSoundEnt->m_SoundPool[ iIndex ];
}
//=========================================================
// Clients are numbered from 1 to MAXCLIENTS, but the client
// reserved sounds in the soundlist are from 0 to MAXCLIENTS - 1,
// so this function ensures that a client gets the proper index
// to his reserved sound in the soundlist.
//=========================================================
int CSoundEnt :: ClientSoundIndex ( edict_t *pClient )
{
int iReturn = ENTINDEX( pClient ) - 1;
#ifdef _DEBUG
if ( iReturn < 0 || iReturn > gpGlobals->maxClients )
{
ALERT ( at_console, "** ClientSoundIndex returning a bogus value! **\n" );
}
#endif // _DEBUG
return iReturn;
}

95
hlsdk/dmc/dlls/soundent.h Normal file
View File

@ -0,0 +1,95 @@
/***
*
* 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.
*
****/
//=========================================================
// Soundent.h - the entity that spawns when the world
// spawns, and handles the world's active and free sound
// lists.
//=========================================================
#define MAX_WORLD_SOUNDS 64 // maximum number of sounds handled by the world at one time.
#define bits_SOUND_NONE 0
#define bits_SOUND_COMBAT ( 1 << 0 )// gunshots, explosions
#define bits_SOUND_WORLD ( 1 << 1 )// door opening/closing, glass breaking
#define bits_SOUND_PLAYER ( 1 << 2 )// all noises generated by player. walking, shooting, falling, splashing
#define bits_SOUND_CARCASS ( 1 << 3 )// dead body
#define bits_SOUND_MEAT ( 1 << 4 )// gib or pork chop
#define bits_SOUND_DANGER ( 1 << 5 )// pending danger. Grenade that is about to explode, explosive barrel that is damaged, falling crate
#define bits_SOUND_GARBAGE ( 1 << 6 )// trash cans, banana peels, old fast food bags.
#define bits_ALL_SOUNDS 0xFFFFFFFF
#define SOUNDLIST_EMPTY -1
#define SOUNDLISTTYPE_FREE 1// identifiers passed to functions that can operate on either list, to indicate which list to operate on.
#define SOUNDLISTTYPE_ACTIVE 2
#define SOUND_NEVER_EXPIRE -1 // with this set as a sound's ExpireTime, the sound will never expire.
//=========================================================
// CSound - an instance of a sound in the world.
//=========================================================
class CSound
{
public:
void Clear ( void );
void Reset ( void );
Vector m_vecOrigin; // sound's location in space
int m_iType; // what type of sound this is
int m_iVolume; // how loud the sound is
float m_flExpireTime; // when the sound should be purged from the list
int m_iNext; // index of next sound in this list ( Active or Free )
int m_iNextAudible; // temporary link that monsters use to build a list of audible sounds
BOOL FIsSound( void );
BOOL FIsScent( void );
};
//=========================================================
// CSoundEnt - a single instance of this entity spawns when
// the world spawns. The SoundEnt's job is to update the
// world's Free and Active sound lists.
//=========================================================
class CSoundEnt : public CBaseEntity
{
public:
void Precache ( void );
void Spawn( void );
void Think( void );
void Initialize ( void );
static void InsertSound ( int iType, const Vector &vecOrigin, int iVolume, float flDuration );
static void FreeSound ( int iSound, int iPrevious );
static int ActiveList( void );// return the head of the active list
static int FreeList( void );// return the head of the free list
static CSound* SoundPointerForIndex( int iIndex );// return a pointer for this index in the sound list
static int ClientSoundIndex ( edict_t *pClient );
BOOL IsEmpty( void ) { return m_iActiveSound == SOUNDLIST_EMPTY; }
int ISoundsInList ( int iListType );
int IAllocSound ( void );
virtual int ObjectCaps( void ) { return FCAP_DONT_SAVE; }
int m_iFreeSound; // index of the first sound in the free sound list
int m_iActiveSound; // indes of the first sound in the active sound list
int m_cLastActiveSounds; // keeps track of the number of active sounds at the last update. (for diagnostic work)
BOOL m_fShowReport; // if true, dump information about free/active sounds.
private:
CSound m_SoundPool[ MAX_WORLD_SOUNDS ];
};

View File

@ -0,0 +1,149 @@
/***
*
* 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.
*
****/
// CBaseSpectator
// YWB: UNDONE
// Spectator functions
//
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "spectator.h"
/*
===========
SpectatorConnect
called when a spectator connects to a server
============
*/
void CBaseSpectator::SpectatorConnect(void)
{
pev->flags = FL_SPECTATOR;
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NOCLIP;
m_pGoalEnt = NULL;
}
/*
===========
SpectatorDisconnect
called when a spectator disconnects from a server
============
*/
void CBaseSpectator::SpectatorDisconnect(void)
{
}
/*
================
SpectatorImpulseCommand
Called by SpectatorThink if the spectator entered an impulse
================
*/
void CBaseSpectator::SpectatorImpulseCommand(void)
{
static edict_t *pGoal = NULL;
edict_t *pPreviousGoal;
edict_t *pCurrentGoal;
BOOL bFound;
switch (pev->impulse)
{
case 1:
// teleport the spectator to the next spawn point
// note that if the spectator is tracking, this doesn't do
// much
pPreviousGoal = pGoal;
pCurrentGoal = pGoal;
// Start at the current goal, skip the world, and stop if we looped
// back around
bFound = FALSE;
while (1)
{
pCurrentGoal = FIND_ENTITY_BY_CLASSNAME(pCurrentGoal, "info_player_deathmatch");
// Looped around, failure
if (pCurrentGoal == pPreviousGoal)
{
ALERT(at_console, "Could not find a spawn spot.\n");
break;
}
// Found a non-world entity, set success, otherwise, look for the next one.
if (!FNullEnt(pCurrentGoal))
{
bFound = TRUE;
break;
}
}
if (!bFound) // Didn't find a good spot.
break;
pGoal = pCurrentGoal;
UTIL_SetOrigin( pev, pGoal->v.origin );
pev->angles = pGoal->v.angles;
pev->fixangle = FALSE;
break;
default:
ALERT(at_console, "Unknown spectator impulse\n");
break;
}
pev->impulse = 0;
}
/*
================
SpectatorThink
Called every frame after physics are run
================
*/
void CBaseSpectator::SpectatorThink(void)
{
if (!(pev->flags & FL_SPECTATOR))
{
pev->flags = FL_SPECTATOR;
}
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NOCLIP;
if (pev->impulse)
SpectatorImpulseCommand();
}
/*
===========
Spawn
Called when spectator is initialized:
UNDONE: Is this actually being called because spectators are not allocated in normal fashion?
============
*/
void CBaseSpectator::Spawn()
{
pev->flags = FL_SPECTATOR;
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NOCLIP;
m_pGoalEnt = NULL;
}

View File

@ -0,0 +1,27 @@
/***
*
* 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.
*
****/
// Spectator.h
class CBaseSpectator : public CBaseEntity
{
public:
void Spawn();
void SpectatorConnect(void);
void SpectatorDisconnect(void);
void SpectatorThink(void);
private:
void SpectatorImpulseCommand(void);
};

559
hlsdk/dmc/dlls/subs.cpp Normal file
View File

@ -0,0 +1,559 @@
/***
*
* 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.
*
****/
/*
===== subs.cpp ========================================================
frequently used global functions
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "saverestore.h"
#include "nodes.h"
#include "doors.h"
extern CGraph WorldGraph;
extern BOOL FEntIsVisible(entvars_t* pev, entvars_t* pevTarget);
extern DLL_GLOBAL int g_iSkillLevel;
// Landmark class
void CPointEntity :: Spawn( void )
{
pev->solid = SOLID_NOT;
// UTIL_SetSize(pev, g_vecZero, g_vecZero);
}
class CNullEntity : public CBaseEntity
{
public:
void Spawn( void );
};
// Null Entity, remove on startup
void CNullEntity :: Spawn( void )
{
REMOVE_ENTITY(ENT(pev));
}
LINK_ENTITY_TO_CLASS(info_null,CNullEntity);
class CBaseDMStart : public CPointEntity
{
public:
void KeyValue( KeyValueData *pkvd );
BOOL IsTriggered( CBaseEntity *pEntity );
private:
};
// These are the new entry points to entities.
LINK_ENTITY_TO_CLASS(info_player_deathmatch,CBaseDMStart);
LINK_ENTITY_TO_CLASS(info_player_start,CPointEntity);
LINK_ENTITY_TO_CLASS(info_landmark,CPointEntity);
void CBaseDMStart::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "master"))
{
pev->netname = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CPointEntity::KeyValue( pkvd );
}
BOOL CBaseDMStart::IsTriggered( CBaseEntity *pEntity )
{
BOOL master = UTIL_IsMasterTriggered( pev->netname, pEntity );
return master;
}
// This updates global tables that need to know about entities being removed
void CBaseEntity::UpdateOnRemove( void )
{
int i;
if ( FBitSet( pev->flags, FL_GRAPHED ) )
{
// this entity was a LinkEnt in the world node graph, so we must remove it from
// the graph since we are removing it from the world.
for ( i = 0 ; i < WorldGraph.m_cLinks ; i++ )
{
if ( WorldGraph.m_pLinkPool [ i ].m_pLinkEnt == pev )
{
// if this link has a link ent which is the same ent that is removing itself, remove it!
WorldGraph.m_pLinkPool [ i ].m_pLinkEnt = NULL;
}
}
}
if ( pev->globalname )
gGlobalState.EntitySetState( pev->globalname, GLOBAL_DEAD );
}
// Convenient way to delay removing oneself
void CBaseEntity :: SUB_Remove( void )
{
UpdateOnRemove();
if (pev->health > 0)
{
// this situation can screw up monsters who can't tell their entity pointers are invalid.
pev->health = 0;
ALERT( at_aiconsole, "SUB_Remove called on entity with health > 0\n");
}
REMOVE_ENTITY(ENT(pev));
}
// Convenient way to explicitly do nothing (passed to functions that require a method)
void CBaseEntity :: SUB_DoNothing( void )
{
}
// Global Savedata for Delay
TYPEDESCRIPTION CBaseDelay::m_SaveData[] =
{
DEFINE_FIELD( CBaseDelay, m_flDelay, FIELD_FLOAT ),
DEFINE_FIELD( CBaseDelay, m_iszKillTarget, FIELD_STRING ),
};
IMPLEMENT_SAVERESTORE( CBaseDelay, CBaseEntity );
void CBaseDelay :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "delay"))
{
m_flDelay = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "killtarget"))
{
m_iszKillTarget = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
{
CBaseEntity::KeyValue( pkvd );
}
}
/*
==============================
SUB_UseTargets
If self.delay is set, a DelayedUse entity will be created that will actually
do the SUB_UseTargets after that many seconds have passed.
Removes all entities with a targetname that match self.killtarget,
and removes them, so some events can remove other triggers.
Search for (string)targetname in all entities that
match (string)self.target and call their .use function (if they have one)
==============================
*/
void CBaseEntity :: SUB_UseTargets( CBaseEntity *pActivator, USE_TYPE useType, float value )
{
//
// fire targets
//
if (!FStringNull(pev->target))
{
FireTargets( STRING(pev->target), pActivator, this, useType, value );
}
}
void FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
edict_t *pentTarget = NULL;
if ( !targetName )
return;
ALERT( at_aiconsole, "Firing: (%s)\n", targetName );
for (;;)
{
pentTarget = FIND_ENTITY_BY_TARGETNAME(pentTarget, targetName);
if (FNullEnt(pentTarget))
break;
CBaseEntity *pTarget = CBaseEntity::Instance( pentTarget );
if ( pTarget && !(pTarget->pev->flags & FL_KILLME) ) // Don't use dying ents
{
ALERT( at_aiconsole, "Found: %s, firing (%s)\n", STRING(pTarget->pev->classname), targetName );
pTarget->Use( pActivator, pCaller, useType, value );
}
}
}
LINK_ENTITY_TO_CLASS( DelayedUse, CBaseDelay );
void CBaseDelay :: SUB_UseTargets( CBaseEntity *pActivator, USE_TYPE useType, float value )
{
//
// exit immediatly if we don't have a target or kill target
//
if (FStringNull(pev->target) && !m_iszKillTarget)
return;
//
// check for a delay
//
if (m_flDelay != 0)
{
// create a temp object to fire at a later time
CBaseDelay *pTemp = GetClassPtr( (CBaseDelay *)NULL);
pTemp->pev->classname = MAKE_STRING("DelayedUse");
pTemp->pev->nextthink = gpGlobals->time + m_flDelay;
pTemp->SetThink( &CBaseDelay::DelayThink );
// Save the useType
pTemp->pev->button = (int)useType;
pTemp->m_iszKillTarget = m_iszKillTarget;
pTemp->m_flDelay = 0; // prevent "recursion"
pTemp->pev->target = pev->target;
// HACKHACK
// This wasn't in the release build of Half-Life. We should have moved m_hActivator into this class
// but changing member variable hierarchy would break save/restore without some ugly code.
// This code is not as ugly as that code
if ( pActivator && pActivator->IsPlayer() ) // If a player activates, then save it
{
pTemp->pev->owner = pActivator->edict();
}
else
{
pTemp->pev->owner = NULL;
}
return;
}
//
// kill the killtargets
//
if ( m_iszKillTarget )
{
edict_t *pentKillTarget = NULL;
ALERT( at_aiconsole, "KillTarget: %s\n", STRING(m_iszKillTarget) );
pentKillTarget = FIND_ENTITY_BY_TARGETNAME( NULL, STRING(m_iszKillTarget) );
while ( !FNullEnt(pentKillTarget) )
{
UTIL_Remove( CBaseEntity::Instance(pentKillTarget) );
ALERT( at_aiconsole, "killing %s\n", STRING( pentKillTarget->v.classname ) );
pentKillTarget = FIND_ENTITY_BY_TARGETNAME( pentKillTarget, STRING(m_iszKillTarget) );
}
}
//
// fire targets
//
if (!FStringNull(pev->target))
{
FireTargets( STRING(pev->target), pActivator, this, useType, value );
}
}
/*
void CBaseDelay :: SUB_UseTargetsEntMethod( void )
{
SUB_UseTargets(pev);
}
*/
/*
QuakeEd only writes a single float for angles (bad idea), so up and down are
just constant angles.
*/
void SetMovedir( entvars_t *pev )
{
if (pev->angles == Vector(0, -1, 0))
{
pev->movedir = Vector(0, 0, 1);
}
else if (pev->angles == Vector(0, -2, 0))
{
pev->movedir = Vector(0, 0, -1);
}
else
{
UTIL_MakeVectors(pev->angles);
pev->movedir = gpGlobals->v_forward;
}
pev->angles = g_vecZero;
}
void CBaseDelay::DelayThink( void )
{
CBaseEntity *pActivator = NULL;
if ( pev->owner != NULL ) // A player activated this on delay
{
pActivator = CBaseEntity::Instance( pev->owner );
}
// The use type is cached (and stashed) in pev->button
SUB_UseTargets( pActivator, (USE_TYPE)pev->button, 0 );
REMOVE_ENTITY(ENT(pev));
}
// Global Savedata for Toggle
TYPEDESCRIPTION CBaseToggle::m_SaveData[] =
{
DEFINE_FIELD( CBaseToggle, m_toggle_state, FIELD_INTEGER ),
DEFINE_FIELD( CBaseToggle, m_flActivateFinished, FIELD_TIME ),
DEFINE_FIELD( CBaseToggle, m_flMoveDistance, FIELD_FLOAT ),
DEFINE_FIELD( CBaseToggle, m_flWait, FIELD_FLOAT ),
DEFINE_FIELD( CBaseToggle, m_flLip, FIELD_FLOAT ),
DEFINE_FIELD( CBaseToggle, m_flTWidth, FIELD_FLOAT ),
DEFINE_FIELD( CBaseToggle, m_flTLength, FIELD_FLOAT ),
DEFINE_FIELD( CBaseToggle, m_vecPosition1, FIELD_POSITION_VECTOR ),
DEFINE_FIELD( CBaseToggle, m_vecPosition2, FIELD_POSITION_VECTOR ),
DEFINE_FIELD( CBaseToggle, m_vecAngle1, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle?
DEFINE_FIELD( CBaseToggle, m_vecAngle2, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle?
DEFINE_FIELD( CBaseToggle, m_cTriggersLeft, FIELD_INTEGER ),
DEFINE_FIELD( CBaseToggle, m_flHeight, FIELD_FLOAT ),
DEFINE_FIELD( CBaseToggle, m_hActivator, FIELD_EHANDLE ),
DEFINE_FIELD( CBaseToggle, m_pfnCallWhenMoveDone, FIELD_FUNCTION ),
DEFINE_FIELD( CBaseToggle, m_vecFinalDest, FIELD_POSITION_VECTOR ),
DEFINE_FIELD( CBaseToggle, m_vecFinalAngle, FIELD_VECTOR ),
DEFINE_FIELD( CBaseToggle, m_sMaster, FIELD_STRING),
DEFINE_FIELD( CBaseToggle, m_bitsDamageInflict, FIELD_INTEGER ), // damage type inflicted
};
IMPLEMENT_SAVERESTORE( CBaseToggle, CBaseAnimating );
void CBaseToggle::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "lip"))
{
m_flLip = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "wait"))
{
m_flWait = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "master"))
{
m_sMaster = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "distance"))
{
m_flMoveDistance = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CBaseDelay::KeyValue( pkvd );
}
/*
=============
LinearMove
calculate pev->velocity and pev->nextthink to reach vecDest from
pev->origin traveling at flSpeed
===============
*/
void CBaseToggle :: LinearMove( Vector vecDest, float flSpeed )
{
ASSERTSZ(flSpeed != 0, "LinearMove: no speed is defined!");
// ASSERTSZ(m_pfnCallWhenMoveDone != NULL, "LinearMove: no post-move function defined");
m_vecFinalDest = vecDest;
// Already there?
if (vecDest == pev->origin)
{
LinearMoveDone();
return;
}
// set destdelta to the vector needed to move
Vector vecDestDelta = vecDest - pev->origin;
// divide vector length by speed to get time to reach dest
float flTravelTime = vecDestDelta.Length() / flSpeed;
// set nextthink to trigger a call to LinearMoveDone when dest is reached
pev->nextthink = pev->ltime + flTravelTime;
SetThink( &CBaseToggle::LinearMoveDone );
// scale the destdelta vector by the time spent traveling to get velocity
pev->velocity = vecDestDelta / flTravelTime;
}
/*
============
After moving, set origin to exact final destination, call "move done" function
============
*/
void CBaseToggle :: LinearMoveDone( void )
{
UTIL_SetOrigin(pev, m_vecFinalDest);
pev->velocity = g_vecZero;
pev->nextthink = -1;
if ( m_pfnCallWhenMoveDone )
(this->*m_pfnCallWhenMoveDone)();
}
BOOL CBaseToggle :: IsLockedByMaster( void )
{
if (m_sMaster && !UTIL_IsMasterTriggered(m_sMaster, m_hActivator))
return TRUE;
else
return FALSE;
}
/*
=============
AngularMove
calculate pev->velocity and pev->nextthink to reach vecDest from
pev->origin traveling at flSpeed
Just like LinearMove, but rotational.
===============
*/
void CBaseToggle :: AngularMove( Vector vecDestAngle, float flSpeed )
{
ASSERTSZ(flSpeed != 0, "AngularMove: no speed is defined!");
// ASSERTSZ(m_pfnCallWhenMoveDone != NULL, "AngularMove: no post-move function defined");
m_vecFinalAngle = vecDestAngle;
// Already there?
if (vecDestAngle == pev->angles)
{
AngularMoveDone();
return;
}
// set destdelta to the vector needed to move
Vector vecDestDelta = vecDestAngle - pev->angles;
// divide by speed to get time to reach dest
float flTravelTime = vecDestDelta.Length() / flSpeed;
// set nextthink to trigger a call to AngularMoveDone when dest is reached
pev->nextthink = pev->ltime + flTravelTime;
SetThink( &CBaseToggle::AngularMoveDone );
// scale the destdelta vector by the time spent traveling to get velocity
pev->avelocity = vecDestDelta / flTravelTime;
}
/*
============
After rotating, set angle to exact final angle, call "move done" function
============
*/
void CBaseToggle :: AngularMoveDone( void )
{
pev->angles = m_vecFinalAngle;
pev->avelocity = g_vecZero;
pev->nextthink = -1;
if ( m_pfnCallWhenMoveDone )
(this->*m_pfnCallWhenMoveDone)();
}
float CBaseToggle :: AxisValue( int flags, const Vector &angles )
{
if ( FBitSet(flags, SF_DOOR_ROTATE_Z) )
return angles.z;
if ( FBitSet(flags, SF_DOOR_ROTATE_X) )
return angles.x;
return angles.y;
}
void CBaseToggle :: AxisDir( entvars_t *pev )
{
if ( FBitSet(pev->spawnflags, SF_DOOR_ROTATE_Z) )
pev->movedir = Vector ( 0, 0, 1 ); // around z-axis
else if ( FBitSet(pev->spawnflags, SF_DOOR_ROTATE_X) )
pev->movedir = Vector ( 1, 0, 0 ); // around x-axis
else
pev->movedir = Vector ( 0, 1, 0 ); // around y-axis
}
float CBaseToggle :: AxisDelta( int flags, const Vector &angle1, const Vector &angle2 )
{
if ( FBitSet (flags, SF_DOOR_ROTATE_Z) )
return angle1.z - angle2.z;
if ( FBitSet (flags, SF_DOOR_ROTATE_X) )
return angle1.x - angle2.x;
return angle1.y - angle2.y;
}
/*
=============
FEntIsVisible
returns TRUE if the passed entity is visible to caller, even if not infront ()
=============
*/
BOOL
FEntIsVisible(
entvars_t* pev,
entvars_t* pevTarget)
{
Vector vecSpot1 = pev->origin + pev->view_ofs;
Vector vecSpot2 = pevTarget->origin + pevTarget->view_ofs;
TraceResult tr;
UTIL_TraceLine(vecSpot1, vecSpot2, ignore_monsters, ENT(pev), &tr);
if (tr.fInOpen && tr.fInWater)
return FALSE; // sight line crossed contents
if (tr.flFraction == 1)
return TRUE;
return FALSE;
}

View File

@ -0,0 +1,615 @@
/***
*
* 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.
*
****/
//
// teamplay_gamerules.cpp
//
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "teamplay_gamerules.h"
#include "game.h"
/*class CDMCGameMgrHelper : public IVoiceGameMgrHelper
{
public:
virtual bool ComparePlayerTeams(CBasePlayer *pPlayer1, CBasePlayer *pPlayer2)
{
return true;
}
};
static CDMCGameMgrHelper g_GameMgrHelper;*/
static char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH];
static int team_scores[MAX_TEAMS];
static int num_teams = 0;
extern DLL_GLOBAL BOOL g_fGameOver;
CHalfLifeTeamplay :: CHalfLifeTeamplay()
{
// m_VoiceGameMgr.Init(&g_GameMgrHelper, VGMode(HearPVS), gpGlobals->maxClients);
m_DisableDeathMessages = FALSE;
m_DisableDeathPenalty = FALSE;
memset( team_names, 0, sizeof(team_names) );
memset( team_scores, 0, sizeof(team_scores) );
num_teams = 0;
// Copy over the team from the server config
m_szTeamList[0] = 0;
// Cache this because the team code doesn't want to deal with changing this in the middle of a game
strncpy( m_szTeamList, teamlist.string, TEAMPLAY_TEAMLISTLENGTH );
edict_t *pWorld = INDEXENT(0);
if ( pWorld && pWorld->v.team )
{
if ( teamoverride.value )
{
const char *pTeamList = STRING(pWorld->v.team);
if ( pTeamList && strlen(pTeamList) )
{
strncpy( m_szTeamList, pTeamList, TEAMPLAY_TEAMLISTLENGTH );
}
}
}
// Has the server set teams
if ( strlen( m_szTeamList ) )
m_teamLimit = TRUE;
else
m_teamLimit = FALSE;
RecountTeams();
}
BOOL CHalfLifeTeamplay::ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] )
{
// m_VoiceGameMgr.ClientConnected(pEntity);
return CHalfLifeMultiplay::ClientConnected(pEntity, pszName, pszAddress, szRejectReason);
}
extern cvar_t timeleft, fragsleft;
void CHalfLifeTeamplay :: Think ( void )
{
// m_VoiceGameMgr.Update(gpGlobals->frametime);
///// Check game rules /////
static int last_frags;
static int last_time;
int frags_remaining = 0;
int time_remaining = 0;
if ( g_fGameOver ) // someone else quit the game already
{
CHalfLifeMultiplay::Think();
return;
}
float flTimeLimit = CVAR_GET_FLOAT("mp_timelimit") * 60;
time_remaining = (int)(flTimeLimit ? ( flTimeLimit - gpGlobals->time ) : 0);
if ( flTimeLimit != 0 && gpGlobals->time >= flTimeLimit )
{
GoToIntermission();
return;
}
float flFragLimit = fraglimit.value;
if ( flFragLimit )
{
int bestfrags = 9999;
int remain;
// check if any team is over the frag limit
for ( int i = 0; i < num_teams; i++ )
{
if ( team_scores[i] >= flFragLimit )
{
GoToIntermission();
return;
}
remain = static_cast<int>(flFragLimit - team_scores[i]);
if ( remain < bestfrags )
{
bestfrags = remain;
}
}
frags_remaining = bestfrags;
}
// Updates when frags change
if ( frags_remaining != last_frags )
{
g_engfuncs.pfnCvar_DirectSet( &fragsleft, UTIL_VarArgs( "%i", frags_remaining ) );
}
// Updates once per second
if ( timeleft.value != last_time )
{
g_engfuncs.pfnCvar_DirectSet( &timeleft, UTIL_VarArgs( "%i", time_remaining ) );
}
last_frags = frags_remaining;
last_time = time_remaining;
}
//=========================================================
// ClientCommand
// the user has typed a command which is unrecognized by everything else;
// this check to see if the gamerules knows anything about the command
//=========================================================
BOOL CHalfLifeTeamplay :: ClientCommand( CBasePlayer *pPlayer, const char *pcmd )
{
// if(m_VoiceGameMgr.ClientCommand(pPlayer, pcmd))
// return TRUE;
if ( FStrEq( pcmd, "menuselect" ) )
{
if ( CMD_ARGC() < 2 )
return TRUE;
// select the item from the current menu
return TRUE;
}
return FALSE;
}
extern int gmsgGameMode;
extern int gmsgSayText;
extern int gmsgTeamInfo;
void CHalfLifeTeamplay :: UpdateGameMode( CBasePlayer *pPlayer )
{
MESSAGE_BEGIN( MSG_ONE, gmsgGameMode, NULL, pPlayer->edict() );
WRITE_BYTE( 1 ); // game mode teamplay
MESSAGE_END();
}
const char *CHalfLifeTeamplay::SetDefaultPlayerTeam( CBasePlayer *pPlayer )
{
// copy out the team name from the model
char *mdls = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model" );
strncpy( pPlayer->m_szTeamName, mdls, TEAM_NAME_LENGTH );
RecountTeams();
// update the current player of the team he is joining
if ( pPlayer->m_szTeamName[0] == '\0' || !IsValidTeam( pPlayer->m_szTeamName ) || defaultteam.value )
{
const char *pTeamName = NULL;
if ( defaultteam.value )
{
pTeamName = team_names[0];
}
else
{
pTeamName = TeamWithFewestPlayers();
}
strncpy( pPlayer->m_szTeamName, pTeamName, TEAM_NAME_LENGTH );
}
return pPlayer->m_szTeamName;
}
//=========================================================
// InitHUD
//=========================================================
void CHalfLifeTeamplay::InitHUD( CBasePlayer *pPlayer )
{
SetDefaultPlayerTeam( pPlayer );
CHalfLifeMultiplay::InitHUD( pPlayer );
RecountTeams();
char *mdls = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model" );
// update the current player of the team he is joining
char text[1024];
if ( !strcmp( mdls, pPlayer->m_szTeamName ) )
{
sprintf( text, "* you are on team \'%s\'\n", pPlayer->m_szTeamName );
}
else
{
sprintf( text, "* assigned to team %s\n", pPlayer->m_szTeamName );
}
ChangePlayerTeam( pPlayer, pPlayer->m_szTeamName, FALSE, FALSE );
UTIL_SayText( text, pPlayer );
RecountTeams();
// update this player with all the other players team info
// loop through all active players and send their team info to the new client
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBaseEntity *plr = UTIL_PlayerByIndex( i );
if ( plr && IsValidTeam( plr->TeamID() ) )
{
MESSAGE_BEGIN( MSG_ONE, gmsgTeamInfo, NULL, pPlayer->edict() );
WRITE_BYTE( plr->entindex() );
WRITE_STRING( plr->TeamID() );
MESSAGE_END();
}
}
}
void CHalfLifeTeamplay::ChangePlayerTeam( CBasePlayer *pPlayer, const char *pTeamName, BOOL bKill, BOOL bGib )
{
int damageFlags = DMG_GENERIC;
int clientIndex = pPlayer->entindex();
if ( !bGib )
{
damageFlags |= DMG_NEVERGIB;
}
else
{
damageFlags |= DMG_ALWAYSGIB;
}
if ( bKill )
{
// kill the player, remove a death, and let them start on the new team
m_DisableDeathMessages = TRUE;
m_DisableDeathPenalty = TRUE;
entvars_t *pevWorld = VARS( INDEXENT(0) );
pPlayer->TakeDamage( pevWorld, pevWorld, 900, damageFlags );
m_DisableDeathMessages = FALSE;
m_DisableDeathPenalty = FALSE;
}
// copy out the team name from the model
strncpy( pPlayer->m_szTeamName, pTeamName, TEAM_NAME_LENGTH );
g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", pPlayer->m_szTeamName );
g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "team", pPlayer->m_szTeamName );
// notify everyone's HUD of the team change
MESSAGE_BEGIN( MSG_ALL, gmsgTeamInfo );
WRITE_BYTE( clientIndex );
WRITE_STRING( pPlayer->m_szTeamName );
MESSAGE_END();
}
//=========================================================
// ClientUserInfoChanged
//=========================================================
void CHalfLifeTeamplay::ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer )
{
char text[1024];
// prevent skin/color/model changes
char *mdls = g_engfuncs.pfnInfoKeyValue( infobuffer, "model" );
if ( !stricmp( mdls, pPlayer->m_szTeamName ) )
return;
if ( defaultteam.value )
{
int clientIndex = pPlayer->entindex();
g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", pPlayer->m_szTeamName );
g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "team", pPlayer->m_szTeamName );
sprintf( text, "* Not allowed to change teams in this game!\n" );
UTIL_SayText( text, pPlayer );
return;
}
if ( defaultteam.value || !IsValidTeam( mdls ) )
{
int clientIndex = pPlayer->entindex();
g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", pPlayer->m_szTeamName );
sprintf( text, "* Can't change team to \'%s\'\n", mdls );
UTIL_SayText( text, pPlayer );
sprintf( text, "* Server limits teams to \'%s\'\n", m_szTeamList );
UTIL_SayText( text, pPlayer );
return;
}
// notify everyone of the team change
sprintf( text, "* %s has changed to team \'%s\'\n", STRING(pPlayer->pev->netname), mdls );
UTIL_SayTextAll( text, pPlayer );
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" joined team \"%s\"\n",
STRING(pPlayer->pev->netname),
GETPLAYERUSERID( pPlayer->edict() ),
GETPLAYERAUTHID( pPlayer->edict() ),
pPlayer->m_szTeamName,
mdls );
ChangePlayerTeam( pPlayer, mdls, TRUE, TRUE );
// recound stuff
RecountTeams();
}
extern int gmsgDeathMsg;
//=========================================================
// Deathnotice.
//=========================================================
void CHalfLifeTeamplay::DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor )
{
if ( m_DisableDeathMessages )
return;
if ( pVictim && pKiller && pKiller->flags & FL_CLIENT )
{
CBasePlayer *pk = (CBasePlayer*) CBaseEntity::Instance( pKiller );
if ( pk )
{
if ( (pk != pVictim) && (PlayerRelationship( pVictim, pk ) == GR_TEAMMATE) )
{
MESSAGE_BEGIN( MSG_ALL, gmsgDeathMsg );
WRITE_BYTE( ENTINDEX(ENT(pKiller)) ); // the killer
WRITE_BYTE( ENTINDEX(pVictim->edict()) ); // the victim
WRITE_STRING( "teammate" ); // flag this as a teammate kill
MESSAGE_END();
return;
}
}
}
CHalfLifeMultiplay::DeathNotice( pVictim, pKiller, pevInflictor );
}
//=========================================================
//=========================================================
void CHalfLifeTeamplay :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor )
{
if ( !m_DisableDeathPenalty )
{
CHalfLifeMultiplay::PlayerKilled( pVictim, pKiller, pInflictor );
RecountTeams();
}
}
//=========================================================
// IsTeamplay
//=========================================================
BOOL CHalfLifeTeamplay::IsTeamplay( void )
{
return TRUE;
}
BOOL CHalfLifeTeamplay::FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker )
{
if ( pAttacker && PlayerRelationship( pPlayer, pAttacker ) == GR_TEAMMATE )
{
// my teammate hit me.
if ( (CVAR_GET_FLOAT("mp_friendlyfire") == 0) && (pAttacker != pPlayer) )
{
// friendly fire is off, and this hit came from someone other than myself, then don't get hurt
return FALSE;
}
}
return CHalfLifeMultiplay::FPlayerCanTakeDamage( pPlayer, pAttacker );
}
//=========================================================
//=========================================================
int CHalfLifeTeamplay::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget )
{
// half life multiplay has a simple concept of Player Relationships.
// you are either on another player's team, or you are not.
if ( !pPlayer || !pTarget || !pTarget->IsPlayer() )
return GR_NOTTEAMMATE;
if ( (*GetTeamID(pPlayer) != '\0') && (*GetTeamID(pTarget) != '\0') && !stricmp( GetTeamID(pPlayer), GetTeamID(pTarget) ) )
{
return GR_TEAMMATE;
}
return GR_NOTTEAMMATE;
}
//=========================================================
//=========================================================
BOOL CHalfLifeTeamplay::ShouldAutoAim( CBasePlayer *pPlayer, edict_t *target )
{
// always autoaim, unless target is a teammate
CBaseEntity *pTgt = CBaseEntity::Instance( target );
if ( pTgt && pTgt->IsPlayer() )
{
if ( PlayerRelationship( pPlayer, pTgt ) == GR_TEAMMATE )
return FALSE; // don't autoaim at teammates
}
return CHalfLifeMultiplay::ShouldAutoAim( pPlayer, target );
}
//=========================================================
//=========================================================
int CHalfLifeTeamplay::IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled )
{
if ( !pKilled )
return 0;
if ( !pAttacker )
return 1;
if ( pAttacker != pKilled && PlayerRelationship( pAttacker, pKilled ) == GR_TEAMMATE )
return -1;
return 1;
}
//=========================================================
//=========================================================
const char *CHalfLifeTeamplay::GetTeamID( CBaseEntity *pEntity )
{
if ( pEntity == NULL || pEntity->pev == NULL )
return "";
// return their team name
return pEntity->TeamID();
}
int CHalfLifeTeamplay::GetTeamIndex( const char *pTeamName )
{
if ( pTeamName && *pTeamName != 0 )
{
// try to find existing team
for ( int tm = 0; tm < num_teams; tm++ )
{
if ( !stricmp( team_names[tm], pTeamName ) )
return tm;
}
}
return -1; // No match
}
const char *CHalfLifeTeamplay::GetIndexedTeamName( int teamIndex )
{
if ( teamIndex < 0 || teamIndex >= num_teams )
return "";
return team_names[ teamIndex ];
}
BOOL CHalfLifeTeamplay::IsValidTeam( const char *pTeamName )
{
if ( !m_teamLimit ) // Any team is valid if the teamlist isn't set
return TRUE;
return ( GetTeamIndex( pTeamName ) != -1 ) ? TRUE : FALSE;
}
const char *CHalfLifeTeamplay::TeamWithFewestPlayers( void )
{
int i;
int minPlayers = MAX_TEAMS;
int teamCount[ MAX_TEAMS ];
char *pTeamName = NULL;
memset( teamCount, 0, MAX_TEAMS * sizeof(int) );
// loop through all clients, count number of players on each team
for ( i = 1; i <= gpGlobals->maxClients; i++ )
{
CBaseEntity *plr = UTIL_PlayerByIndex( i );
if ( plr )
{
int team = GetTeamIndex( plr->TeamID() );
if ( team >= 0 )
teamCount[team] ++;
}
}
// Find team with least players
for ( i = 0; i < num_teams; i++ )
{
if ( teamCount[i] < minPlayers )
{
minPlayers = teamCount[i];
pTeamName = team_names[i];
}
}
return pTeamName;
}
//=========================================================
//=========================================================
void CHalfLifeTeamplay::RecountTeams( void )
{
char *pName;
char teamlist[TEAMPLAY_TEAMLISTLENGTH];
// loop through all teams, recounting everything
num_teams = 0;
// Copy all of the teams from the teamlist
// make a copy because strtok is destructive
strcpy( teamlist, m_szTeamList );
pName = teamlist;
pName = strtok( pName, ";" );
while ( pName != NULL && *pName )
{
if ( GetTeamIndex( pName ) < 0 )
{
strcpy( team_names[num_teams], pName );
num_teams++;
}
pName = strtok( NULL, ";" );
}
if ( num_teams < 2 )
{
num_teams = 0;
m_teamLimit = FALSE;
}
// Sanity check
memset( team_scores, 0, sizeof(team_scores) );
// loop through all clients
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBaseEntity *plr = UTIL_PlayerByIndex( i );
if ( plr )
{
const char *pTeamName = plr->TeamID();
// try add to existing team
int tm = GetTeamIndex( pTeamName );
if ( tm < 0 ) // no team match found
{
if ( !m_teamLimit )
{
// add to new team
tm = num_teams;
num_teams++;
team_scores[tm] = 0;
strncpy( team_names[tm], pTeamName, MAX_TEAMNAME_LENGTH );
}
}
if ( tm >= 0 )
{
team_scores[tm] += static_cast<int>(plr->pev->frags);
}
}
}
}

View File

@ -0,0 +1,62 @@
/***
*
* 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.
*
****/
//
// teamplay_gamerules.h
//
#include "voice_gamemgr.h"
#define MAX_TEAMNAME_LENGTH 16
#define MAX_TEAMS 32
#define TEAMPLAY_TEAMLISTLENGTH MAX_TEAMS*MAX_TEAMNAME_LENGTH
class CHalfLifeTeamplay : public CHalfLifeMultiplay
{
public:
CHalfLifeTeamplay();
virtual BOOL ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] );
virtual BOOL ClientCommand( CBasePlayer *pPlayer, const char *pcmd );
virtual void ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer );
virtual BOOL IsTeamplay( void );
virtual BOOL FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker );
virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget );
virtual const char *GetTeamID( CBaseEntity *pEntity );
virtual BOOL ShouldAutoAim( CBasePlayer *pPlayer, edict_t *target );
virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled );
virtual void InitHUD( CBasePlayer *pl );
virtual void DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor );
virtual const char *GetGameDescription( void ) { return "HL Teamplay"; } // this is the game name that gets seen in the server browser
virtual void UpdateGameMode( CBasePlayer *pPlayer ); // the client needs to be informed of the current game mode
virtual void PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor );
virtual void Think ( void );
virtual int GetTeamIndex( const char *pTeamName );
virtual const char *GetIndexedTeamName( int teamIndex );
virtual BOOL IsValidTeam( const char *pTeamName );
const char *SetDefaultPlayerTeam( CBasePlayer *pPlayer );
virtual void ChangePlayerTeam( CBasePlayer *pPlayer, const char *pTeamName, BOOL bKill, BOOL bGib );
CVoiceGameMgr m_VoiceGameMgr;
private:
void RecountTeams( void );
const char *TeamWithFewestPlayers( void );
BOOL m_DisableDeathMessages;
BOOL m_DisableDeathPenalty;
BOOL m_teamLimit; // This means the server set only some teams as valid
char m_szTeamList[TEAMPLAY_TEAMLISTLENGTH];
};

127
hlsdk/dmc/dlls/trains.h Normal file
View File

@ -0,0 +1,127 @@
/***
*
* 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.
*
****/
#ifndef TRAINS_H
#define TRAINS_H
// Tracktrain spawn flags
#define SF_TRACKTRAIN_NOPITCH 0x0001
#define SF_TRACKTRAIN_NOCONTROL 0x0002
#define SF_TRACKTRAIN_FORWARDONLY 0x0004
#define SF_TRACKTRAIN_PASSABLE 0x0008
// Spawnflag for CPathTrack
#define SF_PATH_DISABLED 0x00000001
#define SF_PATH_FIREONCE 0x00000002
#define SF_PATH_ALTREVERSE 0x00000004
#define SF_PATH_DISABLE_TRAIN 0x00000008
#define SF_PATH_ALTERNATE 0x00008000
// Spawnflags of CPathCorner
#define SF_CORNER_WAITFORTRIG 0x001
#define SF_CORNER_TELEPORT 0x002
#define SF_CORNER_FIREONCE 0x004
//#define PATH_SPARKLE_DEBUG 1 // This makes a particle effect around path_track entities for debugging
class CPathTrack : public CPointEntity
{
public:
void Spawn( void );
void Activate( void );
void KeyValue( KeyValueData* pkvd);
void SetPrevious( CPathTrack *pprevious );
void Link( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
CPathTrack *ValidPath( CPathTrack *ppath, int testFlag ); // Returns ppath if enabled, NULL otherwise
void Project( CPathTrack *pstart, CPathTrack *pend, Vector *origin, float dist );
static CPathTrack *Instance( edict_t *pent );
CPathTrack *LookAhead( Vector *origin, float dist, int move );
CPathTrack *Nearest( Vector origin );
CPathTrack *GetNext( void );
CPathTrack *GetPrevious( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
#if PATH_SPARKLE_DEBUG
void EXPORT Sparkle(void);
#endif
float m_length;
string_t m_altName;
CPathTrack *m_pnext;
CPathTrack *m_pprevious;
CPathTrack *m_paltpath;
};
class CFuncTrackTrain : public CBaseEntity
{
public:
void Spawn( void );
void Precache( void );
void Blocked( CBaseEntity *pOther );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void KeyValue( KeyValueData* pkvd );
void EXPORT Next( void );
void EXPORT Find( void );
void EXPORT NearestPath( void );
void EXPORT DeadEnd( void );
void NextThink( float thinkTime, BOOL alwaysThink );
void SetTrack( CPathTrack *track ) { m_ppath = track->Nearest(pev->origin); }
void SetControls( entvars_t *pevControls );
BOOL OnControls( entvars_t *pev );
void StopSound ( void );
void UpdateSound ( void );
static CFuncTrackTrain *Instance( edict_t *pent );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DIRECTIONAL_USE; }
virtual void OverrideReset( void );
CPathTrack *m_ppath;
float m_length;
float m_height;
float m_speed;
float m_dir;
float m_startSpeed;
Vector m_controlMins;
Vector m_controlMaxs;
int m_soundPlaying;
int m_sounds;
float m_flVolume;
float m_flBank;
float m_oldSpeed;
private:
unsigned short m_usAdjustPitch;
};
#endif

2715
hlsdk/dmc/dlls/triggers.cpp Normal file

File diff suppressed because it is too large Load Diff

2715
hlsdk/dmc/dlls/util.cpp Normal file

File diff suppressed because it is too large Load Diff

599
hlsdk/dmc/dlls/util.h Normal file
View File

@ -0,0 +1,599 @@
/***
*
* 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.
*
****/
//
// Misc utility code
//
#include <string.h>
#ifndef ACTIVITY_H
#include "activity.h"
#endif
#ifndef ENGINECALLBACK_H
#include "enginecallback.h"
#endif
inline void MESSAGE_BEGIN( int msg_dest, int msg_type, const float *pOrigin, entvars_t *ent ); // implementation later in this file
extern globalvars_t *gpGlobals;
// Use this instead of ALLOC_STRING on constant strings
#define STRING(offset) (const char *)(gpGlobals->pStringBase + (int)offset)
#define MAKE_STRING(str) ((int)str - (int)STRING(0))
inline edict_t *FIND_ENTITY_BY_CLASSNAME(edict_t *entStart, const char *pszName)
{
return FIND_ENTITY_BY_STRING(entStart, "classname", pszName);
}
inline edict_t *FIND_ENTITY_BY_TARGETNAME(edict_t *entStart, const char *pszName)
{
return FIND_ENTITY_BY_STRING(entStart, "targetname", pszName);
}
// for doing a reverse lookup. Say you have a door, and want to find its button.
inline edict_t *FIND_ENTITY_BY_TARGET(edict_t *entStart, const char *pszName)
{
return FIND_ENTITY_BY_STRING(entStart, "target", pszName);
}
// Keeps clutter down a bit, when writing key-value pairs
#define WRITEKEY_INT(pf, szKeyName, iKeyValue) \
ENGINE_FPRINTF(pf, "\"%s\" \"%d\"\n", szKeyName, iKeyValue)
#define WRITEKEY_FLOAT(pf, szKeyName, flKeyValue) \
ENGINE_FPRINTF(pf, "\"%s\" \"%f\"\n", szKeyName, flKeyValue)
#define WRITEKEY_STRING(pf, szKeyName, szKeyValue) \
ENGINE_FPRINTF(pf, "\"%s\" \"%s\"\n", szKeyName, szKeyValue)
#define WRITEKEY_VECTOR(pf, szKeyName, flX, flY, flZ) \
ENGINE_FPRINTF(pf, "\"%s\" \"%f %f %f\"\n", szKeyName, flX, flY, flZ)
// Keeps clutter down a bit, when using a float as a bit-vector
#define SetBits(flBitVector, bits) ((flBitVector) = (int)(flBitVector) | (bits))
#define ClearBits(flBitVector, bits) ((flBitVector) = (int)(flBitVector) & ~(bits))
#define FBitSet(flBitVector, bit) ((int)(flBitVector) & (bit))
// Makes these more explicit, and easier to find
#define FILE_GLOBAL static
#define DLL_GLOBAL
// Until we figure out why "const" gives the compiler problems, we'll just have to use
// this bogus "empty" define to mark things as constant.
#define CONSTANT
// More explicit than "int"
typedef int EOFFSET;
// In case it's not alread defined
typedef int BOOL;
// In case this ever changes
#define M_PI 3.14159265358979323846
// Keeps clutter down a bit, when declaring external entity/global method prototypes
#define DECLARE_GLOBAL_METHOD(MethodName) \
extern void DLLEXPORT MethodName( void )
#define GLOBAL_METHOD(funcname) void DLLEXPORT funcname(void)
// This is the glue that hooks .MAP entity class names to our CPP classes
// The _declspec forces them to be exported by name so we can do a lookup with GetProcAddress()
// The function is used to intialize / allocate the object for the entity
#ifdef _WIN32
#define LINK_ENTITY_TO_CLASS(mapClassName,DLLClassName) \
extern "C" _declspec( dllexport ) void mapClassName( entvars_t *pev ); \
void mapClassName( entvars_t *pev ) { GetClassPtr( (DLLClassName *)pev ); }
#else
#define LINK_ENTITY_TO_CLASS(mapClassName,DLLClassName) \
extern "C" void mapClassName( entvars_t *pev ); \
void mapClassName( entvars_t *pev ) { GetClassPtr( (DLLClassName *)pev ); }
#endif
//
// Conversion among the three types of "entity", including identity-conversions.
//
#ifdef DEBUG
extern edict_t *DBG_EntOfVars(const entvars_t *pev);
inline edict_t *ENT(const entvars_t *pev) { return DBG_EntOfVars(pev); }
#else
inline edict_t *ENT(const entvars_t *pev) { return pev->pContainingEntity; }
#endif
inline edict_t *ENT(edict_t *pent) { return pent; }
inline edict_t *ENT(EOFFSET eoffset) { return (*g_engfuncs.pfnPEntityOfEntOffset)(eoffset); }
inline EOFFSET OFFSET(EOFFSET eoffset) { return eoffset; }
inline EOFFSET OFFSET(const edict_t *pent)
{
#ifdef _DEBUG
if ( !pent )
ALERT( at_error, "Bad ent in OFFSET()\n" );
#endif
return (*g_engfuncs.pfnEntOffsetOfPEntity)(pent);
}
inline EOFFSET OFFSET(entvars_t *pev)
{
#ifdef _DEBUG
if ( !pev )
ALERT( at_error, "Bad pev in OFFSET()\n" );
#endif
return OFFSET(ENT(pev));
}
inline entvars_t *VARS(entvars_t *pev) { return pev; }
inline entvars_t *VARS(edict_t *pent)
{
if ( !pent )
return NULL;
return &pent->v;
}
inline entvars_t* VARS(EOFFSET eoffset) { return VARS(ENT(eoffset)); }
inline int ENTINDEX(edict_t *pEdict) { return (*g_engfuncs.pfnIndexOfEdict)(pEdict); }
inline edict_t* INDEXENT( int iEdictNum ) { return (*g_engfuncs.pfnPEntityOfEntIndex)(iEdictNum); }
inline void MESSAGE_BEGIN( int msg_dest, int msg_type, const float *pOrigin, entvars_t *ent ) {
(*g_engfuncs.pfnMessageBegin)(msg_dest, msg_type, pOrigin, ENT(ent));
}
// Testing the three types of "entity" for nullity
#define eoNullEntity 0
inline BOOL FNullEnt(EOFFSET eoffset) { return eoffset == 0; }
inline BOOL FNullEnt(const edict_t* pent) { return pent == NULL || FNullEnt(OFFSET(pent)); }
inline BOOL FNullEnt(entvars_t* pev) { return pev == NULL || FNullEnt(OFFSET(pev)); }
// Testing strings for nullity
#define iStringNull 0
inline BOOL FStringNull(int iString) { return iString == iStringNull; }
#define cchMapNameMost 32
// Dot products for view cone checking
#define VIEW_FIELD_FULL (float)-1.0 // +-180 degrees
#define VIEW_FIELD_WIDE (float)-0.7 // +-135 degrees 0.1 // +-85 degrees, used for full FOV checks
#define VIEW_FIELD_NARROW (float)0.7 // +-45 degrees, more narrow check used to set up ranged attacks
#define VIEW_FIELD_ULTRA_NARROW (float)0.9 // +-25 degrees, more narrow check used to set up ranged attacks
// All monsters need this data
#define DONT_BLEED -1
#define BLOOD_COLOR_RED (BYTE)247
#define BLOOD_COLOR_YELLOW (BYTE)195
#define BLOOD_COLOR_GREEN BLOOD_COLOR_YELLOW
typedef enum
{
MONSTERSTATE_NONE = 0,
MONSTERSTATE_IDLE,
MONSTERSTATE_COMBAT,
MONSTERSTATE_ALERT,
MONSTERSTATE_HUNT,
MONSTERSTATE_PRONE,
MONSTERSTATE_SCRIPT,
MONSTERSTATE_PLAYDEAD,
MONSTERSTATE_DEAD
} MONSTERSTATE;
// Things that toggle (buttons/triggers/doors) need this
typedef enum
{
TS_AT_TOP,
TS_AT_BOTTOM,
TS_GOING_UP,
TS_GOING_DOWN
} TOGGLE_STATE;
// Misc useful
inline BOOL FStrEq(const char*sz1, const char*sz2)
{ return (strcmp(sz1, sz2) == 0); }
inline BOOL FClassnameIs(edict_t* pent, const char* szClassname)
{ return FStrEq(STRING(VARS(pent)->classname), szClassname); }
inline BOOL FClassnameIs(entvars_t* pev, const char* szClassname)
{ return FStrEq(STRING(pev->classname), szClassname); }
class CBaseEntity;
// Misc. Prototypes
extern void UTIL_SetSize (entvars_t* pev, const Vector &vecMin, const Vector &vecMax);
extern float UTIL_VecToYaw (const Vector &vec);
extern Vector UTIL_VecToAngles (const Vector &vec);
extern float UTIL_AngleMod (float a);
extern float UTIL_AngleDiff ( float destAngle, float srcAngle );
extern CBaseEntity *UTIL_FindEntityInSphere(CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius);
extern CBaseEntity *UTIL_FindEntityByString(CBaseEntity *pStartEntity, const char *szKeyword, const char *szValue );
extern CBaseEntity *UTIL_FindEntityByClassname(CBaseEntity *pStartEntity, const char *szName );
extern CBaseEntity *UTIL_FindEntityByTargetname(CBaseEntity *pStartEntity, const char *szName );
extern CBaseEntity *UTIL_FindEntityGeneric(const char *szName, Vector &vecSrc, float flRadius );
// returns a CBaseEntity pointer to a player by index. Only returns if the player is spawned and connected
// otherwise returns NULL
// Index is 1 based
extern CBaseEntity *UTIL_PlayerByIndex( int playerIndex );
#define UTIL_EntitiesInPVS(pent) (*g_engfuncs.pfnEntitiesInPVS)(pent)
extern void UTIL_MakeVectors (const Vector &vecAngles);
// Pass in an array of pointers and an array size, it fills the array and returns the number inserted
extern int UTIL_MonstersInSphere( CBaseEntity **pList, int listMax, const Vector &center, float radius );
extern int UTIL_EntitiesInBox( CBaseEntity **pList, int listMax, const Vector &mins, const Vector &maxs, int flagMask );
inline void UTIL_MakeVectorsPrivate( const Vector &vecAngles, float *p_vForward, float *p_vRight, float *p_vUp )
{
g_engfuncs.pfnAngleVectors( vecAngles, p_vForward, p_vRight, p_vUp );
}
extern void UTIL_MakeAimVectors ( const Vector &vecAngles ); // like MakeVectors, but assumes pitch isn't inverted
extern void UTIL_MakeInvVectors ( const Vector &vec, globalvars_t *pgv );
extern void UTIL_SetOrigin ( entvars_t* pev, const Vector &vecOrigin );
extern void UTIL_EmitAmbientSound ( edict_t *entity, const Vector &vecOrigin, const char *samp, float vol, float attenuation, int fFlags, int pitch );
extern void UTIL_ParticleEffect ( const Vector &vecOrigin, const Vector &vecDirection, ULONG ulColor, ULONG ulCount );
extern void UTIL_ScreenShake ( const Vector &center, float amplitude, float frequency, float duration, float radius );
extern void UTIL_ScreenShakeAll ( const Vector &center, float amplitude, float frequency, float duration );
extern void UTIL_ShowMessage ( const char *pString, CBaseEntity *pPlayer );
extern void UTIL_ShowMessageAll ( const char *pString );
extern void UTIL_ScreenFadeAll ( const Vector &color, float fadeTime, float holdTime, int alpha, int flags );
extern void UTIL_ScreenFade ( CBaseEntity *pEntity, const Vector &color, float fadeTime, float fadeHold, int alpha, int flags );
typedef enum { ignore_monsters=1, dont_ignore_monsters=0, missile=2 } IGNORE_MONSTERS;
typedef enum { ignore_glass=1, dont_ignore_glass=0 } IGNORE_GLASS;
extern void UTIL_TraceLine (const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, edict_t *pentIgnore, TraceResult *ptr);
extern void UTIL_TraceLine (const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, edict_t *pentIgnore, TraceResult *ptr);
typedef enum { point_hull=0, human_hull=1, large_hull=2, head_hull=3 };
extern void UTIL_TraceHull (const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, int hullNumber, edict_t *pentIgnore, TraceResult *ptr);
extern TraceResult UTIL_GetGlobalTrace (void);
extern void UTIL_TraceModel (const Vector &vecStart, const Vector &vecEnd, int hullNumber, edict_t *pentModel, TraceResult *ptr);
extern Vector UTIL_GetAimVector (edict_t* pent, float flSpeed);
extern int UTIL_PointContents (const Vector &vec);
extern int UTIL_IsMasterTriggered (string_t sMaster, CBaseEntity *pActivator);
extern void UTIL_BloodStream( const Vector &origin, const Vector &direction, int color, int amount );
extern void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount );
extern Vector UTIL_RandomBloodVector( void );
extern BOOL UTIL_ShouldShowBlood( int bloodColor );
extern void UTIL_BloodDecalTrace( TraceResult *pTrace, int bloodColor );
extern void UTIL_DecalTrace( TraceResult *pTrace, int decalNumber );
extern void UTIL_PlayerDecalTrace( TraceResult *pTrace, int playernum, int decalNumber, BOOL bIsCustom );
extern void UTIL_GunshotDecalTrace( TraceResult *pTrace, int decalNumber );
extern void UTIL_Sparks( const Vector &position );
extern void UTIL_Ricochet( const Vector &position, float scale );
extern void UTIL_StringToVector( float *pVector, const char *pString );
extern void UTIL_StringToIntArray( int *pVector, int count, const char *pString );
extern Vector UTIL_ClampVectorToBox( const Vector &input, const Vector &clampSize );
extern float UTIL_Approach( float target, float value, float speed );
extern float UTIL_ApproachAngle( float target, float value, float speed );
extern float UTIL_AngleDistance( float next, float cur );
extern char *UTIL_VarArgs( char *format, ... );
extern void UTIL_Remove( CBaseEntity *pEntity );
extern BOOL UTIL_IsValidEntity( edict_t *pent );
extern BOOL UTIL_TeamsMatch( const char *pTeamName1, const char *pTeamName2 );
// create a TENT projectile on all clients
extern void UTIL_ClientProjectile( const Vector &vecOrigin, const Vector &vecVelocity, short sModelIndex, int iOwnerIndex, int iLife );
// Use for ease-in, ease-out style interpolation (accel/decel)
extern float UTIL_SplineFraction( float value, float scale );
// Search for water transition along a vertical line
extern float UTIL_WaterLevel( const Vector &position, float minz, float maxz );
extern void UTIL_Bubbles( Vector mins, Vector maxs, int count );
extern void UTIL_BubbleTrail( Vector from, Vector to, int count );
// allows precacheing of other entities
extern void UTIL_PrecacheOther( const char *szClassname );
// prints a message to each client
extern void UTIL_ClientPrintAll( int msg_dest, const char *msg_name, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL, const char *param4 = NULL );
inline void UTIL_CenterPrintAll( const char *msg_name, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL, const char *param4 = NULL )
{
UTIL_ClientPrintAll( HUD_PRINTCENTER, msg_name, param1, param2, param3, param4 );
}
class CBasePlayerItem;
class CBasePlayer;
extern BOOL UTIL_GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon );
// prints messages through the HUD
extern void ClientPrint( entvars_t *client, int msg_dest, const char *msg_name, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL, const char *param4 = NULL );
// prints a message to the HUD say (chat)
extern void UTIL_SayText( const char *pText, CBaseEntity *pEntity );
extern void UTIL_SayTextAll( const char *pText, CBaseEntity *pEntity );
typedef struct hudtextparms_s
{
float x;
float y;
int effect;
byte r1, g1, b1, a1;
byte r2, g2, b2, a2;
float fadeinTime;
float fadeoutTime;
float holdTime;
float fxTime;
int channel;
} hudtextparms_t;
// prints as transparent 'title' to the HUD
extern void UTIL_HudMessageAll( const hudtextparms_t &textparms, const char *pMessage );
extern void UTIL_HudMessage( CBaseEntity *pEntity, const hudtextparms_t &textparms, const char *pMessage );
// for handy use with ClientPrint params
extern char *UTIL_dtos1( int d );
extern char *UTIL_dtos2( int d );
extern char *UTIL_dtos3( int d );
extern char *UTIL_dtos4( int d );
// Writes message to console with timestamp and FragLog header.
extern void UTIL_LogPrintf( char *fmt, ... );
// Sorta like FInViewCone, but for nonmonsters.
extern float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vector &vecDir );
extern void UTIL_StripToken( const char *pKey, char *pDest );// for redundant keynames
// Misc functions
extern void SetMovedir(entvars_t* pev);
extern Vector VecBModelOrigin( entvars_t* pevBModel );
extern int BuildChangeList( LEVELLIST *pLevelList, int maxList );
//
// How did I ever live without ASSERT?
//
#ifdef DEBUG
void DBG_AssertFunction(BOOL fExpr, const char* szExpr, const char* szFile, int szLine, const char* szMessage);
#define ASSERT(f) DBG_AssertFunction(f, #f, __FILE__, __LINE__, NULL)
#define ASSERTSZ(f, sz) DBG_AssertFunction(f, #f, __FILE__, __LINE__, sz)
#else // !DEBUG
#define ASSERT(f)
#define ASSERTSZ(f, sz)
#endif // !DEBUG
extern DLL_GLOBAL const Vector g_vecZero;
//
// Constants that were used only by QC (maybe not used at all now)
//
// Un-comment only as needed
//
#define LANGUAGE_ENGLISH 0
#define LANGUAGE_GERMAN 1
#define LANGUAGE_FRENCH 2
#define LANGUAGE_BRITISH 3
extern DLL_GLOBAL int g_Language;
#define AMBIENT_SOUND_STATIC 0 // medium radius attenuation
#define AMBIENT_SOUND_EVERYWHERE 1
#define AMBIENT_SOUND_SMALLRADIUS 2
#define AMBIENT_SOUND_MEDIUMRADIUS 4
#define AMBIENT_SOUND_LARGERADIUS 8
#define AMBIENT_SOUND_START_SILENT 16
#define AMBIENT_SOUND_NOT_LOOPING 32
#define SPEAKER_START_SILENT 1 // wait for trigger 'on' to start announcements
#define SND_SPAWNING (1<<8) // duplicated in protocol.h we're spawing, used in some cases for ambients
#define SND_STOP (1<<5) // duplicated in protocol.h stop sound
#define SND_CHANGE_VOL (1<<6) // duplicated in protocol.h change sound vol
#define SND_CHANGE_PITCH (1<<7) // duplicated in protocol.h change sound pitch
#define LFO_SQUARE 1
#define LFO_TRIANGLE 2
#define LFO_RANDOM 3
// func_rotating
#define SF_BRUSH_ROTATE_Y_AXIS 0
#define SF_BRUSH_ROTATE_INSTANT 1
#define SF_BRUSH_ROTATE_BACKWARDS 2
#define SF_BRUSH_ROTATE_Z_AXIS 4
#define SF_BRUSH_ROTATE_X_AXIS 8
#define SF_PENDULUM_AUTO_RETURN 16
#define SF_PENDULUM_PASSABLE 32
#define SF_BRUSH_ROTATE_SMALLRADIUS 128
#define SF_BRUSH_ROTATE_MEDIUMRADIUS 256
#define SF_BRUSH_ROTATE_LARGERADIUS 512
#define PUSH_BLOCK_ONLY_X 1
#define PUSH_BLOCK_ONLY_Y 2
// QUAKECLASSIC: Different player sizes
//#define VEC_HULL_MIN Vector(-16, -16, -36)
//#define VEC_HULL_MAX Vector( 16, 16, 36)
#define VEC_HULL_MIN Vector(-16, -16, -24)
#define VEC_HULL_MAX Vector(16, 16, 32)
#define VEC_HUMAN_HULL_MIN Vector( -16, -16, 0 )
#define VEC_HUMAN_HULL_MAX Vector( 16, 16, 72 )
#define VEC_HUMAN_HULL_DUCK Vector( 16, 16, 36 )
#define VEC_VIEW Vector( 0, 0, 18 )
#define VEC_DUCK_HULL_MIN Vector(-16, -16, -18 )
#define VEC_DUCK_HULL_MAX Vector( 16, 16, 18)
#define VEC_DUCK_VIEW Vector( 0, 0, 12 )
#define SVC_TEMPENTITY 23
#define SVC_INTERMISSION 30
#define SVC_CDTRACK 32
#define SVC_WEAPONANIM 35
#define SVC_ROOMTYPE 37
#define SVC_ADDANGLE 38 // [vec3] add this angle to the view angle
#define SVC_NEWUSERMSG 39
#define SVC_DIRECTOR 51
// triggers
#define SF_TRIGGER_ALLOWMONSTERS 1// monsters allowed to fire this trigger
#define SF_TRIGGER_NOCLIENTS 2// players not allowed to fire this trigger
#define SF_TRIGGER_PUSHABLES 4// only pushables can fire this trigger
// func breakable
#define SF_BREAK_TRIGGER_ONLY 1// may only be broken by trigger
#define SF_BREAK_TOUCH 2// can be 'crashed through' by running player (plate glass)
#define SF_BREAK_PRESSURE 4// can be broken by a player standing on it
#define SF_BREAK_CROWBAR 256// instant break if hit with crowbar
// func_pushable (it's also func_breakable, so don't collide with those flags)
#define SF_PUSH_BREAKABLE 128
#define SF_LIGHT_START_OFF 1
#define SPAWNFLAG_NOMESSAGE 1
#define SPAWNFLAG_NOTOUCH 1
#define SPAWNFLAG_DROIDONLY 4
#define SPAWNFLAG_USEONLY 1 // can't be touched, must be used (buttons)
#define TELE_PLAYER_ONLY 1
#define TELE_SILENT 2
#define SF_TRIG_PUSH_ONCE 1
// Sound Utilities
// sentence groups
#define CBSENTENCENAME_MAX 16
#define CVOXFILESENTENCEMAX 1536 // max number of sentences in game. NOTE: this must match
// CVOXFILESENTENCEMAX in engine\sound.h!!!
extern char gszallsentencenames[CVOXFILESENTENCEMAX][CBSENTENCENAME_MAX];
extern int gcallsentences;
int USENTENCEG_Pick(int isentenceg, char *szfound);
int USENTENCEG_PickSequential(int isentenceg, char *szfound, int ipick, int freset);
void USENTENCEG_InitLRU(unsigned char *plru, int count);
void SENTENCEG_Init();
void SENTENCEG_Stop(edict_t *entity, int isentenceg, int ipick);
int SENTENCEG_PlayRndI(edict_t *entity, int isentenceg, float volume, float attenuation, int flags, int pitch);
int SENTENCEG_PlayRndSz(edict_t *entity, const char *szrootname, float volume, float attenuation, int flags, int pitch);
int SENTENCEG_PlaySequentialSz(edict_t *entity, const char *szrootname, float volume, float attenuation, int flags, int pitch, int ipick, int freset);
int SENTENCEG_GetIndex(const char *szrootname);
int SENTENCEG_Lookup(const char *sample, char *sentencenum);
void TEXTURETYPE_Init();
char TEXTURETYPE_Find(char *name);
float TEXTURETYPE_PlaySound(TraceResult *ptr, Vector vecSrc, Vector vecEnd, int iBulletType);
#define CBTEXTURENAMEMAX 13 // only load first n chars of name
#define CHAR_TEX_CONCRETE 'C' // texture types
#define CHAR_TEX_METAL 'M'
#define CHAR_TEX_DIRT 'D'
#define CHAR_TEX_VENT 'V'
#define CHAR_TEX_GRATE 'G'
#define CHAR_TEX_TILE 'T'
#define CHAR_TEX_SLOSH 'S'
#define CHAR_TEX_WOOD 'W'
#define CHAR_TEX_COMPUTER 'P'
#define CHAR_TEX_GLASS 'Y'
#define CHAR_TEX_FLESH 'F'
// NOTE: use EMIT_SOUND_DYN to set the pitch of a sound. Pitch of 100
// is no pitch shift. Pitch > 100 up to 255 is a higher pitch, pitch < 100
// down to 1 is a lower pitch. 150 to 70 is the realistic range.
// EMIT_SOUND_DYN with pitch != 100 should be used sparingly, as it's not quite as
// fast as EMIT_SOUND (the pitchshift mixer is not native coded).
void EMIT_SOUND_DYN(edict_t *entity, int channel, const char *sample, float volume, float attenuation,
int flags, int pitch);
inline void EMIT_SOUND(edict_t *entity, int channel, const char *sample, float volume, float attenuation)
{
EMIT_SOUND_DYN(entity, channel, sample, volume, attenuation, 0, PITCH_NORM);
}
inline void STOP_SOUND(edict_t *entity, int channel, const char *sample)
{
EMIT_SOUND_DYN(entity, channel, sample, 0, 0, SND_STOP, PITCH_NORM);
}
void EMIT_SOUND_SUIT(edict_t *entity, const char *sample);
void EMIT_GROUPID_SUIT(edict_t *entity, int isentenceg);
void EMIT_GROUPNAME_SUIT(edict_t *entity, const char *groupname);
#define PRECACHE_SOUND_ARRAY( a ) \
{ for (int i = 0; i < static_cast<int>(ARRAYSIZE( a )); i++ ) PRECACHE_SOUND((char *) a [i]); }
#define EMIT_SOUND_ARRAY_DYN( chan, array ) \
EMIT_SOUND_DYN ( ENT(pev), chan , array [ RANDOM_LONG(0,ARRAYSIZE( array )-1) ], 1.0, ATTN_NORM, 0, RANDOM_LONG(95,105) );
#define RANDOM_SOUND_ARRAY( array ) (array) [ RANDOM_LONG(0,ARRAYSIZE( (array) )-1) ]
#define PLAYBACK_EVENT( flags, who, index ) PLAYBACK_EVENT_FULL( flags, who, index, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 );
#define PLAYBACK_EVENT_DELAY( flags, who, index, delay ) PLAYBACK_EVENT_FULL( flags, who, index, delay, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 );
#define GROUP_OP_AND 0
#define GROUP_OP_NAND 1
extern int g_groupmask;
extern int g_groupop;
class UTIL_GroupTrace
{
public:
UTIL_GroupTrace( int groupmask, int op );
~UTIL_GroupTrace( void );
private:
int m_oldgroupmask, m_oldgroupop;
};
void UTIL_SetGroupTrace( int groupmask, int op );
void UTIL_UnsetGroupTrace( void );
int UTIL_SharedRandomLong( unsigned int seed, int low, int high );
float UTIL_SharedRandomFloat( unsigned int seed, float low, float high );
float UTIL_WeaponTimeBase( void );
typedef enum {
RED = 1,
BLUE,
GREEN,
YELLOW,
WHITE
} printcolor_t;
typedef enum {
F_IN_OUT,
CREDITS,
SCANOUT
} printeffect_t;
typedef enum {
WIN_MSG,
CRITICAL,
INFO,
LEADER_HIT,
MISC_SHIT,
CHASECAM,
CHASECAM_TARGET,
NOTIFY,
} effectchannel_t;
extern void EffectPrint( CBasePlayer *pPlayer, int color, int effect, int channel, char *text );

111
hlsdk/dmc/dlls/vector.h Normal file
View File

@ -0,0 +1,111 @@
/***
*
* 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.
*
****/
#ifndef VECTOR_H
#define VECTOR_H
//=========================================================
// 2DVector - used for many pathfinding and many other
// operations that are treated as planar rather than 3d.
//=========================================================
class Vector2D
{
public:
inline Vector2D(void): x(0.0), y(0.0) { }
inline Vector2D(float X, float Y): x(0.0), y(0.0) { x = X; y = Y; }
inline Vector2D operator+(const Vector2D& v) const { return Vector2D(x+v.x, y+v.y); }
inline Vector2D operator-(const Vector2D& v) const { return Vector2D(x-v.x, y-v.y); }
inline Vector2D operator*(float fl) const { return Vector2D(x*fl, y*fl); }
inline Vector2D operator/(float fl) const { return Vector2D(x/fl, y/fl); }
inline float Length(void) const { return sqrt(x*x + y*y ); }
inline Vector2D Normalize ( void ) const
{
float flLen = Length();
if ( flLen == 0 )
{
return Vector2D( 0, 0 );
}
else
{
flLen = 1 / flLen;
return Vector2D( x * flLen, y * flLen );
}
}
vec_t x, y;
};
inline float DotProduct(const Vector2D& a, const Vector2D& b) { return( a.x*b.x + a.y*b.y ); }
inline Vector2D operator*(float fl, const Vector2D& v) { return v * fl; }
//=========================================================
// 3D Vector
//=========================================================
class Vector // same data-layout as engine's vec3_t,
{ // which is a vec_t[3]
public:
// Construction/destruction
inline Vector(void): x(0.0), y(0.0), z(0.0) { }
inline Vector(float X, float Y, float Z): x(0.0), y(0.0), z(0.0) { x = X; y = Y; z = Z; }
//inline Vector(double X, double Y, double Z) { x = (float)X; y = (float)Y; z = (float)Z; }
//inline Vector(int X, int Y, int Z) { x = (float)X; y = (float)Y; z = (float)Z; }
inline Vector(const Vector& v): x(0.0), y(0.0), z(0.0) { x = v.x; y = v.y; z = v.z; }
inline Vector(float rgfl[3]): x(0.0), y(0.0), z(0.0) { x = rgfl[0]; y = rgfl[1]; z = rgfl[2]; }
// Operators
inline Vector operator-(void) const { return Vector(-x,-y,-z); }
inline int operator==(const Vector& v) const { return x==v.x && y==v.y && z==v.z; }
inline int operator!=(const Vector& v) const { return !(*this==v); }
inline Vector operator+(const Vector& v) const { return Vector(x+v.x, y+v.y, z+v.z); }
inline Vector operator-(const Vector& v) const { return Vector(x-v.x, y-v.y, z-v.z); }
inline Vector operator*(float fl) const { return Vector(x*fl, y*fl, z*fl); }
inline Vector operator/(float fl) const { return Vector(x/fl, y/fl, z/fl); }
// Methods
inline void CopyToArray(float* rgfl) const { rgfl[0] = x, rgfl[1] = y, rgfl[2] = z; }
inline float Length(void) const { return sqrt(x*x + y*y + z*z); }
operator float *() { return &x; } // Vectors will now automatically convert to float * when needed
operator const float *() const { return &x; } // Vectors will now automatically convert to float * when needed
inline Vector Normalize(void) const
{
float flLen = Length();
if (flLen == 0) return Vector(0,0,1); // ????
flLen = 1 / flLen;
return Vector(x * flLen, y * flLen, z * flLen);
}
inline Vector2D Make2D ( void ) const
{
Vector2D Vec2;
Vec2.x = x;
Vec2.y = y;
return Vec2;
}
inline float Length2D(void) const { return sqrt(x*x + y*y); }
// Members
vec_t x, y, z;
};
inline Vector operator*(float fl, const Vector& v) { return v * fl; }
inline float DotProduct(const Vector& a, const Vector& b) { return(a.x*b.x+a.y*b.y+a.z*b.z); }
inline Vector CrossProduct(const Vector& a, const Vector& b) { return Vector( a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x ); }
#endif

1417
hlsdk/dmc/dlls/weapons.cpp Normal file

File diff suppressed because it is too large Load Diff

492
hlsdk/dmc/dlls/weapons.h Normal file
View File

@ -0,0 +1,492 @@
/***
*
* 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.
*
****/
#ifndef WEAPONS_H
#define WEAPONS_H
class CBasePlayer;
extern int gmsgWeapPickup;
// Contact Grenade / Timed grenade / Satchel Charge
class CGrenade : public CBaseMonster
{
public:
void Spawn( void );
typedef enum { SATCHEL_DETONATE = 0, SATCHEL_RELEASE } SATCHELCODE;
static CGrenade *ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time );
static CGrenade *ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity );
static CGrenade *ShootSatchelCharge( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity );
static void UseSatchelCharges( entvars_t *pevOwner, SATCHELCODE code );
void Explode( Vector vecSrc, Vector vecAim );
void Explode( TraceResult *pTrace, int bitsDamageType );
void EXPORT Smoke( void );
void EXPORT BounceTouch( CBaseEntity *pOther );
void EXPORT SlideTouch( CBaseEntity *pOther );
void EXPORT ExplodeTouch( CBaseEntity *pOther );
void EXPORT DangerSoundThink( void );
void EXPORT PreDetonate( void );
void EXPORT Detonate( void );
void EXPORT DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT TumbleThink( void );
virtual void BounceSound( void );
virtual int BloodColor( void ) { return DONT_BLEED; }
virtual void Killed( entvars_t *pevAttacker, int iGib );
BOOL m_fRegisteredSound;// whether or not this grenade has issued its DANGER sound to the world sound list yet.
};
// constant items
#define ITEM_HEALTHKIT 1
#define ITEM_ANTIDOTE 2
#define ITEM_SECURITY 3
#define ITEM_BATTERY 4
#define WEAPON_NONE 0
#define WEAPON_CROWBAR 1
#define WEAPON_GLOCK 2
#define WEAPON_PYTHON 3
#define WEAPON_MP5 4
#define WEAPON_CHAINGUN 5
#define WEAPON_CROSSBOW 6
#define WEAPON_SHOTGUN 7
#define WEAPON_RPG 8
#define WEAPON_GAUSS 9
#define WEAPON_EGON 10
#define WEAPON_HORNETGUN 11
#define WEAPON_HANDGRENADE 12
#define WEAPON_TRIPMINE 13
#define WEAPON_SATCHEL 14
#define WEAPON_SNARK 15
#define WEAPON_ALLWEAPONS (~(1<<WEAPON_SUIT))
#define WEAPON_SUIT 31 // ?????
#define MAX_WEAPONS 257
#define MAX_NORMAL_BATTERY 100
// weapon weight factors (for auto-switching) (-1 = noswitch)
#define CROWBAR_WEIGHT 0
#define GLOCK_WEIGHT 10
#define PYTHON_WEIGHT 15
#define MP5_WEIGHT 15
#define SHOTGUN_WEIGHT 15
#define CROSSBOW_WEIGHT 10
#define RPG_WEIGHT 20
#define GAUSS_WEIGHT 20
#define EGON_WEIGHT 20
#define HORNETGUN_WEIGHT 10
#define HANDGRENADE_WEIGHT 5
#define SNARK_WEIGHT 5
#define SATCHEL_WEIGHT -10
#define TRIPMINE_WEIGHT -10
// weapon clip/carry ammo capacities
#define URANIUM_MAX_CARRY 100
#define _9MM_MAX_CARRY 250
#define _357_MAX_CARRY 36
#define BUCKSHOT_MAX_CARRY 125
#define BOLT_MAX_CARRY 50
#define ROCKET_MAX_CARRY 5
#define HANDGRENADE_MAX_CARRY 10
#define SATCHEL_MAX_CARRY 5
#define TRIPMINE_MAX_CARRY 5
#define SNARK_MAX_CARRY 15
#define HORNET_MAX_CARRY 8
#define M203_GRENADE_MAX_CARRY 10
// the maximum amount of ammo each weapon's clip can hold
#define WEAPON_NOCLIP -1
//#define CROWBAR_MAX_CLIP WEAPON_NOCLIP
#define GLOCK_MAX_CLIP 17
#define PYTHON_MAX_CLIP 6
#define MP5_MAX_CLIP 50
#define MP5_DEFAULT_AMMO 25
#define SHOTGUN_MAX_CLIP 8
#define CROSSBOW_MAX_CLIP 5
#define RPG_MAX_CLIP 1
#define GAUSS_MAX_CLIP WEAPON_NOCLIP
#define EGON_MAX_CLIP WEAPON_NOCLIP
#define HORNETGUN_MAX_CLIP WEAPON_NOCLIP
#define HANDGRENADE_MAX_CLIP WEAPON_NOCLIP
#define SATCHEL_MAX_CLIP WEAPON_NOCLIP
#define TRIPMINE_MAX_CLIP WEAPON_NOCLIP
#define SNARK_MAX_CLIP WEAPON_NOCLIP
// the default amount of ammo that comes with each gun when it spawns
#define GLOCK_DEFAULT_GIVE 17
#define PYTHON_DEFAULT_GIVE 6
#define MP5_DEFAULT_GIVE 25
#define MP5_DEFAULT_AMMO 25
#define MP5_M203_DEFAULT_GIVE 0
#define SHOTGUN_DEFAULT_GIVE 12
#define CROSSBOW_DEFAULT_GIVE 5
#define RPG_DEFAULT_GIVE 1
#define GAUSS_DEFAULT_GIVE 20
#define EGON_DEFAULT_GIVE 20
#define HANDGRENADE_DEFAULT_GIVE 5
#define SATCHEL_DEFAULT_GIVE 1
#define TRIPMINE_DEFAULT_GIVE 1
#define SNARK_DEFAULT_GIVE 5
#define HIVEHAND_DEFAULT_GIVE 8
// The amount of ammo given to a player by an ammo item.
#define AMMO_URANIUMBOX_GIVE 20
#define AMMO_GLOCKCLIP_GIVE GLOCK_MAX_CLIP
#define AMMO_357BOX_GIVE PYTHON_MAX_CLIP
#define AMMO_MP5CLIP_GIVE MP5_MAX_CLIP
#define AMMO_CHAINBOX_GIVE 200
#define AMMO_M203BOX_GIVE 2
#define AMMO_BUCKSHOTBOX_GIVE 12
#define AMMO_CROSSBOWCLIP_GIVE CROSSBOW_MAX_CLIP
#define AMMO_RPGCLIP_GIVE RPG_MAX_CLIP
#define AMMO_URANIUMBOX_GIVE 20
#define AMMO_SNARKBOX_GIVE 5
// bullet types
typedef enum
{
BULLET_NONE = 0,
BULLET_PLAYER_9MM, // glock
BULLET_PLAYER_MP5, // mp5
BULLET_PLAYER_357, // python
BULLET_PLAYER_BUCKSHOT, // shotgun
BULLET_PLAYER_CROWBAR, // crowbar swipe
BULLET_MONSTER_9MM,
BULLET_MONSTER_MP5,
BULLET_MONSTER_12MM,
} Bullet;
#define ITEM_FLAG_SELECTONEMPTY 1
#define ITEM_FLAG_NOAUTORELOAD 2
#define ITEM_FLAG_NOAUTOSWITCHEMPTY 4
#define ITEM_FLAG_LIMITINWORLD 8
#define ITEM_FLAG_EXHAUSTIBLE 16 // A player can totally exhaust their ammo supply and lose this weapon
#define WEAPON_IS_ONTARGET 0x40
typedef struct
{
int iSlot;
int iPosition;
const char *pszAmmo1; // ammo 1 type
int iMaxAmmo1; // max ammo 1
const char *pszAmmo2; // ammo 2 type
int iMaxAmmo2; // max ammo 2
const char *pszName;
int iMaxClip;
int iId;
int iFlags;
int iWeight;// this value used to determine this weapon's importance in autoselection.
} ItemInfo;
typedef struct
{
const char *pszName;
int iId;
} AmmoInfo;
// Items that the player has in their inventory that they can use
class CBasePlayerItem : public CBaseAnimating
{
public:
virtual void SetObjectCollisionBox( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
virtual int AddToPlayer( CBasePlayer *pPlayer ); // return TRUE if the item you want the item added to the player inventory
virtual int AddDuplicate( CBasePlayerItem *pItem ) { return FALSE; } // return TRUE if you want your duplicate removed from world
void EXPORT DestroyItem( void );
void EXPORT DefaultTouch( CBaseEntity *pOther ); // default weapon touch
void EXPORT FallThink ( void );// when an item is first spawned, this think is run to determine when the object has hit the ground.
void EXPORT Materialize( void );// make a weapon visible and tangible
void EXPORT AttemptToMaterialize( void ); // the weapon desires to become visible and tangible, if the game rules allow for it
CBaseEntity* Respawn ( void );// copy a weapon
void FallInit( void );
void CheckRespawn( void );
virtual int GetItemInfo(ItemInfo *p) { return 0; }; // returns 0 if struct not filled out
virtual BOOL CanDeploy( void ) { return TRUE; };
virtual BOOL Deploy( ) // returns is deploy was successful
{ return TRUE; };
virtual BOOL CanHolster( void ) { return TRUE; };// can this weapon be put away right now?
virtual void Holster( int skiplocal = 0 );
virtual void UpdateItemInfo( void ) { return; };
virtual void ItemPreFrame( void ) { return; } // called each frame by the player PreThink
virtual void ItemPostFrame( void ) { return; } // called each frame by the player PostThink
virtual void Drop( void );
virtual void Kill( void );
virtual void AttachToPlayer ( CBasePlayer *pPlayer );
virtual int PrimaryAmmoIndex() { return -1; };
virtual int SecondaryAmmoIndex() { return -1; };
virtual int UpdateClientData( CBasePlayer *pPlayer ) { return 0; }
virtual CBasePlayerItem *GetWeaponPtr( void ) { return NULL; };
static ItemInfo ItemInfoArray[ MAX_WEAPONS ];
static AmmoInfo AmmoInfoArray[ MAX_AMMO_SLOTS ];
CBasePlayer *m_pPlayer;
CBasePlayerItem *m_pNext;
int m_iId; // WEAPON_???
virtual int iItemSlot( void ) { return 0; } // return 0 to MAX_ITEMS_SLOTS, used in hud
int iItemPosition( void ) { return ItemInfoArray[ m_iId ].iPosition; }
const char *pszAmmo1( void ) { return ItemInfoArray[ m_iId ].pszAmmo1; }
int iMaxAmmo1( void ) { return ItemInfoArray[ m_iId ].iMaxAmmo1; }
const char *pszAmmo2( void ) { return ItemInfoArray[ m_iId ].pszAmmo2; }
int iMaxAmmo2( void ) { return ItemInfoArray[ m_iId ].iMaxAmmo2; }
const char *pszName( void ) { return ItemInfoArray[ m_iId ].pszName; }
int iMaxClip( void ) { return ItemInfoArray[ m_iId ].iMaxClip; }
int iWeight( void ) { return ItemInfoArray[ m_iId ].iWeight; }
int iFlags( void ) { return ItemInfoArray[ m_iId ].iFlags; }
// int m_iIdPrimary; // Unique Id for primary ammo
// int m_iIdSecondary; // Unique Id for secondary ammo
};
// inventory items that
class CBasePlayerWeapon : public CBasePlayerItem
{
public:
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
// generic weapon versions of CBasePlayerItem calls
virtual int AddToPlayer( CBasePlayer *pPlayer );
virtual int AddDuplicate( CBasePlayerItem *pItem );
virtual int ExtractAmmo( CBasePlayerWeapon *pWeapon ); //{ return TRUE; }; // Return TRUE if you can add ammo to yourself when picked up
virtual int ExtractClipAmmo( CBasePlayerWeapon *pWeapon );// { return TRUE; }; // Return TRUE if you can add ammo to yourself when picked up
virtual int AddWeapon( void ) { ExtractAmmo( this ); return TRUE; }; // Return TRUE if you want to add yourself to the player
// generic "shared" ammo handlers
BOOL AddPrimaryAmmo( int iCount, char *szName, int iMaxClip, int iMaxCarry );
BOOL AddSecondaryAmmo( int iCount, char *szName, int iMaxCarry );
virtual void UpdateItemInfo( void ) {}; // updates HUD state
int m_iPlayEmptySound;
int m_fFireOnEmpty; // True when the gun is empty and the player is still holding down the
// attack key(s)
virtual BOOL PlayEmptySound( void );
virtual void ResetEmptySound( void );
virtual void SendWeaponAnim( int iAnim, int skiplocal = 0 ); // skiplocal is 1 if client is predicting weapon animations
virtual BOOL CanDeploy( void );
virtual BOOL IsUseable( void );
BOOL DefaultDeploy( char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal = 0 );
int DefaultReload( int iClipSize, int iAnim, float fDelay );
virtual void ItemPostFrame( void ); // called each frame by the player PostThink
// called by CBasePlayerWeapons ItemPostFrame()
virtual void PrimaryAttack( void ) { return; } // do "+ATTACK"
virtual void SecondaryAttack( void ) { return; } // do "+ATTACK2"
virtual void Reload( void ) { return; } // do "+RELOAD"
virtual void WeaponIdle( void ) { return; } // called when no buttons pressed
virtual int UpdateClientData( CBasePlayer *pPlayer ); // sends hud info to client dll, if things have changed
virtual void RetireWeapon( void );
virtual BOOL ShouldWeaponIdle( void ) {return FALSE; };
virtual void Holster( int skiplocal = 0 );
virtual BOOL UseDecrement( void ) { return TRUE; };
int PrimaryAmmoIndex();
int SecondaryAmmoIndex();
void PrintState( void );
virtual CBasePlayerItem *GetWeaponPtr( void ) { return (CBasePlayerItem *)this; };
float m_flNextPrimaryAttack; // soonest time ItemPostFrame will call PrimaryAttack
float m_flNextSecondaryAttack; // soonest time ItemPostFrame will call SecondaryAttack
float m_flTimeWeaponIdle; // soonest time ItemPostFrame will call WeaponIdle
int m_iPrimaryAmmoType; // "primary" ammo index into players m_rgAmmo[]
int m_iSecondaryAmmoType; // "secondary" ammo index into players m_rgAmmo[]
int m_iClip; // number of shots left in the primary weapon clip, -1 it not used
int m_iClientClip; // the last version of m_iClip sent to hud dll
int m_iClientWeaponState; // the last version of the weapon state sent to hud dll (is current weapon, is on target)
int m_fInReload; // Are we in the middle of a reload;
int m_iDefaultAmmo;// how much ammo you get when you pick up this weapon as placed by a level designer.
bool m_bPlayedIdleAnim;
};
class CBasePlayerAmmo : public CBaseEntity
{
public:
virtual void Spawn( void );
void EXPORT DefaultTouch( CBaseEntity *pOther ); // default weapon touch
virtual BOOL AddAmmo( CBaseEntity *pOther ) { return TRUE; };
CBaseEntity* Respawn( void );
void EXPORT Materialize( void );
};
extern DLL_GLOBAL short g_sModelIndexLaser;// holds the index for the laser beam
extern DLL_GLOBAL const char *g_pModelNameLaser;
extern DLL_GLOBAL short g_sModelIndexLaserDot;// holds the index for the laser beam dot
extern DLL_GLOBAL short g_sModelIndexFireball;// holds the index for the fireball
extern DLL_GLOBAL short g_sModelIndexSmoke;// holds the index for the smoke cloud
extern DLL_GLOBAL short g_sModelIndexWExplosion;// holds the index for the underwater explosion
extern DLL_GLOBAL short g_sModelIndexBubbles;// holds the index for the bubbles model
extern DLL_GLOBAL short g_sModelIndexBloodDrop;// holds the sprite index for blood drops
extern DLL_GLOBAL short g_sModelIndexBloodSpray;// holds the sprite index for blood spray (bigger)
extern void ClearMultiDamage(void);
extern void ApplyMultiDamage(entvars_t* pevInflictor, entvars_t* pevAttacker );
extern void AddMultiDamage( entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType);
extern void DecalGunshot( TraceResult *pTrace, int iBulletType );
extern void SpawnBlood(Vector vecSpot, int bloodColor, float flDamage);
extern int DamageDecal( CBaseEntity *pEntity, int bitsDamageType );
extern void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType );
typedef struct
{
CBaseEntity *pEntity;
float amount;
int type;
} MULTIDAMAGE;
extern MULTIDAMAGE gMultiDamage;
#define LOUD_GUN_VOLUME 1000
#define NORMAL_GUN_VOLUME 600
#define QUIET_GUN_VOLUME 200
#define BRIGHT_GUN_FLASH 512
#define NORMAL_GUN_FLASH 256
#define DIM_GUN_FLASH 128
#define BIG_EXPLOSION_VOLUME 2048
#define NORMAL_EXPLOSION_VOLUME 1024
#define SMALL_EXPLOSION_VOLUME 512
#define WEAPON_ACTIVITY_VOLUME 64
#define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 )
#define VECTOR_CONE_2DEGREES Vector( 0.01745, 0.01745, 0.01745 )
#define VECTOR_CONE_3DEGREES Vector( 0.02618, 0.02618, 0.02618 )
#define VECTOR_CONE_4DEGREES Vector( 0.03490, 0.03490, 0.03490 )
#define VECTOR_CONE_5DEGREES Vector( 0.04362, 0.04362, 0.04362 )
#define VECTOR_CONE_6DEGREES Vector( 0.05234, 0.05234, 0.05234 )
#define VECTOR_CONE_7DEGREES Vector( 0.06105, 0.06105, 0.06105 )
#define VECTOR_CONE_8DEGREES Vector( 0.06976, 0.06976, 0.06976 )
#define VECTOR_CONE_9DEGREES Vector( 0.07846, 0.07846, 0.07846 )
#define VECTOR_CONE_10DEGREES Vector( 0.08716, 0.08716, 0.08716 )
#define VECTOR_CONE_15DEGREES Vector( 0.13053, 0.13053, 0.13053 )
#define VECTOR_CONE_20DEGREES Vector( 0.17365, 0.17365, 0.17365 )
//=========================================================
// CWeaponBox - a single entity that can store weapons
// and ammo.
//=========================================================
class CWeaponBox : public CBaseEntity
{
void Precache( void );
void Spawn( void );
void Touch( CBaseEntity *pOther );
void KeyValue( KeyValueData *pkvd );
BOOL IsEmpty( void );
int GiveAmmo( int iCount, char *szName, int iMax, int *pIndex = NULL );
void SetObjectCollisionBox( void );
public:
void EXPORT Kill ( void );
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
BOOL HasWeapon( CBasePlayerItem *pCheckItem );
BOOL PackWeapon( CBasePlayerItem *pWeapon );
BOOL PackAmmo( int iszName, int iCount );
CBasePlayerItem *m_rgpPlayerItems[MAX_ITEM_TYPES];// one slot for each
int m_rgiszAmmo[MAX_AMMO_SLOTS];// ammo names
int m_rgAmmo[MAX_AMMO_SLOTS];// ammo quantities
int m_cAmmoTypes;// how many ammo types packed into this box (if packed by a level designer)
};
// QUAKECLASSIC
void Q_RadiusDamage( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, CBaseEntity *pIgnore );
class CQuakeRocket : public CBaseEntity
{
public:
void Spawn( void );
void Precache( void );
void Explode( void );
// Rocket funcs
static CQuakeRocket *CreateRocket( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner );
void EXPORT RocketTouch( CBaseEntity *pOther );
// Grenade funcs
static CQuakeRocket *CreateGrenade( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner );
void EXPORT GrenadeTouch( CBaseEntity *pOther );
void EXPORT GrenadeExplode( void );
int m_iTrail;
float m_flAttackFinished;
};
class CQuakeNail : public CBaseEntity
{
public:
void Spawn( void );
static CQuakeNail *CreateNail( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner );
static CQuakeNail *CreateSuperNail( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner );
void EXPORT NailTouch( CBaseEntity *pOther );
};
extern char gszQ_DeathType[128];
extern DLL_GLOBAL short g_sModelIndexNail;
#endif // WEAPONS_H

745
hlsdk/dmc/dlls/world.cpp Normal file
View File

@ -0,0 +1,745 @@
/***
*
* 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.
*
****/
/*
===== world.cpp ========================================================
precaches and defs for entities and other data that must always be available.
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "nodes.h"
#include "client.h"
#include "decals.h"
#include "skill.h"
#include "effects.h"
#include "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "teamplay_gamerules.h"
extern CGraph WorldGraph;
extern CBaseEntity *g_pLastSpawn;
DLL_GLOBAL edict_t *g_pBodyQueueHead;
CGlobalState gGlobalState;
extern DLL_GLOBAL int gDisplayTitle;
extern void W_Precache(void);
extern void QuakeClassicPrecache( void );
//
// This must match the list in util.h
//
DLL_DECALLIST gDecals[] = {
{ "{shot1", 0 }, // DECAL_GUNSHOT1
{ "{shot2", 0 }, // DECAL_GUNSHOT2
{ "{shot3",0 }, // DECAL_GUNSHOT3
{ "{shot4", 0 }, // DECAL_GUNSHOT4
{ "{shot5", 0 }, // DECAL_GUNSHOT5
{ "{lambda01", 0 }, // DECAL_LAMBDA1
{ "{lambda02", 0 }, // DECAL_LAMBDA2
{ "{lambda03", 0 }, // DECAL_LAMBDA3
{ "{lambda04", 0 }, // DECAL_LAMBDA4
{ "{lambda05", 0 }, // DECAL_LAMBDA5
{ "{lambda06", 0 }, // DECAL_LAMBDA6
{ "{scorch1", 0 }, // DECAL_SCORCH1
{ "{scorch2", 0 }, // DECAL_SCORCH2
{ "{blood1", 0 }, // DECAL_BLOOD1
{ "{blood2", 0 }, // DECAL_BLOOD2
{ "{blood3", 0 }, // DECAL_BLOOD3
{ "{blood4", 0 }, // DECAL_BLOOD4
{ "{blood5", 0 }, // DECAL_BLOOD5
{ "{blood6", 0 }, // DECAL_BLOOD6
{ "{yblood1", 0 }, // DECAL_YBLOOD1
{ "{yblood2", 0 }, // DECAL_YBLOOD2
{ "{yblood3", 0 }, // DECAL_YBLOOD3
{ "{yblood4", 0 }, // DECAL_YBLOOD4
{ "{yblood5", 0 }, // DECAL_YBLOOD5
{ "{yblood6", 0 }, // DECAL_YBLOOD6
{ "{break1", 0 }, // DECAL_GLASSBREAK1
{ "{break2", 0 }, // DECAL_GLASSBREAK2
{ "{break3", 0 }, // DECAL_GLASSBREAK3
{ "{bigshot1", 0 }, // DECAL_BIGSHOT1
{ "{bigshot2", 0 }, // DECAL_BIGSHOT2
{ "{bigshot3", 0 }, // DECAL_BIGSHOT3
{ "{bigshot4", 0 }, // DECAL_BIGSHOT4
{ "{bigshot5", 0 }, // DECAL_BIGSHOT5
{ "{spit1", 0 }, // DECAL_SPIT1
{ "{spit2", 0 }, // DECAL_SPIT2
{ "{bproof1", 0 }, // DECAL_BPROOF1
{ "{gargstomp", 0 }, // DECAL_GARGSTOMP1, // Gargantua stomp crack
{ "{smscorch1", 0 }, // DECAL_SMALLSCORCH1, // Small scorch mark
{ "{smscorch2", 0 }, // DECAL_SMALLSCORCH2, // Small scorch mark
{ "{smscorch3", 0 }, // DECAL_SMALLSCORCH3, // Small scorch mark
{ "{mommablob", 0 }, // DECAL_MOMMABIRTH // BM Birth spray
{ "{mommablob", 0 }, // DECAL_MOMMASPLAT // BM Mortar spray?? need decal
};
/*
==============================================================================
BODY QUE
==============================================================================
*/
#define SF_DECAL_NOTINDEATHMATCH 2048
class CDecal : public CBaseEntity
{
public:
void Spawn( void );
void KeyValue( KeyValueData *pkvd );
void EXPORT StaticDecal( void );
void EXPORT TriggerDecal( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
};
LINK_ENTITY_TO_CLASS( infodecal, CDecal );
// UNDONE: These won't get sent to joining players in multi-player
void CDecal :: Spawn( void )
{
if ( pev->skin < 0 || (gpGlobals->deathmatch && FBitSet( pev->spawnflags, SF_DECAL_NOTINDEATHMATCH )) )
{
REMOVE_ENTITY(ENT(pev));
return;
}
if ( FStringNull ( pev->targetname ) )
{
SetThink( &CDecal::StaticDecal );
// if there's no targetname, the decal will spray itself on as soon as the world is done spawning.
pev->nextthink = gpGlobals->time;
}
else
{
// if there IS a targetname, the decal sprays itself on when it is triggered.
SetThink ( &CBaseEntity::SUB_DoNothing );
SetUse(&CDecal::TriggerDecal);
}
}
void CDecal :: TriggerDecal ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
// this is set up as a USE function for infodecals that have targetnames, so that the
// decal doesn't get applied until it is fired. (usually by a scripted sequence)
TraceResult trace;
int entityIndex;
UTIL_TraceLine( pev->origin - Vector(5,5,5), pev->origin + Vector(5,5,5), ignore_monsters, ENT(pev), &trace );
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY);
WRITE_BYTE( TE_BSPDECAL );
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_SHORT( (int)pev->skin );
entityIndex = (short)ENTINDEX(trace.pHit);
WRITE_SHORT( entityIndex );
if ( entityIndex )
WRITE_SHORT( (int)VARS(trace.pHit)->modelindex );
MESSAGE_END();
SetThink( &CBaseEntity::SUB_Remove );
pev->nextthink = gpGlobals->time + 0.1;
}
void CDecal :: StaticDecal( void )
{
TraceResult trace;
int entityIndex, modelIndex;
UTIL_TraceLine( pev->origin - Vector(5,5,5), pev->origin + Vector(5,5,5), ignore_monsters, ENT(pev), &trace );
entityIndex = (short)ENTINDEX(trace.pHit);
if ( entityIndex )
modelIndex = (int)VARS(trace.pHit)->modelindex;
else
modelIndex = 0;
g_engfuncs.pfnStaticDecal( pev->origin, (int)pev->skin, entityIndex, modelIndex );
SUB_Remove();
}
void CDecal :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "texture"))
{
pev->skin = DECAL_INDEX( pkvd->szValue );
// Found
if ( pev->skin >= 0 )
return;
ALERT( at_console, "Can't find decal %s\n", pkvd->szValue );
}
else
CBaseEntity::KeyValue( pkvd );
}
// Body queue class here.... It's really just CBaseEntity
class CCorpse : public CBaseEntity
{
virtual int ObjectCaps( void ) { return FCAP_DONT_SAVE; }
};
LINK_ENTITY_TO_CLASS( bodyque, CCorpse );
static void InitBodyQue(void)
{
string_t istrClassname = MAKE_STRING("bodyque");
g_pBodyQueueHead = CREATE_NAMED_ENTITY( istrClassname );
entvars_t *pev = VARS(g_pBodyQueueHead);
// Reserve 3 more slots for dead bodies
for ( int i = 0; i < 3; i++ )
{
pev->owner = CREATE_NAMED_ENTITY( istrClassname );
pev = VARS(pev->owner);
}
pev->owner = g_pBodyQueueHead;
}
//
// make a body que entry for the given ent so the ent can be respawned elsewhere
//
// GLOBALS ASSUMED SET: g_eoBodyQueueHead
//
void CopyToBodyQue(entvars_t *pev)
{
if (pev->effects & EF_NODRAW)
return;
entvars_t *pevHead = VARS(g_pBodyQueueHead);
pevHead->angles = pev->angles;
pevHead->model = pev->model;
pevHead->modelindex = pev->modelindex;
pevHead->frame = pev->frame;
pevHead->colormap = pev->colormap;
pevHead->movetype = MOVETYPE_TOSS;
pevHead->velocity = pev->velocity;
pevHead->flags = 0;
pevHead->deadflag = pev->deadflag;
pevHead->renderfx = kRenderFxDeadPlayer;
pevHead->renderamt = ENTINDEX( ENT( pev ) );
pevHead->effects = pev->effects | EF_NOINTERP;
//pevHead->goalstarttime = pev->goalstarttime;
//pevHead->goalframe = pev->goalframe;
//pevHead->goalendtime = pev->goalendtime ;
pevHead->sequence = pev->sequence;
pevHead->animtime = pev->animtime;
UTIL_SetOrigin(pevHead, pev->origin);
UTIL_SetSize(pevHead, pev->mins, pev->maxs);
g_pBodyQueueHead = pevHead->owner;
}
CGlobalState::CGlobalState( void )
{
Reset();
}
void CGlobalState::Reset( void )
{
m_pList = NULL;
m_listCount = 0;
}
globalentity_t *CGlobalState :: Find( string_t globalname )
{
if ( !globalname )
return NULL;
globalentity_t *pTest;
const char *pEntityName = STRING(globalname);
pTest = m_pList;
while ( pTest )
{
if ( FStrEq( pEntityName, pTest->name ) )
break;
pTest = pTest->pNext;
}
return pTest;
}
// This is available all the time now on impulse 104, remove later
//#ifdef _DEBUG
void CGlobalState :: DumpGlobals( void )
{
static char *estates[] = { "Off", "On", "Dead" };
globalentity_t *pTest;
ALERT( at_console, "-- Globals --\n" );
pTest = m_pList;
while ( pTest )
{
ALERT( at_console, "%s: %s (%s)\n", pTest->name, pTest->levelName, estates[pTest->state] );
pTest = pTest->pNext;
}
}
//#endif
void CGlobalState :: EntityAdd( string_t globalname, string_t mapName, GLOBALESTATE state )
{
ASSERT( !Find(globalname) );
globalentity_t *pNewEntity = (globalentity_t *)calloc( sizeof( globalentity_t ), 1 );
ASSERT( pNewEntity != NULL );
pNewEntity->pNext = m_pList;
m_pList = pNewEntity;
strcpy( pNewEntity->name, STRING( globalname ) );
strcpy( pNewEntity->levelName, STRING(mapName) );
pNewEntity->state = state;
m_listCount++;
}
void CGlobalState :: EntitySetState( string_t globalname, GLOBALESTATE state )
{
globalentity_t *pEnt = Find( globalname );
if ( pEnt )
pEnt->state = state;
}
const globalentity_t *CGlobalState :: EntityFromTable( string_t globalname )
{
globalentity_t *pEnt = Find( globalname );
return pEnt;
}
GLOBALESTATE CGlobalState :: EntityGetState( string_t globalname )
{
globalentity_t *pEnt = Find( globalname );
if ( pEnt )
return pEnt->state;
return GLOBAL_OFF;
}
// Global Savedata for Delay
TYPEDESCRIPTION CGlobalState::m_SaveData[] =
{
DEFINE_FIELD( CGlobalState, m_listCount, FIELD_INTEGER ),
};
// Global Savedata for Delay
TYPEDESCRIPTION gGlobalEntitySaveData[] =
{
DEFINE_ARRAY( globalentity_t, name, FIELD_CHARACTER, 64 ),
DEFINE_ARRAY( globalentity_t, levelName, FIELD_CHARACTER, 32 ),
DEFINE_FIELD( globalentity_t, state, FIELD_INTEGER ),
};
int CGlobalState::Save( CSave &save )
{
int i;
globalentity_t *pEntity;
if ( !save.WriteFields( "GLOBAL", this, m_SaveData, ARRAYSIZE(m_SaveData) ) )
return 0;
pEntity = m_pList;
for ( i = 0; i < m_listCount && pEntity; i++ )
{
if ( !save.WriteFields( "GENT", pEntity, gGlobalEntitySaveData, ARRAYSIZE(gGlobalEntitySaveData) ) )
return 0;
pEntity = pEntity->pNext;
}
return 1;
}
int CGlobalState::Restore( CRestore &restore )
{
int i, listCount;
globalentity_t tmpEntity;
ClearStates();
if ( !restore.ReadFields( "GLOBAL", this, m_SaveData, ARRAYSIZE(m_SaveData) ) )
return 0;
listCount = m_listCount; // Get new list count
m_listCount = 0; // Clear loaded data
for ( i = 0; i < listCount; i++ )
{
if ( !restore.ReadFields( "GENT", &tmpEntity, gGlobalEntitySaveData, ARRAYSIZE(gGlobalEntitySaveData) ) )
return 0;
EntityAdd( MAKE_STRING(tmpEntity.name), MAKE_STRING(tmpEntity.levelName), tmpEntity.state );
}
return 1;
}
void CGlobalState::EntityUpdate( string_t globalname, string_t mapname )
{
globalentity_t *pEnt = Find( globalname );
if ( pEnt )
strcpy( pEnt->levelName, STRING(mapname) );
}
void CGlobalState::ClearStates( void )
{
globalentity_t *pFree = m_pList;
while ( pFree )
{
globalentity_t *pNext = pFree->pNext;
free( pFree );
pFree = pNext;
}
Reset();
}
void SaveGlobalState( SAVERESTOREDATA *pSaveData )
{
CSave saveHelper( pSaveData );
gGlobalState.Save( saveHelper );
}
void RestoreGlobalState( SAVERESTOREDATA *pSaveData )
{
CRestore restoreHelper( pSaveData );
gGlobalState.Restore( restoreHelper );
}
void ResetGlobalState( void )
{
gGlobalState.ClearStates();
gInitHUD = TRUE; // Init the HUD on a new game / load game
}
// moved CWorld class definition to cbase.h
//=======================
// CWorld
//
// This spawns first when each level begins.
//=======================
LINK_ENTITY_TO_CLASS( worldspawn, CWorld );
#define SF_WORLD_DARK 0x0001 // Fade from black at startup
#define SF_WORLD_TITLE 0x0002 // Display game title at startup
#define SF_WORLD_FORCETEAM 0x0004 // Force teams
extern DLL_GLOBAL BOOL g_fGameOver;
float g_flWeaponCheat;
void CWorld :: Spawn( void )
{
g_fGameOver = FALSE;
Precache( );
g_flWeaponCheat = CVAR_GET_FLOAT( "sv_cheats" ); // Is the impulse 101 command allowed?
}
void CWorld :: Precache( void )
{
g_pLastSpawn = NULL;
#if 1
CVAR_SET_STRING("sv_gravity", "800"); // 67ft/sec
CVAR_SET_STRING("sv_stepsize", "18");
#else
CVAR_SET_STRING("sv_gravity", "384"); // 32ft/sec
CVAR_SET_STRING("sv_stepsize", "24");
#endif
CVAR_SET_STRING("room_type", "0");// clear DSP
// QUAKECLASSIC
// Set various physics cvars to Quake's values
CVAR_SET_STRING("sv_friction", "4");
CVAR_SET_STRING("sv_maxspeed", "400");
CVAR_SET_STRING("sv_airaccelerate", "0.7");
// Set up game rules
if (g_pGameRules)
{
delete g_pGameRules;
}
g_pGameRules = InstallGameRules( );
//!!!UNDONE why is there so much Spawn code in the Precache function? I'll just keep it here
InitBodyQue();
// init sentence group playback stuff from sentences.txt.
// ok to call this multiple times, calls after first are ignored.
SENTENCEG_Init();
// init texture type array from materials.txt
TEXTURETYPE_Init();
// the area based ambient sounds MUST be the first precache_sounds
// player precaches
W_Precache (); // get weapon precaches
ClientPrecache();
// QUAKECLASSIC
QuakeClassicPrecache();
// sounds used from C physics code
PRECACHE_SOUND("common/null.wav"); // clears sound channels
PRECACHE_SOUND( "items/suitchargeok1.wav" );//!!! temporary sound for respawning weapons.
PRECACHE_SOUND( "items/gunpickup2.wav" );// player picks up a gun.
PRECACHE_SOUND( "common/bodydrop3.wav" );// dead bodies hitting the ground (animation events)
PRECACHE_SOUND( "common/bodydrop4.wav" );
g_Language = (int)CVAR_GET_FLOAT( "sv_language" );
if ( g_Language == LANGUAGE_GERMAN )
{
PRECACHE_MODEL( "models/germangibs.mdl" );
}
else
{
PRECACHE_MODEL( "models/hgibs.mdl" );
PRECACHE_MODEL( "models/agibs.mdl" );
}
PRECACHE_SOUND ("weapons/ric1.wav");
PRECACHE_SOUND ("weapons/ric2.wav");
PRECACHE_SOUND ("weapons/ric3.wav");
PRECACHE_SOUND ("weapons/ric4.wav");
PRECACHE_SOUND ("weapons/ric5.wav");
//
// Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
//
// 0 normal
LIGHT_STYLE(0, "m");
// 1 FLICKER (first variety)
LIGHT_STYLE(1, "mmnmmommommnonmmonqnmmo");
// 2 SLOW STRONG PULSE
LIGHT_STYLE(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba");
// 3 CANDLE (first variety)
LIGHT_STYLE(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg");
// 4 FAST STROBE
LIGHT_STYLE(4, "mamamamamama");
// 5 GENTLE PULSE 1
LIGHT_STYLE(5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj");
// 6 FLICKER (second variety)
LIGHT_STYLE(6, "nmonqnmomnmomomno");
// 7 CANDLE (second variety)
LIGHT_STYLE(7, "mmmaaaabcdefgmmmmaaaammmaamm");
// 8 CANDLE (third variety)
LIGHT_STYLE(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa");
// 9 SLOW STROBE (fourth variety)
LIGHT_STYLE(9, "aaaaaaaazzzzzzzz");
// 10 FLUORESCENT FLICKER
LIGHT_STYLE(10, "mmamammmmammamamaaamammma");
// 11 SLOW PULSE NOT FADE TO BLACK
LIGHT_STYLE(11, "abcdefghijklmnopqrrqponmlkjihgfedcba");
// 12 UNDERWATER LIGHT MUTATION
// this light only distorts the lightmap - no contribution
// is made to the brightness of affected surfaces
LIGHT_STYLE(12, "mmnnmmnnnmmnn");
// styles 32-62 are assigned by the light program for switchable lights
// 63 testing
LIGHT_STYLE(63, "a");
for ( int i = 0; i < static_cast<int>(ARRAYSIZE(gDecals)); i++ )
gDecals[i].index = DECAL_INDEX( gDecals[i].name );
// init the WorldGraph.
WorldGraph.InitGraph();
// make sure the .NOD file is newer than the .BSP file.
if ( !WorldGraph.CheckNODFile ( ( char * )STRING( gpGlobals->mapname ) ) )
{// NOD file is not present, or is older than the BSP file.
WorldGraph.AllocNodes ();
}
else
{// Load the node graph for this level
if ( !WorldGraph.FLoadGraph ( (char *)STRING( gpGlobals->mapname ) ) )
{// couldn't load, so alloc and prepare to build a graph.
ALERT ( at_console, "*Error opening .NOD file\n" );
WorldGraph.AllocNodes ();
}
else
{
ALERT ( at_console, "\n*Graph Loaded!\n" );
}
}
if ( pev->speed > 0 )
CVAR_SET_FLOAT( "sv_zmax", pev->speed );
else
CVAR_SET_FLOAT( "sv_zmax", 4096 );
// QUAKECLASSIC: No Fades
/*
if ( pev->netname )
{
ALERT( at_aiconsole, "Chapter title: %s\n", STRING(pev->netname) );
CBaseEntity *pEntity = CBaseEntity::Create( "env_message", g_vecZero, g_vecZero, NULL );
if ( pEntity )
{
pEntity->SetThink( SUB_CallUseToggle );
pEntity->pev->message = pev->netname;
pev->netname = 0;
pEntity->pev->nextthink = gpGlobals->time + 0.3;
pEntity->pev->spawnflags = SF_MESSAGE_ONCE;
}
}
*/
// QUAKECLASSIC: No Darkness
/*
if ( pev->spawnflags & SF_WORLD_DARK )
CVAR_SET_FLOAT( "v_dark", 1.0 );
else
CVAR_SET_FLOAT( "v_dark", 0.0 );
*/
if ( pev->spawnflags & SF_WORLD_TITLE )
gDisplayTitle = TRUE; // display the game title if this key is set
else
gDisplayTitle = FALSE;
if ( pev->spawnflags & SF_WORLD_FORCETEAM )
{
CVAR_SET_FLOAT( "mp_defaultteam", 1 );
}
else
{
CVAR_SET_FLOAT( "mp_defaultteam", 0 );
}
}
//
// Just to ignore the "wad" field.
//
void CWorld :: KeyValue( KeyValueData *pkvd )
{
if ( FStrEq(pkvd->szKeyName, "skyname") )
{
// Sent over net now.
CVAR_SET_STRING( "sv_skyname", pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "sounds") )
{
gpGlobals->cdAudioTrack = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "WaveHeight") )
{
// Sent over net now.
pev->scale = atof(pkvd->szValue) * (1.0/8.0);
pkvd->fHandled = TRUE;
CVAR_SET_FLOAT( "sv_wateramp", pev->scale );
}
else if ( FStrEq(pkvd->szKeyName, "MaxRange") )
{
pev->speed = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "chaptertitle") )
{
pev->netname = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "startdark") )
{
// UNDONE: This is a gross hack!!! The CVAR is NOT sent over the client/sever link
// but it will work for single player
int flag = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
if ( flag )
pev->spawnflags |= SF_WORLD_DARK;
}
else if ( FStrEq(pkvd->szKeyName, "newunit") )
{
// Single player only. Clear save directory if set
if ( atoi(pkvd->szValue) )
CVAR_SET_FLOAT( "sv_newunit", 1 );
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "gametitle") )
{
if ( atoi(pkvd->szValue) )
pev->spawnflags |= SF_WORLD_TITLE;
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "mapteams") )
{
pev->team = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "defaultteam") )
{
if ( atoi(pkvd->szValue) )
{
pev->spawnflags |= SF_WORLD_FORCETEAM;
}
pkvd->fHandled = TRUE;
}
else
CBaseEntity::KeyValue( pkvd );
}