distinct bullet hit entities
This commit is contained in:
parent
a76cfc5dfd
commit
18ad1fb69e
@ -145,6 +145,17 @@ f64 CR_FloatFromString(String str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String whole_str = STRING(str.len - whole_start_idx, &str.text[whole_start_idx]);
|
||||||
|
if (MatchString(whole_str, Lit("inf")))
|
||||||
|
{
|
||||||
|
result = Inf * sign;
|
||||||
|
}
|
||||||
|
else if (MatchString(whole_str, Lit("NaN")))
|
||||||
|
{
|
||||||
|
result = Nan;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Find decimal place
|
// Find decimal place
|
||||||
u64 frac_start_idx = whole_start_idx;
|
u64 frac_start_idx = whole_start_idx;
|
||||||
for (; ok && frac_start_idx < str.len; ++frac_start_idx)
|
for (; ok && frac_start_idx < str.len; ++frac_start_idx)
|
||||||
@ -203,7 +214,7 @@ f64 CR_FloatFromString(String str)
|
|||||||
{
|
{
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
38
src/pp/pp.c
38
src/pp/pp.c
@ -3184,6 +3184,8 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
|
|
||||||
// TODO: Separate 'hits' from bullets, so that bullets can have multiple hits
|
// TODO: Separate 'hits' from bullets, so that bullets can have multiple hits
|
||||||
|
|
||||||
|
{
|
||||||
|
P_EntList hits_to_spawn = Zi;
|
||||||
for (P_Ent *bullet = P_FirstEnt(frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
for (P_Ent *bullet = P_FirstEnt(frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||||
{
|
{
|
||||||
if (bullet->is_bullet)
|
if (bullet->is_bullet)
|
||||||
@ -3359,9 +3361,9 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
|
|
||||||
P_EntKey victim_key = Zi;
|
P_EntKey victim_key = Zi;
|
||||||
P_RaycastResult victim_raycast = Zi;
|
P_RaycastResult victim_raycast = Zi;
|
||||||
b32 hit = 0;
|
b32 has_hit = 0;
|
||||||
{
|
{
|
||||||
for (BulletPath *path = first_bullet_path; path && !hit; path = path->next)
|
for (BulletPath *path = first_bullet_path; path && !has_hit; path = path->next)
|
||||||
{
|
{
|
||||||
Vec2 path_dir = SubVec2(path->end, path->start);
|
Vec2 path_dir = SubVec2(path->end, path->start);
|
||||||
P_Space *cast_spaces[] = {
|
P_Space *cast_spaces[] = {
|
||||||
@ -3406,7 +3408,7 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
closest_len_sq = len_sq;
|
closest_len_sq = len_sq;
|
||||||
victim_key = potential_victim_key;
|
victim_key = potential_victim_key;
|
||||||
victim_raycast = entrance_raycast;
|
victim_raycast = entrance_raycast;
|
||||||
hit = 1;
|
has_hit = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3416,28 +3418,30 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
}
|
}
|
||||||
P_Ent *victim = P_EntFromKey(frame, victim_key);
|
P_Ent *victim = P_EntFromKey(frame, victim_key);
|
||||||
|
|
||||||
bullet->has_hit = 0;
|
// Create hit
|
||||||
|
|
||||||
Vec2 final_pos = p1;
|
Vec2 final_pos = p1;
|
||||||
if (hit)
|
if (has_hit)
|
||||||
{
|
{
|
||||||
Vec2 normal = victim_raycast.normal;
|
Vec2 normal = victim_raycast.normal;
|
||||||
|
bullet->bullet_hits_count += 1;
|
||||||
|
|
||||||
bullet->has_hit = 1;
|
P_Ent *hit = P_PushTempEnt(scratch.arena, &hits_to_spawn);
|
||||||
bullet->hit_entry = victim_raycast.p;
|
{
|
||||||
bullet->hit_entry_normal = normal;
|
hit->key = P_EntKeyFromU64(MixU64s(bullet->key.v, P_BulletHitBasis + bullet->bullet_hits_count));
|
||||||
|
hit->is_hit = 1;
|
||||||
|
hit->hit_entry = victim_raycast.p;
|
||||||
|
hit->hit_entry_normal = normal;
|
||||||
|
hit->lifetime_seconds = P_ObservationDurationSeconds;
|
||||||
// FIXME: Use relative velocity at collision point
|
// FIXME: Use relative velocity at collision point
|
||||||
bullet->hit_entry_velocity = bullet->v;
|
hit->hit_entry_velocity = bullet->v;
|
||||||
|
|
||||||
// bullet->bullet_end = bullet->hit_entry;
|
|
||||||
if (victim->is_guy)
|
if (victim->is_guy)
|
||||||
{
|
{
|
||||||
bullet->hit_material = P_MaterialKind_Flesh;
|
hit->hit_material = P_MaterialKind_Flesh;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bullet->hit_material = P_MaterialKind_Wall;
|
hit->hit_material = P_MaterialKind_Wall;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reflect velocity along normal
|
// Reflect velocity along normal
|
||||||
@ -3452,7 +3456,7 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
f32 collision_offset = 0.01; // Tiny offset along normal to prevent collision with the victim during ricochets
|
f32 collision_offset = 0.01; // Tiny offset along normal to prevent collision with the victim during ricochets
|
||||||
final_pos = AddVec2(bullet->hit_entry, MulVec2(bullet->hit_entry_normal, collision_offset));
|
final_pos = AddVec2(hit->hit_entry, MulVec2(hit->hit_entry_normal, collision_offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
bullet->xf.t = final_pos;
|
bullet->xf.t = final_pos;
|
||||||
@ -3485,6 +3489,8 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
P_SpawnEntsFromList(frame, hits_to_spawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
15
src/pp/pp.h
15
src/pp/pp.h
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#define P_WallShapeIDBasis 0x40d501b4cf6d4f0cull
|
#define P_WallShapeIDBasis 0x40d501b4cf6d4f0cull
|
||||||
#define P_BulletSpreadBasis 0xc3b72fe38ca5a1d6ull
|
#define P_BulletSpreadBasis 0xc3b72fe38ca5a1d6ull
|
||||||
|
#define P_BulletHitBasis 0xbc70fc783c1c507full
|
||||||
|
|
||||||
Struct(P_EntKey)
|
Struct(P_EntKey)
|
||||||
{
|
{
|
||||||
@ -84,7 +85,7 @@ Struct(P_DebugDrawNode)
|
|||||||
#define P_RollTimeNs NsFromSeconds(0.5)
|
#define P_RollTimeNs NsFromSeconds(0.5)
|
||||||
#define P_RollTurnTimeNs (NsFromSeconds(0.1))
|
#define P_RollTurnTimeNs (NsFromSeconds(0.1))
|
||||||
#define P_RollTimeoutNs NsFromSeconds(0.5)
|
#define P_RollTimeoutNs NsFromSeconds(0.5)
|
||||||
#define P_ObservationLifetimeNs NsFromSeconds(2)
|
#define P_ObservationDurationSeconds 1
|
||||||
|
|
||||||
Struct(P_Control)
|
Struct(P_Control)
|
||||||
{
|
{
|
||||||
@ -121,8 +122,9 @@ Struct(P_Ent)
|
|||||||
|
|
||||||
//- Client data
|
//- Client data
|
||||||
|
|
||||||
i64 observation_time_ns;
|
i64 initial_observation_time_ns;
|
||||||
b32 has_observed;
|
i64 last_observation_time_ns;
|
||||||
|
b32 is_first_observation;
|
||||||
|
|
||||||
//- Build data
|
//- Build data
|
||||||
|
|
||||||
@ -137,11 +139,14 @@ Struct(P_Ent)
|
|||||||
|
|
||||||
Xform xf;
|
Xform xf;
|
||||||
|
|
||||||
//- Bullet / hit
|
//- Bullet
|
||||||
|
|
||||||
b32 is_bullet;
|
b32 is_bullet;
|
||||||
|
u32 bullet_hits_count;
|
||||||
|
|
||||||
b32 has_hit;
|
//- Hit
|
||||||
|
|
||||||
|
b32 is_hit;
|
||||||
Vec2 hit_entry;
|
Vec2 hit_entry;
|
||||||
Vec2 hit_entry_normal;
|
Vec2 hit_entry_normal;
|
||||||
Vec2 hit_entry_velocity;
|
Vec2 hit_entry_velocity;
|
||||||
|
|||||||
@ -23,7 +23,7 @@ String P_PackWorld(Arena *arena, P_World *src_world)
|
|||||||
{
|
{
|
||||||
// TODO: Pack ignored ents
|
// TODO: Pack ignored ents
|
||||||
b32 ignore = 0;
|
b32 ignore = 0;
|
||||||
if (ent->is_weapon || ent->is_bullet || ent->is_bomb)
|
if (ent->is_weapon || ent->is_bullet || ent->is_bomb || ent->is_hit)
|
||||||
{
|
{
|
||||||
ignore = 1;
|
ignore = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1895,14 +1895,16 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Observe entities
|
//- Observe entities
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
P_EntKey key = ent->key;
|
P_EntKey key = ent->key;
|
||||||
i64 expiration_ns = P_ObservationLifetimeNs;
|
i64 expiration_ns = NsFromSeconds(P_ObservationDurationSeconds);
|
||||||
i64 observation_time_ns = 0;
|
V_Observation *obs = 0;
|
||||||
{
|
{
|
||||||
V_ObservationBin *bin = &V.observation_bins[key.v % countof(V.observation_bins)];
|
V_ObservationBin *bin = &V.observation_bins[key.v % countof(V.observation_bins)];
|
||||||
V_Observation *obs = bin->first;
|
obs = bin->first;
|
||||||
for (; obs; obs = obs->next)
|
for (; obs; obs = obs->next)
|
||||||
{
|
{
|
||||||
if (obs->key == key.v)
|
if (obs->key == key.v)
|
||||||
@ -1910,19 +1912,20 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obs)
|
if (obs)
|
||||||
{
|
{
|
||||||
if (obs->time_ns + expiration_ns > frame->time_ns)
|
if (frame->time_ns > obs->last_observation_time_ns + expiration_ns)
|
||||||
{
|
{
|
||||||
// Re-observe matching expired observation
|
// Observation expired, re-init
|
||||||
|
obs->initial_observation_time_ns = frame->time_ns;
|
||||||
|
}
|
||||||
DllQueueRemove(V.first_observation, V.last_observation, obs);
|
DllQueueRemove(V.first_observation, V.last_observation, obs);
|
||||||
DllQueuePush(V.first_observation, V.last_observation, obs);
|
DllQueuePush(V.first_observation, V.last_observation, obs);
|
||||||
obs->time_ns = frame->time_ns;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (V.first_observation && V.first_observation->time_ns + expiration_ns <= frame->time_ns)
|
if (V.first_observation && frame->time_ns > V.first_observation->last_observation_time_ns + expiration_ns)
|
||||||
{
|
{
|
||||||
// Remove expired observation for reuse
|
// Remove expired observation for reuse
|
||||||
obs = V.first_observation;
|
obs = V.first_observation;
|
||||||
@ -1935,14 +1938,14 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
obs = PushStruct(perm, V_Observation);
|
obs = PushStruct(perm, V_Observation);
|
||||||
}
|
}
|
||||||
obs->key = key.v;
|
obs->key = key.v;
|
||||||
obs->time_ns = frame->time_ns;
|
obs->initial_observation_time_ns = frame->time_ns;
|
||||||
DllQueuePush(V.first_observation, V.last_observation, obs);
|
DllQueuePush(V.first_observation, V.last_observation, obs);
|
||||||
DllQueuePushNP(bin->first, bin->last, obs, next_in_bin, prev_in_bin);
|
DllQueuePushNP(bin->first, bin->last, obs, next_in_bin, prev_in_bin);
|
||||||
}
|
}
|
||||||
observation_time_ns = obs->time_ns;
|
obs->last_observation_time_ns = frame->time_ns;
|
||||||
}
|
}
|
||||||
ent->observation_time_ns = observation_time_ns;
|
ent->last_observation_time_ns = frame->time_ns;
|
||||||
ent->has_observed = observation_time_ns < frame->time_ns;
|
ent->is_first_observation = obs->initial_observation_time_ns == frame->time_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1950,6 +1953,61 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
|
// {
|
||||||
|
// P_EntKey key = ent->key;
|
||||||
|
// i64 expiration_ns = P_ObservationLifetimeNs;
|
||||||
|
// i64 observation_time_ns = 0;
|
||||||
|
// {
|
||||||
|
// V_ObservationBin *bin = &V.observation_bins[key.v % countof(V.observation_bins)];
|
||||||
|
// V_Observation *obs = bin->first;
|
||||||
|
// for (; obs; obs = obs->next)
|
||||||
|
// {
|
||||||
|
// if (obs->key == key.v)
|
||||||
|
// {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (obs)
|
||||||
|
// {
|
||||||
|
// if (obs->time_ns + expiration_ns > frame->time_ns)
|
||||||
|
// {
|
||||||
|
// // Re-observe matching expired observation
|
||||||
|
// DllQueueRemove(V.first_observation, V.last_observation, obs);
|
||||||
|
// DllQueuePush(V.first_observation, V.last_observation, obs);
|
||||||
|
// obs->time_ns = frame->time_ns;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// if (V.first_observation && V.first_observation->time_ns + expiration_ns <= frame->time_ns)
|
||||||
|
// {
|
||||||
|
// // Remove expired observation for reuse
|
||||||
|
// obs = V.first_observation;
|
||||||
|
// V_ObservationBin *old_bin = &V.observation_bins[obs->key % countof(V.observation_bins)];
|
||||||
|
// DllQueueRemove(V.first_observation, V.last_observation, obs);
|
||||||
|
// DllQueueRemoveNP(old_bin->first, old_bin->last, obs, next_in_bin, prev_in_bin);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// obs = PushStruct(perm, V_Observation);
|
||||||
|
// }
|
||||||
|
// obs->key = key.v;
|
||||||
|
// obs->time_ns = frame->time_ns;
|
||||||
|
// DllQueuePush(V.first_observation, V.last_observation, obs);
|
||||||
|
// DllQueuePushNP(bin->first, bin->last, obs, next_in_bin, prev_in_bin);
|
||||||
|
// }
|
||||||
|
// observation_time_ns = obs->time_ns;
|
||||||
|
// }
|
||||||
|
// ent->observation_time_ns = observation_time_ns;
|
||||||
|
// ent->has_observed = observation_time_ns < frame->time_ns;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -2483,80 +2541,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// //////////////////////////////
|
|
||||||
// //- Push test bullet particles
|
|
||||||
|
|
||||||
// // TODO: Not like this
|
|
||||||
|
|
||||||
// for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
|
||||||
// {
|
|
||||||
// if (bullet->is_bullet)
|
|
||||||
// {
|
|
||||||
// // 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;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Push test impact particles
|
//- Push test impact particles
|
||||||
|
|
||||||
@ -2566,24 +2550,15 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
// if (0)
|
// if (0)
|
||||||
{
|
{
|
||||||
for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
for (P_Ent *hit = P_FirstEnt(local_frame); !P_IsEntNil(hit); hit = P_NextEnt(hit))
|
||||||
{
|
{
|
||||||
if (bullet->is_bullet && bullet->has_hit)
|
if (hit->is_hit && hit->is_first_observation)
|
||||||
{
|
{
|
||||||
// FIXME: Use actual velocity
|
P_MaterialKind material = hit->hit_material;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
P_MaterialKind material = bullet->hit_material;
|
Vec2 hit_entry = hit->hit_entry;
|
||||||
|
Vec2 hit_entry_normal = hit->hit_entry_normal;
|
||||||
Vec2 hit_entry = bullet->hit_entry;
|
Vec2 hit_entry_velocity = hit->hit_entry_velocity;
|
||||||
Vec2 hit_entry_normal = bullet->hit_entry_normal;
|
|
||||||
Vec2 hit_entry_velocity = bullet->hit_entry_velocity;
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Wall particles
|
//- Wall particles
|
||||||
@ -2699,6 +2674,232 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// //////////////////////////////
|
||||||
|
// //- Push test bullet particles
|
||||||
|
|
||||||
|
// // TODO: Not like this
|
||||||
|
|
||||||
|
// for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||||
|
// {
|
||||||
|
// if (bullet->is_bullet)
|
||||||
|
// {
|
||||||
|
// // 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;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// //////////////////////////////
|
||||||
|
// //- Push test impact particles
|
||||||
|
|
||||||
|
// // TODO: Not like this
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // if (0)
|
||||||
|
// {
|
||||||
|
// for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||||
|
// {
|
||||||
|
// if (bullet->is_bullet && bullet->has_hit)
|
||||||
|
// {
|
||||||
|
// // FIXME: Use actual velocity
|
||||||
|
// 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;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// P_MaterialKind material = bullet->hit_material;
|
||||||
|
|
||||||
|
// Vec2 hit_entry = bullet->hit_entry;
|
||||||
|
// Vec2 hit_entry_normal = bullet->hit_entry_normal;
|
||||||
|
// Vec2 hit_entry_velocity = bullet->hit_entry_velocity;
|
||||||
|
|
||||||
|
// //////////////////////////////
|
||||||
|
// //- Wall particles
|
||||||
|
|
||||||
|
// if (material != P_MaterialKind_Flesh)
|
||||||
|
// {
|
||||||
|
// //- Wall debris
|
||||||
|
// {
|
||||||
|
// V_Emitter emitter = Zi;
|
||||||
|
// {
|
||||||
|
// // emitter.flags |= V_ParticleFlag_PruneWhenStill;
|
||||||
|
// // emitter.flags |= V_ParticleFlag_StainOnPrune;
|
||||||
|
|
||||||
|
|
||||||
|
// emitter.kind = V_ParticleKind_Debris;
|
||||||
|
// emitter.count = 4;
|
||||||
|
|
||||||
|
// emitter.pos.p0 = emitter.pos.p1 = hit_entry;
|
||||||
|
|
||||||
|
// emitter.speed.min = 0;
|
||||||
|
// emitter.speed.max = 20;
|
||||||
|
|
||||||
|
// // emitter.velocity_falloff = 5;
|
||||||
|
// // emitter.velocity_falloff_spread = emitter.velocity_falloff_spread * 1.5;
|
||||||
|
|
||||||
|
// Vec2 dir = hit_entry_normal;
|
||||||
|
|
||||||
|
// f32 angle = AngleFromVec2(dir);
|
||||||
|
// f32 angle_spread = Tau * 0.5;
|
||||||
|
|
||||||
|
// emitter.angle.min = angle - angle_spread / 2;
|
||||||
|
// emitter.angle.max = angle + angle_spread / 2;
|
||||||
|
|
||||||
|
// // emitter.lifetime = 0.25;
|
||||||
|
// // emitter.lifetime = 0.05;
|
||||||
|
// // emitter.lifetime = 0.04;
|
||||||
|
// // emitter.lifetime_spread = emitter.lifetime * 2;
|
||||||
|
// }
|
||||||
|
// V_PushParticles(emitter);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //- Wall dust
|
||||||
|
// // {
|
||||||
|
// // V_Emitter emitter = Zi;
|
||||||
|
// // {
|
||||||
|
// // emitter.kind = V_ParticleKind_Smoke;
|
||||||
|
// // emitter.count = 128;
|
||||||
|
|
||||||
|
// // emitter.pos.p0 = emitter.pos.p1 = hit_entry;
|
||||||
|
|
||||||
|
// // // emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.5, 0.5, 0.75));
|
||||||
|
|
||||||
|
// // emitter.speed.min = 10;
|
||||||
|
// // emitter.speed.max = 20;
|
||||||
|
|
||||||
|
// // // 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;
|
||||||
|
|
||||||
|
// // emitter.angle.min = angle - angle_spread / 2;
|
||||||
|
// // emitter.angle.max = angle + angle_spread / 2;
|
||||||
|
|
||||||
|
// // }
|
||||||
|
// // V_PushParticles(emitter);
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //////////////////////////////
|
||||||
|
// //- Blood particles
|
||||||
|
|
||||||
|
// if (material == P_MaterialKind_Flesh)
|
||||||
|
// {
|
||||||
|
// {
|
||||||
|
// V_Emitter emitter = Zi;
|
||||||
|
|
||||||
|
// emitter.kind = V_ParticleKind_BloodTrail;
|
||||||
|
// // emitter.kind = V_ParticleKind_BloodDebris;
|
||||||
|
|
||||||
|
// Vec2 dir = NormVec2(NegVec2(hit_entry_velocity));
|
||||||
|
|
||||||
|
// f32 angle = AngleFromVec2(dir);
|
||||||
|
// // f32 angle = 0;
|
||||||
|
// // f32 angle_spread = Tau * 0.25;
|
||||||
|
// f32 angle_spread = TweakFloat("Emitter angle spread", 0.1, 0, 1) * Tau;
|
||||||
|
// // 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 = hit_entry;
|
||||||
|
// 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 = TweakFloat("Emitter count", 1, 0, 100) * (Kibi(1) * frame->dt);
|
||||||
|
// V_PushParticles(emitter);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // V_DrawPoint(victim_raycast.p, Color_Green);
|
||||||
|
// // V_DrawLine(victim_raycast.p, AddVec2(victim_raycast.p, MulVec2(victim_raycast.normal, 0.5)), Color_White);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Push test emitter
|
//- Push test emitter
|
||||||
|
|
||||||
|
|||||||
@ -239,7 +239,8 @@ Struct(V_Observation)
|
|||||||
V_Observation *next_in_bin;
|
V_Observation *next_in_bin;
|
||||||
V_Observation *prev_in_bin;
|
V_Observation *prev_in_bin;
|
||||||
u64 key;
|
u64 key;
|
||||||
i64 time_ns;
|
i64 initial_observation_time_ns;
|
||||||
|
i64 last_observation_time_ns;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_ObservationBin)
|
Struct(V_ObservationBin)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user