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
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;
float hits;
float total;
float hitratio;
+ float mininv_f, mininv_d;
vector hitloc;
vector myblastorigin;
myblastorigin = WarpZone_TransformOrigin(targ, blastorigin);
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
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);
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)
{