Add ball burn marks

This commit is contained in:
James Lambert 2023-02-11 21:17:44 -07:00
parent 26c8fa5f99
commit e0789a13fc
35 changed files with 214 additions and 42 deletions

View file

@ -185,7 +185,8 @@ MODEL_LIST = assets/models/cube/cube.blend \
assets/models/portal/portal_orange_filled.blend \
assets/models/portal/portal_orange_face.blend \
assets/models/pedestal.blend \
assets/models/grav_flare.blend
assets/models/grav_flare.blend \
assets/models/fleck_ash2.blend
ANIM_LIST = build/assets/models/pedestal_anim.o \
build/assets/models/props/box_dropper_anim.o \
@ -220,7 +221,7 @@ build/src/scene/switch.o: build/assets/models/props/switch001.h build/assets/mat
build/src/player/player.o: build/assets/models/player/chell.h build/assets/materials/static.h
build/src/scene/ball.o: build/assets/models/grav_flare.h build/assets/materials/static.h
build/src/scene/ball.o: build/assets/models/grav_flare.h build/assets/models/fleck_ash2.h build/assets/materials/static.h
build/src/scene/ball_launcher.o: build/assets/models/props/combine_ball_launcher.h build/assets/materials/static.h

View file

@ -84,10 +84,6 @@ Where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where Blender
## Current TODO list
- [ ] close portal in elevator
- [ ] checkpoint in elevator
- [ ] keep stationary portal with fizzle grids
- [ ] add more fizzle grids
- [ ] red light district
- [ ] burn marks
- [ ] Skips audio sometimes
@ -100,6 +96,10 @@ Where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where Blender
- [ ] Presort portal gun polygon order
- [ ] Signage should not always be on
- [ ] Camera shake
- [x] close portal in elevator
- [x] keep stationary portal with fizzle grids
- [x] add more fizzle grids
- [x] checkpoint in elevator
- [x] preserve gun between test chambers
- [x] Finish up animation pieces (collider/portable surface/culling logic)
- [x] Implement pedestal button

View file

@ -0,0 +1 @@
-crop 128x128+0+0 -alpha extract -resize 32x32

View file

@ -0,0 +1 @@
-alpha extract

View file

@ -679,4 +679,46 @@ materials:
properties:
tileSizeS: 2
tileSizeT: 2
tileSizeT: 2
orange_spot:
gDPSetTile:
filename: ../../portal_pak_modified/materials/decals/orange_spot.png
fmt: G_IM_FMT_I
siz: G_IM_SIZ_4b
s:
mirror: true
t:
mirror: true
gDPSetRenderMode: G_RM_ZB_XLU_DECAL
gSPGeometryMode:
clear: [G_LIGHTING, G_SHADE]
gDPSetCombineMode:
color: ["0", "0", "0", "PRIMITIVE"]
alpha: ["0", "0", "0", "TEXEL0"]
gDPSetPrimColor:
r: 230
g: 103
b: 36
fleck_ash2:
gDPSetTile:
filename: ../../portal_pak_modified/materials/effects/fleck_ash2.png
fmt: G_IM_FMT_I
siz: G_IM_SIZ_4b
gDPSetRenderMode: G_RM_ZB_XLU_DECAL
gSPGeometryMode:
clear: [G_LIGHTING, G_SHADE]
gDPSetCombineMode:
color: ["0", "0", "0", "PRIMITIVE"]
alpha: ["0", "0", "0", "TEXEL0"]
gDPSetPrimColor:
r: 3
g: 3
b: 3

Binary file not shown.

View file

@ -0,0 +1 @@
-r 0,0,0 -m assets/materials/static.skm.yaml --default-material grav_flare

View file

@ -90,7 +90,7 @@ void decorObjectInit(struct DecorObject* object, struct DecorObjectDefinition* d
collisionObjectUpdateBB(&object->collisionObject);
}
object->dynamicId = dynamicSceneAdd(object, decorObjectRender, &object->rigidBody.transform, definition->radius);
object->dynamicId = dynamicSceneAdd(object, decorObjectRender, &object->rigidBody.transform.position, definition->radius);
dynamicSceneSetRoomFlags(object->dynamicId, ROOM_FLAG_FROM_INDEX(room));

View file

@ -152,7 +152,7 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
quatMultVector(&location->transform.rotation, &gRight, &transformUp);
vector3Negate(&transformUp, &transformUp);
vector3AddScaled(&location->transform.position, &firingRay.dir, -0.1f, &firingRay.origin);
sceneFirePortal(&gScene, &firingRay, &transformUp, step->openPortal.portalIndex, location->roomIndex);
sceneFirePortal(&gScene, &firingRay, &transformUp, step->openPortal.portalIndex, location->roomIndex, 0);
break;
}
case CutsceneStepTypeSetSignal:

View file

@ -17,6 +17,7 @@ struct Transform* levelRelativeTransform();
struct Vector3* levelRelativeVelocity();
extern struct LevelDefinition* gCurrentLevel;
extern int gCurrentLevelIndex;
int levelMaterialCount();
int levelMaterialTransparentStart();

View file

@ -161,7 +161,7 @@ static void gameProc(void* arg) {
contactSolverInit(&gContactSolver);
portalSurfaceCleanupQueueInit();
savefileNew();
levelLoad(0);
levelLoad(4);
cutsceneRunnerReset();
controllersInit();
initAudio(fps);

View file

@ -125,7 +125,7 @@ void playerInit(struct Player* player, struct Location* startLocation, struct Ve
player->flags |= PlayerHasSecondPortalGun;
}
player->dynamicId = dynamicSceneAdd(player, playerRender, &player->body.transform, 1.5f);
player->dynamicId = dynamicSceneAdd(player, playerRender, &player->body.transform.position, 1.5f);
dynamicSceneSetFlags(player->dynamicId, DYNAMIC_SCENE_OBJECT_SKIP_ROOT);
if (startLocation) {

View file

@ -9,6 +9,7 @@
#include "../util/time.h"
#include "../build/assets/models/grav_flare.h"
#include "../build/assets/models/fleck_ash2.h"
#include "../build/assets/models/cube/cube.h"
#include "../build/assets/materials/static.h"
@ -26,6 +27,32 @@ struct ColliderTypeData gBallCollider = {
&gCollisionBoxCallbacks,
};
struct BallBurnMark gBurnMarks[MAX_BURN_MARKS];
short gCurrentBurnIndex;
void ballBurnMarkInit() {
gCurrentBurnIndex = 0;
for (int i = 0; i < 3; ++i) {
gBurnMarks[i].dynamicId = -1;
}
}
void ballBurnFilterOnPortal(struct Transform* portalTransform, int portalIndex) {
for (int i = 0; i < MAX_BURN_MARKS; ++i) {
struct BallBurnMark* burnMark = &gBurnMarks[i];
if (burnMark->dynamicId == -1) {
continue;
}
if (collisionSceneIsTouchingSinglePortal(&burnMark->at, &burnMark->normal, portalTransform, portalIndex)) {
dynamicSceneRemove(burnMark->dynamicId);
burnMark->dynamicId = -1;
}
}
}
void ballRender(void* data, struct RenderScene* renderScene, struct Transform* fromView) {
struct Ball* ball = (struct Ball*)data;
struct Transform transform;
@ -40,6 +67,19 @@ void ballRender(void* data, struct RenderScene* renderScene, struct Transform* f
renderSceneAdd(renderScene, grav_flare_model_gfx, mtx, GRAV_FLARE_INDEX, &ball->rigidBody.transform.position, NULL);
}
void ballBurnRender(void* data, struct DynamicRenderDataList* renderList, struct RenderState* renderState) {
struct BallBurnMark* burn = (struct BallBurnMark*)data;
dynamicRenderListAddData(
renderList,
fleck_ash2_model_gfx,
&burn->matrix,
FLECK_ASH2_INDEX,
&burn->at,
NULL
);
}
void ballInitInactive(struct Ball* ball) {
ball->targetSpeed = 0.0f;
ball->flags = 0;
@ -61,7 +101,7 @@ void ballInit(struct Ball* ball, struct Vector3* position, struct Vector3* veloc
ball->targetSpeed = sqrtf(vector3MagSqrd(&ball->rigidBody.velocity));
ball->dynamicId = dynamicSceneAddViewDependant(ball, ballRender, &ball->rigidBody.transform, BALL_RADIUS);
ball->dynamicId = dynamicSceneAddViewDependant(ball, ballRender, &ball->rigidBody.transform.position, BALL_RADIUS);
dynamicSceneSetRoomFlags(ball->dynamicId, ROOM_FLAG_FROM_INDEX(startingRoom));
}
@ -70,6 +110,46 @@ void ballTurnOnCollision(struct Ball* ball) {
ball->collisionObject.collisionLayers |= COLLISION_LAYERS_BLOCK_BALL;
}
void ballInitBurn(struct Ball* ball, struct ContactManifold* manifold) {
if (!manifold || manifold->contactCount == 0) {
return;
}
// only add burn marks to static objects
if (manifold->shapeA->body != NULL) {
return;
}
struct BallBurnMark* burn = &gBurnMarks[gCurrentBurnIndex];
struct BallBurnMark* lastBurn = &gBurnMarks[(gCurrentBurnIndex == 0 ? MAX_BURN_MARKS : gCurrentBurnIndex) - 1];
struct Transform burnTransform;
burnTransform.position = manifold->contacts[0].contactAWorld;
// don't double up burns
if (vector3DistSqrd(&burnTransform.position, &lastBurn->at) < 0.1f) {
return;
}
++gCurrentBurnIndex;
if (gCurrentBurnIndex == MAX_BURN_MARKS) {
gCurrentBurnIndex = 0;
}
if (burn->dynamicId == -1) {
burn->dynamicId = dynamicSceneAdd(burn, ballBurnRender, &burn->at, 0.2f);
}
quatLook(&manifold->normal, &gUp, &burnTransform.rotation);
burnTransform.scale = gOneVec;
transformToMatrixL(&burnTransform, &burn->matrix, SCENE_SCALE);
burn->at = burnTransform.position;
burn->normal = manifold->normal;
}
void ballUpdate(struct Ball* ball) {
if (ball->targetSpeed == 0.0f || ballIsCaught(ball)) {
return;
@ -96,6 +176,9 @@ void ballUpdate(struct Ball* ball) {
dynamicSceneRemove(ball->dynamicId);
}
}
struct ContactManifold* manifold = contactSolverNextManifold(&gContactSolver, &ball->collisionObject, NULL);
ballInitBurn(ball, manifold);
}
int ballIsActive(struct Ball* ball) {

View file

@ -6,20 +6,33 @@
#define BALL_VELOCITY 2.0f
#define BALL_FADE_TIME 3.0f
#define MAX_BURN_MARKS 3
enum BallFlags {
BallFlagsCaught = (1 << 0),
BallFlagsPowering = (1 << 1),
};
struct BallBurnMark {
Mtx matrix;
struct Vector3 at;
struct Vector3 normal;
short dynamicId;
};
struct Ball {
struct CollisionObject collisionObject;
struct RigidBody rigidBody;
float targetSpeed;
float lifetime;
short dynamicId;
short flags;
};
void ballBurnMarkInit();
void ballBurnFilterOnPortal(struct Transform* portalTransform, int portalIndex);
void ballInitInactive(struct Ball* ball);
void ballInit(struct Ball* ball, struct Vector3* position, struct Vector3* velocity, short startingRoom, float ballLifetime);
void ballTurnOnCollision(struct Ball* ball);

View file

@ -71,7 +71,7 @@ void ballCatcherInit(struct BallCatcher* catcher, struct BallCatcherDefinition*
collisionObjectUpdateBB(&catcher->collisionObject);
catcher->dynamicId = dynamicSceneAdd(catcher, ballCatcherRender, &catcher->rigidBody.transform, 1.0f);
catcher->dynamicId = dynamicSceneAdd(catcher, ballCatcherRender, &catcher->rigidBody.transform.position, 1.0f);
dynamicSceneSetRoomFlags(catcher->dynamicId, ROOM_FLAG_FROM_INDEX(catcher->rigidBody.currentRoom));

View file

@ -66,7 +66,7 @@ void ballLauncherInit(struct BallLauncher* launcher, struct BallLauncherDefiniti
collisionObjectUpdateBB(&launcher->collisionObject);
launcher->dynamicId = dynamicSceneAdd(launcher, ballLauncherRender, &launcher->rigidBody.transform, 1.0f);
launcher->dynamicId = dynamicSceneAdd(launcher, ballLauncherRender, &launcher->rigidBody.transform.position, 1.0f);
dynamicSceneSetRoomFlags(launcher->dynamicId, ROOM_FLAG_FROM_INDEX(launcher->rigidBody.currentRoom));

View file

@ -89,7 +89,7 @@ void boxDropperRender(void* data, struct DynamicRenderDataList* renderList, stru
}
void boxDropperInit(struct BoxDropper* dropper, struct BoxDropperDefinition* definition) {
dropper->dynamicId = dynamicSceneAdd(dropper, boxDropperRender, &dropper->transform, 1.5f);
dropper->dynamicId = dynamicSceneAdd(dropper, boxDropperRender, &dropper->transform.position, 1.5f);
dropper->transform.position = definition->position;
quatIdent(&dropper->transform.rotation);

View file

@ -80,7 +80,7 @@ void buttonInit(struct Button* button, struct ButtonDefinition* definition) {
collisionObjectUpdateBB(&button->collisionObject);
button->dynamicId = dynamicSceneAdd(button, buttonRender, &button->rigidBody.transform, 0.84f);
button->dynamicId = dynamicSceneAdd(button, buttonRender, &button->rigidBody.transform.position, 0.84f);
button->signalIndex = definition->signalIndex;
button->originalPos = definition->location;

View file

@ -71,7 +71,7 @@ void doorInit(struct Door* door, struct DoorDefinition* doorDefinition, struct W
collisionObjectUpdateBB(&door->collisionObject);
door->dynamicId = dynamicSceneAdd(door, doorRender, &door->rigidBody.transform, 1.7f);
door->dynamicId = dynamicSceneAdd(door, doorRender, &door->rigidBody.transform.position, 1.7f);
door->signalIndex = doorDefinition->signalIndex;
door->openAmount = 0.0f;

View file

@ -54,7 +54,7 @@ void dynamicRenderListPopulate(struct DynamicRenderDataList* list, struct Render
int visibleStages = 0;
struct Vector3 scaledPos;
vector3Scale(&object->transform->position, &scaledPos, SCENE_SCALE);
vector3Scale(object->position, &scaledPos, SCENE_SCALE);
for (int stageIndex = 0; stageIndex < stageCount; ++stageIndex) {
if ((stages[stageIndex].visiblerooms & object->roomFlags) == 0) {
@ -117,7 +117,7 @@ void dynamicRenderPopulateRenderScene(
}
struct Vector3 scaledPos;
vector3Scale(&object->transform->position, &scaledPos, SCENE_SCALE);
vector3Scale(object->position, &scaledPos, SCENE_SCALE);
if (isSphereOutsideFrustrum(cullingInfo, &scaledPos, object->scaledRadius)) {
continue;

View file

@ -15,7 +15,7 @@ void dynamicSceneInit() {
}
}
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform* transform, float radius) {
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Vector3* position, float radius) {
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
struct DynamicSceneObject* object = &gDynamicScene.objects[i];
if (!(object->flags & DYNAMIC_SCENE_OBJECT_FLAGS_USED)) {
@ -23,7 +23,7 @@ int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform*
object->flags = DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE;
object->data = data;
object->renderCallback = renderCallback;
object->transform = transform;
object->position = position;
object->scaledRadius = radius * SCENE_SCALE;
object->roomFlags = ~0;
return i;
@ -33,7 +33,7 @@ int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform*
return INVALID_DYNAMIC_OBJECT;
}
int dynamicSceneAddViewDependant(void* data, DynamicViewRender renderCallback, struct Transform* transform, float radius) {
int dynamicSceneAddViewDependant(void* data, DynamicViewRender renderCallback, struct Vector3* position, float radius) {
for (int i = 0; i < MAX_VIEW_DEPENDANT_OBJECTS; ++i) {
struct DynamicSceneViewDependantObject* object = &gDynamicScene.viewDependantObjects[i];
if (!(object->flags & DYNAMIC_SCENE_OBJECT_FLAGS_USED)) {
@ -41,7 +41,7 @@ int dynamicSceneAddViewDependant(void* data, DynamicViewRender renderCallback, s
object->flags = DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE;
object->data = data;
object->renderCallback = renderCallback;
object->transform = transform;
object->position = position;
object->scaledRadius = radius * SCENE_SCALE;
object->roomFlags = ~0;
return i + MAX_DYNAMIC_SCENE_OBJECTS;

View file

@ -11,7 +11,7 @@ struct DynamicRenderDataList;
typedef void (*DynamicRender)(void* data, struct DynamicRenderDataList* renderList, struct RenderState* renderState);
typedef void (*DynamicViewRender)(void* data, struct RenderScene* renderScene, struct Transform* fromView);
#define MAX_DYNAMIC_SCENE_OBJECTS 32
#define MAX_DYNAMIC_SCENE_OBJECTS 64
#define MAX_VIEW_DEPENDANT_OBJECTS 8
#define DYNAMIC_SCENE_OBJECT_FLAGS_USED (1 << 0)
@ -25,7 +25,7 @@ typedef void (*DynamicViewRender)(void* data, struct RenderScene* renderScene, s
struct DynamicSceneObject {
void* data;
DynamicRender renderCallback;
struct Transform* transform;
struct Vector3* position;
float scaledRadius;
u16 flags;
u64 roomFlags;
@ -34,7 +34,7 @@ struct DynamicSceneObject {
struct DynamicSceneViewDependantObject {
void* data;
DynamicViewRender renderCallback;
struct Transform* transform;
struct Vector3* position;
float scaledRadius;
u16 flags;
u64 roomFlags;
@ -47,8 +47,8 @@ struct DynamicScene {
void dynamicSceneInit();
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform* transform, float radius);
int dynamicSceneAddViewDependant(void* data, DynamicViewRender renderCallback, struct Transform* transform, float radius);
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Vector3* position, float radius);
int dynamicSceneAddViewDependant(void* data, DynamicViewRender renderCallback, struct Vector3* position, float radius);
void dynamicSceneRemove(int id);
void dynamicSceneSetFlags(int id, int flags);
void dynamicSceneClearFlags(int id, int flags);

View file

@ -15,7 +15,7 @@
#include "../../build/assets/materials/static.h"
#define AUTO_OPEN_DISTANCE 4.0f
#define INSIDE_DISTANCE 1.0f
#define INSIDE_DISTANCE 1.2f
#define SAME_LEVEL_HEIGHT 3.0f
#define OPEN_SPEED 2.0f
@ -95,7 +95,7 @@ void elevatorInit(struct Elevator* elevator, struct ElevatorDefinition* elevator
collisionObjectUpdateBB(&elevator->collisionObject);
elevator->dynamicId = dynamicSceneAdd(elevator, elevatorRender, &elevator->rigidBody.transform, 3.9f);
elevator->dynamicId = dynamicSceneAdd(elevator, elevatorRender, &elevator->rigidBody.transform.position, 3.9f);
elevator->flags = elevatorDefinition->targetElevator == -1 ? ElevatorFlagsIsExit : 0;
elevator->openAmount = 0.0f;
elevator->roomIndex = elevatorDefinition->roomIndex;

View file

@ -152,7 +152,7 @@ void fizzlerInit(struct Fizzler* fizzler, struct Transform* transform, float wid
}
fizzler->oldestParticleIndex = 0;
fizzler->dynamicId = dynamicSceneAdd(fizzler, fizzlerRender, &fizzler->rigidBody.transform, sqrtf(width * width + height * height) * 0.5f);
fizzler->dynamicId = dynamicSceneAdd(fizzler, fizzlerRender, &fizzler->rigidBody.transform.position, sqrtf(width * width + height * height) * 0.5f);
dynamicSceneSetRoomFlags(fizzler->dynamicId, ROOM_FLAG_FROM_INDEX(room));
}

View file

@ -62,7 +62,7 @@ void pedestalInit(struct Pedestal* pedestal, struct PedestalDefinition* definiti
skAnimatorInit(&pedestal->animator, PEDESTAL_DEFAULT_BONES_COUNT);
pedestal->dynamicId = dynamicSceneAdd(pedestal, pedestalRender, &pedestal->transform, 0.8f);
pedestal->dynamicId = dynamicSceneAdd(pedestal, pedestalRender, &pedestal->transform.position, 0.8f);
dynamicSceneSetRoomFlags(pedestal->dynamicId, ROOM_FLAG_FROM_INDEX(definition->roomIndex));

View file

@ -15,6 +15,7 @@
enum PortalFlags {
PortalFlagsOddParity = (1 << 0),
PortalFlagsNeedsNewHole = (1 << 1),
PortalFlagsPlayerPortal = (1 << 2),
};
struct Portal {

View file

@ -18,6 +18,7 @@
#include "../physics/collision_scene.h"
#include "../levels/static_render.h"
#include "../levels/levels.h"
#include "../levels/checkpoint.h"
#include "../scene/portal_surface.h"
#include "../math/mathf.h"
#include "./hud.h"
@ -36,6 +37,9 @@ struct Vector3 gPortalGunUp = {0.0f, 1.0f, 0.0f};
Lights1 gSceneLights = gdSPDefLights1(128, 128, 128, 128, 128, 128, 0, 127, 0);
#define LEVEL_INDEX_WITH_GUN_0 2
#define LEVEL_INDEX_WITH_GUN_1 8
void sceneUpdateListeners(struct Scene* scene);
void sceneInitDynamicColliders(struct Scene* scene) {
@ -77,6 +81,14 @@ void sceneInit(struct Scene* scene) {
playerInit(&scene->player, &combinedLocation, &startVelocity);
sceneUpdateListeners(scene);
if (gCurrentLevelIndex >= LEVEL_INDEX_WITH_GUN_0) {
playerGivePortalGun(&scene->player, PlayerHasFirstPortalGun);
}
if (gCurrentLevelIndex >= LEVEL_INDEX_WITH_GUN_1) {
playerGivePortalGun(&scene->player, PlayerHasSecondPortalGun);
}
portalInit(&scene->portals[0], 0);
portalInit(&scene->portals[1], PortalFlagsOddParity);
@ -147,6 +159,8 @@ void sceneInit(struct Scene* scene) {
switchInit(&scene->switches[i], &gCurrentLevel->switches[i]);
}
ballBurnMarkInit();
scene->ballLancherCount = gCurrentLevel->ballLauncherCount;
scene->ballLaunchers = malloc(sizeof(struct BallLauncher) * scene->ballLancherCount);
for (int i = 0; i < scene->ballLancherCount; ++i) {
@ -257,18 +271,22 @@ void sceneCheckPortals(struct Scene* scene) {
quatMultVector(&scene->player.lookTransform.rotation, &gUp, &playerUp);
if (controllerGetButtonDown(0, Z_TRIG) && (scene->player.flags & PlayerHasSecondPortalGun)) {
sceneFirePortal(scene, &raycastRay, &playerUp, 0, scene->player.body.currentRoom);
sceneFirePortal(scene, &raycastRay, &playerUp, 0, scene->player.body.currentRoom, 1);
soundPlayerPlay(soundsPortalgunShoot[0], 1.0f, 1.0f, NULL);
}
if (controllerGetButtonDown(0, R_TRIG | L_TRIG) && (scene->player.flags & PlayerHasFirstPortalGun)) {
sceneFirePortal(scene, &raycastRay, &playerUp, 1, scene->player.body.currentRoom);
sceneFirePortal(scene, &raycastRay, &playerUp, 1, scene->player.body.currentRoom, 1);
soundPlayerPlay(soundsPortalgunShoot[1], 1.0f, 1.0f, NULL);
}
if (scene->player.body.flags & RigidBodyFizzled) {
sceneClosePortal(scene, 0);
sceneClosePortal(scene, 1);
if (scene->portals[0].flags & PortalFlagsPlayerPortal) {
sceneClosePortal(scene, 0);
}
if (scene->portals[1].flags & PortalFlagsPlayerPortal) {
sceneClosePortal(scene, 1);
}
scene->player.body.flags &= ~RigidBodyFizzled;
}
@ -437,6 +455,9 @@ void sceneUpdate(struct Scene* scene) {
&gZeroVec,
scene->elevators[teleportTo].roomIndex
);
checkpointSave(&gScene);
sceneClosePortal(&gScene, 0);
sceneClosePortal(&gScene, 1);
}
}
}
@ -508,7 +529,7 @@ void sceneUpdate(struct Scene* scene) {
}
}
int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformIndex, int portalIndex, struct PortalSurfaceMappingRange surfaceMapping, struct CollisionObject* collisionObject, int roomIndex) {
int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformIndex, int portalIndex, struct PortalSurfaceMappingRange surfaceMapping, struct CollisionObject* collisionObject, int roomIndex, int fromPlayer) {
struct Transform finalAt;
struct Transform relativeToTransform;
@ -547,12 +568,19 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformInde
gCollisionScene.portalTransforms[portalIndex] = &portal->transform;
gCollisionScene.portalRooms[portalIndex] = roomIndex;
if (fromPlayer) {
portal->flags |= PortalFlagsPlayerPortal;
} else {
portal->flags &= ~PortalFlagsPlayerPortal;
}
if (collisionSceneIsPortalOpen()) {
// the second portal is fully transparent right away
portal->opacity = 0.0f;
}
contactSolverCheckPortalContacts(&gContactSolver, collisionObject);
ballBurnFilterOnPortal(&portal->transform, portalIndex);
return 1;
}
}
@ -588,7 +616,7 @@ int sceneDetermineSurfaceMapping(struct Scene* scene, struct CollisionObject* hi
return 0;
}
int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* playerUp, int portalIndex, int roomIndex) {
int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* playerUp, int portalIndex, int roomIndex, int fromPlayer) {
struct RaycastHit hit;
if (!collisionSceneRaycast(&gCollisionScene, roomIndex, ray, COLLISION_LAYERS_STATIC | COLLISION_LAYERS_BLOCK_PORTAL, 1000000.0f, 0, &hit)) {
@ -626,7 +654,7 @@ int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* player
quatLook(&hitDirection, &upDir, &portalLocation.rotation);
}
return sceneOpenPortal(scene, &portalLocation, relativeIndex, portalIndex, mappingRange, hit.object, hit.roomIndex);
return sceneOpenPortal(scene, &portalLocation, relativeIndex, portalIndex, mappingRange, hit.object, hit.roomIndex, fromPlayer);
}
void sceneClosePortal(struct Scene* scene, int portalIndex) {

View file

@ -63,7 +63,7 @@ void sceneInit(struct Scene* scene);
void sceneRender(struct Scene* scene, struct RenderState* renderState, struct GraphicsTask* task);
void sceneUpdate(struct Scene* scene);
int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* playerUp, int portalIndex, int roomIndex);
int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* playerUp, int portalIndex, int roomIndex, int fromPlayer);
void sceneClosePortal(struct Scene* scene, int portalIndex);
#endif

View file

@ -143,7 +143,7 @@ void signageInit(struct Signage* signage, struct SignageDefinition* definition)
signage->roomIndex = definition->roomIndex;
signage->testChamberNumber = definition->testChamberNumber;
int dynamicId = dynamicSceneAdd(signage, signageRender, &signage->transform, 1.7f);
int dynamicId = dynamicSceneAdd(signage, signageRender, &signage->transform.position, 1.7f);
dynamicSceneSetRoomFlags(dynamicId, ROOM_FLAG_FROM_INDEX(definition->roomIndex));
}

View file

@ -81,7 +81,7 @@ void switchInit(struct Switch* switchObj, struct SwitchDefinition* definition) {
collisionObjectUpdateBB(&switchObj->collisionObject);
switchObj->dynamicId = dynamicSceneAdd(switchObj, switchRender, &switchObj->rigidBody.transform, COLLIDER_HEIGHT * 0.5f);
switchObj->dynamicId = dynamicSceneAdd(switchObj, switchRender, &switchObj->rigidBody.transform.position, COLLIDER_HEIGHT * 0.5f);
switchObj->signalIndex = definition->signalIndex;
dynamicSceneSetRoomFlags(switchObj->dynamicId, ROOM_FLAG_FROM_INDEX(switchObj->rigidBody.currentRoom));