prevent players from firing through walls
This commit is contained in:
parent
45ac2bf1af
commit
8405d039af
78
src/pp/pp.c
78
src/pp/pp.c
@ -1378,7 +1378,8 @@ P_Space P_SpaceFromWalls(Arena *arena, P_Frame *frame)
|
|||||||
{
|
{
|
||||||
Vec2 p0 = VEC2(wall->start.x / P_TilesPerMeter - P_WorldPitch / 2, wall->start.y / P_TilesPerMeter - P_WorldPitch / 2);
|
Vec2 p0 = VEC2(wall->start.x / P_TilesPerMeter - P_WorldPitch / 2, wall->start.y / P_TilesPerMeter - P_WorldPitch / 2);
|
||||||
Vec2 p1 = VEC2(wall->end.x / P_TilesPerMeter - P_WorldPitch / 2, wall->end.y / P_TilesPerMeter - P_WorldPitch / 2);
|
Vec2 p1 = VEC2(wall->end.x / P_TilesPerMeter - P_WorldPitch / 2, wall->end.y / P_TilesPerMeter - P_WorldPitch / 2);
|
||||||
P_Shape shape = P_ShapeFromDesc(.count = 2, .points = { p0, p1 }, .radius = 0.01 );
|
// P_Shape shape = P_ShapeFromDesc(.count = 2, .points = { p0, p1 }, .radius = 0.01 );
|
||||||
|
P_Shape shape = P_ShapeFromDesc(.count = 2, .points = { p0, p1 }, .radius = 0.0 );
|
||||||
Rng2 aabb = P_BoundingBoxFromShape(shape);
|
Rng2 aabb = P_BoundingBoxFromShape(shape);
|
||||||
aabb = AddRng2Vec2(aabb, VEC2(P_WorldPitch / 2.0, P_WorldPitch / 2.0));
|
aabb = AddRng2Vec2(aabb, VEC2(P_WorldPitch / 2.0, P_WorldPitch / 2.0));
|
||||||
aabb.p0 = FloorVec2(aabb.p0);
|
aabb.p0 = FloorVec2(aabb.p0);
|
||||||
@ -1729,6 +1730,7 @@ void P_SpawnEntsFromList(P_Frame *frame, P_EntList ents)
|
|||||||
dst->next_in_bin = old_next_in_bin;
|
dst->next_in_bin = old_next_in_bin;
|
||||||
dst->prev_in_bin = old_prev_in_bin;
|
dst->prev_in_bin = old_prev_in_bin;
|
||||||
dst->created_at_ns = frame->time_ns;
|
dst->created_at_ns = frame->time_ns;
|
||||||
|
dst->created_at_tick = frame->tick;
|
||||||
++frame->ents_count;
|
++frame->ents_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2717,6 +2719,7 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
|
|
||||||
Vec2 fire_pos = Zi;
|
Vec2 fire_pos = Zi;
|
||||||
Vec2 fire_dir = Zi;
|
Vec2 fire_dir = Zi;
|
||||||
|
Vec2 fire_base = Zi;
|
||||||
if (can_fire)
|
if (can_fire)
|
||||||
{
|
{
|
||||||
Vec2 look = firer->control.look;
|
Vec2 look = firer->control.look;
|
||||||
@ -2764,6 +2767,13 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
SPR_Ray fire_ray = wep.rays[SPR_RayKind_Ap];
|
SPR_Ray fire_ray = wep.rays[SPR_RayKind_Ap];
|
||||||
fire_pos = MulAffineVec2(wep_pix_to_world_af, fire_ray.pos);
|
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 = NormRot(MulAffineBasisVec2(wep_pix_to_world_af, fire_ray.dir));
|
||||||
|
|
||||||
|
fire_base = MulVec2(PerpVec2(NegVec2(firer->xf.r)), WedgeVec2(firer->xf.r, SubVec2(firer->xf.t, fire_pos)));
|
||||||
|
fire_base = AddVec2(fire_base, firer->xf.t);
|
||||||
|
|
||||||
|
P_DebugDrawLine(fire_base, fire_pos, Color_Yellow);
|
||||||
|
P_DebugDrawPoint(fire_base, Color_Yellow);
|
||||||
|
P_DebugDrawPoint(fire_pos, Color_Red);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Prevent obstructed weapons from firing through walls
|
// FIXME: Prevent obstructed weapons from firing through walls
|
||||||
@ -2795,6 +2805,7 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
|
|
||||||
Vec2 dir = Vec2FromAngle(angle);
|
Vec2 dir = Vec2FromAngle(angle);
|
||||||
|
|
||||||
|
bullet->bullet_base = fire_base;
|
||||||
bullet->bullet_start = fire_pos;
|
bullet->bullet_start = fire_pos;
|
||||||
bullet->bullet_end = AddVec2(bullet->bullet_start, MulVec2(dir, speed));
|
bullet->bullet_end = AddVec2(bullet->bullet_start, MulVec2(dir, speed));
|
||||||
bullet->bullet_firer = firer->key;
|
bullet->bullet_firer = firer->key;
|
||||||
@ -2817,30 +2828,56 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
if (bullet->is_bullet)
|
if (bullet->is_bullet)
|
||||||
{
|
{
|
||||||
bullet->has_hit = 0;
|
bullet->has_hit = 0;
|
||||||
Vec2 ray_start = bullet->bullet_start;
|
|
||||||
Vec2 ray_end = bullet->bullet_end;
|
Struct(BulletPath)
|
||||||
Vec2 ray_dir = SubVec2(ray_end, ray_start);
|
{
|
||||||
|
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
|
||||||
|
BulletPath *path = PushStruct(scratch.arena, BulletPath);
|
||||||
|
SllQueuePush(first_bullet_path, last_bullet_path, path);
|
||||||
|
path->start = bullet->bullet_base;
|
||||||
|
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_DebugDrawLine(bullet->bullet_start, bullet->bullet_end, Color_Red);
|
P_DebugDrawLine(bullet->bullet_start, bullet->bullet_end, Color_Red);
|
||||||
|
|
||||||
|
P_EntKey victim_key = Zi;
|
||||||
|
P_RaycastResult victim_raycast = Zi;
|
||||||
|
{
|
||||||
|
for (BulletPath *path = first_bullet_path; path; path = path->next)
|
||||||
|
{
|
||||||
|
Vec2 path_dir = SubVec2(path->end, path->start);
|
||||||
P_Space *cast_spaces[] = {
|
P_Space *cast_spaces[] = {
|
||||||
&world->walls_space,
|
&world->walls_space,
|
||||||
&post_solve_ents_space,
|
&post_solve_ents_space,
|
||||||
};
|
};
|
||||||
|
|
||||||
P_SpaceEntryList cast_entries = Zi;
|
P_SpaceEntryList cast_entries = Zi;
|
||||||
P_UniqueSpaceEntriesFromRay(
|
P_UniqueSpaceEntriesFromRay(
|
||||||
scratch.arena,
|
scratch.arena,
|
||||||
&cast_entries,
|
&cast_entries,
|
||||||
countof(cast_spaces),
|
countof(cast_spaces),
|
||||||
cast_spaces,
|
cast_spaces,
|
||||||
ray_start,
|
path->start,
|
||||||
ray_end
|
path->end
|
||||||
);
|
);
|
||||||
|
|
||||||
P_EntKey victim_key = Zi;
|
|
||||||
P_RaycastResult victim_raycast = Zi;
|
|
||||||
{
|
|
||||||
f32 closest_len_sq = Inf;
|
f32 closest_len_sq = Inf;
|
||||||
for (P_SpaceEntryNode *entry_node = cast_entries.first; entry_node; entry_node = entry_node->next)
|
for (P_SpaceEntryNode *entry_node = cast_entries.first; entry_node; entry_node = entry_node->next)
|
||||||
{
|
{
|
||||||
@ -2849,17 +2886,17 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
if (!P_MatchEntKey(potential_victim_key, bullet->bullet_firer))
|
if (!P_MatchEntKey(potential_victim_key, bullet->bullet_firer))
|
||||||
{
|
{
|
||||||
P_Shape potential_victim_shape = entry->shape;
|
P_Shape potential_victim_shape = entry->shape;
|
||||||
P_RaycastResult entrance_raycast = P_RaycastShape(potential_victim_shape, ray_start, ray_dir);
|
P_RaycastResult entrance_raycast = P_RaycastShape(potential_victim_shape, path->start, path_dir);
|
||||||
Vec2 entrance = entrance_raycast.p;
|
Vec2 entrance = entrance_raycast.p;
|
||||||
if (entrance_raycast.is_intersecting)
|
if (entrance_raycast.is_intersecting)
|
||||||
{
|
{
|
||||||
P_RaycastResult exit_raycast = P_RaycastShape(potential_victim_shape, ray_start, NegVec2(ray_dir));
|
P_RaycastResult exit_raycast = P_RaycastShape(potential_victim_shape, path->start, NegVec2(path_dir));
|
||||||
Vec2 exit = exit_raycast.p;
|
Vec2 exit = exit_raycast.p;
|
||||||
f32 da = DotVec2(ray_dir, SubVec2(entrance, ray_start));
|
f32 da = DotVec2(path_dir, SubVec2(entrance, path->start));
|
||||||
f32 db = DotVec2(ray_dir, SubVec2(exit, ray_start));
|
f32 db = DotVec2(path_dir, SubVec2(exit, path->start));
|
||||||
if (db > 0 && (da <= Vec2LenSq(ray_dir) || da <= 0))
|
if (db > 0 && (da <= Vec2LenSq(path_dir) || da <= 0))
|
||||||
{
|
{
|
||||||
f32 len_sq = Vec2LenSq(SubVec2(entrance_raycast.p, ray_start));
|
f32 len_sq = Vec2LenSq(SubVec2(entrance_raycast.p, path->start));
|
||||||
if (len_sq < closest_len_sq)
|
if (len_sq < closest_len_sq)
|
||||||
{
|
{
|
||||||
closest_len_sq = len_sq;
|
closest_len_sq = len_sq;
|
||||||
@ -2870,7 +2907,14 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!P_IsEntKeyNil(victim_key))
|
||||||
|
{
|
||||||
|
// No need to check future paths if this path hit
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
P_Ent *victim = P_EntFromKey(frame, victim_key);
|
P_Ent *victim = P_EntFromKey(frame, victim_key);
|
||||||
|
|
||||||
// TODO: Truncate bullet trail
|
// TODO: Truncate bullet trail
|
||||||
|
|||||||
@ -110,6 +110,7 @@ Struct(P_Ent)
|
|||||||
P_EntKey key;
|
P_EntKey key;
|
||||||
u64 rand_seq;
|
u64 rand_seq;
|
||||||
i64 created_at_ns;
|
i64 created_at_ns;
|
||||||
|
i64 created_at_tick;
|
||||||
|
|
||||||
//- Build data
|
//- Build data
|
||||||
|
|
||||||
@ -129,6 +130,7 @@ Struct(P_Ent)
|
|||||||
|
|
||||||
P_EntKey bullet_firer;
|
P_EntKey bullet_firer;
|
||||||
b32 is_bullet;
|
b32 is_bullet;
|
||||||
|
Vec2 bullet_base;
|
||||||
Vec2 bullet_start;
|
Vec2 bullet_start;
|
||||||
Vec2 bullet_end;
|
Vec2 bullet_end;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user