#include "entity.h" #include "game.h" #include "entitiesInclude.h" const EntityEntry entityEntries[ENTITY_COUNT] = { (EntityEntry){ .name = "Old Mint", .initCallback = initOldMint, .updateCallback = updateOldMint, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = false, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "Sticky Nickel", .initCallback = initStickyNickel, .updateCallback = updateStickyNickel, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = false, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "Tree", .initCallback = initTree, .updateCallback = updateTree, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = false, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "Bush", .initCallback = initBush, .updateCallback = updateBush, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = false, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "Flower", .initCallback = initFlower, .updateCallback = updateFlower, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = false, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "Pond", .initCallback = initPond, .updateCallback = updatePond, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = true, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "Utility Pole", .initCallback = initUtilityPole, .updateCallback = NULL, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = false, .isBuilding = false, .canBeSelected = false }, (EntityEntry){ .name = "Samantha", .initCallback = initSamantha, .updateCallback = updateSamantha, .closeCallback = closeSamantha, .interactionCallback = interactWithSamantha, .isPlace = false, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "Samantha's Spot", .initCallback = initSamanthasSpot, .updateCallback = updateSamanthasSpot, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = true, .isBuilding = false, .canBeSelected = false }, (EntityEntry){ .name = "Trashcan", .initCallback = initTrashcan, .updateCallback = updateTrashcan, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = false, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "Trash", .initCallback = initTrash, .updateCallback = updateTrash, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = false, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "Medical Trash", .initCallback = initMedicalTrash, .updateCallback = updateMedicalTrash, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = false, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "John", .initCallback = initJohn, .updateCallback = updateJohn, .closeCallback = NULL, .interactionCallback = NULL, .isPlace = false, .isBuilding = false, .canBeSelected = true }, (EntityEntry){ .name = "John's store", .initCallback = initJohnsStore, .updateCallback = updateJohnsStore, .closeCallback = closeJohnsStore, .interactionCallback = NULL, .isPlace = true, .isBuilding = true, .canBeSelected = false }, (EntityEntry){ .name = "Ron", .initCallback = initRon, .updateCallback = updateRon, .closeCallback = NULL, .interactionCallback = interactWithRon, .isPlace = false, .isBuilding = false, .canBeSelected = true } }; Entity createEntity(EntityId id, Vector3 position) { Entity entity; entity.id = id; entity.data = NULL; // Run init callback. InitEntityCallback initCallback = entityEntries[id].initCallback; if (initCallback != NULL) { initCallback(&entity); } entity.position = Vector3Zero(); setEntityPosition(&entity, position); return entity; } void updateEntity(Entity* entity, Game* game) { if (entity->id == ENTITY_NONE) { return; } UpdateEntityCallback updateCallback = entityEntries[entity->id].updateCallback; if (updateCallback != NULL) { updateCallback(entity, game); } } void closeEntity(Entity* entity) { if (entity->id == ENTITY_NONE) { return; } CloseEntityCallback closeCallback = entityEntries[entity->id].closeCallback; if (closeCallback != NULL) { closeCallback(entity); } entity->id = ENTITY_NONE; } const char* getEntityName(EntityId id) { if (id == ENTITY_NONE) { return NULL; } return entityEntries[id].name; } void setEntityPosition(Entity* entity, Vector3 position) { Vector3 movedBy = Vector3Subtract(position, entity->position); entity->position = position; entity->box.min = Vector3Add(entity->box.min, movedBy); entity->box.max = Vector3Add(entity->box.max, movedBy); } void placeEntityOnGround(Entity* entity, const World* world) { Vector3 position = entity->position; position.y = getWorldHeightAtLocation( world, entity->position.x, entity->position.z); position.y += (entity->box.max.y - entity->box.min.y) / 2.0; setEntityPosition(entity, position); } bool entityIsPlace(EntityId id) { if (id == ENTITY_NONE) { return false; } return entityEntries[id].isPlace; } bool entityIsBuilding(EntityId id) { if (id == ENTITY_NONE) { return false; } return entityEntries[id].isBuilding; } bool entityCanBeSelected(EntityId id) { if (id == ENTITY_NONE) { return false; } return entityEntries[id].canBeSelected; } float getEntityDistance(Entity entity, Vector3 position) { return Vector3Distance(entity.position, position) - (Vector3Distance(entity.box.min, entity.box.max) / 2.0); } InteractionCommand interactWithEntity(Entity* entity, Game* game, Selection selection) { if (entity->id == ENTITY_NONE) { return INTERACTION_END; } InteractionCallback callback = entityEntries[entity->id].interactionCallback; if (callback != NULL) { return callback(entity, game, selection); } return INTERACTION_END; } int getInteractionMenuIndex(Selection selection) { if (selection < SELECTION_MENU_ITEM || selection >= SELECTION_LEAVE) { return SELECTION_NONE; } return selection - SELECTION_MENU_ITEM; } BoundingBox entityBoxFromScale(float scale, float width, float height) { Vector2 size = (Vector2){width / height * scale, scale}; size = Vector2Scale(size, 0.5); return (BoundingBox){ .min = (Vector3){-size.x, -size.y, -size.x}, .max = (Vector3){size.x, size.y, size.x} }; } EntityBuilding* createEntityBuilding(Image heightmap) { EntityBuilding* entityBuilding = (EntityBuilding*)FT_MALLOC(sizeof(EntityBuilding)); if (entityBuilding == NULL) { ALLOCATION_ERROR; return NULL; } *entityBuilding = (EntityBuilding){ .model = LoadModelFromMesh(GenMeshCubicmap(heightmap, ENTITY_BUILDING_CUBE_SIZE)), .pixelMap = LoadImageColors(heightmap) }; return entityBuilding; } void freeEntityBuilding(EntityBuilding* entityBuilding) { if (entityBuilding != NULL) { UnloadModel(entityBuilding->model); UnloadImageColors(entityBuilding->pixelMap); FT_FREE(entityBuilding); } }