This commit is contained in:
Gaël committed 2026-10-19 20:59:15 +02:00
commit 87bff164f1
416 files changed
+279512

No files matched your search

+75
View File
@@ -0,0 +1,75 @@
#version 450
#extension GL_GOOGLE_include_directive : require
layout(local_size_x = 64) in;
#include "common.glsl"
// Projectiles shot by creatures: move in one-cell steps, die in solid cells or when they hit the player, drawn as a 3x3 blob into the entity layer.
struct Ent { vec4 a, box, mv, ai; ivec4 st; vec4 hp; ivec4 x; ivec4 rg; ivec4 rg2; ivec4 aux; vec4 ex; vec4 ex2; ivec4 ex3; vec4 ex4; vec4 ex5; vec4 ex6; vec4 ex7; ivec4 ex8; vec4 ex9; vec4 ex10; vec4 ex11; vec4 ex12, ex13, ex14, ex15, ex16, ex17, ex18, ex19; };
struct Proj { vec4 a; vec4 b; vec4 c; }; // pos, vel / damage, life, gravity, colour bits / owner (0 creature, 1 player)
layout(std430, set = 0, binding = 21) buffer EntLayer { uint entlayer[]; };
layout(std430, set = 0, binding = 22) buffer Ents { Ent ents[]; };
layout(std430, set = 0, binding = 25) buffer Projs { Proj projs[]; };
layout(std430, set = 0, binding = 23) readonly buffer Ctrl { ivec4 inp; ivec4 inp2; ivec4 inp3; vec4 outp; vec4 outp2; } ctrl;
bool solid_at(ivec2 w) {
ivec2 p = w - ivec2(pc.view_x, pc.view_y);
if (p.x < 0 || p.y < 0 || p.x >= pc.gw || p.y >= pc.gh) return true;
uint m = cell_mat(cells[p.y * pc.gw + p.x]);
return m != 0u && (mflags(m) & (F_STATIC | F_SAND)) != 0u;
}
void main() {
uint id = gl_GlobalInvocationID.x;
if (id >= 512u) return;
Proj p = projs[id];
if (p.b.y <= 0.0) return;
if (pc.pass_ == 1) { // between ticks: only draw
ivec2 w0 = ivec2(floor(p.a.xy)) - ivec2(pc.view_x, pc.view_y);
for (int y = -1; y <= 1; ++y)
for (int x = -1; x <= 1; ++x) {
ivec2 q = w0 + ivec2(x, y);
if (q.x >= 0 && q.y >= 0 && q.x < pc.gw && q.y < pc.gh) entlayer[q.y * pc.gw + q.x] = floatBitsToUint(p.b.w);
}
return;
}
vec2 pos = p.a.xy, vel = p.a.zw;
vel.y += p.b.z;
int n = max(int(ceil(length(vel))), 1);
bool dead = false;
vec4 pl = ents[0].a, plbox = ents[0].box;
bool player_alive = (ents[0].st.w & 8) == 0 && ents[0].st.x == 3;
for (int i = 0; i < n && !dead; ++i) {
pos += vel / float(n);
if (solid_at(ivec2(floor(pos)))) { dead = true; break; }
if (p.c.x > 0.5) { // the player's bolt: hits the first living creature whose box contains it
for (int k = 1; k < ctrl.inp.w; ++k) {
if (ents[k].st.x == 0 || ents[k].st.x == 3 || (ents[k].st.w & 8) != 0) continue;
vec2 dk = pos - ents[k].a.xy;
if (dk.x >= ents[k].box.x - 1.0 && dk.x <= ents[k].box.y + 1.0 && dk.y >= ents[k].box.z - 1.0 && dk.y <= ents[k].box.w + 1.0) {
atomicAdd(ents[k].x.x, int(p.b.x * ents[k].ex9.x * 1000.0));
dead = true;
break;
}
}
if (dead) break;
continue;
}
vec2 d = pos - pl.xy;
if (player_alive && d.x >= plbox.x - 1.0 && d.x <= plbox.y + 1.0 && d.y >= plbox.z - 1.0 && d.y <= plbox.w + 1.0) {
atomicAdd(ents[0].x.x, int(p.b.x * ents[0].ex9.x * 1000.0));
dead = true;
}
}
float life = dead ? 0.0 : p.b.y - 1.0;
projs[id].a = vec4(pos, vel);
projs[id].b = vec4(p.b.x, life, p.b.z, p.b.w);
if (life > 0.0) { // draw
uint col = floatBitsToUint(p.b.w);
ivec2 w = ivec2(floor(pos)) - ivec2(pc.view_x, pc.view_y);
for (int y = -1; y <= 1; ++y)
for (int x = -1; x <= 1; ++x) {
ivec2 q = w + ivec2(x, y);
if (q.x >= 0 && q.y >= 0 && q.x < pc.gw && q.y < pc.gh) entlayer[q.y * pc.gw + q.x] = col;
}
}
}