working spawn points
This commit is contained in:
parent
e0356f73e8
commit
e88c91b1ab
@ -1,6 +1,47 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Value conversion utilities
|
//~ Value conversion utilities
|
||||||
|
|
||||||
|
String CR_SanitizeString(Arena *arena, String str)
|
||||||
|
{
|
||||||
|
String result = Zi;
|
||||||
|
result.text = ArenaNext(arena, u8);
|
||||||
|
for (u64 idx = 0; idx < str.len; ++idx)
|
||||||
|
{
|
||||||
|
u8 c = str.text[idx];
|
||||||
|
String sanitized = Zi;
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
sanitized.text = &c;
|
||||||
|
sanitized.len = 1;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
{
|
||||||
|
sanitized = Lit("\\n");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
{
|
||||||
|
sanitized = Lit("\\");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
{
|
||||||
|
sanitized = Lit("\\\"");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
result.len += PushString(arena, sanitized).len;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
i64 CR_IntFromString(String str)
|
i64 CR_IntFromString(String str)
|
||||||
{
|
{
|
||||||
i64 result = 0;
|
i64 result = 0;
|
||||||
@ -330,7 +371,7 @@ CR_Item *CR_ItemFromString(Arena *arena, String str)
|
|||||||
}
|
}
|
||||||
else if (c == '\"')
|
else if (c == '\"')
|
||||||
{
|
{
|
||||||
if (pos == text_start)
|
if (!text_is_string && pos == text_start)
|
||||||
{
|
{
|
||||||
text_is_string = 1;
|
text_is_string = 1;
|
||||||
text_start = pos + 1;
|
text_start = pos + 1;
|
||||||
|
|||||||
@ -17,6 +17,7 @@ Struct(CR_Item)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Value conversion utilities
|
//~ Value conversion utilities
|
||||||
|
|
||||||
|
String CR_SanitizeString(Arena *arena, String str);
|
||||||
i64 CR_IntFromString(String str);
|
i64 CR_IntFromString(String str);
|
||||||
f64 CR_FloatFromString(String str);
|
f64 CR_FloatFromString(String str);
|
||||||
b32 CR_BoolFromString(String str);
|
b32 CR_BoolFromString(String str);
|
||||||
|
|||||||
158
src/pp/pp.c
158
src/pp/pp.c
@ -210,166 +210,26 @@ P_Anim P_AnimFromEnt(P_Ent *ent, i64 time_ns)
|
|||||||
{
|
{
|
||||||
P_Anim result = Zi;
|
P_Anim result = Zi;
|
||||||
|
|
||||||
i64 animation_rate_ns = NsFromSeconds(0.100);
|
|
||||||
|
|
||||||
// TODO: Determine animation dynamically
|
// TODO: Determine animation dynamically
|
||||||
|
i64 animation_rate_ns = NsFromSeconds(0.100);
|
||||||
{
|
{
|
||||||
i64 walk_duration_ns = time_ns;
|
i64 walk_duration_ns = time_ns;
|
||||||
result.frame_seq = walk_duration_ns / animation_rate_ns;
|
result.frame_seq = walk_duration_ns / animation_rate_ns;
|
||||||
result.span = SPR_SpanKeyFromName(Lit("walk"));
|
result.span = SPR_SpanKeyFromName(Lit("walk"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Use prefab lookup
|
||||||
|
if (ent->is_guy)
|
||||||
|
{
|
||||||
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("sprite/bla3.ase")));
|
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("sprite/bla3.ase")));
|
||||||
result.wep_sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("sprite/raah.ase")));
|
result.wep_sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("sprite/raah.ase")));
|
||||||
|
}
|
||||||
|
else if (ent->is_guy_spawn)
|
||||||
|
{
|
||||||
|
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("prefab/GuySpawn.ase")));
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// P_Anim result = Zi;
|
|
||||||
|
|
||||||
// // result.slice_to_world_af = AffineIdentity;
|
|
||||||
// // result.slice_to_world_af = ent->af;
|
|
||||||
|
|
||||||
// i64 animation_rate_ns = NsFromSeconds(0.100);
|
|
||||||
|
|
||||||
// SPR_SpanKey span_key = Zi;
|
|
||||||
// {
|
|
||||||
// // TODO: Determine span dynamically
|
|
||||||
// span_key = SPR_SpanKeyFromName(Lit("walk"));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// SPR_SheetKey body_sheet_key = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("sprite/bla3.ase")));
|
|
||||||
// SPR_SheetKey weapon_sheet_key = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("sprite/raahase")));
|
|
||||||
|
|
||||||
// //- Body
|
|
||||||
// {
|
|
||||||
// // TODO: Real walk animation
|
|
||||||
// i64 walk_duration_ns = time_ns;
|
|
||||||
// i64 frame_seq = walk_duration_ns / animation_rate_ns;
|
|
||||||
|
|
||||||
// SPR_Frame sframe = SPR_FrameFromSheet(body_sheet_key, span_key, frame_seq);
|
|
||||||
|
|
||||||
// // FIXME: Use origin ray
|
|
||||||
// {
|
|
||||||
// Vec2 world_dims = DivVec2(sframe.dims, P_CellsPerMeter);
|
|
||||||
// result.body_to_world_af = AffineIdentity;
|
|
||||||
// result.body_to_world_af.og = ent->af.og;
|
|
||||||
// // result.body_to_world_af.og = SubVec2(result.body_to_world_af.og, MulVec2(world_dims, 0.25));
|
|
||||||
// result.body_to_world_af = AffineWithWorldRotation(result.body_to_world_af, AngleFromVec2(ent->control.look));
|
|
||||||
// result.body_to_world_af = TranslateAffine(result.body_to_world_af, MulVec2(world_dims, -0.5));
|
|
||||||
// result.body_to_world_af = ScaleAffine(result.body_to_world_af, world_dims);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// {
|
|
||||||
// result.
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// result.body_slice = sframe.slice;
|
|
||||||
|
|
||||||
// {
|
|
||||||
// // result.
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// // SPR_Ray origin_ray = SPR_RayFromFrame(body_sheet_key, origin_layer_key, frame_idx);
|
|
||||||
// // SPR_Ray ap_ray = SPR_RayFromFrame(body_sheet_key, ap_layer_key, frame_idx);
|
|
||||||
|
|
||||||
// // {
|
|
||||||
// // // Vec2 world_dims = VEC2(0.5, 0.5);
|
|
||||||
// // Vec2 px_dims = slice.dims;
|
|
||||||
// // Vec2 world_dims = DivVec2(px_dims, P_CellsPerMeter);
|
|
||||||
// // result.slice_to_world_af = AffineIdentity;
|
|
||||||
// // result.slice_to_world_af.og = ent->af.og;
|
|
||||||
// // // result.slice_to_world_af.og = SubVec2(result.slice_to_world_af.og, MulVec2(world_dims, 0.25));
|
|
||||||
// // result.slice_to_world_af = AffineWithWorldRotation(result.slice_to_world_af, AngleFromVec2(ent->control.look));
|
|
||||||
// // result.slice_to_world_af = TranslateAffine(result.slice_to_world_af, MulVec2(world_dims, -0.5));
|
|
||||||
// // result.slice_to_world_af = ScaleAffine(result.slice_to_world_af, world_dims);
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // result.slice = SPR_SliceFromSheet(sheet,
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //- Weapon
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return result;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// P_Anim result = Zi;
|
|
||||||
|
|
||||||
// // result.slice_to_world_af = AffineIdentity;
|
|
||||||
// // result.slice_to_world_af = ent->af;
|
|
||||||
|
|
||||||
// i64 animation_rate_ns = NsFromSeconds(0.100);
|
|
||||||
|
|
||||||
// SPR_LayerKey origin_layer_key = SPR_LayerKeyFromName(Lit(".origin"));
|
|
||||||
// SPR_LayerKey ap_layer_key = SPR_LayerKeyFromName(Lit(".ap"));
|
|
||||||
// SPR_SpanKey span_key = Zi;
|
|
||||||
// {
|
|
||||||
// // TODO: Determine span dynamically
|
|
||||||
// span_key = SPR_SpanKeyFromName(Lit("walk"));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// SPR_SheetKey body_sheet_key = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("sprite/bla3.ase")));
|
|
||||||
// SPR_SheetKey weapon_sheet_key = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("sprite/raahase")));
|
|
||||||
|
|
||||||
// // Body
|
|
||||||
// {
|
|
||||||
// i64 frame_idx = 0;
|
|
||||||
// {
|
|
||||||
// // TODO: Real walk animation
|
|
||||||
// SPR_Span span = SPR_SpanFromKey(body_sheet_key, span_key);
|
|
||||||
// i64 walk_duration_ns = time_ns;
|
|
||||||
// i64 frame_seq = walk_duration_ns / animation_rate_ns;
|
|
||||||
// i64 frame_idx = span.start + (frame_seq % (span.end - span.start));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// SPR_Slice slice = SPR_SliceFromFrame(body_sheet_key, SPR_NilLayerKey, frame_idx);
|
|
||||||
// SPR_Ray origin_ray = SPR_RayFromFrame(body_sheet_key, origin_layer_key, frame_idx);
|
|
||||||
// SPR_Ray ap_ray = SPR_RayFromFrame(body_sheet_key, ap_layer_key, frame_idx);
|
|
||||||
|
|
||||||
// {
|
|
||||||
// // Vec2 world_dims = VEC2(0.5, 0.5);
|
|
||||||
// Vec2 px_dims = slice.dims;
|
|
||||||
// Vec2 world_dims = DivVec2(px_dims, P_CellsPerMeter);
|
|
||||||
// result.slice_to_world_af = AffineIdentity;
|
|
||||||
// result.slice_to_world_af.og = ent->af.og;
|
|
||||||
// // result.slice_to_world_af.og = SubVec2(result.slice_to_world_af.og, MulVec2(world_dims, 0.25));
|
|
||||||
// result.slice_to_world_af = AffineWithWorldRotation(result.slice_to_world_af, AngleFromVec2(ent->control.look));
|
|
||||||
// result.slice_to_world_af = TranslateAffine(result.slice_to_world_af, MulVec2(world_dims, -0.5));
|
|
||||||
// result.slice_to_world_af = ScaleAffine(result.slice_to_world_af, world_dims);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // result.slice = SPR_SliceFromSheet(sheet,
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Weapon
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -68,8 +68,7 @@ Struct(P_DebugDrawNode)
|
|||||||
//~ Ent types
|
//~ Ent types
|
||||||
|
|
||||||
// TODO: Move boolean fields into bitwise property flags
|
// TODO: Move boolean fields into bitwise property flags
|
||||||
|
// TODO: Pack efficiently
|
||||||
// TODO: Pack efficiently, deduplicate redundant fields
|
|
||||||
|
|
||||||
#define P_MinPlayerNameLen 1
|
#define P_MinPlayerNameLen 1
|
||||||
#define P_MaxPlayerNameLen 24
|
#define P_MaxPlayerNameLen 24
|
||||||
@ -140,6 +139,10 @@ Struct(P_Ent)
|
|||||||
u8 string_len;
|
u8 string_len;
|
||||||
u8 string_text[P_MaxPlayerNameLen + 8];
|
u8 string_text[P_MaxPlayerNameLen + 8];
|
||||||
|
|
||||||
|
//- Spawn
|
||||||
|
|
||||||
|
b32 is_guy_spawn;
|
||||||
|
|
||||||
//- Solver
|
//- Solver
|
||||||
|
|
||||||
Vec2 solved_v;
|
Vec2 solved_v;
|
||||||
|
|||||||
BIN
src/pp/pp_res/prefab/GuySpawn.ase
(Stored with Git LFS)
Normal file
BIN
src/pp/pp_res/prefab/GuySpawn.ase
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -37,7 +37,7 @@ Enum(P_TileKind)
|
|||||||
X(None, P_PrefabFlag_HideFromEditor) \
|
X(None, P_PrefabFlag_HideFromEditor) \
|
||||||
X(Guy, P_PrefabFlag_None) \
|
X(Guy, P_PrefabFlag_None) \
|
||||||
X(Dummy, P_PrefabFlag_None) \
|
X(Dummy, P_PrefabFlag_None) \
|
||||||
X(SpawnPoint, P_PrefabFlag_None) \
|
X(GuySpawn, P_PrefabFlag_None) \
|
||||||
/* --------------------------------------------------- */
|
/* --------------------------------------------------- */
|
||||||
|
|
||||||
//- Prefab flags
|
//- Prefab flags
|
||||||
|
|||||||
@ -232,6 +232,10 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
DllQueuePushNP(bin->first, bin->last, client, next_in_bin, prev_in_bin);
|
DllQueuePushNP(bin->first, bin->last, client, next_in_bin, prev_in_bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Only accept desired player key from host client
|
||||||
|
client->player = msg->key;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Acknowledge player connection
|
// Acknowledge player connection
|
||||||
{
|
{
|
||||||
@ -292,7 +296,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Create guy entities
|
//- Spawn guys
|
||||||
|
|
||||||
{
|
{
|
||||||
P_EntList new_guys = Zi;
|
P_EntList new_guys = Zi;
|
||||||
@ -308,10 +312,68 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
if (P_IsEntNil(guy))
|
if (P_IsEntNil(guy))
|
||||||
{
|
{
|
||||||
guy = P_PushTempEnt(frame_arena, &new_guys);
|
guy = P_PushTempEnt(frame_arena, &new_guys);
|
||||||
guy->key = player->guy;
|
|
||||||
}
|
|
||||||
guy->is_guy = 1;
|
guy->is_guy = 1;
|
||||||
guy->has_weapon = 1;
|
guy->has_weapon = 1;
|
||||||
|
guy->key = player->guy;
|
||||||
|
|
||||||
|
//- Choose guy spawn point
|
||||||
|
{
|
||||||
|
P_Ent *highest_scoring_spawn = &P_NilEnt;
|
||||||
|
{
|
||||||
|
Struct(SpawnNode)
|
||||||
|
{
|
||||||
|
SpawnNode *next;
|
||||||
|
f32 score;
|
||||||
|
P_Ent *ent;
|
||||||
|
};
|
||||||
|
SpawnNode *first_spawn_node = 0;
|
||||||
|
SpawnNode *last_spawn_node = 0;
|
||||||
|
|
||||||
|
// Push spawns
|
||||||
|
for (P_Ent *spawn = P_FirstEnt(world_frame); !P_IsEntNil(spawn); spawn = P_NextEnt(spawn))
|
||||||
|
{
|
||||||
|
if (spawn->is_guy_spawn)
|
||||||
|
{
|
||||||
|
SpawnNode *spawn_node = PushStruct(frame_arena, SpawnNode);
|
||||||
|
SllQueuePush(first_spawn_node, last_spawn_node, spawn_node);
|
||||||
|
spawn_node->ent = spawn;
|
||||||
|
spawn_node->score = Inf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Score spawns
|
||||||
|
for (P_Ent *ent = P_FirstEnt(world_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
|
{
|
||||||
|
b32 should_score = 0;
|
||||||
|
if (ent->is_guy)
|
||||||
|
{
|
||||||
|
should_score = 1;
|
||||||
|
}
|
||||||
|
if (should_score)
|
||||||
|
{
|
||||||
|
for (SpawnNode *spawn_node = first_spawn_node; spawn_node; spawn_node = spawn_node->next)
|
||||||
|
{
|
||||||
|
f32 score = Vec2Len(SubVec2(ent->xf.t, spawn_node->ent->xf.t));
|
||||||
|
spawn_node->score = MinF32(spawn_node->score, score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find highest scoring spawn_node
|
||||||
|
i64 highest_score = -Inf;
|
||||||
|
for (SpawnNode *spawn_node = first_spawn_node; spawn_node; spawn_node = spawn_node->next)
|
||||||
|
{
|
||||||
|
if (spawn_node->score > highest_score)
|
||||||
|
{
|
||||||
|
highest_score = spawn_node->score;
|
||||||
|
highest_scoring_spawn = spawn_node->ent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guy->xf = highest_scoring_spawn->xf;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P_SpawnEntsFromList(world_frame, new_guys);
|
P_SpawnEntsFromList(world_frame, new_guys);
|
||||||
@ -592,33 +654,42 @@ void S_TickForever(WaveLaneCtx *lane)
|
|||||||
guy->xf = msg->xf;
|
guy->xf = msg->xf;
|
||||||
guy->is_guy = 1;
|
guy->is_guy = 1;
|
||||||
guy->has_weapon = 1;
|
guy->has_weapon = 1;
|
||||||
guy->exists = 1;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case P_PrefabKind_Dummy:
|
case P_PrefabKind_Dummy:
|
||||||
{
|
{
|
||||||
P_Ent *dummy = P_EntFromKey(world_frame, msg->key);
|
P_Ent *dummy = P_EntFromKey(world_frame, msg->key);
|
||||||
if (P_IsEntNil(dummy))
|
if (!dummy->is_dummy)
|
||||||
{
|
{
|
||||||
dummy = P_PushTempEnt(frame_arena, &ents);
|
dummy = P_PushTempEnt(frame_arena, &ents);
|
||||||
dummy->key = msg->key;
|
dummy->key = msg->key;
|
||||||
dummy->is_player = 1;
|
dummy->is_player = 1;
|
||||||
dummy->is_dummy = 1;
|
dummy->is_dummy = 1;
|
||||||
dummy->exists = 1;
|
|
||||||
P_SetEntString(dummy, name);
|
P_SetEntString(dummy, name);
|
||||||
}
|
}
|
||||||
P_Ent *guy = P_EntFromKey(world_frame, dummy->guy);
|
P_Ent *guy = P_EntFromKey(world_frame, dummy->guy);
|
||||||
if (P_IsEntNil(guy))
|
if (!guy->is_guy)
|
||||||
{
|
{
|
||||||
guy = P_PushTempEnt(frame_arena, &ents);
|
guy = P_PushTempEnt(frame_arena, &ents);
|
||||||
guy->key = P_RandKey();
|
guy->key = P_RandKey();
|
||||||
guy->is_guy = 1;
|
guy->is_guy = 1;
|
||||||
guy->has_weapon = 1;
|
guy->has_weapon = 1;
|
||||||
guy->exists = 1;
|
|
||||||
dummy->guy = guy->key;
|
dummy->guy = guy->key;
|
||||||
}
|
}
|
||||||
guy->xf = msg->xf;
|
guy->xf = msg->xf;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case P_PrefabKind_GuySpawn:
|
||||||
|
{
|
||||||
|
P_Ent *spawn = P_EntFromKey(world_frame, msg->key);
|
||||||
|
if (!spawn->is_guy_spawn)
|
||||||
|
{
|
||||||
|
spawn = P_PushTempEnt(frame_arena, &ents);
|
||||||
|
spawn->key = msg->key;
|
||||||
|
spawn->is_guy_spawn = 1;
|
||||||
|
}
|
||||||
|
spawn->xf = msg->xf;
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
P_SpawnEntsFromList(world_frame, ents);
|
P_SpawnEntsFromList(world_frame, ents);
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@ -26,10 +26,6 @@ String P_PackWorld(Arena *arena, P_World *src_world)
|
|||||||
{
|
{
|
||||||
should_pack = 0;
|
should_pack = 0;
|
||||||
}
|
}
|
||||||
if (ent->is_player)
|
|
||||||
{
|
|
||||||
should_pack = 0;
|
|
||||||
}
|
|
||||||
if (should_pack)
|
if (should_pack)
|
||||||
{
|
{
|
||||||
result.len += StringF(arena, " 0x%F:\n", FmtHex(ent->key.v)).len;
|
result.len += StringF(arena, " 0x%F:\n", FmtHex(ent->key.v)).len;
|
||||||
@ -58,13 +54,20 @@ String P_PackWorld(Arena *arena, P_World *src_world)
|
|||||||
{
|
{
|
||||||
result.len += PushString(arena, Lit(" bullet\n")).len;
|
result.len += PushString(arena, Lit(" bullet\n")).len;
|
||||||
}
|
}
|
||||||
|
if (ent->is_guy_spawn)
|
||||||
|
{
|
||||||
|
result.len += PushString(arena, Lit(" guy_spawn\n")).len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result.len += StringF(arena, " }\n").len;
|
result.len += StringF(arena, " }\n").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, " exists: \"%F\"\n", FmtFloat(ent->exists)).len;
|
result.len += StringF(arena, " exists: \"%F\"\n", FmtFloat(ent->exists)).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;
|
||||||
result.len += StringF(arena, " health: \"%F\"\n", FmtFloat(ent->health)).len;
|
result.len += StringF(arena, " health: \"%F\"\n", FmtFloat(ent->health)).len;
|
||||||
|
result.len += StringF(arena, " guy: \"0x%F\"\n", FmtHex(ent->guy.v)).len;
|
||||||
|
result.len += StringF(arena, " text: \"%F\"\n", FmtString(CR_SanitizeString(scratch.arena, STRING(ent->string_len, ent->string_text)))).len;
|
||||||
}
|
}
|
||||||
result.len += PushString(arena, Lit(" }\n")).len;
|
result.len += PushString(arena, Lit(" }\n")).len;
|
||||||
}
|
}
|
||||||
@ -159,6 +162,10 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed)
|
|||||||
{
|
{
|
||||||
ent->is_bullet = 1;
|
ent->is_bullet = 1;
|
||||||
}
|
}
|
||||||
|
if (MatchString(prop->value, Lit("guy_spawn")))
|
||||||
|
{
|
||||||
|
ent->is_guy_spawn = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (MatchString(attr->name, Lit("pos")))
|
if (MatchString(attr->name, Lit("pos")))
|
||||||
@ -169,21 +176,29 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed)
|
|||||||
{
|
{
|
||||||
ent->xf.r = Vec2FromAngle(CR_FloatFromString(attr->value));
|
ent->xf.r = Vec2FromAngle(CR_FloatFromString(attr->value));
|
||||||
}
|
}
|
||||||
|
if (MatchString(attr->name, Lit("look")))
|
||||||
|
{
|
||||||
|
ent->control.look = CR_Vec2FromString(attr->value);
|
||||||
|
}
|
||||||
if (MatchString(attr->name, Lit("exists")))
|
if (MatchString(attr->name, Lit("exists")))
|
||||||
{
|
{
|
||||||
ent->exists = CR_FloatFromString(attr->value);
|
ent->exists = CR_FloatFromString(attr->value);
|
||||||
}
|
}
|
||||||
if (MatchString(attr->name, Lit("health")))
|
|
||||||
{
|
|
||||||
ent->health = CR_FloatFromString(attr->value);
|
|
||||||
}
|
|
||||||
if (MatchString(attr->name, Lit("look")))
|
if (MatchString(attr->name, Lit("look")))
|
||||||
{
|
{
|
||||||
ent->control.look = CR_Vec2FromString(attr->value);
|
ent->control.look = CR_Vec2FromString(attr->value);
|
||||||
}
|
}
|
||||||
if (MatchString(attr->name, Lit("health")))
|
if (MatchString(attr->name, Lit("health")))
|
||||||
{
|
{
|
||||||
ent->health = CR_FloatFromString(attr->value);;
|
ent->health = CR_FloatFromString(attr->value);
|
||||||
|
}
|
||||||
|
if (MatchString(attr->name, Lit("guy")))
|
||||||
|
{
|
||||||
|
ent->guy.v = CR_IntFromString(attr->value);
|
||||||
|
}
|
||||||
|
if (MatchString(attr->name, Lit("text")))
|
||||||
|
{
|
||||||
|
P_SetEntString(ent, attr->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -630,6 +630,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
BB_WriteF32(&bbw, prev_frame->edit_camera_pos.x);
|
BB_WriteF32(&bbw, prev_frame->edit_camera_pos.x);
|
||||||
BB_WriteF32(&bbw, prev_frame->edit_camera_pos.y);
|
BB_WriteF32(&bbw, prev_frame->edit_camera_pos.y);
|
||||||
BB_WriteF32(&bbw, prev_frame->edit_camera_zoom);
|
BB_WriteF32(&bbw, prev_frame->edit_camera_zoom);
|
||||||
|
BB_WriteF32(&bbw, prev_frame->look.x);
|
||||||
|
BB_WriteF32(&bbw, prev_frame->look.y);
|
||||||
BB_WriteString(&bbw, prev_frame->window_restore);
|
BB_WriteString(&bbw, prev_frame->window_restore);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -639,6 +641,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
frame->edit_camera_pos.x = BB_ReadF32(&bbr);
|
frame->edit_camera_pos.x = BB_ReadF32(&bbr);
|
||||||
frame->edit_camera_pos.y = BB_ReadF32(&bbr);
|
frame->edit_camera_pos.y = BB_ReadF32(&bbr);
|
||||||
frame->edit_camera_zoom = BB_ReadF32(&bbr);
|
frame->edit_camera_zoom = BB_ReadF32(&bbr);
|
||||||
|
frame->look.x = BB_ReadF32(&bbr);
|
||||||
|
frame->look.y = BB_ReadF32(&bbr);
|
||||||
frame->window_restore = BB_ReadString(frame->arena, &bbr);
|
frame->window_restore = BB_ReadString(frame->arena, &bbr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1101,7 +1105,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Try to connect to server
|
//- Try to connect to server
|
||||||
|
|
||||||
frame->desired_sim_key = NET_KeyFromString(Lit("127.0.0.1"), Lit("22121"));
|
NET_Key local_sim_key = NET_KeyFromString(Lit("127.0.0.1"), Lit("22121"));
|
||||||
|
frame->desired_sim_key = local_sim_key;
|
||||||
if (!NET_MatchKey(frame->sim_key, frame->desired_sim_key))
|
if (!NET_MatchKey(frame->sim_key, frame->desired_sim_key))
|
||||||
{
|
{
|
||||||
i64 retry_rate_ns = NsFromSeconds(0.100);
|
i64 retry_rate_ns = NsFromSeconds(0.100);
|
||||||
@ -1122,6 +1127,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
P_MsgNode tmp_msg_node = Zi;
|
P_MsgNode tmp_msg_node = Zi;
|
||||||
tmp_msg_node.msg.kind = P_MsgKind_Connect;
|
tmp_msg_node.msg.kind = P_MsgKind_Connect;
|
||||||
tmp_msg_node.msg.data = Lit("Bro");
|
tmp_msg_node.msg.data = Lit("Bro");
|
||||||
|
tmp_msg_node.msg.key = V.player_key;
|
||||||
|
|
||||||
P_MsgList tmp_msglist = Zi;
|
P_MsgList tmp_msglist = Zi;
|
||||||
tmp_msglist.count = 1;
|
tmp_msglist.count = 1;
|
||||||
@ -2070,29 +2076,63 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Draw guy sprites
|
//- Draw entities
|
||||||
|
|
||||||
|
{
|
||||||
|
Struct(DrawNode)
|
||||||
|
{
|
||||||
|
DrawNode *next;
|
||||||
|
P_Ent *ent;
|
||||||
|
};
|
||||||
|
|
||||||
|
i64 draw_nodes_count = 0;
|
||||||
|
DrawNode *first_draw_node = 0;
|
||||||
|
DrawNode *last_draw_node = 0;
|
||||||
|
|
||||||
|
//- Push editor ents
|
||||||
|
if (frame->is_editing)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
if (ent->is_guy_spawn)
|
||||||
|
{
|
||||||
|
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
|
||||||
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))
|
||||||
{
|
{
|
||||||
if (ent->is_guy)
|
if (ent->is_guy)
|
||||||
{
|
{
|
||||||
P_Anim anim = P_AnimFromEnt(ent, local_frame->time_ns);
|
DrawNode *draw_node = PushStruct(frame->arena, DrawNode);
|
||||||
SPR_Sprite body = SPR_SpriteFromSheet(anim.sheet, anim.span, anim.frame_seq);
|
SllQueuePush(first_draw_node, last_draw_node, draw_node);
|
||||||
SPR_Sprite wep = SPR_SpriteFromSheet(anim.wep_sheet, anim.span, anim.frame_seq);
|
++draw_nodes_count;
|
||||||
|
draw_node->ent = ent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//- Compute sprite transforms
|
//- Build quads
|
||||||
Affine body_pix_to_world_af = AffineIdentity;
|
for (DrawNode *draw_node = first_draw_node; draw_node; draw_node = draw_node->next)
|
||||||
Affine wep_pix_to_world_af = AffineIdentity;
|
|
||||||
{
|
{
|
||||||
|
P_Ent *ent = draw_node->ent;
|
||||||
|
P_Anim anim = P_AnimFromEnt(ent, local_frame->time_ns);
|
||||||
|
|
||||||
Vec2 pix_scale = VEC2(1.0 / P_CellsPerMeter, 1.0 / P_CellsPerMeter);
|
Vec2 pix_scale = VEC2(1.0 / P_CellsPerMeter, 1.0 / P_CellsPerMeter);
|
||||||
Affine ent_to_world_af = MulAffineXform(AffineIdentity, ent->xf);
|
Affine ent_to_world_af = MulAffineXform(AffineIdentity, ent->xf);
|
||||||
|
|
||||||
//- Compute body transform
|
//- Compute body sprite
|
||||||
|
SPR_Sprite body = Zi;
|
||||||
|
Affine body_pix_to_world_af = AffineIdentity;
|
||||||
{
|
{
|
||||||
|
body = SPR_SpriteFromSheet(anim.sheet, anim.span, anim.frame_seq);
|
||||||
|
|
||||||
body_pix_to_world_af = MulAffine(body_pix_to_world_af, ent_to_world_af);
|
body_pix_to_world_af = MulAffine(body_pix_to_world_af, ent_to_world_af);
|
||||||
body_pix_to_world_af = ScaleAffine(body_pix_to_world_af, pix_scale);
|
body_pix_to_world_af = ScaleAffine(body_pix_to_world_af, pix_scale);
|
||||||
|
|
||||||
@ -2101,8 +2141,13 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
body_pix_to_world_af = TranslateAffine(body_pix_to_world_af, NegVec2(anchor_ray.pos));
|
body_pix_to_world_af = TranslateAffine(body_pix_to_world_af, NegVec2(anchor_ray.pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Compute weapon transform
|
//- Compute weapon sprite
|
||||||
|
SPR_Sprite wep = Zi;
|
||||||
|
Affine wep_pix_to_world_af = AffineIdentity;
|
||||||
|
if (ent->is_guy)
|
||||||
{
|
{
|
||||||
|
wep = SPR_SpriteFromSheet(anim.wep_sheet, anim.span, anim.frame_seq);
|
||||||
|
|
||||||
wep_pix_to_world_af = MulAffine(wep_pix_to_world_af, ent_to_world_af);
|
wep_pix_to_world_af = MulAffine(wep_pix_to_world_af, ent_to_world_af);
|
||||||
wep_pix_to_world_af = ScaleAffine(wep_pix_to_world_af, pix_scale);
|
wep_pix_to_world_af = ScaleAffine(wep_pix_to_world_af, pix_scale);
|
||||||
|
|
||||||
@ -2116,7 +2161,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, anchor_ray.dir);
|
wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, anchor_ray.dir);
|
||||||
wep_pix_to_world_af = TranslateAffine(wep_pix_to_world_af, NegVec2(anchor_ray.pos));
|
wep_pix_to_world_af = TranslateAffine(wep_pix_to_world_af, NegVec2(anchor_ray.pos));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//- Push weapon quad
|
//- Push weapon quad
|
||||||
if (body.ready && wep.ready)
|
if (body.ready && wep.ready)
|
||||||
@ -2146,7 +2190,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Push test bullet particles
|
//- Push test bullet particles
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user