From b129df68ed2be06d615fa08e6b7a548f14e1bd26 Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Mon, 31 Aug 2020 06:47:40 +0200 Subject: [PATCH] func_plat: Initial implementation. Also went over func_tracktrain (be nice) and made func_tracktraincontrols the overlord of func_vehiclecontrols - which doesn't do anything different anyway. It might one day. --- src/gs-entbase/server.src | 2 + src/gs-entbase/server/basevehicle.cpp | 3 +- src/gs-entbase/server/func_conveyor.cpp | 2 +- src/gs-entbase/server/func_plat.cpp | 158 +++++++++ src/gs-entbase/server/func_tracktrain.cpp | 311 ++++++++++++++---- .../server/func_tracktraincontrols.cpp | 39 +++ src/gs-entbase/server/func_vehicle.cpp | 2 +- .../server/func_vehiclecontrols.cpp | 18 +- 8 files changed, 458 insertions(+), 77 deletions(-) create mode 100644 src/gs-entbase/server/func_plat.cpp create mode 100644 src/gs-entbase/server/func_tracktraincontrols.cpp diff --git a/src/gs-entbase/server.src b/src/gs-entbase/server.src index 52e9c800..2b755566 100644 --- a/src/gs-entbase/server.src +++ b/src/gs-entbase/server.src @@ -41,11 +41,13 @@ server/func_ladder.cpp server/func_train.cpp server/func_guntarget.cpp server/func_tracktrain.cpp +server/func_tracktraincontrols.cpp server/func_pushable.cpp server/func_wall.cpp server/func_wall_toggle.cpp server/func_conveyor.cpp server/func_rotating.cpp +server/func_plat.cpp server/func_pendulum.cpp server/func_vehicle.cpp server/func_vehiclecontrols.cpp diff --git a/src/gs-entbase/server/basevehicle.cpp b/src/gs-entbase/server/basevehicle.cpp index 4ea67636..b950795d 100644 --- a/src/gs-entbase/server/basevehicle.cpp +++ b/src/gs-entbase/server/basevehicle.cpp @@ -14,7 +14,7 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -class CBaseVehicle:CBaseEntity +class CBaseVehicle:CBaseTrigger { entity m_eDriver; @@ -62,6 +62,7 @@ void CBaseVehicle::PlayerLeave(base_player pl) { pl.movetype = MOVETYPE_WALK; + pl.flags &= ~FL_FROZEN; m_eDriver = __NULL__; } diff --git a/src/gs-entbase/server/func_conveyor.cpp b/src/gs-entbase/server/func_conveyor.cpp index 95174039..2fdb46be 100644 --- a/src/gs-entbase/server/func_conveyor.cpp +++ b/src/gs-entbase/server/func_conveyor.cpp @@ -54,7 +54,7 @@ func_conveyor::SetMovementDirection(void) void func_conveyor::touch(void) { - other.basevelocity = m_vecMoveDir * m_flSpeed; + other.basevelocity = m_vecMoveDir * (m_flSpeed * -0.2f); } /* TODO: Handle state? */ diff --git a/src/gs-entbase/server/func_plat.cpp b/src/gs-entbase/server/func_plat.cpp new file mode 100644 index 00000000..34aff7f8 --- /dev/null +++ b/src/gs-entbase/server/func_plat.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2016-2020 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/*QUAKED func_plat (0 .5 .8) ? +"targetname" Name + +Brush that lets light to pass through it. +On idTech 2 BSPs, it will change texture variants when triggered. +*/ + +enum +{ + PLATSTATE_RAISED, + PLATSTATE_LOWERED, + PLATSTATE_UP, + PLATSTATE_DOWN +}; + +class func_plat:CBaseTrigger +{ + int m_iState; + + float m_flSpeed; + float m_flHeight; + + void(void) func_plat; + virtual void(entity, int) Trigger; + virtual void(void) MoveUp; + virtual void(void) MoveDown; + virtual void(void) ArrivedUp; + virtual void(void) ArrivedDown; + virtual void(void) Respawn; + virtual void(void) touch; +}; + +void +func_plat::touch(void) +{ + if (other.movetype != MOVETYPE_WALK) { + return; + } + + Trigger(other, TRIG_TOGGLE); + +} + +void +func_plat::MoveDown(void) +{ + vector vecDifference; + float flTravel, fTravelTime; + + m_iState = PLATSTATE_DOWN; + vecDifference = ((m_oldOrigin - [0,0,m_flHeight]) - origin); + flTravel = vlen(vecDifference); + fTravelTime = (flTravel / m_flSpeed); + think = ArrivedDown; + + if (fTravelTime < 0.1) { + velocity = [0,0,0]; + nextthink = ltime + 0.1f; + return; + } + + velocity = (vecDifference * (1.0f / fTravelTime)); + nextthink = (ltime + fTravelTime); +} + +void +func_plat::MoveUp(void) +{ + vector vecDifference; + float flTravel, fTravelTime; + + m_iState = PLATSTATE_UP; + vecDifference = (m_oldOrigin - origin); + flTravel = vlen(vecDifference); + fTravelTime = (flTravel / m_flSpeed); + think = ArrivedUp; + + if (fTravelTime < 0.1) { + velocity = [0,0,0]; + nextthink = ltime + 0.1f; + return; + } + + velocity = (vecDifference * (1.0f / fTravelTime)); + nextthink = (ltime + fTravelTime); +} + +void +func_plat::ArrivedUp(void) +{ + velocity = [0,0,0]; + m_iState = PLATSTATE_RAISED; +} + +void +func_plat::ArrivedDown(void) +{ + velocity = [0,0,0]; + m_iState = PLATSTATE_LOWERED; +} + +void +func_plat::Trigger(entity act, int state) +{ + if (m_iState == PLATSTATE_RAISED) { + MoveDown(); + } else if (m_iState == PLATSTATE_LOWERED) { + MoveUp(); + } +} + +void +func_plat::Respawn(void) +{ + SetMovetype(MOVETYPE_PUSH); + SetSolid(SOLID_BSP); + SetModel(m_oldModel); + SetOrigin(m_oldOrigin); + + m_iState = PLATSTATE_RAISED; +} + +void +func_plat::func_plat(void) +{ + m_flSpeed = 100.0f; + + for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) { + switch (argv(i)) { + case "height": + m_flHeight = stof(argv(i+1)); + break; + case "speed": + m_flSpeed = stof(argv(i+1)); + break; + default: + break; + } + } + + CBaseTrigger::CBaseTrigger(); +} diff --git a/src/gs-entbase/server/func_tracktrain.cpp b/src/gs-entbase/server/func_tracktrain.cpp index 5e0b4974..2a23f3da 100644 --- a/src/gs-entbase/server/func_tracktrain.cpp +++ b/src/gs-entbase/server/func_tracktrain.cpp @@ -14,6 +14,8 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +var float autocvar_tracktrain_dir = 1.0f; + /*QUAKED func_tracktrain (0 .5 .8) ? "targetname" Name "target" Target when triggered. @@ -23,103 +25,288 @@ Moving platform following along path_* entities that's fully user controlled. Very unfinished. */ -class func_tracktrain:CBaseTrigger +enumflags { + FTRTRAIN_NOPITCH, + FTRTRAIN_NOUSE, + FTRTRAIN_UNUSED, + FTRTRAIN_NONSOLID +}; + +class func_tracktrain:CBaseVehicle +{ + /* attributes... */ + float m_flMaxSpeed; + float m_flStartSpeed; + + CBaseEntity m_ePath; + CBaseEntity m_eOldPath; float m_flSpeed; + vector m_vecControlMins; + vector m_vecControlMaxs; void(void) func_tracktrain; - virtual void(void) Find; - virtual void(void) NextPath; - virtual void(void) GoToTarget; + + virtual void(void) customphysics; virtual void(entity, int) Trigger; + virtual void(void) CheckPathFW; + virtual void(void) CheckPathRV; + virtual void(void) UpdateAngles; + virtual void(void) PlayerUse; + virtual void(void) Realign; virtual void(void) Respawn; }; -void func_tracktrain::GoToTarget(void) +void +func_tracktrain::Trigger(entity act, int state) { - float flTravelTime; - vector vel_to_pos; + m_flSpeed = 1.0f; +} + +void +func_tracktrain::CheckPathFW(void) +{ + if (vlen(m_ePath.origin - origin) < 1.0f) { + entity f; + CBaseEntity current, next; + current = (CBaseEntity)m_ePath; + + for (f = world; (f = find(f, CBaseEntity::m_strTargetName, current.m_strTarget));) { + /* we found the right entity */ + if (f.classname == "path_track" || f.classname == "path_corner") { + CBaseTrigger oldtrig; + oldtrig = (CBaseTrigger)m_ePath; + oldtrig.Trigger(this, TRIG_TOGGLE); + next = f; + break; + } + } + + m_eOldPath = m_ePath; + m_ePath = (entity)next; + } +} + +void +func_tracktrain::CheckPathRV(void) +{ + if (vlen(m_ePath.origin - origin) < 1.0f) { + entity f; + CBaseEntity current, next; + current = (CBaseEntity)m_ePath; + + for (f = world; (f = find(f, CBaseEntity::m_strTarget, current.m_strTargetName));) { + /* we found the right entity */ + if (f.classname == "path_track" || f.classname == "path_corner") { + next = f; + } + } + + m_eOldPath = m_ePath; + m_ePath = (entity)next; + } +} + +void +func_tracktrain::UpdateAngles(void) +{ + vector new_ang; + vector old_ang; + vector tmp; + float progress; + CBaseEntity reallyold, reallynew; entity f; - f = find(world, CBaseTrigger::m_strTargetName, m_strTarget); - - if (!f) { - dprint(sprintf("^1func_tracktrain::^3GoToTarget^7: Trigger-Target for %s not found! Removing.\n", m_strTargetName)); - return; + for (f = world; (f = find(f, CBaseEntity::m_strTarget, m_eOldPath.m_strTargetName));) { + if (f.classname == "path_track" || f.classname == "path_corner") { + reallyold = f; + } + } + + for (f = world; (f = find(f, CBaseEntity::m_strTargetName, m_ePath.m_strTarget));) { + if (f.classname == "path_track" || f.classname == "path_corner") { + reallynew = f; + } } - vel_to_pos = (f.origin - origin); - flTravelTime = (vlen(vel_to_pos) / m_flSpeed); + makevectors(vectoangles(m_eOldPath.origin - reallyold.origin)); + old_ang = v_forward; - if (!flTravelTime) { - NextPath(); - return; + makevectors(vectoangles(m_ePath.origin - m_eOldPath.origin)); + new_ang = v_forward; + + progress = vlen(m_ePath.origin - origin); + progress /= vlen(m_eOldPath.origin - m_ePath.origin); + progress = 1.0f - progress; + + /* print(sprintf("%f %d %d\n", progress, vlen(m_ePath.origin - origin), vlen(m_eOldPath.origin - m_ePath.origin))); */ + + tmp[0] = Math_Lerp(old_ang[0], new_ang[0], progress); + tmp[1] = Math_Lerp(old_ang[1], new_ang[1], progress); + tmp[2] = Math_Lerp(old_ang[2], new_ang[2], progress); + angles = vectoangles(tmp); +} + +void +func_tracktrain::customphysics(void) +{ + /* eject the dead */ + if (m_eDriver && m_eDriver.health <= 0) { + PlayerLeave((base_player)m_eDriver); } - velocity = (vel_to_pos * (1 / flTravelTime)); - think = NextPath; - nextthink = (time + flTravelTime); -} - -void func_tracktrain::NextPath(void) -{ - CBaseTrigger current_target; - - current_target = (CBaseTrigger)find(world, CBaseTrigger::m_strTargetName, m_strTarget); - - m_strTarget = current_target.m_strTarget; - velocity = [0,0,0]; - GoToTarget(); -} - -void func_tracktrain::Trigger(entity act, int state) -{ - GoToTarget(); -} - - -void func_tracktrain::Find(void) -{ - entity f = find(world, CBaseTrigger::m_strTargetName, m_strTarget); - - if (!f) { - dprint(sprintf("^1func_tracktrain::^3GoToTarget^7: Trigger-Target %s for %s not found! Removing.\n", m_strTarget, m_strTargetName)); - remove(this); - return; + if (m_eDriver) { + if (m_eDriver.movement[0] > 0) { + m_flSpeed = bound(0, m_flSpeed += frametime, 1.0f); + } else if (m_eDriver.movement[0] < 0) { + m_flSpeed = bound(0, m_flSpeed -= frametime, 1.0f); + } + m_eDriver.flags |= FL_FROZEN; } - SetOrigin(f.origin); + //m_flSpeed = autocvar_tracktrain_dir; + + if (m_flSpeed > 0.0f) { + makevectors(vectoangles(m_ePath.origin - origin)); + velocity = (v_forward * (m_flMaxSpeed * m_flSpeed)); + setorigin(this, origin + (velocity * frametime)); + UpdateAngles(); + } else { + makevectors(vectoangles(m_eOldPath.origin - origin)); + velocity = (v_forward * (m_flMaxSpeed * m_flSpeed)); + setorigin(this, origin + (velocity * frametime)); + } + + if (m_flSpeed > 0.0f) + CheckPathFW(); + else if (m_flSpeed < 0.0f) + CheckPathRV(); + + PlayerAlign(); + + /* support for think/nextthink */ + if (think && nextthink > 0.0f) { + if (nextthink < time) { + nextthink = 0.0f; + think(); + } + } } -void func_tracktrain::Respawn(void) +void +func_tracktrain::PlayerUse(void) { - SetSolid(SOLID_BSP); - SetMovetype(MOVETYPE_PUSH); - //blocked = Blocked; + vector matrix; + vector offs; + offs = eActivator.origin - origin; + makevectors(angles); + matrix[0] = dotproduct(offs, v_forward); + matrix[1] = -dotproduct(offs, v_right); + matrix[2] = dotproduct(offs, v_up); + + if not (matrix[0] >= m_vecControlMins[0] && matrix[0] <= m_vecControlMaxs[0]) + return; + if not (matrix[1] >= m_vecControlMins[1] && matrix[1] <= m_vecControlMaxs[1]) + return; + if not (matrix[2] >= m_vecControlMins[2] && matrix[2] <= m_vecControlMaxs[2]) + return; + + if (m_eDriver == eActivator) { + PlayerLeave((base_player)eActivator); + } else if (!m_eDriver) { + PlayerEnter((base_player)eActivator); + } +} + +void +func_tracktrain::Realign(void) +{ + entity t; + entity f; + CBaseEntity first, second; + string strFirst, strSecond; + + first = second = t = f = __NULL__; + + for (f = world; (f = find(f, CBaseEntity::m_strTarget, m_strTargetName));) { + /* we found the right entity */ + if (f.classname == "func_tracktraincontrols") { + t = f; + } + } + + if (t) { + vector offs; + offs = t.origin - origin; + m_vecControlMins = t.mins + offs; + m_vecControlMaxs = t.maxs + offs; + } else if (!(spawnflags & FTRTRAIN_NOUSE)) { + m_vecControlMins = [-1024,-1024,-1024]; + m_vecControlMaxs = m_vecControlMins * -1; + } + + /* we rotate and position ourselves after the first path_track/corner */ + strFirst = m_strTarget; + for (f = world; (f = find(f, CBaseEntity::m_strTargetName, strFirst));) { + /* we found the right entity */ + if (f.classname == "path_track" || f.classname == "path_corner") { + first = (CBaseEntity)f; + } + } + + /* now get the second one... */ + strSecond = first.m_strTarget; + for (f = world; (f = find(f, CBaseEntity::m_strTargetName, strSecond));) { + /* we found the right entity */ + if (f.classname == "path_track" || f.classname == "path_corner") { + second = (CBaseEntity)f; + } + } + + if (first && second) { + first = (CBaseEntity)first; + second = (CBaseEntity)second; + angles = vectoangles(first.origin - second.origin); + setorigin(this, first.origin); + } + + m_eOldPath = (entity)first; + m_ePath = (entity)second; +} + +void +func_tracktrain::Respawn(void) +{ + movetype = MOVETYPE_PUSH; + solid = SOLID_BSP; SetModel(m_oldModel); SetOrigin(m_oldOrigin); + SetAngles(m_oldAngle); + owner = m_eDriver = __NULL__; + velocity = [0,0,0]; - /* Make sure we got some time for the paths to spawn */ - nextthink = ltime + 0.1f; - think = Find; + think = Realign; + nextthink = time + 0.1f; + + m_flSpeed = m_flStartSpeed / m_flMaxSpeed; } -void func_tracktrain::func_tracktrain(void) +void +func_tracktrain::func_tracktrain(void) { for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) { switch (argv(i)) { case "speed": - m_flSpeed = stof(argv(i+1)); + m_flMaxSpeed = stof(argv(i+1)); + break; + case "startspeed": + m_flStartSpeed = stof(argv(i+1)); break; default: break; } } - //if (!m_flSpeed) { - m_flSpeed = 50; - //} - - CBaseTrigger::CBaseTrigger(); + CBaseVehicle::CBaseVehicle(); } diff --git a/src/gs-entbase/server/func_tracktraincontrols.cpp b/src/gs-entbase/server/func_tracktraincontrols.cpp new file mode 100644 index 00000000..069c42b1 --- /dev/null +++ b/src/gs-entbase/server/func_tracktraincontrols.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016-2020 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/*QUAKED func_tracktraincontrols (0 .5 .8) ? +"targetname" Name +"target" Name of the func_vehicle to control + +Brush that marks the usable region of a func_tracktrain, in order +to gain control. +*/ + +class func_tracktraincontrols:CBaseTrigger +{ + void(void) func_tracktraincontrols; +}; + +void +func_tracktraincontrols::func_tracktraincontrols(void) +{ + precache_model(model); + SetModel(model); + SetOrigin(origin); + SetRenderMode(RM_TRIGGER); + SetSolid(SOLID_NOT); + CBaseTrigger::CBaseTrigger(); +} diff --git a/src/gs-entbase/server/func_vehicle.cpp b/src/gs-entbase/server/func_vehicle.cpp index d56be9f7..040ad2c5 100644 --- a/src/gs-entbase/server/func_vehicle.cpp +++ b/src/gs-entbase/server/func_vehicle.cpp @@ -463,7 +463,7 @@ func_vehicle::Realign(void) } } - if (t) { + if (first && second) { vector end_pos; first = (CBaseEntity)first; second = (CBaseEntity)second; diff --git a/src/gs-entbase/server/func_vehiclecontrols.cpp b/src/gs-entbase/server/func_vehiclecontrols.cpp index 58ad4e3a..ee0097de 100644 --- a/src/gs-entbase/server/func_vehiclecontrols.cpp +++ b/src/gs-entbase/server/func_vehiclecontrols.cpp @@ -20,20 +20,14 @@ Brush that marks the usable region of a func_vehicle, in order to gain control. + +It's the same as func_tracktraincontrols, except that it's for +func_vehicle instead of func_tracktrain. */ -class func_vehiclecontrols:CBaseTrigger -{ - void(void) func_vehiclecontrols; -}; - void -func_vehiclecontrols::func_vehiclecontrols(void) +func_vehiclecontrols(void) { - precache_model(model); - SetModel(model); - SetOrigin(origin); - SetRenderMode(RM_TRIGGER); - SetSolid(SOLID_NOT); - CBaseTrigger::CBaseTrigger(); + spawnfunc_func_tracktraincontrols(); + self.classname = "func_vehiclecontrols"; }