//===========================================================================// // File: MWMover.cpp //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 09/09/98 JSE Inital base class based off of Shadowrun/Adept //---------------------------------------------------------------------------// // Copyright (C) 1998, Fasa Interactive // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "MW4Headers.hpp" #include "MWMover.hpp" #include "MWObject.hpp" #include "CombatAI.hpp" #include #include #include #include #include #include #include // ngLog addition #include "MWApplication.hpp" #include "Mech.hpp" extern int g_nMR; //############################################################################# //################## Mover::ExecutionStateEngine ######################## //############################################################################# const StateEngine::StateEntry MWMover::ExecutionStateEngine::StateEntries[]= { STATE_ENTRY(MWMover__ExecutionStateEngine, RegularMotion), STATE_ENTRY(MWMover__ExecutionStateEngine, CameraMotion) }; MWMover::ExecutionStateEngine::ClassData* MWMover::ExecutionStateEngine::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::ExecutionStateEngine::InitializeClass() { Check_Object(StateEngine::DefaultData); Verify(!DefaultData); DefaultData = new ClassData( MWMover__ExecutionStateEngineClassID, "MWMover::ExecutionStateEngine", BaseClass::DefaultData, ELEMENTS(StateEntries), StateEntries, (Entity::ExecutionStateEngine::Factory)Make, (Entity::ExecutionStateEngine::FactoryRequest::Factory) &FactoryRequest::ConstructFactoryRequest ); Register_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::ExecutionStateEngine::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWMover::ExecutionStateEngine* MWMover::ExecutionStateEngine::Make( MWMover *mover, FactoryRequest *request ) { Check_Object(mover); Check_Object(request); MWMover::ExecutionStateEngine *engine; gos_PushCurrentHeap(Heap); engine = new MWMover::ExecutionStateEngine(DefaultData, mover, request); gos_PopCurrentHeap(); return engine; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::ExecutionStateEngine::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //############################################################################# //############################### MWMover ############################## //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWMover::ClassData* MWMover::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::InitializeClass() { Check_Object(ExecutionStateEngine::DefaultData); Verify(!DefaultData); DefaultData = new ClassData( MWMoverClassID, "MechWarrior4::MWMover", BaseClass::DefaultData, NULL, NULL, (Entity::Factory)Make, (Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage, ExecutionStateEngine::DefaultData, (Entity::GameModel::Factory)GameModel::ConstructGameModel, NULL, (Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify, (Entity::GameModel::ModelWrite)GameModel::WriteToText, (Entity::GameModel::ModelSave)GameModel::SaveGameModel ); Register_Object(DefaultData); INDIRECT_STATE_ATTRIBUTE( MWMover, ExecutionState, executionState, MWMover__ExecutionStateEngine ); CUSTOM_DIRECT_ATTRIBUTE( MWMover, IsDark, m_isDark, int, IntClassID ); CUSTOM_DIRECT_ATTRIBUTE( MWMover, LTread, LTread, AffineMatrix4D, AffineMatrix4DClassID ); CUSTOM_DIRECT_ATTRIBUTE( MWMover, RTread, RTread, AffineMatrix4D, AffineMatrix4DClassID ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWMover* MWMover::Make( CreateMessage *message, ReplicatorID *base_id ) { Check_Object(message); gos_PushCurrentHeap(Heap); MWMover *new_entity = new MWMover(DefaultData, message, base_id, NULL); gos_PopCurrentHeap(); Check_Object(new_entity); return new_entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Replicator::CreateMessage* MWMover::SaveMakeMessage(MemoryStream *stream, ResourceFile *res_file) { Check_Object(this); Check_Object(stream); stream->AllocateBytes(sizeof(CreateMessage)); BaseClass::SaveMakeMessage(stream, res_file); CreateMessage *message = Cast_Pointer(CreateMessage*, stream->GetPointer()); message->messageLength = sizeof(*message); // //------------------------------------------ // Create the memory stream for the armature //------------------------------------------ // //Assume that we don't have not changed our armature at all message->armatureStreamResourceID = armatureStreamResourceID; message->siteStreamResourceID = siteStreamResourceID; if((myParentVehicle != NULL) && (myParentVehicle->m_hasExecuted)) { //If we do then save them to a stream and reset the armatureStreamID if(!childEntityChain.IsEmpty()) { DynamicMemoryStream armature_stream(sizeof(WORD)); armature_stream << static_cast(0); ReplicatorID span = ReplicatorID::Null; ChainIteratorOf child_iterator(&childEntityChain); Entity *entity; while((entity = child_iterator.ReadAndNext()) != NULL) { Check_Object(entity); if (entity->IsDerivedFrom(MWMover::DefaultData)) { Replicator::CreateMessage *create_message = entity->SaveMakeMessage(&armature_stream, res_file); if (create_message) { Check_Object(create_message); span += create_message->replicatorID; armature_stream.AdvancePointer(create_message->messageLength); } } } // //------------------------------------------------------------------------- // If we actually wrote out some children, rewind the stream and save it to // the resource. Otherwise, just set the resourceID to NULL //------------------------------------------------------------------------- // if (armature_stream.GetBytesUsed() > sizeof(WORD)) { armature_stream.Rewind(); Verify(span.localID > 0); armature_stream << span.localID; Resource armature_resource(NULL, res_file); armature_resource.Save(&armature_stream, NULL); Check_Object(&armature_resource); message->armatureStreamResourceID = armature_resource.GetResourceID(); message->replicatorID += span; } else { message->armatureStreamResourceID = ResourceID::Null; } } message->siteStreamResourceID = ResourceID::Null; if(!m_sites.IsEmpty()) { SortedChainIteratorOf site_iterator(&m_sites); Site *site; DynamicMemoryStream site_stream; while((site = site_iterator.ReadAndNext()) != NULL) { Check_Object(site); site->SaveToStream(&site_stream); } if (site_stream.GetBytesUsed() > 0) { site_stream.Rewind(); Resource site_resource(NULL, res_file); site_resource.Save(&site_stream, NULL); message->siteStreamResourceID = site_resource.GetResourceID(); } else { message->siteStreamResourceID = ResourceID::Null; } } } Str_Copy(message->jointName, (char*)instanceName, sizeof(message->jointName)); return message; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWMover::MWMover( ClassData *class_data, CreateMessage *message, ReplicatorID *base_id, ElementRenderer::Element *element ): BaseClass(class_data, message, base_id, element), m_sites(NULL, true) { Check_Pointer(this); Check_Object(message); if (!instanceName) instanceName = message->jointName; myParentVehicle = NULL; lightIntensity = 0.0f; armatureStreamResourceID = message->armatureStreamResourceID; siteStreamResourceID = message->siteStreamResourceID; if(message->armatureStreamResourceID != ResourceID::Null) { LoadArmatureFromResource( message->armatureStreamResourceID, base_id ); } if(message->siteStreamResourceID != ResourceID::Null) { LoadSitesFromResource(message->siteStreamResourceID); } m_isDark = 1; LTread = Stuff::AffineMatrix4D::Identity; RTread = Stuff::AffineMatrix4D::Identity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWMover::~MWMover() { DESTRUCTOR("Mover"); Check_Object(this); m_sites.DeletePlugs(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::LoadArmatureFromResource( const ResourceID &armature_stream_id, ReplicatorID *base_id ) { Resource stream(armature_stream_id); Verify(stream.DoesResourceExist()); stream.AdvancePointer(sizeof(WORD)); while (stream.GetBytesRemaining() > 0) { Entity::CreateMessage *message = Cast_Pointer(Entity::CreateMessage*, stream.GetPointer()); Entity *entity = CreateEntity(&stream, base_id); Check_Object(entity); AddChild(entity); stream.AdvancePointer(message->messageLength); } stream.UnloadData(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::LoadSitesFromResource(const ResourceID &site_stream_id) { Resource stream(site_stream_id); Verify(stream.DoesResourceExist()); while (stream.GetBytesRemaining() > 0) { MString site_name; YawPitchRoll rotation; Point3D translation; LinearMatrix4D local_to_parent; stream >> rotation; stream >> translation; stream >> site_name; local_to_parent.BuildRotation(rotation); local_to_parent.BuildTranslation(translation); Site *site = new Site(local_to_parent, this, site_name); m_sites.AddValue(site, site_name); } stream.UnloadData(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::ReuseArmature() { Check_Pointer(this); Entity *entity; MWMover *mover; ChainIteratorOf child_iterator(GetChildEntityChain()); if(armatureStreamResourceID != ResourceID::Null) { Resource child_stream(armatureStreamResourceID); child_stream.AdvancePointer(sizeof(WORD)); while (((entity = child_iterator.ReadAndNext()) != NULL) && (child_stream.GetBytesRemaining() > 0)) { if(entity->IsDerivedFrom(MWMover::DefaultData)) { mover = Cast_Object(MWMover *, entity); Entity::CreateMessage *entity_message = Cast_Pointer(Entity::CreateMessage*, child_stream.GetPointer()); mover->ReuseArmature(); mover->Respawn(entity_message); child_stream.AdvancePointer(entity_message->messageLength); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::Respawn(Entity::CreateMessage *message) { Check_Object(this); Check_Object(message); BaseClass::Respawn(message); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::Reuse( const CreateMessage *message, ReplicatorID *base_id ) { Check_Object(this); Check_Object(message); STOP(("Not implemented")); BaseClass::Reuse(message, base_id); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::BecomeInteresting(bool render_me) { Check_Object(this); LOAD_LOGIC("Become Interesting::MWMover"); // //------------------ // Validate children //------------------ // ChainIteratorOf children(&childEntityChain); Entity *entity; while ((entity = children.ReadAndNext()) != NULL) { Check_Object(entity); // Verify(!entity->IsValid()); entity->BecomeInteresting(render_me); } Check_Pointer(Mission::GetInstance()); #if 0 const Mission::GameModel *mission_model = Mission::GetInstance()->GetGameModel(); Check_Object(mission_model); #endif if(!Mission::GetInstance()->DoesAllowRunningLights()) { m_isDark = 1; } else { m_isDark = 0; } // //----------------------------- // Now make ourself interesting //----------------------------- // extern char g_SkinSet; g_SkinSet = GetSkinPrefix(); extern int g_PilotDecal; extern int g_TeamDecal; g_PilotDecal = GetPilotDecal(); g_TeamDecal = GetTeamDecal(); BaseClass::BecomeInteresting(render_me); CheckVideoStates(render_me); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::CheckVideoStates(bool render_me) { //Ok here we go...if we are destroyed than we must fake out the watchers if(IsDestroyed()) { //Change to prestine state visualRepresentation = PrestineState; //Execute ExecuteChildComponentWebs(); //Change back to its destroyed state visualRepresentation = DestroyedState; //Execute ExecuteChildComponentWebs(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MWMover::FriendlyFire(const TakeDamageMessage *message) { if (GetParentVehicle() != 0) return GetParentVehicle()->FriendlyFire(message); return Entity::FriendlyFire(message); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::ReactToHit(const Entity__TakeDamageMessage *message,Adept::DamageObject *part_hit) { Check_Object(this); Check_Object(message); if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->ReactToHit(message,part_hit); myParentVehicle->NotifyWhoHitMe(message->inflictingEntityID, message->weaponID); } if (g_nMR == 2) return; // TODO: move this elsewhere; this should be more general and should take near // misses into account as well as direct hits -- PAULT if ((GetParentVehicle() != 0) && (GetParentVehicle()->GetAI() != 0)) { switch (message->typeOfDamage) { case BeamDamageType: case MissileDamageType: case ProjectileDamageType: { NotifyAIShot(*(GetParentVehicle()->GetAI()),message->inflictingEntityID); break; } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::ReactToDestruction(int damage_mode, int damage_type) { Check_Object(this); bool kill_self = true; if(IsDestroyed()) return; if ((GetParentVehicle() != 0) && (GetParentVehicle()->GetAI() != 0) && (damageObject != 0) && (damageObject->internalDamageObject != 0)) { GetParentVehicle()->GetAI()->NotifyComponentDestroyed(damageObject->internalDamageObject->damageZone); } // MSL 5.07 Advance Mode MWApplication *m_App; m_App = MWApplication::GetInstance (); int m_AdvanceMode = m_App->GetLocalNetParams()->m_advancemodeOn; // MSL 5.07 Advance Mode if (!m_AdvanceMode) { if ((damage_mode == InternalDamageObject::TorsoLeftDamageMode) || (damage_mode == InternalDamageObject::TorsoRightDamageMode)) { damage_mode = InternalDamageObject::DestructionDamageMode; } // if ((damage_mode == InternalDamageObject::ArmLeftDamageMode) || // (damage_mode == InternalDamageObject::ArmRightDamageMode)) // { // damage_mode = InternalDamageObject::DetachableDamageMode; // } } switch(damage_mode) { case InternalDamageObject::EngineDamageMode: { ResourceID resource_id = ResourceID::Null; if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->EngineDead (); const MWObject__GameModel *model = myParentVehicle->GetGameModel(); resource_id = model->partDestructionEffectResource; } // MERC Code FIX // CreatePartDestructionEffect(resource_id); // DestroyChildren(damage_mode); break; } case InternalDamageObject::GimpLeftDamageMode: { ResourceID resource_id = ResourceID::Null; if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->SetLeftGimp(); myParentVehicle->DestroyLeftLegSpecialZones(); const MWObject__GameModel *model = myParentVehicle->GetGameModel(); resource_id = model->partDestructionEffectResource; } CreatePartDestructionEffect(resource_id); DestroyChildren(damage_mode); break; } case InternalDamageObject::GimpRightDamageMode: { ResourceID resource_id = ResourceID::Null; if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->SetRightGimp(); myParentVehicle->DestroyRightLegSpecialZones(); const MWObject__GameModel *model = myParentVehicle->GetGameModel(); resource_id = model->partDestructionEffectResource; } CreatePartDestructionEffect(resource_id); DestroyChildren(damage_mode); break; } // MSL 5.05 Torso case InternalDamageObject::ArmLeftDamageMode: { ResourceID resource_id = ResourceID::Null; if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->DestroyLeftArmSpecialZones(); const MWObject__GameModel *model = myParentVehicle->GetGameModel(); resource_id = model->partDestructionEffectResource; } CreatePartDestructionEffect(resource_id); DestroyChildren(damage_mode); break; } // MSL 5.05 Torso case InternalDamageObject::ArmRightDamageMode: { ResourceID resource_id = ResourceID::Null; if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->DestroyRightArmSpecialZones(); const MWObject__GameModel *model = myParentVehicle->GetGameModel(); resource_id = model->partDestructionEffectResource; } CreatePartDestructionEffect(resource_id); DestroyChildren(damage_mode); break; } case InternalDamageObject::DetachableDamageMode: { ResourceID resource_id = ResourceID::Null; if(myParentVehicle) { Check_Object(myParentVehicle); const MWObject__GameModel *model = myParentVehicle->GetGameModel(); resource_id = model->partDestructionEffectResource; } CreatePartDestructionEffect(resource_id); DestroyChildren(damage_mode); break; } // MSL 5.05 Torso case InternalDamageObject::TorsoLeftDamageMode: { ResourceID resource_id = ResourceID::Null; if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->DestroyLeftArm(); myParentVehicle->DestroyLeftArmSpecialZones(); myParentVehicle->DestroyLeftTorsoSpecialZones(); const MWObject__GameModel *model = myParentVehicle->GetGameModel(); resource_id = model->partDestructionEffectResource; } CreatePartDestructionEffect(resource_id); DestroyChildren(damage_mode); break; } // MSL 5.05 Torso case InternalDamageObject::TorsoRightDamageMode: { ResourceID resource_id = ResourceID::Null; if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->DestroyRightArm(); myParentVehicle->DestroyRightArmSpecialZones(); myParentVehicle->DestroyRightTorsoSpecialZones(); const MWObject__GameModel *model = myParentVehicle->GetGameModel(); resource_id = model->partDestructionEffectResource; } CreatePartDestructionEffect(resource_id); DestroyChildren(damage_mode); break; } // MSL 5.03 Gyro Hit case InternalDamageObject::GyroHitDamageMode: { if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->ReactToDestruction(damage_mode, damage_type); kill_self = false; } else { DestroyChildren(damage_mode); } break; } case InternalDamageObject::HeadShotDamageMode: { if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->ReactToDestruction(damage_mode, damage_type); kill_self = false; } else { DestroyChildren(damage_mode); } break; } case InternalDamageObject::DestructionDamageMode: { if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->ReactToDestruction(damage_mode, damage_type); kill_self = false; } else { DestroyChildren(damage_mode); } break; } } Check_Object(Mission::GetInstance()); ExecuteChildComponentWebs(); if(kill_self) Entity::ReactToDestruction(damage_mode, damage_type); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::CreatePartDestructionEffect(const ResourceID& resource_id) { Check_Object(this); if(resource_id != ResourceID::Null) { ClassID class_ID; class_ID = Entity::GetClassIDFromDataListID(resource_id); Verify(class_ID != NullClassID); Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, Entity::CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags, resource_id, GetLocalToWorld(), 0.0f, Entity::ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Entity *entity; ReplicatorID effect_id = Connection::Hermit->GetNextReplicatorID(); entity = Entity::CreateEntity(&stream, &effect_id, false); Check_Object(entity); // Effect *effect = Cast_Object(Effect *, entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); // effect->SetFollowEntity(this); // effect->effectOffset = LinearMatrix4D::Identity; entity->SyncMatrices(true); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::ReactToInternalDamage(int damage_mode) { Check_Object(this); if ((GetParentVehicle() != 0) && (GetParentVehicle()->GetAI() != 0)) { GetParentVehicle()->GetAI()->NotifyInternalHit(); } switch(damage_mode) { case InternalDamageObject::GimpLeftDamageMode: { if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->ReactToInternalDamage(damage_mode); } break; } case InternalDamageObject::GimpRightDamageMode: { if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->ReactToInternalDamage(damage_mode); } break; } case InternalDamageObject::HeadShotDamageMode: { if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->HeadShotInternal(); } break; } case InternalDamageObject::GyroHitDamageMode: { if(myParentVehicle) { Check_Object(myParentVehicle); myParentVehicle->GyroHitInternal(); } break; } } // Fix Bug #3100 // Damage Object are now refreshed when a mech sustains internal damage if ((GetParentVehicle() != 0) && (GetParentVehicle()->IsDerivedFrom(Mech::DefaultData))) { GetParentVehicle()->ReactToInternalDamage(damage_mode); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::NotifyProjectileApproaching(const Stuff::Point3D& origin) { if ((GetParentVehicle() != 0) && (GetParentVehicle()->GetAI() != 0)) { GetParentVehicle()->GetAI()->NotifyProjectileApproaching(origin); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::NotifyAIShot(AI& ai, Adept::ReplicatorID inflicting_entity_id) { Connection *connection = Network::GetInstance()->GetConnection(inflicting_entity_id.connectionID); if (connection == NULL) return; Replicator* r = connection->FindReplicator(inflicting_entity_id); if (r == 0) { return; } Verify(r->IsDerivedFrom(Entity::DefaultData)); Entity* e = Cast_Object(Entity*,r); ai.NotifyShot(e->objectID); if ((GetParentVehicle() != 0) && (GetParentVehicle()->GetAlignment() == e->GetAlignment()) && (e->IsDerivedFrom(MWObject::DefaultData) == true)) { MWObject* mwobject = Cast_Object(MWObject*,e); if (mwobject->GetAI() != 0) { mwobject->GetAI()->NotifyLastShotWasFriendlyFire(*GetParentVehicle()); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::ToggleLightsOff(bool toggle) //True if going off { Check_Object(this); ChainIteratorOf children(&childEntityChain); Entity *entity; Check_Pointer(Mission::GetInstance()); // // If running lights aren't allowed, don't allow turning them on // if(!Mission::GetInstance()->DoesAllowRunningLights()) { return; } while ((entity = children.ReadAndNext()) != NULL) { Check_Object(entity); if(entity->IsDerivedFrom(MWMover::DefaultData)) { MWMover *mover = Cast_Object(MWMover *, entity); mover->ToggleLightsOff(toggle); } } m_isDark = toggle; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::SetDamageObject(DamageObject *damage_object) { Check_Object(this); Check_Object(damage_object); Entity::SetDamageObject(damage_object); ConnectSitesToZone(damage_object->internalDamageObject); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::ConnectSitesToZone(InternalDamageObject *zone) { Check_Object(this); Check_Object(zone); SortedChainIteratorOf iterator(&m_sites); Site *site; while((site = iterator.ReadAndNext()) != NULL) { Check_Object(site); if(!zone->m_sites.Find(site->GetName())) zone->m_sites.AddValue(site, site->GetName()); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::PreCollisionExecute(Stuff::Time till) { Check_Object(this); PRECOLLISION_LOGIC("MWMover"); Verify(executionState->GetState() != ExecutionStateEngine::NeverExecuteState); DetermineUV (GetTimeSlice (till)); BaseClass::PreCollisionExecute(till); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::DetermineUV (Stuff::Time slice) { Check_Object (this); Vehicle *vehicle = NULL; if (IsDerivedFrom(Vehicle::DefaultData)) vehicle = Cast_Object(Vehicle *, this); else if (myParentVehicle && myParentVehicle->IsDerivedFrom(Vehicle::DefaultData)) vehicle = Cast_Object(Vehicle *, myParentVehicle); if (!vehicle) return; Check_Object(vehicle); Stuff::Vector3D linearVelocity = vehicle->localSpaceVelocity.linearMotion; Stuff::Scalar forward = linearVelocity.GetForwardComponent(); if (Stuff::Small_Enough(forward)) return; const Vehicle__GameModel *model = vehicle->GetGameModel(); Check_Object(model); Stuff::Scalar treadLength = model->m_treadLength; if (treadLength<=0) return; Verify(treadLength); forward = forward*(Stuff::Scalar)(slice)/treadLength; // Treads move in the "backward" direction // as the vehicles move in the "forward" direction LTread(3,0) -= forward; RTread(3,0) -= forward; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWMover::ReactToDamageTaken(Stuff::Scalar damage_taken, const Adept::ReplicatorID& inflicting_entity, int weaponID, int damageType) { if (myParentVehicle != 0) { myParentVehicle->ReactToDamageTaken(damage_taken,inflicting_entity, weaponID, damageType); } }