diff options
Diffstat (limited to 'src/entities')
-rw-r--r-- | src/entities/Entity.cpp | 102 | ||||
-rw-r--r-- | src/entities/Entity.h | 21 | ||||
-rw-r--r-- | src/entities/Physical.cpp | 417 | ||||
-rw-r--r-- | src/entities/Physical.h | 20 |
4 files changed, 451 insertions, 109 deletions
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index b2fcfbc7..ed432e77 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -1,10 +1,10 @@ #include "common.h" -#include "VuVector.h" #include "General.h" #include "RwHelper.h" #include "ModelIndices.h" #include "Timer.h" +#include "Streaming.h" #include "Entity.h" #include "Object.h" #include "World.h" @@ -27,6 +27,12 @@ #include "Dummy.h" #include "WindModifiers.h" #include "SaveBuf.h" +#include "SpecialFX.h" +#include "VisibilityPlugins.h" +#include "RpAnimBlend.h" +#include "CutsceneMgr.h" + +//--LCS: file done except TODO for distance alpha int gBuildings; @@ -79,6 +85,11 @@ CEntity::CEntity(void) bUnderwater = false; bHasPreRenderEffects = false; + bIsTreeModel = false; + bIsVehicle = false; + bIsPed = false; + bMakeVisible = false; + m_scanCode = 0; m_modelIndex = -1; m_rwObject = nil; @@ -97,6 +108,8 @@ void CEntity::SetModelIndex(uint32 id) { m_modelIndex = id; + bIsTreeModel = IsTreeModel(m_modelIndex); + bDrawLast |= bIsTreeModel; bHasPreRenderEffects = HasPreRenderEffects(); CreateRwObject(); } @@ -105,6 +118,8 @@ void CEntity::SetModelIndexNoCreate(uint32 id) { m_modelIndex = id; + bIsTreeModel = IsTreeModel(m_modelIndex); + bDrawLast |= bIsTreeModel; bHasPreRenderEffects = HasPreRenderEffects(); } @@ -127,6 +142,7 @@ CEntity::CreateRwObject(void) else if(RwObjectGetType(m_rwObject) == rpCLUMP) GetMatrix().AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump *)m_rwObject)), false); + // useless IsTextureLoaded(); mi->AddRef(); } } @@ -183,9 +199,11 @@ CEntity::DeleteRwObject(void) if(m_rwObject){ if(RwObjectGetType(m_rwObject) == rpATOMIC){ f = RpAtomicGetFrame((RpAtomic*)m_rwObject); + CStreaming::UnregisterInstance((RpAtomic*)m_rwObject, nil); RpAtomicDestroy((RpAtomic*)m_rwObject); RwFrameDestroy(f); }else if(RwObjectGetType(m_rwObject) == rpCLUMP){ + CStreaming::UnregisterInstance((RpClump*)m_rwObject); if(IsClumpSkinned((RpClump*)m_rwObject)) RpClumpForAllAtomics((RpClump*)m_rwObject, AtomicRemoveAnimFromSkinCB, nil); RpClumpDestroy((RpClump*)m_rwObject); @@ -251,9 +269,18 @@ CEntity::UpdateRwFrame(void) RwFrameUpdateObjects((RwFrame*)rwObjectGetParent(m_rwObject)); } +bool +PauseEntityAnims(void) +{ + return CSpecialFX::bSnapShotActive; +} + void CEntity::UpdateRpHAnim(void) { + if(PauseEntityAnims()) + return; + if(IsClumpSkinned(GetClump())){ RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); RpHAnimHierarchyUpdateMatrices(hier); @@ -315,9 +342,10 @@ CEntity::PreRender(void) if(!bHasPreRenderEffects) return; + // separate function in LCS but we don't know the name switch(m_type){ case ENTITY_TYPE_BUILDING: - if(IsTreeModel(GetModelIndex())){ + if(bIsTreeModel){ float dist = (TheCamera.GetPosition() - GetPosition()).Magnitude2D(); CObject::fDistToNearestTree = Min(CObject::fDistToNearestTree, dist); ModifyMatrixForTreeInWind(); @@ -416,12 +444,53 @@ void CEntity::Render(void) { if(m_rwObject){ - bImBeingRendered = true; - if(RwObjectGetType(m_rwObject) == rpATOMIC) - RpAtomicRender((RpAtomic*)m_rwObject); - else - RpClumpRender((RpClump*)m_rwObject); - bImBeingRendered = false; +#ifdef VIS_DISTANCE_ALPHA + if(CVisibilityPlugins::GetObjectDistanceAlpha(m_rwObject) != 0) +#endif + { + // TODO(LCS): LCS does not use bImBeingRendered here, + // but that may be due to the streamed world. better keep it for safety + bImBeingRendered = true; + if(RwObjectGetType(m_rwObject) == rpATOMIC) + RpAtomicRender((RpAtomic*)m_rwObject); + else + RpClumpRender((RpClump*)m_rwObject); + bImBeingRendered = false; + } + } +} + +#ifdef VIS_DISTANCE_ALPHA +void +CEntity::UpdateDistanceFade(void) +{ + // bDistanceFade is only valid when entity is in alpha list + // but we're always checking it here, see fix in CRenderer + int alpha = CVisibilityPlugins::GetObjectDistanceAlpha(m_rwObject); + if(CCutsceneMgr::IsRunning() || TheCamera.WorldViewerBeingUsed) + alpha = 255; + else if(bDistanceFade) + alpha = Max(alpha-16, 0); + else if(alpha < 255) + alpha = Min(alpha+32, 255); + CVisibilityPlugins::SetObjectDistanceAlpha(m_rwObject, alpha); +} +#endif + +void +CEntity::UpdateAnim(void) +{ + if(PauseEntityAnims()) + return; + + if(m_rwObject && RwObjectGetType(m_rwObject) == rpCLUMP && RpAnimBlendClumpGetFirstAssociation(GetClump())) { + if (IsObject()) + RpAnimBlendClumpUpdateAnimations(GetClump(), CTimer::GetTimeStepNonClippedInSeconds()); + else { + if (!bOffscreen) + bOffscreen = !GetIsOnScreen(); + RpAnimBlendClumpUpdateAnimations(GetClump(), CTimer::GetTimeStepInSeconds(), !bOffscreen); + } } } @@ -434,6 +503,12 @@ CEntity::GetIsTouching(CVUVECTOR const ¢er, float radius) } bool +CEntity::GetIsTouching(CEntity *other) +{ + return sq(GetBoundRadius()+other->GetBoundRadius()) > (GetBoundCentre()-other->GetBoundCentre()).MagnitudeSqr(); +} + +bool CEntity::IsVisible(void) { return m_rwObject && bIsVisible && GetIsOnScreen(); @@ -634,10 +709,15 @@ CEntity::SetupBigBuilding(void) m_level = CTheZones::GetLevelFromPosition(&GetPosition()); if(mi->m_lodDistances[0] <= 2000.0f) bStreamBIGBuilding = true; - if(mi->m_lodDistances[0] > 2500.0f || mi->m_ignoreDrawDist) + if(m_modelIndex == islandLODindust || + m_modelIndex == islandLODcomInd || + m_modelIndex == islandLODcomSub || + m_modelIndex == islandLODsubInd || + m_modelIndex == islandLODsubCom || + mi->m_lodDistances[0] > 5000.0f || mi->m_ignoreDrawDist) m_level = LEVEL_GENERIC; - else if(m_level == LEVEL_GENERIC) - printf("%s isn't in a level\n", mi->GetModelName()); +// else if(m_level == LEVEL_GENERIC) +// printf("%s isn't in a level\n", mi->GetModelName()); } float WindTabel[] = { diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 957ee3bf..6f948d49 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -14,6 +14,7 @@ enum eEntityType ENTITY_TYPE_PED, ENTITY_TYPE_OBJECT, ENTITY_TYPE_DUMMY, + ENTITY_TYPE_MULTIPLAYER }; enum eEntityStatus @@ -26,6 +27,8 @@ enum eEntityStatus STATUS_WRECKED, STATUS_TRAIN_MOVING, STATUS_TRAIN_NOT_MOVING, + STATUS_FERRY_MOVING, + STATUS_FERRY_NOT_MOVING, STATUS_HELI, STATUS_PLANE, STATUS_PLAYER_REMOTE, @@ -43,6 +46,7 @@ private: uint32 m_status : 5; public: // flagsA + // LCS flagsB 02 uint32 bUsesCollision : 1; // does entity use collision uint32 bCollisionProcessed : 1; // has object been processed by a ProcessEntityCollision function uint32 bIsStatic : 1; // is entity static @@ -50,6 +54,7 @@ public: uint32 bPedPhysics : 1; uint32 bIsStuck : 1; // is entity stuck uint32 bIsInSafePosition : 1; // is entity in a collision free safe position + // LCS flagsC uint32 bUseCollisionRecords : 1; // flagsB @@ -60,6 +65,7 @@ public: uint32 bRenderScorched : 1; uint32 bHasBlip : 1; uint32 bIsBIGBuilding : 1; // Set if this entity is a big building + // LCS flagsD uint32 bStreamBIGBuilding : 1; // set when draw dist <= 2000 // flagsC @@ -70,6 +76,7 @@ public: uint32 bMeleeProof : 1; uint32 bOnlyDamagedByPlayer : 1; uint32 bStreamingDontDelete : 1; // Dont let the streaming remove this + // LCS flagsE uint32 bRemoveFromWorld : 1; // remove this entity next time it should be processed // flagsD @@ -80,6 +87,7 @@ public: uint32 bDrawLast : 1; // draw object last uint32 bNoBrightHeadLights : 1; uint32 bDoNotRender : 1; //-- only applies to CObjects apparently + // LCS flagsF uint32 bDistanceFade : 1; // Fade entity because it is far away // flagsE @@ -91,6 +99,12 @@ public: uint32 bUnderwater : 1; // this object is underwater change drawing order uint32 bHasPreRenderEffects : 1; // Object has a prerender effects attached to it + // LCS flagsG + uint32 bIsTreeModel : 1; + uint32 bIsVehicle : 1; // not sure what exactly these two are for + uint32 bIsPed : 1; + uint32 bMakeVisible : 1; + uint16 m_scanCode; uint16 m_randomSeed; int16 m_modelIndex; @@ -118,6 +132,7 @@ public: virtual void Add(void); virtual void Remove(void); + virtual bool UpdatesInCutscene(void) { return false; } virtual void SetModelIndex(uint32 id); virtual void SetModelIndexNoCreate(uint32 id); virtual void CreateRwObject(void); @@ -129,6 +144,7 @@ public: virtual void Teleport(CVector v) {} virtual void PreRender(void); virtual void Render(void); + virtual void UpdateAnim(void); virtual bool SetupLighting(void); virtual void RemoveLighting(bool); virtual void FlagToDestroyWhenNextProcessed(void) {} @@ -138,6 +154,7 @@ public: bool IsPed(void) { return m_type == ENTITY_TYPE_PED; } bool IsObject(void) { return m_type == ENTITY_TYPE_OBJECT; } bool IsDummy(void) { return m_type == ENTITY_TYPE_DUMMY; } + bool IsMultiplayer(void) { return m_type == ENTITY_TYPE_MULTIPLAYER; } RpAtomic *GetAtomic(void) { assert(RwObjectGetType(m_rwObject) == rpATOMIC); @@ -148,11 +165,15 @@ public: return (RpClump*)m_rwObject; } +#ifdef VIS_DISTANCE_ALPHA + void UpdateDistanceFade(void); +#endif void GetBoundCentre(CVUVECTOR &out); CVector GetBoundCentre(void); float GetBoundRadius(void); float GetDistanceFromCentreOfMassToBaseOfModel(void); bool GetIsTouching(CVUVECTOR const ¢er, float r); + bool GetIsTouching(CEntity *other); bool GetIsOnScreen(void); bool GetIsOnScreenComplex(void); bool IsVisible(void); diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index fb796fcd..ef306d5a 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -20,10 +20,12 @@ #include "Bike.h" #include "Pickups.h" #include "Physical.h" +#include "ColStore.h" +#include "Script.h" + +//--LCS: mostly done -#ifdef WALLCLIMB_CHEAT bool gGravityCheat; -#endif CPhysical::CPhysical(void) @@ -82,6 +84,9 @@ CPhysical::CPhysical(void) bIsFrozen = false; bDontLoadCollision = false; + + phys_lcs_unk1 = true; + phys_lcs_unk2 = 0; } CPhysical::~CPhysical(void) @@ -122,6 +127,9 @@ CPhysical::Add(void) case ENTITY_TYPE_OBJECT: list = &s->m_lists[ENTITYLIST_OBJECTS]; break; + case ENTITY_TYPE_MULTIPLAYER: + list = &s->m_lists[ENTITYLIST_MULTIPLAYER]; + break; default: assert(0); }else switch(m_type){ @@ -134,6 +142,9 @@ CPhysical::Add(void) case ENTITY_TYPE_OBJECT: list = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP]; break; + case ENTITY_TYPE_MULTIPLAYER: + list = &s->m_lists[ENTITYLIST_MULTIPLAYER]; + break; default: assert(0); } @@ -154,6 +165,37 @@ CPhysical::Remove(void) } } +static void +MoveVehicleToSafety(CVehicle* pVehicle) +{ + if (pVehicle->VehicleCreatedBy != MISSION_VEHICLE) { + CVector2D pos = LevelPos(CGame::currLevel); + int node = ThePaths.FindNodeClosestToCoors(CVector(pos.x, pos.y, 10.0f), PATH_CAR, 999999.9f, true, true); + CVector nodePos = ThePaths.FindNodeCoorsForScript(node); + float orientation = ThePaths.FindNodeOrientationForCarPlacement(node); + nodePos.x += 0.1f; + nodePos.y += 0.1f; + pVehicle->Teleport(nodePos + CVector(0.0f, 0.0f, pVehicle->GetDistanceFromCentreOfMassToBaseOfModel())); + CTheScripts::ClearSpaceForMissionEntity(nodePos, pVehicle); + pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE; + CCarCtrl::JoinCarWithRoadSystem(pVehicle); + } +} + +static void +MovePedToSafety(CPed* pPed) +{ + if (pPed->CharCreatedBy == RANDOM_CHAR) { + CVector2D pos = LevelPos(CGame::currLevel); + int node = ThePaths.FindNodeClosestToCoors(CVector(pos.x, pos.y, 10.0f), PATH_CAR, 999999.9f, true, true); + CVector nodePos = ThePaths.FindNodeCoorsForScript(node); + nodePos.x += 0.1f; + nodePos.y += 0.1f; + pPed->Teleport(nodePos + CVector(0.0f, 0.0f, pPed->GetDistanceFromCentreOfMassToBaseOfModel())); + CTheScripts::ClearSpaceForMissionEntity(nodePos, pPed); + } +} + void CPhysical::RemoveAndAdd(void) { @@ -169,10 +211,53 @@ CPhysical::RemoveAndAdd(void) ystart = CWorld::GetSectorIndexY(bounds.top); yend = CWorld::GetSectorIndexY(bounds.bottom); ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f); - assert(xstart >= 0); - assert(xend < NUMSECTORS_X); - assert(ystart >= 0); - assert(yend < NUMSECTORS_Y); + //assert(xstart >= 0); + //assert(xend < NUMSECTORS_X); + //assert(ystart >= 0); + //assert(yend < NUMSECTORS_Y); + + // this is basically a replacement for the asserts above + if (xstart < 0 || xstart >= NUMSECTORS_X || ystart < 0 || ystart >= NUMSECTORS_Y) { + printf("*****************************\n"); + printf("ENTITY GONE OUT OF WORLD! :(\n"); + printf("model id = %d\n", GetModelIndex()); + printf("type = %d\n", GetType()); + printf("bound cent = %f %f %f\n", + (GetMatrix() * GetColModel()->boundingSphere.center).x, + (GetMatrix() * GetColModel()->boundingSphere.center).y, + (GetMatrix() * GetColModel()->boundingSphere.center).z); + switch (GetType()) { + case ENTITY_TYPE_PED: + printf("ped created by = %d\n", ((CPed*)this)->CharCreatedBy); + break; + case ENTITY_TYPE_VEHICLE: + printf("vehcile created by = %d\n", ((CVehicle*)this)->VehicleCreatedBy); + break; + case ENTITY_TYPE_OBJECT: + printf("object created by = %d\n", ((CObject*)this)->ObjectCreatedBy); + break; + case ENTITY_TYPE_DUMMY: + printf("no dummy created by info\n"); + break; + default: + printf("unknown entity type to be out of world??\n"); + } + printf("*****************************\n"); + if (GetType() == ENTITY_TYPE_VEHICLE){ + MoveVehicleToSafety((CVehicle*)this); + } + else if (GetType() == ENTITY_TYPE_PED) { + CPed* pThisPed = ((CPed*)this); + if (pThisPed->bInVehicle && pThisPed->m_pMyVehicle) + MoveVehicleToSafety(pThisPed->m_pMyVehicle); + else if (GetType() == ENTITY_TYPE_PED) // why? + MovePedToSafety(pThisPed); + else + return; + } + else + return; + } // we'll try to recycle nodes from here CEntryInfoNode *next = m_entryInfoList.first; @@ -190,6 +275,9 @@ CPhysical::RemoveAndAdd(void) case ENTITY_TYPE_OBJECT: list = &s->m_lists[ENTITYLIST_OBJECTS]; break; + case ENTITY_TYPE_MULTIPLAYER: + list = &s->m_lists[ENTITYLIST_MULTIPLAYER]; + break; }else switch(m_type){ case ENTITY_TYPE_VEHICLE: list = &s->m_lists[ENTITYLIST_VEHICLES_OVERLAP]; @@ -200,6 +288,9 @@ CPhysical::RemoveAndAdd(void) case ENTITY_TYPE_OBJECT: list = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP]; break; + case ENTITY_TYPE_MULTIPLAYER: + list = &s->m_lists[ENTITYLIST_MULTIPLAYER]; + break; } if(next){ // If we still have old nodes, use them @@ -236,7 +327,7 @@ CPhysical::GetBoundRect(void) void CPhysical::AddToMovingList(void) { - if (!bIsStaticWaitingForCollision) + if (m_movingListNode == nil && !bIsStaticWaitingForCollision) m_movingListNode = CWorld::GetMovingEntityList().InsertItem(this); } @@ -334,6 +425,8 @@ CPhysical::PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phy int32 CPhysical::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) { + if(!GetIsTouching(ent)) + return 0; int32 numSpheres = CCollision::ProcessColModels( GetMatrix(), *GetColModel(), ent->GetMatrix(), *ent->GetColModel(), @@ -430,7 +523,7 @@ CPhysical::ApplyTurnSpeed(void) { if(bIsFrozen){ m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); - }else{ + }else if(!m_vecTurnSpeed.IsZero()){ // Move the coordinate axes by their speed // Note that this denormalizes the matrix CVector turnvec = m_vecTurnSpeed*CTimer::GetTimeStep(); @@ -444,6 +537,9 @@ void CPhysical::ApplyMoveForce(float jx, float jy, float jz) { m_vecMoveSpeed += CVector(jx, jy, jz)*(1.0f/m_fMass); + m_vecTurnSpeed.x = Clamp(m_vecTurnSpeed.x, -4.0f, 4.0f); + m_vecTurnSpeed.y = Clamp(m_vecTurnSpeed.y, -4.0f, 4.0f); + m_vecTurnSpeed.z = Clamp(m_vecTurnSpeed.z, -4.0f, 4.0f); } void @@ -452,6 +548,23 @@ CPhysical::ApplyTurnForce(float jx, float jy, float jz, float px, float py, floa CVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass); CVector turnimpulse = CrossProduct(CVector(px, py, pz)-com, CVector(jx, jy, jz)); m_vecTurnSpeed += turnimpulse*(1.0f/m_fTurnMass); + m_vecTurnSpeed.x = Clamp(m_vecTurnSpeed.x, -4.0f, 4.0f); + m_vecTurnSpeed.y = Clamp(m_vecTurnSpeed.y, -4.0f, 4.0f); + m_vecTurnSpeed.z = Clamp(m_vecTurnSpeed.z, -4.0f, 4.0f); +} + +void +CPhysical::ApplyTurnForceMultiplayer(const CVector &j, const CVector &p) +{ + CVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass); + CVector turnimpulse = CrossProduct(p-com, j); + turnimpulse *= (1.0f/m_fTurnMass); + m_vecTurnSpeed.x += Clamp(turnimpulse.x, -0.1f, 0.1f); + m_vecTurnSpeed.y += Clamp(turnimpulse.y, -0.1f, 0.1f); + m_vecTurnSpeed.z += Clamp(turnimpulse.z, -0.1f, 0.1f); + m_vecTurnSpeed.x = Clamp(m_vecTurnSpeed.x, -1.0f, 1.0f); + m_vecTurnSpeed.y = Clamp(m_vecTurnSpeed.y, -1.0f, 1.0f); + m_vecTurnSpeed.z = Clamp(m_vecTurnSpeed.z, -1.0f, 1.0f); } void @@ -482,14 +595,14 @@ CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector & } bool -CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir) +CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir, float &impulse) { float compression = 1.0f - springRatio; if(compression > 0.0f){ if(DotProduct(springDir, forceDir) > 0.0f) forceDir *= -1.0f; float step = Min(CTimer::GetTimeStep(), 3.0f); - float impulse = GRAVITY*m_fMass*step * springConst * compression * bias*2.0f; + impulse = GRAVITY*m_fMass*step * springConst * compression * bias*2.0f; if(bIsHeavy) impulse *= 0.75f; ApplyMoveForce(forceDir*impulse); @@ -498,9 +611,12 @@ CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVecto return true; } +float DAMPING_LIMIT_OF_SPRING_FORCE = 0.999f; +float DAMPING_LIMIT_IN_FRAME= 0.25f; + // What exactly is speed? bool -CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed) +CPhysical::ApplySpringDampening(float damping, float dampingLimit, CVector &springDir, CVector &point, CVector &speed) { float speedA = DotProduct(speed, springDir); float speedB = DotProduct(GetSpeed(point), springDir); @@ -509,16 +625,30 @@ CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &poin return true; #endif float step = Min(CTimer::GetTimeStep(), 3.0f); - float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f; + damping *= step; if(bIsHeavy) - impulse *= 2.0f; + damping *= 2.0f; + damping = Clamp(damping, -DAMPING_LIMIT_IN_FRAME, DAMPING_LIMIT_IN_FRAME); // what is this? - float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass); - a = Min(a, 1.0f); - float b = Abs(impulse / (speedB * m_fMass)); - if(a < b) - impulse *= a/b; + float fSpeed = -speedA * damping; + if(fSpeed > 0.0f && fSpeed+speedB > 0.0f){ + if(speedB < 0.0f) + fSpeed = -speedB; + else + fSpeed = 0.0f; + }else if(fSpeed < 0.0f && fSpeed+speedB < 0.0f){ + if(speedB > 0.0f) + fSpeed = -speedB; + else + fSpeed = 0.0f; + } + + CVector com = Multiply3x3(m_matrix, m_vecCentreOfMass); + float impulse = fSpeed*GetMass(point-com, springDir); + float limit = Abs(dampingLimit)*DAMPING_LIMIT_OF_SPRING_FORCE; + if(impulse > limit) + impulse = limit; ApplyMoveForce(springDir*impulse); ApplyTurnForce(springDir*impulse, point); @@ -530,7 +660,6 @@ CPhysical::ApplyGravity(void) { if (!bAffectedByGravity) return; -#ifdef WALLCLIMB_CHEAT if (gGravityCheat && this == FindPlayerVehicle()) { static CVector gravityUp(0.0f, 0.0f, 1.0f), surfaceUp(0.0f, 0.0f, 1.0f); CVector belowCar = GetPosition() - 2.0f*GetUp(); @@ -549,7 +678,6 @@ CPhysical::ApplyGravity(void) m_vecMoveSpeed -= GRAVITY * CTimer::GetTimeStep() * gravityUp; return; } -#endif m_vecMoveSpeed.z -= GRAVITY * CTimer::GetTimeStep(); } @@ -569,8 +697,8 @@ CPhysical::ApplyAirResistance(void) float f = Pow(m_fAirResistance, CTimer::GetTimeStep()); m_vecMoveSpeed *= f; m_vecTurnSpeed *= f; - }else if(GetStatus() != STATUS_GHOST){ - float f = Pow(1.0f/Abs(1.0f + m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr()), CTimer::GetTimeStep()); + }else{ + float f = Pow(1.0f - m_fAirResistance*m_vecMoveSpeed.Magnitude(), CTimer::GetTimeStep()); m_vecMoveSpeed *= f; m_vecTurnSpeed *= 0.99f; } @@ -613,6 +741,14 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl foo = true; } + CVector comA, comB; + comA = Multiply3x3(A->GetMatrix(), A->m_vecCentreOfMass); + comB = Multiply3x3(B->GetMatrix(), B->m_vecCentreOfMass); + + if(A->IsVehicle() && B->IsObject() && ((CObject*)B)->bIsStreetLight || + B->IsVehicle() && A->IsObject() && ((CObject*)A)->bIsStreetLight) + colpoint.normal.z = 0.0f; + float speedA, speedB; if(B->GetIsStatic() && !foo){ if(A->bPedPhysics){ @@ -633,6 +769,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl if(IsGlass(B->GetModelIndex())) CGlass::WindowRespondsToSoftCollision(B, impulseA); if(!A->bInfiniteMass) +//TODO(LCS): inline without clamp A->ApplyMoveForce(colpoint.GetNormal() * (1.0f + A->m_fElasticity) * impulseA); return true; } @@ -643,6 +780,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl impulseA = -speedA * A->m_fMass; impulseB = 0.0f; if(!A->bInfiniteMass) +//TODO(LCS): inline without clamp A->ApplyMoveForce(colpoint.normal*(1.0f + A->m_fElasticity)*impulseA); return true; } @@ -656,7 +794,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl eA = -1.0f; else eA = -(1.0f + A->m_fElasticity); - impulseA = eA * speedA * A->GetMass(pointposA, colpoint.normal); + impulseA = eA * speedA * A->GetMass(pointposA-comA, colpoint.normal); impulseB = impulseA; if(Bobj->m_nCollisionDamageEffect && impulseA > 20.0f){ @@ -679,6 +817,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl int16 model = B->GetModelIndex(); if(model == MI_FIRE_HYDRANT && !Bobj->bHasBeenDamaged){ CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, B->GetPosition() - CVector(0.0f, 0.0f, 0.5f), true); + CParticleObject::AddObject(POBJECT_FIRE_HYDRANT_STEAM, B->GetPosition() - CVector(0.0f, 0.0f, 0.5f), true); Bobj->bHasBeenDamaged = true; }else if((model == MI_PARKINGMETER || model == MI_PARKINGMETER2) && !Bobj->bHasBeenDamaged){ CPickups::CreateSomeMoney(GetPosition(), CGeneral::GetRandomNumber()%100); @@ -724,7 +863,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl float mA = A->m_fMass; float mB = B->m_fMass; float speedSum; - if(((CPed*)A)->GetPedState() == PED_FOLLOW_PATH){ + if(A->IsPed() && ((CPed*)A)->GetPedState() == PED_FOLLOW_PATH){ affectB = true; speedSum = (2.0f*mA*speedA + mB*speedB)/(2.0f*mA + mB); }else{ @@ -756,7 +895,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal); float mA = A->m_fMass*massFactorA; - float mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB); + float mB = B->GetMassTweak(pointposB-comB, colpoint.normal, massFactorB); float speedSum; if(foo) speedSum = speedB; @@ -794,7 +933,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal); speedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal); - float mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA); + float mA = A->GetMassTweak(pointposA-comA, colpoint.normal, massFactorA); float mB = B->m_fMass*massFactorB; float speedSum = (mB*speedB + mA*speedA)/(mA + mB); if(speedA < speedSum){ @@ -834,8 +973,8 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl CVector pointposB = colpoint.point - B->GetPosition(); speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal); speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal); - float mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA); - float mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB); + float mA = A->GetMassTweak(pointposA-comA, colpoint.normal, massFactorA); + float mB = B->GetMassTweak(pointposB-comB, colpoint.normal, massFactorB); float speedSum = (mB*speedB + mA*speedA)/(mA + mB); if(speedA < speedSum){ if(A->bHasHitWall) @@ -851,8 +990,8 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl CVector fA = colpoint.normal*(impulseA/massFactorA); CVector fB = colpoint.normal*(-impulseB/massFactorB); if(A->IsVehicle() && !A->bHasHitWall){ - fA.x *= 1.4f; - fA.y *= 1.4f; +// fA.x *= 1.4f; +// fA.y *= 1.4f; if(colpoint.normal.z < 0.7f) fA.z *= 0.3f; if(A->GetStatus() == STATUS_PLAYER) @@ -863,8 +1002,8 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl } } if(B->IsVehicle() && !B->bHasHitWall){ - fB.x *= 1.4f; - fB.y *= 1.4f; +// fB.x *= 1.4f; +// fB.y *= 1.4f; if(-colpoint.normal.z < 0.7f) fB.z *= 0.3f; if(B->GetStatus() == STATUS_PLAYER) @@ -915,8 +1054,8 @@ CPhysical::ApplyCollision(CColPoint &colpoint, float &impulse) impulse = -(m_fElasticity + 1.0f) * speed * mass; CVector f = colpoint.normal*impulse; if(IsVehicle()){ - f.x *= 1.4f; - f.y *= 1.4f; +// f.x *= 1.4f; +// f.y *= 1.4f; if(colpoint.normal.z < 0.7f) f.z *= 0.3f; } @@ -1022,6 +1161,7 @@ CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CV return false; } +//LCS: the div by 0 is fixed differently. probably should use their fix? bool CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint) { @@ -1261,6 +1401,10 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) A->GetBoundCentre(center); radius = A->GetBoundRadius(); + + if(A->IsMultiplayer()) + return false; + for(i = 0; i <= ENTITYLIST_PEDS_OVERLAP; i++){ list = &lists[i]; for(node = list->first; node; node = node->next){ @@ -1268,7 +1412,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) Bobj = (CObject*)B; skipShift = false; - if(B->IsBuilding() || + if(B->IsMultiplayer() || B->IsBuilding() || B->IsObject() && B->bInfiniteMass || A->IsPed() && B->IsObject() && B->GetIsStatic() && !Bobj->bHasBeenDamaged) canshift = true; @@ -1335,9 +1479,9 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) else if(A->IsPed() && ((CPed*)A)->m_pCollidingEntity == B || B->IsPed() && ((CPed*)B)->m_pCollidingEntity == A) skipShift = true; - else if(A->GetModelIndex() == MI_RCBANDIT && B->IsVehicle() || - B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle())) - skipShift = true; +// else if(A->GetModelIndex() == MI_RCBANDIT && B->IsVehicle() || +// B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle())) +// skipShift = true; if(skipShift) continue; @@ -1379,6 +1523,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) dir.Normalise(); B->GetMatrix().Translate(dir * colpoints[mostColliding].GetDepth() / (1.0f - f)); // BUG? how can that ever happen? A is a Ped + // LCS: gone or just optimized away? if(B->IsVehicle()) B->ProcessEntityCollision(A, colpoints); }else{ @@ -1441,6 +1586,10 @@ CPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists) B->bUsesCollision && B->GetIsTouching(center, radius)){ B->m_scanCode = CWorld::GetCurrentScanCode(); +#ifndef FIX_BUGS + // surely they didn't mean to call this twice? + numCollisions = A->ProcessEntityCollision(B, aColPoints); +#endif numCollisions = A->ProcessEntityCollision(B, aColPoints); if(numCollisions > 0) goto collision; @@ -1591,7 +1740,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) radius = A->GetBoundRadius(); A->GetBoundCentre(center); - for(j = 0; j <= ENTITYLIST_PEDS_OVERLAP; j++){ + for(j = A->IsMultiplayer() ? 1 : 0; j <= ENTITYLIST_PEDS_OVERLAP; j++){ list = &lists[j]; CPtrNode *listnode; @@ -1600,7 +1749,6 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) Bobj = (CObject*)B; Bped = (CPed*)B; - bool isTouching = true; if(!B->bUsesCollision || B->m_scanCode == CWorld::GetCurrentScanCode() || B == A) @@ -1635,6 +1783,18 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) skipCollision = true; A->bSkipLineCol = true; Bobj->m_pCollidingEntity = A; + }else if(A->IsObject() && Aobj->m_nSpecialCollisionResponseCases == COLLRESPONSE_FENCEPART && + B->IsObject() && Bobj->m_nSpecialCollisionResponseCases == COLLRESPONSE_FENCEPART){ + skipCollision = true; + A->bSkipLineCol = true; + }else if(A->IsObject() && Aobj->bIsStreetLight && !B->IsBuilding() && IsLCSTrafficLight(A->GetModelIndex())){ + skipCollision = true; + A->bSkipLineCol = true; + Aobj->m_pCollidingEntity = B; + }else if(B->IsObject() && Bobj->bIsStreetLight && !A->IsBuilding() && IsLCSTrafficLight(B->GetModelIndex())){ + skipCollision = true; + B->bSkipLineCol = true; + Bobj->m_pCollidingEntity = A; }else if(A->IsObject() && B->IsVehicle()){ if(A->GetModelIndex() == MI_CAR_BUMPER) skipCollision = true; @@ -1679,20 +1839,39 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) B->GetPosition().z < A->GetPosition().z){ skipCollision = true; A->bSkipLineCol = true; - }else if(A->IsPed() && Aped->m_pCollidingEntity == B){ + }else if(A->IsPed() && (Aped->m_pCollidingEntity == B || !A->phys_lcs_unk1)){ skipCollision = true; if(!Aped->bKnockedUpIntoAir || Aped->bKnockedOffBike) A->bSkipLineCol = true; - }else if(B->IsPed() && Bped->m_pCollidingEntity == A){ - skipCollision = true; - A->bSkipLineCol = true; - }else if(A->GetModelIndex() == MI_RCBANDIT && (B->IsPed() || B->IsVehicle()) || - B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle())){ + }else if(B->IsPed() && (Bped->m_pCollidingEntity == A || !B->phys_lcs_unk1)){ skipCollision = true; A->bSkipLineCol = true; +// }else if(A->GetModelIndex() == MI_RCBANDIT && (B->IsPed() || B->IsVehicle()) || +// B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle())){ +// skipCollision = true; +// A->bSkipLineCol = true; }else if(A->IsPed() && B->IsObject() && Bobj->m_fUprootLimit > 0.0f) altcollision = true; + if(A->IsObject() && !B->IsBuilding()){ + if(!A->phys_lcs_unk1){ + A->bSkipLineCol = true; + skipCollision = true; +#ifdef FIX_BUGS + // looks correct below + Aobj->m_pCollidingEntity = B; +#else + Aobj->m_pCollidingEntity = A; +#endif + } + } + if(B->IsObject() && !A->IsBuilding()){ + if(!B->phys_lcs_unk1){ + B->bSkipLineCol = true; + skipCollision = true; + Bobj->m_pCollidingEntity = A; + } + } if(!A->bUsesCollision || skipCollision){ B->m_scanCode = CWorld::GetCurrentScanCode(); @@ -1722,6 +1901,8 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) if(impulseA > maxImpulseA) maxImpulseA = impulseA; if(A->IsVehicle()){ + if(B->IsMultiplayer()) + A->SendMuliVehicleCollision(B, &aColPoints[i], impulseA); if(!(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_SOLID) && impulseA > A->m_fDamageImpulse) A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); @@ -1759,6 +1940,8 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists) float adhesion = CSurfaceTable::GetAdhesiveLimit(aColPoints[i]) / numCollisions; if(A->IsVehicle()){ + if(B->IsMultiplayer()) + A->SendMuliVehicleCollision(B, &aColPoints[i], impulseA); if(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_SOLID) adhesion = 0.0f; else if(impulseA > A->m_fDamageImpulse) @@ -2105,7 +2288,7 @@ CPhysical::ProcessCollision(void) m_bIsVehicleBeingShifted = false; bSkipLineCol = false; - if(!bUsesCollision){ + if(!bUsesCollision || IsMultiplayer()){ bIsStuck = false; bIsInSafePosition = true; RemoveAndAdd(); @@ -2135,61 +2318,66 @@ CPhysical::ProcessCollision(void) float distSq = m_vecMoveSpeed.MagnitudeSqr() * sq(CTimer::GetTimeStep()); if(IsPed() && (distSq >= sq(0.3f) || ped->IsPlayer())){ - if(ped->IsPlayer()){ - if(ped->m_pCurrentPhysSurface) - n = Max(NUMSTEPS(0.15f), 4.0f); - else - n = Max(NUMSTEPS(0.3f), 2.0f); - }else - n = NUMSTEPS(0.45f); + if(ped->IsPlayer() && ped->m_pCurrentPhysSurface) + n = Max(NUMSTEPS(0.15f), 4.0f); + else + n = Max(NUMSTEPS(0.3f), 2.0f); + if(ped->IsPlayer() && ped->bHasHitWall) + n *= 2; step = savedTimeStep / n; if(!ped->IsPlayer()) ped->m_fElasticity *= HIGHSPEED_ELASTICITY_MULT_PED; - }else if(IsVehicle() && distSq >= sq(0.4f)){ + }else if(IsVehicle()){ if(GetStatus() == STATUS_PLAYER) - n = NUMSTEPS(0.2f); + n = NUMSTEPS(0.3f); else - n = distSq > 0.32f ? NUMSTEPS(0.3f) : NUMSTEPS(0.4f); + n = NUMSTEPS(0.4f); + if(n == 0) + n = 1; step = savedTimeStep / n; - - CVector bbox = GetColModel()->boundingBox.GetSize(); - float relDistX = Abs(DotProduct(m_vecMoveSpeed, GetRight())) * CTimer::GetTimeStep() / bbox.x; - float relDistY = Abs(DotProduct(m_vecMoveSpeed, GetForward())) * CTimer::GetTimeStep() / bbox.y; - float relDistZ = Abs(DotProduct(m_vecMoveSpeed, GetUp())) * CTimer::GetTimeStep() / bbox.z; - if(Max(relDistX, Max(relDistY, relDistZ)) < 1.0f){ - // check if we can get away with simplified processing - - ApplyMoveSpeed(); - ApplyTurnSpeed(); - GetMatrix().Reorthogonalise(); - bSkipLineCol = false; - m_bIsVehicleBeingShifted = false; - - bJustCheckCollision = true; - bool savedUsesCollision = bUsesCollision; - bUsesCollision = false; - if(!CheckCollision()){ + if(n > 2){ + CVector bbox = GetColModel()->boundingBox.GetSize(); + float relDistX = Abs(DotProduct(m_vecMoveSpeed, GetRight())) * CTimer::GetTimeStep() / bbox.x; + float relDistY = Abs(DotProduct(m_vecMoveSpeed, GetForward())) * CTimer::GetTimeStep() / bbox.y; + float relDistZ = Abs(DotProduct(m_vecMoveSpeed, GetUp())) * CTimer::GetTimeStep() / bbox.z; + float relDist = Max(relDistX, Max(relDistY, relDistZ)); + if(((CVehicle*)this)->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) + relDist *= 2.0f; + if(relDist < 1.0f){ + // check if we can get away with simplified processing + + ApplyMoveSpeed(); + ApplyTurnSpeed(); + GetMatrix().Reorthogonalise(); + bSkipLineCol = false; + m_bIsVehicleBeingShifted = false; + + bJustCheckCollision = true; + bool savedUsesCollision = bUsesCollision; + bUsesCollision = false; + if(!CheckCollision()){ + bJustCheckCollision = false; + bUsesCollision = savedUsesCollision; + if(IsVehicle()) + ((CVehicle*)this)->bVehicleColProcessed = true; + + bHitByTrain = false; + m_fDistanceTravelled = (GetPosition() - savedMatrix.GetPosition()).Magnitude(); + bSkipLineCol = false; + + bIsStuck = false; + bIsInSafePosition = true; + m_fElasticity = savedElasticity; + RemoveAndAdd(); + return; + } bJustCheckCollision = false; bUsesCollision = savedUsesCollision; - if(IsVehicle()) - ((CVehicle*)this)->bVehicleColProcessed = true; - - bHitByTrain = false; - m_fDistanceTravelled = (GetPosition() - savedMatrix.GetPosition()).Magnitude(); - bSkipLineCol = false; - - bIsStuck = false; - bIsInSafePosition = true; - m_fElasticity = savedElasticity; - RemoveAndAdd(); - return; + GetMatrix() = savedMatrix; + m_vecMoveSpeed = savedMoveSpeed; + if(IsVehicle() && ((CVehicle*)this)->bIsLawEnforcer) + m_fElasticity *= HIGHSPEED_ELASTICITY_MULT_COPCAR; } - bJustCheckCollision = false; - bUsesCollision = savedUsesCollision; - GetMatrix() = savedMatrix; - m_vecMoveSpeed = savedMoveSpeed; - if(IsVehicle() && ((CVehicle*)this)->bIsLawEnforcer) - m_fElasticity *= HIGHSPEED_ELASTICITY_MULT_COPCAR; } }else if(IsObject() && ((CObject*)this)->ObjectCreatedBy != TEMP_OBJECT){ int responsecase = ((CObject*)this)->m_nSpecialCollisionResponseCases; @@ -2272,7 +2460,7 @@ CPhysical::ProcessCollision(void) bSkipLineCol = false; if(!m_vecMoveSpeed.IsZero() || !m_vecTurnSpeed.IsZero() || - bHitByTrain || +// bHitByTrain || GetStatus() == STATUS_PLAYER || IsVehicle() && ((CVehicle*)this)->bRestingOnPhysical || IsPed() && ped->IsPlayer()){ @@ -2293,3 +2481,44 @@ CPhysical::ProcessCollision(void) m_fElasticity = savedElasticity; RemoveAndAdd(); } + + + +// TEMP old VC code until bikes are done +bool +CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir) +{ + float compression = 1.0f - springRatio; + if(compression > 0.0f){ + if(DotProduct(springDir, forceDir) > 0.0f) + forceDir *= -1.0f; + float step = Min(CTimer::GetTimeStep(), 3.0f); + float impulse = GRAVITY*m_fMass*step * springConst * compression * bias*2.0f; + if(bIsHeavy) + impulse *= 0.75f; + ApplyMoveForce(forceDir*impulse); + ApplyTurnForce(forceDir*impulse, point); + } + return true; +} +bool +CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed) +{ + float speedA = DotProduct(speed, springDir); + float speedB = DotProduct(GetSpeed(point), springDir); + float step = Min(CTimer::GetTimeStep(), 3.0f); + float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f; + if(bIsHeavy) + impulse *= 2.0f; + + // what is this? + float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass); + a = Min(a, 1.0f); + float b = Abs(impulse / (speedB * m_fMass)); + if(a < b) + impulse *= a/b; + + ApplyMoveForce(springDir*impulse); + ApplyTurnForce(springDir*impulse, point); + return true; +} diff --git a/src/entities/Physical.h b/src/entities/Physical.h index f552da6c..71e30485 100644 --- a/src/entities/Physical.h +++ b/src/entities/Physical.h @@ -61,9 +61,13 @@ public: uint8 m_bIsVehicleBeingShifted : 1; // wrong name - also used on but never set for peds uint8 bJustCheckCollision : 1; // just see if there is a collision +bool phys_lcs_unk1; + uint8 m_nSurfaceTouched; int8 m_nZoneLevel; +int8 phys_lcs_unk2; + CPhysical(void); ~CPhysical(void); @@ -75,6 +79,9 @@ public: void ProcessShift(void); void ProcessCollision(void); + // these two are virtual in LCS...why? + virtual void ApplyMoveSpeed(void); + virtual void ApplyTurnSpeed(void); virtual int32 ProcessEntityCollision(CEntity *ent, CColPoint *colpoints); void RemoveAndAdd(void); @@ -141,8 +148,6 @@ public: m_vecCentreOfMass.z = z; } - void ApplyMoveSpeed(void); - void ApplyTurnSpeed(void); // Force actually means Impulse here void ApplyMoveForce(float jx, float jy, float jz); void ApplyMoveForce(const CVector &j) { ApplyMoveForce(j.x, j.y, j.z); } @@ -150,14 +155,15 @@ public: void ApplyTurnForce(float jx, float jy, float jz, float px, float py, float pz); // j is direction of force, p is point relative to model center where force is applied void ApplyTurnForce(const CVector &j, const CVector &p) { ApplyTurnForce(j.x, j.y, j.z, p.x, p.y, p.z); } + void ApplyTurnForceMultiplayer(const CVector &j, const CVector &p); void ApplyFrictionMoveForce(float jx, float jy, float jz); void ApplyFrictionMoveForce(const CVector &j) { ApplyFrictionMoveForce(j.x, j.y, j.z); } void ApplyFrictionTurnForce(float jx, float jy, float jz, float rx, float ry, float rz); void ApplyFrictionTurnForce(const CVector &j, const CVector &p) { ApplyFrictionTurnForce(j.x, j.y, j.z, p.x, p.y, p.z); } // springRatio: 1.0 fully extended, 0.0 fully compressed bool ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias); - bool ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir); - bool ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed); + bool ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir, float &impulse); + bool ApplySpringDampening(float damping, float dampingLimit, CVector &springDir, CVector &point, CVector &speed); void ApplyGravity(void); void ApplyFriction(void); void ApplyAirResistance(void); @@ -172,4 +178,10 @@ public: bool ProcessCollisionSectorList(CPtrList *lists); bool CheckCollision(void); bool CheckCollision_SimpleCar(void); + + void SendMuliVehicleCollision(CEntity *,CColPoint *,float) {} + + // TEMP + bool ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir); + bool ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed); }; |