From 515d5957602a87e5f255bba8d4d066a8aa91f42e Mon Sep 17 00:00:00 2001 From: Juhu <5894800-Juhu_@users.noreply.gitlab.com> Date: Mon, 30 Jan 2023 03:03:19 +0100 Subject: [PATCH] q3df compat: remove IntrusiveList in entity field for trigger_push_velocity to avoid overflow crashes --- qcsrc/common/mapobjects/trigger/jumppads.qc | 61 ++++++++++++++++----- qcsrc/common/mapobjects/trigger/jumppads.qh | 6 +- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/qcsrc/common/mapobjects/trigger/jumppads.qc b/qcsrc/common/mapobjects/trigger/jumppads.qc index 17d1d57da..da2f8dc0b 100644 --- a/qcsrc/common/mapobjects/trigger/jumppads.qc +++ b/qcsrc/common/mapobjects/trigger/jumppads.qc @@ -226,13 +226,28 @@ vector trigger_push_velocity_calculatevelocity(entity this, vector org, entity t return vs + '0 0 1' * vz; } -void check_pushed(entity this) +void check_pushed(entity this) // first jump pad to think thinks for every jump pad { - IL_EACH(this.pushed, WarpZoneLib_ExactTrigger_Touch(this, it), + IL_EACH(are_pushed, true, { - IL_REMOVE(this.pushed, it); + bool empty = true; + for(int i = 0; i < MAX_PUSHED; ++i) + { + if(!it.has_pushed[i]) continue; + if(WarpZoneLib_ExactTrigger_Touch(it.has_pushed[i], it)) + { + it.has_pushed[i] = NULL; + continue; + } + empty = false; + } + if(empty) + { + IL_REMOVE(are_pushed, it); + } }); - if(!IL_EMPTY(this.pushed)) + + if(!IL_EMPTY(are_pushed)) { this.nextthink = time; } @@ -251,7 +266,35 @@ bool jumppad_push(entity this, entity targ, bool is_velocity_pad) org.z += 1; // off by 1! } - bool is_pushed = is_velocity_pad && IL_CONTAINS(this.pushed, targ); + bool is_pushed = false; + if(is_velocity_pad) + { + for(int i = 0; i < MAX_PUSHED; ++i) + { + if(this == targ.has_pushed[i]) + { + is_pushed = true; + break; + } + } + + if(!is_pushed && ((this.spawnflags & ADD_XY) || (this.spawnflags & ADD_Z))) // remember jump pads which boost on initial touch + { + bool limit_reached = true; + for(int i = 0; i < MAX_PUSHED; ++i) + { + if(targ.has_pushed[i]) continue; + limit_reached = false; + targ.has_pushed[i] = this; // may be briefly out of sync between client and server if client prediction is toggled + } + if(limit_reached) + { + return false; // too many overlapping jump pads + } + IL_PUSH(are_pushed, targ); + this.nextthink = time; + } + } if(this.enemy) { @@ -299,12 +342,6 @@ bool jumppad_push(entity this, entity targ, bool is_velocity_pad) } } - if(is_velocity_pad && !is_pushed) - { - IL_PUSH(this.pushed, targ); // may be briefly out of sync between client and server if client prediction is toggled - this.nextthink = time; - } - if(!is_pushed) UNSET_ONGROUND(targ); #ifdef CSQC @@ -823,7 +860,6 @@ spawnfunc(trigger_push_velocity) trigger_push_velocity_link(this); // link it now - this.pushed = IL_NEW(); setthink(this, check_pushed); } @@ -922,7 +958,6 @@ NET_HANDLE(ENT_CLIENT_TRIGGER_PUSH_VELOCITY, bool isnew) this.solid = SOLID_TRIGGER; settouch(this, trigger_push_velocity_touch); this.move_time = time; - this.pushed = IL_NEW(); setthink(this, check_pushed); return true; diff --git a/qcsrc/common/mapobjects/trigger/jumppads.qh b/qcsrc/common/mapobjects/trigger/jumppads.qh index 7be45ce93..51ec38d98 100644 --- a/qcsrc/common/mapobjects/trigger/jumppads.qh +++ b/qcsrc/common/mapobjects/trigger/jumppads.qh @@ -18,7 +18,11 @@ STATIC_INIT(g_jumppads) { g_jumppads = IL_NEW(); } .float pushltime; .bool istypefrag; .float height; -.IntrusiveList pushed; + +const int MAX_PUSHED = 16; // maximum amount of jump pads which are allowed to push simultaneously +.entity has_pushed[MAX_PUSHED]; +IntrusiveList are_pushed; +STATIC_INIT(are_pushed) { are_pushed = IL_NEW(); } const int NUM_JUMPPADSUSED = 3; .float jumppadcount; -- 2.39.2