hook now working!
authordiv0 <div0@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Sun, 28 Feb 2010 19:44:25 +0000 (19:44 +0000)
committerdiv0 <div0@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Sun, 28 Feb 2010 19:44:25 +0000 (19:44 +0000)
git-svn-id: svn://svn.icculus.org/nexuiz/trunk@8712 f962a42d-fe04-0410-a3ab-8c8b0445ebaa

data/qcsrc/client/hook.qc
data/qcsrc/server/g_hook.qc
data/qcsrc/server/w_common.qc
data/qcsrc/warpzonelib/TODO
data/qcsrc/warpzonelib/common.qc
data/qcsrc/warpzonelib/common.qh

index e814e19..49949e5 100644 (file)
@@ -29,6 +29,14 @@ void Draw_CylindricLine(vector from, vector to, float thickness, string texture,
        R_EndPolygon();
 }
 
+string Draw_GrapplingHook_trace_callback_tex;
+float Draw_GrapplingHook_trace_callback_rnd;
+void Draw_GrapplingHook_trace_callback(vector start, vector hit, vector end)
+{
+       Draw_CylindricLine(hit, start, 8, Draw_GrapplingHook_trace_callback_tex, 0.25, Draw_GrapplingHook_trace_callback_rnd, '1 1 1', 1, DRAWFLAG_NORMAL);
+       Draw_GrapplingHook_trace_callback_rnd += 0.25 * vlen(hit - start) / 8;
+}
+
 void Draw_GrapplingHook()
 {
        vector a, b;
@@ -71,7 +79,13 @@ void Draw_GrapplingHook()
                tex = "particles/hook_green";
                rgb = '.3 1 .3';
        }
-       Draw_CylindricLine(b, a, 8, tex, 0.25, random(), '1 1 1', 1, DRAWFLAG_NORMAL);
+
+       WarpZone_trace_callback = Draw_GrapplingHook_trace_callback;
+       Draw_GrapplingHook_trace_callback_tex = tex;
+       Draw_GrapplingHook_trace_callback_rnd = random();
+       WarpZone_TraceLine(a, b, MOVE_NOMONSTERS, world);
+       WarpZone_trace_callback = func_null;
+       Draw_GrapplingHook_trace_callback_tex = string_null;
 }
 
 void Net_GrapplingHook()
index abaafe8..0d1a7de 100644 (file)
@@ -51,8 +51,9 @@ And you should be done!
 .float aiment_deadflag;
 void SetMovetypeFollow(entity ent, entity e)
 {
+       // FIXME this may not be warpzone aware
        ent.movetype = MOVETYPE_FOLLOW; // make the hole follow
-       ent.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid
+       ent.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid - this means this cannot be teleported by warpzones any more! Instead, we must notice when our owner gets teleported.
        ent.aiment = e; // make the hole follow bmodel
        ent.punchangle = e.angles; // the original angles of bmodel
        ent.view_ofs = ent.origin - e.origin; // relative origin
@@ -116,7 +117,7 @@ void GrapplingHook_Stop()
 void GrapplingHookThink()
 {
        float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
-       vector dir, org, end, v0, dv;
+       vector dir, org, end, v0, dv, v, myorg;
        if(self.owner.health <= 0 || self.owner.hook != self)   // how did that happen?
        {                                                                                                               // well, better fix it anyway
                remove(self);
@@ -127,39 +128,17 @@ void GrapplingHookThink()
                RemoveGrapplingHook(self.owner);
                return;
        }
+       if(self.aiment)
+               WarpZone_RefSys_AddIncrementally(self, self.aiment);
 
        self.nextthink = time;
 
        makevectors(self.owner.v_angle);
        org = self.owner.origin + self.owner.view_ofs + v_forward * hook_shotorigin_x + v_right * hook_shotorigin_y + v_up * hook_shotorigin_z;
-
-#if 0
-       tracebox(org, self.mins, self.maxs, self.origin, MOVE_NOMONSTERS, self.owner);
-       // do not hit players with this, as they tend to get in the way just too often
-       // NOTE: this assumes sky brushes cannot get in the way
-       // if they can, assume the map is broken! :P
-       if(trace_fraction < 1 && (!self.aiment || trace_ent != self.aiment))
-       {
-               // 0. stop it
-               if(self.state != 1)
-                       GrapplingHook_Stop();
-
-               // 1. detach the hook
-               if(self.aiment)
-                       UnsetMovetypeFollow(self);
-
-               // 2. cut it off
-               setorigin(self, trace_endpos);
-
-               // 3. reattach the hook
-               if(trace_ent)
-                       if(trace_ent.movetype != MOVETYPE_NONE)
-                               SetMovetypeFollow(self, trace_ent);
-       }
-#endif
+       myorg = WarpZone_RefSys_TransformOrigin(self.owner, self, org);
 
        if(self.hook_length < 0)
-               self.hook_length = vlen(org - self.origin);
+               self.hook_length = vlen(myorg - self.origin);
 
        if(self.state == 1)
        {
@@ -184,13 +163,13 @@ void GrapplingHookThink()
                // while hanging on the rope, this friction component will help you a
                // bit to control the rope
 
-               dir = self.origin - org;
+               dir = self.origin - myorg;
                dist = vlen(dir);
                dir = normalize(dir);
 
                if(cvar("g_grappling_hook_tarzan"))
                {
-                       v0 = self.owner.velocity;
+                       v = v0 = WarpZone_RefSys_TransformVelocity(self.owner, self, self.owner.velocity);
 
                        // first pull the rope...
                        if(self.owner.hook_state & HOOK_PULLING)
@@ -201,8 +180,8 @@ void GrapplingHookThink()
                                if(newlength < dist - ropestretch) // overstretched?
                                {
                                        newlength = dist - ropestretch;
-                                       if(self.owner.velocity * dir < 0) // only if not already moving in hook direction
-                                               self.owner.velocity = self.owner.velocity + frametime * dir * rubberforce_overstretch;
+                                       if(v * dir < 0) // only if not already moving in hook direction
+                                               v = v + frametime * dir * rubberforce_overstretch;
                                }
 
                                self.hook_length = newlength;
@@ -217,15 +196,15 @@ void GrapplingHookThink()
                        {
                                // then pull the player
                                spd = bound(0, (dist - self.hook_length) / ropestretch, 1);
-                               self.owner.velocity = self.owner.velocity * (1 - frametime * ropeairfriction);
-                               self.owner.velocity = self.owner.velocity + frametime * dir * spd * rubberforce;
+                               v = v * (1 - frametime * ropeairfriction);
+                               v = v + frametime * dir * spd * rubberforce;
 
-                               dv = ((self.owner.velocity - v0) * dir) * dir;
+                               dv = ((v - v0) * dir) * dir;
                                if(cvar("g_grappling_hook_tarzan") >= 2)
                                {
                                        if(self.aiment.movetype == MOVETYPE_WALK)
                                        {
-                                               self.owner.velocity = self.owner.velocity - dv * 0.5;
+                                               v = v - dv * 0.5;
                                                self.aiment.velocity = self.aiment.velocity - dv * 0.5;
                                                self.aiment.flags &~= FL_ONGROUND;
                                                self.aiment.pusher = self.owner;
@@ -235,11 +214,13 @@ void GrapplingHookThink()
 
                                self.owner.flags &~= FL_ONGROUND;
                        }
+
+                       self.owner.velocity = WarpZone_RefSys_TransformVelocity(self, self.owner, v);
                }
                else
                {
                        end = self.origin - dir*50;
-                       dist = vlen(end - org);
+                       dist = vlen(end - myorg);
                        if(dist < 200)
                                spd = dist * (pullspeed / 200);
                        else
@@ -254,7 +235,7 @@ void GrapplingHookThink()
        }
 
        makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0');
-       te_beam(self.owner, self.origin + v_forward * (-9), org);
+       te_beam(self.owner, WarpZone_RefSys_TransformOrigin(self, self.owner, self.origin) + v_forward * (-9), org);
 }
 
 void GrapplingHookTouch (void)
@@ -266,30 +247,16 @@ void GrapplingHookTouch (void)
                RemoveGrapplingHook(self.owner);
                return;
        }
-
-       if(other == world)
-       {
-               vector tic;
-               tic = self.velocity * sys_frametime;
-               tic = tic + normalize(tic) * vlen(self.maxs - self.mins);
-               traceline(self.origin - tic, self.origin + tic, MOVE_NORMAL, self);
-               if(trace_fraction >= 1)
-               {
-                       dprint("Odd... did not hit...?\n");
-               }
-               else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-               {
-                       dprint("Detected and prevented the sky-grapple bug.\n");
-                       RemoveGrapplingHook(self.owner);
-                       return;
-               }
-       }
+       PROJECTILE_TOUCH;
 
        GrapplingHook_Stop();
 
        if(other)
                if(other.movetype != MOVETYPE_NONE)
+               {
                        SetMovetypeFollow(self, other);
+                       WarpZone_RefSys_BeginAddingIncrementally(self, self.aiment);
+               }
 
        //self.owner.disableclientprediction = TRUE;
 }
@@ -326,7 +293,7 @@ void FireGrapplingHook (void)
        org = self.origin + self.view_ofs + v_forward * hook_shotorigin_x + v_right * hook_shotorigin_y + v_up * hook_shotorigin_z;
        pointparticles(particleeffectnum("grapple_muzzleflash"), org, '0 0 0', 1);
 
-       missile = spawn ();
+       missile = WarpZone_RefSys_SpawnSameRefSys(self);
        missile.owner = self;
        self.hook = missile;
        missile.classname = "grapplinghook";
index cfd04d9..f79d02f 100644 (file)
@@ -324,7 +324,7 @@ void endFireBallisticBullet()
 
 entity fireBallisticBullet_trace_callback_ent;
 float fireBallisticBullet_trace_callback_eff;
-void fireBallisticBullet_trace_callback()
+void fireBallisticBullet_trace_callback(vector start, vector hit, vector end)
 {
        if(vlen(trace_endpos - fireBallisticBullet_trace_callback_ent.origin) > 16)
                zcurveparticles_from_tracetoss(fireBallisticBullet_trace_callback_eff, fireBallisticBullet_trace_callback_ent.origin, trace_endpos, fireBallisticBullet_trace_callback_ent.velocity);
index 2e6dbeb..8c5c4a5 100644 (file)
@@ -17,6 +17,6 @@ Weapon support:
 - minstanex: YES
 - rifle: YES
 - fireball: YES (BFG effect cannot work through warpzones by design, so it's not available through warpzones)
+- hook: YES
 
-- hook: NO (hook beam, pull not working)
 - tuba: NO (sound)
index ccdde98..6854385 100644 (file)
@@ -108,7 +108,7 @@ void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomon
        {
                tracebox(org, mi, ma, end, nomonsters, forent);
                if(WarpZone_trace_callback)
-                       WarpZone_trace_callback();
+                       WarpZone_trace_callback(org, trace_endpos, end);
                if(sol < 0)
                        sol = trace_startsolid;
                if(trace_fraction >= 1)
@@ -156,7 +156,7 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end,
        {
                tracebox(org, mi, ma, end, nomonsters, forent);
                if(WarpZone_trace_callback)
-                       WarpZone_trace_callback();
+                       WarpZone_trace_callback(org, trace_endpos, end);
                if(sol < 0)
                        sol = trace_startsolid;
                if(trace_fraction >= 1)
@@ -208,7 +208,7 @@ void WarpZone_TraceToss(entity e, entity forent)
        {
                tracetoss(e, forent);
                if(WarpZone_trace_callback)
-                       WarpZone_trace_callback();
+                       WarpZone_trace_callback(e.origin, trace_endpos, trace_endpos);
                e.origin = trace_endpos;
                dt = vlen(e.origin - o0) / vlen(e.velocity);
                WarpZone_tracetoss_time += dt;
@@ -430,6 +430,14 @@ void WarpZone_Accumulator_Clear(entity acc)
        acc.warpzone_transform = '0 0 0';
        acc.warpzone_shift = '0 0 0';
 }
+void WarpZone_Accumulator_AddTransform(entity acc, vector t, vector s)
+{
+       vector t, st;
+       t = AnglesTransform_Multiply(t, acc.warpzone_transform);
+       st = AnglesTransform_Multiply_GetPostShift(t, s, acc.warpzone_transform, acc.warpzone_shift);
+       acc.warpzone_transform = t;
+       acc.warpzone_shift = st;
+}
 void WarpZone_Accumulator_Add(entity acc, entity wz)
 {
        vector t, st;
@@ -461,6 +469,35 @@ void WarpZone_RefSys_Add(entity me, entity wz)
        if(wz)
                WarpZone_Accumulator_Add(me.WarpZone_refsys, wz);
 }
+.vector WarpZone_refsys_incremental_shift;
+.vector WarpZone_refsys_incremental_transform;
+void WarpZone_RefSys_AddIncrementally(entity me, entity ref)
+{
+       vector t, s;
+       if(me.WarpZone_refsys_incremental_transform == ref.WarpZone_refsys.warpzone_transform)
+       if(me.WarpZone_refsys_incremental_shift == ref.WarpZone_refsys.warpzone_shift)
+               return;
+       if(me.WarpZone_refsys.owner != me)
+       {
+               me.WarpZone_refsys = spawn();
+               me.WarpZone_refsys.classname = "warpzone_refsys";
+               me.WarpZone_refsys.owner = me;
+               me.WarpZone_refsys.think = WarpZone_RefSys_GC;
+               me.WarpZone_refsys.nextthink = time + 1;
+               WarpZone_Accumulator_Clear(me.WarpZone_refsys);
+       }
+       t = AnglesTransform_Invert(me.WarpZone_refsys_incremental_transform);
+       s = AnglesTransform_PrePostShift_GetPostShift(me.WarpZone_refsys_incremental_shift, t, '0 0 0');
+       WarpZone_Accumulator_AddTransform(me.WarpZone_refsys, t, s);
+       WarpZone_Accumulator_Add(me.WarpZone_refsys, ref);
+       me.WarpZone_refsys_incremental_shift = ref.WarpZone_refsys.warpzone_shift;
+       me.WarpZone_refsys_incremental_transform = ref.WarpZone_refsys.warpzone_transform;
+}
+void WarpZone_RefSys_BeginAddingIncrementally(entity me, entity ref)
+{
+       me.WarpZone_refsys_incremental_shift = ref.WarpZone_refsys.warpzone_shift;
+       me.WarpZone_refsys_incremental_transform = ref.WarpZone_refsys.warpzone_transform;
+}
 vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
 {
        if(from.WarpZone_refsys)
@@ -498,6 +535,14 @@ entity WarpZone_RefSys_SpawnSameRefSys(entity me)
        entity e;
        e = spawn();
        if(me.WarpZone_refsys)
-               WarpZone_RefSys_Add(e, me.WarpZone_refsys);
+       {
+               e.WarpZone_refsys = spawn();
+               e.WarpZone_refsys.classname = "warpzone_refsys";
+               e.WarpZone_refsys.owner = e;
+               e.WarpZone_refsys.think = WarpZone_RefSys_GC;
+               e.WarpZone_refsys.nextthink = time + 1;
+               e.WarpZone_refsys.warpzone_shift = me.WarpZone_refsys.warpzone_shift;
+               e.WarpZone_refsys.warpzone_transform = me.WarpZone_refsys.warpzone_transform;
+       }
        return e;
 }
index 3d984d2..ad351c2 100644 (file)
@@ -17,7 +17,8 @@ entity WarpZone_Find(vector mi, vector ma);
 void WarpZone_MakeAllSolid();
 void WarpZone_MakeAllOther();
 
-var void(void) WarpZone_trace_callback; // called after every trace
+var void(vector start, vector hit, vector end) WarpZone_trace_callback; // called after every trace
+vector WarpZone_trace_startpos; // start pos of the current segment (useful for the callback)
 vector WarpZone_trace_angles; // total angles accumulator
 vector WarpZone_trace_v_angle; // total v_angle accumulator
 vector WarpZone_trace_velocity; // total velocity
@@ -50,6 +51,8 @@ vector WarpZone_UnTransformVAngles(entity wz, vector v);
 
 // reference systems (chained warpzone transforms)
 void WarpZone_RefSys_Add(entity me, entity wz);
+void WarpZone_RefSys_AddIncrementally(entity me, entity ref);
+void WarpZone_RefSys_BeginAddingIncrementally(entity me, entity ref);
 vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org);
 vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel);
 vector WarpZone_RefSys_TransformAngles(entity from, entity to, vector ang);