From eec7bfc9d6f5228781077d9c688e87592727222e Mon Sep 17 00:00:00 2001 From: Mario Date: Thu, 2 Jan 2025 23:32:51 +0000 Subject: [PATCH] Add activation support to some map entities lacking it --- qcsrc/common/mapobjects/func/door.qc | 12 ++++++++ qcsrc/common/mapobjects/func/door_rotating.qc | 1 + qcsrc/common/mapobjects/func/door_secret.qc | 12 +++++--- qcsrc/common/mapobjects/misc/dynlight.qc | 22 +++++++++++++++ qcsrc/common/mapobjects/target/changelevel.qc | 9 ++++++ qcsrc/common/mapobjects/target/levelwarp.qc | 9 ++++++ qcsrc/common/mapobjects/target/spawn.qc | 10 +++++++ qcsrc/common/mapobjects/target/voicescript.qc | 14 ++++++++++ qcsrc/common/mapobjects/trigger/counter.qc | 8 +++++- qcsrc/server/items/items.qc | 16 +++++++++++ qcsrc/server/spawnpoints.qc | 28 +++++++++++++++++++ 11 files changed, 136 insertions(+), 5 deletions(-) diff --git a/qcsrc/common/mapobjects/func/door.qc b/qcsrc/common/mapobjects/func/door.qc index 1e8cb985f..d6d80acc6 100644 --- a/qcsrc/common/mapobjects/func/door.qc +++ b/qcsrc/common/mapobjects/func/door.qc @@ -219,6 +219,8 @@ void door_use(entity this, entity actor, entity trigger) if (!this.owner) return; + if (this.owner.active != ACTIVE_ACTIVE) + return; this = this.owner; if (this.spawnflags & DOOR_TOGGLE) @@ -297,6 +299,10 @@ void door_touch(entity this, entity toucher) return; if (this.owner.door_finished > time) return; +#ifdef SVQC + if (this.owner.active != ACTIVE_ACTIVE) + return; +#endif this.owner.door_finished = time + 2; @@ -364,6 +370,10 @@ void door_trigger_touch(entity this, entity toucher) if(!((IS_CLIENT(toucher) || toucher.classname == "ENT_CLIENT_PROJECTILE") && !IS_DEAD(toucher))) #endif return; +#ifdef SVQC + if (this.owner.active != ACTIVE_ACTIVE) + return; +#endif if (this.owner.state == STATE_UP) return; @@ -641,6 +651,7 @@ void door_reset(entity this) setorigin(this, this.pos1); this.velocity = '0 0 0'; this.state = STATE_BOTTOM; + this.active = ACTIVE_ACTIVE; setthink(this, func_null); this.nextthink = 0; @@ -771,6 +782,7 @@ spawnfunc(func_door) setblocked(this, door_blocked); this.use = door_use; + this.active = ACTIVE_ACTIVE; if(this.spawnflags & DOOR_NONSOLID) this.solid = SOLID_NOT; diff --git a/qcsrc/common/mapobjects/func/door_rotating.qc b/qcsrc/common/mapobjects/func/door_rotating.qc index 29fd1d05f..ef2d64579 100644 --- a/qcsrc/common/mapobjects/func/door_rotating.qc +++ b/qcsrc/common/mapobjects/func/door_rotating.qc @@ -132,6 +132,7 @@ spawnfunc(func_door_rotating) setblocked(this, door_blocked); this.use = door_use; + this.active = ACTIVE_ACTIVE; this.pos1 = '0 0 0'; this.pos2 = this.movedir; diff --git a/qcsrc/common/mapobjects/func/door_secret.qc b/qcsrc/common/mapobjects/func/door_secret.qc index 50593a4e2..45d898a31 100644 --- a/qcsrc/common/mapobjects/func/door_secret.qc +++ b/qcsrc/common/mapobjects/func/door_secret.qc @@ -10,8 +10,8 @@ void fd_secret_done(entity this); void fd_secret_use(entity this, entity actor, entity trigger) { - float temp; - string message_save; + if(this.active != ACTIVE_ACTIVE) + return; SetResourceExplicit(this, RES_HEALTH, 10000); if(!this.bot_attack) @@ -22,7 +22,7 @@ void fd_secret_use(entity this, entity actor, entity trigger) if (this.origin != this.oldorigin) return; - message_save = this.message; + string message_save = this.message; this.message = ""; // no more message SUB_UseTargets(this, actor, trigger); // fire all targets / killtargets this.message = message_save; @@ -35,7 +35,7 @@ void fd_secret_use(entity this, entity actor, entity trigger) _sound(this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM); this.nextthink = this.ltime + 0.1; - temp = 1 - (this.spawnflags & DOOR_SECRET_1ST_LEFT); // 1 or -1 + int temp = 1 - (this.spawnflags & DOOR_SECRET_1ST_LEFT); // 1 or -1 makevectors(this.mangle); if (!this.t_width) @@ -153,6 +153,8 @@ void secret_touch(entity this, entity toucher) return; if (this.door_finished > time) return; + if (this.active != ACTIVE_ACTIVE) + return; this.door_finished = time + 2; @@ -174,6 +176,7 @@ void secret_reset(entity this) setorigin(this, this.oldorigin); setthink(this, func_null); this.nextthink = 0; + this.active = ACTIVE_ACTIVE; } /*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot @@ -244,6 +247,7 @@ spawnfunc(func_door_secret) setblocked(this, secret_blocked); this.speed = 50; this.use = fd_secret_use; + this.active = ACTIVE_ACTIVE; if(!this.targetname || this.targetname == "") this.spawnflags |= DOOR_SECRET_YES_SHOOT; diff --git a/qcsrc/common/mapobjects/misc/dynlight.qc b/qcsrc/common/mapobjects/misc/dynlight.qc index 6395500d2..27566fdd6 100644 --- a/qcsrc/common/mapobjects/misc/dynlight.qc +++ b/qcsrc/common/mapobjects/misc/dynlight.qc @@ -85,11 +85,30 @@ void dynlight_find_target(entity this) } void dynlight_use(entity this, entity actor, entity trigger) { + if(this.active != ACTIVE_ACTIVE) + return; if (this.light_lev == 0) this.light_lev = this.lefty; else this.light_lev = 0; } +void dynlight_setactive(entity this, int act) +{ + int old_status = this.active; + if(act == ACTIVE_TOGGLE) + this.active = (this.active == ACTIVE_ACTIVE) ? ACTIVE_NOT : ACTIVE_ACTIVE; + else + this.active = act; + + if(this.active != old_status) + this.light_lev = (this.active == ACTIVE_ACTIVE) ? this.lefty : 0; +} +void dynlight_reset(entity this) +{ + // TODO should anything else be reset here? + this.active = ACTIVE_ACTIVE; + this.light_lev = this.lefty; +} spawnfunc(dynlight) { if (!this.light_lev) @@ -98,6 +117,9 @@ spawnfunc(dynlight) this.color = '1 1 1'; this.lefty = this.light_lev; this.use = dynlight_use; + this.active = ACTIVE_ACTIVE; + this.setactive = dynlight_setactive; + this.reset = dynlight_reset; setsize (this, '0 0 0', '0 0 0'); setorigin(this, this.origin); //this.pflags = PFLAGS_FULLDYNAMIC; diff --git a/qcsrc/common/mapobjects/target/changelevel.qc b/qcsrc/common/mapobjects/target/changelevel.qc index 2cc3c58ba..096a5804e 100644 --- a/qcsrc/common/mapobjects/target/changelevel.qc +++ b/qcsrc/common/mapobjects/target/changelevel.qc @@ -7,6 +7,8 @@ void target_changelevel_use(entity this, entity actor, entity trigger) { if(game_stopped) return; + if(this.active != ACTIVE_ACTIVE) + return; if(this.spawnflags & CHANGELEVEL_MULTIPLAYER) { @@ -40,6 +42,11 @@ void target_changelevel_use(entity this, entity actor, entity trigger) changelevel(this.chmap); } +void target_changelevel_reset(entity this) +{ + this.active = ACTIVE_ACTIVE; +} + /*target_changelevel Target to change/end level KEYS: @@ -53,6 +60,8 @@ CHANGELEVEL_MULTIPLAYER: multiplayer support spawnfunc(target_changelevel) { this.use = target_changelevel_use; + this.active = ACTIVE_ACTIVE; + this.reset = target_changelevel_reset; if(!this.count) { diff --git a/qcsrc/common/mapobjects/target/levelwarp.qc b/qcsrc/common/mapobjects/target/levelwarp.qc index 21419cf81..83f44b7d6 100644 --- a/qcsrc/common/mapobjects/target/levelwarp.qc +++ b/qcsrc/common/mapobjects/target/levelwarp.qc @@ -5,6 +5,8 @@ void target_levelwarp_use(entity this, entity actor, entity trigger) { if(!autocvar_g_campaign) return; // only in campaign + if(this.active != ACTIVE_ACTIVE) + return; if(this.cnt) CampaignLevelWarp(this.cnt - 1); // specific level @@ -12,10 +14,17 @@ void target_levelwarp_use(entity this, entity actor, entity trigger) CampaignLevelWarp(-1); // next level } +void target_levelwarp_reset(entity this) +{ + this.active = ACTIVE_ACTIVE; +} + spawnfunc(target_levelwarp) { // this.cnt is index (starting from 1) of the campaign level to warp to // 0 means next level this.use = target_levelwarp_use; + this.active = ACTIVE_ACTIVE; + this.reset = target_levelwarp_reset; } #endif diff --git a/qcsrc/common/mapobjects/target/spawn.qc b/qcsrc/common/mapobjects/target/spawn.qc index b96370d18..271631718 100644 --- a/qcsrc/common/mapobjects/target/spawn.qc +++ b/qcsrc/common/mapobjects/target/spawn.qc @@ -270,6 +270,8 @@ bool target_spawn_cancreate(entity this) void target_spawn_use(entity this, entity actor, entity trigger) { + if(this.active != ACTIVE_ACTIVE) + return; if(this.target == "") { // spawn new entity @@ -331,10 +333,18 @@ void initialize_field_db() } } +void target_spawn_reset(entity this) +{ + // TODO call "spawn first" again? + this.active = ACTIVE_ACTIVE; +} + spawnfunc(target_spawn) { initialize_field_db(); this.use = target_spawn_use; + this.active = ACTIVE_ACTIVE; + this.reset = target_spawn_reset; this.message = strzone(strreplace("'", "\"", this.message)); this.target_spawn_id = ++target_spawn_count; InitializeEntity(this, target_spawn_spawnfirst, INITPRIO_LAST); diff --git a/qcsrc/common/mapobjects/target/voicescript.qc b/qcsrc/common/mapobjects/target/voicescript.qc index 6dfb568a8..a31cdb499 100644 --- a/qcsrc/common/mapobjects/target/voicescript.qc +++ b/qcsrc/common/mapobjects/target/voicescript.qc @@ -12,6 +12,8 @@ void target_voicescript_clear(entity pl) void target_voicescript_use(entity this, entity actor, entity trigger) { + if(this.active != ACTIVE_ACTIVE) + return; if(actor.voicescript != this) { actor.voicescript = this; @@ -28,6 +30,11 @@ void target_voicescript_next(entity pl) vs = pl.voicescript; if(!vs) return; + if(vs.active != ACTIVE_ACTIVE) + { + pl.voicescript = NULL; + return; + } if(vs.message == "") return; if (!IS_PLAYER(pl)) @@ -74,6 +81,11 @@ void target_voicescript_next(entity pl) } } +void target_voicescript_reset(entity this) +{ + this.active = ACTIVE_ACTIVE; +} + spawnfunc(target_voicescript) { // netname: directory of the sound files @@ -86,6 +98,8 @@ spawnfunc(target_voicescript) float i, n; this.use = target_voicescript_use; + this.active = ACTIVE_ACTIVE; + this.reset = target_voicescript_reset; n = tokenize_console(this.message); this.cnt = n / 2; diff --git a/qcsrc/common/mapobjects/trigger/counter.qc b/qcsrc/common/mapobjects/trigger/counter.qc index 765d3180e..c33c34925 100644 --- a/qcsrc/common/mapobjects/trigger/counter.qc +++ b/qcsrc/common/mapobjects/trigger/counter.qc @@ -23,8 +23,8 @@ void counter_use(entity this, entity actor, entity trigger) IL_PUSH(g_counters, mycounter); mycounter.owner = this; mycounter.realowner = actor; - mycounter.reset = counter_reset; // NOTE: this may be useless as the player deletes their counters upon respawning mycounter.counter_cnt = 0; + // NOTE: will be deleted when the player respawns or match resets } store = mycounter; } @@ -69,6 +69,12 @@ void counter_reset(entity this) this.nextthink = 0; this.counter_cnt = 0; this.active = ACTIVE_ACTIVE; + + // remove any per-player counters + IL_EACH(g_counters, it.owner == this, + { + delete(it); + }); } /*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage COUNTER_FIRE_AT_COUNT diff --git a/qcsrc/server/items/items.qc b/qcsrc/server/items/items.qc index 839f3ecc9..9b5d2d677 100644 --- a/qcsrc/server/items/items.qc +++ b/qcsrc/server/items/items.qc @@ -791,6 +791,7 @@ void Item_Reset(entity this) } setthink(this, Item_Think); this.nextthink = time; + this.active = ACTIVE_ACTIVE; if (this.waypointsprite_attached) { WaypointSprite_Kill(this.waypointsprite_attached); @@ -981,6 +982,18 @@ void item_use(entity this, entity actor, entity trigger) gettouch(this)(this, actor); } +void item_setactive(entity this, int act) +{ + int old_status = this.active; + if(act == ACTIVE_TOGGLE) + this.active = (this.active == ACTIVE_ACTIVE) ? ACTIVE_NOT : ACTIVE_ACTIVE; + else + this.active = act; + + if(this.active != old_status) + Item_Show(this, ((this.active == ACTIVE_ACTIVE) ? 1 : -1)); +} + void StartItem(entity this, entity def) { if (def.m_spawnfunc_hookreplace) @@ -1147,6 +1160,9 @@ void StartItem(entity this, entity def) if(this.targetname != "" && (this.spawnflags & 16)) this.use = item_use; + this.setactive = item_setactive; + this.active = ACTIVE_ACTIVE; + if(autocvar_spawn_debug >= 2) { // why not flags & fl_item? diff --git a/qcsrc/server/spawnpoints.qc b/qcsrc/server/spawnpoints.qc index 0a4ee0c2b..6548c40aa 100644 --- a/qcsrc/server/spawnpoints.qc +++ b/qcsrc/server/spawnpoints.qc @@ -75,8 +75,30 @@ void spawnpoint_use(entity this, entity actor, entity trigger) //LOG_INFO("spawnpoint was used!\n"); } +bool spawnpoint_customize(entity this, entity client) +{ + return (this.active == ACTIVE_ACTIVE); +} + +void spawnpoint_setactive(entity this, int act) +{ + int old_status = this.active; + if(act == ACTIVE_TOGGLE) + this.active = (this.active == ACTIVE_ACTIVE) ? ACTIVE_NOT : ACTIVE_ACTIVE; + else + this.active = act; + + if(this.active != old_status) + { + // mappers may attempt to let players disable enemy spawns + if(teamplay && have_team_spawns > 0) + some_spawn_has_been_used = true; + this.SendFlags |= 1; + } +} void spawnpoint_reset(entity this) { + this.active = ACTIVE_ACTIVE; this.SendFlags |= 1; // update team since it was restored during reset } @@ -125,6 +147,9 @@ void relocate_spawnpoint(entity this) } } + this.active = ACTIVE_ACTIVE; + this.setactive = spawnpoint_setactive; + setcefc(this, spawnpoint_customize); this.use = spawnpoint_use; setthink(this, spawnpoint_think); this.nextthink = time + 0.5 + random() * 2; // shouldn't need it for a little second @@ -222,6 +247,9 @@ vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck, boo if(!spot.target || spot.target == "") return '-1 0 0'; + if(spot.active != ACTIVE_ACTIVE && targetcheck) + return '-1 0 0'; + if(IS_REAL_CLIENT(this)) { if(spot.restriction == 1) -- 2.39.5