distinct bullet trail entities

This commit is contained in:
jacob 2026-03-19 20:38:58 -05:00
parent 18ad1fb69e
commit 926cfb5cce
4 changed files with 81 additions and 67 deletions

View File

@ -3151,6 +3151,8 @@ void P_StepFrame(P_Frame *frame)
// TDOO: More specific key with seed that only increments on player control (for less misprediction)
bullet->key = P_EntKeyFromU64(P_RandU64FromEnt(firer));
if (weapon->is_launcher)
{
bullet->is_bomb = 1;
@ -3182,10 +3184,8 @@ void P_StepFrame(P_Frame *frame)
// TODO: Separate 'hits' from bullets, so that bullets can have multiple hits
{
P_EntList hits_to_spawn = Zi;
P_EntList ents_to_spawn = Zi;
for (P_Ent *bullet = P_FirstEnt(frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
{
if (bullet->is_bullet)
@ -3315,7 +3315,7 @@ void P_StepFrame(P_Frame *frame)
bullet->xf.r = NormVec2(bullet_dir);
bullet->v = MulVec2(NormVec2(bullet_dir), initial_speed);
bullet->v = AddVec2(bullet->v, firer->v);
// bullet->v = AddVec2(bullet->v, firer->v);
}
@ -3425,7 +3425,7 @@ void P_StepFrame(P_Frame *frame)
Vec2 normal = victim_raycast.normal;
bullet->bullet_hits_count += 1;
P_Ent *hit = P_PushTempEnt(scratch.arena, &hits_to_spawn);
P_Ent *hit = P_PushTempEnt(scratch.arena, &ents_to_spawn);
{
hit->key = P_EntKeyFromU64(MixU64s(bullet->key.v, P_BulletHitBasis + bullet->bullet_hits_count));
hit->is_hit = 1;
@ -3466,6 +3466,17 @@ void P_StepFrame(P_Frame *frame)
}
bullet->v = MulVec2(bullet->v, 1.0 - SaturateF32(speed_falloff * sim_dt));
// Create trail
{
P_Ent *trail = P_PushTempEnt(scratch.arena, &ents_to_spawn);
trail->key = P_EntKeyFromU64(MixU64s(bullet->key.v, P_BulletTrailBasis + frame->tick));
trail->is_trail = 1;
trail->trail_p0 = p0;
trail->trail_p1 = bullet->xf.t;
trail->lifetime_seconds = 0;
}
// TODO: Remove this
if (!is_client && !P_IsEntNil(victim))
{
@ -3473,7 +3484,7 @@ void P_StepFrame(P_Frame *frame)
{
victim->damage_attribution = damager->key;
}
victim->health -= 0.25;
// victim->health -= 0.25;
}
// Prune out of bounds bullet
@ -3489,7 +3500,7 @@ void P_StepFrame(P_Frame *frame)
}
}
}
P_SpawnEntsFromList(frame, hits_to_spawn);
P_SpawnEntsFromList(frame, ents_to_spawn);
}

View File

@ -9,6 +9,7 @@
#define P_WallShapeIDBasis 0x40d501b4cf6d4f0cull
#define P_BulletSpreadBasis 0xc3b72fe38ca5a1d6ull
#define P_BulletHitBasis 0xbc70fc783c1c507full
#define P_BulletTrailBasis 0x27c011f891c571feull
Struct(P_EntKey)
{
@ -152,6 +153,12 @@ Struct(P_Ent)
Vec2 hit_entry_velocity;
P_MaterialKind hit_material;
//- Trail
b32 is_trail;
Vec2 trail_p0;
Vec2 trail_p1;
//- Bomb
b32 is_bomb;

View File

@ -23,7 +23,7 @@ String P_PackWorld(Arena *arena, P_World *src_world)
{
// TODO: Pack ignored ents
b32 ignore = 0;
if (ent->is_weapon || ent->is_bullet || ent->is_bomb || ent->is_hit)
if (ent->is_weapon || ent->is_bullet || ent->is_bomb || ent->is_hit || ent->is_trail)
{
ignore = 1;
}

View File

@ -1905,7 +1905,7 @@ void V_TickForever(WaveLaneCtx *lane)
{
V_ObservationBin *bin = &V.observation_bins[key.v % countof(V.observation_bins)];
obs = bin->first;
for (; obs; obs = obs->next)
for (; obs; obs = obs->next_in_bin)
{
if (obs->key == key.v)
{
@ -2465,76 +2465,72 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
////////////////////////////
//- Push bullet trail particles
// TODO: Not like this
// for (P_Ent *trail = P_FirstEnt(local_frame); !P_IsEntNil(trail); trail = P_NextEnt(trail))
// {
// if (trail->is_trail)
// if (trail->is_trail && trail->is_first_observation)
// {
// // FIXME: Use 'last visible' pos
// P_Ent *old_bullet = P_EntFromKey(prev_local_frame, bullet->key);
// Vec2 start = old_bullet->xf.t;
// Vec2 end = bullet->xf.t;
// if (P_IsEntNil(old_bullet))
// {
// start = end;
// }
// Vec2 p0 = trail->trail_p0;
// Vec2 p1 = trail->trail_p1;
// b32 skip = 0;
// if (bullet->has_hit)
// {
// Vec2 hit_pos = bullet->hit_entry;
// if (DotVec2(SubVec2(hit_pos, start), SubVec2(end, start)) < 0)
// {
// skip = 1;
// }
// // V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, start), Color_Red);
// // V_DrawPoint(MulAffineVec2(frame->af.world_to_screen, end), Color_Purple);
// end = hit_pos;
// }
// if (!skip)
// {
// {
// f32 trail_len = Vec2Len(SubVec2(end, start));
// f32 particles_count = trail_len * frame->dt * Kibi(8); // Particles per meter per second
// particles_count = MaxF32(particles_count, 1);
// f32 angle = AngleFromVec2(PerpVec2(SubVec2(end, start)));
// // f32 angle = AngleFromVec2(NegVec2(SubVec2(end, start)));
// V_Emitter emitter = Zi;
// {
// emitter.kind = V_ParticleKind_BulletTrail;
// emitter.count = particles_count;
// f32 angle_spread = Tau / 4.0;
// emitter.angle.min = angle - angle_spread / 2;
// emitter.angle.max = angle + angle_spread / 2;
// emitter.pos.p0 = start;
// emitter.pos.p1 = end;
// // emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
// // emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
// emitter.speed.min = -1;
// emitter.speed.max = 1;
// }
// V_PushParticles(emitter);
// }
// }
// P_DebugDrawLine(p0, p1, Color_Cyan);
// }
// }
// TODO: Not like this
for (P_Ent *trail = P_FirstEnt(local_frame); !P_IsEntNil(trail); trail = P_NextEnt(trail))
{
if (trail->is_trail && trail->is_first_observation)
{
Vec2 p0 = trail->trail_p0;
Vec2 p1 = trail->trail_p1;
f32 trail_len = Vec2Len(SubVec2(p1, p0));
f32 particles_count = trail_len * frame->dt * Kibi(8); // Particles per meter per second
particles_count = MaxF32(particles_count, 1);
f32 angle = AngleFromVec2(PerpVec2(SubVec2(p1, p0)));
// f32 angle = AngleFromVec2(NegVec2(SubVec2(p1, p0)));
V_Emitter emitter = Zi;
{
emitter.kind = V_ParticleKind_BulletTrail;
emitter.count = particles_count;
f32 angle_spread = Tau / 4.0;
emitter.angle.min = angle - angle_spread / 2;
emitter.angle.max = angle + angle_spread / 2;
emitter.pos.p0 = p0;
emitter.pos.p1 = p1;
// emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
// emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
emitter.speed.min = -1;
emitter.speed.max = 1;
}
V_PushParticles(emitter);
}
}
@ -2660,7 +2656,7 @@ void V_TickForever(WaveLaneCtx *lane)
emitter.speed.max = speed + speed_spread * 0.5;
emitter.angle.min = angle - angle_spread * 0.5;
emitter.angle.max = angle + angle_spread * 0.5;
emitter.count = TweakFloat("Emitter count", 1, 0, 100) * (Kibi(1) * frame->dt);
emitter.count = TweakFloat("Emitter count", 8, 0, Kibi(64));
V_PushParticles(emitter);
}
}