#if defined(_CLANGD) #pragma once #include "feely_pona_unity.h" #endif static bool FP_Entity_IsBuildingForMobs(FP_GameEntity *entity) { bool result = entity->type == FP_EntityType_AirportTerry || entity->type == FP_EntityType_ClubTerry || entity->type == FP_EntityType_ChurchTerry || entity->type == FP_EntityType_KennelTerry; return result; } static Dqn_f32 FP_Entity_CalcSpriteScaleForDesiredHeight(FP_Game *game, FP_Meters height, Dqn_Rect sprite_rect) { Dqn_f32 sprite_in_meters = FP_Game_PixelsToMetersNx1(game->play, sprite_rect.size.y); Dqn_f32 result = height.meters / sprite_in_meters; return result; } static FP_EntityRenderData FP_Entity_GetRenderData(FP_Game *game, FP_EntityType type, uint32_t raw_state, FP_GameDirection direction) { FP_EntityRenderData result = {}; result.sheet = &game->atlas_sprite_sheet; switch (type) { case FP_EntityType_Nil: { } break; case FP_EntityType_Map: { result.height.meters = 41.9f; result.anim_name = g_anim_names.map; } break; case FP_EntityType_Terry: { result.height.meters = 1.8f; FP_EntityTerryState state = DQN_CAST(FP_EntityTerryState)raw_state; switch (state) { case FP_EntityTerryState_Idle: result.anim_name = g_anim_names.terry_walk_idle; break; case FP_EntityTerryState_Attack: { switch (direction) { case FP_GameDirection_Up: { result.anim_name = g_anim_names.terry_attack_up; result.height.meters *= 1.5f; TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name); Dqn_Rect tex_rect = result.sheet->rects.data[sprite_anim->index]; result.offset = Dqn_V2_InitNx2(0, -tex_rect.size.h * .2f); } break; case FP_GameDirection_Down: { result.anim_name = g_anim_names.terry_attack_down; result.height.meters *= 1.6f; TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name); Dqn_Rect tex_rect = result.sheet->rects.data[sprite_anim->index]; result.offset = Dqn_V2_InitNx2(0, -tex_rect.size.h * .2f); } break; case FP_GameDirection_Left: { result.anim_name = g_anim_names.terry_attack_side; result.height.meters *= 1.5f; TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name); Dqn_Rect tex_rect = result.sheet->rects.data[sprite_anim->index]; result.offset = Dqn_V2_InitNx2(0, -tex_rect.size.h * .2f); } break; case FP_GameDirection_Right: { result.anim_name = g_anim_names.terry_attack_side; result.height.meters *= 1.5f; result.flip = TELY_AssetFlip_X; TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name); Dqn_Rect tex_rect = result.sheet->rects.data[sprite_anim->index]; result.offset = Dqn_V2_InitNx2(0, -tex_rect.size.h * .2f); } break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; case FP_EntityTerryState_RangeAttack: { switch (direction) { case FP_GameDirection_Up: result.anim_name = g_anim_names.terry_attack_phone_up; result.height.meters *= 1.25f; break; case FP_GameDirection_Down: result.anim_name = g_anim_names.terry_attack_phone_down; result.height.meters *= 1.25f; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.terry_attack_phone_side; result.height.meters *= 1.25f; result.flip = TELY_AssetFlip_X; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.terry_attack_phone_side; result.height.meters *= 1.25f; break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; case FP_EntityTerryState_Dash: { switch (direction) { case FP_GameDirection_Up: result.anim_name = g_anim_names.terry_ghost; break; case FP_GameDirection_Down: result.anim_name = g_anim_names.terry_ghost; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.terry_ghost; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.terry_ghost; result.flip = TELY_AssetFlip_X; break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; case FP_EntityTerryState_Run: { switch (direction) { case FP_GameDirection_Up: { result.anim_name = g_anim_names.terry_walk_up; TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name); Dqn_Rect tex_rect = result.sheet->rects.data[sprite_anim->index]; result.offset = Dqn_V2_InitNx2(tex_rect.size.w * .3f, 0.f); } break; case FP_GameDirection_Down: result.anim_name = g_anim_names.terry_walk_down; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.terry_walk_left; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.terry_walk_right; break; 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; case FP_EntityType_Perry: { result.height.meters = 1.72f; FP_EntityPerryState state = DQN_CAST(FP_EntityPerryState)raw_state; switch (state) { case FP_EntityTerryState_Idle: { result.anim_name = g_anim_names.perry_walk_idle; } break; case FP_EntityTerryState_Attack: { switch (direction) { case FP_GameDirection_Up: { result.anim_name = g_anim_names.perry_attack_up; result.height.meters *= 1.5f; TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name); Dqn_Rect tex_rect = result.sheet->rects.data[sprite_anim->index]; result.offset = Dqn_V2_InitNx2(0, -tex_rect.size.h * .1f); } break; case FP_GameDirection_Down: { result.anim_name = g_anim_names.perry_attack_down; result.height.meters *= 1.6f; TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name); Dqn_Rect tex_rect = result.sheet->rects.data[sprite_anim->index]; result.offset = Dqn_V2_InitNx2(0, -tex_rect.size.h * .1f); } break; case FP_GameDirection_Left: { result.anim_name = g_anim_names.perry_attack_side; result.height.meters *= 1.5f; TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name); Dqn_Rect tex_rect = result.sheet->rects.data[sprite_anim->index]; result.offset = Dqn_V2_InitNx2(0, -tex_rect.size.h * .1f); } break; case FP_GameDirection_Right: { result.anim_name = g_anim_names.perry_attack_side; result.height.meters *= 1.5f; result.flip = TELY_AssetFlip_X; TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name); Dqn_Rect tex_rect = result.sheet->rects.data[sprite_anim->index]; result.offset = Dqn_V2_InitNx2(0, -tex_rect.size.h * .1f); } break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; case FP_EntityTerryState_RangeAttack: { switch (direction) { case FP_GameDirection_Up: result.anim_name = g_anim_names.perry_attack_phone_up; result.height.meters *= 1.35f; break; case FP_GameDirection_Down: result.anim_name = g_anim_names.perry_attack_phone_down; result.height.meters *= 1.35f; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.perry_attack_phone_side; result.height.meters *= 1.35f; result.flip = TELY_AssetFlip_X; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.perry_attack_phone_side; result.height.meters *= 1.35f; break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; case FP_EntityTerryState_Dash: { switch (direction) { case FP_GameDirection_Up: result.anim_name = g_anim_names.perry_ghost; break; case FP_GameDirection_Down: result.anim_name = g_anim_names.perry_ghost; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.perry_ghost; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.perry_ghost; result.flip = TELY_AssetFlip_X; break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; case FP_EntityTerryState_Run: { switch (direction) { case FP_GameDirection_Up: result.anim_name = g_anim_names.perry_walk_up; break; case FP_GameDirection_Down: result.anim_name = g_anim_names.perry_walk_down; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.perry_walk_right; result.flip = TELY_AssetFlip_X; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.perry_walk_right; break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; case FP_EntityTerryState_DeadGhost: { result.anim_name = g_anim_names.perry_death; break; } break; } } break; case FP_EntityType_Smoochie: { result.height.meters = 1.6f; FP_EntitySmoochieState state = DQN_CAST(FP_EntitySmoochieState)raw_state; switch (state) { case FP_EntitySmoochieState_Idle: result.anim_name = g_anim_names.smoochie_walk_down; break; case FP_EntitySmoochieState_Attack: result.anim_name = g_anim_names.smoochie_attack_down; break; case FP_EntitySmoochieState_HurtSide: result.anim_name = g_anim_names.smoochie_hurt_side; result.flip = direction == FP_GameDirection_Right ? TELY_AssetFlip_X : TELY_AssetFlip_No; break; case FP_EntitySmoochieState_Death: result.anim_name = g_anim_names.smoochie_death; break; case FP_EntitySmoochieState_Run: { switch (direction) { case FP_GameDirection_Up: result.anim_name = g_anim_names.smoochie_walk_up; break; case FP_GameDirection_Down: result.anim_name = g_anim_names.smoochie_walk_down; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.smoochie_walk_left; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.smoochie_walk_right; break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; } } break; case FP_EntityType_MerchantTerry: { result.height.meters = 3.66f; FP_EntityMerchantTerryState state = DQN_CAST(FP_EntityMerchantTerryState)raw_state; switch (state) { case FP_EntityMerchantTerryState_Idle: result.anim_name = g_anim_names.merchant_terry; break; } } break; case FP_EntityType_MerchantGraveyard: { result.height.meters = 3.66f; FP_EntityMerchantGraveyardState state = DQN_CAST(FP_EntityMerchantGraveyardState)raw_state; switch (state) { case FP_EntityMerchantGraveyardState_Idle: result.anim_name = g_anim_names.merchant_graveyard; break; } } break; case FP_EntityType_MerchantGym: { result.height.meters = 3.66f; result.anim_name = g_anim_names.merchant_gym; FP_EntityMerchantGymState state = DQN_CAST(FP_EntityMerchantGymState)raw_state; switch (state) { case FP_EntityMerchantGymState_Idle: result.anim_name = g_anim_names.merchant_gym; break; } } break; case FP_EntityType_MerchantPhoneCompany: { result.height.meters = 5.f; FP_EntityMerchantPhoneCompanyState state = DQN_CAST(FP_EntityMerchantPhoneCompanyState)raw_state; switch (state) { case FP_EntityMerchantPhoneCompanyState_Idle: result.anim_name = g_anim_names.merchant_phone_company; break; } } break; case FP_EntityType_ClubTerry: { result.height.meters = 4.f; FP_EntityClubTerryState state = DQN_CAST(FP_EntityClubTerryState)raw_state; switch (state) { case FP_EntityClubTerryState_Idle: result.anim_name = g_anim_names.club_terry_dark; break; case FP_EntityClubTerryState_PartyTime: result.anim_name = g_anim_names.club_terry_alive; break; } } break; case FP_EntityType_Clinger: { result.height.meters = 1.6f; FP_EntityClingerState state = DQN_CAST(FP_EntityClingerState)raw_state; switch (state) { case FP_EntityClingerState_Idle: result.anim_name = g_anim_names.clinger_walk_down; break; case FP_EntityClingerState_Attack: { switch (direction) { case FP_GameDirection_Up: result.anim_name = g_anim_names.clinger_attack_up; break; case FP_GameDirection_Down: result.anim_name = g_anim_names.clinger_attack_down; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.clinger_attack_side; result.flip = TELY_AssetFlip_X; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.clinger_attack_side; break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; case FP_EntityClingerState_Death: result.anim_name = g_anim_names.clinger_death; break; case FP_EntityClingerState_Run: { switch (direction) { case FP_GameDirection_Up: result.anim_name = g_anim_names.clinger_walk_up; break; case FP_GameDirection_Down: result.anim_name = g_anim_names.clinger_walk_down; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.clinger_walk_down; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.clinger_walk_down; break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; } } break; case FP_EntityType_Heart: { result.height.meters = 4.f; FP_EntityHeartState state = DQN_CAST(FP_EntityHeartState)raw_state; switch (state) { case FP_EntityHeartState_Idle: result.anim_name = g_anim_names.heart; break; } } break; case FP_EntityType_AirportTerry: { result.height.meters = 4.f; FP_EntityAirportTerryState state = DQN_CAST(FP_EntityAirportTerryState)raw_state; switch (state) { case FP_EntityAirportTerryState_Idle: result.anim_name = g_anim_names.airport_terry; break; case FP_EntityAirportTerryState_FlyPassenger: result.anim_name = g_anim_names.airport_terry; break; } } break; case FP_EntityType_Catfish: { result.height.meters = 1.6f; FP_EntityCatfishState state = DQN_CAST(FP_EntityCatfishState)raw_state; switch (state) { case FP_EntityCatfishState_Idle: result.anim_name = g_anim_names.catfish_walk_down; break; case FP_EntityCatfishState_Attack: { switch (direction) { case FP_GameDirection_Up: result.anim_name = g_anim_names.catfish_attack_up; break; case FP_GameDirection_Down: result.anim_name = g_anim_names.catfish_attack_down; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.catfish_attack_side; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.catfish_attack_side; result.flip = TELY_AssetFlip_X; break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; case FP_EntityCatfishState_Death: result.anim_name = g_anim_names.catfish_death; break; case FP_EntityCatfishState_Run: { switch (direction) { case FP_GameDirection_Up: result.anim_name = g_anim_names.catfish_walk_up; break; case FP_GameDirection_Down: result.anim_name = g_anim_names.catfish_walk_down; break; case FP_GameDirection_Left: result.anim_name = g_anim_names.catfish_walk_side; break; case FP_GameDirection_Right: result.anim_name = g_anim_names.catfish_walk_side; result.flip = TELY_AssetFlip_X; break; case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break; } } break; } } break; case FP_EntityType_ChurchTerry: { result.height.meters = 4.f; FP_EntityChurchTerryState state = DQN_CAST(FP_EntityChurchTerryState)raw_state; switch (state) { case FP_EntityChurchTerryState_Idle: result.anim_name = g_anim_names.church_terry_dark; break; case FP_EntityChurchTerryState_ConvertPatron: result.anim_name = g_anim_names.church_terry_alive; break; } } break; case FP_EntityType_KennelTerry: { result.height.meters = 3.f; FP_EntityKennelTerryState state = DQN_CAST(FP_EntityKennelTerryState)raw_state; switch (state) { case FP_EntityKennelTerryState_Idle: result.anim_name = g_anim_names.kennel_terry; break; } } break; case FP_EntityType_PhoneMessageProjectile: { result.height.meters = 1.f; result.anim_name = g_anim_names.terry_attack_phone_message; } break; case FP_EntityType_AirportTerryPlane: { result.height.meters = 1.5f; result.anim_name = g_anim_names.airport_terry_plane; } break; case FP_EntityType_MobSpawner: { result.height.meters = 3.f; FP_EntityMobSpawnerState state = DQN_CAST(FP_EntityMobSpawnerState)raw_state; switch (state) { case FP_EntityMobSpawnerState_Idle: result.anim_name = g_anim_names.portal; break; case FP_EntityMobSpawnerState_Shutdown: { result.anim_name = g_anim_names.portal_break; result.height.meters = 3.5f; } break; } } break; case FP_EntityType_PortalMonkey: { result.height.meters = 1.f; result.anim_name = g_anim_names.portal_monk; break; } break; case FP_EntityType_Billboard: { result.height.meters = 7.5f; FP_EntityBillboardState state = DQN_CAST(FP_EntityBillboardState)raw_state; switch (state) { case FP_EntityBillboardState_Attack: result.anim_name = g_anim_names.map_billboard_attack; break; case FP_EntityBillboardState_Dash: result.anim_name = g_anim_names.map_billboard_dash; break; case FP_EntityBillboardState_Monkey: result.anim_name = g_anim_names.map_billboard_monkey; break; case FP_EntityBillboardState_RangeAttack: result.anim_name = g_anim_names.map_billboard_range_attack; break; case FP_EntityBillboardState_Strafe: result.anim_name = g_anim_names.map_billboard_strafe; break; case FP_EntityBillboardState_Build: result.anim_name = g_anim_names.map_billboard_build; result.height.meters = 6.25f; break; } } break; case FP_EntityType_Count: DQN_INVALID_CODE_PATH; break; } TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(result.sheet, result.anim_name); if (sprite_anim) { result.sheet_rect = result.sheet->rects.data[sprite_anim->index]; Dqn_f32 size_scale = FP_Entity_CalcSpriteScaleForDesiredHeight(game, result.height, result.sheet_rect); result.render_size = result.sheet_rect.size * size_scale; result.sprite = TELY_Asset_MakeAnimatedSprite(result.sheet, result.anim_name, result.flip); } return result; }