reorder folders
This commit is contained in:
771
src/common/const.h
Normal file
771
src/common/const.h
Normal file
@@ -0,0 +1,771 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 2000, 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 CONST_H
|
||||
#define CONST_H
|
||||
//
|
||||
// Constants shared by the engine and dlls
|
||||
// This header file included by engine files and DLL files.
|
||||
// Most came from server.h
|
||||
|
||||
// edict->flags
|
||||
#define FL_FLY (1<<0) // Changes the SV_Movestep() behavior to not need to be on ground
|
||||
#define FL_SWIM (1<<1) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water)
|
||||
#define FL_CONVEYOR (1<<2)
|
||||
#define FL_CLIENT (1<<3)
|
||||
#define FL_INWATER (1<<4)
|
||||
#define FL_MONSTER (1<<5)
|
||||
#define FL_GODMODE (1<<6)
|
||||
#define FL_NOTARGET (1<<7)
|
||||
#define FL_SKIPLOCALHOST (1<<8) // Don't send entity to local host, it's predicting this entity itself
|
||||
#define FL_ONGROUND (1<<9) // At rest / on the ground
|
||||
#define FL_PARTIALGROUND (1<<10) // not all corners are valid
|
||||
#define FL_WATERJUMP (1<<11) // player jumping out of water
|
||||
#define FL_FROZEN (1<<12) // Player is frozen for 3rd person camera
|
||||
#define FL_FAKECLIENT (1<<13) // JAC: fake client, simulated server side; don't send network messages to them
|
||||
#define FL_DUCKING (1<<14) // Player flag -- Player is fully crouched
|
||||
#define FL_FLOAT (1<<15) // Apply floating force to this entity when in water
|
||||
#define FL_GRAPHED (1<<16) // worldgraph has this ent listed as something that blocks a connection
|
||||
|
||||
// UNDONE: Do we need these?
|
||||
#define FL_IMMUNE_WATER (1<<17)
|
||||
#define FL_IMMUNE_SLIME (1<<18)
|
||||
#define FL_IMMUNE_LAVA (1<<19)
|
||||
|
||||
#define FL_PROXY (1<<20) // This is a spectator proxy
|
||||
#define FL_ALWAYSTHINK (1<<21) // Brush model flag -- call think every frame regardless of nextthink - ltime (for constantly changing velocity/path)
|
||||
#define FL_BASEVELOCITY (1<<22) // Base velocity has been applied this frame (used to convert base velocity into momentum)
|
||||
#define FL_MONSTERCLIP (1<<23) // Only collide in with monsters who have FL_MONSTERCLIP set
|
||||
#define FL_ONTRAIN (1<<24) // Player is _controlling_ a train, so movement commands should be ignored on client during prediction.
|
||||
#define FL_WORLDBRUSH (1<<25) // Not moveable/removeable brush entity (really part of the world, but represented as an entity for transparency or something)
|
||||
#define FL_SPECTATOR (1<<26) // This client is a spectator, don't run touch functions, etc.
|
||||
#define FL_CUSTOMENTITY (1<<29) // This is a custom entity
|
||||
#define FL_KILLME (1<<30) // This entity is marked for death -- This allows the engine to kill ents at the appropriate time
|
||||
#define FL_DORMANT (1<<31) // Entity is dormant, no updates to client
|
||||
|
||||
|
||||
// Goes into globalvars_t.trace_flags
|
||||
#define FTRACE_SIMPLEBOX (1<<0) // Traceline with a simple box
|
||||
|
||||
|
||||
// walkmove modes
|
||||
#define WALKMOVE_NORMAL 0 // normal walkmove
|
||||
#define WALKMOVE_WORLDONLY 1 // doesn't hit ANY entities, no matter what the solid type
|
||||
#define WALKMOVE_CHECKONLY 2 // move, but don't touch triggers
|
||||
|
||||
// edict->movetype values
|
||||
#define MOVETYPE_NONE 0 // never moves
|
||||
//#define MOVETYPE_ANGLENOCLIP 1
|
||||
//#define MOVETYPE_ANGLECLIP 2
|
||||
#define MOVETYPE_WALK 3 // Player only - moving on the ground
|
||||
#define MOVETYPE_STEP 4 // gravity, special edge handling -- monsters use this
|
||||
#define MOVETYPE_FLY 5 // No gravity, but still collides with stuff
|
||||
#define MOVETYPE_TOSS 6 // gravity/collisions
|
||||
#define MOVETYPE_PUSH 7 // no clip to world, push and crush
|
||||
#define MOVETYPE_NOCLIP 8 // No gravity, no collisions, still do velocity/avelocity
|
||||
#define MOVETYPE_FLYMISSILE 9 // extra size to monsters
|
||||
#define MOVETYPE_BOUNCE 10 // Just like Toss, but reflect velocity when contacting surfaces
|
||||
#define MOVETYPE_BOUNCEMISSILE 11 // bounce w/o gravity
|
||||
#define MOVETYPE_FOLLOW 12 // track movement of aiment
|
||||
#define MOVETYPE_PUSHSTEP 13 // BSP model that needs physics/world collisions (uses nearest hull for world collision)
|
||||
|
||||
// edict->solid values
|
||||
// NOTE: Some movetypes will cause collisions independent of SOLID_NOT/SOLID_TRIGGER when the entity moves
|
||||
// SOLID only effects OTHER entities colliding with this one when they move - UGH!
|
||||
#define SOLID_NOT 0 // no interaction with other objects
|
||||
#define SOLID_TRIGGER 1 // touch on edge, but not blocking
|
||||
#define SOLID_BBOX 2 // touch on edge, block
|
||||
#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground
|
||||
#define SOLID_BSP 4 // bsp clip, touch on edge, block
|
||||
|
||||
// edict->deadflag values
|
||||
#define DEAD_NO 0 // alive
|
||||
#define DEAD_DYING 1 // playing death animation or still falling off of a ledge waiting to hit ground
|
||||
#define DEAD_DEAD 2 // dead. lying still.
|
||||
#define DEAD_RESPAWNABLE 3
|
||||
#define DEAD_DISCARDBODY 4
|
||||
|
||||
#define DAMAGE_NO 0
|
||||
#define DAMAGE_YES 1
|
||||
#define DAMAGE_AIM 2
|
||||
|
||||
// entity effects
|
||||
#define EF_BRIGHTFIELD 1 // swirling cloud of particles
|
||||
#define EF_MUZZLEFLASH 2 // single frame ELIGHT on entity attachment 0
|
||||
#define EF_BRIGHTLIGHT 4 // DLIGHT centered at entity origin
|
||||
#define EF_DIMLIGHT 8 // player flashlight
|
||||
#define EF_INVLIGHT 16 // get lighting from ceiling
|
||||
#define EF_NOINTERP 32 // don't interpolate the next frame
|
||||
#define EF_LIGHT 64 // rocket flare glow sprite
|
||||
#define EF_NODRAW 128 // don't draw entity
|
||||
|
||||
// entity flags
|
||||
#define EFLAG_SLERP 1 // do studio interpolation of this entity
|
||||
|
||||
//
|
||||
// temp entity events
|
||||
//
|
||||
#define TE_BEAMPOINTS 0 // beam effect between two points
|
||||
// coord coord coord (start position)
|
||||
// coord coord coord (end position)
|
||||
// short (sprite index)
|
||||
// byte (starting frame)
|
||||
// byte (frame rate in 0.1's)
|
||||
// byte (life in 0.1's)
|
||||
// byte (line width in 0.1's)
|
||||
// byte (noise amplitude in 0.01's)
|
||||
// byte,byte,byte (color)
|
||||
// byte (brightness)
|
||||
// byte (scroll speed in 0.1's)
|
||||
|
||||
#define TE_BEAMENTPOINT 1 // beam effect between point and entity
|
||||
// short (start entity)
|
||||
// coord coord coord (end position)
|
||||
// short (sprite index)
|
||||
// byte (starting frame)
|
||||
// byte (frame rate in 0.1's)
|
||||
// byte (life in 0.1's)
|
||||
// byte (line width in 0.1's)
|
||||
// byte (noise amplitude in 0.01's)
|
||||
// byte,byte,byte (color)
|
||||
// byte (brightness)
|
||||
// byte (scroll speed in 0.1's)
|
||||
|
||||
#define TE_GUNSHOT 2 // particle effect plus ricochet sound
|
||||
// coord coord coord (position)
|
||||
|
||||
#define TE_EXPLOSION 3 // additive sprite, 2 dynamic lights, flickering particles, explosion sound, move vertically 8 pps
|
||||
// coord coord coord (position)
|
||||
// short (sprite index)
|
||||
// byte (scale in 0.1's)
|
||||
// byte (framerate)
|
||||
// byte (flags)
|
||||
//
|
||||
// The Explosion effect has some flags to control performance/aesthetic features:
|
||||
#define TE_EXPLFLAG_NONE 0 // all flags clear makes default Half-Life explosion
|
||||
#define TE_EXPLFLAG_NOADDITIVE 1 // sprite will be drawn opaque (ensure that the sprite you send is a non-additive sprite)
|
||||
#define TE_EXPLFLAG_NODLIGHTS 2 // do not render dynamic lights
|
||||
#define TE_EXPLFLAG_NOSOUND 4 // do not play client explosion sound
|
||||
#define TE_EXPLFLAG_NOPARTICLES 8 // do not draw particles
|
||||
|
||||
|
||||
#define TE_TAREXPLOSION 4 // Quake1 "tarbaby" explosion with sound
|
||||
// coord coord coord (position)
|
||||
|
||||
#define TE_SMOKE 5 // alphablend sprite, move vertically 30 pps
|
||||
// coord coord coord (position)
|
||||
// short (sprite index)
|
||||
// byte (scale in 0.1's)
|
||||
// byte (framerate)
|
||||
|
||||
#define TE_TRACER 6 // tracer effect from point to point
|
||||
// coord, coord, coord (start)
|
||||
// coord, coord, coord (end)
|
||||
|
||||
#define TE_LIGHTNING 7 // TE_BEAMPOINTS with simplified parameters
|
||||
// coord, coord, coord (start)
|
||||
// coord, coord, coord (end)
|
||||
// byte (life in 0.1's)
|
||||
// byte (width in 0.1's)
|
||||
// byte (amplitude in 0.01's)
|
||||
// short (sprite model index)
|
||||
|
||||
#define TE_BEAMENTS 8
|
||||
// short (start entity)
|
||||
// short (end entity)
|
||||
// short (sprite index)
|
||||
// byte (starting frame)
|
||||
// byte (frame rate in 0.1's)
|
||||
// byte (life in 0.1's)
|
||||
// byte (line width in 0.1's)
|
||||
// byte (noise amplitude in 0.01's)
|
||||
// byte,byte,byte (color)
|
||||
// byte (brightness)
|
||||
// byte (scroll speed in 0.1's)
|
||||
|
||||
#define TE_SPARKS 9 // 8 random tracers with gravity, ricochet sprite
|
||||
// coord coord coord (position)
|
||||
|
||||
#define TE_LAVASPLASH 10 // Quake1 lava splash
|
||||
// coord coord coord (position)
|
||||
|
||||
#define TE_TELEPORT 11 // Quake1 teleport splash
|
||||
// coord coord coord (position)
|
||||
|
||||
#define TE_EXPLOSION2 12 // Quake1 colormaped (base palette) particle explosion with sound
|
||||
// coord coord coord (position)
|
||||
// byte (starting color)
|
||||
// byte (num colors)
|
||||
|
||||
#define TE_BSPDECAL 13 // Decal from the .BSP file
|
||||
// coord, coord, coord (x,y,z), decal position (center of texture in world)
|
||||
// short (texture index of precached decal texture name)
|
||||
// short (entity index)
|
||||
// [optional - only included if previous short is non-zero (not the world)] short (index of model of above entity)
|
||||
|
||||
#define TE_IMPLOSION 14 // tracers moving toward a point
|
||||
// coord, coord, coord (position)
|
||||
// byte (radius)
|
||||
// byte (count)
|
||||
// byte (life in 0.1's)
|
||||
|
||||
#define TE_SPRITETRAIL 15 // line of moving glow sprites with gravity, fadeout, and collisions
|
||||
// coord, coord, coord (start)
|
||||
// coord, coord, coord (end)
|
||||
// short (sprite index)
|
||||
// byte (count)
|
||||
// byte (life in 0.1's)
|
||||
// byte (scale in 0.1's)
|
||||
// byte (velocity along vector in 10's)
|
||||
// byte (randomness of velocity in 10's)
|
||||
|
||||
#define TE_BEAM 16 // obsolete
|
||||
|
||||
#define TE_SPRITE 17 // additive sprite, plays 1 cycle
|
||||
// coord, coord, coord (position)
|
||||
// short (sprite index)
|
||||
// byte (scale in 0.1's)
|
||||
// byte (brightness)
|
||||
|
||||
#define TE_BEAMSPRITE 18 // A beam with a sprite at the end
|
||||
// coord, coord, coord (start position)
|
||||
// coord, coord, coord (end position)
|
||||
// short (beam sprite index)
|
||||
// short (end sprite index)
|
||||
|
||||
#define TE_BEAMTORUS 19 // screen aligned beam ring, expands to max radius over lifetime
|
||||
// coord coord coord (center position)
|
||||
// coord coord coord (axis and radius)
|
||||
// short (sprite index)
|
||||
// byte (starting frame)
|
||||
// byte (frame rate in 0.1's)
|
||||
// byte (life in 0.1's)
|
||||
// byte (line width in 0.1's)
|
||||
// byte (noise amplitude in 0.01's)
|
||||
// byte,byte,byte (color)
|
||||
// byte (brightness)
|
||||
// byte (scroll speed in 0.1's)
|
||||
|
||||
#define TE_BEAMDISK 20 // disk that expands to max radius over lifetime
|
||||
// coord coord coord (center position)
|
||||
// coord coord coord (axis and radius)
|
||||
// short (sprite index)
|
||||
// byte (starting frame)
|
||||
// byte (frame rate in 0.1's)
|
||||
// byte (life in 0.1's)
|
||||
// byte (line width in 0.1's)
|
||||
// byte (noise amplitude in 0.01's)
|
||||
// byte,byte,byte (color)
|
||||
// byte (brightness)
|
||||
// byte (scroll speed in 0.1's)
|
||||
|
||||
#define TE_BEAMCYLINDER 21 // cylinder that expands to max radius over lifetime
|
||||
// coord coord coord (center position)
|
||||
// coord coord coord (axis and radius)
|
||||
// short (sprite index)
|
||||
// byte (starting frame)
|
||||
// byte (frame rate in 0.1's)
|
||||
// byte (life in 0.1's)
|
||||
// byte (line width in 0.1's)
|
||||
// byte (noise amplitude in 0.01's)
|
||||
// byte,byte,byte (color)
|
||||
// byte (brightness)
|
||||
// byte (scroll speed in 0.1's)
|
||||
|
||||
#define TE_BEAMFOLLOW 22 // create a line of decaying beam segments until entity stops moving
|
||||
// short (entity:attachment to follow)
|
||||
// short (sprite index)
|
||||
// byte (life in 0.1's)
|
||||
// byte (line width in 0.1's)
|
||||
// byte,byte,byte (color)
|
||||
// byte (brightness)
|
||||
|
||||
#define TE_GLOWSPRITE 23
|
||||
// coord, coord, coord (pos) short (model index) byte (scale / 10)
|
||||
|
||||
#define TE_BEAMRING 24 // connect a beam ring to two entities
|
||||
// short (start entity)
|
||||
// short (end entity)
|
||||
// short (sprite index)
|
||||
// byte (starting frame)
|
||||
// byte (frame rate in 0.1's)
|
||||
// byte (life in 0.1's)
|
||||
// byte (line width in 0.1's)
|
||||
// byte (noise amplitude in 0.01's)
|
||||
// byte,byte,byte (color)
|
||||
// byte (brightness)
|
||||
// byte (scroll speed in 0.1's)
|
||||
|
||||
#define TE_STREAK_SPLASH 25 // oriented shower of tracers
|
||||
// coord coord coord (start position)
|
||||
// coord coord coord (direction vector)
|
||||
// byte (color)
|
||||
// short (count)
|
||||
// short (base speed)
|
||||
// short (ramdon velocity)
|
||||
|
||||
#define TE_BEAMHOSE 26 // obsolete
|
||||
|
||||
#define TE_DLIGHT 27 // dynamic light, effect world, minor entity effect
|
||||
// coord, coord, coord (pos)
|
||||
// byte (radius in 10's)
|
||||
// byte byte byte (color)
|
||||
// byte (brightness)
|
||||
// byte (life in 10's)
|
||||
// byte (decay rate in 10's)
|
||||
|
||||
#define TE_ELIGHT 28 // point entity light, no world effect
|
||||
// short (entity:attachment to follow)
|
||||
// coord coord coord (initial position)
|
||||
// coord (radius)
|
||||
// byte byte byte (color)
|
||||
// byte (life in 0.1's)
|
||||
// coord (decay rate)
|
||||
|
||||
#define TE_TEXTMESSAGE 29
|
||||
// short 1.2.13 x (-1 = center)
|
||||
// short 1.2.13 y (-1 = center)
|
||||
// byte Effect 0 = fade in/fade out
|
||||
// 1 is flickery credits
|
||||
// 2 is write out (training room)
|
||||
|
||||
// 4 bytes r,g,b,a color1 (text color)
|
||||
// 4 bytes r,g,b,a color2 (effect color)
|
||||
// ushort 8.8 fadein time
|
||||
// ushort 8.8 fadeout time
|
||||
// ushort 8.8 hold time
|
||||
// optional ushort 8.8 fxtime (time the highlight lags behing the leading text in effect 2)
|
||||
// string text message (512 chars max sz string)
|
||||
#define TE_LINE 30
|
||||
// coord, coord, coord startpos
|
||||
// coord, coord, coord endpos
|
||||
// short life in 0.1 s
|
||||
// 3 bytes r, g, b
|
||||
|
||||
#define TE_BOX 31
|
||||
// coord, coord, coord boxmins
|
||||
// coord, coord, coord boxmaxs
|
||||
// short life in 0.1 s
|
||||
// 3 bytes r, g, b
|
||||
|
||||
#define TE_KILLBEAM 99 // kill all beams attached to entity
|
||||
// short (entity)
|
||||
|
||||
#define TE_LARGEFUNNEL 100
|
||||
// coord coord coord (funnel position)
|
||||
// short (sprite index)
|
||||
// short (flags)
|
||||
|
||||
#define TE_BLOODSTREAM 101 // particle spray
|
||||
// coord coord coord (start position)
|
||||
// coord coord coord (spray vector)
|
||||
// byte (color)
|
||||
// byte (speed)
|
||||
|
||||
#define TE_SHOWLINE 102 // line of particles every 5 units, dies in 30 seconds
|
||||
// coord coord coord (start position)
|
||||
// coord coord coord (end position)
|
||||
|
||||
#define TE_BLOOD 103 // particle spray
|
||||
// coord coord coord (start position)
|
||||
// coord coord coord (spray vector)
|
||||
// byte (color)
|
||||
// byte (speed)
|
||||
|
||||
#define TE_DECAL 104 // Decal applied to a brush entity (not the world)
|
||||
// coord, coord, coord (x,y,z), decal position (center of texture in world)
|
||||
// byte (texture index of precached decal texture name)
|
||||
// short (entity index)
|
||||
|
||||
#define TE_FIZZ 105 // create alpha sprites inside of entity, float upwards
|
||||
// short (entity)
|
||||
// short (sprite index)
|
||||
// byte (density)
|
||||
|
||||
#define TE_MODEL 106 // create a moving model that bounces and makes a sound when it hits
|
||||
// coord, coord, coord (position)
|
||||
// coord, coord, coord (velocity)
|
||||
// angle (initial yaw)
|
||||
// short (model index)
|
||||
// byte (bounce sound type)
|
||||
// byte (life in 0.1's)
|
||||
|
||||
#define TE_EXPLODEMODEL 107 // spherical shower of models, picks from set
|
||||
// coord, coord, coord (origin)
|
||||
// coord (velocity)
|
||||
// short (model index)
|
||||
// short (count)
|
||||
// byte (life in 0.1's)
|
||||
|
||||
#define TE_BREAKMODEL 108 // box of models or sprites
|
||||
// coord, coord, coord (position)
|
||||
// coord, coord, coord (size)
|
||||
// coord, coord, coord (velocity)
|
||||
// byte (random velocity in 10's)
|
||||
// short (sprite or model index)
|
||||
// byte (count)
|
||||
// byte (life in 0.1 secs)
|
||||
// byte (flags)
|
||||
|
||||
#define TE_GUNSHOTDECAL 109 // decal and ricochet sound
|
||||
// coord, coord, coord (position)
|
||||
// short (entity index???)
|
||||
// byte (decal???)
|
||||
|
||||
#define TE_SPRITE_SPRAY 110 // spay of alpha sprites
|
||||
// coord, coord, coord (position)
|
||||
// coord, coord, coord (velocity)
|
||||
// short (sprite index)
|
||||
// byte (count)
|
||||
// byte (speed)
|
||||
// byte (noise)
|
||||
|
||||
#define TE_ARMOR_RICOCHET 111 // quick spark sprite, client ricochet sound.
|
||||
// coord, coord, coord (position)
|
||||
// byte (scale in 0.1's)
|
||||
|
||||
#define TE_PLAYERDECAL 112 // ???
|
||||
// byte (playerindex)
|
||||
// coord, coord, coord (position)
|
||||
// short (entity???)
|
||||
// byte (decal number???)
|
||||
// [optional] short (model index???)
|
||||
|
||||
#define TE_BUBBLES 113 // create alpha sprites inside of box, float upwards
|
||||
// coord, coord, coord (min start position)
|
||||
// coord, coord, coord (max start position)
|
||||
// coord (float height)
|
||||
// short (model index)
|
||||
// byte (count)
|
||||
// coord (speed)
|
||||
|
||||
#define TE_BUBBLETRAIL 114 // create alpha sprites along a line, float upwards
|
||||
// coord, coord, coord (min start position)
|
||||
// coord, coord, coord (max start position)
|
||||
// coord (float height)
|
||||
// short (model index)
|
||||
// byte (count)
|
||||
// coord (speed)
|
||||
|
||||
#define TE_BLOODSPRITE 115 // spray of opaque sprite1's that fall, single sprite2 for 1..2 secs (this is a high-priority tent)
|
||||
// coord, coord, coord (position)
|
||||
// short (sprite1 index)
|
||||
// short (sprite2 index)
|
||||
// byte (color)
|
||||
// byte (scale)
|
||||
|
||||
#define TE_WORLDDECAL 116 // Decal applied to the world brush
|
||||
// coord, coord, coord (x,y,z), decal position (center of texture in world)
|
||||
// byte (texture index of precached decal texture name)
|
||||
|
||||
#define TE_WORLDDECALHIGH 117 // Decal (with texture index > 256) applied to world brush
|
||||
// coord, coord, coord (x,y,z), decal position (center of texture in world)
|
||||
// byte (texture index of precached decal texture name - 256)
|
||||
|
||||
#define TE_DECALHIGH 118 // Same as TE_DECAL, but the texture index was greater than 256
|
||||
// coord, coord, coord (x,y,z), decal position (center of texture in world)
|
||||
// byte (texture index of precached decal texture name - 256)
|
||||
// short (entity index)
|
||||
|
||||
#define TE_PROJECTILE 119 // Makes a projectile (like a nail) (this is a high-priority tent)
|
||||
// coord, coord, coord (position)
|
||||
// coord, coord, coord (velocity)
|
||||
// short (modelindex)
|
||||
// byte (life)
|
||||
// byte (owner) projectile won't collide with owner (if owner == 0, projectile will hit any client).
|
||||
|
||||
#define TE_SPRAY 120 // Throws a shower of sprites or models
|
||||
// coord, coord, coord (position)
|
||||
// coord, coord, coord (direction)
|
||||
// short (modelindex)
|
||||
// byte (count)
|
||||
// byte (speed)
|
||||
// byte (noise)
|
||||
// byte (rendermode)
|
||||
|
||||
#define TE_PLAYERSPRITES 121 // sprites emit from a player's bounding box (ONLY use for players!)
|
||||
// byte (playernum)
|
||||
// short (sprite modelindex)
|
||||
// byte (count)
|
||||
// byte (variance) (0 = no variance in size) (10 = 10% variance in size)
|
||||
|
||||
#define TE_PARTICLEBURST 122 // very similar to lavasplash.
|
||||
// coord (origin)
|
||||
// short (radius)
|
||||
// byte (particle color)
|
||||
// byte (duration * 10) (will be randomized a bit)
|
||||
|
||||
#define TE_FIREFIELD 123 // makes a field of fire.
|
||||
// coord (origin)
|
||||
// short (radius) (fire is made in a square around origin. -radius, -radius to radius, radius)
|
||||
// short (modelindex)
|
||||
// byte (count)
|
||||
// byte (flags)
|
||||
// byte (duration (in seconds) * 10) (will be randomized a bit)
|
||||
//
|
||||
// to keep network traffic low, this message has associated flags that fit into a byte:
|
||||
#define TEFIRE_FLAG_ALLFLOAT 1 // all sprites will drift upwards as they animate
|
||||
#define TEFIRE_FLAG_SOMEFLOAT 2 // some of the sprites will drift upwards. (50% chance)
|
||||
#define TEFIRE_FLAG_LOOP 4 // if set, sprite plays at 15 fps, otherwise plays at whatever rate stretches the animation over the sprite's duration.
|
||||
#define TEFIRE_FLAG_ALPHA 8 // if set, sprite is rendered alpha blended at 50% else, opaque
|
||||
#define TEFIRE_FLAG_PLANAR 16 // if set, all fire sprites have same initial Z instead of randomly filling a cube.
|
||||
|
||||
#define TE_PLAYERATTACHMENT 124 // attaches a TENT to a player (this is a high-priority tent)
|
||||
// byte (entity index of player)
|
||||
// coord (vertical offset) ( attachment origin.z = player origin.z + vertical offset )
|
||||
// short (model index)
|
||||
// short (life * 10 );
|
||||
|
||||
#define TE_KILLPLAYERATTACHMENTS 125 // will expire all TENTS attached to a player.
|
||||
// byte (entity index of player)
|
||||
|
||||
#define TE_MULTIGUNSHOT 126 // much more compact shotgun message
|
||||
// This message is used to make a client approximate a 'spray' of gunfire.
|
||||
// Any weapon that fires more than one bullet per frame and fires in a bit of a spread is
|
||||
// a good candidate for MULTIGUNSHOT use. (shotguns)
|
||||
//
|
||||
// NOTE: This effect makes the client do traces for each bullet, these client traces ignore
|
||||
// entities that have studio models.Traces are 4096 long.
|
||||
//
|
||||
// coord (origin)
|
||||
// coord (origin)
|
||||
// coord (origin)
|
||||
// coord (direction)
|
||||
// coord (direction)
|
||||
// coord (direction)
|
||||
// coord (x noise * 100)
|
||||
// coord (y noise * 100)
|
||||
// byte (count)
|
||||
// byte (bullethole decal texture index)
|
||||
|
||||
#define TE_USERTRACER 127 // larger message than the standard tracer, but allows some customization.
|
||||
// coord (origin)
|
||||
// coord (origin)
|
||||
// coord (origin)
|
||||
// coord (velocity)
|
||||
// coord (velocity)
|
||||
// coord (velocity)
|
||||
// byte ( life * 10 )
|
||||
// byte ( color ) this is an index into an array of color vectors in the engine. (0 - )
|
||||
// byte ( length * 10 )
|
||||
|
||||
|
||||
|
||||
#define MSG_BROADCAST 0 // unreliable to all
|
||||
#define MSG_ONE 1 // reliable to one (msg_entity)
|
||||
#define MSG_ALL 2 // reliable to all
|
||||
#define MSG_INIT 3 // write to the init string
|
||||
#define MSG_PVS 4 // Ents in PVS of org
|
||||
#define MSG_PAS 5 // Ents in PAS of org
|
||||
#define MSG_PVS_R 6 // Reliable to PVS
|
||||
#define MSG_PAS_R 7 // Reliable to PAS
|
||||
#define MSG_ONE_UNRELIABLE 8 // Send to one client, but don't put in reliable stream, put in unreliable datagram ( could be dropped )
|
||||
#define MSG_SPEC 9 // Sends to all spectator proxies
|
||||
|
||||
// contents of a spot in the world
|
||||
#define CONTENTS_EMPTY -1
|
||||
#define CONTENTS_SOLID -2
|
||||
#define CONTENTS_WATER -3
|
||||
#define CONTENTS_SLIME -4
|
||||
#define CONTENTS_LAVA -5
|
||||
#define CONTENTS_SKY -6
|
||||
/* These additional contents constants are defined in bspfile.h
|
||||
#define CONTENTS_ORIGIN -7 // removed at csg time
|
||||
#define CONTENTS_CLIP -8 // changed to contents_solid
|
||||
#define CONTENTS_CURRENT_0 -9
|
||||
#define CONTENTS_CURRENT_90 -10
|
||||
#define CONTENTS_CURRENT_180 -11
|
||||
#define CONTENTS_CURRENT_270 -12
|
||||
#define CONTENTS_CURRENT_UP -13
|
||||
#define CONTENTS_CURRENT_DOWN -14
|
||||
|
||||
#define CONTENTS_TRANSLUCENT -15
|
||||
*/
|
||||
#define CONTENTS_LADDER -16
|
||||
|
||||
#define CONTENT_EMPTY -1
|
||||
#define CONTENT_SOLID -2
|
||||
#define CONTENT_WATER -3
|
||||
#define CONTENT_SLIME -4
|
||||
#define CONTENT_LAVA -5
|
||||
#define CONTENT_SKY -6
|
||||
|
||||
// channels
|
||||
#define CHAN_AUTO 0
|
||||
#define CHAN_WEAPON 1
|
||||
#define CHAN_VOICE 2
|
||||
#define CHAN_ITEM 3
|
||||
#define CHAN_BODY 4
|
||||
#define CHAN_STREAM 5 // allocate stream channel from the static or dynamic area
|
||||
#define CHAN_STATIC 6 // allocate channel from the static area
|
||||
#define CHAN_NETWORKVOICE_BASE 7 // voice data coming across the network
|
||||
#define CHAN_NETWORKVOICE_END 500 // network voice data reserves slots (CHAN_NETWORKVOICE_BASE through CHAN_NETWORKVOICE_END).
|
||||
|
||||
// attenuation values
|
||||
#define ATTN_NONE 0
|
||||
#define ATTN_NORM (float)0.8
|
||||
#define ATTN_IDLE (float)2
|
||||
#define ATTN_STATIC (float)1.25
|
||||
|
||||
// pitch values
|
||||
#define PITCH_NORM 100 // non-pitch shifted
|
||||
#define PITCH_LOW 95 // other values are possible - 0-255, where 255 is very high
|
||||
#define PITCH_HIGH 120
|
||||
|
||||
// volume values
|
||||
#define VOL_NORM 1.0
|
||||
|
||||
// plats
|
||||
#define PLAT_LOW_TRIGGER 1
|
||||
|
||||
// Trains
|
||||
#define SF_TRAIN_WAIT_RETRIGGER 1
|
||||
#define SF_TRAIN_PASSABLE 8 // Train is not solid -- used to make water trains
|
||||
|
||||
// buttons
|
||||
#ifndef IN_BUTTONS_H
|
||||
#include "in_buttons.h"
|
||||
#endif
|
||||
|
||||
// Break Model Defines
|
||||
|
||||
#define BREAK_TYPEMASK 0x4F
|
||||
#define BREAK_GLASS 0x01
|
||||
#define BREAK_METAL 0x02
|
||||
#define BREAK_FLESH 0x04
|
||||
#define BREAK_WOOD 0x08
|
||||
|
||||
#define BREAK_SMOKE 0x10
|
||||
#define BREAK_TRANS 0x20
|
||||
#define BREAK_CONCRETE 0x40
|
||||
#define BREAK_2 0x80
|
||||
|
||||
// Colliding temp entity sounds
|
||||
|
||||
#define BOUNCE_GLASS BREAK_GLASS
|
||||
#define BOUNCE_METAL BREAK_METAL
|
||||
#define BOUNCE_FLESH BREAK_FLESH
|
||||
#define BOUNCE_WOOD BREAK_WOOD
|
||||
#define BOUNCE_SHRAP 0x10
|
||||
#define BOUNCE_SHELL 0x20
|
||||
#define BOUNCE_CONCRETE BREAK_CONCRETE
|
||||
#define BOUNCE_SHOTSHELL 0x80
|
||||
|
||||
// Temp entity bounce sound types
|
||||
#define TE_BOUNCE_NULL 0
|
||||
#define TE_BOUNCE_SHELL 1
|
||||
#define TE_BOUNCE_SHOTSHELL 2
|
||||
|
||||
// Rendering constants
|
||||
enum
|
||||
{
|
||||
kRenderNormal, // src
|
||||
kRenderTransColor, // c*a+dest*(1-a)
|
||||
kRenderTransTexture, // src*a+dest*(1-a)
|
||||
kRenderGlow, // src*a+dest -- No Z buffer checks
|
||||
kRenderTransAlpha, // src*srca+dest*(1-srca)
|
||||
kRenderTransAdd, // src*a+dest
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kRenderFxNone = 0,
|
||||
kRenderFxPulseSlow,
|
||||
kRenderFxPulseFast,
|
||||
kRenderFxPulseSlowWide,
|
||||
kRenderFxPulseFastWide,
|
||||
kRenderFxFadeSlow,
|
||||
kRenderFxFadeFast,
|
||||
kRenderFxSolidSlow,
|
||||
kRenderFxSolidFast,
|
||||
kRenderFxStrobeSlow,
|
||||
kRenderFxStrobeFast,
|
||||
kRenderFxStrobeFaster,
|
||||
kRenderFxFlickerSlow,
|
||||
kRenderFxFlickerFast,
|
||||
kRenderFxNoDissipation,
|
||||
kRenderFxDistort, // Distort/scale/translate flicker
|
||||
kRenderFxHologram, // kRenderFxDistort + distance fade
|
||||
kRenderFxDeadPlayer, // kRenderAmt is the player index
|
||||
kRenderFxExplode, // Scale up really big!
|
||||
kRenderFxGlowShell, // Glowing Shell
|
||||
kRenderFxClampMinScale, // Keep this sprite from getting very small (SPRITES only!)
|
||||
};
|
||||
|
||||
|
||||
typedef int func_t;
|
||||
typedef int string_t;
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
#define _DEF_BYTE_
|
||||
|
||||
#undef true
|
||||
#undef false
|
||||
|
||||
#ifndef __cplusplus
|
||||
typedef enum {false, true} qboolean;
|
||||
#else
|
||||
typedef int qboolean;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte r, g, b;
|
||||
} color24;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned r, g, b, a;
|
||||
} colorVec;
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma pack(push,2)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short r, g, b, a;
|
||||
} PackedColorVec;
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
typedef struct link_s
|
||||
{
|
||||
struct link_s *prev, *next;
|
||||
} link_t;
|
||||
|
||||
typedef struct edict_s edict_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
} plane_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
qboolean allsolid; // if true, plane is not valid
|
||||
qboolean startsolid; // if true, the initial point was in a solid area
|
||||
qboolean inopen, inwater;
|
||||
float fraction; // time completed, 1.0 = didn't hit anything
|
||||
vec3_t endpos; // final position
|
||||
plane_t plane; // surface normal at impact
|
||||
edict_t *ent; // entity the surface is on
|
||||
int hitgroup; // 0 == generic, non zero is specific body part
|
||||
} trace_t;
|
||||
|
||||
#endif
|
||||
|
||||
52
src/common/crc.h
Normal file
52
src/common/crc.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 2000, 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.
|
||||
*
|
||||
****/
|
||||
/* crc.h */
|
||||
#ifndef CRC_H
|
||||
#define CRC_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// MD5 Hash
|
||||
typedef struct
|
||||
{
|
||||
unsigned int buf[4];
|
||||
unsigned int bits[2];
|
||||
unsigned char in[64];
|
||||
} MD5Context_t;
|
||||
|
||||
|
||||
typedef unsigned long CRC32_t;
|
||||
void CRC32_Init(CRC32_t *pulCRC);
|
||||
CRC32_t CRC32_Final(CRC32_t pulCRC);
|
||||
void CRC32_ProcessBuffer(CRC32_t *pulCRC, void *p, int len);
|
||||
void CRC32_ProcessByte(CRC32_t *pulCRC, unsigned char ch);
|
||||
int CRC_File(CRC32_t *crcvalue, char *pszFileName);
|
||||
|
||||
unsigned char COM_BlockSequenceCRCByte (unsigned char *base, int length, int sequence);
|
||||
|
||||
void MD5Init(MD5Context_t *context);
|
||||
void MD5Update(MD5Context_t *context, unsigned char const *buf,
|
||||
unsigned int len);
|
||||
void MD5Final(unsigned char digest[16], MD5Context_t *context);
|
||||
void Transform(unsigned int buf[4], unsigned int const in[16]);
|
||||
|
||||
int MD5_Hash_File(unsigned char digest[16], char *pszFileName, int bUsefopen, int bSeed, unsigned int seed[4]);
|
||||
char *MD5_Print(unsigned char hash[16]);
|
||||
int MD5_Hash_CachedFile(unsigned char digest[16], unsigned char *pCache, int nFileSize, int bSeed, unsigned int seed[4]);
|
||||
|
||||
int CRC_MapFile(CRC32_t *crcvalue, char *pszFileName);
|
||||
|
||||
#endif
|
||||
36
src/common/cvardef.h
Normal file
36
src/common/cvardef.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 2000, 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 CVARDEF_H
|
||||
#define CVARDEF_H
|
||||
|
||||
#define FCVAR_ARCHIVE (1<<0) // set to cause it to be saved to vars.rc
|
||||
#define FCVAR_USERINFO (1<<1) // changes the client's info string
|
||||
#define FCVAR_SERVER (1<<2) // notifies players when changed
|
||||
#define FCVAR_EXTDLL (1<<3) // defined by external DLL
|
||||
#define FCVAR_CLIENTDLL (1<<4) // defined by the client dll
|
||||
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
|
||||
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
|
||||
#define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
|
||||
#define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
|
||||
|
||||
typedef struct cvar_s
|
||||
{
|
||||
char *name;
|
||||
char *string;
|
||||
int flags;
|
||||
float value;
|
||||
struct cvar_s *next;
|
||||
} cvar_t;
|
||||
#endif
|
||||
193
src/common/entity_state.h
Normal file
193
src/common/entity_state.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 2000 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.
|
||||
*
|
||||
****/
|
||||
#if !defined( ENTITY_STATEH )
|
||||
#define ENTITY_STATEH
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// For entityType below
|
||||
#define ENTITY_NORMAL (1<<0)
|
||||
#define ENTITY_BEAM (1<<1)
|
||||
|
||||
// Entity state is used for the baseline and for delta compression of a packet of
|
||||
// entities that is sent to a client.
|
||||
typedef struct entity_state_s entity_state_t;
|
||||
|
||||
struct entity_state_s
|
||||
{
|
||||
// Fields which are filled in by routines outside of delta compression
|
||||
int entityType;
|
||||
// Index into cl_entities array for this entity.
|
||||
int number;
|
||||
float msg_time;
|
||||
|
||||
// Message number last time the player/entity state was updated.
|
||||
int messagenum;
|
||||
|
||||
// Fields which can be transitted and reconstructed over the network stream
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
|
||||
int modelindex;
|
||||
int sequence;
|
||||
float frame;
|
||||
int colormap;
|
||||
short skin;
|
||||
short solid;
|
||||
int effects;
|
||||
float scale;
|
||||
|
||||
byte eflags;
|
||||
|
||||
// Render information
|
||||
int rendermode;
|
||||
int renderamt;
|
||||
color24 rendercolor;
|
||||
int renderfx;
|
||||
|
||||
int movetype;
|
||||
float animtime;
|
||||
float framerate;
|
||||
int body;
|
||||
byte controller[4];
|
||||
byte blending[4];
|
||||
vec3_t velocity;
|
||||
|
||||
// Send bbox down to client for use during prediction.
|
||||
vec3_t mins;
|
||||
vec3_t maxs;
|
||||
|
||||
int aiment;
|
||||
// If owned by a player, the index of that player ( for projectiles ).
|
||||
int owner;
|
||||
|
||||
// Friction, for prediction.
|
||||
float friction;
|
||||
// Gravity multiplier
|
||||
float gravity;
|
||||
|
||||
// PLAYER SPECIFIC
|
||||
int team;
|
||||
int playerclass;
|
||||
int health;
|
||||
qboolean spectator;
|
||||
int weaponmodel;
|
||||
int gaitsequence;
|
||||
// If standing on conveyor, e.g.
|
||||
vec3_t basevelocity;
|
||||
// Use the crouched hull, or the regular player hull.
|
||||
int usehull;
|
||||
// Latched buttons last time state updated.
|
||||
int oldbuttons;
|
||||
// -1 = in air, else pmove entity number
|
||||
int onground;
|
||||
int iStepLeft;
|
||||
// How fast we are falling
|
||||
float flFallVelocity;
|
||||
|
||||
float fov;
|
||||
int weaponanim;
|
||||
|
||||
// Parametric movement overrides
|
||||
vec3_t startpos;
|
||||
vec3_t endpos;
|
||||
float impacttime;
|
||||
float starttime;
|
||||
|
||||
// For mods
|
||||
int iuser1;
|
||||
int iuser2;
|
||||
int iuser3;
|
||||
int iuser4;
|
||||
float fuser1;
|
||||
float fuser2;
|
||||
float fuser3;
|
||||
float fuser4;
|
||||
vec3_t vuser1;
|
||||
vec3_t vuser2;
|
||||
vec3_t vuser3;
|
||||
vec3_t vuser4;
|
||||
};
|
||||
|
||||
#include "pm_info.h"
|
||||
|
||||
typedef struct clientdata_s
|
||||
{
|
||||
vec3_t origin;
|
||||
vec3_t velocity;
|
||||
|
||||
int viewmodel;
|
||||
vec3_t punchangle;
|
||||
int flags;
|
||||
int waterlevel;
|
||||
int watertype;
|
||||
vec3_t view_ofs;
|
||||
float health;
|
||||
|
||||
int bInDuck;
|
||||
|
||||
int weapons; // remove?
|
||||
|
||||
int flTimeStepSound;
|
||||
int flDuckTime;
|
||||
int flSwimTime;
|
||||
int waterjumptime;
|
||||
|
||||
float maxspeed;
|
||||
|
||||
float fov;
|
||||
int weaponanim;
|
||||
|
||||
int m_iId;
|
||||
int ammo_shells;
|
||||
int ammo_nails;
|
||||
int ammo_cells;
|
||||
int ammo_rockets;
|
||||
float m_flNextAttack;
|
||||
|
||||
int tfstate;
|
||||
|
||||
int pushmsec;
|
||||
|
||||
int deadflag;
|
||||
|
||||
char physinfo[ MAX_PHYSINFO_STRING ];
|
||||
|
||||
// For mods
|
||||
int iuser1;
|
||||
int iuser2;
|
||||
int iuser3;
|
||||
int iuser4;
|
||||
float fuser1;
|
||||
float fuser2;
|
||||
float fuser3;
|
||||
float fuser4;
|
||||
vec3_t vuser1;
|
||||
vec3_t vuser2;
|
||||
vec3_t vuser3;
|
||||
vec3_t vuser4;
|
||||
} clientdata_t;
|
||||
|
||||
#include "weaponinfo.h"
|
||||
|
||||
typedef struct local_state_s
|
||||
{
|
||||
entity_state_t playerstate;
|
||||
clientdata_t client;
|
||||
weapon_data_t weapondata[ 32 ];
|
||||
} local_state_t;
|
||||
|
||||
#endif // !ENTITY_STATEH
|
||||
47
src/common/event_flags.h
Normal file
47
src/common/event_flags.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 2000, 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.
|
||||
*
|
||||
****/
|
||||
#if !defined( EVENT_FLAGSH )
|
||||
#define EVENT_FLAGSH
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// Skip local host for event send.
|
||||
#define FEV_NOTHOST (1<<0)
|
||||
|
||||
// Send the event reliably. You must specify the origin and angles and use
|
||||
// PLAYBACK_EVENT_FULL for this to work correctly on the server for anything
|
||||
// that depends on the event origin/angles. I.e., the origin/angles are not
|
||||
// taken from the invoking edict for reliable events.
|
||||
#define FEV_RELIABLE (1<<1)
|
||||
|
||||
// Don't restrict to PAS/PVS, send this event to _everybody_ on the server ( useful for stopping CHAN_STATIC
|
||||
// sounds started by client event when client is not in PVS anymore ( hwguy in TFC e.g. ).
|
||||
#define FEV_GLOBAL (1<<2)
|
||||
|
||||
// If this client already has one of these events in its queue, just update the event instead of sending it as a duplicate
|
||||
//
|
||||
#define FEV_UPDATE (1<<3)
|
||||
|
||||
// Only send to entity specified as the invoker
|
||||
#define FEV_HOSTONLY (1<<4)
|
||||
|
||||
// Only send if the event was created on the server.
|
||||
#define FEV_SERVER (1<<5)
|
||||
|
||||
// Only issue event client side ( from shared code )
|
||||
#define FEV_CLIENT (1<<6)
|
||||
|
||||
#endif
|
||||
38
src/common/in_buttons.h
Normal file
38
src/common/in_buttons.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 2000, 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 IN_BUTTONS_H
|
||||
#define IN_BUTTONS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#define IN_ATTACK (1 << 0)
|
||||
#define IN_JUMP (1 << 1)
|
||||
#define IN_DUCK (1 << 2)
|
||||
#define IN_FORWARD (1 << 3)
|
||||
#define IN_BACK (1 << 4)
|
||||
#define IN_USE (1 << 5)
|
||||
#define IN_CANCEL (1 << 6)
|
||||
#define IN_LEFT (1 << 7)
|
||||
#define IN_RIGHT (1 << 8)
|
||||
#define IN_MOVELEFT (1 << 9)
|
||||
#define IN_MOVERIGHT (1 << 10)
|
||||
#define IN_ATTACK2 (1 << 11)
|
||||
#define IN_RUN (1 << 12)
|
||||
#define IN_RELOAD (1 << 13)
|
||||
#define IN_ALT1 (1 << 14)
|
||||
#define IN_SCORE (1 << 15) // Used by client.dll for when scoreboard is held down
|
||||
|
||||
#endif // IN_BUTTONS_H
|
||||
15
src/common/nowin.h
Normal file
15
src/common/nowin.h
Normal file
@@ -0,0 +1,15 @@
|
||||
//========= Copyright <20> 1996-2001, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#ifndef INC_NOWIN_H
|
||||
#define INC_NOWIN_H
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#endif //!_WIN32
|
||||
#endif //INC_NOWIN_H
|
||||
29
src/common/studio_event.h
Normal file
29
src/common/studio_event.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 2000, 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.
|
||||
*
|
||||
****/
|
||||
#if !defined( STUDIO_EVENTH )
|
||||
#define STUDIO_EVENTH
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
typedef struct mstudioevent_s
|
||||
{
|
||||
int frame;
|
||||
int event;
|
||||
int type;
|
||||
char options[64];
|
||||
} mstudioevent_t;
|
||||
|
||||
#endif // STUDIO_EVENTH
|
||||
3
src/dlls/.gitignore
vendored
Normal file
3
src/dlls/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
msgs/
|
||||
opt.*/
|
||||
debug.*/
|
||||
1392
src/dlls/AI_BaseNPC_Schedule.cpp
Normal file
1392
src/dlls/AI_BaseNPC_Schedule.cpp
Normal file
File diff suppressed because it is too large
Load Diff
56
src/dlls/Makefile
Normal file
56
src/dlls/Makefile
Normal file
@@ -0,0 +1,56 @@
|
||||
CPP = gcc
|
||||
BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp
|
||||
CPPFLAGS = ${BASEFLAGS} -m386 -O2 -w -I. -I../engine -I../common -I../pm_shared -I../../metamod
|
||||
|
||||
OBJ = \
|
||||
agrunt.o \
|
||||
AI_BaseNPC_Schedule.o \
|
||||
animating.o \
|
||||
animation.o \
|
||||
apache.o \
|
||||
barney.o \
|
||||
bigmomma.o \
|
||||
bullsquid.o \
|
||||
cmbase.o \
|
||||
combat.o \
|
||||
controller.o \
|
||||
defaultai.o \
|
||||
dllapi.o \
|
||||
effects.o \
|
||||
ggrenade.o \
|
||||
h_ai.o \
|
||||
h_export.o \
|
||||
hassassin.o \
|
||||
headcrab.o \
|
||||
hgrunt.o \
|
||||
hornet.o \
|
||||
houndeye.o \
|
||||
islave.o \
|
||||
monster_api.o \
|
||||
monster_config.o \
|
||||
monsters.o \
|
||||
monsterstate.o \
|
||||
nodes.o \
|
||||
scientist.o \
|
||||
skill.o \
|
||||
sound.o \
|
||||
squeakgrenade.o \
|
||||
subs.o \
|
||||
talkmonster.o \
|
||||
util.o \
|
||||
weapons.o \
|
||||
zombie.o
|
||||
|
||||
monster_mm_i386.so: ${OBJ}
|
||||
${CPP} -fPIC -shared -o $@ ${OBJ}
|
||||
|
||||
clean:
|
||||
-rm -f *.o
|
||||
-rm -f *.so
|
||||
|
||||
%.o: %.cpp
|
||||
${CPP} ${CPPFLAGS} -c $< -o $@
|
||||
|
||||
%.o: %.c
|
||||
${CPP} ${CPPFLAGS} -c $< -o $@
|
||||
|
||||
109
src/dlls/activity.h
Normal file
109
src/dlls/activity.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
|
||||
#ifndef 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
|
||||
97
src/dlls/activitymap.h
Normal file
97
src/dlls/activitymap.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
|
||||
#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
|
||||
};
|
||||
1100
src/dlls/agrunt.cpp
Normal file
1100
src/dlls/agrunt.cpp
Normal file
File diff suppressed because it is too large
Load Diff
306
src/dlls/animating.cpp
Normal file
306
src/dlls/animating.cpp
Normal file
@@ -0,0 +1,306 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
/*
|
||||
|
||||
===== monsters.cpp ========================================================
|
||||
|
||||
Monster-related utility code
|
||||
|
||||
*/
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "animation.h"
|
||||
|
||||
|
||||
//=========================================================
|
||||
// StudioFrameAdvance - advance the animation frame up to the current time
|
||||
// if an flInterval is passed in, only advance animation that number of seconds
|
||||
//=========================================================
|
||||
float CMBaseAnimating :: 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 CMBaseAnimating :: 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 CMBaseAnimating :: LookupActivityHeaviest ( int activity )
|
||||
{
|
||||
void *pmodel = GET_MODEL_PTR( ENT(pev) );
|
||||
|
||||
return ::LookupActivityHeaviest( pmodel, pev, activity );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
int CMBaseAnimating :: LookupSequence ( const char *label )
|
||||
{
|
||||
void *pmodel = GET_MODEL_PTR( ENT(pev) );
|
||||
|
||||
return ::LookupSequence( pmodel, label );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
void CMBaseAnimating :: 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 CMBaseAnimating :: GetSequenceFlags( )
|
||||
{
|
||||
void *pmodel = GET_MODEL_PTR( ENT(pev) );
|
||||
|
||||
return ::GetSequenceFlags( pmodel, pev );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DispatchAnimEvents
|
||||
//=========================================================
|
||||
void CMBaseAnimating :: 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 CMBaseAnimating :: SetBoneController ( int iController, float flValue )
|
||||
{
|
||||
void *pmodel = GET_MODEL_PTR( ENT(pev) );
|
||||
|
||||
return SetController( pmodel, pev, iController, flValue );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
void CMBaseAnimating :: 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 CMBaseAnimating :: SetBlending ( int iBlender, float flValue )
|
||||
{
|
||||
void *pmodel = GET_MODEL_PTR( ENT(pev) );
|
||||
|
||||
return ::SetBlending( pmodel, pev, iBlender, flValue );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
void CMBaseAnimating :: GetBonePosition ( int iBone, Vector &origin, Vector &angles )
|
||||
{
|
||||
GET_BONE_POSITION( ENT(pev), iBone, origin, angles );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
void CMBaseAnimating :: GetAttachment ( int iAttachment, Vector &origin, Vector &angles )
|
||||
{
|
||||
GET_ATTACHMENT( ENT(pev), iAttachment, origin, angles );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
int CMBaseAnimating :: 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 CMBaseAnimating :: GetAutomovement( Vector &origin, Vector &angles, float flInterval )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CMBaseAnimating :: SetBodygroup( int iGroup, int iValue )
|
||||
{
|
||||
::SetBodygroup( GET_MODEL_PTR( ENT(pev) ), pev, iGroup, iValue );
|
||||
}
|
||||
|
||||
int CMBaseAnimating :: GetBodygroup( int iGroup )
|
||||
{
|
||||
return ::GetBodygroup( GET_MODEL_PTR( ENT(pev) ), pev, iGroup );
|
||||
}
|
||||
|
||||
|
||||
int CMBaseAnimating :: ExtractBbox( int sequence, float *mins, float *maxs )
|
||||
{
|
||||
return ::ExtractBbox( GET_MODEL_PTR( ENT(pev) ), sequence, mins, maxs );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
|
||||
void CMBaseAnimating :: 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;
|
||||
|
||||
if (transformed.x < rmin.x)
|
||||
rmin.x = transformed.x;
|
||||
if (transformed.x > rmax.x)
|
||||
rmax.x = transformed.x;
|
||||
if (transformed.y < rmin.y)
|
||||
rmin.y = transformed.y;
|
||||
if (transformed.y > rmax.y)
|
||||
rmax.y = transformed.y;
|
||||
if (transformed.z < rmin.z)
|
||||
rmin.z = transformed.z;
|
||||
if (transformed.z > rmax.z)
|
||||
rmax.z = transformed.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
rmin.z = 0;
|
||||
rmax.z = rmin.z + 1;
|
||||
UTIL_SetSize( pev, rmin, rmax );
|
||||
}
|
||||
}
|
||||
|
||||
521
src/dlls/animation.cpp
Normal file
521
src/dlls/animation.cpp
Normal file
@@ -0,0 +1,521 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/nowin.h"
|
||||
|
||||
typedef int BOOL;
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
// 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"
|
||||
|
||||
#ifndef ACTIVITY_H
|
||||
#include "activity.h"
|
||||
#endif
|
||||
|
||||
#include "activitymap.h"
|
||||
|
||||
#ifndef ANIMATION_H
|
||||
#include "animation.h"
|
||||
#endif
|
||||
|
||||
#ifndef ENGINECALLBACK_H
|
||||
#include "enginecallback.h"
|
||||
#endif
|
||||
|
||||
extern globalvars_t *gpGlobals;
|
||||
|
||||
#pragma warning( disable : 4244 )
|
||||
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
|
||||
int events = 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);
|
||||
|
||||
// find first controller that matches the index
|
||||
for (int 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 = 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 = 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;
|
||||
}
|
||||
47
src/dlls/animation.h
Normal file
47
src/dlls/animation.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef 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
|
||||
977
src/dlls/apache.cpp
Normal file
977
src/dlls/apache.cpp
Normal file
@@ -0,0 +1,977 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
#ifndef OEM_BUILD
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "weapons.h"
|
||||
#include "nodes.h"
|
||||
#include "effects.h"
|
||||
#include "explode.h"
|
||||
|
||||
|
||||
#define SF_WAITFORTRIGGER (0x04 | 0x40) // UNDONE: Fix!
|
||||
#define SF_NOWRECKAGE 0x08
|
||||
|
||||
void CMApache :: Spawn( void )
|
||||
{
|
||||
Precache( );
|
||||
// motor
|
||||
pev->movetype = MOVETYPE_FLY;
|
||||
pev->solid = SOLID_BBOX;
|
||||
|
||||
SET_MODEL(ENT(pev), "models/apache.mdl");
|
||||
UTIL_SetSize( pev, Vector( -32, -32, -64 ), Vector( 32, 32, 0 ) );
|
||||
UTIL_SetOrigin( pev, pev->origin );
|
||||
|
||||
pev->flags |= FL_MONSTER;
|
||||
pev->takedamage = DAMAGE_AIM;
|
||||
pev->health = gSkillData.apacheHealth;
|
||||
|
||||
m_flFieldOfView = -0.707; // 270 degrees
|
||||
|
||||
pev->sequence = 0;
|
||||
ResetSequenceInfo( );
|
||||
pev->frame = RANDOM_LONG(0, 0xFF);
|
||||
|
||||
InitBoneControllers();
|
||||
|
||||
if (pev->spawnflags & SF_WAITFORTRIGGER)
|
||||
{
|
||||
SetUse( StartupUse );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetThink( HuntThink );
|
||||
SetTouch( FlyTouch );
|
||||
pev->nextthink = gpGlobals->time + 1.0;
|
||||
}
|
||||
|
||||
m_iRockets = 10;
|
||||
m_pBeam = NULL;
|
||||
|
||||
m_pGoalEnt = NULL;
|
||||
m_flGoalSpeed = 0.0f;
|
||||
|
||||
m_flForce = 0.0f;
|
||||
m_flNextRocket = 0.0f;
|
||||
|
||||
Vector m_vecTarget = g_vecZero;
|
||||
Vector m_posTarget = g_vecZero;
|
||||
|
||||
Vector m_vecDesired = g_vecZero;
|
||||
Vector m_posDesired = g_vecZero;
|
||||
|
||||
Vector m_vecGoal = g_vecZero;
|
||||
Vector m_angGun = g_vecZero;
|
||||
|
||||
m_flLastSeen = 0.0f;
|
||||
m_flPrevSeen = 0.0f;
|
||||
|
||||
m_iSoundState = 0;
|
||||
}
|
||||
|
||||
|
||||
void CMApache::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL("models/apache.mdl");
|
||||
|
||||
PRECACHE_SOUND("apache/ap_rotor1.wav");
|
||||
PRECACHE_SOUND("apache/ap_rotor2.wav");
|
||||
PRECACHE_SOUND("apache/ap_rotor3.wav");
|
||||
PRECACHE_SOUND("apache/ap_whine1.wav");
|
||||
|
||||
PRECACHE_SOUND("weapons/mortarhit.wav");
|
||||
|
||||
m_iSpriteTexture = PRECACHE_MODEL( "sprites/white.spr" );
|
||||
|
||||
PRECACHE_SOUND("turret/tu_fire1.wav");
|
||||
|
||||
PRECACHE_MODEL("sprites/lgtning.spr");
|
||||
|
||||
m_iExplode = PRECACHE_MODEL( "sprites/fexplo.spr" );
|
||||
m_iBodyGibs = PRECACHE_MODEL( "models/metalplategibs_green.mdl" );
|
||||
|
||||
CMApacheHVR apache_rocket;
|
||||
apache_rocket.Precache();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMApache::NullThink( void )
|
||||
{
|
||||
StudioFrameAdvance( );
|
||||
pev->nextthink = gpGlobals->time + 0.5;
|
||||
}
|
||||
|
||||
|
||||
void CMApache::StartupUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
SetThink( HuntThink );
|
||||
SetTouch( FlyTouch );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
SetUse( NULL );
|
||||
}
|
||||
|
||||
void CMApache :: Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
pev->movetype = MOVETYPE_TOSS;
|
||||
pev->gravity = 0.3;
|
||||
|
||||
STOP_SOUND( ENT(pev), CHAN_STATIC, "apache/ap_rotor2.wav" );
|
||||
|
||||
UTIL_SetSize( pev, Vector( -32, -32, -64), Vector( 32, 32, 0) );
|
||||
SetThink( DyingThink );
|
||||
SetTouch( CrashTouch );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
pev->health = 0;
|
||||
pev->takedamage = DAMAGE_NO;
|
||||
|
||||
if (pev->spawnflags & SF_NOWRECKAGE)
|
||||
{
|
||||
m_flNextRocket = gpGlobals->time + 4.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flNextRocket = gpGlobals->time + 15.0;
|
||||
}
|
||||
}
|
||||
|
||||
void CMApache :: DyingThink( void )
|
||||
{
|
||||
StudioFrameAdvance( );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
|
||||
pev->avelocity = pev->avelocity * 1.02;
|
||||
|
||||
// still falling?
|
||||
if (m_flNextRocket > gpGlobals->time )
|
||||
{
|
||||
if (g_sModelIndexFireball == 0)
|
||||
g_sModelIndexFireball = PRECACHE_MODEL ("sprites/zerogxplode.spr"); // fireball
|
||||
|
||||
// random explosions
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
|
||||
WRITE_BYTE( TE_EXPLOSION); // This just makes a dynamic light now
|
||||
WRITE_COORD( pev->origin.x + RANDOM_FLOAT( -150, 150 ));
|
||||
WRITE_COORD( pev->origin.y + RANDOM_FLOAT( -150, 150 ));
|
||||
WRITE_COORD( pev->origin.z + RANDOM_FLOAT( -150, -50 ));
|
||||
WRITE_SHORT( g_sModelIndexFireball );
|
||||
WRITE_BYTE( RANDOM_LONG(0,29) + 30 ); // scale * 10
|
||||
WRITE_BYTE( 12 ); // framerate
|
||||
WRITE_BYTE( TE_EXPLFLAG_NONE );
|
||||
MESSAGE_END();
|
||||
|
||||
if (g_sModelIndexSmoke == 0)
|
||||
g_sModelIndexSmoke = PRECACHE_MODEL ("sprites/steam1.spr"); // smoke
|
||||
|
||||
// lots of smoke
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
|
||||
WRITE_BYTE( TE_SMOKE );
|
||||
WRITE_COORD( pev->origin.x + RANDOM_FLOAT( -150, 150 ));
|
||||
WRITE_COORD( pev->origin.y + RANDOM_FLOAT( -150, 150 ));
|
||||
WRITE_COORD( pev->origin.z + RANDOM_FLOAT( -150, -50 ));
|
||||
WRITE_SHORT( g_sModelIndexSmoke );
|
||||
WRITE_BYTE( 100 ); // scale * 10
|
||||
WRITE_BYTE( 10 ); // framerate
|
||||
MESSAGE_END();
|
||||
|
||||
Vector vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5;
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot );
|
||||
WRITE_BYTE( TE_BREAKMODEL);
|
||||
|
||||
// position
|
||||
WRITE_COORD( vecSpot.x );
|
||||
WRITE_COORD( vecSpot.y );
|
||||
WRITE_COORD( vecSpot.z );
|
||||
|
||||
// size
|
||||
WRITE_COORD( 400 );
|
||||
WRITE_COORD( 400 );
|
||||
WRITE_COORD( 132 );
|
||||
|
||||
// velocity
|
||||
WRITE_COORD( pev->velocity.x );
|
||||
WRITE_COORD( pev->velocity.y );
|
||||
WRITE_COORD( pev->velocity.z );
|
||||
|
||||
// randomization
|
||||
WRITE_BYTE( 50 );
|
||||
|
||||
// Model
|
||||
WRITE_SHORT( m_iBodyGibs ); //model id#
|
||||
|
||||
// # of shards
|
||||
WRITE_BYTE( 4 ); // let client decide
|
||||
|
||||
// duration
|
||||
WRITE_BYTE( 30 );// 3.0 seconds
|
||||
|
||||
// flags
|
||||
|
||||
WRITE_BYTE( BREAK_METAL );
|
||||
MESSAGE_END();
|
||||
|
||||
// don't stop it we touch a entity
|
||||
pev->flags &= ~FL_ONGROUND;
|
||||
pev->nextthink = gpGlobals->time + 0.2;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5;
|
||||
|
||||
/*
|
||||
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
|
||||
WRITE_BYTE( TE_EXPLOSION); // This just makes a dynamic light now
|
||||
WRITE_COORD( vecSpot.x );
|
||||
WRITE_COORD( vecSpot.y );
|
||||
WRITE_COORD( vecSpot.z + 300 );
|
||||
WRITE_SHORT( g_sModelIndexFireball );
|
||||
WRITE_BYTE( 250 ); // scale * 10
|
||||
WRITE_BYTE( 8 ); // framerate
|
||||
MESSAGE_END();
|
||||
*/
|
||||
|
||||
// fireball
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot );
|
||||
WRITE_BYTE( TE_SPRITE );
|
||||
WRITE_COORD( vecSpot.x );
|
||||
WRITE_COORD( vecSpot.y );
|
||||
WRITE_COORD( vecSpot.z + 256 );
|
||||
WRITE_SHORT( m_iExplode );
|
||||
WRITE_BYTE( 120 ); // scale * 10
|
||||
WRITE_BYTE( 255 ); // brightness
|
||||
MESSAGE_END();
|
||||
|
||||
// big smoke
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot );
|
||||
WRITE_BYTE( TE_SMOKE );
|
||||
WRITE_COORD( vecSpot.x );
|
||||
WRITE_COORD( vecSpot.y );
|
||||
WRITE_COORD( vecSpot.z + 512 );
|
||||
WRITE_SHORT( g_sModelIndexSmoke );
|
||||
WRITE_BYTE( 250 ); // scale * 10
|
||||
WRITE_BYTE( 5 ); // framerate
|
||||
MESSAGE_END();
|
||||
|
||||
// blast circle
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
|
||||
WRITE_BYTE( TE_BEAMCYLINDER );
|
||||
WRITE_COORD( pev->origin.x);
|
||||
WRITE_COORD( pev->origin.y);
|
||||
WRITE_COORD( pev->origin.z);
|
||||
WRITE_COORD( pev->origin.x);
|
||||
WRITE_COORD( pev->origin.y);
|
||||
WRITE_COORD( pev->origin.z + 2000 ); // reach damage radius over .2 seconds
|
||||
WRITE_SHORT( m_iSpriteTexture );
|
||||
WRITE_BYTE( 0 ); // startframe
|
||||
WRITE_BYTE( 0 ); // framerate
|
||||
WRITE_BYTE( 4 ); // life
|
||||
WRITE_BYTE( 32 ); // width
|
||||
WRITE_BYTE( 0 ); // noise
|
||||
WRITE_BYTE( 255 ); // r, g, b
|
||||
WRITE_BYTE( 255 ); // r, g, b
|
||||
WRITE_BYTE( 192 ); // r, g, b
|
||||
WRITE_BYTE( 128 ); // brightness
|
||||
WRITE_BYTE( 0 ); // speed
|
||||
MESSAGE_END();
|
||||
|
||||
EMIT_SOUND(ENT(pev), CHAN_STATIC, "weapons/mortarhit.wav", 1.0, 0.3);
|
||||
|
||||
RadiusDamage( pev->origin, pev, pev, 300, CLASS_NONE, DMG_BLAST );
|
||||
|
||||
if (/*!(pev->spawnflags & SF_NOWRECKAGE) && */(pev->flags & FL_ONGROUND))
|
||||
{
|
||||
/*jlb
|
||||
CMBaseEntity *pWreckage = Create( "cycler_wreckage", pev->origin, pev->angles );
|
||||
// SET_MODEL( ENT(pWreckage->pev), STRING(pev->model) );
|
||||
UTIL_SetSize( pWreckage->pev, Vector( -200, -200, -128 ), Vector( 200, 200, -32 ) );
|
||||
pWreckage->pev->frame = pev->frame;
|
||||
pWreckage->pev->sequence = pev->sequence;
|
||||
pWreckage->pev->framerate = 0;
|
||||
pWreckage->pev->dmgtime = gpGlobals->time + 5;
|
||||
jlb*/
|
||||
}
|
||||
|
||||
// gibs
|
||||
vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5;
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot );
|
||||
WRITE_BYTE( TE_BREAKMODEL);
|
||||
|
||||
// position
|
||||
WRITE_COORD( vecSpot.x );
|
||||
WRITE_COORD( vecSpot.y );
|
||||
WRITE_COORD( vecSpot.z + 64);
|
||||
|
||||
// size
|
||||
WRITE_COORD( 400 );
|
||||
WRITE_COORD( 400 );
|
||||
WRITE_COORD( 128 );
|
||||
|
||||
// velocity
|
||||
WRITE_COORD( 0 );
|
||||
WRITE_COORD( 0 );
|
||||
WRITE_COORD( 200 );
|
||||
|
||||
// randomization
|
||||
WRITE_BYTE( 30 );
|
||||
|
||||
// Model
|
||||
WRITE_SHORT( m_iBodyGibs ); //model id#
|
||||
|
||||
// # of shards
|
||||
WRITE_BYTE( 200 );
|
||||
|
||||
// duration
|
||||
WRITE_BYTE( 200 );// 10.0 seconds
|
||||
|
||||
// flags
|
||||
|
||||
WRITE_BYTE( BREAK_METAL );
|
||||
MESSAGE_END();
|
||||
|
||||
SetThink( SUB_Remove );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMApache::FlyTouch( edict_t *pOther )
|
||||
{
|
||||
// bounce if we hit something solid
|
||||
if ( pOther->v.solid == SOLID_BSP)
|
||||
{
|
||||
TraceResult tr = UTIL_GetGlobalTrace( );
|
||||
|
||||
// UNDONE, do a real bounce
|
||||
pev->velocity = pev->velocity + tr.vecPlaneNormal * (pev->velocity.Length() + 200);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMApache::CrashTouch( edict_t *pOther )
|
||||
{
|
||||
// only crash if we hit something solid
|
||||
if ( pOther->v.solid == SOLID_BSP)
|
||||
{
|
||||
SetTouch( NULL );
|
||||
m_flNextRocket = gpGlobals->time;
|
||||
pev->nextthink = gpGlobals->time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMApache :: GibMonster( void )
|
||||
{
|
||||
// EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "common/bodysplat.wav", 0.75, ATTN_NORM, 0, 200);
|
||||
}
|
||||
|
||||
|
||||
void CMApache :: HuntThink( void )
|
||||
{
|
||||
StudioFrameAdvance( );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
|
||||
ShowDamage( );
|
||||
|
||||
if ( m_pGoalEnt == NULL && !FStringNull(pev->target) )// this monster has a target
|
||||
{
|
||||
m_pGoalEnt = UTIL_FindEntityByTargetname( NULL, STRING( pev->target ) );
|
||||
if (m_pGoalEnt)
|
||||
{
|
||||
m_posDesired = m_pGoalEnt->v.origin;
|
||||
UTIL_MakeAimVectors( m_pGoalEnt->v.angles );
|
||||
m_vecGoal = gpGlobals->v_forward;
|
||||
}
|
||||
}
|
||||
|
||||
// if (m_hEnemy == NULL)
|
||||
{
|
||||
Look( 4092 );
|
||||
m_hEnemy = BestVisibleEnemy( );
|
||||
}
|
||||
|
||||
// generic speed up
|
||||
if (m_flGoalSpeed < 800)
|
||||
m_flGoalSpeed += 5;
|
||||
|
||||
if (m_hEnemy != NULL)
|
||||
{
|
||||
// ALERT( at_console, "%s\n", STRING( m_hEnemy->pev->classname ) );
|
||||
if (UTIL_FVisible( m_hEnemy, this->edict() ))
|
||||
{
|
||||
if (m_flLastSeen < gpGlobals->time - 5)
|
||||
m_flPrevSeen = gpGlobals->time;
|
||||
m_flLastSeen = gpGlobals->time;
|
||||
m_posTarget = UTIL_Center( m_hEnemy );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hEnemy = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
m_vecTarget = (m_posTarget - pev->origin).Normalize();
|
||||
|
||||
float flLength = (pev->origin - m_posDesired).Length();
|
||||
|
||||
if (m_pGoalEnt)
|
||||
{
|
||||
// ALERT( at_console, "%.0f\n", flLength );
|
||||
|
||||
if (flLength < 128)
|
||||
{
|
||||
m_pGoalEnt = UTIL_FindEntityByTargetname( NULL, STRING( m_pGoalEnt->v.target ) );
|
||||
if (m_pGoalEnt)
|
||||
{
|
||||
m_posDesired = m_pGoalEnt->v.origin;
|
||||
UTIL_MakeAimVectors( m_pGoalEnt->v.angles );
|
||||
m_vecGoal = gpGlobals->v_forward;
|
||||
flLength = (pev->origin - m_posDesired).Length();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_posDesired = pev->origin;
|
||||
}
|
||||
|
||||
if (flLength > 250) // 500
|
||||
{
|
||||
// float flLength2 = (m_posTarget - pev->origin).Length() * (1.5 - DotProduct((m_posTarget - pev->origin).Normalize(), pev->velocity.Normalize() ));
|
||||
// if (flLength2 < flLength)
|
||||
if (m_flLastSeen + 90 > gpGlobals->time && DotProduct( (m_posTarget - pev->origin).Normalize(), (m_posDesired - pev->origin).Normalize( )) > 0.25)
|
||||
{
|
||||
m_vecDesired = (m_posTarget - pev->origin).Normalize( );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vecDesired = (m_posDesired - pev->origin).Normalize( );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vecDesired = m_vecGoal;
|
||||
}
|
||||
|
||||
Flight( );
|
||||
|
||||
// ALERT( at_console, "%.0f %.0f %.0f\n", gpGlobals->time, m_flLastSeen, m_flPrevSeen );
|
||||
if ((m_flLastSeen + 1 > gpGlobals->time) && (m_flPrevSeen + 2 < gpGlobals->time))
|
||||
{
|
||||
if (FireGun( ))
|
||||
{
|
||||
// slow down if we're fireing
|
||||
if (m_flGoalSpeed > 400)
|
||||
m_flGoalSpeed = 400;
|
||||
}
|
||||
}
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
Vector vecEst = (gpGlobals->v_forward * 800 + pev->velocity).Normalize( );
|
||||
// ALERT( at_console, "%d %d %d %4.2f\n", pev->angles.x < 0, DotProduct( pev->velocity, gpGlobals->v_forward ) > -100, m_flNextRocket < gpGlobals->time, DotProduct( m_vecTarget, vecEst ) );
|
||||
|
||||
if ((m_iRockets % 2) == 1)
|
||||
{
|
||||
FireRocket( );
|
||||
m_flNextRocket = gpGlobals->time + 0.5;
|
||||
if (m_iRockets <= 0)
|
||||
{
|
||||
m_flNextRocket = gpGlobals->time + 10;
|
||||
m_iRockets = 10;
|
||||
}
|
||||
}
|
||||
else if (pev->angles.x < 0 && DotProduct( pev->velocity, gpGlobals->v_forward ) > -100 && m_flNextRocket < gpGlobals->time)
|
||||
{
|
||||
if (m_flLastSeen + 60 > gpGlobals->time)
|
||||
{
|
||||
if (m_hEnemy != NULL)
|
||||
{
|
||||
// make sure it's a good shot
|
||||
if (DotProduct( m_vecTarget, vecEst) > .965)
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
UTIL_TraceLine( pev->origin, pev->origin + vecEst * 4096, ignore_monsters, edict(), &tr );
|
||||
if ((tr.vecEndPos - m_posTarget).Length() < 512)
|
||||
FireRocket( );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
UTIL_TraceLine( pev->origin, pev->origin + vecEst * 4096, dont_ignore_monsters, edict(), &tr );
|
||||
// just fire when close
|
||||
if ((tr.vecEndPos - m_posTarget).Length() < 512)
|
||||
FireRocket( );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMApache :: Flight( void )
|
||||
{
|
||||
// tilt model 5 degrees
|
||||
Vector vecAdj = Vector( 5.0, 0, 0 );
|
||||
|
||||
// estimate where I'll be facing in one seconds
|
||||
UTIL_MakeAimVectors( pev->angles + pev->avelocity * 2 + vecAdj);
|
||||
// Vector vecEst1 = pev->origin + pev->velocity + gpGlobals->v_up * m_flForce - Vector( 0, 0, 384 );
|
||||
// float flSide = DotProduct( m_posDesired - vecEst1, gpGlobals->v_right );
|
||||
|
||||
float flSide = DotProduct( m_vecDesired, gpGlobals->v_right );
|
||||
|
||||
if (flSide < 0)
|
||||
{
|
||||
if (pev->avelocity.y < 60)
|
||||
{
|
||||
pev->avelocity.y += 8; // 9 * (3.0/2.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pev->avelocity.y > -60)
|
||||
{
|
||||
pev->avelocity.y -= 8; // 9 * (3.0/2.0);
|
||||
}
|
||||
}
|
||||
pev->avelocity.y *= 0.98;
|
||||
|
||||
// estimate where I'll be in two seconds
|
||||
UTIL_MakeAimVectors( pev->angles + pev->avelocity * 1 + vecAdj);
|
||||
Vector vecEst = pev->origin + pev->velocity * 2.0 + gpGlobals->v_up * m_flForce * 20 - Vector( 0, 0, 384 * 2 );
|
||||
|
||||
// add immediate force
|
||||
UTIL_MakeAimVectors( pev->angles + vecAdj);
|
||||
pev->velocity.x += gpGlobals->v_up.x * m_flForce;
|
||||
pev->velocity.y += gpGlobals->v_up.y * m_flForce;
|
||||
pev->velocity.z += gpGlobals->v_up.z * m_flForce;
|
||||
// add gravity
|
||||
pev->velocity.z -= 38.4; // 32ft/sec
|
||||
|
||||
|
||||
float flSpeed = pev->velocity.Length();
|
||||
float flDir = DotProduct( Vector( gpGlobals->v_forward.x, gpGlobals->v_forward.y, 0 ), Vector( pev->velocity.x, pev->velocity.y, 0 ) );
|
||||
if (flDir < 0)
|
||||
flSpeed = -flSpeed;
|
||||
|
||||
float flDist = DotProduct( m_posDesired - vecEst, gpGlobals->v_forward );
|
||||
|
||||
// float flSlip = DotProduct( pev->velocity, gpGlobals->v_right );
|
||||
float flSlip = -DotProduct( m_posDesired - vecEst, gpGlobals->v_right );
|
||||
|
||||
// fly sideways
|
||||
if (flSlip > 0)
|
||||
{
|
||||
if (pev->angles.z > -30 && pev->avelocity.z > -15)
|
||||
pev->avelocity.z -= 4;
|
||||
else
|
||||
pev->avelocity.z += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (pev->angles.z < 30 && pev->avelocity.z < 15)
|
||||
pev->avelocity.z += 4;
|
||||
else
|
||||
pev->avelocity.z -= 2;
|
||||
}
|
||||
|
||||
// sideways drag
|
||||
pev->velocity.x = pev->velocity.x * (1.0 - fabs( gpGlobals->v_right.x ) * 0.05);
|
||||
pev->velocity.y = pev->velocity.y * (1.0 - fabs( gpGlobals->v_right.y ) * 0.05);
|
||||
pev->velocity.z = pev->velocity.z * (1.0 - fabs( gpGlobals->v_right.z ) * 0.05);
|
||||
|
||||
// general drag
|
||||
pev->velocity = pev->velocity * 0.995;
|
||||
|
||||
// apply power to stay correct height
|
||||
if (m_flForce < 80 && vecEst.z < m_posDesired.z)
|
||||
{
|
||||
m_flForce += 12;
|
||||
}
|
||||
else if (m_flForce > 30)
|
||||
{
|
||||
if (vecEst.z > m_posDesired.z)
|
||||
m_flForce -= 8;
|
||||
}
|
||||
|
||||
// pitch forward or back to get to target
|
||||
if (flDist > 0 && flSpeed < m_flGoalSpeed /* && flSpeed < flDist */ && pev->angles.x + pev->avelocity.x > -40)
|
||||
{
|
||||
// ALERT( at_console, "F " );
|
||||
// lean forward
|
||||
pev->avelocity.x -= 12.0;
|
||||
}
|
||||
else if (flDist < 0 && flSpeed > -50 && pev->angles.x + pev->avelocity.x < 20)
|
||||
{
|
||||
// ALERT( at_console, "B " );
|
||||
// lean backward
|
||||
pev->avelocity.x += 12.0;
|
||||
}
|
||||
else if (pev->angles.x + pev->avelocity.x > 0)
|
||||
{
|
||||
// ALERT( at_console, "f " );
|
||||
pev->avelocity.x -= 4.0;
|
||||
}
|
||||
else if (pev->angles.x + pev->avelocity.x < 0)
|
||||
{
|
||||
// ALERT( at_console, "b " );
|
||||
pev->avelocity.x += 4.0;
|
||||
}
|
||||
|
||||
// ALERT( at_console, "%.0f %.0f : %.0f %.0f : %.0f %.0f : %.0f\n", pev->origin.x, pev->velocity.x, flDist, flSpeed, pev->angles.x, pev->avelocity.x, m_flForce );
|
||||
// ALERT( at_console, "%.0f %.0f : %.0f %0.f : %.0f\n", pev->origin.z, pev->velocity.z, vecEst.z, m_posDesired.z, m_flForce );
|
||||
|
||||
// make rotor, engine sounds
|
||||
if (m_iSoundState == 0)
|
||||
{
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_rotor2.wav", 1.0, 0.3, 0, 110 );
|
||||
// EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_whine1.wav", 0.5, 0.2, 0, 110 );
|
||||
|
||||
m_iSoundState = SND_CHANGE_PITCH; // hack for going through level transitions
|
||||
}
|
||||
else
|
||||
{
|
||||
edict_t *pPlayer = NULL;
|
||||
|
||||
pPlayer = UTIL_FindEntityByClassname( NULL, "player" );
|
||||
// UNDONE: this needs to send different sounds to every player for multiplayer.
|
||||
if (pPlayer)
|
||||
{
|
||||
|
||||
float pitch = DotProduct( pev->velocity - pPlayer->v.velocity, (pPlayer->v.origin - pev->origin).Normalize() );
|
||||
|
||||
pitch = (int)(100 + pitch / 50.0);
|
||||
|
||||
if (pitch > 250)
|
||||
pitch = 250;
|
||||
if (pitch < 50)
|
||||
pitch = 50;
|
||||
if (pitch == 100)
|
||||
pitch = 101;
|
||||
|
||||
float flVol = (m_flForce / 100.0) + .1;
|
||||
if (flVol > 1.0)
|
||||
flVol = 1.0;
|
||||
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_rotor2.wav", 1.0, 0.3, SND_CHANGE_PITCH | SND_CHANGE_VOL, pitch);
|
||||
}
|
||||
// EMIT_SOUND_DYN(ENT(pev), CHAN_STATIC, "apache/ap_whine1.wav", flVol, 0.2, SND_CHANGE_PITCH | SND_CHANGE_VOL, pitch);
|
||||
|
||||
// ALERT( at_console, "%.0f %.2f\n", pitch, flVol );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMApache :: FireRocket( void )
|
||||
{
|
||||
static float side = 1.0;
|
||||
static int count;
|
||||
|
||||
if (m_iRockets <= 0)
|
||||
return;
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
Vector vecSrc = pev->origin + 1.5 * (gpGlobals->v_forward * 21 + gpGlobals->v_right * 70 * side + gpGlobals->v_up * -79);
|
||||
|
||||
switch( m_iRockets % 5)
|
||||
{
|
||||
case 0: vecSrc = vecSrc + gpGlobals->v_right * 10; break;
|
||||
case 1: vecSrc = vecSrc - gpGlobals->v_right * 10; break;
|
||||
case 2: vecSrc = vecSrc + gpGlobals->v_up * 10; break;
|
||||
case 3: vecSrc = vecSrc - gpGlobals->v_up * 10; break;
|
||||
case 4: break;
|
||||
}
|
||||
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
|
||||
WRITE_BYTE( TE_SMOKE );
|
||||
WRITE_COORD( vecSrc.x );
|
||||
WRITE_COORD( vecSrc.y );
|
||||
WRITE_COORD( vecSrc.z );
|
||||
WRITE_SHORT( g_sModelIndexSmoke );
|
||||
WRITE_BYTE( 20 ); // scale * 10
|
||||
WRITE_BYTE( 12 ); // framerate
|
||||
MESSAGE_END();
|
||||
|
||||
//jlb CMBaseEntity *pRocket = CMBaseEntity::Create( "hvr_rocket", vecSrc, pev->angles, edict() );
|
||||
CMApacheHVR *pRocket = CreateClassPtr((CMApacheHVR *)NULL);
|
||||
|
||||
if (pRocket)
|
||||
{
|
||||
pRocket->pev->origin = vecSrc;
|
||||
pRocket->pev->angles = pev->angles;
|
||||
pRocket->pev->owner = edict();
|
||||
|
||||
// Initialize these for entities who don't link to the world
|
||||
pRocket->pev->absmin = pRocket->pev->origin - Vector(1,1,1);
|
||||
pRocket->pev->absmax = pRocket->pev->origin + Vector(1,1,1);
|
||||
|
||||
pRocket->Spawn();
|
||||
|
||||
pRocket->pev->velocity = pev->velocity + gpGlobals->v_forward * 100;
|
||||
}
|
||||
|
||||
m_iRockets--;
|
||||
|
||||
side = - side;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL CMApache :: FireGun( )
|
||||
{
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
|
||||
Vector posGun, angGun;
|
||||
GetAttachment( 1, posGun, angGun );
|
||||
|
||||
Vector vecTarget = (m_posTarget - posGun).Normalize( );
|
||||
|
||||
Vector vecOut;
|
||||
|
||||
vecOut.x = DotProduct( gpGlobals->v_forward, vecTarget );
|
||||
vecOut.y = -DotProduct( gpGlobals->v_right, vecTarget );
|
||||
vecOut.z = DotProduct( gpGlobals->v_up, vecTarget );
|
||||
|
||||
Vector angles = UTIL_VecToAngles (vecOut);
|
||||
|
||||
angles.x = -angles.x;
|
||||
if (angles.y > 180)
|
||||
angles.y = angles.y - 360;
|
||||
if (angles.y < -180)
|
||||
angles.y = angles.y + 360;
|
||||
if (angles.x > 180)
|
||||
angles.x = angles.x - 360;
|
||||
if (angles.x < -180)
|
||||
angles.x = angles.x + 360;
|
||||
|
||||
if (angles.x > m_angGun.x)
|
||||
m_angGun.x = min( angles.x, m_angGun.x + 12 );
|
||||
if (angles.x < m_angGun.x)
|
||||
m_angGun.x = max( angles.x, m_angGun.x - 12 );
|
||||
if (angles.y > m_angGun.y)
|
||||
m_angGun.y = min( angles.y, m_angGun.y + 12 );
|
||||
if (angles.y < m_angGun.y)
|
||||
m_angGun.y = max( angles.y, m_angGun.y - 12 );
|
||||
|
||||
m_angGun.y = SetBoneController( 0, m_angGun.y );
|
||||
m_angGun.x = SetBoneController( 1, m_angGun.x );
|
||||
|
||||
Vector posBarrel, angBarrel;
|
||||
GetAttachment( 0, posBarrel, angBarrel );
|
||||
Vector vecGun = (posBarrel - posGun).Normalize( );
|
||||
|
||||
if (DotProduct( vecGun, vecTarget ) > 0.98)
|
||||
{
|
||||
#if 1
|
||||
FireBullets( 1, posGun, vecGun, VECTOR_CONE_4DEGREES, 8192, BULLET_MONSTER_12MM, 1 );
|
||||
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "turret/tu_fire1.wav", 1, 0.3);
|
||||
#else
|
||||
static float flNext;
|
||||
TraceResult tr;
|
||||
UTIL_TraceLine( posGun, posGun + vecGun * 8192, dont_ignore_monsters, ENT( pev ), &tr );
|
||||
|
||||
if (!m_pBeam)
|
||||
{
|
||||
m_pBeam = CBeam::BeamCreate( "sprites/lgtning.spr", 80 );
|
||||
m_pBeam->PointEntInit( pev->origin, entindex( ) );
|
||||
m_pBeam->SetEndAttachment( 1 );
|
||||
m_pBeam->SetColor( 255, 180, 96 );
|
||||
m_pBeam->SetBrightness( 192 );
|
||||
}
|
||||
|
||||
if (flNext < gpGlobals->time)
|
||||
{
|
||||
flNext = gpGlobals->time + 0.5;
|
||||
m_pBeam->SetStartPos( tr.vecEndPos );
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_pBeam)
|
||||
{
|
||||
UTIL_Remove( m_pBeam->edict() );
|
||||
m_pBeam = NULL;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMApache :: ShowDamage( void )
|
||||
{
|
||||
if (m_iDoSmokePuff > 0 || RANDOM_LONG(0,99) > pev->health)
|
||||
{
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
|
||||
WRITE_BYTE( TE_SMOKE );
|
||||
WRITE_COORD( pev->origin.x );
|
||||
WRITE_COORD( pev->origin.y );
|
||||
WRITE_COORD( pev->origin.z - 32 );
|
||||
WRITE_SHORT( g_sModelIndexSmoke );
|
||||
WRITE_BYTE( RANDOM_LONG(0,9) + 20 ); // scale * 10
|
||||
WRITE_BYTE( 12 ); // framerate
|
||||
MESSAGE_END();
|
||||
}
|
||||
if (m_iDoSmokePuff > 0)
|
||||
m_iDoSmokePuff--;
|
||||
}
|
||||
|
||||
|
||||
int CMApache :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType )
|
||||
{
|
||||
if (pevInflictor->owner == edict())
|
||||
return 0;
|
||||
|
||||
if (bitsDamageType & DMG_BLAST)
|
||||
{
|
||||
flDamage *= 2;
|
||||
}
|
||||
|
||||
/*
|
||||
if ( (bitsDamageType & DMG_BULLET) && flDamage > 50)
|
||||
{
|
||||
// clip bullet damage at 50
|
||||
flDamage = 50;
|
||||
}
|
||||
*/
|
||||
|
||||
// ALERT( at_console, "%.0f\n", flDamage );
|
||||
return CMBaseEntity::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMApache::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
|
||||
{
|
||||
// ALERT( at_console, "%d %.0f\n", ptr->iHitgroup, flDamage );
|
||||
|
||||
// ignore blades
|
||||
if (ptr->iHitgroup == 6 && (bitsDamageType & (DMG_ENERGYBEAM|DMG_BULLET|DMG_CLUB)))
|
||||
return;
|
||||
|
||||
// hit hard, hits cockpit, hits engines
|
||||
if (flDamage > 50 || ptr->iHitgroup == 1 || ptr->iHitgroup == 2)
|
||||
{
|
||||
// ALERT( at_console, "%.0f\n", flDamage );
|
||||
AddMultiDamage( pevAttacker, this->edict(), flDamage, bitsDamageType );
|
||||
m_iDoSmokePuff = 3 + (flDamage / 5.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// do half damage in the body
|
||||
// AddMultiDamage( pevAttacker, this, flDamage / 2.0, bitsDamageType );
|
||||
UTIL_Ricochet( ptr->vecEndPos, 2.0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMApacheHVR :: Spawn( void )
|
||||
{
|
||||
Precache( );
|
||||
// motor
|
||||
pev->movetype = MOVETYPE_FLY;
|
||||
pev->solid = SOLID_BBOX;
|
||||
|
||||
SET_MODEL(ENT(pev), "models/HVR.mdl");
|
||||
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
|
||||
UTIL_SetOrigin( pev, pev->origin );
|
||||
|
||||
SetThink( IgniteThink );
|
||||
SetTouch( ExplodeTouch );
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
m_vecForward = gpGlobals->v_forward;
|
||||
pev->gravity = 0.5;
|
||||
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
|
||||
pev->dmg = 150;
|
||||
}
|
||||
|
||||
|
||||
void CMApacheHVR :: Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL("models/HVR.mdl");
|
||||
m_iTrail = PRECACHE_MODEL("sprites/smoke.spr");
|
||||
PRECACHE_SOUND ("weapons/rocket1.wav");
|
||||
}
|
||||
|
||||
|
||||
void CMApacheHVR :: IgniteThink( void )
|
||||
{
|
||||
// pev->movetype = MOVETYPE_TOSS;
|
||||
|
||||
// pev->movetype = MOVETYPE_FLY;
|
||||
pev->effects |= EF_LIGHT;
|
||||
|
||||
// make rocket sound
|
||||
EMIT_SOUND( ENT(pev), CHAN_VOICE, "weapons/rocket1.wav", 1, 0.5 );
|
||||
|
||||
// rocket trail
|
||||
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
|
||||
|
||||
WRITE_BYTE( TE_BEAMFOLLOW );
|
||||
WRITE_SHORT(entindex()); // entity
|
||||
WRITE_SHORT(m_iTrail ); // model
|
||||
WRITE_BYTE( 15 ); // life
|
||||
WRITE_BYTE( 5 ); // width
|
||||
WRITE_BYTE( 224 ); // r, g, b
|
||||
WRITE_BYTE( 224 ); // r, g, b
|
||||
WRITE_BYTE( 255 ); // r, g, b
|
||||
WRITE_BYTE( 255 ); // brightness
|
||||
|
||||
MESSAGE_END(); // move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS)
|
||||
|
||||
// set to accelerate
|
||||
SetThink( AccelerateThink );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
}
|
||||
|
||||
|
||||
void CMApacheHVR :: AccelerateThink( void )
|
||||
{
|
||||
// check world boundaries
|
||||
if (pev->origin.x < -4096 || pev->origin.x > 4096 || pev->origin.y < -4096 || pev->origin.y > 4096 || pev->origin.z < -4096 || pev->origin.z > 4096)
|
||||
{
|
||||
UTIL_Remove( this->edict() );
|
||||
return;
|
||||
}
|
||||
|
||||
// accelerate
|
||||
float flSpeed = pev->velocity.Length();
|
||||
if (flSpeed < 1800)
|
||||
{
|
||||
pev->velocity = pev->velocity + m_vecForward * 200;
|
||||
}
|
||||
|
||||
// re-aim
|
||||
pev->angles = UTIL_VecToAngles( pev->velocity );
|
||||
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
666
src/dlls/barney.cpp
Normal file
666
src/dlls/barney.cpp
Normal file
@@ -0,0 +1,666 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// monster template
|
||||
//=========================================================
|
||||
// UNDONE: Holster weapon?
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "schedule.h"
|
||||
#include "defaultai.h"
|
||||
#include "weapons.h"
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
// first flag is barney dying for scripted sequences?
|
||||
#define BARNEY_AE_DRAW ( 2 )
|
||||
#define BARNEY_AE_SHOOT ( 3 )
|
||||
#define BARNEY_AE_HOLSTER ( 4 )
|
||||
|
||||
#define BARNEY_BODY_GUNHOLSTERED 0
|
||||
#define BARNEY_BODY_GUNDRAWN 1
|
||||
#define BARNEY_BODY_GUNGONE 2
|
||||
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
Task_t tlBaFollow[] =
|
||||
{
|
||||
{ TASK_MOVE_TO_TARGET_RANGE,(float)128 }, // Move within 128 of target ent (client)
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE },
|
||||
};
|
||||
|
||||
Schedule_t slBaFollow[] =
|
||||
{
|
||||
{
|
||||
tlBaFollow,
|
||||
ARRAYSIZE ( tlBaFollow ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_PROVOKED,
|
||||
0,
|
||||
"Follow"
|
||||
},
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// BarneyDraw- much better looking draw schedule for when
|
||||
// barney knows who he's gonna attack.
|
||||
//=========================================================
|
||||
Task_t tlBarneyEnemyDraw[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_FACE_ENEMY, 0 },
|
||||
{ TASK_PLAY_SEQUENCE_FACE_ENEMY, (float) ACT_ARM },
|
||||
};
|
||||
|
||||
Schedule_t slBarneyEnemyDraw[] =
|
||||
{
|
||||
{
|
||||
tlBarneyEnemyDraw,
|
||||
ARRAYSIZE ( tlBarneyEnemyDraw ),
|
||||
0,
|
||||
0,
|
||||
"Barney Enemy Draw"
|
||||
}
|
||||
};
|
||||
|
||||
Task_t tlBaFaceTarget[] =
|
||||
{
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_FACE_TARGET, (float)0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_CHASE },
|
||||
};
|
||||
|
||||
Schedule_t slBaFaceTarget[] =
|
||||
{
|
||||
{
|
||||
tlBaFaceTarget,
|
||||
ARRAYSIZE ( tlBaFaceTarget ),
|
||||
bits_COND_CLIENT_PUSH |
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_PROVOKED,
|
||||
0,
|
||||
"FaceTarget"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Task_t tlIdleBaStand[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_WAIT, (float)2 }, // repick IDLESTAND every two seconds.
|
||||
{ TASK_TLK_HEADRESET, (float)0 }, // reset head position
|
||||
};
|
||||
|
||||
Schedule_t slIdleBaStand[] =
|
||||
{
|
||||
{
|
||||
tlIdleBaStand,
|
||||
ARRAYSIZE ( tlIdleBaStand ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_SMELL |
|
||||
bits_COND_PROVOKED,
|
||||
|
||||
0,
|
||||
"IdleStand"
|
||||
},
|
||||
};
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CMBarney )
|
||||
{
|
||||
slBaFollow,
|
||||
slBarneyEnemyDraw,
|
||||
slBaFaceTarget,
|
||||
slIdleBaStand,
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CUSTOM_SCHEDULES( CMBarney, CMTalkMonster );
|
||||
|
||||
void CMBarney :: StartTask( Task_t *pTask )
|
||||
{
|
||||
CMTalkMonster::StartTask( pTask );
|
||||
}
|
||||
|
||||
void CMBarney :: RunTask( Task_t *pTask )
|
||||
{
|
||||
switch ( pTask->iTask )
|
||||
{
|
||||
case TASK_RANGE_ATTACK1:
|
||||
if (m_hEnemy != NULL && (UTIL_IsPlayer(m_hEnemy)))
|
||||
{
|
||||
pev->framerate = 1.5;
|
||||
}
|
||||
CMTalkMonster::RunTask( pTask );
|
||||
break;
|
||||
default:
|
||||
CMTalkMonster::RunTask( pTask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ISoundMask - returns a bit mask indicating which types
|
||||
// of sounds this monster regards.
|
||||
//=========================================================
|
||||
int CMBarney :: ISoundMask ( void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CMBarney :: Classify ( void )
|
||||
{
|
||||
return CLASS_PLAYER_ALLY;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ALertSound - barney says "Freeze!"
|
||||
//=========================================================
|
||||
void CMBarney :: AlertSound( void )
|
||||
{
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
if ( FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "BA_ATTACK", RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CMBarney :: SetYawSpeed ( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
ys = 0;
|
||||
|
||||
switch ( m_Activity )
|
||||
{
|
||||
case ACT_IDLE:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_WALK:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_RUN:
|
||||
ys = 90;
|
||||
break;
|
||||
default:
|
||||
ys = 70;
|
||||
break;
|
||||
}
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack1
|
||||
//=========================================================
|
||||
BOOL CMBarney :: CheckRangeAttack1 ( float flDot, float flDist )
|
||||
{
|
||||
if ( flDist <= 1024 && flDot >= 0.5 )
|
||||
{
|
||||
if ( gpGlobals->time > m_checkAttackTime )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
Vector shootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
|
||||
edict_t *pEnemy = m_hEnemy;
|
||||
|
||||
Vector shootTarget = ( (UTIL_BodyTarget( pEnemy, shootOrigin ) - pEnemy->v.origin) + m_vecEnemyLKP );
|
||||
|
||||
UTIL_TraceLine( shootOrigin, shootTarget, dont_ignore_monsters, ENT(pev), &tr );
|
||||
|
||||
m_checkAttackTime = gpGlobals->time + 1;
|
||||
|
||||
if ( tr.flFraction == 1.0 || (tr.pHit != NULL) && (tr.pHit == pEnemy) )
|
||||
m_lastAttackCheck = TRUE;
|
||||
else
|
||||
m_lastAttackCheck = FALSE;
|
||||
|
||||
m_checkAttackTime = gpGlobals->time + 1.5;
|
||||
}
|
||||
return m_lastAttackCheck;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// BarneyFirePistol - shoots one round from the pistol at
|
||||
// the enemy barney is facing.
|
||||
//=========================================================
|
||||
void CMBarney :: BarneyFirePistol ( void )
|
||||
{
|
||||
Vector vecShootOrigin;
|
||||
|
||||
UTIL_MakeVectors(pev->angles);
|
||||
vecShootOrigin = pev->origin + Vector( 0, 0, 55 );
|
||||
Vector vecShootDir = ShootAtEnemy( vecShootOrigin );
|
||||
|
||||
Vector angDir = UTIL_VecToAngles( vecShootDir );
|
||||
SetBlending( 0, angDir.x );
|
||||
pev->effects = EF_MUZZLEFLASH;
|
||||
|
||||
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_9MM );
|
||||
|
||||
int pitchShift = RANDOM_LONG( 0, 20 );
|
||||
|
||||
// Only shift about half the time
|
||||
if ( pitchShift > 10 )
|
||||
pitchShift = 0;
|
||||
else
|
||||
pitchShift -= 5;
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "barney/ba_attack2.wav", 1, ATTN_NORM, 0, 100 + pitchShift );
|
||||
|
||||
// UNDONE: Reload?
|
||||
m_cAmmoLoaded--;// take away a bullet!
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CMBarney :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case BARNEY_AE_SHOOT:
|
||||
BarneyFirePistol();
|
||||
break;
|
||||
|
||||
case BARNEY_AE_DRAW:
|
||||
// barney's bodygroup switches here so he can pull gun from holster
|
||||
pev->body = BARNEY_BODY_GUNDRAWN;
|
||||
m_fGunDrawn = TRUE;
|
||||
break;
|
||||
|
||||
case BARNEY_AE_HOLSTER:
|
||||
// change bodygroup to replace gun in holster
|
||||
pev->body = BARNEY_BODY_GUNHOLSTERED;
|
||||
m_fGunDrawn = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
CMTalkMonster::HandleAnimEvent( pEvent );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CMBarney :: Spawn()
|
||||
{
|
||||
Precache( );
|
||||
|
||||
// every new barney must call this, otherwise
|
||||
// when a level is loaded, nobody will talk (time is reset to 0)
|
||||
TalkInit();
|
||||
|
||||
SET_MODEL(ENT(pev), "models/barney.mdl");
|
||||
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
|
||||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
pev->health = gSkillData.barneyHealth;
|
||||
pev->view_ofs = Vector ( 0, 0, 50 );// position of the eyes relative to monster's origin.
|
||||
m_flFieldOfView = VIEW_FIELD_FULL;
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
pev->body = 0; // gun in holster
|
||||
m_fGunDrawn = FALSE;
|
||||
|
||||
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
|
||||
|
||||
MonsterInit();
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CMBarney :: Precache()
|
||||
{
|
||||
PRECACHE_MODEL("models/barney.mdl");
|
||||
|
||||
PRECACHE_SOUND("barney/ba_attack1.wav" );
|
||||
PRECACHE_SOUND("barney/ba_attack2.wav" );
|
||||
|
||||
PRECACHE_SOUND("barney/ba_pain1.wav");
|
||||
PRECACHE_SOUND("barney/ba_pain2.wav");
|
||||
PRECACHE_SOUND("barney/ba_pain3.wav");
|
||||
|
||||
PRECACHE_SOUND("barney/ba_die1.wav");
|
||||
PRECACHE_SOUND("barney/ba_die2.wav");
|
||||
PRECACHE_SOUND("barney/ba_die3.wav");
|
||||
|
||||
CMTalkMonster::Precache();
|
||||
}
|
||||
|
||||
// Init talk data
|
||||
void CMBarney :: TalkInit()
|
||||
{
|
||||
CMTalkMonster::TalkInit();
|
||||
|
||||
// scientists speach group names (group names are in sentences.txt)
|
||||
|
||||
m_szGrp[TLK_ANSWER] = "BA_ANSWER";
|
||||
m_szGrp[TLK_QUESTION] = "BA_QUESTION";
|
||||
m_szGrp[TLK_IDLE] = "BA_IDLE";
|
||||
m_szGrp[TLK_STARE] = "BA_STARE";
|
||||
m_szGrp[TLK_USE] = "BA_OK";
|
||||
m_szGrp[TLK_UNUSE] = "BA_WAIT";
|
||||
m_szGrp[TLK_STOP] = "BA_STOP";
|
||||
|
||||
m_szGrp[TLK_NOSHOOT] = "BA_SCARED";
|
||||
m_szGrp[TLK_HELLO] = "BA_HELLO";
|
||||
|
||||
m_szGrp[TLK_PLHURT1] = "!BA_CUREA";
|
||||
m_szGrp[TLK_PLHURT2] = "!BA_CUREB";
|
||||
m_szGrp[TLK_PLHURT3] = "!BA_CUREC";
|
||||
|
||||
m_szGrp[TLK_PHELLO] = NULL; //"BA_PHELLO"; // UNDONE
|
||||
m_szGrp[TLK_PIDLE] = NULL; //"BA_PIDLE"; // UNDONE
|
||||
m_szGrp[TLK_PQUESTION] = "BA_PQUEST"; // UNDONE
|
||||
|
||||
m_szGrp[TLK_SMELL] = "BA_SMELL";
|
||||
|
||||
m_szGrp[TLK_WOUND] = "BA_WOUND";
|
||||
m_szGrp[TLK_MORTAL] = "BA_MORTAL";
|
||||
|
||||
// get voice for head - just one barney voice for now
|
||||
m_voicePitch = 100;
|
||||
}
|
||||
|
||||
|
||||
static BOOL IsFacing( entvars_t *pevTest, const Vector &reference )
|
||||
{
|
||||
Vector vecDir = (reference - pevTest->origin);
|
||||
vecDir.z = 0;
|
||||
vecDir = vecDir.Normalize();
|
||||
Vector forward, angle;
|
||||
angle = pevTest->v_angle;
|
||||
angle.x = 0;
|
||||
UTIL_MakeVectorsPrivate( angle, forward, NULL, NULL );
|
||||
// He's facing me, he meant it
|
||||
if ( DotProduct( forward, vecDir ) > 0.96 ) // +/- 15 degrees or so
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
int CMBarney :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType)
|
||||
{
|
||||
// make sure friends talk about it if player hurts talkmonsters...
|
||||
int ret = CMTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
|
||||
if ( !IsAlive() || pev->deadflag == DEAD_DYING )
|
||||
return ret;
|
||||
|
||||
if ( m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT) )
|
||||
{
|
||||
// This is a heurstic to determine if the player intended to harm me
|
||||
// If I have an enemy, we can't establish intent (may just be crossfire)
|
||||
if ( ( m_hEnemy != NULL ) && UTIL_IsPlayer(m_hEnemy) )
|
||||
{
|
||||
Remember( bits_MEMORY_PROVOKED );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// PainSound
|
||||
//=========================================================
|
||||
void CMBarney :: PainSound ( void )
|
||||
{
|
||||
if (gpGlobals->time < m_painTime)
|
||||
return;
|
||||
|
||||
m_painTime = gpGlobals->time + RANDOM_FLOAT(0.5, 0.75);
|
||||
|
||||
switch (RANDOM_LONG(0,2))
|
||||
{
|
||||
case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DeathSound
|
||||
//=========================================================
|
||||
void CMBarney :: DeathSound ( void )
|
||||
{
|
||||
switch (RANDOM_LONG(0,2))
|
||||
{
|
||||
case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMBarney::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
|
||||
{
|
||||
switch( ptr->iHitgroup)
|
||||
{
|
||||
case HITGROUP_CHEST:
|
||||
case HITGROUP_STOMACH:
|
||||
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST))
|
||||
{
|
||||
flDamage = flDamage / 2;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_CLUB))
|
||||
{
|
||||
flDamage -= 20;
|
||||
if (flDamage <= 0)
|
||||
{
|
||||
UTIL_Ricochet( ptr->vecEndPos, 1.0 );
|
||||
flDamage = 0.01;
|
||||
}
|
||||
}
|
||||
// always a head shot
|
||||
ptr->iHitgroup = HITGROUP_HEAD;
|
||||
break;
|
||||
}
|
||||
|
||||
CMTalkMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
|
||||
}
|
||||
|
||||
|
||||
void CMBarney::Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
if ( pev->body < BARNEY_BODY_GUNGONE )
|
||||
{// drop the gun!
|
||||
Vector vecGunPos;
|
||||
Vector vecGunAngles;
|
||||
|
||||
pev->body = BARNEY_BODY_GUNGONE;
|
||||
|
||||
GetAttachment( 0, vecGunPos, vecGunAngles );
|
||||
}
|
||||
|
||||
SetUse( NULL );
|
||||
CMTalkMonster::Killed( pevAttacker, iGib );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
|
||||
Schedule_t* CMBarney :: GetScheduleOfType ( int Type )
|
||||
{
|
||||
Schedule_t *psched;
|
||||
|
||||
switch( Type )
|
||||
{
|
||||
case SCHED_ARM_WEAPON:
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
// face enemy, then draw.
|
||||
return slBarneyEnemyDraw;
|
||||
}
|
||||
break;
|
||||
|
||||
// Hook these to make a looping schedule
|
||||
case SCHED_TARGET_FACE:
|
||||
// call base class default so that barney will talk
|
||||
// when 'used'
|
||||
psched = CMTalkMonster::GetScheduleOfType(Type);
|
||||
|
||||
if (psched == slIdleStand)
|
||||
return slBaFaceTarget; // override this for different target face behavior
|
||||
else
|
||||
return psched;
|
||||
|
||||
case SCHED_TARGET_CHASE:
|
||||
return slBaFollow;
|
||||
|
||||
case SCHED_IDLE_STAND:
|
||||
// call base class default so that scientist will talk
|
||||
// when standing during idle
|
||||
psched = CMTalkMonster::GetScheduleOfType(Type);
|
||||
|
||||
if (psched == slIdleStand)
|
||||
{
|
||||
// just look straight ahead.
|
||||
return slIdleBaStand;
|
||||
}
|
||||
else
|
||||
return psched;
|
||||
}
|
||||
|
||||
return CMTalkMonster::GetScheduleOfType( Type );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// GetSchedule - Decides which type of schedule best suits
|
||||
// the monster's current state and conditions. Then calls
|
||||
// monster's member function to get a pointer to a schedule
|
||||
// of the proper type.
|
||||
//=========================================================
|
||||
Schedule_t *CMBarney :: GetSchedule ( void )
|
||||
{
|
||||
if ( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak() )
|
||||
{
|
||||
PlaySentence( "BA_KILL", 4, VOL_NORM, ATTN_NORM );
|
||||
}
|
||||
|
||||
switch( m_MonsterState )
|
||||
{
|
||||
case MONSTERSTATE_COMBAT:
|
||||
{
|
||||
// dead enemy
|
||||
if ( HasConditions( bits_COND_ENEMY_DEAD ) )
|
||||
{
|
||||
// call base class, all code to handle dead enemies is centralized there.
|
||||
return CMBaseMonster :: GetSchedule();
|
||||
}
|
||||
|
||||
// always act surprized with a new enemy
|
||||
if ( HasConditions( bits_COND_NEW_ENEMY ) && HasConditions( bits_COND_LIGHT_DAMAGE) )
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
|
||||
// wait for one schedule to draw gun
|
||||
if (!m_fGunDrawn )
|
||||
return GetScheduleOfType( SCHED_ARM_WEAPON );
|
||||
|
||||
if ( HasConditions( bits_COND_HEAVY_DAMAGE ) )
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
}
|
||||
break;
|
||||
|
||||
case MONSTERSTATE_ALERT:
|
||||
case MONSTERSTATE_IDLE:
|
||||
if ( HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE))
|
||||
{
|
||||
// flinch if hurt
|
||||
return GetScheduleOfType( SCHED_SMALL_FLINCH );
|
||||
}
|
||||
|
||||
if ( m_hEnemy == NULL && IsFollowing() )
|
||||
{
|
||||
if ( !UTIL_IsAlive(m_hTargetEnt) )
|
||||
{
|
||||
// UNDONE: Comment about the recently dead player here?
|
||||
StopFollowing( FALSE );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY_FOLLOW );
|
||||
}
|
||||
return GetScheduleOfType( SCHED_TARGET_FACE );
|
||||
}
|
||||
}
|
||||
|
||||
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
|
||||
{
|
||||
return GetScheduleOfType( SCHED_MOVE_AWAY );
|
||||
}
|
||||
|
||||
// try to say something about smells
|
||||
TrySmellTalk();
|
||||
break;
|
||||
}
|
||||
|
||||
return CMTalkMonster::GetSchedule();
|
||||
}
|
||||
|
||||
MONSTERSTATE CMBarney :: GetIdealState ( void )
|
||||
{
|
||||
return CMTalkMonster::GetIdealState();
|
||||
}
|
||||
|
||||
|
||||
1194
src/dlls/bigmomma.cpp
Normal file
1194
src/dlls/bigmomma.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1174
src/dlls/bullsquid.cpp
Normal file
1174
src/dlls/bullsquid.cpp
Normal file
File diff suppressed because it is too large
Load Diff
46
src/dlls/cdll_dll.h
Normal file
46
src/dlls/cdll_dll.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// 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 32 // ???
|
||||
|
||||
#define MAX_WEAPON_SLOTS 5 // 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
|
||||
306
src/dlls/cmbase.cpp
Normal file
306
src/dlls/cmbase.cpp
Normal file
@@ -0,0 +1,306 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "decals.h"
|
||||
|
||||
extern Vector VecBModelOrigin( entvars_t* pevBModel );
|
||||
extern DLL_GLOBAL Vector g_vecAttackDir;
|
||||
|
||||
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 edict_t *()
|
||||
{
|
||||
return Get( );
|
||||
};
|
||||
|
||||
|
||||
edict_t * EHANDLE :: operator = (edict_t *pEntity)
|
||||
{
|
||||
if (pEntity)
|
||||
{
|
||||
m_pent = pEntity;
|
||||
if (m_pent)
|
||||
m_serialnumber = m_pent->serialnumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pent = NULL;
|
||||
m_serialnumber = 0;
|
||||
}
|
||||
return pEntity;
|
||||
}
|
||||
|
||||
|
||||
edict_t * EHANDLE :: operator -> ()
|
||||
{
|
||||
return Get( );
|
||||
}
|
||||
|
||||
|
||||
void *CMBaseEntity::operator new( size_t stAllocateBlock )
|
||||
{
|
||||
void *mem = ::operator new( stAllocateBlock );
|
||||
memset( mem, 0, stAllocateBlock );
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
edict_t *CMBaseEntity::CreateEntity(char *classname)
|
||||
{
|
||||
int istr = MAKE_STRING(classname);
|
||||
|
||||
edict_t *pent = CREATE_NAMED_ENTITY(istr);
|
||||
|
||||
if ( FNullEnt( pent ) )
|
||||
return NULL;
|
||||
|
||||
pev = VARS(pent);
|
||||
|
||||
pev->movetype = MOVETYPE_NONE;
|
||||
pev->solid = SOLID_NOT;
|
||||
pev->flags = 0;
|
||||
|
||||
m_pfnThink = NULL;
|
||||
m_pfnTouch = NULL;
|
||||
m_pfnUse = NULL;
|
||||
m_pfnBlocked = NULL;
|
||||
|
||||
pev->euser4 = (edict_t *)this;
|
||||
|
||||
return pent;
|
||||
}
|
||||
|
||||
// give health
|
||||
int CMBaseEntity :: 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 CMBaseEntity :: 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 = pevInflictor->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 CMBaseEntity :: Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
pev->takedamage = DAMAGE_NO;
|
||||
pev->deadflag = DEAD_DEAD;
|
||||
UTIL_Remove( this->edict() );
|
||||
}
|
||||
|
||||
|
||||
// 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( ((float *)pev->mins)[i]);
|
||||
if (v > max)
|
||||
max = v;
|
||||
v = fabs( ((float *)pev->maxs)[i]);
|
||||
if (v > max)
|
||||
max = v;
|
||||
}
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
((float *)pev->absmin)[i] = ((float *)pev->origin)[i] - max;
|
||||
((float *)pev->absmax)[i] = ((float *)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 CMBaseEntity::SetObjectCollisionBox( void )
|
||||
{
|
||||
::SetObjectCollisionBox( pev );
|
||||
}
|
||||
|
||||
|
||||
int CMBaseEntity :: Intersects( CMBaseEntity *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 CMBaseEntity :: 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 CMBaseEntity :: IsDormant( void )
|
||||
{
|
||||
return FBitSet( pev->flags, FL_DORMANT );
|
||||
}
|
||||
|
||||
BOOL CMBaseEntity :: 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 CMBaseEntity::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 CMBaseEntity :: DamageDecal( int bitsDamageType )
|
||||
{
|
||||
if ( pev->rendermode == kRenderTransAlpha )
|
||||
return -1;
|
||||
|
||||
if ( pev->rendermode != kRenderNormal )
|
||||
return DECAL_BPROOF1;
|
||||
|
||||
return DECAL_GUNSHOT1 + RANDOM_LONG(0,4);
|
||||
}
|
||||
|
||||
|
||||
611
src/dlls/cmbase.h
Normal file
611
src/dlls/cmbase.h
Normal file
@@ -0,0 +1,611 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
/*
|
||||
|
||||
Class Hierachy
|
||||
|
||||
CMBaseEntity
|
||||
CMBaseDelay
|
||||
CMBaseAnimating
|
||||
CMBaseToggle
|
||||
CMBaseMonster
|
||||
*/
|
||||
|
||||
#include "monster_plugin.h"
|
||||
|
||||
#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 "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
|
||||
|
||||
typedef enum { USE_OFF = 0, USE_ON = 1, USE_SET = 2, USE_TOGGLE = 3 } USE_TYPE;
|
||||
|
||||
class CMBaseEntity;
|
||||
|
||||
extern void FireTargets( const char *targetName, edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value );
|
||||
|
||||
typedef void (CMBaseEntity::*BASEPTR)(void);
|
||||
typedef void (CMBaseEntity::*ENTITYFUNCPTR)(CMBaseEntity *pOther );
|
||||
typedef void (CMBaseEntity::*USEPTR)( edict_t *pActivator, edict_t *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 CMBaseEntity;
|
||||
class CMBaseMonster;
|
||||
|
||||
|
||||
#define SF_NORESPAWN ( 1 << 30 )// !!!set this bit on guns and stuff that should never respawn.
|
||||
|
||||
//
|
||||
// EHANDLE. Safe way to point to edict_t 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 edict_t *();
|
||||
|
||||
edict_t * operator = (edict_t *pEntity);
|
||||
edict_t * operator ->();
|
||||
};
|
||||
|
||||
|
||||
template <class T> T * GetClassPtr( T *a );
|
||||
|
||||
//
|
||||
// Base Entity. All entity types derive from this
|
||||
//
|
||||
class CMBaseEntity
|
||||
{
|
||||
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
|
||||
edict_t *m_pGoalEnt;// path corner we are heading towards
|
||||
|
||||
edict_t *m_edictList[100];
|
||||
int m_edictList_count;
|
||||
|
||||
void *operator new( size_t stAllocateBlock );
|
||||
|
||||
virtual edict_t *CreateEntity(char *classname);
|
||||
|
||||
// initialization functions
|
||||
virtual void Spawn( void ) { return; }
|
||||
virtual void Precache( void ) { return; }
|
||||
virtual void KeyValue( KeyValueData* pkvd) { pkvd->fHandled = FALSE; }
|
||||
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.
|
||||
|
||||
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( CMBaseEntity *pActivator ) {return TRUE;}
|
||||
virtual CMBaseMonster *MyMonsterPointer( 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 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 *pev ) { 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( CMBaseEntity *pActivator ) {}
|
||||
//jlb virtual CMBaseEntity *GetNextTarget( void );
|
||||
|
||||
// fundamental callbacks
|
||||
void (CMBaseEntity ::*m_pfnThink)(void);
|
||||
void (CMBaseEntity ::*m_pfnTouch)( edict_t *pOther );
|
||||
void (CMBaseEntity ::*m_pfnUse)( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value );
|
||||
void (CMBaseEntity ::*m_pfnBlocked)( edict_t *pOther );
|
||||
|
||||
virtual void Think( void ) { if (m_pfnThink) (this->*m_pfnThink)(); };
|
||||
virtual void Touch( edict_t *pOther ) { if (m_pfnTouch) (this->*m_pfnTouch)( pOther ); };
|
||||
virtual void Use( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
if (m_pfnUse)
|
||||
(this->*m_pfnUse)( pActivator, pCaller, useType, value );
|
||||
}
|
||||
virtual void Blocked( edict_t *pOther ) { if (m_pfnBlocked) (this->*m_pfnBlocked)( pOther ); };
|
||||
|
||||
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->edict(), this->edict(), 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 );
|
||||
Vector FireBulletsPlayer( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq = 4, int iDamage = 0, entvars_t *pevAttacker = NULL, int shared_rand = 0 );
|
||||
|
||||
virtual CMBaseEntity *Respawn( void ) { return NULL; }
|
||||
|
||||
void SUB_UseTargets( edict_t *pActivator, USE_TYPE useType, float value );
|
||||
// Do the bounding boxes of these two intersect?
|
||||
int Intersects( CMBaseEntity *pOther );
|
||||
void MakeDormant( void );
|
||||
int IsDormant( void );
|
||||
BOOL IsLockedByMaster( void ) { return FALSE; }
|
||||
|
||||
static CMBaseEntity *Instance( edict_t *pent )
|
||||
{
|
||||
if ( !pent )
|
||||
pent = ENT(0);
|
||||
if ( pent->v.euser4 == NULL )
|
||||
return (CMBaseEntity *)NULL;
|
||||
CMBaseEntity *pEnt = GetClassPtr((CMBaseEntity *)VARS(pent));
|
||||
return pEnt;
|
||||
}
|
||||
|
||||
static CMBaseEntity *Instance( entvars_t *pev ) { return Instance( ENT( pev ) ); }
|
||||
static CMBaseEntity *Instance( int eoffset) { return Instance( ENT( eoffset) ); }
|
||||
|
||||
/*jlb
|
||||
CMBaseMonster *GetMonsterPointer( entvars_t *pevMonster )
|
||||
{
|
||||
CMBaseEntity *pEntity = Instance( pevMonster );
|
||||
if ( pEntity )
|
||||
return pEntity->MyMonsterPointer();
|
||||
return NULL;
|
||||
}
|
||||
CMBaseMonster *GetMonsterPointer( edict_t *pentMonster )
|
||||
{
|
||||
CMBaseEntity *pEntity = Instance( pentMonster );
|
||||
if ( pEntity )
|
||||
return pEntity->MyMonsterPointer();
|
||||
return NULL;
|
||||
}
|
||||
jlb*/
|
||||
|
||||
// virtual functions used by a few classes
|
||||
|
||||
// used by monsters that are created by the MonsterMaker
|
||||
virtual void UpdateOwner( void ) { return; };
|
||||
|
||||
|
||||
//
|
||||
//jlb static CMBaseEntity *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 ( edict_t *pEntity );
|
||||
// virtual BOOL FVisible ( const Vector &vecOrigin );
|
||||
|
||||
//We use this variables to store each ammo count.
|
||||
int ammo_9mm;
|
||||
int ammo_357;
|
||||
int ammo_bolts;
|
||||
int ammo_buckshot;
|
||||
int ammo_rockets;
|
||||
int ammo_uranium;
|
||||
int ammo_hornets;
|
||||
int ammo_argrens;
|
||||
//Special stuff for grenades and satchels.
|
||||
float m_flStartThrow;
|
||||
float m_flReleaseThrow;
|
||||
int m_chargeReady;
|
||||
int m_fInAttack;
|
||||
|
||||
enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE };
|
||||
int m_fireState;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 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.
|
||||
|
||||
#define SetThink( a ) m_pfnThink = static_cast <void (CMBaseEntity::*)(void)> (a)
|
||||
#define SetTouch( a ) m_pfnTouch = static_cast <void (CMBaseEntity::*)(edict_t *)> (a)
|
||||
#define SetUse( a ) m_pfnUse = static_cast <void (CMBaseEntity::*)( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )> (a)
|
||||
#define SetBlocked( a ) m_pfnBlocked = static_cast <void (CMBaseEntity::*)(edict_t *)> (a)
|
||||
|
||||
|
||||
class CMPointEntity : public CMBaseEntity
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
virtual int ObjectCaps( void ) { return CMBaseEntity :: 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);
|
||||
|
||||
|
||||
//
|
||||
// generic Delay entity.
|
||||
//
|
||||
class CMBaseDelay : public CMBaseEntity
|
||||
{
|
||||
public:
|
||||
float m_flDelay;
|
||||
int m_iszKillTarget;
|
||||
|
||||
virtual void KeyValue( KeyValueData* pkvd);
|
||||
|
||||
// common member functions
|
||||
void SUB_UseTargets( edict_t *pActivator, USE_TYPE useType, float value );
|
||||
void EXPORT DelayThink( void );
|
||||
};
|
||||
|
||||
|
||||
class CMBaseAnimating : public CMBaseDelay
|
||||
{
|
||||
public:
|
||||
|
||||
// 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 CMBaseToggle : public CMBaseAnimating
|
||||
{
|
||||
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;
|
||||
//jlb EHANDLE m_hActivator;
|
||||
void (CMBaseToggle::*m_pfnCallWhenMoveDone)(void);
|
||||
Vector m_vecFinalDest;
|
||||
Vector m_vecFinalAngle;
|
||||
|
||||
int m_bitsDamageInflict; // DMG_ damage type that the door or tigger does
|
||||
|
||||
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 (CMBaseToggle::*)(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)
|
||||
|
||||
// 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 CMBaseMonster;
|
||||
|
||||
|
||||
extern int GetMonsterIndex(void);
|
||||
|
||||
//
|
||||
// Converts a entvars_t * to a class pointer
|
||||
//
|
||||
template <class T> T * GetClassPtr( T *a )
|
||||
{
|
||||
entvars_t *pev = (entvars_t *)a;
|
||||
|
||||
if (pev == NULL)
|
||||
return NULL;
|
||||
|
||||
// get the private data
|
||||
a = (T *)pev->euser4;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
//
|
||||
// Converts a entvars_t * to a class pointer
|
||||
// It will allocate the class and entity
|
||||
//
|
||||
template <class T> T * CreateClassPtr( T *a )
|
||||
{
|
||||
entvars_t *pev = (entvars_t *)a;
|
||||
|
||||
if (pev != NULL)
|
||||
return NULL; // don't allocate if pointer already provided
|
||||
|
||||
// allocate entity...
|
||||
edict_t *temp_edict;
|
||||
int edict_index;
|
||||
int monster_index;
|
||||
|
||||
if ((monster_index = GetMonsterIndex()) == -1)
|
||||
{
|
||||
(*g_engfuncs.pfnServerPrint)("[MONSTER] ERROR: No FREE Monster edicts in CreateClassPtr!\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// allocate private data
|
||||
a = new T;
|
||||
|
||||
if ((temp_edict = a->CreateEntity("func_wall")) == NULL)
|
||||
{
|
||||
(*g_engfuncs.pfnServerPrint)("[MONSTER] ERROR: NULL Ent in CreateClassPtr!\n" );
|
||||
delete a;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
edict_index = (*g_engfuncs.pfnIndexOfEdict)(temp_edict);
|
||||
|
||||
// store the class pointer to the edict pev...
|
||||
pev = VARS(temp_edict);
|
||||
a->pev = pev;
|
||||
|
||||
// store the class pointer in the array here!!!
|
||||
monsters[monster_index].monster_index = edict_index;
|
||||
monsters[monster_index].monster_pent = temp_edict;
|
||||
monsters[monster_index].respawn_index = -1;
|
||||
monsters[monster_index].pMonster = (CMBaseMonster *)a;
|
||||
|
||||
// get the private data
|
||||
a = (T *)pev->euser4;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
1028
src/dlls/cmbasemonster.h
Normal file
1028
src/dlls/cmbasemonster.h
Normal file
File diff suppressed because it is too large
Load Diff
53
src/dlls/cmflyingmonster.h
Normal file
53
src/dlls/cmflyingmonster.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
// Base class for flying monsters. This overrides the movement test & execution code from CBaseMonster
|
||||
|
||||
#ifndef FLYINGMONSTER_H
|
||||
#define FLYINGMONSTER_H
|
||||
|
||||
class CMFlyingMonster : public CMBaseMonster
|
||||
{
|
||||
public:
|
||||
int CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, edict_t *pTarget, float *pflDist );// check validity of a straight move through space
|
||||
BOOL FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, edict_t *pTargetEnt, Vector *pApex );
|
||||
Activity GetStoppedActivity( void );
|
||||
void Killed( entvars_t *pevAttacker, int iGib );
|
||||
void Stop( void );
|
||||
float ChangeYaw( int speed );
|
||||
void HandleAnimEvent( MonsterEvent_t *pEvent );
|
||||
void MoveExecute( edict_t *pTargetEnt, const Vector &vecDir, float flInterval );
|
||||
void Move( float flInterval = 0.1 );
|
||||
BOOL ShouldAdvanceRoute( float flWaypointDist );
|
||||
|
||||
inline void SetFlyingMomentum( float momentum ) { m_momentum = momentum; }
|
||||
inline void SetFlyingFlapSound( const char *pFlapSound ) { m_pFlapSound = pFlapSound; }
|
||||
inline void SetFlyingSpeed( float speed ) { m_flightSpeed = speed; }
|
||||
float CeilingZ( const Vector &position );
|
||||
float FloorZ( const Vector &position );
|
||||
BOOL ProbeZ( const Vector &position, const Vector &probe, float *pFraction );
|
||||
|
||||
|
||||
// UNDONE: Save/restore this stuff!!!
|
||||
protected:
|
||||
Vector m_vecTravel; // Current direction
|
||||
float m_flightSpeed; // Current flight speed (decays when not flapping or gliding)
|
||||
float m_stopTime; // Last time we stopped (to avoid switching states too soon)
|
||||
float m_momentum; // Weight for desired vs. momentum velocity
|
||||
const char *m_pFlapSound;
|
||||
};
|
||||
|
||||
|
||||
#endif //FLYINGMONSTER_H
|
||||
|
||||
178
src/dlls/cmtalkmonster.h
Normal file
178
src/dlls/cmtalkmonster.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
#ifndef TALKMONSTER_H
|
||||
#define TALKMONSTER_H
|
||||
|
||||
#ifndef MONSTERS_H
|
||||
#include "monsters.h"
|
||||
#endif
|
||||
|
||||
//=========================================================
|
||||
// Talking monster base class
|
||||
// Used for scientists and barneys
|
||||
//=========================================================
|
||||
|
||||
#define TALKRANGE_MIN 500.0 // don't talk to anyone farther away than this
|
||||
|
||||
#define TLK_STARE_DIST 128 // anyone closer than this and looking at me is probably staring at me.
|
||||
|
||||
#define bit_saidDamageLight (1<<0) // bits so we don't repeat key sentences
|
||||
#define bit_saidDamageMedium (1<<1)
|
||||
#define bit_saidDamageHeavy (1<<2)
|
||||
#define bit_saidHelloPlayer (1<<3)
|
||||
#define bit_saidWoundLight (1<<4)
|
||||
#define bit_saidWoundHeavy (1<<5)
|
||||
#define bit_saidHeard (1<<6)
|
||||
#define bit_saidSmelled (1<<7)
|
||||
|
||||
#define TLK_CFRIENDS 3
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TLK_ANSWER = 0,
|
||||
TLK_QUESTION,
|
||||
TLK_IDLE,
|
||||
TLK_STARE,
|
||||
TLK_USE,
|
||||
TLK_UNUSE,
|
||||
TLK_STOP,
|
||||
TLK_NOSHOOT,
|
||||
TLK_HELLO,
|
||||
TLK_PHELLO,
|
||||
TLK_PIDLE,
|
||||
TLK_PQUESTION,
|
||||
TLK_PLHURT1,
|
||||
TLK_PLHURT2,
|
||||
TLK_PLHURT3,
|
||||
TLK_SMELL,
|
||||
TLK_WOUND,
|
||||
TLK_MORTAL,
|
||||
|
||||
TLK_CGROUPS, // MUST be last entry
|
||||
} TALKGROUPNAMES;
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
SCHED_CANT_FOLLOW = LAST_COMMON_SCHEDULE + 1,
|
||||
SCHED_MOVE_AWAY, // Try to get out of the player's way
|
||||
SCHED_MOVE_AWAY_FOLLOW, // same, but follow afterward
|
||||
SCHED_MOVE_AWAY_FAIL, // Turn back toward player
|
||||
|
||||
LAST_TALKMONSTER_SCHEDULE, // MUST be last
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
TASK_CANT_FOLLOW = LAST_COMMON_TASK + 1,
|
||||
TASK_MOVE_AWAY_PATH,
|
||||
TASK_WALK_PATH_FOR_UNITS,
|
||||
|
||||
TASK_TLK_RESPOND, // say my response
|
||||
TASK_TLK_SPEAK, // question or remark
|
||||
TASK_TLK_HELLO, // Try to say hello to player
|
||||
TASK_TLK_HEADRESET, // reset head position
|
||||
TASK_TLK_STOPSHOOTING, // tell player to stop shooting friend
|
||||
TASK_TLK_STARE, // let the player know I know he's staring at me.
|
||||
TASK_TLK_LOOK_AT_CLIENT,// faces player if not moving and not talking and in idle.
|
||||
TASK_TLK_CLIENT_STARE, // same as look at client, but says something if the player stares.
|
||||
TASK_TLK_EYECONTACT, // maintain eyecontact with person who I'm talking to
|
||||
TASK_TLK_IDEALYAW, // set ideal yaw to face who I'm talking to
|
||||
TASK_FACE_PLAYER, // Face the player
|
||||
|
||||
LAST_TALKMONSTER_TASK, // MUST be last
|
||||
};
|
||||
|
||||
class CMTalkMonster : public CMBaseMonster
|
||||
{
|
||||
public:
|
||||
void TalkInit( void );
|
||||
edict_t *FindNearestFriend(BOOL fPlayer);
|
||||
float TargetDistance( void );
|
||||
void StopTalking( void ) { SentenceStop(); }
|
||||
|
||||
// Base Monster functions
|
||||
void Precache( void );
|
||||
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType);
|
||||
void TalkTouch( edict_t *pOther );
|
||||
void Killed( entvars_t *pevAttacker, int iGib );
|
||||
int IRelationship ( CMBaseEntity *pTarget );
|
||||
virtual int CanPlaySentence( BOOL fDisregardState );
|
||||
virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation );
|
||||
void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, edict_t *pListener );
|
||||
void KeyValue( KeyValueData *pkvd );
|
||||
|
||||
// AI functions
|
||||
void SetActivity ( Activity newActivity );
|
||||
Schedule_t *GetScheduleOfType ( int Type );
|
||||
void StartTask( Task_t *pTask );
|
||||
void RunTask( Task_t *pTask );
|
||||
void HandleAnimEvent( MonsterEvent_t *pEvent );
|
||||
void PrescheduleThink( void );
|
||||
|
||||
|
||||
// Conversations / communication
|
||||
int GetVoicePitch( void );
|
||||
void IdleRespond( void );
|
||||
int FIdleSpeak( void );
|
||||
int FIdleStare( void );
|
||||
int FIdleHello( void );
|
||||
void IdleHeadTurn( Vector &vecFriend );
|
||||
int FOkToSpeak( void );
|
||||
void TrySmellTalk( void );
|
||||
edict_t *EnumFriends( edict_t *pentPrevious, int listNumber, BOOL bTrace );
|
||||
void AlertFriends( void );
|
||||
void ShutUpFriends( void );
|
||||
BOOL IsTalking( void );
|
||||
void Talk( float flDuration );
|
||||
// For following
|
||||
BOOL CanFollow( void );
|
||||
BOOL IsFollowing( void ) { return m_hTargetEnt != NULL && UTIL_IsPlayer(m_hTargetEnt); }
|
||||
void StopFollowing( BOOL clearSchedule );
|
||||
void StartFollowing( edict_t *pLeader );
|
||||
virtual void DeclineFollowing( void ) {}
|
||||
void LimitFollowers( edict_t *pPlayer, int maxFollowers );
|
||||
|
||||
void EXPORT FollowerUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value );
|
||||
|
||||
virtual void SetAnswerQuestion( edict_t *pSpeaker );
|
||||
virtual int FriendNumber( int arrayNumber ) { return arrayNumber; }
|
||||
|
||||
static char *m_szFriends[TLK_CFRIENDS]; // array of friend names
|
||||
static float g_talkWaitTime;
|
||||
|
||||
int m_bitsSaid; // set bits for sentences we don't want repeated
|
||||
int m_nSpeak; // number of times initiated talking
|
||||
int m_voicePitch; // pitch of voice for this head
|
||||
const char *m_szGrp[TLK_CGROUPS]; // sentence group names
|
||||
float m_useTime; // Don't allow +USE until this time
|
||||
int m_iszUse; // Custom +USE sentence group (follow)
|
||||
int m_iszUnUse; // Custom +USE sentence group (stop following)
|
||||
|
||||
float m_flLastSaidSmelled;// last time we talked about something that stinks
|
||||
float m_flStopTalkTime;// when in the future that I'll be done saying this sentence.
|
||||
|
||||
EHANDLE m_hTalkTarget; // who to look at while talking
|
||||
CUSTOM_SCHEDULES;
|
||||
};
|
||||
|
||||
|
||||
// Clients can push talkmonsters out of their way
|
||||
#define bits_COND_CLIENT_PUSH ( bits_COND_SPECIAL1 )
|
||||
// Don't see a client right now.
|
||||
#define bits_COND_CLIENT_UNSEEN ( bits_COND_SPECIAL2 )
|
||||
|
||||
|
||||
#endif //TALKMONSTER_H
|
||||
1597
src/dlls/combat.cpp
Normal file
1597
src/dlls/combat.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1359
src/dlls/controller.cpp
Normal file
1359
src/dlls/controller.cpp
Normal file
File diff suppressed because it is too large
Load Diff
75
src/dlls/decals.h
Normal file
75
src/dlls/decals.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef 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
|
||||
1084
src/dlls/defaultai.cpp
Normal file
1084
src/dlls/defaultai.cpp
Normal file
File diff suppressed because it is too large
Load Diff
98
src/dlls/defaultai.h
Normal file
98
src/dlls/defaultai.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
#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
|
||||
1157
src/dlls/dllapi.cpp
Normal file
1157
src/dlls/dllapi.cpp
Normal file
File diff suppressed because it is too large
Load Diff
33
src/dlls/doors.h
Normal file
33
src/dlls/doors.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef 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
|
||||
446
src/dlls/effects.cpp
Normal file
446
src/dlls/effects.cpp
Normal file
@@ -0,0 +1,446 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "customentity.h"
|
||||
#include "effects.h"
|
||||
#include "weapons.h"
|
||||
#include "decals.h"
|
||||
#include "func_break.h"
|
||||
#include "shake.h"
|
||||
|
||||
#define SF_GIBSHOOTER_REPEATABLE 1 // allows a gibshooter to be refired
|
||||
|
||||
#define SF_FUNNEL_REVERSE 1 // funnel effect repels particles instead of attracting them.
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
//
|
||||
// Beams
|
||||
//
|
||||
// --------------------------------------------------
|
||||
|
||||
void CMBeam::Spawn( void )
|
||||
{
|
||||
pev->solid = SOLID_NOT; // Remove model & collisions
|
||||
Precache( );
|
||||
}
|
||||
|
||||
void CMBeam::Precache( void )
|
||||
{
|
||||
if ( pev->owner )
|
||||
SetStartEntity( ENTINDEX( pev->owner ) );
|
||||
if ( pev->aiment )
|
||||
SetEndEntity( ENTINDEX( pev->aiment ) );
|
||||
}
|
||||
|
||||
void CMBeam::SetStartEntity( int entityIndex )
|
||||
{
|
||||
pev->sequence = (entityIndex & 0x0FFF) | ((pev->sequence&0xF000)<<12);
|
||||
pev->owner = g_engfuncs.pfnPEntityOfEntIndex( entityIndex );
|
||||
}
|
||||
|
||||
void CMBeam::SetEndEntity( int entityIndex )
|
||||
{
|
||||
pev->skin = (entityIndex & 0x0FFF) | ((pev->skin&0xF000)<<12);
|
||||
pev->aiment = g_engfuncs.pfnPEntityOfEntIndex( entityIndex );
|
||||
}
|
||||
|
||||
|
||||
// These don't take attachments into account
|
||||
const Vector &CMBeam::GetStartPos( void )
|
||||
{
|
||||
if ( GetType() == BEAM_ENTS )
|
||||
{
|
||||
edict_t *pent = g_engfuncs.pfnPEntityOfEntIndex( GetStartEntity() );
|
||||
return pent->v.origin;
|
||||
}
|
||||
return pev->origin;
|
||||
}
|
||||
|
||||
|
||||
const Vector &CMBeam::GetEndPos( void )
|
||||
{
|
||||
int type = GetType();
|
||||
if ( type == BEAM_POINTS || type == BEAM_HOSE )
|
||||
{
|
||||
return pev->angles;
|
||||
}
|
||||
|
||||
edict_t *pent = g_engfuncs.pfnPEntityOfEntIndex( GetEndEntity() );
|
||||
if ( pent )
|
||||
return pent->v.origin;
|
||||
return pev->angles;
|
||||
}
|
||||
|
||||
|
||||
CMBeam *CMBeam::BeamCreate( const char *pSpriteName, int width )
|
||||
{
|
||||
// Create a new entity with CMBeam private data
|
||||
CMBeam *pBeam = CreateClassPtr( (CMBeam *)NULL );
|
||||
|
||||
if (pBeam == NULL)
|
||||
return NULL;
|
||||
|
||||
pBeam->pev->classname = MAKE_STRING("beam");
|
||||
|
||||
pBeam->BeamInit( pSpriteName, width );
|
||||
|
||||
return pBeam;
|
||||
}
|
||||
|
||||
|
||||
void CMBeam::BeamInit( const char *pSpriteName, int width )
|
||||
{
|
||||
pev->flags |= FL_CUSTOMENTITY;
|
||||
SetColor( 255, 255, 255 );
|
||||
SetBrightness( 255 );
|
||||
SetNoise( 0 );
|
||||
SetFrame( 0 );
|
||||
SetScrollRate( 0 );
|
||||
pev->model = MAKE_STRING( pSpriteName );
|
||||
SetTexture( PRECACHE_MODEL( (char *)pSpriteName ) );
|
||||
SetWidth( width );
|
||||
pev->skin = 0;
|
||||
pev->sequence = 0;
|
||||
pev->rendermode = 0;
|
||||
}
|
||||
|
||||
|
||||
void CMBeam::PointsInit( const Vector &start, const Vector &end )
|
||||
{
|
||||
SetType( BEAM_POINTS );
|
||||
SetStartPos( start );
|
||||
SetEndPos( end );
|
||||
SetStartAttachment( 0 );
|
||||
SetEndAttachment( 0 );
|
||||
RelinkBeam();
|
||||
}
|
||||
|
||||
|
||||
void CMBeam::HoseInit( const Vector &start, const Vector &direction )
|
||||
{
|
||||
SetType( BEAM_HOSE );
|
||||
SetStartPos( start );
|
||||
SetEndPos( direction );
|
||||
SetStartAttachment( 0 );
|
||||
SetEndAttachment( 0 );
|
||||
RelinkBeam();
|
||||
}
|
||||
|
||||
|
||||
void CMBeam::PointEntInit( const Vector &start, int endIndex )
|
||||
{
|
||||
SetType( BEAM_ENTPOINT );
|
||||
SetStartPos( start );
|
||||
SetEndEntity( endIndex );
|
||||
SetStartAttachment( 0 );
|
||||
SetEndAttachment( 0 );
|
||||
RelinkBeam();
|
||||
}
|
||||
|
||||
void CMBeam::EntsInit( int startIndex, int endIndex )
|
||||
{
|
||||
SetType( BEAM_ENTS );
|
||||
SetStartEntity( startIndex );
|
||||
SetEndEntity( endIndex );
|
||||
SetStartAttachment( 0 );
|
||||
SetEndAttachment( 0 );
|
||||
RelinkBeam();
|
||||
}
|
||||
|
||||
|
||||
void CMBeam::RelinkBeam( void )
|
||||
{
|
||||
const Vector &startPos = GetStartPos(), &endPos = GetEndPos();
|
||||
|
||||
pev->mins.x = min( startPos.x, endPos.x );
|
||||
pev->mins.y = min( startPos.y, endPos.y );
|
||||
pev->mins.z = min( startPos.z, endPos.z );
|
||||
pev->maxs.x = max( startPos.x, endPos.x );
|
||||
pev->maxs.y = max( startPos.y, endPos.y );
|
||||
pev->maxs.z = max( startPos.z, endPos.z );
|
||||
pev->mins = pev->mins - pev->origin;
|
||||
pev->maxs = pev->maxs - pev->origin;
|
||||
|
||||
UTIL_SetSize( pev, pev->mins, pev->maxs );
|
||||
UTIL_SetOrigin( pev, pev->origin );
|
||||
}
|
||||
|
||||
#if 0
|
||||
void CMBeam::SetObjectCollisionBox( void )
|
||||
{
|
||||
const Vector &startPos = GetStartPos(), &endPos = GetEndPos();
|
||||
|
||||
pev->absmin.x = min( startPos.x, endPos.x );
|
||||
pev->absmin.y = min( startPos.y, endPos.y );
|
||||
pev->absmin.z = min( startPos.z, endPos.z );
|
||||
pev->absmax.x = max( startPos.x, endPos.x );
|
||||
pev->absmax.y = max( startPos.y, endPos.y );
|
||||
pev->absmax.z = max( startPos.z, endPos.z );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void CMBeam::TriggerTouch( edict_t *pOther )
|
||||
{
|
||||
if ( pOther->v.flags & (FL_CLIENT | FL_MONSTER) )
|
||||
{
|
||||
if ( pev->owner )
|
||||
{
|
||||
if (pev->owner->v.euser4 != NULL)
|
||||
{
|
||||
CMBaseEntity *pOwner = GetClassPtr((CMBaseEntity *)VARS(pev->owner));
|
||||
pOwner->Use( pOther, this->edict(), USE_TOGGLE, 0 );
|
||||
}
|
||||
}
|
||||
ALERT( at_console, "Firing targets!!!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
edict_t *CMBeam::RandomTargetname( const char *szName )
|
||||
{
|
||||
int total = 0;
|
||||
|
||||
edict_t *pEntity = NULL;
|
||||
edict_t *pNewEntity = NULL;
|
||||
while ((pNewEntity = UTIL_FindEntityByTargetname( pNewEntity, szName )) != NULL)
|
||||
{
|
||||
total++;
|
||||
if (RANDOM_LONG(0,total-1) < 1)
|
||||
pEntity = pNewEntity;
|
||||
}
|
||||
return pEntity;
|
||||
}
|
||||
|
||||
|
||||
void CMBeam::DoSparks( const Vector &start, const Vector &end )
|
||||
{
|
||||
if ( pev->spawnflags & (SF_BEAM_SPARKSTART|SF_BEAM_SPARKEND) )
|
||||
{
|
||||
if ( pev->spawnflags & SF_BEAM_SPARKSTART )
|
||||
{
|
||||
UTIL_Sparks( start );
|
||||
}
|
||||
if ( pev->spawnflags & SF_BEAM_SPARKEND )
|
||||
{
|
||||
UTIL_Sparks( end );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMBeam::BeamDamage( TraceResult *ptr )
|
||||
{
|
||||
RelinkBeam();
|
||||
if ( ptr->flFraction != 1.0 && ptr->pHit != NULL )
|
||||
{
|
||||
if (UTIL_IsPlayer(ptr->pHit))
|
||||
{
|
||||
ClearMultiDamage();
|
||||
UTIL_TraceAttack(ptr->pHit, pev, pev->dmg * (gpGlobals->time - pev->dmgtime), (ptr->vecEndPos - pev->origin).Normalize(), ptr, DMG_ENERGYBEAM );
|
||||
ApplyMultiDamage( pev, pev );
|
||||
|
||||
if ( pev->spawnflags & SF_BEAM_DECALS )
|
||||
{
|
||||
if ( UTIL_IsBSPModel(ptr->pHit) )
|
||||
UTIL_DecalTrace( ptr, DECAL_BIGSHOT1 + RANDOM_LONG(0,4) );
|
||||
}
|
||||
|
||||
}
|
||||
else if (ptr->pHit->v.euser4 != NULL)
|
||||
{
|
||||
ClearMultiDamage();
|
||||
CMBaseEntity *pMonster = GetClassPtr((CMBaseEntity *)VARS(ptr->pHit));
|
||||
pMonster->TraceAttack( pev, pev->dmg * (gpGlobals->time - pev->dmgtime), (ptr->vecEndPos - pev->origin).Normalize(), ptr, DMG_ENERGYBEAM );
|
||||
ApplyMultiDamage( pev, pev );
|
||||
|
||||
if ( pev->spawnflags & SF_BEAM_DECALS )
|
||||
{
|
||||
if ( pMonster->IsBSPModel() )
|
||||
UTIL_DecalTrace( ptr, DECAL_BIGSHOT1 + RANDOM_LONG(0,4) );
|
||||
}
|
||||
}
|
||||
}
|
||||
pev->dmgtime = gpGlobals->time;
|
||||
}
|
||||
|
||||
|
||||
void CMSprite::Spawn( void )
|
||||
{
|
||||
pev->solid = SOLID_NOT;
|
||||
pev->movetype = MOVETYPE_NONE;
|
||||
pev->effects = 0;
|
||||
pev->frame = 0;
|
||||
|
||||
Precache();
|
||||
SET_MODEL( ENT(pev), STRING(pev->model) );
|
||||
|
||||
m_maxFrame = (float) MODEL_FRAMES( pev->modelindex ) - 1;
|
||||
if ( pev->targetname && !(pev->spawnflags & SF_SPRITE_STARTON) )
|
||||
TurnOff();
|
||||
else
|
||||
TurnOn();
|
||||
|
||||
// Worldcraft only sets y rotation, copy to Z
|
||||
if ( pev->angles.y != 0 && pev->angles.z == 0 )
|
||||
{
|
||||
pev->angles.z = pev->angles.y;
|
||||
pev->angles.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMSprite::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( (char *)STRING(pev->model) );
|
||||
|
||||
// Reset attachment after save/restore
|
||||
if ( pev->aiment )
|
||||
SetAttachment( pev->aiment, pev->body );
|
||||
else
|
||||
{
|
||||
// Clear attachment
|
||||
pev->skin = 0;
|
||||
pev->body = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMSprite::SpriteInit( const char *pSpriteName, const Vector &origin )
|
||||
{
|
||||
pev->model = MAKE_STRING(pSpriteName);
|
||||
pev->origin = origin;
|
||||
Spawn();
|
||||
}
|
||||
|
||||
CMSprite *CMSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate )
|
||||
{
|
||||
CMSprite *pSprite = CreateClassPtr( (CMSprite *)NULL );
|
||||
pSprite->SpriteInit( pSpriteName, origin );
|
||||
pSprite->pev->classname = MAKE_STRING("env_sprite");
|
||||
pSprite->pev->solid = SOLID_NOT;
|
||||
pSprite->pev->movetype = MOVETYPE_NOCLIP;
|
||||
if ( animate )
|
||||
pSprite->TurnOn();
|
||||
|
||||
return pSprite;
|
||||
}
|
||||
|
||||
|
||||
void CMSprite::AnimateThink( void )
|
||||
{
|
||||
Animate( pev->framerate * (gpGlobals->time - m_lastTime) );
|
||||
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
m_lastTime = gpGlobals->time;
|
||||
}
|
||||
|
||||
void CMSprite::AnimateUntilDead( void )
|
||||
{
|
||||
if ( gpGlobals->time > pev->dmgtime )
|
||||
UTIL_Remove(this->edict());
|
||||
else
|
||||
{
|
||||
AnimateThink();
|
||||
pev->nextthink = gpGlobals->time;
|
||||
}
|
||||
}
|
||||
|
||||
void CMSprite::Expand( float scaleSpeed, float fadeSpeed )
|
||||
{
|
||||
pev->speed = scaleSpeed;
|
||||
pev->health = fadeSpeed;
|
||||
SetThink( ExpandThink );
|
||||
|
||||
pev->nextthink = gpGlobals->time;
|
||||
m_lastTime = gpGlobals->time;
|
||||
}
|
||||
|
||||
|
||||
void CMSprite::ExpandThink( void )
|
||||
{
|
||||
float frametime = gpGlobals->time - m_lastTime;
|
||||
pev->scale += pev->speed * frametime;
|
||||
pev->renderamt -= pev->health * frametime;
|
||||
if ( pev->renderamt <= 0 )
|
||||
{
|
||||
pev->renderamt = 0;
|
||||
UTIL_Remove( this->edict() );
|
||||
}
|
||||
else
|
||||
{
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
m_lastTime = gpGlobals->time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMSprite::Animate( float frames )
|
||||
{
|
||||
pev->frame += frames;
|
||||
if ( pev->frame > m_maxFrame )
|
||||
{
|
||||
if ( pev->spawnflags & SF_SPRITE_ONCE )
|
||||
{
|
||||
TurnOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_maxFrame > 0 )
|
||||
pev->frame = fmod( pev->frame, m_maxFrame );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMSprite::TurnOff( void )
|
||||
{
|
||||
pev->effects = EF_NODRAW;
|
||||
pev->nextthink = 0;
|
||||
}
|
||||
|
||||
|
||||
void CMSprite::TurnOn( void )
|
||||
{
|
||||
pev->effects = 0;
|
||||
if ( (pev->framerate && m_maxFrame > 1.0) || (pev->spawnflags & SF_SPRITE_ONCE) )
|
||||
{
|
||||
SetThink( AnimateThink );
|
||||
pev->nextthink = gpGlobals->time;
|
||||
m_lastTime = gpGlobals->time;
|
||||
}
|
||||
pev->frame = 0;
|
||||
}
|
||||
|
||||
|
||||
void CMSprite::Use( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
int on = pev->effects != EF_NODRAW;
|
||||
if ( ShouldToggle( useType, on ) )
|
||||
{
|
||||
if ( on )
|
||||
{
|
||||
TurnOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
TurnOn();
|
||||
}
|
||||
}
|
||||
}
|
||||
203
src/dlls/effects.h
Normal file
203
src/dlls/effects.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef 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 CMSprite : public CMPointEntity
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
|
||||
int ObjectCaps( void )
|
||||
{
|
||||
int flags = 0;
|
||||
if ( pev->spawnflags & SF_SPRITE_TEMPORARY )
|
||||
flags = FCAP_DONT_SAVE;
|
||||
return (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags;
|
||||
}
|
||||
void EXPORT AnimateThink( void );
|
||||
void EXPORT ExpandThink( void );
|
||||
void Use( edict_t *pActivator, edict_t *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(AnimateUntilDead);
|
||||
pev->framerate = framerate;
|
||||
pev->dmgtime = gpGlobals->time + (m_maxFrame / framerate);
|
||||
pev->nextthink = gpGlobals->time;
|
||||
}
|
||||
|
||||
void EXPORT AnimateUntilDead( void );
|
||||
|
||||
static CMSprite *SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate );
|
||||
|
||||
private:
|
||||
|
||||
float m_lastTime;
|
||||
float m_maxFrame;
|
||||
};
|
||||
|
||||
|
||||
class CMBeam : public CMBaseEntity
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
int ObjectCaps( void )
|
||||
{
|
||||
int flags = 0;
|
||||
if ( pev->spawnflags & SF_BEAM_TEMPORARY )
|
||||
flags = FCAP_DONT_SAVE;
|
||||
return (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags;
|
||||
}
|
||||
|
||||
void EXPORT TriggerTouch( edict_t *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 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 pev->renderamt; }
|
||||
inline int GetFrame( void ) { return pev->frame; }
|
||||
inline int GetScrollRate( void ) { return pev->animtime; }
|
||||
|
||||
// Call after you change start/end positions
|
||||
void RelinkBeam( void );
|
||||
// void SetObjectCollisionBox( void );
|
||||
|
||||
void DoSparks( const Vector &start, const Vector &end );
|
||||
edict_t *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 CMBeam *BeamCreate( const char *pSpriteName, int width );
|
||||
|
||||
inline void LiveForTime( float time ) { SetThink(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 CMLaser : public CMBeam
|
||||
{
|
||||
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( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value );
|
||||
|
||||
CMSprite *m_pSprite;
|
||||
int m_iszSpriteName;
|
||||
Vector m_firePosition;
|
||||
};
|
||||
|
||||
#endif //EFFECTS_H
|
||||
158
src/dlls/enginecallback.h
Normal file
158
src/dlls/enginecallback.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef ENGINECALLBACK_H
|
||||
#define ENGINECALLBACK_H
|
||||
#pragma once
|
||||
|
||||
#include "event_flags.h"
|
||||
|
||||
// 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 GETPLAYERWONID (*g_engfuncs.pfnGetPlayerWONId)
|
||||
|
||||
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
|
||||
32
src/dlls/explode.h
Normal file
32
src/dlls/explode.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef 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 ¢er, const Vector &angles, edict_t *pOwner, int magnitude, BOOL doDamage );
|
||||
|
||||
#endif //EXPLODE_H
|
||||
88
src/dlls/extdll.h
Normal file
88
src/dlls/extdll.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef 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
|
||||
#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
|
||||
|
||||
// Prevent tons of unused windows definitions
|
||||
#ifdef _WIN32
|
||||
#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>
|
||||
#ifndef min
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef max
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
|
||||
#endif
|
||||
#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
|
||||
281
src/dlls/flyingmonster.cpp
Normal file
281
src/dlls/flyingmonster.cpp
Normal file
@@ -0,0 +1,281 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "schedule.h"
|
||||
|
||||
#define FLYING_AE_FLAP (8)
|
||||
#define FLYING_AE_FLAPSOUND (9)
|
||||
|
||||
|
||||
extern DLL_GLOBAL edict_t *g_pBodyQueueHead;
|
||||
|
||||
int CMFlyingMonster :: CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, edict_t *pTarget, float *pflDist )
|
||||
{
|
||||
// UNDONE: need to check more than the endpoint
|
||||
if (FBitSet(pev->flags, FL_SWIM) && (UTIL_PointContents(vecEnd) != CONTENTS_WATER))
|
||||
{
|
||||
// ALERT(at_aiconsole, "can't swim out of water\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TraceResult tr;
|
||||
|
||||
UTIL_TraceHull( vecStart + Vector( 0, 0, 32 ), vecEnd + Vector( 0, 0, 32 ), dont_ignore_monsters, large_hull, edict(), &tr );
|
||||
|
||||
// ALERT( at_console, "%.0f %.0f %.0f : ", vecStart.x, vecStart.y, vecStart.z );
|
||||
// ALERT( at_console, "%.0f %.0f %.0f\n", vecEnd.x, vecEnd.y, vecEnd.z );
|
||||
|
||||
if (pflDist)
|
||||
{
|
||||
*pflDist = ( (tr.vecEndPos - Vector( 0, 0, 32 )) - vecStart ).Length();// get the distance.
|
||||
}
|
||||
|
||||
// ALERT( at_console, "check %d %d %f\n", tr.fStartSolid, tr.fAllSolid, tr.flFraction );
|
||||
if (tr.fStartSolid || tr.flFraction < 1.0)
|
||||
{
|
||||
if ( pTarget && (pTarget == gpGlobals->trace_ent) )
|
||||
return LOCALMOVE_VALID;
|
||||
return LOCALMOVE_INVALID;
|
||||
}
|
||||
|
||||
return LOCALMOVE_VALID;
|
||||
}
|
||||
|
||||
|
||||
BOOL CMFlyingMonster :: FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, edict_t *pTargetEnt, Vector *pApex )
|
||||
{
|
||||
return CMBaseMonster::FTriangulate( vecStart, vecEnd, flDist, pTargetEnt, pApex );
|
||||
}
|
||||
|
||||
|
||||
Activity CMFlyingMonster :: GetStoppedActivity( void )
|
||||
{
|
||||
if ( pev->movetype != MOVETYPE_FLY ) // UNDONE: Ground idle here, IDLE may be something else
|
||||
return ACT_IDLE;
|
||||
|
||||
return ACT_HOVER;
|
||||
}
|
||||
|
||||
|
||||
void CMFlyingMonster :: Stop( void )
|
||||
{
|
||||
Activity stopped = GetStoppedActivity();
|
||||
if ( m_IdealActivity != stopped )
|
||||
{
|
||||
m_flightSpeed = 0;
|
||||
m_IdealActivity = stopped;
|
||||
}
|
||||
pev->angles.z = 0;
|
||||
pev->angles.x = 0;
|
||||
m_vecTravel = g_vecZero;
|
||||
}
|
||||
|
||||
|
||||
float CMFlyingMonster :: ChangeYaw( int speed )
|
||||
{
|
||||
if ( pev->movetype == MOVETYPE_FLY )
|
||||
{
|
||||
float diff = FlYawDiff();
|
||||
float target = 0;
|
||||
|
||||
if ( m_IdealActivity != GetStoppedActivity() )
|
||||
{
|
||||
if ( diff < -20 )
|
||||
target = 90;
|
||||
else if ( diff > 20 )
|
||||
target = -90;
|
||||
}
|
||||
pev->angles.z = UTIL_Approach( target, pev->angles.z, 220.0 * gpGlobals->frametime );
|
||||
}
|
||||
return CMBaseMonster::ChangeYaw( speed );
|
||||
}
|
||||
|
||||
|
||||
void CMFlyingMonster :: Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
ClearBits( pev->flags, FL_ONGROUND );
|
||||
pev->angles.z = 0;
|
||||
pev->angles.x = 0;
|
||||
CMBaseMonster::Killed( pevAttacker, iGib );
|
||||
}
|
||||
|
||||
|
||||
void CMFlyingMonster :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case FLYING_AE_FLAP:
|
||||
m_flightSpeed = 400;
|
||||
break;
|
||||
|
||||
case FLYING_AE_FLAPSOUND:
|
||||
if ( m_pFlapSound )
|
||||
EMIT_SOUND( edict(), CHAN_BODY, m_pFlapSound, 1, ATTN_NORM );
|
||||
break;
|
||||
|
||||
default:
|
||||
CMBaseMonster::HandleAnimEvent( pEvent );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMFlyingMonster :: Move( float flInterval )
|
||||
{
|
||||
if ( pev->movetype == MOVETYPE_FLY )
|
||||
m_flGroundSpeed = m_flightSpeed;
|
||||
CMBaseMonster::Move( flInterval );
|
||||
}
|
||||
|
||||
|
||||
BOOL CMFlyingMonster:: ShouldAdvanceRoute( float flWaypointDist )
|
||||
{
|
||||
// Get true 3D distance to the goal so we actually reach the correct height
|
||||
if ( m_Route[ m_iRouteIndex ].iType & bits_MF_IS_GOAL )
|
||||
flWaypointDist = ( m_Route[ m_iRouteIndex ].vecLocation - pev->origin ).Length();
|
||||
|
||||
if ( flWaypointDist <= 64 + (m_flGroundSpeed * gpGlobals->frametime) )
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void CMFlyingMonster::MoveExecute( edict_t *pTargetEnt, const Vector &vecDir, float flInterval )
|
||||
{
|
||||
if ( pev->movetype == MOVETYPE_FLY )
|
||||
{
|
||||
if ( gpGlobals->time - m_stopTime > 1.0 )
|
||||
{
|
||||
if ( m_IdealActivity != m_movementActivity )
|
||||
{
|
||||
m_IdealActivity = m_movementActivity;
|
||||
m_flGroundSpeed = m_flightSpeed = 200;
|
||||
}
|
||||
}
|
||||
Vector vecMove = pev->origin + (( vecDir + (m_vecTravel * m_momentum) ).Normalize() * (m_flGroundSpeed * flInterval));
|
||||
|
||||
if ( m_IdealActivity != m_movementActivity )
|
||||
{
|
||||
m_flightSpeed = UTIL_Approach( 100, m_flightSpeed, 75 * gpGlobals->frametime );
|
||||
if ( m_flightSpeed < 100 )
|
||||
m_stopTime = gpGlobals->time;
|
||||
}
|
||||
else
|
||||
m_flightSpeed = UTIL_Approach( 20, m_flightSpeed, 300 * gpGlobals->frametime );
|
||||
|
||||
if ( CheckLocalMove ( pev->origin, vecMove, pTargetEnt, NULL ) )
|
||||
{
|
||||
m_vecTravel = (vecMove - pev->origin);
|
||||
m_vecTravel = m_vecTravel.Normalize();
|
||||
UTIL_MoveToOrigin(ENT(pev), vecMove, (m_flGroundSpeed * flInterval), MOVE_STRAFE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IdealActivity = GetStoppedActivity();
|
||||
m_stopTime = gpGlobals->time;
|
||||
m_vecTravel = g_vecZero;
|
||||
}
|
||||
}
|
||||
else
|
||||
CMBaseMonster::MoveExecute( pTargetEnt, vecDir, flInterval );
|
||||
}
|
||||
|
||||
|
||||
float CMFlyingMonster::CeilingZ( const Vector &position )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
Vector minUp = position;
|
||||
Vector maxUp = position;
|
||||
maxUp.z += 4096.0;
|
||||
|
||||
UTIL_TraceLine(position, maxUp, ignore_monsters, NULL, &tr);
|
||||
if (tr.flFraction != 1.0)
|
||||
maxUp.z = tr.vecEndPos.z;
|
||||
|
||||
if ((pev->flags) & FL_SWIM)
|
||||
{
|
||||
return UTIL_WaterLevel( position, minUp.z, maxUp.z );
|
||||
}
|
||||
return maxUp.z;
|
||||
}
|
||||
|
||||
BOOL CMFlyingMonster::ProbeZ( const Vector &position, const Vector &probe, float *pFraction)
|
||||
{
|
||||
int conPosition = UTIL_PointContents(position);
|
||||
if ( (((pev->flags) & FL_SWIM) == FL_SWIM) ^ (conPosition == CONTENTS_WATER))
|
||||
{
|
||||
// SWIMING & !WATER
|
||||
// or FLYING & WATER
|
||||
//
|
||||
*pFraction = 0.0;
|
||||
return TRUE; // We hit a water boundary because we are where we don't belong.
|
||||
}
|
||||
int conProbe = UTIL_PointContents(probe);
|
||||
if (conProbe == conPosition)
|
||||
{
|
||||
// The probe is either entirely inside the water (for fish) or entirely
|
||||
// outside the water (for birds).
|
||||
//
|
||||
*pFraction = 1.0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Vector ProbeUnit = (probe-position).Normalize();
|
||||
float ProbeLength = (probe-position).Length();
|
||||
float maxProbeLength = ProbeLength;
|
||||
float minProbeLength = 0;
|
||||
|
||||
float diff = maxProbeLength - minProbeLength;
|
||||
while (diff > 1.0)
|
||||
{
|
||||
float midProbeLength = minProbeLength + diff/2.0;
|
||||
Vector midProbeVec = midProbeLength * ProbeUnit;
|
||||
if (UTIL_PointContents(position+midProbeVec) == conPosition)
|
||||
{
|
||||
minProbeLength = midProbeLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxProbeLength = midProbeLength;
|
||||
}
|
||||
diff = maxProbeLength - minProbeLength;
|
||||
}
|
||||
*pFraction = minProbeLength/ProbeLength;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
float CMFlyingMonster::FloorZ( const Vector &position )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
Vector down = position;
|
||||
down.z -= 2048;
|
||||
|
||||
UTIL_TraceLine( position, down, ignore_monsters, NULL, &tr );
|
||||
|
||||
if ( tr.flFraction != 1.0 )
|
||||
return tr.vecEndPos.z;
|
||||
|
||||
return down.z;
|
||||
}
|
||||
|
||||
70
src/dlls/func_break.h
Normal file
70
src/dlls/func_break.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef 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 CMBreakable : public CMBaseDelay
|
||||
{
|
||||
public:
|
||||
// basic functions
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void KeyValue( KeyValueData* pkvd);
|
||||
void EXPORT BreakTouch( CMBaseEntity *pOther );
|
||||
void Use( CMBaseEntity *pActivator, CMBaseEntity *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 (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION); }
|
||||
|
||||
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[];
|
||||
|
||||
Materials m_Material;
|
||||
Explosions m_Explosion;
|
||||
int m_idShard;
|
||||
float m_angle;
|
||||
int m_iszGibModel;
|
||||
int m_iszSpawnObject;
|
||||
};
|
||||
|
||||
#endif // FUNC_BREAK_H
|
||||
466
src/dlls/ggrenade.cpp
Normal file
466
src/dlls/ggrenade.cpp
Normal file
@@ -0,0 +1,466 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
/*
|
||||
|
||||
===== generic grenade.cpp ========================================================
|
||||
|
||||
*/
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "weapons.h"
|
||||
#include "nodes.h"
|
||||
#include "decals.h"
|
||||
#include "explode.h"
|
||||
|
||||
|
||||
//===================grenade
|
||||
|
||||
// Grenades flagged with this will be triggered when the owner calls detonateSatchelCharges
|
||||
#define SF_DETONATE 0x0001
|
||||
|
||||
//
|
||||
// Grenade Explode
|
||||
//
|
||||
void CMGrenade::Explode( Vector vecSrc, Vector vecAim )
|
||||
{
|
||||
TraceResult tr;
|
||||
UTIL_TraceLine ( pev->origin, pev->origin + Vector ( 0, 0, -32 ), ignore_monsters, ENT(pev), & tr);
|
||||
|
||||
Explode( &tr, DMG_BLAST );
|
||||
}
|
||||
|
||||
// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution.
|
||||
void CMGrenade::Explode( TraceResult *pTrace, int bitsDamageType )
|
||||
{
|
||||
float flRndSound;// sound randomizer
|
||||
|
||||
pev->model = iStringNull;//invisible
|
||||
pev->solid = SOLID_NOT;// intangible
|
||||
|
||||
pev->takedamage = DAMAGE_NO;
|
||||
|
||||
// Pull out of the wall a bit
|
||||
if ( pTrace->flFraction != 1.0 )
|
||||
{
|
||||
pev->origin = pTrace->vecEndPos + (pTrace->vecPlaneNormal * (pev->dmg - 24) * 0.6);
|
||||
}
|
||||
|
||||
int iContents = UTIL_PointContents ( pev->origin );
|
||||
|
||||
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
|
||||
WRITE_BYTE( TE_EXPLOSION ); // This makes a dynamic light and the explosion sprites/sound
|
||||
WRITE_COORD( pev->origin.x ); // Send to PAS because of the sound
|
||||
WRITE_COORD( pev->origin.y );
|
||||
WRITE_COORD( pev->origin.z );
|
||||
if (iContents != CONTENTS_WATER)
|
||||
{
|
||||
WRITE_SHORT( g_sModelIndexFireball );
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE_SHORT( g_sModelIndexWExplosion );
|
||||
}
|
||||
WRITE_BYTE( (pev->dmg - 50) * .60 ); // scale * 10
|
||||
WRITE_BYTE( 15 ); // framerate
|
||||
WRITE_BYTE( TE_EXPLFLAG_NONE );
|
||||
MESSAGE_END();
|
||||
|
||||
entvars_t *pevOwner;
|
||||
if ( pev->owner )
|
||||
pevOwner = VARS( pev->owner );
|
||||
else
|
||||
pevOwner = NULL;
|
||||
|
||||
pev->owner = NULL; // can't traceline attack owner if this is set
|
||||
|
||||
RadiusDamage ( pev, pevOwner, pev->dmg, CLASS_NONE, bitsDamageType );
|
||||
|
||||
if ( RANDOM_FLOAT( 0 , 1 ) < 0.5 )
|
||||
{
|
||||
UTIL_DecalTrace( pTrace, DECAL_SCORCH1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
UTIL_DecalTrace( pTrace, DECAL_SCORCH2 );
|
||||
}
|
||||
|
||||
flRndSound = RANDOM_FLOAT( 0 , 1 );
|
||||
|
||||
switch ( RANDOM_LONG( 0, 2 ) )
|
||||
{
|
||||
case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris1.wav", 0.55, ATTN_NORM); break;
|
||||
case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris2.wav", 0.55, ATTN_NORM); break;
|
||||
case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris3.wav", 0.55, ATTN_NORM); break;
|
||||
}
|
||||
|
||||
pev->effects |= EF_NODRAW;
|
||||
SetThink( Smoke );
|
||||
pev->velocity = g_vecZero;
|
||||
pev->nextthink = gpGlobals->time + 0.3;
|
||||
|
||||
/*jlb
|
||||
if (iContents != CONTENTS_WATER)
|
||||
{
|
||||
int sparkCount = RANDOM_LONG(0,3);
|
||||
for ( int i = 0; i < sparkCount; i++ )
|
||||
Create( "spark_shower", pev->origin, pTrace->vecPlaneNormal, NULL );
|
||||
}
|
||||
jlb*/
|
||||
}
|
||||
|
||||
|
||||
void CMGrenade::Smoke( void )
|
||||
{
|
||||
if (UTIL_PointContents ( pev->origin ) == CONTENTS_WATER)
|
||||
{
|
||||
UTIL_Bubbles( pev->origin - Vector( 64, 64, 64 ), pev->origin + Vector( 64, 64, 64 ), 100 );
|
||||
}
|
||||
else
|
||||
{
|
||||
MESSAGE_BEGIN( MSG_PVS, 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( (pev->dmg - 50) * 0.80 ); // scale * 10
|
||||
WRITE_BYTE( 12 ); // framerate
|
||||
MESSAGE_END();
|
||||
}
|
||||
UTIL_Remove( this->edict() );
|
||||
}
|
||||
|
||||
void CMGrenade::Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
Detonate( );
|
||||
}
|
||||
|
||||
|
||||
// Timed grenade, this think is called when time runs out.
|
||||
void CMGrenade::DetonateUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
SetThink( Detonate );
|
||||
pev->nextthink = gpGlobals->time;
|
||||
}
|
||||
|
||||
void CMGrenade::PreDetonate( void )
|
||||
{
|
||||
SetThink( Detonate );
|
||||
pev->nextthink = gpGlobals->time + 1;
|
||||
}
|
||||
|
||||
|
||||
void CMGrenade::Detonate( void )
|
||||
{
|
||||
TraceResult tr;
|
||||
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);
|
||||
|
||||
Explode( &tr, DMG_BLAST );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Contact grenade, explode when it touches something
|
||||
//
|
||||
void CMGrenade::ExplodeTouch( edict_t *pOther )
|
||||
{
|
||||
TraceResult tr;
|
||||
Vector vecSpot;// trace starts here!
|
||||
|
||||
pev->enemy = pOther;
|
||||
|
||||
vecSpot = pev->origin - pev->velocity.Normalize() * 32;
|
||||
UTIL_TraceLine( vecSpot, vecSpot + pev->velocity.Normalize() * 64, ignore_monsters, ENT(pev), &tr );
|
||||
|
||||
Explode( &tr, DMG_BLAST );
|
||||
}
|
||||
|
||||
|
||||
void CMGrenade::DangerSoundThink( void )
|
||||
{
|
||||
if (!IsInWorld())
|
||||
{
|
||||
UTIL_Remove( this->edict() );
|
||||
return;
|
||||
}
|
||||
|
||||
pev->nextthink = gpGlobals->time + 0.2;
|
||||
|
||||
if (pev->waterlevel != 0)
|
||||
{
|
||||
pev->velocity = pev->velocity * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMGrenade::BounceTouch( edict_t *pOther )
|
||||
{
|
||||
// don't hit the guy that launched this grenade
|
||||
if ( pOther == pev->owner )
|
||||
return;
|
||||
|
||||
// only do damage if we're moving fairly fast
|
||||
if (m_flNextAttack < gpGlobals->time && pev->velocity.Length() > 100)
|
||||
{
|
||||
entvars_t *pevOwner = VARS( pev->owner );
|
||||
if (pevOwner)
|
||||
{
|
||||
TraceResult tr = UTIL_GetGlobalTrace( );
|
||||
ClearMultiDamage( );
|
||||
|
||||
if (UTIL_IsPlayer(pOther))
|
||||
UTIL_TraceAttack(pOther, pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB );
|
||||
else if (pOther->v.euser4 != NULL)
|
||||
{
|
||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther));
|
||||
pMonster->TraceAttack(pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB );
|
||||
}
|
||||
|
||||
ApplyMultiDamage( pev, pevOwner);
|
||||
}
|
||||
m_flNextAttack = gpGlobals->time + 1.0; // debounce
|
||||
}
|
||||
|
||||
Vector vecTestVelocity;
|
||||
// pev->avelocity = Vector (300, 300, 300);
|
||||
|
||||
// this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical
|
||||
// or thrown very far tend to slow down too quickly for me to always catch just by testing velocity.
|
||||
// trimming the Z velocity a bit seems to help quite a bit.
|
||||
vecTestVelocity = pev->velocity;
|
||||
vecTestVelocity.z *= 0.45;
|
||||
|
||||
if ( !m_fRegisteredSound && vecTestVelocity.Length() <= 60 )
|
||||
{
|
||||
//ALERT( at_console, "Grenade Registered!: %f\n", vecTestVelocity.Length() );
|
||||
|
||||
// grenade is moving really slow. It's probably very close to where it will ultimately stop moving.
|
||||
// go ahead and emit the danger sound.
|
||||
|
||||
// register a radius louder than the explosion, so we make sure everyone gets out of the way
|
||||
m_fRegisteredSound = TRUE;
|
||||
}
|
||||
|
||||
if (pev->flags & FL_ONGROUND)
|
||||
{
|
||||
// add a bit of static friction
|
||||
pev->velocity = pev->velocity * 0.8;
|
||||
|
||||
pev->sequence = RANDOM_LONG( 1, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// play bounce sound
|
||||
BounceSound();
|
||||
}
|
||||
pev->framerate = pev->velocity.Length() / 200.0;
|
||||
if (pev->framerate > 1.0)
|
||||
pev->framerate = 1;
|
||||
else if (pev->framerate < 0.5)
|
||||
pev->framerate = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMGrenade::SlideTouch( edict_t *pOther )
|
||||
{
|
||||
// don't hit the guy that launched this grenade
|
||||
if ( pOther == pev->owner )
|
||||
return;
|
||||
|
||||
// pev->avelocity = Vector (300, 300, 300);
|
||||
|
||||
if (pev->flags & FL_ONGROUND)
|
||||
{
|
||||
// add a bit of static friction
|
||||
pev->velocity = pev->velocity * 0.95;
|
||||
|
||||
if (pev->velocity.x != 0 || pev->velocity.y != 0)
|
||||
{
|
||||
// maintain sliding sound
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BounceSound();
|
||||
}
|
||||
}
|
||||
|
||||
void CMGrenade :: BounceSound( void )
|
||||
{
|
||||
switch ( RANDOM_LONG( 0, 2 ) )
|
||||
{
|
||||
case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/grenade_hit1.wav", 0.25, ATTN_NORM); break;
|
||||
case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/grenade_hit2.wav", 0.25, ATTN_NORM); break;
|
||||
case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/grenade_hit3.wav", 0.25, ATTN_NORM); break;
|
||||
}
|
||||
}
|
||||
|
||||
void CMGrenade :: TumbleThink( void )
|
||||
{
|
||||
if (!IsInWorld())
|
||||
{
|
||||
UTIL_Remove( this->edict() );
|
||||
return;
|
||||
}
|
||||
|
||||
StudioFrameAdvance( );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
|
||||
if (pev->dmgtime <= gpGlobals->time)
|
||||
{
|
||||
SetThink( Detonate );
|
||||
}
|
||||
if (pev->waterlevel != 0)
|
||||
{
|
||||
pev->velocity = pev->velocity * 0.5;
|
||||
pev->framerate = 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMGrenade:: Spawn( void )
|
||||
{
|
||||
pev->movetype = MOVETYPE_BOUNCE;
|
||||
pev->classname = MAKE_STRING( "grenade" );
|
||||
|
||||
pev->solid = SOLID_BBOX;
|
||||
|
||||
SET_MODEL(ENT(pev), "models/grenade.mdl");
|
||||
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
|
||||
|
||||
pev->dmg = 100;
|
||||
m_fRegisteredSound = FALSE;
|
||||
}
|
||||
|
||||
|
||||
CMGrenade *CMGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
|
||||
{
|
||||
CMGrenade *pGrenade = CreateClassPtr( (CMGrenade *)NULL );
|
||||
|
||||
if (pGrenade == NULL) // no free monster edicts left?
|
||||
return NULL;
|
||||
|
||||
pGrenade->Spawn();
|
||||
// contact grenades arc lower
|
||||
pGrenade->pev->gravity = 0.5;// lower gravity since grenade is aerodynamic and engine doesn't know it.
|
||||
UTIL_SetOrigin( pGrenade->pev, vecStart );
|
||||
pGrenade->pev->velocity = vecVelocity;
|
||||
pGrenade->pev->angles = UTIL_VecToAngles (pGrenade->pev->velocity);
|
||||
pGrenade->pev->owner = ENT(pevOwner);
|
||||
|
||||
// make monsters afaid of it while in the air
|
||||
pGrenade->SetThink( DangerSoundThink );
|
||||
pGrenade->pev->nextthink = gpGlobals->time;
|
||||
|
||||
// Tumble in air
|
||||
pGrenade->pev->avelocity.x = RANDOM_FLOAT ( -100, -500 );
|
||||
|
||||
// Explode on contact
|
||||
pGrenade->SetTouch( ExplodeTouch );
|
||||
|
||||
pGrenade->pev->dmg = gSkillData.monDmgM203Grenade;
|
||||
|
||||
return pGrenade;
|
||||
}
|
||||
|
||||
|
||||
CMGrenade * CMGrenade:: ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time )
|
||||
{
|
||||
CMGrenade *pGrenade = CreateClassPtr( (CMGrenade *)NULL );
|
||||
|
||||
if (pGrenade == NULL) // no free monster edicts left?
|
||||
return NULL;
|
||||
|
||||
pGrenade->Spawn();
|
||||
UTIL_SetOrigin( pGrenade->pev, vecStart );
|
||||
pGrenade->pev->velocity = vecVelocity;
|
||||
pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity);
|
||||
pGrenade->pev->owner = ENT(pevOwner);
|
||||
|
||||
pGrenade->SetTouch( BounceTouch ); // Bounce if touched
|
||||
|
||||
// Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate
|
||||
// will insert a DANGER sound into the world sound list and delay detonation for one second so that
|
||||
// the grenade explodes after the exact amount of time specified in the call to ShootTimed().
|
||||
|
||||
pGrenade->pev->dmgtime = gpGlobals->time + time;
|
||||
pGrenade->SetThink( TumbleThink );
|
||||
pGrenade->pev->nextthink = gpGlobals->time + 0.1;
|
||||
if (time < 0.1)
|
||||
{
|
||||
pGrenade->pev->nextthink = gpGlobals->time;
|
||||
pGrenade->pev->velocity = Vector( 0, 0, 0 );
|
||||
}
|
||||
|
||||
pGrenade->pev->sequence = RANDOM_LONG( 3, 6 );
|
||||
pGrenade->pev->framerate = 1.0;
|
||||
|
||||
// Tumble through the air
|
||||
// pGrenade->pev->avelocity.x = -400;
|
||||
|
||||
pGrenade->pev->gravity = 0.5;
|
||||
pGrenade->pev->friction = 0.8;
|
||||
|
||||
SET_MODEL(ENT(pGrenade->pev), "models/w_grenade.mdl");
|
||||
pGrenade->pev->dmg = 100;
|
||||
|
||||
return pGrenade;
|
||||
}
|
||||
|
||||
|
||||
CMGrenade * CMGrenade :: ShootSatchelCharge( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
|
||||
{
|
||||
CMGrenade *pGrenade = CreateClassPtr( (CMGrenade *)NULL );
|
||||
|
||||
if (pGrenade == NULL) // no free monster edicts left?
|
||||
return NULL;
|
||||
|
||||
pGrenade->pev->movetype = MOVETYPE_BOUNCE;
|
||||
pGrenade->pev->classname = MAKE_STRING( "grenade" );
|
||||
|
||||
pGrenade->pev->solid = SOLID_BBOX;
|
||||
|
||||
SET_MODEL(ENT(pGrenade->pev), "models/grenade.mdl"); // Change this to satchel charge model
|
||||
|
||||
UTIL_SetSize(pGrenade->pev, Vector( 0, 0, 0), Vector(0, 0, 0));
|
||||
|
||||
pGrenade->pev->dmg = 200;
|
||||
UTIL_SetOrigin( pGrenade->pev, vecStart );
|
||||
pGrenade->pev->velocity = vecVelocity;
|
||||
pGrenade->pev->angles = g_vecZero;
|
||||
pGrenade->pev->owner = ENT(pevOwner);
|
||||
|
||||
// Detonate in "time" seconds
|
||||
pGrenade->SetThink( SUB_DoNothing );
|
||||
pGrenade->SetUse( DetonateUse );
|
||||
pGrenade->SetTouch( SlideTouch );
|
||||
pGrenade->pev->spawnflags = SF_DETONATE;
|
||||
|
||||
pGrenade->pev->friction = 0.9;
|
||||
|
||||
return pGrenade;
|
||||
}
|
||||
|
||||
//======================end grenade
|
||||
|
||||
199
src/dlls/h_ai.cpp
Normal file
199
src/dlls/h_ai.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
/*
|
||||
|
||||
h_ai.cpp - halflife specific ai code
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.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 = g_psv_gravity->value * 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 = g_psv_gravity->value * 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;
|
||||
}
|
||||
|
||||
|
||||
46
src/dlls/h_export.cpp
Normal file
46
src/dlls/h_export.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// botman's monster - MetaMOD plugin
|
||||
//
|
||||
// h_export.cpp
|
||||
//
|
||||
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 2000 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 "h_export.h"
|
||||
|
||||
// From SDK dlls/h_export.cpp:
|
||||
|
||||
//! Holds engine functionality callbacks
|
||||
enginefuncs_t g_engfuncs;
|
||||
globalvars_t *gpGlobals;
|
||||
|
||||
// Receive engine function table from engine.
|
||||
// This appears to be the _first_ DLL routine called by the engine, so we
|
||||
// do some setup operations here.
|
||||
void WINAPI GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals )
|
||||
{
|
||||
memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t));
|
||||
gpGlobals = pGlobals;
|
||||
}
|
||||
|
||||
909
src/dlls/hassassin.cpp
Normal file
909
src/dlls/hassassin.cpp
Normal file
@@ -0,0 +1,909 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
|
||||
|
||||
//=========================================================
|
||||
// hassassin - Human assassin, fast and stealthy
|
||||
//=========================================================
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "schedule.h"
|
||||
#include "weapons.h"
|
||||
|
||||
//=========================================================
|
||||
// monster-specific schedule types
|
||||
//=========================================================
|
||||
enum
|
||||
{
|
||||
SCHED_ASSASSIN_EXPOSED = LAST_COMMON_SCHEDULE + 1,// cover was blown.
|
||||
SCHED_ASSASSIN_JUMP, // fly through the air
|
||||
SCHED_ASSASSIN_JUMP_ATTACK, // fly through the air and shoot
|
||||
SCHED_ASSASSIN_JUMP_LAND, // hit and run away
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// monster-specific tasks
|
||||
//=========================================================
|
||||
|
||||
enum
|
||||
{
|
||||
TASK_ASSASSIN_FALL_TO_GROUND = LAST_COMMON_TASK + 1, // falling and waiting to hit ground
|
||||
};
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
#define ASSASSIN_AE_SHOOT1 1
|
||||
#define ASSASSIN_AE_TOSS1 2
|
||||
#define ASSASSIN_AE_JUMP 3
|
||||
|
||||
|
||||
#define bits_MEMORY_BADJUMP (bits_MEMORY_CUSTOM1)
|
||||
|
||||
|
||||
//=========================================================
|
||||
// DieSound
|
||||
//=========================================================
|
||||
void CMHAssassin :: DeathSound ( void )
|
||||
{
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// IdleSound
|
||||
//=========================================================
|
||||
void CMHAssassin :: IdleSound ( void )
|
||||
{
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ISoundMask - returns a bit mask indicating which types
|
||||
// of sounds this monster regards.
|
||||
//=========================================================
|
||||
int CMHAssassin :: ISoundMask ( void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CMHAssassin :: Classify ( void )
|
||||
{
|
||||
return CLASS_HUMAN_MILITARY;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CMHAssassin :: SetYawSpeed ( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
switch ( m_Activity )
|
||||
{
|
||||
case ACT_TURN_LEFT:
|
||||
case ACT_TURN_RIGHT:
|
||||
ys = 360;
|
||||
break;
|
||||
default:
|
||||
ys = 360;
|
||||
break;
|
||||
}
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Shoot
|
||||
//=========================================================
|
||||
void CMHAssassin :: Shoot ( void )
|
||||
{
|
||||
if (m_hEnemy == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector vecShootOrigin = GetGunPosition();
|
||||
Vector vecShootDir = ShootAtEnemy( vecShootOrigin );
|
||||
|
||||
if (m_flLastShot + 2 < gpGlobals->time)
|
||||
{
|
||||
m_flDiviation = 0.10;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flDiviation -= 0.01;
|
||||
if (m_flDiviation < 0.02)
|
||||
m_flDiviation = 0.02;
|
||||
}
|
||||
m_flLastShot = gpGlobals->time;
|
||||
|
||||
UTIL_MakeVectors ( pev->angles );
|
||||
|
||||
Vector vecShellVelocity = gpGlobals->v_right * RANDOM_FLOAT(40,90) + gpGlobals->v_up * RANDOM_FLOAT(75,200) + gpGlobals->v_forward * RANDOM_FLOAT(-40, 40);
|
||||
EjectBrass ( pev->origin + gpGlobals->v_up * 32 + gpGlobals->v_forward * 12, vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHELL);
|
||||
FireBullets(1, vecShootOrigin, vecShootDir, Vector( m_flDiviation, m_flDiviation, m_flDiviation ), 2048, BULLET_MONSTER_9MM ); // shoot +-8 degrees
|
||||
|
||||
switch(RANDOM_LONG(0,1))
|
||||
{
|
||||
case 0:
|
||||
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/pl_gun1.wav", RANDOM_FLOAT(0.6, 0.8), ATTN_NORM);
|
||||
break;
|
||||
case 1:
|
||||
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/pl_gun2.wav", RANDOM_FLOAT(0.6, 0.8), ATTN_NORM);
|
||||
break;
|
||||
}
|
||||
|
||||
pev->effects |= EF_MUZZLEFLASH;
|
||||
|
||||
Vector angDir = UTIL_VecToAngles( vecShootDir );
|
||||
SetBlending( 0, angDir.x );
|
||||
|
||||
m_cAmmoLoaded--;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CMHAssassin :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case ASSASSIN_AE_SHOOT1:
|
||||
Shoot( );
|
||||
break;
|
||||
case ASSASSIN_AE_TOSS1:
|
||||
{
|
||||
UTIL_MakeVectors( pev->angles );
|
||||
CMGrenade::ShootTimed( pev, pev->origin + gpGlobals->v_forward * 34 + Vector (0, 0, 32), m_vecTossVelocity, 2.0 );
|
||||
|
||||
m_flNextGrenadeCheck = gpGlobals->time + 6;// wait six seconds before even looking again to see if a grenade can be thrown.
|
||||
m_fThrowGrenade = FALSE;
|
||||
// !!!LATER - when in a group, only try to throw grenade if ordered.
|
||||
}
|
||||
break;
|
||||
case ASSASSIN_AE_JUMP:
|
||||
{
|
||||
// ALERT( at_console, "jumping");
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
pev->movetype = MOVETYPE_TOSS;
|
||||
pev->flags &= ~FL_ONGROUND;
|
||||
pev->velocity = m_vecJumpVelocity;
|
||||
m_flNextJump = gpGlobals->time + 3.0;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
CMBaseMonster::HandleAnimEvent( pEvent );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CMHAssassin :: Spawn()
|
||||
{
|
||||
Precache( );
|
||||
|
||||
SET_MODEL(ENT(pev), "models/hassassin.mdl");
|
||||
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
|
||||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
m_bloodColor = BLOOD_COLOR_RED;
|
||||
pev->effects = 0;
|
||||
pev->health = gSkillData.hassassinHealth;
|
||||
m_flFieldOfView = VIEW_FIELD_WIDE; // indicates the width of this monster's forward view cone ( as a dotproduct result )
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
m_afCapability = bits_CAP_MELEE_ATTACK1 | bits_CAP_DOORS_GROUP;
|
||||
pev->friction = 1;
|
||||
|
||||
m_HackedGunPos = Vector( 0, 24, 48 );
|
||||
|
||||
m_iTargetRanderamt = 20;
|
||||
pev->renderamt = 20;
|
||||
pev->rendermode = kRenderTransTexture;
|
||||
|
||||
MonsterInit();
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CMHAssassin :: Precache()
|
||||
{
|
||||
PRECACHE_MODEL("models/hassassin.mdl");
|
||||
|
||||
PRECACHE_SOUND("weapons/pl_gun1.wav");
|
||||
PRECACHE_SOUND("weapons/pl_gun2.wav");
|
||||
|
||||
PRECACHE_SOUND("debris/beamstart1.wav");
|
||||
|
||||
m_iShell = PRECACHE_MODEL ("models/shell.mdl");// brass shell
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
|
||||
//=========================================================
|
||||
// Fail Schedule
|
||||
//=========================================================
|
||||
Task_t tlAssassinFail[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_WAIT_FACE_ENEMY, (float)2 },
|
||||
// { TASK_WAIT_PVS, (float)0 },
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_CHASE_ENEMY },
|
||||
};
|
||||
|
||||
Schedule_t slAssassinFail[] =
|
||||
{
|
||||
{
|
||||
tlAssassinFail,
|
||||
ARRAYSIZE ( tlAssassinFail ),
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_PROVOKED |
|
||||
bits_COND_CAN_RANGE_ATTACK1 |
|
||||
bits_COND_CAN_RANGE_ATTACK2 |
|
||||
bits_COND_CAN_MELEE_ATTACK1 |
|
||||
bits_COND_HEAR_SOUND,
|
||||
0,
|
||||
"AssassinFail"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Enemy exposed Agrunt's cover
|
||||
//=========================================================
|
||||
Task_t tlAssassinExposed[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, (float)0 },
|
||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
||||
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_ASSASSIN_JUMP },
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_TAKE_COVER_FROM_ENEMY },
|
||||
};
|
||||
|
||||
Schedule_t slAssassinExposed[] =
|
||||
{
|
||||
{
|
||||
tlAssassinExposed,
|
||||
ARRAYSIZE ( tlAssassinExposed ),
|
||||
bits_COND_CAN_MELEE_ATTACK1,
|
||||
0,
|
||||
"AssassinExposed",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Take cover from enemy! Tries lateral cover before node
|
||||
// cover!
|
||||
//=========================================================
|
||||
Task_t tlAssassinTakeCoverFromEnemy[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, (float)0 },
|
||||
{ TASK_WAIT, (float)0.2 },
|
||||
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_RANGE_ATTACK1 },
|
||||
{ TASK_FIND_COVER_FROM_ENEMY, (float)0 },
|
||||
{ TASK_RUN_PATH, (float)0 },
|
||||
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||
{ TASK_REMEMBER, (float)bits_MEMORY_INCOVER },
|
||||
{ TASK_FACE_ENEMY, (float)0 },
|
||||
};
|
||||
|
||||
Schedule_t slAssassinTakeCoverFromEnemy[] =
|
||||
{
|
||||
{
|
||||
tlAssassinTakeCoverFromEnemy,
|
||||
ARRAYSIZE ( tlAssassinTakeCoverFromEnemy ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_CAN_MELEE_ATTACK1 |
|
||||
bits_COND_HEAR_SOUND,
|
||||
0,
|
||||
"AssassinTakeCoverFromEnemy"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Take cover from enemy! Tries lateral cover before node
|
||||
// cover!
|
||||
//=========================================================
|
||||
Task_t tlAssassinTakeCoverFromEnemy2[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, (float)0 },
|
||||
{ TASK_WAIT, (float)0.2 },
|
||||
{ TASK_FACE_ENEMY, (float)0 },
|
||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
||||
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_RANGE_ATTACK2 },
|
||||
{ TASK_FIND_FAR_NODE_COVER_FROM_ENEMY, (float)384 },
|
||||
{ TASK_RUN_PATH, (float)0 },
|
||||
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||
{ TASK_REMEMBER, (float)bits_MEMORY_INCOVER },
|
||||
{ TASK_FACE_ENEMY, (float)0 },
|
||||
};
|
||||
|
||||
Schedule_t slAssassinTakeCoverFromEnemy2[] =
|
||||
{
|
||||
{
|
||||
tlAssassinTakeCoverFromEnemy2,
|
||||
ARRAYSIZE ( tlAssassinTakeCoverFromEnemy2 ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_CAN_MELEE_ATTACK2 |
|
||||
bits_COND_HEAR_SOUND,
|
||||
0,
|
||||
"AssassinTakeCoverFromEnemy2"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//=========================================================
|
||||
// hide from the loudest sound source
|
||||
//=========================================================
|
||||
Task_t tlAssassinTakeCoverFromBestSound[] =
|
||||
{
|
||||
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_MELEE_ATTACK1 },
|
||||
{ TASK_STOP_MOVING, (float)0 },
|
||||
{ TASK_FIND_COVER_FROM_BEST_SOUND, (float)0 },
|
||||
{ TASK_RUN_PATH, (float)0 },
|
||||
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||
{ TASK_REMEMBER, (float)bits_MEMORY_INCOVER },
|
||||
{ TASK_TURN_LEFT, (float)179 },
|
||||
};
|
||||
|
||||
Schedule_t slAssassinTakeCoverFromBestSound[] =
|
||||
{
|
||||
{
|
||||
tlAssassinTakeCoverFromBestSound,
|
||||
ARRAYSIZE ( tlAssassinTakeCoverFromBestSound ),
|
||||
bits_COND_NEW_ENEMY,
|
||||
0,
|
||||
"AssassinTakeCoverFromBestSound"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// AlertIdle Schedules
|
||||
//=========================================================
|
||||
Task_t tlAssassinHide[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_WAIT, (float)2 },
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_CHASE_ENEMY },
|
||||
};
|
||||
|
||||
Schedule_t slAssassinHide[] =
|
||||
{
|
||||
{
|
||||
tlAssassinHide,
|
||||
ARRAYSIZE ( tlAssassinHide ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
bits_COND_SEE_ENEMY |
|
||||
bits_COND_SEE_FEAR |
|
||||
bits_COND_LIGHT_DAMAGE |
|
||||
bits_COND_HEAVY_DAMAGE |
|
||||
bits_COND_PROVOKED |
|
||||
bits_COND_HEAR_SOUND,
|
||||
0,
|
||||
"AssassinHide"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=========================================================
|
||||
// HUNT Schedules
|
||||
//=========================================================
|
||||
Task_t tlAssassinHunt[] =
|
||||
{
|
||||
{ TASK_GET_PATH_TO_ENEMY, (float)0 },
|
||||
{ TASK_RUN_PATH, (float)0 },
|
||||
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||
};
|
||||
|
||||
Schedule_t slAssassinHunt[] =
|
||||
{
|
||||
{
|
||||
tlAssassinHunt,
|
||||
ARRAYSIZE ( tlAssassinHunt ),
|
||||
bits_COND_NEW_ENEMY |
|
||||
// bits_COND_SEE_ENEMY |
|
||||
bits_COND_CAN_RANGE_ATTACK1 |
|
||||
bits_COND_HEAR_SOUND,
|
||||
0,
|
||||
"AssassinHunt"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Jumping Schedules
|
||||
//=========================================================
|
||||
Task_t tlAssassinJump[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, (float)0 },
|
||||
{ TASK_PLAY_SEQUENCE, (float)ACT_HOP },
|
||||
{ TASK_SET_SCHEDULE, (float)SCHED_ASSASSIN_JUMP_ATTACK },
|
||||
};
|
||||
|
||||
Schedule_t slAssassinJump[] =
|
||||
{
|
||||
{
|
||||
tlAssassinJump,
|
||||
ARRAYSIZE ( tlAssassinJump ),
|
||||
0,
|
||||
0,
|
||||
"AssassinJump"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//=========================================================
|
||||
// repel
|
||||
//=========================================================
|
||||
Task_t tlAssassinJumpAttack[] =
|
||||
{
|
||||
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_ASSASSIN_JUMP_LAND },
|
||||
// { TASK_SET_ACTIVITY, (float)ACT_FLY },
|
||||
{ TASK_ASSASSIN_FALL_TO_GROUND, (float)0 },
|
||||
};
|
||||
|
||||
|
||||
Schedule_t slAssassinJumpAttack[] =
|
||||
{
|
||||
{
|
||||
tlAssassinJumpAttack,
|
||||
ARRAYSIZE ( tlAssassinJumpAttack ),
|
||||
0,
|
||||
0,
|
||||
"AssassinJumpAttack"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//=========================================================
|
||||
// repel
|
||||
//=========================================================
|
||||
Task_t tlAssassinJumpLand[] =
|
||||
{
|
||||
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_ASSASSIN_EXPOSED },
|
||||
// { TASK_SET_FAIL_SCHEDULE, (float)SCHED_MELEE_ATTACK1 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_REMEMBER, (float)bits_MEMORY_BADJUMP },
|
||||
{ TASK_FIND_NODE_COVER_FROM_ENEMY, (float)0 },
|
||||
{ TASK_RUN_PATH, (float)0 },
|
||||
{ TASK_FORGET, (float)bits_MEMORY_BADJUMP },
|
||||
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||
{ TASK_REMEMBER, (float)bits_MEMORY_INCOVER },
|
||||
{ TASK_FACE_ENEMY, (float)0 },
|
||||
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_RANGE_ATTACK1 },
|
||||
};
|
||||
|
||||
Schedule_t slAssassinJumpLand[] =
|
||||
{
|
||||
{
|
||||
tlAssassinJumpLand,
|
||||
ARRAYSIZE ( tlAssassinJumpLand ),
|
||||
0,
|
||||
0,
|
||||
"AssassinJumpLand"
|
||||
},
|
||||
};
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CMHAssassin )
|
||||
{
|
||||
slAssassinFail,
|
||||
slAssassinExposed,
|
||||
slAssassinTakeCoverFromEnemy,
|
||||
slAssassinTakeCoverFromEnemy2,
|
||||
slAssassinTakeCoverFromBestSound,
|
||||
slAssassinHide,
|
||||
slAssassinHunt,
|
||||
slAssassinJump,
|
||||
slAssassinJumpAttack,
|
||||
slAssassinJumpLand,
|
||||
};
|
||||
|
||||
IMPLEMENT_CUSTOM_SCHEDULES( CMHAssassin, CMBaseMonster );
|
||||
|
||||
|
||||
//=========================================================
|
||||
// CheckMeleeAttack1 - jump like crazy if the enemy gets too close.
|
||||
//=========================================================
|
||||
BOOL CMHAssassin :: CheckMeleeAttack1 ( float flDot, float flDist )
|
||||
{
|
||||
if ( m_flNextJump < gpGlobals->time && (flDist <= 128 || HasMemory( bits_MEMORY_BADJUMP )) && m_hEnemy != NULL )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
Vector vecDest = pev->origin + Vector( RANDOM_FLOAT( -64, 64), RANDOM_FLOAT( -64, 64 ), 160 );
|
||||
|
||||
UTIL_TraceHull( pev->origin + Vector( 0, 0, 36 ), vecDest + Vector( 0, 0, 36 ), dont_ignore_monsters, human_hull, ENT(pev), &tr);
|
||||
|
||||
if ( tr.fStartSolid || tr.flFraction < 1.0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
float flGravity = g_psv_gravity->value;
|
||||
|
||||
float time = sqrt( 160 / (0.5 * flGravity));
|
||||
float speed = flGravity * time / 160;
|
||||
m_vecJumpVelocity = (vecDest - pev->origin) * speed;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack1 - drop a cap in their ass
|
||||
//
|
||||
//=========================================================
|
||||
BOOL CMHAssassin :: CheckRangeAttack1 ( float flDot, float flDist )
|
||||
{
|
||||
if ( !HasConditions( bits_COND_ENEMY_OCCLUDED ) && flDist > 64 && flDist <= 2048 /* && flDot >= 0.5 */ /* && NoFriendlyFire() */ )
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
Vector vecSrc = GetGunPosition();
|
||||
|
||||
// verify that a bullet fired from the gun will hit the enemy before the world.
|
||||
UTIL_TraceLine( vecSrc, UTIL_BodyTarget(m_hEnemy, vecSrc), dont_ignore_monsters, ENT(pev), &tr);
|
||||
|
||||
if ( tr.flFraction == 1 || tr.pHit == m_hEnemy )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack2 - toss grenade is enemy gets in the way and is too close.
|
||||
//=========================================================
|
||||
BOOL CMHAssassin :: CheckRangeAttack2 ( float flDot, float flDist )
|
||||
{
|
||||
m_fThrowGrenade = FALSE;
|
||||
if ( !FBitSet ( m_hEnemy->v.flags, FL_ONGROUND ) )
|
||||
{
|
||||
// don't throw grenades at anything that isn't on the ground!
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// don't get grenade happy unless the player starts to piss you off
|
||||
if ( m_iFrustration <= 2)
|
||||
return FALSE;
|
||||
|
||||
if ( m_flNextGrenadeCheck < gpGlobals->time && !HasConditions( bits_COND_ENEMY_OCCLUDED ) && flDist <= 512 /* && flDot >= 0.5 */ /* && NoFriendlyFire() */ )
|
||||
{
|
||||
Vector vecToss = VecCheckThrow( pev, GetGunPosition( ), UTIL_BodyTarget(m_hEnemy, g_vecZero), flDist, 0.5 ); // use dist as speed to get there in 1 second
|
||||
|
||||
if ( vecToss != g_vecZero )
|
||||
{
|
||||
m_vecTossVelocity = vecToss;
|
||||
|
||||
// throw a hand grenade
|
||||
m_fThrowGrenade = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// RunAI
|
||||
//=========================================================
|
||||
void CMHAssassin :: RunAI( void )
|
||||
{
|
||||
CMBaseMonster :: RunAI();
|
||||
|
||||
// always visible if moving
|
||||
// always visible is not on hard
|
||||
if (m_hEnemy == NULL || pev->deadflag != DEAD_NO || m_Activity == ACT_RUN || m_Activity == ACT_WALK || !(pev->flags & FL_ONGROUND))
|
||||
m_iTargetRanderamt = 255;
|
||||
|
||||
if (pev->renderamt > m_iTargetRanderamt)
|
||||
{
|
||||
if (pev->renderamt == 255)
|
||||
{
|
||||
EMIT_SOUND (ENT(pev), CHAN_BODY, "debris/beamstart1.wav", 0.2, ATTN_NORM );
|
||||
}
|
||||
|
||||
pev->renderamt = max( pev->renderamt - 50, m_iTargetRanderamt );
|
||||
pev->rendermode = kRenderTransTexture;
|
||||
}
|
||||
else if (pev->renderamt < m_iTargetRanderamt)
|
||||
{
|
||||
pev->renderamt = min( pev->renderamt + 50, m_iTargetRanderamt );
|
||||
if (pev->renderamt == 255)
|
||||
pev->rendermode = kRenderNormal;
|
||||
}
|
||||
|
||||
if (m_Activity == ACT_RUN || m_Activity == ACT_WALK)
|
||||
{
|
||||
static int iStep = 0;
|
||||
iStep = ! iStep;
|
||||
if (iStep)
|
||||
{
|
||||
switch( RANDOM_LONG( 0, 3 ) )
|
||||
{
|
||||
case 0: EMIT_SOUND( ENT(pev), CHAN_BODY, "player/pl_step1.wav", 0.5, ATTN_NORM); break;
|
||||
case 1: EMIT_SOUND( ENT(pev), CHAN_BODY, "player/pl_step3.wav", 0.5, ATTN_NORM); break;
|
||||
case 2: EMIT_SOUND( ENT(pev), CHAN_BODY, "player/pl_step2.wav", 0.5, ATTN_NORM); break;
|
||||
case 3: EMIT_SOUND( ENT(pev), CHAN_BODY, "player/pl_step4.wav", 0.5, ATTN_NORM); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// StartTask
|
||||
//=========================================================
|
||||
void CMHAssassin :: StartTask ( Task_t *pTask )
|
||||
{
|
||||
switch ( pTask->iTask )
|
||||
{
|
||||
case TASK_RANGE_ATTACK2:
|
||||
if (!m_fThrowGrenade)
|
||||
{
|
||||
TaskComplete( );
|
||||
}
|
||||
else
|
||||
{
|
||||
CMBaseMonster :: StartTask ( pTask );
|
||||
}
|
||||
break;
|
||||
case TASK_ASSASSIN_FALL_TO_GROUND:
|
||||
break;
|
||||
default:
|
||||
CMBaseMonster :: StartTask ( pTask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// RunTask
|
||||
//=========================================================
|
||||
void CMHAssassin :: RunTask ( Task_t *pTask )
|
||||
{
|
||||
switch ( pTask->iTask )
|
||||
{
|
||||
case TASK_ASSASSIN_FALL_TO_GROUND:
|
||||
MakeIdealYaw( m_vecEnemyLKP );
|
||||
ChangeYaw( pev->yaw_speed );
|
||||
|
||||
if (m_fSequenceFinished)
|
||||
{
|
||||
if (pev->velocity.z > 0)
|
||||
{
|
||||
pev->sequence = LookupSequence( "fly_up" );
|
||||
}
|
||||
else if (HasConditions ( bits_COND_SEE_ENEMY ))
|
||||
{
|
||||
pev->sequence = LookupSequence( "fly_attack" );
|
||||
pev->frame = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pev->sequence = LookupSequence( "fly_down" );
|
||||
pev->frame = 0;
|
||||
}
|
||||
|
||||
ResetSequenceInfo( );
|
||||
SetYawSpeed();
|
||||
}
|
||||
if (pev->flags & FL_ONGROUND)
|
||||
{
|
||||
// ALERT( at_console, "on ground\n");
|
||||
TaskComplete( );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CMBaseMonster :: RunTask ( pTask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// GetSchedule - Decides which type of schedule best suits
|
||||
// the monster's current state and conditions. Then calls
|
||||
// monster's member function to get a pointer to a schedule
|
||||
// of the proper type.
|
||||
//=========================================================
|
||||
Schedule_t *CMHAssassin :: GetSchedule ( void )
|
||||
{
|
||||
switch ( m_MonsterState )
|
||||
{
|
||||
case MONSTERSTATE_IDLE:
|
||||
case MONSTERSTATE_ALERT:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case MONSTERSTATE_COMBAT:
|
||||
{
|
||||
// dead enemy
|
||||
if ( HasConditions( bits_COND_ENEMY_DEAD ) )
|
||||
{
|
||||
// call base class, all code to handle dead enemies is centralized there.
|
||||
return CMBaseMonster :: GetSchedule();
|
||||
}
|
||||
|
||||
// flying?
|
||||
if ( pev->movetype == MOVETYPE_TOSS)
|
||||
{
|
||||
if (pev->flags & FL_ONGROUND)
|
||||
{
|
||||
// ALERT( at_console, "landed\n");
|
||||
// just landed
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
return GetScheduleOfType ( SCHED_ASSASSIN_JUMP_LAND );
|
||||
}
|
||||
else
|
||||
{
|
||||
// ALERT( at_console, "jump\n");
|
||||
// jump or jump/shoot
|
||||
if ( m_MonsterState == MONSTERSTATE_COMBAT )
|
||||
return GetScheduleOfType ( SCHED_ASSASSIN_JUMP );
|
||||
else
|
||||
return GetScheduleOfType ( SCHED_ASSASSIN_JUMP_ATTACK );
|
||||
}
|
||||
}
|
||||
|
||||
if ( HasConditions ( bits_COND_LIGHT_DAMAGE ) )
|
||||
{
|
||||
m_iFrustration++;
|
||||
}
|
||||
if ( HasConditions ( bits_COND_HEAVY_DAMAGE ) )
|
||||
{
|
||||
m_iFrustration++;
|
||||
}
|
||||
|
||||
// jump player!
|
||||
if ( HasConditions ( bits_COND_CAN_MELEE_ATTACK1 ) )
|
||||
{
|
||||
// ALERT( at_console, "melee attack 1\n");
|
||||
return GetScheduleOfType ( SCHED_MELEE_ATTACK1 );
|
||||
}
|
||||
|
||||
// throw grenade
|
||||
if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK2 ) )
|
||||
{
|
||||
// ALERT( at_console, "range attack 2\n");
|
||||
return GetScheduleOfType ( SCHED_RANGE_ATTACK2 );
|
||||
}
|
||||
|
||||
// spotted
|
||||
if ( HasConditions ( bits_COND_SEE_ENEMY ) && HasConditions ( bits_COND_ENEMY_FACING_ME ) )
|
||||
{
|
||||
// ALERT( at_console, "exposed\n");
|
||||
m_iFrustration++;
|
||||
return GetScheduleOfType ( SCHED_ASSASSIN_EXPOSED );
|
||||
}
|
||||
|
||||
// can attack
|
||||
if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
|
||||
{
|
||||
// ALERT( at_console, "range attack 1\n");
|
||||
m_iFrustration = 0;
|
||||
return GetScheduleOfType ( SCHED_RANGE_ATTACK1 );
|
||||
}
|
||||
|
||||
if ( HasConditions ( bits_COND_SEE_ENEMY ) )
|
||||
{
|
||||
// ALERT( at_console, "face\n");
|
||||
return GetScheduleOfType ( SCHED_COMBAT_FACE );
|
||||
}
|
||||
|
||||
// new enemy
|
||||
if ( HasConditions ( bits_COND_NEW_ENEMY ) )
|
||||
{
|
||||
// ALERT( at_console, "take cover\n");
|
||||
return GetScheduleOfType ( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
}
|
||||
|
||||
// ALERT( at_console, "stand\n");
|
||||
return GetScheduleOfType ( SCHED_ALERT_STAND );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CMBaseMonster :: GetSchedule();
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
Schedule_t* CMHAssassin :: GetScheduleOfType ( int Type )
|
||||
{
|
||||
// ALERT( at_console, "%d\n", m_iFrustration );
|
||||
switch ( Type )
|
||||
{
|
||||
case SCHED_TAKE_COVER_FROM_ENEMY:
|
||||
if (pev->health > 30)
|
||||
return slAssassinTakeCoverFromEnemy;
|
||||
else
|
||||
return slAssassinTakeCoverFromEnemy2;
|
||||
case SCHED_TAKE_COVER_FROM_BEST_SOUND:
|
||||
return slAssassinTakeCoverFromBestSound;
|
||||
case SCHED_ASSASSIN_EXPOSED:
|
||||
return slAssassinExposed;
|
||||
case SCHED_FAIL:
|
||||
if (m_MonsterState == MONSTERSTATE_COMBAT)
|
||||
return slAssassinFail;
|
||||
break;
|
||||
case SCHED_ALERT_STAND:
|
||||
if (m_MonsterState == MONSTERSTATE_COMBAT)
|
||||
return slAssassinHide;
|
||||
break;
|
||||
case SCHED_CHASE_ENEMY:
|
||||
return slAssassinHunt;
|
||||
case SCHED_MELEE_ATTACK1:
|
||||
if (pev->flags & FL_ONGROUND)
|
||||
{
|
||||
if (m_flNextJump > gpGlobals->time)
|
||||
{
|
||||
// can't jump yet, go ahead and fail
|
||||
return slAssassinFail;
|
||||
}
|
||||
else
|
||||
{
|
||||
return slAssassinJump;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return slAssassinJumpAttack;
|
||||
}
|
||||
case SCHED_ASSASSIN_JUMP:
|
||||
case SCHED_ASSASSIN_JUMP_ATTACK:
|
||||
return slAssassinJumpAttack;
|
||||
case SCHED_ASSASSIN_JUMP_LAND:
|
||||
return slAssassinJumpLand;
|
||||
}
|
||||
|
||||
return CMBaseMonster :: GetScheduleOfType( Type );
|
||||
}
|
||||
|
||||
#endif
|
||||
506
src/dlls/headcrab.cpp
Normal file
506
src/dlls/headcrab.cpp
Normal file
@@ -0,0 +1,506 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// headcrab.cpp - tiny, jumpy alien parasite
|
||||
//=========================================================
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "schedule.h"
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
#define HC_AE_JUMPATTACK ( 2 )
|
||||
|
||||
Task_t tlHCRangeAttack1[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, (float)0 },
|
||||
{ TASK_FACE_IDEAL, (float)0 },
|
||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
{ TASK_FACE_IDEAL, (float)0 },
|
||||
{ TASK_WAIT_RANDOM, (float)0.5 },
|
||||
};
|
||||
|
||||
Schedule_t slHCRangeAttack1[] =
|
||||
{
|
||||
{
|
||||
tlHCRangeAttack1,
|
||||
ARRAYSIZE ( tlHCRangeAttack1 ),
|
||||
bits_COND_ENEMY_OCCLUDED |
|
||||
bits_COND_NO_AMMO_LOADED,
|
||||
0,
|
||||
"HCRangeAttack1"
|
||||
},
|
||||
};
|
||||
|
||||
Task_t tlHCRangeAttack1Fast[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, (float)0 },
|
||||
{ TASK_FACE_IDEAL, (float)0 },
|
||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
||||
};
|
||||
|
||||
Schedule_t slHCRangeAttack1Fast[] =
|
||||
{
|
||||
{
|
||||
tlHCRangeAttack1Fast,
|
||||
ARRAYSIZE ( tlHCRangeAttack1Fast ),
|
||||
bits_COND_ENEMY_OCCLUDED |
|
||||
bits_COND_NO_AMMO_LOADED,
|
||||
0,
|
||||
"HCRAFast"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CMHeadCrab )
|
||||
{
|
||||
slHCRangeAttack1,
|
||||
slHCRangeAttack1Fast,
|
||||
};
|
||||
|
||||
IMPLEMENT_CUSTOM_SCHEDULES( CMHeadCrab, CMBaseMonster );
|
||||
|
||||
const char *CMHeadCrab::pIdleSounds[] =
|
||||
{
|
||||
"headcrab/hc_idle1.wav",
|
||||
"headcrab/hc_idle2.wav",
|
||||
"headcrab/hc_idle3.wav",
|
||||
};
|
||||
const char *CMHeadCrab::pAlertSounds[] =
|
||||
{
|
||||
"headcrab/hc_alert1.wav",
|
||||
};
|
||||
const char *CMHeadCrab::pPainSounds[] =
|
||||
{
|
||||
"headcrab/hc_pain1.wav",
|
||||
"headcrab/hc_pain2.wav",
|
||||
"headcrab/hc_pain3.wav",
|
||||
};
|
||||
const char *CMHeadCrab::pAttackSounds[] =
|
||||
{
|
||||
"headcrab/hc_attack1.wav",
|
||||
"headcrab/hc_attack2.wav",
|
||||
"headcrab/hc_attack3.wav",
|
||||
};
|
||||
|
||||
const char *CMHeadCrab::pDeathSounds[] =
|
||||
{
|
||||
"headcrab/hc_die1.wav",
|
||||
"headcrab/hc_die2.wav",
|
||||
};
|
||||
|
||||
const char *CMHeadCrab::pBiteSounds[] =
|
||||
{
|
||||
"headcrab/hc_headbite.wav",
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CMHeadCrab :: Classify ( void )
|
||||
{
|
||||
return CLASS_ALIEN_PREY;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Center - returns the real center of the headcrab. The
|
||||
// bounding box is much larger than the actual creature so
|
||||
// this is needed for targeting
|
||||
//=========================================================
|
||||
Vector CMHeadCrab :: Center ( void )
|
||||
{
|
||||
return Vector( pev->origin.x, pev->origin.y, pev->origin.z + 6 );
|
||||
}
|
||||
|
||||
|
||||
Vector CMHeadCrab :: BodyTarget( const Vector &posSrc )
|
||||
{
|
||||
return Center( );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CMHeadCrab :: SetYawSpeed ( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
switch ( m_Activity )
|
||||
{
|
||||
case ACT_IDLE:
|
||||
ys = 30;
|
||||
break;
|
||||
case ACT_RUN:
|
||||
case ACT_WALK:
|
||||
ys = 20;
|
||||
break;
|
||||
case ACT_TURN_LEFT:
|
||||
case ACT_TURN_RIGHT:
|
||||
ys = 60;
|
||||
break;
|
||||
case ACT_RANGE_ATTACK1:
|
||||
ys = 30;
|
||||
break;
|
||||
default:
|
||||
ys = 30;
|
||||
break;
|
||||
}
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//=========================================================
|
||||
void CMHeadCrab :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case HC_AE_JUMPATTACK:
|
||||
{
|
||||
ClearBits( pev->flags, FL_ONGROUND );
|
||||
|
||||
UTIL_SetOrigin (pev, pev->origin + Vector ( 0 , 0 , 1) );// take him off ground so engine doesn't instantly reset onground
|
||||
UTIL_MakeVectors ( pev->angles );
|
||||
|
||||
Vector vecJumpDir;
|
||||
if (m_hEnemy != NULL)
|
||||
{
|
||||
float gravity = g_psv_gravity->value;
|
||||
if (gravity <= 1)
|
||||
gravity = 1;
|
||||
|
||||
// How fast does the headcrab need to travel to reach that height given gravity?
|
||||
float height = (m_hEnemy->v.origin.z + m_hEnemy->v.view_ofs.z - pev->origin.z);
|
||||
if (height < 16)
|
||||
height = 16;
|
||||
float speed = sqrt( 2 * gravity * height );
|
||||
float time = speed / gravity;
|
||||
|
||||
// Scale the sideways velocity to get there at the right time
|
||||
vecJumpDir = (m_hEnemy->v.origin + m_hEnemy->v.view_ofs - pev->origin);
|
||||
vecJumpDir = vecJumpDir * ( 1.0 / time );
|
||||
|
||||
// Speed to offset gravity at the desired height
|
||||
vecJumpDir.z = speed;
|
||||
|
||||
// Don't jump too far/fast
|
||||
float distance = vecJumpDir.Length();
|
||||
|
||||
if (distance > 650)
|
||||
{
|
||||
vecJumpDir = vecJumpDir * ( 650.0 / distance );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// jump hop, don't care where
|
||||
vecJumpDir = Vector( gpGlobals->v_forward.x, gpGlobals->v_forward.y, gpGlobals->v_up.z ) * 350;
|
||||
}
|
||||
|
||||
int iSound = RANDOM_LONG(0,2);
|
||||
if ( iSound != 0 )
|
||||
EMIT_SOUND_DYN( edict(), CHAN_VOICE, pAttackSounds[iSound], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
|
||||
pev->velocity = vecJumpDir;
|
||||
m_flNextAttack = gpGlobals->time + 2;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CMBaseMonster::HandleAnimEvent( pEvent );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CMHeadCrab :: Spawn()
|
||||
{
|
||||
Precache( );
|
||||
|
||||
SET_MODEL(ENT(pev), "models/headcrab.mdl");
|
||||
UTIL_SetSize(pev, Vector(-12, -12, 0), Vector(12, 12, 24));
|
||||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
m_bloodColor = BLOOD_COLOR_GREEN;
|
||||
pev->effects = 0;
|
||||
pev->health = gSkillData.headcrabHealth;
|
||||
pev->view_ofs = Vector ( 0, 0, 20 );// position of the eyes relative to monster's origin.
|
||||
pev->yaw_speed = 5;//!!! should we put this in the monster's changeanim function since turn rates may vary with state/anim?
|
||||
m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
|
||||
MonsterInit();
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CMHeadCrab :: Precache()
|
||||
{
|
||||
PRECACHE_SOUND_ARRAY(pIdleSounds);
|
||||
PRECACHE_SOUND_ARRAY(pAlertSounds);
|
||||
PRECACHE_SOUND_ARRAY(pPainSounds);
|
||||
PRECACHE_SOUND_ARRAY(pAttackSounds);
|
||||
PRECACHE_SOUND_ARRAY(pDeathSounds);
|
||||
PRECACHE_SOUND_ARRAY(pBiteSounds);
|
||||
|
||||
PRECACHE_MODEL("models/headcrab.mdl");
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// RunTask
|
||||
//=========================================================
|
||||
void CMHeadCrab :: RunTask ( Task_t *pTask )
|
||||
{
|
||||
switch ( pTask->iTask )
|
||||
{
|
||||
case TASK_RANGE_ATTACK1:
|
||||
case TASK_RANGE_ATTACK2:
|
||||
{
|
||||
if ( m_fSequenceFinished )
|
||||
{
|
||||
TaskComplete();
|
||||
SetTouch( NULL );
|
||||
m_IdealActivity = ACT_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
CMBaseMonster :: RunTask(pTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// LeapTouch - this is the headcrab's touch function when it
|
||||
// is in the air
|
||||
//=========================================================
|
||||
void CMHeadCrab :: LeapTouch ( edict_t *pOther )
|
||||
{
|
||||
if ( !pOther->v.takedamage )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't hit if back on ground
|
||||
if ( !FBitSet( pev->flags, FL_ONGROUND ) )
|
||||
{
|
||||
EMIT_SOUND_DYN( edict(), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pBiteSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
|
||||
if (UTIL_IsPlayer(pOther))
|
||||
UTIL_TakeDamage( pOther, pev, pev, GetDamageAmount(), DMG_SLASH );
|
||||
else if (pOther->v.euser4 != NULL)
|
||||
{
|
||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther));
|
||||
pMonster->TakeDamage( pev, pev, GetDamageAmount(), DMG_SLASH );
|
||||
}
|
||||
}
|
||||
|
||||
SetTouch( NULL );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// PrescheduleThink
|
||||
//=========================================================
|
||||
void CMHeadCrab :: PrescheduleThink ( void )
|
||||
{
|
||||
// make the crab coo a little bit in combat state
|
||||
if ( m_MonsterState == MONSTERSTATE_COMBAT && RANDOM_FLOAT( 0, 5 ) < 0.1 )
|
||||
{
|
||||
IdleSound();
|
||||
}
|
||||
}
|
||||
|
||||
void CMHeadCrab :: StartTask ( Task_t *pTask )
|
||||
{
|
||||
m_iTaskStatus = TASKSTATUS_RUNNING;
|
||||
|
||||
switch ( pTask->iTask )
|
||||
{
|
||||
case TASK_RANGE_ATTACK1:
|
||||
{
|
||||
EMIT_SOUND_DYN( edict(), CHAN_WEAPON, pAttackSounds[0], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
m_IdealActivity = ACT_RANGE_ATTACK1;
|
||||
SetTouch ( LeapTouch );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
CMBaseMonster :: StartTask( pTask );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack1
|
||||
//=========================================================
|
||||
BOOL CMHeadCrab :: CheckRangeAttack1 ( float flDot, float flDist )
|
||||
{
|
||||
if ( FBitSet( pev->flags, FL_ONGROUND ) && flDist <= 256 && flDot >= 0.65 )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack2
|
||||
//=========================================================
|
||||
BOOL CMHeadCrab :: CheckRangeAttack2 ( float flDot, float flDist )
|
||||
{
|
||||
return FALSE;
|
||||
// BUGBUG: Why is this code here? There is no ACT_RANGE_ATTACK2 animation. I've disabled it for now.
|
||||
#if 0
|
||||
if ( FBitSet( pev->flags, FL_ONGROUND ) && flDist > 64 && flDist <= 256 && flDot >= 0.5 )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
int CMHeadCrab :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
||||
{
|
||||
// Don't take any acid damage -- BigMomma's mortar is acid
|
||||
if ( bitsDamageType & DMG_ACID )
|
||||
flDamage = 0;
|
||||
|
||||
return CMBaseMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// IdleSound
|
||||
//=========================================================
|
||||
#define CRAB_ATTN_IDLE (float)1.5
|
||||
void CMHeadCrab :: IdleSound ( void )
|
||||
{
|
||||
EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pIdleSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AlertSound
|
||||
//=========================================================
|
||||
void CMHeadCrab :: AlertSound ( void )
|
||||
{
|
||||
EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pAlertSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AlertSound
|
||||
//=========================================================
|
||||
void CMHeadCrab :: PainSound ( void )
|
||||
{
|
||||
EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pPainSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DeathSound
|
||||
//=========================================================
|
||||
void CMHeadCrab :: DeathSound ( void )
|
||||
{
|
||||
EMIT_SOUND_DYN( edict(), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDeathSounds), GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||
}
|
||||
|
||||
Schedule_t* CMHeadCrab :: GetScheduleOfType ( int Type )
|
||||
{
|
||||
switch ( Type )
|
||||
{
|
||||
case SCHED_RANGE_ATTACK1:
|
||||
{
|
||||
return &slHCRangeAttack1[ 0 ];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CMBaseMonster::GetScheduleOfType( Type );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMBabyCrab :: Spawn( void )
|
||||
{
|
||||
CMHeadCrab::Spawn();
|
||||
SET_MODEL(ENT(pev), "models/baby_headcrab.mdl");
|
||||
pev->rendermode = kRenderTransTexture;
|
||||
pev->renderamt = 192;
|
||||
UTIL_SetSize(pev, Vector(-12, -12, 0), Vector(12, 12, 24));
|
||||
|
||||
pev->health = gSkillData.headcrabHealth * 0.25; // less health than full grown
|
||||
}
|
||||
|
||||
void CMBabyCrab :: Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL( "models/baby_headcrab.mdl" );
|
||||
CMHeadCrab::Precache();
|
||||
}
|
||||
|
||||
|
||||
void CMBabyCrab :: SetYawSpeed ( void )
|
||||
{
|
||||
pev->yaw_speed = 120;
|
||||
}
|
||||
|
||||
|
||||
BOOL CMBabyCrab :: CheckRangeAttack1( float flDot, float flDist )
|
||||
{
|
||||
if ( pev->flags & FL_ONGROUND )
|
||||
{
|
||||
if ( pev->groundentity && (pev->groundentity->v.flags & (FL_CLIENT|FL_MONSTER)) )
|
||||
return TRUE;
|
||||
|
||||
// A little less accurate, but jump from closer
|
||||
if ( flDist <= 180 && flDot >= 0.55 )
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
Schedule_t* CMBabyCrab :: GetScheduleOfType ( int Type )
|
||||
{
|
||||
switch( Type )
|
||||
{
|
||||
case SCHED_FAIL: // If you fail, try to jump!
|
||||
if ( m_hEnemy != NULL )
|
||||
return slHCRangeAttack1Fast;
|
||||
break;
|
||||
|
||||
case SCHED_RANGE_ATTACK1:
|
||||
{
|
||||
return slHCRangeAttack1Fast;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CMHeadCrab::GetScheduleOfType( Type );
|
||||
}
|
||||
2102
src/dlls/hgrunt.cpp
Normal file
2102
src/dlls/hgrunt.cpp
Normal file
File diff suppressed because it is too large
Load Diff
372
src/dlls/hornet.cpp
Normal file
372
src/dlls/hornet.cpp
Normal file
@@ -0,0 +1,372 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// Hornets
|
||||
//=========================================================
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "weapons.h"
|
||||
#include "hornet.h"
|
||||
|
||||
|
||||
int iHornetTrail;
|
||||
int iHornetPuff;
|
||||
|
||||
//=========================================================
|
||||
// don't let hornets gib, ever.
|
||||
//=========================================================
|
||||
int CMHornet :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
||||
{
|
||||
// filter these bits a little.
|
||||
bitsDamageType &= ~ ( DMG_ALWAYSGIB );
|
||||
bitsDamageType |= DMG_NEVERGIB;
|
||||
|
||||
return CMBaseMonster :: TakeDamage ( pevInflictor, pevAttacker, flDamage, bitsDamageType );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
void CMHornet :: Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
|
||||
pev->movetype = MOVETYPE_FLY;
|
||||
pev->solid = SOLID_BBOX;
|
||||
pev->takedamage = DAMAGE_YES;
|
||||
pev->flags |= FL_MONSTER;
|
||||
pev->health = 1;// weak!
|
||||
|
||||
// hornets don't live as long in multiplayer
|
||||
m_flStopAttack = gpGlobals->time + 3.5;
|
||||
|
||||
m_flFieldOfView = 0.9; // +- 25 degrees
|
||||
|
||||
if ( RANDOM_LONG ( 1, 5 ) <= 2 )
|
||||
{
|
||||
m_iHornetType = HORNET_TYPE_RED;
|
||||
m_flFlySpeed = HORNET_RED_SPEED;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iHornetType = HORNET_TYPE_ORANGE;
|
||||
m_flFlySpeed = HORNET_ORANGE_SPEED;
|
||||
}
|
||||
|
||||
SET_MODEL(ENT( pev ), "models/hornet.mdl");
|
||||
UTIL_SetSize( pev, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ) );
|
||||
|
||||
SetTouch( DieTouch );
|
||||
SetThink( StartTrack );
|
||||
|
||||
edict_t *pSoundEnt = pev->owner;
|
||||
if ( !pSoundEnt )
|
||||
pSoundEnt = edict();
|
||||
|
||||
// no real owner, or owner isn't a client.
|
||||
pev->dmg = gSkillData.monDmgHornet;
|
||||
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
ResetSequenceInfo( );
|
||||
}
|
||||
|
||||
|
||||
void CMHornet :: Precache()
|
||||
{
|
||||
PRECACHE_MODEL("models/hornet.mdl");
|
||||
|
||||
PRECACHE_SOUND( "agrunt/ag_fire1.wav" );
|
||||
PRECACHE_SOUND( "agrunt/ag_fire2.wav" );
|
||||
PRECACHE_SOUND( "agrunt/ag_fire3.wav" );
|
||||
|
||||
PRECACHE_SOUND( "hornet/ag_buzz1.wav" );
|
||||
PRECACHE_SOUND( "hornet/ag_buzz2.wav" );
|
||||
PRECACHE_SOUND( "hornet/ag_buzz3.wav" );
|
||||
|
||||
PRECACHE_SOUND( "hornet/ag_hornethit1.wav" );
|
||||
PRECACHE_SOUND( "hornet/ag_hornethit2.wav" );
|
||||
PRECACHE_SOUND( "hornet/ag_hornethit3.wav" );
|
||||
|
||||
iHornetPuff = PRECACHE_MODEL( "sprites/muz1.spr" );
|
||||
iHornetTrail = PRECACHE_MODEL("sprites/laserbeam.spr");
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// hornets will never get mad at each other, no matter who the owner is.
|
||||
//=========================================================
|
||||
int CMHornet::IRelationship ( CMBaseEntity *pTarget )
|
||||
{
|
||||
if ( pTarget->pev->modelindex == pev->modelindex )
|
||||
{
|
||||
return R_NO;
|
||||
}
|
||||
|
||||
return CMBaseMonster :: IRelationship( pTarget );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ID's Hornet as their owner
|
||||
//=========================================================
|
||||
int CMHornet::Classify ( void )
|
||||
{
|
||||
|
||||
if ( pev->owner && pev->owner->v.flags & FL_CLIENT)
|
||||
{
|
||||
return CLASS_PLAYER_BIOWEAPON;
|
||||
}
|
||||
|
||||
return CLASS_ALIEN_BIOWEAPON;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// StartTrack - starts a hornet out tracking its target
|
||||
//=========================================================
|
||||
void CMHornet :: StartTrack ( void )
|
||||
{
|
||||
IgniteTrail();
|
||||
|
||||
SetTouch( TrackTouch );
|
||||
SetThink( TrackTarget );
|
||||
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// StartDart - starts a hornet out just flying straight.
|
||||
//=========================================================
|
||||
void CMHornet :: StartDart ( void )
|
||||
{
|
||||
IgniteTrail();
|
||||
|
||||
SetTouch( DartTouch );
|
||||
|
||||
SetThink( SUB_Remove );
|
||||
pev->nextthink = gpGlobals->time + 4;
|
||||
}
|
||||
|
||||
void CMHornet::IgniteTrail( void )
|
||||
{
|
||||
/*
|
||||
|
||||
ted's suggested trail colors:
|
||||
|
||||
r161
|
||||
g25
|
||||
b97
|
||||
|
||||
r173
|
||||
g39
|
||||
b14
|
||||
|
||||
old colors
|
||||
case HORNET_TYPE_RED:
|
||||
WRITE_BYTE( 255 ); // r, g, b
|
||||
WRITE_BYTE( 128 ); // r, g, b
|
||||
WRITE_BYTE( 0 ); // r, g, b
|
||||
break;
|
||||
case HORNET_TYPE_ORANGE:
|
||||
WRITE_BYTE( 0 ); // r, g, b
|
||||
WRITE_BYTE( 100 ); // r, g, b
|
||||
WRITE_BYTE( 255 ); // r, g, b
|
||||
break;
|
||||
|
||||
*/
|
||||
|
||||
// trail
|
||||
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
|
||||
WRITE_BYTE( TE_BEAMFOLLOW );
|
||||
WRITE_SHORT( entindex() ); // entity
|
||||
WRITE_SHORT( iHornetTrail ); // model
|
||||
WRITE_BYTE( 10 ); // life
|
||||
WRITE_BYTE( 2 ); // width
|
||||
|
||||
switch ( m_iHornetType )
|
||||
{
|
||||
case HORNET_TYPE_RED:
|
||||
WRITE_BYTE( 179 ); // r, g, b
|
||||
WRITE_BYTE( 39 ); // r, g, b
|
||||
WRITE_BYTE( 14 ); // r, g, b
|
||||
break;
|
||||
case HORNET_TYPE_ORANGE:
|
||||
WRITE_BYTE( 255 ); // r, g, b
|
||||
WRITE_BYTE( 128 ); // r, g, b
|
||||
WRITE_BYTE( 0 ); // r, g, b
|
||||
break;
|
||||
}
|
||||
|
||||
WRITE_BYTE( 128 ); // brightness
|
||||
|
||||
MESSAGE_END();
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Hornet is flying, gently tracking target
|
||||
//=========================================================
|
||||
void CMHornet :: TrackTarget ( void )
|
||||
{
|
||||
Vector vecFlightDir;
|
||||
Vector vecDirToEnemy;
|
||||
float flDelta;
|
||||
|
||||
StudioFrameAdvance( );
|
||||
|
||||
if (gpGlobals->time > m_flStopAttack)
|
||||
{
|
||||
SetTouch( NULL );
|
||||
SetThink( SUB_Remove );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
return;
|
||||
}
|
||||
|
||||
// UNDONE: The player pointer should come back after returning from another level
|
||||
if ( m_hEnemy == NULL )
|
||||
{// enemy is dead.
|
||||
Look( 512 );
|
||||
m_hEnemy = BestVisibleEnemy( );
|
||||
}
|
||||
|
||||
if ( m_hEnemy != NULL && UTIL_FVisible( m_hEnemy, ENT(pev) ))
|
||||
{
|
||||
m_vecEnemyLKP = UTIL_BodyTarget( m_hEnemy, pev->origin );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vecEnemyLKP = m_vecEnemyLKP + pev->velocity * m_flFlySpeed * 0.1;
|
||||
}
|
||||
|
||||
vecDirToEnemy = ( m_vecEnemyLKP - pev->origin ).Normalize();
|
||||
|
||||
if (pev->velocity.Length() < 0.1)
|
||||
vecFlightDir = vecDirToEnemy;
|
||||
else
|
||||
vecFlightDir = pev->velocity.Normalize();
|
||||
|
||||
// measure how far the turn is, the wider the turn, the slow we'll go this time.
|
||||
flDelta = DotProduct ( vecFlightDir, vecDirToEnemy );
|
||||
|
||||
if ( flDelta < 0.5 )
|
||||
{// hafta turn wide again. play sound
|
||||
switch (RANDOM_LONG(0,2))
|
||||
{
|
||||
case 0: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz1.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break;
|
||||
case 1: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz2.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break;
|
||||
case 2: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz3.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( flDelta <= 0 && m_iHornetType == HORNET_TYPE_RED )
|
||||
{// no flying backwards, but we don't want to invert this, cause we'd go fast when we have to turn REAL far.
|
||||
flDelta = 0.25;
|
||||
}
|
||||
|
||||
pev->velocity = ( vecFlightDir + vecDirToEnemy).Normalize();
|
||||
|
||||
if ( pev->owner && (pev->owner->v.flags & FL_MONSTER) )
|
||||
{
|
||||
// random pattern only applies to hornets fired by monsters, not players.
|
||||
|
||||
pev->velocity.x += RANDOM_FLOAT ( -0.10, 0.10 );// scramble the flight dir a bit.
|
||||
pev->velocity.y += RANDOM_FLOAT ( -0.10, 0.10 );
|
||||
pev->velocity.z += RANDOM_FLOAT ( -0.10, 0.10 );
|
||||
}
|
||||
|
||||
switch ( m_iHornetType )
|
||||
{
|
||||
case HORNET_TYPE_RED:
|
||||
pev->velocity = pev->velocity * ( m_flFlySpeed * flDelta );// scale the dir by the ( speed * width of turn )
|
||||
pev->nextthink = gpGlobals->time + RANDOM_FLOAT( 0.1, 0.3 );
|
||||
break;
|
||||
case HORNET_TYPE_ORANGE:
|
||||
pev->velocity = pev->velocity * m_flFlySpeed;// do not have to slow down to turn.
|
||||
pev->nextthink = gpGlobals->time + 0.1;// fixed think time
|
||||
break;
|
||||
}
|
||||
|
||||
pev->angles = UTIL_VecToAngles (pev->velocity);
|
||||
|
||||
pev->solid = SOLID_BBOX;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Tracking Hornet hit something
|
||||
//=========================================================
|
||||
void CMHornet :: TrackTouch ( edict_t *pOther )
|
||||
{
|
||||
if ( (pOther == pev->owner) || pOther->v.modelindex == pev->modelindex )
|
||||
{// bumped into the guy that shot it.
|
||||
pev->solid = SOLID_NOT;
|
||||
return;
|
||||
}
|
||||
|
||||
// is this NOT a player and IS a monster?
|
||||
if (!UTIL_IsPlayer(pOther) && (pOther->v.euser4 != NULL))
|
||||
{
|
||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther));
|
||||
|
||||
if ( IRelationship( pMonster ) <= R_NO )
|
||||
{
|
||||
// hit something we don't want to hurt, so turn around.
|
||||
|
||||
pev->velocity = pev->velocity.Normalize();
|
||||
|
||||
pev->velocity.x *= -1;
|
||||
pev->velocity.y *= -1;
|
||||
|
||||
pev->origin = pev->origin + pev->velocity * 4; // bounce the hornet off a bit.
|
||||
pev->velocity = pev->velocity * m_flFlySpeed;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DieTouch( pOther );
|
||||
}
|
||||
|
||||
void CMHornet::DartTouch( edict_t *pOther )
|
||||
{
|
||||
DieTouch( pOther );
|
||||
}
|
||||
|
||||
void CMHornet::DieTouch ( edict_t *pOther )
|
||||
{
|
||||
if ( pOther && pOther->v.takedamage )
|
||||
{// do the damage
|
||||
|
||||
switch (RANDOM_LONG(0,2))
|
||||
{// buzz when you plug someone
|
||||
case 0: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_hornethit1.wav", 1, ATTN_NORM); break;
|
||||
case 1: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_hornethit2.wav", 1, ATTN_NORM); break;
|
||||
case 2: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_hornethit3.wav", 1, ATTN_NORM); break;
|
||||
}
|
||||
|
||||
if (UTIL_IsPlayer(pOther))
|
||||
UTIL_TakeDamage( pOther, pev, VARS( pev->owner ), pev->dmg, DMG_BULLET );
|
||||
else if (pOther->v.euser4 != NULL)
|
||||
{
|
||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther));
|
||||
pMonster->TakeDamage( pev, VARS( pev->owner ), pev->dmg, DMG_BULLET );
|
||||
}
|
||||
}
|
||||
|
||||
pev->modelindex = 0;// so will disappear for the 0.1 secs we wait until NEXTTHINK gets rid
|
||||
pev->solid = SOLID_NOT;
|
||||
|
||||
SetThink ( SUB_Remove );
|
||||
pev->nextthink = gpGlobals->time + 1;// stick around long enough for the sound to finish!
|
||||
}
|
||||
|
||||
55
src/dlls/hornet.h
Normal file
55
src/dlls/hornet.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// Hornets
|
||||
//=========================================================
|
||||
|
||||
//=========================================================
|
||||
// Hornet Defines
|
||||
//=========================================================
|
||||
#define HORNET_TYPE_RED 0
|
||||
#define HORNET_TYPE_ORANGE 1
|
||||
#define HORNET_RED_SPEED (float)600
|
||||
#define HORNET_ORANGE_SPEED (float)800
|
||||
#define HORNET_BUZZ_VOLUME (float)0.8
|
||||
|
||||
extern int iHornetPuff;
|
||||
|
||||
//=========================================================
|
||||
// Hornet - this is the projectile that the Alien Grunt fires.
|
||||
//=========================================================
|
||||
class CMHornet : public CMBaseMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
int Classify ( void );
|
||||
int IRelationship ( CMBaseEntity *pTarget );
|
||||
|
||||
void IgniteTrail( void );
|
||||
void EXPORT StartTrack ( void );
|
||||
void EXPORT StartDart ( void );
|
||||
void EXPORT TrackTarget ( void );
|
||||
void EXPORT TrackTouch ( edict_t *pOther );
|
||||
void EXPORT DartTouch( edict_t *pOther );
|
||||
void EXPORT DieTouch ( edict_t *pOther );
|
||||
|
||||
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
|
||||
|
||||
float m_flStopAttack;
|
||||
int m_iHornetType;
|
||||
float m_flFlySpeed;
|
||||
};
|
||||
|
||||
1100
src/dlls/houndeye.cpp
Normal file
1100
src/dlls/houndeye.cpp
Normal file
File diff suppressed because it is too large
Load Diff
752
src/dlls/islave.cpp
Normal file
752
src/dlls/islave.cpp
Normal file
@@ -0,0 +1,752 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// Alien slave monster
|
||||
//=========================================================
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "schedule.h"
|
||||
#include "effects.h"
|
||||
#include "weapons.h"
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
#define ISLAVE_AE_CLAW ( 1 )
|
||||
#define ISLAVE_AE_CLAWRAKE ( 2 )
|
||||
#define ISLAVE_AE_ZAP_POWERUP ( 3 )
|
||||
#define ISLAVE_AE_ZAP_SHOOT ( 4 )
|
||||
#define ISLAVE_AE_ZAP_DONE ( 5 )
|
||||
|
||||
|
||||
const char *CMISlave::pAttackHitSounds[] =
|
||||
{
|
||||
"zombie/claw_strike1.wav",
|
||||
"zombie/claw_strike2.wav",
|
||||
"zombie/claw_strike3.wav",
|
||||
};
|
||||
|
||||
const char *CMISlave::pAttackMissSounds[] =
|
||||
{
|
||||
"zombie/claw_miss1.wav",
|
||||
"zombie/claw_miss2.wav",
|
||||
};
|
||||
|
||||
const char *CMISlave::pPainSounds[] =
|
||||
{
|
||||
"aslave/slv_pain1.wav",
|
||||
"aslave/slv_pain2.wav",
|
||||
};
|
||||
|
||||
const char *CMISlave::pDeathSounds[] =
|
||||
{
|
||||
"aslave/slv_die1.wav",
|
||||
"aslave/slv_die2.wav",
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CMISlave :: Classify ( void )
|
||||
{
|
||||
return CLASS_ALIEN_MILITARY;
|
||||
}
|
||||
|
||||
|
||||
int CMISlave::IRelationship( CMBaseEntity *pTarget )
|
||||
{
|
||||
if ( (pTarget->IsPlayer()) )
|
||||
if ( (pev->spawnflags & SF_MONSTER_WAIT_UNTIL_PROVOKED ) && ! (m_afMemory & bits_MEMORY_PROVOKED ))
|
||||
return R_NO;
|
||||
return CMBaseMonster::IRelationship( pTarget );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ALertSound - scream
|
||||
//=========================================================
|
||||
void CMISlave :: AlertSound( void )
|
||||
{
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
SENTENCEG_PlayRndSz(ENT(pev), "SLV_ALERT", 0.85, ATTN_NORM, 0, m_voicePitch);
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// IdleSound
|
||||
//=========================================================
|
||||
void CMISlave :: IdleSound( void )
|
||||
{
|
||||
if (RANDOM_LONG( 0, 2 ) == 0)
|
||||
{
|
||||
SENTENCEG_PlayRndSz(ENT(pev), "SLV_IDLE", 0.85, ATTN_NORM, 0, m_voicePitch);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int side = RANDOM_LONG( 0, 1 ) * 2 - 1;
|
||||
|
||||
ClearBeams( );
|
||||
ArmBeam( side );
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
Vector vecSrc = pev->origin + gpGlobals->v_right * 2 * side;
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
|
||||
WRITE_BYTE(TE_DLIGHT);
|
||||
WRITE_COORD(vecSrc.x); // X
|
||||
WRITE_COORD(vecSrc.y); // Y
|
||||
WRITE_COORD(vecSrc.z); // Z
|
||||
WRITE_BYTE( 8 ); // radius * 0.1
|
||||
WRITE_BYTE( 255 ); // r
|
||||
WRITE_BYTE( 180 ); // g
|
||||
WRITE_BYTE( 96 ); // b
|
||||
WRITE_BYTE( 10 ); // time * 10
|
||||
WRITE_BYTE( 0 ); // decay * 0.1
|
||||
MESSAGE_END( );
|
||||
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "debris/zap1.wav", 1, ATTN_NORM, 0, 100 );
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// PainSound
|
||||
//=========================================================
|
||||
void CMISlave :: PainSound( void )
|
||||
{
|
||||
if (RANDOM_LONG( 0, 2 ) == 0)
|
||||
{
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pPainSounds[ RANDOM_LONG(0,ARRAYSIZE(pPainSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// DieSound
|
||||
//=========================================================
|
||||
|
||||
void CMISlave :: DeathSound( void )
|
||||
{
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pDeathSounds[ RANDOM_LONG(0,ARRAYSIZE(pDeathSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ISoundMask - returns a bit mask indicating which types
|
||||
// of sounds this monster regards.
|
||||
//=========================================================
|
||||
int CMISlave :: ISoundMask ( void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CMISlave::Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
ClearBeams( );
|
||||
CMBaseMonster::Killed( pevAttacker, iGib );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CMISlave :: SetYawSpeed ( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
switch ( m_Activity )
|
||||
{
|
||||
case ACT_WALK:
|
||||
ys = 50;
|
||||
break;
|
||||
case ACT_RUN:
|
||||
ys = 70;
|
||||
break;
|
||||
case ACT_IDLE:
|
||||
ys = 50;
|
||||
break;
|
||||
default:
|
||||
ys = 90;
|
||||
break;
|
||||
}
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//
|
||||
// Returns number of events handled, 0 if none.
|
||||
//=========================================================
|
||||
void CMISlave :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
// ALERT( at_console, "event %d : %f\n", pEvent->event, pev->frame );
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case ISLAVE_AE_CLAW:
|
||||
{
|
||||
// SOUND HERE!
|
||||
edict_t *pHurt = CheckTraceHullAttack( 70, gSkillData.slaveDmgClaw, DMG_SLASH );
|
||||
if ( pHurt )
|
||||
{
|
||||
if ( pHurt->v.flags & (FL_MONSTER|FL_CLIENT) )
|
||||
{
|
||||
pHurt->v.punchangle.z = -18;
|
||||
pHurt->v.punchangle.x = 5;
|
||||
}
|
||||
// Play a random attack hit sound
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Play a random attack miss sound
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ISLAVE_AE_CLAWRAKE:
|
||||
{
|
||||
edict_t *pHurt = CheckTraceHullAttack( 70, gSkillData.slaveDmgClawrake, DMG_SLASH );
|
||||
if ( pHurt )
|
||||
{
|
||||
if ( pHurt->v.flags & (FL_MONSTER|FL_CLIENT) )
|
||||
{
|
||||
pHurt->v.punchangle.z = -18;
|
||||
pHurt->v.punchangle.x = 5;
|
||||
}
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
else
|
||||
{
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, m_voicePitch );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ISLAVE_AE_ZAP_POWERUP:
|
||||
{
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
|
||||
if (m_iBeams == 0)
|
||||
{
|
||||
Vector vecSrc = pev->origin + gpGlobals->v_forward * 2;
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSrc );
|
||||
WRITE_BYTE(TE_DLIGHT);
|
||||
WRITE_COORD(vecSrc.x); // X
|
||||
WRITE_COORD(vecSrc.y); // Y
|
||||
WRITE_COORD(vecSrc.z); // Z
|
||||
WRITE_BYTE( 12 ); // radius * 0.1
|
||||
WRITE_BYTE( 255 ); // r
|
||||
WRITE_BYTE( 180 ); // g
|
||||
WRITE_BYTE( 96 ); // b
|
||||
WRITE_BYTE( 20 / pev->framerate ); // time * 10
|
||||
WRITE_BYTE( 0 ); // decay * 0.1
|
||||
MESSAGE_END( );
|
||||
|
||||
}
|
||||
/*jlb
|
||||
if (m_hDead != NULL)
|
||||
{
|
||||
WackBeam( -1, m_hDead );
|
||||
WackBeam( 1, m_hDead );
|
||||
}
|
||||
else
|
||||
jlb*/
|
||||
{
|
||||
ArmBeam( -1 );
|
||||
ArmBeam( 1 );
|
||||
BeamGlow( );
|
||||
}
|
||||
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0, 100 + m_iBeams * 10 );
|
||||
pev->skin = m_iBeams / 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case ISLAVE_AE_ZAP_SHOOT:
|
||||
{
|
||||
ClearBeams( );
|
||||
|
||||
/*jlb
|
||||
if (m_hDead != NULL)
|
||||
{
|
||||
Vector vecDest = m_hDead->v.origin + Vector( 0, 0, 38 );
|
||||
TraceResult trace;
|
||||
UTIL_TraceHull( vecDest, vecDest, dont_ignore_monsters, human_hull, m_hDead, &trace );
|
||||
|
||||
if ( !trace.fStartSolid )
|
||||
{
|
||||
CMBaseEntity *pNew = Create( "monster_alien_slave", m_hDead->pev->origin, m_hDead->pev->angles );
|
||||
CMBaseMonster *pNewMonster = pNew->MyMonsterPointer( );
|
||||
pNew->pev->spawnflags |= 1;
|
||||
WackBeam( -1, pNew );
|
||||
WackBeam( 1, pNew );
|
||||
UTIL_Remove( m_hDead );
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "hassault/hw_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG( 130, 160 ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
jlb*/
|
||||
ClearMultiDamage();
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
|
||||
ZapBeam( -1 );
|
||||
ZapBeam( 1 );
|
||||
|
||||
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "hassault/hw_shoot1.wav", 1, ATTN_NORM, 0, RANDOM_LONG( 130, 160 ) );
|
||||
// STOP_SOUND( ENT(pev), CHAN_WEAPON, "debris/zap4.wav" );
|
||||
|
||||
ApplyMultiDamage(pev, pev);
|
||||
|
||||
m_flNextAttack = gpGlobals->time + RANDOM_FLOAT( 0.5, 4.0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case ISLAVE_AE_ZAP_DONE:
|
||||
{
|
||||
ClearBeams( );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CMBaseMonster::HandleAnimEvent( pEvent );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack1 - normal beam attack
|
||||
//=========================================================
|
||||
BOOL CMISlave :: CheckRangeAttack1 ( float flDot, float flDist )
|
||||
{
|
||||
if (m_flNextAttack > gpGlobals->time)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return CMBaseMonster::CheckRangeAttack1( flDot, flDist );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// CheckRangeAttack2 - check bravery and try to resurect dead comrades
|
||||
//=========================================================
|
||||
BOOL CMISlave :: CheckRangeAttack2 ( float flDot, float flDist )
|
||||
{
|
||||
return FALSE;
|
||||
|
||||
if (m_flNextAttack > gpGlobals->time)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//jlb m_hDead = NULL;
|
||||
m_iBravery = 0;
|
||||
|
||||
edict_t *pEntity = NULL;
|
||||
while ((pEntity = UTIL_FindEntityByClassname( pEntity, "monster_alien_slave" )) != NULL)
|
||||
{
|
||||
TraceResult tr;
|
||||
|
||||
UTIL_TraceLine( EyePosition( ), UTIL_EyePosition(pEntity), ignore_monsters, ENT(pev), &tr );
|
||||
if (tr.flFraction == 1.0 || tr.pHit == pEntity)
|
||||
{
|
||||
if (pEntity->v.deadflag == DEAD_DEAD)
|
||||
{
|
||||
float d = (pev->origin - pEntity->v.origin).Length();
|
||||
if (d < flDist)
|
||||
{
|
||||
//jlb m_hDead = pEntity;
|
||||
flDist = d;
|
||||
}
|
||||
m_iBravery--;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iBravery++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//jlb if (m_hDead != NULL)
|
||||
//jlb return TRUE;
|
||||
//jlb else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// StartTask
|
||||
//=========================================================
|
||||
void CMISlave :: StartTask ( Task_t *pTask )
|
||||
{
|
||||
ClearBeams( );
|
||||
|
||||
CMBaseMonster :: StartTask ( pTask );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CMISlave :: Spawn()
|
||||
{
|
||||
Precache( );
|
||||
|
||||
SET_MODEL(ENT(pev), "models/islave.mdl");
|
||||
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
|
||||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
m_bloodColor = BLOOD_COLOR_GREEN;
|
||||
pev->effects = 0;
|
||||
pev->health = gSkillData.slaveHealth;
|
||||
pev->view_ofs = Vector ( 0, 0, 64 );// position of the eyes relative to monster's origin.
|
||||
m_flFieldOfView = 0.5;
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_RANGE_ATTACK2 | bits_CAP_DOORS_GROUP;
|
||||
|
||||
m_voicePitch = RANDOM_LONG( 85, 110 );
|
||||
|
||||
for (int i = 0; i < ISLAVE_MAX_BEAMS; i++)
|
||||
m_pBeam[i] = NULL;
|
||||
|
||||
m_iBravery = 0;
|
||||
m_flNextAttack = 0.0f;
|
||||
|
||||
MonsterInit();
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CMISlave :: Precache()
|
||||
{
|
||||
int i;
|
||||
|
||||
PRECACHE_MODEL("models/islave.mdl");
|
||||
PRECACHE_MODEL("sprites/lgtning.spr");
|
||||
PRECACHE_SOUND("debris/zap1.wav");
|
||||
PRECACHE_SOUND("debris/zap4.wav");
|
||||
PRECACHE_SOUND("weapons/electro4.wav");
|
||||
PRECACHE_SOUND("hassault/hw_shoot1.wav");
|
||||
PRECACHE_SOUND("zombie/zo_pain2.wav");
|
||||
PRECACHE_SOUND("headcrab/hc_headbite.wav");
|
||||
PRECACHE_SOUND("weapons/cbar_miss1.wav");
|
||||
|
||||
for ( i = 0; i < ARRAYSIZE( pAttackHitSounds ); i++ )
|
||||
PRECACHE_SOUND((char *)pAttackHitSounds[i]);
|
||||
|
||||
for ( i = 0; i < ARRAYSIZE( pAttackMissSounds ); i++ )
|
||||
PRECACHE_SOUND((char *)pAttackMissSounds[i]);
|
||||
|
||||
for ( i = 0; i < ARRAYSIZE( pPainSounds ); i++ )
|
||||
PRECACHE_SOUND((char *)pPainSounds[i]);
|
||||
|
||||
for ( i = 0; i < ARRAYSIZE( pDeathSounds ); i++ )
|
||||
PRECACHE_SOUND((char *)pDeathSounds[i]);
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// TakeDamage - get provoked when injured
|
||||
//=========================================================
|
||||
|
||||
int CMISlave :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType)
|
||||
{
|
||||
// don't slash one of your own
|
||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pevAttacker));
|
||||
if (pMonster != NULL)
|
||||
{
|
||||
if ((bitsDamageType & DMG_SLASH) && pevAttacker && IRelationship( pMonster ) < R_DL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_afMemory |= bits_MEMORY_PROVOKED;
|
||||
return CMBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
|
||||
}
|
||||
|
||||
|
||||
void CMISlave::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
|
||||
{
|
||||
if (bitsDamageType & DMG_SHOCK)
|
||||
return;
|
||||
|
||||
CMBaseMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
|
||||
|
||||
|
||||
// primary range attack
|
||||
Task_t tlSlaveAttack1[] =
|
||||
{
|
||||
{ TASK_STOP_MOVING, 0 },
|
||||
{ TASK_FACE_IDEAL, (float)0 },
|
||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
||||
};
|
||||
|
||||
Schedule_t slSlaveAttack1[] =
|
||||
{
|
||||
{
|
||||
tlSlaveAttack1,
|
||||
ARRAYSIZE ( tlSlaveAttack1 ),
|
||||
bits_COND_CAN_MELEE_ATTACK1 |
|
||||
bits_COND_HEAR_SOUND |
|
||||
bits_COND_HEAVY_DAMAGE,
|
||||
0,
|
||||
"Slave Range Attack1"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
DEFINE_CUSTOM_SCHEDULES( CMISlave )
|
||||
{
|
||||
slSlaveAttack1,
|
||||
};
|
||||
|
||||
IMPLEMENT_CUSTOM_SCHEDULES( CMISlave, CMBaseMonster );
|
||||
|
||||
|
||||
//=========================================================
|
||||
//=========================================================
|
||||
Schedule_t *CMISlave :: GetSchedule( void )
|
||||
{
|
||||
ClearBeams( );
|
||||
|
||||
/*
|
||||
if (pev->spawnflags)
|
||||
{
|
||||
pev->spawnflags = 0;
|
||||
return GetScheduleOfType( SCHED_RELOAD );
|
||||
}
|
||||
*/
|
||||
|
||||
switch (m_MonsterState)
|
||||
{
|
||||
case MONSTERSTATE_COMBAT:
|
||||
// dead enemy
|
||||
if ( HasConditions( bits_COND_ENEMY_DEAD ) )
|
||||
{
|
||||
// call base class, all code to handle dead enemies is centralized there.
|
||||
return CMBaseMonster :: GetSchedule();
|
||||
}
|
||||
|
||||
if (pev->health < 20 || m_iBravery < 0)
|
||||
{
|
||||
if (!HasConditions( bits_COND_CAN_MELEE_ATTACK1 ))
|
||||
{
|
||||
m_failSchedule = SCHED_CHASE_ENEMY;
|
||||
if (HasConditions( bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE))
|
||||
{
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
}
|
||||
if ( HasConditions ( bits_COND_SEE_ENEMY ) && HasConditions ( bits_COND_ENEMY_FACING_ME ) )
|
||||
{
|
||||
// ALERT( at_console, "exposed\n");
|
||||
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return CMBaseMonster::GetSchedule( );
|
||||
}
|
||||
|
||||
|
||||
Schedule_t *CMISlave :: GetScheduleOfType ( int Type )
|
||||
{
|
||||
switch ( Type )
|
||||
{
|
||||
case SCHED_FAIL:
|
||||
if (HasConditions( bits_COND_CAN_MELEE_ATTACK1 ))
|
||||
{
|
||||
return CMBaseMonster :: GetScheduleOfType( SCHED_MELEE_ATTACK1 ); ;
|
||||
}
|
||||
break;
|
||||
case SCHED_RANGE_ATTACK1:
|
||||
return slSlaveAttack1;
|
||||
case SCHED_RANGE_ATTACK2:
|
||||
return slSlaveAttack1;
|
||||
}
|
||||
return CMBaseMonster :: GetScheduleOfType( Type );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ArmBeam - small beam from arm to nearby geometry
|
||||
//=========================================================
|
||||
|
||||
void CMISlave :: ArmBeam( int side )
|
||||
{
|
||||
TraceResult tr;
|
||||
float flDist = 1.0;
|
||||
|
||||
if (m_iBeams >= ISLAVE_MAX_BEAMS)
|
||||
return;
|
||||
|
||||
UTIL_MakeAimVectors( pev->angles );
|
||||
Vector vecSrc = pev->origin + gpGlobals->v_up * 36 + gpGlobals->v_right * side * 16 + gpGlobals->v_forward * 32;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Vector vecAim = gpGlobals->v_right * side * RANDOM_FLOAT( 0, 1 ) + gpGlobals->v_up * RANDOM_FLOAT( -1, 1 );
|
||||
TraceResult tr1;
|
||||
UTIL_TraceLine ( vecSrc, vecSrc + vecAim * 512, dont_ignore_monsters, ENT( pev ), &tr1);
|
||||
if (flDist > tr1.flFraction)
|
||||
{
|
||||
tr = tr1;
|
||||
flDist = tr.flFraction;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find anything close enough
|
||||
if ( flDist == 1.0 )
|
||||
return;
|
||||
|
||||
DecalGunshot( &tr, BULLET_PLAYER_CROWBAR );
|
||||
|
||||
m_pBeam[m_iBeams] = CMBeam::BeamCreate( "sprites/lgtning.spr", 30 );
|
||||
if (!m_pBeam[m_iBeams])
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, entindex( ) );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
// m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
|
||||
m_pBeam[m_iBeams]->SetColor( 96, 128, 16 );
|
||||
m_pBeam[m_iBeams]->SetBrightness( 64 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 80 );
|
||||
m_iBeams++;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// BeamGlow - brighten all beams
|
||||
//=========================================================
|
||||
void CMISlave :: BeamGlow( )
|
||||
{
|
||||
int b = m_iBeams * 32;
|
||||
if (b > 255)
|
||||
b = 255;
|
||||
|
||||
for (int i = 0; i < m_iBeams; i++)
|
||||
{
|
||||
if (m_pBeam[i]->GetBrightness() != 255)
|
||||
{
|
||||
m_pBeam[i]->SetBrightness( b );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// WackBeam - regenerate dead colleagues
|
||||
//=========================================================
|
||||
void CMISlave :: WackBeam( int side, edict_t *pEntity )
|
||||
{
|
||||
Vector vecDest;
|
||||
float flDist = 1.0;
|
||||
|
||||
if (m_iBeams >= ISLAVE_MAX_BEAMS)
|
||||
return;
|
||||
|
||||
if (pEntity == NULL)
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams] = CMBeam::BeamCreate( "sprites/lgtning.spr", 30 );
|
||||
if (!m_pBeam[m_iBeams])
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams]->PointEntInit( UTIL_Center(pEntity), entindex( ) );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
|
||||
m_pBeam[m_iBeams]->SetBrightness( 255 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 80 );
|
||||
m_iBeams++;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// ZapBeam - heavy damage directly forward
|
||||
//=========================================================
|
||||
void CMISlave :: ZapBeam( int side )
|
||||
{
|
||||
Vector vecSrc, vecAim;
|
||||
TraceResult tr;
|
||||
edict_t *pEntity;
|
||||
|
||||
if (m_iBeams >= ISLAVE_MAX_BEAMS)
|
||||
return;
|
||||
|
||||
vecSrc = pev->origin + gpGlobals->v_up * 36;
|
||||
vecAim = ShootAtEnemy( vecSrc );
|
||||
float deflection = 0.01;
|
||||
vecAim = vecAim + side * gpGlobals->v_right * RANDOM_FLOAT( 0, deflection ) + gpGlobals->v_up * RANDOM_FLOAT( -deflection, deflection );
|
||||
UTIL_TraceLine ( vecSrc, vecSrc + vecAim * 1024, dont_ignore_monsters, ENT( pev ), &tr);
|
||||
|
||||
m_pBeam[m_iBeams] = CMBeam::BeamCreate( "sprites/lgtning.spr", 50 );
|
||||
if (!m_pBeam[m_iBeams])
|
||||
return;
|
||||
|
||||
m_pBeam[m_iBeams]->PointEntInit( tr.vecEndPos, entindex( ) );
|
||||
m_pBeam[m_iBeams]->SetEndAttachment( side < 0 ? 2 : 1 );
|
||||
m_pBeam[m_iBeams]->SetColor( 180, 255, 96 );
|
||||
m_pBeam[m_iBeams]->SetBrightness( 255 );
|
||||
m_pBeam[m_iBeams]->SetNoise( 20 );
|
||||
m_iBeams++;
|
||||
|
||||
pEntity = tr.pHit;
|
||||
if (pEntity != NULL && pEntity->v.takedamage)
|
||||
{
|
||||
if (UTIL_IsPlayer(pEntity))
|
||||
UTIL_TraceAttack( pEntity, pev, gSkillData.slaveDmgZap, vecAim, &tr, DMG_SHOCK );
|
||||
else if (pEntity->v.euser4 != NULL)
|
||||
{
|
||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pEntity));
|
||||
pMonster->TraceAttack( pev, gSkillData.slaveDmgZap, vecAim, &tr, DMG_SHOCK );
|
||||
}
|
||||
}
|
||||
|
||||
UTIL_EmitAmbientSound( ENT(pev), tr.vecEndPos, "weapons/electro4.wav", 0.5, ATTN_NORM, 0, RANDOM_LONG( 140, 160 ) );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// ClearBeams - remove all beams
|
||||
//=========================================================
|
||||
void CMISlave :: ClearBeams( )
|
||||
{
|
||||
for (int i = 0; i < ISLAVE_MAX_BEAMS; i++)
|
||||
{
|
||||
if (m_pBeam[i])
|
||||
{
|
||||
UTIL_Remove( m_pBeam[i]->edict() );
|
||||
m_pBeam[i] = NULL;
|
||||
}
|
||||
}
|
||||
m_iBeams = 0;
|
||||
pev->skin = 0;
|
||||
|
||||
STOP_SOUND( ENT(pev), CHAN_WEAPON, "debris/zap4.wav" );
|
||||
}
|
||||
146
src/dlls/monster_api.cpp
Normal file
146
src/dlls/monster_api.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
//
|
||||
// botman's monster - MetaMOD plugin
|
||||
//
|
||||
// monster_api.cpp
|
||||
//
|
||||
|
||||
/*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this code; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "extdll.h"
|
||||
#include "meta_api.h"
|
||||
#include "sdk_util.h" // UTIL_LogPrintf, etc
|
||||
|
||||
// Must provide at least one of these..
|
||||
static META_FUNCTIONS gMetaFunctionTable = {
|
||||
NULL, // pfnGetEntityAPI HL SDK; called before game DLL
|
||||
NULL, // pfnGetEntityAPI_Post META; called after game DLL
|
||||
GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL
|
||||
GetEntityAPI2_Post, // pfnGetEntityAPI2_Post META; called after game DLL
|
||||
NULL, // pfnGetNewDLLFunctions HL SDK2; called before game DLL
|
||||
NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL
|
||||
NULL, // pfnGetEngineFunctions META; called before HL engine
|
||||
NULL, // pfnGetEngineFunctions_Post META; called after HL engine
|
||||
};
|
||||
|
||||
// Description of plugin
|
||||
plugin_info_t Plugin_info = {
|
||||
META_INTERFACE_VERSION, // interface version
|
||||
"Monster", // name
|
||||
"3.00.00", // version
|
||||
"06/30/2002", // date
|
||||
"botman <botman@planethalflife.com>", // author
|
||||
"http://planethalflife.com/botman/", // url
|
||||
"MONSTER", // logtag
|
||||
PT_CHANGELEVEL, // (when) loadable
|
||||
PT_CHANGELEVEL, // (when) unloadable
|
||||
};
|
||||
|
||||
char *VNAME=Plugin_info.name;
|
||||
char *VVERSION=Plugin_info.version;
|
||||
char *VDATE=Plugin_info.date;
|
||||
char *VAUTHOR=Plugin_info.author;
|
||||
char *VURL=Plugin_info.url;
|
||||
char *VLOGTAG=Plugin_info.logtag;
|
||||
char *COMPILE_TIME=__DATE__ ", " __TIME__;
|
||||
|
||||
// Global vars from metamod:
|
||||
meta_globals_t *gpMetaGlobals; // metamod globals
|
||||
gamedll_funcs_t *gpGamedllFuncs; // gameDLL function tables
|
||||
mutil_funcs_t *gpMetaUtilFuncs; // metamod utility functions
|
||||
|
||||
cvar_t init_dllapi_log = {"monster_log", "0", FCVAR_EXTDLL, 0, NULL};
|
||||
cvar_t *dllapi_log = NULL;
|
||||
cvar_t init_monster_spawn = {"monster_spawn", "1", FCVAR_EXTDLL, 0, NULL};
|
||||
cvar_t *monster_spawn = NULL;
|
||||
|
||||
|
||||
// Metamod requesting info about this plugin:
|
||||
// ifvers (given) interface_version metamod is using
|
||||
// pPlugInfo (requested) struct with info about plugin
|
||||
// pMetaUtilFuncs (given) table of utility functions provided by metamod
|
||||
C_DLLEXPORT int Meta_Query(char *ifvers, plugin_info_t **pPlugInfo,
|
||||
mutil_funcs_t *pMetaUtilFuncs)
|
||||
{
|
||||
if(ifvers); // to satisfy gcc -Wunused
|
||||
// Give metamod our plugin_info struct
|
||||
*pPlugInfo=&Plugin_info;
|
||||
// Get metamod utility function table.
|
||||
gpMetaUtilFuncs=pMetaUtilFuncs;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// Metamod attaching plugin to the server.
|
||||
// now (given) current phase, ie during map, during changelevel, or at startup
|
||||
// pFunctionTable (requested) table of function tables this plugin catches
|
||||
// pMGlobals (given) global vars from metamod
|
||||
// pGamedllFuncs (given) copy of function tables from game dll
|
||||
C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable,
|
||||
meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs)
|
||||
{
|
||||
if(now); // to satisfy gcc -Wunused
|
||||
if(!pMGlobals) {
|
||||
LOG_ERROR(PLID, "Meta_Attach called with null pMGlobals");
|
||||
return(FALSE);
|
||||
}
|
||||
gpMetaGlobals=pMGlobals;
|
||||
if(!pFunctionTable) {
|
||||
LOG_ERROR(PLID, "Meta_Attach called with null pFunctionTable");
|
||||
return(FALSE);
|
||||
}
|
||||
memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS));
|
||||
gpGamedllFuncs=pGamedllFuncs;
|
||||
|
||||
LOG_MESSAGE(PLID, "%s v%s, %s", VNAME, VVERSION, VDATE);
|
||||
LOG_MESSAGE(PLID, "by %s", VAUTHOR);
|
||||
LOG_MESSAGE(PLID, " %s", VURL);
|
||||
LOG_MESSAGE(PLID, "compiled: %s CDT", COMPILE_TIME);
|
||||
|
||||
LOG_CONSOLE(PLID, "[%s] %s v%s, %s", VLOGTAG, VNAME, VVERSION, VDATE);
|
||||
LOG_CONSOLE(PLID, "[%s] by %s", VLOGTAG, VAUTHOR);
|
||||
|
||||
CVAR_REGISTER(&init_dllapi_log);
|
||||
dllapi_log = CVAR_GET_POINTER("monster_log");
|
||||
|
||||
CVAR_REGISTER(&init_monster_spawn);
|
||||
monster_spawn = CVAR_GET_POINTER("monster_spawn");
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
extern void monster_unload(void);
|
||||
|
||||
// Metamod detaching plugin from the server.
|
||||
// now (given) current phase, ie during map, etc
|
||||
// reason (given) why detaching (refresh, console unload, forced unload, etc)
|
||||
C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
|
||||
// remove all the monsters currently in the level...
|
||||
monster_unload();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
418
src/dlls/monster_config.cpp
Normal file
418
src/dlls/monster_config.cpp
Normal file
@@ -0,0 +1,418 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef __linux__
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "extdll.h"
|
||||
#include "dllapi.h"
|
||||
#include "meta_api.h"
|
||||
|
||||
#include "monster_plugin.h"
|
||||
|
||||
extern cvar_t *dllapi_log;
|
||||
|
||||
extern monster_type_t monster_types[];
|
||||
extern int monster_spawn_count;
|
||||
|
||||
|
||||
bool get_input(FILE *fp, char *input)
|
||||
{
|
||||
char line[1024];
|
||||
int len, pos;
|
||||
|
||||
while (!feof(fp))
|
||||
{
|
||||
if (fgets(line, 1023, fp) != NULL)
|
||||
{
|
||||
len = strlen(line);
|
||||
|
||||
if (len == 0)
|
||||
continue; // skip any null lines
|
||||
|
||||
// remove any trailing newline, carriage return or whitespace...
|
||||
while ((line[len-1] == '\n') || (line[len-1] == '\r') ||
|
||||
isspace(line[len-1]))
|
||||
{
|
||||
line[len-1] = 0;
|
||||
len--;
|
||||
if (len == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
|
||||
while (isspace(line[pos]))
|
||||
pos++; // skip leading blanks
|
||||
|
||||
if ((line[pos] == '/') && (line[pos+1] == '/'))
|
||||
continue; // skip comment lines
|
||||
|
||||
if (line[pos] == 0)
|
||||
continue; // skip empty lines
|
||||
|
||||
strcpy(input, &line[pos]);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE; // no input found
|
||||
}
|
||||
|
||||
|
||||
bool scan_monster_cfg(FILE *fp)
|
||||
{
|
||||
char input[1024];
|
||||
bool origin, angle, delay, angle_min, angle_max, monster;
|
||||
float x, y, z;
|
||||
|
||||
while (get_input(fp, input))
|
||||
{
|
||||
if (monster_spawn_count == MAX_MONSTERS)
|
||||
continue; // skip if max monster spawn count reached
|
||||
|
||||
if (input[0] == '{')
|
||||
{
|
||||
origin = angle = delay = angle_min = angle_max = monster = FALSE;
|
||||
|
||||
monster_spawnpoint[monster_spawn_count].monster_count = 0;
|
||||
|
||||
while (get_input(fp, input))
|
||||
{
|
||||
if (input[0] == '}')
|
||||
break;
|
||||
|
||||
if (strncmp(input, "origin/", 7) == 0)
|
||||
{
|
||||
if (origin)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: origin found twice: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: origin found twice: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
if (sscanf(&input[7], "%f %f %f", &x, &y, &z) != 3)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: invalid origin: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: invalid origin: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
origin = TRUE;
|
||||
monster_spawnpoint[monster_spawn_count].origin[0] = x;
|
||||
monster_spawnpoint[monster_spawn_count].origin[1] = y;
|
||||
monster_spawnpoint[monster_spawn_count].origin[2] = z;
|
||||
}
|
||||
else if (strncmp(input, "delay/", 6) == 0)
|
||||
{
|
||||
if (delay)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: delay found twice: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: delay found twice: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
if (sscanf(&input[6], "%f", &x) != 1)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: invalid delay: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: invalid delay: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
delay = TRUE;
|
||||
monster_spawnpoint[monster_spawn_count].delay = x;
|
||||
}
|
||||
else if (strncmp(input, "angle/", 6) == 0)
|
||||
{
|
||||
if (angle)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: angle found twice: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: angle found twice: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
if (angle_min || angle_max)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
if (sscanf(&input[6], "%f", &x) != 1)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: invalid angle: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: invalid angle: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
angle = TRUE;
|
||||
monster_spawnpoint[monster_spawn_count].angle_min = x;
|
||||
monster_spawnpoint[monster_spawn_count].angle_max = x;
|
||||
}
|
||||
else if (strncmp(input, "angle_min/", 10) == 0)
|
||||
{
|
||||
if (angle_min)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: angle_min found twice: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: angle_min found twice: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
if (angle)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
if (sscanf(&input[10], "%f", &x) != 1)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: invalid angle_min: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: invalid angle_min: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
angle_min = TRUE;
|
||||
monster_spawnpoint[monster_spawn_count].angle_min = x;
|
||||
}
|
||||
else if (strncmp(input, "angle_max/", 10) == 0)
|
||||
{
|
||||
if (angle_max)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: angle_max found twice: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: angle_max found twice: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
if (angle)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
if (sscanf(&input[10], "%f", &x) != 1)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: invalid angle_max: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: invalid angle_max: %s", input);
|
||||
return TRUE; // error
|
||||
}
|
||||
angle_max = TRUE;
|
||||
monster_spawnpoint[monster_spawn_count].angle_max = x;
|
||||
}
|
||||
else if (strncmp(input, "monster/", 8) == 0)
|
||||
{
|
||||
int index;
|
||||
int count = monster_spawnpoint[monster_spawn_count].monster_count;
|
||||
if (count < MAX_MONSTER_COUNT)
|
||||
{
|
||||
for (index=0; monster_types[index].name[0]; index++)
|
||||
{
|
||||
if (strcmp(&input[8], monster_types[index].name) == 0)
|
||||
{
|
||||
monster_spawnpoint[monster_spawn_count].monster[count] = index;
|
||||
monster_spawnpoint[monster_spawn_count].monster_count++;
|
||||
|
||||
monster_types[index].need_to_precache = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (monster_types[index].name[0] == 0)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: invalid monster name: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: invalid monster name: %s", input);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
monster = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: unknown command: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: unknown command: %s", input);
|
||||
return TRUE; // error occurred
|
||||
}
|
||||
}
|
||||
|
||||
// check for all necessary fields here...
|
||||
if (!origin)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: you didn't specify an origin!");
|
||||
LOG_MESSAGE(PLID, "ERROR: you didn't specify an origin!");
|
||||
return TRUE;
|
||||
}
|
||||
if (angle_min && !angle_max)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: you specified angle_min but didn't specify angle_max!");
|
||||
LOG_MESSAGE(PLID, "ERROR: you specified angle_min but didn't specify angle_max!");
|
||||
return TRUE;
|
||||
}
|
||||
if (angle_max && !angle_min)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: you specified angle_max but didn't specify angle_min!");
|
||||
LOG_MESSAGE(PLID, "ERROR: you specified angle_max but didn't specify angle_min!");
|
||||
return TRUE;
|
||||
}
|
||||
if (!monster)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: No monster key found!");
|
||||
LOG_MESSAGE(PLID, "ERROR: No monster key found!");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!delay)
|
||||
monster_spawnpoint[monster_spawn_count].delay = 30; // 30 second default delay
|
||||
|
||||
if (monster_spawnpoint[monster_spawn_count].delay < 1)
|
||||
monster_spawnpoint[monster_spawn_count].delay = 1; // no negative or zero delay
|
||||
|
||||
if (!angle && !angle_min && !angle_max) // no angle specified, use 0-359 as default
|
||||
{
|
||||
monster_spawnpoint[monster_spawn_count].angle_min = 0;
|
||||
monster_spawnpoint[monster_spawn_count].angle_max = 359;
|
||||
}
|
||||
|
||||
if (monster_spawnpoint[monster_spawn_count].angle_min < 0)
|
||||
monster_spawnpoint[monster_spawn_count].angle_min = 0; // no negative angles
|
||||
|
||||
if (monster_spawnpoint[monster_spawn_count].angle_max > 359)
|
||||
monster_spawnpoint[monster_spawn_count].angle_max = 359; // no angle > 359 degrees
|
||||
|
||||
monster_spawnpoint[monster_spawn_count].respawn_time = gpGlobals->time + RANDOM_FLOAT(10.0, 20.0);
|
||||
monster_spawnpoint[monster_spawn_count].need_to_respawn = TRUE;
|
||||
|
||||
if (dllapi_log->value)
|
||||
{
|
||||
char name_monsters[256];
|
||||
|
||||
LOG_MESSAGE(PLID, "Added monster spawn at: %7.2f %7.2f %7.2f",
|
||||
monster_spawnpoint[monster_spawn_count].origin.x,
|
||||
monster_spawnpoint[monster_spawn_count].origin.y,
|
||||
monster_spawnpoint[monster_spawn_count].origin.z);
|
||||
LOG_MESSAGE(PLID, " with delay = %7.2f, angle_min = %7.2f, angle_max = %7.2f",
|
||||
monster_spawnpoint[monster_spawn_count].delay,
|
||||
monster_spawnpoint[monster_spawn_count].angle_min,
|
||||
monster_spawnpoint[monster_spawn_count].angle_max);
|
||||
name_monsters[0] = 0;
|
||||
for (int i = 0; i < monster_spawnpoint[monster_spawn_count].monster_count; i++)
|
||||
{
|
||||
strcat(name_monsters, monster_types[monster_spawnpoint[monster_spawn_count].monster[i]].name);
|
||||
strcat(name_monsters, " ");
|
||||
}
|
||||
LOG_MESSAGE(PLID, " monsters = %s", name_monsters);
|
||||
}
|
||||
|
||||
monster_spawn_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
bool process_monster_cfg(void)
|
||||
{
|
||||
char game_dir[256];
|
||||
char filename[256];
|
||||
FILE *fp = NULL;
|
||||
bool status = FALSE; // no error
|
||||
|
||||
monster_spawn_count = 0;
|
||||
|
||||
// find the directory name of the currently running MOD...
|
||||
(*g_engfuncs.pfnGetGameDir)(game_dir);
|
||||
|
||||
strcpy(filename, game_dir);
|
||||
#ifdef __linux__
|
||||
strcat(filename, "/maps/");
|
||||
#else
|
||||
strcat(filename, "\\maps\\");
|
||||
#endif
|
||||
strcat(filename, STRING(gpGlobals->mapname));
|
||||
strcat(filename, "_monster.cfg");
|
||||
|
||||
// check if the map specific filename exists...
|
||||
if (access(filename, 0) == 0)
|
||||
{
|
||||
if (dllapi_log->value)
|
||||
{
|
||||
META_CONS("[MONSTER] Processing config file=%s", filename);
|
||||
LOG_MESSAGE(PLID, "Processing config file=%s", filename);
|
||||
}
|
||||
|
||||
if ((fp = fopen(filename, "r")) == NULL)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
||||
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", filename);
|
||||
|
||||
return TRUE; // return bad status
|
||||
}
|
||||
|
||||
status = scan_monster_cfg(fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
bool scan_monster_precache_cfg(FILE *fp)
|
||||
{
|
||||
char input[1024];
|
||||
bool found;
|
||||
|
||||
while (get_input(fp, input))
|
||||
{
|
||||
found = FALSE;
|
||||
|
||||
for (int index=0; monster_types[index].name[0]; index++)
|
||||
{
|
||||
if (strcmp(input, monster_types[index].name) == 0)
|
||||
{
|
||||
monster_types[index].need_to_precache = TRUE;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == FALSE)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: invalid precache monster name: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: invalid precache monster name: %s", input);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
bool process_monster_precache_cfg(void)
|
||||
{
|
||||
char game_dir[256];
|
||||
char filename[256];
|
||||
FILE *fp = NULL;
|
||||
bool status = FALSE; // no error
|
||||
|
||||
// find the directory name of the currently running MOD...
|
||||
(*g_engfuncs.pfnGetGameDir)(game_dir);
|
||||
|
||||
strcpy(filename, game_dir);
|
||||
strcat(filename, "/monster_precache.cfg");
|
||||
|
||||
// check if the map specific filename exists...
|
||||
if (access(filename, 0) == 0)
|
||||
{
|
||||
if (dllapi_log->value)
|
||||
{
|
||||
META_CONS("[MONSTER] Processing config file=%s", filename);
|
||||
LOG_MESSAGE(PLID, "Processing config file=%s", filename);
|
||||
}
|
||||
|
||||
if ((fp = fopen(filename, "r")) == NULL)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
||||
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", filename);
|
||||
|
||||
return TRUE; // return bad status
|
||||
}
|
||||
|
||||
status = scan_monster_precache_cfg(fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
5
src/dlls/monster_mm.def
Normal file
5
src/dlls/monster_mm.def
Normal file
@@ -0,0 +1,5 @@
|
||||
LIBRARY monster_mm
|
||||
EXPORTS
|
||||
GiveFnptrsToDll @1
|
||||
SECTIONS
|
||||
.data READ WRITE
|
||||
378
src/dlls/monster_mm.dsp
Normal file
378
src/dlls/monster_mm.dsp
Normal file
@@ -0,0 +1,378 @@
|
||||
# Microsoft Developer Studio Project File - Name="monster_mm" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=monster_mm - Win32 Debug
|
||||
!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 "monster_mm.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 "monster_mm.mak" CFG="monster_mm - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "monster_mm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "monster_mm - 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)" == "monster_mm - 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 "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "monster_mm_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\dlls" /I "..\common" /I "..\engine" /I "..\pm_shared" /I "..\..\metamod" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "monster_mm_EXPORTS" /D strcasecmp=stricmp /D strncasecmp=_strnicmp /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /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 /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 odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /def:".\monster_mm.def"
|
||||
# Begin Custom Build - Copying to DLL folder
|
||||
TargetPath=.\Release\monster_mm.dll
|
||||
TargetName=monster_mm
|
||||
InputPath=.\Release\monster_mm.dll
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"$(TargetName)" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetPath) D:\Half-Life\valve\dlls
|
||||
copy $(TargetPath) D:\Half-Life\tfc\dlls
|
||||
copy $(TargetPath) D:\Half-Life\cstrike\dlls
|
||||
copy $(TargetPath) D:\Half-Life\dmc\dlls
|
||||
copy $(TargetPath) D:\Half-Life\dod\dlls
|
||||
copy $(TargetPath) D:\Half-Life\firearms\dlls
|
||||
copy $(TargetPath) D:\Half-Life\frontline\dlls
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ELSEIF "$(CFG)" == "monster_mm - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "monster_mm_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\dlls" /I "..\common" /I "..\engine" /I "..\pm_shared" /I "..\..\metamod" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "monster_mm_EXPORTS" /D strcasecmp=stricmp /D strncasecmp=_strnicmp /FD /GZ /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /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 /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD 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 /dll /debug /machine:I386 /def:".\monster_mm.def" /pdbtype:sept
|
||||
# Begin Custom Build - Copying to DLL folder
|
||||
TargetPath=.\Debug\monster_mm.dll
|
||||
TargetName=monster_mm
|
||||
InputPath=.\Debug\monster_mm.dll
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"$(TargetName)" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetPath) D:\Half-Life\valve\dlls
|
||||
copy $(TargetPath) D:\Half-Life\tfc\dlls
|
||||
copy $(TargetPath) D:\Half-Life\cstrike\dlls
|
||||
copy $(TargetPath) D:\Half-Life\dmc\dlls
|
||||
copy $(TargetPath) D:\Half-Life\dod\dlls
|
||||
copy $(TargetPath) D:\Half-Life\firearms\dlls
|
||||
copy $(TargetPath) D:\Half-Life\frontline\dlls
|
||||
copy $(TargetPath) D:\Half-Life\gearbox\dlls
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "monster_mm - Win32 Release"
|
||||
# Name "monster_mm - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\agrunt.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\AI_BaseNPC_Schedule.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\animating.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\animation.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\apache.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\barney.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\bigmomma.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\bullsquid.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cmbase.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\combat.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\controller.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\defaultai.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dllapi.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\effects.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\flyingmonster.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ggrenade.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=.\hassassin.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\headcrab.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hgrunt.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hornet.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\houndeye.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\islave.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\monster_api.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\monster_config.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=.\nodes.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\scientist.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=.\squeakgrenade.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\subs.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\talkmonster.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\util.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\weapons.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zombie.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\activity.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\animation.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cdll_dll.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cmbase.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cmbasemonster.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cmflyingmonster.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cmtalkmonster.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\decals.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=.\monster_plugin.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=.\schedule.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\skill.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=.\weapons.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
57
src/dlls/monster_plugin.h
Normal file
57
src/dlls/monster_plugin.h
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// monster_plugin.h
|
||||
//
|
||||
|
||||
#ifndef MONSTER_PLUGIN_H
|
||||
#define MONSTER_PLUGIN_H
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
bool need_to_precache;
|
||||
} monster_type_t;
|
||||
|
||||
|
||||
class CMBaseMonster;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int monster_index;
|
||||
edict_t *monster_pent;
|
||||
bool killed;
|
||||
int respawn_index;
|
||||
CMBaseMonster *pMonster;
|
||||
} monster_t;
|
||||
|
||||
#define MAX_MONSTER_ENTS 200
|
||||
|
||||
extern monster_t monsters[MAX_MONSTER_ENTS];
|
||||
|
||||
|
||||
#define MAX_MONSTER_COUNT 20
|
||||
|
||||
typedef struct {
|
||||
Vector origin;
|
||||
float angle_min, angle_max;
|
||||
float delay;
|
||||
unsigned char monster[MAX_MONSTER_COUNT];
|
||||
int monster_count;
|
||||
float respawn_time;
|
||||
bool need_to_respawn;
|
||||
} monster_spawnpoint_t;
|
||||
|
||||
#define MAX_MONSTERS 100
|
||||
extern monster_spawnpoint_t monster_spawnpoint[MAX_MONSTERS];
|
||||
|
||||
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 the initial blood
|
||||
extern DLL_GLOBAL short g_sModelIndexBloodSpray;// holds the sprite index for splattered blood
|
||||
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
|
||||
|
||||
#endif
|
||||
34
src/dlls/monsterevent.h
Normal file
34
src/dlls/monsterevent.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef 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
|
||||
2915
src/dlls/monsters.cpp
Normal file
2915
src/dlls/monsters.cpp
Normal file
File diff suppressed because it is too large
Load Diff
180
src/dlls/monsters.h
Normal file
180
src/dlls/monsters.h
Normal file
@@ -0,0 +1,180 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
#ifndef MONSTERS_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 CMGib : public CMBaseEntity
|
||||
{
|
||||
public:
|
||||
void Spawn( const char *szGibModel );
|
||||
void EXPORT BounceGibTouch ( edict_t *pOther );
|
||||
void EXPORT StickyGibTouch ( edict_t *pOther );
|
||||
void EXPORT WaitTillLand( void );
|
||||
void LimitVelocity( void );
|
||||
|
||||
virtual int ObjectCaps( void ) { return (CMBaseEntity :: 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
|
||||
214
src/dlls/monsterstate.cpp
Normal file
214
src/dlls/monsterstate.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// monsterstate.cpp - base class monster functions for
|
||||
// controlling core AI.
|
||||
//=========================================================
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "nodes.h"
|
||||
#include "monsters.h"
|
||||
#include "animation.h"
|
||||
|
||||
//=========================================================
|
||||
// SetState
|
||||
//=========================================================
|
||||
void CMBaseMonster :: SetState ( MONSTERSTATE State )
|
||||
{
|
||||
/*
|
||||
if ( State != m_MonsterState )
|
||||
{
|
||||
ALERT ( at_aiconsole, "State Changed to %d\n", State );
|
||||
}
|
||||
*/
|
||||
|
||||
switch( State )
|
||||
{
|
||||
|
||||
// Drop enemy pointers when going to idle
|
||||
case MONSTERSTATE_IDLE:
|
||||
|
||||
if (( m_hEnemy != NULL ) &&
|
||||
( strcmp(STRING(pev->model), "models/scientist.mdl") != 0))
|
||||
{
|
||||
m_hEnemy = NULL;// not allowed to have an enemy anymore.
|
||||
ALERT ( at_aiconsole, "Stripped\n" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_MonsterState = State;
|
||||
m_IdealMonsterState = State;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// RunAI
|
||||
//=========================================================
|
||||
void CMBaseMonster :: RunAI ( void )
|
||||
{
|
||||
// to test model's eye height
|
||||
//UTIL_ParticleEffect ( pev->origin + pev->view_ofs, g_vecZero, 255, 10 );
|
||||
|
||||
// IDLE sound permitted in ALERT state is because monsters were silent in ALERT state. Only play IDLE sound in IDLE state
|
||||
// once we have sounds for that state.
|
||||
if ( ( m_MonsterState == MONSTERSTATE_IDLE || m_MonsterState == MONSTERSTATE_ALERT ) && RANDOM_LONG(0,99) == 0 && !(pev->flags & SF_MONSTER_GAG) )
|
||||
{
|
||||
IdleSound();
|
||||
}
|
||||
|
||||
if ( m_MonsterState != MONSTERSTATE_NONE &&
|
||||
m_MonsterState != MONSTERSTATE_PRONE &&
|
||||
m_MonsterState != MONSTERSTATE_DEAD )// don't bother with this crap if monster is prone.
|
||||
{
|
||||
// collect some sensory Condition information.
|
||||
// don't let monsters outside of the player's PVS act up, or most of the interesting
|
||||
// things will happen before the player gets there!
|
||||
// UPDATE: We now let COMBAT state monsters think and act fully outside of player PVS. This allows the player to leave
|
||||
// an area where monsters are fighting, and the fight will continue.
|
||||
if ( !FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) || ( m_MonsterState == MONSTERSTATE_COMBAT ) )
|
||||
{
|
||||
Look( m_flDistLook );
|
||||
//jlb Listen();// check for audible sounds.
|
||||
|
||||
// now filter conditions.
|
||||
ClearConditions( IgnoreConditions() );
|
||||
|
||||
GetEnemy();
|
||||
}
|
||||
|
||||
// do these calculations if monster has an enemy.
|
||||
if ( m_hEnemy != NULL )
|
||||
{
|
||||
CheckEnemy( m_hEnemy );
|
||||
}
|
||||
|
||||
CheckAmmo();
|
||||
}
|
||||
|
||||
FCheckAITrigger();
|
||||
|
||||
PrescheduleThink();
|
||||
|
||||
MaintainSchedule();
|
||||
|
||||
// if the monster didn't use these conditions during the above call to MaintainSchedule() or CheckAITrigger()
|
||||
// we throw them out cause we don't want them sitting around through the lifespan of a schedule
|
||||
// that doesn't use them.
|
||||
m_afConditions &= ~( bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE );
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// GetIdealState - surveys the Conditions information available
|
||||
// and finds the best new state for a monster.
|
||||
//=========================================================
|
||||
MONSTERSTATE CMBaseMonster :: GetIdealState ( void )
|
||||
{
|
||||
int iConditions;
|
||||
|
||||
iConditions = IScheduleFlags();
|
||||
|
||||
// If no schedule conditions, the new ideal state is probably the reason we're in here.
|
||||
switch ( m_MonsterState )
|
||||
{
|
||||
case MONSTERSTATE_IDLE:
|
||||
|
||||
/*
|
||||
IDLE goes to ALERT upon hearing a sound
|
||||
-IDLE goes to ALERT upon being injured
|
||||
IDLE goes to ALERT upon seeing food
|
||||
-IDLE goes to COMBAT upon sighting an enemy
|
||||
IDLE goes to HUNT upon smelling food
|
||||
*/
|
||||
{
|
||||
if ( iConditions & bits_COND_NEW_ENEMY )
|
||||
{
|
||||
// new enemy! This means an idle monster has seen someone it dislikes, or
|
||||
// that a monster in combat has found a more suitable target to attack
|
||||
m_IdealMonsterState = MONSTERSTATE_COMBAT;
|
||||
}
|
||||
else if ( iConditions & bits_COND_LIGHT_DAMAGE )
|
||||
{
|
||||
MakeIdealYaw ( m_vecEnemyLKP );
|
||||
m_IdealMonsterState = MONSTERSTATE_ALERT;
|
||||
}
|
||||
else if ( iConditions & bits_COND_HEAVY_DAMAGE )
|
||||
{
|
||||
MakeIdealYaw ( m_vecEnemyLKP );
|
||||
m_IdealMonsterState = MONSTERSTATE_ALERT;
|
||||
}
|
||||
else if ( iConditions & bits_COND_HEAR_SOUND )
|
||||
{
|
||||
}
|
||||
else if ( iConditions & (bits_COND_SMELL | bits_COND_SMELL_FOOD) )
|
||||
{
|
||||
m_IdealMonsterState = MONSTERSTATE_ALERT;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MONSTERSTATE_ALERT:
|
||||
/*
|
||||
ALERT goes to IDLE upon becoming bored
|
||||
-ALERT goes to COMBAT upon sighting an enemy
|
||||
ALERT goes to HUNT upon hearing a noise
|
||||
*/
|
||||
{
|
||||
if ( iConditions & (bits_COND_NEW_ENEMY|bits_COND_SEE_ENEMY) )
|
||||
{
|
||||
// see an enemy we MUST attack
|
||||
m_IdealMonsterState = MONSTERSTATE_COMBAT;
|
||||
}
|
||||
else if ( iConditions & bits_COND_HEAR_SOUND )
|
||||
{
|
||||
m_IdealMonsterState = MONSTERSTATE_ALERT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MONSTERSTATE_COMBAT:
|
||||
/*
|
||||
COMBAT goes to HUNT upon losing sight of enemy
|
||||
COMBAT goes to ALERT upon death of enemy
|
||||
*/
|
||||
{
|
||||
if ( m_hEnemy == NULL )
|
||||
{
|
||||
m_IdealMonsterState = MONSTERSTATE_ALERT;
|
||||
// pev->effects = EF_BRIGHTFIELD;
|
||||
ALERT ( at_aiconsole, "***Combat state with no enemy!\n" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MONSTERSTATE_HUNT:
|
||||
/*
|
||||
HUNT goes to ALERT upon seeing food
|
||||
HUNT goes to ALERT upon being injured
|
||||
HUNT goes to IDLE if goal touched
|
||||
HUNT goes to COMBAT upon seeing enemy
|
||||
*/
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case MONSTERSTATE_DEAD:
|
||||
m_IdealMonsterState = MONSTERSTATE_DEAD;
|
||||
break;
|
||||
}
|
||||
|
||||
return m_IdealMonsterState;
|
||||
}
|
||||
|
||||
3405
src/dlls/nodes.cpp
Normal file
3405
src/dlls/nodes.cpp
Normal file
File diff suppressed because it is too large
Load Diff
374
src/dlls/nodes.h
Normal file
374
src/dlls/nodes.h
Normal file
@@ -0,0 +1,374 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// 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, CMBaseEntity *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 CMBaseEntity *pEntity ); // what hull the monster uses
|
||||
int NodeType( const CMBaseEntity *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 CMBaseEntity
|
||||
{
|
||||
void Spawn( void );
|
||||
void KeyValue( KeyValueData *pkvd );
|
||||
virtual int ObjectCaps( void ) { return CMBaseEntity :: 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;
|
||||
43
src/dlls/plane.h
Normal file
43
src/dlls/plane.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef 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
|
||||
290
src/dlls/schedule.h
Normal file
290
src/dlls/schedule.h
Normal file
@@ -0,0 +1,290 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// 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
|
||||
1013
src/dlls/scientist.cpp
Normal file
1013
src/dlls/scientist.cpp
Normal file
File diff suppressed because it is too large
Load Diff
254
src/dlls/skill.cpp
Normal file
254
src/dlls/skill.cpp
Normal file
@@ -0,0 +1,254 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef __linux__
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "extdll.h"
|
||||
#include "dllapi.h"
|
||||
#include "meta_api.h"
|
||||
#include "skill.h"
|
||||
|
||||
extern cvar_t *dllapi_log;
|
||||
|
||||
skilldata_t gSkillData;
|
||||
|
||||
struct skill_cfg_t
|
||||
{
|
||||
char *name;
|
||||
float *value;
|
||||
};
|
||||
|
||||
skill_cfg_t skill_cfg[] = {
|
||||
{"sk_agrunt_health", &gSkillData.agruntHealth},
|
||||
{"sk_agrunt_dmg_punch", &gSkillData.agruntDmgPunch},
|
||||
{"sk_apache_health", &gSkillData.apacheHealth},
|
||||
{"sk_barney_health", &gSkillData.barneyHealth},
|
||||
{"sk_bigmomma_health_factor", &gSkillData.bigmommaHealthFactor},
|
||||
{"sk_bigmomma_dmg_slash", &gSkillData.bigmommaDmgSlash},
|
||||
{"sk_bigmomma_dmg_blast", &gSkillData.bigmommaDmgBlast},
|
||||
{"sk_bigmomma_radius_blast", &gSkillData.bigmommaRadiusBlast},
|
||||
{"sk_bullsquid_health", &gSkillData.bullsquidHealth},
|
||||
{"sk_bullsquid_dmg_bite", &gSkillData.bullsquidDmgBite},
|
||||
{"sk_bullsquid_dmg_whip", &gSkillData.bullsquidDmgWhip},
|
||||
{"sk_bullsquid_dmg_spit", &gSkillData.bullsquidDmgSpit},
|
||||
{"sk_gargantua_health", &gSkillData.gargantuaHealth},
|
||||
{"sk_gargantua_dmg_slash", &gSkillData.gargantuaDmgSlash},
|
||||
{"sk_gargantua_dmg_fire", &gSkillData.gargantuaDmgFire},
|
||||
{"sk_gargantua_dmg_stomp", &gSkillData.gargantuaDmgStomp},
|
||||
{"sk_hassassin_health", &gSkillData.hassassinHealth},
|
||||
{"sk_headcrab_health", &gSkillData.headcrabHealth},
|
||||
{"sk_headcrab_dmg_bite", &gSkillData.headcrabDmgBite},
|
||||
{"sk_hgrunt_health", &gSkillData.hgruntHealth},
|
||||
{"sk_hgrunt_kick", &gSkillData.hgruntDmgKick},
|
||||
{"sk_hgrunt_pellets", &gSkillData.hgruntShotgunPellets},
|
||||
{"sk_hgrunt_gspeed", &gSkillData.hgruntGrenadeSpeed},
|
||||
{"sk_houndeye_health", &gSkillData.houndeyeHealth},
|
||||
{"sk_houndeye_dmg_blast", &gSkillData.houndeyeDmgBlast},
|
||||
{"sk_islave_health", &gSkillData.slaveHealth},
|
||||
{"sk_islave_dmg_claw", &gSkillData.slaveDmgClaw},
|
||||
{"sk_islave_dmg_clawrake", &gSkillData.slaveDmgClawrake},
|
||||
{"sk_islave_dmg_zap", &gSkillData.slaveDmgZap},
|
||||
{"sk_ichthyosaur_health", &gSkillData.ichthyosaurHealth},
|
||||
{"sk_ichthyosaur_shake", &gSkillData.ichthyosaurDmgShake},
|
||||
{"sk_leech_health", &gSkillData.leechHealth},
|
||||
{"sk_leech_dmg_bite", &gSkillData.leechDmgBite},
|
||||
{"sk_controller_health", &gSkillData.controllerHealth},
|
||||
{"sk_controller_dmgzap", &gSkillData.controllerDmgZap},
|
||||
{"sk_controller_speedball", &gSkillData.controllerSpeedBall},
|
||||
{"sk_controller_dmgball", &gSkillData.controllerDmgBall},
|
||||
{"sk_nihilanth_health", &gSkillData.nihilanthHealth},
|
||||
{"sk_nihilanth_zap", &gSkillData.nihilanthZap},
|
||||
{"sk_scientist_health", &gSkillData.scientistHealth},
|
||||
{"sk_scientist_heal", &gSkillData.scientistHeal},
|
||||
{"sk_snark_health", &gSkillData.snarkHealth},
|
||||
{"sk_snark_dmg_bite", &gSkillData.snarkDmgBite},
|
||||
{"sk_snark_dmg_pop", &gSkillData.snarkDmgPop},
|
||||
{"sk_zombie_health", &gSkillData.zombieHealth},
|
||||
{"sk_zombie_dmg_one_slash", &gSkillData.zombieDmgOneSlash},
|
||||
{"sk_zombie_dmg_both_slash", &gSkillData.zombieDmgBothSlash},
|
||||
{"sk_12mm_bullet", &gSkillData.monDmg9MM},
|
||||
{"sk_9mmAR_bullet", &gSkillData.monDmgMP5},
|
||||
{"sk_9mm_bullet", &gSkillData.monDmg12MM},
|
||||
{"sk_9mmAR_grenade", &gSkillData.monDmgM203Grenade},
|
||||
{"sk_hornet_dmg", &gSkillData.monDmgHornet},
|
||||
{"", NULL}
|
||||
};
|
||||
|
||||
bool get_input(FILE *fp, char *input);
|
||||
|
||||
|
||||
void scan_monster_skill(FILE *fp)
|
||||
{
|
||||
char input[1024];
|
||||
int index, len, pos;
|
||||
bool found;
|
||||
|
||||
while (get_input(fp, input))
|
||||
{
|
||||
index = 0;
|
||||
found = FALSE;
|
||||
|
||||
while (skill_cfg[index].name[0])
|
||||
{
|
||||
len = strlen(skill_cfg[index].name);
|
||||
if (strncmp(input, skill_cfg[index].name, len) == 0)
|
||||
{
|
||||
found = TRUE;
|
||||
pos = len;
|
||||
sscanf(&input[pos], "%f", skill_cfg[index].value);
|
||||
|
||||
if (dllapi_log->value)
|
||||
LOG_MESSAGE(PLID, "skill setting %s set to %f",
|
||||
skill_cfg[index].name, *skill_cfg[index].value);
|
||||
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: unknown monster_skill.cfg item: %s", input);
|
||||
LOG_MESSAGE(PLID, "ERROR: unknown monster_skill.cfg item: %s", input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void monster_skill_init(void)
|
||||
{
|
||||
char game_dir[256];
|
||||
char filename[256];
|
||||
FILE *fp = NULL;
|
||||
|
||||
// Alien Grunt (agrunt)
|
||||
gSkillData.agruntHealth = 90.0f;
|
||||
gSkillData.agruntDmgPunch = 20.0f;
|
||||
|
||||
// Apache (apache)
|
||||
gSkillData.apacheHealth = 250.0f;
|
||||
|
||||
// Barney (barney)
|
||||
gSkillData.barneyHealth = 35.0f;
|
||||
|
||||
// Big momma
|
||||
gSkillData.bigmommaHealthFactor = 1.5f;
|
||||
gSkillData.bigmommaDmgSlash = 60.0f;
|
||||
gSkillData.bigmommaDmgBlast = 120.0f;
|
||||
gSkillData.bigmommaRadiusBlast = 250.0f;
|
||||
|
||||
// Bullsquid (bullsquid)
|
||||
gSkillData.bullsquidHealth = 40.0f;
|
||||
gSkillData.bullsquidDmgBite = 25.0f;
|
||||
gSkillData.bullsquidDmgWhip = 35.0f;
|
||||
gSkillData.bullsquidDmgSpit = 10.0f;
|
||||
|
||||
// Gargantua
|
||||
gSkillData.gargantuaHealth = 800.0f;
|
||||
gSkillData.gargantuaDmgSlash = 30.0f;
|
||||
gSkillData.gargantuaDmgFire = 5.0f;
|
||||
gSkillData.gargantuaDmgStomp = 100.0f;
|
||||
|
||||
// Hassassin (hassassin)
|
||||
gSkillData.hassassinHealth = 50.0f;
|
||||
|
||||
// Headcrab (headcrab)
|
||||
gSkillData.headcrabHealth = 10.0f;
|
||||
gSkillData.headcrabDmgBite = 10.0f;
|
||||
|
||||
// Hgrunt (hgrunt)
|
||||
gSkillData.hgruntHealth = 50.0f;
|
||||
gSkillData.hgruntDmgKick = 10.0f;
|
||||
gSkillData.hgruntShotgunPellets = 5.0f;
|
||||
gSkillData.hgruntGrenadeSpeed = 600.0f;
|
||||
|
||||
// Houndeye (houndeye)
|
||||
gSkillData.houndeyeHealth = 20.0f;
|
||||
gSkillData.houndeyeDmgBlast = 15.0f;
|
||||
|
||||
// ISlave (islave)
|
||||
gSkillData.slaveHealth = 30.0f;
|
||||
gSkillData.slaveDmgClaw = 10.0f;
|
||||
gSkillData.slaveDmgClawrake = 25.0f;
|
||||
gSkillData.slaveDmgZap = 10.0f;
|
||||
|
||||
// Icthyosaur
|
||||
gSkillData.ichthyosaurHealth = 200.0f;
|
||||
gSkillData.ichthyosaurDmgShake = 35.0f;
|
||||
|
||||
// Leech
|
||||
gSkillData.leechHealth = 2.0f;
|
||||
gSkillData.leechDmgBite = 2.0f;
|
||||
|
||||
// Controller
|
||||
gSkillData.controllerHealth = 60.0f;
|
||||
gSkillData.controllerDmgZap = 25.0f;
|
||||
gSkillData.controllerSpeedBall = 800.0f;
|
||||
gSkillData.controllerDmgBall = 4.0f;
|
||||
|
||||
// Nihilanth
|
||||
gSkillData.nihilanthHealth = 800.0f;
|
||||
gSkillData.nihilanthZap = 30.0f;
|
||||
|
||||
// Scientist (scientist)
|
||||
gSkillData.scientistHealth = 20.0f;
|
||||
gSkillData.scientistHeal = 25.0f;
|
||||
|
||||
// Snark (snark)
|
||||
gSkillData.snarkHealth = 2.0f;
|
||||
gSkillData.snarkDmgBite = 10.0f;
|
||||
gSkillData.snarkDmgPop = 5.0f;
|
||||
|
||||
// Zombie (zombie)
|
||||
gSkillData.zombieHealth = 50.0f;
|
||||
gSkillData.zombieDmgOneSlash = 20.0f;
|
||||
gSkillData.zombieDmgBothSlash = 40.0f;
|
||||
|
||||
// MONSTER WEAPONS
|
||||
gSkillData.monDmg9MM = 5.0f;
|
||||
gSkillData.monDmgMP5 = 4.0f;
|
||||
gSkillData.monDmg12MM = 10.0f;
|
||||
gSkillData.monDmgM203Grenade = 100.0f;
|
||||
|
||||
// HORNET
|
||||
gSkillData.monDmgHornet = 5.0f;
|
||||
|
||||
|
||||
// find the directory name of the currently running MOD...
|
||||
(*g_engfuncs.pfnGetGameDir)(game_dir);
|
||||
|
||||
strcpy(filename, game_dir);
|
||||
strcat(filename, "/monster_skill.cfg");
|
||||
|
||||
// check if the map specific filename exists...
|
||||
if (access(filename, 0) == 0)
|
||||
{
|
||||
if (dllapi_log->value)
|
||||
{
|
||||
META_CONS("[MONSTER] Processing monster skill file=%s", filename);
|
||||
LOG_MESSAGE(PLID, "Processing monster skill file=%s", filename);
|
||||
}
|
||||
|
||||
if ((fp = fopen(filename, "r")) == NULL)
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
||||
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\"!", filename);
|
||||
}
|
||||
|
||||
scan_monster_skill(fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
META_CONS("[MONSTER] ERROR: Could not find \"%s\" (default skill used)", filename);
|
||||
LOG_MESSAGE(PLID, "ERROR: Could not find \"%s\" (default skill used)", filename);
|
||||
}
|
||||
}
|
||||
|
||||
103
src/dlls/skill.h
Normal file
103
src/dlls/skill.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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
|
||||
//=========================================================
|
||||
|
||||
#ifndef SKILL_H
|
||||
#define SKILL_H
|
||||
|
||||
struct skilldata_t
|
||||
{
|
||||
// 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 scientistHeal;
|
||||
|
||||
float snarkHealth;
|
||||
float snarkDmgBite;
|
||||
float snarkDmgPop;
|
||||
|
||||
float zombieHealth;
|
||||
float zombieDmgOneSlash;
|
||||
float zombieDmgBothSlash;
|
||||
|
||||
// weapons shared by monsters
|
||||
float monDmg9MM;
|
||||
float monDmgMP5;
|
||||
float monDmg12MM;
|
||||
float monDmgM203Grenade;
|
||||
|
||||
float monDmgHornet;
|
||||
};
|
||||
|
||||
extern DLL_GLOBAL skilldata_t gSkillData;
|
||||
|
||||
void monster_skill_init(void);
|
||||
|
||||
#endif
|
||||
915
src/dlls/sound.cpp
Normal file
915
src/dlls/sound.cpp
Normal file
@@ -0,0 +1,915 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// sound.cpp
|
||||
//=========================================================
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "weapons.h"
|
||||
#include "cmtalkmonster.h"
|
||||
#include "pm_materials.h"
|
||||
|
||||
|
||||
static char *memfgets( byte *pMemFile, int fileSize, int &filePos, char *pBuffer, int bufferSize );
|
||||
|
||||
|
||||
// ==================== GENERIC AMBIENT SOUND ======================================
|
||||
|
||||
// runtime pitch shift and volume fadein/out structure
|
||||
|
||||
// NOTE: IF YOU CHANGE THIS STRUCT YOU MUST CHANGE THE SAVE/RESTORE VERSION NUMBER
|
||||
// SEE BELOW (in the typedescription for the class)
|
||||
typedef struct dynpitchvol
|
||||
{
|
||||
// NOTE: do not change the order of these parameters
|
||||
// NOTE: unless you also change order of rgdpvpreset array elements!
|
||||
int preset;
|
||||
|
||||
int pitchrun; // pitch shift % when sound is running 0 - 255
|
||||
int pitchstart; // pitch shift % when sound stops or starts 0 - 255
|
||||
int spinup; // spinup time 0 - 100
|
||||
int spindown; // spindown time 0 - 100
|
||||
|
||||
int volrun; // volume change % when sound is running 0 - 10
|
||||
int volstart; // volume change % when sound stops or starts 0 - 10
|
||||
int fadein; // volume fade in time 0 - 100
|
||||
int fadeout; // volume fade out time 0 - 100
|
||||
|
||||
// Low Frequency Oscillator
|
||||
int lfotype; // 0) off 1) square 2) triangle 3) random
|
||||
int lforate; // 0 - 1000, how fast lfo osciallates
|
||||
|
||||
int lfomodpitch; // 0-100 mod of current pitch. 0 is off.
|
||||
int lfomodvol; // 0-100 mod of current volume. 0 is off.
|
||||
|
||||
int cspinup; // each trigger hit increments counter and spinup pitch
|
||||
|
||||
|
||||
int cspincount;
|
||||
|
||||
int pitch;
|
||||
int spinupsav;
|
||||
int spindownsav;
|
||||
int pitchfrac;
|
||||
|
||||
int vol;
|
||||
int fadeinsav;
|
||||
int fadeoutsav;
|
||||
int volfrac;
|
||||
|
||||
int lfofrac;
|
||||
int lfomult;
|
||||
|
||||
|
||||
} dynpitchvol_t;
|
||||
|
||||
#define CDPVPRESETMAX 27
|
||||
|
||||
// presets for runtime pitch and vol modulation of ambient sounds
|
||||
|
||||
/*jlb
|
||||
dynpitchvol_t rgdpvpreset[CDPVPRESETMAX] =
|
||||
{
|
||||
// pitch pstart spinup spindwn volrun volstrt fadein fadeout lfotype lforate modptch modvol cspnup
|
||||
{1, 255, 75, 95, 95, 10, 1, 50, 95, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{2, 255, 85, 70, 88, 10, 1, 20, 88, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{3, 255, 100, 50, 75, 10, 1, 10, 75, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{4, 100, 100, 0, 0, 10, 1, 90, 90, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{5, 100, 100, 0, 0, 10, 1, 80, 80, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{6, 100, 100, 0, 0, 10, 1, 50, 70, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{7, 100, 100, 0, 0, 5, 1, 40, 50, 1, 50, 0, 10, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{8, 100, 100, 0, 0, 5, 1, 40, 50, 1, 150, 0, 10, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{9, 100, 100, 0, 0, 5, 1, 40, 50, 1, 750, 0, 10, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{10,128, 100, 50, 75, 10, 1, 30, 40, 2, 8, 20, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{11,128, 100, 50, 75, 10, 1, 30, 40, 2, 25, 20, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{12,128, 100, 50, 75, 10, 1, 30, 40, 2, 70, 20, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{13,50, 50, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{14,70, 70, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{15,90, 90, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{16,120, 120, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{17,180, 180, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{18,255, 255, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{19,200, 75, 90, 90, 10, 1, 50, 90, 2, 100, 20, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{20,255, 75, 97, 90, 10, 1, 50, 90, 1, 40, 50, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{21,100, 100, 0, 0, 10, 1, 30, 50, 3, 15, 20, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{22,160, 160, 0, 0, 10, 1, 50, 50, 3, 500, 25, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{23,255, 75, 88, 0, 10, 1, 40, 0, 0, 0, 0, 0, 5, 0,0,0,0,0,0,0,0,0,0},
|
||||
{24,200, 20, 95, 70, 10, 1, 70, 70, 3, 20, 50, 0, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{25,180, 100, 50, 60, 10, 1, 40, 60, 2, 90, 100, 100, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{26,60, 60, 0, 0, 10, 1, 40, 70, 3, 80, 20, 50, 0, 0,0,0,0,0,0,0,0,0,0},
|
||||
{27,128, 90, 10, 10, 10, 1, 20, 40, 1, 5, 10, 20, 0, 0,0,0,0,0,0,0,0,0,0}
|
||||
};
|
||||
jlb*/
|
||||
|
||||
|
||||
// ==================== SENTENCE GROUPS, UTILITY FUNCTIONS ======================================
|
||||
|
||||
#define CSENTENCE_LRU_MAX 32 // max number of elements per sentence group
|
||||
|
||||
// group of related sentences
|
||||
|
||||
typedef struct sentenceg
|
||||
{
|
||||
char szgroupname[CBSENTENCENAME_MAX];
|
||||
int count;
|
||||
unsigned char rgblru[CSENTENCE_LRU_MAX];
|
||||
|
||||
} SENTENCEG;
|
||||
|
||||
#define CSENTENCEG_MAX 200 // max number of sentence groups
|
||||
// globals
|
||||
|
||||
SENTENCEG rgsentenceg[CSENTENCEG_MAX];
|
||||
int fSentencesInit = FALSE;
|
||||
|
||||
char gszallsentencenames[CVOXFILESENTENCEMAX][CBSENTENCENAME_MAX];
|
||||
int gcallsentences = 0;
|
||||
|
||||
// randomize list of sentence name indices
|
||||
|
||||
void USENTENCEG_InitLRU(unsigned char *plru, int count)
|
||||
{
|
||||
int i, j, k;
|
||||
unsigned char temp;
|
||||
|
||||
if (!fSentencesInit)
|
||||
return;
|
||||
|
||||
if (count > CSENTENCE_LRU_MAX)
|
||||
count = CSENTENCE_LRU_MAX;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
plru[i] = (unsigned char) i;
|
||||
|
||||
// randomize array
|
||||
for (i = 0; i < (count * 4); i++)
|
||||
{
|
||||
j = RANDOM_LONG(0,count-1);
|
||||
k = RANDOM_LONG(0,count-1);
|
||||
temp = plru[j];
|
||||
plru[j] = plru[k];
|
||||
plru[k] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore lru. pick next sentence from sentence group. Go in order until we hit the last sentence,
|
||||
// then repeat list if freset is true. If freset is false, then repeat last sentence.
|
||||
// ipick is passed in as the requested sentence ordinal.
|
||||
// ipick 'next' is returned.
|
||||
// return of -1 indicates an error.
|
||||
|
||||
int USENTENCEG_PickSequential(int isentenceg, char *szfound, int ipick, int freset)
|
||||
{
|
||||
char *szgroupname;
|
||||
unsigned char count;
|
||||
char sznum[8];
|
||||
|
||||
if (!fSentencesInit)
|
||||
return -1;
|
||||
|
||||
if (isentenceg < 0)
|
||||
return -1;
|
||||
|
||||
szgroupname = rgsentenceg[isentenceg].szgroupname;
|
||||
count = rgsentenceg[isentenceg].count;
|
||||
|
||||
if (count == 0)
|
||||
return -1;
|
||||
|
||||
if (ipick >= count)
|
||||
ipick = count-1;
|
||||
|
||||
strcpy(szfound, "!");
|
||||
strcat(szfound, szgroupname);
|
||||
sprintf(sznum, "%d", ipick);
|
||||
strcat(szfound, sznum);
|
||||
|
||||
if (ipick >= count)
|
||||
{
|
||||
if (freset)
|
||||
// reset at end of list
|
||||
return 0;
|
||||
else
|
||||
return count;
|
||||
}
|
||||
|
||||
return ipick + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// pick a random sentence from rootname0 to rootnameX.
|
||||
// picks from the rgsentenceg[isentenceg] least
|
||||
// recently used, modifies lru array. returns the sentencename.
|
||||
// note, lru must be seeded with 0-n randomized sentence numbers, with the
|
||||
// rest of the lru filled with -1. The first integer in the lru is
|
||||
// actually the size of the list. Returns ipick, the ordinal
|
||||
// of the picked sentence within the group.
|
||||
|
||||
int USENTENCEG_Pick(int isentenceg, char *szfound)
|
||||
{
|
||||
char *szgroupname;
|
||||
unsigned char *plru;
|
||||
unsigned char i;
|
||||
unsigned char count;
|
||||
char sznum[8];
|
||||
unsigned char ipick;
|
||||
int ffound = FALSE;
|
||||
|
||||
if (!fSentencesInit)
|
||||
return -1;
|
||||
|
||||
if (isentenceg < 0)
|
||||
return -1;
|
||||
|
||||
szgroupname = rgsentenceg[isentenceg].szgroupname;
|
||||
count = rgsentenceg[isentenceg].count;
|
||||
plru = rgsentenceg[isentenceg].rgblru;
|
||||
|
||||
while (!ffound)
|
||||
{
|
||||
for (i = 0; i < count; i++)
|
||||
if (plru[i] != 0xFF)
|
||||
{
|
||||
ipick = plru[i];
|
||||
plru[i] = 0xFF;
|
||||
ffound = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ffound)
|
||||
USENTENCEG_InitLRU(plru, count);
|
||||
else
|
||||
{
|
||||
strcpy(szfound, "!");
|
||||
strcat(szfound, szgroupname);
|
||||
sprintf(sznum, "%d", ipick);
|
||||
strcat(szfound, sznum);
|
||||
return ipick;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ===================== SENTENCE GROUPS, MAIN ROUTINES ========================
|
||||
|
||||
// Given sentence group rootname (name without number suffix),
|
||||
// get sentence group index (isentenceg). Returns -1 if no such name.
|
||||
|
||||
int SENTENCEG_GetIndex(const char *szgroupname)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!fSentencesInit || !szgroupname)
|
||||
return -1;
|
||||
|
||||
// search rgsentenceg for match on szgroupname
|
||||
|
||||
i = 0;
|
||||
while (rgsentenceg[i].count)
|
||||
{
|
||||
if (!strcmp(szgroupname, rgsentenceg[i].szgroupname))
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// given sentence group index, play random sentence for given entity.
|
||||
// returns ipick - which sentence was picked to
|
||||
// play from the group. Ipick is only needed if you plan on stopping
|
||||
// the sound before playback is done (see SENTENCEG_Stop).
|
||||
|
||||
int SENTENCEG_PlayRndI(edict_t *entity, int isentenceg,
|
||||
float volume, float attenuation, int flags, int pitch)
|
||||
{
|
||||
char name[64];
|
||||
int ipick;
|
||||
|
||||
if (!fSentencesInit)
|
||||
return -1;
|
||||
|
||||
name[0] = 0;
|
||||
|
||||
ipick = USENTENCEG_Pick(isentenceg, name);
|
||||
if (ipick > 0 && name)
|
||||
EMIT_SOUND_DYN(entity, CHAN_VOICE, name, volume, attenuation, flags, pitch);
|
||||
return ipick;
|
||||
}
|
||||
|
||||
// same as above, but takes sentence group name instead of index
|
||||
|
||||
int SENTENCEG_PlayRndSz(edict_t *entity, const char *szgroupname,
|
||||
float volume, float attenuation, int flags, int pitch)
|
||||
{
|
||||
char name[64];
|
||||
int ipick;
|
||||
int isentenceg;
|
||||
|
||||
if (!fSentencesInit)
|
||||
return -1;
|
||||
|
||||
name[0] = 0;
|
||||
|
||||
isentenceg = SENTENCEG_GetIndex(szgroupname);
|
||||
if (isentenceg < 0)
|
||||
{
|
||||
ALERT( at_console, "No such sentence group %s\n", szgroupname );
|
||||
return -1;
|
||||
}
|
||||
|
||||
ipick = USENTENCEG_Pick(isentenceg, name);
|
||||
if (ipick >= 0 && name[0])
|
||||
EMIT_SOUND_DYN(entity, CHAN_VOICE, name, volume, attenuation, flags, pitch);
|
||||
|
||||
return ipick;
|
||||
}
|
||||
|
||||
// play sentences in sequential order from sentence group. Reset after last sentence.
|
||||
|
||||
int SENTENCEG_PlaySequentialSz(edict_t *entity, const char *szgroupname,
|
||||
float volume, float attenuation, int flags, int pitch, int ipick, int freset)
|
||||
{
|
||||
char name[64];
|
||||
int ipicknext;
|
||||
int isentenceg;
|
||||
|
||||
if (!fSentencesInit)
|
||||
return -1;
|
||||
|
||||
name[0] = 0;
|
||||
|
||||
isentenceg = SENTENCEG_GetIndex(szgroupname);
|
||||
if (isentenceg < 0)
|
||||
return -1;
|
||||
|
||||
ipicknext = USENTENCEG_PickSequential(isentenceg, name, ipick, freset);
|
||||
if (ipicknext >= 0 && name[0])
|
||||
EMIT_SOUND_DYN(entity, CHAN_VOICE, name, volume, attenuation, flags, pitch);
|
||||
return ipicknext;
|
||||
}
|
||||
|
||||
|
||||
// for this entity, for the given sentence within the sentence group, stop
|
||||
// the sentence.
|
||||
|
||||
void SENTENCEG_Stop(edict_t *entity, int isentenceg, int ipick)
|
||||
{
|
||||
char buffer[64];
|
||||
char sznum[8];
|
||||
|
||||
if (!fSentencesInit)
|
||||
return;
|
||||
|
||||
if (isentenceg < 0 || ipick < 0)
|
||||
return;
|
||||
|
||||
strcpy(buffer, "!");
|
||||
strcat(buffer, rgsentenceg[isentenceg].szgroupname);
|
||||
sprintf(sznum, "%d", ipick);
|
||||
strcat(buffer, sznum);
|
||||
|
||||
STOP_SOUND(entity, CHAN_VOICE, buffer);
|
||||
}
|
||||
|
||||
// open sentences.txt, scan for groups, build rgsentenceg
|
||||
// Should be called from world spawn, only works on the
|
||||
// first call and is ignored subsequently.
|
||||
|
||||
void SENTENCEG_Init()
|
||||
{
|
||||
char buffer[512];
|
||||
char szgroup[64];
|
||||
int i, j;
|
||||
int isentencegs;
|
||||
|
||||
if (fSentencesInit)
|
||||
return;
|
||||
|
||||
memset(gszallsentencenames, 0, CVOXFILESENTENCEMAX * CBSENTENCENAME_MAX);
|
||||
gcallsentences = 0;
|
||||
|
||||
memset(rgsentenceg, 0, CSENTENCEG_MAX * sizeof(SENTENCEG));
|
||||
memset(buffer, 0, 512);
|
||||
memset(szgroup, 0, 64);
|
||||
isentencegs = -1;
|
||||
|
||||
|
||||
int filePos = 0, fileSize;
|
||||
byte *pMemFile = g_engfuncs.pfnLoadFileForMe( "sound/sentences.txt", &fileSize );
|
||||
if ( !pMemFile )
|
||||
return;
|
||||
|
||||
// for each line in the file...
|
||||
while ( memfgets(pMemFile, fileSize, filePos, buffer, 511) != NULL )
|
||||
{
|
||||
// skip whitespace
|
||||
i = 0;
|
||||
while(buffer[i] && buffer[i] == ' ')
|
||||
i++;
|
||||
|
||||
if (!buffer[i])
|
||||
continue;
|
||||
|
||||
if (buffer[i] == '/' || !isalpha(buffer[i]))
|
||||
continue;
|
||||
|
||||
// get sentence name
|
||||
j = i;
|
||||
while (buffer[j] && buffer[j] != ' ')
|
||||
j++;
|
||||
|
||||
if (!buffer[j])
|
||||
continue;
|
||||
|
||||
if (gcallsentences > CVOXFILESENTENCEMAX)
|
||||
{
|
||||
ALERT (at_error, "Too many sentences in sentences.txt!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// null-terminate name and save in sentences array
|
||||
buffer[j] = 0;
|
||||
const char *pString = buffer + i;
|
||||
|
||||
if ( strlen( pString ) >= CBSENTENCENAME_MAX )
|
||||
ALERT( at_warning, "Sentence %s longer than %d letters\n", pString, CBSENTENCENAME_MAX-1 );
|
||||
|
||||
strcpy( gszallsentencenames[gcallsentences++], pString );
|
||||
|
||||
j--;
|
||||
if (j <= i)
|
||||
continue;
|
||||
if (!isdigit(buffer[j]))
|
||||
continue;
|
||||
|
||||
// cut out suffix numbers
|
||||
while (j > i && isdigit(buffer[j]))
|
||||
j--;
|
||||
|
||||
if (j <= i)
|
||||
continue;
|
||||
|
||||
buffer[j+1] = 0;
|
||||
|
||||
// if new name doesn't match previous group name,
|
||||
// make a new group.
|
||||
|
||||
if (strcmp(szgroup, &(buffer[i])))
|
||||
{
|
||||
// name doesn't match with prev name,
|
||||
// copy name into group, init count to 1
|
||||
isentencegs++;
|
||||
if (isentencegs >= CSENTENCEG_MAX)
|
||||
{
|
||||
ALERT (at_error, "Too many sentence groups in sentences.txt!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(rgsentenceg[isentencegs].szgroupname, &(buffer[i]));
|
||||
rgsentenceg[isentencegs].count = 1;
|
||||
|
||||
strcpy(szgroup, &(buffer[i]));
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
//name matches with previous, increment group count
|
||||
if (isentencegs >= 0)
|
||||
rgsentenceg[isentencegs].count++;
|
||||
}
|
||||
}
|
||||
|
||||
g_engfuncs.pfnFreeFile( pMemFile );
|
||||
|
||||
fSentencesInit = TRUE;
|
||||
|
||||
// init lru lists
|
||||
|
||||
i = 0;
|
||||
|
||||
while (rgsentenceg[i].count && i < CSENTENCEG_MAX)
|
||||
{
|
||||
USENTENCEG_InitLRU(&(rgsentenceg[i].rgblru[0]), rgsentenceg[i].count);
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// convert sentence (sample) name to !sentencenum, return !sentencenum
|
||||
|
||||
int SENTENCEG_Lookup(const char *sample, char *sentencenum)
|
||||
{
|
||||
char sznum[8];
|
||||
|
||||
int i;
|
||||
// this is a sentence name; lookup sentence number
|
||||
// and give to engine as string.
|
||||
for (i = 0; i < gcallsentences; i++)
|
||||
if (!stricmp(gszallsentencenames[i], sample+1))
|
||||
{
|
||||
if (sentencenum)
|
||||
{
|
||||
strcpy(sentencenum, "!");
|
||||
sprintf(sznum, "%d", i);
|
||||
strcat(sentencenum, sznum);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
// sentence name not found!
|
||||
return -1;
|
||||
}
|
||||
|
||||
void EMIT_SOUND_DYN(edict_t *entity, int channel, const char *sample, float volume, float attenuation,
|
||||
int flags, int pitch)
|
||||
{
|
||||
if (sample && *sample == '!')
|
||||
{
|
||||
char name[32];
|
||||
if (SENTENCEG_Lookup(sample, name) >= 0)
|
||||
EMIT_SOUND_DYN2(entity, channel, name, volume, attenuation, flags, pitch);
|
||||
else
|
||||
ALERT( at_aiconsole, "Unable to find %s in sentences.txt\n", sample );
|
||||
}
|
||||
else
|
||||
EMIT_SOUND_DYN2(entity, channel, sample, volume, attenuation, flags, pitch);
|
||||
}
|
||||
|
||||
// play a specific sentence over the HEV suit speaker - just pass player entity, and !sentencename
|
||||
|
||||
void EMIT_SOUND_SUIT(edict_t *entity, const char *sample)
|
||||
{
|
||||
float fvol;
|
||||
int pitch = PITCH_NORM;
|
||||
|
||||
fvol = CVAR_GET_FLOAT("suitvolume");
|
||||
if (RANDOM_LONG(0,1))
|
||||
pitch = RANDOM_LONG(0,6) + 98;
|
||||
|
||||
if (fvol > 0.05)
|
||||
EMIT_SOUND_DYN(entity, CHAN_STATIC, sample, fvol, ATTN_NORM, 0, pitch);
|
||||
}
|
||||
|
||||
// play a sentence, randomly selected from the passed in group id, over the HEV suit speaker
|
||||
|
||||
void EMIT_GROUPID_SUIT(edict_t *entity, int isentenceg)
|
||||
{
|
||||
float fvol;
|
||||
int pitch = PITCH_NORM;
|
||||
|
||||
fvol = CVAR_GET_FLOAT("suitvolume");
|
||||
if (RANDOM_LONG(0,1))
|
||||
pitch = RANDOM_LONG(0,6) + 98;
|
||||
|
||||
if (fvol > 0.05)
|
||||
SENTENCEG_PlayRndI(entity, isentenceg, fvol, ATTN_NORM, 0, pitch);
|
||||
}
|
||||
|
||||
// play a sentence, randomly selected from the passed in groupname
|
||||
|
||||
void EMIT_GROUPNAME_SUIT(edict_t *entity, const char *groupname)
|
||||
{
|
||||
float fvol;
|
||||
int pitch = PITCH_NORM;
|
||||
|
||||
fvol = CVAR_GET_FLOAT("suitvolume");
|
||||
if (RANDOM_LONG(0,1))
|
||||
pitch = RANDOM_LONG(0,6) + 98;
|
||||
|
||||
if (fvol > 0.05)
|
||||
SENTENCEG_PlayRndSz(entity, groupname, fvol, ATTN_NORM, 0, pitch);
|
||||
}
|
||||
|
||||
// ===================== MATERIAL TYPE DETECTION, MAIN ROUTINES ========================
|
||||
//
|
||||
// Used to detect the texture the player is standing on, map the
|
||||
// texture name to a material type. Play footstep sound based
|
||||
// on material type.
|
||||
|
||||
int fTextureTypeInit = FALSE;
|
||||
|
||||
#define CTEXTURESMAX 512 // max number of textures loaded
|
||||
|
||||
//jlbint gcTextures = 0;
|
||||
//jlbchar grgszTextureName[CTEXTURESMAX][CBTEXTURENAMEMAX]; // texture names
|
||||
//jlbchar grgchTextureType[CTEXTURESMAX]; // parallel array of texture types
|
||||
|
||||
// open materials.txt, get size, alloc space,
|
||||
// save in array. Only works first time called,
|
||||
// ignored on subsequent calls.
|
||||
|
||||
static char *memfgets( byte *pMemFile, int fileSize, int &filePos, char *pBuffer, int bufferSize )
|
||||
{
|
||||
// Bullet-proofing
|
||||
if ( !pMemFile || !pBuffer )
|
||||
return NULL;
|
||||
|
||||
if ( filePos >= fileSize )
|
||||
return NULL;
|
||||
|
||||
int i = filePos;
|
||||
int last = fileSize;
|
||||
|
||||
// fgets always NULL terminates, so only read bufferSize-1 characters
|
||||
if ( last - filePos > (bufferSize-1) )
|
||||
last = filePos + (bufferSize-1);
|
||||
|
||||
int stop = 0;
|
||||
|
||||
// Stop at the next newline (inclusive) or end of buffer
|
||||
while ( i < last && !stop )
|
||||
{
|
||||
if ( pMemFile[i] == '\n' )
|
||||
stop = 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
// If we actually advanced the pointer, copy it over
|
||||
if ( i != filePos )
|
||||
{
|
||||
// We read in size bytes
|
||||
int size = i - filePos;
|
||||
// copy it out
|
||||
memcpy( pBuffer, pMemFile + filePos, sizeof(byte)*size );
|
||||
|
||||
// If the buffer isn't full, terminate (this is always true)
|
||||
if ( size < bufferSize )
|
||||
pBuffer[size] = 0;
|
||||
|
||||
// Update file pointer
|
||||
filePos = i;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
// No data read, bail
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void TEXTURETYPE_Init()
|
||||
{
|
||||
/*jlb
|
||||
char buffer[512];
|
||||
int i, j;
|
||||
byte *pMemFile;
|
||||
int fileSize, filePos;
|
||||
|
||||
if (fTextureTypeInit)
|
||||
return;
|
||||
|
||||
memset(&(grgszTextureName[0][0]), 0, CTEXTURESMAX * CBTEXTURENAMEMAX);
|
||||
memset(grgchTextureType, 0, CTEXTURESMAX);
|
||||
|
||||
gcTextures = 0;
|
||||
memset(buffer, 0, 512);
|
||||
|
||||
pMemFile = g_engfuncs.pfnLoadFileForMe( "sound/materials.txt", &fileSize );
|
||||
if ( !pMemFile )
|
||||
return;
|
||||
|
||||
// for each line in the file...
|
||||
while (memfgets(pMemFile, fileSize, filePos, buffer, 511) != NULL && (gcTextures < CTEXTURESMAX))
|
||||
{
|
||||
// skip whitespace
|
||||
i = 0;
|
||||
while(buffer[i] && isspace(buffer[i]))
|
||||
i++;
|
||||
|
||||
if (!buffer[i])
|
||||
continue;
|
||||
|
||||
// skip comment lines
|
||||
if (buffer[i] == '/' || !isalpha(buffer[i]))
|
||||
continue;
|
||||
|
||||
// get texture type
|
||||
grgchTextureType[gcTextures] = toupper(buffer[i++]);
|
||||
|
||||
// skip whitespace
|
||||
while(buffer[i] && isspace(buffer[i]))
|
||||
i++;
|
||||
|
||||
if (!buffer[i])
|
||||
continue;
|
||||
|
||||
// get sentence name
|
||||
j = i;
|
||||
while (buffer[j] && !isspace(buffer[j]))
|
||||
j++;
|
||||
|
||||
if (!buffer[j])
|
||||
continue;
|
||||
|
||||
// null-terminate name and save in sentences array
|
||||
j = min (j, CBTEXTURENAMEMAX-1+i);
|
||||
buffer[j] = 0;
|
||||
strcpy(&(grgszTextureName[gcTextures++][0]), &(buffer[i]));
|
||||
}
|
||||
|
||||
g_engfuncs.pfnFreeFile( pMemFile );
|
||||
|
||||
fTextureTypeInit = TRUE;
|
||||
jlb*/
|
||||
}
|
||||
|
||||
// given texture name, find texture type
|
||||
// if not found, return type 'concrete'
|
||||
|
||||
// NOTE: this routine should ONLY be called if the
|
||||
// current texture under the player changes!
|
||||
|
||||
char TEXTURETYPE_Find(char *name)
|
||||
{
|
||||
// CONSIDER: pre-sort texture names and perform faster binary search here
|
||||
/*jlb
|
||||
for (int i = 0; i < gcTextures; i++)
|
||||
{
|
||||
if (!strnicmp(name, &(grgszTextureName[i][0]), CBTEXTURENAMEMAX-1))
|
||||
return (grgchTextureType[i]);
|
||||
}
|
||||
jlb*/
|
||||
return CHAR_TEX_CONCRETE;
|
||||
}
|
||||
|
||||
// play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the
|
||||
// original traceline endpoints used by the attacker, iBulletType is the type of bullet that hit the texture.
|
||||
// returns volume of strike instrument (crowbar) to play
|
||||
|
||||
float TEXTURETYPE_PlaySound(TraceResult *ptr, Vector vecSrc, Vector vecEnd, int iBulletType)
|
||||
{
|
||||
// hit the world, try to play sound based on texture material type
|
||||
|
||||
char chTextureType;
|
||||
float fvol;
|
||||
float fvolbar;
|
||||
char szbuffer[64];
|
||||
const char *pTextureName;
|
||||
float rgfl1[3];
|
||||
float rgfl2[3];
|
||||
char *rgsz[4];
|
||||
int cnt;
|
||||
float fattn = ATTN_NORM;
|
||||
|
||||
CMBaseEntity *pEntity = CMBaseEntity::Instance(ptr->pHit);
|
||||
|
||||
chTextureType = 0;
|
||||
|
||||
if (pEntity && pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
|
||||
// hit body
|
||||
chTextureType = CHAR_TEX_FLESH;
|
||||
else
|
||||
{
|
||||
// hit world
|
||||
|
||||
// find texture under strike, get material type
|
||||
|
||||
// copy trace vector into array for trace_texture
|
||||
|
||||
vecSrc.CopyToArray(rgfl1);
|
||||
vecEnd.CopyToArray(rgfl2);
|
||||
|
||||
// get texture from entity or world (world is ent(0))
|
||||
if (pEntity)
|
||||
pTextureName = TRACE_TEXTURE( ENT(pEntity->pev), rgfl1, rgfl2 );
|
||||
else
|
||||
pTextureName = TRACE_TEXTURE( ENT(0), rgfl1, rgfl2 );
|
||||
|
||||
if ( pTextureName )
|
||||
{
|
||||
// strip leading '-0' or '+0~' or '{' or '!'
|
||||
if (*pTextureName == '-' || *pTextureName == '+')
|
||||
pTextureName += 2;
|
||||
|
||||
if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ')
|
||||
pTextureName++;
|
||||
// '}}'
|
||||
strcpy(szbuffer, pTextureName);
|
||||
szbuffer[CBTEXTURENAMEMAX - 1] = 0;
|
||||
|
||||
// ALERT ( at_console, "texture hit: %s\n", szbuffer);
|
||||
|
||||
// get texture type
|
||||
chTextureType = TEXTURETYPE_Find(szbuffer);
|
||||
}
|
||||
}
|
||||
|
||||
switch (chTextureType)
|
||||
{
|
||||
default:
|
||||
case CHAR_TEX_CONCRETE: fvol = 0.9; fvolbar = 0.6;
|
||||
rgsz[0] = "player/pl_step1.wav";
|
||||
rgsz[1] = "player/pl_step2.wav";
|
||||
cnt = 2;
|
||||
break;
|
||||
case CHAR_TEX_METAL: fvol = 0.9; fvolbar = 0.3;
|
||||
rgsz[0] = "player/pl_metal1.wav";
|
||||
rgsz[1] = "player/pl_metal2.wav";
|
||||
cnt = 2;
|
||||
break;
|
||||
case CHAR_TEX_DIRT: fvol = 0.9; fvolbar = 0.1;
|
||||
rgsz[0] = "player/pl_dirt1.wav";
|
||||
rgsz[1] = "player/pl_dirt2.wav";
|
||||
rgsz[2] = "player/pl_dirt3.wav";
|
||||
cnt = 3;
|
||||
break;
|
||||
case CHAR_TEX_VENT: fvol = 0.5; fvolbar = 0.3;
|
||||
rgsz[0] = "player/pl_duct1.wav";
|
||||
rgsz[1] = "player/pl_duct1.wav";
|
||||
cnt = 2;
|
||||
break;
|
||||
case CHAR_TEX_GRATE: fvol = 0.9; fvolbar = 0.5;
|
||||
rgsz[0] = "player/pl_grate1.wav";
|
||||
rgsz[1] = "player/pl_grate4.wav";
|
||||
cnt = 2;
|
||||
break;
|
||||
case CHAR_TEX_TILE: fvol = 0.8; fvolbar = 0.2;
|
||||
rgsz[0] = "player/pl_tile1.wav";
|
||||
rgsz[1] = "player/pl_tile3.wav";
|
||||
rgsz[2] = "player/pl_tile2.wav";
|
||||
rgsz[3] = "player/pl_tile4.wav";
|
||||
cnt = 4;
|
||||
break;
|
||||
case CHAR_TEX_SLOSH: fvol = 0.9; fvolbar = 0.0;
|
||||
rgsz[0] = "player/pl_slosh1.wav";
|
||||
rgsz[1] = "player/pl_slosh3.wav";
|
||||
rgsz[2] = "player/pl_slosh2.wav";
|
||||
rgsz[3] = "player/pl_slosh4.wav";
|
||||
cnt = 4;
|
||||
break;
|
||||
case CHAR_TEX_WOOD: fvol = 0.9; fvolbar = 0.2;
|
||||
rgsz[0] = "debris/wood1.wav";
|
||||
rgsz[1] = "debris/wood2.wav";
|
||||
rgsz[2] = "debris/wood3.wav";
|
||||
cnt = 3;
|
||||
break;
|
||||
case CHAR_TEX_GLASS:
|
||||
case CHAR_TEX_COMPUTER:
|
||||
fvol = 0.8; fvolbar = 0.2;
|
||||
rgsz[0] = "debris/glass1.wav";
|
||||
rgsz[1] = "debris/glass2.wav";
|
||||
rgsz[2] = "debris/glass3.wav";
|
||||
cnt = 3;
|
||||
break;
|
||||
case CHAR_TEX_FLESH:
|
||||
if (iBulletType == BULLET_PLAYER_CROWBAR)
|
||||
return 0.0; // crowbar already makes this sound
|
||||
fvol = 1.0; fvolbar = 0.2;
|
||||
rgsz[0] = "weapons/bullet_hit1.wav";
|
||||
rgsz[1] = "weapons/bullet_hit2.wav";
|
||||
fattn = 1.0;
|
||||
cnt = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// did we hit a breakable?
|
||||
|
||||
if (pEntity && FClassnameIs(pEntity->pev, "func_breakable"))
|
||||
{
|
||||
// drop volumes, the object will already play a damaged sound
|
||||
fvol /= 1.5;
|
||||
fvolbar /= 2.0;
|
||||
}
|
||||
else if (chTextureType == CHAR_TEX_COMPUTER)
|
||||
{
|
||||
// play random spark if computer
|
||||
|
||||
if ( ptr->flFraction != 1.0 && RANDOM_LONG(0,1))
|
||||
{
|
||||
UTIL_Sparks( ptr->vecEndPos );
|
||||
|
||||
float flVolume = RANDOM_FLOAT ( 0.7 , 1.0 );//random volume range
|
||||
switch ( RANDOM_LONG(0,1) )
|
||||
{
|
||||
case 0: UTIL_EmitAmbientSound(ENT(0), ptr->vecEndPos, "buttons/spark5.wav", flVolume, ATTN_NORM, 0, 100); break;
|
||||
case 1: UTIL_EmitAmbientSound(ENT(0), ptr->vecEndPos, "buttons/spark6.wav", flVolume, ATTN_NORM, 0, 100); break;
|
||||
// case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark5.wav", flVolume, ATTN_NORM); break;
|
||||
// case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark6.wav", flVolume, ATTN_NORM); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// play material hit sound
|
||||
UTIL_EmitAmbientSound(ENT(0), ptr->vecEndPos, rgsz[RANDOM_LONG(0,cnt-1)], fvol, fattn, 0, 96 + RANDOM_LONG(0,0xf));
|
||||
//EMIT_SOUND_DYN( ENT(m_pPlayer->pev), CHAN_WEAPON, rgsz[RANDOM_LONG(0,cnt-1)], fvol, ATTN_NORM, 0, 96 + RANDOM_LONG(0,0xf));
|
||||
|
||||
return fvolbar;
|
||||
}
|
||||
|
||||
337
src/dlls/squeakgrenade.cpp
Normal file
337
src/dlls/squeakgrenade.cpp
Normal file
@@ -0,0 +1,337 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "weapons.h"
|
||||
#include "nodes.h"
|
||||
|
||||
enum w_squeak_e {
|
||||
WSQUEAK_IDLE1 = 0,
|
||||
WSQUEAK_FIDGET,
|
||||
WSQUEAK_JUMP,
|
||||
WSQUEAK_RUN,
|
||||
};
|
||||
|
||||
enum squeak_e {
|
||||
SQUEAK_IDLE1 = 0,
|
||||
SQUEAK_FIDGETFIT,
|
||||
SQUEAK_FIDGETNIP,
|
||||
SQUEAK_DOWN,
|
||||
SQUEAK_UP,
|
||||
SQUEAK_THROW
|
||||
};
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
|
||||
|
||||
float CMSqueakGrenade::m_flNextBounceSoundTime = 0;
|
||||
|
||||
#define SQUEEK_DETONATE_DELAY 15.0
|
||||
|
||||
int CMSqueakGrenade :: Classify ( void )
|
||||
{
|
||||
return CLASS_ALIEN_MONSTER;
|
||||
}
|
||||
|
||||
void CMSqueakGrenade :: Spawn( void )
|
||||
{
|
||||
Precache( );
|
||||
// motor
|
||||
pev->movetype = MOVETYPE_BOUNCE;
|
||||
pev->solid = SOLID_BBOX;
|
||||
|
||||
SET_MODEL(ENT(pev), "models/w_squeak.mdl");
|
||||
UTIL_SetSize(pev, Vector( -4, -4, 0), Vector(4, 4, 8));
|
||||
UTIL_SetOrigin( pev, pev->origin );
|
||||
|
||||
SetTouch( SuperBounceTouch );
|
||||
SetThink( HuntThink );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
m_flNextHunt = gpGlobals->time + 1E6;
|
||||
|
||||
pev->flags |= FL_MONSTER;
|
||||
pev->takedamage = DAMAGE_AIM;
|
||||
pev->health = gSkillData.snarkHealth;
|
||||
pev->gravity = 0.5;
|
||||
pev->friction = 0.5;
|
||||
|
||||
pev->dmg = gSkillData.snarkDmgPop;
|
||||
|
||||
m_flDie = gpGlobals->time + SQUEEK_DETONATE_DELAY;
|
||||
|
||||
m_flFieldOfView = 0; // 180 degrees
|
||||
|
||||
m_flNextBounceSoundTime = gpGlobals->time;// reset each time a snark is spawned.
|
||||
|
||||
pev->sequence = WSQUEAK_RUN;
|
||||
ResetSequenceInfo( );
|
||||
|
||||
m_hEnemy = NULL;
|
||||
}
|
||||
|
||||
void CMSqueakGrenade::Precache( void )
|
||||
{
|
||||
PRECACHE_MODEL("models/w_squeak.mdl");
|
||||
PRECACHE_SOUND("squeek/sqk_blast1.wav");
|
||||
PRECACHE_SOUND("common/bodysplat.wav");
|
||||
PRECACHE_SOUND("squeek/sqk_die1.wav");
|
||||
PRECACHE_SOUND("squeek/sqk_hunt1.wav");
|
||||
PRECACHE_SOUND("squeek/sqk_hunt2.wav");
|
||||
PRECACHE_SOUND("squeek/sqk_hunt3.wav");
|
||||
PRECACHE_SOUND("squeek/sqk_deploy1.wav");
|
||||
}
|
||||
|
||||
|
||||
void CMSqueakGrenade :: Killed( entvars_t *pevAttacker, int iGib )
|
||||
{
|
||||
pev->model = iStringNull;// make invisible
|
||||
SetThink( SUB_Remove );
|
||||
SetTouch( NULL );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
|
||||
// since squeak grenades never leave a body behind, clear out their takedamage now.
|
||||
// Squeaks do a bit of radius damage when they pop, and that radius damage will
|
||||
// continue to call this function unless we acknowledge the Squeak's death now. (sjb)
|
||||
pev->takedamage = DAMAGE_NO;
|
||||
|
||||
// play squeek blast
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_ITEM, "squeek/sqk_blast1.wav", 1, 0.5, 0, PITCH_NORM);
|
||||
|
||||
UTIL_BloodDrips( pev->origin, g_vecZero, BloodColor(), 80 );
|
||||
|
||||
RadiusDamage ( pev, pev, pev->dmg, CLASS_NONE, DMG_BLAST );
|
||||
|
||||
CMBaseMonster :: Killed( pevAttacker, GIB_ALWAYS );
|
||||
}
|
||||
|
||||
void CMSqueakGrenade :: GibMonster( void )
|
||||
{
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "common/bodysplat.wav", 0.75, ATTN_NORM, 0, 200);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMSqueakGrenade::HuntThink( void )
|
||||
{
|
||||
// ALERT( at_console, "think\n" );
|
||||
|
||||
if (!IsInWorld())
|
||||
{
|
||||
SetTouch( NULL );
|
||||
UTIL_Remove( this->edict() );
|
||||
return;
|
||||
}
|
||||
|
||||
StudioFrameAdvance( );
|
||||
pev->nextthink = gpGlobals->time + 0.1;
|
||||
|
||||
// explode when ready
|
||||
if (gpGlobals->time >= m_flDie)
|
||||
{
|
||||
g_vecAttackDir = pev->velocity.Normalize( );
|
||||
pev->health = -1;
|
||||
Killed( pev, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
// float
|
||||
if (pev->waterlevel != 0)
|
||||
{
|
||||
if (pev->movetype == MOVETYPE_BOUNCE)
|
||||
{
|
||||
pev->movetype = MOVETYPE_FLY;
|
||||
}
|
||||
pev->velocity = pev->velocity * 0.9;
|
||||
pev->velocity.z += 8.0;
|
||||
}
|
||||
else if (pev->movetype = MOVETYPE_FLY)
|
||||
{
|
||||
pev->movetype = MOVETYPE_BOUNCE;
|
||||
}
|
||||
|
||||
// return if not time to hunt
|
||||
if (m_flNextHunt > gpGlobals->time)
|
||||
return;
|
||||
|
||||
m_flNextHunt = gpGlobals->time + 2.0;
|
||||
|
||||
Vector vecDir;
|
||||
TraceResult tr;
|
||||
|
||||
Vector vecFlat = pev->velocity;
|
||||
vecFlat.z = 0;
|
||||
vecFlat = vecFlat.Normalize( );
|
||||
|
||||
UTIL_MakeVectors( pev->angles );
|
||||
|
||||
if (m_hEnemy == NULL || !UTIL_IsAlive(m_hEnemy))
|
||||
{
|
||||
// find target, bounce a bit towards it.
|
||||
Look( 512 );
|
||||
m_hEnemy = BestVisibleEnemy( );
|
||||
}
|
||||
|
||||
// squeek if it's about time blow up
|
||||
if ((m_flDie - gpGlobals->time <= 0.5) && (m_flDie - gpGlobals->time >= 0.3))
|
||||
{
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_die1.wav", 1, ATTN_NORM, 0, 100 + RANDOM_LONG(0,0x3F));
|
||||
}
|
||||
|
||||
// higher pitch as squeeker gets closer to detonation time
|
||||
float flpitch = 155.0 - 60.0 * ((m_flDie - gpGlobals->time) / SQUEEK_DETONATE_DELAY);
|
||||
if (flpitch < 80)
|
||||
flpitch = 80;
|
||||
|
||||
if (m_hEnemy != NULL)
|
||||
{
|
||||
if (UTIL_FVisible( m_hEnemy, ENT(pev) ))
|
||||
{
|
||||
vecDir = (m_hEnemy->v.origin + m_hEnemy->v.view_ofs) - pev->origin;
|
||||
m_vecTarget = vecDir.Normalize( );
|
||||
}
|
||||
|
||||
float flVel = pev->velocity.Length();
|
||||
float flAdj = 50.0 / (flVel + 10.0);
|
||||
|
||||
if (flAdj > 1.2)
|
||||
flAdj = 1.2;
|
||||
|
||||
// ALERT( at_console, "think : enemy\n");
|
||||
|
||||
// ALERT( at_console, "%.0f %.2f %.2f %.2f\n", flVel, m_vecTarget.x, m_vecTarget.y, m_vecTarget.z );
|
||||
|
||||
pev->velocity = pev->velocity * flAdj + m_vecTarget * 300;
|
||||
}
|
||||
|
||||
if (pev->flags & FL_ONGROUND)
|
||||
{
|
||||
pev->avelocity = Vector( 0, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pev->avelocity == Vector( 0, 0, 0))
|
||||
{
|
||||
pev->avelocity.x = RANDOM_FLOAT( -100, 100 );
|
||||
pev->avelocity.z = RANDOM_FLOAT( -100, 100 );
|
||||
}
|
||||
}
|
||||
|
||||
if ((pev->origin - m_posPrev).Length() < 1.0)
|
||||
{
|
||||
pev->velocity.x = RANDOM_FLOAT( -100, 100 );
|
||||
pev->velocity.y = RANDOM_FLOAT( -100, 100 );
|
||||
}
|
||||
m_posPrev = pev->origin;
|
||||
|
||||
pev->angles = UTIL_VecToAngles( pev->velocity );
|
||||
pev->angles.z = 0;
|
||||
pev->angles.x = 0;
|
||||
}
|
||||
|
||||
|
||||
void CMSqueakGrenade::SuperBounceTouch( edict_t *pOther )
|
||||
{
|
||||
float flpitch;
|
||||
|
||||
TraceResult tr = UTIL_GetGlobalTrace( );
|
||||
|
||||
// don't hit the guy that launched this grenade
|
||||
if ( pev->owner && (pOther == pev->owner) )
|
||||
return;
|
||||
|
||||
// at least until we've bounced once
|
||||
pev->owner = NULL;
|
||||
|
||||
pev->angles.x = 0;
|
||||
pev->angles.z = 0;
|
||||
|
||||
// avoid bouncing too much
|
||||
if (m_flNextHit > gpGlobals->time)
|
||||
return;
|
||||
|
||||
// higher pitch as squeeker gets closer to detonation time
|
||||
flpitch = 155.0 - 60.0 * ((m_flDie - gpGlobals->time) / SQUEEK_DETONATE_DELAY);
|
||||
|
||||
if ( pOther->v.takedamage && m_flNextAttack < gpGlobals->time )
|
||||
{
|
||||
// attack!
|
||||
|
||||
// make sure it's me who has touched them
|
||||
if (tr.pHit == pOther)
|
||||
{
|
||||
// and it's not another squeakgrenade
|
||||
if (tr.pHit->v.modelindex != pev->modelindex)
|
||||
{
|
||||
// ALERT( at_console, "hit enemy\n");
|
||||
ClearMultiDamage( );
|
||||
|
||||
if (UTIL_IsPlayer(pOther))
|
||||
UTIL_TraceAttack(pOther, pev, gSkillData.snarkDmgBite, gpGlobals->v_forward, &tr, DMG_SLASH );
|
||||
else if (pOther->v.euser4 != NULL)
|
||||
{
|
||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther));
|
||||
pMonster->TraceAttack(pev, gSkillData.snarkDmgBite, gpGlobals->v_forward, &tr, DMG_SLASH );
|
||||
}
|
||||
|
||||
ApplyMultiDamage( pev, pev );
|
||||
|
||||
pev->dmg += gSkillData.snarkDmgPop; // add more explosion damage
|
||||
// m_flDie += 2.0; // add more life
|
||||
|
||||
// make bite sound
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "squeek/sqk_deploy1.wav", 1.0, ATTN_NORM, 0, (int)flpitch);
|
||||
m_flNextAttack = gpGlobals->time + 0.5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ALERT( at_console, "been hit\n");
|
||||
}
|
||||
}
|
||||
|
||||
m_flNextHit = gpGlobals->time + 0.1;
|
||||
m_flNextHunt = gpGlobals->time;
|
||||
|
||||
// in multiplayer, we limit how often snarks can make their bounce sounds to prevent overflows.
|
||||
if ( gpGlobals->time < m_flNextBounceSoundTime )
|
||||
{
|
||||
// too soon!
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(pev->flags & FL_ONGROUND))
|
||||
{
|
||||
// play bounce sound
|
||||
float flRndSound = RANDOM_FLOAT ( 0 , 1 );
|
||||
|
||||
if ( flRndSound <= 0.33 )
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt1.wav", 1, ATTN_NORM, 0, (int)flpitch);
|
||||
else if (flRndSound <= 0.66)
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt2.wav", 1, ATTN_NORM, 0, (int)flpitch);
|
||||
else
|
||||
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "squeek/sqk_hunt3.wav", 1, ATTN_NORM, 0, (int)flpitch);
|
||||
}
|
||||
|
||||
m_flNextBounceSoundTime = gpGlobals->time + 0.5;// half second.
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
470
src/dlls/subs.cpp
Normal file
470
src/dlls/subs.cpp
Normal file
@@ -0,0 +1,470 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
/*
|
||||
|
||||
===== subs.cpp ========================================================
|
||||
|
||||
frequently used global functions
|
||||
|
||||
*/
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "nodes.h"
|
||||
#include "doors.h"
|
||||
|
||||
extern CGraph WorldGraph;
|
||||
|
||||
extern BOOL FEntIsVisible(entvars_t* pev, entvars_t* pevTarget);
|
||||
|
||||
void Remove_Entity(edict_t *pEdict);
|
||||
|
||||
|
||||
// Landmark class
|
||||
void CMPointEntity :: Spawn( void )
|
||||
{
|
||||
pev->solid = SOLID_NOT;
|
||||
// UTIL_SetSize(pev, g_vecZero, g_vecZero);
|
||||
}
|
||||
|
||||
|
||||
// This updates global tables that need to know about entities being removed
|
||||
void CMBaseEntity::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
//jlb if ( pev->globalname )
|
||||
//jlb gGlobalState.EntitySetState( pev->globalname, GLOBAL_DEAD );
|
||||
}
|
||||
|
||||
// Convenient way to delay removing oneself
|
||||
void CMBaseEntity :: 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));
|
||||
Remove_Entity(ENT(pev));
|
||||
}
|
||||
|
||||
|
||||
// Convenient way to explicitly do nothing (passed to functions that require a method)
|
||||
void CMBaseEntity :: SUB_DoNothing( void )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CMBaseDelay :: 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
|
||||
{
|
||||
CMBaseEntity::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 CMBaseEntity :: SUB_UseTargets( edict_t *pActivator, USE_TYPE useType, float value )
|
||||
{
|
||||
//
|
||||
// fire targets
|
||||
//
|
||||
if (!FStringNull(pev->target))
|
||||
{
|
||||
FireTargets( STRING(pev->target), pActivator, this->edict(), useType, value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FireTargets( const char *targetName, edict_t *pActivator, edict_t *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;
|
||||
|
||||
CMBaseEntity *pTarget = CMBaseEntity::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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMBaseDelay :: SUB_UseTargets( edict_t *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
|
||||
CMBaseDelay *pTemp = CreateClassPtr( (CMBaseDelay *)NULL);
|
||||
|
||||
if (pTemp == NULL)
|
||||
return;
|
||||
|
||||
pTemp->pev->classname = MAKE_STRING("DelayedUse");
|
||||
|
||||
pTemp->pev->nextthink = gpGlobals->time + m_flDelay;
|
||||
|
||||
pTemp->SetThink( 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 && UTIL_IsPlayer(pActivator) ) // If a player activates, then save it
|
||||
{
|
||||
pTemp->pev->owner = pActivator;
|
||||
}
|
||||
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( CMBaseEntity::Instance(pentKillTarget)->edict() );
|
||||
|
||||
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->edict(), useType, value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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 CMBaseDelay::DelayThink( void )
|
||||
{
|
||||
edict_t *pActivator = NULL;
|
||||
|
||||
if ( pev->owner != NULL ) // A player activated this on delay
|
||||
{
|
||||
pActivator = ENT(pev->owner);
|
||||
}
|
||||
// The use type is cached (and stashed) in pev->button
|
||||
SUB_UseTargets( pActivator, (USE_TYPE)pev->button, 0 );
|
||||
// REMOVE_ENTITY(ENT(pev));
|
||||
Remove_Entity(ENT(pev));
|
||||
}
|
||||
|
||||
|
||||
void CMBaseToggle::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
|
||||
CMBaseDelay::KeyValue( pkvd );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
LinearMove
|
||||
|
||||
calculate pev->velocity and pev->nextthink to reach vecDest from
|
||||
pev->origin traveling at flSpeed
|
||||
===============
|
||||
*/
|
||||
void CMBaseToggle :: 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( 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 CMBaseToggle :: LinearMoveDone( void )
|
||||
{
|
||||
UTIL_SetOrigin(pev, m_vecFinalDest);
|
||||
pev->velocity = g_vecZero;
|
||||
pev->nextthink = -1;
|
||||
if ( m_pfnCallWhenMoveDone )
|
||||
(this->*m_pfnCallWhenMoveDone)();
|
||||
}
|
||||
|
||||
BOOL CMBaseToggle :: IsLockedByMaster( void )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
AngularMove
|
||||
|
||||
calculate pev->velocity and pev->nextthink to reach vecDest from
|
||||
pev->origin traveling at flSpeed
|
||||
Just like LinearMove, but rotational.
|
||||
===============
|
||||
*/
|
||||
void CMBaseToggle :: 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( 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 CMBaseToggle :: AngularMoveDone( void )
|
||||
{
|
||||
pev->angles = m_vecFinalAngle;
|
||||
pev->avelocity = g_vecZero;
|
||||
pev->nextthink = -1;
|
||||
if ( m_pfnCallWhenMoveDone )
|
||||
(this->*m_pfnCallWhenMoveDone)();
|
||||
}
|
||||
|
||||
|
||||
float CMBaseToggle :: 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 CMBaseToggle :: 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 CMBaseToggle :: 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;
|
||||
}
|
||||
|
||||
|
||||
1419
src/dlls/talkmonster.cpp
Normal file
1419
src/dlls/talkmonster.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1963
src/dlls/util.cpp
Normal file
1963
src/dlls/util.cpp
Normal file
File diff suppressed because it is too large
Load Diff
539
src/dlls/util.h
Normal file
539
src/dlls/util.h
Normal file
@@ -0,0 +1,539 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// Misc utility code
|
||||
//
|
||||
#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;
|
||||
extern cvar_t *g_psv_gravity;
|
||||
|
||||
// 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)
|
||||
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
#if _DEBUG
|
||||
if ( !pent )
|
||||
ALERT( at_error, "Bad ent in OFFSET()\n" );
|
||||
#endif
|
||||
return (*g_engfuncs.pfnEntOffsetOfPEntity)(pent);
|
||||
}
|
||||
inline EOFFSET OFFSET(entvars_t *pev)
|
||||
{
|
||||
#if _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); }
|
||||
|
||||
// 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 edict_t *UTIL_FindEntityInSphere(edict_t *pStartEntity, const Vector &vecCenter, float flRadius);
|
||||
extern edict_t *UTIL_FindEntityByString(edict_t *pStartEntity, const char *szKeyword, const char *szValue );
|
||||
extern edict_t *UTIL_FindEntityByClassname(edict_t *pStartEntity, const char *szName );
|
||||
extern edict_t *UTIL_FindEntityByTargetname(edict_t *pStartEntity, const char *szName );
|
||||
extern edict_t *UTIL_FindEntityGeneric(const char *szName, Vector &vecSrc, float flRadius );
|
||||
|
||||
// returns a edict_t pointer to a player by index. Only returns if the player is spawned and connected
|
||||
// otherwise returns NULL
|
||||
// Index is 1 based
|
||||
extern edict_t *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( edict_t **pList, int listMax, const Vector ¢er, float radius );
|
||||
extern int UTIL_EntitiesInBox( edict_t **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 ¢er, float amplitude, float frequency, float duration, float radius );
|
||||
extern void UTIL_ScreenShakeAll ( const Vector ¢er, float amplitude, float frequency, float duration );
|
||||
extern void UTIL_ShowMessage ( const char *pString, edict_t *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 ( edict_t *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 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( edict_t *pEntity );
|
||||
extern BOOL UTIL_IsValidEntity( edict_t *pent );
|
||||
|
||||
// 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 );
|
||||
|
||||
// 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 );
|
||||
}
|
||||
|
||||
// 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, edict_t *pEntity );
|
||||
extern void UTIL_SayTextAll( const char *pText, edict_t *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( edict_t *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 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
|
||||
|
||||
#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
|
||||
|
||||
#define VEC_HULL_MIN Vector(-16, -16, -36)
|
||||
#define VEC_HULL_MAX Vector( 16, 16, 36)
|
||||
#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, 28 )
|
||||
|
||||
#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_HLTV 50
|
||||
|
||||
// prxoy director stuff
|
||||
#define DRC_EVENT 3 // informs the dircetor about ann important game event
|
||||
|
||||
#define DRC_FLAG_PRIO_MASK 0x0F // priorities between 0 and 15 (15 most important)
|
||||
#define DRC_FLAG_DRAMATIC (1<<5)
|
||||
|
||||
// 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);
|
||||
|
||||
// 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 < 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 );
|
||||
|
||||
Vector VecBModelOrigin( entvars_t* pevBModel );
|
||||
bool UTIL_IsAlive(entvars_t *pev);
|
||||
bool UTIL_IsAlive(edict_t *pEdict);
|
||||
bool UTIL_IsPlayer(edict_t *pEdict);
|
||||
Vector UTIL_BodyTarget(edict_t *pEdict, Vector posSrc);
|
||||
bool UTIL_FVisible(edict_t *pEdict, edict_t *pLooker);
|
||||
bool UTIL_FVisible ( const Vector &vecOrigin, edict_t *pLooker );
|
||||
bool UTIL_FInViewCone ( edict_t *pEntity, edict_t *pLooker, float fov );
|
||||
bool UTIL_FInViewCone ( Vector *pOrigin, edict_t *pLooker, float fov );
|
||||
int UTIL_TakeDamage( edict_t *pEdict, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
|
||||
int UTIL_TakeHealth (edict_t *pEdict, float flHealth, int bitsDamageType);
|
||||
void UTIL_TraceBleed( edict_t *pEdict, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType );
|
||||
void UTIL_TraceAttack( edict_t *pEdict, entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
|
||||
int UTIL_IsMoving(edict_t *pEdict);
|
||||
Vector UTIL_EyePosition(edict_t *pEdict);
|
||||
Vector UTIL_Center(edict_t *pEdict);
|
||||
edict_t *UTIL_GetNextTarget( edict_t *pEntity );
|
||||
edict_t *UTIL_FindNearestPlayer(edict_t *pEdict, float m_flFieldOfView);
|
||||
bool UTIL_IsBSPModel( edict_t *pent );
|
||||
112
src/dlls/vector.h
Normal file
112
src/dlls/vector.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 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) { }
|
||||
inline Vector2D(float X, float Y) { 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
|
||||
{
|
||||
Vector2D vec2;
|
||||
|
||||
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) { }
|
||||
inline Vector(float X, float Y, float Z) { 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 = v.x; y = v.y; z = v.z; }
|
||||
inline Vector(float rgfl[3]) { 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
|
||||
218
src/dlls/weapons.cpp
Normal file
218
src/dlls/weapons.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
/*
|
||||
|
||||
===== weapons.cpp ========================================================
|
||||
|
||||
functions governing the selection/use of weapons for players
|
||||
|
||||
*/
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "weapons.h"
|
||||
#include "nodes.h"
|
||||
#include "decals.h"
|
||||
|
||||
extern CGraph WorldGraph;
|
||||
|
||||
MULTIDAMAGE gMultiDamage;
|
||||
|
||||
#define TRACER_FREQ 4 // Tracers fire every fourth bullet
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
MULTI-DAMAGE
|
||||
|
||||
Collects multiple small damages into a single damage
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//
|
||||
// ClearMultiDamage - resets the global multi damage accumulator
|
||||
//
|
||||
void ClearMultiDamage(void)
|
||||
{
|
||||
gMultiDamage.pEntity = NULL;
|
||||
gMultiDamage.amount = 0;
|
||||
gMultiDamage.type = 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ApplyMultiDamage - inflicts contents of global multi damage register on gMultiDamage.pEntity
|
||||
//
|
||||
// GLOBALS USED:
|
||||
// gMultiDamage
|
||||
|
||||
void ApplyMultiDamage(entvars_t *pevInflictor, entvars_t *pevAttacker )
|
||||
{
|
||||
Vector vecSpot1;//where blood comes from
|
||||
Vector vecDir;//direction blood should go
|
||||
TraceResult tr;
|
||||
|
||||
if ( !gMultiDamage.pEntity )
|
||||
return;
|
||||
|
||||
if (UTIL_IsPlayer(gMultiDamage.pEntity))
|
||||
UTIL_TakeDamage(gMultiDamage.pEntity, pevInflictor, pevAttacker, gMultiDamage.amount, gMultiDamage.type );
|
||||
else if (gMultiDamage.pEntity->v.euser4 != NULL)
|
||||
{
|
||||
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(gMultiDamage.pEntity));
|
||||
pMonster->TakeDamage(pevInflictor, pevAttacker, gMultiDamage.amount, gMultiDamage.type );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GLOBALS USED:
|
||||
// gMultiDamage
|
||||
|
||||
void AddMultiDamage( entvars_t *pevInflictor, edict_t *pEntity, float flDamage, int bitsDamageType)
|
||||
{
|
||||
if ( !pEntity )
|
||||
return;
|
||||
|
||||
gMultiDamage.type |= bitsDamageType;
|
||||
|
||||
if ( pEntity != gMultiDamage.pEntity )
|
||||
{
|
||||
ApplyMultiDamage(pevInflictor,pevInflictor); // UNDONE: wrong attacker!
|
||||
gMultiDamage.pEntity = pEntity;
|
||||
gMultiDamage.amount = 0;
|
||||
}
|
||||
|
||||
gMultiDamage.amount += flDamage;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SpawnBlood
|
||||
================
|
||||
*/
|
||||
void SpawnBlood(Vector vecSpot, int bloodColor, float flDamage)
|
||||
{
|
||||
UTIL_BloodDrips( vecSpot, g_vecAttackDir, bloodColor, (int)flDamage );
|
||||
}
|
||||
|
||||
|
||||
int DamageDecal( CMBaseEntity *pEntity, int bitsDamageType )
|
||||
{
|
||||
if ( !pEntity )
|
||||
return (DECAL_GUNSHOT1 + RANDOM_LONG(0,4));
|
||||
|
||||
return pEntity->DamageDecal( bitsDamageType );
|
||||
}
|
||||
|
||||
void DecalGunshot( TraceResult *pTrace, int iBulletType )
|
||||
{
|
||||
// Is the entity valid
|
||||
if ( !UTIL_IsValidEntity( pTrace->pHit ) )
|
||||
return;
|
||||
|
||||
if ( VARS(pTrace->pHit)->solid == SOLID_BSP || VARS(pTrace->pHit)->movetype == MOVETYPE_PUSHSTEP )
|
||||
{
|
||||
CMBaseEntity *pEntity = NULL;
|
||||
// Decal the wall with a gunshot
|
||||
if ( !FNullEnt(pTrace->pHit) )
|
||||
pEntity = CMBaseEntity::Instance(pTrace->pHit);
|
||||
|
||||
switch( iBulletType )
|
||||
{
|
||||
case BULLET_PLAYER_9MM:
|
||||
case BULLET_MONSTER_9MM:
|
||||
case BULLET_PLAYER_MP5:
|
||||
case BULLET_MONSTER_MP5:
|
||||
case BULLET_PLAYER_BUCKSHOT:
|
||||
case BULLET_PLAYER_357:
|
||||
default:
|
||||
// smoke and decal
|
||||
UTIL_GunshotDecalTrace( pTrace, DamageDecal( pEntity, DMG_BULLET ) );
|
||||
break;
|
||||
case BULLET_MONSTER_12MM:
|
||||
// smoke and decal
|
||||
UTIL_GunshotDecalTrace( pTrace, DamageDecal( pEntity, DMG_BULLET ) );
|
||||
break;
|
||||
case BULLET_PLAYER_CROWBAR:
|
||||
// wall decal
|
||||
UTIL_DecalTrace( pTrace, DamageDecal( pEntity, DMG_CLUB ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// EjectBrass - tosses a brass shell from passed origin at passed velocity
|
||||
//
|
||||
void EjectBrass ( const Vector &vecOrigin, const Vector &vecVelocity, float rotation, int model, int soundtype )
|
||||
{
|
||||
// FIX: when the player shoots, their gun isn't in the same position as it is on the model other players see.
|
||||
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecOrigin );
|
||||
WRITE_BYTE( TE_MODEL);
|
||||
WRITE_COORD( vecOrigin.x);
|
||||
WRITE_COORD( vecOrigin.y);
|
||||
WRITE_COORD( vecOrigin.z);
|
||||
WRITE_COORD( vecVelocity.x);
|
||||
WRITE_COORD( vecVelocity.y);
|
||||
WRITE_COORD( vecVelocity.z);
|
||||
WRITE_ANGLE( rotation );
|
||||
WRITE_SHORT( model );
|
||||
WRITE_BYTE ( soundtype);
|
||||
WRITE_BYTE ( 25 );// 2.5 seconds
|
||||
MESSAGE_END();
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// UNDONE: This is no longer used?
|
||||
void ExplodeModel( const Vector &vecOrigin, float speed, int model, int count )
|
||||
{
|
||||
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecOrigin );
|
||||
WRITE_BYTE ( TE_EXPLODEMODEL );
|
||||
WRITE_COORD( vecOrigin.x );
|
||||
WRITE_COORD( vecOrigin.y );
|
||||
WRITE_COORD( vecOrigin.z );
|
||||
WRITE_COORD( speed );
|
||||
WRITE_SHORT( model );
|
||||
WRITE_SHORT( count );
|
||||
WRITE_BYTE ( 15 );// 1.5 seconds
|
||||
MESSAGE_END();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
BOOL CanAttack( float attack_time, float curtime, BOOL isPredicted )
|
||||
{
|
||||
#if defined( CLIENT_WEAPONS )
|
||||
if ( !isPredicted )
|
||||
#else
|
||||
if ( 1 )
|
||||
#endif
|
||||
{
|
||||
return ( attack_time <= curtime ) ? TRUE : FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( attack_time <= 0.0 ) ? TRUE : FALSE;
|
||||
}
|
||||
}
|
||||
258
src/dlls/weapons.h
Normal file
258
src/dlls/weapons.h
Normal file
@@ -0,0 +1,258 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef WEAPONS_H
|
||||
#define WEAPONS_H
|
||||
|
||||
#include "effects.h"
|
||||
|
||||
// Contact Grenade / Timed grenade / Satchel Charge
|
||||
class CMGrenade : public CMBaseMonster
|
||||
{
|
||||
public:
|
||||
void Spawn( void );
|
||||
|
||||
typedef enum { SATCHEL_DETONATE = 0, SATCHEL_RELEASE } SATCHELCODE;
|
||||
|
||||
static CMGrenade *ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time );
|
||||
static CMGrenade *ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity );
|
||||
static CMGrenade *ShootSatchelCharge( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity );
|
||||
|
||||
void Explode( Vector vecSrc, Vector vecAim );
|
||||
void Explode( TraceResult *pTrace, int bitsDamageType );
|
||||
void EXPORT Smoke( void );
|
||||
|
||||
void EXPORT BounceTouch( edict_t *pOther );
|
||||
void EXPORT SlideTouch( edict_t *pOther );
|
||||
void EXPORT ExplodeTouch( edict_t *pOther );
|
||||
void EXPORT DangerSoundThink( void );
|
||||
void EXPORT PreDetonate( void );
|
||||
void EXPORT Detonate( void );
|
||||
void EXPORT DetonateUse( edict_t *pActivator, edict_t *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 32
|
||||
|
||||
|
||||
#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;
|
||||
|
||||
extern void ClearMultiDamage(void);
|
||||
extern void ApplyMultiDamage(entvars_t* pevInflictor, entvars_t* pevAttacker );
|
||||
extern void AddMultiDamage( entvars_t *pevInflictor, edict_t *pEntity, float flDamage, int bitsDamageType);
|
||||
|
||||
extern void DecalGunshot( TraceResult *pTrace, int iBulletType );
|
||||
extern void SpawnBlood(Vector vecSpot, int bloodColor, float flDamage);
|
||||
extern int DamageDecal( CMBaseEntity *pEntity, int bitsDamageType );
|
||||
extern void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
edict_t *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 )
|
||||
|
||||
#endif // WEAPONS_H
|
||||
316
src/dlls/zombie.cpp
Normal file
316
src/dlls/zombie.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This source code contains proprietary and confidential information of
|
||||
* Valve LLC and its suppliers. Access to this code is restricted to
|
||||
* persons who have executed a written SDK license with Valve. Any access,
|
||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||
*
|
||||
****/
|
||||
//=========================================================
|
||||
// Zombie
|
||||
//=========================================================
|
||||
|
||||
// UNDONE: Don't flinch every time you get hit
|
||||
|
||||
#include "extdll.h"
|
||||
#include "util.h"
|
||||
#include "cmbase.h"
|
||||
#include "cmbasemonster.h"
|
||||
#include "monsters.h"
|
||||
#include "schedule.h"
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Monster's Anim Events Go Here
|
||||
//=========================================================
|
||||
#define ZOMBIE_AE_ATTACK_RIGHT 0x01
|
||||
#define ZOMBIE_AE_ATTACK_LEFT 0x02
|
||||
#define ZOMBIE_AE_ATTACK_BOTH 0x03
|
||||
|
||||
#define ZOMBIE_FLINCH_DELAY 2 // at most one flinch every n secs
|
||||
|
||||
|
||||
const char *CMZombie::pAttackHitSounds[] =
|
||||
{
|
||||
"zombie/claw_strike1.wav",
|
||||
"zombie/claw_strike2.wav",
|
||||
"zombie/claw_strike3.wav",
|
||||
};
|
||||
|
||||
const char *CMZombie::pAttackMissSounds[] =
|
||||
{
|
||||
"zombie/claw_miss1.wav",
|
||||
"zombie/claw_miss2.wav",
|
||||
};
|
||||
|
||||
const char *CMZombie::pAttackSounds[] =
|
||||
{
|
||||
"zombie/zo_attack1.wav",
|
||||
"zombie/zo_attack2.wav",
|
||||
};
|
||||
|
||||
const char *CMZombie::pIdleSounds[] =
|
||||
{
|
||||
"zombie/zo_idle1.wav",
|
||||
"zombie/zo_idle2.wav",
|
||||
"zombie/zo_idle3.wav",
|
||||
"zombie/zo_idle4.wav",
|
||||
};
|
||||
|
||||
const char *CMZombie::pAlertSounds[] =
|
||||
{
|
||||
"zombie/zo_alert10.wav",
|
||||
"zombie/zo_alert20.wav",
|
||||
"zombie/zo_alert30.wav",
|
||||
};
|
||||
|
||||
const char *CMZombie::pPainSounds[] =
|
||||
{
|
||||
"zombie/zo_pain1.wav",
|
||||
"zombie/zo_pain2.wav",
|
||||
};
|
||||
|
||||
//=========================================================
|
||||
// Classify - indicates this monster's place in the
|
||||
// relationship table.
|
||||
//=========================================================
|
||||
int CMZombie :: Classify ( void )
|
||||
{
|
||||
return CLASS_ALIEN_MONSTER;
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// SetYawSpeed - allows each sequence to have a different
|
||||
// turn rate associated with it.
|
||||
//=========================================================
|
||||
void CMZombie :: SetYawSpeed ( void )
|
||||
{
|
||||
int ys;
|
||||
|
||||
ys = 120;
|
||||
|
||||
#if 0
|
||||
switch ( m_Activity )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
pev->yaw_speed = ys;
|
||||
}
|
||||
|
||||
int CMZombie :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
||||
{
|
||||
// Take 30% damage from bullets
|
||||
if ( bitsDamageType == DMG_BULLET )
|
||||
{
|
||||
Vector vecDir = pev->origin - (pevInflictor->absmin + pevInflictor->absmax) * 0.5;
|
||||
vecDir = vecDir.Normalize();
|
||||
float flForce = DamageForce( flDamage );
|
||||
pev->velocity = pev->velocity + vecDir * flForce;
|
||||
flDamage *= 0.3;
|
||||
}
|
||||
|
||||
// HACK HACK -- until we fix this.
|
||||
if ( IsAlive() )
|
||||
PainSound();
|
||||
return CMBaseMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
|
||||
}
|
||||
|
||||
void CMZombie :: PainSound( void )
|
||||
{
|
||||
int pitch = 95 + RANDOM_LONG(0,9);
|
||||
|
||||
if (RANDOM_LONG(0,5) < 2)
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pPainSounds[ RANDOM_LONG(0,ARRAYSIZE(pPainSounds)-1) ], 1.0, ATTN_NORM, 0, pitch );
|
||||
}
|
||||
|
||||
void CMZombie :: AlertSound( void )
|
||||
{
|
||||
int pitch = 95 + RANDOM_LONG(0,9);
|
||||
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pAlertSounds[ RANDOM_LONG(0,ARRAYSIZE(pAlertSounds)-1) ], 1.0, ATTN_NORM, 0, pitch );
|
||||
}
|
||||
|
||||
void CMZombie :: IdleSound( void )
|
||||
{
|
||||
int pitch = 95 + RANDOM_LONG(0,9);
|
||||
|
||||
// Play a random idle sound
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pIdleSounds[ RANDOM_LONG(0,ARRAYSIZE(pIdleSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) );
|
||||
}
|
||||
|
||||
void CMZombie :: AttackSound( void )
|
||||
{
|
||||
// Play a random attack sound
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_VOICE, pAttackSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) );
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// HandleAnimEvent - catches the monster-specific messages
|
||||
// that occur when tagged animation frames are played.
|
||||
//=========================================================
|
||||
void CMZombie :: HandleAnimEvent( MonsterEvent_t *pEvent )
|
||||
{
|
||||
switch( pEvent->event )
|
||||
{
|
||||
case ZOMBIE_AE_ATTACK_RIGHT:
|
||||
{
|
||||
// do stuff for this event.
|
||||
// ALERT( at_console, "Slash right!\n" );
|
||||
edict_t *pHurt = CheckTraceHullAttack( 70, gSkillData.zombieDmgOneSlash, DMG_SLASH );
|
||||
if ( pHurt )
|
||||
{
|
||||
if ( pHurt->v.flags & (FL_MONSTER|FL_CLIENT) )
|
||||
{
|
||||
pHurt->v.punchangle.z = -18;
|
||||
pHurt->v.punchangle.x = 5;
|
||||
pHurt->v.velocity = pHurt->v.velocity - gpGlobals->v_right * 100;
|
||||
}
|
||||
// Play a random attack hit sound
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) );
|
||||
}
|
||||
else // Play a random attack miss sound
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) );
|
||||
|
||||
if (RANDOM_LONG(0,1))
|
||||
AttackSound();
|
||||
}
|
||||
break;
|
||||
|
||||
case ZOMBIE_AE_ATTACK_LEFT:
|
||||
{
|
||||
// do stuff for this event.
|
||||
// ALERT( at_console, "Slash left!\n" );
|
||||
edict_t *pHurt = CheckTraceHullAttack( 70, gSkillData.zombieDmgOneSlash, DMG_SLASH );
|
||||
if ( pHurt )
|
||||
{
|
||||
if ( pHurt->v.flags & (FL_MONSTER|FL_CLIENT) )
|
||||
{
|
||||
pHurt->v.punchangle.z = 18;
|
||||
pHurt->v.punchangle.x = 5;
|
||||
pHurt->v.velocity = pHurt->v.velocity + gpGlobals->v_right * 100;
|
||||
}
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) );
|
||||
}
|
||||
else
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) );
|
||||
|
||||
if (RANDOM_LONG(0,1))
|
||||
AttackSound();
|
||||
}
|
||||
break;
|
||||
|
||||
case ZOMBIE_AE_ATTACK_BOTH:
|
||||
{
|
||||
// do stuff for this event.
|
||||
edict_t *pHurt = CheckTraceHullAttack( 70, gSkillData.zombieDmgBothSlash, DMG_SLASH );
|
||||
if ( pHurt )
|
||||
{
|
||||
if ( pHurt->v.flags & (FL_MONSTER|FL_CLIENT) )
|
||||
{
|
||||
pHurt->v.punchangle.x = 5;
|
||||
pHurt->v.velocity = pHurt->v.velocity + gpGlobals->v_forward * -100;
|
||||
}
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackHitSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackHitSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) );
|
||||
}
|
||||
else
|
||||
EMIT_SOUND_DYN ( ENT(pev), CHAN_WEAPON, pAttackMissSounds[ RANDOM_LONG(0,ARRAYSIZE(pAttackMissSounds)-1) ], 1.0, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5) );
|
||||
|
||||
if (RANDOM_LONG(0,1))
|
||||
AttackSound();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CMBaseMonster::HandleAnimEvent( pEvent );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Spawn
|
||||
//=========================================================
|
||||
void CMZombie :: Spawn()
|
||||
{
|
||||
Precache( );
|
||||
|
||||
SET_MODEL(ENT(pev), "models/zombie.mdl");
|
||||
UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX );
|
||||
|
||||
pev->solid = SOLID_SLIDEBOX;
|
||||
pev->movetype = MOVETYPE_STEP;
|
||||
m_bloodColor = BLOOD_COLOR_GREEN;
|
||||
pev->health = gSkillData.zombieHealth;
|
||||
pev->view_ofs = VEC_VIEW;// position of the eyes relative to monster's origin.
|
||||
m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
|
||||
m_MonsterState = MONSTERSTATE_NONE;
|
||||
m_afCapability = bits_CAP_DOORS_GROUP;
|
||||
|
||||
MonsterInit();
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// Precache - precaches all resources this monster needs
|
||||
//=========================================================
|
||||
void CMZombie :: Precache()
|
||||
{
|
||||
int i;
|
||||
|
||||
PRECACHE_MODEL("models/zombie.mdl");
|
||||
|
||||
for ( i = 0; i < ARRAYSIZE( pAttackHitSounds ); i++ )
|
||||
PRECACHE_SOUND((char *)pAttackHitSounds[i]);
|
||||
|
||||
for ( i = 0; i < ARRAYSIZE( pAttackMissSounds ); i++ )
|
||||
PRECACHE_SOUND((char *)pAttackMissSounds[i]);
|
||||
|
||||
for ( i = 0; i < ARRAYSIZE( pAttackSounds ); i++ )
|
||||
PRECACHE_SOUND((char *)pAttackSounds[i]);
|
||||
|
||||
for ( i = 0; i < ARRAYSIZE( pIdleSounds ); i++ )
|
||||
PRECACHE_SOUND((char *)pIdleSounds[i]);
|
||||
|
||||
for ( i = 0; i < ARRAYSIZE( pAlertSounds ); i++ )
|
||||
PRECACHE_SOUND((char *)pAlertSounds[i]);
|
||||
|
||||
for ( i = 0; i < ARRAYSIZE( pPainSounds ); i++ )
|
||||
PRECACHE_SOUND((char *)pPainSounds[i]);
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
// AI Schedules Specific to this monster
|
||||
//=========================================================
|
||||
|
||||
|
||||
|
||||
int CMZombie::IgnoreConditions ( void )
|
||||
{
|
||||
int iIgnore = CMBaseMonster::IgnoreConditions();
|
||||
|
||||
if ((m_Activity == ACT_MELEE_ATTACK1) || (m_Activity == ACT_MELEE_ATTACK1))
|
||||
{
|
||||
#if 0
|
||||
if (pev->health < 20)
|
||||
iIgnore |= (bits_COND_LIGHT_DAMAGE|bits_COND_HEAVY_DAMAGE);
|
||||
else
|
||||
#endif
|
||||
if (m_flNextFlinch >= gpGlobals->time)
|
||||
iIgnore |= (bits_COND_LIGHT_DAMAGE|bits_COND_HEAVY_DAMAGE);
|
||||
}
|
||||
|
||||
if ((m_Activity == ACT_SMALL_FLINCH) || (m_Activity == ACT_BIG_FLINCH))
|
||||
{
|
||||
if (m_flNextFlinch < gpGlobals->time)
|
||||
m_flNextFlinch = gpGlobals->time + ZOMBIE_FLINCH_DELAY;
|
||||
}
|
||||
|
||||
return iIgnore;
|
||||
|
||||
}
|
||||
102
src/engine/custom.h
Normal file
102
src/engine/custom.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 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.
|
||||
*
|
||||
****/
|
||||
// Customization.h
|
||||
|
||||
#ifndef CUSTOM_H
|
||||
#define CUSTOM_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "const.h"
|
||||
|
||||
#define MAX_QPATH 64 // Must match value in quakedefs.h
|
||||
|
||||
/////////////////
|
||||
// Customization
|
||||
// passed to pfnPlayerCustomization
|
||||
// For automatic downloading.
|
||||
typedef enum
|
||||
{
|
||||
t_sound = 0,
|
||||
t_skin,
|
||||
t_model,
|
||||
t_decal,
|
||||
t_generic,
|
||||
t_eventscript
|
||||
} resourcetype_t;
|
||||
|
||||
// Fake type for world
|
||||
#define t_world 6
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int size;
|
||||
} _resourceinfo_t;
|
||||
|
||||
typedef struct resourceinfo_s
|
||||
{
|
||||
_resourceinfo_t info[ 7 ];
|
||||
} resourceinfo_t;
|
||||
|
||||
#define RES_FATALIFMISSING (1<<0) // Disconnect if we can't get this file.
|
||||
#define RES_WASMISSING (1<<1) // Do we have the file locally, did we get it ok?
|
||||
#define RES_CUSTOM (1<<2) // Is this resource one that corresponds to another player's customization
|
||||
// or is it a server startup resource.
|
||||
#define RES_REQUESTED (1<<3) // Already requested a download of this one
|
||||
#define RES_PRECACHED (1<<4) // Already precached
|
||||
|
||||
#include "crc.h"
|
||||
|
||||
typedef struct resource_s
|
||||
{
|
||||
char szFileName[MAX_QPATH]; // File name to download/precache.
|
||||
resourcetype_t type; // t_sound, t_skin, t_model, t_decal.
|
||||
int nIndex; // For t_decals
|
||||
int nDownloadSize; // Size in Bytes if this must be downloaded.
|
||||
unsigned char ucFlags;
|
||||
|
||||
// For handling client to client resource propagation
|
||||
unsigned char rgucMD5_hash[16]; // To determine if we already have it.
|
||||
unsigned char playernum; // Which player index this resource is associated with, if it's a custom resource.
|
||||
|
||||
unsigned char rguc_reserved[ 32 ]; // For future expansion
|
||||
struct resource_s *pNext; // Next in chain.
|
||||
struct resource_s *pPrev;
|
||||
} resource_t;
|
||||
|
||||
typedef struct customization_s
|
||||
{
|
||||
qboolean bInUse; // Is this customization in use;
|
||||
resource_t resource; // The resource_t for this customization
|
||||
qboolean bTranslated; // Has the raw data been translated into a useable format?
|
||||
// (e.g., raw decal .wad make into texture_t *)
|
||||
int nUserData1; // Customization specific data
|
||||
int nUserData2; // Customization specific data
|
||||
void *pInfo; // Buffer that holds the data structure that references the data (e.g., the cachewad_t)
|
||||
void *pBuffer; // Buffer that holds the data for the customization (the raw .wad data)
|
||||
struct customization_s *pNext; // Next in chain
|
||||
} customization_t;
|
||||
|
||||
#define FCUST_FROMHPAK ( 1<<0 )
|
||||
#define FCUST_WIPEDATA ( 1<<1 )
|
||||
#define FCUST_IGNOREINIT ( 1<<2 )
|
||||
|
||||
void COM_ClearCustomizationList( struct customization_s *pHead, qboolean bCleanDecals);
|
||||
qboolean COM_CreateCustomization( struct customization_s *pListHead, struct resource_s *pResource, int playernumber, int flags,
|
||||
struct customization_s **pCustomization, int *nLumps );
|
||||
int COM_SizeofResourceList ( struct resource_s *pList, struct resourceinfo_s *ri );
|
||||
|
||||
#endif // CUSTOM_H
|
||||
38
src/engine/customentity.h
Normal file
38
src/engine/customentity.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef CUSTOMENTITY_H
|
||||
#define CUSTOMENTITY_H
|
||||
|
||||
// Custom Entities
|
||||
|
||||
// Start/End Entity is encoded as 12 bits of entity index, and 4 bits of attachment (4:12)
|
||||
#define BEAMENT_ENTITY(x) ((x)&0xFFF)
|
||||
#define BEAMENT_ATTACHMENT(x) (((x)>>12)&0xF)
|
||||
|
||||
// Beam types, encoded as a byte
|
||||
enum
|
||||
{
|
||||
BEAM_POINTS = 0,
|
||||
BEAM_ENTPOINT,
|
||||
BEAM_ENTS,
|
||||
BEAM_HOSE,
|
||||
};
|
||||
|
||||
#define BEAM_FSINE 0x10
|
||||
#define BEAM_FSOLID 0x20
|
||||
#define BEAM_FSHADEIN 0x40
|
||||
#define BEAM_FSHADEOUT 0x80
|
||||
|
||||
#endif //CUSTOMENTITY_H
|
||||
29
src/engine/edict.h
Normal file
29
src/engine/edict.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#if !defined EDICT_H
|
||||
#define EDICT_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
#define MAX_ENT_LEAFS 48
|
||||
|
||||
#include "progdefs.h"
|
||||
|
||||
struct edict_s
|
||||
{
|
||||
qboolean free;
|
||||
int serialnumber;
|
||||
link_t area; // linked to a division node or leaf
|
||||
|
||||
int headnode; // -1 to use normal leaf check
|
||||
int num_leafs;
|
||||
short leafnums[MAX_ENT_LEAFS];
|
||||
|
||||
float freetime; // sv.time when the object was freed
|
||||
|
||||
void* pvPrivateData; // Alloced and freed by engine, used by DLLs
|
||||
|
||||
entvars_t v; // C exported fields from progs
|
||||
|
||||
// other fields from progs come immediately after
|
||||
};
|
||||
|
||||
#endif
|
||||
493
src/engine/eiface.h
Normal file
493
src/engine/eiface.h
Normal file
@@ -0,0 +1,493 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef EIFACE_H
|
||||
#define EIFACE_H
|
||||
|
||||
#ifdef HLDEMO_BUILD
|
||||
#define INTERFACE_VERSION 001
|
||||
#else // !HLDEMO_BUILD, i.e., regular version of HL
|
||||
#define INTERFACE_VERSION 140
|
||||
#endif // !HLDEMO_BUILD
|
||||
|
||||
#include <stdio.h>
|
||||
#include "custom.h"
|
||||
#include "cvardef.h"
|
||||
//
|
||||
// Defines entity interface between engine and DLLs.
|
||||
// This header file included by engine files and DLL files.
|
||||
//
|
||||
// Before including this header, DLLs must:
|
||||
// include progdefs.h
|
||||
// This is conveniently done for them in extdll.h
|
||||
//
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DLLEXPORT __stdcall
|
||||
#else
|
||||
#define DLLEXPORT /* */
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
at_notice,
|
||||
at_console, // same as at_notice, but forces a ConPrintf, not a message box
|
||||
at_aiconsole, // same as at_console, but only shown if developer level is 2!
|
||||
at_warning,
|
||||
at_error,
|
||||
at_logged // Server print to console ( only in multiplayer games ).
|
||||
} ALERT_TYPE;
|
||||
|
||||
// 4-22-98 JOHN: added for use in pfnClientPrintf
|
||||
typedef enum
|
||||
{
|
||||
print_console,
|
||||
print_center,
|
||||
print_chat,
|
||||
} PRINT_TYPE;
|
||||
|
||||
// For integrity checking of content on clients
|
||||
typedef enum
|
||||
{
|
||||
force_exactfile, // File on client must exactly match server's file
|
||||
force_model_samebounds, // For model files only, the geometry must fit in the same bbox
|
||||
force_model_specifybounds, // For model files only, the geometry must fit in the specified bbox
|
||||
} FORCE_TYPE;
|
||||
|
||||
// Returned by TraceLine
|
||||
typedef struct
|
||||
{
|
||||
int fAllSolid; // if true, plane is not valid
|
||||
int fStartSolid; // if true, the initial point was in a solid area
|
||||
int fInOpen;
|
||||
int fInWater;
|
||||
float flFraction; // time completed, 1.0 = didn't hit anything
|
||||
vec3_t vecEndPos; // final position
|
||||
float flPlaneDist;
|
||||
vec3_t vecPlaneNormal; // surface normal at impact
|
||||
edict_t *pHit; // entity the surface is on
|
||||
int iHitgroup; // 0 == generic, non zero is specific body part
|
||||
} TraceResult;
|
||||
|
||||
// CD audio status
|
||||
typedef struct
|
||||
{
|
||||
int fPlaying;// is sound playing right now?
|
||||
int fWasPlaying;// if not, CD is paused if WasPlaying is true.
|
||||
int fInitialized;
|
||||
int fEnabled;
|
||||
int fPlayLooping;
|
||||
float cdvolume;
|
||||
//BYTE remap[100];
|
||||
int fCDRom;
|
||||
int fPlayTrack;
|
||||
} CDStatus;
|
||||
|
||||
#include "../common/crc.h"
|
||||
|
||||
// Engine hands this to DLLs for functionality callbacks
|
||||
typedef struct enginefuncs_s
|
||||
{
|
||||
int (*pfnPrecacheModel) (char* s);
|
||||
int (*pfnPrecacheSound) (char* s);
|
||||
void (*pfnSetModel) (edict_t *e, const char *m);
|
||||
int (*pfnModelIndex) (const char *m);
|
||||
int (*pfnModelFrames) (int modelIndex);
|
||||
void (*pfnSetSize) (edict_t *e, const float *rgflMin, const float *rgflMax);
|
||||
void (*pfnChangeLevel) (char* s1, char* s2);
|
||||
void (*pfnGetSpawnParms) (edict_t *ent);
|
||||
void (*pfnSaveSpawnParms) (edict_t *ent);
|
||||
float (*pfnVecToYaw) (const float *rgflVector);
|
||||
void (*pfnVecToAngles) (const float *rgflVectorIn, float *rgflVectorOut);
|
||||
void (*pfnMoveToOrigin) (edict_t *ent, const float *pflGoal, float dist, int iMoveType);
|
||||
void (*pfnChangeYaw) (edict_t* ent);
|
||||
void (*pfnChangePitch) (edict_t* ent);
|
||||
edict_t* (*pfnFindEntityByString) (edict_t *pEdictStartSearchAfter, const char *pszField, const char *pszValue);
|
||||
int (*pfnGetEntityIllum) (edict_t* pEnt);
|
||||
edict_t* (*pfnFindEntityInSphere) (edict_t *pEdictStartSearchAfter, const float *org, float rad);
|
||||
edict_t* (*pfnFindClientInPVS) (edict_t *pEdict);
|
||||
edict_t* (*pfnEntitiesInPVS) (edict_t *pplayer);
|
||||
void (*pfnMakeVectors) (const float *rgflVector);
|
||||
void (*pfnAngleVectors) (const float *rgflVector, float *forward, float *right, float *up);
|
||||
edict_t* (*pfnCreateEntity) (void);
|
||||
void (*pfnRemoveEntity) (edict_t* e);
|
||||
edict_t* (*pfnCreateNamedEntity) (int className);
|
||||
void (*pfnMakeStatic) (edict_t *ent);
|
||||
int (*pfnEntIsOnFloor) (edict_t *e);
|
||||
int (*pfnDropToFloor) (edict_t* e);
|
||||
int (*pfnWalkMove) (edict_t *ent, float yaw, float dist, int iMode);
|
||||
void (*pfnSetOrigin) (edict_t *e, const float *rgflOrigin);
|
||||
void (*pfnEmitSound) (edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch);
|
||||
void (*pfnEmitAmbientSound) (edict_t *entity, float *pos, const char *samp, float vol, float attenuation, int fFlags, int pitch);
|
||||
void (*pfnTraceLine) (const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr);
|
||||
void (*pfnTraceToss) (edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr);
|
||||
int (*pfnTraceMonsterHull) (edict_t *pEdict, const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr);
|
||||
void (*pfnTraceHull) (const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr);
|
||||
void (*pfnTraceModel) (const float *v1, const float *v2, int hullNumber, edict_t *pent, TraceResult *ptr);
|
||||
const char *(*pfnTraceTexture) (edict_t *pTextureEntity, const float *v1, const float *v2 );
|
||||
void (*pfnTraceSphere) (const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr);
|
||||
void (*pfnGetAimVector) (edict_t* ent, float speed, float *rgflReturn);
|
||||
void (*pfnServerCommand) (char* str);
|
||||
void (*pfnServerExecute) (void);
|
||||
void (*pfnClientCommand) (edict_t* pEdict, char* szFmt, ...);
|
||||
void (*pfnParticleEffect) (const float *org, const float *dir, float color, float count);
|
||||
void (*pfnLightStyle) (int style, char* val);
|
||||
int (*pfnDecalIndex) (const char *name);
|
||||
int (*pfnPointContents) (const float *rgflVector);
|
||||
void (*pfnMessageBegin) (int msg_dest, int msg_type, const float *pOrigin, edict_t *ed);
|
||||
void (*pfnMessageEnd) (void);
|
||||
void (*pfnWriteByte) (int iValue);
|
||||
void (*pfnWriteChar) (int iValue);
|
||||
void (*pfnWriteShort) (int iValue);
|
||||
void (*pfnWriteLong) (int iValue);
|
||||
void (*pfnWriteAngle) (float flValue);
|
||||
void (*pfnWriteCoord) (float flValue);
|
||||
void (*pfnWriteString) (const char *sz);
|
||||
void (*pfnWriteEntity) (int iValue);
|
||||
void (*pfnCVarRegister) (cvar_t *pCvar);
|
||||
float (*pfnCVarGetFloat) (const char *szVarName);
|
||||
const char* (*pfnCVarGetString) (const char *szVarName);
|
||||
void (*pfnCVarSetFloat) (const char *szVarName, float flValue);
|
||||
void (*pfnCVarSetString) (const char *szVarName, const char *szValue);
|
||||
void (*pfnAlertMessage) (ALERT_TYPE atype, char *szFmt, ...);
|
||||
void (*pfnEngineFprintf) (FILE *pfile, char *szFmt, ...);
|
||||
void* (*pfnPvAllocEntPrivateData) (edict_t *pEdict, long cb);
|
||||
void* (*pfnPvEntPrivateData) (edict_t *pEdict);
|
||||
void (*pfnFreeEntPrivateData) (edict_t *pEdict);
|
||||
const char* (*pfnSzFromIndex) (int iString);
|
||||
int (*pfnAllocString) (const char *szValue);
|
||||
struct entvars_s* (*pfnGetVarsOfEnt) (edict_t *pEdict);
|
||||
edict_t* (*pfnPEntityOfEntOffset) (int iEntOffset);
|
||||
int (*pfnEntOffsetOfPEntity) (const edict_t *pEdict);
|
||||
int (*pfnIndexOfEdict) (const edict_t *pEdict);
|
||||
edict_t* (*pfnPEntityOfEntIndex) (int iEntIndex);
|
||||
edict_t* (*pfnFindEntityByVars) (struct entvars_s* pvars);
|
||||
void* (*pfnGetModelPtr) (edict_t* pEdict);
|
||||
int (*pfnRegUserMsg) (const char *pszName, int iSize);
|
||||
void (*pfnAnimationAutomove) (const edict_t* pEdict, float flTime);
|
||||
void (*pfnGetBonePosition) (const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles );
|
||||
unsigned long (*pfnFunctionFromName) ( const char *pName );
|
||||
const char *(*pfnNameForFunction) ( unsigned long function );
|
||||
void (*pfnClientPrintf) ( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg ); // JOHN: engine callbacks so game DLL can print messages to individual clients
|
||||
void (*pfnServerPrint) ( const char *szMsg );
|
||||
const char *(*pfnCmd_Args) ( void ); // these 3 added
|
||||
const char *(*pfnCmd_Argv) ( int argc ); // so game DLL can easily
|
||||
int (*pfnCmd_Argc) ( void ); // access client 'cmd' strings
|
||||
void (*pfnGetAttachment) (const edict_t *pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles );
|
||||
void (*pfnCRC32_Init) (CRC32_t *pulCRC);
|
||||
void (*pfnCRC32_ProcessBuffer) (CRC32_t *pulCRC, void *p, int len);
|
||||
void (*pfnCRC32_ProcessByte) (CRC32_t *pulCRC, unsigned char ch);
|
||||
CRC32_t (*pfnCRC32_Final) (CRC32_t pulCRC);
|
||||
long (*pfnRandomLong) (long lLow, long lHigh);
|
||||
float (*pfnRandomFloat) (float flLow, float flHigh);
|
||||
void (*pfnSetView) (const edict_t *pClient, const edict_t *pViewent );
|
||||
float (*pfnTime) ( void );
|
||||
void (*pfnCrosshairAngle) (const edict_t *pClient, float pitch, float yaw);
|
||||
byte * (*pfnLoadFileForMe) (char *filename, int *pLength);
|
||||
void (*pfnFreeFile) (void *buffer);
|
||||
void (*pfnEndSection) (const char *pszSectionName); // trigger_endsection
|
||||
int (*pfnCompareFileTime) (char *filename1, char *filename2, int *iCompare);
|
||||
void (*pfnGetGameDir) (char *szGetGameDir);
|
||||
void (*pfnCvar_RegisterVariable) (cvar_t *variable);
|
||||
void (*pfnFadeClientVolume) (const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds);
|
||||
void (*pfnSetClientMaxspeed) (const edict_t *pEdict, float fNewMaxspeed);
|
||||
edict_t * (*pfnCreateFakeClient) (const char *netname); // returns NULL if fake client can't be created
|
||||
void (*pfnRunPlayerMove) (edict_t *fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, byte msec );
|
||||
int (*pfnNumberOfEntities) (void);
|
||||
char* (*pfnGetInfoKeyBuffer) (edict_t *e); // passing in NULL gets the serverinfo
|
||||
char* (*pfnInfoKeyValue) (char *infobuffer, char *key);
|
||||
void (*pfnSetKeyValue) (char *infobuffer, char *key, char *value);
|
||||
void (*pfnSetClientKeyValue) (int clientIndex, char *infobuffer, char *key, char *value);
|
||||
int (*pfnIsMapValid) (char *filename);
|
||||
void (*pfnStaticDecal) ( const float *origin, int decalIndex, int entityIndex, int modelIndex );
|
||||
int (*pfnPrecacheGeneric) (char* s);
|
||||
int (*pfnGetPlayerUserId) (edict_t *e ); // returns the server assigned userid for this player. useful for logging frags, etc. returns -1 if the edict couldn't be found in the list of clients
|
||||
void (*pfnBuildSoundMsg) (edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch, int msg_dest, int msg_type, const float *pOrigin, edict_t *ed);
|
||||
int (*pfnIsDedicatedServer) (void);// is this a dedicated server?
|
||||
cvar_t *(*pfnCVarGetPointer) (const char *szVarName);
|
||||
unsigned int (*pfnGetPlayerWONId) (edict_t *e); // returns the server assigned WONid for this player. useful for logging frags, etc. returns -1 if the edict couldn't be found in the list of clients
|
||||
|
||||
// YWB 8/1/99 TFF Physics additions
|
||||
void (*pfnInfo_RemoveKey) ( char *s, const char *key );
|
||||
const char *(*pfnGetPhysicsKeyValue) ( const edict_t *pClient, const char *key );
|
||||
void (*pfnSetPhysicsKeyValue) ( const edict_t *pClient, const char *key, const char *value );
|
||||
const char *(*pfnGetPhysicsInfoString) ( const edict_t *pClient );
|
||||
unsigned short (*pfnPrecacheEvent) ( int type, const char*psz );
|
||||
void (*pfnPlaybackEvent) ( int flags, const edict_t *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
|
||||
|
||||
unsigned char *(*pfnSetFatPVS) ( float *org );
|
||||
unsigned char *(*pfnSetFatPAS) ( float *org );
|
||||
|
||||
int (*pfnCheckVisibility ) ( const edict_t *entity, unsigned char *pset );
|
||||
|
||||
void (*pfnDeltaSetField) ( struct delta_s *pFields, const char *fieldname );
|
||||
void (*pfnDeltaUnsetField) ( struct delta_s *pFields, const char *fieldname );
|
||||
void (*pfnDeltaAddEncoder) ( char *name, void (*conditionalencode)( struct delta_s *pFields, const unsigned char *from, const unsigned char *to ) );
|
||||
int (*pfnGetCurrentPlayer) ( void );
|
||||
int (*pfnCanSkipPlayer) ( const edict_t *player );
|
||||
int (*pfnDeltaFindField) ( struct delta_s *pFields, const char *fieldname );
|
||||
void (*pfnDeltaSetFieldByIndex) ( struct delta_s *pFields, int fieldNumber );
|
||||
void (*pfnDeltaUnsetFieldByIndex)( struct delta_s *pFields, int fieldNumber );
|
||||
|
||||
void (*pfnSetGroupMask) ( int mask, int op );
|
||||
|
||||
int (*pfnCreateInstancedBaseline) ( int classname, struct entity_state_s *baseline );
|
||||
void (*pfnCvar_DirectSet) ( struct cvar_s *var, char *value );
|
||||
|
||||
// Forces the client and server to be running with the same version of the specified file
|
||||
// ( e.g., a player model ).
|
||||
// Calling this has no effect in single player
|
||||
void (*pfnForceUnmodified) ( FORCE_TYPE type, float *mins, float *maxs, const char *filename );
|
||||
|
||||
void (*pfnGetPlayerStats) ( const edict_t *pClient, int *ping, int *packet_loss );
|
||||
|
||||
void (*pfnAddServerCommand) ( char *cmd_name, void (*function) (void) );
|
||||
|
||||
// For voice communications, set which clients hear eachother.
|
||||
// NOTE: these functions take player entity indices (starting at 1).
|
||||
qboolean (*pfnVoice_GetClientListening)(int iReceiver, int iSender);
|
||||
qboolean (*pfnVoice_SetClientListening)(int iReceiver, int iSender, qboolean bListen);
|
||||
|
||||
const char *(*pfnGetPlayerAuthId) ( edict_t *e );
|
||||
|
||||
} enginefuncs_t;
|
||||
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138
|
||||
|
||||
// Passed to pfnKeyValue
|
||||
typedef struct KeyValueData_s
|
||||
{
|
||||
char *szClassName; // in: entity classname
|
||||
char *szKeyName; // in: name of key
|
||||
char *szValue; // in: value of key
|
||||
long fHandled; // out: DLL sets to true if key-value pair was understood
|
||||
} KeyValueData;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char mapName[ 32 ];
|
||||
char landmarkName[ 32 ];
|
||||
edict_t *pentLandmark;
|
||||
vec3_t vecLandmarkOrigin;
|
||||
} LEVELLIST;
|
||||
#define MAX_LEVEL_CONNECTIONS 16 // These are encoded in the lower 16bits of ENTITYTABLE->flags
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int id; // Ordinal ID of this entity (used for entity <--> pointer conversions)
|
||||
edict_t *pent; // Pointer to the in-game entity
|
||||
|
||||
int location; // Offset from the base data of this entity
|
||||
int size; // Byte size of this entity's data
|
||||
int flags; // This could be a short -- bit mask of transitions that this entity is in the PVS of
|
||||
string_t classname; // entity class name
|
||||
|
||||
} ENTITYTABLE;
|
||||
|
||||
#define FENTTABLE_PLAYER 0x80000000
|
||||
#define FENTTABLE_REMOVED 0x40000000
|
||||
#define FENTTABLE_MOVEABLE 0x20000000
|
||||
#define FENTTABLE_GLOBAL 0x10000000
|
||||
|
||||
typedef struct saverestore_s SAVERESTOREDATA;
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef
|
||||
#endif
|
||||
struct saverestore_s
|
||||
{
|
||||
char *pBaseData; // Start of all entity save data
|
||||
char *pCurrentData; // Current buffer pointer for sequential access
|
||||
int size; // Current data size
|
||||
int bufferSize; // Total space for data
|
||||
int tokenSize; // Size of the linear list of tokens
|
||||
int tokenCount; // Number of elements in the pTokens table
|
||||
char **pTokens; // Hash table of entity strings (sparse)
|
||||
int currentIndex; // Holds a global entity table ID
|
||||
int tableCount; // Number of elements in the entity table
|
||||
int connectionCount;// Number of elements in the levelList[]
|
||||
ENTITYTABLE *pTable; // Array of ENTITYTABLE elements (1 for each entity)
|
||||
LEVELLIST levelList[ MAX_LEVEL_CONNECTIONS ]; // List of connections from this level
|
||||
|
||||
// smooth transition
|
||||
int fUseLandmark;
|
||||
char szLandmarkName[20];// landmark we'll spawn near in next level
|
||||
vec3_t vecLandmarkOffset;// for landmark transitions
|
||||
float time;
|
||||
char szCurrentMapName[32]; // To check global entities
|
||||
|
||||
}
|
||||
#ifdef _WIN32
|
||||
SAVERESTOREDATA
|
||||
#endif
|
||||
;
|
||||
|
||||
typedef enum _fieldtypes
|
||||
{
|
||||
FIELD_FLOAT = 0, // Any floating point value
|
||||
FIELD_STRING, // A string ID (return from ALLOC_STRING)
|
||||
FIELD_ENTITY, // An entity offset (EOFFSET)
|
||||
FIELD_CLASSPTR, // CBaseEntity *
|
||||
FIELD_EHANDLE, // Entity handle
|
||||
FIELD_EVARS, // EVARS *
|
||||
FIELD_EDICT, // edict_t *, or edict_t * (same thing)
|
||||
FIELD_VECTOR, // Any vector
|
||||
FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across level transitions automagically)
|
||||
FIELD_POINTER, // Arbitrary data pointer... to be removed, use an array of FIELD_CHARACTER
|
||||
FIELD_INTEGER, // Any integer or enum
|
||||
FIELD_FUNCTION, // A class function pointer (Think, Use, etc)
|
||||
FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression
|
||||
FIELD_SHORT, // 2 byte integer
|
||||
FIELD_CHARACTER, // a byte
|
||||
FIELD_TIME, // a floating point time (these are fixed up automatically too!)
|
||||
FIELD_MODELNAME, // Engine string that is a model name (needs precache)
|
||||
FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache)
|
||||
|
||||
FIELD_TYPECOUNT, // MUST BE LAST
|
||||
} FIELDTYPE;
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(s,m) (size_t)&(((s *)0)->m)
|
||||
#endif
|
||||
|
||||
#define _FIELD(type,name,fieldtype,count,flags) { fieldtype, #name, offsetof(type, name), count, flags }
|
||||
#define DEFINE_FIELD(type,name,fieldtype) _FIELD(type, name, fieldtype, 1, 0)
|
||||
#define DEFINE_ARRAY(type,name,fieldtype,count) _FIELD(type, name, fieldtype, count, 0)
|
||||
#define DEFINE_ENTITY_FIELD(name,fieldtype) _FIELD(entvars_t, name, fieldtype, 1, 0 )
|
||||
#define DEFINE_ENTITY_GLOBAL_FIELD(name,fieldtype) _FIELD(entvars_t, name, fieldtype, 1, FTYPEDESC_GLOBAL )
|
||||
#define DEFINE_GLOBAL_FIELD(type,name,fieldtype) _FIELD(type, name, fieldtype, 1, FTYPEDESC_GLOBAL )
|
||||
|
||||
|
||||
#define FTYPEDESC_GLOBAL 0x0001 // This field is masked for global entity save/restore
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FIELDTYPE fieldType;
|
||||
char *fieldName;
|
||||
int fieldOffset;
|
||||
short fieldSize;
|
||||
short flags;
|
||||
} TYPEDESCRIPTION;
|
||||
|
||||
#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Initialize/shutdown the game (one-time call after loading of game .dll )
|
||||
void (*pfnGameInit) ( void );
|
||||
int (*pfnSpawn) ( edict_t *pent );
|
||||
void (*pfnThink) ( edict_t *pent );
|
||||
void (*pfnUse) ( edict_t *pentUsed, edict_t *pentOther );
|
||||
void (*pfnTouch) ( edict_t *pentTouched, edict_t *pentOther );
|
||||
void (*pfnBlocked) ( edict_t *pentBlocked, edict_t *pentOther );
|
||||
void (*pfnKeyValue) ( edict_t *pentKeyvalue, KeyValueData *pkvd );
|
||||
void (*pfnSave) ( edict_t *pent, SAVERESTOREDATA *pSaveData );
|
||||
int (*pfnRestore) ( edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity );
|
||||
void (*pfnSetAbsBox) ( edict_t *pent );
|
||||
|
||||
void (*pfnSaveWriteFields) ( SAVERESTOREDATA *, const char *, void *, TYPEDESCRIPTION *, int );
|
||||
void (*pfnSaveReadFields) ( SAVERESTOREDATA *, const char *, void *, TYPEDESCRIPTION *, int );
|
||||
|
||||
void (*pfnSaveGlobalState) ( SAVERESTOREDATA * );
|
||||
void (*pfnRestoreGlobalState) ( SAVERESTOREDATA * );
|
||||
void (*pfnResetGlobalState) ( void );
|
||||
|
||||
qboolean (*pfnClientConnect) ( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] );
|
||||
|
||||
void (*pfnClientDisconnect) ( edict_t *pEntity );
|
||||
void (*pfnClientKill) ( edict_t *pEntity );
|
||||
void (*pfnClientPutInServer) ( edict_t *pEntity );
|
||||
void (*pfnClientCommand) ( edict_t *pEntity );
|
||||
void (*pfnClientUserInfoChanged)( edict_t *pEntity, char *infobuffer );
|
||||
|
||||
void (*pfnServerActivate) ( edict_t *pEdictList, int edictCount, int clientMax );
|
||||
void (*pfnServerDeactivate) ( void );
|
||||
|
||||
void (*pfnPlayerPreThink) ( edict_t *pEntity );
|
||||
void (*pfnPlayerPostThink) ( edict_t *pEntity );
|
||||
|
||||
void (*pfnStartFrame) ( void );
|
||||
void (*pfnParmsNewLevel) ( void );
|
||||
void (*pfnParmsChangeLevel) ( void );
|
||||
|
||||
// Returns string describing current .dll. E.g., TeamFotrress 2, Half-Life
|
||||
const char *(*pfnGetGameDescription)( void );
|
||||
|
||||
// Notify dll about a player customization.
|
||||
void (*pfnPlayerCustomization) ( edict_t *pEntity, customization_t *pCustom );
|
||||
|
||||
// Spectator funcs
|
||||
void (*pfnSpectatorConnect) ( edict_t *pEntity );
|
||||
void (*pfnSpectatorDisconnect) ( edict_t *pEntity );
|
||||
void (*pfnSpectatorThink) ( edict_t *pEntity );
|
||||
|
||||
// Notify game .dll that engine is going to shut down. Allows mod authors to set a breakpoint.
|
||||
void (*pfnSys_Error) ( const char *error_string );
|
||||
|
||||
void (*pfnPM_Move) ( struct playermove_s *ppmove, qboolean server );
|
||||
void (*pfnPM_Init) ( struct playermove_s *ppmove );
|
||||
char (*pfnPM_FindTextureType)( char *name );
|
||||
void (*pfnSetupVisibility)( struct edict_s *pViewEntity, struct edict_s *pClient, unsigned char **pvs, unsigned char **pas );
|
||||
void (*pfnUpdateClientData) ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd );
|
||||
int (*pfnAddToFullPack)( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet );
|
||||
void (*pfnCreateBaseline) ( int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs );
|
||||
void (*pfnRegisterEncoders) ( void );
|
||||
int (*pfnGetWeaponData) ( struct edict_s *player, struct weapon_data_s *info );
|
||||
|
||||
void (*pfnCmdStart) ( const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed );
|
||||
void (*pfnCmdEnd) ( const edict_t *player );
|
||||
|
||||
// Return 1 if the packet is valid. Set response_buffer_size if you want to send a response packet. Incoming, it holds the max
|
||||
// size of the response_buffer, so you must zero it out if you choose not to respond.
|
||||
int (*pfnConnectionlessPacket ) ( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
|
||||
|
||||
// Enumerates player hulls. Returns 0 if the hull number doesn't exist, 1 otherwise
|
||||
int (*pfnGetHullBounds) ( int hullnumber, float *mins, float *maxs );
|
||||
|
||||
// Create baselines for certain "unplaced" items.
|
||||
void (*pfnCreateInstancedBaselines) ( void );
|
||||
|
||||
// One of the pfnForceUnmodified files failed the consistency check for the specified player
|
||||
// Return 0 to allow the client to continue, 1 to force immediate disconnection ( with an optional disconnect message of up to 256 characters )
|
||||
int (*pfnInconsistentFile)( const struct edict_s *player, const char *filename, char *disconnect_message );
|
||||
|
||||
// The game .dll should return 1 if lag compensation should be allowed ( could also just set
|
||||
// the sv_unlag cvar.
|
||||
// Most games right now should return 0, until client-side weapon prediction code is written
|
||||
// and tested for them.
|
||||
int (*pfnAllowLagCompensation)( void );
|
||||
} DLL_FUNCTIONS;
|
||||
|
||||
extern DLL_FUNCTIONS gEntityInterface;
|
||||
|
||||
// Current version.
|
||||
#define NEW_DLL_FUNCTIONS_VERSION 1
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Called right before the object's memory is freed.
|
||||
// Calls its destructor.
|
||||
void (*pfnOnFreeEntPrivateData)(edict_t *pEnt);
|
||||
void (*pfnGameShutdown)(void);
|
||||
int (*pfnShouldCollide)( edict_t *pentTouched, edict_t *pentOther );
|
||||
} NEW_DLL_FUNCTIONS;
|
||||
typedef int (*NEW_DLL_FUNCTIONS_FN)( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
|
||||
|
||||
// Pointers will be null if the game DLL doesn't support this API.
|
||||
extern NEW_DLL_FUNCTIONS gNewDLLFunctions;
|
||||
|
||||
typedef int (*APIFUNCTION)( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
|
||||
typedef int (*APIFUNCTION2)( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
|
||||
|
||||
#endif EIFACE_H
|
||||
224
src/engine/progdefs.h
Normal file
224
src/engine/progdefs.h
Normal file
@@ -0,0 +1,224 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 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 PROGDEFS_H
|
||||
#define PROGDEFS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float time;
|
||||
float frametime;
|
||||
float force_retouch;
|
||||
string_t mapname;
|
||||
string_t startspot;
|
||||
float deathmatch;
|
||||
float coop;
|
||||
float teamplay;
|
||||
float serverflags;
|
||||
float found_secrets;
|
||||
vec3_t v_forward;
|
||||
vec3_t v_up;
|
||||
vec3_t v_right;
|
||||
float trace_allsolid;
|
||||
float trace_startsolid;
|
||||
float trace_fraction;
|
||||
vec3_t trace_endpos;
|
||||
vec3_t trace_plane_normal;
|
||||
float trace_plane_dist;
|
||||
edict_t *trace_ent;
|
||||
float trace_inopen;
|
||||
float trace_inwater;
|
||||
int trace_hitgroup;
|
||||
int trace_flags;
|
||||
int msg_entity;
|
||||
int cdAudioTrack;
|
||||
int maxClients;
|
||||
int maxEntities;
|
||||
const char *pStringBase;
|
||||
|
||||
void *pSaveData;
|
||||
vec3_t vecLandmarkOffset;
|
||||
} globalvars_t;
|
||||
|
||||
|
||||
typedef struct entvars_s
|
||||
{
|
||||
string_t classname;
|
||||
string_t globalname;
|
||||
|
||||
vec3_t origin;
|
||||
vec3_t oldorigin;
|
||||
vec3_t velocity;
|
||||
vec3_t basevelocity;
|
||||
vec3_t clbasevelocity; // Base velocity that was passed in to server physics so
|
||||
// client can predict conveyors correctly. Server zeroes it, so we need to store here, too.
|
||||
vec3_t movedir;
|
||||
|
||||
vec3_t angles; // Model angles
|
||||
vec3_t avelocity; // angle velocity (degrees per second)
|
||||
vec3_t punchangle; // auto-decaying view angle adjustment
|
||||
vec3_t v_angle; // Viewing angle (player only)
|
||||
|
||||
// For parametric entities
|
||||
vec3_t endpos;
|
||||
vec3_t startpos;
|
||||
float impacttime;
|
||||
float starttime;
|
||||
|
||||
int fixangle; // 0:nothing, 1:force view angles, 2:add avelocity
|
||||
float idealpitch;
|
||||
float pitch_speed;
|
||||
float ideal_yaw;
|
||||
float yaw_speed;
|
||||
|
||||
int modelindex;
|
||||
string_t model;
|
||||
|
||||
int viewmodel; // player's viewmodel
|
||||
int weaponmodel; // what other players see
|
||||
|
||||
vec3_t absmin; // BB max translated to world coord
|
||||
vec3_t absmax; // BB max translated to world coord
|
||||
vec3_t mins; // local BB min
|
||||
vec3_t maxs; // local BB max
|
||||
vec3_t size; // maxs - mins
|
||||
|
||||
float ltime;
|
||||
float nextthink;
|
||||
|
||||
int movetype;
|
||||
int solid;
|
||||
|
||||
int skin;
|
||||
int body; // sub-model selection for studiomodels
|
||||
int effects;
|
||||
|
||||
float gravity; // % of "normal" gravity
|
||||
float friction; // inverse elasticity of MOVETYPE_BOUNCE
|
||||
|
||||
int light_level;
|
||||
|
||||
int sequence; // animation sequence
|
||||
int gaitsequence; // movement animation sequence for player (0 for none)
|
||||
float frame; // % playback position in animation sequences (0..255)
|
||||
float animtime; // world time when frame was set
|
||||
float framerate; // animation playback rate (-8x to 8x)
|
||||
byte controller[4]; // bone controller setting (0..255)
|
||||
byte blending[2]; // blending amount between sub-sequences (0..255)
|
||||
|
||||
float scale; // sprite rendering scale (0..255)
|
||||
|
||||
int rendermode;
|
||||
float renderamt;
|
||||
vec3_t rendercolor;
|
||||
int renderfx;
|
||||
|
||||
float health;
|
||||
float frags;
|
||||
int weapons; // bit mask for available weapons
|
||||
float takedamage;
|
||||
|
||||
int deadflag;
|
||||
vec3_t view_ofs; // eye position
|
||||
|
||||
int button;
|
||||
int impulse;
|
||||
|
||||
edict_t *chain; // Entity pointer when linked into a linked list
|
||||
edict_t *dmg_inflictor;
|
||||
edict_t *enemy;
|
||||
edict_t *aiment; // entity pointer when MOVETYPE_FOLLOW
|
||||
edict_t *owner;
|
||||
edict_t *groundentity;
|
||||
|
||||
int spawnflags;
|
||||
int flags;
|
||||
|
||||
int colormap; // lowbyte topcolor, highbyte bottomcolor
|
||||
int team;
|
||||
|
||||
float max_health;
|
||||
float teleport_time;
|
||||
float armortype;
|
||||
float armorvalue;
|
||||
int waterlevel;
|
||||
int watertype;
|
||||
|
||||
string_t target;
|
||||
string_t targetname;
|
||||
string_t netname;
|
||||
string_t message;
|
||||
|
||||
float dmg_take;
|
||||
float dmg_save;
|
||||
float dmg;
|
||||
float dmgtime;
|
||||
|
||||
string_t noise;
|
||||
string_t noise1;
|
||||
string_t noise2;
|
||||
string_t noise3;
|
||||
|
||||
float speed;
|
||||
float air_finished;
|
||||
float pain_finished;
|
||||
float radsuit_finished;
|
||||
|
||||
edict_t *pContainingEntity;
|
||||
|
||||
int playerclass;
|
||||
float maxspeed;
|
||||
|
||||
float fov;
|
||||
int weaponanim;
|
||||
|
||||
int pushmsec;
|
||||
|
||||
int bInDuck;
|
||||
int flTimeStepSound;
|
||||
int flSwimTime;
|
||||
int flDuckTime;
|
||||
int iStepLeft;
|
||||
float flFallVelocity;
|
||||
|
||||
int gamestate;
|
||||
|
||||
int oldbuttons;
|
||||
|
||||
int groupinfo;
|
||||
|
||||
// For mods
|
||||
int iuser1;
|
||||
int iuser2;
|
||||
int iuser3;
|
||||
int iuser4;
|
||||
float fuser1;
|
||||
float fuser2;
|
||||
float fuser3;
|
||||
float fuser4;
|
||||
vec3_t vuser1;
|
||||
vec3_t vuser2;
|
||||
vec3_t vuser3;
|
||||
vec3_t vuser4;
|
||||
edict_t *euser1;
|
||||
edict_t *euser2;
|
||||
edict_t *euser3;
|
||||
edict_t *euser4;
|
||||
} entvars_t;
|
||||
|
||||
|
||||
#endif // PROGDEFS_H
|
||||
55
src/engine/shake.h
Normal file
55
src/engine/shake.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 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 SHAKE_H
|
||||
#define SHAKE_H
|
||||
|
||||
// Screen / View effects
|
||||
|
||||
// screen shake
|
||||
extern int gmsgShake;
|
||||
|
||||
// This structure is sent over the net to describe a screen shake event
|
||||
typedef struct
|
||||
{
|
||||
unsigned short amplitude; // FIXED 4.12 amount of shake
|
||||
unsigned short duration; // FIXED 4.12 seconds duration
|
||||
unsigned short frequency; // FIXED 8.8 noise frequency (low frequency is a jerk,high frequency is a rumble)
|
||||
} ScreenShake;
|
||||
|
||||
extern void V_ApplyShake( float *origin, float *angles, float factor );
|
||||
extern void V_CalcShake( void );
|
||||
extern int V_ScreenShake( const char *pszName, int iSize, void *pbuf );
|
||||
extern int V_ScreenFade( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
|
||||
// Fade in/out
|
||||
extern int gmsgFade;
|
||||
|
||||
#define FFADE_IN 0x0000 // Just here so we don't pass 0 into the function
|
||||
#define FFADE_OUT 0x0001 // Fade out (not in)
|
||||
#define FFADE_MODULATE 0x0002 // Modulate (don't blend)
|
||||
#define FFADE_STAYOUT 0x0004 // ignores the duration, stays faded out until new ScreenFade message received
|
||||
|
||||
// This structure is sent over the net to describe a screen fade event
|
||||
typedef struct
|
||||
{
|
||||
unsigned short duration; // FIXED 4.12 seconds duration
|
||||
unsigned short holdTime; // FIXED 4.12 seconds duration until reset (fade & hold)
|
||||
short fadeFlags; // flags
|
||||
byte r, g, b, a; // fade to color ( max alpha )
|
||||
} ScreenFade;
|
||||
|
||||
#endif // SHAKE_H
|
||||
|
||||
362
src/engine/studio.h
Normal file
362
src/engine/studio.h
Normal file
@@ -0,0 +1,362 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 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 _STUDIO_H_
|
||||
#define _STUDIO_H_
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
STUDIO MODELS
|
||||
|
||||
Studio models are position independent, so the cache manager can move them.
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
#define MAXSTUDIOTRIANGLES 20000 // TODO: tune this
|
||||
#define MAXSTUDIOVERTS 2048 // TODO: tune this
|
||||
#define MAXSTUDIOSEQUENCES 256 // total animation sequences
|
||||
#define MAXSTUDIOSKINS 100 // total textures
|
||||
#define MAXSTUDIOSRCBONES 512 // bones allowed at source movement
|
||||
#define MAXSTUDIOBONES 128 // total bones actually used
|
||||
#define MAXSTUDIOMODELS 32 // sub-models per model
|
||||
#define MAXSTUDIOBODYPARTS 32
|
||||
#define MAXSTUDIOGROUPS 16
|
||||
#define MAXSTUDIOANIMATIONS 512 // per sequence
|
||||
#define MAXSTUDIOMESHES 256
|
||||
#define MAXSTUDIOEVENTS 1024
|
||||
#define MAXSTUDIOPIVOTS 256
|
||||
#define MAXSTUDIOCONTROLLERS 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int id;
|
||||
int version;
|
||||
|
||||
char name[64];
|
||||
int length;
|
||||
|
||||
vec3_t eyeposition; // ideal eye position
|
||||
vec3_t min; // ideal movement hull size
|
||||
vec3_t max;
|
||||
|
||||
vec3_t bbmin; // clipping bounding box
|
||||
vec3_t bbmax;
|
||||
|
||||
int flags;
|
||||
|
||||
int numbones; // bones
|
||||
int boneindex;
|
||||
|
||||
int numbonecontrollers; // bone controllers
|
||||
int bonecontrollerindex;
|
||||
|
||||
int numhitboxes; // complex bounding boxes
|
||||
int hitboxindex;
|
||||
|
||||
int numseq; // animation sequences
|
||||
int seqindex;
|
||||
|
||||
int numseqgroups; // demand loaded sequences
|
||||
int seqgroupindex;
|
||||
|
||||
int numtextures; // raw textures
|
||||
int textureindex;
|
||||
int texturedataindex;
|
||||
|
||||
int numskinref; // replaceable textures
|
||||
int numskinfamilies;
|
||||
int skinindex;
|
||||
|
||||
int numbodyparts;
|
||||
int bodypartindex;
|
||||
|
||||
int numattachments; // queryable attachable points
|
||||
int attachmentindex;
|
||||
|
||||
int soundtable;
|
||||
int soundindex;
|
||||
int soundgroups;
|
||||
int soundgroupindex;
|
||||
|
||||
int numtransitions; // animation node to animation node transition graph
|
||||
int transitionindex;
|
||||
} studiohdr_t;
|
||||
|
||||
// header for demand loaded sequence group data
|
||||
typedef struct
|
||||
{
|
||||
int id;
|
||||
int version;
|
||||
|
||||
char name[64];
|
||||
int length;
|
||||
} studioseqhdr_t;
|
||||
|
||||
// bones
|
||||
typedef struct
|
||||
{
|
||||
char name[32]; // bone name for symbolic links
|
||||
int parent; // parent bone
|
||||
int flags; // ??
|
||||
int bonecontroller[6]; // bone controller index, -1 == none
|
||||
float value[6]; // default DoF values
|
||||
float scale[6]; // scale for delta DoF values
|
||||
} mstudiobone_t;
|
||||
|
||||
|
||||
// bone controllers
|
||||
typedef struct
|
||||
{
|
||||
int bone; // -1 == 0
|
||||
int type; // X, Y, Z, XR, YR, ZR, M
|
||||
float start;
|
||||
float end;
|
||||
int rest; // byte index value at rest
|
||||
int index; // 0-3 user set controller, 4 mouth
|
||||
} mstudiobonecontroller_t;
|
||||
|
||||
// intersection boxes
|
||||
typedef struct
|
||||
{
|
||||
int bone;
|
||||
int group; // intersection group
|
||||
vec3_t bbmin; // bounding box
|
||||
vec3_t bbmax;
|
||||
} mstudiobbox_t;
|
||||
|
||||
#if !defined( CACHE_USER ) && !defined( QUAKEDEF_H )
|
||||
#define CACHE_USER
|
||||
typedef struct cache_user_s
|
||||
{
|
||||
void *data;
|
||||
} cache_user_t;
|
||||
#endif
|
||||
|
||||
// demand loaded sequence groups
|
||||
typedef struct
|
||||
{
|
||||
char label[32]; // textual name
|
||||
char name[64]; // file name
|
||||
cache_user_t cache; // cache index pointer
|
||||
int data; // hack for group 0
|
||||
} mstudioseqgroup_t;
|
||||
|
||||
// sequence descriptions
|
||||
typedef struct
|
||||
{
|
||||
char label[32]; // sequence label
|
||||
|
||||
float fps; // frames per second
|
||||
int flags; // looping/non-looping flags
|
||||
|
||||
int activity;
|
||||
int actweight;
|
||||
|
||||
int numevents;
|
||||
int eventindex;
|
||||
|
||||
int numframes; // number of frames per sequence
|
||||
|
||||
int numpivots; // number of foot pivots
|
||||
int pivotindex;
|
||||
|
||||
int motiontype;
|
||||
int motionbone;
|
||||
vec3_t linearmovement;
|
||||
int automoveposindex;
|
||||
int automoveangleindex;
|
||||
|
||||
vec3_t bbmin; // per sequence bounding box
|
||||
vec3_t bbmax;
|
||||
|
||||
int numblends;
|
||||
int animindex; // mstudioanim_t pointer relative to start of sequence group data
|
||||
// [blend][bone][X, Y, Z, XR, YR, ZR]
|
||||
|
||||
int blendtype[2]; // X, Y, Z, XR, YR, ZR
|
||||
float blendstart[2]; // starting value
|
||||
float blendend[2]; // ending value
|
||||
int blendparent;
|
||||
|
||||
int seqgroup; // sequence group for demand loading
|
||||
|
||||
int entrynode; // transition node at entry
|
||||
int exitnode; // transition node at exit
|
||||
int nodeflags; // transition rules
|
||||
|
||||
int nextseq; // auto advancing sequences
|
||||
} mstudioseqdesc_t;
|
||||
|
||||
// events
|
||||
#include "studio_event.h"
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
int frame;
|
||||
int event;
|
||||
int type;
|
||||
char options[64];
|
||||
} mstudioevent_t;
|
||||
*/
|
||||
|
||||
// pivots
|
||||
typedef struct
|
||||
{
|
||||
vec3_t org; // pivot point
|
||||
int start;
|
||||
int end;
|
||||
} mstudiopivot_t;
|
||||
|
||||
// attachment
|
||||
typedef struct
|
||||
{
|
||||
char name[32];
|
||||
int type;
|
||||
int bone;
|
||||
vec3_t org; // attachment point
|
||||
vec3_t vectors[3];
|
||||
} mstudioattachment_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short offset[6];
|
||||
} mstudioanim_t;
|
||||
|
||||
// animation frames
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
byte valid;
|
||||
byte total;
|
||||
} num;
|
||||
short value;
|
||||
} mstudioanimvalue_t;
|
||||
|
||||
|
||||
|
||||
// body part index
|
||||
typedef struct
|
||||
{
|
||||
char name[64];
|
||||
int nummodels;
|
||||
int base;
|
||||
int modelindex; // index into models array
|
||||
} mstudiobodyparts_t;
|
||||
|
||||
|
||||
|
||||
// skin info
|
||||
typedef struct
|
||||
{
|
||||
char name[64];
|
||||
int flags;
|
||||
int width;
|
||||
int height;
|
||||
int index;
|
||||
} mstudiotexture_t;
|
||||
|
||||
|
||||
// skin families
|
||||
// short index[skinfamilies][skinref]
|
||||
|
||||
// studio models
|
||||
typedef struct
|
||||
{
|
||||
char name[64];
|
||||
|
||||
int type;
|
||||
|
||||
float boundingradius;
|
||||
|
||||
int nummesh;
|
||||
int meshindex;
|
||||
|
||||
int numverts; // number of unique vertices
|
||||
int vertinfoindex; // vertex bone info
|
||||
int vertindex; // vertex vec3_t
|
||||
int numnorms; // number of unique surface normals
|
||||
int norminfoindex; // normal bone info
|
||||
int normindex; // normal vec3_t
|
||||
|
||||
int numgroups; // deformation groups
|
||||
int groupindex;
|
||||
} mstudiomodel_t;
|
||||
|
||||
|
||||
// vec3_t boundingbox[model][bone][2]; // complex intersection info
|
||||
|
||||
|
||||
// meshes
|
||||
typedef struct
|
||||
{
|
||||
int numtris;
|
||||
int triindex;
|
||||
int skinref;
|
||||
int numnorms; // per mesh normals
|
||||
int normindex; // normal vec3_t
|
||||
} mstudiomesh_t;
|
||||
|
||||
// triangles
|
||||
#if 0
|
||||
typedef struct
|
||||
{
|
||||
short vertindex; // index into vertex array
|
||||
short normindex; // index into normal array
|
||||
short s,t; // s,t position on skin
|
||||
} mstudiotrivert_t;
|
||||
#endif
|
||||
|
||||
// lighting options
|
||||
#define STUDIO_NF_FLATSHADE 0x0001
|
||||
#define STUDIO_NF_CHROME 0x0002
|
||||
#define STUDIO_NF_FULLBRIGHT 0x0004
|
||||
|
||||
// motion flags
|
||||
#define STUDIO_X 0x0001
|
||||
#define STUDIO_Y 0x0002
|
||||
#define STUDIO_Z 0x0004
|
||||
#define STUDIO_XR 0x0008
|
||||
#define STUDIO_YR 0x0010
|
||||
#define STUDIO_ZR 0x0020
|
||||
#define STUDIO_LX 0x0040
|
||||
#define STUDIO_LY 0x0080
|
||||
#define STUDIO_LZ 0x0100
|
||||
#define STUDIO_AX 0x0200
|
||||
#define STUDIO_AY 0x0400
|
||||
#define STUDIO_AZ 0x0800
|
||||
#define STUDIO_AXR 0x1000
|
||||
#define STUDIO_AYR 0x2000
|
||||
#define STUDIO_AZR 0x4000
|
||||
#define STUDIO_TYPES 0x7FFF
|
||||
#define STUDIO_RLOOP 0x8000 // controller that wraps shortest distance
|
||||
|
||||
// sequence flags
|
||||
#define STUDIO_LOOPING 0x0001
|
||||
|
||||
// bone flags
|
||||
#define STUDIO_HAS_NORMALS 0x0001
|
||||
#define STUDIO_HAS_VERTICES 0x0002
|
||||
#define STUDIO_HAS_BBOX 0x0004
|
||||
#define STUDIO_HAS_CHROME 0x0008 // if any of the textures have chrome on them
|
||||
|
||||
#define RAD_TO_STUDIO (32768.0/M_PI)
|
||||
#define STUDIO_TO_RAD (M_PI/32768.0)
|
||||
|
||||
#endif
|
||||
3
src/metamod/.gitignore
vendored
Normal file
3
src/metamod/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
msgs/
|
||||
opt.*/
|
||||
debug.*/
|
||||
34
src/metamod/Config.mak
Normal file
34
src/metamod/Config.mak
Normal file
@@ -0,0 +1,34 @@
|
||||
MODNAME = metamod
|
||||
|
||||
#__METAMOD_BUILD__ for our special eiface.h
|
||||
EXTRA_CFLAGS += -D__METAMOD_BUILD__
|
||||
#-DMETA_PERFMON
|
||||
|
||||
SRCFILES = api_hook.cpp api_info.cpp commands_meta.cpp conf_meta.cpp \
|
||||
dllapi.cpp engine_api.cpp engineinfo.cpp game_support.cpp \
|
||||
game_autodetect.cpp h_export.cpp linkgame.cpp linkplug.cpp \
|
||||
log_meta.cpp meta_eiface.cpp metamod.cpp mlist.cpp mplayer.cpp \
|
||||
mplugin.cpp mqueue.cpp mreg.cpp mutil.cpp osdep.cpp \
|
||||
osdep_p.cpp reg_support.cpp sdk_util.cpp studioapi.cpp \
|
||||
support_meta.cpp thread_logparse.cpp vdate.cpp
|
||||
|
||||
INFOFILES = info_name.h vers_meta.h
|
||||
RESFILE = res_meta.rc
|
||||
|
||||
ifeq "$(OS)" "linux"
|
||||
SRCFILES+=osdep_linkent_linux.cpp osdep_detect_gamedll_linux.cpp
|
||||
EXTRA_LINK+=
|
||||
else
|
||||
SRCFILES+=osdep_linkent_win32.cpp osdep_detect_gamedll_win32.cpp
|
||||
EXTRA_LINK+=-Xlinker --script -Xlinker i386pe.merge
|
||||
endif
|
||||
|
||||
ifeq "$(OPT)" "opt"
|
||||
EXTRA_CFLAGS += -D__INTERNALS_USE_REGPARAMS__
|
||||
endif
|
||||
|
||||
ifeq "$(OPT)" "opt-fast"
|
||||
EXTRA_CFLAGS += -D__INTERNALS_USE_REGPARAMS__
|
||||
endif
|
||||
|
||||
#STLFILES = mreg.cpp
|
||||
460
src/metamod/Makefile
Normal file
460
src/metamod/Makefile
Normal file
@@ -0,0 +1,460 @@
|
||||
# vi: set ts=4 sw=4 :
|
||||
# vim: set tw=75 :
|
||||
|
||||
# MetaMod makefile
|
||||
# Copyright (c) 2001-2003 Will Day <willday@hpgx.net>
|
||||
#
|
||||
# based on the Valve SDK 2.1 Makefile as well as the Makefile
|
||||
# in adminmod by Alfred Reynolds.
|
||||
#
|
||||
# From SDK 2.1 dlls/Makefile:
|
||||
#! Half-Life StandardSDK 2.0 mp_i386.so Makefile for i386 Linux
|
||||
#! April 2000 by Leon Hartwig (jehannum@planethalflife.com)
|
||||
|
||||
|
||||
# NOTE: This is a generic Makefile for metamod and the bundled plugins, and
|
||||
# is symlinked into each subdir. Per-module config statements are in
|
||||
# Config.mak in each subdir.
|
||||
|
||||
ifeq "$(shell uname | cut -d _ -f1)" "CYGWIN"
|
||||
HOST=cygwin
|
||||
endif
|
||||
|
||||
ifdef COMSPEC
|
||||
ifeq "$(HOST)" "cygwin"
|
||||
ifeq "$(TARGET)" "win32"
|
||||
OS=windows
|
||||
else
|
||||
OS=linux
|
||||
endif
|
||||
else
|
||||
OS=windows
|
||||
endif
|
||||
else
|
||||
OS=linux
|
||||
endif
|
||||
|
||||
#############################################################################
|
||||
# CONFIGURATION
|
||||
#############################################################################
|
||||
|
||||
# TARGET amd64 disabled since Valve has dropped support for x86-64 server
|
||||
#ifeq "$(TARGET)" "amd64"
|
||||
# TARGETTYPE = amd64
|
||||
#else
|
||||
TARGETTYPE = i386
|
||||
#endif
|
||||
|
||||
# set paths for your environment
|
||||
ifeq "$(OS)" "linux"
|
||||
INST_DIR=$(HOME)/half-life/cstrike/dlls
|
||||
TEST_DIR=$(HOME)/test/tfc/dlls
|
||||
TST_DIR=$(HOME)/tmp
|
||||
else ## windows
|
||||
INST_DIR=/hlserver/tfc/dlls
|
||||
TEST_DIR=/hlserver/tfc/dlls
|
||||
endif
|
||||
|
||||
DLLS_DIR=../dlls
|
||||
SDKSRC=../hlsdk
|
||||
METADIR=../metamod
|
||||
|
||||
COMPILE_TZ=EET
|
||||
## Developer overrides
|
||||
ifeq "$(USER)" "jussi"
|
||||
COMPILE_TZ=EET
|
||||
endif
|
||||
|
||||
|
||||
#############################################################################
|
||||
# OS DEPENDENCIES
|
||||
#############################################################################
|
||||
|
||||
ifeq "$(OS)" "linux"
|
||||
INSTALL=install -m 644
|
||||
LD_WINDLL= i686-w64-mingw32-dllwrap
|
||||
OSTARGET=linux
|
||||
LIBFILE=$(LIBFILE_LINUX)
|
||||
TARGET_FILE=$(TARGET_LINUX)
|
||||
else ## windows
|
||||
INSTALL=cp
|
||||
LD_WINDLL= i686-w64-mingw32-dllwrap
|
||||
OSTARGET=win32
|
||||
LIBFILE=$(LIBFILE_WIN)
|
||||
TARGET_FILE=$(TARGET_WIN)
|
||||
endif
|
||||
|
||||
CC_WIN=i686-w64-mingw32-gcc
|
||||
RES_WIN=i686-w64-mingw32-windres
|
||||
|
||||
ifeq "$(HOST)" "cygwin"
|
||||
CC_WIN += -mno-cygwin
|
||||
EXTRA_LINK += -L/lib/w32api
|
||||
endif
|
||||
|
||||
OBJDIR_LINUX_OPT=opt.linux_$(TARGETTYPE)
|
||||
OBJDIR_LINUX_DBG=debug.linux_$(TARGETTYPE)
|
||||
OBJDIR_WIN_OPT=opt.win32
|
||||
OBJDIR_WIN_DBG=debug.win32
|
||||
|
||||
|
||||
#############################################################################
|
||||
# COMPILE OPTIONS - ARCHITECTURE AND OPTIMIZATIONS
|
||||
#############################################################################
|
||||
|
||||
ifeq "$(OS)" "linux"
|
||||
GCCMAJ = $(shell $(CC) -dumpversion | sed -e 's/\.[0-9][0-9]*//' -e 's/\.[0-9][0-9]*//')
|
||||
GCCMIN = $(shell $(CC) -dumpversion | sed -e 's/[0-9]\.//;s/\.[0-9]//' -e 's/\.[0-9][0-9]*//')
|
||||
else
|
||||
GCCMAJ = $(shell $(CC_WIN) -dumpversion | sed -e 's/\.[0-9][0-9]*//' -e 's/\.[0-9][0-9]*//')
|
||||
GCCMIN = $(shell $(CC_WIN) -dumpversion | sed -e 's/[0-9]\.//;s/\.[0-9]//' -e 's/\.[0-9][0-9]*//')
|
||||
endif
|
||||
|
||||
GCCMAJ_GT_4 = $(shell if [ $(GCCMAJ) -gt 4 ]; then echo 1; else echo 0; fi)
|
||||
|
||||
ifeq "$(HOST)" "cygwin"
|
||||
ifeq "$(TARGETTYPE)" "amd64"
|
||||
CC=gcc-linux-x86_64
|
||||
else
|
||||
CC=gcc-linux
|
||||
endif
|
||||
else
|
||||
ifeq "$(TARGETTYPE)" "amd64"
|
||||
CC=gcc -m64
|
||||
else
|
||||
CC=gcc -m32
|
||||
endif
|
||||
endif
|
||||
|
||||
MCPU=-mcpu
|
||||
|
||||
ifeq "$(GCCMAJ)" "3"
|
||||
ifeq "$(GCCMIN)" "4"
|
||||
MCPU=-mtune
|
||||
endif
|
||||
endif
|
||||
ifeq "$(GCCMAJ)" "4"
|
||||
MCPU=-mtune
|
||||
endif
|
||||
ifeq "$(GCCMAJ_GT_4)" "1"
|
||||
MCPU=-mtune
|
||||
endif
|
||||
|
||||
ifeq "$(OS)" "linux"
|
||||
CC_DEP=$(CC)
|
||||
else
|
||||
CC_DEP=$(CC_WIN)
|
||||
endif
|
||||
|
||||
# Note! About gcc optimization levels.
|
||||
# There is four optimization levels:
|
||||
# -O0 No optimizations.
|
||||
# -O1 Optimize for smaller size.
|
||||
# -O2 Optimize for speed without increasing size (alot).
|
||||
# -O3 Optimize for speed, can result much greater filesize.
|
||||
# Levels higher -O3 (-O6 for example) is threaded as -O3.
|
||||
# See differences at "http://gcc.gnu.org/" (look for link to 'gcc manual').
|
||||
|
||||
# original safe optimization, from valve Makefile
|
||||
#CCOPT = -O2 -ffast-math -funroll-loops \
|
||||
# -fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
|
||||
# -malign-jumps=2 -malign-functions=2
|
||||
|
||||
# safe optimization, adapted from adminmod Makefile
|
||||
#CCOPT = -m486 -O6 -ffast-math -funroll-loops \
|
||||
# -fexpensive-optimizations -malign-loops=2 -malign-jumps=2 \
|
||||
# -malign-functions=2 -Wall
|
||||
|
||||
# full optimization, adapted from adminmod Makefile
|
||||
# "WONT WORK WITH omit-frame-pointer"?
|
||||
# - disable (unneeded) C++ exceptions and rtti code to save some space ?
|
||||
|
||||
CCOPT = $(CCO) $(CCOPT_ARCH) -fno-exceptions -fno-rtti
|
||||
|
||||
# optimization level; overridden for certain problematic files
|
||||
CCO = -O2 -fomit-frame-pointer -funsafe-math-optimizations
|
||||
CCO += -flto -fvisibility=hidden
|
||||
|
||||
# architecture tuning by target type
|
||||
ifeq "$(TARGETTYPE)" "amd64"
|
||||
CCOPT_ARCH =
|
||||
else
|
||||
CCOPT_ARCH = -march=i686 $(MCPU)=generic -msse -msse2
|
||||
endif
|
||||
|
||||
# debugging; halt on warnings
|
||||
CCDEBUG+= -ggdb3
|
||||
|
||||
|
||||
#############################################################################
|
||||
# COMPILE SETUP
|
||||
#############################################################################
|
||||
|
||||
SRCDIR=.
|
||||
INCLUDEDIRS+=-I$(SRCDIR) -I$(METADIR) -I$(SDKSRC)/engine -I$(SDKSRC)/common -I$(SDKSRC)/pm_shared -I$(SDKSRC)/dlls -I$(SDKSRC)
|
||||
FILES_ALL = *.cpp *.h [A-Z]* *.rc
|
||||
|
||||
CFLAGS=-Wall -Wno-unknown-pragmas -Wno-attributes -Wno-write-strings
|
||||
|
||||
CFLAGS+=-std=gnu++98 -Wno-c++11-compat
|
||||
|
||||
#CFLAGS += -DTEST
|
||||
|
||||
ifeq "$(OPT)" "opt-fast"
|
||||
ODEF = -DOPT_TYPE="\"optimized+meta_debug-disabled\""
|
||||
CFLAGS := $(CCOPT) $(CFLAGS) $(ODEF) -D__BUILD_FAST_METAMOD__
|
||||
OBJDIR_LINUX = $(OBJDIR_LINUX_OPT)
|
||||
OBJDIR_WIN = $(OBJDIR_WIN_OPT)
|
||||
else #other
|
||||
ifeq "$(OPT)" "opt"
|
||||
ODEF = -DOPT_TYPE="\"optimized\""
|
||||
CFLAGS := $(CCOPT) $(CFLAGS) $(ODEF)
|
||||
OBJDIR_LINUX = $(OBJDIR_LINUX_OPT)
|
||||
OBJDIR_WIN = $(OBJDIR_WIN_OPT)
|
||||
else # debug
|
||||
ODEF = -DOPT_TYPE="\"debugging\""
|
||||
CFLAGS := $(CCDEBUG) $(CFLAGS) $(ODEF)
|
||||
OBJDIR_LINUX = $(OBJDIR_LINUX_DBG)
|
||||
OBJDIR_WIN = $(OBJDIR_WIN_DBG)
|
||||
DLLS_DIR := $(DLLS_DIR)/debug
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "$(OS)" "linux"
|
||||
OBJDIR = $(OBJDIR_LINUX)
|
||||
else
|
||||
OBJDIR = $(OBJDIR_WIN)
|
||||
endif
|
||||
|
||||
include Config.mak
|
||||
# any local CFLAGS from Config.mak
|
||||
CFLAGS += $(EXTRA_CFLAGS)
|
||||
|
||||
# provide timezone info
|
||||
$(OBJDIR_LINUX)/vdate.o $(OBJDIR_WIN)/vdate.o: CFLAGS += -DCOMPILE_TZ=\"$(COMPILE_TZ)\"
|
||||
|
||||
# ignore complaints from SDK files like cbase.h
|
||||
#$(OBJDIR_LINUX)/sdk_util.o $(OBJDIR_WIN)/sdk_util.o: CFLAGS += -Wno-unused
|
||||
|
||||
# ignore complaints from STL headers
|
||||
STLOBJ = $(STLFILES:%.cpp=$(OBJDIR_LINUX)/%.o)
|
||||
STLOBJ += $(STLFILES:%.cpp=$(OBJDIR_WIN)/%.o)
|
||||
#$(OBJDIR_LINUX)/mreg.o $(OBJDIR_WIN)/mreg.o: CFLAGS += -Wno-effc++
|
||||
$(STLOBJ): FILTER= 2>&1 | ../tools/stlfilter
|
||||
$(STLOBJ): CFLAGS += -Wno-error
|
||||
|
||||
# these files seem to create "Internal compiler error" errors under mingw
|
||||
# when using -O6
|
||||
#$(OBJDIR_WIN)/engine_api.o: CCO = -O5
|
||||
#$(OBJDIR_WIN)/dllapi_api.o: CCO = -O5
|
||||
|
||||
#############################################################################
|
||||
# BUILDING LINUX SO
|
||||
#############################################################################
|
||||
|
||||
# linux .so compile commands
|
||||
DO_CC_LINUX=$(CC) $(CFLAGS) -fPIC $(INCLUDEDIRS) -o $@ -c $< $(FILTER)
|
||||
LINK_LINUX=$(CC) $(CFLAGS) -shared -ldl -lm -static-libgcc $(EXTRA_LINK) $(OBJ_LINUX) -o $@
|
||||
|
||||
# sort by date
|
||||
#SRCFILES := $(shell ls -t $(SRCFILES))
|
||||
|
||||
# linux object files
|
||||
OBJ_LINUX := $(SRCFILES:%.cpp=$(OBJDIR_LINUX)/%.o)
|
||||
|
||||
# compiling linux object files
|
||||
$(OBJDIR_LINUX)/%.o: $(SRCDIR)/%.cpp
|
||||
$(DO_CC_LINUX)
|
||||
|
||||
# linux .so target file
|
||||
LIBFILE_LINUX = $(MODNAME).so
|
||||
TARGET_LINUX = $(OBJDIR_LINUX)/$(LIBFILE_LINUX)
|
||||
|
||||
|
||||
#############################################################################
|
||||
# BUILDING WINDOWS DLL
|
||||
#############################################################################
|
||||
|
||||
# windows .dll compile commands
|
||||
DO_CC_WIN=$(CC_WIN) $(CFLAGS) $(INCLUDEDIRS) -o $@ -c $<
|
||||
DO_RES_WIN=$(RES_WIN) '$(ODEF)' --include-dir . --include-dir ../metamod -i $< -O coff -o $@
|
||||
#LINK_WIN=$(LD_WINDLL) -k -mwindows --add-stdcall-alias --def metamod.def -o $@ $(OBJ_WIN)
|
||||
#LINK_WIN=$(LD_WINDLL) -A -k -mwindows --export-all-symbols -o $@ $(OBJ_WIN)
|
||||
#LINK_WIN=$(LD_WINDLL) -mwindows --add-stdcall-alias $(OBJ_WIN) $(RES_OBJ_WIN) -lstdc++ -s -o $@
|
||||
LINK_WIN=$(CC_WIN) $(CFLAGS) -mdll -Xlinker --add-stdcall-alias $(EXTRA_LINK) $(OBJ_WIN) $(RES_OBJ_WIN) -s -o $@
|
||||
|
||||
# windows object files
|
||||
OBJ_WIN := $(SRCFILES:%.cpp=$(OBJDIR_WIN)/%.o)
|
||||
RES_OBJ_WIN := $(RESFILE:%.rc=$(OBJDIR_WIN)/%.o)
|
||||
|
||||
# compiling windows object files
|
||||
$(OBJDIR_WIN)/%.o: $(SRCDIR)/%.cpp
|
||||
$(DO_CC_WIN)
|
||||
|
||||
# compiling windows resource file
|
||||
$(OBJDIR_WIN)/%.o: $(SRCDIR)/%.rc $(INFOFILES)
|
||||
$(DO_RES_WIN)
|
||||
|
||||
# windows .dll target file
|
||||
LIBFILE_WIN = $(MODNAME).dll
|
||||
TARGET_WIN = $(OBJDIR_WIN)/$(LIBFILE_WIN)
|
||||
|
||||
|
||||
#############################################################################
|
||||
# OVERRIDES
|
||||
#############################################################################
|
||||
|
||||
ifeq "$(PLATFORM)" "linux-only"
|
||||
LIBFILE_WIN =
|
||||
TARGET_WIN =
|
||||
endif
|
||||
ifeq "$(PLATFORM)" "win32-only"
|
||||
LIBFILE_LINUX =
|
||||
TARGET_LINUX =
|
||||
OSTARGET=win32
|
||||
LIBFILE=$(LIBFILE_WIN)
|
||||
TARGET_FILE=$(TARGET_WIN)
|
||||
endif
|
||||
|
||||
|
||||
#############################################################################
|
||||
# BUILD RULES
|
||||
#############################################################################
|
||||
|
||||
default: $(TARGET_FILE)
|
||||
|
||||
all: do_dll_linux do_dll_win32
|
||||
|
||||
opt:
|
||||
$(MAKE) default OPT=opt
|
||||
|
||||
linux: do_dll_linux
|
||||
win32: do_dll_win32
|
||||
|
||||
linux_opt:
|
||||
$(MAKE) linux OPT=opt
|
||||
win32_opt:
|
||||
$(MAKE) win32 OPT=opt
|
||||
|
||||
$(TARGET_LINUX): msgs/debug msgs/warning msgs/log msgs/error $(OBJDIR_LINUX) $(OBJ_LINUX)
|
||||
$(LINK_LINUX)
|
||||
|
||||
# for plugins, recompile meta_api.cpp if info_name.h changed
|
||||
$(OBJDIR_LINUX)/meta_api.o $(OBJDIR_WIN)/meta_api.o: info_name.h
|
||||
|
||||
$(TARGET_WIN): msgs/debug msgs/warning msgs/log msgs/error $(OBJDIR_WIN) $(OBJ_WIN) $(RES_OBJ_WIN)
|
||||
$(LINK_WIN)
|
||||
|
||||
$(OBJDIR_LINUX) $(OBJDIR_WIN) msgs:
|
||||
mkdir $@
|
||||
|
||||
# make sure to recompile vdate.c for each link
|
||||
$(OBJDIR_LINUX)/vdate.o $(OBJDIR_WIN)/vdate.o : $(SRCFILES) *.h
|
||||
|
||||
domsgs: msgs/debug msgs/log msgs/error msgs/warning
|
||||
|
||||
msgs/debug: $(SRCFILES) *.h msgs
|
||||
egrep "DEBUG\([0-9]" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort -k2,2 > $@
|
||||
|
||||
msgs/log: $(SRCFILES) *.h msgs
|
||||
egrep "META_LOG\(" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort > $@
|
||||
|
||||
msgs/error: $(SRCFILES) *.h msgs
|
||||
egrep "META_ERROR\(" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort > $@
|
||||
|
||||
msgs/warning: $(SRCFILES) *.h msgs
|
||||
egrep "META_WARNING\(" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort > $@
|
||||
|
||||
tags: .tags .htags
|
||||
ctags: .tags
|
||||
htags: .htags
|
||||
|
||||
.tags: $(SRCFILES) *.h
|
||||
-ctags -a $?
|
||||
|
||||
.htags: *.h
|
||||
-htags $?
|
||||
|
||||
retags:
|
||||
-rm -f .tags .htags
|
||||
ctags -f .tags `find $(SDKSRC) -name '*.h'`
|
||||
ctags -f .tags -a `find $(METADIR) -name old -prune -o -name '*.h' -print`
|
||||
ctags -f .tags -a $(SRCFILES)
|
||||
htags -R $(SDKSRC)
|
||||
htags `find $(METADIR) -name old -prune -o -name '*.h' -print`
|
||||
htags *.h
|
||||
|
||||
clean: clean_$(OSTARGET)
|
||||
|
||||
clean_linux:
|
||||
test -n "$(OBJDIR_LINUX)"
|
||||
-rm -f $(OBJDIR_LINUX)/*
|
||||
|
||||
clean_win32:
|
||||
test -n "$(OBJDIR_WIN)"
|
||||
-rm -f $(OBJDIR_WIN)/*
|
||||
|
||||
cleanall_linux:
|
||||
$(MAKE) clean_linux
|
||||
$(MAKE) clean_linux OPT=opt
|
||||
$(MAKE) clean_linux TARGET=amd64
|
||||
$(MAKE) clean_linux TARGET=amd64 OPT=opt
|
||||
|
||||
cleanall_win32:
|
||||
$(MAKE) clean_win32
|
||||
$(MAKE) clean_win32 OPT=opt
|
||||
|
||||
cleanall: cleanall_linux cleanall_win32
|
||||
|
||||
dll_linux dll_win32:
|
||||
$(MAKE) do_$@
|
||||
$(MAKE) do_$@ OPT=opt
|
||||
|
||||
do_dll_linux: $(DLLS_DIR) $(DLLS_DIR)/$(LIBFILE_LINUX)
|
||||
do_dll_win32: $(DLLS_DIR) $(DLLS_DIR)/$(LIBFILE_WIN)
|
||||
|
||||
$(DLLS_DIR):
|
||||
mkdir $(DLLS_DIR)
|
||||
|
||||
$(DLLS_DIR)/$(LIBFILE_LINUX): $(TARGET_LINUX)
|
||||
$(INSTALL) $+ $@
|
||||
|
||||
$(DLLS_DIR)/$(LIBFILE_WIN): $(TARGET_WIN)
|
||||
$(INSTALL) $+ $@
|
||||
|
||||
dlls: dll_linux dll_win32
|
||||
rmdlls:
|
||||
-rm -f ../dlls/*.* ../dlls/debug/*.*
|
||||
|
||||
spotless: cleanall
|
||||
-rmdir $(OBJDIR_LINUX) $(OBJDIR_WIN)
|
||||
# -rm -f .snap $(GENERATED)
|
||||
|
||||
distclean: spotless
|
||||
|
||||
install: $(INST_DIR)/$(LIBFILE)
|
||||
test: $(TEST_DIR)/$(LIBFILE)
|
||||
test_opt:
|
||||
$(MAKE) test OPT=opt
|
||||
|
||||
$(INST_DIR)/$(LIBFILE) $(TEST_DIR)/$(LIBFILE): $(TARGET_FILE)
|
||||
$(INSTALL) $< $@
|
||||
|
||||
tst: $(TST_DIR)/$(LIBFILE_WIN)
|
||||
|
||||
$(TST_DIR)/$(LIBFILE_WIN): $(TARGET_WIN)
|
||||
cp $< $@
|
||||
|
||||
snap: .snap
|
||||
|
||||
.snap: $(FILES_ALL)
|
||||
mkdir -p snapshots
|
||||
tar zcvf snapshots/`date '+%m%d-%H%M'`.tgz $(FILES_ALL)
|
||||
touch .snap
|
||||
|
||||
depend: $(OBJDIR)/Rules.depend
|
||||
|
||||
$(OBJDIR)/Rules.depend: Makefile $(SRCFILES) $(OBJDIR)
|
||||
$(CC_DEP) -MM $(INCLUDEDIRS) $(SRCFILES) | sed "s;\(^[^ ]*\):\(.*\);$(OBJDIR)/\1: Makefile Config.mak \2;" > $@
|
||||
|
||||
include $(OBJDIR)/Rules.depend
|
||||
690
src/metamod/api_hook.cpp
Normal file
690
src/metamod/api_hook.cpp
Normal file
@@ -0,0 +1,690 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
||||
*
|
||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h> // offsetof
|
||||
#include <extdll.h>
|
||||
|
||||
#include "ret_type.h"
|
||||
#include "types_meta.h"
|
||||
#include "api_info.h"
|
||||
#include "api_hook.h"
|
||||
#include "mplugin.h"
|
||||
#include "metamod.h"
|
||||
#include "osdep.h" //unlikely
|
||||
|
||||
// getting pointer with table index is faster than with if-else
|
||||
static const void ** api_tables[3] = {
|
||||
(const void**)&Engine.funcs,
|
||||
(const void**)&GameDLL.funcs.dllapi_table,
|
||||
(const void**)&GameDLL.funcs.newapi_table
|
||||
};
|
||||
|
||||
static const void ** api_info_tables[3] = {
|
||||
(const void**)&engine_info,
|
||||
(const void**)&dllapi_info,
|
||||
(const void**)&newapi_info
|
||||
};
|
||||
|
||||
// Safety check for metamod-bot-plugin bugfix.
|
||||
// engine_api->pfnRunPlayerMove calls dllapi-functions before it returns.
|
||||
// This causes problems with bots running as metamod plugins, because
|
||||
// metamod assumed that PublicMetaGlobals is free to be used.
|
||||
// With call_count we can fix this by backuping up PublicMetaGlobals if
|
||||
// it's already being used.
|
||||
static unsigned int call_count = 0;
|
||||
|
||||
// get function pointer from api table by function pointer offset
|
||||
inline void * DLLINTERNAL get_api_function(const void * api_table, unsigned int func_offset) {
|
||||
return(*(void**)((unsigned long)api_table + func_offset));
|
||||
}
|
||||
|
||||
// get data pointer from api_info table by function offset
|
||||
inline const api_info_t * DLLINTERNAL get_api_info(enum_api_t api, unsigned int api_info_offset) {
|
||||
return((const api_info_t *)((unsigned long)api_info_tables[api] + api_info_offset));
|
||||
}
|
||||
|
||||
// simplified 'void' version of main hook function
|
||||
void DLLINTERNAL main_hook_function_void(unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void * packed_args) {
|
||||
const api_info_t *api_info;
|
||||
int i;
|
||||
META_RES mres, status, prev_mres;
|
||||
MPlugin *iplug;
|
||||
void *pfn_routine;
|
||||
int loglevel;
|
||||
const void *api_table;
|
||||
meta_globals_t backup_meta_globals[1];
|
||||
|
||||
//passing offset from api wrapper function makes code faster/smaller
|
||||
api_info = get_api_info(api, api_info_offset);
|
||||
|
||||
//Fix bug with metamod-bot-plugins.
|
||||
if(unlikely(call_count++>0)) {
|
||||
//Backup PublicMetaGlobals.
|
||||
backup_meta_globals[0] = PublicMetaGlobals;
|
||||
}
|
||||
|
||||
//Setup
|
||||
loglevel=api_info->loglevel;
|
||||
mres=MRES_UNSET;
|
||||
status=MRES_UNSET;
|
||||
prev_mres=MRES_UNSET;
|
||||
pfn_routine=NULL;
|
||||
|
||||
//Pre plugin functions
|
||||
prev_mres=MRES_UNSET;
|
||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
||||
iplug=&Plugins->plist[i];
|
||||
|
||||
if(unlikely(iplug->status != PL_RUNNING))
|
||||
continue;
|
||||
|
||||
api_table = iplug->get_api_table(api);
|
||||
if(likely(!api_table)) {
|
||||
//plugin doesn't provide this api table
|
||||
continue;
|
||||
}
|
||||
|
||||
pfn_routine=get_api_function(api_table, func_offset);
|
||||
if(likely(!pfn_routine)) {
|
||||
//plugin doesn't provide this function
|
||||
continue;
|
||||
}
|
||||
|
||||
// initialize PublicMetaGlobals
|
||||
PublicMetaGlobals.mres = MRES_UNSET;
|
||||
PublicMetaGlobals.prev_mres = prev_mres;
|
||||
PublicMetaGlobals.status = status;
|
||||
|
||||
// call plugin
|
||||
META_DEBUG(loglevel, ("Calling %s:%s()", iplug->file, api_info->name));
|
||||
api_info->api_caller(pfn_routine, packed_args);
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
|
||||
// plugin's result code
|
||||
mres=PublicMetaGlobals.mres;
|
||||
if(unlikely(mres > status))
|
||||
status = mres;
|
||||
|
||||
// save this for successive plugins to see
|
||||
prev_mres = mres;
|
||||
|
||||
if(unlikely(mres==MRES_UNSET))
|
||||
META_WARNING("Plugin didn't set meta_result: %s:%s()", iplug->file, api_info->name);
|
||||
}
|
||||
|
||||
call_count--;
|
||||
|
||||
//Api call
|
||||
if(likely(status!=MRES_SUPERCEDE)) {
|
||||
//get api table
|
||||
api_table = *api_tables[api];
|
||||
|
||||
if(likely(api_table)) {
|
||||
pfn_routine = get_api_function(api_table, func_offset);
|
||||
if(likely(pfn_routine)) {
|
||||
META_DEBUG(loglevel, ("Calling %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
api_info->api_caller(pfn_routine, packed_args);
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
} else {
|
||||
// don't complain for NULL routines in NEW_DLL_FUNCTIONS
|
||||
if(unlikely(api != e_api_newapi))
|
||||
META_WARNING("Couldn't find api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name);
|
||||
status=MRES_UNSET;
|
||||
}
|
||||
} else {
|
||||
// don't complain for NULL NEW_DLL_FUNCTIONS-table
|
||||
if(unlikely(api != e_api_newapi))
|
||||
META_DEBUG(loglevel, ("No api table defined for api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
status=MRES_UNSET;
|
||||
}
|
||||
} else
|
||||
META_DEBUG(loglevel, ("Skipped (supercede) %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
|
||||
call_count++;
|
||||
|
||||
//Post plugin functions
|
||||
prev_mres=MRES_UNSET;
|
||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
||||
iplug=&Plugins->plist[i];
|
||||
|
||||
if(unlikely(iplug->status != PL_RUNNING))
|
||||
continue;
|
||||
|
||||
api_table = iplug->get_api_post_table(api);
|
||||
if(likely(!api_table)) {
|
||||
//plugin doesn't provide this api table
|
||||
continue;
|
||||
}
|
||||
|
||||
pfn_routine=get_api_function(api_table, func_offset);
|
||||
if(likely(!pfn_routine)) {
|
||||
//plugin doesn't provide this function
|
||||
continue;
|
||||
}
|
||||
|
||||
// initialize PublicMetaGlobals
|
||||
PublicMetaGlobals.mres = MRES_UNSET;
|
||||
PublicMetaGlobals.prev_mres = prev_mres;
|
||||
PublicMetaGlobals.status = status;
|
||||
|
||||
// call plugin
|
||||
META_DEBUG(loglevel, ("Calling %s:%s_Post()", iplug->file, api_info->name));
|
||||
api_info->api_caller(pfn_routine, packed_args);
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
|
||||
// plugin's result code
|
||||
mres=PublicMetaGlobals.mres;
|
||||
if(unlikely(mres > status))
|
||||
status = mres;
|
||||
|
||||
// save this for successive plugins to see
|
||||
prev_mres = mres;
|
||||
|
||||
if(unlikely(mres==MRES_UNSET))
|
||||
META_WARNING("Plugin didn't set meta_result: %s:%s_Post()", iplug->file, api_info->name);
|
||||
else if(unlikely(mres==MRES_SUPERCEDE))
|
||||
META_WARNING("MRES_SUPERCEDE not valid in Post functions: %s:%s_Post()", iplug->file, api_info->name);
|
||||
}
|
||||
|
||||
if(unlikely(--call_count>0)) {
|
||||
//Restore backup
|
||||
PublicMetaGlobals = backup_meta_globals[0];
|
||||
}
|
||||
}
|
||||
|
||||
// full return typed version of main hook function
|
||||
void * DLLINTERNAL main_hook_function(const class_ret_t ret_init, unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void * packed_args) {
|
||||
const api_info_t *api_info;
|
||||
int i;
|
||||
META_RES mres, status, prev_mres;
|
||||
MPlugin *iplug;
|
||||
void *pfn_routine;
|
||||
int loglevel;
|
||||
const void *api_table;
|
||||
meta_globals_t backup_meta_globals[1];
|
||||
|
||||
//passing offset from api wrapper function makes code faster/smaller
|
||||
api_info = get_api_info(api, api_info_offset);
|
||||
|
||||
//Fix bug with metamod-bot-plugins.
|
||||
if(unlikely(call_count++>0)) {
|
||||
//Backup PublicMetaGlobals.
|
||||
backup_meta_globals[0] = PublicMetaGlobals;
|
||||
}
|
||||
|
||||
//Return class setup
|
||||
class_ret_t dllret=ret_init;
|
||||
class_ret_t override_ret=ret_init;
|
||||
class_ret_t pub_override_ret=ret_init;
|
||||
class_ret_t orig_ret=ret_init;
|
||||
class_ret_t pub_orig_ret=ret_init;
|
||||
|
||||
//Setup
|
||||
loglevel=api_info->loglevel;
|
||||
mres=MRES_UNSET;
|
||||
status=MRES_UNSET;
|
||||
prev_mres=MRES_UNSET;
|
||||
pfn_routine=NULL;
|
||||
|
||||
//Pre plugin functions
|
||||
prev_mres=MRES_UNSET;
|
||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
||||
iplug=&Plugins->plist[i];
|
||||
|
||||
if(unlikely(iplug->status != PL_RUNNING))
|
||||
continue;
|
||||
|
||||
api_table = iplug->get_api_table(api);
|
||||
if(likely(!api_table)) {
|
||||
//plugin doesn't provide this api table
|
||||
continue;
|
||||
}
|
||||
|
||||
pfn_routine=get_api_function(api_table, func_offset);
|
||||
if(likely(!pfn_routine)) {
|
||||
//plugin doesn't provide this function
|
||||
continue;
|
||||
}
|
||||
|
||||
// initialize PublicMetaGlobals
|
||||
PublicMetaGlobals.mres = MRES_UNSET;
|
||||
PublicMetaGlobals.prev_mres = prev_mres;
|
||||
PublicMetaGlobals.status = status;
|
||||
pub_orig_ret = orig_ret;
|
||||
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
|
||||
if(unlikely(status==MRES_SUPERCEDE)) {
|
||||
pub_override_ret = override_ret;
|
||||
PublicMetaGlobals.override_ret = pub_override_ret.getptr();
|
||||
}
|
||||
|
||||
// call plugin
|
||||
META_DEBUG(loglevel, ("Calling %s:%s()", iplug->file, api_info->name));
|
||||
dllret = class_ret_t(api_info->api_caller(pfn_routine, packed_args));
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
|
||||
// plugin's result code
|
||||
mres=PublicMetaGlobals.mres;
|
||||
if(unlikely(mres > status))
|
||||
status = mres;
|
||||
|
||||
// save this for successive plugins to see
|
||||
prev_mres = mres;
|
||||
|
||||
if(unlikely(mres==MRES_SUPERCEDE)) {
|
||||
pub_override_ret = dllret;
|
||||
override_ret = dllret;
|
||||
}
|
||||
else if(unlikely(mres==MRES_UNSET)) {
|
||||
META_WARNING("Plugin didn't set meta_result: %s:%s()", iplug->file, api_info->name);
|
||||
}
|
||||
}
|
||||
|
||||
call_count--;
|
||||
|
||||
//Api call
|
||||
if(likely(status!=MRES_SUPERCEDE)) {
|
||||
//get api table
|
||||
api_table = *api_tables[api];
|
||||
|
||||
if(likely(api_table)) {
|
||||
pfn_routine = get_api_function(api_table, func_offset);
|
||||
if(likely(pfn_routine)) {
|
||||
META_DEBUG(loglevel, ("Calling %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
dllret = class_ret_t(api_info->api_caller(pfn_routine, packed_args));
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
orig_ret = dllret;
|
||||
} else {
|
||||
// don't complain for NULL routines in NEW_DLL_FUNCTIONS
|
||||
if(unlikely(api != e_api_newapi))
|
||||
META_WARNING("Couldn't find api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name);
|
||||
status=MRES_UNSET;
|
||||
}
|
||||
} else {
|
||||
// don't complain for NULL NEW_DLL_FUNCTIONS-table
|
||||
if(unlikely(api != e_api_newapi))
|
||||
META_DEBUG(loglevel, ("No api table defined for api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
status=MRES_UNSET;
|
||||
}
|
||||
} else {
|
||||
META_DEBUG(loglevel, ("Skipped (supercede) %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
orig_ret = override_ret;
|
||||
pub_orig_ret = override_ret;
|
||||
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
|
||||
}
|
||||
|
||||
call_count++;
|
||||
|
||||
//Pre plugin functions
|
||||
prev_mres=MRES_UNSET;
|
||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
||||
iplug=&Plugins->plist[i];
|
||||
|
||||
if(unlikely(iplug->status != PL_RUNNING))
|
||||
continue;
|
||||
|
||||
api_table = iplug->get_api_post_table(api);
|
||||
if(likely(!api_table)) {
|
||||
//plugin doesn't provide this api table
|
||||
continue;
|
||||
}
|
||||
|
||||
pfn_routine=get_api_function(api_table, func_offset);
|
||||
if(likely(!pfn_routine)) {
|
||||
//plugin doesn't provide this function
|
||||
continue;
|
||||
}
|
||||
|
||||
// initialize PublicMetaGlobals
|
||||
PublicMetaGlobals.mres = MRES_UNSET;
|
||||
PublicMetaGlobals.prev_mres = prev_mres;
|
||||
PublicMetaGlobals.status = status;
|
||||
pub_orig_ret = orig_ret;
|
||||
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
|
||||
if(unlikely(status==MRES_OVERRIDE)) {
|
||||
pub_override_ret = override_ret;
|
||||
PublicMetaGlobals.override_ret = pub_override_ret.getptr();
|
||||
}
|
||||
|
||||
// call plugin
|
||||
META_DEBUG(loglevel, ("Calling %s:%s_Post()", iplug->file, api_info->name));
|
||||
dllret = class_ret_t(api_info->api_caller(pfn_routine, packed_args));
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
|
||||
// plugin's result code
|
||||
mres=PublicMetaGlobals.mres;
|
||||
if(unlikely(mres > status))
|
||||
status = mres;
|
||||
|
||||
// save this for successive plugins to see
|
||||
prev_mres = mres;
|
||||
|
||||
if(unlikely(mres==MRES_OVERRIDE)) {
|
||||
pub_override_ret = dllret;
|
||||
override_ret = dllret;
|
||||
}
|
||||
else if(unlikely(mres==MRES_UNSET)) {
|
||||
META_WARNING("Plugin didn't set meta_result: %s:%s_Post()", iplug->file, api_info->name);
|
||||
}
|
||||
else if(unlikely(mres==MRES_SUPERCEDE)) {
|
||||
META_WARNING("MRES_SUPERCEDE not valid in Post functions: %s:%s_Post()", iplug->file, api_info->name);
|
||||
}
|
||||
}
|
||||
|
||||
if(unlikely(--call_count>0)) {
|
||||
//Restore backup
|
||||
PublicMetaGlobals = backup_meta_globals[0];
|
||||
}
|
||||
|
||||
//return value is passed through ret_init!
|
||||
if(likely(status!=MRES_OVERRIDE)) {
|
||||
return(*(void**)orig_ret.getptr());
|
||||
} else {
|
||||
META_DEBUG(loglevel, ("Returning (override) %s()", api_info->name));
|
||||
return(*(void**)override_ret.getptr());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Macros for creating api caller functions
|
||||
//
|
||||
#define BEGIN_API_CALLER_FUNC(ret_type, args_type_code) \
|
||||
void * DLLINTERNAL _COMBINE4(api_caller_, ret_type, _args_, args_type_code)(const void * func, const void * packed_args) { \
|
||||
_COMBINE2(pack_args_type_, args_type_code) * p ATTRIBUTE(unused)= (_COMBINE2(pack_args_type_, args_type_code) *)packed_args;
|
||||
#define END_API_CALLER_FUNC(ret_t, args_t, args) \
|
||||
API_PAUSE_TSC_TRACKING(); \
|
||||
return(*(void **)class_ret_t((*(( ret_t (*) args_t )func)) args).getptr()); \
|
||||
}
|
||||
#define END_API_CALLER_FUNC_void(args_t, args) \
|
||||
API_PAUSE_TSC_TRACKING(); \
|
||||
return((*(( void* (*) args_t )func)) args); \
|
||||
}
|
||||
|
||||
//
|
||||
// API function callers.
|
||||
//
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, ipV)
|
||||
END_API_CALLER_FUNC_void( (int, const void*, ...), (p->i1, p->p1, p->str) )
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pV)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, ...), (p->p1, p->p2, p->str) )
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, void)
|
||||
END_API_CALLER_FUNC_void( (void), () )
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, void)
|
||||
END_API_CALLER_FUNC(void*, (void), () )
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, void)
|
||||
END_API_CALLER_FUNC(int, (void), () )
|
||||
|
||||
BEGIN_API_CALLER_FUNC(float, void)
|
||||
END_API_CALLER_FUNC(float, (void), () )
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(float, 2f)
|
||||
END_API_CALLER_FUNC( float, (float, float), (p->f1, p->f2) )
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2i)
|
||||
END_API_CALLER_FUNC_void( (int, int), (p->i1, p->i2) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 2i)
|
||||
END_API_CALLER_FUNC(int, (int, int), (p->i1, p->i2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2i2p)
|
||||
END_API_CALLER_FUNC_void( (int, int, const void*, const void*), (p->i1, p->i2, p->p1, p->p2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2i2pi2p)
|
||||
END_API_CALLER_FUNC_void( (int, int, const void*, const void*, int, const void*, const void*), (p->i1, p->i2, p->p1, p->p2, p->i3, p->p3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*), (p->p1, p->p2) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, 2p)
|
||||
END_API_CALLER_FUNC(void*, (const void*, const void*), (p->p1, p->p2) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 2p)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*), (p->p1, p->p2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2p2f)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, float, float), (p->p1, p->p2, p->f1, p->f2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2p2i2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, int, int, const void*, const void*), (p->p1, p->p2, p->i1, p->i2, p->p3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2p3fus2uc)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, float, float, float, unsigned short, unsigned char, unsigned char), (p->p1, p->p2, p->f1, p->f2, p->f3, p->us1, p->uc1, p->uc2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(ptr, 2pf)
|
||||
END_API_CALLER_FUNC(void*, (const void*, const void*, float), (p->p1, p->p2, p->f1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pfi)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, float, int), (p->p1, p->p2, p->f1, p->i1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pi)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, int), (p->p1, p->p2, p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 2pi)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*, int), (p->p1, p->p2, p->i1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pui)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, unsigned int), (p->p1, p->p2, p->ui1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pi2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, int, const void*, const void*), (p->p1, p->p2, p->i1, p->p3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pif2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, int, float, const void*, const void*), (p->p1, p->p2, p->i1, p->f1, p->p3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(int, 3i)
|
||||
END_API_CALLER_FUNC(int, (int, int, int), (p->i1, p->i2, p->i3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 3p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*), (p->p1, p->p2, p->p3) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, 3p)
|
||||
END_API_CALLER_FUNC(void*, (const void*, const void*, const void*), (p->p1, p->p2, p->p3) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 3p)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*), (p->p1, p->p2, p->p3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 3p2f2i)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*, float, float, int, int), (p->p1, p->p2, p->p3, p->f1, p->f2, p->i1, p->i2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(int, 3pi2p)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*, int, const void*, const void*), (p->p1, p->p2, p->p3, p->i1, p->p4, p->p5) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 4p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*, const void*), (p->p1, p->p2, p->p3, p->p4) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 4p)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*, const void*), (p->p1, p->p2, p->p3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 4pi)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*, const void*, int), (p->p1, p->p2, p->p3, p->p4, p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 4pi)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*, const void*, int), (p->p1, p->p2, p->p3, p->p4, p->i1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, f)
|
||||
END_API_CALLER_FUNC_void( (float), (p->f1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, i)
|
||||
END_API_CALLER_FUNC_void( (int), (p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, i)
|
||||
END_API_CALLER_FUNC(int, (int), (p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, i)
|
||||
END_API_CALLER_FUNC(void*, (int), (p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(uint, ui)
|
||||
END_API_CALLER_FUNC(unsigned int, (unsigned int), (p->ui1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, ui)
|
||||
END_API_CALLER_FUNC(void*, (unsigned int), (p->ui1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(ulong, ul)
|
||||
END_API_CALLER_FUNC(unsigned long, (unsigned long), (p->ul1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, i2p)
|
||||
END_API_CALLER_FUNC_void( (int, const void*, const void*), (p->i1, p->p1, p->p2) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, i2p)
|
||||
END_API_CALLER_FUNC(int, (int, const void*, const void*), (p->i1, p->p1, p->p2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, i3p)
|
||||
END_API_CALLER_FUNC_void( (int, const void*, const void*, const void*), (p->i1, p->p1, p->p2, p->p3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, ip)
|
||||
END_API_CALLER_FUNC_void( (int, const void*), (p->i1, p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ushort, ip)
|
||||
END_API_CALLER_FUNC( unsigned short, (int, const void*), (p->i1, p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, ip)
|
||||
END_API_CALLER_FUNC( int, (int, const void*), (p->i1, p->p1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, ipusf2p2f4i)
|
||||
END_API_CALLER_FUNC_void( (int, const void*, unsigned short, float, const void*, const void*, float, float, int, int, int, int), (p->i1, p->p1, p->us1, p->f1, p->p2, p->p3, p->f2, p->f3, p->i2, p->i3, p->i4, p->i5) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, p)
|
||||
END_API_CALLER_FUNC_void( (const void*), (p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, p)
|
||||
END_API_CALLER_FUNC(void*, (const void*), (p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(char, p)
|
||||
END_API_CALLER_FUNC(char, (const void*), (p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, p)
|
||||
END_API_CALLER_FUNC(int, (const void*), (p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(uint, p)
|
||||
END_API_CALLER_FUNC(unsigned int, (const void*), (p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(float, p)
|
||||
END_API_CALLER_FUNC(float, (const void*), (p->p1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, p2f)
|
||||
END_API_CALLER_FUNC_void( (const void*, float, float), (p->p1, p->f1, p->f2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(int, p2fi)
|
||||
END_API_CALLER_FUNC(int, (const void*, float, float, int), (p->p1, p->f1, p->f2, p->i1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, p2i)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, int), (p->p1, p->i1, p->i2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, p3i)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, int, int), (p->p1, p->i1, p->i2, p->i3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, p4i)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, int, int, int), (p->p1, p->i1, p->i2, p->i3, p->i4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, puc)
|
||||
END_API_CALLER_FUNC_void( (const void*, unsigned char), (p->p1, p->uc1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pf)
|
||||
END_API_CALLER_FUNC_void( (const void*, float), (p->p1, p->f1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pfp)
|
||||
END_API_CALLER_FUNC_void( (const void*, float, const void*), (p->p1, p->f1, p->p2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pi)
|
||||
END_API_CALLER_FUNC_void( (const void*, int), (p->p1, p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, pi)
|
||||
END_API_CALLER_FUNC(void*, (const void*, int), (p->p1, p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, pi)
|
||||
END_API_CALLER_FUNC(int, (const void*, int), (p->p1, p->i1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pi2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, const void*, const void*), (p->p1, p->i1, p->p2, p->p3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(int, pi2p2ip)
|
||||
END_API_CALLER_FUNC(int, (const void*, int, const void*, const void*, int, int, const void*), (p->p1, p->i1, p->p2, p->p3, p->i2, p->i3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pip)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, const void*), (p->p1, p->i1, p->p2) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, pip)
|
||||
END_API_CALLER_FUNC(void*, (const void*, int, const void*), (p->p1, p->i1, p->p2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pip2f2i)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, const void*, float, float, int, int), (p->p1, p->i1, p->p2, p->f1, p->f2, p->i2, p->i3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pip2f4i2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, const void*, float, float, int, int, int, int, const void*, const void*), (p->p1, p->i1, p->p2, p->f1, p->f2, p->i2, p->i3, p->i4, p->i5, p->p3, p->p4) );
|
||||
397
src/metamod/api_hook.h
Normal file
397
src/metamod/api_hook.h
Normal file
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
||||
*
|
||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
#ifndef API_HOOK_H
|
||||
#define API_HOOK_H
|
||||
|
||||
#include "ret_type.h"
|
||||
#include "api_info.h"
|
||||
#include "meta_api.h"
|
||||
#include "osdep.h" //OPEN_ARGS
|
||||
|
||||
// Compine 4 parts for single name
|
||||
#define _COMBINE4(w,x,y,z) w##x##y##z
|
||||
#define _COMBINE2(x,y) x##y
|
||||
|
||||
// simplified 'void' version of main hook function
|
||||
void DLLINTERNAL main_hook_function_void(unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void * packed_args);
|
||||
|
||||
// full return typed version of main hook function
|
||||
void * DLLINTERNAL main_hook_function(const class_ret_t ret_init, unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void * packed_args);
|
||||
|
||||
//
|
||||
// API function args structures/classes
|
||||
//
|
||||
#define API_PACK_ARGS(type, args) \
|
||||
_COMBINE2(pack_args_type_, type) packed_args args;
|
||||
|
||||
#define PACK_ARGS_CLASS_HEADER(type, constructor_args) \
|
||||
class _COMBINE2(pack_args_type_, type) : public class_metamod_new { \
|
||||
public: inline _COMBINE2(pack_args_type_, type) constructor_args
|
||||
|
||||
#define PACK_ARGS_END };
|
||||
|
||||
#define VOID_ARG 0
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(void, (int)) {};
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(i, (int _i1)): i1(_i1) {};
|
||||
int i1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2i, (int _i1, int _i2)): i1(_i1), i2(_i2) {};
|
||||
int i1,i2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(3i, (int _i1, int _i2, int _i3)): i1(_i1), i2(_i2), i3(_i3) {};
|
||||
int i1,i2,i3;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(ui, (unsigned int _ui1)): ui1(_ui1) {};
|
||||
unsigned int ui1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(ul, (unsigned long _ul1)): ul1(_ul1) {};
|
||||
unsigned long ul1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(f, (float _f1)): f1(_f1) {};
|
||||
float f1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2f, (float _f1, float _f2)): f1(_f1), f2(_f2) {};
|
||||
float f1,f2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(p, (const void *_p1)): p1(_p1) {};
|
||||
const void *p1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2p, (const void *_p1, const void *_p2)): p1(_p1), p2(_p2) {};
|
||||
const void *p1,*p2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(3p, (const void *_p1, const void *_p2, const void *_p3)): p1(_p1), p2(_p2), p3(_p3) {};
|
||||
const void *p1,*p2,*p3;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(4p, (const void *_p1, const void *_p2, const void *_p3, const void *_p4)): p1(_p1), p2(_p2), p3(_p3), p4(_p4) {};
|
||||
const void *p1,*p2,*p3,*p4;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2pV, (const void *_p1, const void *_p2, const void *_str)): p1(_p1), p2(_p2), str(_str) {};
|
||||
const void *p1,*p2,*str;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(ipV, (int _i1, const void *_p1, const void *_str)): i1(_i1), p1(_p1), str(_str) {};
|
||||
int i1;
|
||||
const void *p1,*str;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2i2p, (int _i1, int _i2, const void *_p1, const void *_p2)): i1(_i1), i2(_i2), p1(_p1), p2(_p2) {};
|
||||
int i1,i2;
|
||||
const void *p1,*p2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2p2f, (const void *_p1, const void *_p2, float _f1, float _f2)): p1(_p1), p2(_p2), f1(_f1), f2(_f2) {};
|
||||
const void *p1,*p2;
|
||||
float f1,f2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2p2i2p, (const void *_p1, const void *_p2, int _i1, int _i2, const void *_p3, const void *_p4)): p1(_p1), p2(_p2), i1(_i1), i2(_i2), p3(_p3), p4(_p4) {};
|
||||
const void *p1,*p2;
|
||||
int i1,i2;
|
||||
const void *p3,*p4;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2p3fus2uc, (const void *_p1, const void *_p2, float _f1, float _f2, float _f3, unsigned short _us1, unsigned char _uc1, unsigned char _uc2)): p1(_p1), p2(_p2), f1(_f1), f2(_f2), f3(_f3), us1(_us1), uc1(_uc1), uc2(_uc2) {};
|
||||
const void *p1,*p2;
|
||||
float f1,f2,f3;
|
||||
unsigned int us1;
|
||||
unsigned int uc1,uc2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2pf, (const void *_p1, const void *_p2, float _f1)): p1(_p1), p2(_p2), f1(_f1) {};
|
||||
const void *p1,*p2;
|
||||
float f1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2pfi, (const void *_p1, const void *_p2, float _f1, int _i1)): p1(_p1), p2(_p2), f1(_f1), i1(_i1) {};
|
||||
const void *p1,*p2;
|
||||
float f1;
|
||||
int i1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2pi, (const void *_p1, const void *_p2, int _i1)): p1(_p1), p2(_p2), i1(_i1) {};
|
||||
const void *p1,*p2;
|
||||
int i1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2pi2p, (const void *_p1, const void *_p2, int _i1, const void *_p3, const void *_p4)): p1(_p1), p2(_p2), i1(_i1), p3(_p3), p4(_p4) {};
|
||||
const void *p1,*p2;
|
||||
int i1;
|
||||
const void *p3,*p4;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2pif2p, (const void *_p1, const void *_p2, int _i1, float _f1, const void *_p3, const void *_p4)): p1(_p1), p2(_p2), i1(_i1), f1(_f1), p3(_p3), p4(_p4) {};
|
||||
const void *p1,*p2;
|
||||
int i1;
|
||||
float f1;
|
||||
const void *p3,*p4;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(3p2f2i, (const void *_p1, const void *_p2, const void *_p3, float _f1, float _f2, int _i1, int _i2)): p1(_p1), p2(_p2), p3(_p3), f1(_f1), f2(_f2), i1(_i1), i2(_i2) {};
|
||||
const void *p1,*p2,*p3;
|
||||
float f1,f2;
|
||||
int i1,i2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(3pi2p, (const void *_p1, const void *_p2, const void *_p3, int _i1, const void *_p4, const void *_p5)): p1(_p1), p2(_p2), p3(_p3), i1(_i1), p4(_p4), p5(_p5) {};
|
||||
const void *p1,*p2,*p3;
|
||||
int i1;
|
||||
const void *p4,*p5;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(i3p, (int _i1, const void *_p1, const void *_p2, const void *_p3)): i1(_i1), p1(_p1), p2(_p2), p3(_p3) {};
|
||||
int i1;
|
||||
const void *p1,*p2,*p3;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(ip, (int _i1, const void *_p1)): i1(_i1), p1(_p1) {};
|
||||
int i1;
|
||||
const void *p1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(ipusf2p2f4i, (int _i1, const void *_p1, unsigned short _us1, float _f1, const void *_p2, const void *_p3, float _f2, float _f3, int _i2, int _i3, int _i4, int _i5)): i1(_i1), p1(_p1), us1(_us1), f1(_f1), p2(_p2), p3(_p3), f2(_f2), f3(_f3), i2(_i2), i3(_i3), i4(_i4), i5(_i5) {};
|
||||
int i1;
|
||||
const void *p1;
|
||||
unsigned int us1;
|
||||
float f1;
|
||||
const void *p2,*p3;
|
||||
float f2,f3;
|
||||
int i2,i3,i4,i5;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(3pi, (const void *_p1, const void *_p2, const void *_p3, int _i1)): p1(_p1), p2(_p2), p3(_p3), i1(_i1) {};
|
||||
const void *p1,*p2,*p3;
|
||||
int i1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(4pi, (const void *_p1, const void *_p2, const void *_p3, const void *_p4, int _i1)): p1(_p1), p2(_p2), p3(_p3), p4(_p4), i1(_i1) {};
|
||||
const void *p1,*p2,*p3,*p4;
|
||||
int i1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(pf, (const void *_p1, float _f1)): p1(_p1), f1(_f1) {};
|
||||
const void *p1;
|
||||
float f1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(pfp, (const void *_p1, float _f1, const void *_p2)): p1(_p1), f1(_f1), p2(_p2) {};
|
||||
const void *p1;
|
||||
float f1;
|
||||
const void *p2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(pi, (const void *_p1, int _i1)): p1(_p1), i1(_i1) {};
|
||||
const void *p1;
|
||||
int i1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(pi2p, (const void *_p1, int _i1, const void *_p2, const void *_p3)): p1(_p1), i1(_i1), p2(_p2), p3(_p3) {};
|
||||
const void *p1;
|
||||
int i1;
|
||||
const void *p2, *p3;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(pip, (const void *_p1, int _i1, const void *_p2)): p1(_p1), i1(_i1), p2(_p2) {};
|
||||
const void *p1;
|
||||
int i1;
|
||||
const void *p2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(pip2f2i, (const void *_p1, int _i1, const void *_p2, float _f1, float _f2, int _i2, int _i3)): p1(_p1), i1(_i1), p2(_p2), f1(_f1), f2(_f2), i2(_i2), i3(_i3) {};
|
||||
const void *p1;
|
||||
int i1;
|
||||
const void *p2;
|
||||
float f1,f2;
|
||||
int i2,i3;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(pip2f4i2p, (const void *_p1, int _i1, const void *_p2, float _f1, float _f2, int _i2, int _i3, int _i4, int _i5, const void *_p3, const void *_p4)): p1(_p1), i1(_i1), p2(_p2), f1(_f1), f2(_f2), i2(_i2), i3(_i3), i4(_i4), i5(_i5), p3(_p3), p4(_p4) {};
|
||||
const void *p1;
|
||||
int i1;
|
||||
const void *p2;
|
||||
float f1,f2;
|
||||
int i2,i3,i4,i5;
|
||||
const void *p3,*p4;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(puc, (const void *_p1, unsigned char _uc1)): p1(_p1), uc1(_uc1) {};
|
||||
const void *p1;
|
||||
unsigned int uc1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2i2pi2p, (int _i1, int _i2, const void *_p1, const void *_p2, int _i3, const void *_p3, const void *_p4)): i1(_i1), i2(_i2), p1(_p1), p2(_p2), i3(_i3), p3(_p3), p4(_p4) {};
|
||||
int i1,i2;
|
||||
const void *p1,*p2;
|
||||
int i3;
|
||||
const void *p3,*p4;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(2pui, (const void *_p1, const void *_p2, unsigned int _ui1)): p1(_p1), p2(_p2), ui1(_ui1) {};
|
||||
const void *p1,*p2;
|
||||
unsigned int ui1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(i2p, (int _i1, const void *_p1, const void *_p2)): i1(_i1), p1(_p1), p2(_p2) {};
|
||||
int i1;
|
||||
const void *p1,*p2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(p2f, (const void *_p1, float _f1, float _f2)): p1(_p1), f1(_f1), f2(_f2) {};
|
||||
const void *p1;
|
||||
float f1,f2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(p2fi, (const void *_p1, float _f1, float _f2, int _i1)): p1(_p1), f1(_f1), f2(_f2), i1(_i1) {};
|
||||
const void *p1;
|
||||
float f1,f2;
|
||||
int i1;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(p2i, (const void *_p1, int _i1, int _i2)): p1(_p1), i1(_i1), i2(_i2) {};
|
||||
const void *p1;
|
||||
int i1,i2;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(p3i, (const void *_p1, int _i1, int _i2, int _i3)): p1(_p1), i1(_i1), i2(_i2), i3(_i3) {};
|
||||
const void *p1;
|
||||
int i1,i2,i3;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(p4i, (const void *_p1, int _i1, int _i2, int _i3, int _i4)): p1(_p1), i1(_i1), i2(_i2), i3(_i3), i4(_i4) {};
|
||||
const void *p1;
|
||||
int i1,i2,i3,i4;
|
||||
PACK_ARGS_END
|
||||
|
||||
PACK_ARGS_CLASS_HEADER(pi2p2ip, (const void *_p1, int _i1, const void *_p2, const void *_p3, int _i2, int _i3, const void *_p4)): p1(_p1), i1(_i1), p2(_p2), p3(_p3), i2(_i2), i3(_i3), p4(_p4) {};
|
||||
const void *p1;
|
||||
int i1;
|
||||
const void *p2,*p3;
|
||||
int i2,i3;
|
||||
const void *p4;
|
||||
PACK_ARGS_END
|
||||
|
||||
//
|
||||
// API function callers.
|
||||
//
|
||||
#ifdef __METAMOD_BUILD__
|
||||
#define EXTERN_API_CALLER_FUNCTION(ret_type, args_code) \
|
||||
void * DLLINTERNAL _COMBINE4(api_caller_, ret_type, _args_, args_code)(const void * func, const void * packed_args)
|
||||
#else
|
||||
#define EXTERN_API_CALLER_FUNCTION(ret_type, args_code) \
|
||||
static const api_caller_func_t _COMBINE4(api_caller_, ret_type, _args_, args_code) DLLHIDDEN = (api_caller_func_t)0
|
||||
#endif
|
||||
|
||||
EXTERN_API_CALLER_FUNCTION(void, ipV);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2pV);
|
||||
EXTERN_API_CALLER_FUNCTION(void, void);
|
||||
EXTERN_API_CALLER_FUNCTION(ptr, void);
|
||||
EXTERN_API_CALLER_FUNCTION(int, void);
|
||||
EXTERN_API_CALLER_FUNCTION(float, void);
|
||||
EXTERN_API_CALLER_FUNCTION(float, 2f);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2i);
|
||||
EXTERN_API_CALLER_FUNCTION(int, 2i);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2i2p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2i2pi2p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2p);
|
||||
EXTERN_API_CALLER_FUNCTION(ptr, 2p);
|
||||
EXTERN_API_CALLER_FUNCTION(int, 2p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2p2f);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2p2i2p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2p3fus2uc);
|
||||
EXTERN_API_CALLER_FUNCTION(ptr, 2pf);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2pfi);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2pi);
|
||||
EXTERN_API_CALLER_FUNCTION(int, 2pi);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2pui);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2pi2p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 2pif2p);
|
||||
EXTERN_API_CALLER_FUNCTION(int, 3i);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 3p);
|
||||
EXTERN_API_CALLER_FUNCTION(ptr, 3p);
|
||||
EXTERN_API_CALLER_FUNCTION(int, 3p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 3p2f2i);
|
||||
EXTERN_API_CALLER_FUNCTION(int, 3pi2p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 4p);
|
||||
EXTERN_API_CALLER_FUNCTION(int, 4p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, 4pi);
|
||||
EXTERN_API_CALLER_FUNCTION(int, 4pi);
|
||||
EXTERN_API_CALLER_FUNCTION(void, f);
|
||||
EXTERN_API_CALLER_FUNCTION(void, i);
|
||||
EXTERN_API_CALLER_FUNCTION(ptr, i);
|
||||
EXTERN_API_CALLER_FUNCTION(int, i);
|
||||
EXTERN_API_CALLER_FUNCTION(ptr, ui);
|
||||
EXTERN_API_CALLER_FUNCTION(uint, ui);
|
||||
EXTERN_API_CALLER_FUNCTION(ulong, ul);
|
||||
EXTERN_API_CALLER_FUNCTION(void, i2p);
|
||||
EXTERN_API_CALLER_FUNCTION(int, i2p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, i3p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, ip);
|
||||
EXTERN_API_CALLER_FUNCTION(ushort, ip);
|
||||
EXTERN_API_CALLER_FUNCTION(int, ip);
|
||||
EXTERN_API_CALLER_FUNCTION(void, ipusf2p2f4i);
|
||||
EXTERN_API_CALLER_FUNCTION(void, p);
|
||||
EXTERN_API_CALLER_FUNCTION(ptr, p);
|
||||
EXTERN_API_CALLER_FUNCTION(char, p);
|
||||
EXTERN_API_CALLER_FUNCTION(int, p);
|
||||
EXTERN_API_CALLER_FUNCTION(uint, p);
|
||||
EXTERN_API_CALLER_FUNCTION(float, p);
|
||||
EXTERN_API_CALLER_FUNCTION(void, p2f);
|
||||
EXTERN_API_CALLER_FUNCTION(int, p2fi);
|
||||
EXTERN_API_CALLER_FUNCTION(void, p2i);
|
||||
EXTERN_API_CALLER_FUNCTION(void, p3i);
|
||||
EXTERN_API_CALLER_FUNCTION(void, p4i);
|
||||
EXTERN_API_CALLER_FUNCTION(void, puc);
|
||||
EXTERN_API_CALLER_FUNCTION(void, pf);
|
||||
EXTERN_API_CALLER_FUNCTION(void, pfp);
|
||||
EXTERN_API_CALLER_FUNCTION(void, pi);
|
||||
EXTERN_API_CALLER_FUNCTION(ptr, pi);
|
||||
EXTERN_API_CALLER_FUNCTION(int, pi);
|
||||
EXTERN_API_CALLER_FUNCTION(void, pi2p);
|
||||
EXTERN_API_CALLER_FUNCTION(int, pi2p2ip);
|
||||
EXTERN_API_CALLER_FUNCTION(void, pip);
|
||||
EXTERN_API_CALLER_FUNCTION(ptr, pip);
|
||||
EXTERN_API_CALLER_FUNCTION(void, pip2f2i);
|
||||
EXTERN_API_CALLER_FUNCTION(void, pip2f4i2p);
|
||||
|
||||
#endif /*API_HOOK_H*/
|
||||
275
src/metamod/api_info.cpp
Normal file
275
src/metamod/api_info.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// api_info.cpp - info for api routines
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "api_info.h" // me
|
||||
#include "api_hook.h"
|
||||
|
||||
// trace flag, loglevel, name
|
||||
const dllapi_info_t dllapi_info = {
|
||||
{ mFALSE, 3, api_caller_void_args_void, "GameDLLInit" }, // pfnGameInit
|
||||
{ mFALSE, 10, api_caller_int_args_p, "DispatchSpawn" }, // pfnSpawn
|
||||
{ mFALSE, 16, api_caller_void_args_p, "DispatchThink" }, // pfnThink
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "DispatchUse" }, // pfnUse
|
||||
{ mFALSE, 11, api_caller_void_args_2p, "DispatchTouch" }, // pfnTouch
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "DispatchBlocked" }, // pfnBlocked
|
||||
{ mFALSE, 10, api_caller_void_args_2p, "DispatchKeyValue" }, // pfnKeyValue
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "DispatchSave" }, // pfnSave
|
||||
{ mFALSE, 9, api_caller_int_args_2pi, "DispatchRestore" }, // pfnRestore
|
||||
{ mFALSE, 20, api_caller_void_args_p, "DispatchObjectCollsionBox" }, // pfnSetAbsBox
|
||||
{ mFALSE, 9, api_caller_void_args_4pi, "SaveWriteFields" }, // pfnSaveWriteFields
|
||||
{ mFALSE, 9, api_caller_void_args_4pi, "SaveReadFields" }, // pfnSaveReadFields
|
||||
{ mFALSE, 9, api_caller_void_args_p, "SaveGlobalState" }, // pfnSaveGlobalState
|
||||
{ mFALSE, 9, api_caller_void_args_p, "RestoreGlobalState" }, // pfnRestoreGlobalState
|
||||
{ mFALSE, 9, api_caller_void_args_void, "ResetGlobalState" }, // pfnResetGlobalState
|
||||
{ mFALSE, 3, api_caller_int_args_4p, "ClientConnect" }, // pfnClientConnect
|
||||
{ mFALSE, 3, api_caller_void_args_p, "ClientDisconnect" }, // pfnClientDisconnect
|
||||
{ mFALSE, 3, api_caller_void_args_p, "ClientKill" }, // pfnClientKill
|
||||
{ mFALSE, 3, api_caller_void_args_p, "ClientPutInServer" }, // pfnClientPutInServer
|
||||
{ mFALSE, 9, api_caller_void_args_p, "ClientCommand" }, // pfnClientCommand
|
||||
{ mFALSE, 11, api_caller_void_args_2p, "ClientUserInfoChanged" }, // pfnClientUserInfoChanged
|
||||
{ mFALSE, 3, api_caller_void_args_p2i, "ServerActivate" }, // pfnServerActivate
|
||||
{ mFALSE, 3, api_caller_void_args_void, "ServerDeactivate" }, // pfnServerDeactivate
|
||||
{ mFALSE, 14, api_caller_void_args_p, "PlayerPreThink" }, // pfnPlayerPreThink
|
||||
{ mFALSE, 14, api_caller_void_args_p, "PlayerPostThink" }, // pfnPlayerPostThink
|
||||
{ mFALSE, 18, api_caller_void_args_void, "StartFrame" }, // pfnStartFrame
|
||||
{ mFALSE, 9, api_caller_void_args_void, "ParmsNewLevel" }, // pfnParmsNewLevel
|
||||
{ mFALSE, 9, api_caller_void_args_void, "ParmsChangeLevel" }, // pfnParmsChangeLevel
|
||||
{ mFALSE, 9, api_caller_ptr_args_void, "GetGameDescription" }, // pfnGetGameDescription
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "PlayerCustomization" }, // pfnPlayerCustomization
|
||||
{ mFALSE, 9, api_caller_void_args_p, "SpectatorConnect" }, // pfnSpectatorConnect
|
||||
{ mFALSE, 9, api_caller_void_args_p, "SpectatorDisconnect" }, // pfnSpectatorDisconnect
|
||||
{ mFALSE, 9, api_caller_void_args_p, "SpectatorThink" }, // pfnSpectatorThink
|
||||
{ mFALSE, 3, api_caller_void_args_p, "Sys_Error" }, // pfnSys_Error
|
||||
{ mFALSE, 13, api_caller_void_args_pi, "PM_Move" }, // pfnPM_Move
|
||||
{ mFALSE, 9, api_caller_void_args_p, "PM_Init" }, // pfnPM_Init
|
||||
{ mFALSE, 9, api_caller_char_args_p, "PM_FindTextureType" }, // pfnPM_FindTextureType
|
||||
{ mFALSE, 12, api_caller_void_args_4p, "SetupVisibility" }, // pfnSetupVisibility
|
||||
{ mFALSE, 12, api_caller_void_args_pip, "UpdateClientData" }, // pfnUpdateClientData
|
||||
{ mFALSE, 16, api_caller_int_args_pi2p2ip, "AddToFullPack" }, // pfnAddToFullPack
|
||||
{ mFALSE, 9, api_caller_void_args_2i2pi2p, "CreateBaseline" }, // pfnCreateBaseline
|
||||
{ mFALSE, 9, api_caller_void_args_void, "RegisterEncoders" }, // pfnRegisterEncoders
|
||||
{ mFALSE, 9, api_caller_int_args_2p, "GetWeaponData" }, // pfnGetWeaponData
|
||||
{ mFALSE, 15, api_caller_void_args_2pui, "CmdStart" }, // pfnCmdStart
|
||||
{ mFALSE, 15, api_caller_void_args_p, "CmdEnd" }, // pfnCmdEnd
|
||||
{ mFALSE, 9, api_caller_int_args_4p, "ConnectionlessPacket" }, // pfnConnectionlessPacket
|
||||
{ mFALSE, 9, api_caller_int_args_i2p, "GetHullBounds" }, // pfnGetHullBounds
|
||||
{ mFALSE, 9, api_caller_void_args_void, "CreateInstancedBaselines" }, // pfnCreateInstancedBaselines
|
||||
{ mFALSE, 3, api_caller_int_args_3p, "InconsistentFile" }, // pfnInconsistentFile
|
||||
{ mFALSE, 20, api_caller_int_args_void, "AllowLagCompensation" }, // pfnAllowLagCompensation
|
||||
{ mFALSE, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
const newapi_info_t newapi_info = {
|
||||
{ mFALSE, 16, api_caller_void_args_p, "OnFreeEntPrivateData" }, // pfnOnFreeEntPrivateData
|
||||
{ mFALSE, 3, api_caller_void_args_void, "GameShutdown" }, // pfnGameShutdown
|
||||
{ mFALSE, 14, api_caller_int_args_2p, "ShouldCollide" }, // pfnShouldCollide
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
{ mFALSE, 3, api_caller_void_args_2p, "CvarValue" }, // pfnCvarValue
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
{ mFALSE, 3, api_caller_void_args_pi2p, "CvarValue2" }, // pfnCvarValue2
|
||||
{ mFALSE, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
const engine_info_t engine_info = {
|
||||
{ mFALSE, 13, api_caller_int_args_p, "PrecacheModel" }, // pfnPrecacheModel
|
||||
{ mFALSE, 13, api_caller_int_args_p, "PrecacheSound" }, // pfnPrecacheSound
|
||||
{ mFALSE, 18, api_caller_void_args_2p, "SetModel" }, // pfnSetModel
|
||||
{ mFALSE, 34, api_caller_int_args_p, "ModelIndex" }, // pfnModelIndex
|
||||
{ mFALSE, 10, api_caller_int_args_i, "ModelFrames" }, // pfnModelFrames
|
||||
{ mFALSE, 14, api_caller_void_args_3p, "SetSize" }, // pfnSetSize
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "ChangeLevel" }, // pfnChangeLevel
|
||||
{ mFALSE, 9, api_caller_void_args_p, "GetSpawnParms" }, // pfnGetSpawnParms
|
||||
{ mFALSE, 9, api_caller_void_args_p, "SaveSpawnParms" }, // pfnSaveSpawnParms
|
||||
{ mFALSE, 9, api_caller_float_args_p, "VecToYaw" }, // pfnVecToYaw
|
||||
{ mFALSE, 14, api_caller_void_args_2p, "VecToAngles" }, // pfnVecToAngles
|
||||
{ mFALSE, 9, api_caller_void_args_2pfi, "MoveToOrigin" }, // pfnMoveToOrigin
|
||||
{ mFALSE, 9, api_caller_void_args_p, "ChangeYaw" }, // pfnChangeYaw
|
||||
{ mFALSE, 9, api_caller_void_args_p, "ChangePitch" }, // pfnChangePitch
|
||||
{ mFALSE, 32, api_caller_ptr_args_3p, "FindEntityByString" }, // pfnFindEntityByString
|
||||
{ mFALSE, 9, api_caller_int_args_p, "GetEntityIllum" }, // pfnGetEntityIllum
|
||||
{ mFALSE, 9, api_caller_ptr_args_2pf, "FindEntityInSphere" }, // pfnFindEntityInSphere
|
||||
{ mFALSE, 19, api_caller_ptr_args_p, "FindClientInPVS" }, // pfnFindClientInPVS
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "EntitiesInPVS" }, // pfnEntitiesInPVS
|
||||
{ mFALSE, 40, api_caller_void_args_p, "MakeVectors" }, // pfnMakeVectors
|
||||
{ mFALSE, 9, api_caller_void_args_4p, "AngleVectors" }, // pfnAngleVectors
|
||||
{ mFALSE, 13, api_caller_ptr_args_void, "CreateEntity" }, // pfnCreateEntity
|
||||
{ mFALSE, 13, api_caller_void_args_p, "RemoveEntity" }, // pfnRemoveEntity
|
||||
{ mFALSE, 13, api_caller_ptr_args_i, "CreateNamedEntity" }, // pfnCreateNamedEntity
|
||||
{ mFALSE, 9, api_caller_void_args_p, "MakeStatic" }, // pfnMakeStatic
|
||||
{ mFALSE, 9, api_caller_int_args_p, "EntIsOnFloor" }, // pfnEntIsOnFloor
|
||||
{ mFALSE, 9, api_caller_int_args_p, "DropToFloor" }, // pfnDropToFloor
|
||||
{ mFALSE, 9, api_caller_int_args_p2fi, "WalkMove" }, // pfnWalkMove
|
||||
{ mFALSE, 14, api_caller_void_args_2p, "SetOrigin" }, // pfnSetOrigin
|
||||
{ mFALSE, 12, api_caller_void_args_pip2f2i, "EmitSound" }, // pfnEmitSound
|
||||
{ mFALSE, 12, api_caller_void_args_3p2f2i, "EmitAmbientSound" }, // pfnEmitAmbientSound
|
||||
{ mFALSE, 20, api_caller_void_args_2pi2p, "TraceLine" }, // pfnTraceLine
|
||||
{ mFALSE, 9, api_caller_void_args_3p, "TraceToss" }, // pfnTraceToss
|
||||
{ mFALSE, 9, api_caller_int_args_3pi2p, "TraceMonsterHull" }, // pfnTraceMonsterHull
|
||||
{ mFALSE, 9, api_caller_void_args_2p2i2p, "TraceHull" }, // pfnTraceHull
|
||||
{ mFALSE, 9, api_caller_void_args_2pi2p, "TraceModel" }, // pfnTraceModel
|
||||
{ mFALSE, 15, api_caller_ptr_args_3p, "TraceTexture" }, // pfnTraceTexture // CS: when moving
|
||||
{ mFALSE, 9, api_caller_void_args_2pif2p, "TraceSphere" }, // pfnTraceSphere
|
||||
{ mFALSE, 9, api_caller_void_args_pfp, "GetAimVector" }, // pfnGetAimVector
|
||||
{ mFALSE, 9, api_caller_void_args_p, "ServerCommand" }, // pfnServerCommand
|
||||
{ mFALSE, 9, api_caller_void_args_void, "ServerExecute" }, // pfnServerExecute
|
||||
{ mFALSE, 11, api_caller_void_args_2pV, "engClientCommand" }, // pfnClientCommand // d'oh, ClientCommand in dllapi too
|
||||
{ mFALSE, 9, api_caller_void_args_2p2f, "ParticleEffect" }, // pfnParticleEffect
|
||||
{ mFALSE, 9, api_caller_void_args_ip, "LightStyle" }, // pfnLightStyle
|
||||
{ mFALSE, 9, api_caller_int_args_p, "DecalIndex" }, // pfnDecalIndex
|
||||
{ mFALSE, 15, api_caller_int_args_p, "PointContents" }, // pfnPointContents // CS: when moving
|
||||
{ mFALSE, 22, api_caller_void_args_2i2p, "MessageBegin" }, // pfnMessageBegin
|
||||
{ mFALSE, 22, api_caller_void_args_void, "MessageEnd" }, // pfnMessageEnd
|
||||
{ mFALSE, 30, api_caller_void_args_i, "WriteByte" }, // pfnWriteByte
|
||||
{ mFALSE, 23, api_caller_void_args_i, "WriteChar" }, // pfnWriteChar
|
||||
{ mFALSE, 24, api_caller_void_args_i, "WriteShort" }, // pfnWriteShort
|
||||
{ mFALSE, 23, api_caller_void_args_i, "WriteLong" }, // pfnWriteLong
|
||||
{ mFALSE, 23, api_caller_void_args_f, "WriteAngle" }, // pfnWriteAngle
|
||||
{ mFALSE, 23, api_caller_void_args_f, "WriteCoord" }, // pfnWriteCoord
|
||||
{ mFALSE, 25, api_caller_void_args_p, "WriteString" }, // pfnWriteString
|
||||
{ mFALSE, 23, api_caller_void_args_i, "WriteEntity" }, // pfnWriteEntity
|
||||
{ mFALSE, 9, api_caller_void_args_p, "CVarRegister" }, // pfnCVarRegister
|
||||
{ mFALSE, 21, api_caller_float_args_p, "CVarGetFloat" }, // pfnCVarGetFloat
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "CVarGetString" }, // pfnCVarGetString
|
||||
{ mFALSE, 10, api_caller_void_args_pf, "CVarSetFloat" }, // pfnCVarSetFloat
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "CVarSetString" }, // pfnCVarSetString
|
||||
{ mFALSE, 15, api_caller_void_args_ipV, "AlertMessage" }, // pfnAlertMessage
|
||||
{ mFALSE, 17, api_caller_void_args_2pV, "EngineFprintf" }, // pfnEngineFprintf
|
||||
{ mFALSE, 14, api_caller_ptr_args_pi, "PvAllocEntPrivateData" }, // pfnPvAllocEntPrivateData
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "PvEntPrivateData" }, // pfnPvEntPrivateData
|
||||
{ mFALSE, 9, api_caller_void_args_p, "FreeEntPrivateData" }, // pfnFreeEntPrivateData
|
||||
{ mFALSE, 9, api_caller_ptr_args_i, "SzFromIndex" }, // pfnSzFromIndex
|
||||
{ mFALSE, 10, api_caller_int_args_p, "AllocString" }, // pfnAllocString
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "GetVarsOfEnt" }, // pfnGetVarsOfEnt
|
||||
{ mFALSE, 14, api_caller_ptr_args_i, "PEntityOfEntOffset" }, // pfnPEntityOfEntOffset
|
||||
{ mFALSE, 19, api_caller_int_args_p, "EntOffsetOfPEntity" }, // pfnEntOffsetOfPEntity
|
||||
{ mFALSE, 14, api_caller_int_args_p, "IndexOfEdict" }, // pfnIndexOfEdict
|
||||
{ mFALSE, 17, api_caller_ptr_args_i, "PEntityOfEntIndex" }, // pfnPEntityOfEntIndex
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "FindEntityByVars" }, // pfnFindEntityByVars
|
||||
{ mFALSE, 14, api_caller_ptr_args_p, "GetModelPtr" }, // pfnGetModelPtr
|
||||
{ mFALSE, 9, api_caller_int_args_pi, "RegUserMsg" }, // pfnRegUserMsg
|
||||
{ mFALSE, 9, api_caller_void_args_pf, "AnimationAutomove" }, // pfnAnimationAutomove
|
||||
{ mFALSE, 9, api_caller_void_args_pi2p, "GetBonePosition" }, // pfnGetBonePosition
|
||||
{ mFALSE, 9, api_caller_uint_args_p, "FunctionFromName" }, // pfnFunctionFromName
|
||||
{ mFALSE, 9, api_caller_ptr_args_ui, "NameForFunction" }, // pfnNameForFunction
|
||||
{ mFALSE, 9, api_caller_void_args_pip, "ClientPrintf" }, // pfnClientPrintf
|
||||
{ mFALSE, 9, api_caller_void_args_p, "ServerPrint" }, // pfnServerPrint
|
||||
{ mFALSE, 13, api_caller_ptr_args_void, "Cmd_Args" }, // pfnCmd_Args
|
||||
{ mFALSE, 13, api_caller_ptr_args_i, "Cmd_Argv" }, // pfnCmd_Argv
|
||||
{ mFALSE, 13, api_caller_int_args_void, "Cmd_Argc" }, // pfnCmd_Argc
|
||||
{ mFALSE, 9, api_caller_void_args_pi2p, "GetAttachment" }, // pfnGetAttachment
|
||||
{ mFALSE, 9, api_caller_void_args_p, "CRC32_Init" }, // pfnCRC32_Init
|
||||
{ mFALSE, 9, api_caller_void_args_2pi, "CRC32_ProcessBuffer" }, // pfnCRC32_ProcessBuffer
|
||||
{ mFALSE, 9, api_caller_void_args_puc, "CRC32_ProcessByte" }, // pfnCRC32_ProcessByte
|
||||
{ mFALSE, 9, api_caller_ulong_args_ul, "CRC32_Final" }, // pfnCRC32_Final
|
||||
{ mFALSE, 16, api_caller_int_args_2i, "RandomLong" }, // pfnRandomLong
|
||||
{ mFALSE, 14, api_caller_float_args_2f, "RandomFloat" }, // pfnRandomFloat // CS: when firing
|
||||
{ mFALSE, 14, api_caller_void_args_2p, "SetView" }, // pfnSetView
|
||||
{ mFALSE, 9, api_caller_float_args_void, "Time" }, // pfnTime
|
||||
{ mFALSE, 9, api_caller_void_args_p2f, "CrosshairAngle" }, // pfnCrosshairAngle
|
||||
{ mFALSE, 10, api_caller_ptr_args_2p, "LoadFileForMe" }, // pfnLoadFileForMe
|
||||
{ mFALSE, 10, api_caller_void_args_p, "FreeFile" }, // pfnFreeFile
|
||||
{ mFALSE, 9, api_caller_void_args_p, "EndSection" }, // pfnEndSection
|
||||
{ mFALSE, 9, api_caller_int_args_3p, "CompareFileTime" }, // pfnCompareFileTime
|
||||
{ mFALSE, 9, api_caller_void_args_p, "GetGameDir" }, // pfnGetGameDir
|
||||
{ mFALSE, 9, api_caller_void_args_p, "Cvar_RegisterVariable" }, // pfnCvar_RegisterVariable
|
||||
{ mFALSE, 9, api_caller_void_args_p4i, "FadeClientVolume" }, // pfnFadeClientVolume
|
||||
{ mFALSE, 14, api_caller_void_args_pf, "SetClientMaxspeed" }, // pfnSetClientMaxspeed
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "CreateFakeClient" }, // pfnCreateFakeClient
|
||||
{ mFALSE, 9, api_caller_void_args_2p3fus2uc, "RunPlayerMove" }, // pfnRunPlayerMove
|
||||
{ mFALSE, 9, api_caller_int_args_void, "NumberOfEntities" }, // pfnNumberOfEntities
|
||||
{ mFALSE, 17, api_caller_ptr_args_p, "GetInfoKeyBuffer" }, // pfnGetInfoKeyBuffer
|
||||
{ mFALSE, 13, api_caller_ptr_args_2p, "InfoKeyValue" }, // pfnInfoKeyValue
|
||||
{ mFALSE, 9, api_caller_void_args_3p, "SetKeyValue" }, // pfnSetKeyValue
|
||||
{ mFALSE, 12, api_caller_void_args_i3p, "SetClientKeyValue" }, // pfnSetClientKeyValue
|
||||
{ mFALSE, 9, api_caller_int_args_p, "IsMapValid" }, // pfnIsMapValid
|
||||
{ mFALSE, 9, api_caller_void_args_p3i, "StaticDecal" }, // pfnStaticDecal
|
||||
{ mFALSE, 9, api_caller_int_args_p, "PrecacheGeneric" }, // pfnPrecacheGeneric
|
||||
{ mFALSE, 10, api_caller_int_args_p, "GetPlayerUserId" }, // pfnGetPlayerUserId
|
||||
{ mFALSE, 9, api_caller_void_args_pip2f4i2p, "BuildSoundMsg" }, // pfnBuildSoundMsg
|
||||
{ mFALSE, 9, api_caller_int_args_void, "IsDedicatedServer" }, // pfnIsDedicatedServer
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "CVarGetPointer" }, // pfnCVarGetPointer
|
||||
{ mFALSE, 9, api_caller_uint_args_p, "GetPlayerWONId" }, // pfnGetPlayerWONId
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "Info_RemoveKey" }, // pfnInfo_RemoveKey
|
||||
{ mFALSE, 15, api_caller_ptr_args_2p, "GetPhysicsKeyValue" }, // pfnGetPhysicsKeyValue
|
||||
{ mFALSE, 14, api_caller_void_args_3p, "SetPhysicsKeyValue" }, // pfnSetPhysicsKeyValue
|
||||
{ mFALSE, 15, api_caller_ptr_args_p, "GetPhysicsInfoString" }, // pfnGetPhysicsInfoString
|
||||
{ mFALSE, 13, api_caller_ushort_args_ip, "PrecacheEvent" }, // pfnPrecacheEvent
|
||||
{ mFALSE, 9, api_caller_void_args_ipusf2p2f4i,"PlaybackEvent" }, // pfnPlaybackEvent
|
||||
{ mFALSE, 31, api_caller_ptr_args_p, "SetFatPVS" }, // pfnSetFatPVS
|
||||
{ mFALSE, 31, api_caller_ptr_args_p, "SetFatPAS" }, // pfnSetFatPAS
|
||||
{ mFALSE, 50, api_caller_int_args_2p, "CheckVisibility" }, // pfnCheckVisibility
|
||||
{ mFALSE, 37, api_caller_void_args_2p, "DeltaSetField" }, // pfnDeltaSetField
|
||||
{ mFALSE, 38, api_caller_void_args_2p, "DeltaUnsetField" }, // pfnDeltaUnsetField
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "DeltaAddEncoder" }, // pfnDeltaAddEncoder
|
||||
{ mFALSE, 45, api_caller_int_args_void, "GetCurrentPlayer" }, // pfnGetCurrentPlayer
|
||||
{ mFALSE, 14, api_caller_int_args_p, "CanSkipPlayer" }, // pfnCanSkipPlayer
|
||||
{ mFALSE, 9, api_caller_int_args_2p, "DeltaFindField" }, // pfnDeltaFindField
|
||||
{ mFALSE, 37, api_caller_void_args_pi, "DeltaSetFieldByIndex" }, // pfnDeltaSetFieldByIndex
|
||||
{ mFALSE, 38, api_caller_void_args_pi, "DeltaUnsetFieldByIndex" }, // pfnDeltaUnsetFieldByIndex
|
||||
{ mFALSE, 9, api_caller_void_args_2i, "SetGroupMask" }, // pfnSetGroupMask
|
||||
{ mFALSE, 9, api_caller_int_args_ip, "engCreateInstancedBaseline" }, // pfnCreateInstancedBaseline // d'oh, CreateInstancedBaseline in dllapi too
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "Cvar_DirectSet" }, // pfnCvar_DirectSet
|
||||
{ mFALSE, 9, api_caller_void_args_i3p, "ForceUnmodified" }, // pfnForceUnmodified
|
||||
{ mFALSE, 9, api_caller_void_args_3p, "GetPlayerStats" }, // pfnGetPlayerStats
|
||||
{ mFALSE, 3, api_caller_void_args_2p, "AddServerCommand" }, // pfnAddServerCommand
|
||||
// Added in SDK 2.2:
|
||||
{ mFALSE, 9, api_caller_int_args_2i, "Voice_GetClientListening" }, // Voice_GetClientListening
|
||||
{ mFALSE, 9, api_caller_int_args_3i, "Voice_SetClientListening" }, // Voice_SetClientListening
|
||||
// Added for HL 1109 (no SDK update):
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "GetPlayerAuthId" }, // pfnGetPlayerAuthId
|
||||
// Added 2003/11/10 (no SDK update):
|
||||
{ mFALSE, 30, api_caller_ptr_args_2p, "SequenceGet" }, // pfnSequenceGet
|
||||
{ mFALSE, 30, api_caller_ptr_args_pip, "SequencePickSentence" }, // pfnSequencePickSentence
|
||||
{ mFALSE, 30, api_caller_int_args_p, "GetFileSize" }, // pfnGetFileSize
|
||||
{ mFALSE, 30, api_caller_uint_args_p, "GetApproxWavePlayLen" }, // pfnGetApproxWavePlayLen
|
||||
{ mFALSE, 30, api_caller_int_args_void, "IsCareerMatch" }, // pfnIsCareerMatch
|
||||
{ mFALSE, 30, api_caller_int_args_p, "GetLocalizedStringLength" }, // pfnGetLocalizedStringLength
|
||||
{ mFALSE, 30, api_caller_void_args_i, "RegisterTutorMessageShown" }, // pfnRegisterTutorMessageShown
|
||||
{ mFALSE, 30, api_caller_int_args_i, "GetTimesTutorMessageShown" }, // pfnGetTimesTutorMessageShown
|
||||
{ mFALSE, 30, api_caller_void_args_pi, "ProcessTutorMessageDecayBuffer" }, // pfnProcessTutorMessageDecayBuffer
|
||||
{ mFALSE, 30, api_caller_void_args_pi, "ConstructTutorMessageDecayBuffer" }, // pfnConstructTutorMessageDecayBuffer
|
||||
{ mFALSE, 9, api_caller_void_args_void, "ResetTutorMessageDecayData" }, // pfnResetTutorMessageDecayData
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
{ mFALSE, 3, api_caller_void_args_2p, "QueryClientCvarValue" }, // pfnQueryClientCvarValue
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
{ mFALSE, 3, api_caller_void_args_2pi, "QueryClientCvarValue2" }, // pfnQueryClientCvarValue2
|
||||
// Added 2009-06-17 (no SDK update):
|
||||
{ mFALSE, 8, api_caller_int_args_2p, "EngCheckParm" }, // pfnEngCheckParm
|
||||
// end
|
||||
{ mFALSE, 0, NULL, NULL },
|
||||
};
|
||||
312
src/metamod/api_info.h
Normal file
312
src/metamod/api_info.h
Normal file
@@ -0,0 +1,312 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// api_info.h - structures to store info about api routines
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef API_INFO_H
|
||||
#define API_INFO_H
|
||||
|
||||
#include "comp_dep.h"
|
||||
#include "types_meta.h" // mBOOL
|
||||
#include "ret_type.h"
|
||||
|
||||
|
||||
#define P_PRE 0 // plugin function called before gamedll
|
||||
#define P_POST 1 // plugin function called after gamedll
|
||||
|
||||
|
||||
// API selector
|
||||
typedef enum enum_api_t {
|
||||
e_api_engine = 0,
|
||||
e_api_dllapi = 1,
|
||||
e_api_newapi = 2,
|
||||
} enum_api_t;
|
||||
|
||||
// API caller function prototype
|
||||
typedef void * (DLLINTERNAL_NOVIS * api_caller_func_t)(const void * func, const void * packed_args);
|
||||
|
||||
|
||||
typedef struct api_info_s {
|
||||
mBOOL trace; // if true, log info about this function
|
||||
int loglevel; // level at which to log info about this function
|
||||
api_caller_func_t api_caller; // argument format/type for single-main-hook-function optimization
|
||||
const char *name; // string representation of function name
|
||||
} api_info_t;
|
||||
|
||||
|
||||
// DLL api functions
|
||||
typedef struct dllapi_info_s {
|
||||
api_info_t pfnGameInit;
|
||||
api_info_t pfnSpawn;
|
||||
api_info_t pfnThink;
|
||||
api_info_t pfnUse;
|
||||
api_info_t pfnTouch;
|
||||
api_info_t pfnBlocked;
|
||||
api_info_t pfnKeyValue;
|
||||
api_info_t pfnSave;
|
||||
api_info_t pfnRestore;
|
||||
api_info_t pfnSetAbsBox;
|
||||
api_info_t pfnSaveWriteFields;
|
||||
api_info_t pfnSaveReadFields;
|
||||
api_info_t pfnSaveGlobalState;
|
||||
api_info_t pfnRestoreGlobalState;
|
||||
api_info_t pfnResetGlobalState;
|
||||
api_info_t pfnClientConnect;
|
||||
api_info_t pfnClientDisconnect;
|
||||
api_info_t pfnClientKill;
|
||||
api_info_t pfnClientPutInServer;
|
||||
api_info_t pfnClientCommand;
|
||||
api_info_t pfnClientUserInfoChanged;
|
||||
api_info_t pfnServerActivate;
|
||||
api_info_t pfnServerDeactivate;
|
||||
api_info_t pfnPlayerPreThink;
|
||||
api_info_t pfnPlayerPostThink;
|
||||
api_info_t pfnStartFrame;
|
||||
api_info_t pfnParmsNewLevel;
|
||||
api_info_t pfnParmsChangeLevel;
|
||||
api_info_t pfnGetGameDescription;
|
||||
api_info_t pfnPlayerCustomization;
|
||||
api_info_t pfnSpectatorConnect;
|
||||
api_info_t pfnSpectatorDisconnect;
|
||||
api_info_t pfnSpectatorThink;
|
||||
api_info_t pfnSys_Error;
|
||||
api_info_t pfnPM_Move;
|
||||
api_info_t pfnPM_Init;
|
||||
api_info_t pfnPM_FindTextureType;
|
||||
api_info_t pfnSetupVisibility;
|
||||
api_info_t pfnUpdateClientData;
|
||||
api_info_t pfnAddToFullPack;
|
||||
api_info_t pfnCreateBaseline;
|
||||
api_info_t pfnRegisterEncoders;
|
||||
api_info_t pfnGetWeaponData;
|
||||
api_info_t pfnCmdStart;
|
||||
api_info_t pfnCmdEnd;
|
||||
api_info_t pfnConnectionlessPacket;
|
||||
api_info_t pfnGetHullBounds;
|
||||
api_info_t pfnCreateInstancedBaselines;
|
||||
api_info_t pfnInconsistentFile;
|
||||
api_info_t pfnAllowLagCompensation;
|
||||
api_info_t END;
|
||||
} dllapi_info_t;
|
||||
|
||||
|
||||
// "New" api functions
|
||||
typedef struct newapi_info_s {
|
||||
api_info_t pfnOnFreeEntPrivateData;
|
||||
api_info_t pfnGameShutdown;
|
||||
api_info_t pfnShouldCollide;
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
api_info_t pfnCvarValue;
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
api_info_t pfnCvarValue2;
|
||||
api_info_t END;
|
||||
} newapi_info_t;
|
||||
|
||||
|
||||
// Engine functions
|
||||
typedef struct engine_info_s {
|
||||
api_info_t pfnPrecacheModel;
|
||||
api_info_t pfnPrecacheSound;
|
||||
api_info_t pfnSetModel;
|
||||
api_info_t pfnModelIndex;
|
||||
api_info_t pfnModelFrames;
|
||||
api_info_t pfnSetSize;
|
||||
api_info_t pfnChangeLevel;
|
||||
api_info_t pfnGetSpawnParms;
|
||||
api_info_t pfnSaveSpawnParms;
|
||||
api_info_t pfnVecToYaw;
|
||||
api_info_t pfnVecToAngles;
|
||||
api_info_t pfnMoveToOrigin;
|
||||
api_info_t pfnChangeYaw;
|
||||
api_info_t pfnChangePitch;
|
||||
api_info_t pfnFindEntityByString;
|
||||
api_info_t pfnGetEntityIllum;
|
||||
api_info_t pfnFindEntityInSphere;
|
||||
api_info_t pfnFindClientInPVS;
|
||||
api_info_t pfnEntitiesInPVS;
|
||||
api_info_t pfnMakeVectors;
|
||||
api_info_t pfnAngleVectors;
|
||||
api_info_t pfnCreateEntity;
|
||||
api_info_t pfnRemoveEntity;
|
||||
api_info_t pfnCreateNamedEntity;
|
||||
api_info_t pfnMakeStatic;
|
||||
api_info_t pfnEntIsOnFloor;
|
||||
api_info_t pfnDropToFloor;
|
||||
api_info_t pfnWalkMove;
|
||||
api_info_t pfnSetOrigin;
|
||||
api_info_t pfnEmitSound;
|
||||
api_info_t pfnEmitAmbientSound;
|
||||
api_info_t pfnTraceLine;
|
||||
api_info_t pfnTraceToss;
|
||||
api_info_t pfnTraceMonsterHull;
|
||||
api_info_t pfnTraceHull;
|
||||
api_info_t pfnTraceModel;
|
||||
api_info_t pfnTraceTexture;
|
||||
api_info_t pfnTraceSphere;
|
||||
api_info_t pfnGetAimVector;
|
||||
api_info_t pfnServerCommand;
|
||||
api_info_t pfnServerExecute;
|
||||
api_info_t pfnClientCommand;
|
||||
api_info_t pfnParticleEffect;
|
||||
api_info_t pfnLightStyle;
|
||||
api_info_t pfnDecalIndex;
|
||||
api_info_t pfnPointContents;
|
||||
api_info_t pfnMessageBegin;
|
||||
api_info_t pfnMessageEnd;
|
||||
api_info_t pfnWriteByte;
|
||||
api_info_t pfnWriteChar;
|
||||
api_info_t pfnWriteShort;
|
||||
api_info_t pfnWriteLong;
|
||||
api_info_t pfnWriteAngle;
|
||||
api_info_t pfnWriteCoord;
|
||||
api_info_t pfnWriteString;
|
||||
api_info_t pfnWriteEntity;
|
||||
api_info_t pfnCVarRegister;
|
||||
api_info_t pfnCVarGetFloat;
|
||||
api_info_t pfnCVarGetString;
|
||||
api_info_t pfnCVarSetFloat;
|
||||
api_info_t pfnCVarSetString;
|
||||
api_info_t pfnAlertMessage;
|
||||
api_info_t pfnEngineFprintf;
|
||||
api_info_t pfnPvAllocEntPrivateData;
|
||||
api_info_t pfnPvEntPrivateData;
|
||||
api_info_t pfnFreeEntPrivateData;
|
||||
api_info_t pfnSzFromIndex;
|
||||
api_info_t pfnAllocString;
|
||||
api_info_t pfnGetVarsOfEnt;
|
||||
api_info_t pfnPEntityOfEntOffset;
|
||||
api_info_t pfnEntOffsetOfPEntity;
|
||||
api_info_t pfnIndexOfEdict;
|
||||
api_info_t pfnPEntityOfEntIndex;
|
||||
api_info_t pfnFindEntityByVars;
|
||||
api_info_t pfnGetModelPtr;
|
||||
api_info_t pfnRegUserMsg;
|
||||
api_info_t pfnAnimationAutomove;
|
||||
api_info_t pfnGetBonePosition;
|
||||
api_info_t pfnFunctionFromName;
|
||||
api_info_t pfnNameForFunction;
|
||||
api_info_t pfnClientPrintf;
|
||||
api_info_t pfnServerPrint;
|
||||
api_info_t pfnCmd_Args;
|
||||
api_info_t pfnCmd_Argv;
|
||||
api_info_t pfnCmd_Argc;
|
||||
api_info_t pfnGetAttachment;
|
||||
api_info_t pfnCRC32_Init;
|
||||
api_info_t pfnCRC32_ProcessBuffer;
|
||||
api_info_t pfnCRC32_ProcessByte;
|
||||
api_info_t pfnCRC32_Final;
|
||||
api_info_t pfnRandomLong;
|
||||
api_info_t pfnRandomFloat;
|
||||
api_info_t pfnSetView;
|
||||
api_info_t pfnTime;
|
||||
api_info_t pfnCrosshairAngle;
|
||||
api_info_t pfnLoadFileForMe;
|
||||
api_info_t pfnFreeFile;
|
||||
api_info_t pfnEndSection;
|
||||
api_info_t pfnCompareFileTime;
|
||||
api_info_t pfnGetGameDir;
|
||||
api_info_t pfnCvar_RegisterVariable;
|
||||
api_info_t pfnFadeClientVolume;
|
||||
api_info_t pfnSetClientMaxspeed;
|
||||
api_info_t pfnCreateFakeClient;
|
||||
api_info_t pfnRunPlayerMove;
|
||||
api_info_t pfnNumberOfEntities;
|
||||
api_info_t pfnGetInfoKeyBuffer;
|
||||
api_info_t pfnInfoKeyValue;
|
||||
api_info_t pfnSetKeyValue;
|
||||
api_info_t pfnSetClientKeyValue;
|
||||
api_info_t pfnIsMapValid;
|
||||
api_info_t pfnStaticDecal;
|
||||
api_info_t pfnPrecacheGeneric;
|
||||
api_info_t pfnGetPlayerUserId;
|
||||
api_info_t pfnBuildSoundMsg;
|
||||
api_info_t pfnIsDedicatedServer;
|
||||
api_info_t pfnCVarGetPointer;
|
||||
api_info_t pfnGetPlayerWONId;
|
||||
api_info_t pfnInfo_RemoveKey;
|
||||
api_info_t pfnGetPhysicsKeyValue;
|
||||
api_info_t pfnSetPhysicsKeyValue;
|
||||
api_info_t pfnGetPhysicsInfoString;
|
||||
api_info_t pfnPrecacheEvent;
|
||||
api_info_t pfnPlaybackEvent;
|
||||
api_info_t pfnSetFatPVS;
|
||||
api_info_t pfnSetFatPAS;
|
||||
api_info_t pfnCheckVisibility;
|
||||
api_info_t pfnDeltaSetField;
|
||||
api_info_t pfnDeltaUnsetField;
|
||||
api_info_t pfnDeltaAddEncoder;
|
||||
api_info_t pfnGetCurrentPlayer;
|
||||
api_info_t pfnCanSkipPlayer;
|
||||
api_info_t pfnDeltaFindField;
|
||||
api_info_t pfnDeltaSetFieldByIndex;
|
||||
api_info_t pfnDeltaUnsetFieldByIndex;
|
||||
api_info_t pfnSetGroupMask;
|
||||
api_info_t pfnCreateInstancedBaseline;
|
||||
api_info_t pfnCvar_DirectSet;
|
||||
api_info_t pfnForceUnmodified;
|
||||
api_info_t pfnGetPlayerStats;
|
||||
api_info_t pfnAddServerCommand;
|
||||
// Added in SDK 2.2:
|
||||
api_info_t pfnVoice_GetClientListening;
|
||||
api_info_t pfnVoice_SetClientListening;
|
||||
// Added for HL 1109 (no SDK update):
|
||||
api_info_t pfnGetPlayerAuthId;
|
||||
// Added 2003/11/10 (no SDK update):
|
||||
api_info_t pfnSequenceGet;
|
||||
api_info_t pfnSequencePickSentence;
|
||||
api_info_t pfnGetFileSize;
|
||||
api_info_t pfnGetApproxWavePlayLen;
|
||||
api_info_t pfnIsCareerMatch;
|
||||
api_info_t pfnGetLocalizedStringLength;
|
||||
api_info_t pfnRegisterTutorMessageShown;
|
||||
api_info_t pfnGetTimesTutorMessageShown;
|
||||
api_info_t pfnProcessTutorMessageDecayBuffer;
|
||||
api_info_t pfnConstructTutorMessageDecayBuffer;
|
||||
api_info_t pfnResetTutorMessageDecayData;
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
api_info_t pfnQueryClientCvarValue;
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
api_info_t pfnQueryClientCvarValue2;
|
||||
// Added 2009/06/17 (no SDK update):
|
||||
api_info_t pfnEngCheckParm;
|
||||
// end
|
||||
api_info_t END;
|
||||
} engine_info_t;
|
||||
|
||||
|
||||
extern const dllapi_info_t dllapi_info DLLHIDDEN;
|
||||
extern const newapi_info_t newapi_info DLLHIDDEN;
|
||||
extern const engine_info_t engine_info DLLHIDDEN;
|
||||
|
||||
#endif /* API_INFO_H */
|
||||
5
src/metamod/build_all.sh
Normal file
5
src/metamod/build_all.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
make HOST=cygwin TARGET=win32 OPT=opt
|
||||
make HOST=cygwin OPT=opt
|
||||
make HOST=cygwin TARGET=amd64 OPT=opt
|
||||
513
src/metamod/commands_meta.cpp
Normal file
513
src/metamod/commands_meta.cpp
Normal file
@@ -0,0 +1,513 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// commands_meta.cpp - implementation of various console commands
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // strtol()
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "commands_meta.h" // me
|
||||
#include "metamod.h" // Plugins, etc
|
||||
#include "log_meta.h" // META_CONS, etc
|
||||
#include "info_name.h" // VNAME, etc
|
||||
#include "vdate.h" // COMPILE_TIME, COMPILE_TZONE
|
||||
|
||||
|
||||
#ifdef META_PERFMON
|
||||
|
||||
long double total_tsc=0;
|
||||
unsigned long long count_tsc=0;
|
||||
unsigned long long active_tsc=0;
|
||||
unsigned long long min_tsc=0;
|
||||
|
||||
void DLLINTERNAL cmd_meta_tsc(void) {
|
||||
if(!count_tsc)
|
||||
return;
|
||||
|
||||
META_CONS(" ");
|
||||
META_CONS(" count_tsc: %.0f", (double)count_tsc);
|
||||
META_CONS(" mean_tsc: %.1f", (double)(total_tsc / count_tsc));
|
||||
META_CONS(" min_tsc: %.0f", (double)min_tsc);
|
||||
}
|
||||
|
||||
void DLLINTERNAL cmd_meta_reset_tsc(void) {
|
||||
total_tsc=0;
|
||||
count_tsc=0;
|
||||
min_tsc=0;
|
||||
}
|
||||
#endif /*META_PERFMON*/
|
||||
|
||||
// Register commands and cvars.
|
||||
void DLLINTERNAL meta_register_cmdcvar() {
|
||||
CVAR_REGISTER(&meta_debug);
|
||||
CVAR_REGISTER(&meta_version);
|
||||
|
||||
meta_debug_value = (int)meta_debug.value;
|
||||
|
||||
REG_SVR_COMMAND("meta", svr_meta);
|
||||
}
|
||||
|
||||
// Parse "meta" console command.
|
||||
void DLLHIDDEN svr_meta(void) {
|
||||
const char *cmd;
|
||||
cmd=CMD_ARGV(1);
|
||||
// arguments: none
|
||||
if(!strcasecmp(cmd, "version"))
|
||||
cmd_meta_version();
|
||||
else if(!strcasecmp(cmd, "gpl"))
|
||||
cmd_meta_gpl();
|
||||
else if(!strcasecmp(cmd, "refresh"))
|
||||
cmd_meta_refresh();
|
||||
else if(!strcasecmp(cmd, "list"))
|
||||
cmd_meta_pluginlist();
|
||||
else if(!strcasecmp(cmd, "cmds"))
|
||||
cmd_meta_cmdlist();
|
||||
else if(!strcasecmp(cmd, "cvars"))
|
||||
cmd_meta_cvarlist();
|
||||
else if(!strcasecmp(cmd, "game"))
|
||||
cmd_meta_game();
|
||||
else if(!strcasecmp(cmd, "config"))
|
||||
cmd_meta_config();
|
||||
// arguments: existing plugin(s)
|
||||
else if(!strcasecmp(cmd, "pause"))
|
||||
cmd_doplug(PC_PAUSE);
|
||||
else if(!strcasecmp(cmd, "unpause"))
|
||||
cmd_doplug(PC_UNPAUSE);
|
||||
else if(!strcasecmp(cmd, "unload"))
|
||||
cmd_doplug(PC_UNLOAD);
|
||||
else if(!strcasecmp(cmd, "force_unload"))
|
||||
cmd_doplug(PC_FORCE_UNLOAD);
|
||||
else if(!strcasecmp(cmd, "reload"))
|
||||
cmd_doplug(PC_RELOAD);
|
||||
else if(!strcasecmp(cmd, "retry"))
|
||||
cmd_doplug(PC_RETRY);
|
||||
else if(!strcasecmp(cmd, "clear"))
|
||||
cmd_doplug(PC_CLEAR);
|
||||
else if(!strcasecmp(cmd, "info"))
|
||||
cmd_doplug(PC_INFO);
|
||||
else if(!strcasecmp(cmd, "require"))
|
||||
cmd_doplug(PC_REQUIRE);
|
||||
// arguments: filename, description
|
||||
else if(!strcasecmp(cmd, "load"))
|
||||
cmd_meta_load();
|
||||
#ifdef META_PERFMON
|
||||
else if(!strcasecmp(cmd, "tsc"))
|
||||
cmd_meta_tsc();
|
||||
else if(!strcasecmp(cmd, "reset_tsc"))
|
||||
cmd_meta_reset_tsc();
|
||||
#endif /*META_PERFMON*/
|
||||
// unrecognized
|
||||
else {
|
||||
META_CONS("Unrecognized meta command: %s", cmd);
|
||||
cmd_meta_usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse "meta" client command.
|
||||
void DLLINTERNAL client_meta(edict_t *pEntity) {
|
||||
const char *cmd;
|
||||
cmd=CMD_ARGV(1);
|
||||
META_LOG("ClientCommand 'meta %s' from player '%s'",
|
||||
CMD_ARGS(), STRING(pEntity->v.netname));
|
||||
// arguments: none
|
||||
if(strmatch(cmd, "version"))
|
||||
client_meta_version(pEntity);
|
||||
else if(strmatch(cmd, "list"))
|
||||
client_meta_pluginlist(pEntity);
|
||||
else if(strmatch(cmd, "aybabtu"))
|
||||
client_meta_aybabtu(pEntity);
|
||||
// unrecognized
|
||||
else {
|
||||
META_CLIENT(pEntity, "Unrecognized meta command: %s", cmd);
|
||||
client_meta_usage(pEntity);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Print usage for "meta" console command.
|
||||
void DLLINTERNAL cmd_meta_usage(void) {
|
||||
META_CONS("usage: meta <command> [<arguments>]");
|
||||
META_CONS("valid commands are:");
|
||||
META_CONS(" version - display metamod version info");
|
||||
META_CONS(" game - display gamedll info");
|
||||
META_CONS(" list - list plugins currently loaded");
|
||||
META_CONS(" cmds - list console cmds registered by plugins");
|
||||
META_CONS(" cvars - list cvars registered by plugins");
|
||||
META_CONS(" refresh - load/unload any new/deleted/updated plugins");
|
||||
META_CONS(" config - show config info loaded from config.ini");
|
||||
META_CONS(" load <name> - find and load a plugin with the given name");
|
||||
META_CONS(" unload <plugin> - unload a loaded plugin");
|
||||
META_CONS(" reload <plugin> - unload a plugin and load it again");
|
||||
META_CONS(" info <plugin> - show all information about a plugin");
|
||||
META_CONS(" pause <plugin> - pause a loaded, running plugin");
|
||||
META_CONS(" unpause <plugin> - unpause a previously paused plugin");
|
||||
META_CONS(" retry <plugin> - retry a plugin that previously failed its action");
|
||||
META_CONS(" clear <plugin> - clear a failed plugin from the list");
|
||||
META_CONS(" force_unload <plugin> - forcibly unload a loaded plugin");
|
||||
META_CONS(" require <plugin> - exit server if plugin not loaded/running");
|
||||
}
|
||||
|
||||
// Print usage for "meta" client command.
|
||||
void DLLINTERNAL client_meta_usage(edict_t *pEntity) {
|
||||
META_CLIENT(pEntity, "usage: meta <command> [<arguments>]");
|
||||
META_CLIENT(pEntity, "valid commands are:");
|
||||
META_CLIENT(pEntity, " version - display metamod version info");
|
||||
META_CLIENT(pEntity, " list - list plugins currently loaded");
|
||||
}
|
||||
|
||||
// "meta aybabtu" client command.
|
||||
void DLLINTERNAL client_meta_aybabtu(edict_t *pEntity) {
|
||||
META_CLIENT(pEntity, "%s", "All Your Base Are Belong To Us");
|
||||
}
|
||||
|
||||
// "meta version" console command.
|
||||
void DLLINTERNAL cmd_meta_version(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta version");
|
||||
return;
|
||||
}
|
||||
META_CONS("%s v%s %s (%s)", VNAME, VVERSION, VDATE, META_INTERFACE_VERSION);
|
||||
META_CONS("by %s", VAUTHOR);
|
||||
META_CONS(" %s", VURL);
|
||||
META_CONS(" Patch: %s v%d", VPATCH_NAME, VPATCH_IVERSION);
|
||||
META_CONS(" by %s", VPATCH_AUTHOR);
|
||||
META_CONS(" %s", VPATCH_WEBSITE);
|
||||
META_CONS("compiled: %s %s (%s)", COMPILE_TIME, COMPILE_TZONE, OPT_TYPE);
|
||||
}
|
||||
|
||||
// "meta version" client command.
|
||||
void DLLINTERNAL client_meta_version(edict_t *pEntity) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CLIENT(pEntity, "usage: meta version");
|
||||
return;
|
||||
}
|
||||
META_CLIENT(pEntity, "%s v%s %s (%s)", VNAME, VVERSION, VDATE, META_INTERFACE_VERSION);
|
||||
META_CLIENT(pEntity, "by %s", VAUTHOR);
|
||||
META_CLIENT(pEntity, " %s", VURL);
|
||||
META_CLIENT(pEntity, " Patch: %s v%d", VPATCH_NAME, VPATCH_IVERSION);
|
||||
META_CLIENT(pEntity, " by %s", VPATCH_AUTHOR);
|
||||
META_CLIENT(pEntity, " %s", VPATCH_WEBSITE);
|
||||
META_CLIENT(pEntity, "compiled: %s %s (%s)", COMPILE_TIME, COMPILE_TZONE, OPT_TYPE);
|
||||
META_CLIENT(pEntity, "ifvers: %s", META_INTERFACE_VERSION);
|
||||
}
|
||||
|
||||
// "meta gpl" console command.
|
||||
void DLLINTERNAL cmd_meta_gpl(void) {
|
||||
META_CONS("%s version %s %s", VNAME, VVERSION, VDATE);
|
||||
META_CONS("Copyright (c) 2001-%s %s", COPYRIGHT_YEAR, VAUTHOR);
|
||||
META_CONS("");
|
||||
META_CONS(" %s is free software; you can redistribute it and/or", VNAME);
|
||||
META_CONS(" modify it under the terms of the GNU General Public License");
|
||||
META_CONS(" as published by the Free Software Foundation; either");
|
||||
META_CONS(" version 2 of the License, or (at your option) any later");
|
||||
META_CONS(" version.");
|
||||
META_CONS(" ");
|
||||
META_CONS(" %s is distributed in the hope that it will be useful,", VNAME);
|
||||
META_CONS(" but WITHOUT ANY WARRANTY; without even the implied warranty");
|
||||
META_CONS(" of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
|
||||
META_CONS(" See the GNU General Public License for more details.");
|
||||
META_CONS(" ");
|
||||
META_CONS(" You should have received a copy of the GNU General Public");
|
||||
META_CONS(" License along with Metamod; if not, write to the Free");
|
||||
META_CONS(" Software Foundation, Inc., 59 Temple Place, Suite 330,");
|
||||
META_CONS(" Boston, MA 02111-1307 USA");
|
||||
META_CONS(" ");
|
||||
META_CONS(" In addition, as a special exception, the author gives");
|
||||
META_CONS(" permission to link the code of this program with the");
|
||||
META_CONS(" Half-Life Game Engine (\"HL Engine\") and Modified Game");
|
||||
META_CONS(" Libraries (\"MODs\") developed by Valve, L.L.C (\"Valve\").");
|
||||
META_CONS(" You must obey the GNU General Public License in all");
|
||||
META_CONS(" respects for all of the code used other than the HL Engine");
|
||||
META_CONS(" and MODs from Valve. If you modify this file, you may");
|
||||
META_CONS(" extend this exception to your version of the file, but you");
|
||||
META_CONS(" are not obligated to do so. If you do not wish to do so,");
|
||||
META_CONS(" delete this exception statement from your version.");
|
||||
}
|
||||
|
||||
// "meta game" console command.
|
||||
void DLLINTERNAL cmd_meta_game(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta game");
|
||||
return;
|
||||
}
|
||||
META_CONS("GameDLL info:");
|
||||
META_CONS(" name: %s", GameDLL.name);
|
||||
META_CONS(" desc: %s", GameDLL.desc);
|
||||
META_CONS(" gamedir: %s", GameDLL.gamedir);
|
||||
META_CONS(" dll file: %s", GameDLL.file);
|
||||
META_CONS("dll pathname: %s", GameDLL.pathname);
|
||||
RegMsgs->show();
|
||||
}
|
||||
|
||||
// "meta refresh" console command.
|
||||
void DLLINTERNAL cmd_meta_refresh(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta refresh");
|
||||
return;
|
||||
}
|
||||
META_LOG("Refreshing the plugins on demand...");
|
||||
if(Plugins->refresh(PT_ANYTIME) != mTRUE) {
|
||||
META_LOG("Refresh failed.");
|
||||
}
|
||||
}
|
||||
|
||||
// "meta list" console command.
|
||||
void DLLINTERNAL cmd_meta_pluginlist(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta list");
|
||||
return;
|
||||
}
|
||||
Plugins->show();
|
||||
}
|
||||
|
||||
// "meta list" client command.
|
||||
void DLLINTERNAL client_meta_pluginlist(edict_t *pEntity) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CLIENT(pEntity, "usage: meta list");
|
||||
return;
|
||||
}
|
||||
Plugins->show_client(pEntity);
|
||||
}
|
||||
|
||||
// "meta cmds" console command.
|
||||
void DLLINTERNAL cmd_meta_cmdlist(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta cmds");
|
||||
return;
|
||||
}
|
||||
RegCmds->show();
|
||||
}
|
||||
|
||||
// "meta cvars" console command.
|
||||
void DLLINTERNAL cmd_meta_cvarlist(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta cvars");
|
||||
return;
|
||||
}
|
||||
RegCvars->show();
|
||||
}
|
||||
|
||||
// "meta config" console command.
|
||||
void DLLINTERNAL cmd_meta_config(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta cvars");
|
||||
return;
|
||||
}
|
||||
Config->show();
|
||||
}
|
||||
|
||||
// gamedir/filename
|
||||
// gamedir/dlls/filename
|
||||
//
|
||||
// dir/mm_file
|
||||
// dir/file
|
||||
//
|
||||
// path
|
||||
// path_mm
|
||||
// path_MM
|
||||
// path.so, path.dll
|
||||
// path_i386.so, path_i486.so, etc
|
||||
|
||||
// "meta load" console command.
|
||||
void DLLINTERNAL cmd_meta_load(void) {
|
||||
int argc;
|
||||
const char *args;
|
||||
argc=CMD_ARGC();
|
||||
if(argc < 3) {
|
||||
META_CONS("usage: meta load <name> [<description>]");
|
||||
META_CONS(" where <name> is an identifier used to locate the plugin file.");
|
||||
META_CONS(" The system will look for a number of files based on this name, including:");
|
||||
META_CONS(" name");
|
||||
#ifdef linux
|
||||
META_CONS(" name.so");
|
||||
META_CONS(" name_mm.so");
|
||||
META_CONS(" name_MM.so");
|
||||
META_CONS(" mm_name.so");
|
||||
#ifdef __x86_64__
|
||||
META_CONS(" name_amd64.so");
|
||||
META_CONS(" name_x86_64.so");
|
||||
#else
|
||||
META_CONS(" name_i386.so");
|
||||
META_CONS(" name_i686.so");
|
||||
#endif
|
||||
#elif defined(_WIN32)
|
||||
META_CONS(" name.dll");
|
||||
META_CONS(" name_mm.dll");
|
||||
META_CONS(" mm_name.dll");
|
||||
#endif /* linux */
|
||||
META_CONS(" in a number of directories, including:");
|
||||
META_CONS(" <gamedir>");
|
||||
META_CONS(" <gamedir>/dlls");
|
||||
META_CONS(" <given path, if absolute>");
|
||||
return;
|
||||
}
|
||||
args=CMD_ARGS();
|
||||
// cmd_addload() handles all the feedback to the console..
|
||||
Plugins->cmd_addload(args);
|
||||
}
|
||||
|
||||
// Handle various console commands that refer to a known/loaded plugin.
|
||||
void DLLINTERNAL cmd_doplug(PLUG_CMD pcmd) {
|
||||
int i=0, argc;
|
||||
const char *cmd, *arg;
|
||||
MPlugin *findp;
|
||||
|
||||
argc=CMD_ARGC();
|
||||
cmd=CMD_ARGV(1);
|
||||
if(argc < 3) {
|
||||
META_CONS("usage: meta %s <plugin> [<plugin> ...]", cmd);
|
||||
META_CONS(" where <plugin> can be either the plugin index #");
|
||||
META_CONS(" or a non-ambiguous prefix string matching name, desc, file, or logtag");
|
||||
return;
|
||||
}
|
||||
// i=2 to skip first arg, as that's the "cmd"
|
||||
for(i=2; i < argc; i++) {
|
||||
int pindex;
|
||||
char *endptr;
|
||||
|
||||
arg=CMD_ARGV(i);
|
||||
|
||||
// try to match plugin id first
|
||||
pindex = strtol(arg, &endptr, 10);
|
||||
if(*arg && !*endptr)
|
||||
findp=Plugins->find(pindex);
|
||||
// else try to match some string (prefix)
|
||||
else
|
||||
findp=Plugins->find_match(arg);
|
||||
|
||||
// Require that:
|
||||
// - specified plugin was found in the list of current plugins
|
||||
// - plugin successfully loaded and began running
|
||||
// Otherwise, print error and exit.
|
||||
if(pcmd==PC_REQUIRE) {
|
||||
if(findp && findp->status >= PL_RUNNING) {
|
||||
META_DEBUG(3, ("Required plugin '%s' found loaded and running.",
|
||||
arg));
|
||||
return;
|
||||
}
|
||||
// Output to both places, because we don't want the admin
|
||||
// to miss this..
|
||||
if(!findp && meta_errno == ME_NOTUNIQ) {
|
||||
META_ERROR("Unique match for required plugin '%s' was not found! Exiting.", arg);
|
||||
META_CONS("\nERROR: Unique match for required plugin '%s' was not found! Exiting.\n", arg);
|
||||
}
|
||||
else if(!findp) {
|
||||
META_ERROR("Required plugin '%s' was not found! Exiting.",
|
||||
arg);
|
||||
META_CONS("\nERROR: Required plugin '%s' was not found! Exiting.\n",
|
||||
arg);
|
||||
}
|
||||
else {
|
||||
META_ERROR("Required plugin '%s' did not load successfully! (status=%s) Exiting.", arg, findp->str_status(ST_SIMPLE));
|
||||
META_CONS("\nERROR: Required plugin '%s' did not load successfully! (status=%s) Exiting.\n", arg, findp->str_status(ST_SIMPLE));
|
||||
}
|
||||
// Allow chance to read the message, before any window closes.
|
||||
do_exit(1);
|
||||
}
|
||||
|
||||
if(!findp) {
|
||||
if(meta_errno == ME_NOTUNIQ)
|
||||
META_CONS("Couldn't find unique plugin matching '%s'", arg);
|
||||
else
|
||||
META_CONS("Couldn't find plugin matching '%s'", arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if(pcmd==PC_PAUSE) {
|
||||
if(findp->pause())
|
||||
META_CONS("Paused plugin '%s'", findp->desc);
|
||||
else
|
||||
META_CONS("Pause failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_UNPAUSE) {
|
||||
if(findp->unpause())
|
||||
META_CONS("Unpaused plugin '%s'", findp->desc);
|
||||
else
|
||||
META_CONS("Unpause failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_UNLOAD) {
|
||||
findp->action=PA_UNLOAD;
|
||||
if(findp->unload(PT_ANYTIME, PNL_COMMAND, PNL_COMMAND)) {
|
||||
META_CONS("Unloaded plugin '%s'", findp->desc);
|
||||
Plugins->show();
|
||||
}
|
||||
else if(meta_errno == ME_DELAYED)
|
||||
META_CONS("Unload delayed for plugin '%s'", findp->desc);
|
||||
else
|
||||
META_CONS("Unload failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_FORCE_UNLOAD) {
|
||||
findp->action=PA_UNLOAD;
|
||||
if(findp->unload(PT_ANYTIME, PNL_CMD_FORCED, PNL_CMD_FORCED)) {
|
||||
META_CONS("Forced unload plugin '%s'", findp->desc);
|
||||
Plugins->show();
|
||||
}
|
||||
else
|
||||
META_CONS("Forced unload failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_RELOAD) {
|
||||
findp->action=PA_RELOAD;
|
||||
if(findp->reload(PT_ANYTIME, PNL_COMMAND))
|
||||
META_CONS("Reloaded plugin '%s'", findp->desc);
|
||||
else if(meta_errno == ME_DELAYED)
|
||||
META_CONS("Reload delayed for plugin '%s'", findp->desc);
|
||||
else if(meta_errno == ME_NOTALLOWED)
|
||||
META_CONS("Reload not allowed for plugin '%s' now, only allowed %s", findp->desc, findp->str_loadable(SL_ALLOWED));
|
||||
else
|
||||
META_CONS("Reload failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_RETRY) {
|
||||
if(findp->retry(PT_ANYTIME, PNL_COMMAND))
|
||||
META_CONS("Retry succeeded for plugin '%s'", findp->desc);
|
||||
else
|
||||
META_CONS("Retry failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_CLEAR) {
|
||||
if(findp->clear()) {
|
||||
META_CONS("Cleared failed plugin '%s' from list", findp->desc);
|
||||
Plugins->show();
|
||||
}
|
||||
else
|
||||
META_CONS("Clear failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_INFO)
|
||||
findp->show();
|
||||
else {
|
||||
META_WARNING("Unexpected plug_cmd: %d", pcmd);
|
||||
META_CONS("Command failed; see log");
|
||||
}
|
||||
}
|
||||
}
|
||||
83
src/metamod/commands_meta.h
Normal file
83
src/metamod/commands_meta.h
Normal file
@@ -0,0 +1,83 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// commands_meta.h - prototypes for console commands
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMMANDS_META_H
|
||||
#define COMMANDS_META_H
|
||||
|
||||
#include "types_meta.h" // mBOOL
|
||||
#include "comp_dep.h"
|
||||
|
||||
// Flags to use for meta_cmd_doplug(), to operate on existing plugins; note
|
||||
// "load" operates on a non-existing plugin thus isn't included here.
|
||||
typedef enum {
|
||||
PC_NULL = 0,
|
||||
PC_PAUSE, // pause the plugin
|
||||
PC_UNPAUSE, // unpause the plugin
|
||||
PC_UNLOAD, // unload the plugin
|
||||
PC_RELOAD, // unload the plugin and load it again
|
||||
PC_RETRY, // retry a failed operation (usually load/attach)
|
||||
PC_INFO, // show all info about the plugin
|
||||
PC_CLEAR, // remove a failed plugin from the list
|
||||
PC_FORCE_UNLOAD, // forcibly unload the plugin
|
||||
PC_REQUIRE, // require that this plugin is loaded/running
|
||||
} PLUG_CMD;
|
||||
|
||||
void DLLINTERNAL meta_register_cmdcvar();
|
||||
|
||||
void DLLHIDDEN svr_meta(void); // only hidden because called from outside!
|
||||
|
||||
void DLLINTERNAL cmd_meta_usage(void);
|
||||
void DLLINTERNAL cmd_meta_version(void);
|
||||
void DLLINTERNAL cmd_meta_gpl(void);
|
||||
|
||||
void DLLINTERNAL cmd_meta_game(void);
|
||||
void DLLINTERNAL cmd_meta_refresh(void);
|
||||
void DLLINTERNAL cmd_meta_load(void);
|
||||
|
||||
void DLLINTERNAL cmd_meta_pluginlist(void);
|
||||
void DLLINTERNAL cmd_meta_cmdlist(void);
|
||||
void DLLINTERNAL cmd_meta_cvarlist(void);
|
||||
void DLLINTERNAL cmd_meta_config(void);
|
||||
|
||||
void DLLINTERNAL cmd_doplug(PLUG_CMD pcmd);
|
||||
|
||||
void DLLINTERNAL client_meta(edict_t *pEntity);
|
||||
void DLLINTERNAL client_meta_usage(edict_t *pEntity);
|
||||
void DLLINTERNAL client_meta_version(edict_t *pEntity);
|
||||
void DLLINTERNAL client_meta_pluginlist(edict_t *pEntity);
|
||||
void DLLINTERNAL client_meta_aybabtu(edict_t *pEntity);
|
||||
|
||||
#endif /* COMMANDS_META_H */
|
||||
97
src/metamod/comp_dep.h
Normal file
97
src/metamod/comp_dep.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
||||
*
|
||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMP_DEP_H
|
||||
#define COMP_DEP_H
|
||||
|
||||
#define DECLSPEC(kw)
|
||||
#if defined (_WIN32) && defined (_MSC_VER)
|
||||
#define ATTRIBUTE(kw)
|
||||
#else
|
||||
#define ATTRIBUTE(kw) __attribute__((kw))
|
||||
#endif
|
||||
#define MM_CDECL
|
||||
|
||||
// We use these macros to hide our internal globals from being exported
|
||||
// on ELF .so
|
||||
#if defined(__GNUC__) && !defined(_WIN32) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 3
|
||||
// Hidden data/function.
|
||||
#define DLLHIDDEN __attribute__((visibility("hidden")))
|
||||
// Hidden internal function.
|
||||
#if defined(__x86_64__) || defined(__amd64__)
|
||||
#define DLLINTERNAL __attribute__((visibility("internal")))
|
||||
#define DLLINTERNAL_NOVIS
|
||||
#else
|
||||
#ifdef __INTERNALS_USE_REGPARAMS__
|
||||
#define DLLINTERNAL __attribute__((visibility("internal"), regparm(3)))
|
||||
#define DLLINTERNAL_NOVIS __attribute__((regparm(3)))
|
||||
#else
|
||||
#define DLLINTERNAL __attribute__((visibility("internal")))
|
||||
#define DLLINTERNAL_NOVIS
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define DLLHIDDEN
|
||||
#if defined (_WIN32) && defined (_MSC_VER)
|
||||
#define DLLINTERNAL_NOVIS
|
||||
#define DLLINTERNAL
|
||||
#else
|
||||
#ifdef __INTERNALS_USE_REGPARAMS__
|
||||
#define DLLINTERNAL_NOVIS __attribute__((regparm(3)))
|
||||
#define DLLINTERNAL DLLINTERNAL_NOVIS
|
||||
#else
|
||||
#define DLLINTERNAL_NOVIS
|
||||
#define DLLINTERNAL
|
||||
#endif
|
||||
#endif //defined WIN32
|
||||
#endif
|
||||
|
||||
#if defined (_WIN32) && defined (_MSC_VER)
|
||||
// On x86 va_list is just a pointer.
|
||||
#define va_copy(dst,src) ((dst)=(src))
|
||||
#else
|
||||
// Some systems that do not supply va_copy have __va_copy instead, since
|
||||
// that was the name used in the draft proposal.
|
||||
#if !defined(__GNUC__) || __GNUC__ < 3
|
||||
#define va_copy __va_copy
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Manual branch optimization for GCC 3.0.0 and newer
|
||||
#if !defined(__GNUC__) || __GNUC__ < 3
|
||||
#define likely(x) (x)
|
||||
#define unlikely(x) (x)
|
||||
#else
|
||||
#define likely(x) __builtin_expect((long int)(x), true)
|
||||
#define unlikely(x) __builtin_expect((long int)(x), false)
|
||||
#endif
|
||||
|
||||
#endif /*COMP_DEP_H*/
|
||||
240
src/metamod/conf_meta.cpp
Normal file
240
src/metamod/conf_meta.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// conf_meta.cpp - configfile reading routines
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h> // FILE,
|
||||
#include <stdlib.h> // atoi
|
||||
#include <ctype.h> // isdigit
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "conf_meta.h" // me
|
||||
#include "support_meta.h" // strmatch
|
||||
#include "osdep.h" // strtok,
|
||||
|
||||
MConfig::MConfig(void)
|
||||
: list(NULL), filename(NULL), debuglevel(0), gamedll(NULL),
|
||||
plugins_file(NULL), exec_cfg(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// Initialize default values from the stored options struct. Has to happen
|
||||
// _after_ constructor, so that all the fields are allocated (d'oh).
|
||||
void DLLINTERNAL MConfig::init(option_t *global_options) {
|
||||
option_t *optp;
|
||||
list=global_options;
|
||||
for(optp=list; optp->name; optp++)
|
||||
set(optp, optp->init);
|
||||
}
|
||||
|
||||
option_t * DLLINTERNAL MConfig::find(const char *lookup) {
|
||||
option_t *optp;
|
||||
|
||||
for(optp=list; optp->name && !strmatch(optp->name, lookup); optp++);
|
||||
if(optp->name)
|
||||
return(optp);
|
||||
else
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
mBOOL DLLINTERNAL MConfig::set(const char *key, const char *value) {
|
||||
option_t *optp;
|
||||
optp=find(key);
|
||||
if(optp)
|
||||
return(set(optp, value));
|
||||
else
|
||||
RETURN_ERRNO(mFALSE, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
mBOOL DLLINTERNAL MConfig::set(option_t *setp, const char *setstr) {
|
||||
char pathbuf[PATH_MAX];
|
||||
int *optval = (int *) setp->dest;
|
||||
char **optstr = (char **) setp->dest;
|
||||
// cvar_t *optcvar = (cvar_t *) setp->dest;
|
||||
// SETOPT_FN optcmd = (SETOPT_FN) setp->dest;
|
||||
|
||||
if(!setstr)
|
||||
return(mTRUE);
|
||||
|
||||
switch(setp->type) {
|
||||
case CF_INT:
|
||||
if(!isdigit(setstr[0])) {
|
||||
META_WARNING("option '%s' invalid format '%s'", setp->name, setstr);
|
||||
RETURN_ERRNO(mFALSE, ME_FORMAT);
|
||||
}
|
||||
*optval=atoi(setstr);
|
||||
META_DEBUG(3, ("set config int: %s = %d", setp->name, *optval));
|
||||
break;
|
||||
case CF_BOOL:
|
||||
if(strcasematch(setstr, "true")
|
||||
|| strcasematch(setstr, "yes")
|
||||
|| strmatch(setstr, "1"))
|
||||
{
|
||||
*optval=1;
|
||||
}
|
||||
else if(strcasematch(setstr, "false")
|
||||
|| strcasematch(setstr, "no")
|
||||
|| strmatch(setstr, "0"))
|
||||
{
|
||||
*optval=0;
|
||||
}
|
||||
else {
|
||||
META_WARNING("option '%s' invalid format '%s'", setp->name, setstr);
|
||||
RETURN_ERRNO(mFALSE, ME_FORMAT);
|
||||
}
|
||||
META_DEBUG(3, ("set config bool: %s = %s", setp->name, *optval ? "true" : "false"));
|
||||
break;
|
||||
case CF_STR:
|
||||
if(*optstr)
|
||||
free(*optstr);
|
||||
*optstr=strdup(setstr);
|
||||
META_DEBUG(3, ("set config string: %s = %s", setp->name, *optstr));
|
||||
break;
|
||||
case CF_PATH:
|
||||
if(*optstr)
|
||||
free(*optstr);
|
||||
full_gamedir_path(setstr, pathbuf);
|
||||
*optstr=strdup(pathbuf);
|
||||
META_DEBUG(3, ("set config path: %s = %s", setp->name, *optstr));
|
||||
break;
|
||||
#if 0
|
||||
case CF_CVAR:
|
||||
CVAR_SET_STRING(optcvar->name, setstr);
|
||||
META_DEBUG(3, ("set config cvar: %s = %s", optcvar->name, setstr));
|
||||
break;
|
||||
case CF_CMD:
|
||||
optcmd(setp->name, setstr);
|
||||
META_DEBUG(3, ("set config command: %s, %s", optcvar->name, setstr));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
META_WARNING("unrecognized config type '%d'", setp->type);
|
||||
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
|
||||
}
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
mBOOL DLLINTERNAL MConfig::load(const char *fn) {
|
||||
FILE *fp;
|
||||
char loadfile[PATH_MAX];
|
||||
char line[MAX_CONF_LEN];
|
||||
char *optname, *optval;
|
||||
option_t *optp;
|
||||
int ln;
|
||||
|
||||
// Make full pathname (from gamedir if relative, collapse "..",
|
||||
// backslashes, etc).
|
||||
full_gamedir_path(fn, loadfile);
|
||||
|
||||
fp=fopen(loadfile, "r");
|
||||
if(!fp) {
|
||||
META_WARNING("unable to open config file '%s': %s", loadfile,
|
||||
strerror(errno));
|
||||
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
||||
}
|
||||
|
||||
META_DEBUG(2, ("Loading from config file: %s", loadfile));
|
||||
for(ln=1; !feof(fp) && fgets(line, sizeof(line), fp); ln++) {
|
||||
if(line[0]=='#')
|
||||
continue;
|
||||
if(line[0]==';')
|
||||
continue;
|
||||
if(strnmatch(line, "//", 2))
|
||||
continue;
|
||||
if(!(optname=strtok(line, " \t\r\n"))) {
|
||||
META_WARNING("'%s' line %d: bad config format: missing option",
|
||||
loadfile, ln);
|
||||
continue;
|
||||
}
|
||||
if(!(optval=strtok(NULL, "\r\n"))) {
|
||||
META_WARNING("'%s' line %d: bad config format: missing value",
|
||||
loadfile, ln);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!(optp=find(optname))) {
|
||||
META_WARNING("'%s' line %d: unknown option name '%s'",
|
||||
loadfile, ln, optname);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!set(optp, optval)) {
|
||||
META_WARNING("'%s' line %d: unable to set option '%s' value '%s'",
|
||||
loadfile, ln, optname, optval);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
filename=strdup(loadfile);
|
||||
fclose(fp);
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
void DLLINTERNAL MConfig::show(void) {
|
||||
option_t *optp;
|
||||
if(filename)
|
||||
META_CONS("%s and %s:", "Config options from localinfo", filename);
|
||||
else
|
||||
META_CONS("%s:", "Config options from localinfo");
|
||||
for(optp=list; optp->name; optp++) {
|
||||
int *optval = (int *) optp->dest;
|
||||
char **optstr = (char **) optp->dest;
|
||||
// cvar_t *optcvar = (cvar_t *) optp->dest;
|
||||
// SETOPT_FN optcmd = (SETOPT_FN) optp->dest;
|
||||
switch(optp->type) {
|
||||
case CF_INT:
|
||||
META_CONS(" %-20s\t%d\n", optp->name, *optval);
|
||||
break;
|
||||
case CF_BOOL:
|
||||
META_CONS(" %-20s\t%s\n", optp->name,
|
||||
*optval ? "true" : "false");
|
||||
break;
|
||||
case CF_STR:
|
||||
case CF_PATH:
|
||||
META_CONS(" %-20s\t%s\n", optp->name,
|
||||
*optstr ? *optstr : "");
|
||||
break;
|
||||
#if 0
|
||||
case CF_CVAR:
|
||||
META_CONS(" %-20s\tstores in: %s\n", optp->name, optcvar->name);
|
||||
break;
|
||||
case CF_CMD:
|
||||
META_CONS(" %-20s\tparsed by: %d\n", optp->name, (int) optcmd);
|
||||
break;
|
||||
#endif
|
||||
case CF_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
100
src/metamod/conf_meta.h
Normal file
100
src/metamod/conf_meta.h
Normal file
@@ -0,0 +1,100 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// conf_meta.h - configfile reading
|
||||
|
||||
// Modeled after mutt/init.[ch].
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONF_META_H
|
||||
#define CONF_META_H
|
||||
|
||||
#include "types_meta.h" // mBOOL
|
||||
#include "new_baseclass.h"
|
||||
#include "comp_dep.h"
|
||||
|
||||
// Max length of line in config file.
|
||||
#define MAX_CONF_LEN 1024
|
||||
|
||||
// Supported config value-types.
|
||||
typedef enum {
|
||||
CF_NONE=0,
|
||||
CF_INT,
|
||||
CF_BOOL,
|
||||
CF_STR,
|
||||
CF_PATH,
|
||||
#if 0
|
||||
CF_CVAR,
|
||||
CF_CMD,
|
||||
#endif
|
||||
} cf_type_t;
|
||||
|
||||
//typedef mBOOL (*SETOPT_FN) (char *key, char *value);
|
||||
|
||||
typedef struct option_s {
|
||||
char *name; // option name
|
||||
cf_type_t type; // option type
|
||||
void *dest; // addr of destination variable, or handler function
|
||||
char *init; // initial value, as a string, just as config file would
|
||||
} option_t;
|
||||
|
||||
class MConfig : public class_metamod_new {
|
||||
private:
|
||||
// data
|
||||
option_t *list;
|
||||
char *filename;
|
||||
// functions
|
||||
option_t * DLLINTERNAL find(const char *lookup);
|
||||
mBOOL DLLINTERNAL set(option_t *setp, const char *value);
|
||||
// Private; to satisfy -Weffc++ "has pointer data members but does
|
||||
// not override" copy/assignment constructor.
|
||||
void operator=(const MConfig &src);
|
||||
MConfig(const MConfig &src);
|
||||
public:
|
||||
// contructor
|
||||
MConfig(void) DLLINTERNAL;
|
||||
// data
|
||||
int debuglevel; // to use for meta_debug
|
||||
char *gamedll; // string if specified in config.ini
|
||||
char *plugins_file; // ie metamod.ini, plugins.ini
|
||||
char *exec_cfg; // ie metaexec.cfg, exec.cfg
|
||||
int autodetect; // autodetection of gamedll (Metamod-All-Support patch)
|
||||
int clientmeta; // control 'meta' client-command
|
||||
// functions
|
||||
void DLLINTERNAL init(option_t *global_options);
|
||||
mBOOL DLLINTERNAL load(const char *filename);
|
||||
mBOOL DLLINTERNAL set(const char *key, const char *value);
|
||||
void DLLINTERNAL show(void);
|
||||
};
|
||||
|
||||
#endif /* CONF_META_H */
|
||||
513
src/metamod/dllapi.cpp
Normal file
513
src/metamod/dllapi.cpp
Normal file
@@ -0,0 +1,513 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// dllapi.cpp - implementation of Half-Life DLL routines
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h> // offsetof
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "dllapi.h" // me
|
||||
#include "metamod.h" // SETUP_API_CALLS, etc
|
||||
#include "api_info.h" // dllapi_info, etc
|
||||
#include "commands_meta.h" // client_meta, etc
|
||||
#include "log_meta.h" // META_ERROR, etc
|
||||
#include "api_hook.h"
|
||||
|
||||
|
||||
// Original DLL routines, functions returning "void".
|
||||
#define META_DLLAPI_HANDLE_void(FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
||||
API_START_TSC_TRACKING(); \
|
||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
||||
main_hook_function_void(offsetof(dllapi_info_t, pfnName), e_api_dllapi, offsetof(DLL_FUNCTIONS, pfnName), &packed_args); \
|
||||
API_END_TSC_TRACKING()
|
||||
|
||||
// Original DLL routines, functions returning an actual value.
|
||||
#define META_DLLAPI_HANDLE(ret_t, ret_init, FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
||||
API_START_TSC_TRACKING(); \
|
||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
||||
class_ret_t ret_val(main_hook_function(class_ret_t((ret_t)ret_init), offsetof(dllapi_info_t, pfnName), e_api_dllapi, offsetof(DLL_FUNCTIONS, pfnName), &packed_args)); \
|
||||
API_END_TSC_TRACKING()
|
||||
|
||||
// The "new" api routines (just 3 right now), functions returning "void".
|
||||
#define META_NEWAPI_HANDLE_void(FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
||||
API_START_TSC_TRACKING(); \
|
||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
||||
main_hook_function_void(offsetof(newapi_info_t, pfnName), e_api_newapi, offsetof(NEW_DLL_FUNCTIONS, pfnName), &packed_args); \
|
||||
API_END_TSC_TRACKING()
|
||||
|
||||
// The "new" api routines (just 3 right now), functions returning an actual value.
|
||||
#define META_NEWAPI_HANDLE(ret_t, ret_init, FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
||||
API_START_TSC_TRACKING(); \
|
||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
||||
class_ret_t ret_val(main_hook_function(class_ret_t((ret_t)ret_init), offsetof(newapi_info_t, pfnName), e_api_newapi, offsetof(NEW_DLL_FUNCTIONS, pfnName), &packed_args)); \
|
||||
API_END_TSC_TRACKING()
|
||||
|
||||
|
||||
// From SDK dlls/game.cpp:
|
||||
static void mm_GameDLLInit(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_GAMEINIT, pfnGameInit, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
|
||||
// From SDK dlls/cbase.cpp:
|
||||
static int mm_DispatchSpawn(edict_t *pent) {
|
||||
// 0==Success, -1==Failure ?
|
||||
META_DLLAPI_HANDLE(int, 0, FN_DISPATCHSPAWN, pfnSpawn, p, (pent));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static void mm_DispatchThink(edict_t *pent) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHTHINK, pfnThink, p, (pent));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_DispatchUse(edict_t *pentUsed, edict_t *pentOther) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHUSE, pfnUse, 2p, (pentUsed, pentOther));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_DispatchTouch(edict_t *pentTouched, edict_t *pentOther) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHTOUCH, pfnTouch, 2p, (pentTouched, pentOther));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_DispatchBlocked(edict_t *pentBlocked, edict_t *pentOther) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHBLOCKED, pfnBlocked, 2p, (pentBlocked, pentOther));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_DispatchKeyValue(edict_t *pentKeyvalue, KeyValueData *pkvd) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHKEYVALUE, pfnKeyValue, 2p, (pentKeyvalue, pkvd));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_DispatchSave(edict_t *pent, SAVERESTOREDATA *pSaveData) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHSAVE, pfnSave, 2p, (pent, pSaveData));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_DispatchRestore(edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity) {
|
||||
// 0==Success, -1==Failure ?
|
||||
META_DLLAPI_HANDLE(int, 0, FN_DISPATCHRESTORE, pfnRestore, 2pi, (pent, pSaveData, globalEntity));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static void mm_DispatchObjectCollsionBox(edict_t *pent) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHOBJECTCOLLISIONBOX, pfnSetAbsBox, p, (pent));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_SaveWriteFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount) {
|
||||
META_DLLAPI_HANDLE_void(FN_SAVEWRITEFIELDS, pfnSaveWriteFields, 4pi, (pSaveData, pname, pBaseData, pFields, fieldCount));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_SaveReadFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount) {
|
||||
META_DLLAPI_HANDLE_void(FN_SAVEREADFIELDS, pfnSaveReadFields, 4pi, (pSaveData, pname, pBaseData, pFields, fieldCount));
|
||||
RETURN_API_void();
|
||||
}
|
||||
|
||||
// From SDK dlls/world.cpp:
|
||||
static void mm_SaveGlobalState(SAVERESTOREDATA *pSaveData) {
|
||||
META_DLLAPI_HANDLE_void(FN_SAVEGLOBALSTATE, pfnSaveGlobalState, p, (pSaveData));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_RestoreGlobalState(SAVERESTOREDATA *pSaveData) {
|
||||
META_DLLAPI_HANDLE_void(FN_RESTOREGLOBALSTATE, pfnRestoreGlobalState, p, (pSaveData));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ResetGlobalState(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_RESETGLOBALSTATE, pfnResetGlobalState, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
|
||||
// From SDK dlls/client.cpp:
|
||||
static qboolean mm_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) {
|
||||
g_Players.clear_player_cvar_query(pEntity);
|
||||
META_DLLAPI_HANDLE(qboolean, TRUE, FN_CLIENTCONNECT, pfnClientConnect, 4p, (pEntity, pszName, pszAddress, szRejectReason));
|
||||
RETURN_API(qboolean);
|
||||
}
|
||||
static void mm_ClientDisconnect(edict_t *pEntity) {
|
||||
g_Players.clear_player_cvar_query(pEntity);
|
||||
META_DLLAPI_HANDLE_void(FN_CLIENTDISCONNECT, pfnClientDisconnect, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ClientKill(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_CLIENTKILL, pfnClientKill, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ClientPutInServer(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_CLIENTPUTINSERVER, pfnClientPutInServer, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ClientCommand(edict_t *pEntity) {
|
||||
if(Config->clientmeta && strmatch(CMD_ARGV(0), "meta")) {
|
||||
client_meta(pEntity);
|
||||
}
|
||||
META_DLLAPI_HANDLE_void(FN_CLIENTCOMMAND, pfnClientCommand, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ClientUserInfoChanged(edict_t *pEntity, char *infobuffer) {
|
||||
META_DLLAPI_HANDLE_void(FN_CLIENTUSERINFOCHANGED, pfnClientUserInfoChanged, 2p, (pEntity, infobuffer));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) {
|
||||
META_DLLAPI_HANDLE_void(FN_SERVERACTIVATE, pfnServerActivate, p2i, (pEdictList, edictCount, clientMax));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ServerDeactivate(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_SERVERDEACTIVATE, pfnServerDeactivate, void, (VOID_ARG));
|
||||
// Update loaded plugins. Look for new plugins in inifile, as well as
|
||||
// any plugins waiting for a changelevel to load.
|
||||
//
|
||||
// This is done in ServerDeactivate rather than Activate, as the latter
|
||||
// isn't actually the first routine to be called on a new map. In
|
||||
// particular DispatchKeyValue and DispatchSpawn are called before
|
||||
// Activate, and we want any newly loaded plugins to be able to catch
|
||||
// these.
|
||||
//
|
||||
// So, we do this from Deactivate, which is the _last_ routine called
|
||||
// from the previous map. It's also called right before shutdown,
|
||||
// which means whenever hlds quits, it'll reload the plugins just
|
||||
// before it exits, which is rather silly, but oh well.
|
||||
Plugins->refresh(PT_CHANGELEVEL);
|
||||
Plugins->unpause_all();
|
||||
// Plugins->retry_all(PT_CHANGELEVEL);
|
||||
g_Players.clear_all_cvar_queries();
|
||||
requestid_counter = 0;
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_PlayerPreThink(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_PLAYERPRETHINK, pfnPlayerPreThink, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_PlayerPostThink(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_PLAYERPOSTTHINK, pfnPlayerPostThink, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_StartFrame(void) {
|
||||
meta_debug_value = (int)meta_debug.value;
|
||||
|
||||
META_DLLAPI_HANDLE_void(FN_STARTFRAME, pfnStartFrame, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ParmsNewLevel(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_PARMSNEWLEVEL, pfnParmsNewLevel, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ParmsChangeLevel(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_PARMSCHANGELEVEL, pfnParmsChangeLevel, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static const char *mm_GetGameDescription(void) {
|
||||
META_DLLAPI_HANDLE(const char *, NULL, FN_GETGAMEDESCRIPTION, pfnGetGameDescription, void, (VOID_ARG));
|
||||
RETURN_API(const char *);
|
||||
}
|
||||
static void mm_PlayerCustomization(edict_t *pEntity, customization_t *pCust) {
|
||||
META_DLLAPI_HANDLE_void(FN_PLAYERCUSTOMIZATION, pfnPlayerCustomization, 2p, (pEntity, pCust));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_SpectatorConnect(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_SPECTATORCONNECT, pfnSpectatorConnect, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_SpectatorDisconnect(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_SPECTATORDISCONNECT, pfnSpectatorDisconnect, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_SpectatorThink(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_SPECTATORTHINK, pfnSpectatorThink, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_Sys_Error(const char *error_string) {
|
||||
META_DLLAPI_HANDLE_void(FN_SYS_ERROR, pfnSys_Error, p, (error_string));
|
||||
RETURN_API_void();
|
||||
}
|
||||
|
||||
// From SDK pm_shared/pm_shared.c:
|
||||
static void mm_PM_Move (struct playermove_s *ppmove, int server) {
|
||||
META_DLLAPI_HANDLE_void(FN_PM_MOVE, pfnPM_Move, pi, (ppmove, server));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_PM_Init(struct playermove_s *ppmove) {
|
||||
META_DLLAPI_HANDLE_void(FN_PM_INIT, pfnPM_Init, p, (ppmove));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static char mm_PM_FindTextureType(char *name) {
|
||||
META_DLLAPI_HANDLE(char, '\0', FN_PM_FINDTEXTURETYPE, pfnPM_FindTextureType, p, (name));
|
||||
RETURN_API(char);
|
||||
}
|
||||
|
||||
// From SDK dlls/client.cpp:
|
||||
static void mm_SetupVisibility(edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas) {
|
||||
META_DLLAPI_HANDLE_void(FN_SETUPVISIBILITY, pfnSetupVisibility, 4p, (pViewEntity, pClient, pvs, pas));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_UpdateClientData (const struct edict_s *ent, int sendweapons, struct clientdata_s *cd) {
|
||||
META_DLLAPI_HANDLE_void(FN_UPDATECLIENTDATA, pfnUpdateClientData, pip, (ent, sendweapons, cd));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_AddToFullPack(struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_ADDTOFULLPACK, pfnAddToFullPack, pi2p2ip, (state, e, ent, host, hostflags, player, pSet));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static void mm_CreateBaseline(int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs) {
|
||||
META_DLLAPI_HANDLE_void(FN_CREATEBASELINE, pfnCreateBaseline, 2i2pi2p, (player, eindex, baseline, entity, playermodelindex, (float*)player_mins, (float*)player_maxs));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_RegisterEncoders(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_REGISTERENCODERS, pfnRegisterEncoders, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_GetWeaponData(struct edict_s *player, struct weapon_data_s *info) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_GETWEAPONDATA, pfnGetWeaponData, 2p, (player, info));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static void mm_CmdStart(const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed) {
|
||||
META_DLLAPI_HANDLE_void(FN_CMDSTART, pfnCmdStart, 2pui, (player, cmd, random_seed));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_CmdEnd (const edict_t *player) {
|
||||
META_DLLAPI_HANDLE_void(FN_CMDEND, pfnCmdEnd, p, (player));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_ConnectionlessPacket(const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_CONNECTIONLESSPACKET, pfnConnectionlessPacket, 4p, (net_from, args, response_buffer, response_buffer_size));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static int mm_GetHullBounds(int hullnumber, float *mins, float *maxs) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_GETHULLBOUNDS, pfnGetHullBounds, i2p, (hullnumber, mins, maxs));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static void mm_CreateInstancedBaselines (void) {
|
||||
META_DLLAPI_HANDLE_void(FN_CREATEINSTANCEDBASELINES, pfnCreateInstancedBaselines, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_InconsistentFile(const edict_t *player, const char *filename, char *disconnect_message) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_INCONSISTENTFILE, pfnInconsistentFile, 3p, (player, filename, disconnect_message));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static int mm_AllowLagCompensation(void) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_ALLOWLAGCOMPENSATION, pfnAllowLagCompensation, void, (VOID_ARG));
|
||||
RETURN_API(int);
|
||||
}
|
||||
|
||||
|
||||
// New API functions
|
||||
// From SDK ?
|
||||
static void mm_OnFreeEntPrivateData(edict_t *pEnt) {
|
||||
META_NEWAPI_HANDLE_void(FN_ONFREEENTPRIVATEDATA, pfnOnFreeEntPrivateData, p, (pEnt));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_GameShutdown(void) {
|
||||
META_NEWAPI_HANDLE_void(FN_GAMESHUTDOWN, pfnGameShutdown, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_ShouldCollide(edict_t *pentTouched, edict_t *pentOther) {
|
||||
META_NEWAPI_HANDLE(int, 1, FN_SHOULDCOLLIDE, pfnShouldCollide, 2p, (pentTouched, pentOther));
|
||||
RETURN_API(int);
|
||||
}
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
static void mm_CvarValue(const edict_t *pEnt, const char *value) {
|
||||
g_Players.clear_player_cvar_query(pEnt);
|
||||
META_NEWAPI_HANDLE_void(FN_CVARVALUE, pfnCvarValue, 2p, (pEnt, value));
|
||||
|
||||
RETURN_API_void();
|
||||
}
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
static void mm_CvarValue2(const edict_t *pEnt, int requestID, const char *cvarName, const char *value) {
|
||||
META_NEWAPI_HANDLE_void(FN_CVARVALUE2, pfnCvarValue2, pi2p, (pEnt, requestID, cvarName, value));
|
||||
|
||||
RETURN_API_void();
|
||||
}
|
||||
|
||||
|
||||
// From SDK dlls/cbase.cpp:
|
||||
// "(wd)" indicates my comments on the functions
|
||||
static DLL_FUNCTIONS gFunctionTable =
|
||||
{
|
||||
mm_GameDLLInit, //! pfnGameInit() Initialize the game (one-time call after loading of game .dll)
|
||||
mm_DispatchSpawn, //! pfnSpawn()
|
||||
mm_DispatchThink, //! pfnThink()
|
||||
mm_DispatchUse, //! pfnUse()
|
||||
mm_DispatchTouch, //! pfnTouch()
|
||||
mm_DispatchBlocked, //! pfnBlocked()
|
||||
mm_DispatchKeyValue, //! pfnKeyValue()
|
||||
mm_DispatchSave, //! pfnSave()
|
||||
mm_DispatchRestore, //! pfnRestore()
|
||||
mm_DispatchObjectCollsionBox, //! pfnSetAbsBox()
|
||||
|
||||
mm_SaveWriteFields, //! pfnSaveWriteFields()
|
||||
mm_SaveReadFields, //! pfnSaveReadFields()
|
||||
|
||||
mm_SaveGlobalState, //! pfnSaveGlobalState()
|
||||
mm_RestoreGlobalState, //! pfnRestoreGlobalState()
|
||||
mm_ResetGlobalState, //! pfnResetGlobalState()
|
||||
|
||||
mm_ClientConnect, //! pfnClientConnect() (wd) Client has connected
|
||||
mm_ClientDisconnect, //! pfnClientDisconnect() (wd) Player has left the game
|
||||
mm_ClientKill, //! pfnClientKill() (wd) Player has typed "kill"
|
||||
mm_ClientPutInServer, //! pfnClientPutInServer() (wd) Client is entering the game
|
||||
mm_ClientCommand, //! pfnClientCommand() (wd) Player has sent a command (typed, or from a bind)
|
||||
mm_ClientUserInfoChanged, //! pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure
|
||||
mm_ServerActivate, //! pfnServerActivate() (wd) Server is starting a new map
|
||||
mm_ServerDeactivate, //! pfnServerDeactivate() (wd) Server is leaving the map (shutdown, or changelevel); SDK2
|
||||
|
||||
mm_PlayerPreThink, //! pfnPlayerPreThink()
|
||||
mm_PlayerPostThink, //! pfnPlayerPostThink()
|
||||
|
||||
mm_StartFrame, //! pfnStartFrame()
|
||||
mm_ParmsNewLevel, //! pfnParmsNewLevel()
|
||||
mm_ParmsChangeLevel, //! pfnParmsChangeLevel()
|
||||
|
||||
mm_GetGameDescription, //! pfnGetGameDescription() Returns string describing current .dll. E.g. "TeamFotrress 2", "Half-Life"
|
||||
mm_PlayerCustomization, //! pfnPlayerCustomization() Notifies .dll of new customization for player.
|
||||
|
||||
mm_SpectatorConnect, //! pfnSpectatorConnect() Called when spectator joins server
|
||||
mm_SpectatorDisconnect, //! pfnSpectatorDisconnect() Called when spectator leaves the server
|
||||
mm_SpectatorThink, //! pfnSpectatorThink() Called when spectator sends a command packet (usercmd_t)
|
||||
|
||||
mm_Sys_Error, //! pfnSys_Error() Notify game .dll that engine is going to shut down. Allows mod authors to set a breakpoint. SDK2
|
||||
|
||||
mm_PM_Move, //! pfnPM_Move() (wd) SDK2
|
||||
mm_PM_Init, //! pfnPM_Init() Server version of player movement initialization; (wd) SDK2
|
||||
mm_PM_FindTextureType, //! pfnPM_FindTextureType() (wd) SDK2
|
||||
|
||||
mm_SetupVisibility, //! pfnSetupVisibility() Set up PVS and PAS for networking for this client; (wd) SDK2
|
||||
mm_UpdateClientData, //! pfnUpdateClientData() Set up data sent only to specific client; (wd) SDK2
|
||||
mm_AddToFullPack, //! pfnAddToFullPack() (wd) SDK2
|
||||
mm_CreateBaseline, //! pfnCreateBaseline() Tweak entity baseline for network encoding, allows setup of player baselines, too.; (wd) SDK2
|
||||
mm_RegisterEncoders, //! pfnRegisterEncoders() Callbacks for network encoding; (wd) SDK2
|
||||
mm_GetWeaponData, //! pfnGetWeaponData() (wd) SDK2
|
||||
mm_CmdStart, //! pfnCmdStart() (wd) SDK2
|
||||
mm_CmdEnd, //! pfnCmdEnd() (wd) SDK2
|
||||
mm_ConnectionlessPacket, //! pfnConnectionlessPacket() (wd) SDK2
|
||||
mm_GetHullBounds, //! pfnGetHullBounds() (wd) SDK2
|
||||
mm_CreateInstancedBaselines, //! pfnCreateInstancedBaselines() (wd) SDK2
|
||||
mm_InconsistentFile, //! pfnInconsistentFile() (wd) SDK2
|
||||
mm_AllowLagCompensation, //! pfnAllowLagCompensation() (wd) SDK2
|
||||
};
|
||||
|
||||
DLL_FUNCTIONS *g_pHookedDllFunctions = &gFunctionTable;
|
||||
|
||||
// It's not clear what the difference is between GetAPI and GetAPI2; they
|
||||
// both appear to return the exact same function table.
|
||||
//
|
||||
// Only one of them appears to be ever called, though. If the DLL provides
|
||||
// GetAPI2, the engine/hlds will call that, and will not call GetAPI. If
|
||||
// the engine couldn't find GetAPI2 in the DLL, it appears to fall back to
|
||||
// GetAPI.
|
||||
//
|
||||
// So, GetAPI2 appears to replace GetAPI, and appears to have been added
|
||||
// with SDK 2.0. My best guess is that, with the new SDK, interface
|
||||
// version checking became important, and without the int ptr used in
|
||||
// GetAPI2, the engine can't find out the version of the DLL via GetAPI.
|
||||
//
|
||||
// It's unclear whether a DLL coded under SDK2 needs to provide the older
|
||||
// GetAPI or not..
|
||||
|
||||
C_DLLEXPORT int GetEntityAPI(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion)
|
||||
{
|
||||
META_DEBUG(3, ("called: GetEntityAPI; version=%d", interfaceVersion));
|
||||
if(!pFunctionTable || metamod_not_loaded) {
|
||||
META_WARNING("GetEntityAPI called with null pFunctionTable");
|
||||
return(FALSE);
|
||||
}
|
||||
else if(interfaceVersion != INTERFACE_VERSION) {
|
||||
META_WARNING("GetEntityAPI version mismatch; requested=%d ours=%d", interfaceVersion, INTERFACE_VERSION);
|
||||
return(FALSE);
|
||||
}
|
||||
memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS));
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion)
|
||||
{
|
||||
META_DEBUG(3, ("called: GetEntityAPI2; version=%d", *interfaceVersion));
|
||||
if(!pFunctionTable || metamod_not_loaded) {
|
||||
META_WARNING("GetEntityAPI2 called with null pFunctionTable");
|
||||
return(FALSE);
|
||||
}
|
||||
else if(*interfaceVersion != INTERFACE_VERSION) {
|
||||
META_WARNING("GetEntityAPI2 version mismatch; requested=%d ours=%d", *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);
|
||||
}
|
||||
|
||||
|
||||
// I could find _no_ documentation or examples for the intended use of
|
||||
// NEW_DLL_FUNCTIONS. I wouldn't have even _known_ about the
|
||||
// GetNewDLLFunctions() function except for the reference in Adminmod.. It
|
||||
// appears to be new with SDK 2.0.
|
||||
//
|
||||
// Obviously, it seems to provide additional functions to the engine, but
|
||||
// it's unclear why a new table and interface were added, rather than
|
||||
// appending new functions to the GetAPI table/interface.
|
||||
//
|
||||
// Interestingly, it appears to be called by the engine _before_ GetAPI.
|
||||
|
||||
static meta_new_dll_functions_t sNewFunctionTable(
|
||||
&mm_OnFreeEntPrivateData, //! pfnOnFreeEntPrivateData() Called right before the object's memory is freed. Calls its destructor.
|
||||
&mm_GameShutdown, //! pfnGameShutdown()
|
||||
&mm_ShouldCollide, //! pfnShouldCollide()
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
&mm_CvarValue, //! pfnCvarValue()
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
&mm_CvarValue2 //! pfnCvarValue2()
|
||||
);
|
||||
|
||||
NEW_DLL_FUNCTIONS *g_pHookedNewDllFunctions = &sNewFunctionTable;
|
||||
|
||||
C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion)
|
||||
{
|
||||
META_DEBUG(6, ("called: GetNewDLLFunctions; version=%d", *interfaceVersion));
|
||||
#if 0 // ~dvander - but then you can't use cvar querying on many mods...
|
||||
// Don't provide these functions to engine if gamedll doesn't provide
|
||||
// them. Otherwise, we're in the position of having to provide answers
|
||||
// we can't necessarily provide (for instance, ShouldCollide())...
|
||||
if(!GameDLL.funcs.newapi_table)
|
||||
return(FALSE);
|
||||
#endif
|
||||
|
||||
if(!pNewFunctionTable) {
|
||||
META_ERROR("GetNewDLLFunctions called with null pNewFunctionTable");
|
||||
return(FALSE);
|
||||
}
|
||||
else if(*interfaceVersion != NEW_DLL_FUNCTIONS_VERSION) {
|
||||
META_ERROR("GetNewDLLFunctions version mismatch; requested=%d ours=%d", *interfaceVersion, NEW_DLL_FUNCTIONS_VERSION);
|
||||
//! Tell engine what version we had, so it can figure out who is out of date.
|
||||
*interfaceVersion = NEW_DLL_FUNCTIONS_VERSION;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
sNewFunctionTable.copy_to(pNewFunctionTable);
|
||||
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
121
src/metamod/dllapi.h
Normal file
121
src/metamod/dllapi.h
Normal file
@@ -0,0 +1,121 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// dllapi.h - prototypes and typedefs for Half-Life DLL API routines
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DLLAPI_H
|
||||
#define DLLAPI_H
|
||||
|
||||
#include "sdk_util.h" // BOOL
|
||||
#include "osdep.h" // DLLEXPORT, etc
|
||||
|
||||
// Typedefs for these are provided in SDK engine/eiface.h, but I didn't
|
||||
// like the names (APIFUNCTION, APIFUNCTION2, NEW_DLL_FUNCTIONS_FN).
|
||||
typedef int (*GETENTITYAPI_FN) (DLL_FUNCTIONS *pFunctionTable, int interfaceVersion);
|
||||
typedef int (*GETENTITYAPI2_FN) (DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion);
|
||||
typedef int (*GETNEWDLLFUNCTIONS_FN) (NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion);
|
||||
|
||||
// From SDK dlls/cbase.h:
|
||||
C_DLLEXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
|
||||
C_DLLEXPORT int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
|
||||
|
||||
// No example in SDK..
|
||||
// From Adminmod dll.cpp:
|
||||
C_DLLEXPORT int GetNewDLLFunctions( NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion );
|
||||
|
||||
// Typedefs for the above functions:
|
||||
|
||||
typedef void (*FN_GAMEINIT) ( void );
|
||||
typedef int (*FN_DISPATCHSPAWN) ( edict_t *pent );
|
||||
typedef void (*FN_DISPATCHTHINK) ( edict_t *pent );
|
||||
typedef void (*FN_DISPATCHUSE) ( edict_t *pentUsed, edict_t *pentOther );
|
||||
typedef void (*FN_DISPATCHTOUCH) ( edict_t *pentTouched, edict_t *pentOther );
|
||||
typedef void (*FN_DISPATCHBLOCKED) ( edict_t *pentBlocked, edict_t *pentOther );
|
||||
typedef void (*FN_DISPATCHKEYVALUE) ( edict_t *pentKeyvalue, KeyValueData *pkvd );
|
||||
typedef void (*FN_DISPATCHSAVE) ( edict_t *pent, SAVERESTOREDATA *pSaveData );
|
||||
typedef int (*FN_DISPATCHRESTORE) ( edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity );
|
||||
typedef void (*FN_DISPATCHOBJECTCOLLISIONBOX) ( edict_t *pent );
|
||||
typedef void (*FN_SAVEWRITEFIELDS) ( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
|
||||
typedef void (*FN_SAVEREADFIELDS) ( SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
|
||||
typedef void (*FN_SAVEGLOBALSTATE) ( SAVERESTOREDATA *pSaveData );
|
||||
typedef void (*FN_RESTOREGLOBALSTATE) ( SAVERESTOREDATA *pSaveData );
|
||||
typedef void (*FN_RESETGLOBALSTATE) ( void );
|
||||
|
||||
typedef qboolean (*FN_CLIENTCONNECT) ( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]);
|
||||
typedef void (*FN_CLIENTDISCONNECT) ( edict_t *pEntity );
|
||||
typedef void (*FN_CLIENTKILL) ( edict_t *pEntity );
|
||||
typedef void (*FN_CLIENTPUTINSERVER) ( edict_t *pEntity );
|
||||
typedef void (*FN_CLIENTCOMMAND) ( edict_t *pEntity );
|
||||
typedef void (*FN_CLIENTUSERINFOCHANGED) ( edict_t *pEntity, char *infobuffer );
|
||||
typedef void (*FN_SERVERACTIVATE) ( edict_t *pEdictList, int edictCount, int clientMax );
|
||||
typedef void (*FN_SERVERDEACTIVATE) ( void );
|
||||
typedef void (*FN_PLAYERPRETHINK) ( edict_t *pEntity );
|
||||
typedef void (*FN_PLAYERPOSTTHINK) ( edict_t *pEntity );
|
||||
typedef void (*FN_STARTFRAME) ( void );
|
||||
typedef void (*FN_PARMSNEWLEVEL) ( void );
|
||||
typedef void (*FN_PARMSCHANGELEVEL) ( void );
|
||||
typedef const char *(*FN_GETGAMEDESCRIPTION) ( void );
|
||||
typedef void (*FN_PLAYERCUSTOMIZATION) ( edict_t *pEntity, customization_t *pCust );
|
||||
typedef void (*FN_SPECTATORCONNECT) ( edict_t *pEntity );
|
||||
typedef void (*FN_SPECTATORDISCONNECT) ( edict_t *pEntity );
|
||||
typedef void (*FN_SPECTATORTHINK) ( edict_t *pEntity );
|
||||
typedef void (*FN_SYS_ERROR) ( const char *error_string );
|
||||
|
||||
typedef void (*FN_PM_MOVE) ( struct playermove_s *ppmove, int server );
|
||||
typedef void (*FN_PM_INIT) ( struct playermove_s *ppmove );
|
||||
typedef char (*FN_PM_FINDTEXTURETYPE) ( char *name );
|
||||
|
||||
typedef void (*FN_SETUPVISIBILITY) ( edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas );
|
||||
typedef void (*FN_UPDATECLIENTDATA) ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd );
|
||||
typedef int (*FN_ADDTOFULLPACK) ( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet );
|
||||
typedef void (*FN_CREATEBASELINE) ( int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs );
|
||||
typedef void (*FN_REGISTERENCODERS) ( void );
|
||||
typedef int (*FN_GETWEAPONDATA) ( struct edict_s *player, struct weapon_data_s *info );
|
||||
typedef void (*FN_CMDSTART) ( const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed );
|
||||
typedef void (*FN_CMDEND) ( const edict_t *player );
|
||||
typedef int (*FN_CONNECTIONLESSPACKET) ( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
|
||||
typedef int (*FN_GETHULLBOUNDS) ( int hullnumber, float *mins, float *maxs );
|
||||
typedef void (*FN_CREATEINSTANCEDBASELINES) ( void );
|
||||
typedef int (*FN_INCONSISTENTFILE) ( const edict_t *player, const char *filename, char *disconnect_message );
|
||||
typedef int (*FN_ALLOWLAGCOMPENSATION) ( void );
|
||||
|
||||
typedef void (*FN_ONFREEENTPRIVATEDATA) (edict_t *pEnt);
|
||||
typedef void (*FN_GAMESHUTDOWN) (void);
|
||||
typedef int (*FN_SHOULDCOLLIDE) (edict_t *pentTouched, edict_t *pentOther);
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
typedef void (*FN_CVARVALUE)(const edict_t *pEnt, const char *value);
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
typedef void (*FN_CVARVALUE2)(const edict_t *pEnt, int requestID, const char *cvarName, const char *value);
|
||||
|
||||
#endif /* DLLAPI_H */
|
||||
1130
src/metamod/engine_api.cpp
Normal file
1130
src/metamod/engine_api.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user