bomb ricochet
This commit is contained in:
parent
62776720c3
commit
e6d842227f
@ -1151,16 +1151,10 @@ Vec2 MulXformVec2(Xform xf, Vec2 v)
|
||||
|
||||
Xform NormXform(Xform xf)
|
||||
{
|
||||
xf.r = NormRot(xf.r);
|
||||
xf.r = NormVec2(xf.r);
|
||||
return xf;
|
||||
}
|
||||
|
||||
Vec2 NormRot(Vec2 r)
|
||||
{
|
||||
r = Vec2WithLen(r, 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Line
|
||||
|
||||
|
||||
@ -525,7 +525,6 @@ Xform InvertXform(Xform xf);
|
||||
Vec2 MulXformVec2(Xform xf, Vec2 v);
|
||||
|
||||
Xform NormXform(Xform xf);
|
||||
Vec2 NormRot(Vec2 r);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Line
|
||||
|
||||
626
src/pp/pp.c
626
src/pp/pp.c
@ -70,6 +70,11 @@ P_ConstraintKey P_ConstraintKeyFromU64s(u64 a, u64 b)
|
||||
return (P_ConstraintKey) { .v = MixU64s(a, b) };
|
||||
}
|
||||
|
||||
P_EntKey P_EntKeyFromU64(u64 v)
|
||||
{
|
||||
return (P_EntKey) { .v = v };
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Rand helpers
|
||||
|
||||
@ -1525,7 +1530,9 @@ void P_UniqueSpaceEntriesFromRay(Arena *arena, P_SpaceEntryList *result, i32 spa
|
||||
|
||||
Vec2I32 dda_pos = dda_start;
|
||||
b32 done = 0;
|
||||
while (!done)
|
||||
u32 max_iterations = 512;
|
||||
u32 iteration_idx = 0;
|
||||
for (; iteration_idx < max_iterations && !done; ++iteration_idx)
|
||||
{
|
||||
if (dda_pos.x >= 0 && dda_pos.y >= 0 && dda_pos.x < P_WorldPitch && dda_pos.y < P_WorldPitch)
|
||||
{
|
||||
@ -1592,6 +1599,12 @@ void P_UniqueSpaceEntriesFromRay(Arena *arena, P_SpaceEntryList *result, i32 spa
|
||||
t_max.y += t_delta.y;
|
||||
}
|
||||
}
|
||||
|
||||
if (iteration_idx >= max_iterations)
|
||||
{
|
||||
// This should never happen unless we have a bug in the algorithm
|
||||
Assert(0);
|
||||
}
|
||||
}
|
||||
EndScratch(scratch);
|
||||
}
|
||||
@ -2241,7 +2254,7 @@ void P_StepFrame(P_Frame *frame)
|
||||
weapon->is_weapon = 1;
|
||||
weapon->key = P_RandEntKey();
|
||||
weapon->source = guy->key;
|
||||
// weapon->is_uzi = 1;
|
||||
// weapon->1is_uzi = 1;
|
||||
weapon->is_launcher = 1;
|
||||
guy->weapon = weapon->key;
|
||||
}
|
||||
@ -2300,8 +2313,8 @@ void P_StepFrame(P_Frame *frame)
|
||||
if (frame->time_ns - roll_timeout_ns - roll_time_ns > guy->last_roll_time_ns || guy->last_roll_time_ns == 0)
|
||||
{
|
||||
guy->last_roll_time_ns = frame->time_ns;
|
||||
// guy->last_roll_dir = NormRot(guy->control.move);
|
||||
guy->last_roll_dir = NormRot(guy->control.look);
|
||||
// guy->last_roll_dir = NormVec2(guy->control.move);
|
||||
guy->last_roll_dir = NormVec2(guy->control.look);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2318,15 +2331,15 @@ void P_StepFrame(P_Frame *frame)
|
||||
|
||||
// Dampen movement
|
||||
{
|
||||
if (Vec2Len(guy->solved_v) > 0.001)
|
||||
if (Vec2Len(guy->v) > 0.001)
|
||||
{
|
||||
f32 damp_force = TweakFloat("Guy damp force", 50, 0, 100);
|
||||
Vec2 damp = MulVec2(NegVec2(guy->solved_v), damp_force * sim_dt);
|
||||
guy->solved_v = AddVec2(guy->solved_v, damp);
|
||||
Vec2 damp = MulVec2(NegVec2(guy->v), damp_force * sim_dt);
|
||||
guy->v = AddVec2(guy->v, damp);
|
||||
}
|
||||
else
|
||||
{
|
||||
guy->solved_v = VEC2(0, 0);
|
||||
guy->v = VEC2(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2341,8 +2354,8 @@ void P_StepFrame(P_Frame *frame)
|
||||
b32 is_rolling = P_IsEntRolling(frame, guy);
|
||||
if (is_rolling)
|
||||
{
|
||||
// Vec2 roll_dir = NormRot(guy->last_roll_dir);
|
||||
Vec2 roll_dir = NormRot(guy->xf.r);
|
||||
// Vec2 roll_dir = NormVec2(guy->last_roll_dir);
|
||||
Vec2 roll_dir = NormVec2(guy->xf.r);
|
||||
|
||||
move = roll_dir;
|
||||
// look = roll_dir;
|
||||
@ -2359,14 +2372,14 @@ void P_StepFrame(P_Frame *frame)
|
||||
|
||||
// Integrate linear movement
|
||||
{
|
||||
Vec2 new_velocity = guy->solved_v;
|
||||
Vec2 new_velocity = guy->v;
|
||||
new_velocity = AddVec2(new_velocity, MulVec2(move, move_force * sim_dt));
|
||||
if (Vec2Len(new_velocity) > max_speed)
|
||||
{
|
||||
new_velocity = Vec2WithLen(new_velocity, max_speed);
|
||||
}
|
||||
|
||||
guy->solved_v = new_velocity;
|
||||
guy->v = new_velocity;
|
||||
}
|
||||
|
||||
// Integrate look
|
||||
@ -2375,7 +2388,7 @@ void P_StepFrame(P_Frame *frame)
|
||||
f32 desired_angle = AngleFromVec2(look);
|
||||
f32 diff = UnwindAngleF32(desired_angle - cur_angle);
|
||||
f32 look_force = 1.0 / (sim_dt * sim_dt) * turn_rate;
|
||||
guy->solved_w = diff * sim_dt * look_force;
|
||||
guy->w = diff * sim_dt * look_force;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2680,10 +2693,10 @@ void P_StepFrame(P_Frame *frame)
|
||||
P_Ent *ent0 = P_EntFromKey(frame, constraint->ent0);
|
||||
P_Ent *ent1 = P_EntFromKey(frame, constraint->ent1);
|
||||
|
||||
Vec2 v0 = ent0->solved_v;
|
||||
Vec2 v1 = ent1->solved_v;
|
||||
f32 w0 = ent0->solved_w;
|
||||
f32 w1 = ent1->solved_w;
|
||||
Vec2 v0 = ent0->v;
|
||||
Vec2 v1 = ent1->v;
|
||||
f32 w0 = ent0->w;
|
||||
f32 w1 = ent1->w;
|
||||
|
||||
Vec2 normal = constraint->normal;
|
||||
Vec2 tangent = PerpVec2(normal);
|
||||
@ -2705,13 +2718,13 @@ void P_StepFrame(P_Frame *frame)
|
||||
|
||||
if (!P_IsEntNil(ent0))
|
||||
{
|
||||
ent0->solved_v = v0;
|
||||
ent0->solved_w = w0;
|
||||
ent0->v = v0;
|
||||
ent0->w = w0;
|
||||
}
|
||||
if (!P_IsEntNil(ent1))
|
||||
{
|
||||
ent1->solved_v = v1;
|
||||
ent1->solved_w = w1;
|
||||
ent1->v = v1;
|
||||
ent1->w = w1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2733,10 +2746,10 @@ void P_StepFrame(P_Frame *frame)
|
||||
f32 inv_m1 = constraint->inv_m1;
|
||||
f32 inv_i0 = constraint->inv_i0;
|
||||
f32 inv_i1 = constraint->inv_i1;
|
||||
Vec2 v0 = ent0->solved_v;
|
||||
Vec2 v1 = ent1->solved_v;
|
||||
f32 w0 = ent0->solved_w;
|
||||
f32 w1 = ent1->solved_w;
|
||||
Vec2 v0 = ent0->v;
|
||||
Vec2 v1 = ent1->v;
|
||||
f32 w0 = ent0->w;
|
||||
f32 w1 = ent1->w;
|
||||
|
||||
Vec2 center0 = constraint->static_center0;
|
||||
Vec2 center1 = constraint->static_center1;
|
||||
@ -2837,13 +2850,13 @@ void P_StepFrame(P_Frame *frame)
|
||||
|
||||
if (!P_IsEntNil(ent0))
|
||||
{
|
||||
ent0->solved_v = v0;
|
||||
ent0->solved_w = w0;
|
||||
ent0->v = v0;
|
||||
ent0->w = w0;
|
||||
}
|
||||
if (!P_IsEntNil(ent1))
|
||||
{
|
||||
ent1->solved_v = v1;
|
||||
ent1->solved_w = w1;
|
||||
ent1->v = v1;
|
||||
ent1->w = w1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2876,13 +2889,13 @@ void P_StepFrame(P_Frame *frame)
|
||||
|
||||
if (!P_IsEntNil(ent0))
|
||||
{
|
||||
ent0->solved_v = v0;
|
||||
ent0->solved_w = w0;
|
||||
ent0->v = v0;
|
||||
ent0->w = w0;
|
||||
}
|
||||
if (!P_IsEntNil(ent1))
|
||||
{
|
||||
ent1->solved_v = v1;
|
||||
ent1->solved_w = w1;
|
||||
ent1->v = v1;
|
||||
ent1->w = w1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2892,11 +2905,11 @@ void P_StepFrame(P_Frame *frame)
|
||||
|
||||
for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||
{
|
||||
if (!is_predicting || ent == local_guy)
|
||||
if (!ent->is_bullet && (!is_predicting || ent == local_guy))
|
||||
{
|
||||
Xform xf = ent->xf;
|
||||
xf.t = AddVec2(xf.t, MulVec2(ent->solved_v, solver_dt));
|
||||
xf.r = RotateVec2Angle(xf.r, ent->solved_w * solver_dt);
|
||||
xf.t = AddVec2(xf.t, MulVec2(ent->v, solver_dt));
|
||||
xf.r = RotateVec2Angle(xf.r, ent->w * solver_dt);
|
||||
ent->xf = xf;
|
||||
}
|
||||
}
|
||||
@ -2908,7 +2921,19 @@ void P_StepFrame(P_Frame *frame)
|
||||
P_Space post_solve_ents_space = P_SpaceFromEnts(scratch.arena, frame);
|
||||
|
||||
//////////////////////////////
|
||||
//- Fire bullets
|
||||
//- Spawn bullets
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -2920,31 +2945,121 @@ 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 && (firer->control.fire_held || firer->control.fire_presses))
|
||||
if (weapon->is_weapon && firer->control.fire_presses)
|
||||
{
|
||||
// i64 fire_delta_ns = frame->time_ns - firer->last_fire_ns;
|
||||
|
||||
// i64 single_bullet_delta_ns = NsFromSeconds(1) / firer->fire_rate;
|
||||
|
||||
// i64 tick_bullets_count = sim_dt * firer->fire_rate;
|
||||
|
||||
f32 fire_rate = 50;
|
||||
f32 bullets_per_fire = 1;
|
||||
f32 spread = Tau * 0.05;
|
||||
// f32 spread = Tau * 0.01;
|
||||
f32 bullet_speed = TweakFloat("Bullet speed", 100, 1, 100);
|
||||
f32 bomb_speed = 10;
|
||||
|
||||
// f32 tweak_speed = TweakFloat("Bullet speed", 1, 1, 100);
|
||||
b32 can_fire = (weapon->last_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= frame->time_ns;
|
||||
|
||||
b32 can_fire = (firer->last_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= frame->time_ns;
|
||||
if (can_fire)
|
||||
{
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
weapon->last_fire_ns = frame->time_ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
P_SpawnEntsFromList(frame, bullets_to_spawn);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Update bullets
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: Separate 'hits' from bullets, so that bullets can have multiple hits
|
||||
|
||||
for (P_Ent *bullet = P_FirstEnt(frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||
{
|
||||
if (bullet->is_bullet)
|
||||
{
|
||||
P_Ent *weapon = P_EntFromKey(frame, bullet->source);
|
||||
P_Ent *firer = P_EntFromKey(frame, weapon->source);
|
||||
P_Ent *damager = P_EntFromKey(frame, bullet->damage_attribution);
|
||||
|
||||
b32 is_first_bullet_tick = bullet->created_at_tick == frame->tick;
|
||||
|
||||
//////////////////////////////
|
||||
//- Bullet properties
|
||||
|
||||
f32 spread = Tau * 0.05;
|
||||
// f32 spread = Tau * 0.01;
|
||||
|
||||
b32 should_ricochet = 0;
|
||||
|
||||
f32 initial_speed = 1;
|
||||
f32 speed_falloff = 0;
|
||||
if (weapon->is_uzi)
|
||||
{
|
||||
initial_speed = TweakFloat("Bullet speed", 100, 1, 100);
|
||||
}
|
||||
else if (weapon->is_launcher)
|
||||
{
|
||||
should_ricochet = 1;
|
||||
initial_speed = 50;
|
||||
// initial_speed = 100;
|
||||
speed_falloff = 5;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Initialize
|
||||
|
||||
// if (bullet->created_at_tick != frame->tick)
|
||||
// {
|
||||
// Vec2 start = bullet->bullet_start;
|
||||
// Vec2 end = bullet->bullet_end;
|
||||
// Vec2 vel = SubVec2(end, start);
|
||||
// bullet->bullet_start = end;
|
||||
// bullet->bullet_end = AddVec2(end, vel);
|
||||
// bullet->xf.t = bullet->bullet_start;
|
||||
// bullet->xf.r = NormVec2(vel);
|
||||
// }
|
||||
|
||||
Struct(BulletPath)
|
||||
{
|
||||
BulletPath *next;
|
||||
Vec2 start;
|
||||
Vec2 end;
|
||||
};
|
||||
BulletPath *first_bullet_path = 0;
|
||||
BulletPath *last_bullet_path = 0;
|
||||
|
||||
if (is_first_bullet_tick)
|
||||
{
|
||||
|
||||
Vec2 fire_pos = Zi;
|
||||
Vec2 fire_dir = Zi;
|
||||
Vec2 fire_base0 = Zi;
|
||||
Vec2 fire_base1 = Zi;
|
||||
if (can_fire)
|
||||
{
|
||||
Vec2 look = firer->control.look;
|
||||
P_Anim anim = P_AnimFromEnt(frame, firer);
|
||||
@ -2990,7 +3105,7 @@ void P_StepFrame(P_Frame *frame)
|
||||
|
||||
SPR_Ray fire_ray = wep.rays[SPR_RayKind_Ap];
|
||||
fire_pos = MulAffineVec2(wep_pix_to_world_af, fire_ray.pos);
|
||||
fire_dir = NormRot(MulAffineBasisVec2(wep_pix_to_world_af, fire_ray.dir));
|
||||
fire_dir = NormVec2(MulAffineBasisVec2(wep_pix_to_world_af, fire_ray.dir));
|
||||
|
||||
fire_base0 = MulVec2(PerpVec2(NegVec2(firer->xf.r)), WedgeVec2(firer->xf.r, SubVec2(firer->xf.t, fire_pos)));
|
||||
fire_base0 = AddVec2(fire_base0, firer->xf.t);
|
||||
@ -3005,96 +3120,14 @@ void P_StepFrame(P_Frame *frame)
|
||||
P_DebugDrawPoint(fire_base0, Color_Yellow);
|
||||
P_DebugDrawPoint(fire_base1, Color_Green);
|
||||
P_DebugDrawPoint(fire_pos, Color_Red);
|
||||
|
||||
bullet->xf.t = fire_pos;
|
||||
bullet->xf.r = NormVec2(fire_dir);
|
||||
|
||||
bullet->v = MulVec2(NormVec2(fire_dir), initial_speed);
|
||||
bullet->v = AddVec2(bullet->v, firer->v);
|
||||
}
|
||||
|
||||
// FIXME: Prevent obstructed weapons from firing through walls
|
||||
|
||||
if (can_fire)
|
||||
{
|
||||
if (weapon->is_uzi)
|
||||
{
|
||||
i64 tick_bullets_count = bullets_per_fire;
|
||||
if (tick_bullets_count > 0)
|
||||
{
|
||||
P_Shape firer_world_shape = P_WorldShapeFromEnt(firer);
|
||||
|
||||
// Vec2 fire_pos = P_EdgePointFromShape(firer_world_shape, firer->control.look);
|
||||
// Vec2 fire_dir = firer->control.look;
|
||||
|
||||
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;
|
||||
bullet->key = P_RandEntKey();
|
||||
|
||||
f32 rand_speed = Norm24(P_RandU64FromEnt(firer)) - 0.5;
|
||||
f32 rand_angle = Norm24(P_RandU64FromEnt(firer)) - 0.5;
|
||||
|
||||
f32 speed = bullet_speed * sim_dt;
|
||||
f32 angle = AngleFromVec2(fire_dir);
|
||||
|
||||
speed += (speed * 0.5) * rand_speed;
|
||||
angle += rand_angle * spread;
|
||||
|
||||
Vec2 dir = Vec2FromAngle(angle);
|
||||
|
||||
bullet->bullet_base0 = fire_base0;
|
||||
bullet->bullet_base1 = fire_base1;
|
||||
bullet->bullet_start = fire_pos;
|
||||
bullet->bullet_end = AddVec2(bullet->bullet_start, MulVec2(dir, speed));
|
||||
bullet->xf.t = bullet->bullet_start;
|
||||
bullet->xf.r = NormRot(dir);
|
||||
bullet->source = weapon->key;
|
||||
bullet->damage_attribution = firer->source;
|
||||
}
|
||||
}
|
||||
firer->last_fire_ns = frame->time_ns;
|
||||
}
|
||||
else if (weapon->is_launcher)
|
||||
{
|
||||
i64 tick_bullets_count = bullets_per_fire;
|
||||
if (tick_bullets_count > 0)
|
||||
{
|
||||
P_Shape firer_world_shape = P_WorldShapeFromEnt(firer);
|
||||
|
||||
// Vec2 fire_pos = P_EdgePointFromShape(firer_world_shape, firer->control.look);
|
||||
// Vec2 fire_dir = firer->control.look;
|
||||
|
||||
for (i64 bullet_idx = 0; bullet_idx < tick_bullets_count; ++bullet_idx)
|
||||
{
|
||||
P_Ent *bomb = P_PushTempEnt(scratch.arena, &bullets_to_spawn);
|
||||
bomb->is_bomb = 1;
|
||||
bomb->is_bullet = 1;
|
||||
bomb->key = P_RandEntKey();
|
||||
|
||||
f32 rand_speed = Norm24(P_RandU64FromEnt(firer)) - 0.5;
|
||||
f32 rand_angle = Norm24(P_RandU64FromEnt(firer)) - 0.5;
|
||||
|
||||
f32 speed = bomb_speed * sim_dt;
|
||||
f32 angle = AngleFromVec2(fire_dir);
|
||||
|
||||
speed += (speed * 0.5) * rand_speed;
|
||||
angle += rand_angle * spread;
|
||||
|
||||
Vec2 dir = Vec2FromAngle(angle);
|
||||
|
||||
bomb->bullet_base0 = fire_base0;
|
||||
bomb->bullet_base1 = fire_base1;
|
||||
bomb->bullet_start = fire_pos;
|
||||
bomb->xf.t = bomb->bullet_start;
|
||||
bomb->xf.r = NormRot(dir);
|
||||
bomb->bullet_end = AddVec2(bomb->bullet_start, MulVec2(dir, speed));
|
||||
bomb->source = weapon->key;
|
||||
bomb->damage_attribution = firer->source;
|
||||
}
|
||||
}
|
||||
firer->last_fire_ns = frame->time_ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
P_SpawnEntsFromList(frame, bullets_to_spawn);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -3102,70 +3135,6 @@ void P_StepFrame(P_Frame *frame)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Update bullets
|
||||
|
||||
// TODO: Separate 'hits' from bullets, so that bullets can have multiple hits
|
||||
|
||||
for (P_Ent *bullet = P_FirstEnt(frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||
{
|
||||
if (bullet->is_bullet)
|
||||
{
|
||||
P_Ent *bullet_weapon = P_EntFromKey(frame, bullet->source);
|
||||
P_Ent *bullet_guy = P_EntFromKey(frame, bullet_weapon->source);
|
||||
P_Ent *bullet_damager = P_EntFromKey(frame, bullet->damage_attribution);
|
||||
|
||||
|
||||
|
||||
if (bullet->created_at_tick != frame->tick)
|
||||
{
|
||||
Vec2 start = bullet->bullet_start;
|
||||
Vec2 end = bullet->bullet_end;
|
||||
Vec2 vel = SubVec2(end, start);
|
||||
bullet->bullet_start = end;
|
||||
bullet->bullet_end = AddVec2(end, vel);
|
||||
bullet->xf.t = bullet->bullet_start;
|
||||
bullet->xf.r = NormRot(vel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bullet->has_hit = 0;
|
||||
|
||||
Struct(BulletPath)
|
||||
{
|
||||
BulletPath *next;
|
||||
Vec2 start;
|
||||
Vec2 end;
|
||||
};
|
||||
BulletPath *first_bullet_path = 0;
|
||||
BulletPath *last_bullet_path = 0;
|
||||
|
||||
if (bullet->created_at_tick == frame->tick)
|
||||
{
|
||||
// On bullet's first tick, we want to ensure that the firer/weapon
|
||||
// wasn't obstructed (e.g. to prevent shooting through walls), so we
|
||||
// insert a path from the bullet's base to its starting position before
|
||||
@ -3174,23 +3143,30 @@ void P_StepFrame(P_Frame *frame)
|
||||
// Firer origin -> weapon chamber path
|
||||
BulletPath *path = PushStruct(scratch.arena, BulletPath);
|
||||
SllQueuePush(first_bullet_path, last_bullet_path, path);
|
||||
path->start = bullet->bullet_base0;
|
||||
path->end = bullet->bullet_base1;
|
||||
path->start = fire_base0;
|
||||
path->end = fire_base1;
|
||||
}
|
||||
{
|
||||
// Weapon chamber -> bullet start path
|
||||
BulletPath *path = PushStruct(scratch.arena, BulletPath);
|
||||
SllQueuePush(first_bullet_path, last_bullet_path, path);
|
||||
path->start = bullet->bullet_base1;
|
||||
path->end = bullet->bullet_start;
|
||||
path->start = fire_base1;
|
||||
path->end = fire_pos;
|
||||
}
|
||||
}
|
||||
|
||||
Vec2 dir = MulVec2(bullet->v, sim_dt);
|
||||
Vec2 p0 = bullet->xf.t;
|
||||
Vec2 p1 = p0;
|
||||
|
||||
// Cur pos -> next pos path
|
||||
if (!is_first_bullet_tick)
|
||||
{
|
||||
p1 = AddVec2(p0, dir);
|
||||
BulletPath *path = PushStruct(scratch.arena, BulletPath);
|
||||
SllQueuePush(first_bullet_path, last_bullet_path, path);
|
||||
path->start = bullet->bullet_start;
|
||||
path->end = bullet->bullet_end;
|
||||
path->start = p0;
|
||||
path->end = p1;
|
||||
}
|
||||
|
||||
P_EntKey victim_key = Zi;
|
||||
@ -3218,7 +3194,7 @@ void P_StepFrame(P_Frame *frame)
|
||||
{
|
||||
P_SpaceEntry *entry = &entry_node->entry;
|
||||
P_EntKey potential_victim_key = (P_EntKey) { .v = entry->shape_id };
|
||||
if (!P_MatchEntKey(potential_victim_key, bullet_guy->key) || P_IsEntKeyNil(bullet_guy->key))
|
||||
if (!P_MatchEntKey(potential_victim_key, firer->key) || P_IsEntKeyNil(firer->key))
|
||||
{
|
||||
P_Shape potential_victim_shape = entry->shape;
|
||||
P_RaycastResult entrance_raycast = P_RaycastShape(potential_victim_shape, path->start, path_dir);
|
||||
@ -3247,14 +3223,21 @@ void P_StepFrame(P_Frame *frame)
|
||||
}
|
||||
P_Ent *victim = P_EntFromKey(frame, victim_key);
|
||||
|
||||
// TODO: Truncate bullet trail
|
||||
bullet->has_hit = 0;
|
||||
|
||||
Vec2 final_pos = p1;
|
||||
if (hit)
|
||||
{
|
||||
Vec2 normal = victim_raycast.normal;
|
||||
|
||||
bullet->has_hit = 1;
|
||||
bullet->hit_entry = victim_raycast.p;
|
||||
bullet->hit_entry_normal = victim_raycast.normal;
|
||||
bullet->hit_entry_normal = normal;
|
||||
|
||||
// FIXME: Use relative velocity at collision point
|
||||
bullet->hit_entry_velocity = bullet->v;
|
||||
|
||||
// bullet->bullet_end = bullet->hit_entry;
|
||||
bullet->exists = 0;
|
||||
if (victim->is_guy)
|
||||
{
|
||||
bullet->hit_material = P_MaterialKind_Flesh;
|
||||
@ -3263,14 +3246,35 @@ void P_StepFrame(P_Frame *frame)
|
||||
{
|
||||
bullet->hit_material = P_MaterialKind_Wall;
|
||||
}
|
||||
|
||||
// Reflect velocity along normal
|
||||
if (should_ricochet)
|
||||
{
|
||||
bullet->v = SubVec2(bullet->v, MulVec2(normal, 2 * DotVec2(bullet->v, normal)));
|
||||
bullet->v = MulVec2(bullet->v, 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
bullet->exists = 0;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
bullet->xf.t = final_pos;
|
||||
if (Vec2LenSq(dir) > (0.001 * 0.001))
|
||||
{
|
||||
bullet->xf.r = NormVec2(dir);
|
||||
}
|
||||
bullet->v = MulVec2(bullet->v, 1.0 - SaturateF32(speed_falloff * sim_dt));
|
||||
|
||||
// TODO: Remove this
|
||||
if (!P_IsEntNil(victim))
|
||||
{
|
||||
if (bullet_damager->is_player)
|
||||
if (damager->is_player)
|
||||
{
|
||||
victim->damage_attribution = bullet_damager->key;
|
||||
victim->damage_attribution = damager->key;
|
||||
}
|
||||
victim->health -= 0.25;
|
||||
}
|
||||
@ -3280,8 +3284,8 @@ void P_StepFrame(P_Frame *frame)
|
||||
bounds.p0 = VEC2(-P_WorldPitch / 2, -P_WorldPitch / 2);
|
||||
bounds.p1 = VEC2(P_WorldPitch / 2, P_WorldPitch / 2);
|
||||
if (
|
||||
bullet->bullet_start.x < bounds.p0.x || bullet->bullet_start.y < bounds.p0.y ||
|
||||
bullet->bullet_start.x > bounds.p1.x || bullet->bullet_start.y > bounds.p1.y
|
||||
bullet->xf.t.x < bounds.p0.x || bullet->xf.t.y < bounds.p0.y ||
|
||||
bullet->xf.t.x > bounds.p1.x || bullet->xf.t.y > bounds.p1.y
|
||||
)
|
||||
{
|
||||
bullet->exists = 0;
|
||||
@ -3289,6 +3293,190 @@ void P_StepFrame(P_Frame *frame)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// // TODO: Separate 'hits' from bullets, so that bullets can have multiple hits
|
||||
|
||||
// for (P_Ent *bullet = P_FirstEnt(frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||
// {
|
||||
// if (bullet->is_bullet)
|
||||
// {
|
||||
// P_Ent *weapon = P_EntFromKey(frame, bullet->source);
|
||||
// P_Ent *firer = P_EntFromKey(frame, weapon->source);
|
||||
// P_Ent *damager = P_EntFromKey(frame, bullet->damage_attribution);
|
||||
|
||||
|
||||
|
||||
// if (bullet->created_at_tick != frame->tick)
|
||||
// {
|
||||
// Vec2 start = bullet->bullet_start;
|
||||
// Vec2 end = bullet->bullet_end;
|
||||
// Vec2 vel = SubVec2(end, start);
|
||||
// bullet->bullet_start = end;
|
||||
// bullet->bullet_end = AddVec2(end, vel);
|
||||
// bullet->xf.t = bullet->bullet_start;
|
||||
// bullet->xf.r = NormVec2(vel);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// bullet->has_hit = 0;
|
||||
|
||||
// Struct(BulletPath)
|
||||
// {
|
||||
// BulletPath *next;
|
||||
// Vec2 start;
|
||||
// Vec2 end;
|
||||
// };
|
||||
// BulletPath *first_bullet_path = 0;
|
||||
// BulletPath *last_bullet_path = 0;
|
||||
|
||||
// if (bullet->created_at_tick == frame->tick)
|
||||
// {
|
||||
// // On bullet's first tick, we want to ensure that the firer/weapon
|
||||
// // wasn't obstructed (e.g. to prevent shooting through walls), so we
|
||||
// // insert a path from the bullet's base to its starting position before
|
||||
// // its actual firing path
|
||||
// {
|
||||
// // Firer origin -> weapon chamber path
|
||||
// BulletPath *path = PushStruct(scratch.arena, BulletPath);
|
||||
// SllQueuePush(first_bullet_path, last_bullet_path, path);
|
||||
// path->start = bullet->bullet_base0;
|
||||
// path->end = bullet->bullet_base1;
|
||||
// }
|
||||
// {
|
||||
// // Weapon chamber -> bullet start path
|
||||
// BulletPath *path = PushStruct(scratch.arena, BulletPath);
|
||||
// SllQueuePush(first_bullet_path, last_bullet_path, path);
|
||||
// path->start = bullet->bullet_base1;
|
||||
// path->end = bullet->bullet_start;
|
||||
// }
|
||||
// }
|
||||
|
||||
// {
|
||||
// BulletPath *path = PushStruct(scratch.arena, BulletPath);
|
||||
// SllQueuePush(first_bullet_path, last_bullet_path, path);
|
||||
// path->start = bullet->bullet_start;
|
||||
// path->end = bullet->bullet_end;
|
||||
// }
|
||||
|
||||
// P_EntKey victim_key = Zi;
|
||||
// P_RaycastResult victim_raycast = Zi;
|
||||
// b32 hit = 0;
|
||||
// {
|
||||
// for (BulletPath *path = first_bullet_path; path && !hit; path = path->next)
|
||||
// {
|
||||
// Vec2 path_dir = SubVec2(path->end, path->start);
|
||||
// P_Space *cast_spaces[] = {
|
||||
// &world->walls_space,
|
||||
// &post_solve_ents_space,
|
||||
// };
|
||||
// P_SpaceEntryList cast_entries = Zi;
|
||||
// P_UniqueSpaceEntriesFromRay(
|
||||
// scratch.arena,
|
||||
// &cast_entries,
|
||||
// countof(cast_spaces),
|
||||
// cast_spaces,
|
||||
// path->start,
|
||||
// path->end
|
||||
// );
|
||||
// f32 closest_len_sq = Inf;
|
||||
// for (P_SpaceEntryNode *entry_node = cast_entries.first; entry_node; entry_node = entry_node->next)
|
||||
// {
|
||||
// P_SpaceEntry *entry = &entry_node->entry;
|
||||
// P_EntKey potential_victim_key = (P_EntKey) { .v = entry->shape_id };
|
||||
// if (!P_MatchEntKey(potential_victim_key, firer->key) || P_IsEntKeyNil(firer->key))
|
||||
// {
|
||||
// P_Shape potential_victim_shape = entry->shape;
|
||||
// P_RaycastResult entrance_raycast = P_RaycastShape(potential_victim_shape, path->start, path_dir);
|
||||
// Vec2 entrance = entrance_raycast.p;
|
||||
// if (entrance_raycast.is_intersecting)
|
||||
// {
|
||||
// P_RaycastResult exit_raycast = P_RaycastShape(potential_victim_shape, path->start, NegVec2(path_dir));
|
||||
// Vec2 exit = exit_raycast.p;
|
||||
// f32 da = DotVec2(path_dir, SubVec2(entrance, path->start));
|
||||
// f32 db = DotVec2(path_dir, SubVec2(exit, path->start));
|
||||
// if (db > 0 && (da <= Vec2LenSq(path_dir) || da <= 0))
|
||||
// {
|
||||
// f32 len_sq = Vec2LenSq(SubVec2(entrance_raycast.p, path->start));
|
||||
// if (len_sq < closest_len_sq)
|
||||
// {
|
||||
// closest_len_sq = len_sq;
|
||||
// victim_key = potential_victim_key;
|
||||
// victim_raycast = entrance_raycast;
|
||||
// hit = 1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// P_Ent *victim = P_EntFromKey(frame, victim_key);
|
||||
|
||||
// // TODO: Truncate bullet trail
|
||||
// if (hit)
|
||||
// {
|
||||
// bullet->has_hit = 1;
|
||||
// bullet->hit_entry = victim_raycast.p;
|
||||
// bullet->hit_entry_normal = victim_raycast.normal;
|
||||
// // bullet->bullet_end = bullet->hit_entry;
|
||||
// bullet->exists = 0;
|
||||
// if (victim->is_guy)
|
||||
// {
|
||||
// bullet->hit_material = P_MaterialKind_Flesh;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// bullet->hit_material = P_MaterialKind_Wall;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // TODO: Remove this
|
||||
// if (!P_IsEntNil(victim))
|
||||
// {
|
||||
// if (damager->is_player)
|
||||
// {
|
||||
// victim->damage_attribution = damager->key;
|
||||
// }
|
||||
// victim->health -= 0.25;
|
||||
// }
|
||||
|
||||
// // Prune out of bounds bullet
|
||||
// Rng2 bounds = Zi;
|
||||
// bounds.p0 = VEC2(-P_WorldPitch / 2, -P_WorldPitch / 2);
|
||||
// bounds.p1 = VEC2(P_WorldPitch / 2, P_WorldPitch / 2);
|
||||
// if (
|
||||
// bullet->bullet_start.x < bounds.p0.x || bullet->bullet_start.y < bounds.p0.y ||
|
||||
// bullet->bullet_start.x > bounds.p1.x || bullet->bullet_start.y > bounds.p1.y
|
||||
// )
|
||||
// {
|
||||
// bullet->exists = 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Kill guys
|
||||
|
||||
|
||||
11
src/pp/pp.h
11
src/pp/pp.h
@ -129,14 +129,11 @@ Struct(P_Ent)
|
||||
//- Bullet / hit
|
||||
|
||||
b32 is_bullet;
|
||||
Vec2 bullet_base0;
|
||||
Vec2 bullet_base1;
|
||||
Vec2 bullet_start;
|
||||
Vec2 bullet_end;
|
||||
|
||||
b32 has_hit;
|
||||
Vec2 hit_entry;
|
||||
Vec2 hit_entry_normal;
|
||||
Vec2 hit_entry_velocity;
|
||||
P_MaterialKind hit_material;
|
||||
|
||||
//- Bomb
|
||||
@ -189,8 +186,8 @@ Struct(P_Ent)
|
||||
|
||||
//- Solver
|
||||
|
||||
Vec2 solved_v;
|
||||
f32 solved_w;
|
||||
Vec2 v; // Linear velocity
|
||||
f32 w; // Angular velocity
|
||||
};
|
||||
|
||||
Struct(P_EntListNode)
|
||||
@ -417,6 +414,7 @@ Enum(P_MsgKind)
|
||||
// Client -> Server
|
||||
P_MsgKind_SaveWorld,
|
||||
P_MsgKind_ResetWorld,
|
||||
P_MsgKind_ClearBullets,
|
||||
P_MsgKind_Teleport,
|
||||
P_MsgKind_TileEdit,
|
||||
P_MsgKind_Prefab,
|
||||
@ -586,6 +584,7 @@ b32 P_IsFrameNil(P_Frame *frame);
|
||||
b32 P_MatchEntKey(P_EntKey a, P_EntKey b);
|
||||
b32 P_MatchConstraintKey(P_ConstraintKey a, P_ConstraintKey b);
|
||||
P_ConstraintKey P_ConstraintKeyFromU64s(u64 a, u64 b);
|
||||
P_EntKey P_EntKeyFromU64(u64 v);
|
||||
|
||||
#define P_FmtKey(key) FmtHandle((key).v)
|
||||
|
||||
|
||||
@ -557,6 +557,18 @@ void S_TickForever(WaveLaneCtx *lane)
|
||||
}
|
||||
}
|
||||
} break;
|
||||
//- Clear bullets
|
||||
case P_MsgKind_ClearBullets:
|
||||
{
|
||||
// TODO: Real reset
|
||||
for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||
{
|
||||
if (ent->is_bullet)
|
||||
{
|
||||
ent->exists = 0;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
//- Teleport
|
||||
case P_MsgKind_Teleport:
|
||||
{
|
||||
|
||||
@ -914,8 +914,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
Vec2 look_delta = mouse_delta;
|
||||
look_delta = MulVec2(look_delta, mouse_sensitivity * mouse_scale_factor);
|
||||
|
||||
Vec2 prev_crosshair_rot = NormRot(SubVec2(prev_frame->world_crosshair, prev_frame->world_crosshair_base));
|
||||
Vec2 prev_look_rot = NormRot(prev_frame->look);
|
||||
Vec2 prev_crosshair_rot = NormVec2(SubVec2(prev_frame->world_crosshair, prev_frame->world_crosshair_base));
|
||||
Vec2 prev_look_rot = NormVec2(prev_frame->look);
|
||||
Vec2 rot = RotateVec2(prev_look_rot, InvertRot(prev_crosshair_rot));
|
||||
|
||||
look_delta = RotateVec2(look_delta, rot);
|
||||
@ -952,8 +952,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
frame->edit_camera_pos = AddVec2(frame->edit_camera_pos, MulVec2(move, edit_move_speed * frame->dt));
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGBREAKABLE;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@ -1002,8 +1000,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
look_ratio = VEC2(0.5, 0.5);
|
||||
}
|
||||
|
||||
Vec2 prev_crosshair_rot = NormRot(SubVec2(prev_frame->world_crosshair, prev_frame->world_crosshair_base));
|
||||
Vec2 prev_look_rot = NormRot(prev_frame->look);
|
||||
Vec2 prev_crosshair_rot = NormVec2(SubVec2(prev_frame->world_crosshair, prev_frame->world_crosshair_base));
|
||||
Vec2 prev_look_rot = NormVec2(prev_frame->look);
|
||||
Vec2 rot = RotateVec2(prev_look_rot, InvertRot(prev_crosshair_rot));
|
||||
|
||||
Vec2 look_pos = frame->look;
|
||||
@ -1840,9 +1838,12 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
}
|
||||
local_world->seed = predict_world->seed;
|
||||
|
||||
P_ClearFrames(local_world, I64Min, I64Max);
|
||||
P_ClearFrames(local_world, I64Min, local_world->last_frame->tick - 1);
|
||||
local_frame = P_PushFrame(local_world, predict_world->last_frame, predict_world->last_frame->tick);
|
||||
|
||||
// LogDebugF("First frame: %F, Last frame: %F", FmtSint(local_world->first_frame->tick), FmtSint(local_world->last_frame->tick));
|
||||
|
||||
|
||||
P_DebugDrawFrame(local_frame);
|
||||
}
|
||||
|
||||
@ -1901,7 +1902,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
//- Compute sprite transforms
|
||||
Affine cur_ent_to_world_af = MulAffineXform(AffineIdentity, ent->xf);
|
||||
Affine desired_ent_to_world_af = MulAffineXform(AffineIdentity, XformTR(ent->xf.t, NormRot(look)));
|
||||
Affine desired_ent_to_world_af = MulAffineXform(AffineIdentity, XformTR(ent->xf.t, NormVec2(look)));
|
||||
Affine cur_body_pix_to_world_af = AffineIdentity;
|
||||
Affine cur_wep_pix_to_world_af = AffineIdentity;
|
||||
Affine desired_body_pix_to_world_af = AffineIdentity;
|
||||
@ -1944,9 +1945,9 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
SPR_Ray fire_ray = wep.rays[SPR_RayKind_Ap];
|
||||
|
||||
Vec2 cur_fire_pos = MulAffineVec2(cur_wep_pix_to_world_af, fire_ray.pos);
|
||||
Vec2 cur_fire_dir = NormRot(MulAffineBasisVec2(cur_wep_pix_to_world_af, fire_ray.dir));
|
||||
Vec2 cur_fire_dir = NormVec2(MulAffineBasisVec2(cur_wep_pix_to_world_af, fire_ray.dir));
|
||||
Vec2 desired_fire_pos = MulAffineVec2(desired_wep_pix_to_world_af, fire_ray.pos);
|
||||
Vec2 desired_fire_dir = NormRot(MulAffineBasisVec2(desired_wep_pix_to_world_af, fire_ray.dir));
|
||||
Vec2 desired_fire_dir = NormVec2(MulAffineBasisVec2(desired_wep_pix_to_world_af, fire_ray.dir));
|
||||
|
||||
Vec2 desired_hold_pos = MulAffineVec2(desired_body_pix_to_world_af, body.rays[SPR_RayKind_Ap].pos);
|
||||
|
||||
@ -1962,7 +1963,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
frame->world_guy_origin = desired_ent_to_world_af.og;
|
||||
frame->world_crosshair_base = desired_crosshair_base;
|
||||
|
||||
Vec2 look_rot = NormRot(look);
|
||||
Vec2 look_rot = NormVec2(look);
|
||||
|
||||
Vec2 line_start = cur_fire_pos;
|
||||
Vec2 line_end = AddVec2(line_start, cur_fire_dir);
|
||||
@ -2263,8 +2264,14 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
{
|
||||
if (bullet->is_bullet)
|
||||
{
|
||||
Vec2 start = bullet->bullet_start;
|
||||
Vec2 end = bullet->bullet_end;
|
||||
// FIXME: Use 'last visible' pos
|
||||
P_Ent *old_bullet = P_EntFromKey(local_world->last_frame->prev, 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)
|
||||
@ -2331,13 +2338,22 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
{
|
||||
if (bullet->is_bullet && bullet->has_hit)
|
||||
{
|
||||
// FIXME: Use actual velocity
|
||||
P_Ent *old_bullet = P_EntFromKey(local_frame->prev, 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 bullet_vel = SubVec2(bullet->bullet_end, bullet->bullet_start);
|
||||
Vec2 hit_entry_velocity = bullet->hit_entry_velocity;
|
||||
|
||||
V_DrawLine(bullet->bullet_start, bullet->bullet_end, Color_Cyan);
|
||||
V_DrawLine(start, end, Color_Cyan);
|
||||
|
||||
//////////////////////////////
|
||||
//- Wall particles
|
||||
@ -2419,7 +2435,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
emitter.kind = V_ParticleKind_BloodTrail;
|
||||
// emitter.kind = V_ParticleKind_BloodDebris;
|
||||
|
||||
Vec2 dir = NormVec2(NegVec2(bullet_vel));
|
||||
Vec2 dir = NormVec2(NegVec2(hit_entry_velocity));
|
||||
|
||||
f32 angle = AngleFromVec2(dir);
|
||||
// f32 angle = 0;
|
||||
@ -2453,267 +2469,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// if (0)
|
||||
// {
|
||||
// for (P_Ent *bullet = P_FirstEnt(local_frame); !P_IsEntNil(bullet); bullet = P_NextEnt(bullet))
|
||||
// {
|
||||
// if (bullet->is_bullet && bullet->has_hit)
|
||||
// {
|
||||
// P_MaterialKind material = bullet->hit_material;
|
||||
|
||||
// Vec2 hit_entry = bullet->hit_entry;
|
||||
// Vec2 hit_entry_normal = bullet->hit_entry_normal;
|
||||
// Vec2 bullet_vel = SubVec2(bullet->bullet_end, bullet->bullet_start);
|
||||
|
||||
// V_DrawLine(bullet->bullet_start, bullet->bullet_end, Color_Cyan);
|
||||
|
||||
// //////////////////////////////
|
||||
// //- Wall particles
|
||||
|
||||
// if (material != P_MaterialKind_Flesh)
|
||||
// {
|
||||
// //- Wall debris
|
||||
// {
|
||||
// V_Emitter emitter = Zi;
|
||||
// {
|
||||
// // emitter.flags |= V_ParticleFlag_PruneWhenStill;
|
||||
// // emitter.flags |= V_ParticleFlag_StainOnPrune;
|
||||
|
||||
|
||||
// emitter.count = 4;
|
||||
|
||||
// emitter.start = hit_entry;
|
||||
// emitter.end = emitter.start;
|
||||
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.4, 0.3, 0.2, 0.75));
|
||||
// emitter.color_spread = VEC4(0, 0, 0, 0.25);
|
||||
|
||||
// emitter.speed = 2;
|
||||
// // emitter.speed_spread = emitter.speed * 2;
|
||||
// emitter.speed_spread = emitter.speed * 2.5;
|
||||
|
||||
// emitter.velocity_falloff = 5;
|
||||
// emitter.velocity_falloff_spread = emitter.velocity_falloff_spread * 1.5;
|
||||
|
||||
// Vec2 dir = hit_entry_normal;
|
||||
|
||||
// emitter.angle = AngleFromVec2(dir);
|
||||
// emitter.angle_spread = Tau * 0.5;
|
||||
|
||||
// // 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.flags |= V_ParticleFlag_PruneWhenStill;
|
||||
|
||||
// emitter.count = 32;
|
||||
|
||||
// emitter.start = hit_entry;
|
||||
// emitter.end = emitter.start;
|
||||
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.5, 0.5, 0.75));
|
||||
|
||||
// emitter.speed = 4;
|
||||
// // emitter.speed_spread = emitter.speed * 2;
|
||||
// emitter.speed_spread = emitter.speed * 2;
|
||||
|
||||
// emitter.velocity_falloff = 12;
|
||||
// emitter.velocity_falloff_spread = emitter.velocity_falloff_spread * 1.5;
|
||||
|
||||
// Vec2 dir = hit_entry_normal;
|
||||
|
||||
// emitter.angle = AngleFromVec2(dir);
|
||||
// emitter.angle_spread = Tau * 0.1;
|
||||
|
||||
// emitter.lifetime = 1;
|
||||
// // emitter.lifetime = 0.05;
|
||||
// // emitter.lifetime = 0.04;
|
||||
// emitter.lifetime_spread = emitter.lifetime * 2;
|
||||
// }
|
||||
// V_PushParticles(emitter);
|
||||
// }
|
||||
// }
|
||||
|
||||
// //////////////////////////////
|
||||
// //- Blood particles
|
||||
|
||||
// if (material == P_MaterialKind_Flesh)
|
||||
// {
|
||||
// // Vec2 bullet_start = bullet->start;
|
||||
// // Vec2 bullet_end = bullet->end;
|
||||
|
||||
// V_ParticleFlag flags = 0;
|
||||
// flags |= V_ParticleFlag_PruneWhenStill;
|
||||
// flags |= V_ParticleFlag_StainOnPrune;
|
||||
// if (TweakBool("Emitter stain trail", 1))
|
||||
// {
|
||||
// flags |= V_ParticleFlag_StainTrail;
|
||||
// }
|
||||
// // f32 count = TweakFloat("Emitter count", 50, 0, 10000);
|
||||
// f32 count = TweakFloat("Emitter count", 20, 1, 1000);
|
||||
// f32 speed = TweakFloat("Emitter speed", 20, 0, 100);
|
||||
// f32 falloff = TweakFloat("Emitter falloff", 50, 0, 100);
|
||||
// f32 angle_spread = TweakFloat("Emitter angle spread", 0.1, 0, 1) * Tau;
|
||||
|
||||
// V_Emitter emitter = Zi;
|
||||
// {
|
||||
// emitter.count = count;
|
||||
// emitter.flags = flags;
|
||||
|
||||
// // Vec2 dir = hit_entry_normal;
|
||||
// Vec2 dir = NormVec2(NegVec2(bullet_vel));
|
||||
|
||||
// emitter.start = hit_entry;
|
||||
// emitter.end = emitter.start;
|
||||
|
||||
// emitter.speed = speed;
|
||||
// emitter.speed_spread = speed * 2;
|
||||
|
||||
// emitter.velocity_falloff = falloff;
|
||||
// emitter.velocity_falloff_spread = falloff * 1.5;
|
||||
|
||||
// emitter.angle = AngleFromVec2(dir);
|
||||
// // emitter.angle_spread = Tau / 4;
|
||||
// emitter.angle_spread = angle_spread;
|
||||
// // emitter.angle_spread = Tau / 32;
|
||||
|
||||
// // emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 1));
|
||||
// emitter.color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 0.5));
|
||||
|
||||
// // emitter.color_spread = VEC4(0.1, 0, 0, 0);
|
||||
// emitter.color_spread = VEC4(0.1, 0, 0, 0.5);
|
||||
|
||||
// // emitter.color = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
|
||||
|
||||
// // emitter.angle_spread = 1;
|
||||
// // emitter.angle_spread = 0.5;
|
||||
// // emitter.angle_spread = Tau;
|
||||
// }
|
||||
// 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);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// {
|
||||
// for (P_Ent *firer = P_FirstEnt(local_frame); firer->valid; firer = P_NextEnt(firer))
|
||||
// {
|
||||
// if (firer->fire_held)
|
||||
// {
|
||||
// Affine firer_af = firer->af;
|
||||
// P_Shape firer_world_shape = P_MulAffineShape(firer_af, firer->local_shape);
|
||||
|
||||
// Vec2 ray_start = firer_world_shape.centroid;
|
||||
// Vec2 ray_dir = firer->look;
|
||||
|
||||
// // TODO: Real raycast query
|
||||
// P_Ent *closest_victim = &P_NilEnt;
|
||||
// P_RaycastResult victim_raycast = Zi;
|
||||
// {
|
||||
// f32 closest_len_sq = Inf;
|
||||
// for (P_Ent *victim = P_FirstEnt(local_frame); victim->valid; victim = P_NextEnt(victim))
|
||||
// {
|
||||
// if (victim != firer)
|
||||
// {
|
||||
// Affine victim_af = victim->af;
|
||||
// P_Shape victim_world_shape = P_MulAffineShape(victim_af, victim->local_shape);
|
||||
|
||||
// P_RaycastResult raycast = P_RaycastShape(victim_world_shape, ray_start, ray_dir);
|
||||
// if (raycast.is_intersecting)
|
||||
// {
|
||||
// f32 len_sq = Vec2LenSq(SubVec2(raycast.p, ray_start));
|
||||
// if (len_sq < closest_len_sq)
|
||||
// {
|
||||
// closest_len_sq = len_sq;
|
||||
// closest_victim = victim;
|
||||
// victim_raycast = raycast;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (closest_victim->valid)
|
||||
// {
|
||||
// V_ParticleFlag flags = 0;
|
||||
// flags |= V_ParticleFlag_PruneWhenStill;
|
||||
// flags |= V_ParticleFlag_StainOnPrune;
|
||||
// if (TweakBool("Emitter stain trail", 1))
|
||||
// {
|
||||
// flags |= V_ParticleFlag_StainTrail;
|
||||
// }
|
||||
// // f32 count = TweakFloat("Emitter count", 50, 0, 10000);
|
||||
// f32 count = TweakFloat("Emitter count", 50, 1, 1000);
|
||||
// f32 speed = TweakFloat("Emitter speed", 20, 0, 100);
|
||||
// f32 falloff = TweakFloat("Emitter falloff", 50, 0, 100);
|
||||
// f32 angle_spread = TweakFloat("Emitter angle spread", 0.1, 0, 1) * Tau;
|
||||
|
||||
// V_Emitter *emitter = V_PushEmitter(count);
|
||||
// emitter->flags = flags;
|
||||
|
||||
// Vec2 dir = victim_raycast.normal;
|
||||
// emitter->start = victim_raycast.p;
|
||||
// emitter->end = emitter->start;
|
||||
|
||||
// emitter->speed = speed;
|
||||
// emitter->speed_spread = speed * 2;
|
||||
|
||||
// emitter->velocity_falloff = falloff;
|
||||
// emitter->velocity_falloff_spread = falloff * 1.5;
|
||||
|
||||
// emitter->angle = AngleFromVec2(dir);
|
||||
// // emitter->angle_spread = Tau / 4;
|
||||
// emitter->angle_spread = angle_spread;
|
||||
// // emitter->angle_spread = Tau / 32;
|
||||
|
||||
// emitter->color_lin = LinearFromSrgb(VEC4(0.5, 0.1, 0.1, 1));
|
||||
// emitter->color_spread = VEC4(0.1, 0, 0, 0);
|
||||
|
||||
// // emitter->color = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1));
|
||||
|
||||
// emitter->seed = RandU64FromState(&frame->rand);
|
||||
// // emitter->angle_spread = 1;
|
||||
// // emitter->angle_spread = 0.5;
|
||||
// // emitter->angle_spread = Tau;
|
||||
|
||||
// // V_DrawPoint(victim_raycast.p, Color_Green);
|
||||
// // V_DrawLine(victim_raycast.p, AddVec2(victim_raycast.p, MulVec2(victim_raycast.normal, 0.5)), Color_White);
|
||||
// }
|
||||
|
||||
|
||||
// // for (P_QueryResult query = P_FirstRaycast(world, ray_start, ray_dir); query.
|
||||
// // P_RaycastWorldResult hits = P_RaycastWorld(local_frame, ray_start, ray_dir)
|
||||
// // {
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Push test emitter
|
||||
|
||||
@ -4949,6 +4704,11 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
frame->should_clear_particles = 1;
|
||||
} break;
|
||||
|
||||
case V_CmdKind_clear_bullets:
|
||||
{
|
||||
P_Msg *msg = P_PushMsg(P_MsgKind_ClearBullets, Zstr);
|
||||
} break;
|
||||
|
||||
case V_CmdKind_test:
|
||||
{
|
||||
// V_PushNotif(Lit("Hello!!!"));
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
X(delete, Delete entity at cursor, V_CmdDescFlag_None, V_HOTKEY( Button_M2 ), ) \
|
||||
X(reset_world, Reset world, V_CmdDescFlag_None, V_HOTKEY( Button_R, .ctrl = 1, .alt = 1 ), ) \
|
||||
X(clear_particles, Clear particles, V_CmdDescFlag_None, V_HOTKEY( Button_C ), ) \
|
||||
X(clear_bullets, Clear bullets, V_CmdDescFlag_None, V_HOTKEY( Button_C, .shift = 1 ), ) \
|
||||
X(test, Test, V_CmdDescFlag_None, V_HOTKEY( Button_Y ), ) \
|
||||
/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user