From 27b41be9519f0f377728feaf3a4e6586b88abbfd Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sun, 24 Nov 2024 22:54:36 +0200 Subject: [PATCH] game: add 'trigger_flashlight' support Based on: * https://github.com/id-Software/quake2-rerelease-dll.git --- src/common/header/shared.h | 1 + src/game/g_items.c | 70 +++++++++++++++++++++++ src/game/g_trigger.c | 52 ++++++++++++++++- src/game/header/local.h | 4 +- src/game/player/client.c | 2 +- src/game/player/view.c | 5 ++ src/game/savegame/tables/gamefunc_decs.h | 2 + src/game/savegame/tables/gamefunc_list.h | 2 + src/game/savegame/tables/spawnfunc_decs.h | 1 + src/game/savegame/tables/spawnfunc_list.h | 1 + 10 files changed, 137 insertions(+), 3 deletions(-) diff --git a/src/common/header/shared.h b/src/common/header/shared.h index 14ee4322..2ddffff2 100644 --- a/src/common/header/shared.h +++ b/src/common/header/shared.h @@ -692,6 +692,7 @@ typedef struct * it has a zero index model. */ #define EF_ROTATE 0x00000001 /* rotate (bonus items) */ #define EF_GIB 0x00000002 /* leave a trail */ +#define EF_FLASHLIGHT 0x00000004 /* project flashlight, only for players */ #define EF_BLASTER 0x00000008 /* redlight + trail */ #define EF_ROCKET 0x00000010 /* redlight + trail */ #define EF_GRENADE 0x00000020 diff --git a/src/game/g_items.c b/src/game/g_items.c index 6ccf8f21..e0258049 100644 --- a/src/game/g_items.c +++ b/src/game/g_items.c @@ -276,6 +276,32 @@ Pickup_Powerup(edict_t *ent, edict_t *other) return true; } +qboolean +Pickup_General(edict_t *ent, edict_t *other) +{ + if (!ent || !other) + { + return false; + } + + if (other->client->pers.inventory[ITEM_INDEX(ent->item)]) + { + return false; + } + + other->client->pers.inventory[ITEM_INDEX(ent->item)]++; + + if (deathmatch->value) + { + if (!(ent->spawnflags & DROPPED_ITEM)) + { + SetRespawn(ent, ent->item->quantity); + } + } + + return true; +} + void Drop_General(edict_t *ent, gitem_t *item) { @@ -2406,6 +2432,29 @@ SpawnItem(edict_t *ent, gitem_t *item) } } + +void +P_ToggleFlashlight(edict_t *ent, qboolean state) +{ + if (!!(ent->flags & FL_FLASHLIGHT) == state) + { + return; + } + + ent->flags ^= FL_FLASHLIGHT; + + gi.sound(ent, CHAN_AUTO, + gi.soundindex(ent->flags & FL_FLASHLIGHT ? + "items/flashlight_on.wav" : "items/flashlight_off.wav"), + 1.f, ATTN_STATIC, 0); +} + +void +Use_Flashlight(edict_t *ent, gitem_t *inv) +{ + P_ToggleFlashlight(ent, !(ent->flags & FL_FLASHLIGHT)); +} + /* ====================================================================== */ static const gitem_t gameitemlist[] = { @@ -4303,6 +4352,27 @@ static const gitem_t gameitemlist[] = { "ctf/tech4.wav" }, + { + "item_flashlight", + Pickup_General, + Use_Flashlight, + NULL, + NULL, + "items/pkup.wav", + "models/items/flashlight/tris.md2", EF_ROTATE, + NULL, + "p_torch", + "Flashlight", + 2, + 0, + NULL, + IT_STAY_COOP, + 0, + NULL, + 0, + "items/flashlight_on.wav items/flashlight_off.wav", + }, + /* end of list marker */ {NULL} }; diff --git a/src/game/g_trigger.c b/src/game/g_trigger.c index 9c3d3c27..f2d3bd8b 100644 --- a/src/game/g_trigger.c +++ b/src/game/g_trigger.c @@ -1125,9 +1125,59 @@ SP_trigger_monsterjump(edict_t *self) self->movedir[2] = st.height; } +/* QUAKED trigger_flashlight (.5 .5 .5) ? + * Players moving against this trigger will have their flashlight turned on or off. + * "style" default to 0, set to 1 to always turn flashlight on, 2 to always turn off, + * otherwise "angles" are used to control on/off state + */ + +#define SPAWNFLAG_FLASHLIGHT_CLIPPED 1 + +void +trigger_flashlight_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, + csurface_t *surf /* unused */) +{ + if (!other->client) + { + return; + } + + if (self->style == 1) + { + P_ToggleFlashlight(other, true); + } + else if (self->style == 2) + { + P_ToggleFlashlight(other, false); + } + else if (VectorLength(other->velocity) > 6) + { + vec3_t forward; + + VectorNormalize2(other->velocity, forward); + + P_ToggleFlashlight(other, _DotProduct(forward, self->movedir) > 0); + } +} + +void +SP_trigger_flashlight(edict_t *self) +{ + if (self->s.angles[YAW] == 0) + { + self->s.angles[YAW] = 360; + } + + InitTrigger(self); + self->touch = trigger_flashlight_touch; + self->movedir[2] = (float) st.height; + + gi.linkentity(self); +} + /* * QUAKED choose_cdtrack (.5 .5 .5) ? - * HEretic 2: Sets CD track + * Heretic 2: Sets CD track * * style: CD Track Id */ diff --git a/src/game/header/local.h b/src/game/header/local.h index 998ad624..520f5dd2 100644 --- a/src/game/header/local.h +++ b/src/game/header/local.h @@ -76,7 +76,8 @@ #define FL_TEAMSLAVE 0x00000400 /* not the first on the team */ #define FL_NO_KNOCKBACK 0x00000800 #define FL_POWER_ARMOR 0x00001000 /* power armor (if any) is active */ -#define FL_COOP_TAKEN 0x00002000 /* Another client has already taken it */ +#define FL_COOP_TAKEN 0x00002000 /* Another client has already taken it */ +#define FL_FLASHLIGHT 0x00004000 /* enable flashlight */ #define FL_RESPAWN 0x80000000 /* used for item respawning */ #define FL_MECHANICAL 0x00002000 /* entity is mechanical, use sparks not blood */ @@ -1091,6 +1092,7 @@ void fire_doppleganger(edict_t *ent, vec3_t start, vec3_t aimdir); void ED_CallSpawn(edict_t *ent); char *ED_NewString(const char *string, qboolean raw); void SpawnInit(void); +void P_ToggleFlashlight(edict_t *ent, qboolean state); edict_t *CreateFlyMonster(vec3_t origin, vec3_t angles, vec3_t mins, vec3_t maxs, char *classname); edict_t *CreateGroundMonster(vec3_t origin, vec3_t angles, vec3_t mins, diff --git a/src/game/player/client.c b/src/game/player/client.c index 201bfb5c..463a7ad4 100644 --- a/src/game/player/client.c +++ b/src/game/player/client.c @@ -1344,7 +1344,7 @@ SaveClientData(void) game.clients[i].pers.health = ent->health; game.clients[i].pers.max_health = ent->max_health; game.clients[i].pers.savedFlags = - (ent->flags & (FL_GODMODE | FL_NOTARGET | FL_POWER_ARMOR)); + (ent->flags & (FL_FLASHLIGHT | FL_GODMODE | FL_NOTARGET | FL_POWER_ARMOR)); if (coop->value) { diff --git a/src/game/player/view.c b/src/game/player/view.c index 673f26a1..52b013c1 100644 --- a/src/game/player/view.c +++ b/src/game/player/view.c @@ -1123,6 +1123,11 @@ G_SetClientEffects(edict_t *ent) return; } + if (ent->flags & FL_FLASHLIGHT) + { + ent->s.effects |= EF_FLASHLIGHT; + } + if (ent->flags & FL_DISGUISED) { ent->s.renderfx |= RF_USE_DISGUISE; diff --git a/src/game/savegame/tables/gamefunc_decs.h b/src/game/savegame/tables/gamefunc_decs.h index e6e0e7da..c994db8e 100644 --- a/src/game/savegame/tables/gamefunc_decs.h +++ b/src/game/savegame/tables/gamefunc_decs.h @@ -306,6 +306,7 @@ extern void Use_Defender ( edict_t * ent , gitem_t * item ) ; extern void Use_Doppleganger ( edict_t * ent , gitem_t * item ) ; extern void Use_Double ( edict_t * ent , gitem_t * item ) ; extern void Use_Envirosuit ( edict_t * ent , gitem_t * item ) ; +extern void Use_Flashlight ( edict_t * ent , gitem_t * item ) ; extern void Use_Hunter ( edict_t * ent , gitem_t * item ) ; extern void Use_IR ( edict_t * ent , gitem_t * item ) ; extern void Use_Invulnerability ( edict_t * ent , gitem_t * item ) ; @@ -1400,6 +1401,7 @@ extern void trigger_effect ( edict_t * self ) ; extern void trigger_elevator_init ( edict_t * self ) ; extern void trigger_elevator_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void trigger_enable ( edict_t * self , edict_t * other , edict_t * activator ) ; +extern void trigger_flashlight_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void trigger_gravity_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; extern void trigger_gravity_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void trigger_key_use ( edict_t * self , edict_t * other , edict_t * activator ) ; diff --git a/src/game/savegame/tables/gamefunc_list.h b/src/game/savegame/tables/gamefunc_list.h index e8ea8133..e14190f1 100644 --- a/src/game/savegame/tables/gamefunc_list.h +++ b/src/game/savegame/tables/gamefunc_list.h @@ -257,6 +257,7 @@ {"Use_Doppleganger", (byte *)Use_Doppleganger}, {"Use_Double", (byte *)Use_Double}, {"Use_Envirosuit", (byte *)Use_Envirosuit}, +{"Use_Flashlight", (byte *)Use_Flashlight}, {"Use_Hunter", (byte *)Use_Hunter}, {"Use_IR", (byte *)Use_IR}, {"Use_Invulnerability", (byte *)Use_Invulnerability}, @@ -1395,6 +1396,7 @@ {"trigger_elevator_init", (byte *)trigger_elevator_init}, {"trigger_elevator_use", (byte *)trigger_elevator_use}, {"trigger_enable", (byte *)trigger_enable}, +{"trigger_flashlight_touch", (byte *)trigger_flashlight_touch}, {"trigger_gravity_touch", (byte *)trigger_gravity_touch}, {"trigger_gravity_use", (byte *)trigger_gravity_use}, {"trigger_key_use", (byte *)trigger_key_use}, diff --git a/src/game/savegame/tables/spawnfunc_decs.h b/src/game/savegame/tables/spawnfunc_decs.h index adef8e0e..a9e85b2d 100644 --- a/src/game/savegame/tables/spawnfunc_decs.h +++ b/src/game/savegame/tables/spawnfunc_decs.h @@ -196,6 +196,7 @@ extern void SP_trigger_always ( edict_t * ent ) ; extern void SP_trigger_counter(edict_t * self); extern void SP_trigger_disguise(edict_t * self); extern void SP_trigger_elevator(edict_t * self); +extern void SP_trigger_flashlight(edict_t * self); extern void SP_trigger_gravity(edict_t * self); extern void SP_trigger_hurt(edict_t * self); extern void SP_trigger_key(edict_t * self); diff --git a/src/game/savegame/tables/spawnfunc_list.h b/src/game/savegame/tables/spawnfunc_list.h index 8c30c04f..1788a0f6 100644 --- a/src/game/savegame/tables/spawnfunc_list.h +++ b/src/game/savegame/tables/spawnfunc_list.h @@ -180,6 +180,7 @@ {"target_crosslevel_trigger", SP_target_crosslevel_trigger}, {"target_earthquake", SP_target_earthquake}, {"target_explosion", SP_target_explosion}, +{"trigger_flashlight", SP_trigger_flashlight}, {"target_goal", SP_target_goal}, {"target_gravity", SP_target_gravity}, {"target_help", SP_target_help},