game: Sync game/header/game.h, game/header/local.h

This commit is contained in:
Denis Pauk 2023-10-18 19:40:55 +03:00
parent 748cc322b3
commit 7b50b2d89f
42 changed files with 3164 additions and 698 deletions

View file

@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
This program 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.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
@ -88,9 +88,9 @@ typedef enum
DAMAGE_AIM // auto targeting recognizes this
} damage_t;
typedef enum
typedef enum
{
WEAPON_READY,
WEAPON_READY,
WEAPON_ACTIVATING,
WEAPON_DROPPING,
WEAPON_FIRING
@ -219,15 +219,15 @@ typedef struct
#define IT_POWERUP 32
// gitem_t->weapmodel for weapons indicates model index
#define WEAP_BLASTER 1
#define WEAP_SHOTGUN 2
#define WEAP_SUPERSHOTGUN 3
#define WEAP_MACHINEGUN 4
#define WEAP_CHAINGUN 5
#define WEAP_GRENADES 6
#define WEAP_GRENADELAUNCHER 7
#define WEAP_ROCKETLAUNCHER 8
#define WEAP_HYPERBLASTER 9
#define WEAP_BLASTER 1
#define WEAP_SHOTGUN 2
#define WEAP_SUPERSHOTGUN 3
#define WEAP_MACHINEGUN 4
#define WEAP_CHAINGUN 5
#define WEAP_GRENADES 6
#define WEAP_GRENADELAUNCHER 7
#define WEAP_ROCKETLAUNCHER 8
#define WEAP_HYPERBLASTER 9
#define WEAP_RAILGUN 10
#define WEAP_BFG 11
@ -458,11 +458,6 @@ extern spawn_temp_t st;
extern int sm_meat_index;
extern int snd_fry;
extern int jacket_armor_index;
extern int combat_armor_index;
extern int body_armor_index;
// means of death
#define MOD_UNKNOWN 0
#define MOD_BLASTER 1
@ -570,7 +565,7 @@ extern cvar_t *sv_maplist;
#define FFL_NOSPAWN 2
typedef enum {
F_INT,
F_INT,
F_FLOAT,
F_LSTRING, // string on disk, pointer in memory, TAG_LEVEL
F_GSTRING, // string on disk, pointer in memory, TAG_GAME
@ -976,7 +971,7 @@ struct edict_s
// FIXME: move these fields to a server private sv_entity_t
link_t area; // linked to a division node or leaf
int num_clusters; // if -1, use headnode instead
int clusternums[MAX_ENT_CLUSTERS];
int headnode; // unused if num_clusters != -1
@ -1001,7 +996,7 @@ struct edict_s
char *model;
float freetime; // sv.time when the object was freed
//
// only used locally in game, not by server
//

View file

@ -1632,7 +1632,7 @@ CTFResetGrapple(edict_t *self)
}
gi.sound(self->owner, CHAN_RELIABLE + CHAN_WEAPON,
gi.soundindex( "weapons/grapple/grreset.wav"), volume, ATTN_NORM, 0);
gi.soundindex("weapons/grapple/grreset.wav"), volume, ATTN_NORM, 0);
cl = self->owner->client;
cl->ctf_grapple = NULL;
cl->ctf_grapplereleasetime = level.time;

View file

@ -984,7 +984,7 @@ body_die(edict_t *self, edict_t *inflictor, edict_t *attacker,
if (self->health < -40)
{
gi.sound(self, CHAN_BODY, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_BODY, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 4; n++)
{

View file

@ -801,7 +801,7 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
{
if (targ->pain_debounce_time < level.time)
{
gi.sound(targ, CHAN_ITEM, gi.soundindex( "items/protect4.wav"), 1, ATTN_NORM, 0);
gi.sound(targ, CHAN_ITEM, gi.soundindex("items/protect4.wav"), 1, ATTN_NORM, 0);
targ->pain_debounce_time = level.time + 2;
}
@ -816,7 +816,7 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
{
if (targ->pain_debounce_time < level.time)
{
gi.sound(targ, CHAN_ITEM, gi.soundindex( "items/protect4.wav"), 1, ATTN_NORM, 0);
gi.sound(targ, CHAN_ITEM, gi.soundindex("items/protect4.wav"), 1, ATTN_NORM, 0);
targ->pain_debounce_time = level.time + 2;
}

View file

@ -17,6 +17,7 @@
qboolean Pickup_Weapon(edict_t *ent, edict_t *other);
void Use_Weapon(edict_t *ent, gitem_t *inv);
void Use_Weapon2(edict_t *ent, gitem_t *inv);
void Drop_Weapon(edict_t *ent, gitem_t *inv);
void Weapon_Blaster(edict_t *ent);
@ -1426,7 +1427,7 @@ Use_PowerArmor(edict_t *ent, gitem_t *item)
if (ent->flags & FL_POWER_ARMOR)
{
ent->flags &= ~FL_POWER_ARMOR;
gi.sound(ent, CHAN_AUTO, gi.soundindex( "misc/power2.wav"), 1, ATTN_NORM, 0);
gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
}
else
{
@ -3589,6 +3590,28 @@ SP_item_health_mega(edict_t *self)
self->style = HEALTH_IGNORE_MAX | HEALTH_TIMED;
}
void
SP_item_foodcube(edict_t *self)
{
if (!self)
{
return;
}
if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH))
{
G_FreeEdict(self);
return;
}
self->model = "models/objects/trapfx/tris.md2";
SpawnItem(self, FindItem("Health"));
self->spawnflags |= DROPPED_ITEM;
self->style = HEALTH_IGNORE_MAX;
gi.soundindex("items/s_health.wav");
self->classname = "foodcube";
}
void
InitItems(void)
{

View file

@ -1,8 +1,24 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
* Licensed under the GNU General Public License 2.0.
*/
/* =======================================================================
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Misc. utility functions for the game logic.
*
@ -13,10 +29,10 @@
#define MAXCHOICES 8
vec3_t VEC_UP = {0, -1, 0};
vec3_t MOVEDIR_UP = {0, 0, 1};
vec3_t VEC_DOWN = {0, -2, 0};
vec3_t MOVEDIR_DOWN = {0, 0, -1};
static vec3_t VEC_UP = {0, -1, 0};
static vec3_t MOVEDIR_UP = {0, 0, 1};
static vec3_t VEC_DOWN = {0, -2, 0};
static vec3_t MOVEDIR_DOWN = {0, 0, -1};
void
G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward,
@ -24,7 +40,8 @@ G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward,
{
result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1];
result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1];
result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] + distance[2];
result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] +
distance[2];
}
void
@ -40,14 +57,13 @@ G_ProjectSource2(vec3_t point, vec3_t distance, vec3_t forward,
}
/*
* Searches all active entities for the next one that holds
* the matching string at fieldofs (use the FOFS() macro) in
* the structure.
* Searches all active entities for the next
* one that holds the matching string at fieldofs
* (use the FOFS() macro) in the structure.
*
* Searches beginning at the edict after from, or the beginning
* if NULL.
*
* NULL will be returned if the end of the list is reached.
* Searches beginning at the edict after from, or
* the beginning. If NULL, NULL will be returned
* if the end of the list is reached.
*/
edict_t *
G_Find(edict_t *from, int fieldofs, char *match)
@ -92,7 +108,8 @@ G_Find(edict_t *from, int fieldofs, char *match)
}
/*
* Returns entities that have origins within a spherical area
* Returns entities that have origins
* within a spherical area
*/
edict_t *
findradius(edict_t *from, vec3_t org, float rad)
@ -123,7 +140,8 @@ findradius(edict_t *from, vec3_t org, float rad)
for (j = 0; j < 3; j++)
{
eorg[j] = org[j] - (from->s.origin[j] + (from->mins[j] + from->maxs[j]) * 0.5);
eorg[j] = org[j] - (from->s.origin[j] +
(from->mins[j] + from->maxs[j]) * 0.5);
}
if (VectorLength(eorg) > rad)
@ -195,14 +213,14 @@ findradius2(edict_t *from, vec3_t org, float rad)
}
/*
* Searches all active entities for the next one that holds
* the matching string at fieldofs (use the FOFS() macro) in
* the structure.
* Searches all active entities for
* the next one that holds the matching
* string at fieldofs (use the FOFS() macro)
* in the structure.
*
* Searches beginning at the edict after from, or the beginning
* if NULL.
*
* NULL will be returned if the end of the list is reached.
* Searches beginning at the edict after from,
* or the beginning. If NULL, NULL will be
* returned if the end of the list is reached.
*/
edict_t *
G_PickTarget(char *targetname)
@ -240,7 +258,7 @@ G_PickTarget(char *targetname)
return NULL;
}
return choice[rand() % num_choices];
return choice[randk() % num_choices];
}
void
@ -256,17 +274,17 @@ Think_Delay(edict_t *ent)
}
/*
* the global "activator" should be set to the entity that initiated the firing.
* The global "activator" should be set to
* the entity that initiated the firing.
*
* If self.delay is set, a DelayedUse entity will be created that will actually
* do the SUB_UseTargets after that many seconds have passed.
* If self.delay is set, a DelayedUse entity
* will be created that will actually do the
* SUB_UseTargets after that many seconds have passed.
*
* Centerprints any self.message to the activator.
*
* Search for (string)targetname in all entities that
* match (string)self.target and call their .use function
*
* ==============================
*/
void
G_UseTargets(edict_t *ent, edict_t *activator)
@ -289,6 +307,11 @@ G_UseTargets(edict_t *ent, edict_t *activator)
t->think = Think_Delay;
t->activator = activator;
if (!activator)
{
gi.dprintf("Think_Delay with no activator\n");
}
t->message = ent->message;
t->target = ent->target;
t->killtarget = ent->killtarget;
@ -306,7 +329,8 @@ G_UseTargets(edict_t *ent, edict_t *activator)
}
else
{
gi.sound(activator, CHAN_AUTO, gi.soundindex("misc/talk1.wav"), 1, ATTN_NORM, 0);
gi.sound(activator, CHAN_AUTO, gi.soundindex(
"misc/talk1.wav"), 1, ATTN_NORM, 0);
}
}
@ -398,8 +422,9 @@ tv(float x, float y, float z)
static vec3_t vecs[8];
float *v;
/* use an array so that multiple tempvectors
won't collide for a while */
/* use an array so that multiple
tempvectors won't collide
for a while */
v = vecs[index];
index = (index + 1) & 7;
@ -469,17 +494,15 @@ vectoyaw(vec3_t vec)
if (vec[PITCH] == 0)
{
if (vec[YAW] == 0)
{
yaw = 0;
}
else if (vec[YAW] > 0)
yaw = 0;
if (vec[YAW] > 0)
{
yaw = 90;
}
else
else if (vec[YAW] < 0)
{
yaw = 270;
yaw = -90;
}
}
else
@ -559,7 +582,7 @@ vectoangles(vec3_t value1, vec3_t angles)
}
else
{
yaw = 270;
yaw = -90;
}
if (yaw < 0)
@ -749,9 +772,19 @@ G_FreeEdict(edict_t *ed)
gi.unlinkentity(ed); /* unlink from world */
if ((ed - g_edicts) <= (maxclients->value + BODY_QUEUE_SIZE))
if (deathmatch->value || coop->value)
{
return;
if ((ed - g_edicts) <= (maxclients->value + BODY_QUEUE_SIZE))
{
return;
}
}
else
{
if ((ed - g_edicts) <= maxclients->value)
{
return;
}
}
memset(ed, 0, sizeof(*ed));
@ -801,8 +834,10 @@ G_TouchTriggers(edict_t *ent)
}
/*
* Call after linking a new trigger in during gameplay
* to force all entities it covers to immediately touch it
* Call after linking a new trigger
* in during gameplay to force all
* entities it covers to immediately
* touch it
*/
void
G_TouchSolids(edict_t *ent)
@ -815,7 +850,8 @@ G_TouchSolids(edict_t *ent)
return;
}
num = gi.BoxEdicts(ent->absmin, ent->absmax, touch, MAX_EDICTS, AREA_SOLID);
num = gi.BoxEdicts(ent->absmin, ent->absmax, touch,
MAX_EDICTS, AREA_SOLID);
/* be careful, it is possible to have an entity in this
list removed before we get to it (killtriggered) */
@ -841,8 +877,9 @@ G_TouchSolids(edict_t *ent)
}
/*
* Kills all entities that would touch the proposed new positioning
* of ent. Ent should be unlinked before calling this!
* Kills all entities that would touch the
* proposed new positioning of ent. Ent s
* hould be unlinked before calling this!
*/
qboolean
KillBox(edict_t *ent)
@ -856,8 +893,8 @@ KillBox(edict_t *ent)
while (1)
{
tr = gi.trace(ent->s.origin, ent->mins, ent->maxs,
ent->s.origin, NULL, MASK_PLAYERSOLID);
tr = gi.trace(ent->s.origin, ent->mins, ent->maxs, ent->s.origin,
NULL, MASK_PLAYERSOLID);
if (!tr.ent)
{

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,24 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
* Licensed under the GNU General Public License 2.0.
*/
/* =======================================================================
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Here are the client, server and game are tied together.
*
@ -29,6 +45,8 @@
#define SVF_MONSTER 0x00000004 /* treat as CONTENTS_MONSTER for collision */
#define SVF_DAMAGEABLE 0x00000008
#define MAX_ENT_CLUSTERS 16
typedef enum
{
SOLID_NOT, /* no interaction with other objects */
@ -45,7 +63,6 @@ typedef struct link_s
struct link_s *prev, *next;
} link_t;
#define MAX_ENT_CLUSTERS 16
typedef struct edict_s edict_t;
typedef struct gclient_s gclient_t;
@ -54,7 +71,7 @@ typedef struct gclient_s gclient_t;
struct gclient_s
{
player_state_t ps; /* communicated by server to clients */
player_state_t ps; /* communicated by server to clients */
int ping;
/* the game dll can add anything it wants
after this point in the structure */
@ -95,29 +112,34 @@ struct edict_s
typedef struct
{
/* special messages */
void (*bprintf)(int printlevel, char *fmt, ...);
void (*dprintf)(char *fmt, ...);
void (*cprintf)(edict_t *ent, int printlevel, char *fmt, ...);
void (*centerprintf)(edict_t *ent, char *fmt, ...);
void (*sound)(edict_t *ent, int channel, int soundindex, float volume, float attenuation, float timeofs);
void (*positioned_sound)(vec3_t origin, edict_t *ent, int channel, int soundinedex, float volume, float attenuation, float timeofs);
void (*bprintf)(int printlevel, const char *fmt, ...);
void (*dprintf)(const char *fmt, ...);
void (*cprintf)(edict_t *ent, int printlevel, const char *fmt, ...);
void (*centerprintf)(edict_t *ent, const char *fmt, ...);
void (*sound)(edict_t *ent, int channel, int soundindex, float volume,
float attenuation, float timeofs);
void (*positioned_sound)(vec3_t origin, edict_t *ent, int channel,
int soundinedex, float volume, float attenuation, float timeofs);
/* config strings hold all the index strings, the lightstyles,
and misc data like the sky definition and cdtrack.
All of the current configstrings are sent to clients when
they connect, and changes are sent to all connected clients. */
void (*configstring)(int num, char *string);
void (*error)(char *fmt, ...);
void (*configstring)(int num, const char *string);
/* the *index functions create configstrings and some internal server state */
int (*modelindex)(char *name);
int (*soundindex)(char *name);
int (*imageindex)(char *name);
YQ2_ATTR_NORETURN_FUNCPTR void (*error)(const char *fmt, ...);
void (*setmodel)(edict_t *ent, char *name);
/* the *index functions create configstrings
and some internal server state */
int (*modelindex)(const char *name);
int (*soundindex)(const char *name);
int (*imageindex)(const char *name);
void (*setmodel)(edict_t *ent, const char *name);
/* collision detection */
trace_t (*trace)(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passent, int contentmask);
trace_t (*trace)(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end,
edict_t *passent, int contentmask);
int (*pointcontents)(vec3_t point);
qboolean (*inPVS)(vec3_t p1, vec3_t p2);
qboolean (*inPHS)(vec3_t p1, vec3_t p2);
@ -125,11 +147,12 @@ typedef struct
qboolean (*AreasConnected)(int area1, int area2);
/* an entity will never be sent to a client or used for collision
if it is not passed to linkentity. If the size, position, or
if it is not passed to linkentity. If the size, position, or
solidity changes, it must be relinked. */
void (*linkentity)(edict_t *ent);
void (*unlinkentity)(edict_t *ent); /* call before removing an interactive edict */
int (*BoxEdicts)(vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int areatype);
int (*BoxEdicts)(vec3_t mins, vec3_t maxs, edict_t **list, int maxcount,
int areatype);
void (*Pmove)(pmove_t *pmove); /* player movement code common with client prediction */
/* network messaging */
@ -140,7 +163,7 @@ typedef struct
void (*WriteShort)(int c);
void (*WriteLong)(int c);
void (*WriteFloat)(float f);
void (*WriteString)(char *s);
void (*WriteString)(const char *s);
void (*WritePosition)(vec3_t pos); /* some fractional bits */
void (*WriteDir)(vec3_t pos); /* single byte encoded, very coarse */
void (*WriteAngle)(float f);
@ -151,17 +174,18 @@ typedef struct
void (*FreeTags)(int tag);
/* console variable interaction */
cvar_t *(*cvar)(char *var_name, char *value, int flags);
cvar_t *(*cvar_set)(char *var_name, char *value);
cvar_t *(*cvar_forceset)(char *var_name, char *value);
cvar_t *(*cvar)(const char *var_name, const char *value, int flags);
cvar_t *(*cvar_set)(const char *var_name, const char *value);
cvar_t *(*cvar_forceset)(const char *var_name, const char *value);
/* ClientCommand and ServerCommand parameter access */
int (*argc)(void);
char *(*argv)(int n);
char *(*args)(void); /* concatenation of all argv >= 1 */
/* add commands to the server console as if they were typed in for map changing, etc */
void (*AddCommandString)(char *text);
/* add commands to the server console as if
they were typed in for map changing, etc */
void (*AddCommandString)(const char *text);
void (*DebugGraph)(float value, int color);
} game_import_t;
@ -178,18 +202,20 @@ typedef struct
void (*Shutdown)(void);
/* each new level entered will cause a call to SpawnEntities */
void (*SpawnEntities)(char *mapname, char *entstring, char *spawnpoint);
void (*SpawnEntities)(const char *mapname, char *entstring, const char *spawnpoint);
/* Read/Write Game is for storing persistant cross level information
about the world state and the clients. WriteGame is called every time
a level is exited. ReadGame is called on a loadgame. */
void (*WriteGame)(char *filename, qboolean autosave);
void (*ReadGame)(char *filename);
about the world state and the clients.
WriteGame is called every time a level is exited.
ReadGame is called on a loadgame. */
void (*WriteGame)(const char *filename, qboolean autosave);
void (*ReadGame)(const char *filename);
/* ReadLevel is called after the default map
information has been loaded with SpawnEntities */
void (*WriteLevel)(char *filename);
void (*ReadLevel)(char *filename);
/* ReadLevel is called after the default
map information has been loaded with
SpawnEntities */
void (*WriteLevel)(const char *filename);
void (*ReadLevel)(const char *filename);
qboolean (*ClientConnect)(edict_t *ent, char *userinfo);
void (*ClientBegin)(edict_t *ent);
@ -200,16 +226,17 @@ typedef struct
void (*RunFrame)(void);
/* ServerCommand will be called when an "sv <command>" command
is issued on the server console. The game can issue gi.argc()
gi.argv() commands to get the rest of the parameters */
/* ServerCommand will be called when an "sv <command>"
command is issued on the server console. The game can
issue gi.argc() / gi.argv() commands to get the rest
of the parameters */
void (*ServerCommand)(void);
/* global variables shared between game and server */
/* The edict array is allocated in the game dll so it can vary in
size from one game to another. The size will be fixed when
ge->Init() is called */
/* The edict array is allocated in the game dll so it
can vary in size from one game to another.
The size will be fixed when ge->Init() is called */
struct edict_s *edicts;
int edict_size;
int num_edicts; /* current number, <= max_edicts */

View file

@ -1,8 +1,24 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
* Licensed under the GNU General Public License 2.0.
*/
/* =======================================================================
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Main header file for the game module.
*
@ -15,8 +31,8 @@
#include "shared.h"
/* define GAME_INCLUDE so that game.h does not define the
short, server-visible gclient_t and edict_t structures,
because we define the full size ones in this file */
short, server-visible gclient_t and edict_t structures,
because we define the full size ones in this file */
#define GAME_INCLUDE
#include "game.h"
@ -147,6 +163,7 @@ typedef enum
#define AI_COMBAT_POINT 0x00001000
#define AI_MEDIC 0x00002000
#define AI_RESURRECTING 0x00004000
#define AI_IGNORE_PAIN 0x00008000
/* ROGUE */
#define AI_WALK_WALLS 0x00008000
@ -216,7 +233,8 @@ typedef enum
MOVETYPE_FLY,
MOVETYPE_TOSS, /* gravity */
MOVETYPE_FLYMISSILE, /* extra size to monsters */
MOVETYPE_BOUNCE,
MOVETYPE_BOUNCE, /* added this (the comma at the end of line) */
MOVETYPE_WALLBOUNCE,
MOVETYPE_NEWTOSS /* for deathball */
} movetype_t;
@ -229,6 +247,7 @@ typedef struct
int armor;
} gitem_armor_t;
/* gitem_t->flags */
#define IT_WEAPON 0x00000001 /* use makes active weapon */
#define IT_AMMO 0x00000002
#define IT_ARMOR 0x00000004
@ -251,12 +270,13 @@ typedef struct
#define WEAP_HYPERBLASTER 9
#define WEAP_RAILGUN 10
#define WEAP_BFG 11
#define WEAP_DISRUPTOR 12
#define WEAP_ETFRIFLE 13
#define WEAP_PLASMA 14
#define WEAP_PROXLAUNCH 15
#define WEAP_CHAINFIST 16
#define WEAP_PHALANX 12
#define WEAP_BOOMER 13
#define WEAP_DISRUPTOR 14
#define WEAP_ETFRIFLE 15
#define WEAP_PLASMA 16
#define WEAP_PROXLAUNCH 17
#define WEAP_CHAINFIST 18
typedef struct gitem_s
{
@ -299,8 +319,9 @@ typedef struct
gclient_t *clients; /* [maxclients] */
/* can't store spawnpoint in level, because it
would get overwritten by the savegame restore */
/* can't store spawnpoint in level, because
it would get overwritten by the savegame
restore */
char spawnpoint[512]; /* needed for coop respawns */
/* store latched cvars here that we want to get at often */
@ -371,6 +392,7 @@ typedef struct
/* world vars */
char *sky;
float skyrotate;
int skyautorotate;
vec3_t skyaxis;
char *nextmap;
@ -445,7 +467,7 @@ typedef struct
void (*search)(edict_t *self);
void (*walk)(edict_t *self);
void (*run)(edict_t *self);
void (*dodge)(edict_t *self, edict_t *other, float eta, trace_t *tr);
void (*dodge)(edict_t *self, edict_t *other, float eta);
void (*attack)(edict_t *self);
void (*melee)(edict_t *self);
void (*sight)(edict_t *self, edict_t *other);
@ -508,10 +530,6 @@ extern spawn_temp_t st;
extern int sm_meat_index;
extern int snd_fry;
extern int jacket_armor_index;
extern int combat_armor_index;
extern int body_armor_index;
extern int debristhisframe;
extern int gibsthisframe;
@ -550,6 +568,12 @@ extern int gibsthisframe;
#define MOD_TRIGGER_HURT 31
#define MOD_HIT 32
#define MOD_TARGET_BLASTER 33
#define MOD_RIPPER 34
#define MOD_PHALANX 35
#define MOD_BRAINTENTACLE 36
#define MOD_BLASTOFF 37
#define MOD_GEKK 38
#define MOD_TRAP 39
#define MOD_FRIENDLY_FIRE 0x8000000
#define MOD_CHAINFIST 40
#define MOD_DISINTEGRATOR 41
@ -589,6 +613,7 @@ extern cvar_t *maxentities;
extern cvar_t *deathmatch;
extern cvar_t *coop;
extern cvar_t *coop_baseq2; /* treat spawnflags according to baseq2 rules */
extern cvar_t *coop_pickup_weapons;
extern cvar_t *coop_elevator_delay;
extern cvar_t *coop_pickup_weapons;
extern cvar_t *dmflags;
@ -597,10 +622,13 @@ extern cvar_t *fraglimit;
extern cvar_t *timelimit;
extern cvar_t *password;
extern cvar_t *spectator_password;
extern cvar_t *needpass;
extern cvar_t *g_select_empty;
extern cvar_t *dedicated;
extern cvar_t *g_footsteps;
extern cvar_t *g_monsterfootsteps;
extern cvar_t *g_fix_triggered;
extern cvar_t *g_commanderbody_nogod;
extern cvar_t *filterban;
@ -639,6 +667,7 @@ extern cvar_t *g_disruptor;
extern cvar_t *aimfix;
extern cvar_t *g_machinegun_norecoil;
extern cvar_t *g_swap_speed;
/* this is for the count of monsters */
#define ENT_SLOTS_LEFT \
@ -659,8 +688,8 @@ extern cvar_t *g_machinegun_norecoil;
#define DROPPED_PLAYER_ITEM 0x00020000
#define ITEM_TARGETS_USED 0x00040000
/* fields are needed for spawning from the entity string
and saving / loading games */
/* fields are needed for spawning from the entity
string and saving / loading games */
#define FFL_SPAWNTEMP 1
#define FFL_NOSPAWN 2
@ -692,8 +721,16 @@ typedef struct
extern field_t fields[];
extern gitem_t itemlist[];
/* player/client.c */
void ClientBegin(edict_t *ent);
void ClientDisconnect(edict_t *ent);
void ClientUserinfoChanged(edict_t *ent, char *userinfo);
qboolean ClientConnect(edict_t *ent, char *userinfo);
void ClientThink(edict_t *ent, usercmd_t *cmd);
/* g_cmds.c */
void Cmd_Help_f(edict_t *ent);
void ClientCommand(edict_t *ent);
/* g_items.c */
void PrecacheItem(gitem_t *it);
@ -703,6 +740,7 @@ gitem_t *FindItem(char *pickup_name);
gitem_t *FindItemByClassname(char *classname);
#define ITEM_INDEX(x) ((x) - itemlist)
edict_t *Drop_Item(edict_t *ent, gitem_t *item);
void SetRespawn(edict_t *ent, float delay);
void ChangeWeapon(edict_t *ent);
@ -748,14 +786,18 @@ float vectoyaw2(vec3_t vec);
void vectoangles2(vec3_t vec, vec3_t angles);
edict_t *findradius2(edict_t *from, vec3_t org, float rad);
/* g_spawn.c */
void ED_CallSpawn(edict_t *ent);
/* g_combat.c */
qboolean OnSameTeam(edict_t *ent1, edict_t *ent2);
qboolean CanDamage(edict_t *targ, edict_t *inflictor);
void T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod);
void T_RadiusDamage(edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore,
float radius, int mod);
void T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
vec3_t dir, vec3_t point, vec3_t normal, int damage,
int knockback, int dflags, int mod);
void T_RadiusDamage(edict_t *inflictor, edict_t *attacker,
float damage, edict_t *ignore, float radius,
int mod);
void T_RadiusNukeDamage(edict_t *inflictor, edict_t *attacker, float damage,
edict_t *ignore, float radius, int mod);
void T_RadiusClassDamage(edict_t *inflictor, edict_t *attacker, float damage,
@ -777,24 +819,33 @@ void cleanupHealTarget(edict_t *ent);
#define DEFAULT_BULLET_VSPREAD 500
#define DEFAULT_SHOTGUN_HSPREAD 1000
#define DEFAULT_SHOTGUN_VSPREAD 500
#define DEFAULT_DEATHMATCH_SHOTGUN_COUNT 12
#define DEFAULT_SHOTGUN_COUNT 12
#define DEFAULT_SSHOTGUN_COUNT 20
/* g_monster.c */
void monster_fire_bullet(edict_t *self, vec3_t start, vec3_t dir, int damage,
int kick, int hspread, int vspread, int flashtype);
void monster_fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int kick, int hspread, int vspread, int count, int flashtype);
void monster_fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage,
void monster_fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir,
int damage, int kick, int hspread, int vspread, int count,
int flashtype);
void monster_fire_blaster(edict_t *self, vec3_t start, vec3_t dir,
int damage, int speed, int flashtype, int effect);
void monster_fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir,
int damage, int speed, int flashtype);
void monster_fire_rocket(edict_t *self, vec3_t start, vec3_t dir,
int damage, int speed, int flashtype);
void monster_fire_railgun(edict_t *self, vec3_t start, vec3_t aimdir,
int damage, int kick, int flashtype);
void monster_fire_bfg(edict_t *self, vec3_t start, vec3_t aimdir,
int damage, int speed, int kick, float damage_radius,
int flashtype);
void monster_fire_ionripper(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int flashtype, int effect);
void monster_fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, int flashtype);
void monster_fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int flashtype);
void monster_fire_railgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int kick, int flashtype);
void monster_fire_bfg(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, int kick, float damage_radius, int flashtype);
void monster_dabeam(edict_t *self);
void monster_fire_blueblaster(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int flashtype, int effect);
void M_droptofloor(edict_t *ent);
void monster_think(edict_t *self);
void walkmonster_start(edict_t *self);
@ -811,8 +862,6 @@ void monster_fire_blaster2(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int flashtype, int effect);
void monster_fire_tracker(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, edict_t *enemy, int flashtype);
void monster_fire_heat(edict_t *self, vec3_t start, vec3_t dir, vec3_t offset,
int damage, int kick, int flashtype);
void stationarymonster_start(edict_t *self);
void monster_done_dodge(edict_t *self);
@ -821,6 +870,8 @@ void ThrowHead(edict_t *self, char *gibname, int damage, int type);
void ThrowClientHead(edict_t *self, int damage);
void ThrowGib(edict_t *self, char *gibname, int damage, int type);
void BecomeExplosion1(edict_t *self);
void ThrowHeadACID(edict_t *self, char *gibname, int damage, int type);
void ThrowGibACID(edict_t *self, char *gibname, int damage, int type);
/* g_ai.c */
void AI_SetSightClient(void);
@ -852,10 +903,19 @@ void fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
void fire_grenade2(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, float timer, float damage_radius, qboolean held);
void fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, float damage_radius, int radius_damage);
int speed, float damage_radius,
int radius_damage);
void fire_rail(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick);
void fire_bfg(edict_t *self, vec3_t start, vec3_t dir,
int damage, int speed, float damage_radius);
void fire_bfg(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, float damage_radius);
void fire_ionripper(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, int effect);
void fire_blueblaster(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, int effect);
void fire_plasma(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed,
float damage_radius, int radius_damage);
void fire_trap(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, float timer, float damage_radius, qboolean held);
/* g_ptrail.c */
void PlayerTrail_Init(void);
@ -918,6 +978,14 @@ void ChaseNext(edict_t *ent);
void ChasePrev(edict_t *ent);
void GetChaseTarget(edict_t *ent);
/* savegame */
void InitGame(void);
void ReadLevel(const char *filename);
void WriteLevel(const char *filename);
void ReadGame(const char *filename);
void WriteGame(const char *filename, qboolean autosave);
void SpawnEntities(const char *mapname, char *entities, const char *spawnpoint);
void fire_flechette(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int kick);
void fire_prox(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
@ -937,9 +1005,6 @@ void fire_tesla(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed);
void fire_blaster2(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, int effect, qboolean hyper);
void fire_heat(edict_t *self, vec3_t start, vec3_t aimdir, vec3_t offset,
int damage, int kick,
qboolean monster);
void fire_tracker(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, edict_t *enemy);
@ -1023,7 +1088,8 @@ typedef struct
qboolean connected; /* a loadgame will leave valid entities that
just don't have a connection yet */
/* values saved and restored from edicts when changing levels */
/* values saved and restored from
edicts when changing levels */
int health;
int max_health;
int savedFlags;
@ -1038,6 +1104,8 @@ typedef struct
int max_grenades;
int max_cells;
int max_slugs;
int max_magslug;
int max_trap;
gitem_t *weapon;
gitem_t *lastweapon;
@ -1139,6 +1207,10 @@ struct gclient_s
qboolean grenade_blew_up;
float grenade_time;
float quadfire_framenum;
qboolean trap_blew_up;
float trap_time;
int silencer_shots;
int weapon_sound;
@ -1232,7 +1304,7 @@ struct edict_s
float ideal_yaw;
float nextthink;
void (*prethink) (edict_t *ent);
void (*prethink)(edict_t *ent);
void (*think)(edict_t *self);
void (*blocked)(edict_t *self, edict_t *other); /* move to moveinfo? */
void (*touch)(edict_t *self, edict_t *other, cplane_t *plane,
@ -1242,10 +1314,11 @@ struct edict_s
void (*die)(edict_t *self, edict_t *inflictor, edict_t *attacker,
int damage, vec3_t point);
float touch_debounce_time;
float touch_debounce_time; /* now also used by fixbots for timeouts when getting stuck */
float pain_debounce_time;
float damage_debounce_time;
float fly_sound_debounce_time; /* now also used by insane marines to store pain sound timeout */
/* and by fixbots for storing object_repair timeout when getting stuck */
float last_move_time;
int health;
@ -1296,6 +1369,7 @@ struct edict_s
vec3_t move_origin;
vec3_t move_angles;
/* move this to clientinfo? */
int light_level;
int style; /* also used as areaportal number */
@ -1305,6 +1379,8 @@ struct edict_s
moveinfo_t moveinfo;
monsterinfo_t monsterinfo;
int orders;
int plat2flags;
vec3_t offset;
vec3_t gravityVector;

View file

@ -710,7 +710,7 @@ hover_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* u
/* check for gib */
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{

View file

@ -735,7 +735,7 @@ player_die(edict_t *self, edict_t *inflictor, edict_t *attacker,
if (!(self->flags & FL_NOGIB))
{
/* gib (play sound at end of server frame) */
self->sounds = gi.soundindex( "misc/udeath.wav");
self->sounds = gi.soundindex("misc/udeath.wav");
/* more meaty gibs for your dollar! */
if ((deathmatch->value) && (self->health < -80))
@ -1366,7 +1366,7 @@ body_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* un
if (self->health < -40)
{
gi.sound(self, CHAN_BODY, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_BODY, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 4; n++)
{

View file

@ -427,7 +427,7 @@ G_SetStats(edict_t *ent)
{
/* ran out of cells for power armor */
ent->flags &= ~FL_POWER_ARMOR;
gi.sound(ent, CHAN_ITEM, gi.soundindex( "misc/power2.wav"), 1, ATTN_NORM, 0);
gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
power_armor_type = 0;
}
}

View file

@ -40,9 +40,9 @@ gitem_armor_t jacketarmor_info = {25, 50, .30, .00, ARMOR_JACKET};
gitem_armor_t combatarmor_info = {50, 100, .60, .30, ARMOR_COMBAT};
gitem_armor_t bodyarmor_info = {100, 200, .80, .60, ARMOR_BODY};
int jacket_armor_index;
int combat_armor_index;
int body_armor_index;
static int jacket_armor_index;
static int combat_armor_index;
static int body_armor_index;
static int power_screen_index;
static int power_shield_index;
@ -2927,7 +2927,7 @@ SP_item_health(edict_t *self)
}
/*
* QUAKED item_health_small (.3 .3 1) (-16 -16 -16) (16 16 16)
* QUAKED item_health_small (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN
*/
void
SP_item_health_small(edict_t *self)
@ -2951,7 +2951,7 @@ SP_item_health_small(edict_t *self)
}
/*
* QUAKED item_health_large (.3 .3 1) (-16 -16 -16) (16 16 16)
* QUAKED item_health_large (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN
*/
void
SP_item_health_large(edict_t *self)
@ -2974,7 +2974,7 @@ SP_item_health_large(edict_t *self)
}
/*
* QUAKED item_health_mega (.3 .3 1) (-16 -16 -16) (16 16 16)
* QUAKED item_health_mega (.3 .3 1) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN
*/
void
SP_item_health_mega(edict_t *self)

View file

@ -543,7 +543,7 @@ M_WorldEffects(edict_t *ent)
{
if (ent->flags & FL_INWATER)
{
gi.sound(ent, CHAN_BODY, gi.soundindex( "player/watr_out.wav"),
gi.sound(ent, CHAN_BODY, gi.soundindex("player/watr_out.wav"),
1, ATTN_NORM, 0);
ent->flags &= ~FL_INWATER;
}
@ -579,7 +579,7 @@ M_WorldEffects(edict_t *ent)
{
if (random() <= 0.5)
{
gi.sound(ent, CHAN_BODY, gi.soundindex( "player/lava1.wav"),
gi.sound(ent, CHAN_BODY, gi.soundindex("player/lava1.wav"),
1, ATTN_NORM, 0);
}
else

View file

@ -1,8 +1,24 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
* Licensed under the GNU General Public License 2.0.
*/
/* =======================================================================
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Misc. utility functions for the game logic.
*
@ -13,13 +29,19 @@
#define MAXCHOICES 8
static vec3_t VEC_UP = {0, -1, 0};
static vec3_t MOVEDIR_UP = {0, 0, 1};
static vec3_t VEC_DOWN = {0, -2, 0};
static vec3_t MOVEDIR_DOWN = {0, 0, -1};
void
G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward,
vec3_t right, vec3_t result)
{
result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1];
result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1];
result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] + distance[2];
result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] +
distance[2];
}
/*
@ -34,6 +56,11 @@ G_Find(edict_t *from, int fieldofs, char *match)
{
char *s;
if (!match)
{
return NULL;
}
if (!from)
{
from = g_edicts;
@ -67,7 +94,8 @@ G_Find(edict_t *from, int fieldofs, char *match)
}
/*
* Returns entities that have origins within a spherical area
* Returns entities that have origins
* within a spherical area
*/
edict_t *
findradius(edict_t *from, vec3_t org, float rad)
@ -338,11 +366,6 @@ get_normal_vector(const cplane_t *p, vec3_t normal)
}
}
vec3_t VEC_UP = {0, -1, 0};
vec3_t MOVEDIR_UP = {0, 0, 1};
vec3_t VEC_DOWN = {0, -2, 0};
vec3_t MOVEDIR_DOWN = {0, 0, -1};
void
G_SetMovedir(vec3_t angles, vec3_t movedir)
{

View file

@ -1,8 +1,24 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
* Licensed under the GNU General Public License 2.0.
*/
/* =======================================================================
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Weapon support functions.
*
@ -48,7 +64,7 @@ check_dodge(edict_t *self, vec3_t start, vec3_t dir, int speed)
{
VectorSubtract(tr.endpos, start, v);
eta = (VectorLength(v) - tr.ent->maxs[0]) / speed;
tr.ent->monsterinfo.dodge(tr.ent, self, eta);
tr.ent->monsterinfo.dodge(tr.ent, self, eta, &tr);
}
}
@ -70,6 +86,7 @@ fire_hit(edict_t *self, vec3_t aim, int damage, int kick)
return false;
}
/* Lazarus: Paranoia check */
if (!self->enemy)
{
return false;
@ -86,12 +103,14 @@ fire_hit(edict_t *self, vec3_t aim, int damage, int kick)
if ((aim[1] > self->mins[0]) && (aim[1] < self->maxs[0]))
{
/* the hit is straight on so back the range up to the edge of their bbox */
/* the hit is straight on so back the
range up to the edge of their bbox */
range -= self->enemy->maxs[0];
}
else
{
/* this is a side hit so adjust the "right" value out to the edge of their bbox */
/* this is a side hit so adjust the "right"
value out to the edge of their bbox */
if (aim[1] < 0)
{
aim[1] = self->enemy->mins[0];
@ -113,7 +132,8 @@ fire_hit(edict_t *self, vec3_t aim, int damage, int kick)
return false;
}
/* if it will hit any client/monster then hit the one we wanted to hit */
/* if it will hit any client/monster
then hit the one we wanted to hit */
if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client))
{
tr.ent = self->enemy;
@ -127,8 +147,8 @@ fire_hit(edict_t *self, vec3_t aim, int damage, int kick)
VectorSubtract(point, self->enemy->s.origin, dir);
/* do the damage */
T_Damage(tr.ent, self, self, dir, point, vec3_origin,
damage, kick / 2, DAMAGE_NO_KNOCKBACK, MOD_HIT);
T_Damage(tr.ent, self, self, dir, point, vec3_origin, damage,
kick / 2, DAMAGE_NO_KNOCKBACK, MOD_HIT);
if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client))
{
@ -150,7 +170,8 @@ fire_hit(edict_t *self, vec3_t aim, int damage, int kick)
}
/*
* This is an internal support routine used for bullet/pellet based weapons.
* This is an internal support routine
* used for bullet/pellet based weapons.
*/
void
fire_lead(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick,
@ -283,7 +304,8 @@ fire_lead(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick,
}
}
/* if went through water, determine where the end and make a bubble trail */
/* if went through water, determine
where the end and make a bubble trail */
if (water)
{
vec3_t pos;
@ -313,8 +335,8 @@ fire_lead(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick,
}
/*
* Fires a single round. Used for machinegun and chaingun.
* Would be fine for pistols, rifles, etc....
* Fires a single round. Used for machinegun and
* chaingun. Would be fine for pistols, rifles, etc....
*/
void
fire_bullet(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
@ -325,12 +347,13 @@ fire_bullet(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
return;
}
fire_lead(self, start, aimdir, damage, kick, TE_GUNSHOT,
hspread, vspread, mod);
fire_lead(self, start, aimdir, damage, kick, TE_GUNSHOT, hspread,
vspread, mod);
}
/*
* Shoots shotgun pellets. Used by shotgun and super shotgun.
* Shoots shotgun pellets. Used
* by shotgun and super shotgun.
*/
void
fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
@ -345,13 +368,14 @@ fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
for (i = 0; i < count; i++)
{
fire_lead(self, start, aimdir, damage, kick,
TE_SHOTGUN, hspread, vspread, mod);
fire_lead(self, start, aimdir, damage, kick, TE_SHOTGUN,
hspread, vspread, mod);
}
}
/*
* Fires a single blaster bolt. Used by the blaster and hyper blaster.
* Fires a single blaster bolt.
* Used by the blaster and hyper blaster.
*/
void
blaster_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
@ -359,7 +383,7 @@ blaster_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
int mod;
vec3_t normal;
if (!self || !other)
if (!self || !other) /* plane and surf can be NULL */
{
G_FreeEdict(self);
return;
@ -376,7 +400,7 @@ blaster_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
return;
}
if (self->owner->client)
if (self->owner && self->owner->client)
{
PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT);
}
@ -439,6 +463,7 @@ fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage,
bolt->clipmask = MASK_SHOT;
bolt->solid = SOLID_BBOX;
bolt->s.effects |= effect;
bolt->s.renderfx |= RF_NOSHADOW;
VectorClear(bolt->mins);
VectorClear(bolt->maxs);
bolt->s.modelindex = gi.modelindex("models/objects/laser/tris.md2");
@ -532,7 +557,7 @@ Grenade_Explode(edict_t *ent)
return;
}
if (ent->owner->client)
if (ent->owner && ent->owner->client)
{
PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT);
}
@ -610,9 +635,9 @@ Grenade_Explode(edict_t *ent)
}
void
Grenade_Touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
Grenade_Touch(edict_t *ent, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf)
{
if (!ent || !other)
if (!ent || !other) /* plane is unused, surf can be NULL */
{
G_FreeEdict(ent);
return;
@ -635,19 +660,19 @@ Grenade_Touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
if (random() > 0.5)
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb1a.wav"),
1, ATTN_NORM, 0);
gi.sound(ent, CHAN_VOICE, gi.soundindex(
"weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0);
}
else
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb2a.wav"),
1, ATTN_NORM, 0);
gi.sound(ent, CHAN_VOICE, gi.soundindex(
"weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0);
}
}
else
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/grenlb1b.wav"),
1, ATTN_NORM, 0);
gi.sound(ent, CHAN_VOICE, gi.soundindex(
"weapons/grenlb1b.wav"), 1, ATTN_NORM, 0);
}
return;
@ -658,8 +683,8 @@ Grenade_Touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
}
void
fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, float timer, float damage_radius)
fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed,
float timer, float damage_radius)
{
edict_t *grenade;
vec3_t dir;
@ -751,8 +776,8 @@ fire_grenade2(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
}
else
{
gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/hgrent1a.wav"),
1, ATTN_NORM, 0);
gi.sound(self, CHAN_WEAPON, gi.soundindex(
"weapons/hgrent1a.wav"), 1, ATTN_NORM, 0);
gi.linkentity(grenade);
}
}
@ -764,7 +789,7 @@ rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
vec3_t normal;
int n;
if (!ent || !other)
if (!ent || !other) /* plane and surf can be NULL */
{
G_FreeEdict(ent);
return;
@ -781,7 +806,7 @@ rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
return;
}
if (ent->owner->client)
if (ent->owner && ent->owner->client)
{
PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT);
}
@ -802,9 +827,9 @@ rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
if (!deathmatch->value && !coop->value)
{
if ((surf) && !(surf->flags &
(SURF_WARP | SURF_TRANS33 | SURF_TRANS66 | SURF_FLOWING)))
(SURF_WARP | SURF_TRANS33 | SURF_TRANS66 | SURF_FLOWING)))
{
n = rand() % 5;
n = randk() % 5;
while (n--)
{
@ -815,8 +840,8 @@ rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
}
}
T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other,
ent->dmg_radius, MOD_R_SPLASH);
T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius,
MOD_R_SPLASH);
gi.WriteByte(svc_temp_entity);
@ -910,6 +935,7 @@ fire_rail(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick)
{
/* -added so rail goes through SOLID_BBOX entities (gibs, etc) */
if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client) ||
(tr.ent->svflags & SVF_DAMAGEABLE) ||
(tr.ent->solid == SOLID_BBOX))
{
ignore = tr.ent;
@ -1029,7 +1055,7 @@ bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
vec3_t normal;
if (!self || !other)
if (!self || !other) /* plane and surf can be NULL */
{
G_FreeEdict(self);
return;
@ -1046,7 +1072,7 @@ bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
return;
}
if (self->owner->client)
if (self->owner && self->owner->client)
{
PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT);
}
@ -1062,11 +1088,21 @@ bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
T_RadiusDamage(self, self->owner, 200, other, 100, MOD_BFG_BLAST);
gi.sound(self, CHAN_VOICE, gi.soundindex("weapons/bfg__x1b.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex(
"weapons/bfg__x1b.wav"), 1, ATTN_NORM, 0);
self->solid = SOLID_NOT;
self->touch = NULL;
VectorMA(self->s.origin, -1 * FRAMETIME, self->velocity, self->s.origin);
/* move it back a bit from walls so the effects aren't cut off */
if (!other->takedamage)
{
VectorNormalize(self->velocity);
VectorMA(self->s.origin, -40.0f, self->velocity, self->s.origin);
}
VectorClear(self->velocity);
self->s.modelindex = gi.modelindex("sprites/s_bfg3.sp2");
self->s.frame = 0;
self->s.sound = 0;
@ -1075,6 +1111,8 @@ bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
self->nextthink = level.time + FRAMETIME;
self->enemy = other;
gi.linkentity(self);
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_BFG_BIGEXPLOSION);
gi.WritePosition(self->s.origin);
@ -1126,8 +1164,8 @@ bfg_think(edict_t *self)
continue;
}
if (!(ent->svflags & SVF_MONSTER) && (!ent->client) &&
(strcmp(ent->classname, "misc_explobox") != 0))
if (!(ent->svflags & SVF_MONSTER) && !(ent->svflags & SVF_DAMAGEABLE) &&
(!ent->client) && (strcmp(ent->classname, "misc_explobox") != 0))
{
continue;
}
@ -1155,12 +1193,13 @@ bfg_think(edict_t *self)
if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER) &&
(tr.ent != self->owner))
{
T_Damage(tr.ent, self, self->owner, dir, tr.endpos,
vec3_origin, dmg, 1, DAMAGE_ENERGY, MOD_BFG_LASER);
T_Damage(tr.ent, self, self->owner, dir, tr.endpos, vec3_origin,
dmg, 1, DAMAGE_ENERGY, MOD_BFG_LASER);
}
/* if we hit something that's not a monster or player we're done */
if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client))
if (!(tr.ent->svflags & SVF_MONSTER) &&
!(tr.ent->svflags & SVF_DAMAGEABLE) && (!tr.ent->client))
{
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_LASER_SPARKS);

View file

@ -1,8 +1,24 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
* Licensed under the GNU General Public License 2.0.
*/
/* =======================================================================
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Here are the client, server and game are tied together.
*
@ -24,18 +40,19 @@
#define GAME_API_VERSION 3
#define SVF_NOCLIENT 0x00000001 /* don't send entity to clients, even if it has effects */
#define SVF_DEADMONSTER 0x00000002 /* treat as CONTENTS_DEADMONSTER for collision */
#define SVF_MONSTER 0x00000004 /* treat as CONTENTS_MONSTER for collision */
#define SVF_NOCLIENT 0x00000001 /* don't send entity to clients, even if it has effects */
#define SVF_DEADMONSTER 0x00000002 /* treat as CONTENTS_DEADMONSTER for collision */
#define SVF_MONSTER 0x00000004 /* treat as CONTENTS_MONSTER for collision */
#define SVF_DAMAGEABLE 0x00000008
#define MAX_ENT_CLUSTERS 16
typedef enum
{
SOLID_NOT, /* no interaction with other objects */
SOLID_TRIGGER, /* only touch when inside, after moving */
SOLID_BBOX, /* touch on edge */
SOLID_BSP /* bsp clip, touch on edge */
SOLID_NOT, /* no interaction with other objects */
SOLID_TRIGGER, /* only touch when inside, after moving */
SOLID_BBOX, /* touch on edge */
SOLID_BSP /* bsp clip, touch on edge */
} solid_t;
/* =============================================================== */
@ -54,7 +71,7 @@ typedef struct gclient_s gclient_t;
struct gclient_s
{
player_state_t ps; /* communicated by server to clients */
player_state_t ps; /* communicated by server to clients */
int ping;
/* the game dll can add anything it wants
after this point in the structure */
@ -67,14 +84,16 @@ struct edict_s
qboolean inuse;
int linkcount;
link_t area; /* linked to a division node or leaf */
link_t area; /* linked to a division node or leaf */
int num_clusters; /* if -1, use headnode instead */
int num_clusters; /* if -1, use headnode instead */
int clusternums[MAX_ENT_CLUSTERS];
int headnode; /* unused if num_clusters != -1 */
int headnode; /* unused if num_clusters != -1 */
int areanum, areanum2;
int svflags; /* SVF_NOCLIENT, SVF_DEADMONSTER, SVF_MONSTER, etc */
/* ================================ */
int svflags; /* SVF_NOCLIENT, SVF_DEADMONSTER, SVF_MONSTER, etc */
vec3_t mins, maxs;
vec3_t absmin, absmax, size;
solid_t solid;
@ -93,10 +112,10 @@ struct edict_s
typedef struct
{
/* special messages */
void (*bprintf)(int printlevel, char *fmt, ...);
void (*dprintf)(char *fmt, ...);
void (*cprintf)(edict_t *ent, int printlevel, char *fmt, ...);
void (*centerprintf)(edict_t *ent, char *fmt, ...);
void (*bprintf)(int printlevel, const char *fmt, ...);
void (*dprintf)(const char *fmt, ...);
void (*cprintf)(edict_t *ent, int printlevel, const char *fmt, ...);
void (*centerprintf)(edict_t *ent, const char *fmt, ...);
void (*sound)(edict_t *ent, int channel, int soundindex, float volume,
float attenuation, float timeofs);
void (*positioned_sound)(vec3_t origin, edict_t *ent, int channel,
@ -106,17 +125,17 @@ typedef struct
and misc data like the sky definition and cdtrack.
All of the current configstrings are sent to clients when
they connect, and changes are sent to all connected clients. */
void (*configstring)(int num, char *string);
void (*configstring)(int num, const char *string);
void (*error)(char *fmt, ...);
YQ2_ATTR_NORETURN_FUNCPTR void (*error)(const char *fmt, ...);
/* the *index functions create configstrings
and some internal server state */
int (*modelindex)(char *name);
int (*soundindex)(char *name);
int (*imageindex)(char *name);
int (*modelindex)(const char *name);
int (*soundindex)(const char *name);
int (*imageindex)(const char *name);
void (*setmodel)(edict_t *ent, char *name);
void (*setmodel)(edict_t *ent, const char *name);
/* collision detection */
trace_t (*trace)(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end,
@ -127,14 +146,14 @@ typedef struct
void (*SetAreaPortalState)(int portalnum, qboolean open);
qboolean (*AreasConnected)(int area1, int area2);
/* an entity will never be sent to a client or used for collision
/* an entity will never be sent to a client or used for collision
if it is not passed to linkentity. If the size, position, or
solidity changes, it must be relinked. */
void (*linkentity)(edict_t *ent);
void (*unlinkentity)(edict_t *ent); /* call before removing an interactive edict */
void (*unlinkentity)(edict_t *ent); /* call before removing an interactive edict */
int (*BoxEdicts)(vec3_t mins, vec3_t maxs, edict_t **list, int maxcount,
int areatype);
void (*Pmove)(pmove_t *pmove); /* player movement code common with client prediction */
void (*Pmove)(pmove_t *pmove); /* player movement code common with client prediction */
/* network messaging */
void (*multicast)(vec3_t origin, multicast_t to);
@ -144,9 +163,9 @@ typedef struct
void (*WriteShort)(int c);
void (*WriteLong)(int c);
void (*WriteFloat)(float f);
void (*WriteString)(char *s);
void (*WritePosition)(vec3_t pos); /* some fractional bits */
void (*WriteDir)(vec3_t pos); /* single byte encoded, very coarse */
void (*WriteString)(const char *s);
void (*WritePosition)(vec3_t pos); /* some fractional bits */
void (*WriteDir)(vec3_t pos); /* single byte encoded, very coarse */
void (*WriteAngle)(float f);
/* managed memory allocation */
@ -155,18 +174,18 @@ typedef struct
void (*FreeTags)(int tag);
/* console variable interaction */
cvar_t *(*cvar)(char *var_name, char *value, int flags);
cvar_t *(*cvar_set)(char *var_name, char *value);
cvar_t *(*cvar_forceset)(char *var_name, char *value);
cvar_t *(*cvar)(const char *var_name, const char *value, int flags);
cvar_t *(*cvar_set)(const char *var_name, const char *value);
cvar_t *(*cvar_forceset)(const char *var_name, const char *value);
/* ClientCommand and ServerCommand parameter access */
int (*argc)(void);
char *(*argv)(int n);
char *(*args)(void); /* concatenation of all argv >= 1 */
char *(*args)(void); /* concatenation of all argv >= 1 */
/* add commands to the server console as if
they were typed in for map changing, etc */
void (*AddCommandString)(char *text);
void (*AddCommandString)(const char *text);
void (*DebugGraph)(float value, int color);
} game_import_t;
@ -183,20 +202,20 @@ typedef struct
void (*Shutdown)(void);
/* each new level entered will cause a call to SpawnEntities */
void (*SpawnEntities)(char *mapname, char *entstring, char *spawnpoint);
void (*SpawnEntities)(const char *mapname, char *entstring, const char *spawnpoint);
/* Read/Write Game is for storing persistant cross level information
about the world state and the clients.
WriteGame is called every time a level is exited.
ReadGame is called on a loadgame. */
void (*WriteGame)(char *filename, qboolean autosave);
void (*ReadGame)(char *filename);
void (*WriteGame)(const char *filename, qboolean autosave);
void (*ReadGame)(const char *filename);
/* ReadLevel is called after the default
map information has been loaded with
SpawnEntities */
void (*WriteLevel)(char *filename);
void (*ReadLevel)(char *filename);
void (*WriteLevel)(const char *filename);
void (*ReadLevel)(const char *filename);
qboolean (*ClientConnect)(edict_t *ent, char *userinfo);
void (*ClientBegin)(edict_t *ent);
@ -208,7 +227,7 @@ typedef struct
void (*RunFrame)(void);
/* ServerCommand will be called when an "sv <command>"
command is issued on the server console. The game can
command is issued on the server console. The game can
issue gi.argc() / gi.argv() commands to get the rest
of the parameters */
void (*ServerCommand)(void);
@ -220,7 +239,7 @@ typedef struct
The size will be fixed when ge->Init() is called */
struct edict_s *edicts;
int edict_size;
int num_edicts; /* current number, <= max_edicts */
int num_edicts; /* current number, <= max_edicts */
int max_edicts;
} game_export_t;

File diff suppressed because it is too large Load diff

View file

@ -471,7 +471,7 @@ berserk_die(edict_t *self, edict_t *inflictor /* unsued */, edict_t *attacker /*
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{

View file

@ -414,7 +414,7 @@ G_SetStats(edict_t *ent)
{
/* ran out of cells for power armor */
ent->flags &= ~FL_POWER_ARMOR;
gi.sound(ent, CHAN_ITEM, gi.soundindex( "misc/power2.wav"),
gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/power2.wav"),
1, ATTN_NORM, 0);
power_armor_type = 0;
}

View file

@ -400,7 +400,7 @@ GetPCXPalette24to8(byte *d_8to24table, byte** d_16to8table)
if (!(*d_16to8table))
{
Com_Error(ERR_FATAL, "%s: Couldn't allocate memory for d_16to8table", __func__);
// code never returns after ERR_FATAL
/* code never returns after ERR_FATAL */
return;
}
@ -468,14 +468,14 @@ GetPCXPalette(byte **colormap, unsigned *d_8to24table)
int i;
memcpy(d_8to24table, pic, 256 * 4);
d_8to24table[255] &= LittleLong(0xffffff); // 255 is transparent
d_8to24table[255] &= LittleLong(0xffffff); /* 255 is transparent */
/* generate colormap */
*colormap = malloc(256 * 320);
if (!(*colormap))
{
Com_Error(ERR_FATAL, "%s: Couldn't allocate memory for colormap", __func__);
// code never returns after ERR_FATAL
/* code never returns after ERR_FATAL */
return;
}
@ -516,14 +516,14 @@ GetPCXPalette(byte **colormap, unsigned *d_8to24table)
d_8to24table[i] = LittleLong(v);
}
d_8to24table[255] &= LittleLong(0xffffff); // 255 is transparent
d_8to24table[255] &= LittleLong(0xffffff); /* 255 is transparent */
/* generate colormap */
*colormap = malloc(256 * 320);
if (!(*colormap))
{
Com_Error(ERR_FATAL, "%s: Couldn't allocate memory for colormap", __func__);
// code never returns after ERR_FATAL
/* code never returns after ERR_FATAL */
return;
}
@ -531,9 +531,9 @@ GetPCXPalette(byte **colormap, unsigned *d_8to24table)
return;
}
for (i=0 ; i<256 ; i++)
for (i = 0; i < 256; i++)
{
unsigned v;
unsigned v;
int r, g, b;
r = pal[i*3+0];

View file

@ -275,7 +275,7 @@ R_LoadPic8 (char *name, byte *pic, int width, int realwidth, int height, int rea
if (!image->pixels[0])
{
Com_Error(ERR_FATAL, "%s: Can't allocate image.", __func__);
// code never returns after ERR_FATAL
/* code never returns after ERR_FATAL */
return NULL;
}
@ -339,7 +339,7 @@ R_LoadPic (char *name, byte *pic, int width, int realwidth, int height, int real
if (!pic8)
{
Com_Error(ERR_FATAL, "%s: Can't allocate image.", __func__);
// code never returns after ERR_FATAL
/* code never returns after ERR_FATAL */
return NULL;
}

View file

@ -2407,7 +2407,7 @@ SWimp_CreateRender(int width, int height)
if (!swap_buffers)
{
Com_Error(ERR_FATAL, "%s: Can't allocate swapbuffer.", __func__);
// code never returns after ERR_FATAL
/* code never returns after ERR_FATAL */
return;
}
swap_frames[0] = swap_buffers;

View file

@ -293,7 +293,7 @@ R_InitCaches (void)
if (!sc_base)
{
Com_Error(ERR_FATAL, "%s: Can't allocate cache.", __func__);
// code never returns after ERR_FATAL
/* code never returns after ERR_FATAL */
return;
}
sc_rover = sc_base;

View file

@ -882,8 +882,9 @@ Returns number of mip levels and scales native resolution
if vk_picmip is set. Does not use power of 2 scaling.
===============
*/
static uint32_t Vk_Upload32Native (byte *data, int width, int height, imagetype_t type,
byte **texBuffer, int *upload_width, int *upload_height)
static uint32_t
Vk_Upload32Native(byte *data, int width, int height, imagetype_t type,
byte **texBuffer, int *upload_width, int *upload_height)
{
int scaled_width = width, scaled_height = height;
int miplevel = 1;
@ -1018,8 +1019,9 @@ Returns number of mip levels
===============
*/
static uint32_t Vk_Upload8 (const byte *data, int width, int height, imagetype_t type,
byte **texBuffer, int *upload_width, int *upload_height)
static uint32_t
Vk_Upload8(const byte *data, int width, int height, imagetype_t type,
byte **texBuffer, int *upload_width, int *upload_height)
{
unsigned *trans;
int i, s;
@ -1043,7 +1045,7 @@ static uint32_t Vk_Upload8 (const byte *data, int width, int height, imagetype_t
{
for (i = 0; i < s; i++)
{
int p;
int p;
p = data[i];
@ -1052,16 +1054,27 @@ static uint32_t Vk_Upload8 (const byte *data, int width, int height, imagetype_t
// to avoid alpha fringes
// FIXME: do a full flood fill so mips work...
if (i > width && data[i - width] != 255)
{
p = data[i - width];
}
else if (i < s - width && data[i + width] != 255)
{
p = data[i + width];
}
else if (i > 0 && data[i - 1] != 255)
{
p = data[i - 1];
}
else if (i < s - 1 && data[i + 1] != 255)
{
p = data[i + 1];
}
else
{
p = 0;
// copy rgb components
}
/* copy rgb components */
((byte *)&trans[i])[0] = ((byte *)&d_8to24table[p])[0];
((byte *)&trans[i])[1] = ((byte *)&d_8to24table[p])[1];
((byte *)&trans[i])[2] = ((byte *)&d_8to24table[p])[2];
@ -1075,11 +1088,14 @@ static uint32_t Vk_Upload8 (const byte *data, int width, int height, imagetype_t
SmoothColorImage(trans, s, s >> 7);
}
miplevel = Vk_Upload32Native((byte *)trans, width, height, type, texBuffer, upload_width, upload_height);
miplevel = Vk_Upload32Native((byte *)trans, width, height, type, texBuffer,
upload_width, upload_height);
// Only free if *texBuffer isn't the image data we sent
if (!texBuffer || *texBuffer != (byte *)trans)
{
free(trans);
}
return miplevel;
}

View file

@ -31,6 +31,7 @@
qboolean Pickup_Weapon(edict_t *ent, edict_t *other);
void Use_Weapon(edict_t *ent, gitem_t *inv);
void Use_Weapon2(edict_t *ent, gitem_t *inv);
void Drop_Weapon(edict_t *ent, gitem_t *inv);
void Weapon_Blaster(edict_t *ent);
@ -56,6 +57,8 @@ static int power_screen_index;
static int power_shield_index;
void Use_Quad(edict_t *ent, gitem_t *item);
void Use_QuadFire(edict_t *ent, gitem_t *item);
static int quad_drop_timeout_hack;
/* ====================================================================== */
@ -587,7 +590,7 @@ Use_Invulnerability(edict_t *ent, gitem_t *item)
ent->client->invincible_framenum = level.framenum + 300;
}
gi.sound(ent, CHAN_ITEM, gi.soundindex( "items/protect.wav"), 1, ATTN_NORM, 0);
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/protect.wav"), 1, ATTN_NORM, 0);
}
/* ====================================================================== */
@ -2681,6 +2684,28 @@ SP_item_health_mega(edict_t *self)
self->style = HEALTH_IGNORE_MAX | HEALTH_TIMED;
}
void
SP_item_foodcube(edict_t *self)
{
if (!self)
{
return;
}
if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH))
{
G_FreeEdict(self);
return;
}
self->model = "models/objects/trapfx/tris.md2";
SpawnItem(self, FindItem("Health"));
self->spawnflags |= DROPPED_ITEM;
self->style = HEALTH_IGNORE_MAX;
gi.soundindex("items/s_health.wav");
self->classname = "foodcube";
}
void
InitItems(void)
{

View file

@ -349,11 +349,11 @@ trigger_key_use(edict_t *self, edict_t *other /* unused */,
self->touch_debounce_time = level.time + 5.0;
gi.centerprintf(activator, "You need the %s", self->item->pickup_name);
gi.sound(activator, CHAN_AUTO, gi.soundindex( "misc/keytry.wav"), 1, ATTN_NORM, 0);
gi.sound(activator, CHAN_AUTO, gi.soundindex("misc/keytry.wav"), 1, ATTN_NORM, 0);
return;
}
gi.sound(activator, CHAN_AUTO, gi.soundindex( "misc/keyuse.wav"), 1, ATTN_NORM, 0);
gi.sound(activator, CHAN_AUTO, gi.soundindex("misc/keyuse.wav"), 1, ATTN_NORM, 0);
if (coop->value)
{

View file

@ -1,5 +1,6 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -28,6 +29,11 @@
#define MAXCHOICES 8
static vec3_t VEC_UP = {0, -1, 0};
static vec3_t MOVEDIR_UP = {0, 0, 1};
static vec3_t VEC_DOWN = {0, -2, 0};
static vec3_t MOVEDIR_DOWN = {0, 0, -1};
void
G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward,
vec3_t right, vec3_t result)
@ -38,6 +44,18 @@ G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward,
distance[2];
}
void
G_ProjectSource2(vec3_t point, vec3_t distance, vec3_t forward,
vec3_t right, vec3_t up, vec3_t result)
{
result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1] +
up[0] * distance[2];
result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1] +
up[1] * distance[2];
result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] +
up[2] * distance[2];
}
/*
* Searches all active entities for the next
* one that holds the matching string at fieldofs
@ -52,6 +70,11 @@ G_Find(edict_t *from, int fieldofs, char *match)
{
char *s;
if (!match)
{
return NULL;
}
if (!from)
{
from = g_edicts;
@ -61,11 +84,6 @@ G_Find(edict_t *from, int fieldofs, char *match)
from++;
}
if (!match)
{
return NULL;
}
for ( ; from < &g_edicts[globals.num_edicts]; from++)
{
if (!from->inuse)
@ -137,6 +155,63 @@ findradius(edict_t *from, vec3_t org, float rad)
return NULL;
}
/*
* Returns entities that have origins within a spherical area
*/
edict_t *
findradius2(edict_t *from, vec3_t org, float rad)
{
/* rad must be positive */
vec3_t eorg;
int j;
if (!from)
{
from = g_edicts;
}
else
{
from++;
}
for ( ; from < &g_edicts[globals.num_edicts]; from++)
{
if (!from->inuse)
{
continue;
}
if (from->solid == SOLID_NOT)
{
continue;
}
if (!from->takedamage)
{
continue;
}
if (!(from->svflags & SVF_DAMAGEABLE))
{
continue;
}
for (j = 0; j < 3; j++)
{
eorg[j] = org[j] - (from->s.origin[j] + (from->mins[j] + from->maxs[j]) * 0.5);
}
if (VectorLength(eorg) > rad)
{
continue;
}
return from;
}
return NULL;
}
/*
* Searches all active entities for
* the next one that holds the matching
@ -371,10 +446,18 @@ vtos(vec3_t v)
return s;
}
static vec3_t VEC_UP = {0, -1, 0};
static vec3_t MOVEDIR_UP = {0, 0, 1};
static vec3_t VEC_DOWN = {0, -2, 0};
static vec3_t MOVEDIR_DOWN = {0, 0, -1};
void
get_normal_vector(const cplane_t *p, vec3_t normal)
{
if (p)
{
VectorCopy(p->normal, normal);
}
else
{
VectorCopy(vec3_origin, normal);
}
}
void
G_SetMovedir(vec3_t angles, vec3_t movedir)
@ -426,6 +509,39 @@ vectoyaw(vec3_t vec)
return yaw;
}
float
vectoyaw2(vec3_t vec)
{
float yaw;
if (vec[PITCH] == 0)
{
if (vec[YAW] == 0)
{
yaw = 0;
}
else if (vec[YAW] > 0)
{
yaw = 90;
}
else
{
yaw = 270;
}
}
else
{
yaw = (atan2(vec[YAW], vec[PITCH]) * 180 / M_PI);
if (yaw < 0)
{
yaw += 360;
}
}
return yaw;
}
void
vectoangles(vec3_t value1, vec3_t angles)
{
@ -479,11 +595,69 @@ vectoangles(vec3_t value1, vec3_t angles)
angles[ROLL] = 0;
}
void
vectoangles2(vec3_t value1, vec3_t angles)
{
float forward;
float yaw, pitch;
if ((value1[1] == 0) && (value1[0] == 0))
{
yaw = 0;
if (value1[2] > 0)
{
pitch = 90;
}
else
{
pitch = 270;
}
}
else
{
if (value1[0])
{
yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
}
else if (value1[1] > 0)
{
yaw = 90;
}
else
{
yaw = 270;
}
if (yaw < 0)
{
yaw += 360;
}
forward = sqrt(value1[0] * value1[0] + value1[1] * value1[1]);
pitch = (atan2(value1[2], forward) * 180 / M_PI);
if (pitch < 0)
{
pitch += 360;
}
}
angles[PITCH] = -pitch;
angles[YAW] = yaw;
angles[ROLL] = 0;
}
char *
G_CopyString(char *in)
{
char *out;
if (!in)
{
return NULL;
}
out = gi.TagMalloc(strlen(in) + 1, TAG_LEVEL);
strcpy(out, in);
return out;
@ -492,10 +666,24 @@ G_CopyString(char *in)
void
G_InitEdict(edict_t *e)
{
if (!e)
{
return;
}
if (e->nextthink)
{
e->nextthink = 0;
}
e->inuse = true;
e->classname = "noclass";
e->gravity = 1.0;
e->s.number = e - g_edicts;
e->gravityVector[0] = 0.0;
e->gravityVector[1] = 0.0;
e->gravityVector[2] = -1.0;
}
/*
@ -568,6 +756,11 @@ G_Spawn(void)
void
G_FreeEdict(edict_t *ed)
{
if (!ed)
{
return;
}
gi.unlinkentity(ed); /* unlink from world */
if (deathmatch->value || coop->value)

View file

@ -1,5 +1,6 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,6 +27,8 @@
#include "header/local.h"
extern void SP_item_foodcube(edict_t *best);
/*
* This is a support routine used when a client is firing
* a non-instant attack weapon. It checks to see if a
@ -378,6 +381,7 @@ void
blaster_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
int mod;
vec3_t normal;
if (!self || !other) /* plane and surf can be NULL */
{
@ -401,6 +405,8 @@ blaster_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT);
}
get_normal_vector(plane, normal);
if (other->takedamage)
{
if (self->spawnflags & 1)
@ -412,32 +418,15 @@ blaster_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
mod = MOD_BLASTER;
}
if (plane)
{
T_Damage(other, self, self->owner, self->velocity, self->s.origin,
plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod);
}
else
{
T_Damage(other, self, self->owner, self->velocity, self->s.origin,
vec3_origin, self->dmg, 1, DAMAGE_ENERGY, mod);
}
T_Damage(other, self, self->owner, self->velocity, self->s.origin,
normal, self->dmg, 1, DAMAGE_ENERGY, mod);
}
else
{
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_BLASTER);
gi.WritePosition(self->s.origin);
if (!plane)
{
gi.WriteDir(vec3_origin);
}
else
{
gi.WriteDir(plane->normal);
}
gi.WriteDir(normal);
gi.multicast(self->s.origin, MULTICAST_PVS);
}
@ -507,6 +496,56 @@ fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage,
}
}
void
fire_blueblaster(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int effect)
{
edict_t *bolt;
trace_t tr;
if (!self)
{
return;
}
VectorNormalize(dir);
bolt = G_Spawn();
VectorCopy(start, bolt->s.origin);
VectorCopy(start, bolt->s.old_origin);
vectoangles(dir, bolt->s.angles);
VectorScale(dir, speed, bolt->velocity);
bolt->movetype = MOVETYPE_FLYMISSILE;
bolt->clipmask = MASK_SHOT;
bolt->solid = SOLID_BBOX;
bolt->s.effects |= effect;
VectorClear(bolt->mins);
VectorClear(bolt->maxs);
bolt->s.modelindex = gi.modelindex("models/objects/blaser/tris.md2");
bolt->s.sound = gi.soundindex("misc/lasfly.wav");
bolt->owner = self;
bolt->touch = blaster_touch;
bolt->nextthink = level.time + 2;
bolt->think = G_FreeEdict;
bolt->dmg = damage;
bolt->classname = "bolt";
gi.linkentity(bolt);
if (self->client)
{
check_dodge(self, bolt->s.origin, dir, speed);
}
tr = gi.trace(self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT);
if (tr.fraction < 1.0)
{
VectorMA(bolt->s.origin, -10, dir, bolt->s.origin);
bolt->touch(bolt, tr.ent, NULL, NULL);
}
}
void
Grenade_Explode(edict_t *ent)
{
@ -747,6 +786,7 @@ void
rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
vec3_t origin;
vec3_t normal;
int n;
if (!ent || !other) /* plane and surf can be NULL */
@ -776,16 +816,10 @@ rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
if (other->takedamage)
{
if (plane)
{
T_Damage(other, ent, ent->owner, ent->velocity, ent->s.origin,
plane->normal, ent->dmg, 0, 0, MOD_ROCKET);
}
else
{
T_Damage(other, ent, ent->owner, ent->velocity, ent->s.origin,
vec3_origin, ent->dmg, 0, 0, MOD_ROCKET);
}
get_normal_vector(plane, normal);
T_Damage(other, ent, ent->owner, ent->velocity, ent->s.origin,
normal, ent->dmg, 0, 0, MOD_ROCKET);
}
else
{
@ -851,7 +885,7 @@ fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage,
rocket->s.modelindex = gi.modelindex("models/objects/rocket/tris.md2");
rocket->owner = self;
rocket->touch = rocket_touch;
rocket->nextthink = level.time + 8000 / speed;
rocket->nextthink = level.time + (8000.0f / (float)speed);
rocket->think = G_FreeEdict;
rocket->dmg = damage;
rocket->radius_dmg = radius_damage;
@ -899,7 +933,9 @@ fire_rail(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick)
}
else
{
/* -added so rail goes through SOLID_BBOX entities (gibs, etc) */
if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client) ||
(tr.ent->svflags & SVF_DAMAGEABLE) ||
(tr.ent->solid == SOLID_BBOX))
{
ignore = tr.ent;
@ -1000,8 +1036,8 @@ bfg_explode(edict_t *self)
gi.WriteByte(TE_BFG_EXPLOSION);
gi.WritePosition(ent->s.origin);
gi.multicast(ent->s.origin, MULTICAST_PHS);
T_Damage(ent, self, self->owner, self->velocity, ent->s.origin, vec3_origin,
(int)points, 0, DAMAGE_ENERGY, MOD_BFG_EFFECT);
T_Damage(ent, self, self->owner, self->velocity, ent->s.origin,
vec3_origin, (int)points, 0, DAMAGE_ENERGY, MOD_BFG_EFFECT);
}
}
@ -1017,6 +1053,8 @@ bfg_explode(edict_t *self)
void
bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
vec3_t normal;
if (!self || !other) /* plane and surf can be NULL */
{
G_FreeEdict(self);
@ -1042,9 +1080,10 @@ bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
/* core explosion - prevents firing it into the wall/floor */
if (other->takedamage)
{
get_normal_vector(plane, normal);
T_Damage(other, self, self->owner, self->velocity, self->s.origin,
(plane) ? plane->normal : vec3_origin,
200, 0, 0, MOD_BFG_BLAST);
normal, 200, 0, 0, MOD_BFG_BLAST);
}
T_RadiusDamage(self, self->owner, 200, other, 100, MOD_BFG_BLAST);
@ -1125,8 +1164,8 @@ bfg_think(edict_t *self)
continue;
}
if (!(ent->svflags & SVF_MONSTER) && (!ent->client) &&
(strcmp(ent->classname, "misc_explobox") != 0))
if (!(ent->svflags & SVF_MONSTER) && !(ent->svflags & SVF_DAMAGEABLE) &&
(!ent->client) && (strcmp(ent->classname, "misc_explobox") != 0))
{
continue;
}
@ -1159,7 +1198,8 @@ bfg_think(edict_t *self)
}
/* if we hit something that's not a monster or player we're done */
if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client))
if (!(tr.ent->svflags & SVF_MONSTER) &&
!(tr.ent->svflags & SVF_DAMAGEABLE) && (!tr.ent->client))
{
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_LASER_SPARKS);
@ -1210,7 +1250,7 @@ fire_bfg(edict_t *self, vec3_t start, vec3_t dir, int damage,
bfg->s.modelindex = gi.modelindex("sprites/s_bfg1.sp2");
bfg->owner = self;
bfg->touch = bfg_touch;
bfg->nextthink = level.time + 8000 / speed;
bfg->nextthink = level.time + (8000.0f / (float)speed);
bfg->think = G_FreeEdict;
bfg->radius_dmg = damage;
bfg->dmg_radius = damage_radius;
@ -1229,3 +1269,604 @@ fire_bfg(edict_t *self, vec3_t start, vec3_t dir, int damage,
gi.linkentity(bfg);
}
void
ionripper_sparks(edict_t *self)
{
if (!self)
{
return;
}
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_WELDING_SPARKS);
gi.WriteByte(0);
gi.WritePosition(self->s.origin);
gi.WriteDir(vec3_origin);
gi.WriteByte(0xe4 + (rand() & 3));
gi.multicast(self->s.origin, MULTICAST_PVS);
G_FreeEdict(self);
}
void
ionripper_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
vec3_t normal;
if (!self || !other)
{
return;
}
if (other == self->owner)
{
return;
}
if (surf && (surf->flags & SURF_SKY))
{
G_FreeEdict(self);
return;
}
if (self->owner->client)
{
PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT);
}
if (other->takedamage)
{
get_normal_vector(plane, normal);
T_Damage(other, self, self->owner, self->velocity, self->s.origin,
normal, self->dmg, 1, DAMAGE_ENERGY, MOD_RIPPER);
G_FreeEdict(self);
}
}
void
fire_ionripper(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int effect)
{
edict_t *ion;
trace_t tr;
if (!self)
{
return;
}
VectorNormalize(dir);
ion = G_Spawn();
VectorCopy(start, ion->s.origin);
VectorCopy(start, ion->s.old_origin);
vectoangles(dir, ion->s.angles);
VectorScale(dir, speed, ion->velocity);
ion->movetype = MOVETYPE_WALLBOUNCE;
ion->clipmask = MASK_SHOT;
ion->solid = SOLID_BBOX;
ion->s.effects |= effect;
ion->s.renderfx |= RF_FULLBRIGHT;
VectorClear(ion->mins);
VectorClear(ion->maxs);
ion->s.modelindex = gi.modelindex("models/objects/boomrang/tris.md2");
ion->s.sound = gi.soundindex("misc/lasfly.wav");
ion->owner = self;
ion->touch = ionripper_touch;
ion->nextthink = level.time + 3;
ion->think = ionripper_sparks;
ion->dmg = damage;
ion->dmg_radius = 100;
gi.linkentity(ion);
if (self->client)
{
check_dodge(self, ion->s.origin, dir, speed);
}
tr = gi.trace(self->s.origin, NULL, NULL, ion->s.origin, ion, MASK_SHOT);
if (tr.fraction < 1.0)
{
VectorMA(ion->s.origin, -10, dir, ion->s.origin);
ion->touch(ion, tr.ent, NULL, NULL);
}
}
void
heat_think(edict_t *self)
{
edict_t *target = NULL;
edict_t *aquire = NULL;
vec3_t vec;
float len;
float oldlen = 0;
if (!self)
{
return;
}
/* aquire new target */
while ((target = findradius(target, self->s.origin, 1024)) != NULL)
{
if (self->owner == target)
{
continue;
}
if (!target->client)
{
continue;
}
if (target->health <= 0)
{
continue;
}
if (!infront(self, target))
{
continue;
}
if (!visible(self, target))
{
continue;
}
VectorSubtract(self->s.origin, target->s.origin, vec);
len = VectorLength(vec);
if ((!aquire) || (len < oldlen))
{
aquire = target;
oldlen = len;
}
}
if (aquire)
{
VectorSubtract(aquire->s.origin, self->s.origin, vec);
vectoangles(vec, self->s.angles);
VectorNormalize(vec);
VectorScale(vec, 500, self->velocity);
}
self->nextthink = level.time + 0.1;
}
void
fire_heat(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed,
float damage_radius, int radius_damage)
{
edict_t *heat;
if (!self)
{
return;
}
heat = G_Spawn();
VectorCopy(start, heat->s.origin);
VectorCopy(dir, heat->movedir);
vectoangles(dir, heat->s.angles);
VectorScale(dir, speed, heat->velocity);
heat->movetype = MOVETYPE_FLYMISSILE;
heat->clipmask = MASK_SHOT;
heat->solid = SOLID_BBOX;
heat->s.effects |= EF_ROCKET;
VectorClear(heat->mins);
VectorClear(heat->maxs);
heat->s.modelindex = gi.modelindex("models/objects/rocket/tris.md2");
heat->owner = self;
heat->touch = rocket_touch;
heat->nextthink = level.time + 0.1;
heat->think = heat_think;
heat->dmg = damage;
heat->radius_dmg = radius_damage;
heat->dmg_radius = damage_radius;
heat->s.sound = gi.soundindex("weapons/rockfly.wav");
if (self->client)
{
check_dodge(self, heat->s.origin, dir, speed);
}
gi.linkentity(heat);
}
void
plasma_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
vec3_t origin;
vec3_t normal;
if (!ent || !other)
{
return;
}
if (other == ent->owner)
{
return;
}
if (surf && (surf->flags & SURF_SKY))
{
G_FreeEdict(ent);
return;
}
if (ent->owner->client)
{
PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT);
}
/* calculate position for the explosion entity */
VectorMA(ent->s.origin, -0.02, ent->velocity, origin);
if (other->takedamage)
{
get_normal_vector(plane, normal);
T_Damage(other, ent, ent->owner, ent->velocity, ent->s.origin,
normal, ent->dmg, 0, 0, MOD_PHALANX);
}
T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other,
ent->dmg_radius, MOD_PHALANX);
gi.WriteByte(svc_temp_entity);
gi.WriteByte(TE_PLASMA_EXPLOSION);
gi.WritePosition(origin);
gi.multicast(ent->s.origin, MULTICAST_PVS);
G_FreeEdict(ent);
}
void
fire_plasma(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, float damage_radius, int radius_damage)
{
edict_t *plasma;
if (!self)
{
return;
}
plasma = G_Spawn();
VectorCopy(start, plasma->s.origin);
VectorCopy(dir, plasma->movedir);
vectoangles(dir, plasma->s.angles);
VectorScale(dir, speed, plasma->velocity);
plasma->movetype = MOVETYPE_FLYMISSILE;
plasma->clipmask = MASK_SHOT;
plasma->solid = SOLID_BBOX;
VectorClear(plasma->mins);
VectorClear(plasma->maxs);
plasma->owner = self;
plasma->touch = plasma_touch;
plasma->nextthink = level.time + (8000.0f / (float)speed);
plasma->think = G_FreeEdict;
plasma->dmg = damage;
plasma->radius_dmg = radius_damage;
plasma->dmg_radius = damage_radius;
plasma->s.sound = gi.soundindex("weapons/rockfly.wav");
plasma->s.modelindex = gi.modelindex("sprites/s_photon.sp2");
plasma->s.effects |= EF_PLASMA | EF_ANIM_ALLFAST;
if (self->client)
{
check_dodge(self, plasma->s.origin, dir, speed);
}
gi.linkentity(plasma);
}
void
Trap_Think(edict_t *ent)
{
edict_t *target = NULL;
edict_t *best = NULL;
vec3_t vec;
int len, i;
int oldlen = 8000;
vec3_t forward, right, up;
if (!ent)
{
return;
}
if (ent->timestamp < level.time)
{
BecomeExplosion1(ent);
return;
}
ent->nextthink = level.time + 0.1;
if (!ent->groundentity)
{
return;
}
/* ok lets do the blood effect */
if (ent->s.frame > 4)
{
if (ent->s.frame == 5)
{
if (ent->wait == 64)
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/trapdown.wav"),
1, ATTN_IDLE, 0);
}
ent->wait -= 2;
ent->delay += level.time;
for (i = 0; i < 3; i++)
{
best = G_Spawn();
if (strcmp(ent->enemy->classname, "monster_gekk") == 0)
{
best->s.modelindex = gi.modelindex("models/objects/gekkgib/torso/tris.md2");
best->s.effects |= TE_GREENBLOOD;
}
else if (ent->mass > 200)
{
best->s.modelindex = gi.modelindex("models/objects/gibs/chest/tris.md2");
best->s.effects |= TE_BLOOD;
}
else
{
best->s.modelindex = gi.modelindex("models/objects/gibs/sm_meat/tris.md2");
best->s.effects |= TE_BLOOD;
}
AngleVectors(ent->s.angles, forward, right, up);
RotatePointAroundVector(vec, up, right, ((360.0 / 3) * i) + ent->delay);
VectorMA(vec, ent->wait / 2, vec, vec);
VectorAdd(vec, ent->s.origin, vec);
VectorAdd(vec, forward, best->s.origin);
best->s.origin[2] = ent->s.origin[2] + ent->wait;
VectorCopy(ent->s.angles, best->s.angles);
best->solid = SOLID_NOT;
best->s.effects |= EF_GIB;
best->takedamage = DAMAGE_YES;
best->movetype = MOVETYPE_TOSS;
best->svflags |= SVF_MONSTER;
best->deadflag = DEAD_DEAD;
VectorClear(best->mins);
VectorClear(best->maxs);
best->watertype = gi.pointcontents(best->s.origin);
if (best->watertype & MASK_WATER)
{
best->waterlevel = 1;
}
best->nextthink = level.time + 0.1;
best->think = G_FreeEdict;
gi.linkentity(best);
}
if (ent->wait < 19)
{
ent->s.frame++;
}
return;
}
ent->s.frame++;
if (ent->s.frame == 8)
{
ent->nextthink = level.time + 1.0;
ent->think = G_FreeEdict;
best = G_Spawn();
SP_item_foodcube(best);
VectorCopy(ent->s.origin, best->s.origin);
best->s.origin[2] += 16;
best->velocity[2] = 400;
best->count = ent->mass;
gi.linkentity(best);
return;
}
return;
}
ent->s.effects &= ~EF_TRAP;
if (ent->s.frame >= 4)
{
ent->s.effects |= EF_TRAP;
VectorClear(ent->mins);
VectorClear(ent->maxs);
}
if (ent->s.frame < 4)
{
ent->s.frame++;
}
while ((target = findradius(target, ent->s.origin, 256)) != NULL)
{
if (target == ent)
{
continue;
}
if (!(target->svflags & SVF_MONSTER) && !target->client)
{
continue;
}
if (target->health <= 0)
{
continue;
}
if (!visible(ent, target))
{
continue;
}
if (!best)
{
best = target;
continue;
}
VectorSubtract(ent->s.origin, target->s.origin, vec);
len = VectorLength(vec);
if (len < oldlen)
{
oldlen = len;
best = target;
}
}
/* pull the enemy in */
if (best)
{
vec3_t forward;
if (best->groundentity)
{
best->s.origin[2] += 1;
best->groundentity = NULL;
}
VectorSubtract(ent->s.origin, best->s.origin, vec);
len = VectorLength(vec);
if (best->client)
{
VectorNormalize(vec);
VectorMA(best->velocity, 250, vec, best->velocity);
}
else
{
best->ideal_yaw = vectoyaw(vec);
M_ChangeYaw(best);
AngleVectors(best->s.angles, forward, NULL, NULL);
VectorScale(forward, 256, best->velocity);
}
gi.sound(ent, CHAN_VOICE, gi.soundindex(
"weapons/trapsuck.wav"), 1, ATTN_IDLE, 0);
if (len < 32)
{
if (best->mass < 400)
{
T_Damage(best, ent, ent->owner, vec3_origin, best->s.origin,
vec3_origin, 100000, 1, 0, MOD_TRAP);
ent->enemy = best;
ent->wait = 64;
VectorCopy(ent->s.origin, ent->s.old_origin);
ent->timestamp = level.time + 30;
if (deathmatch->value)
{
ent->mass = best->mass / 4;
}
else
{
ent->mass = best->mass / 10;
}
/* ok spawn the food cube */
ent->s.frame = 5;
}
else
{
BecomeExplosion1(ent);
return;
}
}
}
}
void
fire_trap(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, float timer, float damage_radius, qboolean held)
{
edict_t *trap;
vec3_t dir;
vec3_t forward, right, up;
if (!self)
{
return;
}
vectoangles(aimdir, dir);
AngleVectors(dir, forward, right, up);
trap = G_Spawn();
VectorCopy(start, trap->s.origin);
VectorScale(aimdir, speed, trap->velocity);
VectorMA(trap->velocity, 200 + crandom() * 10.0, up, trap->velocity);
VectorMA(trap->velocity, crandom() * 10.0, right, trap->velocity);
VectorSet(trap->avelocity, 0, 300, 0);
trap->movetype = MOVETYPE_BOUNCE;
trap->clipmask = MASK_SHOT;
trap->solid = SOLID_BBOX;
VectorSet(trap->mins, -4, -4, 0);
VectorSet(trap->maxs, 4, 4, 8);
trap->s.modelindex = gi.modelindex("models/weapons/z_trap/tris.md2");
trap->owner = self;
trap->nextthink = level.time + 1.0;
trap->think = Trap_Think;
trap->dmg = damage;
trap->dmg_radius = damage_radius;
trap->classname = "htrap";
trap->s.sound = gi.soundindex("weapons/traploop.wav");
if (held)
{
trap->spawnflags = 3;
}
else
{
trap->spawnflags = 1;
}
if (timer <= 0.0)
{
Grenade_Explode(trap);
}
else
{
gi.linkentity(trap);
}
trap->timestamp = level.time + 30;
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -36,18 +37,19 @@
#define GAME_API_VERSION 3
#define SVF_NOCLIENT 0x00000001 /* don't send entity to clients, even if it has effects */
#define SVF_DEADMONSTER 0x00000002 /* treat as CONTENTS_DEADMONSTER for collision */
#define SVF_MONSTER 0x00000004 /* treat as CONTENTS_MONSTER for collision */
#define SVF_NOCLIENT 0x00000001 /* don't send entity to clients, even if it has effects */
#define SVF_DEADMONSTER 0x00000002 /* treat as CONTENTS_DEADMONSTER for collision */
#define SVF_MONSTER 0x00000004 /* treat as CONTENTS_MONSTER for collision */
#define SVF_DAMAGEABLE 0x00000008
#define MAX_ENT_CLUSTERS 16
typedef enum
{
SOLID_NOT, /* no interaction with other objects */
SOLID_TRIGGER, /* only touch when inside, after moving */
SOLID_BBOX, /* touch on edge */
SOLID_BSP /* bsp clip, touch on edge */
SOLID_NOT, /* no interaction with other objects */
SOLID_TRIGGER, /* only touch when inside, after moving */
SOLID_BBOX, /* touch on edge */
SOLID_BSP /* bsp clip, touch on edge */
} solid_t;
/* =============================================================== */
@ -69,7 +71,7 @@ struct gclient_s
player_state_t ps; /* communicated by server to clients */
int ping;
/* the game dll can add anything it wants
after this point in the structure */
after this point in the structure */
};
struct edict_s
@ -86,6 +88,8 @@ struct edict_s
int headnode; /* unused if num_clusters != -1 */
int areanum, areanum2;
/* ================================ */
int svflags; /* SVF_NOCLIENT, SVF_DEADMONSTER, SVF_MONSTER, etc */
vec3_t mins, maxs;
vec3_t absmin, absmax, size;
@ -143,10 +147,10 @@ typedef struct
if it is not passed to linkentity. If the size, position, or
solidity changes, it must be relinked. */
void (*linkentity)(edict_t *ent);
void (*unlinkentity)(edict_t *ent); /* call before removing an interactive edict */
void (*unlinkentity)(edict_t *ent); /* call before removing an interactive edict */
int (*BoxEdicts)(vec3_t mins, vec3_t maxs, edict_t **list, int maxcount,
int areatype);
void (*Pmove)(pmove_t *pmove); /* player movement code common with client prediction */
void (*Pmove)(pmove_t *pmove); /* player movement code common with client prediction */
/* network messaging */
void (*multicast)(vec3_t origin, multicast_t to);
@ -157,8 +161,8 @@ typedef struct
void (*WriteLong)(int c);
void (*WriteFloat)(float f);
void (*WriteString)(const char *s);
void (*WritePosition)(vec3_t pos); /* some fractional bits */
void (*WriteDir)(vec3_t pos); /* single byte encoded, very coarse */
void (*WritePosition)(vec3_t pos); /* some fractional bits */
void (*WriteDir)(vec3_t pos); /* single byte encoded, very coarse */
void (*WriteAngle)(float f);
/* managed memory allocation */
@ -174,7 +178,7 @@ typedef struct
/* ClientCommand and ServerCommand parameter access */
int (*argc)(void);
char *(*argv)(int n);
char *(*args)(void); /* concatenation of all argv >= 1 */
char *(*args)(void); /* concatenation of all argv >= 1 */
/* add commands to the server console as if
they were typed in for map changing, etc */
@ -220,7 +224,7 @@ typedef struct
void (*RunFrame)(void);
/* ServerCommand will be called when an "sv <command>"
command is issued on the server console. The game can
command is issued on the server console. The game can
issue gi.argc() / gi.argv() commands to get the rest
of the parameters */
void (*ServerCommand)(void);

View file

@ -1,5 +1,6 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (c) ZeniMax Media Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -59,27 +60,33 @@
#define SPAWNFLAG_NOT_DEATHMATCH 0x00000800
#define SPAWNFLAG_NOT_COOP 0x00001000
/* edict->flags */
#define FL_FLY 0x00000001
#define FL_SWIM 0x00000002 /* implied immunity to drowining */
#define FL_SWIM 0x00000002 /* implied immunity to drowining */
#define FL_IMMUNE_LASER 0x00000004
#define FL_INWATER 0x00000008
#define FL_GODMODE 0x00000010
#define FL_NOTARGET 0x00000020
#define FL_IMMUNE_SLIME 0x00000040
#define FL_IMMUNE_LAVA 0x00000080
#define FL_PARTIALGROUND 0x00000100 /* not all corners are valid */
#define FL_WATERJUMP 0x00000200 /* player jumping out of water */
#define FL_TEAMSLAVE 0x00000400 /* not the first on the team */
#define FL_PARTIALGROUND 0x00000100 /* not all corners are valid */
#define FL_WATERJUMP 0x00000200 /* player jumping out of water */
#define FL_TEAMSLAVE 0x00000400 /* not the first on the team */
#define FL_NO_KNOCKBACK 0x00000800
#define FL_POWER_ARMOR 0x00001000 /* power armor (if any) is active */
#define FL_POWER_ARMOR 0x00001000 /* power armor (if any) is active */
#define FL_COOP_TAKEN 0x00002000 /* Another client has already taken it */
#define FL_RESPAWN 0x80000000 /* used for item respawning */
#define FL_RESPAWN 0x80000000 /* used for item respawning */
#define FL_MECHANICAL 0x00002000 /* entity is mechanical, use sparks not blood */
#define FL_SAM_RAIMI 0x00004000 /* entity is in sam raimi cam mode */
#define FL_DISGUISED 0x00008000 /* entity is in disguise, monsters will not recognize. */
#define FL_NOGIB 0x00010000 /* player has been vaporized by a nuke, drop no gibs */
#define FRAMETIME 0.1
/* memory tags to allow dynamic memory to be cleaned up */
#define TAG_GAME 765 /* clear when unloading the dll */
#define TAG_LEVEL 766 /* clear when loading a new level */
#define TAG_GAME 765 /* clear when unloading the dll */
#define TAG_LEVEL 766 /* clear when loading a new level */
#define MELEE_DISTANCE 80
#define BODY_QUEUE_SIZE 8
@ -87,8 +94,8 @@
typedef enum
{
DAMAGE_NO,
DAMAGE_YES, /* will take damage if hit */
DAMAGE_AIM /* auto targeting recognizes this */
DAMAGE_YES, /* will take damage if hit */
DAMAGE_AIM /* auto targeting recognizes this */
} damage_t;
typedef enum
@ -106,7 +113,12 @@ typedef enum
AMMO_ROCKETS,
AMMO_GRENADES,
AMMO_CELLS,
AMMO_SLUGS
AMMO_SLUGS,
AMMO_FLECHETTES,
AMMO_TESLA,
AMMO_PROX,
AMMO_DISRUPTOR
} ammo_t;
/* Maximum debris / gibs per frame */
@ -145,12 +157,29 @@ typedef enum
#define AI_COMBAT_POINT 0x00001000
#define AI_MEDIC 0x00002000
#define AI_RESURRECTING 0x00004000
#define AI_IGNORE_PAIN 0x00008000
/* ROGUE */
#define AI_WALK_WALLS 0x00008000
#define AI_MANUAL_STEERING 0x00010000
#define AI_TARGET_ANGER 0x00020000
#define AI_DODGING 0x00040000
#define AI_CHARGING 0x00080000
#define AI_HINT_PATH 0x00100000
#define AI_IGNORE_SHOTS 0x00200000
#define AI_DO_NOT_COUNT 0x00400000 /* set for healed monsters */
#define AI_SPAWNED_CARRIER 0x00800000 /* both do_not_count and spawned are set for spawned monsters */
#define AI_SPAWNED_MEDIC_C 0x01000000 /* both do_not_count and spawned are set for spawned monsters */
#define AI_SPAWNED_WIDOW 0x02000000 /* both do_not_count and spawned are set for spawned monsters */
#define AI_SPAWNED_MASK 0x03800000 /* mask to catch all three flavors of spawned */
#define AI_BLOCKED 0x04000000 /* used by blocked_checkattack: set to say I'm attacking while blocked */
/* (prevents run-attacks) */
/* monster attack state */
#define AS_STRAIGHT 1
#define AS_SLIDING 2
#define AS_MELEE 3
#define AS_MISSILE 4
#define AS_BLIND 5
/* armor types */
#define ARMOR_NONE 0
@ -188,17 +217,19 @@ typedef enum
/* edict->movetype values */
typedef enum
{
MOVETYPE_NONE, /* never moves */
MOVETYPE_NOCLIP, /* origin and angles change with no interaction */
MOVETYPE_PUSH, /* no clip to world, push on box contact */
MOVETYPE_STOP, /* no clip to world, stops on box contact */
MOVETYPE_NONE, /* never moves */
MOVETYPE_NOCLIP, /* origin and angles change with no interaction */
MOVETYPE_PUSH, /* no clip to world, push on box contact */
MOVETYPE_STOP, /* no clip to world, stops on box contact */
MOVETYPE_WALK, /* gravity */
MOVETYPE_STEP, /* gravity, special edge handling */
MOVETYPE_WALK, /* gravity */
MOVETYPE_STEP, /* gravity, special edge handling */
MOVETYPE_FLY,
MOVETYPE_TOSS, /* gravity */
MOVETYPE_TOSS, /* gravity */
MOVETYPE_FLYMISSILE, /* extra size to monsters */
MOVETYPE_BOUNCE
MOVETYPE_BOUNCE, /* added this (the comma at the end of line) */
MOVETYPE_WALLBOUNCE,
MOVETYPE_NEWTOSS /* for deathball */
} movetype_t;
typedef struct
@ -210,13 +241,16 @@ typedef struct
int armor;
} gitem_armor_t;
#define IT_WEAPON 1 /* use makes active weapon */
#define IT_AMMO 2
#define IT_ARMOR 4
#define IT_STAY_COOP 8
#define IT_KEY 16
#define IT_POWERUP 32
#define IT_INSTANT_USE 64 /* item is insta-used on pickup if dmflag is set */
/* gitem_t->flags */
#define IT_WEAPON 0x00000001 /* use makes active weapon */
#define IT_AMMO 0x00000002
#define IT_ARMOR 0x00000004
#define IT_STAY_COOP 0x00000008
#define IT_KEY 0x00000010
#define IT_POWERUP 0x00000020
#define IT_MELEE 0x00000040
#define IT_NOT_GIVEABLE 0x00000080 /* item can not be given */
#define IT_INSTANT_USE 0x000000100 /* item is insta-used on pickup if dmflag is set */
/* gitem_t->weapmodel for weapons indicates model index */
#define WEAP_BLASTER 1
@ -230,6 +264,13 @@ typedef struct
#define WEAP_HYPERBLASTER 9
#define WEAP_RAILGUN 10
#define WEAP_BFG 11
#define WEAP_PHALANX 12
#define WEAP_BOOMER 13
#define WEAP_DISRUPTOR 14
#define WEAP_ETFRIFLE 15
#define WEAP_PLASMA 16
#define WEAP_PROXLAUNCH 17
#define WEAP_CHAINFIST 18
typedef struct gitem_s
{
@ -245,19 +286,19 @@ typedef struct gitem_s
/* client side info */
char *icon;
char *pickup_name; /* for printing on pickup */
int count_width; /* number of digits to display by icon */
char *pickup_name; /* for printing on pickup */
int count_width; /* number of digits to display by icon */
int quantity; /* for ammo how much, for weapons how much is used per shot */
char *ammo; /* for weapons */
int flags; /* IT_* flags */
int quantity; /* for ammo how much, for weapons how much is used per shot */
char *ammo; /* for weapons */
int flags; /* IT_* flags */
int weapmodel; /* weapon model index (for weapons) */
int weapmodel; /* weapon model index (for weapons) */
void *info;
int tag;
char *precaches; /* string of all models, sounds, and images this item will use */
char *precaches; /* string of all models, sounds, and images this item will use */
} gitem_t;
/* this structure is left intact through an entire game
@ -267,15 +308,15 @@ typedef struct
{
char helpmessage1[512];
char helpmessage2[512];
int helpchanged; /* flash F1 icon if non 0, play sound
and increment only if 1, 2, or 3 */
int helpchanged; /* flash F1 icon if non 0, play sound */
/* and increment only if 1, 2, or 3 */
gclient_t *clients; /* [maxclients] */
gclient_t *clients; /* [maxclients] */
/* can't store spawnpoint in level, because
it would get overwritten by the savegame
restore */
char spawnpoint[512]; /* needed for coop respawns */
char spawnpoint[512]; /* needed for coop respawns */
/* store latched cvars here that we want to get at often */
int maxclients;
@ -297,18 +338,18 @@ typedef struct
int framenum;
float time;
char level_name[MAX_QPATH]; /* the descriptive name (Outer Base, etc) */
char mapname[MAX_QPATH]; /* the server name (base1, etc) */
char nextmap[MAX_QPATH]; /* go here when fraglimit is hit */
char level_name[MAX_QPATH]; /* the descriptive name (Outer Base, etc) */
char mapname[MAX_QPATH]; /* the server name (base1, etc) */
char nextmap[MAX_QPATH]; /* go here when fraglimit is hit */
/* intermission state */
float intermissiontime; /* time the intermission was started */
float intermissiontime; /* time the intermission was started */
char *changemap;
int exitintermission;
vec3_t intermission_origin;
vec3_t intermission_angle;
edict_t *sight_client; /* changed once each frame for coop games */
edict_t *sight_client; /* changed once each frame for coop games */
edict_t *sight_entity;
int sight_entity_framenum;
@ -328,14 +369,17 @@ typedef struct
int total_monsters;
int killed_monsters;
edict_t *current_entity; /* entity running from G_RunFrame */
int body_que; /* dead bodies */
edict_t *current_entity; /* entity running from G_RunFrame */
int body_que; /* dead bodies */
int power_cubes; /* ugly necessity for coop */
int power_cubes; /* ugly necessity for coop */
edict_t *disguise_violator;
int disguise_violation_framenum;
} level_locals_t;
/* spawn_temp_t is only used to hold entity field values that
can be set from the editor, but aren't actualy present
can be set from the editor, but aren't actualy present/
in edict_t during gameplay */
typedef struct
{
@ -408,7 +452,7 @@ typedef struct
typedef struct
{
mmove_t *currentmove;
int aiflags;
unsigned int aiflags; /* unsigned, since we're close to the max */
int nextframe;
float scale;
@ -437,8 +481,40 @@ typedef struct
int power_armor_type;
int power_armor_power;
qboolean (*blocked)(edict_t *self, float dist);
float last_hint_time; /* last time the monster checked for hintpaths. */
edict_t *goal_hint; /* which hint_path we're trying to get to */
int medicTries;
edict_t *badMedic1, *badMedic2; /* these medics have declared this monster "unhealable" */
edict_t *healer; /* this is who is healing this monster */
void (*duck)(edict_t *self, float eta);
void (*unduck)(edict_t *self);
void (*sidestep)(edict_t *self);
float base_height;
float next_duck_time;
float duck_wait_time;
edict_t *last_player_enemy;
qboolean blindfire; /* will the monster blindfire? */
float blind_fire_delay;
vec3_t blind_fire_target;
/* used by the spawners to not spawn too much and keep track of #s of monsters spawned */
int monster_slots;
int monster_used;
edict_t *commander;
/* powerup timers, used by widow, our friend */
float quad_framenum;
float invincible_framenum;
float double_framenum;
} monsterinfo_t;
/* this determines how long to wait after a duck to duck again.
this needs to be longer than the time after the monster_duck_up
in all of the animation sequences */
#define DUCK_INTERVAL 0.5
extern game_locals_t game;
extern level_locals_t level;
extern game_import_t gi;
@ -486,7 +562,29 @@ extern int gibsthisframe;
#define MOD_TRIGGER_HURT 31
#define MOD_HIT 32
#define MOD_TARGET_BLASTER 33
#define MOD_RIPPER 34
#define MOD_PHALANX 35
#define MOD_BRAINTENTACLE 36
#define MOD_BLASTOFF 37
#define MOD_GEKK 38
#define MOD_TRAP 39
#define MOD_FRIENDLY_FIRE 0x8000000
#define MOD_CHAINFIST 40
#define MOD_DISINTEGRATOR 41
#define MOD_ETF_RIFLE 42
#define MOD_BLASTER2 43
#define MOD_HEATBEAM 44
#define MOD_TESLA 45
#define MOD_PROX 46
#define MOD_NUKE 47
#define MOD_VENGEANCE_SPHERE 48
#define MOD_HUNTER_SPHERE 49
#define MOD_DEFENDER_SPHERE 50
#define MOD_TRACKER 51
#define MOD_DBALL_CRUSH 52
#define MOD_DOPPLE_EXPLODE 53
#define MOD_DOPPLE_VENGEANCE 54
#define MOD_DOPPLE_HUNTER 55
/* Easier handling of AI skill levels */
#define SKILL_EASY 0
@ -495,7 +593,6 @@ extern int gibsthisframe;
#define SKILL_HARDPLUS 3
extern int meansOfDeath;
extern edict_t *g_edicts;
#define FOFS(x) (size_t)&(((edict_t *)NULL)->x)
@ -509,8 +606,10 @@ extern edict_t *g_edicts;
extern cvar_t *maxentities;
extern cvar_t *deathmatch;
extern cvar_t *coop;
extern cvar_t *coop_baseq2; /* treat spawnflags according to baseq2 rules */
extern cvar_t *coop_pickup_weapons;
extern cvar_t *coop_elevator_delay;
extern cvar_t *coop_pickup_weapons;
extern cvar_t *dmflags;
extern cvar_t *skill;
extern cvar_t *fraglimit;
@ -550,10 +649,28 @@ extern cvar_t *flood_waitdelay;
extern cvar_t *sv_maplist;
extern cvar_t *sv_stopspeed;
extern cvar_t *g_showlogic;
extern cvar_t *gamerules;
extern cvar_t *huntercam;
extern cvar_t *strong_mines;
extern cvar_t *randomrespawn;
extern cvar_t *g_disruptor;
extern cvar_t *aimfix;
extern cvar_t *g_machinegun_norecoil;
extern cvar_t *g_swap_speed;
/* this is for the count of monsters */
#define ENT_SLOTS_LEFT \
(ent->monsterinfo.monster_slots - \
ent->monsterinfo.monster_used)
#define SELF_SLOTS_LEFT \
(self->monsterinfo.monster_slots - \
self->monsterinfo.monster_used)
#define world (&g_edicts[0])
/* item spawnflags */
@ -574,13 +691,13 @@ typedef enum
{
F_INT,
F_FLOAT,
F_LSTRING, /* string on disk, pointer in memory, TAG_LEVEL */
F_GSTRING, /* string on disk, pointer in memory, TAG_GAME */
F_LSTRING, /* string on disk, pointer in memory, TAG_LEVEL */
F_GSTRING, /* string on disk, pointer in memory, TAG_GAME */
F_VECTOR,
F_ANGLEHACK,
F_EDICT, /* index on disk, pointer in memory */
F_ITEM, /* index on disk, pointer in memory */
F_CLIENT, /* index on disk, pointer in memory */
F_EDICT, /* index on disk, pointer in memory */
F_ITEM, /* index on disk, pointer in memory */
F_CLIENT, /* index on disk, pointer in memory */
F_FUNCTION,
F_MMOVE,
F_IGNORE
@ -627,7 +744,8 @@ int ArmorIndex(edict_t *ent);
int PowerArmorType(edict_t *ent);
gitem_t *GetItemByIndex(int index);
qboolean Add_Ammo(edict_t *ent, gitem_t *item, int count);
void Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);
void Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane,
csurface_t *surf);
/* g_utils.c */
qboolean KillBox(edict_t *ent);
@ -651,10 +769,17 @@ char *G_CopyString(char *in);
float *tv(float x, float y, float z);
char *vtos(vec3_t v);
void get_normal_vector(const cplane_t *p, vec3_t normal);
float vectoyaw(vec3_t vec);
void vectoangles(vec3_t vec, vec3_t angles);
void G_ProjectSource2(vec3_t point, vec3_t distance, vec3_t forward, vec3_t right,
vec3_t up, vec3_t result);
float vectoyaw2(vec3_t vec);
void vectoangles2(vec3_t vec, vec3_t angles);
edict_t *findradius2(edict_t *from, vec3_t org, float rad);
/* g_spawn.c */
void ED_CallSpawn(edict_t *ent);
@ -667,14 +792,22 @@ void T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
void T_RadiusDamage(edict_t *inflictor, edict_t *attacker,
float damage, edict_t *ignore, float radius,
int mod);
void T_RadiusNukeDamage(edict_t *inflictor, edict_t *attacker, float damage,
edict_t *ignore, float radius, int mod);
void T_RadiusClassDamage(edict_t *inflictor, edict_t *attacker, float damage,
char *ignoreClass, float radius, int mod);
void cleanupHealTarget(edict_t *ent);
/* damage flags */
#define DAMAGE_RADIUS 0x00000001 /* damage was indirect */
#define DAMAGE_NO_ARMOR 0x00000002 /* armour does not protect from this damage */
#define DAMAGE_ENERGY 0x00000004 /* damage is from an energy based weapon */
#define DAMAGE_NO_KNOCKBACK 0x00000008 /* do not affect velocity, just view angles */
#define DAMAGE_BULLET 0x00000010 /* damage is from a bullet (used for ricochets) */
#define DAMAGE_NO_PROTECTION 0x00000020 /* armor, shields, invulnerability, and godmode have no effect */
#define DAMAGE_RADIUS 0x00000001 /* damage was indirect */
#define DAMAGE_NO_ARMOR 0x00000002 /* armour does not protect from this damage */
#define DAMAGE_ENERGY 0x00000004 /* damage is from an energy based weapon */
#define DAMAGE_NO_KNOCKBACK 0x00000008 /* do not affect velocity, just view angles */
#define DAMAGE_BULLET 0x00000010 /* damage is from a bullet (used for ricochets) */
#define DAMAGE_NO_PROTECTION 0x00000020 /* armor, shields, invulnerability, and godmode have no effect */
#define DAMAGE_DESTROY_ARMOR 0x00000040 /* damage is done to armor and health. */
#define DAMAGE_NO_REG_ARMOR 0x00000080 /* damage skips regular armor */
#define DAMAGE_NO_POWER_ARMOR 0x00000100 /* damage skips power armor */
#define DEFAULT_BULLET_HSPREAD 300
#define DEFAULT_BULLET_VSPREAD 500
@ -701,6 +834,12 @@ void monster_fire_railgun(edict_t *self, vec3_t start, vec3_t aimdir,
void monster_fire_bfg(edict_t *self, vec3_t start, vec3_t aimdir,
int damage, int speed, int kick, float damage_radius,
int flashtype);
void monster_fire_ionripper(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int flashtype, int effect);
void monster_dabeam(edict_t *self);
void monster_fire_blueblaster(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int flashtype, int effect);
void M_droptofloor(edict_t *ent);
void monster_think(edict_t *self);
void walkmonster_start(edict_t *self);
@ -713,11 +852,20 @@ qboolean M_CheckAttack(edict_t *self);
void M_FlyCheck(edict_t *self);
void M_CheckGround(edict_t *ent);
void monster_fire_blaster2(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int flashtype, int effect);
void monster_fire_tracker(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, edict_t *enemy, int flashtype);
void stationarymonster_start(edict_t *self);
void monster_done_dodge(edict_t *self);
/* g_misc.c */
void ThrowHead(edict_t *self, char *gibname, int damage, int type);
void ThrowClientHead(edict_t *self, int damage);
void ThrowGib(edict_t *self, char *gibname, int damage, int type);
void BecomeExplosion1(edict_t *self);
void ThrowHeadACID(edict_t *self, char *gibname, int damage, int type);
void ThrowGibACID(edict_t *self, char *gibname, int damage, int type);
/* g_ai.c */
void AI_SetSightClient(void);
@ -749,10 +897,19 @@ void fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
void fire_grenade2(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, float timer, float damage_radius, qboolean held);
void fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, float damage_radius, int radius_damage);
int speed, float damage_radius,
int radius_damage);
void fire_rail(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick);
void fire_bfg(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, float damage_radius);
void fire_ionripper(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, int effect);
void fire_blueblaster(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, int effect);
void fire_plasma(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed,
float damage_radius, int radius_damage);
void fire_trap(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, float timer, float damage_radius, qboolean held);
/* g_ptrail.c */
void PlayerTrail_Init(void);
@ -823,10 +980,91 @@ void ReadGame(const char *filename);
void WriteGame(const char *filename, qboolean autosave);
void SpawnEntities(const char *mapname, char *entities, const char *spawnpoint);
void fire_flechette(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, int kick);
void fire_prox(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed);
void fire_nuke(edict_t *self, vec3_t start, vec3_t aimdir, int speed);
void fire_flame(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed);
void fire_burst(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed);
void fire_maintain(edict_t *, edict_t *, vec3_t start, vec3_t aimdir,
int damage, int speed);
void fire_incendiary_grenade(edict_t *self, vec3_t start, vec3_t aimdir,
int damage, int speed, float timer, float damage_radius);
void fire_player_melee(edict_t *self, vec3_t start, vec3_t aim, int reach,
int damage, int kick, int quiet, int mod);
void fire_tesla(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed);
void fire_blaster2(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
int speed, int effect, qboolean hyper);
void fire_tracker(edict_t *self, vec3_t start, vec3_t dir, int damage,
int speed, edict_t *enemy);
/* g_newai.c */
qboolean blocked_checkplat(edict_t *self, float dist);
qboolean blocked_checkjump(edict_t *self, float dist, float maxDown, float maxUp);
qboolean blocked_checknewenemy(edict_t *self);
qboolean monsterlost_checkhint(edict_t *self);
qboolean inback(edict_t *self, edict_t *other);
float realrange(edict_t *self, edict_t *other);
edict_t *SpawnBadArea(vec3_t mins, vec3_t maxs, float lifespan, edict_t *owner);
edict_t *CheckForBadArea(edict_t *ent);
qboolean MarkTeslaArea(edict_t *self, edict_t *tesla);
void InitHintPaths(void);
void PredictAim(edict_t *target, vec3_t start, float bolt_speed, qboolean eye_height,
float offset, vec3_t aimdir, vec3_t aimpoint);
qboolean below(edict_t *self, edict_t *other);
void drawbbox(edict_t *self);
void M_MonsterDodge(edict_t *self, edict_t *attacker, float eta, trace_t *tr);
void monster_duck_down(edict_t *self);
void monster_duck_hold(edict_t *self);
void monster_duck_up(edict_t *self);
qboolean has_valid_enemy(edict_t *self);
void TargetTesla(edict_t *self, edict_t *tesla);
void hintpath_stop(edict_t *self);
edict_t *PickCoopTarget(edict_t *self);
int CountPlayers(void);
void monster_jump_start(edict_t *self);
qboolean monster_jump_finished(edict_t *self);
/* g_sphere.c */
void Defender_Launch(edict_t *self);
void Vengeance_Launch(edict_t *self);
void Hunter_Launch(edict_t *self);
/* g_newdm.c */
void InitGameRules(void);
edict_t *DoRandomRespawn(edict_t *ent);
void PrecacheForRandomRespawn(void);
qboolean Tag_PickupToken(edict_t *ent, edict_t *other);
void Tag_DropToken(edict_t *ent, gitem_t *item);
void Tag_PlayerDeath(edict_t *targ, edict_t *inflictor, edict_t *attacker);
void fire_doppleganger(edict_t *ent, vec3_t start, vec3_t aimdir);
/* g_spawn.c */
edict_t *CreateMonster(vec3_t origin, vec3_t angles, char *classname);
edict_t *CreateFlyMonster(vec3_t origin, vec3_t angles, vec3_t mins,
vec3_t maxs, char *classname);
edict_t *CreateGroundMonster(vec3_t origin, vec3_t angles, vec3_t mins,
vec3_t maxs, char *classname, int height);
qboolean FindSpawnPoint(vec3_t startpoint, vec3_t mins, vec3_t maxs,
vec3_t spawnpoint, float maxMoveUp);
qboolean CheckSpawnPoint(vec3_t origin, vec3_t mins, vec3_t maxs);
qboolean CheckGroundSpawnPoint(vec3_t origin, vec3_t entMins, vec3_t entMaxs,
float height, float gravity);
void DetermineBBox(char *classname, vec3_t mins, vec3_t maxs);
void SpawnGrow_Spawn(vec3_t startpos, int size);
void Widowlegs_Spawn(vec3_t startpos, vec3_t angles);
/* p_client.c */
void RemoveAttackingPainDaemons(edict_t *self);
/* ============================================================================ */
/* client_t->anim_priority */
#define ANIM_BASIC 0 /* stand / run */
#define ANIM_BASIC 0 /* stand / run */
#define ANIM_WAVE 1
#define ANIM_JUMP 2
#define ANIM_PAIN 3
@ -841,11 +1079,11 @@ typedef struct
char netname[16];
int hand;
qboolean connected; /* a loadgame will leave valid entities that
just don't have a connection yet */
qboolean connected; /* a loadgame will leave valid entities that
just don't have a connection yet */
/* values saved and restored
from edicts when changing levels */
/* values saved and restored from
edicts when changing levels */
int health;
int max_health;
int savedFlags;
@ -860,45 +1098,53 @@ typedef struct
int max_grenades;
int max_cells;
int max_slugs;
int max_magslug;
int max_trap;
gitem_t *weapon;
gitem_t *lastweapon;
int power_cubes; /* used for tracking the cubes in coop games */
int score; /* for calculating total unit score in coop games */
int power_cubes; /* used for tracking the cubes in coop games */
int score; /* for calculating total unit score in coop games */
int game_helpchanged;
int helpchanged;
qboolean spectator; /* client is a spectator */
qboolean spectator; /* client is a spectator */
int max_tesla;
int max_prox;
int max_mines;
int max_flechettes;
int max_rounds;
} client_persistant_t;
/* client data that stays across deathmatch respawns */
typedef struct
{
client_persistant_t coop_respawn; /* what to set client->pers to on a respawn */
int enterframe; /* level.framenum the client entered the game */
int score; /* frags, etc */
vec3_t cmd_angles; /* angles sent over in the last command */
client_persistant_t coop_respawn; /* what to set client->pers to on a respawn */
int enterframe; /* level.framenum the client entered the game */
int score; /* frags, etc */
vec3_t cmd_angles; /* angles sent over in the last command */
qboolean spectator; /* client is a spectator */
qboolean spectator; /* client is a spectator */
} client_respawn_t;
/* this structure is cleared on each PutClientInServer(),
except for 'client->pers' */
/* this structure is cleared on each
PutClientInServer(), except for 'client->pers' */
struct gclient_s
{
/* known to server */
player_state_t ps; /* communicated by server to clients */
player_state_t ps; /* communicated by server to clients */
int ping;
/* private to game */
client_persistant_t pers;
client_respawn_t resp;
pmove_state_t old_pmove; /* for detecting out-of-pmove changes */
pmove_state_t old_pmove; /* for detecting out-of-pmove changes */
qboolean showscores; /* set layout stat */
qboolean showinventory; /* set layout stat */
qboolean showscores; /* set layout stat */
qboolean showinventory; /* set layout stat */
qboolean showhelp;
qboolean showhelpicon;
@ -914,24 +1160,24 @@ struct gclient_s
/* sum up damage over an entire frame, so
shotgun blasts give a single big kick */
int damage_armor; /* damage absorbed by armor */
int damage_parmor; /* damage absorbed by power armor */
int damage_blood; /* damage taken out of health */
int damage_knockback; /* impact damage */
vec3_t damage_from; /* origin for vector calculation */
int damage_armor; /* damage absorbed by armor */
int damage_parmor; /* damage absorbed by power armor */
int damage_blood; /* damage taken out of health */
int damage_knockback; /* impact damage */
vec3_t damage_from; /* origin for vector calculation */
float killer_yaw; /* when dead, look at killer */
float killer_yaw; /* when dead, look at killer */
weaponstate_t weaponstate;
vec3_t kick_angles; /* weapon kicks */
vec3_t kick_angles; /* weapon kicks */
vec3_t kick_origin;
float v_dmg_roll, v_dmg_pitch, v_dmg_time; /* damage kicks */
float fall_time, fall_value; /* for view drop on fall */
float v_dmg_roll, v_dmg_pitch, v_dmg_time; /* damage kicks */
float fall_time, fall_value; /* for view drop on fall */
float damage_alpha;
float bonus_alpha;
vec3_t damage_blend;
vec3_t v_angle; /* aiming direction */
float bobtime; /* so off-ground doesn't change it */
vec3_t v_angle; /* aiming direction */
float bobtime; /* so off-ground doesn't change it */
vec3_t oldviewangles;
vec3_t oldvelocity;
@ -939,7 +1185,7 @@ struct gclient_s
int old_waterlevel;
int breather_sound;
int machinegun_shots; /* for weapon raising */
int machinegun_shots; /* for weapon raising */
/* animation vars */
int anim_end;
@ -955,37 +1201,47 @@ struct gclient_s
qboolean grenade_blew_up;
float grenade_time;
float quadfire_framenum;
qboolean trap_blew_up;
float trap_time;
int silencer_shots;
int weapon_sound;
float pickup_msg_time;
float flood_locktill; /* locked from talking */
float flood_when[10]; /* when messages were said */
int flood_whenhead; /* head pointer for when said */
float flood_locktill; /* locked from talking */
float flood_when[10]; /* when messages were said */
int flood_whenhead; /* head pointer for when said */
float respawn_time; /* can respawn when time > this */
float respawn_time; /* can respawn when time > this */
edict_t *chase_target; /* player we are chasing */
qboolean update_chase; /* need to update chase info? */
edict_t *chase_target; /* player we are chasing */
qboolean update_chase; /* need to update chase info? */
float double_framenum;
float ir_framenum;
float nuke_framenum;
float tracker_pain_framenum;
edict_t *owned_sphere; /* this points to the player's sphere */
};
struct edict_s
{
entity_state_t s;
struct gclient_s *client; /* NULL if not a player
the server expects the first part
of gclient_s to be a player_state_t
but the rest of it is opaque */
struct gclient_s *client; /* NULL if not a player the server expects the first part
of gclient_s to be a player_state_t but the rest of it is
opaque */
qboolean inuse;
int linkcount;
link_t area; /* linked to a division node or leaf */
link_t area; /* linked to a division node or leaf */
int num_clusters; /* if -1, use headnode instead */
int num_clusters; /* if -1, use headnode instead */
int clusternums[MAX_ENT_CLUSTERS];
int headnode; /* unused if num_clusters != -1 */
int headnode; /* unused if num_clusters != -1 */
int areanum, areanum2;
/* ================================ */
@ -1001,11 +1257,12 @@ struct edict_s
/* EXPECTS THE FIELDS IN THAT ORDER! */
/* ================================ */
int movetype;
int flags;
char *model;
float freetime; /* sv.time when the object was freed */
float freetime; /* sv.time when the object was freed */
/* only used locally in game, not by server */
char *message;
@ -1014,7 +1271,7 @@ struct edict_s
float timestamp;
float angle; /* set in qe3, -1 = up, -2 = down */
float angle; /* set in qe3, -1 = up, -2 = down */
char *target;
char *targetname;
char *killtarget;
@ -1032,8 +1289,8 @@ struct edict_s
vec3_t avelocity;
int mass;
float air_finished;
float gravity; /* per entity gravity multiplier (1.0 is normal)
use for lowgrav artifact, flares */
float gravity; /* per entity gravity multiplier (1.0 is normal) */
/* use for lowgrav artifact, flares */
edict_t *goalentity;
edict_t *movetarget;
@ -1043,7 +1300,7 @@ struct edict_s
float nextthink;
void (*prethink)(edict_t *ent);
void (*think)(edict_t *self);
void (*blocked)(edict_t *self, edict_t *other);
void (*blocked)(edict_t *self, edict_t *other); /* move to moveinfo? */
void (*touch)(edict_t *self, edict_t *other, cplane_t *plane,
csurface_t *surf);
void (*use)(edict_t *self, edict_t *other, edict_t *activator);
@ -1051,10 +1308,11 @@ struct edict_s
void (*die)(edict_t *self, edict_t *inflictor, edict_t *attacker,
int damage, vec3_t point);
float touch_debounce_time;
float touch_debounce_time; /* now also used by fixbots for timeouts when getting stuck */
float pain_debounce_time;
float damage_debounce_time;
float fly_sound_debounce_time; /* now also used by insane marines to store pain sound timeout */
/* and by fixbots for storing object_repair timeout when getting stuck */
float last_move_time;
int health;
@ -1065,14 +1323,14 @@ struct edict_s
float show_hostile;
float powerarmor_time;
char *map; /* target_changelevel */
char *map; /* target_changelevel */
int viewheight; /* height above origin where eyesight is determined */
int viewheight; /* height above origin where eyesight is determined */
int takedamage;
int dmg;
int radius_dmg;
float dmg_radius;
int sounds; /* now also used for player death sound aggregation */
int sounds; /* now also used for player death sound aggregation */
int count;
edict_t *chain;
@ -1084,7 +1342,7 @@ struct edict_s
edict_t *teamchain;
edict_t *teammaster;
edict_t *mynoise; /* can go in client only */
edict_t *mynoise; /* can go in client only */
edict_t *mynoise2;
int noise_index;
@ -1094,7 +1352,7 @@ struct edict_s
/* timing variables */
float wait;
float delay; /* before firing targets */
float delay; /* before firing targets */
float random;
float last_sound_time;
@ -1107,16 +1365,74 @@ struct edict_s
/* move this to clientinfo? */
int light_level;
int style; /* also used as areaportal number */
int style; /* also used as areaportal number */
gitem_t *item; /* for bonus items */
gitem_t *item; /* for bonus items */
/* common data blocks */
moveinfo_t moveinfo;
monsterinfo_t monsterinfo;
int orders;
int plat2flags;
vec3_t offset;
vec3_t gravityVector;
edict_t *bad_area;
edict_t *hint_chain;
edict_t *monster_hint_chain;
edict_t *target_hint_chain;
int hint_chain_id;
float lastMoveTime;
};
#define SPHERE_DEFENDER 0x0001
#define SPHERE_HUNTER 0x0002
#define SPHERE_VENGEANCE 0x0004
#define SPHERE_DOPPLEGANGER 0x0100
#define SPHERE_TYPE 0x00FF
#define SPHERE_FLAGS 0xFF00
/* deathmatch games */
#define RDM_TAG 2
#define RDM_DEATHBALL 3
typedef struct dm_game_rs
{
void (*GameInit)(void);
void (*PostInitSetup)(void);
void (*ClientBegin)(edict_t *ent);
void (*SelectSpawnPoint)(edict_t *ent, vec3_t origin, vec3_t angles);
void (*PlayerDeath)(edict_t *targ, edict_t *inflictor, edict_t *attacker);
void (*Score)(edict_t *attacker, edict_t *victim, int scoreChange);
void (*PlayerEffects)(edict_t *ent);
void (*DogTag)(edict_t *ent, edict_t *killer, char **pic);
void (*PlayerDisconnect)(edict_t *ent);
int (*ChangeDamage)(edict_t *targ, edict_t *attacker, int damage, int mod);
int (*ChangeKnockback)(edict_t *targ, edict_t *attacker, int knockback, int mod);
int (*CheckDMRules)(void);
} dm_game_rt;
extern dm_game_rt DMGame;
void Tag_GameInit(void);
void Tag_PostInitSetup(void);
void Tag_PlayerDeath(edict_t *targ, edict_t *inflictor, edict_t *attacker);
void Tag_Score(edict_t *attacker, edict_t *victim, int scoreChange);
void Tag_PlayerEffects(edict_t *ent);
void Tag_DogTag(edict_t *ent, edict_t *killer, char **pic);
void Tag_PlayerDisconnect(edict_t *ent);
int Tag_ChangeDamage(edict_t *targ, edict_t *attacker, int damage, int mod);
void DBall_GameInit(void);
void DBall_ClientBegin(edict_t *ent);
void DBall_SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles);
int DBall_ChangeKnockback(edict_t *targ, edict_t *attacker, int knockback, int mod);
int DBall_ChangeDamage(edict_t *targ, edict_t *attacker, int damage, int mod);
void DBall_PostInitSetup(void);
int DBall_CheckDMRules(void);
/*
* Uncomment for check that exported functions declarations are same as in
* implementation. (-Wmissing-prototypes )

View file

@ -521,7 +521,7 @@ berserk_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /*
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{

View file

@ -873,7 +873,7 @@ makron_torso_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attack
return;
}
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2",
damage, GIB_ORGANIC);
@ -960,7 +960,7 @@ makron_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /*
/* check for gib */
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2",
damage, GIB_ORGANIC);

View file

@ -767,7 +767,7 @@ brain_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* u
/* check for gib */
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{

View file

@ -517,7 +517,7 @@ chick_die(edict_t *self, edict_t *inflictor /* unused */,
/* check for gib */
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{

View file

@ -477,7 +477,7 @@ flipper_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /*
/* check for gib */
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{

View file

@ -497,7 +497,7 @@ gladiator_die(edict_t *self, edict_t *inflictor /* unused */,
/* check for gib */
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{

View file

@ -513,7 +513,7 @@ gunner_die(edict_t *self, edict_t *inflictor /* unused */,
/* check for gib */
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{

View file

@ -527,7 +527,7 @@ infantry_die(edict_t *self, edict_t *inflictor /* unused */,
/* check for gib */
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{

View file

@ -888,7 +888,7 @@ insane_die(edict_t *self, edict_t *inflictor /* unused */,
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_IDLE, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_IDLE, 0);
for (n = 0; n < 2; n++)
{

View file

@ -593,7 +593,7 @@ medic_die(edict_t *self, edict_t *inflictor /* unused */,
/* check for gib */
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{

View file

@ -790,7 +790,7 @@ mutant_die(edict_t *self, edict_t *inflictor /* unused */,
if (self->health <= self->gib_health)
{
gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0);
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
for (n = 0; n < 2; n++)
{