death events

This commit is contained in:
jacob 2026-04-04 10:50:31 -05:00
parent 2a3a446fdc
commit 0d2871d664
10 changed files with 348 additions and 235 deletions

View File

@ -322,9 +322,6 @@ P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent)
if (wep->is_uzi)
{
result.wep_sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("wep/uzi.ase")));
} else if (wep->is_launcher)
{
result.wep_sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("wep/launcher.ase")));
}
result.frame_seq = animation_time_ns / animation_rate_ns;
@ -335,9 +332,9 @@ P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent)
b32 P_IsEntRolling(P_Frame *frame, P_Ent *ent)
{
b32 result = (
ent->last_roll_time_ns > 0 &&
(frame->time_ns - ent->last_roll_time_ns) > 0 &&
(frame->time_ns - ent->last_roll_time_ns) < P_RollTimeNs
ent->last_roll_ns > 0 &&
(frame->time_ns - ent->last_roll_ns) > 0 &&
(frame->time_ns - ent->last_roll_ns) < P_RollTimeNs
);
return result;
}
@ -2481,16 +2478,16 @@ void P_StepFrame(P_Frame *frame)
if (guy->is_guy)
{
// if (guy->control.roll_presses && !IsVec2Zero(guy->control.move))
if (guy->control.roll_presses)
if (guy->control.downs[P_Button_Roll])
{
// TODO: Not like this
i64 roll_timeout_ns = P_RollTimeoutNs;
i64 roll_time_ns = P_RollTimeNs;
if (frame->time_ns - roll_timeout_ns - roll_time_ns > guy->last_roll_time_ns || guy->last_roll_time_ns == 0)
if (frame->time_ns - roll_timeout_ns - roll_time_ns > guy->last_roll_ns || guy->last_roll_ns == 0)
{
guy->last_roll_time_ns = frame->time_ns;
guy->last_roll_ns = frame->time_ns;
// guy->last_roll_dir = NormVec2(guy->control.move);
guy->last_roll_dir = NormVec2(guy->control.look);
}
@ -2552,7 +2549,7 @@ void P_StepFrame(P_Frame *frame)
move_force *= roll_factor;
max_speed *= roll_factor;
// if ((frame->time_ns - guy->last_roll_time_ns) > P_RollTurnTimeNs)
// if ((frame->time_ns - guy->last_roll_ns) > P_RollTurnTimeNs)
{
turn_rate = 0.1;
}
@ -3133,40 +3130,57 @@ void P_StepFrame(P_Frame *frame)
for (P_Ent *firer = P_FirstEnt(frame); !P_IsEntNil(firer); firer = P_NextEnt(firer))
{
P_Ent *weapon = P_EntFromKey(frame, firer->weapon);
if (weapon->is_weapon && (firer->control.fire_held || firer->control.fire_presses))
// if (weapon->is_weapon && firer->control.fire_presses)
if (weapon->is_weapon)
{
f32 fire_rate = 50;
f32 bullets_per_fire = 1;
b32 can_fire = (weapon->last_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= frame->time_ns;
if (can_fire)
for (P_Button button = 0; button < P_Button_COUNT; ++button)
{
i64 tick_bullets_count = bullets_per_fire;
if (tick_bullets_count > 0)
f32 fire_rate = 1; // In bullets per second
f32 bullets_per_fire = 1;
b32 firing = 0;
b32 is_bomb = 0;
if (button == P_Button_PrimaryFire && (firer->control.held[button] || firer->control.downs[button]))
{
for (i64 bullet_idx = 0; bullet_idx < tick_bullets_count; ++bullet_idx)
// fire_rate = 100;
// bullets_per_fire = 4;
fire_rate = 10;
bullets_per_fire = 1;
firing = (weapon->last_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= frame->time_ns;
if (firing)
{
P_Ent *bullet = P_PushTempEnt(scratch.arena, &bullets_to_spawn);
bullet->is_bullet = 1;
// 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;
}
bullet->source = weapon->key;
bullet->damage_attribution = firer->source;
bullet->sim = weapon->sim;
weapon->last_fire_ns = frame->time_ns;
}
}
if (button == P_Button_AltFire && (firer->control.held[button] || firer->control.downs[button]))
{
fire_rate = 10;
bullets_per_fire = 4;
firing = (weapon->last_alt_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= frame->time_ns;
is_bomb = 1;
if (firing)
{
weapon->last_alt_fire_ns = frame->time_ns;
}
}
if (firing)
{
i64 tick_bullets_count = bullets_per_fire;
if (tick_bullets_count > 0)
{
for (i64 bullet_idx = 0; bullet_idx < tick_bullets_count; ++bullet_idx)
{
P_Ent *bullet = P_PushTempEnt(scratch.arena, &bullets_to_spawn);
bullet->is_bullet = 1;
// TDOO: More specific key with seed that only increments on player control (for less chance of misprediction)
bullet->key = P_EntKeyFromU64(P_RandU64FromEnt(firer));
bullet->is_bomb = is_bomb;
bullet->source = weapon->key;
bullet->damage_attribution = firer->source;
bullet->sim = weapon->sim;
}
}
}
weapon->last_fire_ns = frame->time_ns;
}
}
}
@ -3202,25 +3216,26 @@ void P_StepFrame(P_Frame *frame)
//////////////////////////////
//- Bullet properties
f32 spread = Tau * 0.05;
// f32 spread = Tau * 0.05;
// f32 spread = Tau * 0.2;
// f32 spread = Tau * 0.01;
// f32 spread = 0;
f32 spread = 0;
b32 should_ricochet = 0;
f32 initial_speed = 1;
f32 speed_falloff = 0;
if (weapon->is_uzi)
{
initial_speed = TweakFloat("Bullet speed", 75, 1, 100);
}
else if (weapon->is_launcher)
if (bullet->is_bomb)
{
should_ricochet = 1;
initial_speed = 50;
// initial_speed = 100;
speed_falloff = 5;
}
else
{
initial_speed = TweakFloat("Bullet speed", 75, 1, 100);
}
//////////////////////////////
//- Initialize
@ -3490,7 +3505,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
@ -3696,17 +3711,19 @@ void P_StepFrame(P_Frame *frame)
//////////////////////////////
//- Kill guys
{
P_EntList ents_to_spawn = Zi;
for (P_Ent *guy = P_FirstEnt(frame); !P_IsEntNil(guy); guy = P_NextEnt(guy))
{
if (guy->is_guy)
if (guy->is_guy && guy->health <= 0)
{
if (guy->health <= 0)
P_Ent *old_guy = P_EntFromKey(prev_frame, guy->key);
if (old_guy->health > 0)
{
P_Ent *old_guy = P_EntFromKey(prev_frame, guy->key);
if (old_guy->health > 0)
P_Ent *player = P_EntFromKey(frame, guy->source);
P_Ent *killer = P_EntFromKey(frame, guy->damage_attribution);
// Update kill info
{
P_Ent *player = P_EntFromKey(frame, guy->source);
P_Ent *killer = P_EntFromKey(frame, guy->damage_attribution);
if (player->is_player)
{
player->deaths += 1;
@ -3717,10 +3734,23 @@ void P_StepFrame(P_Frame *frame)
}
guy->exists = 0;
guy->continuity_gen += 1;
guy->health = 1;
}
// Push kill event
{
P_Ent *death = P_PushTempEnt(scratch.arena, &ents_to_spawn);
death->key = P_EntKeyFromU64(MixU64s(guy->key.v, P_DeathBasis + (u64)player->deaths));
death->death_pos = guy->xf.t;
death->is_death = 1;
death->death_player = player->key;
death->death_killer = killer->key;
death->lifetime_seconds = P_ObservationDurationSeconds;
}
}
}
}
P_SpawnEntsFromList(frame, ents_to_spawn);
}
//////////////////////////////
//- Debug draw

View File

@ -10,6 +10,7 @@
#define P_BulletSpreadBasis 0xc3b72fe38ca5a1d6ull
#define P_BulletHitBasis 0xbc70fc783c1c507full
#define P_BulletTrailBasis 0x27c011f891c571feull
#define P_DeathBasis 0x2e3c75a3286d872aull
Struct(P_EntKey)
{
@ -88,6 +89,15 @@ Struct(P_DebugDrawNode)
#define P_RollTimeoutNs NsFromSeconds(0.5)
#define P_ObservationDurationSeconds 1
Enum(P_Button)
{
P_Button_PrimaryFire,
P_Button_AltFire,
P_Button_Roll,
P_Button_COUNT
};
Struct(P_Control)
{
i64 tick;
@ -98,9 +108,8 @@ Struct(P_Control)
Vec2 move;
Vec2 look;
f32 fire_held;
f32 fire_presses;
f32 roll_presses;
f32 held[P_Button_COUNT];
f32 downs[P_Button_COUNT];
};
Struct(P_Ent)
@ -159,6 +168,11 @@ Struct(P_Ent)
Vec2 hit_entry_velocity;
P_MaterialKind hit_material;
b32 is_death;
Vec2 death_pos;
P_EntKey death_player;
P_EntKey death_killer;
//- Bomb
b32 is_bomb;
@ -189,8 +203,9 @@ Struct(P_Ent)
P_EntKey guy;
f32 ping;
f32 kills;
f32 deaths;
u64 kills;
u64 deaths;
u8 string_len;
u8 string_text[P_MaxPlayerNameLen + 8];
@ -198,18 +213,19 @@ Struct(P_Ent)
//- Guy
P_EntKey weapon;
i64 last_roll_time_ns;
Vec2 last_roll_dir;
i64 walk_time_accum_ns;
i64 last_fire_ns;
i64 last_alt_fire_ns;
i64 last_roll_ns;
//- Weapon
b32 is_weapon;
b32 is_uzi;
b32 is_launcher;
i64 last_fire_ns;
//- Spawner
b32 is_guy_spawn;

BIN
src/pp/pp_res/wep/launcher.ase (Stored with Git LFS)

Binary file not shown.

View File

@ -425,7 +425,7 @@ void S_TickForever(WaveLaneCtx *lane)
//- Apply bot controls
{
f32 move_bias = TweakFloat("Bot movement bias", 1, -1, 1);
f32 move_bias = TweakFloat("Bot movement bias", 0, -1, 1);
f32 move_frequency = TweakFloat("Bot movement frequency", 0, 0, 10);
f32 turn_frequency = TweakFloat("Bot turn frequency", 0, 0, 10);
// b32 bot_movement_enabled = TweakBool("Bot movement enabled", 1);

View File

@ -958,8 +958,6 @@ void V_TickForever(WaveLaneCtx *lane)
frame->is_editing = prev_frame->is_editing;
frame->ui_debug = prev_frame->ui_debug;
frame->look = prev_frame->look;
frame->fire_presses = prev_frame->fire_presses;
frame->roll_presses = prev_frame->roll_presses;
frame->show_consoles = prev_frame->show_consoles;
frame->show_profilers = prev_frame->show_profilers;
frame->edit_mode = prev_frame->edit_mode;
@ -1443,18 +1441,20 @@ void V_TickForever(WaveLaneCtx *lane)
look = ClampVec2Len(look, min_look_radius, max_look_radius);
}
f32 fire_held = frame->held_buttons[Button_M1];
f32 roll_held = frame->held_buttons[Button_Space];
f32 fire_presses = fire_held && !prev_frame->held_buttons[Button_M1];
f32 roll_presses = roll_held && !prev_frame->held_buttons[Button_Space];
if (frame->is_looking)
{
frame->look = look;
frame->fire_held = fire_held;
frame->fire_presses += fire_presses;
frame->roll_presses += roll_presses;
// Update game control
{
P_Control *control = &V.queued_pp_control;
control->held[P_Button_PrimaryFire] = frame->held_buttons[Button_M1];
control->held[P_Button_AltFire] = frame->held_buttons[Button_M2];
control->held[P_Button_Roll] = frame->held_buttons[Button_Space];
control->downs[P_Button_PrimaryFire] += frame->held_buttons[Button_M1] && !prev_frame->held_buttons[Button_M1];
control->downs[P_Button_AltFire] += frame->held_buttons[Button_M2] && !prev_frame->held_buttons[Button_M2];
control->downs[P_Button_Roll] += frame->held_buttons[Button_Space] && !prev_frame->held_buttons[Button_Space];
}
}
if (frame->is_moving)
@ -1462,13 +1462,10 @@ void V_TickForever(WaveLaneCtx *lane)
frame->move = move;
}
if (!frame->is_looking)
if (!frame->is_looking && !frame->is_panning)
{
if (!frame->is_panning)
{
f32 edit_move_speed = 20.0 * MaxF32(frame->edit_camera_zoom, min_zoom);
frame->edit_camera_pos = AddVec2(frame->edit_camera_pos, MulVec2(move, edit_move_speed * frame->dt));
}
f32 edit_move_speed = 20.0 * MaxF32(frame->edit_camera_zoom, min_zoom);
frame->edit_camera_pos = AddVec2(frame->edit_camera_pos, MulVec2(move, edit_move_speed * frame->dt));
}
}
@ -1995,17 +1992,14 @@ void V_TickForever(WaveLaneCtx *lane)
{
i64 control_tick = predict_to;
P_Control control = Zi;
control.tick = control_tick;
control.orig_tick = control_tick;
control.move = frame->move;
control.look = frame->look;
control.fire_held = frame->fire_held;
control.fire_presses = frame->fire_presses;
control.roll_presses = frame->roll_presses;
frame->fire_presses = 0;
frame->roll_presses = 0;
P_Control control = V.queued_pp_control;
{
control.tick = control_tick;
control.orig_tick = control_tick;
control.move = frame->move;
control.look = frame->look;
ZeroStruct(&V.queued_pp_control);
}
//- Fill controls buffer backwards
i64 max_fill_count = SIM_TICKS_PER_SECOND / 4;
@ -2936,7 +2930,7 @@ void V_TickForever(WaveLaneCtx *lane)
{
Affine wep_uv_to_world_af = ScaleAffine(wep_pix_to_world_af, DimsFromRng2(wep.tex_rect));
V_Quad *quad = PushStruct(frame->quads_arena, V_Quad);
V_GpuQuad *quad = PushStruct(frame->quads_arena, V_GpuQuad);
quad->quad_uv_to_world_af = wep_uv_to_world_af;
quad->tex = wep.tex;
quad->tex_slice_uv = DivRng2Vec2(wep.tex_rect, wep.tex_dims);
@ -2946,7 +2940,7 @@ void V_TickForever(WaveLaneCtx *lane)
if (body.ready)
{
//- Legs quad
V_Quad legs_quad = Zi;
V_GpuQuad legs_quad = Zi;
{
Affine legs_uv_to_world_af = ScaleAffine(legs_pix_to_world_af, DimsFromRng2(legs.tex_rect));
legs_quad.quad_uv_to_world_af = legs_uv_to_world_af;
@ -2955,7 +2949,7 @@ void V_TickForever(WaveLaneCtx *lane)
}
//- Body quad
V_Quad body_quad = Zi;
V_GpuQuad body_quad = Zi;
{
Affine body_uv_to_world_af = ScaleAffine(body_pix_to_world_af, DimsFromRng2(body.tex_rect));
body_quad.quad_uv_to_world_af = body_uv_to_world_af;
@ -2968,7 +2962,7 @@ void V_TickForever(WaveLaneCtx *lane)
}
//- Weapon quad
V_Quad wep_quad = Zi;
V_GpuQuad wep_quad = Zi;
{
Affine wep_uv_to_world_af = ScaleAffine(wep_pix_to_world_af, DimsFromRng2(wep.tex_rect));
wep_quad.quad_uv_to_world_af = wep_uv_to_world_af;
@ -2982,21 +2976,21 @@ void V_TickForever(WaveLaneCtx *lane)
{
if (anim.weapon_over)
{
*PushStructNoZero(frame->quads_arena, V_Quad) = legs_quad;
*PushStructNoZero(frame->quads_arena, V_Quad) = body_quad;
*PushStructNoZero(frame->quads_arena, V_Quad) = wep_quad;
*PushStructNoZero(frame->quads_arena, V_GpuQuad) = legs_quad;
*PushStructNoZero(frame->quads_arena, V_GpuQuad) = body_quad;
*PushStructNoZero(frame->quads_arena, V_GpuQuad) = wep_quad;
}
else
{
*PushStructNoZero(frame->quads_arena, V_Quad) = wep_quad;
*PushStructNoZero(frame->quads_arena, V_Quad) = legs_quad;
*PushStructNoZero(frame->quads_arena, V_Quad) = body_quad;
*PushStructNoZero(frame->quads_arena, V_GpuQuad) = wep_quad;
*PushStructNoZero(frame->quads_arena, V_GpuQuad) = legs_quad;
*PushStructNoZero(frame->quads_arena, V_GpuQuad) = body_quad;
}
}
else
{
*PushStructNoZero(frame->quads_arena, V_Quad) = legs_quad;
*PushStructNoZero(frame->quads_arena, V_Quad) = body_quad;
*PushStructNoZero(frame->quads_arena, V_GpuQuad) = legs_quad;
*PushStructNoZero(frame->quads_arena, V_GpuQuad) = body_quad;
}
}
}
@ -3012,7 +3006,7 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
//- Process event entities
//- Process world events
for (P_Ent *event = P_FirstEnt(local_frame); !P_IsEntNil(event); event = P_NextEnt(event))
{
@ -3142,8 +3136,11 @@ void V_TickForever(WaveLaneCtx *lane)
// }
// Bullet fired
if (event->is_first_trail)
{
// frame->camera_shake += 0.5;
//- Bullet particle
{
V_Emitter emitter = Zi;
@ -3182,7 +3179,7 @@ void V_TickForever(WaveLaneCtx *lane)
emitter.kind = V_ParticleKind_MuzzleWide;
// emitter.count = MaxF32(1000 * frame->dt, 1);
// emitter.count = 128;
emitter.count = 8;
emitter.count = 2;
f32 angle = AngleFromVec2(SubVec2(p1, p0));
@ -3398,9 +3395,14 @@ void V_TickForever(WaveLaneCtx *lane)
{
P_MaterialKind material = event->hit_material;
Vec2 hit_entry = event->hit_entry;
Vec2 hit_entry_normal = event->hit_entry_normal;
Vec2 hit_entry_velocity = event->hit_entry_velocity;
Vec2 impact_pos = event->hit_entry;
Vec2 impact_velocity = event->hit_entry_velocity;
f32 impact_dir_velocity_weight = 0;
Vec2 impact_dir = SlerpVec2(event->hit_entry_normal, NegVec2(impact_velocity), impact_dir_velocity_weight);
f32 impact_offset_angle = rand_angle * (Tau * 0);
impact_dir = RotateVec2Angle(impact_dir, impact_offset_angle);
//- Wall impact particles
if (material != P_MaterialKind_Flesh)
@ -3425,7 +3427,7 @@ void V_TickForever(WaveLaneCtx *lane)
// // emitter.velocity_falloff = 5;
// // emitter.velocity_falloff_spread = emitter.velocity_falloff_spread * 1.5;
// Vec2 dir = hit_entry_normal;
// Vec2 dir = impact_dir;
// f32 angle = AngleFromVec2(dir);
// f32 angle_spread = Tau * 0.5;
@ -3441,52 +3443,51 @@ void V_TickForever(WaveLaneCtx *lane)
// V_PushParticles(emitter);
// }
// Fire
// {
// V_Emitter emitter = Zi;
// emitter.kind = V_ParticleKind_Fire;
// // emitter.count = MaxF32(1000 * frame->dt, 1);
// emitter.count = 2;
// Hot debris
{
V_Emitter emitter = Zi;
emitter.kind = V_ParticleKind_HotDebris;
// emitter.count = MaxF32(1000 * frame->dt, 1);
emitter.count = 32;
// // f32 angle = AngleFromVec2(SubVec2(p1, p0));
// f32 angle = AngleFromVec2(SubVec2(p1, p0));
// f32 angle = AngleFromVec2(hit_entry_normal);
// angle += rand_angle * (Tau * 0.05);
f32 angle = AngleFromVec2(impact_dir);
// f32 angle_particle_spread = Tau / 4;
// emitter.angle.min = angle - angle_particle_spread / 2;
// emitter.angle.max = angle + angle_particle_spread / 2;
f32 angle_particle_spread = Tau / 2.5;
emitter.angle.min = angle - angle_particle_spread / 2;
emitter.angle.max = angle + angle_particle_spread / 2;
// emitter.pos.p0 =
// emitter.pos.p1 = hit_entry;
emitter.pos.p0 =
emitter.pos.p1 = impact_pos;
// // emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
// emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
// // emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
// emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
// emitter.speed.min = 0;
// emitter.speed.max = 25;
emitter.speed.min = 0;
emitter.speed.max = 30;
// // emitter.angle.min = angle - angle_spread / 2;
// // emitter.angle.max = angle + angle_spread / 2;
// emitter.angle.min = angle - angle_spread / 2;
// emitter.angle.max = angle + angle_spread / 2;
// // emitter.angle.min =
// // emitter.angle.max = angle;
// emitter.angle.min =
// emitter.angle.max = angle;
// // emitter.pos.p0 =
// // emitter.pos.p1 = p0;
// emitter.pos.p0 =
// emitter.pos.p1 = p0;
// // emitter.speed.min =
// // emitter.speed.max =
// emitter.speed.min =
// emitter.speed.max =
// // emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
// emitter.color_lin = LinearFromSrgb(VEC4(0, 1, 0, 1));
// // emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
// // emitter.speed.min =
// // emitter.speed.max = Vec2Len(SubVec2(p1, p0)) / frame->dt;
// emitter.color_lin = LinearFromSrgb(VEC4(0.8, 0.6, 0.2, 1));
// emitter.speed.min =
// emitter.speed.max = Vec2Len(SubVec2(p1, p0)) / frame->dt;
// V_PushParticles(emitter);
// }
V_PushParticles(emitter);
}
@ -3494,32 +3495,32 @@ void V_TickForever(WaveLaneCtx *lane)
// Wall dust
// {
// V_Emitter emitter = Zi;
// {
// emitter.kind = V_ParticleKind_Smoke;
// emitter.count = 128;
{
V_Emitter emitter = Zi;
{
emitter.kind = V_ParticleKind_WallDust;
emitter.count = 128;
// emitter.pos.p0 = emitter.pos.p1 = hit_entry;
emitter.pos.p0 = emitter.pos.p1 = impact_pos;
// // emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.5, 0.5, 0.75));
// emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.5, 0.5, 0.75));
// emitter.speed.min = 10;
// emitter.speed.max = 20;
emitter.speed.min = 1;
emitter.speed.max = 20;
// // emitter.velocity_falloff = 12;
// // emitter.velocity_falloff_spread = emitter.velocity_falloff_spread * 1.5;
// emitter.velocity_falloff = 12;
// emitter.velocity_falloff_spread = emitter.velocity_falloff_spread * 1.5;
// Vec2 dir = hit_entry_normal;
// f32 angle = AngleFromVec2(dir);
// f32 angle_spread = Tau * 0.1;
Vec2 dir = impact_dir;
f32 angle = AngleFromVec2(dir);
f32 angle_spread = Tau * 0.1;
// emitter.angle.min = angle - angle_spread / 2;
// emitter.angle.max = angle + angle_spread / 2;
emitter.angle.min = angle - angle_spread / 2;
emitter.angle.max = angle + angle_spread / 2;
// }
// V_PushParticles(emitter);
// }
}
V_PushParticles(emitter);
}
}
//- Flesh impact particles
@ -3530,7 +3531,7 @@ void V_TickForever(WaveLaneCtx *lane)
emitter.kind = V_ParticleKind_BloodTrail;
// emitter.kind = V_ParticleKind_BloodDebris;
Vec2 dir = NormVec2(NegVec2(hit_entry_velocity));
Vec2 dir = NormVec2(NegVec2(impact_velocity));
f32 angle = AngleFromVec2(dir);
// f32 angle = 0;
@ -3545,7 +3546,7 @@ void V_TickForever(WaveLaneCtx *lane)
// f32 speed = 100;
f32 speed_spread = speed * 2;
emitter.pos.p0 = emitter.pos.p1 = hit_entry;
emitter.pos.p0 = emitter.pos.p1 = impact_pos;
emitter.speed.min = speed - speed_spread * 0.5;
emitter.speed.max = speed + speed_spread * 0.5;
emitter.angle.min = angle - angle_spread * 0.5;
@ -3557,6 +3558,49 @@ void V_TickForever(WaveLaneCtx *lane)
// V_DrawPoint(victim_raycast.p, Color_Green);
// V_DrawLine(victim_raycast.p, AddVec2(victim_raycast.p, MulVec2(victim_raycast.normal, 0.5)), Color_White);
}
//////////////////////////////
//- Death
if (event->is_death)
{
Vec2 death_pos = event->death_pos;
//- Death particles
{
V_Emitter emitter = Zi;
emitter.kind = V_ParticleKind_BloodTrail;
// emitter.kind = V_ParticleKind_BloodDebris;
// f32 angle = AngleFromVec2(frame->look);
f32 angle = 0;
// f32 angle_spread = Tau * 0.25;
f32 angle_spread = Tau;
// f32 angle_spread = 0;
// f32 speed = 5;
// f32 speed = 25;
f32 speed = 50;
// f32 speed = 100;
f32 speed_spread = speed * 2;
emitter.pos.p0 = emitter.pos.p1 = death_pos;
emitter.speed.min = speed - speed_spread * 0.5;
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 = Kibi(32) * frame->dt;
// emitter.count = Kibi(1);
emitter.count = Kibi(4);
V_PushParticles(emitter);
}
}
}
}
@ -5486,20 +5530,6 @@ void V_TickForever(WaveLaneCtx *lane)
}
}
// //- Test profiler panel
// {
// V_Panel *parent = right_bottom_panel;
// V_Panel *panel = PushStruct(perm, V_Panel);
// panel->axis = Axis_X;
// DllQueuePush(panel->parent->first, panel->parent->last, panel);
// panel->box = UI_KeyF("test raah profiler panel");
// panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v));
// panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v));
// panel->flags |= V_PanelFlag_Profiler;
// panel->flags |= V_PanelFlag_Ignore;
// panel->pct = 2;
// }
//- Test spawn panel
{
V_Panel *panel = PushStruct(perm, V_Panel);
@ -5539,6 +5569,20 @@ void V_TickForever(WaveLaneCtx *lane)
panel->flags |= V_PanelFlag_Screen;
panel->pct = 1;
}
// //- Test profiler panel
// {
// V_Panel *panel = PushStruct(perm, V_Panel);
// panel->parent = right_panel;
// panel->axis = Axis_X;
// DllQueuePush(panel->parent->first, panel->parent->last, panel);
// panel->box = UI_RandKey();
// panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v));
// panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v));
// panel->flags |= V_PanelFlag_Profiler;
// panel->flags |= V_PanelFlag_Ignore;
// panel->pct = 2;
// }
}
@ -8005,10 +8049,10 @@ void V_TickForever(WaveLaneCtx *lane)
Rng2 shade_scissor = RNG2(VEC2(shade_viewport.p0.x, shade_viewport.p0.y), VEC2(shade_viewport.p1.x, shade_viewport.p1.y));
// Quad buffers
frame->quads_count = ArenaCount(frame->quads_arena, V_Quad);
frame->quads_count = ArenaCount(frame->quads_arena, V_GpuQuad);
frame->quads = G_PushStructsFromCpu(
cl, gpu_frame_arena,
ArenaFirst(frame->quads_arena, V_Quad), frame->quads_count,
ArenaFirst(frame->quads_arena, V_GpuQuad), frame->quads_count,
.name = StringF(frame->arena, "quads [%F]", FmtSint(frame->tick))
);
@ -8085,6 +8129,7 @@ void V_TickForever(WaveLaneCtx *lane)
// Clear particles
if (frame->should_clear_particles)
{
LogDebugF("Clearing particles");
G_Compute(cl, V_ClearParticlesCS, V_ParticlesCap);
V.particle_seq = 0;
}

View File

@ -418,8 +418,8 @@ Struct(V_Frame)
f64 blend_sim_tick;
f64 blend_predict_tick;
Button held_buttons[Button_COUNT]; // User input state captured for gameplay
Button real_held_buttons[Button_COUNT]; // Actual state of user input regardless of keyboard / mouse focus
b32 held_buttons[Button_COUNT]; // User input state captured for gameplay
b32 real_held_buttons[Button_COUNT]; // Actual state of user input regardless of keyboard / mouse focus
V_Palette palette;
UI_Key text_input_focus;
@ -460,6 +460,8 @@ Struct(V_Ctx)
V_CmdNode *last_queued_cmd_node;
V_CmdNode *first_free_cmd_node;
P_Control queued_pp_control;

View File

@ -17,6 +17,14 @@ f32 V_LifetimeFromParticleDesc(V_ParticleDesc desc, u32 particle_idx)
return result;
}
f32 V_FalloffFromParticleDesc(V_ParticleDesc desc, u32 particle_idx)
{
u64 seed = MixU64(V_ParticleFalloffBasis ^ particle_idx);
f32 rand_falloff = Norm16(seed >> 16);
f32 result = lerp(desc.falloff_min, desc.falloff_max, rand_falloff);
return result;
}
Vec4 V_ColorFromParticleDesc(V_ParticleDesc desc, u32 particle_idx, f32 alive_seconds, u32 density)
{
Vec4 result = 0;
@ -36,7 +44,7 @@ Vec4 V_ColorFromParticleDesc(V_ParticleDesc desc, u32 particle_idx, f32 alive_se
result.a += (1.0 - result.a) * (t);
}
else if (desc.kind == V_ParticleKind_BloodTrail || desc.kind == V_ParticleKind_BloodDebris)
else if (desc.kind == V_ParticleKind_BloodTrail)
{
// f32 t = (f32)density / 5;
// t = pow(t, 2);
@ -209,7 +217,8 @@ ComputeShader(V_PrepareCellsCS)
}
else
{
f32 dry_rate = saturate(frame.dt * 0.1);
// f32 dry_rate = saturate(frame.dt * 0.1);
f32 dry_rate = saturate(frame.dt * 0.2);
Vec4 before_stain = stains[cell_pos];
Vec4 before_dry_stain = dry_stains[cell_pos];
@ -360,9 +369,9 @@ ComputeShader(V_BackdropUpCS)
VertexShader(V_QuadVS, V_QuadPSInput)
{
V_SharedFrame frame = G_Deref(V_GpuReg_Frame, StructuredBuffer<V_SharedFrame>)[0];
StructuredBuffer<V_Quad> quads = G_Deref(frame.quads, StructuredBuffer<V_Quad>);
StructuredBuffer<V_GpuQuad> quads = G_Deref(frame.quads, StructuredBuffer<V_GpuQuad>);
V_Quad quad = quads[SV_InstanceID];
V_GpuQuad quad = quads[SV_InstanceID];
Vec2 rect_uv = RectUvFromIdx(SV_VertexID);
Vec2 world_pos = mul(quad.quad_uv_to_world_af, Vec3(rect_uv, 1));
@ -387,7 +396,7 @@ PixelShader(V_QuadPS, V_QuadPSOutput, V_QuadPSInput input)
SamplerState sampler = G_Deref(frame.basic_samplers[G_BasicSamplerKind_PointClamp], SamplerState);
RWTexture2D<u32> occluders = G_Deref(frame.occluders, RWTexture2D<u32>);
V_Quad quad = input.quad;
V_GpuQuad quad = input.quad;
Texture2D<Vec4> tex = G_Deref(quad.tex, Texture2D<Vec4>);
Vec2 world_pos = input.world_pos;
@ -465,7 +474,6 @@ ComputeShader(V_SimParticlesCS)
f32 rand_offset = Norm16(seed0 >> 0);
f32 rand_angle = Norm16(seed0 >> 16);
f32 rand_speed = Norm16(seed0 >> 32);
f32 rand_falloff = Norm16(seed0 >> 48);
//////////////////////////////
//- Init particle
@ -711,9 +719,13 @@ ComputeShader(V_SimParticlesCS)
}
}
f32 rand_falloff = Norm16(seed0 >> 48);
// f32 falloff = saturate(lerp(1, 2, rand_falloff) * frame.dt);
// f32 falloff = saturate(lerp(10, 20, rand_falloff) * frame.dt);
f32 falloff = 0;
// f32 falloff = saturate(lerp(10, 20, rand_falloff * frame.dt));
// f32 falloff = saturate(lerp(5, 10, rand_falloff * frame.dt));
// f32 falloff = 20 * frame.dt;
f32 falloff = V_FalloffFromParticleDesc(desc, particle_idx) * frame.dt;
particle.velocity *= 1.0f - falloff;
particle.pos = p0 + (p1 - p0) * t;
@ -1291,13 +1303,8 @@ ComputeShader(V_BloomDownCS)
f32 knee_weight = 1;
if (is_first_pass)
{
// f32 luminance = LuminanceFromColor(src);
// f32 max_rgb = max(max(src.r, src.g), src.b); // So that we can get bloom on colors with high rgb, not just high luminance
f32 luminance = LuminanceFromColor(src);
f32 max_rgb = -1; // So that we can get bloom on colors with high rgb, not just high luminance
f32 max_rgb = max(max(src.r, src.g), src.b); // So that we can get bloom on colors with high rgb, not just high luminance
f32 bright = max(luminance, (max_rgb - 1.0) * 0.5);
if (bright > 0)
{

View File

@ -6,7 +6,7 @@ Struct(V_QuadPSInput)
Vec4 Semantic(sv_position);
Vec2 Semantic(world_pos);
Vec2 Semantic(samp_uv);
nointerpolation V_Quad Semantic(quad);
nointerpolation V_GpuQuad Semantic(quad);
};
Struct(V_QuadPSOutput)
@ -46,6 +46,7 @@ Struct(V_DVertPSOutput)
f32 V_RandFromPos(Vec3 pos);
f32 V_LifetimeFromParticleDesc(V_ParticleDesc desc, u32 particle_idx);
f32 V_FalloffFromParticleDesc(V_ParticleDesc desc, u32 particle_idx);
Vec4 V_ColorFromParticleDesc(V_ParticleDesc desc, u32 particle_idx, f32 alive_seconds, u32 density);
////////////////////////////////////////////////////////////

View File

@ -4,18 +4,20 @@
V_ParticleDesc V_DescFromParticleKind(V_ParticleKind kind)
{
V_ParticleDesc descs[V_ParticleKind_COUNT] = {
#define X(name, flags, layer, stain_rate, pen_rate, lifetime_min, lifetime_max, prune_speed_threshold, base_color, dry_factor) \
{ \
V_ParticleKind_##name, \
flags, \
layer, \
stain_rate, \
pen_rate, \
lifetime_min, \
lifetime_max, \
prune_speed_threshold, \
LinearFromSrgb(base_color), \
LinearFromSrgb(dry_factor) \
#define X(name, flags, layer, stain_rate, pen_rate, lifetime_min, lifetime_max, falloff_min, falloff_max, prune_speed_threshold, base_color, dry_factor) \
{ \
V_ParticleKind_##name, \
flags, \
layer, \
stain_rate, \
pen_rate, \
lifetime_min, \
lifetime_max, \
falloff_min, \
falloff_max, \
prune_speed_threshold, \
LinearFromSrgb(base_color), \
LinearFromSrgb(dry_factor) \
},
V_ParticlesXList(X)
#undef X

View File

@ -25,6 +25,7 @@ G_DeclRegister(i32, V_GpuReg_MipIdx, 4);
#define V_ParticleCellBasis 0xf60c0cff344b0c5dull
#define V_ParticleStainBasis 0x3c64e8226d98d376ull
#define V_ParticleLifetimeBasis 0x4969cf8f60816abfull
#define V_ParticleFalloffBasis 0xa475ffbeeeef3b9dull
Enum(V_ParticleFlag)
{
@ -46,7 +47,7 @@ Enum(V_ParticleLayer)
V_ParticleLayer_COUNT
};
// NOTE: Higher particle enum values take priority over lower ones
// NOTE: Higher particle enum values take priority over lower within the same layer ones when drawing / staining
#define V_ParticlesXList(X) \
X( \
/* Name */ None, \
@ -54,6 +55,7 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Ground, \
/* Stain rate, pen chance */ 30, 0, \
/* Lifetime */ Inf, Inf, \
/* Falloff */ 0, 0, \
/* Prune speed threshold */ 0.01, \
/* Base color */ VEC4(0, 0, 0, 0), \
/* Dry color factor */ VEC4(1, 1, 1, 1) \
@ -66,26 +68,18 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Ground, \
/* Stain rate, pen chance */ 100, 0.25, \
/* Lifetime */ Inf, Inf, \
/* Falloff */ 10, 20, \
/* Prune speed threshold */ 0.5, \
/* Base color */ VEC4(0.6, 0.1, 0.1, 0.05), \
/* Dry color factor */ VEC4(0.4, 0.4, 0.4, 1) \
) \
X( \
/* Name */ BloodDebris, \
/* Flags */ V_ParticleFlag_StainWhenPruned, \
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 30, 0, \
/* Lifetime */ Inf, Inf, \
/* Prune speed threshold */ 0.01, \
/* Base color */ VEC4(0.5, 0.1, 0.1, 0.8), \
/* Dry color factor */ VEC4(1, 1, 1, 1) \
) \
X( \
/* Name */ Debris, \
/* Flags */ V_ParticleFlag_StainWhenPruned, \
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, Inf, \
/* Falloff */ 10, 20, \
/* Prune speed threshold */ 0.01, \
/* Base color */ VEC4(0.4, 0.3, 0.2, 1), \
/* Dry color factor */ VEC4(1, 1, 1, 1) \
@ -96,38 +90,42 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, Inf, \
/* Falloff */ 10, 20, \
/* Prune speed threshold */ 0.1, \
/* Base color */ VEC4(2, 0.5, 0, 1), \
/* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \
) \
X( \
/* Name */ HotDebris, \
/* Flags */ V_ParticleFlag_StainWhenPruned, \
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, Inf, \
/* Falloff */ 20, 30, \
/* Prune speed threshold */ 0.1, \
/* Base color */ VEC4(0.4, 0.3, 0.2, 1), \
/* Dry color factor */ VEC4(0.2, 0.1, 0.1, 1) \
) \
X( \
/* Name */ Spark, \
/* Flags */ V_ParticleFlag_StainWhenPruned, \
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ 0.2, 0.3, \
/* Falloff */ 10, 20, \
/* Prune speed threshold */ 0.1, \
/* Base color */ VEC4(2, 0.5, 0, 1), \
/* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \
) \
\
/* Air particles */ \
X( \
/* Name */ Smoke, \
/* Flags */ V_ParticleFlag_OnlyCollideWithWalls | V_ParticleFlag_GasBlend | V_ParticleFlag_FadeLifetime, \
/* Layer */ V_ParticleLayer_Air, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, Inf, \
/* Prune speed threshold */ 0.01, \
/* Base color */ VEC4(0.25, 0.25, 0.25, 0.75), \
/* Dry color factor */ VEC4(1, 1, 1, 1) \
) \
X( \
/* Name */ BulletSmoke, \
/* Flags */ V_ParticleFlag_OnlyCollideWithWalls | V_ParticleFlag_GasBlend | V_ParticleFlag_FadeLifetime, \
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ 0.075, 0.2, \
/* Falloff */ 0, 0, \
/* Prune speed threshold */ 0.00, \
/* Base color */ VEC4(0.8, 0.6, 0.2, 0.005), \
/* Dry color factor */ VEC4(1, 1, 1, 1) \
@ -138,6 +136,7 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Air, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ 0.0, .05, \
/* Falloff */ 0, 0, \
/* Prune speed threshold */ 0, \
/* Base color */ VEC4(10, 3.5, 0, 1), \
/* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \
@ -148,6 +147,7 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Air, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ 0.0, 0.05, \
/* Falloff */ 0, 0, \
/* Prune speed threshold */ 0, \
/* Base color */ VEC4(10, 3.5, 0, 1), \
/* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \
@ -158,6 +158,7 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Air, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ 0.075, 0.075, \
/* Falloff */ 0, 0, \
/* Prune speed threshold */ 0, \
/* Base color */ VEC4(3, 1.5, 0, 1), \
/* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \
@ -168,9 +169,21 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Air, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, Inf, \
/* Falloff */ 0, 0, \
/* Prune speed threshold */ 0.01, \
/* Base color */ VEC4(5, 1.75, 0.75, 1), \
/* Dry color factor */ VEC4(0.2, 0.1, 0.0, 1) \
) \
X( \
/* Name */ WallDust, \
/* Flags */ V_ParticleFlag_OnlyCollideWithWalls | V_ParticleFlag_GasBlend | V_ParticleFlag_FadeLifetime, \
/* Layer */ V_ParticleLayer_Air, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ 0.1, 0.25, \
/* Falloff */ 10, 20, \
/* Prune speed threshold */ 0.01, \
/* Base color */ VEC4(0.5, 0.5, 0.5, 0.35), \
/* Dry color factor */ VEC4(1, 1, 1, 1) \
) \
\
/* Test particles */ \
@ -180,6 +193,7 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, Inf, \
/* Falloff */ 0, 0, \
/* Prune speed threshold */ 0.01, \
/* Base color */ VEC4(1, 1, 0, 1), \
/* Dry color factor */ VEC4(1, 1, 1, 1) \
@ -228,6 +242,8 @@ Struct(V_ParticleDesc)
f32 pen_rate;
f32 lifetime_min;
f32 lifetime_max;
f32 falloff_min;
f32 falloff_max;
f32 prune_speed_threshold;
Vec4 base_color;
Vec4 dry_factor;
@ -244,14 +260,14 @@ Struct(V_ParticleDesc)
////////////////////////////////////////////////////////////
//~ Quad types
Enum(V_QuadFlag)
Enum(V_GpuQuadFlag)
{
V_QuadFlag_None = 0,
};
Struct(V_Quad)
Struct(V_GpuQuad)
{
V_QuadFlag flags;
V_GpuQuadFlag flags;
u32 occluder_id;
Affine quad_uv_to_world_af;
G_TextureRef tex;
@ -433,9 +449,6 @@ Struct(V_SharedFrame)
Vec2 move;
Vec2 look;
f32 fire_held;
f32 fire_presses;
f32 roll_presses;
//- Gpu data