djcev.com

//

Git Repos / fte_dogmode / qc / triggers / push.qc

Last update to this file was on 2024-04-08 at 15:40.

Show push.qc

////////////////////////////////////////////////////////////////////////////////
// trigger_push -- id1 with additions by dumptruck_ds & CEV
////////////////////////////////////////////////////////////////////////////////

//======================================================================
// constants
//======================================================================

const float TRIGGER_PUSH_ONCE = 1; // only trigger once
const float TRIGGER_PUSH_STARTOFF = 8; // trigger will start off
const float TRIGGER_PUSH_SILENT = 16; // push silently
const float TRIGGER_PUSH_NOISE = 32; // use custom sound via noise key/value

//======================================================================
// forward declarations
//======================================================================

vector(float a, float b, float c) solve_quadratic;

// base_trigger_push
vector(vector org, entity tgt, float ht) base_trigger_push_calculatevelocity;
void() base_trigger_push_findtarget;
void() base_trigger_push_touch;

// trigger_push
// void() trigger_push_use;
void(entity e) trigger_push_init;
void() trigger_push;

// trigger_push_custom
void() trigger_push_custom_use;
void(entity e) trigger_push_custom_init;
void() trigger_push_custom;

//------------------------------------------------------------------------------

//----------------------------------------------------------------------
// solve_quadratic -- from Nexuiz source code; original can be found at
// https://github.com/smlinux/nexuiz/blob/master/data/qcsrc/common/util.qc
//----------------------------------------------------------------------
vector(float a, float b, float c) solve_quadratic =
{
// ax^2 + bx + c = 0
vector v = '0 0 0';
float D;
if (a == 0)
{
if (b != 0)
{
v_x = v_y = -c / b;
v_z = 1;
}
else
{
if (c == 0)
{
// actually, every number solves the equation!
v_z = 1;
}
}
}
else
{
D = b * b - 4 * a * c;
if (D >= 0)
{
D = sqrt (D);
if (a > 0)
{
// put the smaller solution first
v_x = ((-b) - D) / (2 * a);
v_y = ((-b) + D) / (2 * a);
}
else
{
v_x = (-b + D) / (2 * a);
v_y = (-b - D) / (2 * a);
}
v_z = 1;
}
else
{
// complex solutions!
D = sqrt (-D);
v_x = -b / (2 * a);
if (a > 0)
v_y = D / (2 * a);
else
v_y = -D / (2 * a);
v_z = 0;
}
}
return v;
};

//----------------------------------------------------------------------
// class base_trigger_push: base_trigger
// {
//--------------------------------------------------------------
// trigger_push_calculatevelocity
//
// Arguments:
// org - origin of the object which is to be pushed
// tgt - target entity (can be either a point or a model entity;
// if it is the latter, its midpoint is used)
// ht - jump height, measured from the higher one of org and tgt's
// midpoint
//
// Returns: velocity for the jump
// the global trigger_push_calculatevelocity_flighttime is set to the
// total jump time
//
// copied from Nexuiz source code; original can be found here:
// github.com/smlinux/nexuiz/blob/master/data/qcsrc/server/t_jumppads.qc
//--------------------------------------------------------------
vector(vector org, entity tgt, float ht)
base_trigger_push_calculatevelocity =
{
local float sdist, zdist, vs, vz, jumpheight;
local vector sdir, torg;
local vector solution;
local float flighttime;

torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;

zdist = torg_z - org_z;
sdist = vlen (torg - org - zdist * '0 0 1');
sdir = normalize (torg - org - zdist * '0 0 1');

// how high do we need to push the player?
jumpheight = fabs (ht);
if (zdist > 0)
jumpheight = jumpheight + zdist;

/*
STOP.

You will not understand the following equations anyway...
But here is what I did to get them.

I used the functions

s(t) = t * vs
z(t) = t * vz - 1/2 grav t^2

and solved for:

s(ti) = sdist
z(ti) = zdist
max(z, ti) = jumpheight

From these three equations, you will find the three
parameters vs, vz and ti.
*/

// push him so high... NOTE: sqrt(positive)!
vz = sqrt (2 * world_gravity * jumpheight);

// we start with downwards velocity only if it's a downjump
// and the jump apex should be outside the jump!
if (ht < 0)
if (zdist < 0)
vz = -vz;

// equation "z(ti) = zdist"
solution = solve_quadratic (0.5 * world_gravity, -vz, zdist);
// ALWAYS solvable because jumpheight >= zdist
if (!solution_z)
// just in case it is not solvable due to roundoff
// errors, assume two equal solutions at their center
// (this is mainly for the usual case with ht == 0)
solution_y = solution_x;
if (zdist == 0)
// solution_x is 0 in this case, so don't use it, but
// rather use solution_y (which will be
// sqrt(0.5 * jumpheight / grav), actually)
solution_x = solution_y;

if (zdist < 0)
{
// down-jump
if (ht < 0)
{
// almost straight line type
// jump apex is before the jump
// we must take the larger one
flighttime = solution_y;
}
else
{
// regular jump
// jump apex is during the jump
// we must take the larger one too
flighttime = solution_y;
}
}
else
{
// up-jump
if (ht < 0)
{
// almost straight line type
// jump apex is after the jump
// we must take the smaller one
flighttime = solution_x;
}
else
{
// regular jump
// jump apex is during the jump
// we must take the larger one
flighttime = solution_y;
}
}
vs = sdist / flighttime;

// finally calculate the velocity
return sdir * vs + '0 0 1' * vz;
};

//--------------------------------------------------------------
void() base_trigger_push_findtarget =
{
self.enemy = find (world, targetname, self.target);
if (self.enemy)
{
local vector org;
org = (self.absmin + self.absmax) * 0.5;
org_z = self.absmax_z - -24; // - PL_MIN_z;
self.movedir = base_trigger_push_calculatevelocity (
org, self.enemy, self.height);
}
};

//--------------------------------------------------------------
void() base_trigger_push_touch =
{
if (self.estate != STATE_ACTIVE)
return;

// from Copper -- dumptruck_ds
if (other.movetype == MOVETYPE_NOCLIP)
return;

// try to find target again if necessary
if (self.target && (!self.enemy))
base_trigger_push_findtarget ();

// we have a target, set movedir accordingly
if (self.target && self.enemy)
self.movedir = base_trigger_push_calculatevelocity (
other.origin, self.enemy, self.height);

if (other.classtype == CT_PROJECTILE_GRENADE)
{
if (self.target && self.enemy)
other.velocity = self.movedir;
else
other.velocity = self.speed * self.movedir * 10;
}
else if (other.health > 0)
{
if (self.target && self.enemy)
other.velocity = self.movedir;
else
other.velocity = self.speed * self.movedir * 10;

if (other.classtype == CT_PLAYER &&
!(self.spawnflags & TRIGGER_PUSH_SILENT))
{
if (other.fly_sound < time)
{
if (!(self.spawnflags &
TRIGGER_PUSH_NOISE))
{
other.fly_sound = time + 1.5;
sound (other, CHAN_AUTO,
"ambience/windfly.wav",
1, ATTN_NORM);
}
else
{
other.fly_sound = time + 1.5;
sound (other, CHAN_AUTO,
self.noise,
1, ATTN_NORM);
}
}
}
}

if (self.spawnflags & TRIGGER_PUSH_ONCE)
remove (self);
};
// };

/*QUAKED trigger_push (.5 .5 .5) ? TRIGGER_PUSH_ONCE X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
Pushes the player
*/
//----------------------------------------------------------------------
// class trigger_push: base_trigger_push
// {
//--------------------------------------------------------------
// dumptruck_ds
//--------------------------------------------------------------
/*
void() trigger_push_use =
{
self.is_waiting = !self.is_waiting;
}
*/

//--------------------------------------------------------------
void(entity e) trigger_push_init =
{
e.classname = "trigger_push";
e.classtype = CT_TRIGGER_PUSH;
e.touch = base_trigger_push_touch;

base_trigger_init (e);
precache_sound ("ambience/windfly.wav");

if (!e.speed)
e.speed = 1000;

if (e.target != __NULL__ && e.target != "")
{
// attempt to find the target
base_trigger_push_findtarget ();
if (!e.enemy)
if (!e.movedir)
// TODO CEV is this up? I don't remember
e.movedir = '0 0 180';
}

sub_checkwaiting (e);
};

//--------------------------------------------------------------
void() trigger_push =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

trigger_push_init (self);
};
// };

/*QUAKED trigger_push_custom (.5 .5 .5) ? TRIGGER_PUSH_ONCE TRIGGER_PUSH_STARTOFF TRIGGER_PUSH_SILENT X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY


dumptruck_ds

trigger_push_custom is a new entity. This can be used to create traps,
jumppads, currents in water and more.

If TRIGGER_PUSH_STARTOFF flag is set, this disables the trigger. This can
be targeted and toggled off and on. If the TRIGGER_PUSH_SILENT flag is set
it won't make the windfly sound. Use TRIGGER_PUSH_NOISE spawnflag and the
noise key/value to use a custom push sound. Custom sounds should be "one
off" sounds NOT be looping.

Adapted from Hipnotic's func_togglewall
*/
//----------------------------------------------------------------------
// class trigger_push_custom: base_trigger_push
// {
//--------------------------------------------------------------
// dumptruck_ds was based on hipnotic blocker_use now Alkaline estate
//--------------------------------------------------------------
void() trigger_push_custom_use =
{
if (self.estate != STATE_ACTIVE)
self.estate = STATE_ACTIVE;
else
self.estate = STATE_INACTIVE;
};

//--------------------------------------------------------------
void(entity e) trigger_push_custom_init =
{
e.classname = "trigger_push_custom";
e.classtype = CT_TRIGGER_PUSH_CUSTOM;
e.touch = base_trigger_push_touch;
e.use = trigger_push_custom_use;

base_trigger_init (e);
precache_sound ("ambience/windfly.wav");

if (e.spawnflags & TRIGGER_PUSH_STARTOFF)
e.estate = STATE_INACTIVE;

if (e.noise != "")
precache_sound (e.noise);

if (!e.speed)
e.speed = 1000;

if (e.target != __NULL__ && e.target != "")
{
// attempt to find the target
base_trigger_push_findtarget ();
if (!e.enemy)
if (!e.movedir)
// TODO CEV is this up? I don't remember
e.movedir = '0 0 180';
}

sub_checkwaiting (e);
};

//--------------------------------------------------------------
void() trigger_push_custom =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

trigger_push_custom_init (self);
};
// };

Return to the top of this page or return to the overview of this repo.

Log push.qc

Return to the top of this page or return to the overview of this repo.