Player can hold objects through portals recursively
- fixed a bug where security camera was not updating its PLAYER_STANDING flag - added a new parameter numPortalsPassed to collisionSceneRaycast to indicate how many portals the raycast went through, if any - altered all player code involving the grabbingThroughPortal variable - grabbingThroughPortal is now: 0 if not grabbing through portal, >0 if grabbing through portal 0, <0 if grabbing through portal 1. - objects are dropped when they are being held through a portal and the player no longer has line of sight to them.
This commit is contained in:
parent
02237dcfb3
commit
4bacaa9607
|
@ -423,7 +423,7 @@ int collisionSceneRaycastOnlyDynamic(struct CollisionScene* scene, struct Ray* r
|
|||
return hit->distance != maxDistance;
|
||||
}
|
||||
|
||||
int collisionSceneRaycast(struct CollisionScene* scene, int roomIndex, struct Ray* ray, int collisionLayers, float maxDistance, int passThroughPortals, struct RaycastHit* hit) {
|
||||
int collisionSceneRaycast(struct CollisionScene* scene, int roomIndex, struct Ray* ray, int collisionLayers, float maxDistance, int passThroughPortals, struct RaycastHit* hit, short* numPortalsPassed) {
|
||||
hit->distance = maxDistance;
|
||||
hit->throughPortal = NULL;
|
||||
hit->roomIndex = roomIndex;
|
||||
|
@ -458,6 +458,12 @@ int collisionSceneRaycast(struct CollisionScene* scene, int roomIndex, struct Ra
|
|||
collisionSceneIsPortalOpen()) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (collisionSceneIsTouchingSinglePortal(&hit->at, &hit->normal, gCollisionScene.portalTransforms[i], i)) {
|
||||
if (i == 0){
|
||||
*numPortalsPassed += 1;
|
||||
}else{
|
||||
*numPortalsPassed -= 1;
|
||||
}
|
||||
|
||||
struct Transform portalTransform;
|
||||
collisionSceneGetPortalTransform(i, &portalTransform);
|
||||
|
||||
|
@ -468,7 +474,7 @@ int collisionSceneRaycast(struct CollisionScene* scene, int roomIndex, struct Ra
|
|||
|
||||
struct RaycastHit newHit;
|
||||
|
||||
int result = collisionSceneRaycast(scene, gCollisionScene.portalRooms[1 - i], &newRay, collisionLayers, maxDistance - hit->distance, 0, &newHit);
|
||||
int result = collisionSceneRaycast(scene, gCollisionScene.portalRooms[1 - i], &newRay, collisionLayers, maxDistance - hit->distance, passThroughPortals, &newHit, numPortalsPassed);
|
||||
|
||||
if (result) {
|
||||
newHit.distance += hit->distance;
|
||||
|
|
|
@ -44,7 +44,7 @@ struct Transform* collisionSceneTransformToPortal(int fromPortal);
|
|||
|
||||
void collisionScenePushObjectsOutOfPortal(int portalIndex);
|
||||
|
||||
int collisionSceneRaycast(struct CollisionScene* scene, int roomIndex, struct Ray* ray, int collisionLayers, float maxDistance, int passThroughPortals, struct RaycastHit* hit);
|
||||
int collisionSceneRaycast(struct CollisionScene* scene, int roomIndex, struct Ray* ray, int collisionLayers, float maxDistance, int passThroughPortals, struct RaycastHit* hit, short* numPortalsPassed);
|
||||
int collisionSceneRaycastOnlyDynamic(struct CollisionScene* scene, struct Ray* ray, int collisionLayers, float maxDistance, struct RaycastHit* hit);
|
||||
|
||||
void collisionSceneGetPortalTransform(int fromPortal, struct Transform* out);
|
||||
|
|
|
@ -234,16 +234,18 @@ void playerHandleCollision(struct Player* player) {
|
|||
}
|
||||
|
||||
void playerApplyPortalGrab(struct Player* player, int portalIndex) {
|
||||
if (player->grabbingThroughPortal == PLAYER_GRABBING_THROUGH_NOTHING) {
|
||||
player->grabbingThroughPortal = portalIndex;
|
||||
} else if (player->grabbingThroughPortal != portalIndex) {
|
||||
player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING;
|
||||
if (portalIndex){
|
||||
player->grabbingThroughPortal -= 1;
|
||||
}else{
|
||||
player->grabbingThroughPortal += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void playerSetGrabbing(struct Player* player, struct CollisionObject* grabbing) {
|
||||
if (grabbing && grabbing->flags & COLLISION_OBJECT_PLAYER_STANDING){
|
||||
player->grabConstraint.object = NULL;
|
||||
contactSolverRemovePointConstraint(&gContactSolver, &player->grabConstraint);
|
||||
player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING;
|
||||
}
|
||||
else if (grabbing && !player->grabConstraint.object) {
|
||||
pointConstraintInit(&player->grabConstraint, grabbing, 8.0f, 5.0f, 1.0f);
|
||||
|
@ -253,6 +255,7 @@ void playerSetGrabbing(struct Player* player, struct CollisionObject* grabbing)
|
|||
player->grabConstraint.object = NULL;
|
||||
contactSolverRemovePointConstraint(&gContactSolver, &player->grabConstraint);
|
||||
hudResolvePrompt(&gScene.hud, CutscenePromptTypeDrop);
|
||||
player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING;
|
||||
} else if (grabbing != player->grabConstraint.object) {
|
||||
pointConstraintInit(&player->grabConstraint, grabbing, 8.0f, 5.0f, 1.0f);
|
||||
}
|
||||
|
@ -290,7 +293,7 @@ int playerIsGrabbing(struct Player* player) {
|
|||
return player->grabConstraint.object != NULL;
|
||||
}
|
||||
|
||||
int playerRaycastGrab(struct Player* player, struct RaycastHit* hit, int checkPastObject) {
|
||||
int playerRaycastGrab(struct Player* player, struct RaycastHit* hit, int checkPastObject, short* numPortalsPassed) {
|
||||
struct Ray ray;
|
||||
|
||||
ray.origin = player->lookTransform.position;
|
||||
|
@ -303,11 +306,11 @@ int playerRaycastGrab(struct Player* player, struct RaycastHit* hit, int checkPa
|
|||
if (checkPastObject){
|
||||
short prevCollisionLayers = player->grabConstraint.object->collisionLayers;
|
||||
player->grabConstraint.object->collisionLayers = 0;
|
||||
result = collisionSceneRaycast(&gCollisionScene, player->body.currentRoom, &ray, COLLISION_LAYERS_TANGIBLE, GRAB_RAYCAST_DISTANCE, 1, hit);
|
||||
result = collisionSceneRaycast(&gCollisionScene, player->body.currentRoom, &ray, COLLISION_LAYERS_TANGIBLE, GRAB_RAYCAST_DISTANCE, 1, hit, numPortalsPassed);
|
||||
player->grabConstraint.object->collisionLayers = prevCollisionLayers;
|
||||
}
|
||||
else{
|
||||
result = collisionSceneRaycast(&gCollisionScene, player->body.currentRoom, &ray, COLLISION_LAYERS_GRABBABLE | COLLISION_LAYERS_TANGIBLE, GRAB_RAYCAST_DISTANCE, 1, hit);
|
||||
result = collisionSceneRaycast(&gCollisionScene, player->body.currentRoom, &ray, COLLISION_LAYERS_GRABBABLE | COLLISION_LAYERS_TANGIBLE, GRAB_RAYCAST_DISTANCE, 1, hit, numPortalsPassed);
|
||||
}
|
||||
|
||||
player->collisionObject.collisionLayers = PLAYER_COLLISION_LAYERS;
|
||||
|
@ -325,19 +328,15 @@ void playerUpdateGrabbedObject(struct Player* player) {
|
|||
playerSetGrabbing(player, NULL);
|
||||
} else {
|
||||
struct RaycastHit hit;
|
||||
short numPortalsPassed = 0;
|
||||
|
||||
if (playerRaycastGrab(player, &hit, 0)) {
|
||||
if (playerRaycastGrab(player, &hit, 0, &numPortalsPassed)) {
|
||||
hit.object->flags |= COLLISION_OBJECT_INTERACTED;
|
||||
|
||||
if (hit.object->body && (hit.object->body->flags & RigidBodyFlagsGrabbable)) {
|
||||
if (hit.object->body && (hit.object->body->flags & RigidBodyFlagsGrabbable) && !(hit.object->flags & COLLISION_OBJECT_PLAYER_STANDING)) {
|
||||
playerSetGrabbing(player, hit.object);
|
||||
player->flags |= PlayerJustSelect;
|
||||
|
||||
if (hit.throughPortal) {
|
||||
player->grabbingThroughPortal = hit.throughPortal == gCollisionScene.portalTransforms[0] ? 0 : 1;
|
||||
} else {
|
||||
player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING;
|
||||
}
|
||||
player->grabbingThroughPortal = numPortalsPassed;
|
||||
}
|
||||
else if ((hit.object->body)){
|
||||
player->flags |= PlayerJustSelect;
|
||||
|
@ -357,6 +356,18 @@ void playerUpdateGrabbedObject(struct Player* player) {
|
|||
playerSetGrabbing(player, NULL);
|
||||
}
|
||||
|
||||
// if the object is being held through a portal and can no longer be seen, drop it.
|
||||
if (player->grabConstraint.object && player->grabbingThroughPortal){
|
||||
struct RaycastHit testhit;
|
||||
short testnumPortalsPassed = 0;
|
||||
if (playerRaycastGrab(player, &testhit, 0, &testnumPortalsPassed)){
|
||||
if ((testnumPortalsPassed != player->grabbingThroughPortal) && (testhit.object != player->grabConstraint.object)){
|
||||
playerSetGrabbing(player, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (player->grabConstraint.object) {
|
||||
if (player->body.flags & RigidBodyFlagsCrossedPortal0) {
|
||||
playerApplyPortalGrab(player, 1);
|
||||
|
@ -380,7 +391,8 @@ void playerUpdateGrabbedObject(struct Player* player) {
|
|||
// try to determine how far away to set the grab dist
|
||||
struct RaycastHit hit;
|
||||
struct Vector3 temp_grab_dist = gGrabDistance;
|
||||
if (playerRaycastGrab(player, &hit, 1)){
|
||||
short unused = 0;
|
||||
if (playerRaycastGrab(player, &hit, 1, &unused)){
|
||||
float dist = hit.distance;
|
||||
temp_grab_dist.z = maxf(((-1.0f*fabsf(dist))+0.2f), gGrabDistance.z);
|
||||
temp_grab_dist.z = minf(temp_grab_dist.z, -0.2f);
|
||||
|
@ -401,12 +413,14 @@ void playerUpdateGrabbedObject(struct Player* player) {
|
|||
}
|
||||
|
||||
struct Transform pointTransform;
|
||||
collisionSceneGetPortalTransform(player->grabbingThroughPortal, &pointTransform);
|
||||
collisionSceneGetPortalTransform(player->grabbingThroughPortal > 0 ? 0 : 1, &pointTransform);
|
||||
|
||||
transformPoint(&pointTransform, &grabPoint, &grabPoint);
|
||||
struct Quaternion finalRotation;
|
||||
quatMultiply(&pointTransform.rotation, &grabRotation, &finalRotation);
|
||||
grabRotation = finalRotation;
|
||||
for (int i = 0; i < abs(player->grabbingThroughPortal); ++i) {
|
||||
transformPoint(&pointTransform, &grabPoint, &grabPoint);
|
||||
struct Quaternion finalRotation;
|
||||
quatMultiply(&pointTransform.rotation, &grabRotation, &finalRotation);
|
||||
grabRotation = finalRotation;
|
||||
}
|
||||
}
|
||||
|
||||
pointConstraintUpdateTarget(&player->grabConstraint, &grabPoint, &grabRotation);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "../sk64/skelatool_armature.h"
|
||||
#include "../physics/point_constraint.h"
|
||||
|
||||
#define PLAYER_GRABBING_THROUGH_NOTHING -1
|
||||
#define PLAYER_GRABBING_THROUGH_NOTHING 0
|
||||
|
||||
#define PLAYER_HEAD_HEIGHT 1.0f
|
||||
|
||||
|
|
|
@ -212,8 +212,9 @@ void portalGunUpdate(struct PortalGun* portalGun, struct Player* player) {
|
|||
}
|
||||
|
||||
struct RaycastHit hit;
|
||||
short numPortalsPassed;
|
||||
|
||||
if (collisionSceneRaycast(&gCollisionScene, projectile->roomIndex, &projectile->positionDirection, COLLISION_LAYERS_STATIC | COLLISION_LAYERS_BLOCK_PORTAL, PORTAL_PROJECTILE_SPEED * FIXED_DELTA_TIME + 0.1f, 0, &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, &numPortalsPassed)) {
|
||||
if (!sceneOpenPortalFromHit(
|
||||
&gScene,
|
||||
&projectile->positionDirection,
|
||||
|
@ -247,8 +248,9 @@ void portalGunFire(struct PortalGun* portalGun, int portalIndex, struct Ray* ray
|
|||
struct PortalGunProjectile* projectile = &portalGun->projectiles[portalIndex];
|
||||
|
||||
struct RaycastHit hit;
|
||||
short numPortalsPassed;
|
||||
|
||||
if (!collisionSceneRaycast(&gCollisionScene, roomIndex, ray, COLLISION_LAYERS_STATIC | COLLISION_LAYERS_BLOCK_PORTAL, 1000000.0f, 0, &hit)) {
|
||||
if (!collisionSceneRaycast(&gCollisionScene, roomIndex, ray, COLLISION_LAYERS_STATIC | COLLISION_LAYERS_BLOCK_PORTAL, 1000000.0f, 0, &hit, &numPortalsPassed)) {
|
||||
vector3AddScaled(&ray->origin, &ray->dir, NO_HIT_DISTANCE, &hit.at);
|
||||
hit.distance = NO_HIT_DISTANCE;
|
||||
hit.normal = gZeroVec;
|
||||
|
|
|
@ -939,8 +939,9 @@ int sceneOpenPortalFromHit(struct Scene* scene, struct Ray* ray, struct RaycastH
|
|||
|
||||
int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* playerUp, int portalIndex, int roomIndex, int fromPlayer, int just_checking) {
|
||||
struct RaycastHit hit;
|
||||
short numPortalsPassed;
|
||||
|
||||
if (!collisionSceneRaycast(&gCollisionScene, roomIndex, ray, COLLISION_LAYERS_STATIC | COLLISION_LAYERS_BLOCK_PORTAL, 1000000.0f, 0, &hit)) {
|
||||
if (!collisionSceneRaycast(&gCollisionScene, roomIndex, ray, COLLISION_LAYERS_STATIC | COLLISION_LAYERS_BLOCK_PORTAL, 1000000.0f, 0, &hit, &numPortalsPassed)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,9 @@ void securityCameraInit(struct SecurityCamera* securityCamera, struct SecurityCa
|
|||
}
|
||||
|
||||
void securityCameraUpdate(struct SecurityCamera* securityCamera) {
|
||||
if (securityCamera->collisionObject.flags & COLLISION_OBJECT_PLAYER_STANDING) {
|
||||
securityCamera->collisionObject.flags &= ~COLLISION_OBJECT_PLAYER_STANDING;
|
||||
}
|
||||
if (decorObjectUpdateFizzler(&securityCamera->collisionObject, &securityCamera->fizzleTime) == FizzleCheckResultEnd) {
|
||||
dynamicSceneRemove(securityCamera->dynamicId);
|
||||
collisionSceneRemoveDynamicObject(&securityCamera->collisionObject);
|
||||
|
|
Loading…
Reference in a new issue