// Native hit-liquid policy (00ab9a90). Called at the damage source, once per channel. struct HitLiquidPolicy { uvec4 liquid; uvec4 state; vec4 bounds; vec4 inventory; vec4 pressure; }; layout(std430, set = 0, binding = 67) readonly buffer HitLiquid { ivec4 bloodSettings; HitLiquidPolicy bloodPolicy[4096]; vec4 bloodProjectile[512]; }; void hit_liquid(int target, float damage, vec2 hit, vec2 impulse, float incoming, float speedScale, int fx, uint seed) { if (damage <= 0.0 || incoming <= 0.0 || fx == 0 || (bloodPolicy[target].state.x & 2u) != 0u) return; const uvec4 policy = bloodPolicy[target].liquid; int matp1 = int(policy.x & 65535u); uint colour = policy.z; if (bloodSettings.y != 0 && (policy.x >> 16) != 0u) { matp1 = int(policy.x >> 16); colour = policy.w; } if (matp1 == 0) return; const float u = float(hash3(seed, 0u, 11u) & 32767u) / 32767.0; const int count = int(((u * 20.0 + 20.0) * uintBitsToFloat(policy.y) + 0.5) * incoming) * bloodSettings.x; vec2 v = impulse; for (int k = 0; k < count; ++k) { const float su = float(hash3(seed, uint(k), 12u) & 32767u) / 32767.0; const float au = float(hash3(seed, uint(k), 13u) & 32767u) / 32767.0; const float yu = float(hash3(seed, uint(k), 14u) & 32767u) / 32767.0; const float xu = float(hash3(seed, uint(k), 15u) & 32767u) / 32767.0; const float a = -0.6 + 1.2 * au; v = vec2(v.x * cos(a) - v.y * sin(a), v.x * sin(a) + v.y * cos(a)); // The constructor adds +0.5 after the hit handler's +/-1.5 jitter. const vec2 pos = hit - vec2(1.0) + 3.0 * vec2(xu, yu); const ivec2 p = ivec2(floor(pos)) - ivec2(pc.view_x, pc.view_y); if (any(lessThan(p, ivec2(0))) || any(greaterThanEqual(p, ivec2(pc.gw, pc.gh)))) continue; emit_material_particle(pos, v * ((20.0 / 60.0) * (0.5 + 0.75 * su) * speedScale), 70.0 + au * 40.0, PART_GRAV, colour, matp1 - 1); } }