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.

This commit is contained in:
Marco Cawthorne 2020-08-31 06:47:40 +02:00
parent 1d111506ea
commit b129df68ed
8 changed files with 458 additions and 77 deletions

View file

@ -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

View file

@ -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__;
}

View file

@ -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? */

View file

@ -0,0 +1,158 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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();
}

View file

@ -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();
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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();
}

View file

@ -463,7 +463,7 @@ func_vehicle::Realign(void)
}
}
if (t) {
if (first && second) {
vector end_pos;
first = (CBaseEntity)first;
second = (CBaseEntity)second;

View file

@ -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";
}