fp: Add terry ghost mode

This commit is contained in:
doyle 2023-10-08 18:02:10 +11:00
parent 065292c7ac
commit 21a8f87f98
3 changed files with 39 additions and 1 deletions

View File

@ -193,7 +193,7 @@ static void FP_Game_MoveEntity(FP_Game *game, FP_GameEntityHandle entity_handle,
case FP_EntityType_Terry: { case FP_EntityType_Terry: {
// NOTE: Don't collide with mobs when dashing (e.g. phase through) // NOTE: Don't collide with mobs when dashing (e.g. phase through)
FP_EntityTerryState state = *DQN_CAST(FP_EntityTerryState *)&entity->action.state; 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) if (collider->type == FP_EntityType_Smoochie || collider->type == FP_EntityType_Clinger || collider->type == FP_EntityType_Catfish)
entity_collides_with_collider = false; 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) { switch (*state) {
case FP_EntityTerryState_Idle: { case FP_EntityTerryState_Idle: {
if (entering_new_state) { 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; entity->action.sprite_alpha = 1.f;
} }
} break; } 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; } break;
@ -1431,6 +1456,14 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
case FP_EntityType_Terry: { case FP_EntityType_Terry: {
auto *state = DQN_CAST(FP_EntityTerryState *)&entity->action.state; auto *state = DQN_CAST(FP_EntityTerryState *)&entity->action.state;
move_entity = *state == FP_EntityTerryState_Run || *state == FP_EntityTerryState_Idle; 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; } break;
case FP_EntityType_Smoochie: { case FP_EntityType_Smoochie: {

View File

@ -34,6 +34,7 @@ enum FP_EntityTerryState
FP_EntityTerryState_RangeAttack, FP_EntityTerryState_RangeAttack,
FP_EntityTerryState_Run, FP_EntityTerryState_Run,
FP_EntityTerryState_Dash, FP_EntityTerryState_Dash,
FP_EntityTerryState_DeadGhost,
}; };
enum FP_EntityMobSpawnerState enum FP_EntityMobSpawnerState

View File

@ -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; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
} }
} break; } break;
case FP_EntityTerryState_DeadGhost: {
result.anim_name = g_anim_names.terry_death; break;
} break;
} }
} break; } break;