]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Make ladders use the same iterative logic as conveyors, fixes some maps with super...
authorMario <mario.mario@y7mail.com>
Sat, 18 Jul 2020 14:24:54 +0000 (00:24 +1000)
committerMario <mario.mario@y7mail.com>
Sat, 18 Jul 2020 14:24:54 +0000 (00:24 +1000)
qcsrc/common/mapobjects/func/ladder.qc
qcsrc/common/mapobjects/func/ladder.qh
qcsrc/common/physics/player.qc
qcsrc/common/viewloc.qc
qcsrc/ecs/systems/physics.qc
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/navigation.qc
qcsrc/server/client.qc

index 6fb3a435aa59b7b557cf04b521f2e77a01367665..23cdf1d49f4ac454c8d6901070e9d90ab9df3199 100644 (file)
@@ -1,22 +1,45 @@
 #include "ladder.qh"
 REGISTER_NET_LINKED(ENT_CLIENT_LADDER)
 
-void func_ladder_touch(entity this, entity toucher)
+void func_ladder_think(entity this)
 {
-#ifdef SVQC
-       if (!toucher.iscreature)
-               return;
-       if(IS_VEHICLE(toucher))
-               return;
-#elif defined(CSQC)
-       if(!IS_PLAYER(toucher)) // don't allow non-player predicted entities!
-               return;
+#ifdef CSQC
+       // TODO: check if this is what is causing the glitchiness when switching between them
+       float dt = time - this.move_time;
+       this.move_time = time;
+       if(dt <= 0) { return; }
 #endif
 
-       EXACTTRIGGER_TOUCH(this, toucher);
+       // set myself as current ladders where possible
+       IL_EACH(g_ladderents, it.ladder_entity == this,
+       {
+               it.ladder_entity = NULL;
+               IL_REMOVE(g_ladderents, it);
+       });
 
-       toucher.ladder_time = time + 0.1;
-       toucher.ladder_entity = this;
+       FOREACH_ENTITY_RADIUS((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1, !it.ladder_entity && IS_PLAYER(it) && it.move_movetype != MOVETYPE_NOCLIP && !IS_DEAD(it),
+       {
+               vector emin = it.absmin;
+               vector emax = it.absmax;
+               if(this.solid == SOLID_BSP || (IS_CSQC && this.solid == SOLID_TRIGGER)) // CSQC doesn't expand properly
+               {
+                       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.ladder_entity)
+                                       IL_PUSH(g_ladderents, it);
+                               it.ladder_entity = this;
+                       }
+               }
+       });
+
+#ifdef SVQC
+       this.nextthink = time;
+#endif
 }
 
 #ifdef SVQC
@@ -41,9 +64,10 @@ void func_ladder_link(entity this)
 
 void func_ladder_init(entity this)
 {
-       settouch(this, func_ladder_touch);
        trigger_init(this);
        func_ladder_link(this);
+       setthink(this, func_ladder_think);
+       this.nextthink = time;
 
        if(min(this.absmax.x - this.absmin.x, this.absmax.y - this.absmin.y) > 100)
                return;
@@ -124,8 +148,15 @@ spawnfunc(func_water)
 #elif defined(CSQC)
 .float speed;
 
+void func_ladder_draw(entity this) { func_ladder_think(this); }
+
 void func_ladder_remove(entity this)
 {
+       IL_EACH(g_ladderents, it.ladder_entity == this,
+       {
+               it.ladder_entity = NULL;
+               IL_REMOVE(g_ladderents, it);
+       });
        strfree(this.classname);
 }
 
@@ -134,15 +165,22 @@ NET_HANDLE(ENT_CLIENT_LADDER, bool isnew)
        this.classname = strzone(ReadString());
        this.skin = ReadByte();
        this.speed = ReadCoord();
+       this.solid = SOLID_TRIGGER;
 
        trigger_common_read(this, false);
 
-       this.solid = SOLID_TRIGGER;
-       settouch(this, func_ladder_touch);
+       if(isnew)
+               IL_PUSH(g_drawables, this);
+       this.draw = func_ladder_draw;
        this.drawmask = MASK_NORMAL;
+
        this.move_time = time;
        this.entremove = func_ladder_remove;
 
+       // NOTE: CSQC's version of setorigin doesn't expand
+       this.absmin -= '1 1 1';
+       this.absmax += '1 1 1';
+
        return true;
 }
 #endif
index 26cbbda032b0422dc6f7e9c6e749be79a4ccd3d7..e087ba8410a341fb09d77f6fa338030a7d109b65 100644 (file)
@@ -1,4 +1,6 @@
 #pragma once
 
-.float ladder_time;
+IntrusiveList g_ladderents;
+STATIC_INIT(g_ladderents) { g_ladderents = IL_NEW(); }
+
 .entity ladder_entity;
index 5d4beb1acf1a7615391d14f5f035a264ca7875ca..2fd66af671f54ea1bb85cbde7f8b7a04f0d3ba7a 100644 (file)
@@ -628,7 +628,7 @@ void PM_check_hitground(entity this)
        if (!this.wasFlying) return;
     this.wasFlying = false;
     if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
-    if (time < this.ladder_time) return;
+    if (this.ladder_entity) return;
     for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
     {
        .entity weaponentity = weaponentities[slot];
index e5f90df089ebe2498a7a1f33b68fb7012796e16e..c3d70fc509d2d992fae61b7be4d37d2af8df271b 100644 (file)
@@ -19,7 +19,7 @@ void viewloc_PlayerPhysics(entity this)
 
                vector old_movement = PHYS_CS(this).movement;
                PHYS_CS(this).movement_x = old_movement_y;
-               if((this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && !(time < this.ladder_time))
+               if((this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && !this.ladder_entity)
                        PHYS_CS(this).movement_y = old_movement_x;
                else
                        PHYS_CS(this).movement_y = 0;
@@ -30,7 +30,7 @@ void viewloc_PlayerPhysics(entity this)
                vector forward = vectoangles(normalize(level_end - level_start));
                vector backward = vectoangles(normalize(level_start - level_end));
 
-               if((this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && this.angles_y < 0 && !(time < this.ladder_time))
+               if((this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && this.angles_y < 0 && !this.ladder_entity)
                        PHYS_CS(this).movement_y = -PHYS_CS(this).movement_y;
 
                if(this.viewloc.spawnflags & VIEWLOC_FREEAIM)
index 75657c90f268c6f9248377114df942c96fbf1674..70ecc524cafd2680feae7769785296f0f58f6f14 100644 (file)
@@ -112,7 +112,7 @@ void sys_phys_update(entity this, float dt)
                sys_phys_simulate(this, dt);
                this.com_phys_water = false;
                this.jumppadcount = 0;
-       } else if (time < this.ladder_time) {
+       } else if (this.ladder_entity) {
                this.com_phys_friction = PHYS_FRICTION(this);
                this.com_phys_vel_max = PHYS_MAXSPEED(this) * maxspeed_mod;
                this.com_phys_acc_rate = PHYS_ACCELERATE(this) * maxspeed_mod;
index d0c6da839ceb26d2b902657ef494f308b3bbeccf..0ff47977762180e7eb5688d9215e3623ccd0fafe 100644 (file)
@@ -1174,7 +1174,7 @@ void havocbot_movetogoal(entity this)
        }
 
        float ladder_zdir = 0;
-       if(time < this.ladder_time)
+       if(this.ladder_entity)
        {
                if(this.goalcurrent.origin.z + this.goalcurrent.mins.z > this.origin.z + this.mins.z)
                {
index ebc18a6875353a2306ea07c6304d989860b76cac..fe608d1f55ac26de10917346710bff7de2e6ff68 100644 (file)
@@ -1756,7 +1756,7 @@ int navigation_poptouchedgoals(entity this)
                        gc_min = this.goalcurrent.origin - '1 1 1' * 12;
                        gc_max = this.goalcurrent.origin + '1 1 1' * 12 + eZ * (jumpheight_vec.z + STAT(PL_MIN, this).z);
                }
-               if (time < this.ladder_time)
+               if (this.ladder_entity)
                {
                        if (!boxesoverlap(this.absmin, this.absmax - eZ * STAT(PL_MAX, this).z, gc_min, gc_max))
                                break;
index 5047334f0a4e9025d2b54d9da8527b06c0200626..1211e8988ea98b65c5fb90ac8f952a3c0e540067 100644 (file)
@@ -39,6 +39,7 @@
 #include <common/effects/qc/globalsound.qh>
 
 #include "../common/mapobjects/func/conveyor.qh"
+#include <common/mapobjects/func/ladder.qh>
 #include "../common/mapobjects/teleporters.qh"
 #include "../common/mapobjects/target/spawnpoint.qh"
 #include <common/mapobjects/trigger/counter.qh>
@@ -691,6 +692,9 @@ void PutPlayerInServer(entity this)
                IL_REMOVE(g_swamped, this);
        this.swampslug = NULL;
        this.swamp_interval = 0;
+       if(this.ladder_entity)
+               IL_REMOVE(g_ladderents, this);
+       this.ladder_entity = NULL;
        IL_EACH(g_counters, it.realowner == this,
        {
                delete(it);