From a0c50c9a9628589c23fb42ca41d06b8a0279c524 Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Wed, 18 Apr 2012 15:56:11 +0200 Subject: [PATCH] make damage through floor more exact (use a cvar for max stddev) --- defaultXonotic.cfg | 17 +++++++++++++++++ qcsrc/server/autocvars.qh | 7 +++++++ qcsrc/server/g_damage.qc | 38 +++++++++++++++++++++++++++++++------- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index b461da300..0c399bb18 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -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 diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index 002cce330..5e1c65f79 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -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; diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index 1fd0734a6..b32d3ac6b 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -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) { -- 2.39.2