CStructure* CStructure::CreateStructure(structure_type eType, CSPPlayer* pOwner, CSpire* pSpire, const CScalableVector& vecOrigin) { CStructure* pStructure = nullptr; switch (eType) { default: case STRUCTURE_NONE: TAssert(false); return nullptr; case STRUCTURE_SPIRE: pStructure = GameServer()->Create<CSpire>("CSpire"); break; case STRUCTURE_MINE: pStructure = GameServer()->Create<CMine>("CMine"); break; case STRUCTURE_PALLET: pStructure = GameServer()->Create<CPallet>("CPallet"); break; case STRUCTURE_STOVE: pStructure = GameServer()->Create<CStove>("CStove"); break; } pStructure->GameData().SetPlayerOwner(pOwner->GetPlayerCharacter()->GameData().GetPlayerOwner()); pStructure->GameData().SetPlanet(pOwner->GetPlayerCharacter()->GameData().GetPlanet()); pStructure->SetOwner(pOwner); pStructure->SetSpire(pSpire); pStructure->SetGlobalOrigin(pOwner->GetPlayerCharacter()->GameData().GetPlanet()->GetGlobalOrigin()); // Avoid floating point precision problems pStructure->SetMoveParent(pOwner->GetPlayerCharacter()->GameData().GetPlanet()); pStructure->SetLocalOrigin(vecOrigin); if (pStructure->GameData().GetPlanet()) { Vector vecUp = pStructure->GetLocalOrigin().Normalized(); Matrix4x4 mDirection; mDirection.SetUpVector(vecUp); mDirection.SetForwardVector(vecUp.Cross(pOwner->GetPlayerCharacter()->GetLocalTransform().GetRightVector()).Normalized()); mDirection.SetRightVector(mDirection.GetForwardVector().Cross(vecUp).Normalized()); pStructure->SetLocalAngles(mDirection.GetAngles()); } pStructure->AddToPhysics(CT_STATIC_MESH); pStructure->PostConstruction(); return pStructure; }
void CSPCharacter::LockViewToPlanet() { // Now lock the roll value to the planet. CPlanet* pNearestPlanet = GetNearestPlanet(); if (!pNearestPlanet) return; Matrix4x4 mGlobalRotation = GetGlobalTransform(); mGlobalRotation.SetTranslation(CScalableVector()); // Construct a "local space" for the planet Vector vecPlanetUp = GetUpVector(); Vector vecPlanetForward = mGlobalRotation.GetForwardVector(); Vector vecPlanetRight = vecPlanetForward.Cross(vecPlanetUp).Normalized(); vecPlanetForward = vecPlanetUp.Cross(vecPlanetRight).Normalized(); Matrix4x4 mPlanet(vecPlanetForward, vecPlanetUp, vecPlanetRight); Matrix4x4 mPlanetInverse = mPlanet; mPlanetInverse.InvertTR(); // Bring our current view angles into that local space Matrix4x4 mLocalRotation = mPlanetInverse * mGlobalRotation; EAngle angLocalRotation = mLocalRotation.GetAngles(); // Lock them so that the roll is 0 // I'm sure there's a way to do this without converting to euler but at this point I don't care. angLocalRotation.r = 0; Matrix4x4 mLockedLocalRotation; mLockedLocalRotation.SetAngles(angLocalRotation); // Bring it back out to global space Matrix4x4 mLockedRotation = mPlanet * mLockedLocalRotation; // Only use the changed r value to avoid floating point crap EAngle angNewLockedRotation = GetGlobalAngles(); EAngle angOverloadRotation = mLockedRotation.GetAngles(); // Lerp our way there float flTimeToLocked = 1; if (GameServer()->GetGameTime() - m_flLastEnteredAtmosphere > flTimeToLocked) angNewLockedRotation.r = angOverloadRotation.r; else angNewLockedRotation.r = RemapValClamped(SLerp(GameServer()->GetGameTime() - m_flLastEnteredAtmosphere, 0.3f), 0, flTimeToLocked, m_flRollFromSpace, angOverloadRotation.r); SetGlobalAngles(angNewLockedRotation); }
void CCharacterController::CharacterMovement(btCollisionWorld* pCollisionWorld, btScalar deltaTime) { // Grab the new player transform before doing movement steps in case the player has been moved, // such as by a platform or teleported. No need to do a physics trace for it, the penetration // functions should handle that. btTransform mCharacter; CPhysicsEntity* pPhysicsEntity = static_cast<CBulletPhysics*>(GamePhysics())->GetPhysicsEntity(m_hEntity); pPhysicsEntity->m_oMotionState.getWorldTransform(mCharacter); #ifdef _DEBUG Matrix4x4 mTest; mCharacter.getOpenGLMatrix(mTest); TAssert(mTest.GetForwardVector().Cross(mTest.GetLeftVector()).Equals(mTest.GetUpVector(), 0.001f)); TAssert(mTest.GetUpVector().Equals(m_hEntity->GetUpVector(), 0.001f)); #endif m_pGhostObject->setWorldTransform(mCharacter); PreStep(pCollisionWorld); if (m_hEntity->IsFlying()) PlayerFly(pCollisionWorld, deltaTime); else if (!m_hEntity->GetGroundEntity()) PlayerFall(pCollisionWorld, deltaTime); else PlayerWalk(pCollisionWorld, deltaTime); FindGround(pCollisionWorld); btVector3 vecOrigin = m_pGhostObject->getWorldTransform().getOrigin(); TAssert(vecOrigin.x() < 999999); TAssert(vecOrigin.x() > -999999); TAssert(vecOrigin.y() < 999999); TAssert(vecOrigin.y() > -999999); TAssert(vecOrigin.z() < 999999); TAssert(vecOrigin.z() > -999999); if ((mCharacter.getOrigin() - vecOrigin).length2() > 0.0001f) pPhysicsEntity->m_oMotionState.setWorldTransform(m_pGhostObject->getWorldTransform()); }