fp: Add mobbing behaviour to surround club terry
This commit is contained in:
parent
378ef2959b
commit
158fcb12fe
108
feely_pona.cpp
108
feely_pona.cpp
@ -4,38 +4,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Dqn_f32 const PHYSICS_STEP = 1 / 60.f;
|
Dqn_f32 const PHYSICS_STEP = 1 / 60.f;
|
||||||
struct FP_GlobalAnimations
|
|
||||||
{
|
|
||||||
Dqn_String8 terry_walk_idle = DQN_STRING8("terry_walk_idle");
|
|
||||||
Dqn_String8 terry_walk_up = DQN_STRING8("terry_walk_up");
|
|
||||||
Dqn_String8 terry_walk_down = DQN_STRING8("terry_walk_down");
|
|
||||||
Dqn_String8 terry_walk_left = DQN_STRING8("terry_walk_left");
|
|
||||||
Dqn_String8 terry_walk_right = DQN_STRING8("terry_walk_right");
|
|
||||||
Dqn_String8 terry_attack_up = DQN_STRING8("terry_attack_up");
|
|
||||||
Dqn_String8 terry_attack_side = DQN_STRING8("terry_attack_side");
|
|
||||||
Dqn_String8 terry_attack_down = DQN_STRING8("terry_attack_down");
|
|
||||||
Dqn_String8 terry_merchant = DQN_STRING8("terry_merchant");
|
|
||||||
|
|
||||||
Dqn_String8 smoochie_walk_up = DQN_STRING8("smoochie_walk_up");
|
|
||||||
Dqn_String8 smoochie_walk_down = DQN_STRING8("smoochie_walk_down");
|
|
||||||
Dqn_String8 smoochie_walk_left = DQN_STRING8("smoochie_walk_left");
|
|
||||||
Dqn_String8 smoochie_walk_right = DQN_STRING8("smoochie_walk_right");
|
|
||||||
Dqn_String8 smoochie_attack_down = DQN_STRING8("smoochie_attack_down");
|
|
||||||
Dqn_String8 smoochie_hurt_side = DQN_STRING8("smoochie_hurt_side");
|
|
||||||
Dqn_String8 smoochie_attack_heart = DQN_STRING8("smoochie_attack_heart");
|
|
||||||
Dqn_String8 smoochie_death = DQN_STRING8("smoochie_death");
|
|
||||||
|
|
||||||
Dqn_String8 clinger_attack_down = DQN_STRING8("clinger_attack_down");
|
|
||||||
Dqn_String8 clinger_attack_side = DQN_STRING8("clinger_attack_side");
|
|
||||||
Dqn_String8 clinger_attack_up = DQN_STRING8("clinger_attack_up");
|
|
||||||
Dqn_String8 clinger_death = DQN_STRING8("clinger_death");
|
|
||||||
Dqn_String8 clinger_walk_up = DQN_STRING8("clinger_walk_up");
|
|
||||||
Dqn_String8 clinger_walk_down = DQN_STRING8("clinger_walk_down");
|
|
||||||
|
|
||||||
Dqn_String8 club_terry_alive = DQN_STRING8("club_terry_alive");
|
|
||||||
Dqn_String8 club_terry_dark = DQN_STRING8("club_terry_dark");
|
|
||||||
}
|
|
||||||
g_anim_names;
|
|
||||||
|
|
||||||
TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform, TELY_Assets *assets, Dqn_Arena *arena, Dqn_String8 sheet_name)
|
TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_Platform *platform, TELY_Assets *assets, Dqn_Arena *arena, Dqn_String8 sheet_name)
|
||||||
{
|
{
|
||||||
@ -964,8 +932,10 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
move_entity = *state == FP_EntityClingerState_Run || *state == FP_EntityClingerState_Idle;
|
move_entity = *state == FP_EntityClingerState_Run || *state == FP_EntityClingerState_Idle;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_EntityType_Merchant: break;
|
case FP_EntityType_Merchant: break;
|
||||||
case FP_EntityType_Nil: break;
|
case FP_EntityType_Nil: break;
|
||||||
|
case FP_EntityType_ClubTerry: break;
|
||||||
|
case FP_EntityType_Count: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (move_entity) {
|
if (move_entity) {
|
||||||
@ -988,30 +958,14 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
Dqn_V2 entity_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
|
Dqn_V2 entity_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
|
||||||
|
|
||||||
if (entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) {
|
if (entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) {
|
||||||
Dqn_f32 closest_terry_dist = DQN_F32_MAX;
|
FP_GameFindClosestEntityResult closest_result = FP_Game_FindClosestEntityWithType(game, entity->handle, FP_EntityType_Terry);
|
||||||
Dqn_V2 closest_terry_pos = Dqn_V2_InitNx1(DQN_F32_MAX);
|
if (closest_result.dist_squared < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game, 4.f))) {
|
||||||
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(FP_Game_MetersToPixelsNx1(game, 4.f))) {
|
|
||||||
FP_SentinelListLink<FP_GameWaypoint> *first_waypoint = FP_SentinelList_Front(&entity->waypoints);
|
FP_SentinelListLink<FP_GameWaypoint> *first_waypoint = FP_SentinelList_Front(&entity->waypoints);
|
||||||
if (first_waypoint->data.entity != closest_terry->handle) {
|
if (first_waypoint->data.entity != closest_result.entity) {
|
||||||
|
FP_GameEntity *terry = FP_Game_GetEntity(game, closest_result.entity);
|
||||||
FP_GameDirection aggro_direction = FP_GameDirection_Count;
|
FP_GameDirection aggro_direction = FP_GameDirection_Count;
|
||||||
DQN_FOR_UINDEX(dir_index, FP_GameDirection_Count) {
|
DQN_FOR_UINDEX(dir_index, FP_GameDirection_Count) {
|
||||||
FP_GameEntityHandle slot_entity_handle = closest_terry->aggro_slot[dir_index];
|
FP_GameEntityHandle slot_entity_handle = terry->aggro_slot[dir_index];
|
||||||
FP_GameEntity *slot_entity = FP_Game_GetEntity(game, slot_entity_handle);
|
FP_GameEntity *slot_entity = FP_Game_GetEntity(game, slot_entity_handle);
|
||||||
if (FP_Game_IsNilEntity(slot_entity)) {
|
if (FP_Game_IsNilEntity(slot_entity)) {
|
||||||
aggro_direction = DQN_CAST(FP_GameDirection)dir_index;
|
aggro_direction = DQN_CAST(FP_GameDirection)dir_index;
|
||||||
@ -1021,17 +975,33 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
|
|
||||||
FP_SentinelListLink<FP_GameWaypoint> *link = FP_SentinelList_MakeBefore(&entity->waypoints, first_waypoint, game->chunk_pool);
|
FP_SentinelListLink<FP_GameWaypoint> *link = FP_SentinelList_MakeBefore(&entity->waypoints, first_waypoint, game->chunk_pool);
|
||||||
FP_GameWaypoint *waypoint = &link->data;
|
FP_GameWaypoint *waypoint = &link->data;
|
||||||
waypoint->entity = closest_terry->handle;
|
waypoint->entity = terry->handle;
|
||||||
|
|
||||||
if (aggro_direction != FP_GameDirection_Count) {
|
if (aggro_direction != FP_GameDirection_Count) {
|
||||||
waypoint->type = FP_GameWaypointType_Side;
|
waypoint->type = FP_GameWaypointType_Side;
|
||||||
waypoint->type_direction = aggro_direction;
|
waypoint->type_direction = aggro_direction;
|
||||||
closest_terry->aggro_slot[aggro_direction] = entity->handle;
|
terry->aggro_slot[aggro_direction] = entity->handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entity->flags & FP_GameEntityFlag_RespondsToClubTerry) {
|
||||||
|
FP_GameFindClosestEntityResult closest_result = FP_Game_FindClosestEntityWithType(game, entity->handle, FP_EntityType_ClubTerry);
|
||||||
|
if (closest_result.dist_squared < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game, 4.f))) {
|
||||||
|
FP_SentinelListLink<FP_GameWaypoint> *first_waypoint = FP_SentinelList_Front(&entity->waypoints);
|
||||||
|
if (first_waypoint->data.entity != closest_result.entity) {
|
||||||
|
FP_GameEntity *club_terry = FP_Game_GetEntity(game, closest_result.entity);
|
||||||
|
|
||||||
|
FP_SentinelListLink<FP_GameWaypoint> *link = FP_SentinelList_MakeBefore(&entity->waypoints, first_waypoint, game->chunk_pool);
|
||||||
|
FP_GameWaypoint *waypoint = &link->data;
|
||||||
|
waypoint->entity = club_terry->handle;
|
||||||
|
waypoint->type = FP_GameWaypointType_Side;
|
||||||
|
waypoint->type_direction = FP_GameDirection_Down;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@ -1051,7 +1021,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
Dqn_f32 arrival_threshold = {};
|
Dqn_f32 arrival_threshold = {};
|
||||||
switch (waypoint->arrive) {
|
switch (waypoint->arrive) {
|
||||||
case FP_GameWaypointArrive_Default: {
|
case FP_GameWaypointArrive_Default: {
|
||||||
arrival_threshold = FP_Game_MetersToPixelsNx1(game, 1.f);
|
arrival_threshold = FP_Game_MetersToPixelsNx1(game, 0.5f);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_GameWaypointArrive_WhenWithinEntitySize: {
|
case FP_GameWaypointArrive_WhenWithinEntitySize: {
|
||||||
@ -1067,14 +1037,11 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: We have arrived at the waypoint
|
// NOTE: We have arrived at the waypoint
|
||||||
if ((entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) && waypoint_entity->type == FP_EntityType_Terry) {
|
bool aggro_on_terry = (entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) && waypoint_entity->type == FP_EntityType_Terry;
|
||||||
// NOTE: We had a waypoint to move to Terry because he has
|
bool club_terry_response = (entity->flags & FP_GameEntityFlag_RespondsToClubTerry) && waypoint_entity->type == FP_EntityType_ClubTerry;
|
||||||
// drawn our aggro and we've arrived at Terry
|
if (aggro_on_terry || club_terry_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;
|
|
||||||
|
|
||||||
if (can_attack) {
|
if (can_attack) {
|
||||||
|
|
||||||
Dqn_V2 attack_dir_vectors[FP_GameDirection_Count] = {};
|
Dqn_V2 attack_dir_vectors[FP_GameDirection_Count] = {};
|
||||||
attack_dir_vectors[FP_GameDirection_Up] = Dqn_V2_InitNx2(+0, -1);
|
attack_dir_vectors[FP_GameDirection_Up] = Dqn_V2_InitNx2(+0, -1);
|
||||||
attack_dir_vectors[FP_GameDirection_Down] = Dqn_V2_InitNx2(+0, +1);
|
attack_dir_vectors[FP_GameDirection_Down] = Dqn_V2_InitNx2(+0, +1);
|
||||||
@ -1117,7 +1084,8 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
entity->direction = best_attack_dir;
|
entity->direction = best_attack_dir;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_EntityType_Count: DQN_INVALID_CODE_PATH; break;
|
case FP_EntityType_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
|
case FP_EntityType_ClubTerry: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1195,6 +1163,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
FP_GameEntity *mob = FP_Game_GetEntity(game, link->data);
|
FP_GameEntity *mob = FP_Game_GetEntity(game, link->data);
|
||||||
mob->waypoints = FP_SentinelList_Init<FP_GameWaypoint>(game->chunk_pool);
|
mob->waypoints = FP_SentinelList_Init<FP_GameWaypoint>(game->chunk_pool);
|
||||||
mob->flags |= FP_GameEntityFlag_AggrosWhenNearTerry;
|
mob->flags |= FP_GameEntityFlag_AggrosWhenNearTerry;
|
||||||
|
mob->flags |= FP_GameEntityFlag_RespondsToClubTerry;
|
||||||
|
|
||||||
for (FP_GameEntity *waypoint_entity = entity->first_child; waypoint_entity; waypoint_entity = waypoint_entity->next) {
|
for (FP_GameEntity *waypoint_entity = entity->first_child; waypoint_entity; waypoint_entity = waypoint_entity->next) {
|
||||||
if ((waypoint_entity->flags & FP_GameEntityFlag_MobSpawnerWaypoint) == 0)
|
if ((waypoint_entity->flags & FP_GameEntityFlag_MobSpawnerWaypoint) == 0)
|
||||||
@ -1245,7 +1214,8 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
|
|||||||
case FP_EntityType_Nil: /*FALLTRHU*/
|
case FP_EntityType_Nil: /*FALLTRHU*/
|
||||||
case FP_EntityType_Terry: /*FALLTRHU*/
|
case FP_EntityType_Terry: /*FALLTRHU*/
|
||||||
case FP_EntityType_Merchant: /*FALLTRHU*/
|
case FP_EntityType_Merchant: /*FALLTRHU*/
|
||||||
case FP_EntityType_Count: break;
|
case FP_EntityType_Count: break;
|
||||||
|
case FP_EntityType_ClubTerry: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!permit_attack)
|
if (!permit_attack)
|
||||||
|
33
feely_pona.h
33
feely_pona.h
@ -21,3 +21,36 @@ struct FP_Meters
|
|||||||
Dqn_f32 meters;
|
Dqn_f32 meters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FP_GlobalAnimations
|
||||||
|
{
|
||||||
|
Dqn_String8 terry_walk_idle = DQN_STRING8("terry_walk_idle");
|
||||||
|
Dqn_String8 terry_walk_up = DQN_STRING8("terry_walk_up");
|
||||||
|
Dqn_String8 terry_walk_down = DQN_STRING8("terry_walk_down");
|
||||||
|
Dqn_String8 terry_walk_left = DQN_STRING8("terry_walk_left");
|
||||||
|
Dqn_String8 terry_walk_right = DQN_STRING8("terry_walk_right");
|
||||||
|
Dqn_String8 terry_attack_up = DQN_STRING8("terry_attack_up");
|
||||||
|
Dqn_String8 terry_attack_side = DQN_STRING8("terry_attack_side");
|
||||||
|
Dqn_String8 terry_attack_down = DQN_STRING8("terry_attack_down");
|
||||||
|
Dqn_String8 terry_merchant = DQN_STRING8("terry_merchant");
|
||||||
|
|
||||||
|
Dqn_String8 smoochie_walk_up = DQN_STRING8("smoochie_walk_up");
|
||||||
|
Dqn_String8 smoochie_walk_down = DQN_STRING8("smoochie_walk_down");
|
||||||
|
Dqn_String8 smoochie_walk_left = DQN_STRING8("smoochie_walk_left");
|
||||||
|
Dqn_String8 smoochie_walk_right = DQN_STRING8("smoochie_walk_right");
|
||||||
|
Dqn_String8 smoochie_attack_down = DQN_STRING8("smoochie_attack_down");
|
||||||
|
Dqn_String8 smoochie_hurt_side = DQN_STRING8("smoochie_hurt_side");
|
||||||
|
Dqn_String8 smoochie_attack_heart = DQN_STRING8("smoochie_attack_heart");
|
||||||
|
Dqn_String8 smoochie_death = DQN_STRING8("smoochie_death");
|
||||||
|
|
||||||
|
Dqn_String8 clinger_attack_down = DQN_STRING8("clinger_attack_down");
|
||||||
|
Dqn_String8 clinger_attack_side = DQN_STRING8("clinger_attack_side");
|
||||||
|
Dqn_String8 clinger_attack_up = DQN_STRING8("clinger_attack_up");
|
||||||
|
Dqn_String8 clinger_death = DQN_STRING8("clinger_death");
|
||||||
|
Dqn_String8 clinger_walk_up = DQN_STRING8("clinger_walk_up");
|
||||||
|
Dqn_String8 clinger_walk_down = DQN_STRING8("clinger_walk_down");
|
||||||
|
|
||||||
|
Dqn_String8 club_terry_alive = DQN_STRING8("club_terry_alive");
|
||||||
|
Dqn_String8 club_terry_dark = DQN_STRING8("club_terry_dark");
|
||||||
|
}
|
||||||
|
g_anim_names;
|
||||||
|
|
||||||
|
@ -14,6 +14,13 @@ static void FP_Entity_AddDebugEditorFlags(FP_Game *game, FP_GameEntityHandle han
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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, sprite_rect.size.y);
|
||||||
|
Dqn_f32 result = height.meters / sprite_in_meters;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static FP_GameEntityHandle FP_Entity_CreateWaypointF(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
|
static FP_GameEntityHandle FP_Entity_CreateWaypointF(FP_Game *game, Dqn_V2 pos, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -48,7 +55,8 @@ static FP_GameEntityHandle FP_Entity_CreateClinger(FP_Game *game, Dqn_V2 pos, DQ
|
|||||||
entity->is_dying = false;
|
entity->is_dying = false;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->sprite_height.meters = 1.6f;
|
entity->sprite_height.meters = 1.6f;
|
||||||
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.4f, 1.7f);
|
|
||||||
|
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.4f, entity->sprite_height.meters * .5f);
|
||||||
FP_Entity_AddDebugEditorFlags(game, entity->handle);
|
FP_Entity_AddDebugEditorFlags(game, entity->handle);
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
entity->flags |= FP_GameEntityFlag_Attackable;
|
entity->flags |= FP_GameEntityFlag_Attackable;
|
||||||
@ -68,7 +76,7 @@ static FP_GameEntityHandle FP_Entity_CreateSmoochie(FP_Game *game, Dqn_V2 pos, D
|
|||||||
entity->is_dying = false;
|
entity->is_dying = false;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->sprite_height.meters = 1.6f;
|
entity->sprite_height.meters = 1.6f;
|
||||||
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.4f, 1.6f);
|
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.4f, entity->sprite_height.meters * .6f);
|
||||||
FP_Entity_AddDebugEditorFlags(game, entity->handle);
|
FP_Entity_AddDebugEditorFlags(game, entity->handle);
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
entity->flags |= FP_GameEntityFlag_Attackable;
|
entity->flags |= FP_GameEntityFlag_Attackable;
|
||||||
@ -131,7 +139,7 @@ static FP_GameEntityHandle FP_Entity_CreateTerry(FP_Game *game, Dqn_V2 pos, DQN_
|
|||||||
entity->type = FP_EntityType_Terry;
|
entity->type = FP_EntityType_Terry;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->sprite_height.meters = 1.8f;
|
entity->sprite_height.meters = 1.8f;
|
||||||
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.5f, entity->sprite_height.meters);
|
entity->local_hit_box_size = FP_Game_MetersToPixelsNx2(game, 0.5f, entity->sprite_height.meters * .6f);
|
||||||
FP_Entity_AddDebugEditorFlags(game, result);
|
FP_Entity_AddDebugEditorFlags(game, result);
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
entity->flags |= FP_GameEntityFlag_Attackable;
|
entity->flags |= FP_GameEntityFlag_Attackable;
|
||||||
@ -166,8 +174,14 @@ static FP_GameEntityHandle FP_Entity_CreateClubTerry(FP_Game *game, Dqn_V2 pos,
|
|||||||
|
|
||||||
entity->type = FP_EntityType_ClubTerry;
|
entity->type = FP_EntityType_ClubTerry;
|
||||||
entity->local_pos = pos;
|
entity->local_pos = pos;
|
||||||
entity->local_hit_box_size = Dqn_V2_InitNx2(50, 50);
|
entity->sprite_height.meters = 4.f;
|
||||||
entity->sprite_height.meters = 3.66f;
|
|
||||||
|
TELY_AssetSpriteAnimation *sprite_anim = TELY_Asset_GetSpriteAnimation(&game->club_terry_sprite_sheet, g_anim_names.club_terry_alive);
|
||||||
|
Dqn_Rect sprite_rect = game->club_terry_sprite_sheet.rects.data[sprite_anim->index];
|
||||||
|
Dqn_f32 size_scale = FP_Entity_CalcSpriteScaleForDesiredHeight(game, entity->sprite_height, sprite_rect);
|
||||||
|
Dqn_V2 sprite_rect_scaled = sprite_rect.size * size_scale;
|
||||||
|
|
||||||
|
entity->local_hit_box_size = Dqn_V2_InitNx2(sprite_rect_scaled.w, sprite_rect_scaled.h - (sprite_rect_scaled.h * .4f));
|
||||||
FP_Entity_AddDebugEditorFlags(game, result);
|
FP_Entity_AddDebugEditorFlags(game, result);
|
||||||
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
entity->flags |= FP_GameEntityFlag_NonTraversable;
|
||||||
|
|
||||||
|
@ -651,19 +651,19 @@ static Dqn_V2 FP_Game_CalcWaypointWorldPos(FP_Game *game, FP_GameWaypoint const
|
|||||||
Dqn_Rect entity_rect = FP_Game_CalcEntityWorldHitBox(game, waypoint_entity->handle);
|
Dqn_Rect entity_rect = FP_Game_CalcEntityWorldHitBox(game, waypoint_entity->handle);
|
||||||
switch (waypoint->type_direction) {
|
switch (waypoint->type_direction) {
|
||||||
case FP_GameDirection_Up: {
|
case FP_GameDirection_Up: {
|
||||||
result = Dqn_V2_InitNx2(entity_rect.pos.x + entity_rect.size.w * .5f, entity_rect.pos.y - entity_rect.size.h * .5f);
|
result = Dqn_V2_InitNx2(entity_rect.pos.x + entity_rect.size.w * .5f, entity_rect.pos.y + entity_rect.size.h * .1f);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_GameDirection_Down: {
|
case FP_GameDirection_Down: {
|
||||||
result = Dqn_V2_InitNx2(entity_rect.pos.x + entity_rect.size.w * .5f, entity_rect.pos.y + entity_rect.size.h + (entity_rect.size.h * .5f));
|
result = 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);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_GameDirection_Left: {
|
case FP_GameDirection_Left: {
|
||||||
result = Dqn_V2_InitNx2(entity_rect.pos.x - entity_rect.size.w * .5f, entity_rect.pos.y + entity_rect.size.h * .5f);
|
result = Dqn_V2_InitNx2(entity_rect.pos.x - entity_rect.size.w * .1f, entity_rect.pos.y + entity_rect.size.h * .5f);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_GameDirection_Right: {
|
case FP_GameDirection_Right: {
|
||||||
result = Dqn_V2_InitNx2(entity_rect.pos.x + entity_rect.size.w + entity_rect.size.w * .5f, entity_rect.pos.y + entity_rect.size.h * .5f);
|
result = 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);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
case FP_GameDirection_Count: DQN_INVALID_CODE_PATH; break;
|
||||||
@ -674,4 +674,31 @@ static Dqn_V2 FP_Game_CalcWaypointWorldPos(FP_Game *game, FP_GameWaypoint const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FP_GameFindClosestEntityResult FP_Game_FindClosestEntityWithType(FP_Game *game, FP_GameEntityHandle src_entity_handle, FP_EntityType type)
|
||||||
|
{
|
||||||
|
FP_GameFindClosestEntityResult result = {};
|
||||||
|
FP_GameEntity *src_entity = FP_Game_GetEntity(game, src_entity_handle);
|
||||||
|
if (FP_Game_IsNilEntity(src_entity))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
Dqn_V2 src_pos = FP_Game_CalcEntityWorldPos(game, src_entity_handle);
|
||||||
|
result.dist_squared = DQN_F32_MAX;
|
||||||
|
result.pos = Dqn_V2_InitNx1(DQN_F32_MAX);
|
||||||
|
|
||||||
|
for (FP_GameEntityIterator it = {}; FP_Game_DFSPostOrderWalkEntityTree(game, &it, game->root_entity); ) {
|
||||||
|
FP_GameEntity *it_entity = it.entity;
|
||||||
|
if (it_entity->type != type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Dqn_V2 pos = FP_Game_CalcEntityWorldPos(game, it_entity->handle);
|
||||||
|
Dqn_f32 dist = Dqn_V2_LengthSq_V2x2(pos, src_pos);
|
||||||
|
if (dist < result.dist_squared) {
|
||||||
|
result.pos = pos;
|
||||||
|
result.dist_squared = dist;
|
||||||
|
result.entity = it_entity->handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ enum FP_GameEntityFlag
|
|||||||
FP_GameEntityFlag_MobSpawnerWaypoint = 1 << 8,
|
FP_GameEntityFlag_MobSpawnerWaypoint = 1 << 8,
|
||||||
FP_GameEntityFlag_AggrosWhenNearTerry = 1 << 9,
|
FP_GameEntityFlag_AggrosWhenNearTerry = 1 << 9,
|
||||||
FP_GameEntityFlag_Attackable = 1 << 10,
|
FP_GameEntityFlag_Attackable = 1 << 10,
|
||||||
|
FP_GameEntityFlag_RespondsToClubTerry = 1 << 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FP_GameShapeType
|
enum FP_GameShapeType
|
||||||
@ -235,3 +236,11 @@ struct FP_GameAStarNode
|
|||||||
Dqn_V2I came_from;
|
Dqn_V2I came_from;
|
||||||
bool non_traversable;
|
bool non_traversable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FP_GameFindClosestEntityResult
|
||||||
|
{
|
||||||
|
FP_GameEntityHandle entity;
|
||||||
|
Dqn_f32 dist_squared;
|
||||||
|
Dqn_V2 pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user