findradius wrapper - more guns work now
authordiv0 <div0@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Sun, 28 Feb 2010 19:43:54 +0000 (19:43 +0000)
committerdiv0 <div0@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Sun, 28 Feb 2010 19:43:54 +0000 (19:43 +0000)
git-svn-id: svn://svn.icculus.org/nexuiz/trunk@8706 f962a42d-fe04-0410-a3ab-8c8b0445ebaa

data/qcsrc/server/g_damage.qc
data/qcsrc/warpzonelib/TODO
data/qcsrc/warpzonelib/common.qc
data/qcsrc/warpzonelib/common.qh

index e4779dd..4b02534 100644 (file)
@@ -1084,7 +1084,7 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e
        stat_damagedone = 0;
        stat_maxdamage = 0;
 
-       targ = findradius (blastorigin, rad);
+       targ = WarpZone_FindRadius (blastorigin, rad, FALSE);
        while (targ)
        {
                next = targ.chain;
@@ -1093,8 +1093,8 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e
                        {
                                // LordHavoc: measure distance to nearest point on target (not origin)
                                // (this guarentees 100% damage on a touch impact)
-                               nearest = NearestPointOnBox(targ, blastorigin);
-                               diff = nearest - blastorigin;
+                               nearest = targ.WarpZone_findradius_nearest;
+                               diff = targ.WarpZone_findradius_dist;
                                // round up a little on the damage to ensure full damage on impacts
                                // and turn the distance into a fraction of the radius
                                power = 1 - ((vlen (diff) - 2) / rad);
@@ -1115,11 +1115,13 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e
                                                local float total;
                                                local float hitratio;
                                                local vector hitloc;
+                                               local vector myblastorigin;
+                                               myblastorigin = WarpZone_UnTransformOrigin(targ, blastorigin);
                                                center = targ.origin + (targ.mins + targ.maxs) * 0.5;
                                                // if it's a player, use the view origin as reference
                                                if (targ.classname == "player")
                                                        center = targ.origin + targ.view_ofs;
-                                               force = normalize(center - blastorigin);
+                                               force = normalize(center - myblastorigin);
                                                force = force * (finaldmg / coredamage) * forceintensity;
                                                // test line of sight to multiple positions on box,
                                                // and do damage if any of them hit
@@ -1132,7 +1134,8 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e
                                                c = 0;
                                                while (c < total)
                                                {
-                                                       traceline(blastorigin, nearest, MOVE_NOMONSTERS, inflictor);
+                                                       //traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor);
+                                                       WarpZone_TraceLine(blastorigin, WarpZone_TransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor);
                                                        if (trace_fraction == 1 || trace_ent == targ)
                                                        {
                                                                hits = hits + 1;
index cd10ee7..7d1e386 100644 (file)
@@ -6,21 +6,21 @@ Open issues:
 
 Weapon support:
 
+- laser: YES
 - shotgun: YES
 - uzi: YES
+- grenadelauncher: YES
+- crylink: YES
 - nex: YES
+- hagar: YES
 - porto: YES (bwahahahaha)
+- hlac: YES
 - minstanex: YES
 - rifle: YES
-- crylink: YES
 
-- laser: PARTIAL (no radius damage)
-- grenadelauncher: PARTIAL (no radius damage)
-- electro: PARTIAL (no radius damage)
-- hagar: PARTIAL (no radius damage)
-- hlac: PARTIAL (no radius damage)
+- electro: PARTIAL (no combo detonation)
 - fireball: PARTIAL (no radius damage, laser damage)
 
 - rocketlauncher: NO (guiding not working, trail bug)
-- hook: NO (no radius damage, hook beam, pull not working)
-- tuba: NO (no radius damage, sound)
+- hook: NO (hook beam, pull not working)
+- tuba: NO (sound)
index c2ad3cc..13587ed 100644 (file)
@@ -94,6 +94,7 @@ void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomon
 {
        float frac, sol;
        vector o0, e0;
+       entity e;
        vector vf, vr, vu;
        vf = v_forward;
        vr = v_right;
@@ -103,6 +104,7 @@ void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomon
        e0 = end;
        sol = -1;
        frac = 0;
+       e = world;
        for(;;)
        {
                tracebox(org, mi, ma, end, nomonsters, forent);
@@ -121,6 +123,12 @@ void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomon
                WarpZone_trace_velocity = WarpZone_TransformVelocity(trace_ent, WarpZone_trace_velocity);
                WarpZone_trace_angles = WarpZone_TransformAngles(trace_ent, WarpZone_trace_angles);
                WarpZone_trace_v_angle = WarpZone_TransformVAngles(trace_ent, WarpZone_trace_v_angle);
+               if(trace_ent == e)
+               {
+                       dprint("I transformed into the same zone again, wtf, aborting the trace\n");
+                       break;
+               }
+               e = trace_ent;
        }
        WarpZone_MakeAllOther();
        trace_startsolid = sol;
@@ -215,7 +223,7 @@ float WarpZone_TargetPlaneDist(entity wz, vector v)
 
 vector WarpZone_TransformOrigin(entity wz, vector v)
 {
-       return wz.enemy.warpzone_origin + AnglesTransform_Apply(wz.warpzone_transform, v - wz.warpzone_origin);
+       return wz.warpzone_targetorigin + AnglesTransform_Apply(wz.warpzone_transform, v - wz.warpzone_origin);
 }
 
 vector WarpZone_TransformVelocity(entity wz, vector v)
@@ -242,3 +250,120 @@ vector WarpZone_TransformVAngles(entity wz, vector ang)
        ang_z = roll;
        return ang;
 }
+
+vector WarpZone_UnTransformOrigin(entity wz, vector v)
+{
+       return wz.warpzone_origin + AnglesTransform_Apply(AnglesTransform_Invert(wz.warpzone_transform), v - wz.warpzone_targetorigin);
+}
+
+vector WarpZone_UnTransformVelocity(entity wz, vector v)
+{
+       return AnglesTransform_Apply(AnglesTransform_Invert(wz.warpzone_transform), v);
+}
+
+vector WarpZone_UnTransformAngles(entity wz, vector v)
+{
+       return AnglesTransform_ApplyToAngles(AnglesTransform_Invert(wz.warpzone_transform), v);
+}
+
+vector WarpZone_UnTransformVAngles(entity wz, vector ang)
+{
+       float roll;
+
+       roll = ang_z;
+       ang_z = 0;
+
+       ang = AnglesTransform_ApplyToVAngles(AnglesTransform_Invert(wz.warpzone_transform), ang);
+       ang = AnglesTransform_Normalize(ang, TRUE);
+       ang = AnglesTransform_CancelRoll(ang);
+
+       ang_z = roll;
+       return ang;
+}
+
+vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org)
+{
+       vector nearest;
+       nearest_x = bound(mi_x, org_x, ma_x);
+       nearest_y = bound(mi_y, org_y, ma_y);
+       nearest_z = bound(mi_z, org_z, ma_z);
+       return nearest;
+}
+
+.float WarpZone_findradius_hit;
+.entity WarpZone_findradius_next;
+void WarpZone_FindRadius_Recurse(vector org, float rad,        vector org0,            vector shift0, vector transform, vector shift1, float needlineofsight)
+//                               blast origin of current search   original blast origin   how to untransform (victim to blast system)
+{
+       vector org_new;
+       vector org0_new;
+       vector shift0_new, transform_new, shift1_new;
+       vector p;
+       entity e, e0;
+       entity wz;
+       if(rad <= 0)
+               return;
+       e0 = findradius(org, rad);
+       wz = world;
+
+       for(e = e0; e; e = e.chain)
+       {
+               p = WarpZoneLib_NearestPointOnBox(e.origin + e.mins, e.origin + e.maxs, org0);
+               if(needlineofsight)
+               {
+                       traceline(org, p, MOVE_NOMONSTERS, e);
+                       if(trace_fraction < 1)
+                               continue;
+               }
+               if(!e.WarpZone_findradius_hit || vlen(e.WarpZone_findradius_dist) > vlen(org0 - p))
+               {
+                       e.WarpZone_findradius_nearest = p;
+                       e.WarpZone_findradius_dist = org0 - p;
+                       e.WarpZone_findradius_findorigin = org;
+                       e.WarpZone_findradius_findradius = rad;
+                       if(e.classname == "trigger_warpzone")
+                       {
+                               e.WarpZone_findradius_next = wz;
+                               wz = e;
+
+                               e.WarpZone_findradius_hit = 1;
+                               e.enemy.WarpZone_findradius_dist = '0 0 0'; // we don't want to go through this zone ever again
+                               e.enemy.WarpZone_findradius_hit = 1;
+                       }
+                       else
+                       {
+                               e.warpzone_transform = transform;
+                               e.warpzone_origin = shift0;
+                               e.warpzone_targetorigin = shift1;
+
+                               e.WarpZone_findradius_hit = 1;
+                       }
+               }
+       }
+       for(e = wz; e; e = e.WarpZone_findradius_next)
+       {
+               org0_new = WarpZone_TransformOrigin(e, org);
+               traceline(e.warpzone_targetorigin, org0_new, MOVE_NOMONSTERS, e);
+               org_new = trace_endpos;
+               transform_new = AnglesTransform_Multiply(transform, AnglesTransform_Invert(e.warpzone_transform));
+               shift0_new = e.warpzone_targetorigin;
+               shift1_new = AnglesTransform_Apply(transform, e.warpzone_origin - shift0) + shift1;
+               WarpZone_FindRadius_Recurse(
+                       org_new,
+                       bound(0, rad - vlen(org_new - org0_new), rad - 8),
+                       org0_new,
+                       shift0_new, transform_new, shift1_new,
+                       needlineofsight);
+               e.WarpZone_findradius_hit = 0;
+               e.enemy.WarpZone_findradius_hit = 0;
+       }
+}
+entity WarpZone_FindRadius(vector org, float rad, float needlineofsight)
+{
+       entity e0, e;
+       WarpZone_FindRadius_Recurse(org, rad, org, '0 0 0', '0 0 0', '0 0 0', needlineofsight);
+       e0 = findchainfloat(WarpZone_findradius_hit, 1);
+       for(e = e0; e; e = e.chain)
+               e.WarpZone_findradius_hit = 0;
+       return e0;
+}
index 0f46b1d..53e1871 100644 (file)
@@ -10,6 +10,7 @@ void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, ve
 float FL_CAMERA = 8192;
 
 float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig);
+vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org);
 
 entity WarpZone_Find(vector mi, vector ma);
 void WarpZone_MakeAllSolid();
@@ -27,9 +28,20 @@ void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
 void WarpZone_TraceToss(entity e, entity forent);
 void WarpZone_TrailParticles(entity own, float eff, vector org, vector end);
 
+.vector WarpZone_findradius_dist;
+.vector WarpZone_findradius_nearest;
+// also set: warpzone parameters, so WarpZone_TransformOrigin can transform vectors from victim's to blast's system
+.vector WarpZone_findradius_findorigin;
+.float WarpZone_findradius_findradius;
+entity WarpZone_FindRadius(vector org, float radius, float needlineofsight);
+
 float WarpZone_PlaneDist(entity wz, vector v);
 float WarpZone_TargetPlaneDist(entity wz, vector v);
 vector WarpZone_TransformOrigin(entity wz, vector v);
 vector WarpZone_TransformVelocity(entity wz, vector v);
 vector WarpZone_TransformAngles(entity wz, vector v);
 vector WarpZone_TransformVAngles(entity wz, vector v);
+vector WarpZone_UnTransformOrigin(entity wz, vector v);
+vector WarpZone_UnTransformVelocity(entity wz, vector v);
+vector WarpZone_UnTransformAngles(entity wz, vector v);
+vector WarpZone_UnTransformVAngles(entity wz, vector v);