From a064dc6d09e2a50a611789604ac0fdc91e2fea5f Mon Sep 17 00:00:00 2001 From: doyle Date: Sat, 14 Oct 2023 12:01:22 +1100 Subject: [PATCH] fp: Make transported entities adopt the new mob spawner waypoints --- _clang-format | 4 --- feely_pona.cpp | 82 +++++++++++++++++++++++++++------------------ feely_pona_stdlib.h | 9 ++++- 3 files changed, 57 insertions(+), 38 deletions(-) diff --git a/_clang-format b/_clang-format index a123814..9132132 100644 --- a/_clang-format +++ b/_clang-format @@ -327,10 +327,6 @@ NamespaceIndentation: None PackConstructorInitializers: CurrentLine PointerAlignment: Right -# Different ways to arrange specifiers and qualifiers (e.g. const/volatile). -QualifierAlignment: Custom -QualifierOrder: ['inline', 'static', 'type', 'const', 'volatile'] - # false: # // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information # /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */ diff --git a/feely_pona.cpp b/feely_pona.cpp index f982728..82d81e7 100644 --- a/feely_pona.cpp +++ b/feely_pona.cpp @@ -588,6 +588,37 @@ FP_GetClosestPortalMonkeyResult FP_GetClosestPortalMonkey(FP_Game *game, FP_Game return result; } +static void FP_AppendMobSpawnerWaypoints(FP_Game *game, FP_GameEntityHandle src_handle, FP_GameEntityHandle dest_handle) +{ + FP_GameEntity *src = FP_Game_GetEntity(game, src_handle); + FP_GameEntity *dest = FP_Game_GetEntity(game, dest_handle); + if (FP_Game_IsNilEntity(src) || FP_Game_IsNilEntity(dest)) + return; + + Dqn_f32 one_meter = FP_Game_MetersToPixelsNx1(game->play, 1.f); + for (FP_GameEntity *waypoint_entity = src->first_child; waypoint_entity; waypoint_entity = waypoint_entity->next) { + if ((waypoint_entity->flags & FP_GameEntityFlag_MobSpawnerWaypoint) == 0) + continue; + + // NOTE: Add the waypoint + FP_SentinelListLink *waypoint = FP_SentinelList_Make(&dest->waypoints, game->play.chunk_pool); + waypoint->data.entity = waypoint_entity->handle; + waypoint->data.arrive = FP_GameWaypointArrive_WhenWithinEntitySize; + waypoint->data.value = 1.5f; + + uint32_t min_vary = DQN_CAST(uint32_t)(one_meter * .5f); + uint32_t max_vary = DQN_CAST(uint32_t)(one_meter * 2.f); + waypoint->data.offset += Dqn_V2_InitNx2(DQN_CAST(Dqn_f32) Dqn_PCG32_Range(&game->play.rng, min_vary, max_vary), + DQN_CAST(Dqn_f32) Dqn_PCG32_Range(&game->play.rng, min_vary, max_vary)); + + if (Dqn_PCG32_NextF32(&game->play.rng) >= .5f) + waypoint->data.offset.x *= -1; + if (Dqn_PCG32_NextF32(&game->play.rng) >= .5f) + waypoint->data.offset.y *= -1; + } +} + + void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_PlatformInput *input, FP_GameEntity *entity, Dqn_V2 *acceleration_meters_per_s) { TELY_AssetSpriteSheet *sheet = &game->atlas_sprite_sheet; @@ -1119,11 +1150,13 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform entity->building_patron = {}; // NOTE: Add a waypoint for the plane to the mob spawn + FP_GameEntityHandle mob_spawner = {}; + Dqn_V2 mob_spawner_pos = {}; { - uint32_t mob_spawner_index = Dqn_PCG32_Range(&game->play.rng, 0, DQN_CAST(uint32_t)game->play.mob_spawners.size); - FP_GameEntityHandle mob_spawner = game->play.mob_spawners.data[mob_spawner_index]; - Dqn_V2 target_pos = FP_Game_CalcEntityWorldPos(game, mob_spawner); - plane->waypoints = FP_SentinelList_Init(game->play.chunk_pool); + uint32_t mob_spawner_index = Dqn_PCG32_Range(&game->play.rng, 0, DQN_CAST(uint32_t)game->play.mob_spawners.size); + mob_spawner = game->play.mob_spawners.data[mob_spawner_index]; + mob_spawner_pos = FP_Game_CalcEntityWorldPos(game, mob_spawner); + plane->waypoints = FP_SentinelList_Init(game->play.chunk_pool); FP_SentinelListLink *link = FP_SentinelList_MakeBefore(&plane->waypoints, FP_SentinelList_Front(&plane->waypoints), game->play.chunk_pool); @@ -1132,6 +1165,11 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform waypoint->type = FP_GameWaypointType_ClosestSide; } + // NOTE: Update the mob's waypoints to the mob spawner waypoints + FP_GameEntity *patron = FP_Game_GetEntity(game, plane->building_patron); + FP_SentinelList_Clear(&patron->waypoints, game->play.chunk_pool); + + FP_AppendMobSpawnerWaypoints(game, entity->handle, plane->building_patron); FP_Game_EntityTransitionState(game, entity, FP_EntityAirportTerryState_Idle); } } break; @@ -1876,14 +1914,13 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input // NOTE: Remove them from the queue Dqn_FArray_EraseRange(&waypoint_entity->building_queue, 0 /*index*/, 1 /*count*/, Dqn_ArrayErase_Stable); - Dqn_Rect hit_box = FP_Game_CalcEntityWorldHitBox(game, building->handle); - Dqn_V2 exit_pos = Dqn_Rect_InterpolatedPoint(hit_box, Dqn_V2_InitNx2(0.5f, 1.1f)); + Dqn_Rect building_hit_box = FP_Game_CalcEntityWorldHitBox(game, building->handle); + Dqn_V2 exit_pos = Dqn_Rect_InterpolatedPoint(building_hit_box, Dqn_V2_InitNx2(0.5f, 1.1f)); if (building->type == FP_EntityType_ClubTerry) { FP_Game_EntityTransitionState(game, building, FP_EntityClubTerryState_PartyTime); entity->local_pos = exit_pos; // TODO(doyle): Only works when parent world pos is 0,0 } else if (building->type == FP_EntityType_AirportTerry) { FP_Game_EntityTransitionState(game, building, FP_EntityAirportTerryState_FlyPassenger); - entity->local_pos = exit_pos; // TODO(doyle): Only works when parent world pos is 0,0 } else { DQN_ASSERT(building->type == FP_EntityType_ChurchTerry); FP_Game_EntityTransitionState(game, building, FP_EntityChurchTerryState_ConvertPatron); @@ -2130,13 +2167,11 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input entity->next_spawn_timestamp_s = DQN_CAST(uint64_t)(input->timer_s + 2.5f); FP_SentinelListLink *link = FP_SentinelList_Make(&entity->spawn_list, game->play.chunk_pool); + Dqn_V2 entity_world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle); + Dqn_Rect entity_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle); + Dqn_f32 step_y = (entity_hit_box.size.h / spawn_count) * 1.5f; + Dqn_f32 mob_y_offset = (Dqn_PCG32_NextF32(&game->play.rng) * step_y) + (step_y * spawn_index); - Dqn_f32 one_meter = FP_Game_MetersToPixelsNx1(game->play, 1.f); - Dqn_V2 entity_world_pos = FP_Game_CalcEntityWorldPos(game, entity->handle); - Dqn_Rect entity_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle); - - Dqn_f32 step_y = (entity_hit_box.size.h / spawn_count) * 1.5f; - Dqn_f32 mob_y_offset = (Dqn_PCG32_NextF32(&game->play.rng) * step_y) + (step_y * spawn_index); if (Dqn_PCG32_NextF32(&game->play.rng) >= .5f) mob_y_offset *= -1; @@ -2157,31 +2192,12 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input mob->hp_cap *= hp_adjustment; mob->hp = mob->hp_cap; - for (FP_GameEntity *waypoint_entity = entity->first_child; waypoint_entity; waypoint_entity = waypoint_entity->next) { - if ((waypoint_entity->flags & FP_GameEntityFlag_MobSpawnerWaypoint) == 0) - continue; - - // NOTE: Add the waypoint - FP_SentinelListLink *waypoint = FP_SentinelList_Make(&mob->waypoints, game->play.chunk_pool); - waypoint->data.entity = waypoint_entity->handle; - waypoint->data.arrive = FP_GameWaypointArrive_WhenWithinEntitySize; - waypoint->data.value = 1.5f; - - uint32_t min_vary = DQN_CAST(uint32_t)(one_meter * .5f); - uint32_t max_vary = DQN_CAST(uint32_t)(one_meter * 2.f); - waypoint->data.offset += Dqn_V2_InitNx2(DQN_CAST(Dqn_f32)Dqn_PCG32_Range(&game->play.rng, min_vary, max_vary), - DQN_CAST(Dqn_f32)Dqn_PCG32_Range(&game->play.rng, min_vary, max_vary)); - - if (Dqn_PCG32_NextF32(&game->play.rng) >= .5f) - waypoint->data.offset *= -1; - } - + FP_AppendMobSpawnerWaypoints(game, entity->handle, mob->handle); game->play.enemies_spawned_this_wave++; if (game->play.enemies_spawned_this_wave >= game->play.enemies_per_wave) game->play.wave_cooldown_timestamp_ms = game->play.clock_ms + 30'000; } } - } } diff --git a/feely_pona_stdlib.h b/feely_pona_stdlib.h index f677176..c270549 100644 --- a/feely_pona_stdlib.h +++ b/feely_pona_stdlib.h @@ -115,14 +115,21 @@ FP_SentinelListLink *FP_SentinelList_Erase(FP_SentinelList *list, FP_Senti } template -void FP_SentinelList_Deinit(FP_SentinelList *list, TELY_ChunkPool *pool) +void FP_SentinelList_Clear(FP_SentinelList *list, TELY_ChunkPool *pool) { if (!list || !pool) return; for (FP_SentinelListLink *link = nullptr; FP_SentinelList_Iterate(list, &link); ) link = FP_SentinelList_Erase(list, link, pool); +} +template +void FP_SentinelList_Deinit(FP_SentinelList *list, TELY_ChunkPool *pool) +{ + if (!list || !pool) + return; + FP_SentinelList_Clear(list, pool); TELY_ChunkPool_Dealloc(pool, list->sentinel); *list = {}; }