health kit
This commit is contained in:
parent
08b8f10616
commit
e0cfc853cf
76
src/pp/pp.c
76
src/pp/pp.c
@ -237,6 +237,14 @@ P_Shape P_LocalShapeFromEnt(P_Ent *ent)
|
|||||||
// .points[3] = VEC2(test_rect.p0.x, test_rect.p1.y),
|
// .points[3] = VEC2(test_rect.p0.x, test_rect.p1.y),
|
||||||
// );
|
// );
|
||||||
}
|
}
|
||||||
|
else if (ent->is_pickup)
|
||||||
|
{
|
||||||
|
result = P_ShapeFromDesc(
|
||||||
|
.mass = 10,
|
||||||
|
.count = 1,
|
||||||
|
.radius = 0.10,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -293,10 +301,22 @@ P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent)
|
|||||||
{
|
{
|
||||||
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("prefab/GuySpawn.ase")));
|
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("prefab/GuySpawn.ase")));
|
||||||
}
|
}
|
||||||
|
else if (ent->is_health_spawn)
|
||||||
|
{
|
||||||
|
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("prefab/HealthSpawn.ase")));
|
||||||
|
}
|
||||||
else if (ent->is_bomb)
|
else if (ent->is_bomb)
|
||||||
{
|
{
|
||||||
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("misc/bomb.ase")));
|
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("misc/bomb.ase")));
|
||||||
}
|
}
|
||||||
|
else if (ent->is_health)
|
||||||
|
{
|
||||||
|
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("misc/health.ase")));
|
||||||
|
}
|
||||||
|
else if (ent->is_health)
|
||||||
|
{
|
||||||
|
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("misc/health.ase")));
|
||||||
|
}
|
||||||
|
|
||||||
if (wep->is_uzi)
|
if (wep->is_uzi)
|
||||||
{
|
{
|
||||||
@ -1285,7 +1305,7 @@ P_Space P_SpaceFromEnts(Arena *arena, P_Frame *frame)
|
|||||||
//- Insert entity shapes
|
//- Insert entity shapes
|
||||||
for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
{
|
{
|
||||||
b32 should_insert = ent->is_guy;
|
b32 should_insert = ent->is_guy || ent->is_pickup;
|
||||||
if (should_insert)
|
if (should_insert)
|
||||||
{
|
{
|
||||||
P_Shape shape = P_WorldShapeFromEnt(ent);
|
P_Shape shape = P_WorldShapeFromEnt(ent);
|
||||||
@ -2227,6 +2247,53 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Spawn pickups
|
||||||
|
|
||||||
|
if (!is_predicting)
|
||||||
|
{
|
||||||
|
P_EntList queued_ents = Zi;
|
||||||
|
for (P_Ent *spawner = P_FirstEnt(frame); !P_IsEntNil(spawner); spawner = P_NextEnt(spawner))
|
||||||
|
{
|
||||||
|
b32 is_spawner = spawner->is_health_spawn;
|
||||||
|
if (is_spawner)
|
||||||
|
{
|
||||||
|
if (!P_IsEntKeyNil(spawner->pickup))
|
||||||
|
{
|
||||||
|
P_Ent *pickup = P_EntFromKey(frame, spawner->pickup);
|
||||||
|
if (P_IsEntNil(pickup))
|
||||||
|
{
|
||||||
|
spawner->last_spawn_reset_ns = frame->time_ns;
|
||||||
|
spawner->pickup = P_NilEntKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_spawner && P_IsEntKeyNil(spawner->pickup))
|
||||||
|
{
|
||||||
|
i64 spawn_interval_ns = 0;
|
||||||
|
if (spawner->is_health_spawn)
|
||||||
|
{
|
||||||
|
spawn_interval_ns = NsFromSeconds(1);
|
||||||
|
}
|
||||||
|
b32 should_spawn = spawner->last_spawn_reset_ns == 0 || spawner->last_spawn_reset_ns + spawn_interval_ns <= frame->time_ns;
|
||||||
|
if (should_spawn)
|
||||||
|
{
|
||||||
|
spawner->last_spawn_reset_ns = frame->time_ns;
|
||||||
|
P_Ent *pickup = P_PushTempEnt(scratch.arena, &queued_ents);
|
||||||
|
{
|
||||||
|
pickup->key = P_RandEntKey();
|
||||||
|
pickup->xf = spawner->xf;
|
||||||
|
pickup->is_pickup = 1;
|
||||||
|
pickup->source = spawner->key;
|
||||||
|
pickup->is_health = spawner->is_health_spawn;
|
||||||
|
}
|
||||||
|
spawner->pickup = pickup->key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
P_SpawnEntsFromList(frame, queued_ents);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Spawn guys
|
//- Spawn guys
|
||||||
|
|
||||||
@ -3293,7 +3360,12 @@ void P_StepFrame(P_Frame *frame)
|
|||||||
{
|
{
|
||||||
P_SpaceEntry *entry = &entry_node->entry;
|
P_SpaceEntry *entry = &entry_node->entry;
|
||||||
P_EntKey potential_victim_key = (P_EntKey) { .v = entry->shape_id };
|
P_EntKey potential_victim_key = (P_EntKey) { .v = entry->shape_id };
|
||||||
if (!P_MatchEntKey(potential_victim_key, firer->key) || P_IsEntKeyNil(firer->key))
|
P_Ent *potential_victim = P_EntFromKey(frame, potential_victim_key);
|
||||||
|
b32 can_hit = (
|
||||||
|
P_IsEntNil(potential_victim) ||
|
||||||
|
(potential_victim->is_guy && (!P_MatchEntKey(potential_victim->key, firer->key) || P_IsEntKeyNil(firer->key)))
|
||||||
|
);
|
||||||
|
if (can_hit)
|
||||||
{
|
{
|
||||||
P_Shape potential_victim_shape = entry->shape;
|
P_Shape potential_victim_shape = entry->shape;
|
||||||
P_RaycastResult entrance_raycast = P_RaycastShape(potential_victim_shape, path->start, path_dir);
|
P_RaycastResult entrance_raycast = P_RaycastShape(potential_victim_shape, path->start, path_dir);
|
||||||
|
|||||||
14
src/pp/pp.h
14
src/pp/pp.h
@ -144,10 +144,16 @@ Struct(P_Ent)
|
|||||||
|
|
||||||
b32 is_bomb;
|
b32 is_bomb;
|
||||||
|
|
||||||
//- Player / guy / weapon / bullet
|
//- Health
|
||||||
|
|
||||||
|
b32 is_health;
|
||||||
|
|
||||||
|
//- Player / guy / weapon / bullet / pickup
|
||||||
|
|
||||||
P_EntKey source;
|
P_EntKey source;
|
||||||
|
|
||||||
|
b32 is_pickup;
|
||||||
|
|
||||||
//- Player / Guy
|
//- Player / Guy
|
||||||
|
|
||||||
P_Control control;
|
P_Control control;
|
||||||
@ -185,9 +191,13 @@ Struct(P_Ent)
|
|||||||
|
|
||||||
i64 last_fire_ns;
|
i64 last_fire_ns;
|
||||||
|
|
||||||
//- Spawn
|
//- Spawner
|
||||||
|
|
||||||
b32 is_guy_spawn;
|
b32 is_guy_spawn;
|
||||||
|
b32 is_health_spawn;
|
||||||
|
|
||||||
|
i64 last_spawn_reset_ns;
|
||||||
|
P_EntKey pickup;
|
||||||
|
|
||||||
//- Solver
|
//- Solver
|
||||||
|
|
||||||
|
|||||||
BIN
src/pp/pp_res/misc/health.ase
(Stored with Git LFS)
Normal file
BIN
src/pp/pp_res/misc/health.ase
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
src/pp/pp_res/prefab/HealthSpawn.ase
(Stored with Git LFS)
Normal file
BIN
src/pp/pp_res/prefab/HealthSpawn.ase
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -49,6 +49,7 @@ Enum(P_TileKind)
|
|||||||
X(None, P_PrefabFlag_HideFromEditor) \
|
X(None, P_PrefabFlag_HideFromEditor) \
|
||||||
X(Bot, P_PrefabFlag_None) \
|
X(Bot, P_PrefabFlag_None) \
|
||||||
X(GuySpawn, P_PrefabFlag_None) \
|
X(GuySpawn, P_PrefabFlag_None) \
|
||||||
|
X(HealthSpawn, P_PrefabFlag_None) \
|
||||||
/* --------------------------------------------------- */
|
/* --------------------------------------------------- */
|
||||||
|
|
||||||
//- Prefab flags
|
//- Prefab flags
|
||||||
|
|||||||
@ -628,6 +628,19 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
spawn->xf = msg->xf;
|
spawn->xf = msg->xf;
|
||||||
spawn->continuity_gen += 1;
|
spawn->continuity_gen += 1;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case P_PrefabKind_HealthSpawn:
|
||||||
|
{
|
||||||
|
P_Ent *spawn = P_EntFromKey(world_frame, msg->key);
|
||||||
|
if (!spawn->is_health_spawn)
|
||||||
|
{
|
||||||
|
spawn = P_PushTempEnt(frame_arena, &ents);
|
||||||
|
spawn->key = msg->key;
|
||||||
|
spawn->is_health_spawn = 1;
|
||||||
|
}
|
||||||
|
spawn->xf = msg->xf;
|
||||||
|
spawn->continuity_gen += 1;
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
P_SpawnEntsFromList(world_frame, ents);
|
P_SpawnEntsFromList(world_frame, ents);
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@ -59,10 +59,24 @@ String P_PackWorld(Arena *arena, P_World *src_world)
|
|||||||
{
|
{
|
||||||
result.len += PushString(arena, Lit(" guy_spawn\n")).len;
|
result.len += PushString(arena, Lit(" guy_spawn\n")).len;
|
||||||
}
|
}
|
||||||
|
if (ent->is_health_spawn)
|
||||||
|
{
|
||||||
|
result.len += PushString(arena, Lit(" health_spawn\n")).len;
|
||||||
|
}
|
||||||
|
if (ent->is_health)
|
||||||
|
{
|
||||||
|
result.len += PushString(arena, Lit(" health\n")).len;
|
||||||
|
}
|
||||||
|
if (ent->is_pickup)
|
||||||
|
{
|
||||||
|
result.len += PushString(arena, Lit(" pickup\n")).len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result.len += StringF(arena, " }\n").len;
|
result.len += StringF(arena, " }\n").len;
|
||||||
result.len += StringF(arena, " created_at_ns: \"%F\"\n", FmtSint(ent->created_at_ns)).len;
|
result.len += StringF(arena, " created_at_ns: \"%F\"\n", FmtSint(ent->created_at_ns)).len;
|
||||||
result.len += StringF(arena, " created_at_tick: \"%F\"\n", FmtSint(ent->created_at_tick)).len;
|
result.len += StringF(arena, " created_at_tick: \"%F\"\n", FmtSint(ent->created_at_tick)).len;
|
||||||
|
result.len += StringF(arena, " last_spawn_reset_ns: \"%F\"\n", FmtSint(ent->last_spawn_reset_ns)).len;
|
||||||
|
result.len += StringF(arena, " pickup: \"0x%F\"\n", FmtHex(ent->pickup.v)).len;
|
||||||
result.len += StringF(arena, " pos: \"%F\"\n", FmtFloat2(ent->xf.t)).len;
|
result.len += StringF(arena, " pos: \"%F\"\n", FmtFloat2(ent->xf.t)).len;
|
||||||
result.len += StringF(arena, " angle: \"%F\"\n", FmtFloat(AngleFromVec2(ent->xf.r))).len;
|
result.len += StringF(arena, " angle: \"%F\"\n", FmtFloat(AngleFromVec2(ent->xf.r))).len;
|
||||||
result.len += StringF(arena, " look: \"%F\"\n", FmtFloat2(ent->control.look)).len;
|
result.len += StringF(arena, " look: \"%F\"\n", FmtFloat2(ent->control.look)).len;
|
||||||
@ -176,6 +190,18 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed)
|
|||||||
{
|
{
|
||||||
ent->is_guy_spawn = 1;
|
ent->is_guy_spawn = 1;
|
||||||
}
|
}
|
||||||
|
if (MatchString(prop->value, Lit("health_spawn")))
|
||||||
|
{
|
||||||
|
ent->is_health_spawn = 1;
|
||||||
|
}
|
||||||
|
if (MatchString(prop->value, Lit("health")))
|
||||||
|
{
|
||||||
|
ent->is_health = 1;
|
||||||
|
}
|
||||||
|
if (MatchString(prop->value, Lit("pickup")))
|
||||||
|
{
|
||||||
|
ent->is_pickup = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (MatchString(attr->name, Lit("created_at_ns")))
|
if (MatchString(attr->name, Lit("created_at_ns")))
|
||||||
@ -186,6 +212,14 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed)
|
|||||||
{
|
{
|
||||||
ent->created_at_tick = CR_IntFromString(attr->value);
|
ent->created_at_tick = CR_IntFromString(attr->value);
|
||||||
}
|
}
|
||||||
|
if (MatchString(attr->name, Lit("last_spawn_reset_ns")))
|
||||||
|
{
|
||||||
|
ent->last_spawn_reset_ns = CR_IntFromString(attr->value);
|
||||||
|
}
|
||||||
|
if (MatchString(attr->name, Lit("pickup")))
|
||||||
|
{
|
||||||
|
ent->pickup.v = CR_IntFromString(attr->value);
|
||||||
|
}
|
||||||
if (MatchString(attr->name, Lit("pos")))
|
if (MatchString(attr->name, Lit("pos")))
|
||||||
{
|
{
|
||||||
ent->xf.t = CR_Vec2FromString(attr->value);
|
ent->xf.t = CR_Vec2FromString(attr->value);
|
||||||
|
|||||||
@ -1785,7 +1785,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
frame->local_world->seed = predict_world->seed;
|
frame->local_world->seed = predict_world->seed;
|
||||||
P_ClearFrames(frame->local_world, I64Min, I64Max);
|
P_ClearFrames(frame->local_world, I64Min, I64Max);
|
||||||
|
|
||||||
if (TweakBool("Interpolation enabled", 1))
|
if (TweakBool("Interpolation enabled", 0))
|
||||||
{
|
{
|
||||||
// Locate sim keyframes
|
// Locate sim keyframes
|
||||||
P_Frame *left_sim_frame = &P_NilFrame;
|
P_Frame *left_sim_frame = &P_NilFrame;
|
||||||
@ -2030,7 +2030,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
frame->shade_cursor = MulAffineVec2(frame->af.screen_to_shade, frame->screen_cursor);
|
frame->shade_cursor = MulAffineVec2(frame->af.screen_to_shade, frame->screen_cursor);
|
||||||
frame->world_cursor = MulAffineVec2(frame->af.screen_to_world, frame->screen_cursor);
|
frame->world_cursor = MulAffineVec2(frame->af.screen_to_world, frame->screen_cursor);
|
||||||
|
|
||||||
b32 show_editor_ui = TweakBool("Show editor UI", 0);
|
b32 show_editor_ui = TweakBool("Show editor UI", 1);
|
||||||
|
|
||||||
frame->world_selection_start = frame->world_cursor;
|
frame->world_selection_start = frame->world_cursor;
|
||||||
if (frame->is_editing)
|
if (frame->is_editing)
|
||||||
@ -2150,7 +2150,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
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))
|
||||||
{
|
{
|
||||||
// TODO: Use entity's prefab flags to determine editor draw status
|
// TODO: Use entity's prefab flags to determine editor draw status
|
||||||
if (ent->is_guy_spawn)
|
if (ent->is_guy_spawn || ent->is_health_spawn)
|
||||||
{
|
{
|
||||||
DrawNode *draw_node = PushStruct(frame->arena, DrawNode);
|
DrawNode *draw_node = PushStruct(frame->arena, DrawNode);
|
||||||
SllQueuePush(first_draw_node, last_draw_node, draw_node);
|
SllQueuePush(first_draw_node, last_draw_node, draw_node);
|
||||||
@ -2172,6 +2172,18 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- Push pickups
|
||||||
|
for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
|
{
|
||||||
|
if (ent->is_pickup)
|
||||||
|
{
|
||||||
|
DrawNode *draw_node = PushStruct(frame->arena, DrawNode);
|
||||||
|
SllQueuePush(first_draw_node, last_draw_node, draw_node);
|
||||||
|
++draw_nodes_count;
|
||||||
|
draw_node->ent = ent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//- Push guys
|
//- Push guys
|
||||||
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))
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user