diff --git a/External/tely b/External/tely index 96ddc4d..e86fb0c 160000 --- a/External/tely +++ b/External/tely @@ -1 +1 @@ -Subproject commit 96ddc4d93441f1fdccf04d9f7faed96de7971c52 +Subproject commit e86fb0cad3342a12713c400da017648741c29234 diff --git a/feely_pona.cpp b/feely_pona.cpp index bb7136e..a1b0b5d 100644 --- a/feely_pona.cpp +++ b/feely_pona.cpp @@ -667,8 +667,37 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input } } - // NOTE: Determine acceleration to move towards next waypoint if we have one + // NOTE: Determine AI movement ============================================================= if (acceleration.x == 0 && acceleration.y == 0) { + Dqn_V2 entity_pos = FP_Game_CalcEntityWorldPos(game, entity->handle); + + if (entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) { + Dqn_f32 closest_terry_dist = DQN_F32_MAX; + Dqn_V2 closest_terry_pos = Dqn_V2_InitNx1(DQN_F32_MAX); + FP_GameEntity *closest_terry = nullptr; + for (FP_GameEntityIterator terry_it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &terry_it, game->root_entity); ) { + FP_GameEntity *terry = terry_it.entity; + if (terry->type != FP_EntityType_Terry) + continue; + + Dqn_V2 terry_pos = FP_Game_CalcEntityWorldPos(game, terry->handle); + Dqn_f32 dist_to_terry = Dqn_V2_LengthSq_V2x2(terry_pos, entity_pos); + if (dist_to_terry < closest_terry_dist) { + closest_terry_pos = terry_pos; + closest_terry_dist = dist_to_terry; + closest_terry = terry; + } + } + + if (closest_terry_dist < DQN_SQUARED(200.f)) { + FP_SentinelListLink *first_waypoint = FP_SentinelList_Front(&entity->waypoints); + if (first_waypoint->data != closest_terry->handle) { + FP_SentinelListLink *link = FP_SentinelList_MakeBefore(&entity->waypoints, first_waypoint, game->chunk_pool); + link->data = closest_terry->handle; + } + } + } + while (entity->waypoints.size) { FP_SentinelListLink *waypoint_link = entity->waypoints.sentinel->next; FP_GameEntity *waypoint = FP_Game_GetEntity(game, waypoint_link->data); @@ -679,7 +708,6 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input // NOTE: We found a waypoint that is valid to move towards Dqn_V2 waypoint_pos = FP_Game_CalcEntityWorldPos(game, waypoint->handle); - Dqn_V2 entity_pos = FP_Game_CalcEntityWorldPos(game, entity->handle); Dqn_V2 entity_to_waypoint = waypoint_pos - entity_pos; // NOTE: Check if we've arrived at the waypoint @@ -842,8 +870,9 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input link->data = FP_Entity_CreateSmoochie(game, entity_world_pos, "Smoochie"); // NOTE: Setup the mob with waypoints - FP_GameEntity *mob = FP_Game_GetEntity(game, link->data); - mob->waypoints = FP_SentinelList_Init(game->chunk_pool); + FP_GameEntity *mob = FP_Game_GetEntity(game, link->data); + mob->waypoints = FP_SentinelList_Init(game->chunk_pool); + mob->flags |= FP_GameEntityFlag_AggrosWhenNearTerry; for (FP_GameEntity *waypoint_entity = entity->first_child; waypoint_entity; waypoint_entity = waypoint_entity->next) { if ((waypoint_entity->flags & FP_GameEntityFlag_MobSpawnerWaypoint) == 0) diff --git a/feely_pona_game.h b/feely_pona_game.h index 6c60f80..25f17ba 100644 --- a/feely_pona_game.h +++ b/feely_pona_game.h @@ -14,6 +14,7 @@ enum FP_GameEntityFlag FP_GameEntityFlag_NonTraversable = 1 << 6, FP_GameEntityFlag_MobSpawner = 1 << 7, FP_GameEntityFlag_MobSpawnerWaypoint = 1 << 8, + FP_GameEntityFlag_AggrosWhenNearTerry = 1 << 9, }; enum FP_GameShapeType diff --git a/feely_pona_stdlib.h b/feely_pona_stdlib.h index 8e9e1cb..26bfa94 100644 --- a/feely_pona_stdlib.h +++ b/feely_pona_stdlib.h @@ -18,6 +18,15 @@ struct FP_SentinelList FP_SentinelListLink *sentinel; }; +template +FP_SentinelListLink *FP_SentinelList_Front(FP_SentinelList *list) +{ + FP_SentinelListLink *result = nullptr; + if (list && list->sentinel && list->sentinel->next) + result = list->sentinel->next; + return result; +} + template bool FP_SentinelList_Iterate(FP_SentinelList *list, FP_SentinelListLink **it) { @@ -47,6 +56,13 @@ FP_SentinelList FP_SentinelList_Init(TELY_ChunkPool *pool) template FP_SentinelListLink *FP_SentinelList_Make(FP_SentinelList *list, TELY_ChunkPool *pool) +{ + FP_SentinelListLink *result = FP_SentinelList_MakeBefore(list, list->sentinel, pool); + return result; +} + +template +FP_SentinelListLink *FP_SentinelList_MakeBefore(FP_SentinelList *list, FP_SentinelListLink *link, TELY_ChunkPool *pool) { DQN_ASSERT(list->sentinel->next); DQN_ASSERT(list->sentinel->prev); @@ -54,8 +70,25 @@ FP_SentinelListLink *FP_SentinelList_Make(FP_SentinelList *list, TELY_Chun DQN_ASSERT(list->sentinel->next->prev == list->sentinel); FP_SentinelListLink *result = TELY_ChunkPool_New(pool, FP_SentinelListLink); - result->next = list->sentinel; - result->prev = list->sentinel->prev; + result->next = link; + result->prev = link->prev; + result->next->prev = result; + result->prev->next = result; + list->size++; + return result; +} + +template +FP_SentinelListLink *FP_SentinelList_MakeAfter(FP_SentinelList *list, FP_SentinelListLink *link, TELY_ChunkPool *pool) +{ + DQN_ASSERT(list->sentinel->next); + DQN_ASSERT(list->sentinel->prev); + DQN_ASSERT(list->sentinel->prev->next == list->sentinel); + DQN_ASSERT(list->sentinel->next->prev == list->sentinel); + + FP_SentinelListLink *result = TELY_ChunkPool_New(pool, FP_SentinelListLink); + result->next = link->next; + result->prev = link; result->next->prev = result; result->prev->next = result; list->size++;