From deb4c0dce1468665f6328aea364ab570b93490f8 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 19 Jul 2020 00:24:54 +1000 Subject: [PATCH] Make ladders use the same iterative logic as conveyors, fixes some maps with super thin ladders --- qcsrc/common/mapobjects/func/ladder.qc | 68 +++++++++++++++---- qcsrc/common/mapobjects/func/ladder.qh | 4 +- qcsrc/common/physics/player.qc | 2 +- qcsrc/common/viewloc.qc | 4 +- qcsrc/ecs/systems/physics.qc | 2 +- qcsrc/server/bot/default/havocbot/havocbot.qc | 2 +- qcsrc/server/bot/default/navigation.qc | 2 +- qcsrc/server/client.qc | 4 ++ 8 files changed, 66 insertions(+), 22 deletions(-) diff --git a/qcsrc/common/mapobjects/func/ladder.qc b/qcsrc/common/mapobjects/func/ladder.qc index 6fb3a435aa..23cdf1d49f 100644 --- a/qcsrc/common/mapobjects/func/ladder.qc +++ b/qcsrc/common/mapobjects/func/ladder.qc @@ -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 diff --git a/qcsrc/common/mapobjects/func/ladder.qh b/qcsrc/common/mapobjects/func/ladder.qh index 26cbbda032..e087ba8410 100644 --- a/qcsrc/common/mapobjects/func/ladder.qh +++ b/qcsrc/common/mapobjects/func/ladder.qh @@ -1,4 +1,6 @@ #pragma once -.float ladder_time; +IntrusiveList g_ladderents; +STATIC_INIT(g_ladderents) { g_ladderents = IL_NEW(); } + .entity ladder_entity; diff --git a/qcsrc/common/physics/player.qc b/qcsrc/common/physics/player.qc index 5d4beb1acf..2fd66af671 100644 --- a/qcsrc/common/physics/player.qc +++ b/qcsrc/common/physics/player.qc @@ -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]; diff --git a/qcsrc/common/viewloc.qc b/qcsrc/common/viewloc.qc index e5f90df089..c3d70fc509 100644 --- a/qcsrc/common/viewloc.qc +++ b/qcsrc/common/viewloc.qc @@ -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) diff --git a/qcsrc/ecs/systems/physics.qc b/qcsrc/ecs/systems/physics.qc index 75657c90f2..70ecc524ca 100644 --- a/qcsrc/ecs/systems/physics.qc +++ b/qcsrc/ecs/systems/physics.qc @@ -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; diff --git a/qcsrc/server/bot/default/havocbot/havocbot.qc b/qcsrc/server/bot/default/havocbot/havocbot.qc index d0c6da839c..0ff4797776 100644 --- a/qcsrc/server/bot/default/havocbot/havocbot.qc +++ b/qcsrc/server/bot/default/havocbot/havocbot.qc @@ -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) { diff --git a/qcsrc/server/bot/default/navigation.qc b/qcsrc/server/bot/default/navigation.qc index ebc18a6875..fe608d1f55 100644 --- a/qcsrc/server/bot/default/navigation.qc +++ b/qcsrc/server/bot/default/navigation.qc @@ -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; diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index 5047334f0a..1211e8988e 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -39,6 +39,7 @@ #include #include "../common/mapobjects/func/conveyor.qh" +#include #include "../common/mapobjects/teleporters.qh" #include "../common/mapobjects/target/spawnpoint.qh" #include @@ -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); -- 2.39.2