From 42960cda05a711936083e3cd54804fc767e6942d Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Thu, 27 May 2021 09:44:01 +0200 Subject: [PATCH] GS-Entbase: Initial func_pushable implementation --- src/gs-entbase/server/func_pushable.qc | 97 +++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 9 deletions(-) diff --git a/src/gs-entbase/server/func_pushable.qc b/src/gs-entbase/server/func_pushable.qc index 0b838b2f..21dc5042 100644 --- a/src/gs-entbase/server/func_pushable.qc +++ b/src/gs-entbase/server/func_pushable.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 Marco Hladik + * Copyright (c) 2016-2021 Marco Hladik * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,7 +19,9 @@ "target" Target when triggered. "killtarget" Target to kill when triggered. -STUB! +This is essentially the same entity as a func_breakable, but +a player can push and pull it around the level. +It uses stepping player physics to move around. Trivia: This entity was introduced in Half-Life (1998). @@ -27,26 +29,103 @@ This entity was introduced in Half-Life (1998). class func_pushable:func_breakable { + entity m_pPuller; + entity m_eCollBox; + void(void) func_pushable; virtual void(void) customphysics; - virtual void(void) touch; + virtual void(void) Respawn; + virtual void(void) PlayerTouch; + virtual void(void) OnPlayerUse; }; void func_pushable::customphysics(void) { - tracebox(origin, mins, maxs, origin + (velocity * frametime), MOVE_NORMAL, this); + input_movevalues = [0,0,0]; + input_impulse = 0; + input_buttons = 0; + input_angles = [0,0,0]; + input_timelength = frametime; + + /* when we pull the box, it'll follow us whereever we go, just not too fast so it doesn't clip into us! */ + if (!m_pPuller.button5) { + m_pPuller = world; + } else { + /* drag us, make sure we don't collide */ + velocity[0] = m_pPuller.velocity[0] * 0.9f; + velocity[1] = m_pPuller.velocity[1] * 0.9f; + } + + /* see if we're clipping against entities or other func_pushable_bbox helper entities */ + vector position = absmin + (0.5 * (absmax - absmin)); + + /* if we're too far away from our box, split */ + if ((vlen(m_pPuller.origin - position) - vlen(size)) > 64) + m_pPuller = world; + + tracebox(position, -(size/2) * 0.95f, (size/2) * 0.95f, \ + position + (velocity * input_timelength), MOVE_NORMAL, this); + + if (trace_fraction < 1.0f) + return; + + /* run the physics, then fix our helper bbox! */ + runstandardplayerphysics(this); + setorigin(m_eCollBox, absmin + (0.5 * (absmax - absmin))); } void -func_pushable::touch(void) +func_pushable::PlayerTouch(void) { - if (other.movetype == MOVETYPE_WALK) { - + /* don't cause bounces */ + if (other.movetype == MOVETYPE_NONE) { + return; + } + + /* get the real position of the pushable */ + vector position = absmin + (0.5 * (absmax - absmin)); + + /* check if we're inside the pushable */ + if (other.origin[0] >= absmin[0] && other.origin[0] <= absmax[0]) + if (other.origin[1] >= absmin[1] && other.origin[1] <= absmax[1]) + return; + + /* check if we're above the pushable... */ + if ((other.absmin[2] + 16) >= absmax[2]) { + return; + } + + /* get the direction of the pushing player towards the pushable, then get a matrix */ + makevectors(vectoangles(other.origin - position)); + + /* add forward direction times speed */ + velocity = v_forward * -64; +} + +void +func_pushable::OnPlayerUse(void) +{ + m_pPuller = eActivator; +} + +void +func_pushable::Respawn(void) +{ + func_breakable::Respawn(); + movetype = MOVETYPE_STEP; + touch = PlayerTouch; + PlayerUse = OnPlayerUse; + + if (!m_eCollBox) { + m_eCollBox = spawn(); + m_eCollBox.classname = "func_pushable_bbox"; + m_eCollBox.solid = SOLID_BBOX; + m_eCollBox.owner = this; + setsize(m_eCollBox, -(size/2) * 0.9f, (size/2) * 0.9f); + setorigin(m_eCollBox, absmin + (0.5 * (absmax - absmin))); } - - velocity = other.velocity * 0.25; } void