mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2025-03-23 11:22:05 +00:00
Roll the ctf crap back. It won't work this way, since some low level
parts of the code (g_local.h) differ too much. We need a better solution...
This commit is contained in:
parent
c958563b2b
commit
bc8a06bdd4
34 changed files with 6280 additions and 16426 deletions
84
Makefile
84
Makefile
|
@ -11,6 +11,7 @@
|
|||
# #
|
||||
# Dependencies: #
|
||||
# - SDL 1.2 #
|
||||
# - libX11 #
|
||||
# - libGL #
|
||||
# - libvorbis #
|
||||
# - libogg #
|
||||
|
@ -51,12 +52,6 @@ CFLAGS := -O2 -fno-strict-aliasing -fomit-frame-pointer\
|
|||
|
||||
# ----------
|
||||
|
||||
# SDL Flags
|
||||
CFSDL := $(shell sdl-config --cflags)
|
||||
LDSDL := $(shell sdl-config --libs)
|
||||
|
||||
# ----------
|
||||
|
||||
# Base include path.
|
||||
ifeq ($(OSTYPE),Linux)
|
||||
INCLUDE := -I/usr/include
|
||||
|
@ -74,6 +69,11 @@ else ifeq ($(OSTYPE),FreeBSD)
|
|||
LDFLAGS := -L/usr/local/lib -lm
|
||||
endif
|
||||
|
||||
# ----------
|
||||
|
||||
# Converter rule
|
||||
|
||||
|
||||
# ----------
|
||||
|
||||
# Builds everything
|
||||
|
@ -95,10 +95,12 @@ client:
|
|||
build/client/%.o: %.c
|
||||
@echo '===> CC $<'
|
||||
@mkdir -p $(@D)
|
||||
@$(CC) -c $(CFLAGS) $(CFSDL) $(INCLUDE) -o $@ $<
|
||||
@$(CC) -c $(CFLAGS) $(INCLUDE) -o $@ $<
|
||||
|
||||
release/quake2 : INCLUDE += -I/usr/include/SDL -I/usr/local/include/SDL
|
||||
release/quake2 : LDFLAGS += -lvorbis -lvorbisfile -logg -lz \
|
||||
-lXxf86vm -lX11
|
||||
-lXxf86vm -lX11 \
|
||||
$(shell sdl-config --libs)
|
||||
# ----------
|
||||
|
||||
# The server
|
||||
|
@ -126,9 +128,10 @@ refresher:
|
|||
build/refresher/%.o: %.c
|
||||
@echo '===> CC $<'
|
||||
@mkdir -p $(@D)
|
||||
@$(CC) -c $(CFLAGS) $(CFSDL) $(INCLUDE) -o $@ $<
|
||||
@$(CC) -c $(CFLAGS) $(INCLUDE) -o $@ $<
|
||||
|
||||
release/ref_gl.so : INCLUDE += $(shell pkg-config x11 --cflags)
|
||||
release/ref_gl.so : INCLUDE += -I/usr/local/include/SDL \
|
||||
-I/usr/include/SDL -I/usr/X11R6/include
|
||||
release/ref_gl.so : CFLAGS += -fPIC
|
||||
release/ref_gl.so : LDFLAGS += -shared
|
||||
|
||||
|
@ -161,7 +164,7 @@ build/ctf/%.o: %.c
|
|||
@mkdir -p $(@D)
|
||||
@$(CC) -c $(CFLAGS) $(INCLUDE) -o $@ $<
|
||||
|
||||
release/ctf/game.so : CFLAGS += -fPIC -DCTF
|
||||
release/ctf/game.so : CFLAGS += -fPIC
|
||||
release/ctf/game.so : LDFLAGS += -shared
|
||||
|
||||
# ----------
|
||||
|
@ -273,32 +276,32 @@ COMMON_OBJS_ := \
|
|||
|
||||
# Used by the ctf game
|
||||
CTF_OBJS_ = \
|
||||
src/game/baseq2/g_ai.o \
|
||||
src/game/baseq2/g_chase.o \
|
||||
src/game/baseq2/g_cmds.o \
|
||||
src/game/baseq2/g_combat.o \
|
||||
src/game/baseq2/g_ctf.o \
|
||||
src/game/baseq2/g_func.o \
|
||||
src/game/baseq2/g_items.o \
|
||||
src/game/baseq2/g_main.o \
|
||||
src/game/baseq2/g_misc.o \
|
||||
src/game/baseq2/g_monster.o \
|
||||
src/game/baseq2/g_phys.o \
|
||||
src/game/baseq2/g_spawn.o \
|
||||
src/game/baseq2/g_svcmds.o \
|
||||
src/game/baseq2/g_target.o \
|
||||
src/game/baseq2/g_trigger.o \
|
||||
src/game/baseq2/g_utils.o \
|
||||
src/game/baseq2/g_weapon.o \
|
||||
src/game/baseq2/m_move.o \
|
||||
src/game/baseq2/p_client.o \
|
||||
src/game/baseq2/p_hud.o \
|
||||
src/game/baseq2/p_menu.o \
|
||||
src/game/baseq2/p_trail.o \
|
||||
src/game/baseq2/p_view.o \
|
||||
src/game/baseq2/p_weapon.o \
|
||||
src/game/baseq2/q_shared.o \
|
||||
src/game/baseq2/savegame/savegame.o
|
||||
src/game/ctf/g_ai.o \
|
||||
src/game/ctf/g_chase.o \
|
||||
src/game/ctf/g_cmds.o \
|
||||
src/game/ctf/g_combat.o \
|
||||
src/game/ctf/g_ctf.o \
|
||||
src/game/ctf/g_func.o \
|
||||
src/game/ctf/g_items.o \
|
||||
src/game/ctf/g_main.o \
|
||||
src/game/ctf/g_misc.o \
|
||||
src/game/ctf/g_monster.o \
|
||||
src/game/ctf/g_phys.o \
|
||||
src/game/ctf/g_save.o \
|
||||
src/game/ctf/g_spawn.o \
|
||||
src/game/ctf/g_svcmds.o \
|
||||
src/game/ctf/g_target.o \
|
||||
src/game/ctf/g_trigger.o \
|
||||
src/game/ctf/g_utils.o \
|
||||
src/game/ctf/g_weapon.o \
|
||||
src/game/ctf/m_move.o \
|
||||
src/game/ctf/p_client.o \
|
||||
src/game/ctf/p_hud.o \
|
||||
src/game/ctf/p_menu.o \
|
||||
src/game/ctf/p_trail.o \
|
||||
src/game/ctf/p_view.o \
|
||||
src/game/ctf/p_weapon.o \
|
||||
src/game/ctf/q_shared.o
|
||||
|
||||
# Used by the client and the server
|
||||
GAME_ABI_OBJS_ := \
|
||||
|
@ -397,7 +400,7 @@ SDL_OPENGL_OBJS = $(patsubst %,build/refresher/%,$(SDL_OPENGL_OBJS_))
|
|||
|
||||
BASEQ2_OBJS = $(patsubst %,build/baseq2/%,$(BASEQ2_OBJS_))
|
||||
|
||||
CTF_OBJS = $(patsubst %,build/ctf/%,$(CTF_OBJS_))
|
||||
CTF_OBJS = $(patsubst %,build/baseq2/%,$(CTF_OBJS_))
|
||||
|
||||
# ----------
|
||||
|
||||
|
@ -453,7 +456,7 @@ CTF_DEPS= $(CTF_OBJS:.o=.d)
|
|||
release/quake2 : $(CLIENT_OBJS) $(CLIENT_COMMON_OBJS) $(CLIENT_GAME_ABI_OBJS) \
|
||||
$(UNIX_CLIENT_OBJS) $(SDL_OBJS) $(CLIENT_SERVER_OBJS)
|
||||
@echo '===> LD $@'
|
||||
@$(CC) $(LDFLAGS) $(LDSDL) -o $@ $(CLIENT_OBJS) $(CLIENT_COMMON_OBJS) \
|
||||
@$(CC) $(LDFLAGS) -o $@ $(CLIENT_OBJS) $(CLIENT_COMMON_OBJS) \
|
||||
$(CLIENT_GAME_ABI_OBJS) $(UNIX_CLIENT_OBJS) \
|
||||
$(SDL_OBJS) $(CLIENT_SERVER_OBJS)
|
||||
|
||||
|
@ -471,7 +474,7 @@ release/ref_gl.so : $(OPENGL_OBJS) $(OPENGL_GAME_ABI_OBJS) \
|
|||
@$(CC) $(LDFLAGS) -o $@ $(OPENGL_OBJS) $(OPENGL_GAME_ABI_OBJS) \
|
||||
$(UNIX_OPENGL_OBJS) $(SDL_OPENGL_OBJS)
|
||||
|
||||
# release/baseq2/game.so
|
||||
# release/bsaeq2/game.so
|
||||
release/baseq2/game.so : $(BASEQ2_OBJS)
|
||||
@echo '===> LD $@'
|
||||
@$(CC) $(LDFLAGS) -o $@ $(BASEQ2_OBJS)
|
||||
|
@ -482,4 +485,3 @@ release/ctf/game.so : $(CTF_OBJS)
|
|||
@$(CC) $(LDFLAGS) -o $@ $(CTF_OBJS)
|
||||
|
||||
# ----------
|
||||
|
||||
|
|
|
@ -1111,60 +1111,14 @@ Cmd_Wave_f(edict_t *ent)
|
|||
}
|
||||
}
|
||||
|
||||
qboolean
|
||||
CheckFlood(edict_t *ent)
|
||||
{
|
||||
int i;
|
||||
gclient_t *cl;
|
||||
|
||||
if (!ent)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flood_msgs->value)
|
||||
{
|
||||
cl = ent->client;
|
||||
|
||||
if (level.time < cl->flood_locktill)
|
||||
{
|
||||
gi.cprintf(ent, PRINT_HIGH, "You can't talk for %d more seconds\n",
|
||||
(int)(cl->flood_locktill - level.time));
|
||||
return true;
|
||||
}
|
||||
|
||||
i = cl->flood_whenhead - flood_msgs->value + 1;
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
i = (sizeof(cl->flood_when) / sizeof(cl->flood_when[0])) + i;
|
||||
}
|
||||
|
||||
if (cl->flood_when[i] &&
|
||||
(level.time - cl->flood_when[i] < flood_persecond->value))
|
||||
{
|
||||
cl->flood_locktill = level.time + flood_waitdelay->value;
|
||||
gi.cprintf(ent, PRINT_CHAT,
|
||||
"Flood protection: You can't talk for %d seconds.\n",
|
||||
(int)flood_waitdelay->value);
|
||||
return true;
|
||||
}
|
||||
|
||||
cl->flood_whenhead = (cl->flood_whenhead + 1) %
|
||||
(sizeof(cl->flood_when) / sizeof(cl->flood_when[0]));
|
||||
cl->flood_when[cl->flood_whenhead] = level.time;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0)
|
||||
{
|
||||
int j;
|
||||
int i, j;
|
||||
edict_t *other;
|
||||
char *p;
|
||||
char text[2048];
|
||||
gclient_t *cl;
|
||||
|
||||
if (!ent)
|
||||
{
|
||||
|
@ -1217,9 +1171,37 @@ Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0)
|
|||
|
||||
strcat(text, "\n");
|
||||
|
||||
if (CheckFlood(ent))
|
||||
if (flood_msgs->value)
|
||||
{
|
||||
return;
|
||||
cl = ent->client;
|
||||
|
||||
if (level.time < cl->flood_locktill)
|
||||
{
|
||||
gi.cprintf(ent, PRINT_HIGH, "You can't talk for %d more seconds\n",
|
||||
(int)(cl->flood_locktill - level.time));
|
||||
return;
|
||||
}
|
||||
|
||||
i = cl->flood_whenhead - flood_msgs->value + 1;
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
i = (sizeof(cl->flood_when) / sizeof(cl->flood_when[0])) + i;
|
||||
}
|
||||
|
||||
if (cl->flood_when[i] &&
|
||||
(level.time - cl->flood_when[i] < flood_persecond->value))
|
||||
{
|
||||
cl->flood_locktill = level.time + flood_waitdelay->value;
|
||||
gi.cprintf(ent, PRINT_CHAT,
|
||||
"Flood protection: You can't talk for %d seconds.\n",
|
||||
(int)flood_waitdelay->value);
|
||||
return;
|
||||
}
|
||||
|
||||
cl->flood_whenhead = (cl->flood_whenhead + 1) %
|
||||
(sizeof(cl->flood_when) / sizeof(cl->flood_when[0]));
|
||||
cl->flood_when[cl->flood_whenhead] = level.time;
|
||||
}
|
||||
|
||||
if (dedicated->value)
|
||||
|
@ -1326,19 +1308,11 @@ ClientCommand(edict_t *ent)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef CTF
|
||||
if ((Q_stricmp(cmd, "say_team") == 0) || (Q_stricmp(cmd, "steam") == 0))
|
||||
{
|
||||
CTFSay_Team(ent, gi.args());
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (Q_stricmp(cmd, "say_team") == 0)
|
||||
{
|
||||
Cmd_Say_f(ent, true, false);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Q_stricmp(cmd, "score") == 0)
|
||||
{
|
||||
|
|
|
@ -288,12 +288,7 @@ CheckPowerArmor(edict_t *ent, vec3_t point, vec3_t normal, int damage,
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifdef CTF
|
||||
damagePerCell = 1;
|
||||
#else
|
||||
damagePerCell = 2;
|
||||
#endif
|
||||
|
||||
pa_te_type = TE_SHIELD_SPARKS;
|
||||
damage = (2 * damage) / 3;
|
||||
}
|
||||
|
@ -466,15 +461,6 @@ M_ReactToDamage(edict_t *targ, edict_t *attacker)
|
|||
(strcmp(attacker->classname, "monster_makron") != 0) &&
|
||||
(strcmp(attacker->classname, "monster_jorg") != 0))
|
||||
{
|
||||
#ifdef CTF
|
||||
if (targ->enemy)
|
||||
{
|
||||
if (targ->enemy->client)
|
||||
{
|
||||
targ->oldenemy = targ->enemy;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (targ->enemy && targ->enemy->client)
|
||||
{
|
||||
targ->oldenemy = targ->enemy;
|
||||
|
@ -494,7 +480,6 @@ M_ReactToDamage(edict_t *targ, edict_t *attacker)
|
|||
{
|
||||
targ->oldenemy = targ->enemy;
|
||||
}
|
||||
#endif
|
||||
|
||||
targ->enemy = attacker;
|
||||
|
||||
|
@ -538,7 +523,6 @@ CheckTeamDamage (edict_t *targ, edict_t *attacker)
|
|||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
|
@ -744,14 +728,7 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
|||
SpawnDamage(te_sparks, point, normal);
|
||||
}
|
||||
|
||||
#ifdef CTF
|
||||
if (!CTFMatchSetup())
|
||||
{
|
||||
targ->health = targ->health - take;
|
||||
}
|
||||
#else
|
||||
targ->health = targ->health - take;
|
||||
#endif
|
||||
|
||||
if (targ->health <= 0)
|
||||
{
|
||||
|
@ -782,11 +759,7 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
|||
}
|
||||
else if (client)
|
||||
{
|
||||
if (!(targ->flags & FL_GODMODE) && (take)
|
||||
#ifdef CTF
|
||||
&& !CTFMatchSetup()
|
||||
#endif
|
||||
)
|
||||
if (!(targ->flags & FL_GODMODE) && (take))
|
||||
{
|
||||
targ->pain(targ, attacker, knockback, take);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,209 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, 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
|
||||
* 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.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* Header file for the CTF code. Included at the end of g_local.h.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#ifdef CTF
|
||||
|
||||
#ifndef G_CTF_H
|
||||
#define G_CTF_H
|
||||
|
||||
#define CTF_VERSION 1.52
|
||||
#define CTF_VSTRING2(x) # x
|
||||
#define CTF_VSTRING(x) CTF_VSTRING2(x)
|
||||
#define CTF_STRING_VERSION CTF_VSTRING(CTF_VERSION)
|
||||
|
||||
#define STAT_CTF_TEAM1_PIC 17
|
||||
#define STAT_CTF_TEAM1_CAPS 18
|
||||
#define STAT_CTF_TEAM2_PIC 19
|
||||
#define STAT_CTF_TEAM2_CAPS 20
|
||||
#define STAT_CTF_FLAG_PIC 21
|
||||
#define STAT_CTF_JOINED_TEAM1_PIC 22
|
||||
#define STAT_CTF_JOINED_TEAM2_PIC 23
|
||||
#define STAT_CTF_TEAM1_HEADER 24
|
||||
#define STAT_CTF_TEAM2_HEADER 25
|
||||
#define STAT_CTF_TECH 26
|
||||
#define STAT_CTF_ID_VIEW 27
|
||||
#define STAT_CTF_MATCH 28
|
||||
#define STAT_CTF_ID_VIEW_COLOR 29
|
||||
#define STAT_CTF_TEAMINFO 30
|
||||
|
||||
#define CONFIG_CTF_MATCH (CS_AIRACCEL - 1)
|
||||
#define CONFIG_CTF_TEAMINFO (CS_AIRACCEL - 2)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CTF_NOTEAM,
|
||||
CTF_TEAM1,
|
||||
CTF_TEAM2
|
||||
} ctfteam_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CTF_GRAPPLE_STATE_FLY,
|
||||
CTF_GRAPPLE_STATE_PULL,
|
||||
CTF_GRAPPLE_STATE_HANG
|
||||
} ctfgrapplestate_t;
|
||||
|
||||
typedef struct ghost_s
|
||||
{
|
||||
char netname[16];
|
||||
int number;
|
||||
|
||||
/* stats */
|
||||
int deaths;
|
||||
int kills;
|
||||
int caps;
|
||||
int basedef;
|
||||
int carrierdef;
|
||||
|
||||
int code; /* ghost code */
|
||||
int team; /* team */
|
||||
int score; /* frags at time of disconnect */
|
||||
edict_t *ent;
|
||||
} ghost_t;
|
||||
|
||||
extern cvar_t *ctf;
|
||||
|
||||
#define CTF_TEAM1_SKIN "ctf_r"
|
||||
#define CTF_TEAM2_SKIN "ctf_b"
|
||||
|
||||
#define DF_CTF_FORCEJOIN 131072
|
||||
#define DF_ARMOR_PROTECT 262144
|
||||
#define DF_CTF_NO_TECH 524288
|
||||
|
||||
#define CTF_CAPTURE_BONUS 15 /* what you get for capture */
|
||||
#define CTF_TEAM_BONUS 10 /* what your team gets for capture */
|
||||
#define CTF_RECOVERY_BONUS 1 /* what you get for recovery */
|
||||
#define CTF_FLAG_BONUS 0 /* what you get for picking up enemy flag */
|
||||
#define CTF_FRAG_CARRIER_BONUS 2 /* what you get for fragging enemy flag carrier */
|
||||
#define CTF_FLAG_RETURN_TIME 40 /* seconds until auto return */
|
||||
|
||||
#define CTF_CARRIER_DANGER_PROTECT_BONUS 2 /* bonus for fraggin someone who has recently hurt your flag carrier */
|
||||
#define CTF_CARRIER_PROTECT_BONUS 1 /* bonus for fraggin someone while either you or your target are near your flag carrier */
|
||||
#define CTF_FLAG_DEFENSE_BONUS 1 /* bonus for fraggin someone while either you or your target are near your flag */
|
||||
#define CTF_RETURN_FLAG_ASSIST_BONUS 1 /* awarded for returning a flag that causes a capture to happen almost immediately */
|
||||
#define CTF_FRAG_CARRIER_ASSIST_BONUS 2 /* award for fragging a flag carrier if a capture happens almost immediately */
|
||||
|
||||
#define CTF_TARGET_PROTECT_RADIUS 400 /* the radius around an object being defended where a target will be worth extra frags */
|
||||
#define CTF_ATTACKER_PROTECT_RADIUS 400 /* the radius around an object being defended where an attacker will get extra frags when making kills */
|
||||
|
||||
#define CTF_CARRIER_DANGER_PROTECT_TIMEOUT 8
|
||||
#define CTF_FRAG_CARRIER_ASSIST_TIMEOUT 10
|
||||
#define CTF_RETURN_FLAG_ASSIST_TIMEOUT 10
|
||||
|
||||
#define CTF_AUTO_FLAG_RETURN_TIMEOUT 30 /* number of seconds before dropped flag auto-returns */
|
||||
|
||||
#define CTF_TECH_TIMEOUT 60 /* seconds before techs spawn again */
|
||||
|
||||
#define CTF_GRAPPLE_SPEED 650 /* speed of grapple in flight */
|
||||
#define CTF_GRAPPLE_PULL_SPEED 650 /* speed player is pulled at */
|
||||
|
||||
void CTFInit(void);
|
||||
void CTFSpawn(void);
|
||||
void CTFPrecache(void);
|
||||
|
||||
void SP_info_player_team1(edict_t *self);
|
||||
void SP_info_player_team2(edict_t *self);
|
||||
|
||||
char *CTFTeamName(int team);
|
||||
char *CTFOtherTeamName(int team);
|
||||
void CTFAssignSkin(edict_t *ent, char *s);
|
||||
void CTFAssignTeam(gclient_t *who);
|
||||
edict_t *SelectCTFSpawnPoint(edict_t *ent);
|
||||
qboolean CTFPickup_Flag(edict_t *ent, edict_t *other);
|
||||
void CTFDrop_Flag(edict_t *ent, gitem_t *item);
|
||||
void CTFEffects(edict_t *player);
|
||||
void CTFCalcScores(void);
|
||||
void SetCTFStats(edict_t *ent);
|
||||
void CTFDeadDropFlag(edict_t *self);
|
||||
void CTFScoreboardMessage(edict_t *ent, edict_t *killer);
|
||||
void CTFTeam_f(edict_t *ent);
|
||||
void CTFID_f(edict_t *ent);
|
||||
void CTFSay_Team(edict_t *who, char *msg);
|
||||
void CTFFlagSetup(edict_t *ent);
|
||||
void CTFResetFlag(int ctf_team);
|
||||
void CTFFragBonuses(edict_t *targ, edict_t *inflictor, edict_t *attacker);
|
||||
void CTFCheckHurtCarrier(edict_t *targ, edict_t *attacker);
|
||||
|
||||
/* GRAPPLE */
|
||||
void CTFWeapon_Grapple(edict_t *ent);
|
||||
void CTFPlayerResetGrapple(edict_t *ent);
|
||||
void CTFGrapplePull(edict_t *self);
|
||||
void CTFResetGrapple(edict_t *self);
|
||||
|
||||
/* TECH */
|
||||
gitem_t *CTFWhat_Tech(edict_t *ent);
|
||||
qboolean CTFPickup_Tech(edict_t *ent, edict_t *other);
|
||||
void CTFDrop_Tech(edict_t *ent, gitem_t *item);
|
||||
void CTFDeadDropTech(edict_t *ent);
|
||||
void CTFSetupTechSpawn(void);
|
||||
int CTFApplyResistance(edict_t *ent, int dmg);
|
||||
int CTFApplyStrength(edict_t *ent, int dmg);
|
||||
qboolean CTFApplyStrengthSound(edict_t *ent);
|
||||
qboolean CTFApplyHaste(edict_t *ent);
|
||||
void CTFApplyHasteSound(edict_t *ent);
|
||||
void CTFApplyRegeneration(edict_t *ent);
|
||||
qboolean CTFHasRegeneration(edict_t *ent);
|
||||
void CTFRespawnTech(edict_t *ent);
|
||||
void CTFResetTech(void);
|
||||
|
||||
void CTFOpenJoinMenu(edict_t *ent);
|
||||
qboolean CTFStartClient(edict_t *ent);
|
||||
void CTFVoteYes(edict_t *ent);
|
||||
void CTFVoteNo(edict_t *ent);
|
||||
void CTFReady(edict_t *ent);
|
||||
void CTFNotReady(edict_t *ent);
|
||||
qboolean CTFNextMap(void);
|
||||
qboolean CTFMatchSetup(void);
|
||||
qboolean CTFMatchOn(void);
|
||||
void CTFGhost(edict_t *ent);
|
||||
void CTFAdmin(edict_t *ent);
|
||||
qboolean CTFInMatch(void);
|
||||
void CTFStats(edict_t *ent);
|
||||
void CTFWarp(edict_t *ent);
|
||||
void CTFBoot(edict_t *ent);
|
||||
void CTFPlayerList(edict_t *ent);
|
||||
|
||||
qboolean CTFCheckRules(void);
|
||||
|
||||
void SP_misc_ctf_banner(edict_t *ent);
|
||||
void SP_misc_ctf_small_banner(edict_t *ent);
|
||||
|
||||
extern char *ctf_statusbar;
|
||||
|
||||
void UpdateChaseCam(edict_t *ent);
|
||||
void ChaseNext(edict_t *ent);
|
||||
void ChasePrev(edict_t *ent);
|
||||
|
||||
void CTFObserver(edict_t *ent);
|
||||
|
||||
void SP_trigger_teleport(edict_t *ent);
|
||||
void SP_info_teleport_destination(edict_t *ent);
|
||||
|
||||
void CTFSetPowerUpEffect(edict_t *ent, int def);
|
||||
|
||||
#endif /* G_CTF_H */
|
||||
#endif /* CTF */
|
||||
|
|
@ -822,7 +822,6 @@ Drop_Ammo(edict_t *ent, gitem_t *item)
|
|||
dropped->count = ent->client->pers.inventory[index];
|
||||
}
|
||||
|
||||
#ifndef CTF
|
||||
if (ent->client->pers.weapon &&
|
||||
(ent->client->pers.weapon->tag == AMMO_GRENADES) &&
|
||||
(item->tag == AMMO_GRENADES) &&
|
||||
|
@ -832,7 +831,6 @@ Drop_Ammo(edict_t *ent, gitem_t *item)
|
|||
G_FreeEdict(dropped);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ent->client->pers.inventory[index] -= dropped->count;
|
||||
ValidateSelectedItem(ent);
|
||||
|
@ -1857,33 +1855,6 @@ gitem_t itemlist[] = {
|
|||
"misc/power2.wav misc/power1.wav"
|
||||
},
|
||||
|
||||
#ifdef CTF
|
||||
/*
|
||||
* weapon_grapple (.3 .3 1) (-16 -16 -16) (16 16 16)
|
||||
* always owned, never in the world
|
||||
*/
|
||||
{
|
||||
"weapon_grapple",
|
||||
NULL,
|
||||
Use_Weapon,
|
||||
NULL,
|
||||
CTFWeapon_Grapple,
|
||||
"misc/w_pkup.wav",
|
||||
NULL, 0,
|
||||
"models/weapons/grapple/tris.md2",
|
||||
"w_grapple",
|
||||
"Grapple",
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
IT_WEAPON,
|
||||
WEAP_GRAPPLE,
|
||||
NULL,
|
||||
0,
|
||||
"weapons/grapple/grfire.wav weapons/grapple/grpull.wav weapons/grapple/grhang.wav weapons/grapple/grreset.wav weapons/grapple/grhit.wav"
|
||||
},
|
||||
#endif
|
||||
|
||||
/* weapon_blaster (.3 .3 1) (-16 -16 -16) (16 16 16)
|
||||
always owned, never in the world */
|
||||
{
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
* =======================================================================
|
||||
*/
|
||||
|
||||
#ifndef G_LOCAL_H
|
||||
#define G_LOCAL_H
|
||||
|
||||
#include "q_shared.h"
|
||||
|
||||
/* define GAME_INCLUDE so that game.h does not define the
|
||||
|
@ -309,10 +306,6 @@ typedef struct
|
|||
char mapname[MAX_QPATH]; /* the server name (base1, etc) */
|
||||
char nextmap[MAX_QPATH]; /* go here when fraglimit is hit */
|
||||
|
||||
#ifdef CTF
|
||||
char forcemap[MAX_QPATH]; /* go here */
|
||||
#endif
|
||||
|
||||
/* intermission state */
|
||||
float intermissiontime; /* time the intermission was started */
|
||||
char *changemap;
|
||||
|
@ -494,9 +487,6 @@ extern int snd_fry;
|
|||
#define MOD_TRIGGER_HURT 31
|
||||
#define MOD_HIT 32
|
||||
#define MOD_TARGET_BLASTER 33
|
||||
#ifdef CTF
|
||||
#define MOD_GRAPPLE 34
|
||||
#endif
|
||||
#define MOD_FRIENDLY_FIRE 0x8000000
|
||||
|
||||
extern int meansOfDeath;
|
||||
|
@ -599,9 +589,6 @@ extern field_t fields[];
|
|||
extern gitem_t itemlist[];
|
||||
|
||||
/* g_cmds.c */
|
||||
#ifdef CTF
|
||||
qboolean CheckFlood(edict_t *ent);
|
||||
#endif
|
||||
void Cmd_Help_f(edict_t *ent);
|
||||
void Cmd_Score_f(edict_t *ent);
|
||||
|
||||
|
@ -653,9 +640,6 @@ void vectoangles(vec3_t vec, vec3_t angles);
|
|||
/* g_combat.c */
|
||||
qboolean OnSameTeam(edict_t *ent1, edict_t *ent2);
|
||||
qboolean CanDamage(edict_t *targ, edict_t *inflictor);
|
||||
#ifdef CTF
|
||||
qboolean CheckTeamDamage (edict_t *targ, edict_t *attacker);
|
||||
#endif
|
||||
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);
|
||||
|
@ -765,9 +749,6 @@ void InitClientPersistant(gclient_t *client);
|
|||
void InitClientResp(gclient_t *client);
|
||||
void InitBodyQue(void);
|
||||
void ClientBeginServerFrame(edict_t *ent);
|
||||
#ifdef CTF
|
||||
void ClientUserinfoChanged (edict_t *ent, char *userinfo);
|
||||
#endif
|
||||
|
||||
/* g_player.c */
|
||||
void player_pain(edict_t *self, edict_t *other, float kick, int damage);
|
||||
|
@ -791,13 +772,6 @@ void DeathmatchScoreboardMessage(edict_t *client, edict_t *killer);
|
|||
|
||||
/* g_pweapon.c */
|
||||
void PlayerNoise(edict_t *who, vec3_t where, int type);
|
||||
#ifdef CTF
|
||||
void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance,
|
||||
vec3_t forward, vec3_t right, vec3_t result);
|
||||
void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST,
|
||||
int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST,
|
||||
int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent));
|
||||
#endif
|
||||
|
||||
/* m_move.c */
|
||||
qboolean M_CheckBottom(edict_t *ent);
|
||||
|
@ -811,9 +785,6 @@ void G_RunEntity(edict_t *ent);
|
|||
/* g_main.c */
|
||||
void SaveClientData(void);
|
||||
void FetchClientEntData(edict_t *ent);
|
||||
#ifdef CTF
|
||||
void EndDMLevel (void);
|
||||
#endif
|
||||
|
||||
/* g_chase.c */
|
||||
void UpdateChaseCam(edict_t *ent);
|
||||
|
@ -992,6 +963,8 @@ struct gclient_s
|
|||
float ctf_regentime; /* regen tech */
|
||||
float ctf_techsndtime;
|
||||
float ctf_lasttechmsg;
|
||||
edict_t *chase_target;
|
||||
qboolean update_chase;
|
||||
float menutime; /* time to update menu */
|
||||
qboolean menudirty;
|
||||
#endif
|
||||
|
@ -1151,5 +1124,3 @@ struct edict_s
|
|||
#include "g_ctf.h"
|
||||
#endif
|
||||
|
||||
#endif /* G_LOCAL_H */
|
||||
|
||||
|
|
|
@ -234,14 +234,6 @@ EndDMLevel(void)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef CTF
|
||||
if (*level.forcemap)
|
||||
{
|
||||
BeginIntermission(CreateTargetChangeLevel(level.forcemap));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* see if it's in the map list */
|
||||
if (*sv_maplist->string)
|
||||
{
|
||||
|
@ -401,31 +393,13 @@ ExitLevel(void)
|
|||
edict_t *ent;
|
||||
char command[256];
|
||||
|
||||
#ifndef CTF
|
||||
Com_sprintf(command, sizeof(command), "gamemap \"%s\"\n", level.changemap);
|
||||
gi.AddCommandString(command);
|
||||
level.changemap = NULL;
|
||||
#endif
|
||||
|
||||
level.exitintermission = 0;
|
||||
level.intermissiontime = 0;
|
||||
|
||||
#ifdef CTF
|
||||
if (CTFNextMap())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Com_sprintf(command, sizeof(command), "gamemap \"%s\"\n", level.changemap);
|
||||
gi.AddCommandString(command);
|
||||
#endif
|
||||
|
||||
ClientEndServerFrames();
|
||||
|
||||
#ifdef CTF
|
||||
level.changemap = NULL;
|
||||
#endif
|
||||
|
||||
/* clear some things before going to next level */
|
||||
for (i = 0; i < maxclients->value; i++)
|
||||
{
|
||||
|
|
|
@ -526,9 +526,7 @@ path_corner_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */,
|
|||
v[2] -= other->mins[2];
|
||||
VectorCopy(v, other->s.origin);
|
||||
next = G_PickTarget(next->target);
|
||||
#ifndef CTF
|
||||
other->s.event = EV_OTHER_TELEPORT;
|
||||
#endif
|
||||
}
|
||||
|
||||
other->goalentity = other->movetarget = next;
|
||||
|
@ -699,19 +697,6 @@ TH_viewthing(edict_t *ent)
|
|||
|
||||
ent->s.frame = (ent->s.frame + 1) % 7;
|
||||
ent->nextthink = level.time + FRAMETIME;
|
||||
|
||||
#ifdef CTF
|
||||
static int robotron[4];
|
||||
|
||||
if (ent->spawnflags)
|
||||
{
|
||||
if (ent->s.frame == 0)
|
||||
{
|
||||
ent->spawnflags = (ent->spawnflags + 1) % 4 + 1;
|
||||
ent->s.modelindex = robotron[ent->spawnflags - 1];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2515,10 +2500,8 @@ func_clock_think(edict_t *self)
|
|||
|
||||
if (!(self->spawnflags & 8))
|
||||
{
|
||||
#ifndef CTF
|
||||
self->think = G_FreeEdict;
|
||||
self->nextthink = level.time + 1;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,12 +76,10 @@ SV_TestEntityPosition(edict_t *ent)
|
|||
|
||||
if (trace.startsolid)
|
||||
{
|
||||
#ifndef CTF
|
||||
if ((ent->svflags & SVF_DEADMONSTER) && (trace.ent->client || (trace.ent->svflags & SVF_MONSTER)))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return g_edicts;
|
||||
}
|
||||
|
@ -528,13 +526,11 @@ retry:
|
|||
|
||||
trace = gi.trace(start, ent->mins, ent->maxs, end, ent, mask);
|
||||
|
||||
#ifndef CTF
|
||||
if (trace.startsolid || trace.allsolid)
|
||||
{
|
||||
mask ^= CONTENTS_DEADMONSTER;
|
||||
trace = gi.trace (start, ent->mins, ent->maxs, end, ent, mask);
|
||||
}
|
||||
#endif
|
||||
|
||||
VectorCopy(trace.endpos, ent->s.origin);
|
||||
gi.linkentity(ent);
|
||||
|
|
|
@ -207,9 +207,7 @@ spawn_t spawns[] = {
|
|||
{"target_crosslevel_target", SP_target_crosslevel_target},
|
||||
{"target_laser", SP_target_laser},
|
||||
{"target_help", SP_target_help},
|
||||
#ifndef CTF
|
||||
{"target_actor", SP_target_actor},
|
||||
#endif
|
||||
{"target_lightramp", SP_target_lightramp},
|
||||
{"target_earthquake", SP_target_earthquake},
|
||||
{"target_character", SP_target_character},
|
||||
|
@ -234,15 +232,11 @@ spawn_t spawns[] = {
|
|||
{"misc_ctf_small_banner", SP_misc_ctf_small_banner},
|
||||
#endif
|
||||
{"misc_satellite_dish", SP_misc_satellite_dish},
|
||||
#ifndef CTF
|
||||
{"misc_actor", SP_misc_actor},
|
||||
#endif
|
||||
{"misc_gib_arm", SP_misc_gib_arm},
|
||||
{"misc_gib_leg", SP_misc_gib_leg},
|
||||
{"misc_gib_head", SP_misc_gib_head},
|
||||
#ifndef CTF
|
||||
{"misc_insane", SP_misc_insane},
|
||||
#endif
|
||||
{"misc_deadsoldier", SP_misc_deadsoldier},
|
||||
{"misc_viper", SP_misc_viper},
|
||||
{"misc_viper_bomb", SP_misc_viper_bomb},
|
||||
|
@ -1026,7 +1020,6 @@ SP_worldspawn(edict_t *ent)
|
|||
gi.modelindex("#w_hyperblaster.md2");
|
||||
gi.modelindex("#w_railgun.md2");
|
||||
gi.modelindex("#w_bfg.md2");
|
||||
gi.modelindex("#w_grapple.md2");
|
||||
|
||||
/* ------------------- */
|
||||
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
*/
|
||||
|
||||
#ifndef GAME_H
|
||||
#define GAME_H
|
||||
|
||||
#define GAME_API_VERSION 3
|
||||
|
||||
#define SVF_NOCLIENT 0x00000001 /* don't send entity to clients, even if it has effects */
|
||||
|
@ -245,5 +242,3 @@ typedef struct
|
|||
|
||||
game_export_t *GetGameApi(game_import_t *import);
|
||||
|
||||
#endif /* GAME_H */
|
||||
|
||||
|
|
|
@ -1,415 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, 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
|
||||
* 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.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* The CTF menu.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#ifdef CTF
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
/*
|
||||
* Note that the pmenu entries are duplicated
|
||||
* this is so that a static set of pmenu entries
|
||||
* can be used for multiple clients and changed
|
||||
* without interference. Note that arg will be
|
||||
* freed when the menu is closed, it must be
|
||||
* allocated memory.
|
||||
*/
|
||||
pmenuhnd_t *
|
||||
PMenu_Open(edict_t *ent, pmenu_t *entries, int cur, int num, void *arg)
|
||||
{
|
||||
pmenuhnd_t *hnd;
|
||||
pmenu_t *p;
|
||||
int i;
|
||||
|
||||
if (!ent || !entries || !arg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ent->client)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ent->client->menu)
|
||||
{
|
||||
gi.dprintf("warning, ent already has a menu\n");
|
||||
PMenu_Close(ent);
|
||||
}
|
||||
|
||||
hnd = malloc(sizeof(*hnd));
|
||||
|
||||
hnd->arg = arg;
|
||||
hnd->entries = malloc(sizeof(pmenu_t) * num);
|
||||
memcpy(hnd->entries, entries, sizeof(pmenu_t) * num);
|
||||
|
||||
/* duplicate the strings since they may be from static memory */
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
if (entries[i].text)
|
||||
{
|
||||
hnd->entries[i].text = strdup(entries[i].text);
|
||||
}
|
||||
}
|
||||
|
||||
hnd->num = num;
|
||||
|
||||
if ((cur < 0) || !entries[cur].SelectFunc)
|
||||
{
|
||||
for (i = 0, p = entries; i < num; i++, p++)
|
||||
{
|
||||
if (p->SelectFunc)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i = cur;
|
||||
}
|
||||
|
||||
if (i >= num)
|
||||
{
|
||||
hnd->cur = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hnd->cur = i;
|
||||
}
|
||||
|
||||
ent->client->showscores = true;
|
||||
ent->client->inmenu = true;
|
||||
ent->client->menu = hnd;
|
||||
|
||||
PMenu_Do_Update(ent);
|
||||
gi.unicast(ent, true);
|
||||
|
||||
return hnd;
|
||||
}
|
||||
|
||||
void
|
||||
PMenu_Close(edict_t *ent)
|
||||
{
|
||||
int i;
|
||||
pmenuhnd_t *hnd;
|
||||
|
||||
if (!ent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hnd = ent->client->menu;
|
||||
|
||||
for (i = 0; i < hnd->num; i++)
|
||||
{
|
||||
if (hnd->entries[i].text)
|
||||
{
|
||||
free(hnd->entries[i].text);
|
||||
}
|
||||
}
|
||||
|
||||
free(hnd->entries);
|
||||
|
||||
if (hnd->arg)
|
||||
{
|
||||
free(hnd->arg);
|
||||
}
|
||||
|
||||
free(hnd);
|
||||
ent->client->menu = NULL;
|
||||
ent->client->showscores = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* only use on pmenu's that have
|
||||
* been called with PMenu_Open
|
||||
* */
|
||||
void
|
||||
PMenu_UpdateEntry(pmenu_t *entry, const char *text,
|
||||
int align, SelectFunc_t SelectFunc)
|
||||
{
|
||||
if (!entry || !text)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry->text)
|
||||
{
|
||||
free(entry->text);
|
||||
}
|
||||
|
||||
entry->text = strdup(text);
|
||||
entry->align = align;
|
||||
entry->SelectFunc = SelectFunc;
|
||||
}
|
||||
|
||||
void
|
||||
PMenu_Do_Update(edict_t *ent)
|
||||
{
|
||||
char string[1400];
|
||||
int i;
|
||||
pmenu_t *p;
|
||||
int x;
|
||||
pmenuhnd_t *hnd;
|
||||
char *t;
|
||||
qboolean alt = false;
|
||||
|
||||
if (!ent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
gi.dprintf("warning: ent has no menu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hnd = ent->client->menu;
|
||||
|
||||
strcpy(string, "xv 32 yv 8 picn inventory ");
|
||||
|
||||
for (i = 0, p = hnd->entries; i < hnd->num; i++, p++)
|
||||
{
|
||||
if (!p->text || !*(p->text))
|
||||
{
|
||||
continue; /* blank line */
|
||||
}
|
||||
|
||||
t = p->text;
|
||||
|
||||
if (*t == '*')
|
||||
{
|
||||
alt = true;
|
||||
t++;
|
||||
}
|
||||
|
||||
sprintf(string + strlen(string), "yv %d ", 32 + i * 8);
|
||||
|
||||
if (p->align == PMENU_ALIGN_CENTER)
|
||||
{
|
||||
x = 196 / 2 - strlen(t) * 4 + 64;
|
||||
}
|
||||
else if (p->align == PMENU_ALIGN_RIGHT)
|
||||
{
|
||||
x = 64 + (196 - strlen(t) * 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 64;
|
||||
}
|
||||
|
||||
sprintf(string + strlen(string), "xv %d ",
|
||||
x - ((hnd->cur == i) ? 8 : 0));
|
||||
|
||||
if (hnd->cur == i)
|
||||
{
|
||||
sprintf(string + strlen(string), "string2 \"\x0d%s\" ", t);
|
||||
}
|
||||
else if (alt)
|
||||
{
|
||||
sprintf(string + strlen(string), "string2 \"%s\" ", t);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(string + strlen(string), "string \"%s\" ", t);
|
||||
}
|
||||
|
||||
alt = false;
|
||||
}
|
||||
|
||||
gi.WriteByte(svc_layout);
|
||||
gi.WriteString(string);
|
||||
}
|
||||
|
||||
void
|
||||
PMenu_Update(edict_t *ent)
|
||||
{
|
||||
if (!ent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
gi.dprintf("warning: ent has no menu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (level.time - ent->client->menutime >= 1.0)
|
||||
{
|
||||
/* been a second or more since
|
||||
last update, update now */
|
||||
PMenu_Do_Update(ent);
|
||||
gi.unicast(ent, true);
|
||||
ent->client->menutime = level.time;
|
||||
ent->client->menudirty = false;
|
||||
}
|
||||
|
||||
ent->client->menutime = level.time + 0.2;
|
||||
ent->client->menudirty = true;
|
||||
}
|
||||
|
||||
void
|
||||
PMenu_Next(edict_t *ent)
|
||||
{
|
||||
pmenuhnd_t *hnd;
|
||||
int i;
|
||||
pmenu_t *p;
|
||||
|
||||
if (!ent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
gi.dprintf("warning: ent has no menu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hnd = ent->client->menu;
|
||||
|
||||
if (hnd->cur < 0)
|
||||
{
|
||||
return; /* no selectable entries */
|
||||
}
|
||||
|
||||
i = hnd->cur;
|
||||
p = hnd->entries + hnd->cur;
|
||||
|
||||
do
|
||||
{
|
||||
i++, p++;
|
||||
|
||||
if (i == hnd->num)
|
||||
{
|
||||
i = 0, p = hnd->entries;
|
||||
}
|
||||
|
||||
if (p->SelectFunc)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (i != hnd->cur);
|
||||
|
||||
hnd->cur = i;
|
||||
|
||||
PMenu_Update(ent);
|
||||
}
|
||||
|
||||
void
|
||||
PMenu_Prev(edict_t *ent)
|
||||
{
|
||||
pmenuhnd_t *hnd;
|
||||
int i;
|
||||
pmenu_t *p;
|
||||
|
||||
if (!ent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
gi.dprintf("warning: ent has no menu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hnd = ent->client->menu;
|
||||
|
||||
if (hnd->cur < 0)
|
||||
{
|
||||
return; /* no selectable entries */
|
||||
}
|
||||
|
||||
i = hnd->cur;
|
||||
p = hnd->entries + hnd->cur;
|
||||
|
||||
do
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
i = hnd->num - 1;
|
||||
p = hnd->entries + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
i--, p--;
|
||||
}
|
||||
|
||||
if (p->SelectFunc)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (i != hnd->cur);
|
||||
|
||||
hnd->cur = i;
|
||||
|
||||
PMenu_Update(ent);
|
||||
}
|
||||
|
||||
void
|
||||
PMenu_Select(edict_t *ent)
|
||||
{
|
||||
pmenuhnd_t *hnd;
|
||||
pmenu_t *p;
|
||||
|
||||
if (!ent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ent->client->menu)
|
||||
{
|
||||
gi.dprintf("warning: ent has no menu\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hnd = ent->client->menu;
|
||||
|
||||
if (hnd->cur < 0)
|
||||
{
|
||||
return; /* no selectable entries */
|
||||
}
|
||||
|
||||
p = hnd->entries + hnd->cur;
|
||||
|
||||
if (p->SelectFunc)
|
||||
{
|
||||
p->SelectFunc(ent, hnd);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CTF */
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, 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
|
||||
* 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.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* Header file for the CTF menu.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#ifdef CTF
|
||||
|
||||
#ifndef P_MENU_H
|
||||
#define P_MENU_H
|
||||
|
||||
enum
|
||||
{
|
||||
PMENU_ALIGN_LEFT,
|
||||
PMENU_ALIGN_CENTER,
|
||||
PMENU_ALIGN_RIGHT
|
||||
};
|
||||
|
||||
typedef struct pmenuhnd_s
|
||||
{
|
||||
struct pmenu_s *entries;
|
||||
int cur;
|
||||
int num;
|
||||
void *arg;
|
||||
} pmenuhnd_t;
|
||||
|
||||
typedef void (*SelectFunc_t)(edict_t *ent, pmenuhnd_t *hnd);
|
||||
|
||||
typedef struct pmenu_s
|
||||
{
|
||||
char *text;
|
||||
int align;
|
||||
SelectFunc_t SelectFunc;
|
||||
} pmenu_t;
|
||||
|
||||
pmenuhnd_t *PMenu_Open(edict_t *ent, pmenu_t *entries, int cur,
|
||||
int num, void *arg);
|
||||
void PMenu_Close(edict_t *ent);
|
||||
void PMenu_UpdateEntry(pmenu_t *entry, const char *text, int align,
|
||||
SelectFunc_t SelectFunc);
|
||||
void PMenu_Do_Update(edict_t *ent);
|
||||
void PMenu_Update(edict_t *ent);
|
||||
void PMenu_Next(edict_t *ent);
|
||||
void PMenu_Prev(edict_t *ent);
|
||||
void PMenu_Select(edict_t *ent);
|
||||
|
||||
#endif /* P_MENU_H */
|
||||
#endif /* CTF */
|
||||
|
|
@ -25,9 +25,6 @@
|
|||
* =======================================================================
|
||||
*/
|
||||
|
||||
#ifndef QSHARED_H
|
||||
#define QSHARED_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
@ -1080,5 +1077,3 @@ extern int vidref_val;
|
|||
size_t verify_fread(void *, size_t, size_t, FILE *);
|
||||
size_t verify_fwrite(void *, size_t, size_t, FILE *);
|
||||
|
||||
#endif /* QSHARED_H */
|
||||
|
||||
|
|
|
@ -602,9 +602,7 @@ extern void berserk_fidget ( edict_t * self ) ;
|
|||
extern void berserk_stand ( edict_t * self ) ;
|
||||
extern void berserk_search ( edict_t * self ) ;
|
||||
extern void berserk_sight ( edict_t * self , edict_t * other ) ;
|
||||
#ifndef CTF
|
||||
extern void SP_target_actor ( edict_t * self ) ;
|
||||
#endif
|
||||
extern void target_actor_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ;
|
||||
extern void SP_misc_actor ( edict_t * self ) ;
|
||||
extern void actor_use ( edict_t * self , edict_t * other , edict_t * activator ) ;
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
* =======================================================================
|
||||
*/
|
||||
|
||||
#ifndef CTF
|
||||
|
||||
{"ReadLevel", (byte *)ReadLevel},
|
||||
{"ReadLevelLocals", (byte *)ReadLevelLocals},
|
||||
{"ReadEdict", (byte *)ReadEdict},
|
||||
|
@ -1055,8 +1053,4 @@
|
|||
{"ai_stand", (byte *)ai_stand},
|
||||
{"ai_move", (byte *)ai_move},
|
||||
{"AI_SetSightClient", (byte *)AI_SetSightClient},
|
||||
|
||||
#endif /* CTF */
|
||||
|
||||
{0, 0}
|
||||
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
* =======================================================================
|
||||
*/
|
||||
|
||||
#ifndef CTF
|
||||
|
||||
{"tank_move_death", &tank_move_death},
|
||||
{"tank_move_attack_chain", &tank_move_attack_chain},
|
||||
{"tank_move_attack_post_rocket", &tank_move_attack_post_rocket},
|
||||
|
@ -313,7 +311,4 @@
|
|||
{"actor_move_run", &actor_move_run},
|
||||
{"actor_move_walk", &actor_move_walk},
|
||||
{"actor_move_stand", &actor_move_stand},
|
||||
|
||||
#endif /* CTF */
|
||||
|
||||
{0, 0}
|
||||
|
|
1086
src/game/ctf/g_ai.c
1086
src/game/ctf/g_ai.c
File diff suppressed because it is too large
Load diff
|
@ -1,26 +1,26 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, 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 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.
|
||||
*
|
||||
*/
|
||||
Copyright (C) 1997-2001 Id Software, 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 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.
|
||||
|
||||
*/
|
||||
#include "g_local.h"
|
||||
|
||||
void
|
||||
UpdateChaseCam(edict_t *ent)
|
||||
|
||||
void UpdateChaseCam(edict_t *ent)
|
||||
{
|
||||
vec3_t o, ownerv, goal;
|
||||
edict_t *targ;
|
||||
|
@ -30,9 +30,8 @@ UpdateChaseCam(edict_t *ent)
|
|||
vec3_t oldgoal;
|
||||
vec3_t angles;
|
||||
|
||||
/* is our chase target gone? */
|
||||
if (!ent->client->chase_target->inuse)
|
||||
{
|
||||
// is our chase target gone?
|
||||
if (!ent->client->chase_target->inuse) {
|
||||
ent->client->chase_target = NULL;
|
||||
return;
|
||||
}
|
||||
|
@ -45,26 +44,18 @@ UpdateChaseCam(edict_t *ent)
|
|||
ownerv[2] += targ->viewheight;
|
||||
|
||||
VectorCopy(targ->client->v_angle, angles);
|
||||
|
||||
if (angles[PITCH] > 56)
|
||||
{
|
||||
angles[PITCH] = 56;
|
||||
}
|
||||
|
||||
AngleVectors(angles, forward, right, NULL);
|
||||
AngleVectors (angles, forward, right, NULL);
|
||||
VectorNormalize(forward);
|
||||
VectorMA(ownerv, -30, forward, o);
|
||||
|
||||
if (o[2] < targ->s.origin[2] + 20)
|
||||
{
|
||||
o[2] = targ->s.origin[2] + 20;
|
||||
}
|
||||
|
||||
/* jump animation lifts */
|
||||
// jump animation lifts
|
||||
if (!targ->groundentity)
|
||||
{
|
||||
o[2] += 16;
|
||||
}
|
||||
|
||||
trace = gi.trace(ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
|
||||
|
||||
|
@ -72,13 +63,11 @@ UpdateChaseCam(edict_t *ent)
|
|||
|
||||
VectorMA(goal, 2, forward, goal);
|
||||
|
||||
/* pad for floors and ceilings */
|
||||
// pad for floors and ceilings
|
||||
VectorCopy(goal, o);
|
||||
o[2] += 6;
|
||||
trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
|
||||
|
||||
if (trace.fraction < 1)
|
||||
{
|
||||
if (trace.fraction < 1) {
|
||||
VectorCopy(trace.endpos, goal);
|
||||
goal[2] -= 6;
|
||||
}
|
||||
|
@ -86,9 +75,7 @@ UpdateChaseCam(edict_t *ent)
|
|||
VectorCopy(goal, o);
|
||||
o[2] -= 6;
|
||||
trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
|
||||
|
||||
if (trace.fraction < 1)
|
||||
{
|
||||
if (trace.fraction < 1) {
|
||||
VectorCopy(trace.endpos, goal);
|
||||
goal[2] += 6;
|
||||
}
|
||||
|
@ -96,12 +83,8 @@ UpdateChaseCam(edict_t *ent)
|
|||
ent->client->ps.pmove.pm_type = PM_FREEZE;
|
||||
|
||||
VectorCopy(goal, ent->s.origin);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(
|
||||
targ->client->v_angle[i] - ent->client->resp.cmd_angles[i]);
|
||||
}
|
||||
for (i=0 ; i<3 ; i++)
|
||||
ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(targ->client->v_angle[i] - ent->client->resp.cmd_angles[i]);
|
||||
|
||||
VectorCopy(targ->client->v_angle, ent->client->ps.viewangles);
|
||||
VectorCopy(targ->client->v_angle, ent->client->v_angle);
|
||||
|
@ -111,95 +94,63 @@ UpdateChaseCam(edict_t *ent)
|
|||
gi.linkentity(ent);
|
||||
|
||||
if ((!ent->client->showscores && !ent->client->menu &&
|
||||
!ent->client->showinventory && !ent->client->showhelp &&
|
||||
!(level.framenum & 31)) || ent->client->update_chase)
|
||||
{
|
||||
!ent->client->showinventory && !ent->client->showhelp &&
|
||||
!(level.framenum & 31)) || ent->client->update_chase) {
|
||||
char s[1024];
|
||||
|
||||
ent->client->update_chase = false;
|
||||
sprintf(s, "xv 0 yb -68 string2 \"Chasing %s\"",
|
||||
targ->client->pers.netname);
|
||||
gi.WriteByte(svc_layout);
|
||||
gi.WriteString(s);
|
||||
targ->client->pers.netname);
|
||||
gi.WriteByte (svc_layout);
|
||||
gi.WriteString (s);
|
||||
gi.unicast(ent, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ChaseNext(edict_t *ent)
|
||||
void ChaseNext(edict_t *ent)
|
||||
{
|
||||
int i;
|
||||
edict_t *e;
|
||||
|
||||
if (!ent->client->chase_target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
i = ent->client->chase_target - g_edicts;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
i++;
|
||||
|
||||
if (i > maxclients->value)
|
||||
{
|
||||
i = 1;
|
||||
}
|
||||
|
||||
e = g_edicts + i;
|
||||
|
||||
if (!e->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e->solid != SOLID_NOT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (e != ent->client->chase_target);
|
||||
} while (e != ent->client->chase_target);
|
||||
|
||||
ent->client->chase_target = e;
|
||||
ent->client->update_chase = true;
|
||||
}
|
||||
|
||||
void
|
||||
ChasePrev(edict_t *ent)
|
||||
void ChasePrev(edict_t *ent)
|
||||
{
|
||||
int i;
|
||||
edict_t *e;
|
||||
|
||||
if (!ent->client->chase_target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
i = ent->client->chase_target - g_edicts;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
i--;
|
||||
|
||||
if (i < 1)
|
||||
{
|
||||
i = maxclients->value;
|
||||
}
|
||||
|
||||
e = g_edicts + i;
|
||||
|
||||
if (!e->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e->solid != SOLID_NOT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (e != ent->client->chase_target);
|
||||
} while (e != ent->client->chase_target);
|
||||
|
||||
ent->client->chase_target = e;
|
||||
ent->client->update_chase = true;
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,114 +1,115 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, 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 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.
|
||||
*
|
||||
*/
|
||||
Copyright (C) 1997-2001 Id Software, 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 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.
|
||||
|
||||
*/
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
game_locals_t game;
|
||||
level_locals_t level;
|
||||
game_import_t gi;
|
||||
game_export_t globals;
|
||||
spawn_temp_t st;
|
||||
game_locals_t game;
|
||||
level_locals_t level;
|
||||
game_import_t gi;
|
||||
game_export_t globals;
|
||||
spawn_temp_t st;
|
||||
|
||||
int sm_meat_index;
|
||||
int snd_fry;
|
||||
int sm_meat_index;
|
||||
int snd_fry;
|
||||
int meansOfDeath;
|
||||
|
||||
edict_t *g_edicts;
|
||||
edict_t *g_edicts;
|
||||
|
||||
cvar_t *deathmatch;
|
||||
cvar_t *coop;
|
||||
cvar_t *dmflags;
|
||||
cvar_t *skill;
|
||||
cvar_t *fraglimit;
|
||||
cvar_t *timelimit;
|
||||
/* ZOID */
|
||||
cvar_t *capturelimit;
|
||||
cvar_t *instantweap;
|
||||
/* ZOID */
|
||||
cvar_t *password;
|
||||
cvar_t *maxclients;
|
||||
cvar_t *maxentities;
|
||||
cvar_t *g_select_empty;
|
||||
cvar_t *dedicated;
|
||||
cvar_t *deathmatch;
|
||||
cvar_t *coop;
|
||||
cvar_t *dmflags;
|
||||
cvar_t *skill;
|
||||
cvar_t *fraglimit;
|
||||
cvar_t *timelimit;
|
||||
//ZOID
|
||||
cvar_t *capturelimit;
|
||||
cvar_t *instantweap;
|
||||
//ZOID
|
||||
cvar_t *password;
|
||||
cvar_t *maxclients;
|
||||
cvar_t *maxentities;
|
||||
cvar_t *g_select_empty;
|
||||
cvar_t *dedicated;
|
||||
|
||||
cvar_t *filterban;
|
||||
cvar_t *filterban;
|
||||
|
||||
cvar_t *sv_maxvelocity;
|
||||
cvar_t *sv_gravity;
|
||||
cvar_t *sv_maxvelocity;
|
||||
cvar_t *sv_gravity;
|
||||
|
||||
cvar_t *sv_rollspeed;
|
||||
cvar_t *sv_rollangle;
|
||||
cvar_t *gun_x;
|
||||
cvar_t *gun_y;
|
||||
cvar_t *gun_z;
|
||||
cvar_t *sv_rollspeed;
|
||||
cvar_t *sv_rollangle;
|
||||
cvar_t *gun_x;
|
||||
cvar_t *gun_y;
|
||||
cvar_t *gun_z;
|
||||
|
||||
cvar_t *run_pitch;
|
||||
cvar_t *run_roll;
|
||||
cvar_t *bob_up;
|
||||
cvar_t *bob_pitch;
|
||||
cvar_t *bob_roll;
|
||||
cvar_t *run_pitch;
|
||||
cvar_t *run_roll;
|
||||
cvar_t *bob_up;
|
||||
cvar_t *bob_pitch;
|
||||
cvar_t *bob_roll;
|
||||
|
||||
cvar_t *sv_cheats;
|
||||
cvar_t *sv_cheats;
|
||||
|
||||
cvar_t *flood_msgs;
|
||||
cvar_t *flood_persecond;
|
||||
cvar_t *flood_waitdelay;
|
||||
cvar_t *flood_msgs;
|
||||
cvar_t *flood_persecond;
|
||||
cvar_t *flood_waitdelay;
|
||||
|
||||
cvar_t *sv_maplist;
|
||||
cvar_t *sv_maplist;
|
||||
|
||||
void SpawnEntities(char *mapname, char *entities, char *spawnpoint);
|
||||
void ClientThink(edict_t *ent, usercmd_t *cmd);
|
||||
qboolean ClientConnect(edict_t *ent, char *userinfo);
|
||||
void ClientUserinfoChanged(edict_t *ent, char *userinfo);
|
||||
void ClientDisconnect(edict_t *ent);
|
||||
void ClientBegin(edict_t *ent);
|
||||
void ClientCommand(edict_t *ent);
|
||||
void RunEntity(edict_t *ent);
|
||||
void WriteGame(char *filename, qboolean autosave);
|
||||
void ReadGame(char *filename);
|
||||
void WriteLevel(char *filename);
|
||||
void ReadLevel(char *filename);
|
||||
void InitGame(void);
|
||||
void G_RunFrame(void);
|
||||
void SpawnEntities (char *mapname, char *entities, char *spawnpoint);
|
||||
void ClientThink (edict_t *ent, usercmd_t *cmd);
|
||||
qboolean ClientConnect (edict_t *ent, char *userinfo);
|
||||
void ClientUserinfoChanged (edict_t *ent, char *userinfo);
|
||||
void ClientDisconnect (edict_t *ent);
|
||||
void ClientBegin (edict_t *ent);
|
||||
void ClientCommand (edict_t *ent);
|
||||
void RunEntity (edict_t *ent);
|
||||
void WriteGame (char *filename, qboolean autosave);
|
||||
void ReadGame (char *filename);
|
||||
void WriteLevel (char *filename);
|
||||
void ReadLevel (char *filename);
|
||||
void InitGame (void);
|
||||
void G_RunFrame (void);
|
||||
|
||||
/* =================================================================== */
|
||||
|
||||
void
|
||||
ShutdownGame(void)
|
||||
//===================================================================
|
||||
|
||||
|
||||
void ShutdownGame (void)
|
||||
{
|
||||
gi.dprintf("==== ShutdownGame ====\n");
|
||||
gi.dprintf ("==== ShutdownGame ====\n");
|
||||
|
||||
gi.FreeTags(TAG_LEVEL);
|
||||
gi.FreeTags(TAG_GAME);
|
||||
gi.FreeTags (TAG_LEVEL);
|
||||
gi.FreeTags (TAG_GAME);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* =================
|
||||
* GetGameAPI
|
||||
*
|
||||
* Returns a pointer to the structure with all entry points
|
||||
* and global variables
|
||||
* =================
|
||||
*/
|
||||
game_export_t *
|
||||
GetGameAPI(game_import_t *import)
|
||||
=================
|
||||
GetGameAPI
|
||||
|
||||
Returns a pointer to the structure with all entry points
|
||||
and global variables
|
||||
=================
|
||||
*/
|
||||
game_export_t *GetGameAPI (game_import_t *import)
|
||||
{
|
||||
gi = *import;
|
||||
|
||||
|
@ -139,76 +140,70 @@ GetGameAPI(game_import_t *import)
|
|||
}
|
||||
|
||||
#ifndef GAME_HARD_LINKED
|
||||
/* this is only here so the functions in q_shared.c and q_shwin.c can link */
|
||||
void
|
||||
Sys_Error(char *error, ...)
|
||||
// this is only here so the functions in q_shared.c and q_shwin.c can link
|
||||
void Sys_Error (char *error, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char text[1024];
|
||||
va_list argptr;
|
||||
char text[1024];
|
||||
|
||||
va_start(argptr, error);
|
||||
vsprintf(text, error, argptr);
|
||||
va_end(argptr);
|
||||
va_start (argptr, error);
|
||||
vsprintf (text, error, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
gi.error(ERR_FATAL, "%s", text);
|
||||
gi.error (ERR_FATAL, "%s", text);
|
||||
}
|
||||
|
||||
void
|
||||
Com_Printf(char *msg, ...)
|
||||
void Com_Printf (char *msg, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char text[1024];
|
||||
va_list argptr;
|
||||
char text[1024];
|
||||
|
||||
va_start(argptr, msg);
|
||||
vsprintf(text, msg, argptr);
|
||||
va_end(argptr);
|
||||
va_start (argptr, msg);
|
||||
vsprintf (text, msg, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
gi.dprintf("%s", text);
|
||||
gi.dprintf ("%s", text);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================== */
|
||||
//======================================================================
|
||||
|
||||
|
||||
/*
|
||||
* =================
|
||||
* ClientEndServerFrames
|
||||
* =================
|
||||
*/
|
||||
void
|
||||
ClientEndServerFrames(void)
|
||||
=================
|
||||
ClientEndServerFrames
|
||||
=================
|
||||
*/
|
||||
void ClientEndServerFrames (void)
|
||||
{
|
||||
int i;
|
||||
edict_t *ent;
|
||||
int i;
|
||||
edict_t *ent;
|
||||
|
||||
/* calc the player views now that all pushing */
|
||||
/* and damage has been added */
|
||||
for (i = 0; i < maxclients->value; i++)
|
||||
// calc the player views now that all pushing
|
||||
// and damage has been added
|
||||
for (i=0 ; i<maxclients->value ; i++)
|
||||
{
|
||||
ent = g_edicts + 1 + i;
|
||||
|
||||
if (!ent->inuse || !ent->client)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ClientEndServerFrame(ent);
|
||||
ClientEndServerFrame (ent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* CreateTargetChangeLevel
|
||||
*
|
||||
* Returns the created target changelevel
|
||||
* =================
|
||||
*/
|
||||
edict_t *
|
||||
CreateTargetChangeLevel(char *map)
|
||||
=================
|
||||
CreateTargetChangeLevel
|
||||
|
||||
Returns the created target changelevel
|
||||
=================
|
||||
*/
|
||||
edict_t *CreateTargetChangeLevel(char *map)
|
||||
{
|
||||
edict_t *ent;
|
||||
|
||||
ent = G_Spawn();
|
||||
ent = G_Spawn ();
|
||||
ent->classname = "target_changelevel";
|
||||
Com_sprintf(level.nextmap, sizeof(level.nextmap), "%s", map);
|
||||
ent->map = level.nextmap;
|
||||
|
@ -216,275 +211,219 @@ CreateTargetChangeLevel(char *map)
|
|||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* EndDMLevel
|
||||
*
|
||||
* The timelimit or fraglimit has been exceeded
|
||||
* =================
|
||||
*/
|
||||
void
|
||||
EndDMLevel(void)
|
||||
=================
|
||||
EndDMLevel
|
||||
|
||||
The timelimit or fraglimit has been exceeded
|
||||
=================
|
||||
*/
|
||||
void EndDMLevel (void)
|
||||
{
|
||||
edict_t *ent;
|
||||
edict_t *ent;
|
||||
char *s, *t, *f;
|
||||
static const char *seps = " ,\n\r";
|
||||
|
||||
/* stay on same level flag */
|
||||
// stay on same level flag
|
||||
if ((int)dmflags->value & DF_SAME_LEVEL)
|
||||
{
|
||||
BeginIntermission(CreateTargetChangeLevel(level.mapname));
|
||||
BeginIntermission (CreateTargetChangeLevel (level.mapname) );
|
||||
return;
|
||||
}
|
||||
|
||||
if (*level.forcemap)
|
||||
{
|
||||
BeginIntermission(CreateTargetChangeLevel(level.forcemap));
|
||||
if (*level.forcemap) {
|
||||
BeginIntermission (CreateTargetChangeLevel (level.forcemap) );
|
||||
return;
|
||||
}
|
||||
|
||||
/* see if it's in the map list */
|
||||
if (*sv_maplist->string)
|
||||
{
|
||||
// see if it's in the map list
|
||||
if (*sv_maplist->string) {
|
||||
s = strdup(sv_maplist->string);
|
||||
f = NULL;
|
||||
t = strtok(s, seps);
|
||||
|
||||
while (t != NULL)
|
||||
{
|
||||
if (Q_stricmp(t, level.mapname) == 0)
|
||||
{
|
||||
/* it's in the list, go to the next one */
|
||||
while (t != NULL) {
|
||||
if (Q_stricmp(t, level.mapname) == 0) {
|
||||
// it's in the list, go to the next one
|
||||
t = strtok(NULL, seps);
|
||||
|
||||
if (t == NULL) /* end of list, go to first one */
|
||||
{
|
||||
if (f == NULL) /* there isn't a first one, same level */
|
||||
{
|
||||
BeginIntermission(CreateTargetChangeLevel(level.mapname));
|
||||
}
|
||||
if (t == NULL) { // end of list, go to first one
|
||||
if (f == NULL) // there isn't a first one, same level
|
||||
BeginIntermission (CreateTargetChangeLevel (level.mapname) );
|
||||
else
|
||||
{
|
||||
BeginIntermission(CreateTargetChangeLevel(f));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BeginIntermission(CreateTargetChangeLevel(t));
|
||||
}
|
||||
|
||||
BeginIntermission (CreateTargetChangeLevel (f) );
|
||||
} else
|
||||
BeginIntermission (CreateTargetChangeLevel (t) );
|
||||
free(s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!f)
|
||||
{
|
||||
f = t;
|
||||
}
|
||||
|
||||
t = strtok(NULL, seps);
|
||||
}
|
||||
|
||||
free(s);
|
||||
}
|
||||
|
||||
if (level.nextmap[0]) /* go to a specific map */
|
||||
{
|
||||
BeginIntermission(CreateTargetChangeLevel(level.nextmap));
|
||||
}
|
||||
else /* search for a changelevel */
|
||||
{
|
||||
ent = G_Find(NULL, FOFS(classname), "target_changelevel");
|
||||
|
||||
if (level.nextmap[0]) // go to a specific map
|
||||
BeginIntermission (CreateTargetChangeLevel (level.nextmap) );
|
||||
else { // search for a changelevel
|
||||
ent = G_Find (NULL, FOFS(classname), "target_changelevel");
|
||||
if (!ent)
|
||||
{ /* the map designer didn't include a changelevel, */
|
||||
/* so create a fake ent that goes back to the same level */
|
||||
BeginIntermission(CreateTargetChangeLevel(level.mapname));
|
||||
{ // the map designer didn't include a changelevel,
|
||||
// so create a fake ent that goes back to the same level
|
||||
BeginIntermission (CreateTargetChangeLevel (level.mapname) );
|
||||
return;
|
||||
}
|
||||
|
||||
BeginIntermission(ent);
|
||||
BeginIntermission (ent);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* CheckDMRules
|
||||
* =================
|
||||
*/
|
||||
void
|
||||
CheckDMRules(void)
|
||||
=================
|
||||
CheckDMRules
|
||||
=================
|
||||
*/
|
||||
void CheckDMRules (void)
|
||||
{
|
||||
int i;
|
||||
gclient_t *cl;
|
||||
int i;
|
||||
gclient_t *cl;
|
||||
|
||||
if (level.intermissiontime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!deathmatch->value)
|
||||
{
|
||||
return;
|
||||
|
||||
//ZOID
|
||||
if (ctf->value && CTFCheckRules()) {
|
||||
EndDMLevel ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* ZOID */
|
||||
if (ctf->value && CTFCheckRules())
|
||||
{
|
||||
EndDMLevel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (CTFInMatch())
|
||||
{
|
||||
return; /* no checking in match mode */
|
||||
}
|
||||
|
||||
/* ZOID */
|
||||
return; // no checking in match mode
|
||||
//ZOID
|
||||
|
||||
if (timelimit->value)
|
||||
{
|
||||
if (level.time >= timelimit->value * 60)
|
||||
if (level.time >= timelimit->value*60)
|
||||
{
|
||||
gi.bprintf(PRINT_HIGH, "Timelimit hit.\n");
|
||||
EndDMLevel();
|
||||
gi.bprintf (PRINT_HIGH, "Timelimit hit.\n");
|
||||
EndDMLevel ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fraglimit->value)
|
||||
{
|
||||
for (i = 0; i < maxclients->value; i++)
|
||||
for (i=0 ; i<maxclients->value ; i++)
|
||||
{
|
||||
cl = game.clients + i;
|
||||
|
||||
if (!g_edicts[i + 1].inuse)
|
||||
{
|
||||
if (!g_edicts[i+1].inuse)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cl->resp.score >= fraglimit->value)
|
||||
{
|
||||
gi.bprintf(PRINT_HIGH, "Fraglimit hit.\n");
|
||||
EndDMLevel();
|
||||
gi.bprintf (PRINT_HIGH, "Fraglimit hit.\n");
|
||||
EndDMLevel ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* =============
|
||||
* ExitLevel
|
||||
* =============
|
||||
*/
|
||||
void
|
||||
ExitLevel(void)
|
||||
=============
|
||||
ExitLevel
|
||||
=============
|
||||
*/
|
||||
void ExitLevel (void)
|
||||
{
|
||||
int i;
|
||||
edict_t *ent;
|
||||
char command[256];
|
||||
int i;
|
||||
edict_t *ent;
|
||||
char command [256];
|
||||
|
||||
level.exitintermission = 0;
|
||||
level.intermissiontime = 0;
|
||||
|
||||
if (CTFNextMap())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Com_sprintf(command, sizeof(command), "gamemap \"%s\"\n", level.changemap);
|
||||
gi.AddCommandString(command);
|
||||
ClientEndServerFrames();
|
||||
Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", level.changemap);
|
||||
gi.AddCommandString (command);
|
||||
ClientEndServerFrames ();
|
||||
|
||||
level.changemap = NULL;
|
||||
|
||||
/* clear some things before going to next level */
|
||||
for (i = 0; i < maxclients->value; i++)
|
||||
// clear some things before going to next level
|
||||
for (i=0 ; i<maxclients->value ; i++)
|
||||
{
|
||||
ent = g_edicts + 1 + i;
|
||||
|
||||
if (!ent->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ent->health > ent->client->pers.max_health)
|
||||
{
|
||||
ent->health = ent->client->pers.max_health;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ================
|
||||
* G_RunFrame
|
||||
*
|
||||
* Advances the world by 0.1 seconds
|
||||
* ================
|
||||
*/
|
||||
void
|
||||
G_RunFrame(void)
|
||||
================
|
||||
G_RunFrame
|
||||
|
||||
Advances the world by 0.1 seconds
|
||||
================
|
||||
*/
|
||||
void G_RunFrame (void)
|
||||
{
|
||||
int i;
|
||||
edict_t *ent;
|
||||
int i;
|
||||
edict_t *ent;
|
||||
|
||||
level.framenum++;
|
||||
level.time = level.framenum * FRAMETIME;
|
||||
level.time = level.framenum*FRAMETIME;
|
||||
|
||||
/* choose a client for monsters to target this frame */
|
||||
AI_SetSightClient();
|
||||
// choose a client for monsters to target this frame
|
||||
AI_SetSightClient ();
|
||||
|
||||
/* exit intermissions */
|
||||
// exit intermissions
|
||||
|
||||
if (level.exitintermission)
|
||||
{
|
||||
ExitLevel();
|
||||
ExitLevel ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* */
|
||||
/* treat each object in turn */
|
||||
/* even the world gets a chance to think */
|
||||
/* */
|
||||
//
|
||||
// treat each object in turn
|
||||
// even the world gets a chance to think
|
||||
//
|
||||
ent = &g_edicts[0];
|
||||
|
||||
for (i = 0; i < globals.num_edicts; i++, ent++)
|
||||
for (i=0 ; i<globals.num_edicts ; i++, ent++)
|
||||
{
|
||||
if (!ent->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
level.current_entity = ent;
|
||||
|
||||
VectorCopy(ent->s.origin, ent->s.old_origin);
|
||||
VectorCopy (ent->s.origin, ent->s.old_origin);
|
||||
|
||||
/* if the ground entity moved, make sure we are still on it */
|
||||
if ((ent->groundentity) &&
|
||||
(ent->groundentity->linkcount != ent->groundentity_linkcount))
|
||||
// if the ground entity moved, make sure we are still on it
|
||||
if ((ent->groundentity) && (ent->groundentity->linkcount != ent->groundentity_linkcount))
|
||||
{
|
||||
ent->groundentity = NULL;
|
||||
|
||||
if (!(ent->flags & (FL_SWIM | FL_FLY)) &&
|
||||
(ent->svflags & SVF_MONSTER))
|
||||
if ( !(ent->flags & (FL_SWIM|FL_FLY)) && (ent->svflags & SVF_MONSTER) )
|
||||
{
|
||||
M_CheckGround(ent);
|
||||
M_CheckGround (ent);
|
||||
}
|
||||
}
|
||||
|
||||
if ((i > 0) && (i <= maxclients->value))
|
||||
if (i > 0 && i <= maxclients->value)
|
||||
{
|
||||
ClientBeginServerFrame(ent);
|
||||
ClientBeginServerFrame (ent);
|
||||
continue;
|
||||
}
|
||||
|
||||
G_RunEntity(ent);
|
||||
G_RunEntity (ent);
|
||||
}
|
||||
|
||||
/* see if it is time to end a deathmatch */
|
||||
CheckDMRules();
|
||||
// see if it is time to end a deathmatch
|
||||
CheckDMRules ();
|
||||
|
||||
/* build the playerstate_t structures for all players */
|
||||
ClientEndServerFrames();
|
||||
// build the playerstate_t structures for all players
|
||||
ClientEndServerFrames ();
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,369 +1,300 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, 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 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.
|
||||
*
|
||||
*/
|
||||
Copyright (C) 1997-2001 Id Software, 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 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.
|
||||
|
||||
*/
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
void
|
||||
Svcmd_Test_f(void)
|
||||
|
||||
void Svcmd_Test_f (void)
|
||||
{
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Svcmd_Test_f()\n");
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Svcmd_Test_f()\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* ==============================================================================
|
||||
*
|
||||
* PACKET FILTERING
|
||||
*
|
||||
*
|
||||
* You can add or remove addresses from the filter list with:
|
||||
*
|
||||
* addip <ip>
|
||||
* removeip <ip>
|
||||
*
|
||||
* The ip address is specified in dot format, and any unspecified digits will match any value, so you can specify an entire class C network with "addip 192.246.40".
|
||||
*
|
||||
* Removeip will only remove an address specified exactly the same way. You cannot addip a subnet, then removeip a single host.
|
||||
*
|
||||
* listip
|
||||
* Prints the current list of filters.
|
||||
*
|
||||
* writeip
|
||||
* Dumps "addip <ip>" commands to listip.cfg so it can be execed at a later date. The filter lists are not saved and restored by default, because I beleive it would cause too much confusion.
|
||||
*
|
||||
* filterban <0 or 1>
|
||||
*
|
||||
* If 1 (the default), then ip addresses matching the current list will be prohibited from entering the game. This is the default setting.
|
||||
*
|
||||
* If 0, then only addresses matching the list will be allowed. This lets you easily set up a private game, or a game that only allows players from your local network.
|
||||
*
|
||||
*
|
||||
* ==============================================================================
|
||||
*/
|
||||
==============================================================================
|
||||
|
||||
PACKET FILTERING
|
||||
|
||||
|
||||
You can add or remove addresses from the filter list with:
|
||||
|
||||
addip <ip>
|
||||
removeip <ip>
|
||||
|
||||
The ip address is specified in dot format, and any unspecified digits will match any value, so you can specify an entire class C network with "addip 192.246.40".
|
||||
|
||||
Removeip will only remove an address specified exactly the same way. You cannot addip a subnet, then removeip a single host.
|
||||
|
||||
listip
|
||||
Prints the current list of filters.
|
||||
|
||||
writeip
|
||||
Dumps "addip <ip>" commands to listip.cfg so it can be execed at a later date. The filter lists are not saved and restored by default, because I beleive it would cause too much confusion.
|
||||
|
||||
filterban <0 or 1>
|
||||
|
||||
If 1 (the default), then ip addresses matching the current list will be prohibited from entering the game. This is the default setting.
|
||||
|
||||
If 0, then only addresses matching the list will be allowed. This lets you easily set up a private game, or a game that only allows players from your local network.
|
||||
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned mask;
|
||||
unsigned compare;
|
||||
unsigned mask;
|
||||
unsigned compare;
|
||||
} ipfilter_t;
|
||||
|
||||
#define MAX_IPFILTERS 1024
|
||||
#define MAX_IPFILTERS 1024
|
||||
|
||||
ipfilter_t ipfilters[MAX_IPFILTERS];
|
||||
int numipfilters;
|
||||
ipfilter_t ipfilters[MAX_IPFILTERS];
|
||||
int numipfilters;
|
||||
|
||||
/*
|
||||
* =================
|
||||
* StringToFilter
|
||||
* =================
|
||||
*/
|
||||
static qboolean
|
||||
StringToFilter(char *s, ipfilter_t *f)
|
||||
=================
|
||||
StringToFilter
|
||||
=================
|
||||
*/
|
||||
static qboolean StringToFilter (char *s, ipfilter_t *f)
|
||||
{
|
||||
char num[128];
|
||||
int i, j;
|
||||
byte b[4];
|
||||
byte m[4];
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
char num[128];
|
||||
int i, j;
|
||||
byte b[4];
|
||||
byte m[4];
|
||||
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
b[i] = 0;
|
||||
m[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
if ((*s < '0') || (*s > '9'))
|
||||
if (*s < '0' || *s > '9')
|
||||
{
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Bad filter address: %s\n", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
j = 0;
|
||||
|
||||
while (*s >= '0' && *s <= '9')
|
||||
{
|
||||
num[j++] = *s++;
|
||||
}
|
||||
|
||||
num[j] = 0;
|
||||
b[i] = atoi(num);
|
||||
|
||||
if (b[i] != 0)
|
||||
{
|
||||
m[i] = 255;
|
||||
}
|
||||
|
||||
if (!*s)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
s++;
|
||||
}
|
||||
|
||||
|
||||
f->mask = *(unsigned *)m;
|
||||
f->compare = *(unsigned *)b;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* SV_FilterPacket
|
||||
* =================
|
||||
*/
|
||||
qboolean
|
||||
SV_FilterPacket(char *from)
|
||||
=================
|
||||
SV_FilterPacket
|
||||
=================
|
||||
*/
|
||||
qboolean SV_FilterPacket (char *from)
|
||||
{
|
||||
int i;
|
||||
unsigned in;
|
||||
int i;
|
||||
unsigned in;
|
||||
byte m[4];
|
||||
char *p;
|
||||
|
||||
i = 0;
|
||||
p = from;
|
||||
|
||||
while (*p && i < 4)
|
||||
{
|
||||
while (*p && i < 4) {
|
||||
m[i] = 0;
|
||||
|
||||
while (*p >= '0' && *p <= '9')
|
||||
{
|
||||
m[i] = m[i] * 10 + (*p - '0');
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
m[i] = m[i]*10 + (*p - '0');
|
||||
p++;
|
||||
}
|
||||
|
||||
if (!*p || (*p == ':'))
|
||||
{
|
||||
if (!*p || *p == ':')
|
||||
break;
|
||||
}
|
||||
|
||||
i++, p++;
|
||||
}
|
||||
|
||||
|
||||
in = *(unsigned *)m;
|
||||
|
||||
for (i = 0; i < numipfilters; i++)
|
||||
{
|
||||
if ((in & ipfilters[i].mask) == ipfilters[i].compare)
|
||||
{
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
if ( (in & ipfilters[i].mask) == ipfilters[i].compare)
|
||||
return (int)filterban->value;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)!filterban->value;
|
||||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* SV_AddIP_f
|
||||
* =================
|
||||
*/
|
||||
void
|
||||
SVCmd_AddIP_f(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (gi.argc() < 3)
|
||||
{
|
||||
/*
|
||||
=================
|
||||
SV_AddIP_f
|
||||
=================
|
||||
*/
|
||||
void SVCmd_AddIP_f (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (gi.argc() < 3) {
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Usage: addip <ip-mask>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < numipfilters; i++)
|
||||
{
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
if (ipfilters[i].compare == 0xffffffff)
|
||||
{
|
||||
break; /* free spot */
|
||||
}
|
||||
}
|
||||
|
||||
break; // free spot
|
||||
if (i == numipfilters)
|
||||
{
|
||||
if (numipfilters == MAX_IPFILTERS)
|
||||
{
|
||||
gi.cprintf(NULL, PRINT_HIGH, "IP filter list is full\n");
|
||||
gi.cprintf (NULL, PRINT_HIGH, "IP filter list is full\n");
|
||||
return;
|
||||
}
|
||||
|
||||
numipfilters++;
|
||||
}
|
||||
|
||||
if (!StringToFilter(gi.argv(2), &ipfilters[i]))
|
||||
{
|
||||
|
||||
if (!StringToFilter (gi.argv(2), &ipfilters[i]))
|
||||
ipfilters[i].compare = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* SV_RemoveIP_f
|
||||
* =================
|
||||
*/
|
||||
void
|
||||
SVCmd_RemoveIP_f(void)
|
||||
=================
|
||||
SV_RemoveIP_f
|
||||
=================
|
||||
*/
|
||||
void SVCmd_RemoveIP_f (void)
|
||||
{
|
||||
ipfilter_t f;
|
||||
int i, j;
|
||||
ipfilter_t f;
|
||||
int i, j;
|
||||
|
||||
if (gi.argc() < 3)
|
||||
{
|
||||
if (gi.argc() < 3) {
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Usage: sv removeip <ip-mask>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!StringToFilter(gi.argv(2), &f))
|
||||
{
|
||||
if (!StringToFilter (gi.argv(2), &f))
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < numipfilters; i++)
|
||||
{
|
||||
if ((ipfilters[i].mask == f.mask) &&
|
||||
(ipfilters[i].compare == f.compare))
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
if (ipfilters[i].mask == f.mask
|
||||
&& ipfilters[i].compare == f.compare)
|
||||
{
|
||||
for (j = i + 1; j < numipfilters; j++)
|
||||
{
|
||||
ipfilters[j - 1] = ipfilters[j];
|
||||
}
|
||||
|
||||
for (j=i+1 ; j<numipfilters ; j++)
|
||||
ipfilters[j-1] = ipfilters[j];
|
||||
numipfilters--;
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Removed.\n");
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Removed.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Didn't find %s.\n", gi.argv(2));
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Didn't find %s.\n", gi.argv(2));
|
||||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* SV_ListIP_f
|
||||
* =================
|
||||
*/
|
||||
void
|
||||
SVCmd_ListIP_f(void)
|
||||
=================
|
||||
SV_ListIP_f
|
||||
=================
|
||||
*/
|
||||
void SVCmd_ListIP_f (void)
|
||||
{
|
||||
int i;
|
||||
byte b[4];
|
||||
int i;
|
||||
byte b[4];
|
||||
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Filter list:\n");
|
||||
|
||||
for (i = 0; i < numipfilters; i++)
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Filter list:\n");
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
{
|
||||
*(unsigned *)b = ipfilters[i].compare;
|
||||
gi.cprintf(NULL,
|
||||
PRINT_HIGH,
|
||||
"%3i.%3i.%3i.%3i\n",
|
||||
b[0],
|
||||
b[1],
|
||||
b[2],
|
||||
b[3]);
|
||||
gi.cprintf (NULL, PRINT_HIGH, "%3i.%3i.%3i.%3i\n", b[0], b[1], b[2], b[3]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* SV_WriteIP_f
|
||||
* =================
|
||||
*/
|
||||
void
|
||||
SVCmd_WriteIP_f(void)
|
||||
=================
|
||||
SV_WriteIP_f
|
||||
=================
|
||||
*/
|
||||
void SVCmd_WriteIP_f (void)
|
||||
{
|
||||
FILE *f;
|
||||
char name[MAX_OSPATH];
|
||||
byte b[4];
|
||||
int i;
|
||||
cvar_t *game;
|
||||
FILE *f;
|
||||
char name[MAX_OSPATH];
|
||||
byte b[4];
|
||||
int i;
|
||||
cvar_t *game;
|
||||
|
||||
game = gi.cvar("game", "", 0);
|
||||
|
||||
if (!*game->string)
|
||||
{
|
||||
sprintf(name, "%s/listip.cfg", GAMEVERSION);
|
||||
}
|
||||
sprintf (name, "%s/listip.cfg", GAMEVERSION);
|
||||
else
|
||||
{
|
||||
sprintf(name, "%s/listip.cfg", game->string);
|
||||
}
|
||||
sprintf (name, "%s/listip.cfg", game->string);
|
||||
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Writing %s.\n", name);
|
||||
|
||||
f = fopen(name, "wb");
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Writing %s.\n", name);
|
||||
|
||||
f = fopen (name, "wb");
|
||||
if (!f)
|
||||
{
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Couldn't open %s\n", name);
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Couldn't open %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fprintf(f, "set filterban %d\n", (int)filterban->value);
|
||||
|
||||
for (i = 0; i < numipfilters; i++)
|
||||
for (i=0 ; i<numipfilters ; i++)
|
||||
{
|
||||
*(unsigned *)b = ipfilters[i].compare;
|
||||
fprintf(f, "sv addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]);
|
||||
fprintf (f, "sv addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* ServerCommand
|
||||
*
|
||||
* ServerCommand will be called when an "sv" command is issued.
|
||||
* The game can issue gi.argc() / gi.argv() commands to get the rest
|
||||
* of the parameters
|
||||
* =================
|
||||
*/
|
||||
void
|
||||
ServerCommand(void)
|
||||
=================
|
||||
ServerCommand
|
||||
|
||||
ServerCommand will be called when an "sv" command is issued.
|
||||
The game can issue gi.argc() / gi.argv() commands to get the rest
|
||||
of the parameters
|
||||
=================
|
||||
*/
|
||||
void ServerCommand (void)
|
||||
{
|
||||
char *cmd;
|
||||
char *cmd;
|
||||
|
||||
cmd = gi.argv(1);
|
||||
|
||||
if (Q_stricmp(cmd, "test") == 0)
|
||||
{
|
||||
Svcmd_Test_f();
|
||||
}
|
||||
else if (Q_stricmp(cmd, "addip") == 0)
|
||||
{
|
||||
SVCmd_AddIP_f();
|
||||
}
|
||||
else if (Q_stricmp(cmd, "removeip") == 0)
|
||||
{
|
||||
SVCmd_RemoveIP_f();
|
||||
}
|
||||
else if (Q_stricmp(cmd, "listip") == 0)
|
||||
{
|
||||
SVCmd_ListIP_f();
|
||||
}
|
||||
else if (Q_stricmp(cmd, "writeip") == 0)
|
||||
{
|
||||
SVCmd_WriteIP_f();
|
||||
}
|
||||
if (Q_stricmp (cmd, "test") == 0)
|
||||
Svcmd_Test_f ();
|
||||
else if (Q_stricmp (cmd, "addip") == 0)
|
||||
SVCmd_AddIP_f ();
|
||||
else if (Q_stricmp (cmd, "removeip") == 0)
|
||||
SVCmd_RemoveIP_f ();
|
||||
else if (Q_stricmp (cmd, "listip") == 0)
|
||||
SVCmd_ListIP_f ();
|
||||
else if (Q_stricmp (cmd, "writeip") == 0)
|
||||
SVCmd_WriteIP_f ();
|
||||
else
|
||||
{
|
||||
gi.cprintf(NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd);
|
||||
}
|
||||
gi.cprintf (NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,162 +1,136 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, 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 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.
|
||||
*
|
||||
*/
|
||||
Copyright (C) 1997-2001 Id Software, 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 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.
|
||||
|
||||
*/
|
||||
#include "g_local.h"
|
||||
|
||||
void
|
||||
InitTrigger(edict_t *self)
|
||||
|
||||
void InitTrigger (edict_t *self)
|
||||
{
|
||||
if (!VectorCompare(self->s.angles, vec3_origin))
|
||||
{
|
||||
G_SetMovedir(self->s.angles, self->movedir);
|
||||
}
|
||||
if (!VectorCompare (self->s.angles, vec3_origin))
|
||||
G_SetMovedir (self->s.angles, self->movedir);
|
||||
|
||||
self->solid = SOLID_TRIGGER;
|
||||
self->movetype = MOVETYPE_NONE;
|
||||
gi.setmodel(self, self->model);
|
||||
gi.setmodel (self, self->model);
|
||||
self->svflags = SVF_NOCLIENT;
|
||||
}
|
||||
|
||||
/* the wait time has passed, so set back up for another activation */
|
||||
void
|
||||
multi_wait(edict_t *ent)
|
||||
|
||||
// the wait time has passed, so set back up for another activation
|
||||
void multi_wait (edict_t *ent)
|
||||
{
|
||||
ent->nextthink = 0;
|
||||
}
|
||||
|
||||
/* the trigger was just activated */
|
||||
/* ent->activator should be set to the activator so it can be held through a delay */
|
||||
/* so wait for the delay time before firing */
|
||||
void
|
||||
multi_trigger(edict_t *ent)
|
||||
|
||||
// the trigger was just activated
|
||||
// ent->activator should be set to the activator so it can be held through a delay
|
||||
// so wait for the delay time before firing
|
||||
void multi_trigger (edict_t *ent)
|
||||
{
|
||||
if (ent->nextthink)
|
||||
{
|
||||
return; /* already been triggered */
|
||||
}
|
||||
return; // already been triggered
|
||||
|
||||
G_UseTargets(ent, ent->activator);
|
||||
G_UseTargets (ent, ent->activator);
|
||||
|
||||
if (ent->wait > 0)
|
||||
if (ent->wait > 0)
|
||||
{
|
||||
ent->think = multi_wait;
|
||||
ent->nextthink = level.time + ent->wait;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we can't just remove (self) here, because this is a touch function */
|
||||
/* called while looping through area links... */
|
||||
{ // we can't just remove (self) here, because this is a touch function
|
||||
// called while looping through area links...
|
||||
ent->touch = NULL;
|
||||
ent->nextthink = level.time + FRAMETIME;
|
||||
ent->think = G_FreeEdict;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Use_Multi(edict_t *ent, edict_t *other, edict_t *activator)
|
||||
void Use_Multi (edict_t *ent, edict_t *other, edict_t *activator)
|
||||
{
|
||||
ent->activator = activator;
|
||||
multi_trigger(ent);
|
||||
multi_trigger (ent);
|
||||
}
|
||||
|
||||
void
|
||||
Touch_Multi(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
||||
void Touch_Multi (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
||||
{
|
||||
if (other->client)
|
||||
if(other->client)
|
||||
{
|
||||
if (self->spawnflags & 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (other->svflags & SVF_MONSTER)
|
||||
{
|
||||
if (!(self->spawnflags & 1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!VectorCompare(self->movedir, vec3_origin))
|
||||
{
|
||||
vec3_t forward;
|
||||
vec3_t forward;
|
||||
|
||||
AngleVectors(other->s.angles, forward, NULL, NULL);
|
||||
|
||||
if (_DotProduct(forward, self->movedir) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self->activator = other;
|
||||
multi_trigger(self);
|
||||
multi_trigger (self);
|
||||
}
|
||||
|
||||
/*QUAKED trigger_multiple (.5 .5 .5) ? MONSTER NOT_PLAYER TRIGGERED
|
||||
* Variable sized repeatable trigger. Must be targeted at one or more entities.
|
||||
* If "delay" is set, the trigger waits some time after activating before firing.
|
||||
* "wait" : Seconds between triggerings. (.2 default)
|
||||
* sounds
|
||||
* 1) secret
|
||||
* 2) beep beep
|
||||
* 3) large switch
|
||||
* 4)
|
||||
* set "message" to text string
|
||||
*/
|
||||
void
|
||||
trigger_enable(edict_t *self, edict_t *other, edict_t *activator)
|
||||
Variable sized repeatable trigger. Must be targeted at one or more entities.
|
||||
If "delay" is set, the trigger waits some time after activating before firing.
|
||||
"wait" : Seconds between triggerings. (.2 default)
|
||||
sounds
|
||||
1) secret
|
||||
2) beep beep
|
||||
3) large switch
|
||||
4)
|
||||
set "message" to text string
|
||||
*/
|
||||
void trigger_enable (edict_t *self, edict_t *other, edict_t *activator)
|
||||
{
|
||||
self->solid = SOLID_TRIGGER;
|
||||
self->use = Use_Multi;
|
||||
gi.linkentity(self);
|
||||
gi.linkentity (self);
|
||||
}
|
||||
|
||||
void
|
||||
SP_trigger_multiple(edict_t *ent)
|
||||
void SP_trigger_multiple (edict_t *ent)
|
||||
{
|
||||
if (ent->sounds == 1)
|
||||
{
|
||||
ent->noise_index = gi.soundindex("misc/secret.wav");
|
||||
}
|
||||
ent->noise_index = gi.soundindex ("misc/secret.wav");
|
||||
else if (ent->sounds == 2)
|
||||
{
|
||||
ent->noise_index = gi.soundindex("misc/talk.wav");
|
||||
}
|
||||
ent->noise_index = gi.soundindex ("misc/talk.wav");
|
||||
else if (ent->sounds == 3)
|
||||
{
|
||||
ent->noise_index = gi.soundindex("misc/trigger1.wav");
|
||||
}
|
||||
|
||||
ent->noise_index = gi.soundindex ("misc/trigger1.wav");
|
||||
|
||||
if (!ent->wait)
|
||||
{
|
||||
ent->wait = 0.2;
|
||||
}
|
||||
|
||||
ent->touch = Touch_Multi;
|
||||
ent->movetype = MOVETYPE_NONE;
|
||||
ent->svflags |= SVF_NOCLIENT;
|
||||
|
||||
|
||||
if (ent->spawnflags & 4)
|
||||
{
|
||||
ent->solid = SOLID_NOT;
|
||||
|
@ -169,140 +143,112 @@ SP_trigger_multiple(edict_t *ent)
|
|||
}
|
||||
|
||||
if (!VectorCompare(ent->s.angles, vec3_origin))
|
||||
{
|
||||
G_SetMovedir(ent->s.angles, ent->movedir);
|
||||
}
|
||||
G_SetMovedir (ent->s.angles, ent->movedir);
|
||||
|
||||
gi.setmodel(ent, ent->model);
|
||||
gi.linkentity(ent);
|
||||
gi.setmodel (ent, ent->model);
|
||||
gi.linkentity (ent);
|
||||
}
|
||||
|
||||
/*QUAKED trigger_once (.5 .5 .5) ? x x TRIGGERED
|
||||
* Triggers once, then removes itself.
|
||||
* You must set the key "target" to the name of another object in the level that has a matching "targetname".
|
||||
*
|
||||
* If TRIGGERED, this trigger must be triggered before it is live.
|
||||
*
|
||||
* sounds
|
||||
* 1) secret
|
||||
* 2) beep beep
|
||||
* 3) large switch
|
||||
* 4)
|
||||
*
|
||||
* "message" string to be displayed when triggered
|
||||
*/
|
||||
|
||||
void
|
||||
SP_trigger_once(edict_t *ent)
|
||||
/*QUAKED trigger_once (.5 .5 .5) ? x x TRIGGERED
|
||||
Triggers once, then removes itself.
|
||||
You must set the key "target" to the name of another object in the level that has a matching "targetname".
|
||||
|
||||
If TRIGGERED, this trigger must be triggered before it is live.
|
||||
|
||||
sounds
|
||||
1) secret
|
||||
2) beep beep
|
||||
3) large switch
|
||||
4)
|
||||
|
||||
"message" string to be displayed when triggered
|
||||
*/
|
||||
|
||||
void SP_trigger_once(edict_t *ent)
|
||||
{
|
||||
/* make old maps work because I messed up on flag assignments here */
|
||||
/* triggered was on bit 1 when it should have been on bit 4 */
|
||||
// make old maps work because I messed up on flag assignments here
|
||||
// triggered was on bit 1 when it should have been on bit 4
|
||||
if (ent->spawnflags & 1)
|
||||
{
|
||||
vec3_t v;
|
||||
vec3_t v;
|
||||
|
||||
VectorMA(ent->mins, 0.5, ent->size, v);
|
||||
VectorMA (ent->mins, 0.5, ent->size, v);
|
||||
ent->spawnflags &= ~1;
|
||||
ent->spawnflags |= 4;
|
||||
gi.dprintf("fixed TRIGGERED flag on %s at %s\n", ent->classname, vtos(v));
|
||||
}
|
||||
|
||||
ent->wait = -1;
|
||||
SP_trigger_multiple(ent);
|
||||
SP_trigger_multiple (ent);
|
||||
}
|
||||
|
||||
/*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
|
||||
* This fixed size trigger cannot be touched, it can only be fired by other events.
|
||||
*/
|
||||
void
|
||||
trigger_relay_use(edict_t *self, edict_t *other, edict_t *activator)
|
||||
This fixed size trigger cannot be touched, it can only be fired by other events.
|
||||
*/
|
||||
void trigger_relay_use (edict_t *self, edict_t *other, edict_t *activator)
|
||||
{
|
||||
G_UseTargets(self, activator);
|
||||
G_UseTargets (self, activator);
|
||||
}
|
||||
|
||||
void
|
||||
SP_trigger_relay(edict_t *self)
|
||||
void SP_trigger_relay (edict_t *self)
|
||||
{
|
||||
self->use = trigger_relay_use;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ==============================================================================
|
||||
*
|
||||
* trigger_key
|
||||
*
|
||||
* ==============================================================================
|
||||
*/
|
||||
==============================================================================
|
||||
|
||||
trigger_key
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*QUAKED trigger_key (.5 .5 .5) (-8 -8 -8) (8 8 8)
|
||||
* A relay trigger that only fires it's targets if player has the proper key.
|
||||
* Use "item" to specify the required key, for example "key_data_cd"
|
||||
*/
|
||||
void
|
||||
trigger_key_use(edict_t *self, edict_t *other, edict_t *activator)
|
||||
A relay trigger that only fires it's targets if player has the proper key.
|
||||
Use "item" to specify the required key, for example "key_data_cd"
|
||||
*/
|
||||
void trigger_key_use (edict_t *self, edict_t *other, edict_t *activator)
|
||||
{
|
||||
int index;
|
||||
int index;
|
||||
|
||||
if (!self->item)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!activator->client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
index = ITEM_INDEX(self->item);
|
||||
|
||||
if (!activator->client->pers.inventory[index])
|
||||
{
|
||||
if (level.time < self->touch_debounce_time)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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.centerprintf (activator, "You need the %s", self->item->pickup_name);
|
||||
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)
|
||||
{
|
||||
int player;
|
||||
edict_t *ent;
|
||||
int player;
|
||||
edict_t *ent;
|
||||
|
||||
if (strcmp(self->item->classname, "key_power_cube") == 0)
|
||||
{
|
||||
int cube;
|
||||
int cube;
|
||||
|
||||
for (cube = 0; cube < 8; cube++)
|
||||
{
|
||||
if (activator->client->pers.power_cubes & (1 << cube))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (player = 1; player <= game.maxclients; player++)
|
||||
{
|
||||
ent = &g_edicts[player];
|
||||
|
||||
if (!ent->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ent->client)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ent->client->pers.power_cubes & (1 << cube))
|
||||
{
|
||||
ent->client->pers.inventory[index]--;
|
||||
|
@ -315,17 +261,10 @@ trigger_key_use(edict_t *self, edict_t *other, edict_t *activator)
|
|||
for (player = 1; player <= game.maxclients; player++)
|
||||
{
|
||||
ent = &g_edicts[player];
|
||||
|
||||
if (!ent->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ent->client)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ent->client->pers.inventory[index] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -335,420 +274,324 @@ trigger_key_use(edict_t *self, edict_t *other, edict_t *activator)
|
|||
activator->client->pers.inventory[index]--;
|
||||
}
|
||||
|
||||
G_UseTargets(self, activator);
|
||||
G_UseTargets (self, activator);
|
||||
|
||||
self->use = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
SP_trigger_key(edict_t *self)
|
||||
void SP_trigger_key (edict_t *self)
|
||||
{
|
||||
if (!st.item)
|
||||
{
|
||||
gi.dprintf("no key item for trigger_key at %s\n", vtos(self->s.origin));
|
||||
return;
|
||||
}
|
||||
|
||||
self->item = FindItemByClassname(st.item);
|
||||
self->item = FindItemByClassname (st.item);
|
||||
|
||||
if (!self->item)
|
||||
{
|
||||
gi.dprintf("item %s not found for trigger_key at %s\n", st.item,
|
||||
vtos(self->s.origin));
|
||||
gi.dprintf("item %s not found for trigger_key at %s\n", st.item, vtos(self->s.origin));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
gi.dprintf("%s at %s has no target\n", self->classname,
|
||||
vtos(self->s.origin));
|
||||
gi.dprintf("%s at %s has no target\n", self->classname, vtos(self->s.origin));
|
||||
return;
|
||||
}
|
||||
|
||||
gi.soundindex("misc/keytry.wav");
|
||||
gi.soundindex("misc/keyuse.wav");
|
||||
gi.soundindex ("misc/keytry.wav");
|
||||
gi.soundindex ("misc/keyuse.wav");
|
||||
|
||||
self->use = trigger_key_use;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ==============================================================================
|
||||
*
|
||||
* trigger_counter
|
||||
*
|
||||
* ==============================================================================
|
||||
*/
|
||||
==============================================================================
|
||||
|
||||
trigger_counter
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*QUAKED trigger_counter (.5 .5 .5) ? nomessage
|
||||
* Acts as an intermediary for an action that takes multiple inputs.
|
||||
*
|
||||
* If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
|
||||
*
|
||||
* After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
|
||||
*/
|
||||
Acts as an intermediary for an action that takes multiple inputs.
|
||||
|
||||
void
|
||||
trigger_counter_use(edict_t *self, edict_t *other, edict_t *activator)
|
||||
If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
|
||||
|
||||
After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
|
||||
*/
|
||||
|
||||
void trigger_counter_use(edict_t *self, edict_t *other, edict_t *activator)
|
||||
{
|
||||
if (self->count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
self->count--;
|
||||
|
||||
if (self->count)
|
||||
{
|
||||
if (!(self->spawnflags & 1))
|
||||
if (! (self->spawnflags & 1))
|
||||
{
|
||||
gi.centerprintf(activator, "%i more to go...", self->count);
|
||||
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);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(self->spawnflags & 1))
|
||||
|
||||
if (! (self->spawnflags & 1))
|
||||
{
|
||||
gi.centerprintf(activator, "Sequence completed!");
|
||||
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);
|
||||
}
|
||||
|
||||
self->activator = activator;
|
||||
multi_trigger(self);
|
||||
multi_trigger (self);
|
||||
}
|
||||
|
||||
void
|
||||
SP_trigger_counter(edict_t *self)
|
||||
void SP_trigger_counter (edict_t *self)
|
||||
{
|
||||
self->wait = -1;
|
||||
|
||||
if (!self->count)
|
||||
{
|
||||
self->count = 2;
|
||||
}
|
||||
|
||||
self->use = trigger_counter_use;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ==============================================================================
|
||||
*
|
||||
* trigger_always
|
||||
*
|
||||
* ==============================================================================
|
||||
*/
|
||||
==============================================================================
|
||||
|
||||
trigger_always
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*QUAKED trigger_always (.5 .5 .5) (-8 -8 -8) (8 8 8)
|
||||
* This trigger will always fire. It is activated by the world.
|
||||
*/
|
||||
void
|
||||
SP_trigger_always(edict_t *ent)
|
||||
This trigger will always fire. It is activated by the world.
|
||||
*/
|
||||
void SP_trigger_always (edict_t *ent)
|
||||
{
|
||||
/* we must have some delay to make sure our use targets are present */
|
||||
// we must have some delay to make sure our use targets are present
|
||||
if (ent->delay < 0.2)
|
||||
{
|
||||
ent->delay = 0.2;
|
||||
}
|
||||
|
||||
G_UseTargets(ent, ent);
|
||||
}
|
||||
|
||||
/*
|
||||
* ==============================================================================
|
||||
*
|
||||
* trigger_push
|
||||
*
|
||||
* ==============================================================================
|
||||
*/
|
||||
|
||||
#define PUSH_ONCE 1
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
trigger_push
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define PUSH_ONCE 1
|
||||
|
||||
static int windsound;
|
||||
|
||||
void
|
||||
trigger_push_touch(edict_t *self,
|
||||
edict_t *other,
|
||||
cplane_t *plane,
|
||||
csurface_t *surf)
|
||||
void trigger_push_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
||||
{
|
||||
if (strcmp(other->classname, "grenade") == 0)
|
||||
{
|
||||
VectorScale(self->movedir, self->speed * 10, other->velocity);
|
||||
VectorScale (self->movedir, self->speed * 10, other->velocity);
|
||||
}
|
||||
else if (other->health > 0)
|
||||
{
|
||||
VectorScale(self->movedir, self->speed * 10, other->velocity);
|
||||
VectorScale (self->movedir, self->speed * 10, other->velocity);
|
||||
|
||||
if (other->client)
|
||||
{
|
||||
/* don't take falling damage immediately from this */
|
||||
VectorCopy(other->velocity, other->client->oldvelocity);
|
||||
|
||||
// don't take falling damage immediately from this
|
||||
VectorCopy (other->velocity, other->client->oldvelocity);
|
||||
if (other->fly_sound_debounce_time < level.time)
|
||||
{
|
||||
other->fly_sound_debounce_time = level.time + 1.5;
|
||||
gi.sound(other, CHAN_AUTO, windsound, 1, ATTN_NORM, 0);
|
||||
gi.sound (other, CHAN_AUTO, windsound, 1, ATTN_NORM, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self->spawnflags & PUSH_ONCE)
|
||||
{
|
||||
G_FreeEdict(self);
|
||||
}
|
||||
G_FreeEdict (self);
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED trigger_push (.5 .5 .5) ? PUSH_ONCE
|
||||
* Pushes the player
|
||||
* "speed" defaults to 1000
|
||||
*/
|
||||
void
|
||||
SP_trigger_push(edict_t *self)
|
||||
Pushes the player
|
||||
"speed" defaults to 1000
|
||||
*/
|
||||
void SP_trigger_push (edict_t *self)
|
||||
{
|
||||
InitTrigger(self);
|
||||
windsound = gi.soundindex("misc/windfly.wav");
|
||||
InitTrigger (self);
|
||||
windsound = gi.soundindex ("misc/windfly.wav");
|
||||
self->touch = trigger_push_touch;
|
||||
|
||||
if (!self->speed)
|
||||
{
|
||||
self->speed = 1000;
|
||||
}
|
||||
|
||||
gi.linkentity(self);
|
||||
gi.linkentity (self);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ==============================================================================
|
||||
*
|
||||
* trigger_hurt
|
||||
*
|
||||
* ==============================================================================
|
||||
*/
|
||||
==============================================================================
|
||||
|
||||
trigger_hurt
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*QUAKED trigger_hurt (.5 .5 .5) ? START_OFF TOGGLE SILENT NO_PROTECTION SLOW
|
||||
* Any entity that touches this will be hurt.
|
||||
*
|
||||
* It does dmg points of damage each server frame
|
||||
*
|
||||
* SILENT supresses playing the sound
|
||||
* SLOW changes the damage rate to once per second
|
||||
* NO_PROTECTION *nothing* stops the damage
|
||||
*
|
||||
* "dmg" default 5 (whole numbers only)
|
||||
*
|
||||
*/
|
||||
void
|
||||
hurt_use(edict_t *self, edict_t *other, edict_t *activator)
|
||||
Any entity that touches this will be hurt.
|
||||
|
||||
It does dmg points of damage each server frame
|
||||
|
||||
SILENT supresses playing the sound
|
||||
SLOW changes the damage rate to once per second
|
||||
NO_PROTECTION *nothing* stops the damage
|
||||
|
||||
"dmg" default 5 (whole numbers only)
|
||||
|
||||
*/
|
||||
void hurt_use (edict_t *self, edict_t *other, edict_t *activator)
|
||||
{
|
||||
if (self->solid == SOLID_NOT)
|
||||
{
|
||||
self->solid = SOLID_TRIGGER;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->solid = SOLID_NOT;
|
||||
}
|
||||
|
||||
gi.linkentity(self);
|
||||
gi.linkentity (self);
|
||||
|
||||
if (!(self->spawnflags & 2))
|
||||
{
|
||||
self->use = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hurt_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
||||
|
||||
void hurt_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
||||
{
|
||||
int dflags;
|
||||
int dflags;
|
||||
|
||||
if (!other->takedamage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->timestamp > level.time)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->spawnflags & 16)
|
||||
{
|
||||
self->timestamp = level.time + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->timestamp = level.time + FRAMETIME;
|
||||
}
|
||||
|
||||
if (!(self->spawnflags & 4))
|
||||
{
|
||||
if ((level.framenum % 10) == 0)
|
||||
{
|
||||
gi.sound(other, CHAN_AUTO, self->noise_index, 1, ATTN_NORM, 0);
|
||||
}
|
||||
gi.sound (other, CHAN_AUTO, self->noise_index, 1, ATTN_NORM, 0);
|
||||
}
|
||||
|
||||
if (self->spawnflags & 8)
|
||||
{
|
||||
dflags = DAMAGE_NO_PROTECTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
dflags = 0;
|
||||
}
|
||||
|
||||
T_Damage(other,
|
||||
self,
|
||||
self,
|
||||
vec3_origin,
|
||||
other->s.origin,
|
||||
vec3_origin,
|
||||
self->dmg,
|
||||
self->dmg,
|
||||
dflags,
|
||||
MOD_TRIGGER_HURT);
|
||||
T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, self->dmg, dflags, MOD_TRIGGER_HURT);
|
||||
}
|
||||
|
||||
void
|
||||
SP_trigger_hurt(edict_t *self)
|
||||
void SP_trigger_hurt (edict_t *self)
|
||||
{
|
||||
InitTrigger(self);
|
||||
InitTrigger (self);
|
||||
|
||||
self->noise_index = gi.soundindex("world/electro.wav");
|
||||
self->noise_index = gi.soundindex ("world/electro.wav");
|
||||
self->touch = hurt_touch;
|
||||
|
||||
if (!self->dmg)
|
||||
{
|
||||
self->dmg = 5;
|
||||
}
|
||||
|
||||
if (self->spawnflags & 1)
|
||||
{
|
||||
self->solid = SOLID_NOT;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->solid = SOLID_TRIGGER;
|
||||
}
|
||||
|
||||
if (self->spawnflags & 2)
|
||||
{
|
||||
self->use = hurt_use;
|
||||
}
|
||||
|
||||
gi.linkentity(self);
|
||||
gi.linkentity (self);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ==============================================================================
|
||||
*
|
||||
* trigger_gravity
|
||||
*
|
||||
* ==============================================================================
|
||||
*/
|
||||
==============================================================================
|
||||
|
||||
trigger_gravity
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*QUAKED trigger_gravity (.5 .5 .5) ?
|
||||
* Changes the touching entites gravity to
|
||||
* the value of "gravity". 1.0 is standard
|
||||
* gravity for the level.
|
||||
*/
|
||||
Changes the touching entites gravity to
|
||||
the value of "gravity". 1.0 is standard
|
||||
gravity for the level.
|
||||
*/
|
||||
|
||||
void
|
||||
trigger_gravity_touch(edict_t *self,
|
||||
edict_t *other,
|
||||
cplane_t *plane,
|
||||
csurface_t *surf)
|
||||
void trigger_gravity_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
||||
{
|
||||
other->gravity = self->gravity;
|
||||
}
|
||||
|
||||
void
|
||||
SP_trigger_gravity(edict_t *self)
|
||||
void SP_trigger_gravity (edict_t *self)
|
||||
{
|
||||
if (st.gravity == 0)
|
||||
{
|
||||
gi.dprintf("trigger_gravity without gravity set at %s\n",
|
||||
vtos(self->s.origin));
|
||||
G_FreeEdict(self);
|
||||
gi.dprintf("trigger_gravity without gravity set at %s\n", vtos(self->s.origin));
|
||||
G_FreeEdict (self);
|
||||
return;
|
||||
}
|
||||
|
||||
InitTrigger(self);
|
||||
InitTrigger (self);
|
||||
self->gravity = atoi(st.gravity);
|
||||
self->touch = trigger_gravity_touch;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ==============================================================================
|
||||
*
|
||||
* trigger_monsterjump
|
||||
*
|
||||
* ==============================================================================
|
||||
*/
|
||||
==============================================================================
|
||||
|
||||
trigger_monsterjump
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*QUAKED trigger_monsterjump (.5 .5 .5) ?
|
||||
* Walking monsters that touch this will jump in the direction of the trigger's angle
|
||||
* "speed" default to 200, the speed thrown forward
|
||||
* "height" default to 200, the speed thrown upwards
|
||||
*/
|
||||
Walking monsters that touch this will jump in the direction of the trigger's angle
|
||||
"speed" default to 200, the speed thrown forward
|
||||
"height" default to 200, the speed thrown upwards
|
||||
*/
|
||||
|
||||
void
|
||||
trigger_monsterjump_touch(edict_t *self,
|
||||
edict_t *other,
|
||||
cplane_t *plane,
|
||||
csurface_t *surf)
|
||||
void trigger_monsterjump_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
||||
{
|
||||
if (other->flags & (FL_FLY | FL_SWIM))
|
||||
{
|
||||
if (other->flags & (FL_FLY | FL_SWIM) )
|
||||
return;
|
||||
}
|
||||
|
||||
if (other->svflags & SVF_DEADMONSTER)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(other->svflags & SVF_MONSTER))
|
||||
{
|
||||
if ( !(other->svflags & SVF_MONSTER))
|
||||
return;
|
||||
}
|
||||
|
||||
/* set XY even if not on ground, so the jump will clear lips */
|
||||
// set XY even if not on ground, so the jump will clear lips
|
||||
other->velocity[0] = self->movedir[0] * self->speed;
|
||||
other->velocity[1] = self->movedir[1] * self->speed;
|
||||
|
||||
|
||||
if (!other->groundentity)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
other->groundentity = NULL;
|
||||
other->velocity[2] = self->movedir[2];
|
||||
}
|
||||
|
||||
void
|
||||
SP_trigger_monsterjump(edict_t *self)
|
||||
void SP_trigger_monsterjump (edict_t *self)
|
||||
{
|
||||
if (!self->speed)
|
||||
{
|
||||
self->speed = 200;
|
||||
}
|
||||
|
||||
if (!st.height)
|
||||
{
|
||||
st.height = 200;
|
||||
}
|
||||
|
||||
if (self->s.angles[YAW] == 0)
|
||||
{
|
||||
self->s.angles[YAW] = 360;
|
||||
}
|
||||
|
||||
InitTrigger(self);
|
||||
InitTrigger (self);
|
||||
self->touch = trigger_monsterjump_touch;
|
||||
self->movedir[2] = st.height;
|
||||
}
|
||||
|
|
|
@ -1,162 +1,125 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, 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 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.
|
||||
*
|
||||
*/
|
||||
/* g_utils.c -- misc utility functions for game module */
|
||||
Copyright (C) 1997-2001 Id Software, 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 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.
|
||||
|
||||
*/
|
||||
// g_utils.c -- misc utility functions for game module
|
||||
|
||||
#include "g_local.h"
|
||||
|
||||
void
|
||||
G_ProjectSource(vec3_t point,
|
||||
vec3_t distance,
|
||||
vec3_t forward,
|
||||
vec3_t right,
|
||||
vec3_t result)
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* =============
|
||||
* G_Find
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* =============
|
||||
*/
|
||||
edict_t *
|
||||
G_Find(edict_t *from, int fieldofs, char *match)
|
||||
=============
|
||||
G_Find
|
||||
|
||||
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.
|
||||
|
||||
=============
|
||||
*/
|
||||
edict_t *G_Find (edict_t *from, int fieldofs, char *match)
|
||||
{
|
||||
char *s;
|
||||
char *s;
|
||||
|
||||
if (!from)
|
||||
{
|
||||
from = g_edicts;
|
||||
}
|
||||
else
|
||||
{
|
||||
from++;
|
||||
}
|
||||
|
||||
for ( ; from < &g_edicts[globals.num_edicts]; from++)
|
||||
for ( ; from < &g_edicts[globals.num_edicts] ; from++)
|
||||
{
|
||||
if (!from->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
s = *(char **)((byte *)from + fieldofs);
|
||||
|
||||
s = *(char **) ((byte *)from + fieldofs);
|
||||
if (!s)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Q_stricmp(s, match))
|
||||
{
|
||||
if (!Q_stricmp (s, match))
|
||||
return from;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* =================
|
||||
* findradius
|
||||
*
|
||||
* Returns entities that have origins within a spherical area
|
||||
*
|
||||
* findradius (origin, radius)
|
||||
* =================
|
||||
*/
|
||||
edict_t *
|
||||
findradius(edict_t *from, vec3_t org, float rad)
|
||||
=================
|
||||
findradius
|
||||
|
||||
Returns entities that have origins within a spherical area
|
||||
|
||||
findradius (origin, radius)
|
||||
=================
|
||||
*/
|
||||
edict_t *findradius (edict_t *from, vec3_t org, float rad)
|
||||
{
|
||||
vec3_t eorg;
|
||||
int j;
|
||||
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;
|
||||
}
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
eorg[j] = org[j] -
|
||||
(from->s.origin[j] +
|
||||
(from->mins[j] + from->maxs[j]) * 0.5);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* =============
|
||||
* G_PickTarget
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* =============
|
||||
*/
|
||||
#define MAXCHOICES 8
|
||||
|
||||
edict_t *
|
||||
G_PickTarget(char *targetname)
|
||||
/*
|
||||
=============
|
||||
G_PickTarget
|
||||
|
||||
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.
|
||||
|
||||
=============
|
||||
*/
|
||||
#define MAXCHOICES 8
|
||||
|
||||
edict_t *G_PickTarget (char *targetname)
|
||||
{
|
||||
edict_t *ent = NULL;
|
||||
int num_choices = 0;
|
||||
edict_t *choice[MAXCHOICES];
|
||||
edict_t *ent = NULL;
|
||||
int num_choices = 0;
|
||||
edict_t *choice[MAXCHOICES];
|
||||
|
||||
if (!targetname)
|
||||
{
|
||||
|
@ -164,21 +127,14 @@ G_PickTarget(char *targetname)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
while (1)
|
||||
while(1)
|
||||
{
|
||||
ent = G_Find(ent, FOFS(targetname), targetname);
|
||||
|
||||
ent = G_Find (ent, FOFS(targetname), targetname);
|
||||
if (!ent)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
choice[num_choices++] = ent;
|
||||
|
||||
if (num_choices == MAXCHOICES)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!num_choices)
|
||||
|
@ -190,86 +146,75 @@ G_PickTarget(char *targetname)
|
|||
return choice[rand() % num_choices];
|
||||
}
|
||||
|
||||
void
|
||||
Think_Delay(edict_t *ent)
|
||||
|
||||
|
||||
void Think_Delay (edict_t *ent)
|
||||
{
|
||||
G_UseTargets(ent, ent->activator);
|
||||
G_FreeEdict(ent);
|
||||
G_UseTargets (ent, ent->activator);
|
||||
G_FreeEdict (ent);
|
||||
}
|
||||
|
||||
/*
|
||||
* ==============================
|
||||
* G_UseTargets
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
edict_t *t;
|
||||
==============================
|
||||
G_UseTargets
|
||||
|
||||
/* */
|
||||
/* check for a delay */
|
||||
/* */
|
||||
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.
|
||||
|
||||
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)
|
||||
{
|
||||
edict_t *t;
|
||||
|
||||
//
|
||||
// check for a delay
|
||||
//
|
||||
if (ent->delay)
|
||||
{
|
||||
/* create a temp object to fire at a later time */
|
||||
// create a temp object to fire at a later time
|
||||
t = G_Spawn();
|
||||
t->classname = "DelayedUse";
|
||||
t->nextthink = level.time + ent->delay;
|
||||
t->think = Think_Delay;
|
||||
t->activator = activator;
|
||||
|
||||
if (!activator)
|
||||
{
|
||||
gi.dprintf("Think_Delay with no activator\n");
|
||||
}
|
||||
|
||||
gi.dprintf ("Think_Delay with no activator\n");
|
||||
t->message = ent->message;
|
||||
t->target = ent->target;
|
||||
t->killtarget = ent->killtarget;
|
||||
return;
|
||||
}
|
||||
|
||||
/* */
|
||||
/* print the message */
|
||||
/* */
|
||||
|
||||
|
||||
//
|
||||
// print the message
|
||||
//
|
||||
if ((ent->message) && !(activator->svflags & SVF_MONSTER))
|
||||
{
|
||||
gi.centerprintf(activator, "%s", ent->message);
|
||||
|
||||
gi.centerprintf (activator, "%s", ent->message);
|
||||
if (ent->noise_index)
|
||||
{
|
||||
gi.sound(activator, CHAN_AUTO, ent->noise_index, 1, ATTN_NORM, 0);
|
||||
}
|
||||
gi.sound (activator, CHAN_AUTO, ent->noise_index, 1, ATTN_NORM, 0);
|
||||
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);
|
||||
}
|
||||
|
||||
/* */
|
||||
/* kill killtargets */
|
||||
/* */
|
||||
//
|
||||
// kill killtargets
|
||||
//
|
||||
if (ent->killtarget)
|
||||
{
|
||||
t = NULL;
|
||||
|
||||
while ((t = G_Find(t, FOFS(targetname), ent->killtarget)))
|
||||
while ((t = G_Find (t, FOFS(targetname), ent->killtarget)))
|
||||
{
|
||||
G_FreeEdict(t);
|
||||
|
||||
G_FreeEdict (t);
|
||||
if (!ent->inuse)
|
||||
{
|
||||
gi.dprintf("entity was removed while using killtargets\n");
|
||||
|
@ -278,36 +223,28 @@ G_UseTargets(edict_t *ent, edict_t *activator)
|
|||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
/* fire targets */
|
||||
/* */
|
||||
//
|
||||
// fire targets
|
||||
//
|
||||
if (ent->target)
|
||||
{
|
||||
t = NULL;
|
||||
|
||||
while ((t = G_Find(t, FOFS(targetname), ent->target)))
|
||||
while ((t = G_Find (t, FOFS(targetname), ent->target)))
|
||||
{
|
||||
/* doors fire area portals in a specific way */
|
||||
// doors fire area portals in a specific way
|
||||
if (!Q_stricmp(t->classname, "func_areaportal") &&
|
||||
(!Q_stricmp(ent->classname,
|
||||
"func_door") ||
|
||||
!Q_stricmp(ent->classname, "func_door_rotating")))
|
||||
{
|
||||
(!Q_stricmp(ent->classname, "func_door") || !Q_stricmp(ent->classname, "func_door_rotating")))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t == ent)
|
||||
{
|
||||
gi.dprintf("WARNING: Entity used itself.\n");
|
||||
gi.dprintf ("WARNING: Entity used itself.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t->use)
|
||||
{
|
||||
t->use(t, ent, activator);
|
||||
}
|
||||
t->use (t, ent, activator);
|
||||
}
|
||||
|
||||
if (!ent->inuse)
|
||||
{
|
||||
gi.dprintf("entity was removed while using targets\n");
|
||||
|
@ -317,25 +254,25 @@ G_UseTargets(edict_t *ent, edict_t *activator)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* =============
|
||||
* TempVector
|
||||
*
|
||||
* This is just a convenience function
|
||||
* for making temporary vectors for function calls
|
||||
* =============
|
||||
*/
|
||||
float *
|
||||
tv(float x, float y, float z)
|
||||
{
|
||||
static int index;
|
||||
static vec3_t vecs[8];
|
||||
float *v;
|
||||
|
||||
/* use an array so that multiple tempvectors won't collide */
|
||||
/* for a while */
|
||||
/*
|
||||
=============
|
||||
TempVector
|
||||
|
||||
This is just a convenience function
|
||||
for making temporary vectors for function calls
|
||||
=============
|
||||
*/
|
||||
float *tv (float x, float y, float z)
|
||||
{
|
||||
static int index;
|
||||
static vec3_t vecs[8];
|
||||
float *v;
|
||||
|
||||
// use an array so that multiple tempvectors won't collide
|
||||
// for a while
|
||||
v = vecs[index];
|
||||
index = (index + 1) & 7;
|
||||
index = (index + 1)&7;
|
||||
|
||||
v[0] = x;
|
||||
v[1] = y;
|
||||
|
@ -344,131 +281,106 @@ tv(float x, float y, float z)
|
|||
return v;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* =============
|
||||
* VectorToString
|
||||
*
|
||||
* This is just a convenience function
|
||||
* for printing vectors
|
||||
* =============
|
||||
*/
|
||||
char *
|
||||
vtos(vec3_t v)
|
||||
=============
|
||||
VectorToString
|
||||
|
||||
This is just a convenience function
|
||||
for printing vectors
|
||||
=============
|
||||
*/
|
||||
char *vtos (vec3_t v)
|
||||
{
|
||||
static int index;
|
||||
static char str[8][32];
|
||||
char *s;
|
||||
static int index;
|
||||
static char str[8][32];
|
||||
char *s;
|
||||
|
||||
/* use an array so that multiple vtos won't collide */
|
||||
// use an array so that multiple vtos won't collide
|
||||
s = str[index];
|
||||
index = (index + 1) & 7;
|
||||
index = (index + 1)&7;
|
||||
|
||||
Com_sprintf(s, 32, "(%i %i %i)", (int)v[0], (int)v[1], (int)v[2]);
|
||||
Com_sprintf (s, 32, "(%i %i %i)", (int)v[0], (int)v[1], (int)v[2]);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
if (VectorCompare(angles, VEC_UP))
|
||||
if (VectorCompare (angles, VEC_UP))
|
||||
{
|
||||
VectorCopy(MOVEDIR_UP, movedir);
|
||||
VectorCopy (MOVEDIR_UP, movedir);
|
||||
}
|
||||
else if (VectorCompare(angles, VEC_DOWN))
|
||||
else if (VectorCompare (angles, VEC_DOWN))
|
||||
{
|
||||
VectorCopy(MOVEDIR_DOWN, movedir);
|
||||
VectorCopy (MOVEDIR_DOWN, movedir);
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleVectors(angles, movedir, NULL, NULL);
|
||||
AngleVectors (angles, movedir, NULL, NULL);
|
||||
}
|
||||
|
||||
VectorClear(angles);
|
||||
VectorClear (angles);
|
||||
}
|
||||
|
||||
float
|
||||
vectoyaw(vec3_t vec)
|
||||
{
|
||||
float yaw;
|
||||
|
||||
if (/* vec[YAW] == 0 && */ vec[PITCH] == 0)
|
||||
float vectoyaw (vec3_t vec)
|
||||
{
|
||||
float yaw;
|
||||
|
||||
if (/* vec[YAW] == 0 && */ vec[PITCH] == 0)
|
||||
{
|
||||
yaw = 0;
|
||||
|
||||
if (vec[YAW] > 0)
|
||||
{
|
||||
yaw = 90;
|
||||
}
|
||||
else if (vec[YAW] < 0)
|
||||
{
|
||||
yaw = -90;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
yaw = (int)(atan2(vec[YAW], vec[PITCH]) * 180 / M_PI);
|
||||
|
||||
yaw = (int) (atan2(vec[YAW], vec[PITCH]) * 180 / M_PI);
|
||||
if (yaw < 0)
|
||||
{
|
||||
yaw += 360;
|
||||
}
|
||||
}
|
||||
|
||||
return yaw;
|
||||
}
|
||||
|
||||
void
|
||||
vectoangles(vec3_t value1, vec3_t angles)
|
||||
{
|
||||
float forward;
|
||||
float yaw, pitch;
|
||||
|
||||
if ((value1[1] == 0) && (value1[0] == 0))
|
||||
void vectoangles (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 = (int)(atan2(value1[1], value1[0]) * 180 / M_PI);
|
||||
}
|
||||
yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
|
||||
else if (value1[1] > 0)
|
||||
{
|
||||
yaw = 90;
|
||||
}
|
||||
else
|
||||
{
|
||||
yaw = -90;
|
||||
}
|
||||
|
||||
if (yaw < 0)
|
||||
{
|
||||
yaw += 360;
|
||||
}
|
||||
|
||||
forward = sqrt(value1[0] * value1[0] + value1[1] * value1[1]);
|
||||
pitch = (int)(atan2(value1[2], forward) * 180 / M_PI);
|
||||
|
||||
forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
|
||||
pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
|
||||
if (pitch < 0)
|
||||
{
|
||||
pitch += 360;
|
||||
}
|
||||
}
|
||||
|
||||
angles[PITCH] = -pitch;
|
||||
|
@ -476,18 +388,17 @@ vectoangles(vec3_t value1, vec3_t angles)
|
|||
angles[ROLL] = 0;
|
||||
}
|
||||
|
||||
char *
|
||||
G_CopyString(char *in)
|
||||
char *G_CopyString (char *in)
|
||||
{
|
||||
char *out;
|
||||
|
||||
out = gi.TagMalloc(strlen(in) + 1, TAG_LEVEL);
|
||||
strcpy(out, in);
|
||||
char *out;
|
||||
|
||||
out = gi.TagMalloc (strlen(in)+1, TAG_LEVEL);
|
||||
strcpy (out, in);
|
||||
return out;
|
||||
}
|
||||
|
||||
void
|
||||
G_InitEdict(edict_t *e)
|
||||
|
||||
void G_InitEdict (edict_t *e)
|
||||
{
|
||||
e->inuse = true;
|
||||
e->classname = "noclass";
|
||||
|
@ -496,203 +407,162 @@ G_InitEdict(edict_t *e)
|
|||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* G_Spawn
|
||||
*
|
||||
* Either finds a free edict, or allocates a new one.
|
||||
* Try to avoid reusing an entity that was recently freed, because it
|
||||
* can cause the client to think the entity morphed into something else
|
||||
* instead of being removed and recreated, which can cause interpolated
|
||||
* angles and bad trails.
|
||||
* =================
|
||||
*/
|
||||
edict_t *
|
||||
G_Spawn(void)
|
||||
=================
|
||||
G_Spawn
|
||||
|
||||
Either finds a free edict, or allocates a new one.
|
||||
Try to avoid reusing an entity that was recently freed, because it
|
||||
can cause the client to think the entity morphed into something else
|
||||
instead of being removed and recreated, which can cause interpolated
|
||||
angles and bad trails.
|
||||
=================
|
||||
*/
|
||||
edict_t *G_Spawn (void)
|
||||
{
|
||||
int i;
|
||||
edict_t *e;
|
||||
int i;
|
||||
edict_t *e;
|
||||
|
||||
e = &g_edicts[(int)maxclients->value + 1];
|
||||
|
||||
for (i = maxclients->value + 1; i < globals.num_edicts; i++, e++)
|
||||
e = &g_edicts[(int)maxclients->value+1];
|
||||
for ( i=maxclients->value+1 ; i<globals.num_edicts ; i++, e++)
|
||||
{
|
||||
/* the first couple seconds of server time can involve a lot of */
|
||||
/* freeing and allocating, so relax the replacement policy */
|
||||
if (!e->inuse && ((e->freetime < 2) || (level.time - e->freetime > 0.5)))
|
||||
// the first couple seconds of server time can involve a lot of
|
||||
// freeing and allocating, so relax the replacement policy
|
||||
if (!e->inuse && ( e->freetime < 2 || level.time - e->freetime > 0.5 ) )
|
||||
{
|
||||
G_InitEdict(e);
|
||||
G_InitEdict (e);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (i == game.maxentities)
|
||||
{
|
||||
gi.error("ED_Alloc: no free edicts");
|
||||
}
|
||||
|
||||
gi.error ("ED_Alloc: no free edicts");
|
||||
|
||||
globals.num_edicts++;
|
||||
G_InitEdict(e);
|
||||
G_InitEdict (e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* =================
|
||||
* G_FreeEdict
|
||||
*
|
||||
* Marks the edict as free
|
||||
* =================
|
||||
*/
|
||||
void
|
||||
G_FreeEdict(edict_t *ed)
|
||||
=================
|
||||
G_FreeEdict
|
||||
|
||||
Marks the edict as free
|
||||
=================
|
||||
*/
|
||||
void G_FreeEdict (edict_t *ed)
|
||||
{
|
||||
gi.unlinkentity(ed); /* unlink from world */
|
||||
gi.unlinkentity (ed); // unlink from world
|
||||
|
||||
if ((ed - g_edicts) <= (maxclients->value + BODY_QUEUE_SIZE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memset(ed, 0, sizeof(*ed));
|
||||
memset (ed, 0, sizeof(*ed));
|
||||
ed->classname = "freed";
|
||||
ed->freetime = level.time;
|
||||
ed->inuse = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* ============
|
||||
* G_TouchTriggers
|
||||
*
|
||||
* ============
|
||||
*/
|
||||
void
|
||||
G_TouchTriggers(edict_t *ent)
|
||||
{
|
||||
int i, num;
|
||||
edict_t *touch[MAX_EDICTS], *hit;
|
||||
|
||||
/* dead things don't activate triggers! */
|
||||
/*
|
||||
============
|
||||
G_TouchTriggers
|
||||
|
||||
============
|
||||
*/
|
||||
void G_TouchTriggers (edict_t *ent)
|
||||
{
|
||||
int i, num;
|
||||
edict_t *touch[MAX_EDICTS], *hit;
|
||||
|
||||
// dead things don't activate triggers!
|
||||
if ((ent->client || (ent->svflags & SVF_MONSTER)) && (ent->health <= 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
num = gi.BoxEdicts(ent->absmin, ent->absmax, touch,
|
||||
MAX_EDICTS, AREA_TRIGGERS);
|
||||
num = gi.BoxEdicts (ent->absmin, ent->absmax, touch
|
||||
, MAX_EDICTS, AREA_TRIGGERS);
|
||||
|
||||
/* be careful, it is possible to have an entity in this */
|
||||
/* list removed before we get to it (killtriggered) */
|
||||
for (i = 0; i < num; i++)
|
||||
// be careful, it is possible to have an entity in this
|
||||
// list removed before we get to it (killtriggered)
|
||||
for (i=0 ; i<num ; i++)
|
||||
{
|
||||
hit = touch[i];
|
||||
|
||||
if (!hit->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hit->touch)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hit->touch(hit, ent, NULL, NULL);
|
||||
hit->touch (hit, ent, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ============
|
||||
* G_TouchSolids
|
||||
*
|
||||
* 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)
|
||||
============
|
||||
G_TouchSolids
|
||||
|
||||
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)
|
||||
{
|
||||
int i, num;
|
||||
edict_t *touch[MAX_EDICTS], *hit;
|
||||
int i, num;
|
||||
edict_t *touch[MAX_EDICTS], *hit;
|
||||
|
||||
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) */
|
||||
for (i = 0; i < num; i++)
|
||||
// be careful, it is possible to have an entity in this
|
||||
// list removed before we get to it (killtriggered)
|
||||
for (i=0 ; i<num ; i++)
|
||||
{
|
||||
hit = touch[i];
|
||||
|
||||
if (!hit->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ent->touch)
|
||||
{
|
||||
ent->touch(hit, ent, NULL, NULL);
|
||||
}
|
||||
|
||||
ent->touch (hit, ent, NULL, NULL);
|
||||
if (!ent->inuse)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ==============================================================================
|
||||
*
|
||||
* Kill box
|
||||
*
|
||||
* ==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* =================
|
||||
* KillBox
|
||||
*
|
||||
* Kills all entities that would touch the proposed new positioning
|
||||
* of ent. Ent should be unlinked before calling this!
|
||||
* =================
|
||||
*/
|
||||
qboolean
|
||||
KillBox(edict_t *ent)
|
||||
==============================================================================
|
||||
|
||||
Kill box
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=================
|
||||
KillBox
|
||||
|
||||
Kills all entities that would touch the proposed new positioning
|
||||
of ent. Ent should be unlinked before calling this!
|
||||
=================
|
||||
*/
|
||||
qboolean KillBox (edict_t *ent)
|
||||
{
|
||||
trace_t tr;
|
||||
trace_t tr;
|
||||
|
||||
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)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* nail it */
|
||||
T_Damage(tr.ent,
|
||||
ent,
|
||||
ent,
|
||||
vec3_origin,
|
||||
ent->s.origin,
|
||||
vec3_origin,
|
||||
100000,
|
||||
0,
|
||||
DAMAGE_NO_PROTECTION,
|
||||
MOD_TELEFRAG);
|
||||
// nail it
|
||||
T_Damage (tr.ent, ent, ent, vec3_origin, ent->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
|
||||
|
||||
/* if we didn't kill it, fail */
|
||||
// if we didn't kill it, fail
|
||||
if (tr.ent->solid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true; /* all clear */
|
||||
return true; // all clear
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue