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
This commit is contained in:
Gaël committed 2026-10-21 20:46:13 +02:00
1 parent a34f42d53e
commit 00a9c1c26c
48 files changed
+5799 -435

No files matched your search

+6 -10
View File
@@ -4,23 +4,19 @@ const int FP_MAX = 32768, FPART_MAX = 16384, FANIM_MAX = 256, FANIM_ALL = 512;
struct FProj { vec4 a; vec4 b; vec4 c; ivec4 d; vec4 e; vec4 f; }; // d.w: the cast serial (0 = dead; the host's twins match it), d.z bit 10 = friendly fire of the shot; f: the wand's damage_electricity_add, damage_ice_add, knockback_force add, trail material (material + 1 | amount << 12) // e: rotation angle, angular velocity (thrown bodies) // pos, vel / damage, life left, gravity, friction / explosion radius, damage, age, bounces / type, spec, fired mask + team, alive
struct FPart { vec4 a; vec4 b; uvec4 c; }; // pos, vel / life, max life, gravity, colour bits (rgb, bit 24 = fades)
struct FAnim { vec4 a; ivec4 b; vec4 c; }; // x, y, light radius, light strength / boom, age, max age, colour bits / angle
layout(std430, set = 0, binding = 36) buffer FxState {
layout(std430, set = 0, binding = 36) coherent buffer FxState {
uint fcnt[4]; // projectile ring, particle ring, animation ring
FProj fprojs[FP_MAX]; // (src/gun/gpu_fx.h kMaxProj)
FPart fparts[16384];
FAnim fanims[512];
};
// Integer alias of the same storage, solely for atomically claiming a particle's
// life word. A plain float test allowed concurrent searches to return the same slot.
layout(std430, set = 0, binding = 36) coherent buffer FxStateAtomic { uint fxwords[]; };
// A free record (00717400 / 007174e0: the pools return null when they are full, a live particle is never replaced): the search starts at the ring position and takes the first dead
// record of the next 64; -1 when there is none.
int alloc_part() {
const uint s0 = atomicAdd(fcnt[1], 1u);
for (uint k = 0u; k < 64u; ++k) {
const uint s = (s0 + k) % uint(FPART_MAX);
if (fparts[s].b.x <= 0.0) return int(s);
}
return -1;
}
#include "particle_alloc.glsl"
// colour bits: rgb, bit 24 = fades with its life, bit 25 = additive. c.w of a cosmetic: bit 1 = no grid collision (collide_with_grid 0), bit 2 = the bounce is spent
// (00712010 sets the bounce flag 6a:20 on every record; fx_particles.comp)
@@ -39,7 +35,7 @@ bool cell_free_at(vec2 w) {
return q.x >= 0 && q.y >= 0 && q.x < pc.gw && q.y < pc.gh && cell_mat(cells[q.y * pc.gw + q.x]) == 0u;
}
void emit_particle(vec2 pos, vec2 vel, float life, float grav, uint rgb, bool fade, bool additive) { emit_particle_g(pos, vel, life, grav, rgb, fade, additive, true); }
// A droplet without a cell that ends where it meets any cell (the cosmetic blood spray): c.x = 1; with a material (c.z = material + 1) it leaves a cell of it there, so the spray feeds the pools.
// A droplet without a cell that ends where it meets any cell (the cosmetic blood spray): c.x = 1; c.z = material + 1 supplies the stain colour. It never owns or deposits a cell.
uint emit_particle_hit(vec2 pos, vec2 vel, float life, float grav, uint rgb, int material) { // returns 0xFFFFFFFF when the pool is full
const int si = alloc_part();
if (si < 0) return 0xFFFFFFFFu;