]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge remote-tracking branch 'origin/master' into tzork/csqc-items
authorJakob MG <jakob_mg@hotmail.com>
Fri, 1 Jun 2012 20:10:43 +0000 (22:10 +0200)
committerJakob MG <jakob_mg@hotmail.com>
Fri, 1 Jun 2012 20:10:43 +0000 (22:10 +0200)
19 files changed:
balance25.cfg
balanceFruitieX.cfg
balanceXPM.cfg
balanceXonotic.cfg
defaultXonotic.cfg
effectinfo.txt
gfx/vehicles/vth-mover.tga [new file with mode: 0644]
gfx/vehicles/vth-stationary.tga [new file with mode: 0644]
qcsrc/client/autocvars.qh
qcsrc/client/tturrets.qc
qcsrc/client/vehicles/vehicles.qc
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/server/autocvars.qh
qcsrc/server/command/radarmap.qc
qcsrc/server/g_damage.qc
qcsrc/server/g_subs.qc
qcsrc/server/mutators/mutator_dodging.qc
qcsrc/server/w_common.qc

index bea9ad263a3243ef5904d70fe8de2eca52047a3b..aafb163b441941ea73ad9a0ba736837fcc0bc25f 100644 (file)
@@ -162,6 +162,7 @@ set g_projectiles_damage 2
 // 0: only damage from contents (lava/slime) or exceptions 
 // 1: only self damage or damage from contents or exceptions
 // 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
 set g_projectiles_newton_style 2
 // possible values:
 // 0: absolute velocity projectiles (like Quake)
index 16286fe0f8b85eb63c3529617bef7dc2cb259a74..1bb8989120df04a0f5f3b7864c66c23ab0df2f57 100644 (file)
@@ -162,6 +162,7 @@ set g_projectiles_damage 2
 // 0: only damage from contents (lava/slime) or exceptions 
 // 1: only self damage or damage from contents or exceptions
 // 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
 set g_projectiles_newton_style 2
 // possible values:
 // 0: absolute velocity projectiles (like Quake)
index d3478a969f292339c212b96bc934eb284e9adc2e..759551d8d2357a4a2e53f7f1125d229659802fe7 100644 (file)
@@ -162,6 +162,7 @@ set g_projectiles_damage 1
 // 0: only damage from contents (lava/slime) or exceptions 
 // 1: only self damage or damage from contents or exceptions
 // 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
 set g_projectiles_newton_style 0
 // possible values:
 // 0: absolute velocity projectiles (like Quake)
index b7dbd3db8ceb72ecd803766d758db460b7b4c1bd..52c8a74d84cecfe381db5adbb156bc778f7da233 100644 (file)
@@ -162,6 +162,7 @@ set g_projectiles_damage 2
 // 0: only damage from contents (lava/slime) or exceptions 
 // 1: only self damage or damage from contents or exceptions
 // 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
 set g_projectiles_newton_style 2
 // possible values:
 // 0: absolute velocity projectiles (like Quake)
index 23588aff19c077679f56aa8de2cbcbac8c323a15..e2645a0a88bf3fa3ea4afa1f5ea79b7c1090e998 100644 (file)
@@ -1645,6 +1645,9 @@ seta cl_casings_maxcount 100 "maximum amount of shell casings (must be at least
 seta cl_gibs_maxcount 100 "maximum amount of gibs (must be at least 1)"
 seta cl_vehicle_spiderbot_cross_alpha 0.6
 seta cl_vehicle_spiderbot_cross_size 1
+seta cl_vehicles_hudscale 0.5 
+seta cl_vehicles_hudalpha 0.75
+seta cl_vehicles_hud_tactical 1
 
 //cl_gunalign calculator
 seta menu_cl_gunalign 3 "Gun alignment; 1 = center (if allowed by g_shootfromclient) or right, 2 = center (if allowed by g_shootfromclient) or left, 3 = right only, 4 = left only"
index 05c249b976d02cb746dbaa95451bd6c6f16fe9ba..5e06d075e6bf292b1c41e3889b90412272a78dd0 100644 (file)
@@ -7409,4 +7409,4 @@ velocityjitter 64 64 64
 //lightradius 50
 //lightradiusfade 50
 //lightcolor 1 0.9 0.7
-//lightshadow 1
\ No newline at end of file
+//lightshadow 1
diff --git a/gfx/vehicles/vth-mover.tga b/gfx/vehicles/vth-mover.tga
new file mode 100644 (file)
index 0000000..d831896
Binary files /dev/null and b/gfx/vehicles/vth-mover.tga differ
diff --git a/gfx/vehicles/vth-stationary.tga b/gfx/vehicles/vth-stationary.tga
new file mode 100644 (file)
index 0000000..31703bc
Binary files /dev/null and b/gfx/vehicles/vth-stationary.tga differ
index 344c3731c4561f1932d123df8a2032bc9f139934..1e938c26ae3d95c12b9056b484edde0c87fbee82 100644 (file)
@@ -67,6 +67,7 @@ float autocvar_cl_reticle_stretch;
 float autocvar_cl_stripcolorcodes;
 var float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
 var float autocvar_cl_vehicle_spiderbot_cross_size = 1;
+var float autocvar_cl_vehicles_hud_tactical = 1;
 float autocvar_cl_velocityzoom;
 var float autocvar_cl_velocityzoom_type = 3;
 float autocvar_cl_velocityzoom_speed;
index 2b9ec0297b2ef63411d210cc8a8597bc8438691f..d7abeb0919de42e95d278942f363cb9009336b96 100644 (file)
@@ -235,36 +235,46 @@ void turret_draw2d()
         return; 
 
        float dist = vlen(self.origin - view_origin);
+    float t = (GetPlayerColor(player_localnum) + 1);   
+
        vector o;
-       /*
-       // TODO: Vehicle tactical hud
-       o = project_3d_to_2d(self.origin + '0 0 32');
-       if(o_z < 0 
-       || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) 
-       || o_y < (vid_conheight * waypointsprite_edgeoffset_top) 
-       || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))  
-       || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
-           return; // Dont draw wp's for turrets out of view
-    o_z = 0;
-    if(hud != HUD_NORMAL)
-    {        
-        switch(hud)
-        {
-            case HUD_SPIDERBOT:
-            case HUD_WAKIZASHI:
-            case HUD_RAPTOR:
-                vector pz = drawgetimagesize("gfx/vehicles/axh-bracket.tga") * 0.25;
-                drawpic(o - pz * 0.5 , "gfx/vehicles/axh-bracket.tga", pz , '1 1 1', 0.75, DRAWFLAG_NORMAL);
-                break;
+       string txt;
+       
+       if(autocvar_cl_vehicles_hud_tactical)
+       if(dist < 10240 && t != self.team)
+       {
+        // TODO: Vehicle tactical hud
+        o = project_3d_to_2d(self.origin + '0 0 32');
+        if(o_z < 0 
+        || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) 
+        || o_y < (vid_conheight * waypointsprite_edgeoffset_top) 
+        || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))  
+        || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
+            return; // Dont draw wp's for turrets out of view
+        o_z = 0;
+        if(hud != HUD_NORMAL)
+        {        
+            switch(hud)
+            {
+                case HUD_SPIDERBOT:
+                case HUD_WAKIZASHI:
+                case HUD_RAPTOR:
+                    if(self.turret_type == TID_EWHEEL || self.turret_type == TID_WALKER)
+                        txt = "gfx/vehicles/vth-mover.tga";
+                    else
+                        txt = "gfx/vehicles/vth-stationary.tga";
+                        
+                    vector pz = drawgetimagesize(txt) * 0.25;
+                    drawpic(o - pz * 0.5, txt, pz , '1 1 1', 0.75, DRAWFLAG_NORMAL);
+                    break;
+            }
         }
-    }
-    */
+       }
     
        if(dist > self.maxdistance)
         return;
 
        string spriteimage = self.netname;
-       float t = (GetPlayerColor(player_localnum) + 1);        
        float a = self.alpha * autocvar_hud_panel_fg_alpha;
        vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
 
@@ -280,7 +290,7 @@ void turret_draw2d()
                print(sprintf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage)); 
        }
 
-       string txt = self.netname;
+       txt = self.netname;
        if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
                txt = _("Spam");
        else
@@ -540,37 +550,38 @@ entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, flo
 
 void turret_die()
 {    
-    entity headgib;
     
     sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
     pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
     turret_tid2info(self.turret_type);
-    
-    // Base
-    if(self.turret_type == TID_EWHEEL)
-        turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', TRUE);
-    else if (self.turret_type == TID_WALKER)
-        turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', TRUE);
-    else if (self.turret_type == TID_TESLA)
-        turret_gibtoss(tid2info_base, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', FALSE);
-    else
-    {        
-        if (random() > 0.5)
-        {            
-            turret_gibtoss("models/turrets/base-gib2.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
-            turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
-            turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
-        }
+    if (!autocvar_cl_nogibs)
+    {
+        // Base
+        if(self.turret_type == TID_EWHEEL)
+            turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', TRUE);
+        else if (self.turret_type == TID_WALKER)
+            turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', TRUE);
+        else if (self.turret_type == TID_TESLA)
+            turret_gibtoss(tid2info_base, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', FALSE);
         else
-            turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', TRUE);
-
-        headgib = turret_gibtoss(tid2info_head, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', TRUE);
-        if(headgib)
-        {
-            headgib.angles = headgib.move_angles = self.tur_head.angles;
-            headgib.avelocity = headgib.move_avelocity = self.tur_head.move_avelocity + randomvec() * 45;
-            headgib.avelocity_y = headgib.move_avelocity_y = headgib.move_avelocity_y * 5;
-            headgib.gravity = 0.5;        
+        {        
+            if (random() > 0.5)
+            {            
+                turret_gibtoss("models/turrets/base-gib2.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
+                turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
+                turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
+            }
+            else
+                turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', TRUE);
+
+            entity headgib = turret_gibtoss(tid2info_head, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', TRUE);
+            if(headgib)
+            {
+                headgib.angles = headgib.move_angles = self.tur_head.angles;
+                headgib.avelocity = headgib.move_avelocity = self.tur_head.move_avelocity + randomvec() * 45;
+                headgib.avelocity_y = headgib.move_avelocity_y = headgib.move_avelocity_y * 5;
+                headgib.gravity = 0.5;        
+            }
         }
     }
     
index ccb9cff58363374f82761aa58899984b800b86f8..6081f5a66efdd6ea1e23d947adeb1f3c0a953609 100644 (file)
@@ -661,11 +661,13 @@ void CSQC_WAKIZASHI_HUD()
 void Vehicles_Precache()
 {
 // fixme: HAAAAKKKZZZ!!!!!!!!!!!! (this belongs as a setting in default.cfg)
-    autocvar_cl_vehicles_hudscale = 0.5;
-    autocvar_cl_vehicles_hudalpha = 0.75;
-
+    if(!autocvar_cl_vehicles_hudscale )
+        autocvar_cl_vehicles_hudscale = 0.5;
+    
+    if(!autocvar_cl_vehicles_hudalpha)
+        autocvar_cl_vehicles_hudalpha = 0.75;
 
-       precache_model("models/vehicles/wakizashi.dpm");
+       //precache_model("models/vehicles/wakizashi.dpm");
 
        precache_model("models/vehicles/bomblet.md3");
        precache_model("models/vehicles/clusterbomb.md3");
index b973850cc9f23393062a1b60a781e6ead3052d3f..6e534ffc19464a92777b956353b926f48ddd578e 100644 (file)
@@ -2364,3 +2364,55 @@ void queue_to_execute_next_frame(string s)
        }
        to_execute_next_frame = strzone(s);
 }
+
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
+{
+       return
+               (((     startspeedfactor + endspeedfactor - 2
+               ) * x - 2 * startspeedfactor - endspeedfactor + 3
+               ) * x + startspeedfactor
+               ) * x;
+}
+
+float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
+{
+       if(startspeedfactor < 0 || endspeedfactor < 0)
+               return FALSE;
+
+       /*
+       // if this is the case, the possible zeros of the first derivative are outside
+       // 0..1
+       We can calculate this condition as condition 
+       if(se <= 3)
+               return TRUE;
+       */
+
+       // better, see below:
+       if(startspeedfactor <= 3 && endspeedfactor <= 3)
+               return TRUE;
+
+       // if this is the case, the first derivative has no zeros at all
+       float se = startspeedfactor + endspeedfactor;
+       float s_e = startspeedfactor - endspeedfactor;
+       if(3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
+               return TRUE;
+
+       // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
+       // we also get s_e <= 6 - se
+       // 3 * (se - 4)^2 + (6 - se)^2
+       // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
+       // Therefore, above "better" check works!
+
+       return FALSE;
+
+       // known good cases:
+       // (0, [0..3])
+       // (0.5, [0..3.8])
+       // (1, [0..4])
+       // (1.5, [0..3.9])
+       // (2, [0..3.7])
+       // (2.5, [0..3.4])
+       // (3, [0..3])
+       // (3.5, [0.2..2.3])
+       // (4, 1)
+}
index c409de3544578c00acc39b6b4e0c2248fabe65f3..3ce173bf638e95d705a70042fc6bfae62f4838aa 100644 (file)
@@ -320,3 +320,17 @@ void queue_to_execute_next_frame(string s);
 
 // for marking written-to values as unused where it's a good idea to do this
 noref float unused_float;
+
+
+
+// a function f with:
+// f(0) = 0
+// f(1) = 1
+// f'(0) = startspeedfactor
+// f'(1) = endspeedfactor
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x);
+
+// checks whether f'(x) = 0 anywhere from 0 to 1
+// because if this is the case, the function is not usable for platforms
+// as it may exceed 0..1 bounds, or go in reverse
+float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor);
index 0cfdec53c9f6349bd1c99a166adc88396fdfa910..c75a4387339f58f429cecf8b6d31acb2292652d6 100644 (file)
@@ -927,6 +927,7 @@ float autocvar_g_playerclip_collisions;
 string autocvar_g_playerstats_uri;
 float autocvar_g_powerups;
 float autocvar_g_projectiles_damage;
+float autocvar_g_projectiles_keep_owner;
 float autocvar_g_projectiles_newton_style;
 float autocvar_g_projectiles_newton_style_2_maxfactor;
 float autocvar_g_projectiles_newton_style_2_minfactor;
index 16f3212eda0cc1852569ac0de61a11d67b1ff470..d8651762965d9d6859dbc05ed205b5ee0407d8dc 100644 (file)
@@ -28,7 +28,7 @@ float FullTraceFraction(vector a, vector mi, vector ma, vector b)
                        c = trace_endpos;
                }
 
-               n += tracebox_inverted(c, mi, ma, b, MOVE_WORLDONLY, world);
+               n += tracebox_inverted(c, mi, ma, b, MOVE_WORLDONLY, world, FALSE);
 
                white += vlen(trace_endpos - c);
                c = trace_endpos;
@@ -424,4 +424,4 @@ float RadarMap_Make(float argc)
        }
        
        return FALSE;
-}
\ No newline at end of file
+}
index a49aad27bdc401027a66ca15a1e181140cf765c4..ac7c3cd2a7ceb637b4a69d5f2529a110a454a456 100644 (file)
@@ -1269,43 +1269,59 @@ float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
 
                if(maxtime > mintime || maxdps > mindps)
                {
+                       // Constraints:
+                       
+                       // damage we have right now
                        mindamage = mindps * mintime;
-                       maxdamage = mindamage + d;
-
-                       // interval [mintime, maxtime] * [mindps, maxdps]
-                       // intersected with
-                       // [mindamage, maxdamage]
-                       // maximum of this!
-
-                       if(maxdamage >= maxtime * maxdps)
-                       {
-                               totaltime = maxtime;
-                               totaldamage = maxtime * maxdps;
 
-                               // this branch increases totaldamage if either t > mintime, or dps > mindps
-                       }
-                       else
-                       {
-                               // maxdamage is inside the interval!
-                               // first, try to use mindps; only if this fails, increase dps as needed
-                               totaltime = min(maxdamage / mindps, maxtime); // maxdamage / mindps >= mindamage / mindps = mintime
-                               totaldamage = maxdamage;
-                               // can totaldamage / totaltime be >= maxdps?
-                               // max(mindps, maxdamage / maxtime) >= maxdps?
-                               // we know maxdamage < maxtime * maxdps
-                               // so it cannot be
-
-                               // this branch ALWAYS increases totaldamage, but requires maxdamage < maxtime * maxdps
-                       }
+                       // damage we want to get
+                       maxdamage = mindamage + d;
 
-                       // total conditions for increasing:
-                       //     maxtime > mintime OR maxdps > mindps OR maxtime * maxdps > maxdamage
-                       // however:
-                       //     if maxtime = mintime, maxdps = mindps
-                       // then:
-                       //     maxdamage = mindamage + d
-                       //     mindamage = mindps * mintime = maxdps * maxtime < maxdamage!
-                       // so the last condition is not needed
+                       // but we can't exceed maxtime * maxdps!
+                       totaldamage = min(maxdamage, maxtime * maxdps);
+
+                       // LEMMA:
+                       // Look at:
+                       // totaldamage = min(mindamage + d, maxtime * maxdps)
+                       // We see:
+                       // totaldamage <= maxtime * maxdps
+                       // ==> totaldamage / maxdps <= maxtime.
+                       // We also see:
+                       // totaldamage / mindps = min(mindamage / mindps + d, maxtime * maxdps / mindps)
+                       //                     >= min(mintime, maxtime)
+                       // ==> totaldamage / maxdps >= mintime.
+
+                       /*
+                       // how long do we damage then?
+                       // at least as long as before
+                       // but, never exceed maxdps
+                       totaltime = max(mintime, totaldamage / maxdps); // always <= maxtime due to lemma
+                       */
+
+                       // alternate:
+                       // at most as long as maximum allowed
+                       // but, never below mindps
+                       totaltime = min(maxtime, totaldamage / mindps); // always >= mintime due to lemma
+
+                       // assuming t > mintime, dps > mindps:
+                       // we get d = t * dps = maxtime * maxdps
+                       // totaldamage = min(maxdamage, maxtime * maxdps) = min(... + d, maxtime * maxdps) = maxtime * maxdps
+                       // totaldamage / maxdps = maxtime
+                       // totaldamage / mindps > totaldamage / maxdps = maxtime
+                       // FROM THIS:
+                       // a) totaltime = max(mintime, maxtime) = maxtime
+                       // b) totaltime = min(maxtime, totaldamage / maxdps) = maxtime
+
+                       // assuming t <= mintime:
+                       // we get maxtime = mintime
+                       // a) totaltime = max(mintime, ...) >= mintime, also totaltime <= maxtime by the lemma, therefore totaltime = mintime = maxtime
+                       // b) totaltime = min(maxtime, ...) <= maxtime, also totaltime >= mintime by the lemma, therefore totaltime = mintime = maxtime
+
+                       // assuming dps <= mindps:
+                       // we get mindps = maxdps.
+                       // With this, the lemma says that mintime <= totaldamage / mindps = totaldamage / maxdps <= maxtime.
+                       // a) totaltime = max(mintime, totaldamage / maxdps) = totaldamage / maxdps
+                       // b) totaltime = min(maxtime, totaldamage / mindps) = totaldamage / maxdps
 
                        e.fire_damagepersec = totaldamage / totaltime;
                        e.fire_endtime = time + totaltime;
index 0aaf5d337c2c1be0b2e689e54952ddbed3bbb9e9..df63a70bb85d4f01578823b1b4ea3ceaba48f8ce 100644 (file)
@@ -498,10 +498,11 @@ void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma,
        tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, TRUE);
 }
 
-float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent) // returns the number of traces done, for benchmarking
+float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent, float stopatentity) // returns the number of traces done, for benchmarking
 {
        vector pos, dir, t;
        float nudge;
+       entity stopentity;
 
        //nudge = 2 * cvar("collision_impactnudge"); // why not?
        nudge = 0.5;
@@ -534,6 +535,8 @@ float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomon
                        dprint("  trace distance is ", ftos(vlen(pos - trace_endpos)), "\n");
                }
 
+               stopentity = trace_ent;
+
                if(trace_startsolid)
                {
                        // we started inside solid.
@@ -546,6 +549,15 @@ float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomon
                                // t is still inside solid? bad
                                // force advance, then, and retry
                                pos = t + dir * nudge;
+
+                               // but if we hit an entity, stop RIGHT before it
+                               if(stopatentity && stopentity)
+                               {
+                                       trace_ent = stopentity;
+                                       trace_endpos = t;
+                                       trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
+                                       return c;
+                               }
                        }
                        else
                        {
@@ -564,59 +576,9 @@ float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomon
        }
 }
 
-void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent)
+void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity)
 {
-#if 0
-       vector pos, dir, t;
-       float nudge;
-
-       //nudge = 2 * cvar("collision_impactnudge"); // why not?
-       nudge = 0.5;
-
-       dir = normalize(v2 - v1);
-
-       pos = v1 + dir * nudge;
-
-       for(;;)
-       {
-               if((pos - v1) * dir >= (v2 - v1) * dir)
-               {
-                       // went too far
-                       trace_fraction = 1;
-                       return;
-               }
-
-               traceline(pos, v2, nomonsters, forent);
-
-               if(trace_startsolid)
-               {
-                       // we started inside solid.
-                       // then trace from endpos to pos
-                       t = trace_endpos;
-                       traceline(t, pos, nomonsters, forent);
-                       if(trace_startsolid)
-                       {
-                               // t is inside solid? bad
-                               // force advance, then
-                               pos = pos + dir * nudge;
-                       }
-                       else
-                       {
-                               // we actually LEFT solid!
-                               trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
-                               return;
-                       }
-               }
-               else
-               {
-                       // pos is outside solid?!? but why?!? never mind, just return it.
-                       trace_endpos = pos;
-                       trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
-                       return;
-               }
-       }
-#else
-       tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent);
+       tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity);
 }
 
 /*
index 2d2334c563e2a05480e8f27e0fb898f645fe0f61..bdd39b1283f487fe0e74ab42135b6d66f4b180c7 100644 (file)
@@ -55,6 +55,9 @@ MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
        float velocity_difference;
        float clean_up_and_do_nothing;
 
+    if (self.deadflag != DEAD_NO)
+        return 0;
+
        new_velocity_gain = 0;
        clean_up_and_do_nothing = 0;
 
@@ -241,8 +244,6 @@ MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
                }
        }
 
-
-
        if (dodge_detected == 1) {
                self.last_dodging_time = time;
 
index 1cd8b812cee7e1bc324b824d964459269820bd9d..a2f23956eed6f4f3f7b0389d523e8062555fb2d1 100644 (file)
@@ -243,31 +243,58 @@ void W_BallisticBullet_LeaveSolid_think()
        UpdateCSQCProjectile(self);
 }
 
-float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant)
+float W_BallisticBullet_LeaveSolid(float eff)
 {
        // move the entity along its velocity until it's out of solid, then let it resume
-
+       vector vel = self.velocity;
        float dt, dst, velfactor, v0, vs;
        float maxdist;
        float E0_m, Es_m;
+       float constant = self.dmg_radius * (other.ballistics_density ? other.ballistics_density : 1);
 
        // outside the world? forget it
        if(self.origin_x > world.maxs_x || self.origin_y > world.maxs_y || self.origin_z > world.maxs_z || self.origin_x < world.mins_x || self.origin_y < world.mins_y || self.origin_z < world.mins_z)
                return 0;
 
+       // special case for zero density and zero bullet constant: 
+
+       if(self.dmg_radius == 0)
+       {
+               if(other.ballistics_density < 0)
+                       constant = 0; // infinite travel distance
+               else
+                       return 0; // no penetration
+       }
+       else
+       {
+               if(other.ballistics_density < 0)
+                       constant = 0; // infinite travel distance
+               else if(other.ballistics_density == 0)
+                       constant = self.dmg_radius;
+               else
+                       constant = self.dmg_radius * other.ballistics_density;
+       }
+
        // E(s) = E0 - constant * s, constant = area of bullet circle * material constant / mass
        v0 = vlen(vel);
 
        E0_m = 0.5 * v0 * v0;
-       maxdist = E0_m / constant;
-       // maxdist = 0.5 * v0 * v0 / constant
-       // dprint("max dist = ", ftos(maxdist), "\n");
 
-       if(maxdist <= autocvar_g_ballistics_mindistance)
-               return 0;
+       if(constant)
+       {
+               maxdist = E0_m / constant;
+               // maxdist = 0.5 * v0 * v0 / constant
+               // dprint("max dist = ", ftos(maxdist), "\n");
 
-       traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self);
+               if(maxdist <= autocvar_g_ballistics_mindistance)
+                       return 0;
+       }
+       else
+       {
+               maxdist = vlen(other.maxs - other.mins) + 1; // any distance, as long as we leave the entity
+       }
 
+       traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self, TRUE);
        if(trace_fraction == 1) // 1: we never got out of solid
                return 0;
 
@@ -300,6 +327,13 @@ float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant)
        self.flags |= FL_ONGROUND; // prevent moving
        self.W_BallisticBullet_LeaveSolid_velocity = vel;
 
+       if(eff >= 0)
+               if(vlen(trace_endpos - self.origin) > 4)
+               {
+                       endzcurveparticles();
+                       trailparticles(self, eff, self.origin, trace_endpos);
+               }
+
        return 1;
 }
 
@@ -313,6 +347,12 @@ void W_BallisticBullet_Touch (void)
        PROJECTILE_TOUCH;
        W_BallisticBullet_Hit ();
 
+       if(self.dmg_radius < 0) // these NEVER penetrate solid
+       {
+               remove(self);
+               return;
+       }
+
        // if we hit "weapclip", bail out
        //
        // rationale of this check:
@@ -333,12 +373,8 @@ void W_BallisticBullet_Touch (void)
                return;
        }
 
-       density = other.ballistics_density;
-       if(density == 0)
-               density = 1;
-
        // go through solid!
-       if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density))
+       if(!W_BallisticBullet_LeaveSolid(-1))
        {
                remove(self);
                return;
@@ -386,7 +422,12 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f
        proj.nextthink = time + lifetime; // min(pLifetime, vlen(world.maxs - world.mins) / pSpeed);
        W_SetupProjectileVelocityEx(proj, dir, v_up, pSpeed, 0, 0, spread, antilagging);
        proj.angles = vectoangles(proj.velocity);
-       proj.dmg_radius = autocvar_g_ballistics_materialconstant / bulletconstant;
+       if(bulletconstant > 0)
+               proj.dmg_radius = autocvar_g_ballistics_materialconstant / bulletconstant;
+       else if(bulletconstant == 0)
+               proj.dmg_radius = 0;
+       else
+               proj.dmg_radius = -1;
        // so: bulletconstant = bullet mass / area of bullet circle
        setorigin(proj, start);
        proj.flags = FL_PROJECTILE;
@@ -470,6 +511,9 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f
                                W_BallisticBullet_Hit();
                        }
 
+                       if(proj.dmg_radius < 0) // these NEVER penetrate solid
+                               break;
+
                        // if we hit "weapclip", bail out
                        //
                        // rationale of this check:
@@ -487,15 +531,13 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f
                        if not(trace_dphitcontents & DPCONTENTS_OPAQUE)
                                break;
 
-                       density = other.ballistics_density;
-                       if(density == 0)
-                               density = 1;
-
                        // go through solid!
-                       if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density))
+                       if(!W_BallisticBullet_LeaveSolid((other && (other.solid != SOLID_BSP)) ? eff : -1))
                                break;
 
                        W_BallisticBullet_LeaveSolid_think();
+
+                       self.projectiledeathtype |= HITTYPE_BOUNCE;
                }
                frametime = savetime;
                self = oldself;
@@ -588,7 +630,7 @@ void W_PrepareExplosionByDamage(entity attacker, void() explode)
        self.takedamage = DAMAGE_NO;
        self.event_damage = SUB_Null;
        
-       if not(g_ca)
+       if((attacker.flags & FL_CLIENT) && !autocvar_g_projectiles_keep_owner)
        {
                self.owner = attacker;
                self.realowner = attacker;