break;
case ENT_CLIENT_LGBEAM:
case ENT_CLIENT_GAUNTLET:
- b = view_origin + view_forward * MAX_SHOT_DISTANCE;
+ b = view_origin + view_forward * vlen(self.velocity - self.origin); // honor original length of beam!
WarpZone_TraceLine(view_origin, b, MOVE_NORMAL, world);
b = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
a = view_origin + view_forward * vs_x + view_right * -vs_y + view_up * vs_z;
Draw_GrapplingHook_trace_callback_tex = tex;
Draw_GrapplingHook_trace_callback_rnd = random();
- WarpZone_TraceBox_ThroughZone(a, '0 0 0', '0 0 0', b, MOVE_NOMONSTERS, world, world, Draw_GrapplingHook_trace_callback);
+ WarpZone_TraceBox_ThroughZone(a, '0 0 0', '0 0 0', b, ((self.HookType == ENT_CLIENT_HOOK) ? MOVE_NOTHING : MOVE_NORMAL), world, world, Draw_GrapplingHook_trace_callback);
Draw_GrapplingHook_trace_callback_tex = string_null;
switch(self.HookType)
{
default:
case ENT_CLIENT_HOOK:
- self.angles = vectoangles(b - a);
+ setorigin(self, trace_endpos); // hook endpoint!
+ self.angles = vectoangles(trace_endpos - WarpZone_TransformOrigin(WarpZone_trace_transform, a));
break;
case ENT_CLIENT_LGBEAM:
case ENT_CLIENT_GAUNTLET:
+ setorigin(self, a); // beam origin!
break;
}
}
W_HitPlotAnalysis(ent, v_forward, v_right, v_up);
if(ent.weaponentity.movedir_x > 0)
- {
vecs = ent.weaponentity.movedir;
- vecs_y = -vecs_y;
- }
else
vecs = '0 0 0';
-
if(debug_shotorg != '0 0 0')
vecs = debug_shotorg;
- dv = v_right * vecs_y + v_up * vecs_z;
+ dv = v_right * -vecs_y + v_up * vecs_z;
w_shotorg = ent.origin + ent.view_ofs + dv;
// now move the shotorg forward as much as requested if possible
if(argv(0) == "debug_shotorg")
{
debug_shotorg = stov(argv(1));
+ debug_shotorg_y = -debug_shotorg_y;
return;
}
.float prevlgfire;
void lgbeam_think()
{
+ vector endpos;
self.owner.prevlgfire = time;
if (self.owner.weaponentity.state != WS_INUSE || (self.owner.ammo_cells <= 0 && !(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)) || self != self.owner.lgbeam || self.owner.deadflag != DEAD_NO || !self.owner.BUTTON_ATCK)
{
makevectors(self.owner.v_angle);
vector angle;
angle = v_forward;
+ // get effect origin
+ vector vecs, org;
+ if(self.owner.weaponentity.movedir_x > 0)
+ vecs = self.owner.weaponentity.movedir;
+ else
+ vecs = '0 0 0';
+ if(debug_shotorg != '0 0 0')
+ vecs = debug_shotorg;
+ org = self.owner.origin + self.owner.view_ofs + v_forward * vecs_x + v_right * -vecs_y + v_up * vecs_z;
WarpZone_traceline_antilag(self.owner, self.owner.origin + self.owner.view_ofs, self.owner.origin + self.owner.view_ofs + angle * cvar("g_balance_electro_primary_range"), FALSE, self.owner, ANTILAG_LATENCY(self.owner));
+ endpos = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+ WarpZone_traceline_antilag(self.owner, org, endpos, FALSE, self.owner, ANTILAG_LATENCY(self.owner));
if not(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)
self.owner.ammo_cells = max(0, self.owner.ammo_cells - cvar("g_balance_electro_primary_ammo") * frametime);
}
// draw effect
- vector vecs, org;
- if(self.owner.weaponentity.movedir_x > 0)
- {
- vecs = self.owner.weaponentity.movedir;
- vecs_y = -vecs_y;
- }
- else
- vecs = '0 0 0';
- org = self.owner.origin + self.owner.view_ofs + v_forward * vecs_x + v_right * vecs_y + v_up * vecs_z;
-
if(org != self.hook_start)
{
self.SendFlags |= 2;
self.hook_start = org;
}
- if(trace_endpos != self.hook_end)
+ if(endpos != self.hook_end)
{
self.SendFlags |= 4;
- self.hook_end = trace_endpos;
+ self.hook_end = endpos;
}
}
.float prevgauntletfire;
void gauntletbeam_think()
{
+ vector endpos;
float damage, myforce, myradius;
if(self.cnt)
{
makevectors(self.owner.v_angle);
vector angle;
angle = v_forward;
-
+ // get effect origin
+ vector vecs, org;
+ if(self.owner.weaponentity.movedir_x > 0)
+ vecs = self.owner.weaponentity.movedir;
+ else
+ vecs = '0 0 0';
+ if(debug_shotorg != '0 0 0')
+ vecs = debug_shotorg;
+ org = self.owner.origin + self.owner.view_ofs + v_forward * vecs_x + v_right * -vecs_y + v_up * vecs_z;
+
WarpZone_traceline_antilag(self.owner, self.owner.origin + self.owner.view_ofs, self.owner.origin + self.owner.view_ofs + angle * myradius, FALSE, self.owner, ANTILAG_LATENCY(self.owner));
+ endpos = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+ WarpZone_traceline_antilag(self.owner, org, endpos, FALSE, self.owner, ANTILAG_LATENCY(self.owner));
// apply the damage
if(trace_fraction < 1)
}
// draw effect
- vector vecs, org;
- if(self.owner.weaponentity.movedir_x > 0)
- {
- vecs = self.owner.weaponentity.movedir;
- vecs_y = -vecs_y;
- }
- else
- vecs = '0 0 0';
- org = self.owner.origin + self.owner.view_ofs + v_forward * vecs_x + v_right * vecs_y + v_up * vecs_z;
-
if(org != self.hook_start)
{
self.SendFlags |= 2;
self.hook_start = org;
}
- if(trace_endpos != self.hook_end)
+ if(endpos != self.hook_end)
{
self.SendFlags |= 4;
- self.hook_end = trace_endpos;
+ self.hook_end = endpos;
}
}
void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent, entity zone, WarpZone_trace_callback_t cb)
{
+ float nomonsters_adjusted;
float frac, sol, i;
vector o0, e0;
entity wz;
vu = v_up;
o0 = org;
e0 = end;
+
+ switch(nomonsters)
+ {
+ case MOVE_WORLDONLY:
+ case MOVE_NOTHING:
+ nomonsters_adjusted = MOVE_NOMONSTERS;
+ break;
+ default:
+ nomonsters_adjusted = nomonsters;
+ break;
+ }
+
WarpZone_Trace_InitTransform();
// if starting in warpzone, first transform
wz = WarpZone_Find(org + mi, org + ma);
trace_ent = world;
break;
}
- tracebox(org, mi, ma, end, nomonsters, forent);
+ tracebox(org, mi, ma, end, nomonsters_adjusted, forent);
if(cb)
cb(org, trace_endpos, end);
if(sol < 0)
if(trace_fraction >= 1)
break;
if(trace_ent.classname != "trigger_warpzone")
+ {
+ if((nomonsters == MOVE_NOTHING) || ((nomonsters == MOVE_WORLDONLY) && trace_ent))
+ {
+ // continue the trace, ignoring this hit (we only care for warpzones)
+ org = trace_endpos + normalize(end - org);
+ continue;
+ // we cannot do an inverted trace here, as we do care for further warpzones inside that "solid" to be found
+ // otherwise, players could block entrances that way
+ }
break;
+ }
if(trace_ent == wz)
{
dprint("I transformed into the same zone again, wtf, aborting the trace\n");
vu = v_up;
o0 = e.origin;
v0 = e.velocity;
+
WarpZone_Trace_InitTransform();
// if starting in warpzone, first transform
wz = WarpZone_Find(e.origin + e.mins, e.origin + e.maxs);
void WarpZone_MakeAllSolid();
void WarpZone_MakeAllOther();
+#define MOVE_NOTHING -1
typedef void(vector start, vector hit, vector end) WarpZone_trace_callback_t; // called on every elementary trace
const var WarpZone_trace_callback_t WarpZone_trace_callback_t_null;
entity WarpZone_trace_transform; // transform accumulator during a trace