From 21a8f87f98edfa6c7680b72761e3b46cbdd883c1 Mon Sep 17 00:00:00 2001 From: doyle Date: Sun, 8 Oct 2023 18:02:10 +1100 Subject: [PATCH] fp: Add terry ghost mode --- feely_pona.cpp | 35 ++++++++++++++++++++++++++++++++++- feely_pona_entity.h | 1 + feely_pona_entity_create.cpp | 4 ++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/feely_pona.cpp b/feely_pona.cpp index be3ff9f..517f106 100644 --- a/feely_pona.cpp +++ b/feely_pona.cpp @@ -193,7 +193,7 @@ static void FP_Game_MoveEntity(FP_Game *game, FP_GameEntityHandle entity_handle, case FP_EntityType_Terry: { // NOTE: Don't collide with mobs when dashing (e.g. phase through) FP_EntityTerryState state = *DQN_CAST(FP_EntityTerryState *)&entity->action.state; - if (state == FP_EntityTerryState_Dash) { + if (state == FP_EntityTerryState_Dash || state == FP_EntityTerryState_DeadGhost) { if (collider->type == FP_EntityType_Smoochie || collider->type == FP_EntityType_Clinger || collider->type == FP_EntityType_Catfish) entity_collides_with_collider = false; } @@ -597,6 +597,11 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform } } + if (entity->hp <= 0 && *state != FP_EntityTerryState_DeadGhost) { + FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_DeadGhost); + break; + } + switch (*state) { case FP_EntityTerryState_Idle: { if (entering_new_state) { @@ -748,6 +753,26 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform entity->action.sprite_alpha = 1.f; } } break; + + case FP_EntityTerryState_DeadGhost: { + if (entering_new_state) { + uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER; + FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite); + entity->action.sprite_play_once = true; + entity->faction = FP_GameEntityFaction_Nil; + } + + Dqn_f32 hp_t = entity->hp / DQN_CAST(Dqn_f32)entity->hp_cap; + if (hp_t >= 0.9f) + entity->action.sprite_alpha = Dqn_PCG32_NextF32(&game->play.rng); + + if (entity->hp >= entity->hp_cap) { + entity->faction = FP_GameEntityFaction_Friendly; + entity->action.sprite_alpha = 1.f; + entity->action.sprite_play_once = false; + FP_Game_EntityTransitionState(game, entity, FP_EntityTerryState_Idle); + } + } break; } } break; @@ -1431,6 +1456,14 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input case FP_EntityType_Terry: { auto *state = DQN_CAST(FP_EntityTerryState *)&entity->action.state; move_entity = *state == FP_EntityTerryState_Run || *state == FP_EntityTerryState_Idle; + if (*state == FP_EntityTerryState_DeadGhost) { + FP_GameEntityAction const *action = &entity->action; + uint64_t const elapsed_ms = game->play.clock_ms - action->started_at_clock_ms; + uint16_t const raw_anim_frame = DQN_CAST(uint16_t)(elapsed_ms / action->sprite.anim->ms_per_frame); + if (raw_anim_frame >= action->sprite.anim->count) { + move_entity = true; + } + } } break; case FP_EntityType_Smoochie: { diff --git a/feely_pona_entity.h b/feely_pona_entity.h index 9b6d6ee..6f31a8b 100644 --- a/feely_pona_entity.h +++ b/feely_pona_entity.h @@ -34,6 +34,7 @@ enum FP_EntityTerryState FP_EntityTerryState_RangeAttack, FP_EntityTerryState_Run, FP_EntityTerryState_Dash, + FP_EntityTerryState_DeadGhost, }; enum FP_EntityMobSpawnerState diff --git a/feely_pona_entity_create.cpp b/feely_pona_entity_create.cpp index f3e1854..5b2328c 100644 --- a/feely_pona_entity_create.cpp +++ b/feely_pona_entity_create.cpp @@ -76,6 +76,10 @@ FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, u case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; + + case FP_EntityTerryState_DeadGhost: { + result.anim_name = g_anim_names.terry_death; break; + } break; } } break;