Compare commits
2 Commits
8b155c9021
...
169170945b
Author | SHA1 | Date | |
---|---|---|---|
169170945b | |||
22c2c4096f |
BIN
Data/Audio/monkey.ogg
(Stored with Git LFS)
BIN
Data/Audio/monkey.ogg
(Stored with Git LFS)
Binary file not shown.
BIN
Data/Audio/portal_destroy.ogg
(Stored with Git LFS)
BIN
Data/Audio/portal_destroy.ogg
(Stored with Git LFS)
Binary file not shown.
2
External/tely
vendored
2
External/tely
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 883007994e1077746ffe86f78d380559174d188f
|
Subproject commit e5c7d83121adb093e23655d7ae01820374872340
|
144
feely_pona.cpp
144
feely_pona.cpp
@ -516,6 +516,8 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
game->audio[FP_GameAudio_MerchantGym] = platform->func_load_audio(assets, DQN_STRING8("Gym"), DQN_STRING8("Data/Audio/merchant_gym.ogg"));
|
game->audio[FP_GameAudio_MerchantGym] = platform->func_load_audio(assets, DQN_STRING8("Gym"), DQN_STRING8("Data/Audio/merchant_gym.ogg"));
|
||||||
game->audio[FP_GameAudio_MerchantPhone] = platform->func_load_audio(assets, DQN_STRING8("Phone"), DQN_STRING8("Data/Audio/merchant_tech.ogg"));
|
game->audio[FP_GameAudio_MerchantPhone] = platform->func_load_audio(assets, DQN_STRING8("Phone"), DQN_STRING8("Data/Audio/merchant_tech.ogg"));
|
||||||
game->audio[FP_GameAudio_Message] = platform->func_load_audio(assets, DQN_STRING8("Message"), DQN_STRING8("Data/Audio/message.ogg"));
|
game->audio[FP_GameAudio_Message] = platform->func_load_audio(assets, DQN_STRING8("Message"), DQN_STRING8("Data/Audio/message.ogg"));
|
||||||
|
game->audio[FP_GameAudio_Monkey] = platform->func_load_audio(assets, DQN_STRING8("Monkey"), DQN_STRING8("Data/Audio/monkey.ogg"));
|
||||||
|
game->audio[FP_GameAudio_PortalDestroy] = platform->func_load_audio(assets, DQN_STRING8("Portal Destroy"), DQN_STRING8("Data/Audio/portal_destroy.ogg"));
|
||||||
|
|
||||||
platform->user_data = game;
|
platform->user_data = game;
|
||||||
{
|
{
|
||||||
@ -634,6 +636,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) {
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) {
|
||||||
entity->carried_monkey = closest_monkey.entity;
|
entity->carried_monkey = closest_monkey.entity;
|
||||||
picked_up_monkey_this_frame = true;
|
picked_up_monkey_this_frame = true;
|
||||||
|
TELY_Audio_Play(audio, game->audio[FP_GameAudio_Monkey], 1.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -700,6 +703,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) {
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_J)) {
|
||||||
entity->carried_monkey = closest_monkey.entity;
|
entity->carried_monkey = closest_monkey.entity;
|
||||||
picked_up_monkey_this_frame = true;
|
picked_up_monkey_this_frame = true;
|
||||||
|
TELY_Audio_Play(audio, game->audio[FP_GameAudio_Monkey], 1.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1295,6 +1299,7 @@ void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Platform
|
|||||||
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
|
uint64_t duration_ms = FP_GAME_ENTITY_ACTION_INFINITE_TIMER;
|
||||||
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
FP_Game_EntityActionReset(game, entity->handle, duration_ms, render_data.sprite);
|
||||||
entity->action.sprite_play_once = true;
|
entity->action.sprite_play_once = true;
|
||||||
|
TELY_Audio_Play(audio, game->audio[FP_GameAudio_PortalDestroy], 1.f);
|
||||||
FP_Game_DeleteEntity(game, entity->carried_monkey);
|
FP_Game_DeleteEntity(game, entity->carried_monkey);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -1577,7 +1582,10 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity->flags & FP_GameEntityFlag_RespondsToBuildings) {
|
// NOTE: Make waypoint to building =====================================================
|
||||||
|
// We can queue up to ente a building if we respond to the building AND we aren't
|
||||||
|
// already queuing up in a building already.
|
||||||
|
if (entity->flags & FP_GameEntityFlag_RespondsToBuildings && FP_Game_IsNilEntityHandle(game, entity->queued_at_building)) {
|
||||||
FP_GameFindClosestEntityResult closest_building = {};
|
FP_GameFindClosestEntityResult closest_building = {};
|
||||||
closest_building.dist_squared = DQN_F32_MAX;
|
closest_building.dist_squared = DQN_F32_MAX;
|
||||||
closest_building.pos = Dqn_V2_InitNx1(DQN_F32_MAX);
|
closest_building.pos = Dqn_V2_InitNx1(DQN_F32_MAX);
|
||||||
@ -1589,13 +1597,18 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
it_entity->type != FP_EntityType_ChurchTerry)
|
it_entity->type != FP_EntityType_ChurchTerry)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// NOTE: Already converted, we cannot attend church again ======================
|
// NOTE: Already converted, we cannot attend church again
|
||||||
if (entity->converted_faction && it_entity->type == FP_EntityType_ChurchTerry)
|
if (entity->converted_faction && it_entity->type == FP_EntityType_ChurchTerry)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// NOTE: The queue to enter the building is completely full skip
|
||||||
if (it_entity->building_queue.size == Dqn_FArray_Max(&it_entity->building_queue))
|
if (it_entity->building_queue.size == Dqn_FArray_Max(&it_entity->building_queue))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// NOTE: Entity is already in the building queue, skip
|
||||||
|
if (Dqn_FArray_Find<FP_GameEntityHandle>(&it_entity->building_queue, entity->handle).data)
|
||||||
|
continue;
|
||||||
|
|
||||||
bool already_visited_building = false;
|
bool already_visited_building = false;
|
||||||
for (FP_SentinelListLink<FP_GameEntityHandle> *link_it = {};
|
for (FP_SentinelListLink<FP_GameEntityHandle> *link_it = {};
|
||||||
!already_visited_building && FP_SentinelList_Iterate(&entity->buildings_visited, &link_it);
|
!already_visited_building && FP_SentinelList_Iterate(&entity->buildings_visited, &link_it);
|
||||||
@ -1633,32 +1646,84 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
FP_SentinelListLink<FP_GameWaypoint> *link = FP_SentinelList_MakeBefore(&entity->waypoints, FP_SentinelList_Front(&entity->waypoints), game->play.chunk_pool);
|
FP_SentinelListLink<FP_GameWaypoint> *link = FP_SentinelList_MakeBefore(&entity->waypoints, FP_SentinelList_Front(&entity->waypoints), game->play.chunk_pool);
|
||||||
FP_GameWaypoint *waypoint = &link->data;
|
FP_GameWaypoint *waypoint = &link->data;
|
||||||
waypoint->entity = closest_building.entity;
|
waypoint->entity = closest_building.entity;
|
||||||
waypoint->type = FP_GameWaypointType_Side;
|
waypoint->type = FP_GameWaypointType_Queue;
|
||||||
|
|
||||||
|
// NOTE: Add the entity to the building queue
|
||||||
|
FP_GameEntity *building = FP_Game_GetEntity(game, closest_building.entity);
|
||||||
|
Dqn_FArray_Add(&building->building_queue, entity->handle);
|
||||||
|
|
||||||
uint32_t *direction_hit_count = nullptr;
|
// NOTE: Remember the building we are queued at
|
||||||
FP_GameDirection least_encountered_direction = FP_GameDirection_Down;
|
entity->queued_at_building = building->handle;
|
||||||
|
|
||||||
DQN_FOR_UINDEX(dir_index, FP_GameDirection_Count) {
|
|
||||||
FP_GameEntity *waypoint_entity = FP_Game_GetEntity(game, waypoint->entity);
|
|
||||||
uint32_t *hit_count = waypoint_entity->count_of_entities_targetting_sides + dir_index;
|
|
||||||
if (!direction_hit_count || *hit_count < *direction_hit_count) {
|
|
||||||
direction_hit_count = hit_count;
|
|
||||||
least_encountered_direction = DQN_CAST(FP_GameDirection)dir_index;
|
|
||||||
} else if (hit_count == direction_hit_count) {
|
|
||||||
if (Dqn_PCG32_NextF32(&game->play.rng) >= 0.5f) {
|
|
||||||
direction_hit_count = hit_count;
|
|
||||||
least_encountered_direction = DQN_CAST(FP_GameDirection)dir_index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
waypoint->type_direction = least_encountered_direction;
|
// NOTE: Building queue ================================================================
|
||||||
(*direction_hit_count)++;
|
for (Dqn_usize index = 0; index < entity->building_queue.size; index++) {
|
||||||
|
FP_GameEntityHandle queue_entity_handle = entity->building_queue.data[index];
|
||||||
|
// NOTE: Delete dead entities
|
||||||
|
if (FP_Game_IsNilEntityHandle(game, queue_entity_handle)) {
|
||||||
|
index = Dqn_FArray_EraseRange(&entity->building_queue, index, 1 /*count*/, Dqn_ArrayErase_Stable).it_index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Delete far away entities
|
||||||
|
FP_GameEntity *queue_entity = FP_Game_GetEntity(game, queue_entity_handle);
|
||||||
|
Dqn_V2 queue_entity_p = FP_Game_CalcEntityWorldPos(game, queue_entity_handle);
|
||||||
|
Dqn_V2 building_p = FP_Game_CalcEntityWorldPos(game, entity->handle);
|
||||||
|
Dqn_f32 dist_sq = Dqn_V2_LengthSq_V2x2(queue_entity_p, building_p);
|
||||||
|
Dqn_f32 threshold_sq = DQN_SQUARED(FP_Game_MetersToPixelsNx1(game->play, 10.f));
|
||||||
|
if (dist_sq >= threshold_sq || queue_entity->converted_faction) {
|
||||||
|
// NOTE: Remove the entity from the building
|
||||||
|
queue_entity->queued_at_building = {};
|
||||||
|
|
||||||
|
// NOTE: Remove it from the queue
|
||||||
|
index = Dqn_FArray_EraseRange(&entity->building_queue, index, 1 /*count*/, Dqn_ArrayErase_Stable).it_index;
|
||||||
|
|
||||||
|
// NOTE: Make sure the entity doesnt' try and revisit
|
||||||
|
FP_SentinelList_Add(&queue_entity->buildings_visited, game->play.chunk_pool, entity->handle);
|
||||||
|
|
||||||
|
// NOTE: Remove the waypoint from the entity
|
||||||
|
if (queue_entity->waypoints.size) {
|
||||||
|
for (FP_SentinelListLink<FP_GameWaypoint> *link = nullptr;
|
||||||
|
FP_SentinelList_Iterate<FP_GameWaypoint>(&queue_entity->waypoints, &link); ) {
|
||||||
|
if (link->data.entity == entity->handle) {
|
||||||
|
FP_SentinelList_Erase(&queue_entity->waypoints, link, game->play.chunk_pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// NOTE: Bubble sort entities in the building queue by distance to the building ========
|
||||||
|
// For example the closest entity will be assigned the first queue slot to the building
|
||||||
|
if (entity->building_queue.size && game->play.clock_ms >= entity->building_queue_next_sort_timestamp_ms) {
|
||||||
|
|
||||||
|
// NOTE: We only sort the queue for the building every second. This prevents the queue
|
||||||
|
// from stagnating incase some entity has locked a position in the queue but had
|
||||||
|
// some dodgy physics that sent it far away
|
||||||
|
entity->building_queue_next_sort_timestamp_ms = game->play.clock_ms + 1000;
|
||||||
|
for (bool swapped = true; swapped; ) {
|
||||||
|
swapped = false;
|
||||||
|
for (Dqn_usize index = 0; index < (entity->building_queue.size - 1); index++) {
|
||||||
|
FP_GameEntityHandle left_handle = entity->building_queue.data[index + 0];
|
||||||
|
FP_GameEntityHandle right_handle = entity->building_queue.data[index + 1];
|
||||||
|
Dqn_V2 left_world_p = FP_Game_CalcEntityWorldPos(game, left_handle);
|
||||||
|
Dqn_V2 right_world_p = FP_Game_CalcEntityWorldPos(game, right_handle);
|
||||||
|
Dqn_f32 left_dist_sq = Dqn_V2_LengthSq_V2x2(entity_pos, left_world_p);
|
||||||
|
Dqn_f32 right_dist_sq = Dqn_V2_LengthSq_V2x2(entity_pos, right_world_p);
|
||||||
|
|
||||||
|
if (left_dist_sq > (right_dist_sq * 1.1f)) {
|
||||||
|
DQN_SWAP(entity->building_queue.data[index + 0], entity->building_queue.data[index + 1]);
|
||||||
|
swapped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NOTE: Handle waypoints ==============================================================
|
||||||
while (entity->waypoints.size) {
|
while (entity->waypoints.size) {
|
||||||
FP_SentinelListLink<FP_GameWaypoint> *waypoint_link = entity->waypoints.sentinel->next;
|
FP_SentinelListLink<FP_GameWaypoint> *waypoint_link = entity->waypoints.sentinel->next;
|
||||||
FP_GameWaypoint const *waypoint = &waypoint_link->data;
|
FP_GameWaypoint const *waypoint = &waypoint_link->data;
|
||||||
@ -1760,7 +1825,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (entity->type == FP_EntityType_Clinger) {
|
} else if (entity->type == FP_EntityType_Clinger) {
|
||||||
if (game->play.clock_ms >= entity->clinger_next_dash_timestamp) {
|
if (game->play.clock_ms >= entity->clinger_next_dash_timestamp && dist_to_waypoint_sq > (DQN_SQUARED(arrival_threshold * 4.f))) {
|
||||||
entity->clinger_next_dash_timestamp = game->play.clock_ms + 2000;
|
entity->clinger_next_dash_timestamp = game->play.clock_ms + 2000;
|
||||||
acceleration_meters_per_s = entity_to_waypoint_norm * entity->base_acceleration_per_s.meters * 45.f;
|
acceleration_meters_per_s = entity_to_waypoint_norm * entity->base_acceleration_per_s.meters * 45.f;
|
||||||
}
|
}
|
||||||
@ -1779,12 +1844,33 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
waypoint_entity->type == FP_EntityType_ClubTerry ||
|
waypoint_entity->type == FP_EntityType_ClubTerry ||
|
||||||
waypoint_entity->type == FP_EntityType_AirportTerry ||
|
waypoint_entity->type == FP_EntityType_AirportTerry ||
|
||||||
waypoint_entity->type == FP_EntityType_ChurchTerry;
|
waypoint_entity->type == FP_EntityType_ChurchTerry;
|
||||||
if (((waypoint->flags & FP_GameWaypointFlag_NonInterruptible) == 0) && (aggro || building_response)) {
|
|
||||||
|
if (aggro || building_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
|
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 (building_response) {
|
if (building_response) {
|
||||||
FP_GameEntity *building = waypoint_entity;
|
FP_GameEntity *building = waypoint_entity;
|
||||||
|
can_attack = false;
|
||||||
|
|
||||||
|
DQN_ASSERTF(
|
||||||
|
waypoint->type == FP_GameWaypointType_Queue,
|
||||||
|
"There's nothing stopping us from supporting other "
|
||||||
|
"waypoint types to buildings, but, for this game "
|
||||||
|
"we only ever make mobs queue at the building");
|
||||||
|
|
||||||
|
DQN_ASSERTF(
|
||||||
|
building->building_queue.size,
|
||||||
|
"An entity should only be forming a waypoint to "
|
||||||
|
"the building if there was space in the queue and "
|
||||||
|
"they were added the the queue");
|
||||||
|
|
||||||
if (FP_Game_IsNilEntityHandle(game, building->building_patron)) {
|
if (FP_Game_IsNilEntityHandle(game, building->building_patron)) {
|
||||||
|
if (waypoint_entity->building_queue.data[0] == entity->handle) {
|
||||||
|
// NOTE: This entity is front-in-line in the queue to enter the building, we can enter!
|
||||||
building->building_patron = entity->handle;
|
building->building_patron = entity->handle;
|
||||||
|
entity->queued_at_building = {};
|
||||||
|
|
||||||
|
// NOTE: Remove them from the queue
|
||||||
|
Dqn_FArray_EraseRange(&waypoint_entity->building_queue, 0 /*index*/, 1 /*count*/, Dqn_ArrayErase_Stable);
|
||||||
|
|
||||||
Dqn_Rect hit_box = FP_Game_CalcEntityWorldHitBox(game, building->handle);
|
Dqn_Rect hit_box = FP_Game_CalcEntityWorldHitBox(game, building->handle);
|
||||||
Dqn_V2 exit_pos = Dqn_Rect_InterpolatedPoint(hit_box, Dqn_V2_InitNx2(0.5f, 1.1f));
|
Dqn_V2 exit_pos = Dqn_Rect_InterpolatedPoint(hit_box, Dqn_V2_InitNx2(0.5f, 1.1f));
|
||||||
@ -1800,11 +1886,13 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
}
|
}
|
||||||
|
|
||||||
entity->flags |= FP_GameEntityFlag_OccupiedInBuilding;
|
entity->flags |= FP_GameEntityFlag_OccupiedInBuilding;
|
||||||
can_attack = false;
|
|
||||||
FP_SentinelList_Erase(&entity->waypoints, waypoint_link, game->play.chunk_pool);
|
FP_SentinelList_Erase(&entity->waypoints, waypoint_link, game->play.chunk_pool);
|
||||||
|
|
||||||
|
// NOTE: Add the building to the entity's visit list to prevent them from re-entering
|
||||||
FP_SentinelList_Add(&entity->buildings_visited, game->play.chunk_pool, building->handle);
|
FP_SentinelList_Add(&entity->buildings_visited, game->play.chunk_pool, building->handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (can_attack) {
|
if (can_attack) {
|
||||||
switch (entity->type) {
|
switch (entity->type) {
|
||||||
@ -3303,6 +3391,8 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
|
|||||||
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, " F7 Increase mobile data"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
|
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, " F7 Increase mobile data"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
|
||||||
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, " F8 %s god mode", game->play.god_mode ? "Disable" : "Enable"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
|
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, " F8 %s god mode", game->play.god_mode ? "Disable" : "Enable"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
|
||||||
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, " F9 %s noclip", player->flags & FP_GameEntityFlag_NoClip ? "Disable" : "Enable"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
|
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, " F9 %s noclip", player->flags & FP_GameEntityFlag_NoClip ? "Disable" : "Enable"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
|
||||||
|
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, " F10 Building inventory +1"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
|
||||||
|
TELY_Render_TextF(renderer, draw_p, Dqn_V2_Zero, " F11 %s by enemies", player->faction == FP_GameEntityFaction_Nil ? "Attacked" : "Ignored"); draw_p.y += TELY_Render_FontHeight(renderer, assets);
|
||||||
TELY_Render_PopFont(renderer);
|
TELY_Render_PopFont(renderer);
|
||||||
TELY_Render_PopColourV4(renderer);
|
TELY_Render_PopColourV4(renderer);
|
||||||
|
|
||||||
@ -3346,6 +3436,18 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer,
|
|||||||
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F9))
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F9))
|
||||||
player->flags ^= FP_GameEntityFlag_NoClip;
|
player->flags ^= FP_GameEntityFlag_NoClip;
|
||||||
|
|
||||||
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F10)) {
|
||||||
|
player->inventory.clubs += 1;
|
||||||
|
player->inventory.airports += 1;
|
||||||
|
player->inventory.churchs += 1;
|
||||||
|
player->inventory.kennels += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F11)) {
|
||||||
|
player->faction = player->faction == FP_GameEntityFaction_Nil
|
||||||
|
? FP_GameEntityFaction_Friendly
|
||||||
|
: FP_GameEntityFaction_Nil;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,7 +701,7 @@ static Dqn_Slice<Dqn_V2I> FP_Game_AStarPathFind(FP_Game *game,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Dqn_V2 FP_Game_CalcWaypointWorldPos(FP_Game *game, FP_GameEntityHandle src_entity, FP_GameWaypoint const *waypoint)
|
static Dqn_V2 FP_Game_CalcWaypointWorldPos(FP_Game *game, FP_GameEntityHandle entity_handle, FP_GameWaypoint const *waypoint)
|
||||||
{
|
{
|
||||||
Dqn_V2 result = {};
|
Dqn_V2 result = {};
|
||||||
if (!game || !waypoint)
|
if (!game || !waypoint)
|
||||||
@ -720,40 +720,46 @@ static Dqn_V2 FP_Game_CalcWaypointWorldPos(FP_Game *game, FP_GameEntityHandle sr
|
|||||||
case FP_GameWaypointType_ClosestSide: /*FALLTHRU*/
|
case FP_GameWaypointType_ClosestSide: /*FALLTHRU*/
|
||||||
case FP_GameWaypointType_Side: {
|
case FP_GameWaypointType_Side: {
|
||||||
// NOTE: Sweep entity with half the radius of the source entity
|
// NOTE: Sweep entity with half the radius of the source entity
|
||||||
Dqn_Rect src_rect = FP_Game_CalcEntityWorldHitBox(game, src_entity);
|
Dqn_Rect entity_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity_handle);
|
||||||
Dqn_Rect entity_rect = FP_Game_CalcEntityWorldHitBox(game, waypoint_entity->handle);
|
Dqn_Rect waypoint_hit_box = FP_Game_CalcEntityWorldHitBox(game, waypoint_entity->handle);
|
||||||
entity_rect.pos -= (src_rect.size * .5f);
|
waypoint_hit_box.pos -= (entity_hit_box.size * .5f);
|
||||||
entity_rect.size += src_rect.size;
|
waypoint_hit_box.size += entity_hit_box.size;
|
||||||
|
|
||||||
Dqn_V2 side_pos_list[FP_GameDirection_Count] = {};
|
Dqn_V2 side_pos_list[FP_GameDirection_Count] = {};
|
||||||
side_pos_list[FP_GameDirection_Up] = Dqn_V2_InitNx2(entity_rect.pos.x + entity_rect.size.w * .5f, entity_rect.pos.y - entity_rect.size.h * .1f);
|
side_pos_list[FP_GameDirection_Up] = Dqn_V2_InitNx2(waypoint_hit_box.pos.x + waypoint_hit_box.size.w * .5f, waypoint_hit_box.pos.y - waypoint_hit_box.size.h * .1f);
|
||||||
side_pos_list[FP_GameDirection_Down] = Dqn_V2_InitNx2(entity_rect.pos.x + entity_rect.size.w * .5f, entity_rect.pos.y + entity_rect.size.h + entity_rect.size.h * .1f);
|
side_pos_list[FP_GameDirection_Down] = Dqn_V2_InitNx2(waypoint_hit_box.pos.x + waypoint_hit_box.size.w * .5f, waypoint_hit_box.pos.y + waypoint_hit_box.size.h + waypoint_hit_box.size.h * .1f);
|
||||||
side_pos_list[FP_GameDirection_Left] = Dqn_V2_InitNx2(entity_rect.pos.x - entity_rect.size.w * .1f, entity_rect.pos.y + entity_rect.size.h * .5f);
|
side_pos_list[FP_GameDirection_Left] = Dqn_V2_InitNx2(waypoint_hit_box.pos.x - waypoint_hit_box.size.w * .1f, waypoint_hit_box.pos.y + waypoint_hit_box.size.h * .5f);
|
||||||
side_pos_list[FP_GameDirection_Right] = Dqn_V2_InitNx2(entity_rect.pos.x + entity_rect.size.w + entity_rect.size.w * .1f, entity_rect.pos.y + entity_rect.size.h * .5f);
|
side_pos_list[FP_GameDirection_Right] = Dqn_V2_InitNx2(waypoint_hit_box.pos.x + waypoint_hit_box.size.w + waypoint_hit_box.size.w * .1f, waypoint_hit_box.pos.y + waypoint_hit_box.size.h * .5f);
|
||||||
|
|
||||||
if (waypoint->type == FP_GameWaypointType_Side) {
|
if (waypoint->type == FP_GameWaypointType_Side) {
|
||||||
result = side_pos_list[waypoint->type_direction];
|
result = side_pos_list[waypoint->type_direction];
|
||||||
} else {
|
} else {
|
||||||
Dqn_f32 best_dist = DQN_F32_MAX;
|
Dqn_f32 best_dist = DQN_F32_MAX;
|
||||||
for (Dqn_V2 target_pos : side_pos_list) {
|
for (Dqn_V2 target_pos : side_pos_list) {
|
||||||
Dqn_f32 dist_squared = Dqn_V2_LengthSq_V2x2(src_rect.pos, target_pos);
|
Dqn_f32 dist_squared = Dqn_V2_LengthSq_V2x2(entity_hit_box.pos, target_pos);
|
||||||
if (dist_squared < best_dist) {
|
if (dist_squared < best_dist) {
|
||||||
best_dist = dist_squared;
|
best_dist = dist_squared;
|
||||||
result = target_pos;
|
result = target_pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
#if 0
|
case FP_GameWaypointType_Queue: {
|
||||||
Dqn_V2 entity_pos = FP_Game_CalcEntityWorldPos(game, waypoint_entity->handle);
|
Dqn_ArrayFindResult<FP_GameEntityHandle> find_result = Dqn_FArray_Find<FP_GameEntityHandle>(&waypoint_entity->building_queue, entity_handle);
|
||||||
Dqn_V2 src_pos = FP_Game_CalcEntityWorldPos(game, src_entity);
|
Dqn_usize index_in_queue = find_result.index;
|
||||||
Dqn_f32 curr_dist_to_entity = Dqn_V2_LengthSq_V2x2(entity_pos, src_pos);
|
Dqn_Rect entity_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity_handle);
|
||||||
if (curr_dist_to_entity < best_dist) {
|
Dqn_Rect waypoint_hit_box = FP_Game_CalcEntityWorldHitBox(game, waypoint_entity->handle);
|
||||||
// NOTE: We are already closer to the entity than the closest calculated side,
|
|
||||||
// we assume we're at the entity already.
|
Dqn_V2 queue_starting_p = {};
|
||||||
result = FP_Game_CalcEntityWorldPos(game, src_entity);
|
if (waypoint_entity->type == FP_EntityType_ClubTerry || waypoint_entity->type == FP_EntityType_ChurchTerry) {
|
||||||
}
|
queue_starting_p = Dqn_Rect_InterpolatedPoint(waypoint_hit_box, Dqn_V2_InitNx2(0.5f, 1.1f));
|
||||||
#endif
|
} else {
|
||||||
|
queue_starting_p = Dqn_Rect_InterpolatedPoint(waypoint_hit_box, Dqn_V2_InitNx2(1.f, 1.1f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dqn_f32 queue_spacing = FP_Game_MetersToPixelsNx1(game->play, 1.f);
|
||||||
|
result = Dqn_V2_InitNx2(queue_starting_p.x - (queue_spacing * index_in_queue), queue_starting_p.y);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ enum FP_GameWaypointType
|
|||||||
FP_GameWaypointType_At, // Move to the specified entity
|
FP_GameWaypointType_At, // Move to the specified entity
|
||||||
FP_GameWaypointType_Side, // Move to the side of the entity specified by the direction
|
FP_GameWaypointType_Side, // Move to the side of the entity specified by the direction
|
||||||
FP_GameWaypointType_ClosestSide, // Move to the side of the entity closest to us
|
FP_GameWaypointType_ClosestSide, // Move to the side of the entity closest to us
|
||||||
|
FP_GameWaypointType_Queue, // Queue at the target entity
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FP_GameDirection
|
enum FP_GameDirection
|
||||||
@ -87,14 +88,8 @@ enum FP_GameDirection
|
|||||||
FP_GameDirection_Count,
|
FP_GameDirection_Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FP_GameWaypointFlag
|
|
||||||
{
|
|
||||||
FP_GameWaypointFlag_NonInterruptible = 1 << 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FP_GameWaypoint
|
struct FP_GameWaypoint
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
|
||||||
FP_GameWaypointType type;
|
FP_GameWaypointType type;
|
||||||
FP_GameDirection type_direction; // Used if type is `FP_GameWaypointType_Side`
|
FP_GameDirection type_direction; // Used if type is `FP_GameWaypointType_Side`
|
||||||
FP_GameEntityHandle entity; // The entity to move to
|
FP_GameEntityHandle entity; // The entity to move to
|
||||||
@ -237,7 +232,10 @@ struct FP_GameEntity
|
|||||||
|
|
||||||
uint32_t count_of_entities_targetting_sides[FP_GameDirection_Count];
|
uint32_t count_of_entities_targetting_sides[FP_GameDirection_Count];
|
||||||
FP_GameEntityHandle carried_monkey;
|
FP_GameEntityHandle carried_monkey;
|
||||||
Dqn_FArray<FP_GameEntityHandle, 8> building_queue;
|
|
||||||
|
Dqn_FArray<FP_GameEntityHandle, 3> building_queue;
|
||||||
|
uint64_t building_queue_next_sort_timestamp_ms;
|
||||||
|
FP_GameEntityHandle queued_at_building;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FP_GameEntityIterator
|
struct FP_GameEntityIterator
|
||||||
@ -276,6 +274,8 @@ enum FP_GameAudio
|
|||||||
FP_GameAudio_MerchantGym,
|
FP_GameAudio_MerchantGym,
|
||||||
FP_GameAudio_MerchantPhone,
|
FP_GameAudio_MerchantPhone,
|
||||||
FP_GameAudio_Message,
|
FP_GameAudio_Message,
|
||||||
|
FP_GameAudio_Monkey,
|
||||||
|
FP_GameAudio_PortalDestroy,
|
||||||
FP_GameAudio_Count,
|
FP_GameAudio_Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user