#pragma once #include #include namespace ng { // 00ab9a90 and real-particle constructor 00716af0. RNG supplied by caller. inline int hit_liquid_count(float u, float entity, float incoming, int world) { return int(((u * 20.0f + 20.0f) * entity + 0.5f) * incoming) * world; } inline bool hit_liquid_enabled(float damage, float incoming, int fx, bool frozen) { return damage > 0.0f && incoming > 0.0f && fx != 0 && !frozen; } inline float projectile_hit_liquid_speed(float ragdollForce) { return ragdollForce != 0.0f ? std::sqrt(0.005f / ragdollForce) : 1.0f; } inline bool inventory_hit_liquid_enabled(float damage, float hp, float probability, float threshold, float u, bool emitter) { return probability > 0 && damage < hp && damage > threshold && u < probability && emitter; } inline void hit_liquid_local_point(float& x, float& y, float sx, float sy, float angle, bool hitbox, const float* bounds) { if (sx != 0) x /= sx; if (sy != 0) y /= sy; const float c = std::cos(angle), s = std::sin(angle), nx = c * x + s * y; y = -s * x + c * y; x = nx; if (hitbox) { x = x < bounds[0] ? bounds[0] : (x > bounds[1] ? bounds[1] : x); y = y < bounds[2] ? bounds[2] : (y > bounds[3] ? bounds[3] : y); } else if (x * x + y * y > 65536.0f) x = y = 0; } struct HitLiquidDrop { float x, y, vx, vy; }; inline HitLiquidDrop hit_liquid_drop(float x, float y, float& vx, float& vy, float speedScale, float speedU, float angleU, float yU, float xU) { const float a = -0.6f + 1.2f * angleU, c = std::cos(a), s = std::sin(a); const float nx = vx * c - vy * s; vy = vx * s + vy * c; vx = nx; const float speed = (20.0f / 60.0f) * (0.5f + 0.75f * speedU) * speedScale; return {x - 1.0f + 3.0f * xU, y - 1.0f + 3.0f * yU, vx * speed, vy * speed}; } inline int ragdoll_hit_liquid_reserve(float u, float world, float ragdoll, double partMass, double totalMass, int absolute) { const double amount = absolute < 0 || totalMass <= 0 ? partMass * 1000.0 : partMass / totalMass * absolute; return int((0.8f + 0.40000004f * u) * float(int(world * ragdoll) * int(amount))); } // std430 ABI: binding 67; one entry per entity, then one per projectile type. struct HitLiquidPolicy { uint32_t materials = 0, multiplier = 0, baseColour = 0, sprayColour = 0; uint32_t flags = 0, reserved[3] = {}; float bounds[4] = {}; // min x, max x, min y, max y float inventory[4] = {0, 0.09f, 1, 1}; // probability, minimum damage, entity scale x/y float pressure[4] = {0.7f, 1.1f, 0, 0}; // pressure range, trail gap, reserved }; struct HitLiquidTable { int32_t settings[4] = {1, 0, 0, 0}; HitLiquidPolicy entities[4096]; float projectile[512][4] = {}; }; static_assert(sizeof(HitLiquidPolicy) == 80); }