Files
Noita-GPU-Vulkan/src/entity/hit_liquid.h
T
Gaël 00a9c1c26c Lot of bugfixes
* Adding clipper to generate the terrain's negative powder-contour offset.
* Fixing RDB issues (fracture, active trigger, performances)
* Fixing blood emission
* Fixing the freezing formula on liquids
* Fixing Steve spawning due to a missed test.
* Reaction table properly build
2026-10-21 20:46:13 +02:00

55 lines
2.8 KiB
C++

#pragma once
#include <cmath>
#include <cstdint>
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);
}