diff --git a/src/pp/pp.c b/src/pp/pp.c index ef27b1a4..fdcb0206 100644 --- a/src/pp/pp.c +++ b/src/pp/pp.c @@ -1992,20 +1992,7 @@ void P_SpawnEntsFromList(P_Frame *frame, P_EntList ents) DllQueuePushNPZ(&P_NilEnt, frame->first_ent, frame->last_ent, dst, next, prev); DllQueuePushNP(bin->first, bin->last, dst, next_in_bin, prev_in_bin); } - { - P_Ent *old_next = dst->next; - P_Ent *old_prev = dst->prev; - P_Ent *old_next_in_bin = dst->next_in_bin; - P_Ent *old_prev_in_bin = dst->prev_in_bin; - { - *dst = *src; - dst->xf = NormXform(dst->xf); - } - dst->next = old_next; - dst->prev = old_prev; - dst->next_in_bin = old_next_in_bin; - dst->prev_in_bin = old_prev_in_bin; - } + dst->net_state = src->net_state; dst->created_at_ns = frame->time_ns; dst->created_at_tick = frame->tick; dst->sim = !P_tl.is_client; @@ -3189,11 +3176,11 @@ void P_StepFrame(P_Frame *frame) b32 is_bomb = 0; if (button == P_Button_PrimaryFire && (firer->control.held[button] || firer->control.downs[button])) { - // fire_rate = 100; - bullets_per_fire = 4; + fire_rate = 25; + bullets_per_fire = 5; // fire_rate = 50; - fire_rate = 50; - bullets_per_fire = 1; + // fire_rate = 50; + // bullets_per_fire = 1; firing = (weapon->last_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= frame->time_ns; if (firing) { @@ -3267,9 +3254,10 @@ void P_StepFrame(P_Frame *frame) ////////////////////////////// //- Bullet properties - // f32 spread = Tau * 0.05; + // f32 spread = Tau * 0.5; + f32 spread = Tau * 0.05; // f32 spread = Tau * 0.2; - f32 spread = Tau * 0.01; + // f32 spread = Tau * 0.01; // f32 spread = 0; b32 should_ricochet = 0; @@ -3754,54 +3742,58 @@ 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 && guy->health <= 0) + P_EntList ents_to_spawn = Zi; + for (P_Ent *guy = P_FirstEnt(frame); !P_IsEntNil(guy); guy = P_NextEnt(guy)) { - P_Ent *old_guy = P_EntFromKey(prev_frame, guy->key); - if (old_guy->health > 0) + if (guy->is_guy && 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 *old_guy = P_EntFromKey(prev_frame, guy->key); + if (old_guy->health > 0) { - if (player->is_player) + P_Ent *player = P_EntFromKey(frame, guy->source); + P_Ent *killer = P_EntFromKey(frame, guy->damage_attribution); + // Update kill info { - player->deaths += 1; + if (player->is_player) + { + player->deaths += 1; + } + if (killer->is_player && !P_MatchEntKey(player->key, killer->key)) + { + killer->kills += 1; + } + guy->exists = 0; + guy->continuity_gen += 1; + guy->health = 1; } - if (killer->is_player && !P_MatchEntKey(player->key, killer->key)) + // Push kill event { - killer->kills += 1; + 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_victim = player->key; + death->death_killer = killer->key; + death->lifetime_seconds = P_ObservationDurationSeconds; } - 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_victim = player->key; - death->death_killer = killer->key; - death->lifetime_seconds = P_ObservationDurationSeconds; } } } + P_SpawnEntsFromList(frame, ents_to_spawn); + } + + ////////////////////////////// + //- Smooth values + + for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + { + f32 lerp_rate = SaturateF32(25 * sim_dt); + ent->smoothed_move_dir = SlerpVec2(ent->smoothed_move_dir, NormVec2(ent->control.move), lerp_rate); } - P_SpawnEntsFromList(frame, ents_to_spawn); - } ////////////////////////////// //- Debug draw diff --git a/src/pp/pp.h b/src/pp/pp.h index 69f7c8bd..76b51b03 100644 --- a/src/pp/pp.h +++ b/src/pp/pp.h @@ -113,29 +113,13 @@ Struct(P_Control) f32 downs[P_Button_COUNT]; }; -Struct(P_Ent) +Struct(P_NetworkedEntState) { - //- Internal world state - - P_Ent *next; - P_Ent *prev; - - P_Ent *next_in_bin; - P_Ent *prev_in_bin; - //- Persistent data P_EntKey key; - u64 rand_seq; i64 created_at_ns; i64 created_at_tick; - f64 lifetime_seconds; - - //- Client data - - i64 initial_observation_time_ns; - i64 last_observation_time_ns; - b32 is_first_observation; //- Build data @@ -150,12 +134,15 @@ Struct(P_Ent) Xform xf; + f64 lifetime_seconds; + + u64 rand_seq; + //- Bullet b32 is_bullet; u32 bullet_hits_count; - //- Events b32 is_trail; @@ -242,6 +229,35 @@ Struct(P_Ent) Vec2 v; // Linear velocity f32 w; // Angular velocity + + //- Smoothed values + Vec2 smoothed_move_dir; +}; + +Struct(P_LocalEntState) +{ + //- Observation info + + i64 initial_observation_time_ns; + i64 last_observation_time_ns; + b32 is_first_observation; + + // Vec2 smoothed_v; + // Vec2 smoothed_v_dir; + // Vec2 smoothed_move_dir; + // f32 smoothed_w; +}; + +Struct(P_Ent) +{ + P_Ent *next; + P_Ent *prev; + + P_Ent *next_in_bin; + P_Ent *prev_in_bin; + + Embed(P_NetworkedEntState, net_state); + Embed(P_LocalEntState, local_state); }; Struct(P_EntListNode) diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index 14bdf544..d94616a8 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -794,7 +794,7 @@ void S_TickForever(WaveLaneCtx *lane) { // TODO: Delta compress should_transmit = 1; - BB_WriteBytes(&packer_bbw, StringFromStruct(ent)); + BB_WriteBytes(&packer_bbw, StringFromStruct(&ent->net_state)); } u64 delta_end = BB_GetNumBytesWritten(&packer_bbw); if (should_transmit) diff --git a/src/pp/pp_terms.h b/src/pp/pp_terms.h index 78ce7ad2..11150d0e 100644 --- a/src/pp/pp_terms.h +++ b/src/pp/pp_terms.h @@ -52,30 +52,30 @@ PERSIST Readonly String P_PresetHumanNames[] = { // Taken from a random GMOD server PERSIST Readonly String P_PresetPlayerNames[] = { + CompLit("lionberg"), + CompLit("charlie main"), + CompLit("frezh"), + CompLit("KARMA"), CompLit("Kirep"), + CompLit("Cyan Crayon"), + CompLit("THE WIFE"), + CompLit("Panda"), CompLit("adoti"), + CompLit("yoyota"), + CompLit("Mr. Bones"), CompLit("TaurusJ3"), CompLit("dub"), CompLit("Tidunbly"), CompLit("Siepter"), - CompLit("frezh"), CompLit("lowayo"), CompLit("Zunix"), CompLit("_Runne_"), CompLit("Fr0stie"), - CompLit("Mr. Bones"), CompLit("Lumby"), CompLit("Legs"), CompLit("Talids"), - CompLit("yoyota"), CompLit("Train"), - CompLit("lionberg"), - CompLit("Cyan Crayon"), CompLit("Poy"), CompLit("Kaitsedd"), - CompLit("Panda"), - CompLit("THE WIFE"), - CompLit("KARMA"), CompLit("jiyu"), - CompLit("charlie main"), }; diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 217e1efd..240f9756 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -1822,11 +1822,11 @@ void V_TickForever(WaveLaneCtx *lane) while (!done && BB_NumBitsRemaining(&bbr) > 0) { // TODO: Delta compress - P_Ent *raw_ent = (P_Ent *)BB_ReadBytesRaw(&bbr, sizeof(P_Ent)); - if (raw_ent) + P_NetworkedEntState *raw_net_state = (P_NetworkedEntState *)BB_ReadBytesRaw(&bbr, sizeof(P_NetworkedEntState)); + if (raw_net_state) { P_EntListNode tmp_ent_node = Zi; - CopyStruct(&tmp_ent_node.ent, raw_ent); + CopyStruct(&tmp_ent_node.ent.net_state, raw_net_state); P_EntList ent_list = Zi; ent_list.first = &tmp_ent_node; ent_list.last = &tmp_ent_node; @@ -2429,8 +2429,10 @@ void V_TickForever(WaveLaneCtx *lane) ent->xf.t = LerpVec2(left->xf.t, right->xf.t, blend_t); ent->xf.r = SlerpVec2(left->xf.r, right->xf.r, blend_t); ent->walk_time_accum_ns = LerpI64(left->walk_time_accum_ns, right->walk_time_accum_ns, blend_t); + ent->fire_time_accum_ns = LerpI64(left->fire_time_accum_ns, right->fire_time_accum_ns, blend_t); ent->v = LerpVec2(left->v, right->v, blend_t); ent->w = LerpF32(left->w, right->w, blend_t); + ent->smoothed_move_dir = SlerpVec2(left->smoothed_move_dir, right->smoothed_move_dir, blend_t); } } } @@ -2456,6 +2458,8 @@ void V_TickForever(WaveLaneCtx *lane) { P_EntKey key = ent->key; i64 expiration_ns = NsFromSeconds(P_ObservationDurationSeconds); + + //- Fetch observation V_Observation *obs = 0; { V_ObservationBin *bin = &V.observation_bins[key.v % countof(V.observation_bins)]; @@ -2499,6 +2503,8 @@ void V_TickForever(WaveLaneCtx *lane) } obs->last_observation_time_ns = frame->time_ns; } + + //- Observe ent->last_observation_time_ns = frame->time_ns; ent->is_first_observation = obs->initial_observation_time_ns == frame->time_ns; } @@ -2897,7 +2903,8 @@ void V_TickForever(WaveLaneCtx *lane) SPR_Sprite legs = Zi; Affine legs_pix_to_world_af = AffineIdentity; { - Vec2 legs_dir = NormVec2(ent->control.move); + // Vec2 legs_dir = NormVec2(ent->control.move); + Vec2 legs_dir = ent->smoothed_move_dir; if (P_IsEntRolling(local_frame, ent)) { legs_dir = ent->xf.r; @@ -3441,10 +3448,10 @@ void V_TickForever(WaveLaneCtx *lane) //- Wall impact particles if (material != P_MaterialKind_Flesh) { - // Hot debris + //- Debris { V_Emitter emitter = Zi; - emitter.kind = V_ParticleKind_HotDebris; + emitter.kind = V_ParticleKind_Debris; emitter.count = 32; f32 angle = AngleFromVec2(impact_dir); @@ -3466,13 +3473,13 @@ void V_TickForever(WaveLaneCtx *lane) - //- Wall spark + //- Hot debris { V_Emitter emitter = Zi; - emitter.kind = V_ParticleKind_Spark; + emitter.kind = V_ParticleKind_HotDebris; // emitter.count = MaxF32(1000 * frame->dt, 1); // emitter.count = 128; - emitter.count = 1; + emitter.count = 32; f32 angle = AngleFromVec2(impact_dir); @@ -3668,12 +3675,16 @@ void V_TickForever(WaveLaneCtx *lane) // f32 speed = 100; f32 speed_spread = speed * 2; - emitter.pos.p0 = emitter.pos.p1 = frame->world_cursor; + f32 particles_per_meter_per_second = Kibi(128); + emitter.pos.p0 = prev_frame->world_cursor; + emitter.pos.p1 = frame->world_cursor; + f32 len_meters = MaxF32(Vec2Len(SubVec2(emitter.pos.p1, emitter.pos.p0)), 1); + emitter.count = particles_per_meter_per_second * len_meters * frame->dt; + 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; V_PushParticles(emitter); } @@ -3733,26 +3744,18 @@ void V_TickForever(WaveLaneCtx *lane) f32 speed = 100; f32 speed_spread = speed * 2; - emitter.pos.p0 = emitter.pos.p1 = frame->world_cursor; + f32 particles_per_meter_per_second = Kibi(128); + + emitter.pos.p0 = prev_frame->world_cursor; + emitter.pos.p1 = frame->world_cursor; + f32 len_meters = MaxF32(Vec2Len(SubVec2(emitter.pos.p1, emitter.pos.p0)), 1); + emitter.count = particles_per_meter_per_second * len_meters * frame->dt; + 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.falloff.min = emitter.falloff.max = 0; - - // emitter.count = CeilF32(Kibi(64) * frame->dt); - // emitter.count = CeilF32(Mebi(32) * frame->dt); - // emitter.count = CeilF32(Mebi(8) * frame->dt); - // emitter.count = Mebi(16); - // emitter.count = Mebi(2); - // emitter.count = Kibi(32); - emitter.count = Kibi(8); - // emitter.count = 128; - // emitter.count = 128; - // emitter.count = 32; - // emitter.count = 1; - V_PushParticles(emitter); } @@ -5619,10 +5622,10 @@ void V_TickForever(WaveLaneCtx *lane) // TODO: Remove this - if (frame->tick == 1) - { - frame->show_consoles = 1; - } + // if (frame->tick == 1) + // { + // frame->show_consoles = 1; + // } diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index 8343d68c..d5914a6e 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -378,6 +378,7 @@ Struct(V_Observation) V_Observation *prev; V_Observation *next_in_bin; V_Observation *prev_in_bin; + u64 key; i64 initial_observation_time_ns; i64 last_observation_time_ns; diff --git a/src/pp/pp_vis/pp_vis_shared.cgh b/src/pp/pp_vis/pp_vis_shared.cgh index 8ef9176f..70c23d68 100644 --- a/src/pp/pp_vis/pp_vis_shared.cgh +++ b/src/pp/pp_vis/pp_vis_shared.cgh @@ -79,10 +79,10 @@ Enum(V_ParticleLayer) /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ Inf, Inf, \ - /* Falloff */ 10, 20, \ - /* Prune speed threshold */ 0.01, \ + /* Falloff */ 20, 30, \ + /* Prune speed threshold */ 0.1, \ /* Base color */ VEC4(0.4, 0.3, 0.2, 1), \ - /* Dry color factor */ VEC4(1, 1, 1, 1) \ + /* Dry color factor */ VEC4(0.2, 0.1, 0.1, 1) \ ) \ X( \ /* Name */ Fire, \ @@ -103,12 +103,12 @@ Enum(V_ParticleLayer) /* Lifetime */ Inf, Inf, \ /* Falloff */ 20, 30, \ /* Prune speed threshold */ 0.1, \ - /* Base color */ VEC4(0.4, 0.3, 0.2, 1), \ + /* Base color */ VEC4(2, 0.5, 0, 1), \ /* Dry color factor */ VEC4(0.2, 0.1, 0.1, 1) \ ) \ X( \ /* Name */ Spark, \ - /* Flags */ V_ParticleFlag_StainWhenPruned, \ + /* Flags */ V_ParticleFlag_None, \ /* Layer */ V_ParticleLayer_Mid, \ /* Stain rate, pen chance */ 0, 0, \ /* Lifetime */ 0.2, 0.3, \