]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
make damage through floor more exact (use a cvar for max stddev)
authorRudolf Polzer <divverent@xonotic.org>
Wed, 18 Apr 2012 13:56:11 +0000 (15:56 +0200)
committerRudolf Polzer <divverent@xonotic.org>
Wed, 18 Apr 2012 14:05:32 +0000 (16:05 +0200)
defaultXonotic.cfg
qcsrc/server/autocvars.qh
qcsrc/server/g_damage.qc

index b461da300412dab01c23fda87116794c34b20410..0c399bb183cde7a50c4ff80e690bd59764527ffc 100644 (file)
@@ -793,6 +793,23 @@ set g_multijump 0  "Number of multiple jumps to allow (jumping again in the air),
 set g_multijump_add 0  "0 = make the current z velocity equal to jumpvelocity, 1 = add jumpvelocity to the current z velocity"
 set g_multijump_speed -999999  "Minimum vertical speed a player must have in order to jump again"
 
+set g_throughfloor_debug 0 "enable debugging messages for throughfloor calculations"
+set g_throughfloor_damage_max_stddev 2 "Maximum standard deviation for splash damage"
+set g_throughfloor_force_max_stddev 10 "Maximum standard deviation for splash force"
+set g_throughfloor_min_steps_player 1 "Minimum number of steps for splash damage"
+set g_throughfloor_min_steps_other 1 "Minimum number of steps for splash damage"
+set g_throughfloor_max_steps_player 100 "Maximum number of steps for splash damage"
+set g_throughfloor_max_steps_other 10 "Maximum number of steps for splash damage"
+// note: for damage X, 0.25 * ((1-g_throughfloor_damage)*X / g_throughfloor_damage_max_stddev)^2 steps are used
+// for these numbers:
+//   damage  25: 3
+//   damage  60: 15
+//   damage  80: 25
+//   damage 200: 157
+//   force  250: 10
+//   force  300: 15
+//   force  600: 57
+
 // effects
 r_glsl_vertextextureblend_usebothalphas 1 // allows to abuse texture blending as detail texture
 r_glsl_postprocess 0 // but note, hud_postprocessing enables this
index 002cce33082a26cd1b68b0862d6065fb7fc3db3c..5e1c65f796e159525962b01e0cd69074475710f8 100644 (file)
@@ -978,8 +978,15 @@ float autocvar_g_telefrags;
 float autocvar_g_telefrags_avoid;
 float autocvar_g_telefrags_teamplay;
 float autocvar_g_teleport_maxspeed;
+float autocvar_g_throughfloor_debug;
 float autocvar_g_throughfloor_damage;
 float autocvar_g_throughfloor_force;
+float autocvar_g_throughfloor_damage_max_stddev;
+float autocvar_g_throughfloor_force_max_stddev;
+float autocvar_g_throughfloor_min_steps_player;
+float autocvar_g_throughfloor_max_steps_player;
+float autocvar_g_throughfloor_min_steps_other;
+float autocvar_g_throughfloor_max_steps_other;
 float autocvar_g_triggerimpulse_accel_multiplier;
 float autocvar_g_triggerimpulse_accel_power;
 float autocvar_g_triggerimpulse_directional_multiplier;
index 1fd0734a617f0a11a9074c4f7c1b571b7a6a1e69..b32d3ac6b2693bbb3d325c9757b3965b41bfcec6 100644 (file)
@@ -1058,6 +1058,7 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e
                                                float hits;
                                                float total;
                                                float hitratio;
+                                               float mininv_f, mininv_d;
                                                vector hitloc;
                                                vector myblastorigin;
                                                myblastorigin = WarpZone_TransformOrigin(targ, blastorigin);
@@ -1067,22 +1068,42 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e
                                                        center = targ.origin + targ.view_ofs;
                                                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
                                                hits = 0;
+                                               hitloc = nearest;
+
+                                               // we know: max stddev of hitratio = 1 / (2 * sqrt(n))
+                                               // so for a given max stddev:
+                                               // n = (1 / (2 * max stddev of hitratio))^2
+
+                                               mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev;
+                                               mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev;
+
+                                               if(autocvar_g_throughfloor_debug)
+                                                       print(sprintf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f));
+
+                                               total = 0.25 * pow(max(mininv_f, mininv_d), 2);
+
+                                               if(autocvar_g_throughfloor_debug)
+                                                       print(sprintf(" steps=%f", total));
+
                                                if (targ.classname == "player")
-                                                       total = ceil(bound(1, finaldmg, 50));
+                                                       total = ceil(bound(autocvar_g_throughfloor_min_steps_player, total, autocvar_g_throughfloor_max_steps_player));
                                                else
-                                                       total = ceil(bound(1, finaldmg/10, 5));
-                                               hitloc = nearest;
-                                               c = 0;
-                                               while (c < total)
+                                                       total = ceil(bound(autocvar_g_throughfloor_min_steps_other, total, autocvar_g_throughfloor_max_steps_other));
+
+                                               if(autocvar_g_throughfloor_debug)
+                                                       print(sprintf(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total))));
+
+                                               for(c = 0; c < total; ++c)
                                                {
                                                        //traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor);
                                                        WarpZone_TraceLine(blastorigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor);
                                                        if (trace_fraction == 1 || trace_ent == targ)
                                                        {
-                                                               hits = hits + 1;
+                                                               ++hits;
                                                                if (hits > 1)
                                                                        hitloc = hitloc + nearest;
                                                                else
@@ -1091,8 +1112,8 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e
                                                        nearest_x = targ.origin_x + targ.mins_x + random() * targ.size_x;
                                                        nearest_y = targ.origin_y + targ.mins_y + random() * targ.size_y;
                                                        nearest_z = targ.origin_z + targ.mins_z + random() * targ.size_z;
-                                                       c = c + 1;
                                                }
+
                                                nearest = hitloc * (1 / max(1, hits));
                                                hitratio = (hits / total);
                                                a = bound(0, tfloordmg + (1-tfloordmg) * hitratio, 1);
@@ -1100,6 +1121,9 @@ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float e
                                                a = bound(0, tfloorforce + (1-tfloorforce) * hitratio, 1);
                                                force = force * a;
 
+                                               if(autocvar_g_throughfloor_debug)
+                                                       print(sprintf(" D=%f F=%f\n", finaldmg, vlen(force)));
+
                                                // laser force adjustments :P
                                                if(DEATH_WEAPONOF(deathtype) == WEP_LASER)
                                                {