-const float PUSH_ONCE = 1;
-const float PUSH_SILENT = 2;
+#include "t_jumppads.qh"
-.float pushltime;
-.float istypefrag;
-.float height;
-
-void() SUB_UseTargets;
-
-float trigger_push_calculatevelocity_flighttime;
+#ifdef SVQC
void trigger_push_use()
{
if(teamplay)
+ {
self.team = activator.team;
+ self.SendFlags |= 2;
+ }
}
+#endif
/*
trigger_push_calculatevelocity
torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
- grav = autocvar_sv_gravity;
- if(other.gravity)
- grav *= other.gravity;
+ grav = PHYS_GRAVITY;
+ if(PHYS_ENTGRAVITY(other))
+ grav *= PHYS_ENTGRAVITY(other);
- zdist = torg_z - org_z;
+ zdist = torg.z - org.z;
sdist = vlen(torg - org - zdist * '0 0 1');
sdir = normalize(torg - org - zdist * '0 0 1');
vector solution;
solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
// ALWAYS solvable because jumpheight >= zdist
- if(!solution_z)
- solution_y = solution_x; // 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)
+ if(!solution.z)
+ solution.y = solution.x; // 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)
if(zdist == 0)
- solution_x = solution_y; // 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; // 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)
if(zdist < 0)
{
// almost straight line type
// jump apex is before the jump
// we must take the larger one
- trigger_push_calculatevelocity_flighttime = solution_y;
+ trigger_push_calculatevelocity_flighttime = solution.y;
}
else
{
// regular jump
// jump apex is during the jump
// we must take the larger one too
- trigger_push_calculatevelocity_flighttime = solution_y;
+ trigger_push_calculatevelocity_flighttime = solution.y;
}
}
else
// almost straight line type
// jump apex is after the jump
// we must take the smaller one
- trigger_push_calculatevelocity_flighttime = solution_x;
+ trigger_push_calculatevelocity_flighttime = solution.x;
}
else
{
// regular jump
// jump apex is during the jump
// we must take the larger one
- trigger_push_calculatevelocity_flighttime = solution_y;
+ trigger_push_calculatevelocity_flighttime = solution.y;
}
}
vs = sdist / trigger_push_calculatevelocity_flighttime;
if (self.active == ACTIVE_NOT)
return;
+#ifdef SVQC
if (!isPushable(other))
return;
+#endif
if(self.team)
- if(((self.spawnflags & 4) == 0) == (self.team != other.team))
+ if(((self.spawnflags & 4) == 0) == (DIFF_TEAM(self, other)))
return;
EXACTTRIGGER_TOUCH;
other.velocity = self.movedir;
}
- other.flags &= ~FL_ONGROUND;
+ UNSET_ONGROUND(other);
+#ifdef SVQC
if (IS_PLAYER(other))
{
// reset tracking of oldvelocity for impact damage (sudden velocity changes)
}
if(IS_REAL_CLIENT(other) || IS_BOT_CLIENT(other))
{
- float i;
- float found;
- found = FALSE;
- for(i = 0; i < other.jumppadcount && i < NUM_JUMPPADSUSED; ++i)
+ bool found = false;
+ for(int i = 0; i < other.jumppadcount && i < NUM_JUMPPADSUSED; ++i)
if(other.(jumppadsused[i]) == self)
- found = TRUE;
+ found = true;
if(!found)
{
- other.(jumppadsused[mod(other.jumppadcount, NUM_JUMPPADSUSED)]) = self;
+ other.(jumppadsused[other.jumppadcount % NUM_JUMPPADSUSED]) = self;
other.jumppadcount = other.jumppadcount + 1;
}
other.lastteleporttime = time;
if (other.deadflag == DEAD_NO)
- animdecide_setaction(other, ANIMACTION_JUMP, TRUE);
+ animdecide_setaction(other, ANIMACTION_JUMP, true);
}
else
- other.jumppadcount = TRUE;
+ other.jumppadcount = true;
// reset tracking of who pushed you into a hazard (for kill credit)
other.pushltime = 0;
self.think = SUB_Remove;
self.nextthink = time;
}
+#endif
}
.vector dest;
+#ifdef SVQC
+void trigger_push_link();
+void trigger_push_updatelink();
+#endif
void trigger_push_findtarget()
{
- entity e, t;
+ entity t;
vector org;
// first calculate a typical start point for the jump
org = (self.absmin + self.absmax) * 0.5;
- org_z = self.absmax_z - PL_MIN_z;
+ org.z = self.absmax.z - PL_MIN_z;
if (self.target)
{
- float n;
- n = 0;
+ float n = 0;
for(t = world; (t = find(t, targetname, self.target)); )
{
++n;
- e = spawn();
+#ifdef SVQC
+ entity e = spawn();
setorigin(e, org);
setsize(e, PL_MIN, PL_MAX);
e.velocity = trigger_push_calculatevelocity(org, t, self.height);
if(e.movetype == MOVETYPE_NONE)
waypoint_spawnforteleporter(self, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity));
remove(e);
+#endif
}
- if(n == 0)
+ if(!n)
{
// no dest!
+#ifdef SVQC
objerror ("Jumppad with nonexistant target");
+#endif
return;
}
else if(n == 1)
self.enemy = world;
}
}
+#ifdef SVQC
else
{
- e = spawn();
+ entity e = spawn();
setorigin(e, org);
setsize(e, PL_MIN, PL_MAX);
e.velocity = self.movedir;
waypoint_spawnforteleporter(self, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity));
remove(e);
}
+
+ trigger_push_link();
+ defer(0.1, trigger_push_updatelink);
+#endif
}
+#ifdef SVQC
+float trigger_push_send(entity to, float sf)
+{
+ WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_PUSH);
+ WriteByte(MSG_ENTITY, sf);
+
+ if(sf & 1)
+ {
+ WriteString(MSG_ENTITY, self.target);
+ WriteByte(MSG_ENTITY, self.team);
+ WriteInt24_t(MSG_ENTITY, self.spawnflags);
+ WriteByte(MSG_ENTITY, self.active);
+ WriteByte(MSG_ENTITY, self.warpzone_isboxy);
+ WriteByte(MSG_ENTITY, self.height);
+ WriteByte(MSG_ENTITY, self.scale);
+ WriteCoord(MSG_ENTITY, self.origin_x);
+ WriteCoord(MSG_ENTITY, self.origin_y);
+ WriteCoord(MSG_ENTITY, self.origin_z);
+
+ WriteCoord(MSG_ENTITY, self.mins_x);
+ WriteCoord(MSG_ENTITY, self.mins_y);
+ WriteCoord(MSG_ENTITY, self.mins_z);
+ WriteCoord(MSG_ENTITY, self.maxs_x);
+ WriteCoord(MSG_ENTITY, self.maxs_y);
+ WriteCoord(MSG_ENTITY, self.maxs_z);
+
+ WriteCoord(MSG_ENTITY, self.movedir_x);
+ WriteCoord(MSG_ENTITY, self.movedir_y);
+ WriteCoord(MSG_ENTITY, self.movedir_z);
+
+ WriteCoord(MSG_ENTITY, self.angles_x);
+ WriteCoord(MSG_ENTITY, self.angles_y);
+ WriteCoord(MSG_ENTITY, self.angles_z);
+ }
+
+ if(sf & 2)
+ {
+ WriteByte(MSG_ENTITY, self.team);
+ WriteByte(MSG_ENTITY, self.active);
+ }
+
+ return true;
+}
+
+void trigger_push_updatelink()
+{
+ self.SendFlags |= 1;
+}
+
+void trigger_push_link()
+{
+ Net_LinkEntity(self, false, 0, trigger_push_send);
+}
+#endif
+#ifdef SVQC
/*
* ENTITY PARAMETERS:
*
InitializeEntity(self, trigger_push_findtarget, INITPRIO_FINDTARGET);
}
-void spawnfunc_target_push() {}
-void spawnfunc_info_notnull() {}
-void spawnfunc_target_position() {}
+
+float target_push_send(entity to, float sf)
+{
+ WriteByte(MSG_ENTITY, ENT_CLIENT_TARGET_PUSH);
+
+ WriteByte(MSG_ENTITY, self.cnt);
+ WriteString(MSG_ENTITY, self.targetname);
+ WriteCoord(MSG_ENTITY, self.origin_x);
+ WriteCoord(MSG_ENTITY, self.origin_y);
+ WriteCoord(MSG_ENTITY, self.origin_z);
+
+ return true;
+}
+
+void target_push_link()
+{
+ Net_LinkEntity(self, false, 0, target_push_send);
+ self.SendFlags |= 1; // update
+}
+
+void spawnfunc_target_push() { target_push_link(); }
+void spawnfunc_info_notnull() { target_push_link(); }
+void spawnfunc_target_position() { target_push_link(); }
+
+#endif
+
+#ifdef CSQC
+void trigger_push_draw()
+{
+ float dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0) { return; }
+
+ trigger_touch_generic(trigger_push_touch);
+}
+
+void ent_trigger_push()
+{
+ float sf = ReadByte();
+
+ if(sf & 1)
+ {
+ self.classname = "jumppad";
+ self.target = strzone(ReadString());
+ float mytm = ReadByte(); if(mytm) { self.team = mytm - 1; }
+ self.spawnflags = ReadInt24_t();
+ self.active = ReadByte();
+ self.warpzone_isboxy = ReadByte();
+ self.height = ReadByte();
+ self.scale = ReadByte();
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
+ self.mins_x = ReadCoord();
+ self.mins_y = ReadCoord();
+ self.mins_z = ReadCoord();
+ self.maxs_x = ReadCoord();
+ self.maxs_y = ReadCoord();
+ self.maxs_z = ReadCoord();
+ setsize(self, self.mins, self.maxs);
+ self.movedir_x = ReadCoord();
+ self.movedir_y = ReadCoord();
+ self.movedir_z = ReadCoord();
+ self.angles_x = ReadCoord();
+ self.angles_y = ReadCoord();
+ self.angles_z = ReadCoord();
+
+ self.solid = SOLID_TRIGGER;
+ //self.draw = trigger_push_draw;
+ self.drawmask = MASK_ENGINE;
+ self.move_time = time;
+ //self.touch = trigger_push_touch;
+ trigger_push_findtarget();
+ }
+
+ if(sf & 2)
+ {
+ self.team = ReadByte();
+ self.active = ReadByte();
+ }
+}
+
+void ent_target_push()
+{
+ self.classname = "push_target";
+ self.cnt = ReadByte();
+ self.targetname = strzone(ReadString());
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
+
+ self.drawmask = MASK_ENGINE;
+}
+#endif