From 4d66d1798a184156ef4132920c73ac21dcc8fb3e Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Fri, 1 May 2026 14:05:27 +0300 Subject: [PATCH 1/9] workflows: add coverity --- .github/workflows/coverity.yml | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/coverity.yml diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml new file mode 100644 index 0000000..251e12c --- /dev/null +++ b/.github/workflows/coverity.yml @@ -0,0 +1,64 @@ +name: Coverity for Linux (aarch64) +run-name: Coverity_linux_aarch64 +on: + push: + branches: + - 'master' +concurrency: + # Cancel concurrent workflows for the same PR or commit hash. + group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}} + cancel-in-progress: true +jobs: + build_ubuntu_aarch64: + runs-on: ubuntu-24.04-arm + permissions: + actions: read + contents: read + strategy: + fail-fast: false + matrix: + include: + - env: ubuntu + steps: + - name: Install build dependencies + run: | + sudo apt update + sudo apt install libgl1-mesa-dev libsdl2-dev libopenal-dev libcurl4-openssl-dev \ + build-essential + - name: Check out repository code + uses: actions/checkout@v6 + with: + submodules: 'true' + - name: Download coverity + run: | + if [ -z "${{ secrets.COVERITY_SCAN_TOKEN }}" ]; then + echo "COVERITY_SCAN_TOKEN is not set. Skipping workflow." + else + wget https://scan.coverity.com/download/cxx/linux-ARM64 \ + --post-data "token=${{secrets.COVERITY_SCAN_TOKEN}}&project=${{github.repository}}" \ + -O coverity_tool.tgz -cq + tar -xf coverity_tool.tgz + mv -v cov-analysis-linux-arm64-* cov-analysis-linux-arm64 + fi + - name: Build + run: | + if [ -z "${{ secrets.COVERITY_SCAN_TOKEN }}" ]; then + echo "COVERITY_SCAN_TOKEN is not set. Skipping workflow." + else + rm -rf cov-int + make clean + cov-analysis-linux-arm64/bin/cov-build --dir cov-int make WITH_SDL3=no -j 4 + fi + - name: Upload result + run: | + if [ -z "${{ secrets.COVERITY_SCAN_TOKEN }}" ]; then + echo "COVERITY_SCAN_TOKEN is not set. Skipping workflow." + else + tar -czf cov-int.tgz cov-int + curl --form token=${{secrets.COVERITY_SCAN_TOKEN}} \ + --form email=${{secrets.COVERITY_SCAN_EMAIL}} \ + --form file=@cov-int.tgz \ + --form version="${{github.sha}}" \ + --form description="${{github.sha}}" \ + https://scan.coverity.com/builds?project=${{github.repository}} + fi From d1004dc47cd5f9709ddcc16a3452e430ce9f626d Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Fri, 1 May 2026 14:09:28 +0300 Subject: [PATCH 2/9] game: use randk() instead rand() --- src/g_ai.c | 2 +- src/g_ctf.c | 24 ++++++++++++------------ src/g_items.c | 2 +- src/g_misc.c | 4 ++-- src/g_monster.c | 2 +- src/g_utils.c | 2 +- src/g_weapon.c | 2 +- src/header/local.h | 14 +++++++------- src/monster/move.c | 6 +++--- src/player/client.c | 4 ++-- src/player/hud.c | 2 +- src/player/view.c | 6 +++--- src/player/weapon.c | 4 ++-- 13 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/g_ai.c b/src/g_ai.c index f796f3a..e6deea9 100644 --- a/src/g_ai.c +++ b/src/g_ai.c @@ -713,7 +713,7 @@ M_CheckAttack(edict_t *self) if (enemy_range == RANGE_MELEE) { /* don't always melee in easy mode */ - if ((skill->value == 0) && (rand() & 3)) + if ((skill->value == 0) && (randk() & 3)) { return false; } diff --git a/src/g_ctf.c b/src/g_ctf.c index 7227763..709fad8 100644 --- a/src/g_ctf.c +++ b/src/g_ctf.c @@ -533,7 +533,7 @@ CTFAssignTeam(gclient_t *who) { who->resp.ctf_team = CTF_TEAM2; } - else if (rand() & 1) + else if (randk() & 1) { who->resp.ctf_team = CTF_TEAM1; } @@ -617,7 +617,7 @@ SelectCTFSpawnPoint(edict_t *ent) count -= 2; } - selection = rand() % count; + selection = randk() % count; spot = NULL; @@ -1142,7 +1142,7 @@ CTFDeadDropFlag(edict_t *self) void CTFDrop_Flag(edict_t *ent, gitem_t *item) { - if (rand() & 1) + if (randk() & 1) { gi.cprintf(ent, PRINT_HIGH, "Only lusers drop flags.\n"); } @@ -2346,7 +2346,7 @@ static edict_t * FindTechSpawn(void) { edict_t *spot = NULL; - int i = rand() % 16; + int i = randk() % 16; while (i--) { @@ -2406,8 +2406,8 @@ CTFDeadDropTech(edict_t *ent) dropped = Drop_Item(ent, tech); /* hack the velocity to make it bounce random */ - dropped->velocity[0] = (rand() % 600) - 300; - dropped->velocity[1] = (rand() % 600) - 300; + dropped->velocity[0] = (randk() % 600) - 300; + dropped->velocity[1] = (randk() % 600) - 300; dropped->nextthink = level.time + CTF_TECH_TIMEOUT; dropped->think = TechThink; dropped->owner = NULL; @@ -2441,7 +2441,7 @@ SpawnTech(gitem_t *item, edict_t *spot) ent->owner = ent; angles[0] = 0; - angles[1] = rand() % 360; + angles[1] = randk() % 360; angles[2] = 0; AngleVectors(angles, forward, right, NULL); @@ -3273,7 +3273,7 @@ SP_misc_ctf_banner(edict_t *ent) ent->s.skinnum = 1; } - ent->s.frame = rand() % 16; + ent->s.frame = randk() % 16; gi.linkentity(ent); ent->think = misc_ctf_banner_think; @@ -3297,7 +3297,7 @@ SP_misc_ctf_small_banner(edict_t *ent) ent->s.skinnum = 1; } - ent->s.frame = rand() % 16; + ent->s.frame = randk() % 16; gi.linkentity(ent); ent->think = misc_ctf_banner_think; @@ -3466,7 +3466,7 @@ CTFAssignGhost(edict_t *ent) for ( ; ; ) { - ctfgame.ghosts[ghost].code = 10000 + (rand() % 90000); + ctfgame.ghosts[ghost].code = 10000 + (randk() % 90000); for (i = 0; i < MAX_CLIENTS; i++) { @@ -3533,7 +3533,7 @@ CTFStartMatch(void) ent->svflags = SVF_NOCLIENT; ent->flags &= ~FL_GODMODE; - ent->client->respawn_time = level.time + 1.0 + ((rand() % 30) / 10.0); + ent->client->respawn_time = level.time + 1.0 + ((randk() % 30) / 10.0); ent->client->ps.pmove.pm_type = PM_DEAD; ent->client->anim_priority = ANIM_DEATH; ent->s.frame = FRAME_death308 - 1; @@ -4199,7 +4199,7 @@ CTFUpdateJoinMenu(edict_t *ent) return CTF_TEAM2; } - return (rand() & 1) ? CTF_TEAM1 : CTF_TEAM2; + return (randk() & 1) ? CTF_TEAM1 : CTF_TEAM2; } void diff --git a/src/g_items.c b/src/g_items.c index d87f901..4488369 100644 --- a/src/g_items.c +++ b/src/g_items.c @@ -147,7 +147,7 @@ DoRespawn(edict_t *ent) { } - choice = rand() % count; + choice = randk() % count; for (count = 0, ent = master; count < choice; ent = ent->chain, count++) { diff --git a/src/g_misc.c b/src/g_misc.c index bc0a152..bb372f2 100644 --- a/src/g_misc.c +++ b/src/g_misc.c @@ -239,7 +239,7 @@ ThrowClientHead(edict_t *self, int damage) vec3_t vd; char *gibname; - if (rand() & 1) + if (randk() & 1) { gibname = "models/objects/gibs/head2/tris.md2"; self->s.skinnum = 1; /* second skin is player */ @@ -1391,7 +1391,7 @@ SP_misc_banner(edict_t *ent) ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_NOT; ent->s.modelindex = gi.modelindex("models/objects/banner/tris.md2"); - ent->s.frame = rand() % 16; + ent->s.frame = randk() % 16; gi.linkentity(ent); ent->think = misc_banner_think; diff --git a/src/g_monster.c b/src/g_monster.c index a01fb5d..127940a 100644 --- a/src/g_monster.c +++ b/src/g_monster.c @@ -683,7 +683,7 @@ monster_start(edict_t *self) if (self->monsterinfo.currentmove) { self->s.frame = self->monsterinfo.currentmove->firstframe + - (rand() % (self->monsterinfo.currentmove->lastframe - + (randk() % (self->monsterinfo.currentmove->lastframe - self->monsterinfo.currentmove->firstframe + 1)); } diff --git a/src/g_utils.c b/src/g_utils.c index fe53607..3070b59 100644 --- a/src/g_utils.c +++ b/src/g_utils.c @@ -174,7 +174,7 @@ G_PickTarget(char *targetname) return NULL; } - return choice[rand() % num_choices]; + return choice[randk() % num_choices]; } void diff --git a/src/g_weapon.c b/src/g_weapon.c index 4850e69..18ca8db 100644 --- a/src/g_weapon.c +++ b/src/g_weapon.c @@ -702,7 +702,7 @@ rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) if ((surf) && !(surf->flags & (SURF_WARP | SURF_TRANS33 | SURF_TRANS66 | SURF_FLOWING))) { - n = rand() % 5; + n = randk() % 5; while (n--) { diff --git a/src/header/local.h b/src/header/local.h index 1e4aece..67b46a9 100644 --- a/src/header/local.h +++ b/src/header/local.h @@ -496,12 +496,12 @@ extern int meansOfDeath; extern edict_t *g_edicts; -#define FOFS(x) (size_t)&(((edict_t *)0)->x) -#define STOFS(x) (size_t)&(((spawn_temp_t *)0)->x) -#define LLOFS(x) (size_t)&(((level_locals_t *)0)->x) -#define CLOFS(x) (size_t)&(((gclient_t *)0)->x) +#define FOFS(x) (size_t)&(((edict_t *)NULL)->x) +#define STOFS(x) (size_t)&(((spawn_temp_t *)NULL)->x) +#define LLOFS(x) (size_t)&(((level_locals_t *)NULL)->x) +#define CLOFS(x) (size_t)&(((gclient_t *)NULL)->x) -#define random() ((rand() & 0x7fff) / ((float)0x7fff)) +#define random() ((randk() & 0x7fff) / ((float)0x7fff)) #define crandom() (2.0 * (random() - 0.5)) extern cvar_t *maxentities; @@ -573,8 +573,8 @@ typedef enum typedef struct { - char *name; - int ofs; + const char *name; + size_t ofs; fieldtype_t type; int flags; } field_t; diff --git a/src/monster/move.c b/src/monster/move.c index 7db90c3..be66654 100644 --- a/src/monster/move.c +++ b/src/monster/move.c @@ -527,7 +527,7 @@ SV_NewChaseDir(edict_t *actor, edict_t *enemy, float dist) } /* try other directions */ - if (((rand() & 3) & 1) || (fabsf(deltay) > fabsf(deltax))) + if (((randk() & 3) & 1) || (fabsf(deltay) > fabsf(deltax))) { tdir = d[1]; d[1] = d[2]; @@ -552,7 +552,7 @@ SV_NewChaseDir(edict_t *actor, edict_t *enemy, float dist) return; } - if (rand() & 1) /*randomly determine direction of search*/ + if (randk() & 1) /*randomly determine direction of search*/ { for (tdir = 0; tdir <= 315; tdir += 45) { @@ -629,7 +629,7 @@ M_MoveToGoal(edict_t *ent, float dist) } /* bump around... */ - if (((rand() & 3) == 1) || !SV_StepDirection(ent, ent->ideal_yaw, dist)) + if (((randk() & 3) == 1) || !SV_StepDirection(ent, ent->ideal_yaw, dist)) { if (ent->inuse) { diff --git a/src/player/client.c b/src/player/client.c index 4baa349..aabbb1a 100644 --- a/src/player/client.c +++ b/src/player/client.c @@ -574,7 +574,7 @@ player_die(edict_t *self, edict_t *inflictor, edict_t *attacker, } gi.sound(self, CHAN_VOICE, gi.soundindex(va("*death%i.wav", - (rand() % 4) + 1)), 1, ATTN_NORM, 0); + (randk() % 4) + 1)), 1, ATTN_NORM, 0); } } @@ -778,7 +778,7 @@ SelectRandomDeathmatchSpawnPoint(void) count -= 2; } - selection = rand() % count; + selection = randk() % count; spot = NULL; diff --git a/src/player/hud.c b/src/player/hud.c index 7bd7f4b..c158795 100644 --- a/src/player/hud.c +++ b/src/player/hud.c @@ -166,7 +166,7 @@ BeginIntermission(edict_t *targ) else { /* chose one of four spots */ - i = rand() & 3; + i = randk() & 3; while (i--) { diff --git a/src/player/view.c b/src/player/view.c index d1d3cd2..472b0d3 100644 --- a/src/player/view.c +++ b/src/player/view.c @@ -148,7 +148,7 @@ P_DamageFeedback(edict_t *player) !(player->flags & FL_GODMODE) && (client->invincible_framenum <= level.framenum)) { - r = 1 + (rand() & 1); + r = 1 + (randk() & 1); player->pain_debounce_time = level.time + 0.7; if (player->health < 25) @@ -864,7 +864,7 @@ P_WorldEffects(void) gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/drown1.wav"), 1, ATTN_NORM, 0); } - else if (rand() & 1) + else if (randk() & 1) { gi.sound(current_player, CHAN_VOICE, gi.soundindex("*gurp1.wav"), 1, ATTN_NORM, 0); @@ -899,7 +899,7 @@ P_WorldEffects(void) (current_player->pain_debounce_time <= level.time) && (current_client->invincible_framenum < level.framenum)) { - if (rand() & 1) + if (randk() & 1) { gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/burn1.wav"), 1, ATTN_NORM, 0); diff --git a/src/player/weapon.c b/src/player/weapon.c index 587a789..d241277 100644 --- a/src/player/weapon.c +++ b/src/player/weapon.c @@ -567,7 +567,7 @@ Weapon_Generic2(edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, { if (ent->client->ps.gunframe == pause_frames[n]) { - if (rand() & 15) + if (randk() & 15) { return; } @@ -758,7 +758,7 @@ Weapon_Grenade(edict_t *ent) (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48)) { - if (rand() & 15) + if (randk() & 15) { return; } From 710ffd5f2405e845c5fec74e0aed5a5ff144fc43 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Fri, 1 May 2026 14:17:24 +0300 Subject: [PATCH 3/9] small style fix --- src/g_phys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_phys.c b/src/g_phys.c index 472f5ad..384443b 100644 --- a/src/g_phys.c +++ b/src/g_phys.c @@ -682,7 +682,7 @@ SV_Push(edict_t *pusher, vec3_t move, vec3_t amove) if (!block) { - /* pushed ok */ + /* pushed ok */ gi.linkentity(check); continue; } From d7b81d4f3278d6d56fbcf734cc049808c6b75ce8 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Fri, 1 May 2026 14:33:21 +0300 Subject: [PATCH 4/9] game: use const in functions --- src/g_main.c | 15 ------------- src/header/game.h | 52 ++++++++++++++++++++++----------------------- src/header/local.h | 19 ++++++++++++++++- src/header/shared.h | 2 +- 4 files changed, 45 insertions(+), 43 deletions(-) diff --git a/src/g_main.c b/src/g_main.c index 13ed634..690cf45 100644 --- a/src/g_main.c +++ b/src/g_main.c @@ -79,21 +79,6 @@ cvar_t *sv_maplist; cvar_t *aimfix; -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 diff --git a/src/header/game.h b/src/header/game.h index 41d8e1c..38970b6 100644 --- a/src/header/game.h +++ b/src/header/game.h @@ -111,33 +111,33 @@ typedef struct /* special messages */ void (*bprintf)(int printlevel, const char *fmt, ...); void (*dprintf)(const char *fmt, ...); - void (*cprintf)(edict_t *ent, int printlevel, const char *fmt, ...); - void (*centerprintf)(edict_t *ent, const char *fmt, ...); - void (*sound)(edict_t *ent, int channel, int soundindex, float volume, + void (*cprintf)(const edict_t *ent, int printlevel, const char *fmt, ...); + void (*centerprintf)(const edict_t *ent, const char *fmt, ...); + void (*sound)(const edict_t *ent, int channel, int soundindex, float volume, float attenuation, float timeofs); - void (*positioned_sound)(vec3_t origin, edict_t *ent, int channel, + void (*positioned_sound)(const vec3_t origin, const edict_t *ent, int channel, int soundinedex, float volume, float attenuation, float timeofs); /* config strings hold all the index strings, the lightstyles, and misc data like the sky definition and cdtrack. All of the current configstrings are sent to clients when they connect, and changes are sent to all connected clients. */ - void (*configstring)(int num, char *string); + void (*configstring)(int num, const char *string); YQ2_ATTR_NORETURN_FUNCPTR void (*error)(const char *fmt, ...); /* the *index functions create configstrings and some internal server state */ - int (*modelindex)(char *name); - int (*soundindex)(char *name); - int (*imageindex)(char *name); + int (*modelindex)(const char *name); + int (*soundindex)(const char *name); + int (*imageindex)(const char *name); - void (*setmodel)(edict_t *ent, char *name); + void (*setmodel)(edict_t *ent, const char *name); /* collision detection */ - trace_t (*trace)(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, - edict_t *passent, int contentmask); - int (*pointcontents)(vec3_t point); + trace_t (*trace)(const vec3_t start, const vec3_t mins, const vec3_t maxs, + const vec3_t end, const edict_t *passent, int contentmask); + int (*pointcontents)(const vec3_t point); qboolean (*inPVS)(vec3_t p1, vec3_t p2); qboolean (*inPHS)(vec3_t p1, vec3_t p2); void (*SetAreaPortalState)(int portalnum, qboolean open); @@ -148,21 +148,21 @@ typedef struct solidity changes, it must be relinked. */ void (*linkentity)(edict_t *ent); void (*unlinkentity)(edict_t *ent); /* call before removing an interactive edict */ - int (*BoxEdicts)(vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, + int (*BoxEdicts)(const vec3_t mins, const vec3_t maxs, edict_t **list, int maxcount, int areatype); void (*Pmove)(pmove_t *pmove); /* player movement code common with client prediction */ /* network messaging */ - void (*multicast)(vec3_t origin, multicast_t to); - void (*unicast)(edict_t *ent, qboolean reliable); + void (*multicast)(const vec3_t origin, multicast_t to); + void (*unicast)(const edict_t *ent, qboolean reliable); void (*WriteChar)(int c); void (*WriteByte)(int c); void (*WriteShort)(int c); void (*WriteLong)(int c); void (*WriteFloat)(float f); - void (*WriteString)(char *s); - void (*WritePosition)(vec3_t pos); /* some fractional bits */ - void (*WriteDir)(vec3_t pos); /* single byte encoded, very coarse */ + void (*WriteString)(const char *s); + void (*WritePosition)(const vec3_t pos); /* some fractional bits */ + void (*WriteDir)(const vec3_t pos); /* single byte encoded, very coarse */ void (*WriteAngle)(float f); /* managed memory allocation */ @@ -173,7 +173,7 @@ typedef struct /* console variable interaction */ cvar_t *(*cvar)(const char *var_name, const char *value, int flags); cvar_t *(*cvar_set)(const char *var_name, const char *value); - cvar_t *(*cvar_forceset)(const char *var_name, char *value); + cvar_t *(*cvar_forceset)(const char *var_name, const char *value); /* ClientCommand and ServerCommand parameter access */ int (*argc)(void); @@ -182,7 +182,7 @@ typedef struct /* add commands to the server console as if they were typed in for map changing, etc */ - void (*AddCommandString)(char *text); + void (*AddCommandString)(const char *text); void (*DebugGraph)(float value, int color); } game_import_t; @@ -199,20 +199,20 @@ typedef struct void (*Shutdown)(void); /* each new level entered will cause a call to SpawnEntities */ - void (*SpawnEntities)(char *mapname, char *entstring, char *spawnpoint); + void (*SpawnEntities)(const char *mapname, char *entstring, const char *spawnpoint); /* Read/Write Game is for storing persistant cross level information about the world state and the clients. WriteGame is called every time a level is exited. ReadGame is called on a loadgame. */ - void (*WriteGame)(char *filename, qboolean autosave); - void (*ReadGame)(char *filename); + void (*WriteGame)(const char *filename, qboolean autosave); + void (*ReadGame)(const char *filename); /* ReadLevel is called after the default map information has been loaded with SpawnEntities */ - void (*WriteLevel)(char *filename); - void (*ReadLevel)(char *filename); + void (*WriteLevel)(const char *filename); + void (*ReadLevel)(const char *filename); qboolean (*ClientConnect)(edict_t *ent, char *userinfo); void (*ClientBegin)(edict_t *ent); @@ -224,7 +224,7 @@ typedef struct void (*RunFrame)(void); /* ServerCommand will be called when an "sv " - command is issued on the server console. The game can + command is issued on the server console. The game can issue gi.argc() / gi.argv() commands to get the rest of the parameters */ void (*ServerCommand)(void); diff --git a/src/header/local.h b/src/header/local.h index 67b46a9..6e92edc 100644 --- a/src/header/local.h +++ b/src/header/local.h @@ -582,9 +582,19 @@ typedef struct extern field_t fields[]; extern gitem_t itemlist[]; +/* player/client.c */ +void ClientBegin(edict_t *ent); +void ClientDisconnect(edict_t *ent); +void ClientUserinfoChanged(edict_t *ent, char *userinfo); +qboolean ClientConnect(edict_t *ent, char *userinfo); +void ClientThink(edict_t *ent, usercmd_t *cmd); +void RunEntity(edict_t *ent); +void G_RunFrame(void); + /* g_cmds.c */ qboolean CheckFlood(edict_t *ent); void Cmd_Help_f(edict_t *ent); +void ClientCommand(edict_t *ent); void Cmd_Score_f(edict_t *ent); /* g_items.c */ @@ -741,7 +751,6 @@ void InitClientPersistant(gclient_t *client); void InitClientResp(gclient_t *client); void InitBodyQue(void); void ClientBeginServerFrame(edict_t *ent); -void ClientUserinfoChanged(edict_t *ent, char *userinfo); /* g_player.c */ void player_pain(edict_t *self, edict_t *other, float kick, int damage); @@ -785,6 +794,14 @@ void EndDMLevel(void); /* g_svcmds.c */ qboolean SV_FilterPacket(char *from); +/* savegame */ +void InitGame(void); +void ReadLevel(const char *filename); +void WriteLevel(const char *filename); +void ReadGame(const char *filename); +void WriteGame(const char *filename, qboolean autosave); +void SpawnEntities(const char *mapname, char *entities, const char *spawnpoint); + /* ============================================================================ */ /* client_t->anim_priority */ diff --git a/src/header/shared.h b/src/header/shared.h index 0bf8584..a06b06b 100644 --- a/src/header/shared.h +++ b/src/header/shared.h @@ -708,7 +708,7 @@ typedef struct /* callbacks to test the world */ trace_t (*trace)(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end); - int (*pointcontents)(vec3_t point); + int (*pointcontents)(const vec3_t point); } pmove_t; /* entity_state_t->effects From f4565f206a82b03e1a1fbdf25f04428988477ac8 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Fri, 1 May 2026 16:09:28 +0300 Subject: [PATCH 5/9] game: make gitem_t operations const --- src/g_ai.c | 117 ++++++++--- src/g_cmds.c | 207 +++++++++++++------ src/g_combat.c | 115 +++++++---- src/g_ctf.c | 94 ++++----- src/g_func.c | 42 ++-- src/g_items.c | 295 ++++++++++++++++++++------ src/g_misc.c | 488 ++++++++++++++++++++++++++++++++++++++++---- src/g_trigger.c | 34 +-- src/g_utils.c | 106 +++++++--- src/g_weapon.c | 24 +-- src/header/ctf.h | 4 +- src/header/local.h | 145 +++++++------ src/player/client.c | 233 ++++++++++++++++++--- src/player/hud.c | 8 +- src/player/view.c | 103 +++++++--- src/player/weapon.c | 182 +++++++++++++++-- 16 files changed, 1704 insertions(+), 493 deletions(-) diff --git a/src/g_ai.c b/src/g_ai.c index e6deea9..6a56635 100644 --- a/src/g_ai.c +++ b/src/g_ai.c @@ -117,6 +117,11 @@ ai_stand(edict_t *self, float dist) { vec3_t v; + if (!self) + { + return; + } + if (dist) { M_walkmove(self, self->s.angles[YAW], dist); @@ -132,8 +137,7 @@ ai_stand(edict_t *self, float dist) if ((self->s.angles[YAW] != self->ideal_yaw) && self->monsterinfo.aiflags & AI_TEMP_STAND_GROUND) { - self->monsterinfo.aiflags &= - ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND); + self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND); self->monsterinfo.run(self); } @@ -180,6 +184,11 @@ ai_stand(edict_t *self, float dist) void ai_walk(edict_t *self, float dist) { + if (!self) + { + return; + } + M_MoveToGoal(self, dist); /* check for noticing a player */ @@ -212,7 +221,16 @@ ai_charge(edict_t *self, float dist) { vec3_t v; - VectorSubtract(self->enemy->s.origin, self->s.origin, v); + if (!self) + { + return; + } + + if(self->enemy) + { + VectorSubtract(self->enemy->s.origin, self->s.origin, v); + } + self->ideal_yaw = vectoyaw(v); M_ChangeYaw(self); @@ -230,6 +248,11 @@ ai_charge(edict_t *self, float dist) void ai_turn(edict_t *self, float dist) { + if (!self) + { + return; + } + if (dist) { M_walkmove(self, self->s.angles[YAW], dist); @@ -244,7 +267,6 @@ ai_turn(edict_t *self, float dist) } /* - * * .enemy * Will be world if not currently angry at anyone. * @@ -285,6 +307,11 @@ range(edict_t *self, edict_t *other) vec3_t v; float len; + if (!self || !other) + { + return 0; + } + VectorSubtract(self->s.origin, other->s.origin, v); len = VectorLength(v); @@ -308,15 +335,20 @@ range(edict_t *self, edict_t *other) /* * returns 1 if the entity is visible - * to self, even if not infront (). + * to self, even if not infront() */ qboolean -visible(edict_t *self, edict_t *other) +visible(const edict_t *self, const edict_t *other) { vec3_t spot1; vec3_t spot2; trace_t trace; + if (!self || !other) + { + return false; + } + VectorCopy(self->s.origin, spot1); spot1[2] += self->viewheight; VectorCopy(other->s.origin, spot2); @@ -332,7 +364,8 @@ visible(edict_t *self, edict_t *other) } /* - * returns 1 if the entity is in front (in sight) of self + * returns 1 if the entity is in + * front (in sight) of self */ qboolean infront(edict_t *self, edict_t *other) @@ -341,18 +374,12 @@ infront(edict_t *self, edict_t *other) float dot; vec3_t forward; - if ((self == NULL) || (other == NULL)) + if (!self || !other) { return false; } AngleVectors(self->s.angles, forward, NULL, NULL); - - if ((self == NULL) || (other == NULL)) - { - return false; - } - VectorSubtract(other->s.origin, self->s.origin, vec); VectorNormalize(vec); dot = DotProduct(vec, forward); @@ -372,6 +399,11 @@ HuntTarget(edict_t *self) { vec3_t vec; + if (!self) + { + return; + } + self->goalentity = self->enemy; if (self->monsterinfo.aiflags & AI_STAND_GROUND) @@ -396,6 +428,11 @@ HuntTarget(edict_t *self) void FoundTarget(edict_t *self) { + if (!self|| !self->enemy || !self->enemy->inuse) + { + return; + } + /* let other monsters see this monster for a while */ if (self->enemy->client) { @@ -404,7 +441,7 @@ FoundTarget(edict_t *self) level.sight_entity->light_level = 128; } - self->show_hostile = (int)level.time + 1; /* wake up other monsters */ + self->show_hostile = level.time + 1; /* wake up other monsters */ VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting); self->monsterinfo.trail_time = level.time; @@ -463,6 +500,11 @@ FindTarget(edict_t *self) qboolean heardit; int r; + if (!self) + { + return false; + } + if (self->monsterinfo.aiflags & AI_GOOD_GUY) { return false; @@ -577,7 +619,7 @@ FindTarget(edict_t *self) if (r == RANGE_NEAR) { - if ((client->show_hostile < (int)level.time) && !infront(self, client)) + if ((client->show_hostile < level.time) && !infront(self, client)) { return false; } @@ -629,7 +671,7 @@ FindTarget(edict_t *self) VectorSubtract(client->s.origin, self->s.origin, temp); - if (VectorLength(temp) > 1000) /* too far to hear */ + if (VectorLength(temp) > 1000) /* too far to hear */ { return false; } @@ -667,10 +709,15 @@ FindTarget(edict_t *self) /* ============================================================================= */ qboolean -FacingIdeal(edict_t *self) +FacingIdeal(const edict_t *self) { float delta; + if (!self) + { + return false; + } + delta = anglemod(self->s.angles[YAW] - self->ideal_yaw); if ((delta > 45) && (delta < 315)) @@ -690,6 +737,11 @@ M_CheckAttack(edict_t *self) float chance; trace_t tr; + if (!self || !self->enemy || !self->enemy->inuse) + { + return false; + } + if (self->enemy->health > 0) { /* see if any entities are in the way of the shot */ @@ -713,7 +765,7 @@ M_CheckAttack(edict_t *self) if (enemy_range == RANGE_MELEE) { /* don't always melee in easy mode */ - if ((skill->value == 0) && (randk() & 3)) + if ((skill->value == SKILL_EASY) && (randk() & 3)) { return false; } @@ -767,11 +819,11 @@ M_CheckAttack(edict_t *self) return false; } - if (skill->value == 0) + if (skill->value == SKILL_EASY) { chance *= 0.5; } - else if (skill->value >= 2) + else if (skill->value >= SKILL_HARD) { chance *= 2; } @@ -805,6 +857,11 @@ M_CheckAttack(edict_t *self) void ai_run_melee(edict_t *self) { + if (!self) + { + return; + } + self->ideal_yaw = enemy_yaw; M_ChangeYaw(self); @@ -825,6 +882,11 @@ ai_run_melee(edict_t *self) void ai_run_missile(edict_t *self) { + if (!self) + { + return; + } + self->ideal_yaw = enemy_yaw; M_ChangeYaw(self); @@ -847,6 +909,11 @@ ai_run_slide(edict_t *self, float distance) { float ofs; + if (!self) + { + return; + } + self->ideal_yaw = enemy_yaw; M_ChangeYaw(self); @@ -986,7 +1053,7 @@ ai_checkattack(edict_t *self, float dist) } } - self->show_hostile = (int)level.time + 1; /* wake up other monsters */ + self->show_hostile = level.time + 1; /* wake up other monsters */ /* check knowledge of enemy */ enemy_vis = visible(self, self->enemy); @@ -1041,6 +1108,11 @@ ai_run(edict_t *self, float dist) float left, center, right; vec3_t left_target, right_target; + if (!self) + { + return; + } + /* if we're going to a combat point, just proceed */ if (self->monsterinfo.aiflags & AI_COMBAT_POINT) { @@ -1233,4 +1305,3 @@ ai_run(edict_t *self, float dist) self->goalentity = save; } } - diff --git a/src/g_cmds.c b/src/g_cmds.c index eeeb2d1..76b457c 100644 --- a/src/g_cmds.c +++ b/src/g_cmds.c @@ -28,18 +28,23 @@ #include "monster/player.h" static char * -ClientTeam(edict_t *ent, char* value) +ClientTeam(const edict_t *ent, char* value, size_t val_len) { char *p; value[0] = 0; + if (!ent) + { + return value; + } + if (!ent->client) { return value; } - strcpy(value, Info_ValueForKey(ent->client->pers.userinfo, "skin")); + Q_strlcpy(value, Info_ValueForKey(ent->client->pers.userinfo, "skin"), val_len); p = strchr(value, '/'); if (!p) @@ -57,18 +62,23 @@ ClientTeam(edict_t *ent, char* value) } qboolean -OnSameTeam(edict_t *ent1, edict_t *ent2) +OnSameTeam(const edict_t *ent1, const edict_t *ent2) { char ent1Team[512]; char ent2Team[512]; + if (!ent1 || !ent2) + { + return false; + } + if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) { return false; } - ClientTeam(ent1, ent1Team); - ClientTeam(ent2, ent2Team); + ClientTeam(ent1, ent1Team, sizeof(ent1Team)); + ClientTeam(ent2, ent2Team, sizeof(ent2Team)); if (ent1Team[0] != '\0' && strcmp(ent1Team, ent2Team) == 0) { @@ -196,7 +206,7 @@ ValidateSelectedItem(edict_t *ent) /* * Give items to a client */ -void +static void Cmd_Give_f(edict_t *ent) { char *name; @@ -206,9 +216,14 @@ Cmd_Give_f(edict_t *ent) qboolean give_all; edict_t *it_ent; + if (!ent) + { + return; + } + if (deathmatch->value && !sv_cheats->value) { - gi.cprintf( ent, PRINT_HIGH, + gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } @@ -294,7 +309,7 @@ Cmd_Give_f(edict_t *ent) if (give_all || (Q_stricmp(name, "armor") == 0)) { - gitem_armor_t *info; + const gitem_armor_t *info; it = FindItem("Jacket Armor"); ent->client->pers.inventory[ITEM_INDEX(it)] = 0; @@ -403,14 +418,19 @@ Cmd_Give_f(edict_t *ent) /* * Sets client to godmode */ -void +static void Cmd_God_f(edict_t *ent) { char *msg; + if (!ent) + { + return; + } + if (deathmatch->value && !sv_cheats->value) { - gi.cprintf( ent, PRINT_HIGH, + gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } @@ -432,14 +452,19 @@ Cmd_God_f(edict_t *ent) /* * Sets client to notarget */ -void +static void Cmd_Notarget_f(edict_t *ent) { char *msg; + if (!ent) + { + return; + } + if (deathmatch->value && !sv_cheats->value) { - gi.cprintf( ent, PRINT_HIGH, + gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } @@ -458,14 +483,22 @@ Cmd_Notarget_f(edict_t *ent) gi.cprintf(ent, PRINT_HIGH, msg); } -void +/* + * argv(0) noclip + */ +static void Cmd_Noclip_f(edict_t *ent) { char *msg; + if (!ent) + { + return; + } + if (deathmatch->value && !sv_cheats->value) { - gi.cprintf( ent, PRINT_HIGH, + gi.cprintf(ent, PRINT_HIGH, "You must run the server with '+set cheats 1' to enable this command.\n"); return; } @@ -487,13 +520,18 @@ Cmd_Noclip_f(edict_t *ent) /* * Use an inventory item */ -void +static void Cmd_Use_f(edict_t *ent) { int index; gitem_t *it; char *s; + if (!ent) + { + return; + } + s = gi.args(); it = FindItem(s); @@ -523,13 +561,18 @@ Cmd_Use_f(edict_t *ent) /* * Drop an inventory item */ -void +static void Cmd_Drop_f(edict_t *ent) { int index; - gitem_t *it; + const gitem_t *it; char *s; + if (!ent) + { + return; + } + if ((Q_stricmp(gi.args(), "tech") == 0) && ((it = CTFWhat_Tech(ent)) != NULL)) { it->drop(ent, it); @@ -562,12 +605,17 @@ Cmd_Drop_f(edict_t *ent) it->drop(ent, it); } -void +const void Cmd_Inven_f(edict_t *ent) { int i; gclient_t *cl; + if (!ent) + { + return; + } + cl = ent->client; cl->showscores = false; @@ -604,11 +652,16 @@ Cmd_Inven_f(edict_t *ent) gi.unicast(ent, true); } -void +static void Cmd_InvUse_f(edict_t *ent) { gitem_t *it; + if (!ent) + { + return; + } + if (ent->client->menu) { PMenu_Select(ent); @@ -634,22 +687,7 @@ Cmd_InvUse_f(edict_t *ent) it->use(ent, it); } -void -Cmd_LastWeap_f(edict_t *ent) -{ - gclient_t *cl; - - cl = ent->client; - - if (!cl->pers.weapon || !cl->pers.lastweapon) - { - return; - } - - cl->pers.lastweapon->use(ent, cl->pers.lastweapon); -} - -void +static void Cmd_WeapPrev_f(edict_t *ent) { gclient_t *cl; @@ -657,6 +695,11 @@ Cmd_WeapPrev_f(edict_t *ent) gitem_t *it; int selected_weapon; + if (!ent) + { + return; + } + cl = ent->client; if (!cl->pers.weapon) @@ -697,14 +740,19 @@ Cmd_WeapPrev_f(edict_t *ent) } } -void +static void Cmd_WeapNext_f(edict_t *ent) { gclient_t *cl; int i, index; - gitem_t *it; + const gitem_t *it; int selected_weapon; + if (!ent) + { + return; + } + cl = ent->client; if (!cl->pers.weapon) @@ -745,13 +793,18 @@ Cmd_WeapNext_f(edict_t *ent) } } -void +static void Cmd_WeapLast_f(edict_t *ent) { gclient_t *cl; int index; gitem_t *it; + if (!ent) + { + return; + } + cl = ent->client; if (!cl->pers.weapon || !cl->pers.lastweapon) @@ -781,11 +834,16 @@ Cmd_WeapLast_f(edict_t *ent) it->use(ent, it); } -void +static void Cmd_InvDrop_f(edict_t *ent) { gitem_t *it; + if (!ent) + { + return; + } + ValidateSelectedItem(ent); if (ent->client->pers.selected_item == -1) @@ -805,9 +863,14 @@ Cmd_InvDrop_f(edict_t *ent) it->drop(ent, it); } -void +static void Cmd_Kill_f(edict_t *ent) { + if (!ent) + { + return; + } + if (ent->solid == SOLID_NOT) { return; @@ -824,9 +887,14 @@ Cmd_Kill_f(edict_t *ent) player_die(ent, ent, ent, 100000, vec3_origin); } -void +static void Cmd_PutAway_f(edict_t *ent) { + if (!ent) + { + return; + } + ent->client->showscores = false; ent->client->showhelp = false; ent->client->showinventory = false; @@ -839,11 +907,16 @@ Cmd_PutAway_f(edict_t *ent) ent->client->update_chase = true; } -int +static int PlayerSort(void const *a, void const *b) { int anum, bnum; + if (!a || !b) + { + return 0; + } + anum = *(int *)a; bnum = *(int *)b; @@ -863,14 +936,19 @@ PlayerSort(void const *a, void const *b) return 0; } -void +static void Cmd_Players_f(edict_t *ent) { int i; int count; char small[64]; char large[1280]; - int index[256]; + int index[256] = {0}; + + if (!ent) + { + return; + } count = 0; @@ -896,23 +974,28 @@ Cmd_Players_f(edict_t *ent) game.clients[index[i]].pers.netname); if (strlen(small) + strlen(large) > sizeof(large) - 100) - { + { /* can't print all of them in one packet */ - strcat(large, "...\n"); + Q_strlcat(large, "...\n", sizeof(large)); break; } - strcat(large, small); + Q_strlcat(large, small, sizeof(large)); } gi.cprintf(ent, PRINT_HIGH, "%s\n%i players\n", large, count); } -void +static void Cmd_Wave_f(edict_t *ent) { int i; + if (!ent) + { + return; + } + i = atoi(gi.argv(1)); /* can't wave when ducked */ @@ -1001,14 +1084,18 @@ CheckFlood(edict_t *ent) return false; } -void +static void Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0) { int j; - edict_t *other; char *p; char text[2048]; + if (!ent) + { + return; + } + if ((gi.argc() < 2) && !arg0) { return; @@ -1030,9 +1117,9 @@ Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0) if (arg0) { - strcat(text, gi.argv(0)); - strcat(text, " "); - strcat(text, gi.args()); + Q_strlcat(text, gi.argv(0), sizeof(text)); + Q_strlcat(text, " ", sizeof(text)); + Q_strlcat(text, gi.args(), sizeof(text)); } else { @@ -1044,7 +1131,7 @@ Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0) p[strlen(p) - 1] = 0; } - strcat(text, p); + Q_strlcat(text, p, sizeof(text)); } /* don't let text be too long for malicious reasons */ @@ -1053,7 +1140,7 @@ Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0) text[150] = 0; } - strcat(text, "\n"); + Q_strlcat(text, "\n", sizeof(text)); if (CheckFlood(ent)) { @@ -1067,6 +1154,8 @@ Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0) for (j = 1; j <= game.maxclients; j++) { + edict_t *other; + other = &g_edicts[j]; if (!other->inuse) @@ -1094,7 +1183,12 @@ Cmd_Say_f(edict_t *ent, qboolean team, qboolean arg0) void ClientCommand(edict_t *ent) { - char *cmd; + const char *cmd; + + if (!ent) + { + return; + } if (!ent->client) { @@ -1280,4 +1374,3 @@ ClientCommand(edict_t *ent) Cmd_Say_f(ent, false, true); } } - diff --git a/src/g_combat.c b/src/g_combat.c index 31bfc2c..7c72301 100644 --- a/src/g_combat.c +++ b/src/g_combat.c @@ -27,7 +27,7 @@ #include "header/local.h" /* - * Returns true if the inflictor can + * Returns true if the inflictor can * directly damage the target. Used for * explosions and melee attacks. */ @@ -37,6 +37,11 @@ CanDamage(edict_t *targ, edict_t *inflictor) vec3_t dest; trace_t trace; + if (!targ || !inflictor) + { + return false; + } + /* bmodels need special checking because their origin is 0,0,0 */ if (targ->movetype == MOVETYPE_PUSH) { @@ -113,10 +118,15 @@ CanDamage(edict_t *targ, edict_t *inflictor) return false; } -void +static void Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) + int damage, const vec3_t point) { + if (!targ || !inflictor || !attacker) + { + return; + } + if (targ->health < -999) { targ->health = -999; @@ -136,7 +146,7 @@ Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker, } /* medics won't heal monsters that they kill themselves */ - if (strcmp(attacker->classname, "monster_medic") == 0) + if (attacker->classname && strcmp(attacker->classname, "monster_medic") == 0) { targ->owner = attacker; } @@ -144,8 +154,9 @@ Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker, } if ((targ->movetype == MOVETYPE_PUSH) || - (targ->movetype == MOVETYPE_STOP) || (targ->movetype == MOVETYPE_NONE)) - { + (targ->movetype == MOVETYPE_STOP) || + (targ->movetype == MOVETYPE_NONE)) + { /* doors, triggers, etc */ targ->die(targ, inflictor, attacker, damage, point); return; @@ -160,14 +171,9 @@ Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker, targ->die(targ, inflictor, attacker, damage, point); } -void -SpawnDamage(int type, vec3_t origin, vec3_t normal, int damage) +static void +SpawnDamage(int type, const vec3_t origin, const vec3_t normal) { - if (damage > 255) - { - damage = 255; - } - gi.WriteByte(svc_temp_entity); gi.WriteByte(type); gi.WritePosition(origin); @@ -196,7 +202,7 @@ SpawnDamage(int type, vec3_t origin, vec3_t normal, int damage) * ============ */ static int -CheckPowerArmor(edict_t *ent, vec3_t point, vec3_t normal, +CheckPowerArmor(edict_t *ent, const vec3_t point, const vec3_t normal, int damage, int dflags) { gclient_t *client; @@ -208,11 +214,18 @@ CheckPowerArmor(edict_t *ent, vec3_t point, vec3_t normal, int power = 0; int power_used; + if (!ent) + { + return 0; + } + if (!damage) { return 0; } + index = 0; + client = ent->client; if (dflags & DAMAGE_NO_ARMOR) @@ -291,7 +304,7 @@ CheckPowerArmor(edict_t *ent, vec3_t point, vec3_t normal, save = damage; } - SpawnDamage(pa_te_type, point, normal, save); + SpawnDamage(pa_te_type, point, normal); ent->powerarmor_time = level.time + 0.2; power_used = save / damagePerCell; @@ -309,13 +322,18 @@ CheckPowerArmor(edict_t *ent, vec3_t point, vec3_t normal, } static int -CheckArmor(edict_t *ent, vec3_t point, vec3_t normal, - int damage, int te_sparks, int dflags) +CheckArmor(edict_t *ent, vec3_t point, const vec3_t normal, int damage, + int te_sparks, int dflags) { gclient_t *client; int save; int index; - gitem_t *armor; + const gitem_t *armor; + + if (!ent) + { + return 0; + } if (!damage) { @@ -363,7 +381,7 @@ CheckArmor(edict_t *ent, vec3_t point, vec3_t normal, } client->pers.inventory[index] -= save; - SpawnDamage(te_sparks, point, normal, save); + SpawnDamage(te_sparks, point, normal); return save; } @@ -371,6 +389,16 @@ CheckArmor(edict_t *ent, vec3_t point, vec3_t normal, void M_ReactToDamage(edict_t *targ, edict_t *attacker) { + if (!targ || !attacker) + { + return; + } + + if (targ->health <= 0) + { + return; + } + if (!(attacker->client) && !(attacker->svflags & SVF_MONSTER)) { return; @@ -381,8 +409,8 @@ M_ReactToDamage(edict_t *targ, edict_t *attacker) return; } - /* if we are a good guy monster and our - attacker is a player or another good + /* if we are a good guy monster and our + attacker is a player or another good guy, do not get mad at them */ if (targ->monsterinfo.aiflags & AI_GOOD_GUY) { @@ -392,13 +420,13 @@ M_ReactToDamage(edict_t *targ, edict_t *attacker) } } - /* if attacker is a client, get mad at + /* if attacker is a client, get mad at them because he's good and we're not */ if (attacker->client) { - /* this can only happen in coop (both + /* this can only happen in coop (both new and old enemies are clients) - only switch if can't see the + only switch if can't see the current enemy */ if (targ->enemy && targ->enemy->client) { @@ -422,7 +450,7 @@ M_ReactToDamage(edict_t *targ, edict_t *attacker) } /* it's the same base (walk/swim/fly) type - and a different classname and it's not a tank + and a different classname and it's not a tank (they spray too much), get mad at them */ if (((targ->flags & (FL_FLY | FL_SWIM)) == (attacker->flags & (FL_FLY | FL_SWIM))) && @@ -478,9 +506,9 @@ CheckTeamDamage(edict_t *targ, edict_t *attacker) } 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) +T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir, + vec3_t point, const vec3_t normal, int damage, int knockback, int dflags, + int mod) { gclient_t *client; int take; @@ -489,14 +517,19 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, int psave; int te_sparks; + if (!targ || !inflictor || !attacker) + { + return; + } + if (!targ->takedamage) { return; } - /* friendly fire avoidance + /* friendly fire avoidance if enabled you can't hurt - teammates (but you can hurt + teammates (but you can hurt yourself) knockback still occurs */ if ((targ != attacker) && ((deathmatch->value && @@ -519,7 +552,7 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, meansOfDeath = mod; /* easy mode takes half damage */ - if ((skill->value == 0) && (deathmatch->value == 0) && targ->client) + if ((skill->value == SKILL_EASY) && (deathmatch->value == 0) && targ->client) { damage *= 0.5; @@ -598,7 +631,7 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, { take = 0; save = damage; - SpawnDamage(te_sparks, point, normal, save); + SpawnDamage(te_sparks, point, normal); } /* check for invincibility */ @@ -651,11 +684,11 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, { if ((targ->svflags & SVF_MONSTER) || (client)) { - SpawnDamage(TE_BLOOD, point, normal, take); + SpawnDamage(TE_BLOOD, point, normal); } else { - SpawnDamage(te_sparks, point, normal, take); + SpawnDamage(te_sparks, point, normal); } if (!CTFMatchSetup()) @@ -684,7 +717,7 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, targ->pain(targ, attacker, knockback, take); /* nightmare mode monsters don't go into pain frames often */ - if (skill->value == 3) + if (skill->value == SKILL_HARDPLUS) { targ->pain_debounce_time = level.time + 5; } @@ -705,10 +738,10 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, } } - /* add to the damage inflicted on a + /* add to the damage inflicted on a player this frame the total will - be turned into screen blends and - view angle kicks at the end of + be turned into screen blends and + view angle kicks at the end of the frame */ if (client) { @@ -722,12 +755,16 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, void T_RadiusDamage(edict_t *inflictor, edict_t *attacker, float damage, - edict_t *ignore, float radius, int mod) + const edict_t *ignore, float radius, int mod) { float points; edict_t *ent = NULL; vec3_t v; vec3_t dir; + if (!inflictor || !attacker) + { + return; + } while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL) { diff --git a/src/g_ctf.c b/src/g_ctf.c index 709fad8..c26f2d2 100644 --- a/src/g_ctf.c +++ b/src/g_ctf.c @@ -85,7 +85,7 @@ cvar_t *warp_list; cvar_t *warn_unbalanced; /* Index for various CTF pics, this saves us - * from calling gi.imageindex all the time + * from calling gi.imageindex all the time * and saves a few CPU cycles since we don't * have to do a bunch of string compares all * the time. * These are set in CTFPrecache() @@ -249,7 +249,7 @@ stuffcmd(edict_t *ent, char *s) /*--------------------------------------------------------------------------*/ /* - * Returns entities that have + * Returns entities that have * origins within a spherical area */ static edict_t * @@ -640,7 +640,7 @@ SelectCTFSpawnPoint(edict_t *ent) /* * Calculate the bonuses for flag defense, * flag carrier defense, etc. Note that b - * onuses are not cumaltive. You get one, + * onuses are not cumaltive. You get one, * they are in importance order. */ void @@ -705,7 +705,7 @@ CTFFragBonuses(edict_t *targ, edict_t *inflictor, edict_t *attacker) CTF_FRAG_CARRIER_BONUS); /* the target had the flag, clear - the hurt carrier field on the + the hurt carrier field on the other team */ for (i = 1; i <= maxclients->value; i++) { @@ -725,8 +725,8 @@ CTFFragBonuses(edict_t *targ, edict_t *inflictor, edict_t *attacker) CTF_CARRIER_DANGER_PROTECT_TIMEOUT) && !attacker->client->pers.inventory[ITEM_INDEX(flag_item)]) { - /* attacker is on the same team - as the flag carrier and + /* attacker is on the same team + as the flag carrier and fragged a guy who hurt our flag carrier */ attacker->client->resp.score += CTF_CARRIER_DANGER_PROTECT_BONUS; @@ -743,8 +743,8 @@ CTFFragBonuses(edict_t *targ, edict_t *inflictor, edict_t *attacker) return; } - /* flag and flag carrier area defense bonuses - we have to find the flag and carrier entities + /* flag and flag carrier area defense bonuses + we have to find the flag and carrier entities find the flag */ switch (attacker->client->resp.ctf_team) { @@ -940,7 +940,7 @@ CTFPickup_Flag(edict_t *ent, edict_t *other) return false; } - /* same team, if the flag at base, + /* same team, if the flag at base, check to he has the enemy flag */ if (ctf_team == CTF_TEAM1) { @@ -1058,9 +1058,9 @@ CTFPickup_Flag(edict_t *ent, edict_t *other) other->client->pers.inventory[ITEM_INDEX(flag_item)] = 1; other->client->resp.ctf_flagsince = level.time; - /* pick up the flag - if it's not a dropped flag, - we just make is disappear + /* pick up the flag + if it's not a dropped flag, + we just make is disappear if it's dropped, it will be removed by the pickup caller */ if (!(ent->spawnflags & DROPPED_ITEM)) @@ -1075,7 +1075,7 @@ CTFPickup_Flag(edict_t *ent, edict_t *other) static void CTFDropFlagTouch(edict_t *ent, edict_t *other, - cplane_t *plane, csurface_t *surf) + const cplane_t *plane, const csurface_t *surf) { /* owner (who dropped us) can't touch for two secs */ if ((other == ent->owner) && @@ -1090,8 +1090,8 @@ CTFDropFlagTouch(edict_t *ent, edict_t *other, static void CTFDropFlagThink(edict_t *ent) { - /* auto return the flag - reset flag will remove + /* auto return the flag + reset flag will remove ourselves */ if (strcmp(ent->classname, "item_flag_team1") == 0) { @@ -1107,7 +1107,7 @@ CTFDropFlagThink(edict_t *ent) } } -/* +/* * Called from PlayerDie, to drop * the flag from a dying player */ @@ -1140,7 +1140,7 @@ CTFDeadDropFlag(edict_t *self) } void -CTFDrop_Flag(edict_t *ent, gitem_t *item) +CTFDrop_Flag(edict_t *ent, const gitem_t *item) { if (randk() & 1) { @@ -1241,8 +1241,8 @@ CTFEffects(edict_t *player) } } -/* - * Called when we enter the intermission +/* + * Called when we enter the intermission */ void CTFCalcScores(void) @@ -1406,7 +1406,7 @@ SetCTFStats(edict_t *ent) /* if during intermission, we must blink the team header of the winning team */ if (level.intermissiontime && (level.framenum & 8)) /* blink 1/8th second */ - { + { /* note that ctfgame.total[12] is set when we go to intermission */ if (ctfgame.team1 > ctfgame.team2) @@ -1449,9 +1449,9 @@ SetCTFStats(edict_t *ent) } /* figure out what icon to display for team logos - three states: + three states: flag at base - flag taken + flag taken flag dropped */ p1 = imageindex_i_ctf1; e = G_Find(NULL, FOFS(classname), "item_flag_team1"); @@ -1462,7 +1462,7 @@ SetCTFStats(edict_t *ent) { int i; - /* not at base + /* not at base check if on player */ p1 = imageindex_i_ctf1d; /* default to dropped */ @@ -1492,7 +1492,7 @@ SetCTFStats(edict_t *ent) { int i; - /* not at base + /* not at base check if on player */ p2 = imageindex_i_ctf2d; /* default to dropped */ @@ -1643,7 +1643,7 @@ CTFResetGrapple(edict_t *self) } void -CTFGrappleTouch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +CTFGrappleTouch(edict_t *self, edict_t *other, const cplane_t *plane, const csurface_t *surf) { float volume = 1.0; @@ -1706,8 +1706,8 @@ CTFGrappleTouch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf gi.multicast(self->s.origin, MULTICAST_PVS); } -/* - * Draw beam between grapple and self +/* + * Draw beam between grapple and self */ void CTFGrappleDrawCable(edict_t *self) @@ -1745,8 +1745,8 @@ CTFGrappleDrawCable(edict_t *self) void SV_AddGravity(edict_t *ent); -/* - * pull the player toward the grapple +/* + * pull the player toward the grapple */ void CTFGrapplePull(edict_t *self) @@ -1811,10 +1811,10 @@ CTFGrapplePull(edict_t *self) if (self->owner->client->ctf_grapplestate > CTF_GRAPPLE_STATE_FLY) { - /* pull player toward grapple + /* pull player toward grapple this causes icky stuff with prediction, we need to extend/ the prediction layer to include two new fields in the player/ - move stuff: a point and a velocity. The client should add + move stuff: a point and a velocity. The client should add that velociy in the direction of the point */ vec3_t forward, up; @@ -2040,7 +2040,7 @@ CTFTeam_f(edict_t *ent) /* add a teleportation effect */ ent->s.event = EV_PLAYER_TELEPORT; - + /* hold in place briefly */ ent->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; ent->client->ps.pmove.pm_time = 14; @@ -2127,7 +2127,7 @@ CTFScoreboardMessage(edict_t *ent, edict_t *killer) total[team]++; } - /* print level name and exit rules + /* print level name and exit rules add the clients in sorted order */ *string = 0; len = 0; @@ -2340,7 +2340,7 @@ CTFPickup_Tech(edict_t *ent, edict_t *other) return true; } -static void SpawnTech(gitem_t *item, edict_t *spot); +static void SpawnTech(const gitem_t *item, edict_t *spot); static edict_t * FindTechSpawn(void) @@ -2379,7 +2379,7 @@ TechThink(edict_t *tech) } void -CTFDrop_Tech(edict_t *ent, gitem_t *item) +CTFDrop_Tech(edict_t *ent, const gitem_t *item) { edict_t *tech; @@ -2419,7 +2419,7 @@ CTFDeadDropTech(edict_t *ent) } static void -SpawnTech(gitem_t *item, edict_t *spot) +SpawnTech(const gitem_t *item, edict_t *spot) { edict_t *ent; vec3_t forward, right; @@ -2482,8 +2482,8 @@ SpawnTechs(edict_t *ent) } } -/* - * frees the passed edict! +/* + * frees the passed edict! */ void CTFRespawnTech(edict_t *ent) @@ -2763,10 +2763,10 @@ CTFHasRegeneration(edict_t *ent) * ====================================================================== */ -/* +/* * This array is in 'importance order', - * it indicates what items are more - * important when reporting their names. + * it indicates what items are more + * important when reporting their names. */ struct { @@ -2875,7 +2875,7 @@ CTFSay_Team_Location(edict_t *who, char *buf, size_t bufsize) } /* we now have the closest item - see if there's more than one + see if there's more than one in the map, if so we need to determine what team is closest */ what = NULL; @@ -2887,8 +2887,8 @@ CTFSay_Team_Location(edict_t *who, char *buf, size_t bufsize) continue; } - /* if we are here, there is more - than one, find out if hot is + /* if we are here, there is more + than one, find out if hot is closer to red flag or blue flag */ if (((flag1 = G_Find(NULL, FOFS(classname), "item_flag_team1")) != NULL) && ((flag2 = G_Find(NULL, FOFS(classname), "item_flag_team2")) != NULL)) @@ -3970,7 +3970,7 @@ CTFJoinTeam(edict_t *ent, int desired_team) /* add a teleportation effect */ ent->s.event = EV_PLAYER_TELEPORT; - + /* hold in place briefly */ ent->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT; ent->client->ps.pmove.pm_time = 14; @@ -4515,8 +4515,8 @@ CTFCheckRules(void) *--------------------------------------------------------------------------*/ static void -old_teleporter_touch(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf) +old_teleporter_touch(edict_t *self, edict_t *other, const cplane_t *plane, + const csurface_t *surf) { edict_t *dest; int i; diff --git a/src/g_func.c b/src/g_func.c index c8bf77f..d21a462 100644 --- a/src/g_func.c +++ b/src/g_func.c @@ -351,8 +351,8 @@ plat_Accelerate(moveinfo_t *moveinfo) return; } - /* during this move we will accelrate from current_speed to move_speed - and cross over the decel_distance; figure the average speed for the + /* during this move we will accelrate from current_speed to move_speed + and cross over the decel_distance; figure the average speed for the entire move */ p1_distance = moveinfo->remaining_distance - moveinfo->decel_distance; p1_speed = (old_speed + moveinfo->move_speed) / 2.0; @@ -516,8 +516,8 @@ Use_Plat(edict_t *ent, edict_t *other, edict_t *activator) } void -Touch_Plat_Center(edict_t *ent, edict_t *other, cplane_t *plane, - csurface_t *surf) +Touch_Plat_Center(edict_t *ent, edict_t *other, const cplane_t *plane, + const csurface_t *surf) { if (!other->client) { @@ -591,7 +591,7 @@ plat_spawn_inside_trigger(edict_t *ent) * QUAKED func_plat (0 .5 .8) ? PLAT_LOW_TRIGGER * speed default 150 * - * Plats are always drawn in the extended position, + * Plats are always drawn in the extended position, * so they will light correctly. * * If the plat is the target of another trigger or button, @@ -704,7 +704,7 @@ SP_func_plat(edict_t *ent) /* * QUAKED func_rotating (0 .5 .8) ? START_ON REVERSE X_AXIS Y_AXIS TOUCH_PAIN STOP ANIMATED ANIMATED_FAST - * + * * You need to have an origin brush as part of this entity. The center of that brush will be * the point around which it is rotated. It will rotate around the Z axis by default. You can * check either the X_AXIS or Y_AXIS box to change that. @@ -724,7 +724,7 @@ rotating_blocked(edict_t *self, edict_t *other) } void -rotating_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +rotating_touch(edict_t *self, edict_t *other, const cplane_t *plane, const csurface_t *surf) { if (self->avelocity[0] || self->avelocity[1] || self->avelocity[2]) { @@ -836,8 +836,8 @@ SP_func_rotating(edict_t *ent) /* * QUAKED func_button (0 .5 .8) ? - * When a button is touched, it moves some distance in the - * direction of it's angle, triggers all of it's targets, + * When a button is touched, it moves some distance in the + * direction of it's angle, triggers all of it's targets, * waits some time, then returns to it's original position * where it can be triggered again. * @@ -924,7 +924,7 @@ button_use(edict_t *self, edict_t *other, edict_t *activator) } void -button_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +button_touch(edict_t *self, edict_t *other, const cplane_t *plane, const csurface_t *surf) { if (!other->client) { @@ -942,7 +942,7 @@ button_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) void button_killed(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) + int damage, const vec3_t point) { self->activator = attacker; self->health = self->max_health; @@ -1042,7 +1042,7 @@ SP_func_button(edict_t *ent) * QUAKED func_door (0 .5 .8) ? START_OPEN x CRUSHER NOMONSTER ANIMATED TOGGLE ANIMATED_FAST * TOGGLE wait in both the start and end states for a trigger event. * START_OPEN the door to moves to its destination when spawned, and operate in reverse. - * It is used to temporarily or permanently close off an area when triggered + * It is used to temporarily or permanently close off an area when triggered * (not useful for touch or takedamage doors). * NOMONSTER monsters will not trigger this door * @@ -1172,7 +1172,7 @@ door_go_up(edict_t *self, edict_t *activator) } if (self->moveinfo.state == STATE_TOP) - { + { /* reset top wait time */ if (self->moveinfo.wait >= 0) { @@ -1246,8 +1246,8 @@ door_use(edict_t *self, edict_t *other, edict_t *activator) } void -Touch_DoorTrigger(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf) +Touch_DoorTrigger(edict_t *self, edict_t *other, const cplane_t *plane, + const csurface_t *surf) { if (other->health <= 0) { @@ -1429,7 +1429,7 @@ door_blocked(edict_t *self, edict_t *other) void door_killed(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) + int damage, const vec3_t point) { edict_t *ent; @@ -1443,7 +1443,7 @@ door_killed(edict_t *self, edict_t *inflictor, edict_t *attacker, } void -door_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +door_touch(edict_t *self, edict_t *other, const cplane_t *plane, const csurface_t *surf) { if (!other->client) { @@ -1590,8 +1590,8 @@ SP_func_door(edict_t *ent) /* * QUAKED func_door_rotating (0 .5 .8) ? START_OPEN REVERSE CRUSHER NOMONSTER ANIMATED TOGGLE X_AXIS Y_AXIS * TOGGLE causes the door to wait in both the start and end states for a trigger event. - * START_OPEN the door to moves to its destination when spawned, and operate in reverse. - * It is used to temporarily or permanently close off an area when triggered + * START_OPEN the door to moves to its destination when spawned, and operate in reverse. + * It is used to temporarily or permanently close off an area when triggered * (not useful for touch or takedamage doors). * NOMONSTER monsters will not trigger this door * @@ -2141,7 +2141,7 @@ SP_func_train(edict_t *self) if (self->target) { - /* start trains on the second frame, to make + /* start trains on the second frame, to make sure their targets have had a chance to spawn */ self->nextthink = level.time + FRAMETIME; self->think = func_train_find; @@ -2465,7 +2465,7 @@ door_secret_blocked(edict_t *self, edict_t *other) void door_secret_die(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) + int damage, const vec3_t point) { self->takedamage = DAMAGE_NO; door_secret_use(self, attacker, attacker); diff --git a/src/g_items.c b/src/g_items.c index 4488369..7369b87 100644 --- a/src/g_items.c +++ b/src/g_items.c @@ -22,29 +22,16 @@ * Item handling and item definitions. * * ======================================================================= - */ + */ #include "header/local.h" -qboolean Pickup_Weapon(edict_t *ent, edict_t *other); -void Use_Weapon(edict_t *ent, gitem_t *inv); -void Drop_Weapon(edict_t *ent, gitem_t *inv); - -void Weapon_Blaster(edict_t *ent); -void Weapon_Shotgun(edict_t *ent); -void Weapon_SuperShotgun(edict_t *ent); -void Weapon_Machinegun(edict_t *ent); -void Weapon_Chaingun(edict_t *ent); -void Weapon_HyperBlaster(edict_t *ent); -void Weapon_RocketLauncher(edict_t *ent); -void Weapon_Grenade(edict_t *ent); -void Weapon_GrenadeLauncher(edict_t *ent); -void Weapon_Railgun(edict_t *ent); -void Weapon_BFG(edict_t *ent); - -gitem_armor_t jacketarmor_info = {25, 50, .30, .00, ARMOR_JACKET}; -gitem_armor_t combatarmor_info = {50, 100, .60, .30, ARMOR_COMBAT}; -gitem_armor_t bodyarmor_info = {100, 200, .80, .60, ARMOR_BODY}; +#define HEALTH_IGNORE_MAX 1 +#define HEALTH_TIMED 2 + +static gitem_armor_t jacketarmor_info = {25, 50, .30, .00, ARMOR_JACKET}; +static gitem_armor_t combatarmor_info = {50, 100, .60, .30, ARMOR_COMBAT}; +static gitem_armor_t bodyarmor_info = {100, 200, .80, .60, ARMOR_BODY}; static int jacket_armor_index; static int combat_armor_index; @@ -52,11 +39,6 @@ static int body_armor_index; static int power_screen_index; static int power_shield_index; -#define HEALTH_IGNORE_MAX 1 -#define HEALTH_TIMED 2 - -void Use_Quad(edict_t *ent, gitem_t *item); - static int quad_drop_timeout_hack; /* ====================================================================== */ @@ -73,11 +55,16 @@ GetItemByIndex(int index) } gitem_t * -FindItemByClassname(char *classname) +FindItemByClassname(const char *classname) { int i; gitem_t *it; + if (!classname) + { + return NULL; + } + it = itemlist; for (i = 0; i < game.num_items; i++, it++) @@ -97,11 +84,16 @@ FindItemByClassname(char *classname) } gitem_t * -FindItem(char *pickup_name) +FindItem(const char *pickup_name) { int i; gitem_t *it; + if (!pickup_name) + { + return NULL; + } + it = itemlist; for (i = 0; i < game.num_items; i++, it++) @@ -125,6 +117,11 @@ FindItem(char *pickup_name) void DoRespawn(edict_t *ent) { + if (!ent) + { + return; + } + if (ent->team) { edict_t *master; @@ -147,7 +144,7 @@ DoRespawn(edict_t *ent) { } - choice = randk() % count; + choice = count ? randk() % count : 0; for (count = 0, ent = master; count < choice; ent = ent->chain, count++) { @@ -155,6 +152,11 @@ DoRespawn(edict_t *ent) } } + if (!ent) + { + return; + } + ent->svflags &= ~SVF_NOCLIENT; ent->solid = SOLID_TRIGGER; gi.linkentity(ent); @@ -166,6 +168,11 @@ DoRespawn(edict_t *ent) void SetRespawn(edict_t *ent, float delay) { + if (!ent) + { + return; + } + ent->flags |= FL_RESPAWN; ent->svflags |= SVF_NOCLIENT; ent->solid = SOLID_NOT; @@ -181,9 +188,15 @@ Pickup_Powerup(edict_t *ent, edict_t *other) { int quantity; + if (!ent || !other) + { + return false; + } + quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)]; - if (((skill->value == 1) && (quantity >= 2)) || ((skill->value >= 2) && (quantity >= 1))) + if (((skill->value == SKILL_MEDIUM) && + (quantity >= 2)) || ((skill->value >= SKILL_HARD) && (quantity >= 1))) { return false; } @@ -221,8 +234,13 @@ Pickup_Powerup(edict_t *ent, edict_t *other) } void -Drop_General(edict_t *ent, gitem_t *item) +Drop_General(edict_t *ent, const gitem_t *item) { + if (!ent || !item) + { + return; + } + Drop_Item(ent, item); ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); @@ -233,6 +251,11 @@ Drop_General(edict_t *ent, gitem_t *item) qboolean Pickup_Adrenaline(edict_t *ent, edict_t *other) { + if (!ent || !other) + { + return false; + } + if (!deathmatch->value) { other->max_health += 1; @@ -254,6 +277,11 @@ Pickup_Adrenaline(edict_t *ent, edict_t *other) qboolean Pickup_AncientHead(edict_t *ent, edict_t *other) { + if (!ent || !other) + { + return false; + } + other->max_health += 2; if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value)) @@ -270,6 +298,11 @@ Pickup_Bandolier(edict_t *ent, edict_t *other) gitem_t *item; int index; + if (!ent || !other) + { + return false; + } + if (other->client->pers.max_bullets < 250) { other->client->pers.max_bullets = 250; @@ -334,6 +367,11 @@ Pickup_Pack(edict_t *ent, edict_t *other) gitem_t *item; int index; + if (!ent || !other) + { + return false; + } + if (other->client->pers.max_bullets < 300) { other->client->pers.max_bullets = 300; @@ -465,10 +503,15 @@ Pickup_Pack(edict_t *ent, edict_t *other) /* ====================================================================== */ void -Use_Quad(edict_t *ent, gitem_t *item) +Use_Quad(edict_t *ent, const gitem_t *item) { int timeout; + if (!ent || !item || !ent->client) + { + return; + } + ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); @@ -497,8 +540,13 @@ Use_Quad(edict_t *ent, gitem_t *item) /* ====================================================================== */ void -Use_Breather(edict_t *ent, gitem_t *item) +Use_Breather(edict_t *ent, const gitem_t *item) { + if (!ent || !item || !ent->client) + { + return; + } + ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); @@ -515,8 +563,13 @@ Use_Breather(edict_t *ent, gitem_t *item) /* ====================================================================== */ void -Use_Envirosuit(edict_t *ent, gitem_t *item) +Use_Envirosuit(edict_t *ent, const gitem_t *item) { + if (!ent || !item || !ent->client) + { + return; + } + ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); @@ -533,8 +586,13 @@ Use_Envirosuit(edict_t *ent, gitem_t *item) /* ====================================================================== */ void -Use_Invulnerability(edict_t *ent, gitem_t *item) +Use_Invulnerability(edict_t *ent, const gitem_t *item) { + if (!ent || !item) + { + return; + } + ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); @@ -554,8 +612,13 @@ Use_Invulnerability(edict_t *ent, gitem_t *item) /* ====================================================================== */ void -Use_Silencer(edict_t *ent, gitem_t *item) +Use_Silencer(edict_t *ent, const gitem_t *item) { + if (!ent || !item) + { + return; + } + ent->client->pers.inventory[ITEM_INDEX(item)]--; ValidateSelectedItem(ent); ent->client->silencer_shots += 30; @@ -566,6 +629,11 @@ Use_Silencer(edict_t *ent, gitem_t *item) qboolean Pickup_Key(edict_t *ent, edict_t *other) { + if (!ent || !other) + { + return false; + } + if (coop->value) { if (strcmp(ent->classname, "key_power_cube") == 0) @@ -600,12 +668,12 @@ Pickup_Key(edict_t *ent, edict_t *other) /* ====================================================================== */ qboolean -Add_Ammo(edict_t *ent, gitem_t *item, int count) +Add_Ammo(edict_t *ent, const gitem_t *item, int count) { int index; int max; - if (!ent->client) + if (!ent || !item || !ent->client) { return false; } @@ -663,6 +731,11 @@ Pickup_Ammo(edict_t *ent, edict_t *other) int count; qboolean weapon; + if (!ent || !other) + { + return false; + } + weapon = (ent->item->flags & IT_WEAPON); if ((weapon) && ((int)dmflags->value & DF_INFINITE_AMMO)) @@ -705,11 +778,16 @@ Pickup_Ammo(edict_t *ent, edict_t *other) } void -Drop_Ammo(edict_t *ent, gitem_t *item) +Drop_Ammo(edict_t *ent, const gitem_t *item) { edict_t *dropped; int index; + if (!ent || !item) + { + return; + } + index = ITEM_INDEX(item); dropped = Drop_Item(ent, item); @@ -731,6 +809,11 @@ Drop_Ammo(edict_t *ent, gitem_t *item) void MegaHealth_think(edict_t *self) { + if (!self) + { + return; + } + if ((self->owner->health > self->owner->max_health) && !CTFHasRegeneration(self->owner)) { @@ -752,6 +835,11 @@ MegaHealth_think(edict_t *self) qboolean Pickup_Health(edict_t *ent, edict_t *other) { + if (!ent || !other) + { + return false; + } + if (!(ent->style & HEALTH_IGNORE_MAX)) { if (other->health >= other->max_health) @@ -803,9 +891,9 @@ Pickup_Health(edict_t *ent, edict_t *other) /* ====================================================================== */ int -ArmorIndex(edict_t *ent) +ArmorIndex(const edict_t *ent) { - if (!ent->client) + if (!ent || !ent->client) { return 0; } @@ -838,6 +926,11 @@ Pickup_Armor(edict_t *ent, edict_t *other) float salvage; int salvagecount; + if (!ent || !other) + { + return false; + } + /* get info on new armor */ newinfo = (gitem_armor_t *)ent->item->info; @@ -933,8 +1026,13 @@ Pickup_Armor(edict_t *ent, edict_t *other) /* ====================================================================== */ int -PowerArmorType(edict_t *ent) +PowerArmorType(const edict_t *ent) { + if (!ent) + { + return POWER_ARMOR_NONE; + } + if (!ent->client) { return POWER_ARMOR_NONE; @@ -959,9 +1057,12 @@ PowerArmorType(edict_t *ent) } void -Use_PowerArmor(edict_t *ent, gitem_t *item) +Use_PowerArmor(edict_t *ent, const gitem_t *item) { - int index; + if (!ent || !item) + { + return; + } if (ent->flags & FL_POWER_ARMOR) { @@ -970,6 +1071,8 @@ Use_PowerArmor(edict_t *ent, gitem_t *item) } else { + int index; + index = ITEM_INDEX(FindItem("cells")); if (!ent->client->pers.inventory[index]) @@ -988,6 +1091,11 @@ Pickup_PowerArmor(edict_t *ent, edict_t *other) { int quantity; + if (!ent || !other) + { + return false; + } + quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)]; other->client->pers.inventory[ITEM_INDEX(ent->item)]++; @@ -1010,8 +1118,13 @@ Pickup_PowerArmor(edict_t *ent, edict_t *other) } void -Drop_PowerArmor(edict_t *ent, gitem_t *item) +Drop_PowerArmor(edict_t *ent, const gitem_t *item) { + if (!ent || !item) + { + return; + } + if ((ent->flags & FL_POWER_ARMOR) && (ent->client->pers.inventory[ITEM_INDEX(item)] == 1)) { @@ -1024,10 +1137,16 @@ Drop_PowerArmor(edict_t *ent, gitem_t *item) /* ====================================================================== */ void -Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +Touch_Item(edict_t *ent, edict_t *other, const cplane_t *plane /* unused */, + const csurface_t *surf /* unused */) { qboolean taken; + if (!ent || !other) + { + return; + } + if (!other->client) { return; @@ -1126,8 +1245,13 @@ Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) /* ====================================================================== */ static void -drop_temp_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +drop_temp_touch(edict_t *ent, edict_t *other, const cplane_t *plane, const csurface_t *surf) { + if (!ent || !other) + { + return; + } + if (other == ent->owner) { return; @@ -1149,11 +1273,15 @@ drop_make_touchable(edict_t *ent) } edict_t * -Drop_Item(edict_t *ent, gitem_t *item) +Drop_Item(edict_t *ent, const gitem_t *item) { edict_t *dropped; vec3_t forward, right; - vec3_t offset; + + if (!ent || !item) + { + return NULL; + } dropped = G_Spawn(); @@ -1172,6 +1300,7 @@ Drop_Item(edict_t *ent, gitem_t *item) if (ent->client) { + vec3_t offset; trace_t trace; AngleVectors(ent->client->v_angle, forward, right, NULL); @@ -1199,8 +1328,13 @@ Drop_Item(edict_t *ent, gitem_t *item) } void -Use_Item(edict_t *ent, edict_t *other, edict_t *activator) +Use_Item(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { + if (!ent) + { + return; + } + ent->svflags &= ~SVF_NOCLIENT; ent->use = NULL; @@ -1225,7 +1359,12 @@ droptofloor(edict_t *ent) { trace_t tr; vec3_t dest; - float *v; + const float *v; + + if (!ent) + { + return; + } v = tv(-15, -15, -15); VectorCopy(v, ent->mins); @@ -1252,7 +1391,9 @@ droptofloor(edict_t *ent) if (tr.startsolid) { - gi.dprintf("droptofloor: %s startsolid at %s\n", ent->classname, + gi.dprintf("%s: %s startsolid at %s\n", + __func__, + ent->classname, vtos(ent->s.origin)); G_FreeEdict(ent); return; @@ -1300,12 +1441,10 @@ droptofloor(edict_t *ent) * and for each item in each client's inventory. */ void -PrecacheItem(gitem_t *it) +PrecacheItem(const gitem_t *it) { - char *s, *start; + const char *s; char data[MAX_QPATH]; - int len; - gitem_t *ammo; if (!it) { @@ -1335,6 +1474,8 @@ PrecacheItem(gitem_t *it) /* parse everything for its ammo */ if (it->ammo && it->ammo[0]) { + const gitem_t *ammo; + ammo = FindItem(it->ammo); if (ammo != it) @@ -1353,6 +1494,9 @@ PrecacheItem(gitem_t *it) while (*s) { + const char *start; + int len; + start = s; while (*s && *s != ' ') @@ -1365,6 +1509,7 @@ PrecacheItem(gitem_t *it) if ((len >= MAX_QPATH) || (len < 5)) { gi.error("PrecacheItem: %s has bad precache string", it->classname); + return; } memcpy(data, start, len); @@ -1405,6 +1550,11 @@ PrecacheItem(gitem_t *it) void SpawnItem(edict_t *ent, gitem_t *item) { + if (!ent || !item) + { + return; + } + PrecacheItem(item); if (ent->spawnflags) @@ -1651,7 +1801,7 @@ gitem_t itemlist[] = { "misc/power2.wav misc/power1.wav" }, - /* + /* * weapon_grapple (.3 .3 1) (-16 -16 -16) (16 16 16) * always owned, never in the world */ @@ -1677,7 +1827,7 @@ gitem_t itemlist[] = { "weapons/grapple/grfire.wav weapons/grapple/grpull.wav weapons/grapple/grhang.wav weapons/grapple/grreset.wav weapons/grapple/grhit.wav" }, - /* + /* * weapon_blaster (.3 .3 1) (-16 -16 -16) (16 16 16) * always owned, never in the world */ @@ -1771,7 +1921,6 @@ gitem_t itemlist[] = { WEAP_MACHINEGUN, NULL, 0, - "weapons/machgf1b.wav weapons/machgf2b.wav weapons/machgf3b.wav weapons/machgf4b.wav weapons/machgf5b.wav" }, @@ -1796,7 +1945,6 @@ gitem_t itemlist[] = { WEAP_CHAINGUN, NULL, 0, - "weapons/chngnu1a.wav weapons/chngnl1a.wav weapons/machgf3b.wav` weapons/chngnd1a.wav" }, @@ -1821,7 +1969,6 @@ gitem_t itemlist[] = { WEAP_GRENADES, NULL, AMMO_GRENADES, - "weapons/hgrent1a.wav weapons/hgrena1b.wav weapons/hgrenc1b.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav " }, @@ -1846,7 +1993,6 @@ gitem_t itemlist[] = { WEAP_GRENADELAUNCHER, NULL, 0, - "models/objects/grenade/tris.md2 weapons/grenlf1a.wav weapons/grenlr1b.wav weapons/grenlb1b.wav" }, @@ -1871,7 +2017,6 @@ gitem_t itemlist[] = { WEAP_ROCKETLAUNCHER, NULL, 0, - "models/objects/rocket/tris.md2 weapons/rockfly.wav weapons/rocklf1a.wav weapons/rocklr1b.wav models/objects/debris2/tris.md2" }, @@ -1896,7 +2041,6 @@ gitem_t itemlist[] = { WEAP_HYPERBLASTER, NULL, 0, - "weapons/hyprbu1a.wav weapons/hyprbl1a.wav weapons/hyprbf1a.wav weapons/hyprbd1a.wav misc/lasfly.wav" }, @@ -1945,7 +2089,6 @@ gitem_t itemlist[] = { WEAP_BFG, NULL, 0, - "sprites/s_bfg1.sp2 sprites/s_bfg2.sp2 sprites/s_bfg3.sp2 weapons/bfg__f1y.wav weapons/bfg__l1a.wav weapons/bfg__x1b.wav weapons/bfg_hum.wav" }, @@ -2263,7 +2406,7 @@ gitem_t itemlist[] = { "" }, - /* + /* * QUAKED item_pack (.3 .3 1) (-16 -16 -16) (16 16 16) */ { @@ -2530,7 +2673,6 @@ gitem_t itemlist[] = { 0, NULL, 0, - "items/s_health.wav items/n_health.wav items/l_health.wav items/m_health.wav" }, @@ -2680,6 +2822,11 @@ gitem_t itemlist[] = { void SP_item_health(edict_t *self) { + if (!self) + { + return; + } + if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) { G_FreeEdict(self); @@ -2698,6 +2845,11 @@ SP_item_health(edict_t *self) void SP_item_health_small(edict_t *self) { + if (!self) + { + return; + } + if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) { G_FreeEdict(self); @@ -2717,6 +2869,11 @@ SP_item_health_small(edict_t *self) void SP_item_health_large(edict_t *self) { + if (!self) + { + return; + } + if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) { G_FreeEdict(self); @@ -2735,6 +2892,11 @@ SP_item_health_large(edict_t *self) void SP_item_health_mega(edict_t *self) { + if (!self) + { + return; + } + if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) { G_FreeEdict(self); @@ -2775,4 +2937,3 @@ SetItemNames(void) power_screen_index = ITEM_INDEX(FindItem("Power Screen")); power_shield_index = ITEM_INDEX(FindItem("Power Shield")); } - diff --git a/src/g_misc.c b/src/g_misc.c index bb372f2..eb23966 100644 --- a/src/g_misc.c +++ b/src/g_misc.c @@ -1,3 +1,29 @@ +/* + * 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. + * + * ======================================================================= + * + * Miscellaneos entities, functs and functions. + * + * ======================================================================= + */ + #include "header/local.h" int debristhisframe; @@ -11,8 +37,13 @@ int gibsthisframe; /* ===================================================== */ void -Use_Areaportal(edict_t *ent, edict_t *other, edict_t *activator) +Use_Areaportal(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { + if (!ent) + { + return; + } + ent->count ^= 1; /* toggle state */ gi.SetAreaPortalState(ent->style, ent->count); } @@ -27,8 +58,13 @@ Use_Areaportal(edict_t *ent, edict_t *other, edict_t *activator) void SP_func_areaportal(edict_t *ent) { + if (!ent) + { + return; + } + ent->use = Use_Areaportal; - ent->count = 0; /* allways start closed; */ + ent->count = 0; /* always start closed; */ } /* ===================================================== */ @@ -53,6 +89,11 @@ VelocityForDamage(int damage, vec3_t v) void ClipGibVelocity(edict_t *ent) { + if (!ent) + { + return; + } + if (ent->velocity[0] < -300) { ent->velocity[0] = -300; @@ -81,9 +122,16 @@ ClipGibVelocity(edict_t *ent) } } +/* ===================================================== */ + void gib_think(edict_t *self) { + if (!self) + { + return; + } + self->s.frame++; self->nextthink = level.time + FRAMETIME; @@ -95,8 +143,13 @@ gib_think(edict_t *self) } void -gib_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +gib_touch(edict_t *self, edict_t *other /* unused */, const cplane_t *plane, const csurface_t *surf /* unused */) { + if (!self) + { + return; + } + vec3_t normal_angles, right; if (!self->groundentity) @@ -124,14 +177,19 @@ gib_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) } void -gib_die(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) +gib_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, + int damage /* unused */, const vec3_t point /* unused */) { + if (!self) + { + return; + } + G_FreeEdict(self); } void -ThrowGib(edict_t *self, char *gibname, int damage, int type) +ThrowGib(edict_t *self, const char *gibname, int damage, gibtype_t type) { edict_t *gib; vec3_t vd; @@ -139,6 +197,11 @@ ThrowGib(edict_t *self, char *gibname, int damage, int type) vec3_t size; float vscale; + if (!self || !gibname) + { + return; + } + gibsthisframe++; if (gibsthisframe > MAX_GIBS) @@ -188,11 +251,16 @@ ThrowGib(edict_t *self, char *gibname, int damage, int type) } void -ThrowHead(edict_t *self, char *gibname, int damage, int type) +ThrowHead(edict_t *self, const char *gibname, int damage, gibtype_t type) { vec3_t vd; float vscale; + if (!self || !gibname) + { + return; + } + self->s.skinnum = 0; self->s.frame = 0; VectorClear(self->mins); @@ -239,6 +307,11 @@ ThrowClientHead(edict_t *self, int damage) vec3_t vd; char *gibname; + if (!self) + { + return; + } + if (randk() & 1) { gibname = "models/objects/gibs/head2/tris.md2"; @@ -276,9 +349,14 @@ ThrowClientHead(edict_t *self, int damage) } void -debris_die(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) +debris_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, + int damage /* unused */, const vec3_t point /* unused */) { + if (!self) + { + return; + } + G_FreeEdict(self); } @@ -288,6 +366,11 @@ ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin) edict_t *chunk; vec3_t v; + if (!self || !modelname) + { + return; + } + debristhisframe++; if (debristhisframe > MAX_DEBRIS) @@ -321,6 +404,11 @@ ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin) void BecomeExplosion1(edict_t *self) { + if (!self) + { + return; + } + /* flags are important */ if (strcmp(self->classname, "item_flag_team1") == 0) { @@ -356,6 +444,11 @@ BecomeExplosion1(edict_t *self) void BecomeExplosion2(edict_t *self) { + if (!self) + { + return; + } + gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_EXPLOSION2); gi.WritePosition(self->s.origin); @@ -372,12 +465,17 @@ BecomeExplosion2(edict_t *self) */ void -path_corner_touch(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf) +path_corner_touch(edict_t *self, edict_t *other, const cplane_t *plane /* unused */, + const csurface_t *surf /* unused */) { vec3_t v; edict_t *next; + if (!self || !other) + { + return; + } + if (other->movetarget != self) { return; @@ -440,6 +538,11 @@ path_corner_touch(edict_t *self, edict_t *other, cplane_t *plane, void SP_path_corner(edict_t *self) { + if (!self) + { + return; + } + if (!self->targetname) { gi.dprintf("path_corner with no targetname at %s\n", @@ -463,11 +566,16 @@ SP_path_corner(edict_t *self) * hold is selected, it will stay here. */ void -point_combat_touch(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf) +point_combat_touch(edict_t *self, edict_t *other, const cplane_t *plane /* unused */, + const csurface_t *surf /* unused */) { edict_t *activator; + if (!self || !other) + { + return; + } + if (other->movetarget != self) { return; @@ -534,6 +642,11 @@ point_combat_touch(edict_t *self, edict_t *other, cplane_t *plane, void SP_point_combat(edict_t *self) { + if (!self) + { + return; + } + if (deathmatch->value) { G_FreeEdict(self); @@ -557,6 +670,11 @@ static int robotron[4]; void TH_viewthing(edict_t *ent) { + if (!ent) + { + return; + } + ent->s.frame = (ent->s.frame + 1) % 7; ent->nextthink = level.time + FRAMETIME; @@ -573,6 +691,11 @@ TH_viewthing(edict_t *ent) void SP_viewthing(edict_t *ent) { + if (!ent) + { + return; + } + gi.dprintf("viewthing spawned\n"); ent->movetype = MOVETYPE_NONE; @@ -594,6 +717,11 @@ SP_viewthing(edict_t *ent) void SP_info_null(edict_t *self) { + if (!self) + { + return; + } + G_FreeEdict(self); } @@ -604,10 +732,17 @@ SP_info_null(edict_t *self) void SP_info_notnull(edict_t *self) { + if (!self) + { + return; + } + VectorCopy(self->s.origin, self->absmin); VectorCopy(self->s.origin, self->absmax); } +#define START_OFF 1 + /* * QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) START_OFF * Non-displayed light. @@ -616,12 +751,14 @@ SP_info_notnull(edict_t *self) * If targeted, will toggle between on and off. * Default _cone value is 10 (used to set size of light for spotlights) */ - -#define START_OFF 1 - -static void -light_use(edict_t *self, edict_t *other, edict_t *activator) +void +light_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { + if (!self) + { + return; + } + if (self->spawnflags & START_OFF) { gi.configstring(CS_LIGHTS + self->style, "m"); @@ -637,6 +774,11 @@ light_use(edict_t *self, edict_t *other, edict_t *activator) void SP_light(edict_t *self) { + if (!self) + { + return; + } + /* no targeted lights in deathmatch, because they cause global messages */ if (!self->targetname || deathmatch->value) { @@ -674,8 +816,13 @@ SP_light(edict_t *self) * the wall will initially be present */ void -func_wall_use(edict_t *self, edict_t *other, edict_t *activator) +func_wall_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { + if (!self) + { + return; + } + if (self->solid == SOLID_NOT) { self->solid = SOLID_BSP; @@ -699,6 +846,11 @@ func_wall_use(edict_t *self, edict_t *other, edict_t *activator) void SP_func_wall(edict_t *self) { + if (!self) + { + return; + } + self->movetype = MOVETYPE_PUSH; gi.setmodel(self, self->model); @@ -757,11 +909,12 @@ SP_func_wall(edict_t *self) */ void -func_object_touch(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf) +func_object_touch(edict_t *self, edict_t *other, const cplane_t *plane, + const csurface_t *surf /* unused */) { /* only squash thing we fall on top of */ - if (!plane) + + if (!self || !other || !plane) { return; } @@ -783,13 +936,23 @@ func_object_touch(edict_t *self, edict_t *other, cplane_t *plane, void func_object_release(edict_t *self) { + if (!self) + { + return; + } + self->movetype = MOVETYPE_TOSS; self->touch = func_object_touch; } void -func_object_use(edict_t *self, edict_t *other, edict_t *activator) +func_object_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { + if (!self) + { + return; + } + self->solid = SOLID_BSP; self->svflags &= ~SVF_NOCLIENT; self->use = NULL; @@ -800,6 +963,11 @@ func_object_use(edict_t *self, edict_t *other, edict_t *activator) void SP_func_object(edict_t *self) { + if (!self) + { + return; + } + gi.setmodel(self, self->model); self->mins[0] += 1; @@ -860,7 +1028,7 @@ SP_func_object(edict_t *self) */ void func_explosive_explode(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) + int damage /* unused */, const vec3_t point /* unused */) { vec3_t origin; vec3_t chunkorigin; @@ -868,6 +1036,11 @@ func_explosive_explode(edict_t *self, edict_t *inflictor, edict_t *attacker, int count; int mass; + if (!self || !inflictor || !attacker) + { + return; + } + /* bmodel origins are (0 0 0), we need to adjust that here */ VectorScale(self->size, 0.5, size); VectorAdd(self->absmin, size, origin); @@ -961,6 +1134,11 @@ func_explosive_spawn(edict_t *self, edict_t *other, edict_t *activator) void SP_func_explosive(edict_t *self) { + if (!self) + { + return; + } + if (deathmatch->value) { /* auto-remove for deathmatch */ @@ -1021,12 +1199,16 @@ SP_func_explosive(edict_t *self) * health (80), and dmg (150). */ void -barrel_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) - +barrel_touch(edict_t *self, edict_t *other, const cplane_t *plane /* unused */, const csurface_t *surf /*unused */) { float ratio; vec3_t v; + if (!self || !other) + { + return; + } + if ((!other->groundentity) || (other->groundentity == self)) { return; @@ -1044,6 +1226,11 @@ barrel_explode(edict_t *self) float spd; vec3_t save; + if (!self) + { + return; + } + T_RadiusDamage(self, self->activator, self->dmg, NULL, self->dmg + 40, MOD_BARREL); @@ -1124,9 +1311,14 @@ barrel_explode(edict_t *self) } void -barrel_delay(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) +barrel_delay(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker, + int damage /* unused */, const vec3_t point /* unused */) { + if (!self || !attacker) + { + return; + } + self->takedamage = DAMAGE_NO; self->nextthink = level.time + 2 * FRAMETIME; self->think = barrel_explode; @@ -1136,6 +1328,11 @@ barrel_delay(edict_t *self, edict_t *inflictor, edict_t *attacker, void SP_misc_explobox(edict_t *self) { + if (!self) + { + return; + } + if (deathmatch->value) { /* auto-remove for deathmatch */ @@ -1186,14 +1383,24 @@ SP_misc_explobox(edict_t *self) * QUAKED misc_blackhole (1 .5 0) (-8 -8 -8) (8 8 8) */ void -misc_blackhole_use(edict_t *ent, edict_t *other, edict_t *activator) +misc_blackhole_use(edict_t *ent, edict_t *other /* unused */, edict_t *activator /* unused */) { + if (!ent) + { + return; + } + G_FreeEdict(ent); } void misc_blackhole_think(edict_t *self) { + if (!self) + { + return; + } + if (++self->s.frame < 19) { self->nextthink = level.time + FRAMETIME; @@ -1208,6 +1415,11 @@ misc_blackhole_think(edict_t *self) void SP_misc_blackhole(edict_t *ent) { + if (!ent) + { + return; + } + ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_NOT; VectorSet(ent->mins, -64, -64, 0); @@ -1226,6 +1438,11 @@ SP_misc_blackhole(edict_t *ent) void misc_eastertank_think(edict_t *self) { + if (!self) + { + return; + } + if (++self->s.frame < 293) { self->nextthink = level.time + FRAMETIME; @@ -1240,6 +1457,11 @@ misc_eastertank_think(edict_t *self) void SP_misc_eastertank(edict_t *ent) { + if (!ent) + { + return; + } + ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; VectorSet(ent->mins, -32, -32, -16); @@ -1257,6 +1479,11 @@ SP_misc_eastertank(edict_t *ent) void misc_easterchick_think(edict_t *self) { + if (!self) + { + return; + } + if (++self->s.frame < 247) { self->nextthink = level.time + FRAMETIME; @@ -1271,6 +1498,11 @@ misc_easterchick_think(edict_t *self) void SP_misc_easterchick(edict_t *ent) { + if (!ent) + { + return; + } + ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; VectorSet(ent->mins, -32, -32, 0); @@ -1288,6 +1520,11 @@ SP_misc_easterchick(edict_t *ent) void misc_easterchick2_think(edict_t *self) { + if (!self) + { + return; + } + if (++self->s.frame < 287) { self->nextthink = level.time + FRAMETIME; @@ -1302,6 +1539,11 @@ misc_easterchick2_think(edict_t *self) void SP_misc_easterchick2(edict_t *ent) { + if (!ent) + { + return; + } + ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; VectorSet(ent->mins, -32, -32, 0); @@ -1321,6 +1563,11 @@ SP_misc_easterchick2(edict_t *ent) void commander_body_think(edict_t *self) { + if (!self) + { + return; + } + if (++self->s.frame < 24) { self->nextthink = level.time + FRAMETIME; @@ -1337,8 +1584,13 @@ commander_body_think(edict_t *self) } void -commander_body_use(edict_t *self, edict_t *other, edict_t *activator) +commander_body_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { + if (!self) + { + return; + } + self->think = commander_body_think; self->nextthink = level.time + FRAMETIME; gi.sound(self, CHAN_BODY, gi.soundindex("tank/pain.wav"), 1, ATTN_NORM, 0); @@ -1347,6 +1599,11 @@ commander_body_use(edict_t *self, edict_t *other, edict_t *activator) void commander_body_drop(edict_t *self) { + if (!self) + { + return; + } + self->movetype = MOVETYPE_TOSS; self->s.origin[2] += 2; } @@ -1354,6 +1611,11 @@ commander_body_drop(edict_t *self) void SP_monster_commander_body(edict_t *self) { + if (!self) + { + return; + } + self->movetype = MOVETYPE_NONE; self->solid = SOLID_BBOX; self->model = "models/monsters/commandr/tris.md2"; @@ -1381,6 +1643,11 @@ SP_monster_commander_body(edict_t *self) void misc_banner_think(edict_t *ent) { + if (!ent) + { + return; + } + ent->s.frame = (ent->s.frame + 1) % 16; ent->nextthink = level.time + FRAMETIME; } @@ -1388,6 +1655,11 @@ misc_banner_think(edict_t *ent) void SP_misc_banner(edict_t *ent) { + if (!ent) + { + return; + } + ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_NOT; ent->s.modelindex = gi.modelindex("models/objects/banner/tris.md2"); @@ -1403,11 +1675,16 @@ SP_misc_banner(edict_t *ent) * This is the dead player model. Comes in 6 exciting different poses! */ void -misc_deadsoldier_die(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) +misc_deadsoldier_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, + int damage, const vec3_t point /* unused */) { int n; + if (!self) + { + return; + } + if (self->health > -80) { return; @@ -1427,6 +1704,11 @@ misc_deadsoldier_die(edict_t *self, edict_t *inflictor, edict_t *attacker, void SP_misc_deadsoldier(edict_t *ent) { + if (!ent) + { + return; + } + if (deathmatch->value) { /* auto-remove for deathmatch */ @@ -1489,6 +1771,11 @@ extern void func_train_find(edict_t *self); void misc_viper_use(edict_t *self, edict_t *other, edict_t *activator) { + if (!self || !other || !activator) + { + return; + } + self->svflags &= ~SVF_NOCLIENT; self->use = train_use; train_use(self, other, activator); @@ -1497,6 +1784,11 @@ misc_viper_use(edict_t *self, edict_t *other, edict_t *activator) void SP_misc_viper(edict_t *ent) { + if (!ent) + { + return; + } + if (!ent->target) { gi.dprintf("misc_viper without a target at %s\n", vtos(ent->absmin)); @@ -1544,9 +1836,14 @@ SP_misc_bigviper(edict_t *ent) * "dmg" how much boom should the bomb make? */ void -misc_viper_bomb_touch(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf) +misc_viper_bomb_touch(edict_t *self, edict_t *other /* unused */, const cplane_t *plane /* unused */, + const csurface_t *surf /* unused */) { + if (!self) + { + return; + } + G_UseTargets(self, self->activator); self->s.origin[2] = self->absmin[2] + 1; @@ -1560,6 +1857,11 @@ misc_viper_bomb_prethink(edict_t *self) vec3_t v; float diff; + if (!self) + { + return; + } + self->groundentity = NULL; diff = self->timestamp - level.time; @@ -1578,10 +1880,15 @@ misc_viper_bomb_prethink(edict_t *self) } void -misc_viper_bomb_use(edict_t *self, edict_t *other, edict_t *activator) +misc_viper_bomb_use(edict_t *self, edict_t *other /* unused */, edict_t *activator) { edict_t *viper; + if (!self || !activator) + { + return; + } + self->solid = SOLID_BBOX; self->svflags &= ~SVF_NOCLIENT; self->s.effects |= EF_ROCKET; @@ -1601,6 +1908,11 @@ misc_viper_bomb_use(edict_t *self, edict_t *other, edict_t *activator) void SP_misc_viper_bomb(edict_t *self) { + if (!self) + { + return; + } + self->movetype = MOVETYPE_NONE; self->solid = SOLID_NOT; VectorSet(self->mins, -8, -8, -8); @@ -1631,8 +1943,13 @@ extern void train_use(edict_t *self, edict_t *other, edict_t *activator); extern void func_train_find(edict_t *self); void -misc_strogg_ship_use(edict_t *self, edict_t *other, edict_t *activator) +misc_strogg_ship_use(edict_t *self, edict_t *other /* other */, edict_t *activator) { + if (!self || !activator) + { + return; + } + self->svflags &= ~SVF_NOCLIENT; self->use = train_use; train_use(self, other, activator); @@ -1641,9 +1958,15 @@ misc_strogg_ship_use(edict_t *self, edict_t *other, edict_t *activator) void SP_misc_strogg_ship(edict_t *ent) { + if (!ent) + { + return; + } + if (!ent->target) { - gi.dprintf("%s without a target at %s\n", ent->classname, vtos(ent->absmin)); + gi.dprintf("%s without a target at %s\n", ent->classname, + vtos(ent->absmin)); G_FreeEdict(ent); return; } @@ -1674,6 +1997,11 @@ SP_misc_strogg_ship(edict_t *ent) void misc_satellite_dish_think(edict_t *self) { + if (!self) + { + return; + } + self->s.frame++; if (self->s.frame < 38) @@ -1683,8 +2011,13 @@ misc_satellite_dish_think(edict_t *self) } void -misc_satellite_dish_use(edict_t *self, edict_t *other, edict_t *activator) +misc_satellite_dish_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */) { + if (!self) + { + return; + } + self->s.frame = 0; self->think = misc_satellite_dish_think; self->nextthink = level.time + FRAMETIME; @@ -1693,6 +2026,11 @@ misc_satellite_dish_use(edict_t *self, edict_t *other, edict_t *activator) void SP_misc_satellite_dish(edict_t *ent) { + if (!ent) + { + return; + } + ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; VectorSet(ent->mins, -64, -64, 0); @@ -1708,6 +2046,11 @@ SP_misc_satellite_dish(edict_t *ent) void SP_light_mine1(edict_t *ent) { + if (!ent) + { + return; + } + ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; ent->s.modelindex = gi.modelindex("models/objects/minelite/light1/tris.md2"); @@ -1720,6 +2063,11 @@ SP_light_mine1(edict_t *ent) void SP_light_mine2(edict_t *ent) { + if (!ent) + { + return; + } + ent->movetype = MOVETYPE_NONE; ent->solid = SOLID_BBOX; ent->s.modelindex = gi.modelindex("models/objects/minelite/light2/tris.md2"); @@ -1733,6 +2081,11 @@ SP_light_mine2(edict_t *ent) void SP_misc_gib_arm(edict_t *ent) { + if (!ent) + { + return; + } + gi.setmodel(ent, "models/objects/gibs/arm/tris.md2"); ent->solid = SOLID_BBOX; ent->s.effects |= EF_GIB; @@ -1756,6 +2109,11 @@ SP_misc_gib_arm(edict_t *ent) void SP_misc_gib_leg(edict_t *ent) { + if (!ent) + { + return; + } + gi.setmodel(ent, "models/objects/gibs/leg/tris.md2"); ent->solid = SOLID_BBOX; ent->s.effects |= EF_GIB; @@ -1779,6 +2137,11 @@ SP_misc_gib_leg(edict_t *ent) void SP_misc_gib_head(edict_t *ent) { + if (!ent) + { + return; + } + gi.setmodel(ent, "models/objects/gibs/head/tris.md2"); ent->solid = SOLID_BBOX; ent->s.effects |= EF_GIB; @@ -1806,6 +2169,11 @@ SP_misc_gib_head(edict_t *ent) void SP_target_character(edict_t *self) { + if (!self) + { + return; + } + self->movetype = MOVETYPE_PUSH; gi.setmodel(self, self->model); self->solid = SOLID_BSP; @@ -1892,6 +2260,11 @@ SP_target_string(edict_t *self) static void func_clock_reset(edict_t *self) { + if (!self) + { + return; + } + self->activator = NULL; if (self->spawnflags & 1) @@ -2031,6 +2404,16 @@ func_clock_think(edict_t *self) void func_clock_use(edict_t *self, edict_t *other, edict_t *activator) { + if (!self) + { + return; + } + + if (!self->think) + { + return; + } + if (!(self->spawnflags & 8)) { self->use = NULL; @@ -2048,9 +2431,16 @@ func_clock_use(edict_t *self, edict_t *other, edict_t *activator) void SP_func_clock(edict_t *self) { + if (!self) + { + return; + } + if (!self->target) { - gi.dprintf("%s with no target at %s\n", self->classname, vtos(self->s.origin)); + gi.dprintf("%s with no target at %s\n", self->classname, + vtos(self->s.origin)); + G_FreeEdict(self); return; } @@ -2086,12 +2476,17 @@ SP_func_clock(edict_t *self) /* ================================================================================= */ void -teleporter_touch(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf) +teleporter_touch(edict_t *self, edict_t *other, const cplane_t *plane /* unused */, + const csurface_t *surf /* unused */) { edict_t *dest; int i; + if (!self || !other) + { + return; + } + if (!other->client) { return; @@ -2147,6 +2542,11 @@ teleporter_touch(edict_t *self, edict_t *other, cplane_t *plane, void SP_misc_teleporter(edict_t *ent) { + if (!ent) + { + return; + } + edict_t *trig; if (!ent->target) @@ -2184,6 +2584,11 @@ SP_misc_teleporter(edict_t *ent) void SP_misc_teleporter_dest(edict_t *ent) { + if (!ent) + { + return; + } + gi.setmodel(ent, "models/objects/dmspot/tris.md2"); ent->s.skinnum = 0; ent->solid = SOLID_BBOX; @@ -2191,4 +2596,3 @@ SP_misc_teleporter_dest(edict_t *ent) VectorSet(ent->maxs, 32, 32, -16); gi.linkentity(ent); } - diff --git a/src/g_trigger.c b/src/g_trigger.c index 873e40b..e66ea2d 100644 --- a/src/g_trigger.c +++ b/src/g_trigger.c @@ -40,9 +40,9 @@ InitTrigger(edict_t *self) self->svflags = SVF_NOCLIENT; } -/* - * The wait time has passed, so set - * back up for another activation +/* + * The wait time has passed, so set + * back up for another activation */ void multi_wait(edict_t *ent) @@ -83,7 +83,7 @@ Use_Multi(edict_t *ent, edict_t *other, edict_t *activator) } void -Touch_Multi(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +Touch_Multi(edict_t *self, edict_t *other, const cplane_t *plane, const csurface_t *surf) { if (other->client) { @@ -125,13 +125,13 @@ Touch_Multi(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) * 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 @@ -190,7 +190,7 @@ SP_trigger_multiple(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 + * 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. @@ -207,7 +207,7 @@ SP_trigger_multiple(edict_t *ent) void SP_trigger_once(edict_t *ent) { - /* make old maps work because I messed up on flag assignments here + /* 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) { @@ -395,10 +395,10 @@ SP_trigger_key(edict_t *self) * 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 + * 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 + * After the counter has been triggered "count" times (default 2), it * will fire all of it's targets and remove itself. */ void @@ -482,8 +482,8 @@ SP_trigger_always(edict_t *ent) static int windsound; void -trigger_push_touch(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf) +trigger_push_touch(edict_t *self, edict_t *other, const cplane_t *plane, + const csurface_t *surf) { if (strcmp(other->classname, "grenade") == 0) { @@ -574,7 +574,7 @@ hurt_use(edict_t *self, edict_t *other, edict_t *activator) } void -hurt_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +hurt_touch(edict_t *self, edict_t *other, const cplane_t *plane, const csurface_t *surf) { int dflags; @@ -664,8 +664,8 @@ SP_trigger_hurt(edict_t *self) */ void -trigger_gravity_touch(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf) +trigger_gravity_touch(edict_t *self, edict_t *other, const cplane_t *plane, + const csurface_t *surf) { other->gravity = self->gravity; } @@ -700,8 +700,8 @@ SP_trigger_gravity(edict_t *self) * "height" default to 200, the speed thrown upwards */ void -trigger_monsterjump_touch(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf) +trigger_monsterjump_touch(edict_t *self, edict_t *other, const cplane_t *plane, + const csurface_t *surf) { if (other->flags & (FL_FLY | FL_SWIM)) { diff --git a/src/g_utils.c b/src/g_utils.c index 3070b59..f66011a 100644 --- a/src/g_utils.c +++ b/src/g_utils.c @@ -26,9 +26,11 @@ #include "header/local.h" +#define MAXCHOICES 8 + void -G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward, - vec3_t right, vec3_t result) +G_ProjectSource(const vec3_t point, const vec3_t distance, const vec3_t forward, + const 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]; @@ -46,10 +48,15 @@ G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward, * of the list is reached. */ edict_t * -G_Find(edict_t *from, int fieldofs, char *match) +G_Find(edict_t *from, int fieldofs, const char *match) { char *s; + if (!match) + { + return NULL; + } + if (!from) { from = g_edicts; @@ -86,7 +93,7 @@ G_Find(edict_t *from, int fieldofs, char *match) * Returns entities that have origins within a spherical area */ edict_t * -findradius(edict_t *from, vec3_t org, float rad) +findradius(edict_t *from, const vec3_t org, float rad) { vec3_t eorg; int j; @@ -136,8 +143,6 @@ findradius(edict_t *from, vec3_t org, float rad) * 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) { @@ -180,6 +185,11 @@ G_PickTarget(char *targetname) void Think_Delay(edict_t *ent) { + if (!ent) + { + return; + } + G_UseTargets(ent, ent->activator); G_FreeEdict(ent); } @@ -202,6 +212,11 @@ G_UseTargets(edict_t *ent, edict_t *activator) { edict_t *t; + if (!ent) + { + return; + } + /* check for a delay */ if (ent->delay) { @@ -273,7 +288,7 @@ G_UseTargets(edict_t *ent, edict_t *activator) if (t == ent) { - gi.dprintf("WARNING: Entity used itself.\n"); + gi.dprintf("WARNING: %s used itself.\n", t->classname); } else { @@ -303,6 +318,9 @@ tv(float x, float y, float z) static vec3_t vecs[8]; float *v; + /* use an array so that multiple + tempvectors won't collide + for a while */ v = vecs[index]; index = (index + 1) & 7; @@ -333,10 +351,10 @@ vtos(vec3_t v) 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}; +static vec3_t VEC_UP = {0, -1, 0}; +static vec3_t MOVEDIR_UP = {0, 0, 1}; +static vec3_t VEC_DOWN = {0, -2, 0}; +static vec3_t MOVEDIR_DOWN = {0, 0, -1}; void G_SetMovedir(vec3_t angles, vec3_t movedir) @@ -389,16 +407,16 @@ vectoyaw(vec3_t vec) } void -vectoangles(vec3_t value1, vec3_t angles) +vectoangles(const vec3_t value, vec3_t angles) { float forward; float yaw, pitch; - if ((value1[1] == 0) && (value1[0] == 0)) + if ((value[1] == 0) && (value[0] == 0)) { yaw = 0; - if (value1[2] > 0) + if (value[2] > 0) { pitch = 90; } @@ -409,11 +427,11 @@ vectoangles(vec3_t value1, vec3_t angles) } else { - if (value1[0]) + if (value[0]) { - yaw = (int)(atan2(value1[1], value1[0]) * 180 / M_PI); + yaw = (int)(atan2(value[1], value[0]) * 180 / M_PI); } - else if (value1[1] > 0) + else if (value[1] > 0) { yaw = 90; } @@ -427,8 +445,8 @@ vectoangles(vec3_t value1, vec3_t angles) yaw += 360; } - forward = sqrt(value1[0] * value1[0] + value1[1] * value1[1]); - pitch = (int)(atan2(value1[2], forward) * 180 / M_PI); + forward = sqrt(value[0] * value[0] + value[1] * value[1]); + pitch = (int)(atan2(value[2], forward) * 180 / M_PI); if (pitch < 0) { @@ -442,10 +460,15 @@ vectoangles(vec3_t value1, vec3_t angles) } char * -G_CopyString(char *in) +G_CopyString(const char *in) { char *out; + if (!in) + { + return NULL; + } + out = gi.TagMalloc(strlen(in) + 1, TAG_LEVEL); strcpy(out, in); return out; @@ -454,6 +477,11 @@ G_CopyString(char *in) void G_InitEdict(edict_t *e) { + if (!e) + { + return; + } + e->inuse = true; e->classname = "noclass"; e->gravity = 1.0; @@ -502,6 +530,11 @@ G_Spawn(void) void G_FreeEdict(edict_t *ed) { + if (!ed) + { + return; + } + gi.unlinkentity(ed); /* unlink from world */ if ((ed - g_edicts) <= (maxclients->value + BODY_QUEUE_SIZE)) @@ -521,6 +554,11 @@ G_TouchTriggers(edict_t *ent) int i, num; edict_t *touch[MAX_EDICTS], *hit; + if (!ent) + { + return; + } + /* dead things don't activate triggers! */ if ((ent->client || (ent->svflags & SVF_MONSTER)) && (ent->health <= 0)) { @@ -530,7 +568,7 @@ G_TouchTriggers(edict_t *ent) num = gi.BoxEdicts(ent->absmin, ent->absmax, touch, MAX_EDICTS, AREA_TRIGGERS); - /* be careful, it is possible to have an entity in this + /* 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++) { @@ -560,10 +598,15 @@ G_TouchSolids(edict_t *ent) int i, num; edict_t *touch[MAX_EDICTS], *hit; + if (!ent) + { + return; + } + num = gi.BoxEdicts(ent->absmin, ent->absmax, touch, MAX_EDICTS, AREA_SOLID); - /* be careful, it is possible to have an entity in this + /* 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++) { @@ -587,22 +630,20 @@ G_TouchSolids(edict_t *ent) } /* - * ============================================================================== - * - * Kill box - * - * ============================================================================== - */ - -/* - * Kills all entities that would touch the proposed new positioning - * of ent. Ent should be unlinked before calling this! + * Kills all entities that would touch the + * proposed new positioning of ent. Ent s + * hould be unlinked before calling this! */ qboolean KillBox(edict_t *ent) { trace_t tr; + if (!ent) + { + return false; + } + while (1) { tr = gi.trace(ent->s.origin, ent->mins, ent->maxs, ent->s.origin, @@ -627,4 +668,3 @@ KillBox(edict_t *ent) return true; /* all clear */ } - diff --git a/src/g_weapon.c b/src/g_weapon.c index 18ca8db..27be690 100644 --- a/src/g_weapon.c +++ b/src/g_weapon.c @@ -22,7 +22,7 @@ * Weapon support functions. * * ======================================================================= - */ + */ #include "header/local.h" @@ -84,13 +84,13 @@ fire_hit(edict_t *self, vec3_t aim, int damage, int kick) if ((aim[1] > self->mins[0]) && (aim[1] < self->maxs[0])) { - /* the hit is straight on so back the + /* the hit is straight on so back the range up to the edge of their bbox */ range -= self->enemy->maxs[0]; } else { - /* this is a side hit so adjust the "right" + /* this is a side hit so adjust the "right" value out to the edge of their bbox */ if (aim[1] < 0) { @@ -150,7 +150,7 @@ fire_hit(edict_t *self, vec3_t aim, int damage, int kick) } /* - * This is an internal support routine + * This is an internal support routine * used for bullet/pellet based weapons. */ static void @@ -279,7 +279,7 @@ fire_lead(edict_t *self, vec3_t start, vec3_t aimdir, int damage, } } - /* if went through water, determine where + /* if went through water, determine where the end and make a bubble trail */ if (water) { @@ -310,7 +310,7 @@ fire_lead(edict_t *self, vec3_t start, vec3_t aimdir, int damage, } /* - * Fires a single round. Used for machinegun and + * Fires a single round. Used for machinegun and * chaingun. Would be fine for pistols, rifles, etc.... */ void @@ -322,7 +322,7 @@ fire_bullet(edict_t *self, vec3_t start, vec3_t aimdir, int damage, } /* - * Shoots shotgun pellets. Used by + * Shoots shotgun pellets. Used by * shotgun and super shotgun. */ void @@ -339,11 +339,11 @@ fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, } /* - * Fires a single blaster bolt. Used + * Fires a single blaster bolt. Used * by the blaster and hyper blaster. */ void -blaster_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +blaster_touch(edict_t *self, edict_t *other, const cplane_t *plane, const csurface_t *surf) { int mod; @@ -533,7 +533,7 @@ Grenade_Explode(edict_t *ent) } static void -Grenade_Touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +Grenade_Touch(edict_t *ent, edict_t *other, const cplane_t *plane, const csurface_t *surf) { if (other == ent->owner) { @@ -665,7 +665,7 @@ fire_grenade2(edict_t *self, vec3_t start, vec3_t aimdir, int damage, } void -rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +rocket_touch(edict_t *ent, edict_t *other, const cplane_t *plane, const csurface_t *surf) { vec3_t origin; int n; @@ -903,7 +903,7 @@ bfg_explode(edict_t *self) } void -bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +bfg_touch(edict_t *self, edict_t *other, const cplane_t *plane, const csurface_t *surf) { if (other == self->owner) { diff --git a/src/header/ctf.h b/src/header/ctf.h index 0e8dd12..d22a0a1 100644 --- a/src/header/ctf.h +++ b/src/header/ctf.h @@ -131,7 +131,7 @@ 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 CTFDrop_Flag(edict_t *ent, const gitem_t *item); void CTFEffects(edict_t *player); void CTFCalcScores(void); void SetCTFStats(edict_t *ent); @@ -154,7 +154,7 @@ 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 CTFDrop_Tech(edict_t *ent, const gitem_t *item); void CTFDeadDropTech(edict_t *ent); void CTFSetupTechSpawn(void); int CTFApplyResistance(edict_t *ent, int dmg); diff --git a/src/header/local.h b/src/header/local.h index 6e92edc..c9b352f 100644 --- a/src/header/local.h +++ b/src/header/local.h @@ -127,8 +127,11 @@ typedef enum #define RANGE_FAR 3 /* gib types */ -#define GIB_ORGANIC 0 -#define GIB_METALLIC 1 +typedef enum +{ + GIB_ORGANIC, + GIB_METALLIC +} gibtype_t; /* monster ai flags */ #define AI_STAND_GROUND 0x00000001 @@ -236,23 +239,23 @@ typedef struct typedef struct gitem_s { - char *classname; /* spawning name */ + const char *classname; /* spawning name */ qboolean (*pickup)(struct edict_s *ent, struct edict_s *other); - void (*use)(struct edict_s *ent, struct gitem_s *item); - void (*drop)(struct edict_s *ent, struct gitem_s *item); + void (*use)(struct edict_s *ent, const struct gitem_s *item); + void (*drop)(struct edict_s *ent, const struct gitem_s *item); void (*weaponthink)(struct edict_s *ent); - char *pickup_sound; - char *world_model; + const char *pickup_sound; + const char *world_model; int world_model_flags; - char *view_model; + const char *view_model; /* client side info */ - char *icon; - char *pickup_name; /* for printing on pickup */ + const char *icon; + const char *pickup_name; /* for printing on pickup */ int count_width; /* number of digits to display by icon */ int quantity; /* for ammo how much, for weapons how much is used per shot */ - char *ammo; /* for weapons */ + const char *ammo; /* for weapons */ int flags; /* IT_* flags */ int weapmodel; /* weapon model index (for weapons) */ @@ -260,7 +263,7 @@ typedef struct gitem_s void *info; int tag; - char *precaches; /* string of all models, sounds, and images this item will use */ + const char *precaches; /* string of all models, sounds, and images this item will use */ } gitem_t; /* this structure is left intact through an entire game @@ -306,7 +309,7 @@ typedef struct /* intermission state */ float intermissiontime; /* time the intermission was started */ - char *changemap; + const char *changemap; int exitintermission; vec3_t intermission_origin; vec3_t intermission_angle; @@ -492,8 +495,13 @@ extern int gibsthisframe; #define MOD_GRAPPLE 34 #define MOD_FRIENDLY_FIRE 0x8000000 -extern int meansOfDeath; +/* Easier handling of AI skill levels */ +#define SKILL_EASY 0 +#define SKILL_MEDIUM 1 +#define SKILL_HARD 2 +#define SKILL_HARDPLUS 3 +extern int meansOfDeath; extern edict_t *g_edicts; #define FOFS(x) (size_t)&(((edict_t *)NULL)->x) @@ -598,30 +606,32 @@ void ClientCommand(edict_t *ent); void Cmd_Score_f(edict_t *ent); /* g_items.c */ -void PrecacheItem(gitem_t *it); +void PrecacheItem(const gitem_t *it); void InitItems(void); void SetItemNames(void); -gitem_t *FindItem(char *pickup_name); -gitem_t *FindItemByClassname(char *classname); +gitem_t *FindItem(const char *pickup_name); +gitem_t *FindItemByClassname(const char *classname); #define ITEM_INDEX(x) ((x) - itemlist) -edict_t *Drop_Item(edict_t *ent, gitem_t *item); + +edict_t *Drop_Item(edict_t *ent, const gitem_t *item); void SetRespawn(edict_t *ent, float delay); void ChangeWeapon(edict_t *ent); void SpawnItem(edict_t *ent, gitem_t *item); void Think_Weapon(edict_t *ent); -int ArmorIndex(edict_t *ent); -int PowerArmorType(edict_t *ent); +int ArmorIndex(const edict_t *ent); +int PowerArmorType(const edict_t *ent); gitem_t *GetItemByIndex(int index); -qboolean Add_Ammo(edict_t *ent, gitem_t *item, int count); -void Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf); +qboolean Add_Ammo(edict_t *ent, const gitem_t *item, int count); +void Touch_Item(edict_t *ent, edict_t *other, const cplane_t *plane, + const csurface_t *surf); /* g_utils.c */ qboolean KillBox(edict_t *ent); -void G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward, - vec3_t right, vec3_t result); -edict_t *G_Find(edict_t *from, int fieldofs, char *match); -edict_t *findradius(edict_t *from, vec3_t org, float rad); +void G_ProjectSource(const vec3_t point, const vec3_t distance, const vec3_t forward, + const vec3_t right, vec3_t result); +edict_t *G_Find(edict_t *from, int fieldofs, const char *match); +edict_t *findradius(edict_t *from, const vec3_t org, float rad); edict_t *G_PickTarget(char *targetname); void G_UseTargets(edict_t *ent, edict_t *activator); void G_SetMovedir(vec3_t angles, vec3_t movedir); @@ -633,23 +643,24 @@ void G_FreeEdict(edict_t *e); void G_TouchTriggers(edict_t *ent); void G_TouchSolids(edict_t *ent); -char *G_CopyString(char *in); +char *G_CopyString(const char *in); float *tv(float x, float y, float z); char *vtos(vec3_t v); float vectoyaw(vec3_t vec); -void vectoangles(vec3_t vec, vec3_t angles); +void vectoangles(const vec3_t value, vec3_t angles); /* g_combat.c */ -qboolean OnSameTeam(edict_t *ent1, edict_t *ent2); +qboolean OnSameTeam(const edict_t *ent1, const edict_t *ent2); qboolean CanDamage(edict_t *targ, edict_t *inflictor); qboolean CheckTeamDamage(edict_t *targ, edict_t *attacker); void T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, - vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, - int dflags, int mod); -void T_RadiusDamage(edict_t *inflictor, edict_t *attacker, float damage, - edict_t *ignore, float radius, int mod); + vec3_t dir, vec3_t point, const vec3_t normal, int damage, + int knockback, int dflags, int mod); +void T_RadiusDamage(edict_t *inflictor, edict_t *attacker, + float damage, const edict_t *ignore, float radius, + int mod); /* damage flags */ #define DAMAGE_RADIUS 0x00000001 /* damage was indirect */ @@ -670,18 +681,20 @@ void T_RadiusDamage(edict_t *inflictor, edict_t *attacker, float damage, /* g_monster.c */ void monster_fire_bullet(edict_t *self, vec3_t start, vec3_t dir, int damage, int kick, int hspread, int vspread, int flashtype); -void monster_fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, - int kick, int hspread, int vspread, int count, int flashtype); -void monster_fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage, - int speed, int flashtype, int effect); +void monster_fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, + int damage, int kick, int hspread, int vspread, int count, + int flashtype); +void monster_fire_blaster(edict_t *self, vec3_t start, vec3_t dir, + int damage, int speed, int flashtype, int effect); void monster_fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int flashtype); -void monster_fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage, - int speed, int flashtype); +void monster_fire_rocket(edict_t *self, vec3_t start, vec3_t dir, + int damage, int speed, int flashtype); void monster_fire_railgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int flashtype); -void monster_fire_bfg(edict_t *self, vec3_t start, vec3_t aimdir, int damage, - int speed, int kick, float damage_radius, int flashtype); +void monster_fire_bfg(edict_t *self, vec3_t start, vec3_t aimdir, + int damage, int speed, int kick, float damage_radius, + int flashtype); void M_droptofloor(edict_t *ent); void monster_think(edict_t *self); void walkmonster_start(edict_t *self); @@ -695,9 +708,9 @@ void M_FlyCheck(edict_t *self); void M_CheckGround(edict_t *ent); /* g_misc.c */ -void ThrowHead(edict_t *self, char *gibname, int damage, int type); +void ThrowHead(edict_t *self, const char *gibname, int damage, gibtype_t type); void ThrowClientHead(edict_t *self, int damage); -void ThrowGib(edict_t *self, char *gibname, int damage, int type); +void ThrowGib(edict_t *self, const char *gibname, int damage, gibtype_t type); void BecomeExplosion1(edict_t *self); /* g_ai.c */ @@ -713,8 +726,8 @@ int range(edict_t *self, edict_t *other); void FoundTarget(edict_t *self); qboolean infront(edict_t *self, edict_t *other); -qboolean visible(edict_t *self, edict_t *other); -qboolean FacingIdeal(edict_t *self); +qboolean visible(const edict_t *self, const edict_t *other); +qboolean FacingIdeal(const edict_t *self); /* g_weapon.c */ void ThrowDebris(edict_t *self, char *modelname, float speed, vec3_t origin); @@ -745,7 +758,7 @@ edict_t *PlayerTrail_LastSpot(void); /* g_client.c */ void respawn(edict_t *ent); -void BeginIntermission(edict_t *targ); +void BeginIntermission(const edict_t *targ); void PutClientInServer(edict_t *ent); void InitClientPersistant(gclient_t *client); void InitClientResp(gclient_t *client); @@ -755,7 +768,7 @@ void ClientBeginServerFrame(edict_t *ent); /* g_player.c */ void player_pain(edict_t *self, edict_t *other, float kick, int damage); void player_die(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point); + int damage, const vec3_t point); /* g_svcmds.c */ void ServerCommand(void); @@ -771,6 +784,21 @@ void DeathmatchScoreboardMessage(edict_t *client, edict_t *killer); /* g_pweapon.c */ void PlayerNoise(edict_t *who, vec3_t where, int type); +qboolean Pickup_Weapon(edict_t *ent, edict_t *other); +void Use_Weapon(edict_t *ent, const gitem_t *item); +void Drop_Weapon(edict_t *ent, const gitem_t *item); +void Weapon_Blaster(edict_t *ent); +void Weapon_Shotgun(edict_t *ent); +void Weapon_SuperShotgun(edict_t *ent); +void Weapon_Machinegun(edict_t *ent); +void Weapon_Chaingun(edict_t *ent); +void Weapon_HyperBlaster(edict_t *ent); +void Weapon_RocketLauncher(edict_t *ent); +void Weapon_Grenade(edict_t *ent); +void Weapon_GrenadeLauncher(edict_t *ent); +void Weapon_Railgun(edict_t *ent); +void Weapon_BFG(edict_t *ent); +void Use_Quad(edict_t *ent, const gitem_t *item); void P_ProjectSource(edict_t *ent, 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, @@ -788,7 +816,6 @@ void G_RunEntity(edict_t *ent); /* g_main.c */ void SaveClientData(void); -void FetchClientEntData(edict_t *ent); void EndDMLevel(void); /* g_svcmds.c */ @@ -839,8 +866,8 @@ typedef struct int max_cells; int max_slugs; - gitem_t *weapon; - gitem_t *lastweapon; + const gitem_t *weapon; + const gitem_t *lastweapon; int power_cubes; /* used for tracking the cubes in coop games */ int score; /* for calculating total unit score in coop games */ @@ -897,7 +924,7 @@ struct gclient_s qboolean weapon_thunk; - gitem_t *newweapon; + const gitem_t *newweapon; /* sum up damage over an entire frame, so shotgun blasts give a single big kick */ @@ -1004,14 +1031,14 @@ struct edict_s /* only used locally in game, not by server */ char *message; - char *classname; + const char *classname; int spawnflags; float timestamp; float angle; /* set in qe3, -1 = up, -2 = down */ char *target; - char *targetname; + const char *targetname; char *killtarget; char *team; char *pathtarget; @@ -1039,12 +1066,12 @@ struct edict_s void (*prethink)(edict_t *ent); void (*think)(edict_t *self); void (*blocked)(edict_t *self, edict_t *other); /* move to moveinfo? */ - void (*touch)(edict_t *self, edict_t *other, cplane_t *plane, - csurface_t *surf); + void (*touch)(edict_t *self, edict_t *other, const cplane_t *plane, + const csurface_t *surf); void (*use)(edict_t *self, edict_t *other, edict_t *activator); void (*pain)(edict_t *self, edict_t *other, float kick, int damage); void (*die)(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point); + int damage, const vec3_t point); float touch_debounce_time; /* are all these legit? do we need more/less of them? */ float pain_debounce_time; @@ -1056,11 +1083,11 @@ struct edict_s int max_health; int gib_health; int deadflag; - int show_hostile; + float show_hostile; float powerarmor_time; - char *map; /* target_changelevel */ + const char *map; /* target_changelevel */ int viewheight; /* height above origin where eyesight is determined */ int takedamage; @@ -1105,7 +1132,7 @@ struct edict_s int style; /* also used as areaportal number */ - gitem_t *item; /* for bonus items */ + const gitem_t *item; /* for bonus items */ /* common data blocks */ moveinfo_t moveinfo; diff --git a/src/player/client.c b/src/player/client.c index aabbb1a..7daa1e2 100644 --- a/src/player/client.c +++ b/src/player/client.c @@ -36,6 +36,12 @@ void SP_misc_teleporter_dest(edict_t *ent); void SP_info_player_start(edict_t *self) { + if (!self) + { + return; + } + + if (!coop->value) { return; @@ -49,6 +55,11 @@ SP_info_player_start(edict_t *self) void SP_info_player_deathmatch(edict_t *self) { + if (!self) + { + return; + } + if (!deathmatch->value) { G_FreeEdict(self); @@ -66,6 +77,11 @@ SP_info_player_deathmatch(edict_t *self) void SP_info_player_coop(edict_t *self) { + if (!self) + { + return; + } + if (!coop->value) { G_FreeEdict(self); @@ -87,17 +103,26 @@ SP_info_player_intermission(edict_t *ent) /* ======================================================================= */ void -player_pain(edict_t *self, edict_t *other, float kick, int damage) +player_pain(edict_t *self /* unused */, edict_t *other /* unused */, + float kick /* unused */, int damage /* unused */) { - /* player pain is handled at the - end of the frame in P_DamageFeedback */ + /* Player pain is handled at the end + * of the frame in P_DamageFeedback. + * This function is still here since + * the player is an entity and needs + * a pain callback */ } -qboolean +static qboolean IsFemale(edict_t *ent) { char *info; + if (!ent) + { + return false; + } + if (!ent->client) { return false; @@ -113,15 +138,52 @@ IsFemale(edict_t *ent) return false; } +static qboolean +IsNeutral(edict_t *ent) +{ + char *info; + + if (!ent) + { + return false; + } + + if (!ent->client) + { + return false; + } + + info = Info_ValueForKey(ent->client->pers.userinfo, "gender"); + + if (strstr(info, "crakhor")) + { + return false; + } + + if ((info[0] != 'f') && (info[0] != 'F') && (info[0] != 'm') && + (info[0] != 'M')) + { + return true; + } + + return false; +} + void -ClientObituary(edict_t *self, edict_t *inflictor, edict_t *attacker) +ClientObituary(edict_t *self, edict_t *inflictor /* unused */, + edict_t *attacker) { int mod; char *message; char *message2; qboolean ff; - if (coop->value && attacker->client) + if (!self || !inflictor) + { + return; + } + + if (coop->value && attacker && attacker->client) { meansOfDeath |= MOD_FRIENDLY_FIRE; } @@ -183,7 +245,11 @@ ClientObituary(edict_t *self, edict_t *inflictor, edict_t *attacker) case MOD_HG_SPLASH: case MOD_G_SPLASH: - if (IsFemale(self)) + if (IsNeutral(self)) + { + message = "tripped on its own grenade"; + } + else if (IsFemale(self)) { message = "tripped on her own grenade"; } @@ -195,7 +261,11 @@ ClientObituary(edict_t *self, edict_t *inflictor, edict_t *attacker) break; case MOD_R_SPLASH: - if (IsFemale(self)) + if (IsNeutral(self)) + { + message = "blew itself up"; + } + else if (IsFemale(self)) { message = "blew herself up"; } @@ -210,7 +280,11 @@ ClientObituary(edict_t *self, edict_t *inflictor, edict_t *attacker) break; default: - if (IsFemale(self)) + if (IsNeutral(self)) + { + message = "killed itself"; + } + else if (IsFemale(self)) { message = "killed herself"; } @@ -348,16 +422,19 @@ ClientObituary(edict_t *self, edict_t *inflictor, edict_t *attacker) } } -void Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf); - void TossClientWeapon(edict_t *self) { - gitem_t *item; + const gitem_t *item; edict_t *drop; qboolean quad; float spread; + if (!self) + { + return; + } + if (!deathmatch->value) { return; @@ -420,6 +497,11 @@ LookAtKiller(edict_t *self, edict_t *inflictor, edict_t *attacker) { vec3_t dir; + if (!self) + { + return; + } + if (attacker && (attacker != world) && (attacker != self)) { VectorSubtract(attacker->s.origin, self->s.origin, dir); @@ -460,10 +542,15 @@ LookAtKiller(edict_t *self, edict_t *inflictor, edict_t *attacker) void player_die(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) + int damage, const vec3_t point /* unused */) { int n; + if (!self || !inflictor || !attacker) + { + return; + } + VectorClear(self->avelocity); self->takedamage = DAMAGE_YES; @@ -596,6 +683,11 @@ InitClientPersistant(gclient_t *client) { gitem_t *item; + if (!client) + { + return; + } + memset(&client->pers, 0, sizeof(client->pers)); item = FindItem("Blaster"); @@ -627,6 +719,11 @@ InitClientResp(gclient_t *client) int ctf_team = client->resp.ctf_team; qboolean id_state = client->resp.id_state; + if (!client) + { + return; + } + memset(&client->resp, 0, sizeof(client->resp)); client->resp.ctf_team = ctf_team; @@ -674,9 +771,14 @@ SaveClientData(void) } } -void +static void FetchClientEntData(edict_t *ent) { + if (!ent) + { + return; + } + ent->health = ent->client->pers.health; ent->max_health = ent->client->pers.max_health; ent->flags |= ent->client->pers.savedFlags; @@ -702,6 +804,11 @@ PlayersRangeFromSpot(edict_t *spot) int n; float playerdistance; + if (!spot) + { + return 0.0; + } + bestplayerdistance = 9999999; for (n = 1; n <= maxclients->value; n++) @@ -832,7 +939,7 @@ SelectFarthestDeathmatchSpawnPoint(void) return spot; } -edict_t * +static edict_t * SelectDeathmatchSpawnPoint(void) { if ((int)(dmflags->value) & DF_SPAWN_FARTHEST) @@ -845,12 +952,16 @@ SelectDeathmatchSpawnPoint(void) } } -edict_t * +static edict_t * SelectCoopSpawnPoint(edict_t *ent) { int index; edict_t *spot = NULL; - char *target; + + if (!ent) + { + return NULL; + } index = ent->client - game.clients; @@ -865,6 +976,8 @@ SelectCoopSpawnPoint(edict_t *ent) /* assume there are four coop spots at each spawnpoint */ while (1) { + const char *target; + spot = G_Find(spot, FOFS(classname), "info_player_coop"); if (!spot) @@ -977,11 +1090,17 @@ InitBodyQue(void) } void -body_die(edict_t *self, edict_t *inflictor, edict_t *attacker, - int damage, vec3_t point) +body_die(edict_t *self, edict_t *inflictor /* unused */, + edict_t *attacker /* unused */, int damage, + const vec3_t point /* unused */) { int n; + if (!self) + { + return; + } + if (self->health < -40) { gi.sound(self, CHAN_BODY, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0); @@ -1003,12 +1122,16 @@ CopyToBodyQue(edict_t *ent) { edict_t *body; + if (!ent) + { + return; + } + /* grab a body que and cycle to the next one */ body = &g_edicts[(int)maxclients->value + level.body_que + 1]; level.body_que = (level.body_que + 1) % BODY_QUEUE_SIZE; gi.unlinkentity(ent); - gi.unlinkentity(body); body->s = ent->s; body->s.number = body - g_edicts; @@ -1033,8 +1156,14 @@ CopyToBodyQue(edict_t *ent) void respawn(edict_t *self) { + if (!self) + { + return; + } + if (deathmatch->value || coop->value) { + /* spectator's don't leave bodies */ if (self->movetype != MOVETYPE_NOCLIP) { CopyToBodyQue(self); @@ -1069,6 +1198,11 @@ respawn(edict_t *self) void PutClientInServer(edict_t *ent) { + if (!ent) + { + return; + } + vec3_t mins = {-16, -16, -24}; vec3_t maxs = {16, 16, 32}; int index; @@ -1245,6 +1379,11 @@ PutClientInServer(edict_t *ent) void ClientBeginDeathmatch(edict_t *ent) { + if (!ent) + { + return; + } + G_InitEdict(ent); InitClientResp(ent->client); @@ -1280,6 +1419,11 @@ ClientBegin(edict_t *ent) { int i; + if (!ent) + { + return; + } + ent->client = game.clients + (ent - g_edicts - 1); if (deathmatch->value) @@ -1349,6 +1493,11 @@ ClientUserinfoChanged(edict_t *ent, char *userinfo) char *s; int playernum; + if (!ent || !userinfo) + { + return; + } + /* check for malformed or illegal info strings */ if (!Info_Validate(userinfo)) { @@ -1357,7 +1506,7 @@ ClientUserinfoChanged(edict_t *ent, char *userinfo) /* set name */ s = Info_ValueForKey(userinfo, "name"); - strncpy(ent->client->pers.netname, s, sizeof(ent->client->pers.netname) - 1); + Q_strlcpy(ent->client->pers.netname, s, sizeof(ent->client->pers.netname)); /* set skin */ s = Info_ValueForKey(userinfo, "skin"); @@ -1406,8 +1555,7 @@ ClientUserinfoChanged(edict_t *ent, char *userinfo) } /* save off the userinfo in case we want to check something later */ - strncpy(ent->client->pers.userinfo, userinfo, - sizeof(ent->client->pers.userinfo) - 1); + Q_strlcpy(ent->client->pers.userinfo, userinfo, sizeof(ent->client->pers.userinfo)); } /* @@ -1423,6 +1571,11 @@ ClientConnect(edict_t *ent, char *userinfo) { char *value; + if (!ent || !userinfo) + { + return false; + } + /* check to see if they are on the banned IP list */ value = Info_ValueForKey(userinfo, "ip"); @@ -1482,6 +1635,11 @@ ClientDisconnect(edict_t *ent) { int playernum; + if (!ent) + { + return; + } + if (!ent->client) { return; @@ -1511,13 +1669,13 @@ ClientDisconnect(edict_t *ent) /* ============================================================== */ -edict_t *pm_passent; +static edict_t *pm_passent; /* - * pmove doesn't need to know about - * passent and contentmask + * pmove doesn't need to know + * about passent and contentmask */ -trace_t +static trace_t PM_trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end) { if (pm_passent->health > 0) @@ -1535,6 +1693,11 @@ CheckBlock(void *b, int c) { int v, i; + if (!b) + { + return 0; + } + v = 0; for (i = 0; i < c; i++) @@ -1550,6 +1713,11 @@ PrintPmove(pmove_t *pm) { unsigned c1, c2; + if (!pm) + { + return; + } + c1 = CheckBlock(&pm->s, sizeof(pm->s)); c2 = CheckBlock(&pm->cmd, sizeof(pm->cmd)); Com_Printf("sv %3i:%i %i\n", pm->cmd.impulse, c1, c2); @@ -1567,6 +1735,11 @@ ClientThink(edict_t *ent, usercmd_t *ucmd) int i, j; pmove_t pm; + if (!ent || !ucmd) + { + return; + } + level.current_entity = ent; client = ent->client; @@ -1774,6 +1947,11 @@ ClientBeginServerFrame(edict_t *ent) gclient_t *client; int buttonMask; + if (!ent) + { + return; + } + if (level.intermissiontime) { return; @@ -1831,4 +2009,3 @@ ClientBeginServerFrame(edict_t *ent) client->latched_buttons = 0; } - diff --git a/src/player/hud.c b/src/player/hud.c index c158795..3f75c8a 100644 --- a/src/player/hud.c +++ b/src/player/hud.c @@ -79,7 +79,7 @@ MoveClientToIntermission(edict_t *ent) } void -BeginIntermission(edict_t *targ) +BeginIntermission(const edict_t *targ) { int i, n; edict_t *ent, *client; @@ -154,7 +154,7 @@ BeginIntermission(edict_t *targ) ent = G_Find(NULL, FOFS(classname), "info_player_intermission"); if (!ent) - { + { /* the map creator forgot to put in an intermission point... */ ent = G_Find(NULL, FOFS(classname), "info_player_start"); @@ -474,7 +474,7 @@ G_SetStats(edict_t *ent) cells = ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))]; if (cells == 0) - { + { /* ran out of cells for power armor */ ent->flags &= ~FL_POWER_ARMOR; gi.sound(ent, CHAN_ITEM, gi.soundindex( @@ -486,7 +486,7 @@ G_SetStats(edict_t *ent) index = ArmorIndex(ent); if (power_armor_type && (!index || (level.framenum & 8))) - { + { /* flash between power armor and other armor icon */ ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex("i_powershield"); ent->client->ps.stats[STAT_ARMOR] = cells; diff --git a/src/player/view.c b/src/player/view.c index 472b0d3..99891ce 100644 --- a/src/player/view.c +++ b/src/player/view.c @@ -22,7 +22,7 @@ * The "camera" through which the player looks into the game. * * ======================================================================= - */ + */ #include "../header/local.h" #include "../monster/player.h" @@ -31,11 +31,11 @@ static edict_t *current_player; static gclient_t *current_client; static vec3_t forward, right, up; -float xyspeed; +static float xyspeed; -float bobmove; -int bobcycle; /* odd cycles are right foot going forward */ -float bobfracsin; /* sin(bobfrac*M_PI) */ +static float bobmove; +static int bobcycle; /* odd cycles are right foot going forward */ +static float bobfracsin; /* sin(bobfrac*M_PI) */ float SV_CalcRoll(vec3_t angles, vec3_t velocity) @@ -77,6 +77,11 @@ P_DamageFeedback(edict_t *player) static vec3_t acolor = {1.0, 1.0, 1.0}; static vec3_t bcolor = {1.0, 0.0, 0.0}; + if (!player) + { + return; + } + client = player->client; /* flash the backgrounds behind the status numbers */ @@ -172,7 +177,7 @@ P_DamageFeedback(edict_t *player) l, r)), 1, ATTN_NORM, 0); } - /* the total alpha of the blend is allways proportional to count */ + /* the total alpha of the blend is always proportional to count */ if (client->damage_alpha < 0) { client->damage_alpha = 0; @@ -409,6 +414,11 @@ SV_CalcGunOffset(edict_t *ent) int i; float delta; + if (!ent) + { + return; + } + /* gun angles from bobbing */ ent->client->ps.gunangles[ROLL] = xyspeed * bobfracsin * 0.005; ent->client->ps.gunangles[YAW] = xyspeed * bobfracsin * 0.01; @@ -471,6 +481,11 @@ SV_AddBlend(float r, float g, float b, float a, float *v_blend) { float a2, a3; + if (!v_blend) + { + return; + } + if (a <= 0) { return; @@ -492,6 +507,11 @@ SV_CalcBlend(edict_t *ent) vec3_t vieworg; int remaining; + if (!ent) + { + return; + } + ent->client->ps.blend[0] = ent->client->ps.blend[1] = ent->client->ps.blend[2] = ent->client->ps.blend[3] = 0; @@ -624,6 +644,11 @@ P_FallingDamage(edict_t *ent) int damage; vec3_t dir; + if (!ent) + { + return; + } + if (ent->s.modelindex != 255) { return; /* not in the player model */ @@ -799,14 +824,14 @@ P_WorldEffects(void) if ((old_waterlevel == 3) && (waterlevel != 3)) { if (current_player->air_finished < level.time) - { + { /* gasp for air */ gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/gasp1.wav"), 1, ATTN_NORM, 0); PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); } else if (current_player->air_finished < level.time + 11) - { + { /* just break surface */ gi.sound(current_player, CHAN_VOICE, gi.soundindex("player/gasp2.wav"), 1, ATTN_NORM, 0); @@ -843,7 +868,7 @@ P_WorldEffects(void) /* if out of air, start drowning */ if (current_player->air_finished < level.time) - { + { /* drown! */ if ((current_player->client->next_drown_time < level.time) && (current_player->health > 0)) @@ -930,7 +955,7 @@ P_WorldEffects(void) if (current_player->watertype & CONTENTS_SLIME) { if (!envirosuit) - { + { /* no damage from slime with envirosuit */ T_Damage(current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, @@ -946,6 +971,11 @@ G_SetClientEffects(edict_t *ent) int pa_type; int remaining; + if (!ent) + { + return; + } + ent->s.effects = 0; ent->s.renderfx = 0; @@ -1002,11 +1032,21 @@ G_SetClientEffects(edict_t *ent) void G_SetClientEvent(edict_t *ent) { + if (!ent) + { + return; + } + if (ent->s.event) { return; } + if (ent->health <= 0) + { + return; + } + if (ent->groundentity && (xyspeed > 225)) { if ((int)(current_client->bobtime + bobmove) != bobcycle) @@ -1019,7 +1059,12 @@ G_SetClientEvent(edict_t *ent) void G_SetClientSound(edict_t *ent) { - char *weap; + const char *weap; + + if (!ent) + { + return; + } if (ent->client->resp.game_helpchanged != game.helpchanged) { @@ -1073,6 +1118,11 @@ G_SetClientFrame(edict_t *ent) gclient_t *client; qboolean duck, run; + if (!ent) + { + return; + } + if (ent->s.modelindex != 255) { return; /* not in the player model */ @@ -1123,7 +1173,7 @@ G_SetClientFrame(edict_t *ent) } } else if (ent->s.frame < client->anim_end) - { + { /* continue an animation */ ent->s.frame++; return; @@ -1148,7 +1198,7 @@ G_SetClientFrame(edict_t *ent) } newanim: - + /* return to either a running or standing frame */ client->anim_priority = ANIM_BASIC; client->anim_duck = duck; @@ -1176,7 +1226,7 @@ G_SetClientFrame(edict_t *ent) } } else if (run) - { + { /* running */ if (duck) { @@ -1206,8 +1256,8 @@ G_SetClientFrame(edict_t *ent) } /* - * Called for each player at the end of the server frame - * and right after spawning + * Called for each player at the end of + * the server frame and right after spawning */ void ClientEndServerFrame(edict_t *ent) @@ -1215,13 +1265,17 @@ ClientEndServerFrame(edict_t *ent) float bobtime; int i; + if (!ent) + { + return; + } + current_player = ent; current_client = ent->client; /* If the origin or velocity have changed since ClientThink(), - update the pmove values. This will happen when the client - is pushed by a bmodel or kicked by an explosion. - + update the pmove values. This will happen when the client + is pushed by a bmodel or kicked by an explosion. If it wasn't updated here, the view position would lag a frame behind the body position when pushed -- "sinking into plats" */ for (i = 0; i < 3; i++) @@ -1260,7 +1314,7 @@ ClientEndServerFrame(edict_t *ent) ent->s.angles[ROLL] = 0; ent->s.angles[ROLL] = SV_CalcRoll(ent->s.angles, ent->velocity) * 4; - /* calculate speed and cycle to be used for + /* calculate speed and cycle to be used for all cyclic walking effects */ xyspeed = sqrt(ent->velocity[0] * ent->velocity[0] + ent->velocity[1] * ent->velocity[1]); @@ -1271,7 +1325,7 @@ ClientEndServerFrame(edict_t *ent) current_client->bobtime = 0; /* start at beginning of cycle again */ } else if (ent->groundentity) - { + { /* so bobbing only cycles when on ground */ if (xyspeed > 210) { @@ -1309,9 +1363,9 @@ ClientEndServerFrame(edict_t *ent) /* determine the gun offsets */ SV_CalcGunOffset(ent); - /* determine the full screen color blend - must be after viewoffset, so eye contents can be - accurately determined */ + /* determine the full screen color blend + must be after viewoffset, so eye contents + can be accurately determined */ SV_CalcBlend(ent); if (!ent->client->chase_target) @@ -1367,4 +1421,3 @@ ClientEndServerFrame(edict_t *ent) gi.unicast(ent, false); } } - diff --git a/src/player/weapon.c b/src/player/weapon.c index d241277..e1d9aff 100644 --- a/src/player/weapon.c +++ b/src/player/weapon.c @@ -22,7 +22,7 @@ * Player weapons. * * ======================================================================= - */ + */ #include "../header/local.h" #include "../monster/player.h" @@ -40,6 +40,11 @@ P_ProjectSource(edict_t *ent, vec3_t distance, float *point = ent->s.origin; vec3_t _distance; + if (!client) + { + return; + } + VectorCopy(distance, _distance); if (client->pers.hand == LEFT_HANDED) @@ -82,6 +87,11 @@ PlayerNoise(edict_t *who, vec3_t where, int type) { edict_t *noise; + if (!who || !who->client) + { + return; + } + if (type == PNOISE_WEAPON) { if (who->client->silencer_shots) @@ -146,6 +156,11 @@ Pickup_Weapon(edict_t *ent, edict_t *other) int index; gitem_t *ammo; + if (!ent || !other) + { + return false; + } + index = ITEM_INDEX(ent->item); if ((((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value) && @@ -206,7 +221,7 @@ Pickup_Weapon(edict_t *ent, edict_t *other) } /* - * The old weapon has been dropped all the + * The old weapon has been dropped all the * way, so make the new one current */ void @@ -214,6 +229,11 @@ ChangeWeapon(edict_t *ent) { int i; + if (!ent) + { + return; + } + if (ent->client->grenade_time) { ent->client->grenade_time = level.time; @@ -331,6 +351,11 @@ NoAmmoWeaponChange(edict_t *ent) void Think_Weapon(edict_t *ent) { + if (!ent) + { + return; + } + /* if just died, put the weapon away */ if (ent->health < 1) { @@ -360,11 +385,16 @@ Think_Weapon(edict_t *ent) * Make the weapon ready if there is ammo */ void -Use_Weapon(edict_t *ent, gitem_t *item) +Use_Weapon(edict_t *ent, const gitem_t *item) { int ammo_index; gitem_t *ammo_item; + if (!ent || !item) + { + return; + } + /* see if we're already using it */ if (item == ent->client->pers.weapon) { @@ -396,10 +426,15 @@ Use_Weapon(edict_t *ent, gitem_t *item) } void -Drop_Weapon(edict_t *ent, gitem_t *item) +Drop_Weapon(edict_t *ent, const gitem_t *item) { int index; + if (!ent || !item) + { + return; + } + if ((int)(dmflags->value) & DF_WEAPONS_STAY) { return; @@ -433,6 +468,10 @@ Weapon_Generic2(edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int *fire_frames, void (*fire)(edict_t *ent)) { int n; + if (!ent || !fire_frames || !fire) + { + return; + } if (ent->deadflag || (ent->s.modelindex != 255)) /* VWep animations screw up corpses */ { @@ -441,7 +480,7 @@ Weapon_Generic2(edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, if (ent->client->weaponstate == WEAPON_DROPPING) { - if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST) + if (ent->client->ps.gunframe >= FRAME_DEACTIVATE_LAST) { ChangeWeapon(ent); return; @@ -667,6 +706,11 @@ weapon_grenade_fire(edict_t *ent, qboolean held) int speed; float radius; + if (!ent) + { + return; + } + radius = damage + 40; if (is_quad) @@ -695,6 +739,11 @@ weapon_grenade_fire(edict_t *ent, qboolean held) return; } + if (ent->health <= 0) + { + return; + } + if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->client->anim_priority = ANIM_ATTACK; @@ -712,6 +761,11 @@ weapon_grenade_fire(edict_t *ent, qboolean held) void Weapon_Grenade(edict_t *ent) { + if (!ent) + { + return; + } + if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY)) { ChangeWeapon(ent); @@ -856,6 +910,11 @@ weapon_grenadelauncher_fire(edict_t *ent) int damage = 120; float radius; + if (!ent) + { + return; + } + radius = damage + 40; if (is_quad) @@ -914,6 +973,11 @@ Weapon_RocketLauncher_Fire(edict_t *ent) float damage_radius; int radius_damage; + if (!ent) + { + return; + } + damage = 100 + (int)(random() * 20.0); radius_damage = 120; damage_radius = 120; @@ -975,6 +1039,11 @@ Blaster_Fire(edict_t *ent, vec3_t g_offset, int damage, vec3_t start; vec3_t offset; + if (!ent) + { + return; + } + if (is_quad) { damage *= 4; @@ -1013,6 +1082,11 @@ Weapon_Blaster_Fire(edict_t *ent) { int damage; + if (!ent) + { + return; + } + if (deathmatch->value) { damage = 15; @@ -1032,6 +1106,11 @@ Weapon_Blaster(edict_t *ent) static int pause_frames[] = {19, 32, 0}; static int fire_frames[] = {5, 0}; + if (!ent) + { + return; + } + Weapon_Generic(ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire); } @@ -1044,6 +1123,11 @@ Weapon_HyperBlaster_Fire(edict_t *ent) int effect; int damage; + if (!ent) + { + return; + } + ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav"); if (!(ent->client->buttons & BUTTON_ATTACK)) @@ -1133,6 +1217,11 @@ Weapon_HyperBlaster(edict_t *ent) static int pause_frames[] = {0}; static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0}; + if (!ent) + { + return; + } + Weapon_Generic(ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire); } @@ -1156,6 +1245,11 @@ Machinegun_Fire(edict_t *ent) int kick = 2; vec3_t offset; + if (!ent) + { + return; + } + if (!(ent->client->buttons & BUTTON_ATTACK)) { ent->client->machinegun_shots = 0; @@ -1254,6 +1348,11 @@ Weapon_Machinegun(edict_t *ent) static int pause_frames[] = {23, 45, 0}; static int fire_frames[] = {4, 5, 0}; + if (!ent) + { + return; + } + Weapon_Generic(ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire); } @@ -1270,6 +1369,11 @@ Chaingun_Fire(edict_t *ent) int damage; int kick = 2; + if (!ent) + { + return; + } + if (deathmatch->value) { damage = 6; @@ -1411,6 +1515,11 @@ Weapon_Chaingun(edict_t *ent) static int pause_frames[] = {38, 43, 51, 61, 0}; static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0}; + if (!ent) + { + return; + } + Weapon_Generic(ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire); } @@ -1431,6 +1540,11 @@ weapon_shotgun_fire(edict_t *ent) int damage = 4; int kick = 8; + if (!ent) + { + return; + } + if (ent->client->ps.gunframe == 9) { ent->client->ps.gunframe++; @@ -1483,6 +1597,11 @@ Weapon_Shotgun(edict_t *ent) static int pause_frames[] = {22, 28, 34, 0}; static int fire_frames[] = {8, 9, 0}; + if (!ent) + { + return; + } + Weapon_Generic(ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire); } @@ -1497,6 +1616,11 @@ weapon_supershotgun_fire(edict_t *ent) int damage = 6; int kick = 12; + if (!ent) + { + return; + } + AngleVectors(ent->client->v_angle, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); @@ -1515,9 +1639,9 @@ weapon_supershotgun_fire(edict_t *ent) v[YAW] = ent->client->v_angle[YAW] - 5; v[ROLL] = ent->client->v_angle[ROLL]; AngleVectors(v, forward, NULL, NULL); - + if (aimfix->value) - { + { AngleVectors(v, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); @@ -1525,16 +1649,16 @@ weapon_supershotgun_fire(edict_t *ent) VectorSet(offset, 0, 8, ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); - } - + } + fire_shotgun(ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT / 2, MOD_SSHOTGUN); - + v[YAW] = ent->client->v_angle[YAW] + 5; AngleVectors(v, forward, NULL, NULL); - + if (aimfix->value) - { + { AngleVectors(v, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); @@ -1542,8 +1666,8 @@ weapon_supershotgun_fire(edict_t *ent) VectorSet(offset, 0, 8, ent->viewheight - 8); P_ProjectSource(ent, offset, forward, right, start); - } - + } + fire_shotgun(ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT / 2, MOD_SSHOTGUN); @@ -1569,6 +1693,11 @@ Weapon_SuperShotgun(edict_t *ent) static int pause_frames[] = {29, 42, 57, 0}; static int fire_frames[] = {7, 0}; + if (!ent) + { + return; + } + Weapon_Generic(ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire); } @@ -1590,8 +1719,13 @@ weapon_railgun_fire(edict_t *ent) int damage; int kick; + if (!ent) + { + return; + } + if (deathmatch->value) - { + { /* normal damage is too extreme in dm */ damage = 100; kick = 200; @@ -1638,6 +1772,11 @@ Weapon_Railgun(edict_t *ent) static int pause_frames[] = {56, 0}; static int fire_frames[] = {4, 0}; + if (!ent) + { + return; + } + Weapon_Generic(ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire); } @@ -1658,6 +1797,11 @@ weapon_bfg_fire(edict_t *ent) int damage; float damage_radius = 1000; + if (!ent) + { + return; + } + if (deathmatch->value) { damage = 200; @@ -1681,7 +1825,7 @@ weapon_bfg_fire(edict_t *ent) return; } - /* cells can go down during windup (from power armor hits), so + /* cells can go down during windup (from power armor hits), so check again and abort firing if we don't have enough now */ if (ent->client->pers.inventory[ent->client->ammo_index] < 50) { @@ -1723,7 +1867,11 @@ Weapon_BFG(edict_t *ent) static int pause_frames[] = {39, 45, 50, 55, 0}; static int fire_frames[] = {9, 17, 0}; + if (!ent) + { + return; + } + Weapon_Generic(ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire); } - From 361f1727eec0840fa862f54dfc6e475c0bc52f6c Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Fri, 1 May 2026 16:33:39 +0300 Subject: [PATCH 6/9] Makefile: fix build --- CMakeLists.txt | 13 +- Makefile | 161 ++++++++++++--- src/g_cmds.c | 4 +- src/header/local.h | 2 +- src/player/client.c | 13 +- src/shared/flash.c | 463 ++++++++++++++++++++++++++++++++++++++++++++ src/shared/rand.c | 97 ++++++++++ 7 files changed, 717 insertions(+), 36 deletions(-) create mode 100644 src/shared/flash.c create mode 100644 src/shared/rand.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a496c52..5c49bbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,15 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fno-strict-aliasing -fwrapv") # Use -O2 as maximum optimization level. -O3 has it's problems with yquake2. string(REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") +# Operating system +add_definitions(-DYQ2OSTYPE="${CMAKE_SYSTEM_NAME}") + +# Architecture string +string(REGEX REPLACE "amd64" "x86_64" YQ2_ARCH "${CMAKE_SYSTEM_PROCESSOR}") +string(REGEX REPLACE "i.86" "i386" YQ2_ARCH "${YQ2_ARCH}") +string(REGEX REPLACE "^arm.*" "arm" YQ2_ARCH "${YQ2_ARCH}") +add_definitions(-DYQ2ARCH="${YQ2_ARCH}") + # Linker Flags if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") list(APPEND CtfLinkerFlags "-lm") @@ -36,6 +45,9 @@ set(Ctf-Source src/player/trail.c src/player/view.c src/player/weapon.c + src/savegame/savegame.c + src/shared/flash.c + src/shared/rand.c src/shared/shared.c src/g_ai.c src/g_chase.c @@ -48,7 +60,6 @@ set(Ctf-Source src/g_misc.c src/g_monster.c src/g_phys.c - src/savegame/savegame.c src/g_spawn.c src/g_svcmds.c src/g_target.c diff --git a/Makefile b/Makefile index 68ae484..b3b1426 100755 --- a/Makefile +++ b/Makefile @@ -6,8 +6,8 @@ # # # Dependencies: # # - None, but you need a Quake II to play. # -# While in theory every one should work # -# Yamagi Quake II is recommended. # +# While in theory every one should work # +# Yamagi Quake II is recommended. # # # # Platforms: # # - FreeBSD # @@ -17,6 +17,54 @@ # - Windows # # ----------------------------------------------------- # +# Variables +# --------- +# ASAN +# Builds with address sanitizer, includes DEBUG. +# DEBUG +# Builds a debug build, forces -O0 and adds debug symbols. +# MINGW_CHOST +# If you use mingw this can specify architecture. +# Available values: +# x86_64-w64-mingw32 -> indicates x86_64 +# i686-w64-mingw32 -> indicates i386 +# QUIET +# If defined, "===> CC ..." lines are silenced. +# SOURCE_DATE_EPOCH +# For reproduceable builds, look here for details: +# https://reproducible-builds.org/specs/source-date-epoch/ +# If set, adds a BUILD_DATE define to CFLAGS. +# UBSAN +# Builds with undefined behavior sanitizer.includes DEBUG. +# VERBOSE +# Prints full compile, linker and misc commands. +# WERR +# Treat compiler warnings as errors. +# If defined, -Werror is added to compiler flags. +# ---------- + +# User configurable options +# ------------------------- + +# CONFIG_FILE +# This is an optional configuration file, it'll be used in +# case of presence. +CONFIG_FILE:=config.mk + +# ---------- + +# In case of a configuration file being present, we'll just use it +ifeq ($(wildcard $(CONFIG_FILE)), $(CONFIG_FILE)) +include $(CONFIG_FILE) +endif + +# Normalize QUIET value to either "x" or "" +ifdef QUIET + override QUIET := "x" +else + override QUIET := "" +endif + # Detect the OS ifdef SystemRoot YQ2_OSTYPE ?= Windows @@ -49,7 +97,7 @@ endif # windows but MINGW_CHOST not defined else ifneq ($(YQ2_OSTYPE), Darwin) # Normalize some abiguous YQ2_ARCH strings -YQ2_ARCH ?= $(shell uname -m | sed -e 's/i.86/i386/' -e 's/amd64/x86_64/' -e 's/arm64/aarch64/' -e 's/^arm.*/arm/') +YQ2_ARCH ?= $(shell uname -m | sed -e 's/i.86/i386/' -e 's/amd64/x86_64/' -e 's/^arm.*/arm/') else YQ2_ARCH ?= $(shell uname -m) endif @@ -71,24 +119,58 @@ else COMPILER := unknown endif +# ASAN includes DEBUG +ifdef ASAN +DEBUG=1 +endif + +# UBSAN includes DEBUG +ifdef UBSAN +DEBUG=1 +endif + +# ---------- + +# Set up build and bin output directories + +# Root dir names +override BINROOT := +override BUILDROOT := build + +override BINDIR := $(BINROOT)release +override BUILDDIR := $(BUILDROOT) + # ---------- # Base CFLAGS. These may be overridden by the environment. # Highest supported optimizations are -O2, higher levels # will likely break this crappy code. ifdef DEBUG -CFLAGS ?= -O0 -g -Wall -pipe +CFLAGS ?= -O0 -g -Wall -pipe -DDEBUG +ifdef ASAN +override CFLAGS += -fsanitize=address -DUSE_SANITIZER +endif +ifdef UBSAN +override CFLAGS += -fsanitize=undefined -DUSE_SANITIZER +endif else CFLAGS ?= -O2 -Wall -pipe -fomit-frame-pointer endif +# Optionally treat warnings as errors +ifdef WERR +override CFLAGS += -Werror +endif + # Always needed are: # -fno-strict-aliasing since the source doesn't comply # with strict aliasing rules and it's next to impossible # to get it there... # -fwrapv for defined integer wrapping. MSVC6 did this # and the game code requires it. -override CFLAGS += -fno-strict-aliasing -fwrapv +# -fvisibility=hidden to keep symbols hidden. This is +# mostly best practice and not really necessary. +override CFLAGS += -fno-strict-aliasing -fwrapv -fvisibility=hidden # -MMD to generate header dependencies. Unsupported by # the Clang shipped with OS X. @@ -103,7 +185,7 @@ endif # ---------- -# Switch off some annoying warnings. +# Switch of some annoying warnings. ifeq ($(COMPILER), clang) # -Wno-missing-braces because otherwise clang complains # about totally valid 'vec3_t bla = {0}' constructs. @@ -124,8 +206,6 @@ override CFLAGS += -DYQ2OSTYPE=\"$(YQ2_OSTYPE)\" -DYQ2ARCH=\"$(YQ2_ARCH)\" # ---------- -# For reproducible builds, look here for details: -# https://reproducible-builds.org/specs/source-date-epoch/ ifdef SOURCE_DATE_EPOCH CFLAGS += -DBUILD_DATE=\"$(shell date --utc --date="@${SOURCE_DATE_EPOCH}" +"%b %_d %Y" | sed -e 's/ /\\ /g')\" endif @@ -154,6 +234,16 @@ LDFLAGS ?= # It's a shared library. override LDFLAGS += -shared +# Link address sanitizer if requested. +ifdef ASAN +override LDFLAGS += -fsanitize=address +endif + +# Link undefined behavior sanitizer if requested. +ifdef UBSAN +override LDFLAGS += -fsanitize=undefined +endif + # Required libraries ifeq ($(YQ2_OSTYPE), Darwin) override LDFLAGS += -arch $(YQ2_ARCH) @@ -163,6 +253,19 @@ else override LDFLAGS += -lm endif +# ASAN and UBSAN must not be linked +# with --no-undefined. OSX and OpenBSD +# don't support it at all. +ifndef ASAN +ifndef UBSAN +ifneq ($(YQ2_OSTYPE), Darwin) +ifneq ($(YQ2_OSTYPE), OpenBSD) +override LDFLAGS += -Wl,--no-undefined +endif +endif +endif +endif + # ---------- # Builds everything @@ -197,26 +300,28 @@ clean: ifeq ($(YQ2_OSTYPE), Windows) ctf: @echo "===> Building game.dll" - $(Q)mkdir -p release - $(MAKE) release/game.dll + ${Q}mkdir -p $(BINDIR) + ${MAKE} $(BINDIR)/game.dll else ifeq ($(YQ2_OSTYPE), Darwin) ctf: @echo "===> Building game.dylib" - ${Q}mkdir -p release - $(MAKE) release/game.dylib + ${Q}mkdir -p $(BINDIR) + $(MAKE) $(BINDIR)/game.dylib else ctf: @echo "===> Building game.so" - $(Q)mkdir -p release - $(MAKE) release/game.so + ${Q}mkdir -p $(BINDIR) + $(MAKE) $(BINDIR)/game.so -release/game.so : CFLAGS += -fPIC +$(BINDIR)/game.so : CFLAGS += -fPIC endif -build/%.o: %.c - @echo "===> CC $<" - $(Q)mkdir -p $(@D) - $(Q)$(CC) -c $(CFLAGS) -o $@ $< +$(BUILDDIR)/%.o: %.c + @if [ -z $(QUIET) ]; then\ + echo "===> CC $<";\ + fi + ${Q}mkdir -p $(@D) + ${Q}$(CC) -c $(CFLAGS) -o $@ $< # ---------- @@ -232,7 +337,6 @@ CTF_OBJS_ = \ src/g_misc.o \ src/g_monster.o \ src/g_phys.o \ - src/savegame/savegame.o \ src/g_spawn.o \ src/g_svcmds.o \ src/g_target.o \ @@ -246,12 +350,15 @@ CTF_OBJS_ = \ src/player/trail.o \ src/player/view.o \ src/player/weapon.o \ + src/savegame/savegame.o \ + src/shared/flash.o \ + src/shared/rand.o \ src/shared/shared.o # ---------- -# Rewrite pathes to our object directory -CTF_OBJS = $(patsubst %,build/%,$(CTF_OBJS_)) +# Rewrite paths to our object directory +CTF_OBJS = $(patsubst %,$(BUILDDIR)/%,$(CTF_OBJS_)) # ---------- @@ -266,17 +373,17 @@ CTF_DEPS= $(CTF_OBJS:.o=.d) # ---------- ifeq ($(YQ2_OSTYPE), Windows) -release/game.dll : $(CTF_OBJS) +$(BINDIR)/game.dll : $(CTF_OBJS) @echo "===> LD $@" - $(Q)$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS) + ${Q}$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS) else ifeq ($(YQ2_OSTYPE), Darwin) -release/game.dylib : $(CTF_OBJS) +$(BINDIR)/game.dylib : $(CTF_OBJS) @echo "===> LD $@" ${Q}$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS) else -release/game.so : $(CTF_OBJS) +$(BINDIR)/game.so : $(CTF_OBJS) @echo "===> LD $@" - $(Q)$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS) + ${Q}$(CC) -o $@ $(CTF_OBJS) $(LDFLAGS) endif # ---------- diff --git a/src/g_cmds.c b/src/g_cmds.c index 76b457c..9d3c50f 100644 --- a/src/g_cmds.c +++ b/src/g_cmds.c @@ -244,7 +244,7 @@ Cmd_Give_f(edict_t *ent) if (gi.argc() == 3) { ent->health = atoi(gi.argv(2)); - ent->health = ent->health < 1 ? 1 : ent->health; + ent->health = ent->health < 1 ? 1 : ent->health; } else { @@ -605,7 +605,7 @@ Cmd_Drop_f(edict_t *ent) it->drop(ent, it); } -const void +static void Cmd_Inven_f(edict_t *ent) { int i; diff --git a/src/header/local.h b/src/header/local.h index c9b352f..2f8b955 100644 --- a/src/header/local.h +++ b/src/header/local.h @@ -595,7 +595,7 @@ void ClientBegin(edict_t *ent); void ClientDisconnect(edict_t *ent); void ClientUserinfoChanged(edict_t *ent, char *userinfo); qboolean ClientConnect(edict_t *ent, char *userinfo); -void ClientThink(edict_t *ent, usercmd_t *cmd); +void ClientThink(edict_t *ent, usercmd_t *ucmd); void RunEntity(edict_t *ent); void G_RunFrame(void); diff --git a/src/player/client.c b/src/player/client.c index 7daa1e2..51ef264 100644 --- a/src/player/client.c +++ b/src/player/client.c @@ -114,7 +114,7 @@ player_pain(edict_t *self /* unused */, edict_t *other /* unused */, } static qboolean -IsFemale(edict_t *ent) +IsFemale(const edict_t *ent) { char *info; @@ -139,7 +139,7 @@ IsFemale(edict_t *ent) } static qboolean -IsNeutral(edict_t *ent) +IsNeutral(const edict_t *ent) { char *info; @@ -170,7 +170,7 @@ IsNeutral(edict_t *ent) } void -ClientObituary(edict_t *self, edict_t *inflictor /* unused */, +ClientObituary(edict_t *self, const edict_t *inflictor /* unused */, edict_t *attacker) { int mod; @@ -716,14 +716,17 @@ InitClientPersistant(gclient_t *client) void InitClientResp(gclient_t *client) { - int ctf_team = client->resp.ctf_team; - qboolean id_state = client->resp.id_state; + int ctf_team; + qboolean id_state; if (!client) { return; } + ctf_team = client->resp.ctf_team; + id_state = client->resp.id_state; + memset(&client->resp, 0, sizeof(client->resp)); client->resp.ctf_team = ctf_team; diff --git a/src/shared/flash.c b/src/shared/flash.c new file mode 100644 index 0000000..943f591 --- /dev/null +++ b/src/shared/flash.c @@ -0,0 +1,463 @@ +/* + * ======================================================================= + * + * Muzzle flash posititions. + * + * ======================================================================= + */ + +#include "../header/shared.h" + +vec3_t monster_flash_offset[] = { + /* flash 0 is not used */ + {0.0, 0.0, 0.0}, + + /* MZ2_TANK_BLASTER_1 1 */ + {20.7, -18.5, 28.7}, + /* MZ2_TANK_BLASTER_2 2 */ + {16.6, -21.5, 30.1}, + /* MZ2_TANK_BLASTER_3 3 */ + {11.8, -23.9, 32.1}, + /* MZ2_TANK_MACHINEGUN_1 4 */ + {22.9, -0.7, 25.3}, + /* MZ2_TANK_MACHINEGUN_2 5 */ + {22.2, 6.2, 22.3}, + /* MZ2_TANK_MACHINEGUN_3 6 */ + {19.4, 13.1, 18.6}, + /* MZ2_TANK_MACHINEGUN_4 7 */ + {19.4, 18.8, 18.6}, + /* MZ2_TANK_MACHINEGUN_5 8 */ + {17.9, 25.0, 18.6}, + /* MZ2_TANK_MACHINEGUN_6 9 */ + {14.1, 30.5, 20.6}, + /* MZ2_TANK_MACHINEGUN_7 10 */ + {9.3, 35.3, 22.1}, + /* MZ2_TANK_MACHINEGUN_8 11 */ + {4.7, 38.4, 22.1}, + /* MZ2_TANK_MACHINEGUN_9 12 */ + {-1.1, 40.4, 24.1}, + /* MZ2_TANK_MACHINEGUN_10 13 */ + {-6.5, 41.2, 24.1}, + /* MZ2_TANK_MACHINEGUN_11 14 */ + {3.2, 40.1, 24.7}, + /* MZ2_TANK_MACHINEGUN_12 15 */ + {11.7, 36.7, 26.0}, + /* MZ2_TANK_MACHINEGUN_13 16 */ + {18.9, 31.3, 26.0}, + /* MZ2_TANK_MACHINEGUN_14 17 */ + {24.4, 24.4, 26.4}, + /* MZ2_TANK_MACHINEGUN_15 18 */ + {27.1, 17.1, 27.2}, + /* MZ2_TANK_MACHINEGUN_16 19 */ + {28.5, 9.1, 28.0}, + /* MZ2_TANK_MACHINEGUN_17 20 */ + {27.1, 2.2, 28.0}, + /* MZ2_TANK_MACHINEGUN_18 21 */ + {24.9, -2.8, 28.0}, + /* MZ2_TANK_MACHINEGUN_19 22 */ + {21.6, -7.0, 26.4}, + /* MZ2_TANK_ROCKET_1 23 */ + {6.2, 29.1, 49.1}, + /* MZ2_TANK_ROCKET_2 24 */ + {6.9, 23.8, 49.1}, + /* MZ2_TANK_ROCKET_3 25 */ + {8.3, 17.8, 49.5}, + + /* MZ2_INFANTRY_MACHINEGUN_1 26 */ + {26.6, 7.1, 13.1}, + /* MZ2_INFANTRY_MACHINEGUN_2 27 */ + {18.2, 7.5, 15.4}, + /* MZ2_INFANTRY_MACHINEGUN_3 28 */ + {17.2, 10.3, 17.9}, + /* MZ2_INFANTRY_MACHINEGUN_4 29 */ + {17.0, 12.8, 20.1}, + /* MZ2_INFANTRY_MACHINEGUN_5 30 */ + {15.1, 14.1, 21.8}, + /* MZ2_INFANTRY_MACHINEGUN_6 31 */ + {11.8, 17.2, 23.1}, + /* MZ2_INFANTRY_MACHINEGUN_7 32 */ + {11.4, 20.2, 21.0}, + /* MZ2_INFANTRY_MACHINEGUN_8 33 */ + {9.0, 23.0, 18.9}, + /* MZ2_INFANTRY_MACHINEGUN_9 34 */ + {13.9, 18.6, 17.7}, + /* MZ2_INFANTRY_MACHINEGUN_10 35 */ + {15.4, 15.6, 15.8}, + /* MZ2_INFANTRY_MACHINEGUN_11 36 */ + {10.2, 15.2, 25.1}, + /* MZ2_INFANTRY_MACHINEGUN_12 37 */ + {-1.9, 15.1, 28.2}, + /* MZ2_INFANTRY_MACHINEGUN_13 38 */ + {-12.4, 13.0, 20.2}, + + /* MZ2_SOLDIER_BLASTER_1 39 */ + {10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2}, + /* MZ2_SOLDIER_BLASTER_2 40 */ + {21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2}, + /* MZ2_SOLDIER_SHOTGUN_1 41 */ + {10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2}, + /* MZ2_SOLDIER_SHOTGUN_2 42 */ + {21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2}, + /* MZ2_SOLDIER_MACHINEGUN_1 43 */ + {10.6 * 1.2, 7.7 * 1.2, 7.8 * 1.2}, + /* MZ2_SOLDIER_MACHINEGUN_2 44 */ + {21.1 * 1.2, 3.6 * 1.2, 19.0 * 1.2}, + + /* MZ2_GUNNER_MACHINEGUN_1 45 */ + {30.1 * 1.15, 3.9 * 1.15, 19.6 * 1.15}, + /* MZ2_GUNNER_MACHINEGUN_2 46 */ + {29.1 * 1.15, 2.5 * 1.15, 20.7 * 1.15}, + /* MZ2_GUNNER_MACHINEGUN_3 47 */ + {28.2 * 1.15, 2.5 * 1.15, 22.2 * 1.15}, + /* MZ2_GUNNER_MACHINEGUN_4 48 */ + {28.2 * 1.15, 3.6 * 1.15, 22.0 * 1.15}, + /* MZ2_GUNNER_MACHINEGUN_5 49 */ + {26.9 * 1.15, 2.0 * 1.15, 23.4 * 1.15}, + /* MZ2_GUNNER_MACHINEGUN_6 50 */ + {26.5 * 1.15, 0.6 * 1.15, 20.8 * 1.15}, + /* MZ2_GUNNER_MACHINEGUN_7 51 */ + {26.9 * 1.15, 0.5 * 1.15, 21.5 * 1.15}, + /* MZ2_GUNNER_MACHINEGUN_8 52 */ + {29.0 * 1.15, 2.4 * 1.15, 19.5 * 1.15}, + /* MZ2_GUNNER_GRENADE_1 53 */ + {4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15}, + /* MZ2_GUNNER_GRENADE_2 54 */ + {4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15}, + /* MZ2_GUNNER_GRENADE_3 55 */ + {4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15}, + /* MZ2_GUNNER_GRENADE_4 56 */ + {4.6 * 1.15, -16.8 * 1.15, 7.3 * 1.15}, + + /* MZ2_CHICK_ROCKET_1 57 */ + {24.8, -9.0, 39.0}, + + /* MZ2_FLYER_BLASTER_1 58 */ + {12.1, 13.4, -14.5}, + /* MZ2_FLYER_BLASTER_2 59 */ + {12.1, -7.4, -14.5}, + + /* MZ2_MEDIC_BLASTER_1 60 */ + {12.1, 5.4, 16.5}, + + /* MZ2_GLADIATOR_RAILGUN_1 61 */ + {30.0, 18.0, 28.0}, + + /* MZ2_HOVER_BLASTER_1 62 */ + {32.5, -0.8, 10.0}, + + /* MZ2_ACTOR_MACHINEGUN_1 63 */ + {18.4, 7.4, 9.6}, + + /* MZ2_SUPERTANK_MACHINEGUN_1 64 */ + {30.0, 30.0, 88.5}, + /* MZ2_SUPERTANK_MACHINEGUN_2 65 */ + {30.0, 30.0, 88.5}, + /* MZ2_SUPERTANK_MACHINEGUN_3 66 */ + {30.0, 30.0, 88.5}, + /* MZ2_SUPERTANK_MACHINEGUN_4 67 */ + {30.0, 30.0, 88.5}, + /* MZ2_SUPERTANK_MACHINEGUN_5 68 */ + {30.0, 30.0, 88.5}, + /* MZ2_SUPERTANK_MACHINEGUN_6 69 */ + {30.0, 30.0, 88.5}, + /* MZ2_SUPERTANK_ROCKET_1 70 */ + {16.0, -22.5, 91.2}, + /* MZ2_SUPERTANK_ROCKET_2 71 */ + {16.0, -33.4, 86.7}, + /* MZ2_SUPERTANK_ROCKET_3 72 */ + {16.0, -42.8, 83.3}, + + /* MZ2_BOSS2_MACHINEGUN_L1 73 */ + {32, -40, 70}, + /* MZ2_BOSS2_MACHINEGUN_L2 74 */ + {32, -40, 70}, + /* MZ2_BOSS2_MACHINEGUN_L3 75 */ + {32, -40, 70}, + /* MZ2_BOSS2_MACHINEGUN_L4 76 */ + {32, -40, 70}, + /* MZ2_BOSS2_MACHINEGUN_L5 77 */ + {32, -40, 70}, + + /* MZ2_BOSS2_ROCKET_1 78 */ + {22.0, 16.0, 10.0}, + /* MZ2_BOSS2_ROCKET_2 79 */ + {22.0, 8.0, 10.0}, + /* MZ2_BOSS2_ROCKET_3 80 */ + {22.0, -8.0, 10.0}, + /* MZ2_BOSS2_ROCKET_4 81 */ + {22.0, -16.0, 10.0}, + + /* MZ2_FLOAT_BLASTER_1 82 */ + {32.5, -0.8, 10}, + + /* MZ2_SOLDIER_BLASTER_3 83 */ + {20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2}, + /* MZ2_SOLDIER_SHOTGUN_3 84 */ + {20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2}, + /* MZ2_SOLDIER_MACHINEGUN_3 85 */ + {20.8 * 1.2, 10.1 * 1.2, -2.7 * 1.2}, + /* MZ2_SOLDIER_BLASTER_4 86 */ + {7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2}, + /* MZ2_SOLDIER_SHOTGUN_4 87 */ + {7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2}, + /* MZ2_SOLDIER_MACHINEGUN_4 88 */ + {7.6 * 1.2, 9.3 * 1.2, 0.8 * 1.2}, + /* MZ2_SOLDIER_BLASTER_5 89 */ + {30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2}, + /* MZ2_SOLDIER_SHOTGUN_5 90 */ + {30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2}, + /* MZ2_SOLDIER_MACHINEGUN_5 91 */ + {30.5 * 1.2, 9.9 * 1.2, -18.7 * 1.2}, + /* MZ2_SOLDIER_BLASTER_6 92 */ + {27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2}, + /* MZ2_SOLDIER_SHOTGUN_6 93 */ + {27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2}, + /* MZ2_SOLDIER_MACHINEGUN_6 94 */ + {27.6 * 1.2, 3.4 * 1.2, -10.4 * 1.2}, + /* MZ2_SOLDIER_BLASTER_7 95 */ + {28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2}, + /* MZ2_SOLDIER_SHOTGUN_7 96 */ + {28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2}, + /* MZ2_SOLDIER_MACHINEGUN_7 97 */ + {28.9 * 1.2, 4.6 * 1.2, -8.1 * 1.2}, + /* MZ2_SOLDIER_BLASTER_8 98 */ + {31.5 * 1.2, 9.6 * 1.2, 10.1 * 1.2}, + /* MZ2_SOLDIER_SHOTGUN_8 99 */ + {34.5 * 1.2, 9.6 * 1.2, 6.1 * 1.2}, + /* MZ2_SOLDIER_MACHINEGUN_8 100 */ + {34.5 * 1.2, 9.6 * 1.2, 6.1 * 1.2}, + + /* MZ2_MAKRON_BFG 101 */ + {17, -19.5, 62.9}, + /* MZ2_MAKRON_BLASTER_1 102 */ + {-3.6, -24.1, 59.5}, + /* MZ2_MAKRON_BLASTER_2 103 */ + {-1.6, -19.3, 59.5}, + /* MZ2_MAKRON_BLASTER_3 104 */ + {-0.1, -14.4, 59.5}, + /* MZ2_MAKRON_BLASTER_4 105 */ + {2.0, -7.6, 59.5}, + /* MZ2_MAKRON_BLASTER_5 106 */ + {3.4, 1.3, 59.5}, + /* MZ2_MAKRON_BLASTER_6 107 */ + {3.7, 11.1, 59.5}, + /* MZ2_MAKRON_BLASTER_7 108 */ + {-0.3, 22.3, 59.5}, + /* MZ2_MAKRON_BLASTER_8 109 */ + {-6, 33, 59.5}, + /* MZ2_MAKRON_BLASTER_9 110 */ + {-9.3, 36.4, 59.5}, + /* MZ2_MAKRON_BLASTER_10 111 */ + {-7, 35, 59.5}, + /* MZ2_MAKRON_BLASTER_11 112 */ + {-2.1, 29, 59.5}, + /* MZ2_MAKRON_BLASTER_12 113 */ + {3.9, 17.3, 59.5}, + /* MZ2_MAKRON_BLASTER_13 114 */ + {6.1, 5.8, 59.5}, + /* MZ2_MAKRON_BLASTER_14 115 */ + {5.9, -4.4, 59.5}, + /* MZ2_MAKRON_BLASTER_15 116 */ + {4.2, -14.1, 59.5}, + /* MZ2_MAKRON_BLASTER_16 117 */ + {2.4, -18.8, 59.5}, + /* MZ2_MAKRON_BLASTER_17 118 */ + {-1.8, -25.5, 59.5}, + /* MZ2_MAKRON_RAILGUN_1 119 */ + {-17.3, 7.8, 72.4}, + + /* MZ2_JORG_MACHINEGUN_L1 120 */ + {78.5, -47.1, 96}, + /* MZ2_JORG_MACHINEGUN_L2 121 */ + {78.5, -47.1, 96}, + /* MZ2_JORG_MACHINEGUN_L3 122 */ + {78.5, -47.1, 96}, + /* MZ2_JORG_MACHINEGUN_L4 123 */ + {78.5, -47.1, 96}, + /* MZ2_JORG_MACHINEGUN_L5 124 */ + {78.5, -47.1, 96}, + /* MZ2_JORG_MACHINEGUN_L6 125 */ + {78.5, -47.1, 96}, + /* MZ2_JORG_MACHINEGUN_R1 126 */ + {78.5, 46.7, 96}, + /* MZ2_JORG_MACHINEGUN_R2 127 */ + {78.5, 46.7, 96}, + /* MZ2_JORG_MACHINEGUN_R3 128 */ + {78.5, 46.7, 96}, + /* MZ2_JORG_MACHINEGUN_R4 129 */ + {78.5, 46.7, 96}, + /* MZ2_JORG_MACHINEGUN_R5 130 */ + {78.5, 46.7, 96}, + /* MZ2_JORG_MACHINEGUN_R6 131 */ + {78.5, 46.7, 96}, + /* MZ2_JORG_BFG_1 132 */ + {6.3, -9, 111.2}, + + /* MZ2_BOSS2_MACHINEGUN_R1 73 */ + {32, 40, 70}, + /* MZ2_BOSS2_MACHINEGUN_R2 74 */ + {32, 40, 70}, + /* MZ2_BOSS2_MACHINEGUN_R3 75 */ + {32, 40, 70}, + /* MZ2_BOSS2_MACHINEGUN_R4 76 */ + {32, 40, 70}, + /* MZ2_BOSS2_MACHINEGUN_R5 77 */ + {32, 40, 70}, + + + /* MZ2_CARRIER_MACHINEGUN_L1 */ + {56, -32, 32}, + /* MZ2_CARRIER_MACHINEGUN_R1 */ + {56, 32, 32}, + /* MZ2_CARRIER_GRENADE */ + {42, 24, 50}, + /* MZ2_TURRET_MACHINEGUN 141 */ + {16, 0, 0}, + /* MZ2_TURRET_ROCKET 142 */ + {16, 0, 0}, + /* MZ2_TURRET_BLASTER 143 */ + {16, 0, 0}, + /* MZ2_STALKER_BLASTER 144 */ + {24, 0, 6}, + /* MZ2_DAEDALUS_BLASTER 145 */ + {32.5, -0.8, 10.0}, + /* MZ2_MEDIC_BLASTER_2 146 */ + {12.1, 5.4, 16.5}, + /* MZ2_CARRIER_RAILGUN 147 */ + {32, 0, 6}, + /* MZ2_WIDOW_DISRUPTOR 148 */ + {57.72, 14.50, 88.81}, + /* MZ2_WIDOW_BLASTER 149 */ + {56, 32, 32}, + /* MZ2_WIDOW_RAIL 150 */ + {62, -20, 84}, + /* MZ2_WIDOW_PLASMABEAM 151 */ + {32, 0, 6}, + /* MZ2_CARRIER_MACHINEGUN_L2 152 */ + {61, -32, 12}, + /* MZ2_CARRIER_MACHINEGUN_R2 153 */ + {61, 32, 12}, + /* MZ2_WIDOW_RAIL_LEFT 154 */ + {17, -62, 91}, + /* MZ2_WIDOW_RAIL_RIGHT 155 */ + {68, 12, 86}, + /* MZ2_WIDOW_BLASTER_SWEEP1 156 */ + {47.5, 56, 89}, + /* MZ2_WIDOW_BLASTER_SWEEP2 157 */ + {54, 52, 91}, + /* MZ2_WIDOW_BLASTER_SWEEP3 158 */ + {58, 40, 91}, + /* MZ2_WIDOW_BLASTER_SWEEP4 159 */ + {68, 30, 88}, + /* MZ2_WIDOW_BLASTER_SWEEP5 160 */ + {74, 20, 88}, + /* MZ2_WIDOW_BLASTER_SWEEP6 161 */ + {73, 11, 87}, + /* MZ2_WIDOW_BLASTER_SWEEP7 162 */ + {73, 3, 87}, + /* MZ2_WIDOW_BLASTER_SWEEP8 163 */ + {70, -12, 87}, + /* MZ2_WIDOW_BLASTER_SWEEP9 164 */ + {67, -20, 90}, + /* MZ2_WIDOW_BLASTER_100 165 */ + {-20, 76, 90}, + /* MZ2_WIDOW_BLASTER_90 166 */ + {-8, 74, 90}, + /* MZ2_WIDOW_BLASTER_80 167 */ + {0, 72, 90}, + /* MZ2_WIDOW_BLASTER_70 168 d06 */ + {10, 71, 89}, + /* MZ2_WIDOW_BLASTER_60 169 d07 */ + {23, 70, 87}, + /* MZ2_WIDOW_BLASTER_50 170 d08 */ + {32, 64, 85}, + /* MZ2_WIDOW_BLASTER_40 171 */ + {40, 58, 84}, + /* MZ2_WIDOW_BLASTER_30 172 d10 */ + {48, 50, 83}, + /* MZ2_WIDOW_BLASTER_20 173 */ + {54, 42, 82}, + /* MZ2_WIDOW_BLASTER_10 174 d12 */ + {56, 34, 82}, + /* MZ2_WIDOW_BLASTER_0 175 */ + {58, 26, 82}, + /* MZ2_WIDOW_BLASTER_10L 176 d14 */ + {60, 16, 82}, + /* MZ2_WIDOW_BLASTER_20L 177 */ + {59, 6, 81}, + /* MZ2_WIDOW_BLASTER_30L 178 d16 */ + {58, -2, 80}, + /* MZ2_WIDOW_BLASTER_40L 179 */ + {57, -10, 79}, + /* MZ2_WIDOW_BLASTER_50L 180 d18 */ + {54, -18, 78}, + /* MZ2_WIDOW_BLASTER_60L 181 */ + {42, -32, 80}, + /* MZ2_WIDOW_BLASTER_70L 182 d20 */ + {36, -40, 78}, + /* MZ2_WIDOW_RUN_1 183 */ + {68.4, 10.88, 82.08}, + /* MZ2_WIDOW_RUN_2 184 */ + {68.51, 8.64, 85.14}, + /* MZ2_WIDOW_RUN_3 185 */ + {68.66, 6.38, 88.78}, + /* MZ2_WIDOW_RUN_4 186 */ + {68.73, 5.1, 84.47}, + /* MZ2_WIDOW_RUN_5 187 */ + {68.82, 4.79, 80.52}, + /* MZ2_WIDOW_RUN_6 188 */ + {68.77, 6.11, 85.37}, + /* MZ2_WIDOW_RUN_7 189 */ + {68.67, 7.99, 90.24}, + /* MZ2_WIDOW_RUN_8 190 */ + {68.55, 9.54, 87.36}, + /* MZ2_CARRIER_ROCKET_1 191 */ + {0, 0, -5}, + /* MZ2_CARRIER_ROCKET_2 192 */ + {0, 0, -5}, + /* MZ2_CARRIER_ROCKET_3 193 */ + {0, 0, -5}, + /* MZ2_CARRIER_ROCKET_4 194 */ + {0, 0, -5}, + /* MZ2_WIDOW2_BEAMER_1 195 */ + /* { 72.13, -17.63, 93.77 }, */ + {69.00, -17.63, 93.77}, + /* MZ2_WIDOW2_BEAMER_2 196 */ + /* { 71.46, -17.08, 89.82 }, */ + {69.00, -17.08, 89.82}, + /* MZ2_WIDOW2_BEAMER_3 197 */ + /* { 71.47, -18.40, 90.70 }, */ + {69.00, -18.40, 90.70}, + /* MZ2_WIDOW2_BEAMER_4 198 */ + /* { 71.96, -18.34, 94.32 }, */ + {69.00, -18.34, 94.32}, + /* MZ2_WIDOW2_BEAMER_5 199 */ + /* { 72.25, -18.30, 97.98 }, */ + {69.00, -18.30, 97.98}, + /* MZ2_WIDOW2_BEAM_SWEEP_1 200 */ + {45.04, -59.02, 92.24}, + /* MZ2_WIDOW2_BEAM_SWEEP_2 201 */ + {50.68, -54.70, 91.96}, + /* MZ2_WIDOW2_BEAM_SWEEP_3 202 */ + {56.57, -47.72, 91.65}, + /* MZ2_WIDOW2_BEAM_SWEEP_4 203 */ + {61.75, -38.75, 91.38}, + /* MZ2_WIDOW2_BEAM_SWEEP_5 204 */ + {65.55, -28.76, 91.24}, + /* MZ2_WIDOW2_BEAM_SWEEP_6 205 */ + {67.79, -18.90, 91.22}, + /* MZ2_WIDOW2_BEAM_SWEEP_7 206 */ + {68.60, -9.52, 91.23}, + /* MZ2_WIDOW2_BEAM_SWEEP_8 207 */ + {68.08, 0.18, 91.32}, + /* MZ2_WIDOW2_BEAM_SWEEP_9 208 */ + {66.14, 9.79, 91.44}, + /* MZ2_WIDOW2_BEAM_SWEEP_10 209 */ + {62.77, 18.91, 91.65}, + /* MZ2_WIDOW2_BEAM_SWEEP_11 210 */ + {58.29, 27.11, 92.00}, + + /* end of table */ + {0.0, 0.0, 0.0} +}; + diff --git a/src/shared/rand.c b/src/shared/rand.c new file mode 100644 index 0000000..22b4a71 --- /dev/null +++ b/src/shared/rand.c @@ -0,0 +1,97 @@ +/* + * KISS PRNG (c) 2011 Shinobu + * + * This file was optained from zuttobenkyou.wordpress.com + * and modified by the Yamagi Quake II developers. + * + * LICENSE: Public domain + * + * ======================================================================= + * + * KISS PRNG, as devised by Dr. George Marsaglia + * + * ======================================================================= + */ + +#include + +#define QSIZE 0x200000 +#define CNG (cng = 6906969069ULL * cng + 13579) +#define XS (xs ^= (xs << 13), xs ^= (xs >> 17), xs ^= (xs << 43)) +#define KISS (B64MWC() + CNG + XS) + +static uint64_t QARY[QSIZE]; +static int j; +static uint64_t carry; +static uint64_t xs; +static uint64_t cng; + +uint64_t +B64MWC(void) +{ + uint64_t t, x; + + j = (j + 1) & (QSIZE - 1); + x = QARY[j]; + t = (x << 28) + carry; + carry = (x >> 36) - (t < x); + return QARY[j] = t - x; +} + +/* + * Generate a pseudorandom + * integer >0. + */ +int +randk(void) +{ + int r; + + r = (int)KISS; + r = (r < 0) ? (r * -1) : r; + + return r; +} + +/* + * Generate a pseudorandom + * signed float between + * 0 and 1. + */ +float +frandk(void) +{ + return (randk()&32767)* (1.0/32767); +} + +/* Generate a pseudorandom + * float between -1 and 1. + */ +float +crandk(void) +{ + return (randk()&32767)* (2.0/32767) - 1; +} + +/* + * Seeds the PRNG + */ +void +randk_seed(void) +{ + uint64_t i; + + /* Seed QARY[] with CNG+XS: */ + for (i = 0; i < QSIZE; i++) + { + QARY[i] = CNG + XS; + } + + /* Run through several rounds + to warm up the state */ + for (i = 0; i < 256; i++) + { + randk(); + } +} + From c0d117a51e26a7b2f2ab19b6010b300f4835c554 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sat, 2 May 2026 00:00:24 +0300 Subject: [PATCH 7/9] game: init randk() --- src/g_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/g_main.c b/src/g_main.c index 690cf45..7929958 100644 --- a/src/g_main.c +++ b/src/g_main.c @@ -95,7 +95,7 @@ ShutdownGame(void) * all entry points and global variables */ Q2_DLL_EXPORTED game_export_t * -GetGameAPI(game_import_t *import) +GetGameAPI(const game_import_t *import) { gi = *import; @@ -122,6 +122,9 @@ GetGameAPI(game_import_t *import) globals.edict_size = sizeof(edict_t); + /* Initalize the PRNG */ + randk_seed(); + return &globals; } From b911c3b7e2079950ba1a0455e4bf2f6d31196b4b Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sat, 2 May 2026 14:08:37 +0300 Subject: [PATCH 8/9] workflows: fix cppcheck flow --- .github/workflows/linux_aarch64.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/linux_aarch64.yml b/.github/workflows/linux_aarch64.yml index 15892b2..bcf77c0 100644 --- a/.github/workflows/linux_aarch64.yml +++ b/.github/workflows/linux_aarch64.yml @@ -15,7 +15,9 @@ concurrency: cancel-in-progress: true jobs: build_ubuntu_aarch64: - runs-on: ubuntu-24.04-arm + runs-on: ubuntu-latest + container: + image: debian:testing permissions: actions: read contents: read @@ -28,8 +30,8 @@ jobs: steps: - name: Install build dependencies run: | - sudo apt update - sudo apt install build-essential snapd + apt update + apt install -y build-essential cppcheck - name: Check out repository code uses: actions/checkout@v6 - name: Build @@ -53,8 +55,7 @@ jobs: if-no-files-found: error - name: Run Cppcheck run: | - sudo snap install cppcheck --edge - /snap/bin/cppcheck -j 4 --enable=all --output-format=sarif \ + cppcheck -j 4 --enable=all --output-format=sarif \ --output-file=cppcheck_results.sarif --inconclusive --library=posix \ -DYQ2OSTYPE=\"Linux\" src - name: Upload SARIF to GitHub Code Scanning From 3a7c1ff9fe3679dd8d1453587948ccbc2d175071 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Fri, 15 May 2026 00:40:45 +0300 Subject: [PATCH 9/9] game: fix initialization in SelectSpawnPoint https://github.com/yquake2/zaero/pull/64 --- src/g_ctf.c | 2 +- src/header/ctf.h | 2 +- src/player/client.c | 93 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 80 insertions(+), 17 deletions(-) diff --git a/src/g_ctf.c b/src/g_ctf.c index c26f2d2..9f862cf 100644 --- a/src/g_ctf.c +++ b/src/g_ctf.c @@ -548,7 +548,7 @@ CTFAssignTeam(gclient_t *who) * two points closest to other players */ edict_t * -SelectCTFSpawnPoint(edict_t *ent) +SelectCTFSpawnPoint(const edict_t *ent) { edict_t *spot, *spot1, *spot2; int count = 0; diff --git a/src/header/ctf.h b/src/header/ctf.h index d22a0a1..211d6c4 100644 --- a/src/header/ctf.h +++ b/src/header/ctf.h @@ -129,7 +129,7 @@ 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); +edict_t *SelectCTFSpawnPoint(const edict_t *ent); qboolean CTFPickup_Flag(edict_t *ent, edict_t *other); void CTFDrop_Flag(edict_t *ent, const gitem_t *item); void CTFEffects(edict_t *player); diff --git a/src/player/client.c b/src/player/client.c index 51ef264..6d03d51 100644 --- a/src/player/client.c +++ b/src/player/client.c @@ -31,6 +31,7 @@ void SP_misc_teleporter_dest(edict_t *ent); /* * QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 32) + * * The normal starting point for a level. */ void @@ -50,6 +51,7 @@ SP_info_player_start(edict_t *self) /* * QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 32) + * * potential spawning position for deathmatch games */ void @@ -73,7 +75,6 @@ SP_info_player_deathmatch(edict_t *self) * QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 32) * potential spawning position for coop games */ - void SP_info_player_coop(edict_t *self) { @@ -96,8 +97,12 @@ SP_info_player_coop(edict_t *self) * roll as well as yaw. 'pitch yaw roll' */ void -SP_info_player_intermission(edict_t *ent) +SP_info_player_intermission(edict_t *self) { + /* This function cannot be removed + * since the info_player_intermission + * needs a callback function. Like + * every entity. */ } /* ======================================================================= */ @@ -956,7 +961,7 @@ SelectDeathmatchSpawnPoint(void) } static edict_t * -SelectCoopSpawnPoint(edict_t *ent) +SelectCoopSpawnPoint(const edict_t *ent) { int index; edict_t *spot = NULL; @@ -1014,10 +1019,18 @@ SelectCoopSpawnPoint(edict_t *ent) * Chooses a player start, deathmatch start, coop start, etc */ void -SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles) +SelectSpawnPoint(const edict_t *ent, vec3_t origin, vec3_t angles) { edict_t *spot = NULL; + VectorClear(origin); + VectorClear(angles); + + if (!ent) + { + return; + } + if (deathmatch->value) { if (ctf->value) @@ -1066,6 +1079,52 @@ SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles) if (!spot) { gi.error("Couldn't find spawn point %s\n", game.spawnpoint); + return; + } + } + } + + /* If we are in coop and we didn't find a coop + spawnpoint due to map bugs (not correctly + connected or the map was loaded via console + and thus no previously map is known to the + client) use one in 550 units radius. */ + if (coop->value) + { + int index; + + index = ent->client - game.clients; + + if (Q_stricmp(spot->classname, "info_player_start") == 0 && index != 0) + { + int counter = 0; + + while (counter < 3) + { + edict_t *coopspot = NULL; + vec3_t d; + + coopspot = G_Find(coopspot, FOFS(classname), "info_player_coop"); + + if (!coopspot) + { + break; + } + + VectorSubtract(coopspot->s.origin, spot->s.origin, d); + + if ((VectorLength(d) < 550)) + { + if (index == counter) + { + spot = coopspot; + break; + } + else + { + counter++; + } + } } } } @@ -1080,15 +1139,19 @@ SelectSpawnPoint(edict_t *ent, vec3_t origin, vec3_t angles) void InitBodyQue(void) { - int i; - edict_t *ent; + if (deathmatch->value || coop->value) + { + int i; - level.body_que = 0; + level.body_que = 0; - for (i = 0; i < BODY_QUEUE_SIZE; i++) - { - ent = G_Spawn(); - ent->classname = "bodyque"; + for (i = 0; i < BODY_QUEUE_SIZE; i++) + { + edict_t *ent; + + ent = G_Spawn(); + ent->classname = "bodyque"; + } } } @@ -1106,7 +1169,8 @@ body_die(edict_t *self, edict_t *inflictor /* unused */, if (self->health < -40) { - gi.sound(self, CHAN_BODY, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0); + gi.sound(self, CHAN_BODY, gi.soundindex( + "misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 4; n++) { @@ -1194,9 +1258,8 @@ respawn(edict_t *self) /* ============================================================== */ /* - * Called when a player connects - * to a server or respawns in - * a deathmatch. + * Called when a player connects to + * a server or respawns in a deathmatch. */ void PutClientInServer(edict_t *ent)