diff --git a/assets/models/props/round_elevator.flags b/assets/models/props/round_elevator.flags index 53406ff..ab0f383 100644 --- a/assets/models/props/round_elevator.flags +++ b/assets/models/props/round_elevator.flags @@ -1 +1 @@ --r 90,0,0 -m assets/materials/static.skm.yaml -m assets/materials/elevator.skm.yaml --default-material default \ No newline at end of file +-r 180,0,0 -m assets/materials/static.skm.yaml -m assets/materials/elevator.skm.yaml --default-material default \ No newline at end of file diff --git a/assets/models/props/round_elevator_collision.flags b/assets/models/props/round_elevator_collision.flags index 6047ab9..7ecd284 100644 --- a/assets/models/props/round_elevator_collision.flags +++ b/assets/models/props/round_elevator_collision.flags @@ -1 +1 @@ --r 0,0,0 --mesh-collider \ No newline at end of file +-r 90,0,0 --mesh-collider \ No newline at end of file diff --git a/assets/models/props/round_elevator_interior.flags b/assets/models/props/round_elevator_interior.flags index a3d1a18..53406ff 100644 --- a/assets/models/props/round_elevator_interior.flags +++ b/assets/models/props/round_elevator_interior.flags @@ -1 +1 @@ --r 0,0,0 -m assets/materials/static.skm.yaml -m assets/materials/elevator.skm.yaml --default-material default \ No newline at end of file +-r 90,0,0 -m assets/materials/static.skm.yaml -m assets/materials/elevator.skm.yaml --default-material default \ No newline at end of file diff --git a/assets/test_chambers/test_chamber_00/test_chamber_00_0.blend b/assets/test_chambers/test_chamber_00/test_chamber_00_0.blend index 403adf9..351569f 100644 Binary files a/assets/test_chambers/test_chamber_00/test_chamber_00_0.blend and b/assets/test_chambers/test_chamber_00/test_chamber_00_0.blend differ diff --git a/skelatool64/src/definition_generator/LevelGenerator.cpp b/skelatool64/src/definition_generator/LevelGenerator.cpp index 2add2d2..c4733f4 100644 --- a/skelatool64/src/definition_generator/LevelGenerator.cpp +++ b/skelatool64/src/definition_generator/LevelGenerator.cpp @@ -440,6 +440,52 @@ void generateFizzlerDefinitions( levelDef.AddPrimitive("fizzlerCount", fizzlerCount); } +void generateElevatorDefinitions( + const aiScene* scene, + CFileDefinition& fileDefinition, + StructureDataChunk& levelDef, + const RoomGeneratorOutput& roomOutput, + const DisplayListSettings& settings, + Signals& signals, + NodeGroups& nodeGroups) { + + int elevatorCount = 0; + std::unique_ptr elevators(new StructureDataChunk()); + + aiMatrix4x4 baseTransform = settings.CreateCollisionTransform(); + + for (auto& nodeInfo : nodeGroups.NodesForType("@elevator")) { + if (nodeInfo.arguments.size() == 0) { + continue; + } + + std::unique_ptr elevatorData(new StructureDataChunk()); + aiVector3D pos; + aiQuaternion rot; + aiVector3D scale; + (baseTransform * nodeInfo.node->mTransformation).Decompose(scale, rot, pos); + elevatorData->Add(std::unique_ptr(new StructureDataChunk(pos))); + elevatorData->Add(std::unique_ptr(new StructureDataChunk(rot))); + elevatorData->AddPrimitive(roomOutput.RoomForNode(nodeInfo.node)); + elevatorData->AddPrimitive(signals.SignalIndexForName(nodeInfo.arguments[0])); + elevatorData->AddPrimitive(nodeInfo.arguments.size() >= 2 && nodeInfo.arguments[1] == "isExit" ? 1 : 0); + + elevators->Add(std::move(elevatorData)); + ++elevatorCount; + } + + std::string elevatorsName = fileDefinition.AddDataDefinition( + "elevators", + "struct ElevatorDefinition", + true, + "_geo", + std::move(elevators) + ); + + levelDef.AddPrimitive("elevators", elevatorsName); + levelDef.AddPrimitive("elevatorCount", elevatorCount); +} + void generateLevel( const aiScene* scene, CFileDefinition& fileDefinition, @@ -481,5 +527,7 @@ void generateLevel( generateFizzlerDefinitions(scene, fileDefinition, *levelDef, roomOutput, settings, nodeGroups); + generateElevatorDefinitions(scene, fileDefinition, *levelDef, roomOutput, settings, signals, nodeGroups); + fileDefinition.AddDefinition(std::unique_ptr(new DataFileDefinition("struct LevelDefinition", fileDefinition.GetUniqueName("level"), false, "_geo", std::move(levelDef)))); } \ No newline at end of file diff --git a/skelatool64/src/definition_generator/TriggerGenerator.cpp b/skelatool64/src/definition_generator/TriggerGenerator.cpp index 3ef9047..ff032cd 100644 --- a/skelatool64/src/definition_generator/TriggerGenerator.cpp +++ b/skelatool64/src/definition_generator/TriggerGenerator.cpp @@ -79,6 +79,24 @@ std::unique_ptr generateCutsceneStep(CutsceneStep& step, con setSignal->AddPrimitive(step.command == "set_signal" ? 1 : 0); result->Add("setSignal", std::move(setSignal)); return result; + } else if (step.command == "wait_for_signal" && step.args.size() >= 1) { + result->AddPrimitive("CutsceneStepTypeWaitForSignal"); + std::unique_ptr waitforSignal(new StructureDataChunk()); + waitforSignal->AddPrimitive(signals.SignalIndexForName(step.args[0])); + result->Add("waitForSignal", std::move(waitforSignal)); + return result; + } else if (step.command == "teleport_player" && step.args.size() >= 2) { + short fromLocation = roomOutput.FindLocationIndex(step.args[0]); + short toLocation = roomOutput.FindLocationIndex(step.args[1]); + + if (fromLocation != -1 && toLocation != -1) { + result->AddPrimitive("CutsceneStepTypeTeleportPlayer"); + std::unique_ptr teleportPlayer(new StructureDataChunk()); + teleportPlayer->AddPrimitive(fromLocation); + teleportPlayer->AddPrimitive(toLocation); + result->Add("teleportPlayer", std::move(teleportPlayer)); + return result; + } } result->AddPrimitive("CutsceneStepTypeNoop"); diff --git a/src/levels/cutscene_runner.c b/src/levels/cutscene_runner.c index b64e2b4..20fc7d8 100644 --- a/src/levels/cutscene_runner.c +++ b/src/levels/cutscene_runner.c @@ -35,18 +35,14 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) { case CutsceneStepTypeSetSignal: signalsSetDefault(step->setSignal.signalIndex, step->setSignal.signalValue); break; - case CutsceneOpenElevator: - gScene.elevators[step->openElevator.elevatorIndex].flags = (gScene.elevators[step->openElevator.elevatorIndex].flags & ~ElevatorFlagsIsLocked) | ElevatorFlagsReleasePlayer; - break; - case CutsceneTeleportPlayer: - { + case CutsceneStepTypeTeleportPlayer: rigidBodyTeleport( &gScene.player.body, &gCurrentLevel->locations[step->teleportPlayer.fromLocation].transform, &gCurrentLevel->locations[step->teleportPlayer.toLocation].transform, gCurrentLevel->locations[step->teleportPlayer.toLocation].roomIndex ); - } + break; default: } } @@ -59,8 +55,8 @@ int cutsceneRunnerUpdateCurrentStep(struct CutsceneRunner* runner) { case CutsceneStepTypeDelay: runner->state.delay -= FIXED_DELTA_TIME; return runner->state.delay <= 0.0f; - case CutsceneWaitForElevator: - return (gScene.elevators[step->waitForElevator.elevatorIndex].flags & ElevatorFlagsContainsPlayer) != 0; + case CutsceneStepTypeWaitForSignal: + return signalsRead(step->waitForSignal.signalIndex); default: return 1; } diff --git a/src/levels/level_definition.h b/src/levels/level_definition.h index cf83806..5b4f86b 100644 --- a/src/levels/level_definition.h +++ b/src/levels/level_definition.h @@ -29,10 +29,9 @@ enum CutsceneStepType { CutsceneStepTypeDelay, CutsceneStepTypeOpenPortal, CutsceneStepTypeSetSignal, - CutsceneWaitForElevator, - CutsceneOpenElevator, - CutsceneTeleportPlayer, - CutsceneLoadLevel, + CutsceneStepTypeWaitForSignal, + CutsceneStepTypeTeleportPlayer, + CutsceneStepTypeLoadLevel, }; struct CutsceneStep { @@ -54,11 +53,8 @@ struct CutsceneStep { u16 signalValue; } setSignal; struct { - u16 elevatorIndex; - } waitForElevator; - struct { - u16 elevatorIndex; - } openElevator; + u16 signalIndex; + } waitForSignal; struct { u16 fromLocation; u16 toLocation; @@ -114,6 +110,14 @@ struct FizzlerDefinition { short roomIndex; }; +struct ElevatorDefinition { + struct Vector3 position; + struct Quaternion rotation; + short roomIndex; + short signalIndex; + short isExit; +}; + struct LevelDefinition { struct CollisionObject* collisionQuads; struct StaticContentElement *staticContent; @@ -130,6 +134,7 @@ struct LevelDefinition { struct SignalOperator* signalOperators; struct DecorDefinition* decor; struct FizzlerDefinition* fizzlers; + struct ElevatorDefinition* elevators; short collisionQuadCount; short staticContentCount; short portalSurfaceCount; @@ -140,6 +145,7 @@ struct LevelDefinition { short signalOperatorCount; short decorCount; short fizzlerCount; + short elevatorCount; short startLocation; }; diff --git a/src/scene/elevator.c b/src/scene/elevator.c index 82dd536..b711ea6 100644 --- a/src/scene/elevator.c +++ b/src/scene/elevator.c @@ -2,6 +2,9 @@ #include "../physics/collision_scene.h" #include "../scene/dynamic_scene.h" #include "../physics/mesh_collider.h" +#include "./signals.h" +#include "../math/mathf.h" +#include "../util/time.h" #include "../../build/assets/models/props/round_elevator_collision.h" #include "../../build/assets/models/props/round_elevator_interior.h" @@ -10,8 +13,9 @@ #include "../../build/assets/materials/static.h" #define AUTO_OPEN_DISTANCE 4.0f - #define INSIDE_DISTANCE 1.0f +#define SAME_LEVEL_HEIGHT 3.0f +#define OPEN_SPEED 2.0f struct ColliderTypeData gElevatorColliderType = { CollisionShapeTypeMesh, @@ -42,12 +46,7 @@ void elevatorRender(void* data, struct RenderScene* renderScene) { Mtx* armature = renderStateRequestMatrices(renderScene->renderState, PROPS_ROUND_ELEVATOR_DEFAULT_BONES_COUNT); for (int i = 0; i < PROPS_ROUND_ELEVATOR_DEFAULT_BONES_COUNT; ++i) { - if (elevator->flags & ElevatorFlagsIsOpen) { - props_round_elevator_default_bones[i].position = gOpenPosition[i]; - } else { - props_round_elevator_default_bones[i].position = gClosedPosition[i]; - } - + vector3Lerp(&gClosedPosition[i], &gOpenPosition[i], elevator->openAmount, &props_round_elevator_default_bones[i].position); transformToMatrixL(&props_round_elevator_default_bones[i], &armature[i], 1.0f); } @@ -60,7 +59,11 @@ void elevatorRender(void* data, struct RenderScene* renderScene) { armature ); - if (elevator->flags & (ElevatorFlagsIsOpen | ElevatorFlagsContainsPlayer)) { + int insideCheck = elevator->flags & (ElevatorFlagsIsLocked | ElevatorFlagsIsExit); + + int isPlayerInside = insideCheck == ElevatorFlagsIsLocked || insideCheck == ElevatorFlagsIsExit; + + if (elevator->openAmount > 0.0f || isPlayerInside) { renderSceneAdd( renderScene, props_round_elevator_interior_model_gfx, @@ -72,46 +75,69 @@ void elevatorRender(void* data, struct RenderScene* renderScene) { } } -void elevatorInit(struct Elevator* elevator) { +void elevatorInit(struct Elevator* elevator, struct ElevatorDefinition* elevatorDefinition) { collisionObjectInit(&elevator->collisionObject, &gElevatorColliderType, &elevator->rigidBody, 1.0f, gElevatorCollisionLayers); rigidBodyMarkKinematic(&elevator->rigidBody); collisionSceneAddDynamicObject(&elevator->collisionObject); - elevator->rigidBody.transform.position.x = -10.0f; - elevator->rigidBody.transform.position.z = 2.5f; + elevator->rigidBody.transform.position = elevatorDefinition->position; + elevator->rigidBody.transform.rotation = elevatorDefinition->rotation; collisionObjectUpdateBB(&elevator->collisionObject); elevator->dynamicId = dynamicSceneAdd(elevator, elevatorRender, &elevator->rigidBody.transform, 3.9f); - elevator->flags = 0; + elevator->flags = elevatorDefinition->isExit ? ElevatorFlagsIsExit : 0; + elevator->openAmount = 0.0f; + elevator->roomIndex = elevatorDefinition->roomIndex; + elevator->signalIndex = elevatorDefinition->signalIndex; } void elevatorUpdate(struct Elevator* elevator, struct Player* player) { struct Vector3 offset; vector3Sub(&elevator->rigidBody.transform.position, &player->lookTransform.position, &offset); + + float verticalDistance = fabsf(offset.y); offset.y = 0.0f; float horizontalDistance = vector3MagSqrd(&offset); - int inRange = horizontalDistance < AUTO_OPEN_DISTANCE * AUTO_OPEN_DISTANCE; - int inside = horizontalDistance < INSIDE_DISTANCE * INSIDE_DISTANCE; + int inRange = horizontalDistance < AUTO_OPEN_DISTANCE * AUTO_OPEN_DISTANCE && verticalDistance < SAME_LEVEL_HEIGHT; + int inside = horizontalDistance < INSIDE_DISTANCE * INSIDE_DISTANCE && verticalDistance < SAME_LEVEL_HEIGHT; - if (inside) { - elevator->flags |= ElevatorFlagsContainsPlayer; - player->body.currentRoom = RIGID_BODY_NO_ROOM; + int shouldBeOpen; + int shouldLock; + + if (elevator->flags & ElevatorFlagsIsExit) { + shouldBeOpen = signalsRead(elevator->signalIndex); + shouldLock = !inRange && (elevator->flags & ElevatorFlagsHasHadPlayer) != 0; + } else { + shouldBeOpen = inRange && !inside; + shouldLock = inside; + + if (inside || (elevator->flags & ElevatorFlagsIsLocked) != 0) { + signalsSend(elevator->signalIndex); + } } - int shouldBeOpen = inRange && (elevator->flags & ElevatorFlagsContainsPlayer) == 0; + if (inside) { + elevator->flags |= ElevatorFlagsHasHadPlayer; + } + + if (shouldLock) { + elevator->flags |= ElevatorFlagsIsLocked; + } + + if ((elevator->flags & ElevatorFlagsIsLocked) != 0) { + shouldBeOpen = 0; + } if (shouldBeOpen) { props_round_elevator_collision_collider.children[PROPS_ROUND_ELEVATOR_COLLISION_DOOR_RIGHT_COLLISION_INDEX].collisionLayers = 0; props_round_elevator_collision_collider.children[PROPS_ROUND_ELEVATOR_COLLISION_DOOR_LEFT_COLLISION_INDEX].collisionLayers = 0; - - elevator->flags |= ElevatorFlagsIsOpen; } else { props_round_elevator_collision_collider.children[PROPS_ROUND_ELEVATOR_COLLISION_DOOR_RIGHT_COLLISION_INDEX].collisionLayers = gElevatorCollisionLayers; props_round_elevator_collision_collider.children[PROPS_ROUND_ELEVATOR_COLLISION_DOOR_LEFT_COLLISION_INDEX].collisionLayers = gElevatorCollisionLayers; - - elevator->flags &= ~ElevatorFlagsIsOpen; } + + elevator->openAmount = mathfMoveTowards(elevator->openAmount, shouldBeOpen ? 1.0f : 0.0f, OPEN_SPEED * FIXED_DELTA_TIME); } \ No newline at end of file diff --git a/src/scene/elevator.h b/src/scene/elevator.h index e39146e..a0a4abd 100644 --- a/src/scene/elevator.h +++ b/src/scene/elevator.h @@ -4,12 +4,12 @@ #include "../math/transform.h" #include "../physics/collision_object.h" #include "../player/player.h" +#include "../levels/level_definition.h" enum ElevatorFlags { - ElevatorFlagsIsOpen = (1 << 0), - ElevatorFlagsContainsPlayer = (1 << 1), - ElevatorFlagsReleasePlayer = (1 << 2), - ElevatorFlagsIsLocked = (1 << 3), + ElevatorFlagsIsLocked = (1 << 0), + ElevatorFlagsIsExit = (1 << 1), + ElevatorFlagsHasHadPlayer = (1 << 2), }; struct Elevator { @@ -17,9 +17,12 @@ struct Elevator { struct RigidBody rigidBody; short dynamicId; short flags; + short signalIndex; + short roomIndex; + float openAmount; }; -void elevatorInit(struct Elevator* elevator); +void elevatorInit(struct Elevator* elevator, struct ElevatorDefinition* elevatorDefinition); void elevatorUpdate(struct Elevator* elevator, struct Player* player); diff --git a/src/scene/scene.c b/src/scene/scene.c index 260d019..5b2669d 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -84,10 +84,10 @@ void sceneInit(struct Scene* scene) { fizzlerInit(&scene->fizzlers[i], &fizzlerTransform, fizzlerDef->width, fizzlerDef->height, fizzlerDef->roomIndex); } - scene->elevatorCount = 1; + scene->elevatorCount = gCurrentLevel->elevatorCount; scene->elevators = malloc(sizeof(struct Elevator) * scene->elevatorCount); for (int i = 0; i < scene->elevatorCount; ++i) { - elevatorInit(&scene->elevators[i]); + elevatorInit(&scene->elevators[i], &gCurrentLevel->elevators[i]); } }