diff --git a/src/scene/portal_gun.c b/src/scene/portal_gun.c index 664189d..6178d0e 100644 --- a/src/scene/portal_gun.c +++ b/src/scene/portal_gun.c @@ -2,6 +2,7 @@ #include "../physics/collision_scene.h" #include "../physics/collision_cylinder.h" +#include "./scene.h" #include "../effects/effect_definitions.h" @@ -163,7 +164,18 @@ void portalGunUpdate(struct PortalGun* portalGun, struct Player* player) { struct RaycastHit hit; if (collisionSceneRaycast(&gCollisionScene, projectile->roomIndex, &projectile->positionDirection, COLLISION_LAYERS_STATIC | COLLISION_LAYERS_BLOCK_PORTAL, PORTAL_PROJECTILE_SPEED * FIXED_DELTA_TIME + 0.1f, 0, &hit)) { - // TODO open portal + if (!sceneOpenPortalFromHit( + &gScene, + &projectile->positionDirection, + &hit, + &projectile->playerUp, + i, + projectile->roomIndex, + 1, + 0 + )) { + effectsSplashPlay(&gScene.effects, &gFailPortalSplash[i], &hit.at, &hit.normal); + } projectile->roomIndex = -1; } else { projectile->roomIndex = hit.roomIndex; diff --git a/src/scene/scene.c b/src/scene/scene.c index 6c56949..e3079ea 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -352,7 +352,6 @@ void sceneCheckPortals(struct Scene* scene) { } if (fireOrange && hasOrange && !playerIsGrabbing(&scene->player)) { - sceneFirePortal(scene, &raycastRay, &playerUp, 0, scene->player.body.currentRoom, 1, 0); portalGunFire(&scene->portalGun, 0, &raycastRay, &playerUp, scene->player.body.currentRoom); scene->player.flags |= PlayerJustShotPortalGun; scene->last_portal_indx_shot=0; @@ -360,7 +359,6 @@ void sceneCheckPortals(struct Scene* scene) { } if ((fireBlue || (!hasOrange && fireOrange)) && hasBlue && !playerIsGrabbing(&scene->player)) { - sceneFirePortal(scene, &raycastRay, &playerUp, 1, scene->player.body.currentRoom, 1, 0); portalGunFire(&scene->portalGun, 1, &raycastRay, &playerUp, scene->player.body.currentRoom); scene->player.flags |= PlayerJustShotPortalGun; scene->last_portal_indx_shot=1; @@ -882,6 +880,56 @@ int sceneDetermineSurfaceMapping(struct Scene* scene, struct CollisionObject* hi return 0; } +int sceneOpenPortalFromHit(struct Scene* scene, struct Ray* ray, struct RaycastHit* hit, struct Vector3* playerUp, int portalIndex, int roomIndex, int fromPlayer, int just_checking) { + struct PortalSurfaceMappingRange mappingRange; + int relativeIndex = NO_TRANSFORM_INDEX; + + if (!sceneDetermineSurfaceMapping(scene, hit->object, &mappingRange, &relativeIndex)) { + return 0; + } + + struct Transform portalLocation; + + struct Vector3 hitDirection = hit->normal; + + if (portalIndex == 1) { + vector3Negate(&hitDirection, &hitDirection); + } + + portalLocation.position = hit->at; + portalLocation.scale = gOneVec; + if (fabsf(hit->normal.y) < 0.8) { + quatLook(&hitDirection, &gUp, &portalLocation.rotation); + } else { + struct Vector3 upDir; + + if (ray->dir.y > 0.0f) { + vector3Negate(playerUp, &upDir); + } else { + upDir = *playerUp; + } + + quatLook(&hitDirection, &upDir, &portalLocation.rotation); + } + + if (!sceneOpenPortal(scene, &portalLocation, relativeIndex, portalIndex, mappingRange, hit->object, hit->roomIndex, fromPlayer, just_checking)) { + if (!fromPlayer) { + sceneClosePortal(scene, 1-portalIndex); + scene->continuouslyAttemptingPortalOpen = 1; + scene->savedPortal.portalIndex = portalIndex; + scene->savedPortal.ray = *ray; + scene->savedPortal.roomIndex = roomIndex; + scene->savedPortal.transformUp = *playerUp; + } + + return 0; + } + if (!fromPlayer){ + scene->continuouslyAttemptingPortalOpen = 0; + } + return 1; +} + int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* playerUp, int portalIndex, int roomIndex, int fromPlayer, int just_checking) { struct RaycastHit hit; diff --git a/src/scene/scene.h b/src/scene/scene.h index 5f49913..334f532 100644 --- a/src/scene/scene.h +++ b/src/scene/scene.h @@ -100,6 +100,7 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr void sceneUpdate(struct Scene* scene); void sceneQueueCheckpoint(struct Scene* scene); +int sceneOpenPortalFromHit(struct Scene* scene, struct Ray* ray, struct RaycastHit* hit, struct Vector3* playerUp, int portalIndex, int roomIndex, int fromPlayer, int just_checking); int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* playerUp, int portalIndex, int roomIndex, int fromPlayer, int just_checking); void sceneClosePortal(struct Scene* scene, int portalIndex);