diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index ebaa5f29..ae57e030 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -4,6 +4,7 @@ #include "Accident.h" #include "Automobile.h" +#include "Bike.h" #include "Camera.h" #include "CarAI.h" #include "CarGen.h" @@ -345,7 +346,7 @@ CCarCtrl::GenerateOneRandomCar() if (CModelInfo::IsBoatModel(carModel)) pVehicle = new CBoat(carModel, RANDOM_VEHICLE); else if (CModelInfo::IsBikeModel(carModel)) - return; // TODO(MIAMI): spawn bikes + pVehicle = new CBike(carModel, RANDOM_VEHICLE); else pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE); pVehicle->AutoPilot.m_nPrevRouteNode = 0; @@ -2502,7 +2503,7 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe pSwerve, pAccel, pBrake, pHandbrake); return; case MISSION_HELI_FLYTOCOORS: - //SteerAIHeliTowardsTargetCoors((CAutomobile*)pVehicle); + SteerAIHeliTowardsTargetCoors((CAutomobile*)pVehicle); return; case MISSION_ATTACKPLAYER: SteerAIBoatWithPhysicsAttackingPlayer(pVehicle, pSwerve, pAccel, pBrake, pHandbrake); @@ -2656,9 +2657,8 @@ void CCarCtrl::SteerAIHeliTowardsTargetCoors(CAutomobile* pHeli) else speed *= 0.2f; } - CVector2D vecAdvanceThisFrame = vecToTarget; - vecAdvanceThisFrame.Normalise(); - vecAdvanceThisFrame *= speed; + vecToTarget.Normalise(); + CVector2D vecAdvanceThisFrame(vecToTarget * speed); float resistance = Pow(0.997f, CTimer::GetTimeStep()); pHeli->m_vecMoveSpeed.x *= resistance; pHeli->m_vecMoveSpeed.y *= resistance; @@ -2673,9 +2673,55 @@ void CCarCtrl::SteerAIHeliTowardsTargetCoors(CAutomobile* pHeli) pHeli->AddToMoveSpeed(vecAdvanceThisFrame); else pHeli->AddToMoveSpeed(vecSpeedChange * changeMultiplier); - pHeli->SetPosition(pHeli->GetPosition() + CVector(CTimer::GetTimeStep() * pHeli->m_vecMoveSpeed.x, CTimer::GetTimeStep() * pHeli->m_vecMoveSpeed.y, 0.0f)); - assert(0); - // This is not finished yet. Heli fields in CAutomobile required + pHeli->SetPosition(pHeli->GetPosition() + CVector(CTimer::GetTimeStep() * pHeli->GetMoveSpeed().x, CTimer::GetTimeStep() * pHeli->GetMoveSpeed().y, 0.0f)); + float ZTarget = pHeli->AutoPilot.m_vecDestinationCoors.z; + if (CTimer::GetTimeInMilliseconds() & 0x800) // switch every ~2 seconds + ZTarget += 2.0f; + float ZSpeedTarget = (ZTarget - pHeli->GetPosition().z) * 0.01f; + float ZSpeedChangeTarget = ZSpeedTarget - pHeli->GetMoveSpeed().z; + float ZSpeedChangeMax = 0.01f * CTimer::GetTimeStep(); + if (!pHeli->bHeliDestroyed) { + if (Abs(ZSpeedChangeTarget) < ZSpeedChangeMax) + pHeli->SetMoveSpeed(pHeli->GetMoveSpeed().x, pHeli->GetMoveSpeed().y, ZSpeedTarget); + else if (ZSpeedChangeTarget < 0.0f) + pHeli->AddToMoveSpeed(0.0f, 0.0f, 1.5f * ZSpeedChangeMax); + else + pHeli->AddToMoveSpeed(0.0f, 0.0f, ZSpeedChangeMax); + } + pHeli->SetPosition(pHeli->GetPosition() + CVector(0.0f, 0.0f, CTimer::GetTimeStep() * pHeli->GetMoveSpeed().z)); + pHeli->SetTurnSpeed(pHeli->GetTurnSpeed().x, pHeli->GetTurnSpeed().y, pHeli->GetTurnSpeed().z * Pow(0.99f, CTimer::GetTimeStep())); + float ZTurnSpeedTarget; + if (distanceToTarget < 8.0f && pHeli->m_fHeliOrientation < 0.0f) + ZTurnSpeedTarget = 0.0f; + else { + float fAngleTarget = CGeneral::GetATanOfXY(vecToTarget.x, vecToTarget.y) + PI; + if (pHeli->m_fHeliOrientation >= 0.0f) + fAngleTarget = pHeli->m_fHeliOrientation; + while (fAngleTarget < -PI) + fAngleTarget += TWOPI; + while (fAngleTarget > PI) + fAngleTarget -= TWOPI; + if (Abs(fAngleTarget) <= 0.4f) + ZTurnSpeedTarget = 0.0f; + else if (fAngleTarget < 0.0f) + ZTurnSpeedTarget = 0.03f; + else + ZTurnSpeedTarget = -0.03f; + } + float ZTurnSpeedChangeTarget = ZTurnSpeedTarget - pHeli->GetTurnSpeed().z; + pHeli->m_fOrientation += pHeli->GetTurnSpeed().z * CTimer::GetTimeStep(); + CVector up; + if (pHeli->bHeliMinimumTilt) + up = CVector(0.5f * pHeli->GetMoveSpeed().x, 0.5f * pHeli->GetMoveSpeed().y, 1.0f); + else + up = CVector(3.0f * pHeli->GetMoveSpeed().x, 3.0f * pHeli->GetMoveSpeed().y, 1.0f); + up.Normalise(); + CVector forward(Sin(pHeli->m_fOrientation), Cos(pHeli->m_fOrientation), 0.0f); + CVector right = CrossProduct(up, forward); + forward = CrossProduct(up, right); + pHeli->GetMatrix().GetRight() = right; + pHeli->GetMatrix().GetForward() = forward; + pHeli->GetMatrix().GetUp() = up; } void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake) diff --git a/src/control/Script.cpp b/src/control/Script.cpp index f59701b3..15132f42 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -4,6 +4,7 @@ #include "ScriptCommands.h" #include "AnimBlendAssociation.h" +#include "Bike.h" #include "Boat.h" #include "BulletInfo.h" #include "Camera.h" @@ -2189,9 +2190,12 @@ int8 CRunningScript::ProcessCommands100To199(int32 command) else { CVehicle* car; - // TODO(MIAMI) - //if (!CModelInfo::IsBikeModel(ScriptParams[0])) - car = new CAutomobile(ScriptParams[0], MISSION_VEHICLE); + if (!CModelInfo::IsBikeModel(ScriptParams[0])) + car = new CAutomobile(ScriptParams[0], MISSION_VEHICLE); + else { + car = new CBike(ScriptParams[0], MISSION_VEHICLE); + ((CBike*)(car))->bIsStanding = true; + } CVector pos = *(CVector*)&ScriptParams[1]; if (pos.z <= MAP_Z_LOW_LIMIT) pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y); @@ -7406,7 +7410,13 @@ int8 CRunningScript::ProcessCommands800To899(int32 command) if (pPed->GetPedState() == PED_EXIT_CAR || pPed->GetPedState() == PED_DRAG_FROM_CAR) { uint8 flags = 0; if (pPed->m_pMyVehicle->IsBike()) { - //TODO(MIAMI) + if (pPed->m_vehEnterType == CAR_DOOR_LF || + pPed->m_vehEnterType == CAR_DOOR_RF || + pPed->m_vehEnterType == CAR_WINDSCREEN) + flags = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_RF; + else if (pPed->m_vehEnterType == CAR_DOOR_LR || + pPed->m_vehEnterType == CAR_DOOR_RR) + flags = CAR_DOOR_FLAG_LR | CAR_DOOR_FLAG_RR; } else { switch (pPed->m_vehEnterType) { @@ -8046,7 +8056,8 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); if (pVehicle->IsBike()) { - //TODO(MIAMI) + CBike* pBike = (CBike*)pBike; + pBike->bWaterTight = ScriptParams[1] != 0; } else if (pVehicle->IsCar()) { CAutomobile* pCar = (CAutomobile*)pVehicle; @@ -8542,8 +8553,12 @@ int8 CRunningScript::ProcessCommands900To999(int32 command) if (model == -1) return 0; CVehicle* car; - //if (CModelInfo::IsBikeModel(model)) // TODO(MIAMI) - car = new CAutomobile(model, MISSION_VEHICLE); + if (CModelInfo::IsBikeModel(model)) { + car = new CBike(model, MISSION_VEHICLE); + ((CBike*)(car))->bIsStanding = true; + } + else + car = new CAutomobile(model, MISSION_VEHICLE); CVector pos = *(CVector*)&ScriptParams[0]; pos.z += car->GetDistanceFromCentreOfMassToBaseOfModel(); car->SetPosition(pos); @@ -9248,8 +9263,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command) if (pVehicle->m_vehType == VEHICLE_TYPE_CAR) ((CAutomobile*)pVehicle)->m_fTraction = fTraction; else - // TODO(MIAMI) - //((CBike*)pVehicle)->m_fTraction = fTraction; + ((CBike*)pVehicle)->m_fTraction = fTraction; return 0; } case COMMAND_ARE_MEASUREMENTS_IN_METRES: @@ -10337,8 +10351,21 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command) CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]); assert(pVehicle); bool bIsBurst = false; + CBike* pBike = (CBike*)pVehicle; if (pVehicle->m_vehType == VEHICLE_APPEARANCE_BIKE) { - assert("IS_CAR_TYPE_BURST not yet implemented for bikes"); + if (ScriptParams[1] == 4) { + for (int i = 0; i < 2; i++) { + if (pBike->m_wheelStatus[i] == WHEEL_STATUS_BURST) + bIsBurst = true; + } + } + else { + if (ScriptParams[1] == 2) + ScriptParams[1] = 0; + if (ScriptParams[1] == 3) + ScriptParams[1] = 1; + bIsBurst = pBike->m_wheelStatus[ScriptParams[1]] == WHEEL_STATUS_BURST; + } } else { CAutomobile* pCar = (CAutomobile*)pVehicle; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index e404463e..2d5d953e 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -4270,33 +4270,40 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi if (method != WEAPONTYPE_DROWNING) { #ifdef VC_PED_PORTS if (m_pMyVehicle) { - - // TODO(Miami): Bikes - if (m_pMyVehicle->IsCar() && m_pMyVehicle->pDriver == this) { - if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) { - m_pMyVehicle->SetStatus(STATUS_PHYSICS); - CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle); - } - m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE; - m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; - m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT; - m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; - } -// TODO(MIAMI): argument - if (m_pMyVehicle->CanPedExitCar(false)) { - SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle); - } else { + bool bDone = false; + if (m_pMyVehicle->IsBike()) { m_fHealth = 0.0f; - if (m_pMyVehicle && m_pMyVehicle->pDriver == this) { - SetRadioStation(); - m_pMyVehicle->SetStatus(STATUS_ABANDONED); + //CBike::KnockOffRider -- TODO(MIAMI) + bDone = true; + } + else { + if (m_pMyVehicle->IsCar() && m_pMyVehicle->pDriver == this) { + if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) { + m_pMyVehicle->SetStatus(STATUS_PHYSICS); + CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle); + } + m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE; + m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0; + m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT; + m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; } - SetDie(dieAnim, dieDelta, dieSpeed); - /* - if (damagedBy == FindPlayerPed() && damagedBy != this) { - // TODO(Miami): PlayerInfo stuff + // TODO(MIAMI): argument + if (m_pMyVehicle->CanPedExitCar(false)) { + SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle); + } + else { + m_fHealth = 0.0f; + if (m_pMyVehicle && m_pMyVehicle->pDriver == this) { + SetRadioStation(); + m_pMyVehicle->SetStatus(STATUS_ABANDONED); + } + SetDie(dieAnim, dieDelta, dieSpeed); + /* + if (damagedBy == FindPlayerPed() && damagedBy != this) { + // TODO(Miami): PlayerInfo stuff + } + */ } - */ } for (int i = 0; i < ARRAY_SIZE(m_pMyVehicle->pPassengers); i++) { CPed* passenger = m_pMyVehicle->pPassengers[i]; @@ -4314,6 +4321,8 @@ CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPi } else { CDarkel::RegisterKillNotByPlayer(this, method); } + if (bDone) + return true; } #endif m_fHealth = 1.0f; diff --git a/src/vehicles/CarGen.cpp b/src/vehicles/CarGen.cpp index a1d58ab2..e6c3bbf3 100644 --- a/src/vehicles/CarGen.cpp +++ b/src/vehicles/CarGen.cpp @@ -3,6 +3,7 @@ #include "CarGen.h" #include "Automobile.h" +#include "Bike.h" #include "Boat.h" #include "Camera.h" #include "CarCtrl.h" @@ -88,7 +89,7 @@ void CCarGenerator::DoInternalProcessing() pBoat->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle)); pBoat->SetStatus(STATUS_ABANDONED); pBoat->m_nDoorLock = CARLOCK_UNLOCKED; - }else{ // TODO(MIAMI): bikes + }else{ bool groundFound = false; CVector pos = m_vecPos; if (pos.z > -100.0f){ @@ -105,16 +106,23 @@ void CCarGenerator::DoInternalProcessing() debug("CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \n", m_vecPos.x, m_vecPos.y); return; } - CAutomobile* pCar = new CAutomobile(mi, PARKED_VEHICLE); - pVehicle = pCar; - pCar->bIsStatic = false; - pCar->bEngineOn = false; - pos.z += pCar->GetDistanceFromCentreOfMassToBaseOfModel(); - pCar->SetPosition(pos); - pCar->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle)); - pCar->SetStatus(STATUS_ABANDONED); - pCar->bLightsOn = false; - pCar->m_nDoorLock = CARLOCK_UNLOCKED; + if (CModelInfo::IsBikeModel(mi)) { + CBike* pBike = new CBike(mi, PARKED_VEHICLE); + pBike->bIsStanding = true; + pVehicle = pBike; + } + else { + CAutomobile* pCar = new CAutomobile(mi, PARKED_VEHICLE); + pVehicle = pCar; + } + pVehicle->bIsStatic = false; + pVehicle->bEngineOn = false; + pos.z += pVehicle->GetDistanceFromCentreOfMassToBaseOfModel(); + pVehicle->SetPosition(pos); + pVehicle->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle)); + pVehicle->SetStatus(STATUS_ABANDONED); + pVehicle->bLightsOn = false; + pVehicle->m_nDoorLock = CARLOCK_UNLOCKED; } CWorld::Add(pVehicle);