fp: Load heart & remove aggro when terry distances himself
This commit is contained in:
+73
-4
@@ -277,6 +277,7 @@ void TELY_DLL_Init(void *user_data)
|
||||
game->clinger_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("clinger_resized_25%"));
|
||||
game->club_terry_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("club_terry_resized_25%"));
|
||||
game->map_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("map_resized_25%"));
|
||||
game->heart_sprite_sheet = FP_LoadSpriteSheetFromSpec(platform, assets, &platform->arena, DQN_STRING8("heart_resized_25%"));
|
||||
}
|
||||
|
||||
game->entities = Dqn_VArray_Init<FP_GameEntity>(&platform->arena, 1024 * 8);
|
||||
@@ -388,6 +389,7 @@ void TELY_DLL_Init(void *user_data)
|
||||
FP_Game_PopParentEntity(game);
|
||||
}
|
||||
|
||||
FP_Entity_CreateHeart(game, base_mid_p, "Heart");
|
||||
|
||||
uint16_t font_size = 18;
|
||||
game->camera.scale = Dqn_V2_InitNx1(1);
|
||||
@@ -943,9 +945,27 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
||||
|
||||
} break;
|
||||
|
||||
case FP_EntityType_Heart: {
|
||||
FP_EntityHeartState *state = DQN_CAST(FP_EntityHeartState *) & action->state;
|
||||
TELY_AssetSpriteSheet *sheet = &game->heart_sprite_sheet;
|
||||
|
||||
switch (*state) {
|
||||
case FP_EntityHeartState_Nil: {
|
||||
action->next_state = FP_EntityHeartState_Idle;
|
||||
} break;
|
||||
|
||||
case FP_EntityHeartState_Idle: {
|
||||
if (entering_new_state) {
|
||||
TELY_AssetAnimatedSprite sprite = TELY_Asset_MakeAnimatedSprite(sheet, g_anim_names.heart, TELY_AssetFlip_No);
|
||||
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
|
||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, sprite);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case FP_EntityType_Nil: break;
|
||||
case FP_EntityType_Count: DQN_INVALID_CODE_PATH; break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1058,9 +1078,11 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
||||
Dqn_V2 entity_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
|
||||
|
||||
if (entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) {
|
||||
FP_GameFindClosestEntityResult closest_result = FP_Game_FindClosestEntityWithType(game, entity->handle, FP_EntityType_Terry);
|
||||
if (closest_result.dist_squared < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game, 4.f))) {
|
||||
|
||||
FP_GameFindClosestEntityResult closest_result = FP_Game_FindClosestEntityWithType(game, entity->handle, FP_EntityType_Terry);
|
||||
Dqn_f32 aggro_dist_threshold = FP_Game_MetersToPixelsNx1(game, 4.f);
|
||||
|
||||
if (closest_result.dist_squared < DQN_SQUARED(aggro_dist_threshold)) {
|
||||
bool has_waypoint_to_terry = false;
|
||||
for (FP_SentinelListLink<FP_GameWaypoint> *link = nullptr;
|
||||
!has_waypoint_to_terry && FP_SentinelList_Iterate<FP_GameWaypoint>(&entity->waypoints, &link); ) {
|
||||
@@ -1091,6 +1113,15 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
||||
terry->aggro_slot[aggro_direction] = entity->handle;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (closest_result.dist_squared > DQN_SQUARED(aggro_dist_threshold * 2.f)) {
|
||||
for (FP_SentinelListLink<FP_GameWaypoint> *link = nullptr; FP_SentinelList_Iterate<FP_GameWaypoint>(&entity->waypoints, &link); ) {
|
||||
FP_GameEntity *maybe_terry = FP_Game_GetEntity(game, link->data.entity);
|
||||
if (maybe_terry->type == FP_EntityType_Terry) {
|
||||
link = FP_SentinelList_Erase(&entity->waypoints, link, game->chunk_pool);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1127,6 +1158,39 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
||||
}
|
||||
}
|
||||
|
||||
if (entity->flags & FP_GameEntityFlag_PointOfInterestHeart) {
|
||||
FP_GameFindClosestEntityResult closest_heart = FP_Game_FindClosestEntityWithType(game, entity->handle, FP_EntityType_Heart);
|
||||
if (closest_heart.dist_squared < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game, 4.f))) {
|
||||
|
||||
bool has_waypoint_to = false;
|
||||
for (FP_SentinelListLink<FP_GameWaypoint> *link = nullptr;
|
||||
!has_waypoint_to && FP_SentinelList_Iterate<FP_GameWaypoint>(&entity->waypoints, &link); ) {
|
||||
has_waypoint_to = link->data.entity == closest_heart.entity;
|
||||
}
|
||||
|
||||
if (!has_waypoint_to) {
|
||||
Dqn_Rect club_hit_box = FP_Game_CalcEntityWorldHitBox(game, closest_heart.entity);
|
||||
Dqn_V2 club_top_left = Dqn_Rect_TopLeft(club_hit_box);
|
||||
Dqn_V2 club_top_right = Dqn_Rect_TopRight(club_hit_box);
|
||||
|
||||
FP_SentinelListLink<FP_GameWaypoint> *link = FP_SentinelList_MakeBefore(&entity->waypoints, FP_SentinelList_Front(&entity->waypoints), game->chunk_pool);
|
||||
FP_GameWaypoint *waypoint = &link->data;
|
||||
waypoint->entity = closest_heart.entity;
|
||||
waypoint->type = FP_GameWaypointType_Side;
|
||||
|
||||
if (entity_pos.x <= club_top_left.x) {
|
||||
waypoint->type_direction = FP_GameDirection_Left;
|
||||
} else if (entity_pos.x >= club_top_right.x) {
|
||||
waypoint->type_direction = FP_GameDirection_Right;
|
||||
} else if (entity_pos.y <= club_top_left.y) {
|
||||
waypoint->type_direction = FP_GameDirection_Up;
|
||||
} else {
|
||||
waypoint->type_direction = FP_GameDirection_Down;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (entity->waypoints.size) {
|
||||
FP_SentinelListLink<FP_GameWaypoint> *waypoint_link = entity->waypoints.sentinel->next;
|
||||
FP_GameWaypoint const *waypoint = &waypoint_link->data;
|
||||
@@ -1163,10 +1227,14 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
||||
|
||||
// NOTE: We have arrived at the waypoint
|
||||
bool aggro_on_terry = (entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) && waypoint_entity->type == FP_EntityType_Terry;
|
||||
|
||||
bool club_terry_response = (entity->flags & FP_GameEntityFlag_RespondsToClubTerry) &&
|
||||
((entity->flags & FP_GameEntityFlag_ExperiencedClubTerry) == 0) &&
|
||||
waypoint_entity->type == FP_EntityType_ClubTerry;
|
||||
if (((waypoint->flags & FP_GameWaypointFlag_NonInterruptible) == 0) && (aggro_on_terry || club_terry_response)) {
|
||||
|
||||
bool heart_response = (entity->flags & FP_GameEntityFlag_PointOfInterestHeart) && waypoint_entity->type == FP_EntityType_Heart;
|
||||
|
||||
if (((waypoint->flags & FP_GameWaypointFlag_NonInterruptible) == 0) && (aggro_on_terry || club_terry_response || heart_response)) {
|
||||
bool can_attack = !entity->is_dying; // TODO(doyle): State transition needs to check if it's valid to move to making this not necessary
|
||||
|
||||
if (club_terry_response) {
|
||||
@@ -1230,6 +1298,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
||||
case FP_EntityType_Count: DQN_INVALID_CODE_PATH; break;
|
||||
case FP_EntityType_ClubTerry: break;
|
||||
case FP_EntityType_Map: break;
|
||||
case FP_EntityType_Heart: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user