Rewrite trigger_swamp to not require spawning new entities per player, implementation...
authorMario <mario.mario@y7mail.com>
Mon, 18 May 2020 12:10:24 +0000 (22:10 +1000)
committerMario <mario.mario@y7mail.com>
Mon, 18 May 2020 12:10:24 +0000 (22:10 +1000)
qcsrc/common/mapobjects/trigger/swamp.qc
qcsrc/common/mapobjects/trigger/swamp.qh
qcsrc/common/physics/player.qc
qcsrc/ecs/systems/physics.qc
qcsrc/server/client.qc

index 2794082..495deb7 100644 (file)
 *              2005 11 29
 */
 
-
-/*
-* Uses a entity calld swampslug to handle players in the swamp
-* It works like this: When the plyer enters teh swamp the spawnfunc_trigger_swamp
-* attaches a new "swampslug" to the player. As long as the plyer is inside
-* the swamp the swamp gives the slug new health. But the slug slowly kills itself
-* so when the player goes outside the swamp, it dies and releases the player from the
-* swamps curses (dmg/slowdown)
-*
-* I do it this way becuz there is no "untouch" event.
-*/
-void swampslug_think(entity this)
-{
-       //Slowly kill the slug
-       this.swamp_lifetime -= 1;
-
-       //Slug dead? then remove curses.
-       if(this.swamp_lifetime <= 0)
-       {
-               if(this.owner.swampslug == this)
-               {
-                       this.owner.in_swamp = false;
-                       this.owner.swampslug = NULL;
-               }
-               delete(this);
-               //centerprint(this.owner,"Killing slug...\n");
-               return;
-       }
-
-       // Slug still alive, so we are still in the swamp
-       // Or we have exited it very recently.
-       // Do the damage and renew the timer.
 #ifdef SVQC
-       Damage (this.owner, this, this, this.dmg, DEATH_SWAMP.m_id, DMG_NOWEP, this.owner.origin, '0 0 0');
-#endif
-
-       this.nextthink = time + this.swamp_interval;
-}
-
-void swamp_touch(entity this, entity toucher)
+void swamp_think(entity this)
 {
-       // If whatever thats touching the swamp is not a player
-       // or if its a dead player, just dont care abt it.
-       if(!IS_PLAYER(toucher) || IS_DEAD(toucher))
-               return;
-
-       EXACTTRIGGER_TOUCH(this, toucher);
+       // set myself as current swampslug where possible
+       IL_EACH(g_swamped, it.swampslug == this,
+       {
+               it.swampslug = NULL;
+               IL_REMOVE(g_swamped, it);
+       });
 
-       // Chech if player alredy got a swampslug.
-       if(!toucher.in_swamp)
+       if(this.active == ACTIVE_ACTIVE)
        {
-               // If not attach one.
-               //centerprint(toucher,"Entering swamp!\n");
-               if(!toucher.swampslug) // just incase
-                       toucher.swampslug = spawn();
-               toucher.swampslug.swamp_lifetime = 2;
-               setthink(toucher.swampslug, swampslug_think);
-               toucher.swampslug.nextthink = time;
-               toucher.swampslug.owner = toucher;
-               toucher.swampslug.dmg = this.dmg;
-               toucher.swampslug.swamp_interval = this.swamp_interval;
-               toucher.swamp_slowdown = this.swamp_slowdown;
-               toucher.in_swamp = true;
-               return;
+               FOREACH_ENTITY_RADIUS((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1, it.swampslug.active == ACTIVE_NOT && IS_PLAYER(it) && !IS_DEAD(it),
+               {
+                       vector emin = it.absmin;
+                       vector emax = it.absmax;
+                       if(this.solid == SOLID_BSP)
+                       {
+                               emin -= '1 1 1';
+                               emax += '1 1 1';
+                       }
+                       if(boxesoverlap(emin, emax, this.absmin, this.absmax)) // quick
+                               if(WarpZoneLib_BoxTouchesBrush(emin, emax, this, it)) // accurate
+                               {
+                                       if(!it.swampslug)
+                                               IL_PUSH(g_swamped, it);
+                                       it.swampslug = this;
+                               }
+               });
+
+               IL_EACH(g_swamped, it.swampslug == this,
+               {
+                       if(time > it.swamp_interval)
+                       {
+                               Damage (it, this, this, this.dmg, DEATH_SWAMP.m_id, DMG_NOWEP, it.origin, '0 0 0');
+                               it.swamp_interval = time + this.swamp_interval;
+                       }
+               });
        }
 
-       //toucher.in_swamp = true;
-
-       //Revitalize players swampslug
-       toucher.swampslug.swamp_lifetime = 2;
-}
-
-REGISTER_NET_LINKED(ENT_CLIENT_SWAMP)
-
-#ifdef SVQC
-float swamp_send(entity this, entity to, float sf)
-{
-       WriteHeader(MSG_ENTITY, ENT_CLIENT_SWAMP);
-
-       WriteByte(MSG_ENTITY, this.dmg); // can probably get away with using a single byte here
-       WriteByte(MSG_ENTITY, this.swamp_slowdown);
-       WriteByte(MSG_ENTITY, this.swamp_interval);
-
-       trigger_common_write(this, false);
-
-       return true;
-}
-
-void swamp_link(entity this)
-{
-       trigger_link(this, swamp_send);
+       this.nextthink = time;
 }
 
 /*QUAKED spawnfunc_trigger_swamp (.5 .5 .5) ?
@@ -116,37 +66,18 @@ slowed down and damaged over time
 spawnfunc(trigger_swamp)
 {
        // Init stuff
-       trigger_init(this);
-       settouch(this, swamp_touch);
+       EXACTTRIGGER_INIT;
+       this.active = ACTIVE_ACTIVE;
+       //trigger_init(this);
+       setthink(this, swamp_think);
+       this.nextthink = time;
 
        // Setup default keys, if missing
-       if(this.dmg <= 0)
+       if(!this.dmg)
                this.dmg = 5;
-       if(this.swamp_interval <= 0)
+       if(!this.swamp_interval)
                this.swamp_interval = 1;
-       if(this.swamp_slowdown <= 0)
+       if(!this.swamp_slowdown)
                this.swamp_slowdown = 0.5;
-
-       swamp_link(this);
-}
-
-#elif defined(CSQC)
-
-NET_HANDLE(ENT_CLIENT_SWAMP, bool isnew)
-{
-       this.dmg = ReadByte();
-       this.swamp_slowdown = ReadByte();
-       this.swamp_interval = ReadByte();
-
-       trigger_common_read(this, false);
-
-       return = true;
-
-       this.classname = "trigger_swamp";
-       this.solid = SOLID_TRIGGER;
-       settouch(this, swamp_touch);
-       this.drawmask = MASK_NORMAL;
-       this.move_time = time;
-       this.entremove = trigger_remove_generic;
 }
 #endif
index bfe860e..acb0cb2 100644 (file)
@@ -1,17 +1,11 @@
 #pragma once
 
-.float swamp_interval; //Hurt players in swamp with this interval
-.float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
+#ifdef SVQC
+IntrusiveList g_swamped;
+STATIC_INIT(g_swamped) { g_swamped = IL_NEW(); }
 
-.bool in_swamp;
 .entity swampslug;            // Uses this to release from swamp ("untouch" fix)
 
 .float swamp_interval; //Hurt players in swamp with this interval
-.float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
-.float swamp_lifetime;  // holds the points remaining until slug dies (not quite health!)
-
-#ifdef SVQC
-spawnfunc(trigger_swamp);
+.float swamp_slowdown; //Players in swamp get slowed down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
 #endif
-void swamp_touch(entity this, entity toucher);
-void swampslug_think(entity this);
index 5dce802..cba24ff 100644 (file)
@@ -40,7 +40,7 @@ void Physics_UpdateStats(entity this)
        STAT(MOVEVARS_HIGHSPEED, this) = autocvar_g_movement_highspeed;
 
        MUTATOR_CALLHOOK(PlayerPhysics_UpdateStats, this);
-       float maxspd_mod = PHYS_HIGHSPEED(this);
+       float maxspd_mod = PHYS_HIGHSPEED(this) * ((this.swampslug.active) ? this.swampslug.swamp_slowdown : 1);
         STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed", autocvar_sv_maxspeed) * maxspd_mod; // also slow walking
         if (autocvar_g_movement_highspeed_q3_compat) {
           STAT(MOVEVARS_AIRACCEL_QW, this) = Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw);
index cd59c51..41506ec 100644 (file)
@@ -47,7 +47,7 @@ void sys_phys_update(entity this, float dt)
 
        PM_check_blocked(this);
 
-       float maxspeed_mod = (!this.in_swamp) ? 1 : this.swamp_slowdown;  // cvar("g_balance_swamp_moverate");
+       float maxspeed_mod = 1;
 
 // conveyors: first fix velocity
        if (this.conveyor.active) { this.velocity -= this.conveyor.movedir; }
index b494763..79dca00 100644 (file)
@@ -687,8 +687,9 @@ void PutPlayerInServer(entity this)
                IL_REMOVE(g_conveyed, this);
        this.conveyor = NULL; // prevent conveyors at the previous location from moving a freshly spawned player
        if(this.swampslug)
-               delete(this.swampslug);
-       this.in_swamp = false;
+               IL_REMOVE(g_swamped, this);
+       this.swampslug = NULL;
+       this.swamp_interval = 0;
        STAT(HUD, this) = HUD_NORMAL;
 
        this.event_damage = PlayerDamage;