#include "MW4Headers.hpp" #include "MWObject.hpp" #include "Subsystem.hpp" #include "Torso.hpp" #include "AnimationState.hpp" #include "MWDamageObject.hpp" #include "Weapon.hpp" #include "Sensor.hpp" #include "Beagle.hpp" #include "HeatManager.hpp" #include "AMS.hpp" #include "SearchLight.hpp" #include "Mech_AI.hpp" #include "MWMission.hpp" #include "gameinfo.hpp" #include "AI_Statistics.hpp" #include "obstacle.hpp" #include "ECM.hpp" #include "VehicleInterface.hpp" #include "SubsystemClassData.hpp" #include "MWApplication.hpp" #include "DamageDispatch.hpp" // MSL 5.02 SubSystems //#include "EnhancedOptics.hpp" #include "IFF_Jammer.hpp" #include "AdvancedGyro.hpp" #include #include #include #include #include #include #include #include extern int g_nMR; IdleEffectObject::IdleEffectObject() : Plug(Plug::DefaultData), idleEffect(NULL), siteSlot(NULL) {} //############################################################################# //############################### MWObject ############################## //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWObject::ClassData* MWObject::DefaultData = NULL; const Receiver::MessageEntry MWObject::MessageEntries[]= { MESSAGE_ENTRY(MWObject, TakeDamage) }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::InitializeClass() { Check_Object(MWMover::ExecutionStateEngine::DefaultData); Verify(!DefaultData); DefaultData = new ClassData( MWObjectClassID, "MechWarrior4::MWObject", BaseClass::DefaultData, ELEMENTS(MessageEntries), MessageEntries, (Entity::Factory)Make, (Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage, ExecutionStateEngine::DefaultData, (Entity::GameModel::Factory)GameModel::ConstructGameModel, (Entity::GameModel::Factory)GameModel::ConstructOBBStream, (Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify, (Entity::GameModel::ModelWrite)GameModel::WriteToText, (Entity::GameModel::ModelSave)GameModel::SaveGameModel, AnimationStateEngine::Make ); Register_Object(DefaultData); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, DeathEntityResource, deathEntityResource, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, DestroyedEffectResource, destroyedEffectResource, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, SecondaryDeathEntityResource, secondaryDeathEntityResource, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, SecondaryDestroyedEffectResource, secondaryDestroyedEffectResource, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, VehicleTonnage, vehicleTonnage, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, MaxVehicleTonnage, maxVehicleTonnage, Scalar ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, EyeSiteName, eyeSiteName, const char *, CharClassID ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, PartDestructionEffectResource, partDestructionEffectResource, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, SplashDamageRadius, splashDamageRadius, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, SplashDamageAmount, splashDamageAmount, Scalar ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, VehicleBattleValue, vehicleBattleValue, int, IntClassID ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, CoolantEffectResource, coolantEffectResource, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, SplashHeatAmount, splashHeatAmount, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, EjectEffectResource, ejectEffectResource, ResourceID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, NameIndex, m_nameIndex, int, IntClassID ); DIRECT_GAME_MODEL_ATTRIBUTE( MWObject__GameModel, OverHeatEffectResource, overHeatEffectResource, ResourceID ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWObject* MWObject::Make( CreateMessage *message, ReplicatorID *base_id ) { Check_Object(message); gos_PushCurrentHeap(Heap); MWObject *new_object = new MWObject(DefaultData, message, base_id, NULL); gos_PopCurrentHeap(); Check_Object(new_object); return new_object; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Replicator::CreateMessage* MWObject::SaveMakeMessage(MemoryStream *stream, ResourceFile *res_file) { Check_Object(this); Check_Object(stream); // //--------------------------------------------------------------------- // Make sure there is enough room for the factory request on the 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 subsystems //-------------------------------------------- // DynamicMemoryStream subsystem_stream(sizeof(WORD)); subsystem_stream << static_cast(0); ReplicatorID span = ReplicatorID::Null; ChainIteratorOf sub_iterator(&subsystemsInVehicle); Subsystem *subsystem; while((subsystem = sub_iterator.ReadAndNext()) != NULL) { Check_Object(subsystem); Replicator::CreateMessage *create_message = subsystem->SaveMakeMessage(&subsystem_stream, res_file); if (create_message) { Check_Object(create_message); span += create_message->replicatorID; subsystem_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 //------------------------------------------------------------------------- // //This stream must be written out to the current res_file and not core. if (subsystem_stream.GetBytesUsed() > sizeof(WORD)) { subsystem_stream.Rewind(); Verify(span.localID > 0); subsystem_stream << span.localID; MString sub_resource_name = instanceName; sub_resource_name += "{Subsystem}"; Resource subsystem_resource((const char *)sub_resource_name, res_file); subsystem_resource.Save(&subsystem_stream, NULL); Check_Object(&subsystem_resource); message->subsystemStreamResourceID = subsystem_resource.GetResourceID(); message->replicatorID += span; } else { message->subsystemStreamResourceID = ResourceID::Null; } // //------------------------------------------------------ //Need to save damage objects and Internal DamageObjects //------------------------------------------------------ // //We need to check if we have changed or not...if we have then save to the //the res file given...if not then we need to just do nothing becuase we are already //in the core file and just set the message message->damageStreamResourceID = damageStreamResourceID; if((m_hasExecuted) && (!m_markedForSalvage)) { DynamicMemoryStream damage_stream; DamageObject *damage_object; SortedChainIteratorOf damage_iterator(&damageObjects); damage_stream << damage_iterator.GetSize(); while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); damage_object->Save(&damage_stream); } MWInternalDamageObject *internal_damage_object; SortedChainIteratorOf internal_iterator(&internalDamageObjects); damage_stream << internal_iterator.GetSize(); while((internal_damage_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_damage_object); internal_damage_object->Save(&damage_stream); } // //------------------------------------------------------------------------- // If we actually wrote out some children, rewind the stream and save it to // the resource. Otherwise, just set the resourceID to NULL //------------------------------------------------------------------------- // if (damage_stream.GetBytesUsed()) { Resource damage_resource(NULL, res_file); damage_resource.Save(&damage_stream, NULL); Check_Object(&damage_resource); message->damageStreamResourceID = damage_resource.GetResourceID(); } else { message->damageStreamResourceID = ResourceID::Null; } } message->skinPrefix = m_skinPrefix; message->teamDecal = m_teamDecal; message->pilotDecal = m_pilotDecal; message->nameIndex = m_localizeIndex; message->doesHaveInstanceName = m_doesHaveInstanceName; return message; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::LoadSubsystemsFromResource( const ResourceID &subsystem_stream_id, ReplicatorID *base_id ) { Resource stream(subsystem_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); Subsystem *subsystem; subsystem = Cast_Object(Subsystem *, entity); //Dave here is where you want to do a apendparentname function if (subsystem->IsDerivedFrom(Torso::DefaultData)) { Torso* torso = Cast_Object(Torso*, subsystem); if (std::find(m_Torsos.begin(),m_Torsos.end(),torso) == m_Torsos.end()) { m_Torsos.push_back(torso); } } if (subsystem->IsDerivedFrom(SearchLight::DefaultData)) { searchLight = Cast_Object(SearchLight *, subsystem); } stream.AdvancePointer(message->messageLength); } //stream.UnloadData(); m_hasExecuted = false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::LoadDamageObjectsFromResource( const ResourceID &damage_stream_id ) { Resource stream(damage_stream_id); Verify(stream.DoesResourceExist()); while (stream.GetBytesRemaining() > 0) { RegisteredClass::ClassID class_id; stream >> class_id; RegisteredClass::ClassData *class_data = NULL; class_data = RegisteredClass::FindClassData(class_id); if(class_data == DamageObject::DefaultData) { DamageObject *damage_object; DamageObject::ClassData *damage_class_data = Cast_Pointer(DamageObject::ClassData*, class_data); gos_PushCurrentHeap(Heap); damage_object = new DamageObject( damage_class_data, &stream ); gos_PopCurrentHeap(); Check_Object(damage_object); damageObjects.AddValue(damage_object, damage_object->armorZone); } else { MWInternalDamageObject *internal_damage_object; MWInternalDamageObject::ClassData *damage_class_data = Cast_Pointer(MWInternalDamageObject::ClassData*, class_data); gos_PushCurrentHeap(Heap); internal_damage_object = new MWInternalDamageObject( damage_class_data, &stream ); gos_PopCurrentHeap(); Check_Object(internal_damage_object); internalDamageObjects.AddValue( internal_damage_object, internal_damage_object->damageZone); } } stream.UnloadData(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::LoadIdleEffectsFromResource(const ResourceID &effects_stream_id) { Resource stream(effects_stream_id); Verify(stream.DoesResourceExist()); while (stream.GetBytesRemaining() > 0) { IdleEffectObject *idle_effect_object; idle_effect_object = new IdleEffectObject(); stream >> idle_effect_object->effectResourceID; MString site_name; stream >> site_name; idle_effect_object->siteSlot.Remove(); Site *site_pointer = FindSite(site_name); Check_Object(site_pointer); idle_effect_object->siteSlot.Add(site_pointer); idle_effect_object->idleEffect.Remove(); Effect *idle_effect = CreateIdleEffect(idle_effect_object); Check_Object(idle_effect); idle_effect_object->idleEffect.Add(idle_effect); idleEffects.Add(idle_effect_object); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect* MWObject::CreateIdleEffect(IdleEffectObject *effect_object) { Check_Object(effect_object); if(effect_object->effectResourceID == ResourceID::Null) return NULL; Resource idle_resource(effect_object->effectResourceID); if(idle_resource.DoesResourceExist()) { ClassID class_ID; class_ID = GetClassIDFromDataListID(effect_object->effectResourceID); Verify(class_ID != NullClassID); LinearMatrix4D effect_position = LinearMatrix4D::Identity; UnitVector3D unit_forward; Site *site_pointer = effect_object->siteSlot.GetCurrent(); Check_Object(site_pointer); LinearMatrix4D site_position = site_pointer->GetLocalToWorld(); site_position.GetLocalForwardInWorld(&unit_forward); effect_position.AlignLocalAxisToWorldVector(unit_forward, Y_Axis, X_Axis, Z_Axis); Point3D effect_translation; effect_translation = site_pointer->GetLocalToWorld(); effect_position.BuildTranslation(effect_translation); Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags|Effect::LoopFlag, effect_object->effectResourceID, effect_position, 0.0f, ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Entity *entity; ReplicatorID effect_id = Connection::Hermit->GetNextReplicatorID(); entity = CreateEntity(&stream, &effect_id, false); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); Effect *effect; effect = Cast_Object(Effect *, entity); effect->SetFollowEntity(site_pointer); entity->SyncMatrices(true); return effect; } return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWObject::MWObject( ClassData *class_data, CreateMessage *message, ReplicatorID *base_id, ElementRenderer::Element *element ): MWMover(class_data, message, base_id, element), armatureChain(NULL), subsystemsInVehicle(NULL), executingSubsystems(NULL), damageObjects(NULL, false), internalDamageObjects(NULL, true), idleEffects(NULL), weaponChain(NULL), eyeSitePointer(NULL), sensor(NULL), beagle(NULL), ams(NULL), m_TargetDesirability(desirability_invalid), entitiesToSync(NULL), m_FindObjectCache(NULL), m_FindObjectList(NULL), m_VisibleOnSensors(true), splashedEntities(NULL), // MSL 5.02 SubSystems // enhancedOptics(NULL), advancedGyro(NULL), iff_jammer(NULL) { Check_Pointer(this); Check_Object(message); CommonCreation(message); m_AI = NULL; m_bHasAI = false; ecm = NULL; beagle = NULL; searchLight = NULL; vehicleInterface = NULL; invulnerable=false; m_markedForSalvage = false; m_localizeIndex = message->nameIndex; m_doesHaveInstanceName = message->doesHaveInstanceName; // //---------------------- // Create the subsystems //---------------------- // subsystemStreamResourceID = message->subsystemStreamResourceID; if(message->subsystemStreamResourceID != ResourceID::Null) { LoadSubsystemsFromResource( message->subsystemStreamResourceID, base_id ); } // //-------------------------- // Create the damage Objects //-------------------------- // damageStreamResourceID = message->damageStreamResourceID; if(message->damageStreamResourceID != ResourceID::Null) { LoadDamageObjectsFromResource( message->damageStreamResourceID ); } const GameModel *game_model = GetGameModel(); Check_Object(game_model); m_heatManager = NULL; m_skinPrefix = message->skinPrefix; m_pilotDecal = message->pilotDecal; m_teamDecal = message->teamDecal; MakeArmatureChain(); MakeAnimationArray(); ConnectDamageObjects(); HookUpSubsystems(); InitializeArmorArray (); // //------------------------ // Create the Idle Effects //------------------------ // if(game_model->idleEffectResourceID != ResourceID::Null) { LoadIdleEffectsFromResource(game_model->idleEffectResourceID); } // //------------------------------ // Load up the animation engines //------------------------------ // AnimationStateEngine::FactoryRequest request; request.currentState = AnimationStateEngine::UninitializedState; animStateEngine = (*((MWObject::ClassData*)GetClassData())->animationStateFactory)(this, &request); Register_Object(animStateEngine); const GameModel *model = GetGameModel(); Check_Object(model); MWApplication *app = MWApplication::GetInstance(); if (game_model->animScriptName[0] != NULL) { app->AddToAnimationLoadQue(this); } MWMover* eye = FindChildMover(model->eyeSiteName); if(eye) eyeSitePointer.Add(eye); originalCollisionMask = GetCollisionMask(); originalCullMode = GetElement()->GetCullMode(); jointRunningLight = NULL; jointRunningLight = FindChildMover("joint_runninglights"); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int temporaryQuickIDLookup[COMPRESS_JOINT_COUNT]; void MWObject::LoadAnimationScripts() { for (int i = 0; i < COMPRESS_JOINT_COUNT; ++i) { temporaryQuickIDLookup[i] = -1; } Stuff::ChainIteratorOf iterator(&armatureChain); MWMover *mover; i = 0; while ((mover = iterator.ReadAndNext()) != NULL) { MString temp; int index = MW4Animation::CompressName(mover->instanceName, temp); if (index != -1) { Verify(index < COMPRESS_JOINT_COUNT); Verify(index >= 0); temporaryQuickIDLookup[index] = i; } ++i; } const GameModel *model = GetGameModel(); Check_Object(model); if (model->animScriptName[0] != NULL && !animStateEngine->alreadyLoaded) { animStateEngine->LoadScript(model->animScriptName); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::InitializeArmorArray() { Check_Object(this); m_HitPoints = 0; SortedChainIteratorOf iter(&damageObjects); DamageObject *fred; while ((fred = iter.ReadAndNext ()) != NULL) { m_HitPoints += fred->currentArmorValue; if (fred->internalDamageObject) { m_HitPoints += fred->internalDamageObject->currentInternalDamage; fred->internalDamageObject->SetHitPointPointer (&m_HitPoints); } fred->SetHitPointPointer (&m_HitPoints); } if (m_HitPoints == 0) m_HitPoints = 1; m_MaxHitPoints = m_HitPoints; for(int i=0; i<12; i++) { armorArray[i] = -1.0f; DamageObject *damage_object = damageObjects.Find(i); if(damage_object) { armorArray[i] = damage_object->armorLevel; damage_object->SetArmorArrayEntry(&armorArray[i]); } else { armorArray[i] = -1; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::CommonCreation(CreateMessage *message) { Check_Object(this); Check_Object(message); for (int i=0;i<11;i++) armorArray[i] = -1.0f; const GameModel *game_model = GetGameModel(); Check_Object(game_model); vehicleShutDown = false; vehicleJustPoweredUp = false; animationVelocity = Vector3D::Identity; tonage = game_model->vehicleTonnage; battleValue = game_model->vehicleBattleValue; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::Respawn(Entity::CreateMessage *message) { Check_Object(this); Check_Object(message); BaseClass::Respawn(message); CreateMessage *object_message = Cast_Pointer(CreateMessage *, message); CommonCreation(object_message); animStateEngine->Reset(); // //----------------------------------------- //Load up the Damage Objects and Subsystems //----------------------------------------- // ReuseDamageObjects(); if(object_message->subsystemStreamResourceID != ResourceID::Null) { Resource stream(object_message->subsystemStreamResourceID); Verify(stream.DoesResourceExist()); ReuseSubsystems(&stream); } ReuseArmature(); // // If you set to NeverCullMode, it screws up the sphere sync method. // this results in splash damage not working after a respawn. // // entityElement->SetNeverCullMode(); GetElement()->SetCullMode(originalCullMode ); SetCollisionMask(originalCollisionMask); if (GetAI() != 0) { if (MechWarrior4::AI::GetGraveyard() != 0) { MechWarrior4::AI::GetGraveyard()->NotifyCreated(objectID); } GetAI()->NotifyRespawned(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWObject::~MWObject() { DESTRUCTOR("MWObject"); Unregister_Object(animStateEngine); delete animStateEngine; if (animationArray != NULL) { Unregister_Pointer(animationArray); delete[] animationArray; } if (lastTriggerArray != NULL) { Unregister_Pointer(lastTriggerArray); delete[] lastTriggerArray; } damageObjects.DeletePlugs(); internalDamageObjects.DeletePlugs(); idleEffects.DeletePlugs(); if(m_heatManager) delete m_heatManager; if (m_FindObjectCache) delete m_FindObjectCache; if (m_FindObjectList) delete m_FindObjectList; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::MakeAnimationArray() { Stuff::ChainIteratorOf iterator(&armatureChain); MWMover *mover; animationArrayCount = iterator.GetSize(); if (animationArrayCount == 0) { animationArray = NULL; lastTriggerArray = NULL; return; } animationArray = new MWMover *[animationArrayCount]; Register_Pointer(animationArray); lastTriggerArray = new int [animationArrayCount]; Register_Pointer(lastTriggerArray); for (int counter = 0; counter < animationArrayCount; counter++) { lastTriggerArray[counter] = 0; } int i = 0; while ((mover = iterator.ReadAndNext()) != NULL) { animationArray[i] = mover; i++; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::ApplyChannel ( MW4Animation::ChannelApplication &channel_data, int joint_index, void *user_data ) { MWObject *mw_object; mw_object = Cast_Object(MWObject*, user_data); Stuff::UnitQuaternion rotation; Stuff::Point3D position; LinearMatrix4D new_local_to_parent; MWMover *mover = mw_object->animationArray[joint_index]; Check_Object(mover); #if 0 const char *compare_name = mover->instanceName; if((compare_name = strstr(compare_name, "::")) != NULL) { compare_name += 2; } else { compare_name = mover->instanceName; } if(!_stricmp(mover->instanceName, "site_eyepoint")) { SPEW(("jerryeds", "Animation trying to mess with the eye...bad bad bad!!!!")); return; } #endif if (channel_data.hasTrigger) { if (channel_data.triggerValue != mw_object->lastTriggerArray[joint_index]) { mw_object->animationTriggerManager.DispatchTriggerMessage(joint_index, channel_data.triggerValue, mw_object); mw_object->lastTriggerArray[joint_index] = channel_data.triggerValue; } } if (channel_data.hasVelocity) { //channel_data.velocityValue.y = 0.0f; //channel_data.velocityValue.x = 0.0f; //position.y = channel_data.positionValue.y; //position.x = channel_data.positionValue.x; position = mover->GetLocalToParent(); mw_object->animationVelocity = channel_data.velocityValue; //vehicle->animationVelocity; } else { if (channel_data.hasPosition) { position = channel_data.positionValue; } else { position = mover->GetLocalToParent(); } } if (channel_data.hasAngularVelocity) { mw_object->instantaniousAngularVelocity = channel_data.angularVelocityValue; rotation = mover->GetLocalToParent(); } else { if (channel_data.hasRotation) { rotation = channel_data.rotationValue; } else { rotation = mover->GetLocalToParent(); } } Stuff::Scalar small_backup = Stuff::SMALL; Stuff::SMALL = 1e-3f; rotation.Normalize(); new_local_to_parent.BuildTranslation(position); new_local_to_parent.BuildRotation(rotation); #if defined(_ARMOR) new_local_to_parent.TestInstance(); #endif mover->SetNewLocalToParent(new_local_to_parent); Stuff::SMALL = small_backup; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::MakeArmatureChain() { Check_Object(this); ChainIteratorOf child_iterator(&childEntityChain); Entity *entity; // //Step Through until we find a root mover object // while((entity = child_iterator.ReadAndNext()) != NULL) { if(entity->IsDerivedFrom(MWMover::DefaultData)) { MWMover *mover; mover = Cast_Object(MWMover *, entity); ConnectMWMover(mover); entitiesToSync.Add(mover); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::ConnectMWMover(MWMover *mover) { Check_Object(this); ChainIteratorOf child_iterator(mover->GetChildEntityChain()); Entity *entity; while((entity = child_iterator.ReadAndNext()) != NULL) { if(entity->IsDerivedFrom(MWMover::DefaultData)) { MWMover *child_mover; child_mover = Cast_Object(MWMover *, entity); ConnectMWMover(child_mover); } } SortedChainIteratorOf site_iterator(&mover->m_sites); Site *site; while((site = site_iterator.ReadAndNext()) != NULL) { Check_Object(site); m_sites.AddValue(site, site->GetName()); } armatureChain.Add(mover); mover->myParentVehicle = this; mover->SetSkinPrefix(m_skinPrefix); mover->SetTeamDecal(m_teamDecal); mover->SetPilotDecal(m_pilotDecal); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MWObject::FindChildMoverIndexUserData( const char *joint_name, void *user_data ) { MWObject *mw_object = (MWObject *)user_data; Verify(mw_object->IsDerivedFrom(MWObject::DefaultData)); return mw_object->FindChildMoverIndex(joint_name); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MWObject::FindChildMoverIndex( const char *temp_name ) { MString joint_name; int index = MW4Animation::UncompressName(temp_name, joint_name); if (index != -1) { if (temporaryQuickIDLookup[index] != -1) { return temporaryQuickIDLookup[index]; } } else { Stuff::ChainIteratorOf iterator(&armatureChain); MWMover *mover; int i = 0; while ((mover = iterator.ReadAndNext()) != NULL) { Check_Object(mover); const char *compare_name = mover->instanceName; if (!_stricmp(compare_name, joint_name)) { Verify(mover == animationArray[i]); return i; } ++i; } } return -1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MWMover* MWObject::FindChildMover( const char *joint_name ) { Stuff::ChainIteratorOf iterator(&armatureChain); MWMover *mover; while ((mover = iterator.ReadAndNext()) != NULL) { Check_Object(mover); const char *compare_name = mover->instanceName; if((compare_name = strstr(compare_name, "::")) != NULL) { compare_name += 2; } else { compare_name = mover->instanceName; } if (!_stricmp(compare_name, joint_name)) { return mover; } } return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::ReuseDamageObjects() { Check_Pointer(this); SortedChainIteratorOf iterator(&damageObjects); SortedChainIteratorOf internal_iterator(&internalDamageObjects); DamageObject *damage_object; while((damage_object = iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); damage_object->Reuse(); } InternalDamageObject *internal_object; while((internal_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_object); internal_object->Reuse(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::ConnectDamageObjects() { Check_Pointer(this); SortedChainIteratorOf iterator(&damageObjects); SortedChainIteratorOf internal_iterator(&internalDamageObjects); DamageObject *damage_object; while((damage_object = iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); MWMover *mover; mover = FindChildMover(damage_object->damageObjectName); if(mover) { Check_Object(mover); // //----------------------------------------------- //Assign Damage Object its internal damage object //----------------------------------------------- // damage_object->internalDamageObject = internalDamageObjects.Find(damage_object->internalDamageObjectID); Check_Object(damage_object->internalDamageObject); damage_object->internalDamageObject->parentEntity = FindChildMover(damage_object->internalDamageObject->parentEntityName); damage_object->internalDamageObject->damagePropagationObject = internalDamageObjects.Find(damage_object->internalDamageObject->damagePropagationZoneID); mover->SetDamageObject(damage_object); damage_object->Initialize(mover); } else { // //------------------------------------------------------- //No Name means it is tied to us not part of the armature //------------------------------------------------------- // damage_object->internalDamageObject = internalDamageObjects.Find(damage_object->internalDamageObjectID); Check_Object(damage_object->internalDamageObject); damage_object->internalDamageObject->parentEntity = this; damage_object->internalDamageObject->damagePropagationObject = internalDamageObjects.Find(damage_object->internalDamageObject->damagePropagationZoneID); SetDamageObject(damage_object); damage_object->Initialize(this); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::AddChild(Entity *entity) { Check_Object(this); Check_Object(entity); Entity::AddChild(entity); if (entity->IsDerivedFrom(MWMover::DefaultData)) { //We must make sure that we are on the armature chain if(!armatureChain.IsPlugMember(entity)) { MWMover *mover; mover = Cast_Object(MWMover *, entity); armatureChain.Add(mover); } } if(entity->IsDerivedFrom(Subsystem::DefaultData)) { if(!subsystemsInVehicle.IsPlugMember(entity)) { Subsystem *subsystem; subsystem = Cast_Object(Subsystem *, entity); subsystemsInVehicle.Add(subsystem); if(subsystem->executionState->GetState() != ExecutionStateEngine::NeverExecuteState) { executingSubsystems.Add(subsystem); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::RemoveChild(Entity *entity) { Check_Object(this); Check_Object(entity); if(entity->IsDerivedFrom(Subsystem::DefaultData)) { Subsystem *subsystem; subsystem = Cast_Object(Subsystem *, entity); subsystemsInVehicle.Remove(subsystem); executingSubsystems.Remove(subsystem); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::ChildPreCollisionChanged(Entity *entity) { Check_Object(this); Check_Object(entity); if(entity->IsDerivedFrom(Subsystem::DefaultData)) { Subsystem *subsystem; subsystem = Cast_Object(Subsystem *, entity); if((subsystem->executionState->GetOldState() == ExecutionStateEngine::NeverExecuteState) &&(subsystem->executionState->GetState() != ExecutionStateEngine::NeverExecuteState)) { executingSubsystems.Add(subsystem); } else if((subsystem->executionState->GetOldState() != ExecutionStateEngine::NeverExecuteState) &&(subsystem->executionState->GetState() == ExecutionStateEngine::NeverExecuteState)) { executingSubsystems.Remove(subsystem); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // static Entity* Find_Child( Entity *parent, const char* name ) { Check_Object(parent); Check_Pointer(name); return Cast_Object(MWObject*, parent)->FindChildMover(name); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::BecomeInteresting(bool render_me) { Check_Object(this); LOAD_LOGIC("Become Interesting::MWObject"); // //------------------------------------------------------------------------ // The entity version will just load the solid volumes. Go ahead and load // the stream resource that should be indicated in the game model //------------------------------------------------------------------------ // if (!solidVolume && !hierarchicalVolume) { const GameModel *game_model = GetGameModel(); Check_Object(game_model); // //------------------------------- // Load in the solid if it exists //------------------------------- // #if defined(LAB_ONLY) extern char g_LastEntity[255]; if (!instanceName) g_LastEntity[0] = '\0'; else { strncpy(g_LastEntity, instanceName, sizeof(g_LastEntity)-1); g_LastEntity[sizeof(g_LastEntity)-1] = '\0'; } #endif if (game_model->obbStreamResourceID != ResourceID::Null) { gos_PushCurrentHeap(Adept::Entity::s_CollisionHeap); Resource obb_stream(game_model->obbStreamResourceID); Verify(obb_stream.DoesResourceExist()); solidVolume = new CollisionVolume( this, &obb_stream, CollisionVolume::ReadOBBVersion(&obb_stream) ); Check_Object(solidVolume); gos_PopCurrentHeap(); } if (game_model->hierarchicalOBBStreamResourceID != ResourceID::Null) { gos_PushCurrentHeap(Adept::Entity::s_CollisionHeap); Resource obb_stream(game_model->hierarchicalOBBStreamResourceID); Verify(obb_stream.DoesResourceExist()); if (!armatureChain.IsEmpty()) { hierarchicalVolume = new CollisionVolume( this, Find_Child, this, &obb_stream, CollisionVolume::ReadOBBVersion(&obb_stream) ); Check_Object(hierarchicalVolume); } else { #ifdef LAB_ONLY PAUSE(("Error: %s is missing its armature!", (char*)instanceName)); #endif if (!solidVolume) { solidVolume = new CollisionVolume( this, &obb_stream, CollisionVolume::ReadOBBVersion(&obb_stream) ); Check_Object(solidVolume); } } gos_PopCurrentHeap(); } } if(!Mission::GetInstance()->DoesAllowRunningLights()) { DestroyRunningLight(); } BaseClass::BecomeInteresting(render_me); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::CheckVideoStates(bool render_me) { if(render_me && IsDestroyed()) { entityElement->SetAlwaysCullMode(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::DestroyRunningLight() { Check_Object(this); if(jointRunningLight) { Check_Object(jointRunningLight); jointRunningLight->GetElement()->SetAlwaysCullMode(); if(jointRunningLight->GetSolidVolume() && !jointRunningLight->GetSolidVolume()->IsDestroyed()) jointRunningLight->GetSolidVolume()->Destroy(); if(jointRunningLight->GetHierarchicalVolume() && !jointRunningLight->GetHierarchicalVolume()->IsDestroyed()) jointRunningLight->GetHierarchicalVolume()->Destroy(); // jointRunningLight->GetElement()->SetAlwaysCullMode(); // jointRunningLight->SetDestroyedFlag(InternalDamageObject::DestructionDamageMode); // jointRunningLight->SentenceToDeathRow(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::ReuseSubsystems(MemoryStream *stream) { Check_Pointer(this); Stuff::ChainIteratorOf iterator(&subsystemsInVehicle); Subsystem *subsystem; stream->AdvancePointer(sizeof(WORD)); while (((subsystem = iterator.ReadAndNext()) != NULL) && (stream->GetBytesRemaining() > 0)) { Verify(subsystem->IsDerivedFrom(Subsystem::DefaultData)); Entity::CreateMessage *message = Cast_Pointer(Entity::CreateMessage*, stream->GetPointer()); subsystem->Respawn(message); // MSL 5.02 headshot // bug fix: didn't re-hook these up - note we are explicitly calling the MWObject version MWObject::AddSubsystem(subsystem); stream->AdvancePointer(message->messageLength); } if(sensor) { sensor->SetSensorMode(Sensor::ActiveMode, DoesHaveBeagle()); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::HookUpSubsystems() { Stuff::ChainIteratorOf iterator(&subsystemsInVehicle); Subsystem *subsystem; int weapon_id = 0; while ((subsystem = iterator.ReadAndNext()) != NULL) { Verify(subsystem->IsDerivedFrom(Subsystem::DefaultData)); if(subsystem->ConnectSubsystem()) { // //----------------------------------------------- //Connect the weapons to the correct weapon group //----------------------------------------------- // if(subsystem->IsDerivedFrom(Weapon::DefaultData)) { Weapon *weapon; weapon = Cast_Object(Weapon *, subsystem); weaponChain.Add(weapon); weapon->SetWeaponID(weapon_id); ++weapon_id; } AddSubsystem(subsystem); } else { RemoveChild(subsystem); } } if(sensor) { sensor->SetSensorMode(Sensor::ActiveMode, DoesHaveBeagle()); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::AddSubsystem(Subsystem *subsystem) { Check_Object(this); Check_Object(subsystem); if(subsystem->IsDerivedFrom(Sensor::DefaultData)) { sensor = Cast_Object(Sensor *, subsystem); } else if (subsystem->IsDerivedFrom(Beagle::DefaultData)) { beagle = Cast_Object(Beagle *, subsystem); } else if (subsystem->IsDerivedFrom(AMS::DefaultData)) { ams = Cast_Object(AMS *, subsystem); } else if(subsystem->IsDerivedFrom(ECM::DefaultData)) { ecm = Cast_Object(ECM *, subsystem); } // MSL 5.02 SubSystems // else if(subsystem->IsDerivedFrom(EnhancedOptics::DefaultData)) // { // enhancedOptics = Cast_Object(EnhancedOptics *, subsystem); // } else if(subsystem->IsDerivedFrom(IFF_Jammer::DefaultData)) { iff_jammer = Cast_Object(IFF_Jammer *, subsystem); } else if(subsystem->IsDerivedFrom(AdvancedGyro::DefaultData)) { advancedGyro = Cast_Object(AdvancedGyro *, subsystem); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::RemoveSubsystem(Subsystem *subsystem) { Check_Object(this); Check_Object(subsystem); if(subsystem->IsDerivedFrom(Weapon::DefaultData)) { Weapon *weapon; weapon = Cast_Object(Weapon *, subsystem); weaponChain.Remove(weapon); } else if(subsystem->IsDerivedFrom(Sensor::DefaultData)) { sensor = NULL; } else if (subsystem->IsDerivedFrom(Beagle::DefaultData)) { beagle = NULL; } else if (subsystem->IsDerivedFrom(AMS::DefaultData)) { ams = NULL; } else if(subsystem->IsDerivedFrom(ECM::DefaultData)) { ecm = NULL; } // MSL 5.02 SubSystems // else if(subsystem->IsDerivedFrom(EnhancedOptics::DefaultData)) // { // enhancedOptics = NULL; // } else if(subsystem->IsDerivedFrom(IFF_Jammer::DefaultData)) { iff_jammer = NULL; } else if(subsystem->IsDerivedFrom(AdvancedGyro::DefaultData)) { advancedGyro = NULL; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::ReactToDestruction(int damage_mode, int damage_type) { Check_Object(this); switch(damage_mode) { case InternalDamageObject::DestructionDamageMode: { if(!IsDestroyed()) { Check_Object(executionState); // executionState->RequestState(ExecutionStateEngine::DestroyedState); if(m_AI) { Check_Object(m_AI); m_AI->Die(); } else { MW4AI::g_Rect4DHash->RemovePermRect (this); } SetDestroyedFlag(damage_mode); if (damage_type != SplashDamageType) DealSplashDamage(); const GameModel *model = GetGameModel(); Check_Object(model); CreateEffect(model->destroyedEffectResource, this, false); if(!m_deathEntity.GetCurrent()) { Entity *death_entity = CreateStaticHermitEntity(model->deathEntityResource); if(death_entity) { m_deathEntity.Remove(); m_deathEntity.Add(death_entity); } } RemoveFromExecution(); // SentenceToDeathRow(); DestroyChildren(damage_mode); break; } } } Entity::ReactToDestruction(damage_mode, damage_type); #ifdef LAB_ONLY if (MW4AI::Statistics::Enabled() == true) { MW4AI::Statistics::NotifyDestroyed(objectID); } #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::DestroyDamageObjects() { SortedChainIteratorOf iterator(&damageObjects); SortedChainIteratorOf internal_iterator(&internalDamageObjects); DamageObject *damage_object; while((damage_object = iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); damage_object->SilentDestruction(); } InternalDamageObject *internal_object; while((internal_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_object); internal_object->SilentDestruction(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::DealSplashDamage() { Check_Object(this); Check_Object(CollisionGrid::Instance); extern g_nMR; if (g_nMR == 2) return; if (!Network::GetInstance()->AmIServer()) return; NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if (!params->m_splashOn) return; const GameModel *model = GetGameModel(); Check_Object(model); Verify(splashedEntities.IsEmpty()); splashSize = 0; if (model->splashDamageAmount > 0.0f) { // // Need to see if the target has a solid volume and if so, use that for the positioning of the target // bracket. CollisionVolume * volume; // // This code was just getting the torso and using that local to world but the torso location // was whacked. That should be fixed as a secondary issue, but for here the solid volume is // good since that is what would be doing ramming damage, etc... anyway. // volume = GetSolidVolume(); if (!volume) { if (GetTorso()) volume = GetTorso()->GetHierarchicalVolume(); else volume = GetHierarchicalVolume(); } Stuff::Sphere sphere; if (volume) { OBB world_bounds; world_bounds.Multiply(volume->m_localSpaceBounds, GetLocalToWorld()); sphere.center = world_bounds.localToParent; } else { sphere.center = GetLocalToWorld(); } sphere.radius = model->splashDamageRadius; splashSize = 0; CollisionGrid::Instance->FindEntitiesWithin(sphere, (Adept::CollisionGrid::WithinCallback)SplashCallBack, this); if (splashSize == 0) return; ChainIteratorOf splashed_entities(&splashedEntities); // // First, iterate through the list once to clear the been hit flag so we don't do // double/or more damage to multiple entities, connected to the same damage zones // Entity *hit_entity; while((hit_entity = splashed_entities.ReadAndNext()) != NULL) { if (hit_entity->damageObject) hit_entity->damageObject->ClearTakenDamageFromThisEvent(); } splashed_entities.First(); NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); while((hit_entity = splashed_entities.GetCurrent()) != NULL) { if (hit_entity->damageObject) { // // If there is a damage object verify we aren't hitting it twice // if (!hit_entity->damageObject->GetTakenDamageFromThisEvent()) { hit_entity->damageObject->SetTakenDamageFromThisEvent() ; } else { splashed_entities.Remove(); continue; } } Stuff::Point3D ltwEntity; ltwEntity = hit_entity->GetLocalToWorld(); // MSL 5.06 Armor Mode MWApplication *m_App; m_App = MWApplication::GetInstance (); m_ArmorMode = m_App->GetLocalNetParams()->m_armormodeOn; Adept::Entity__TakeDamageMessage message( hit_entity->GetReplicatorID(), this->GetReplicatorID(), model->splashDamageAmount * ((Scalar)params->m_splashPercentage*0.01f), m_ArmorMode, SplashDamageType, Normal3D(0.0f, 0.0f, 1.0f), ltwEntity, model->splashHeatAmount, false, TakeDamageMessage::DefaultWeaponType ); hit_entity->Receive(&message); splashed_entities.Remove(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::SplashCallBack(Adept::Entity *entity, Adept::Entity *original_caller, const Stuff::Sphere &sphere) { Check_Object(entity); Check_Object(original_caller); MWObject *mwobject = Cast_Object( MWObject*, original_caller); if (!entity->IsDestroyed()) { CollisionVolume *volume = entity->GetHierarchicalVolume(); if (volume) { volume->FindSolidsWithin( sphere, (Adept::CollisionVolume::WithinCallback)SubSplashCallBack, mwobject, entity, entity->GetLocalToWorld() ); } else { mwobject->splashedEntities.Add(entity); ++mwobject->splashSize; } } } void MWObject::SubSplashCallBack(CollisionVolume *solid, Entity *original_caller, const Stuff::Sphere &sphere) { Check_Object(solid); Check_Object(original_caller); MWObject *mwobject = Cast_Object( MWObject*, original_caller); if (solid->m_entity && !solid->m_entity->IsDestroyed()) { mwobject->splashedEntities.Add(solid->m_entity); ++mwobject->splashSize; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::TakeSplashDamage(Adept::Entity__TakeDamageMessage *message) { Check_Object(this); Check_Object(CollisionGrid::Instance); // go thru my damage objects and deal the damage SortedChainIteratorOf damage_iterator(&damageObjects); DamageObject *damage_object; while((damage_object = damage_iterator.ReadAndNext()) != NULL) { damage_object->TakeDamage(message, NULL); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::RemoveFromExecution() { Check_Object(this); Check_Object(entityElement); Check_Object(executionState); if (newCollisions) { delete newCollisions; newCollisions = NULL; } executionState->RequestState(ExecutionStateEngine::NeverExecuteState); entityElement->SetAlwaysCullMode(); EntityManager::GetInstance()->RemovePostCollisionExecution(this); RemoveCollision(); SyncMatrices(true); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::PreCollisionExecute(Stuff::Time till) { Check_Object(this); PRECOLLISION_LOGIC("MWObject"); m_hasExecuted = true; #if defined(LAB_ONLY) if (!instanceName) MWGameInfo::g_LastMWObject[0] = '\0'; else { strncpy(MWGameInfo::g_LastMWObject, instanceName, sizeof(MWGameInfo::g_LastMWObject)-1); MWGameInfo::g_LastMWObject[sizeof(MWGameInfo::g_LastMWObject)-1] = '\0'; } MWGameInfo::g_LastMWObjectPos = GetLocalToWorld(); #endif // //---------------------------------------------- // All MWObjects that execute use post collision //---------------------------------------------- // UsePostCollision(); BaseClass::PreCollisionExecute(till); // //------------------------------------------------- // Run the ubsystems, then finally the heat manager //------------------------------------------------- // { ChainIteratorOf sub_iterator(&executingSubsystems); Subsystem *subsystem; while((subsystem = sub_iterator.ReadAndNext()) != NULL) { Check_Object(subsystem); subsystem->PreCollisionExecute(till); Verify(!subsystem->IsUsingPostCollision() || EntityManager::GetInstance()->IsInPostCollisionExecution(subsystem)); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::SyncMatrices(bool update_matrix) { Check_Object(this); SYNC_LOGIC("MWObject"); #if defined(HUNT_BUG) bool old_update=update_matrix; if (update_matrix) { SPEW((0, "MWObject::SyncMatrices %s(+", GetClassString())); Spew(0, GetReplicatorID()); SPEW((0, ")")); } #endif Set_Statistic(s_EntitiesSynced, s_EntitiesSynced); // //----------------------------------------- // If we have a dirty locator, sync with it //----------------------------------------- // if (IsMatrixDirty()) { if (update_matrix) { Check_Object(entityElement); entityElement->Sync(); update_matrix = false; } ClearNeedMatrixSync(); } // //----------------------------- // Sync our children's locators //----------------------------- // if (!entitiesToSync.IsEmpty()) { ChainIteratorOf children(&entitiesToSync); Entity *child; while ((child = children.ReadAndNext()) != NULL) { Check_Object(child); child->SyncMatrices(update_matrix); } } #if defined(HUNT_BUG) if (old_update) SPEW((0, "")); #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::PostCollisionExecute(Time till) { Check_Object(this); Check_Object(executionState); POSTCOLLISION_LOGIC("MWObject"); {for (std::vector::iterator i = m_Torsos.begin(); i != m_Torsos.end(); ++i) { if ((*i)->followTorsoRequest) { gosREPORT(*i,"somehow a mwobject got a follow torso request when it has no torso"); Check_Object(*i); Point3D target_position = (*i)->torsoRequest; Point3D distance_to_target; distance_to_target.MultiplyByInverse(target_position,(*i)->GetTwistJointMatrix()); #if 0 MWMover *eye_site = eyeSitePointer.GetCurrent(); YawPitchRoll twist_offset = YawPitchRoll::Identity; Point3D local_eye_site_offset_pitch = Point3D::Identity; Point3D local_eye_site_offset_twist = Point3D::Identity; if(eye_site) { Check_Object(eye_site); Point3D world_eye_site = (Point3D) eye_site->GetLocalToWorld(); // LinearMatrix4D world_eye_site = eye_site->GetLocalToWorld(); // world_eye_site.Invert(); // LinearMatrix4D local_eye_site_offset = LinearMatrix4D::Identity; local_eye_site_offset_twist.MultiplyByInverse(world_eye_site, (*i)->GetTwistJointMatrix()); local_eye_site_offset_pitch.MultiplyByInverse(world_eye_site, (*i)->GetPitchJointMatrix()); // twist_offset = (YawPitchRoll) local_eye_site_offset; } #endif Scalar heading_adjustment; Point3D distance_to_target_pitch; distance_to_target_pitch.MultiplyByInverse(target_position,(*i)->GetPitchJointMatrix()); if(!Small_Enough(distance_to_target_pitch.z)) { // heading_adjustment = Arctan(distance_to_target_pitch.y, distance_to_target_pitch.z) - (Arctan(local_eye_site_offset_pitch.y, local_eye_site_offset_pitch.z));; heading_adjustment = Arctan(distance_to_target_pitch.y, distance_to_target_pitch.z); if(!Small_Enough(heading_adjustment)) { Scalar speed_demand; if (heading_adjustment > (*i)->GetPitchSpeed()) { speed_demand = 1.0; } else { speed_demand = heading_adjustment / (*i)->GetPitchSpeed(); speed_demand = Abs(speed_demand); } if(heading_adjustment > 0.02) // down (*i)->pitchDemand = -speed_demand; if(heading_adjustment < -0.02) // up (*i)->pitchDemand = speed_demand; } } #if 0 if(eye_site) { Check_Object(eye_site); Point3D world_eye_site = (Point3D) eye_site->GetLocalToWorld(); // LinearMatrix4D world_eye_site = eye_site->GetLocalToWorld(); // world_eye_site.Invert(); // LinearMatrix4D local_eye_site_offset = LinearMatrix4D::Identity; local_eye_site_offset_twist.MultiplyByInverse(world_eye_site, (*i)->GetTwistJointMatrix()); local_eye_site_offset_pitch.MultiplyByInverse(world_eye_site, (*i)->GetPitchJointMatrix()); // twist_offset = (YawPitchRoll) local_eye_site_offset; } #endif if(!Small_Enough(distance_to_target.z)) { // heading_adjustment = (Arctan(distance_to_target.x, distance_to_target.z)) + twist_offset.yaw; // heading_adjustment = (Arctan(distance_to_target.x, distance_to_target.z)) - (Arctan(local_eye_site_offset_twist.x, local_eye_site_offset_twist.z)); heading_adjustment = (Arctan(distance_to_target.x, distance_to_target.z)); if(!Small_Enough(heading_adjustment)) { Scalar speed_demand; if (heading_adjustment > (*i)->GetTwistSpeed()) { speed_demand = 1.0; } else { speed_demand = heading_adjustment / (*i)->GetTwistSpeed(); speed_demand = Abs(speed_demand); } if(heading_adjustment > 0.02) //left (*i)->yawDemand = speed_demand; if(heading_adjustment < -0.02) //right (*i)->yawDemand = -speed_demand; } } } }} BaseClass::PostCollisionExecute(till); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect* MWObject::CreateEffect(const Adept::ResourceID& effect_id, MWMover *parent_part, bool follow_joint) { if (effect_id == ResourceID::Null) return NULL; Resource resource(effect_id); Verify(resource.DoesResourceExist()); ClassID class_ID; class_ID = Entity::GetClassIDFromDataListID(effect_id); Verify(class_ID != NullClassID); LinearMatrix4D effect_location = GetLocalToWorld(); if(parent_part) { Check_Object(parent_part); effect_location = parent_part->GetLocalToWorld(); } Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, Entity::CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags, effect_id, effect_location, 0.0f, Entity::ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Effect *entity; ReplicatorID effect_rep_id = Connection::Hermit->GetNextReplicatorID(); entity = Cast_Object(Effect *,Entity::CreateEntity(&stream, &effect_rep_id, false)); Check_Object(entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); if (parent_part != NULL && follow_joint) { entity->SetFollowEntity(parent_part); entity->PlaceOnEntity(); } entity->SyncMatrices(true); return entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect* MWObject::CreateEffect(const Adept::ResourceID& effect_id, Site *parent_part, bool follow_joint) { if (effect_id == ResourceID::Null) return NULL; Resource resource(effect_id); Verify(resource.DoesResourceExist()); ClassID class_ID; class_ID = Entity::GetClassIDFromDataListID(effect_id); Verify(class_ID != NullClassID); LinearMatrix4D effect_location = GetLocalToWorld(); if(parent_part) { Check_Object(parent_part); effect_location = parent_part->GetLocalToWorld(); } Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, Entity::CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags, effect_id, effect_location, 0.0f, Entity::ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Effect *entity; ReplicatorID effect_rep_id = Connection::Hermit->GetNextReplicatorID(); entity = Cast_Object(Effect *,Entity::CreateEntity(&stream, &effect_rep_id, false)); Check_Object(entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); if (parent_part != NULL && follow_joint) { entity->SetFollowEntity(parent_part); entity->PlaceOnSite(); } entity->SyncMatrices(true); return entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect* MWObject::CreateLoopingEffect(const Adept::ResourceID& effect_id, MWMover *parent_part, bool follow_joint) { if (effect_id == ResourceID::Null) return NULL; Resource resource(effect_id); Verify(resource.DoesResourceExist()); ClassID class_ID; class_ID = Entity::GetClassIDFromDataListID(effect_id); Verify(class_ID != NullClassID); LinearMatrix4D effect_location = GetLocalToWorld(); if(parent_part) { Check_Object(parent_part); effect_location = parent_part->GetLocalToWorld(); } Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, Entity::CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags|Effect::LoopFlag, effect_id, effect_location, 0.0f, Entity::ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Effect *entity; ReplicatorID effect_rep_id = Connection::Hermit->GetNextReplicatorID(); entity = Cast_Object(Effect *,Entity::CreateEntity(&stream, &effect_rep_id, false)); Check_Object(entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); if (parent_part != NULL && follow_joint) { entity->SetFollowEntity(parent_part); entity->PlaceOnEntity(); } entity->SyncMatrices(true); return entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect* MWObject::CreateLoopingEffect(const Adept::ResourceID& effect_id, const Point3D &location) { if (effect_id == ResourceID::Null) return NULL; Resource resource(effect_id); Verify(resource.DoesResourceExist()); ClassID class_ID; class_ID = Entity::GetClassIDFromDataListID(effect_id); Verify(class_ID != NullClassID); LinearMatrix4D effect_location = LinearMatrix4D::Identity; effect_location.BuildTranslation(location); Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, Entity::CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags|Effect::LoopFlag, effect_id, effect_location, 0.0f, Entity::ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Effect *entity; ReplicatorID effect_rep_id = Connection::Hermit->GetNextReplicatorID(); entity = Cast_Object(Effect *,Entity::CreateEntity(&stream, &effect_rep_id, false)); Check_Object(entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); entity->SyncMatrices(true); return entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect* MWObject::CreateLoopingEffect(const Adept::ResourceID& effect_id, Site *parent_part, bool follow_joint) { if (effect_id == ResourceID::Null) return NULL; Resource resource(effect_id); Verify(resource.DoesResourceExist()); ClassID class_ID; class_ID = Entity::GetClassIDFromDataListID(effect_id); Verify(class_ID != NullClassID); LinearMatrix4D effect_location = GetLocalToWorld(); if(parent_part) { Check_Object(parent_part); effect_location = parent_part->GetLocalToWorld(); } Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, Entity::CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags|Effect::LoopFlag, effect_id, effect_location, 0.0f, Entity::ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Effect *entity; ReplicatorID effect_rep_id = Connection::Hermit->GetNextReplicatorID(); entity = Cast_Object(Effect *,Entity::CreateEntity(&stream, &effect_rep_id, false)); Check_Object(entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); if (parent_part != NULL && follow_joint) { entity->SetFollowEntity(parent_part); entity->PlaceOnSite(); } entity->SyncMatrices(true); return entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect* MWObject::CreateEffect(const Adept::ResourceID& effect_id, const Point3D &location) { if (effect_id == ResourceID::Null) return NULL; Resource resource(effect_id); Verify(resource.DoesResourceExist()); ClassID class_ID; class_ID = Entity::GetClassIDFromDataListID(effect_id); Verify(class_ID != NullClassID); LinearMatrix4D effect_location = LinearMatrix4D::Identity; effect_location.BuildTranslation(location); Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, Entity::CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags, effect_id, effect_location, 0.0f, Entity::ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Effect *entity; ReplicatorID effect_rep_id = Connection::Hermit->GetNextReplicatorID(); entity = Cast_Object(Effect *,Entity::CreateEntity(&stream, &effect_rep_id, false)); Check_Object(entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); entity->SyncMatrices(true); return entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // MSL 5.03 Glass Effect* MWObject::CreateEffect(const Adept::ResourceID& effect_id, const Point3D &location, const Vector3D &vector) { if (effect_id == ResourceID::Null) return NULL; Resource resource(effect_id); Verify(resource.DoesResourceExist()); ClassID class_ID; class_ID = Entity::GetClassIDFromDataListID(effect_id); Verify(class_ID != NullClassID); LinearMatrix4D effect_location = LinearMatrix4D::Identity; effect_location.AlignLocalAxisToWorldVector(vector, Y_Axis, X_Axis, Z_Axis); effect_location.BuildTranslation(location); Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, Entity::CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags, effect_id, effect_location, 0.0f, Entity::ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Effect *entity; ReplicatorID effect_rep_id = Connection::Hermit->GetNextReplicatorID(); entity = Cast_Object(Effect *,Entity::CreateEntity(&stream, &effect_rep_id, false)); Check_Object(entity); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); entity->SyncMatrices(true); return entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Entity * MWObject::CreateStaticHermitEntity(ResourceID entity_id) { if(entity_id == ResourceID::Null) return false; ClassID class_ID; class_ID = GetClassIDFromDataListID(entity_id); Verify(class_ID != NullClassID); unsigned flags = HermitMode; Entity::CreateMessage entity_create_message( sizeof(Entity::CreateMessage), DefaultEventPriority, CreateMessage::DefaultFlags, class_ID, flags, entity_id, GetLocalToWorld(), 0.0f, ExecutionStateEngine::NeverExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&entity_create_message, entity_create_message.messageLength); Entity *entity; ReplicatorID beam_id = Connection::Hermit->GetNextReplicatorID(); entity = CreateEntity(&stream, &beam_id, false); Check_Object(entity); entity->SetPropType(MissionPropType); Map::GetInstance()->AddChild(entity); entity->SyncMatrices(true); return entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } void MWObject::AttachAI (AI *ai) { Check_Object (this); if (ai != 0) { Check_Object (ai); } m_AI = ai; } void MWObject::SentenceToDeathRow() { Check_Object(this); if (m_AI) m_AI->SentenceToDeathRow (); BaseClass::SentenceToDeathRow (); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // const MWObject::GroupList& MWObject::GetGroups() const { return m_groups; } MWObject::GroupList& MWObject::GetGroups() { return m_groups; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int MWObject::GetSensorMode() { Check_Object(this); if(sensor) { Check_Object(sensor); return sensor->sensorMode; } return Sensor::ActiveMode; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MWObject::DoesHaveBeagle() { Check_Object(this); if(beagle) return true; return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::AddStatsToString(std::string& s) { s += instanceName; if ((DamageDispatch::GetGlobalInvulnerability() == true) && (IsPlayerVehicle() == true)) { s += " (INVULNERABLE)"; } if (GetTargetDesirability() == desirability_never) { s += " (IGNORE)"; } if (IsDestroyed() == true) { s += " (DEAD)"; } char temp[80]; if(isPlayerVehicle) { if(VehicleInterface::GetInstance()) { s += "\nTARGETMATERIAL: "; int material_num = VehicleInterface::GetInstance()->targetQuery.m_material; const char *material = MaterialTypeAsciiToText(material_num); sprintf(temp,"%s\n",(char *)material); s += temp; } } s += "\nTONNAGE: "; sprintf(temp,"%d",(int)GetTonage()); s += temp; s += "\nBATTLEVALUE: "; sprintf(temp,"%d",(int)GetBattleValue()); s += temp; s += "\nHEAT: "; if(m_heatManager) sprintf(temp,"%f",m_heatManager->GetHeat()); else sprintf(temp,"NA"); s += temp; s += "\nCOOLANT: "; if(m_heatManager) sprintf(temp,"%f",m_heatManager->GetCoolant()); else sprintf(temp, "NA"); s += temp; s += "\nPOSITION: x="; Point3D pos = (Point3D)GetLocalToWorld(); s += ScalarToString(pos.x); s += ", z="; s += ScalarToString(pos.z); s += "\n"; if (GetTorso() != 0) { s += "Torso: y="; sprintf(temp,"%.2f p=%.2f\n",GetTorso()->yawValue,GetTorso()->pitchValue); s += temp; } if (GetTargetDesirability() >= 0) { sprintf(temp,"Target Desirability: %d\n",(int)(GetTargetDesirability() * 100)); s += temp; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::AddDamageInfoToString(std::string& s) { Check_Object(this); char temp[80]; SortedChainIteratorOf internal_iterator(&internalDamageObjects); SortedChainIteratorOf damage_iterator(&damageObjects); s += "\nARMOR\n"; DamageObject *damage_object; while((damage_object = damage_iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); s += damage_object->damageObjectName; sprintf(temp, "base: %.2f current: %.2f\n", damage_object->baseArmorValue, damage_object->currentArmorValue); s += temp; } s += "\nINTERNAL\n"; MWInternalDamageObject *internal_object; while((internal_object = internal_iterator.ReadAndNext()) != NULL) { Check_Object(internal_object); s += InternalDamageObject::InternalZoneAsciiToText(internal_object->damageZone); sprintf(temp, "Mode: %s\n", InternalDamageObject::DamageModeAsciiToText(internal_object->damageMode)); s += temp; sprintf(temp, "base: %.2f current: %.2f\n", internal_object->baseInternalDamage, internal_object->currentInternalDamage); s += temp; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::NotifyProjectileApproaching(const Stuff::Point3D& origin) { BaseClass::NotifyProjectileApproaching(origin); if (GetAI() != 0) { GetAI()->NotifyProjectileApproaching(origin); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::NotifyOfMissileLock() { Check_Object(this); if(vehicleInterface) vehicleInterface->ReactToEvent (VehicleInterface::MISSILE_LOCKED_ON_ME); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ResourceID MWObject::ReactToMissileApproach(Scalar distance, const Point3D& current_position) { Check_Object(this); if(GetAMS()) { const AMS__GameModel *model = GetAMS()->GetGameModel(); Check_Object(model); if(GetAMS()->DoesHaveAmmo()) { GetAMS()->SubtractAmmo(1); return model->amsEffectResource; } } return ResourceID::Null; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::SetTargetDesirability(Stuff::Scalar desirability) { if (desirability == desirability_never) { Verify(Adept::EntityManager::GetInstance() != 0); NameTable *table = NameTable::GetInstance(); { int size(table->nameTableArray[NameTable::VehicleArray].GetLength()); {for (int i = 0; i < size; ++i) { NameTableEntry *data = &table->nameTableArray [NameTable::VehicleArray][i]; Adept::Entity* ent = data->dataPointer->GetCurrent (); if ((ent != 0) && (ent->IsDerivedFrom(MWObject::DefaultData) == true)) { MWObject* mwobject = Cast_Object(MWObject*,ent); if (mwobject->GetAI() != 0) { mwobject->GetAI()->EnsureNotTargeting(objectID); } } }} } { int size(table->nameTableArray[NameTable::TurretArray].GetLength()); {for (int i = 0; i < size; ++i) { NameTableEntry *data = &table->nameTableArray [NameTable::TurretArray][i]; Adept::Entity* ent = data->dataPointer->GetCurrent (); if ((ent != 0) && (ent->IsDerivedFrom(MWObject::DefaultData) == true)) { MWObject* mwobject = Cast_Object(MWObject*,ent); if (mwobject->GetAI() != 0) { mwobject->GetAI()->EnsureNotTargeting(objectID); } } }} } } else { if (desirability != desirability_invalid) { Verify(desirability >= 0); Verify(desirability <= 1); } } m_TargetDesirability = desirability; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar MWObject::GetTargetDesirability() const { return (m_TargetDesirability); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::NotifyFired(const Adept::Entity::CollisionQuery& query) { if (GetAI() != 0) { GetAI()->NotifyShotFired(query,*this); } if ((GetSensor() == 0) || (query.m_line == 0)) { return; } const MechWarrior4::Sensor::sensorDataArray& sensed_data = GetSensor()->GetSensorData(); {for (int i = 0; i < sensed_data.GetLength(); ++i) { MechWarrior4::SensorData* d = sensed_data[i]; if ((d != 0) && (d->object.GetCurrent() != 0) && (d->object.GetCurrent() != this) && (d->object.GetCurrent()->IsDerivedFrom(MWObject::DefaultData))) { MWObject* that = Cast_Object(MWObject*,d->object.GetCurrent()); Check_Object(that); if (that->GetAI() != 0) { that->GetAI()->NotifyShotFired(query,*this); } } }} // special case for shutdown mechs since they don't appear on sensors MechAI::NotifyShutDownMechsShotFired(query,*this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::NotifyInTargetingReticule(MWObject& who) { if (GetAI() != 0) { GetAI()->NotifyInTargetingReticule(who); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MWObject::CollisionHandler( Stuff::LinearMatrix4D *new_position, Stuff::DynamicArrayOf *collisions ) { Check_Object(this); Verify(GetInterestLevel() != DormantInterestLevel); Verify(EntityManager::GetInstance()->IsInPostCollisionExecution(this)); STOP(("What are we doing here?!?!")); return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::GetLineOfSight(Stuff::LinearMatrix4D& line_of_sight) { if ((GetTorso()) && (GetTorso()->twistJoint)) { line_of_sight = GetTorso()->twistJoint->GetLocalToWorld(); } else { if (eyeSitePointer.GetCurrent()) { line_of_sight = eyeSitePointer.GetCurrent()->GetLocalToWorld(); } else { line_of_sight = GetLocalToWorld(); } } Adept::InternalDamageObject* torso_zone = internalDamageObjects.Find(Adept::InternalDamageObject::CenterTorsoZone); if ((torso_zone != 0) && (torso_zone->parentEntity != 0)) { line_of_sight.BuildTranslation((Stuff::Point3D)torso_zone->parentEntity->GetLocalToWorld()); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Point3D MWObject::GetLineOfSight() { Adept::InternalDamageObject* torso_zone = internalDamageObjects.Find(Adept::InternalDamageObject::CenterTorsoZone); if ((torso_zone != 0) && (torso_zone->parentEntity != 0)) { return (torso_zone->parentEntity->GetLocalToWorld()); } if ((GetTorso()) && (GetTorso()->twistJoint)) { return (GetTorso()->twistJoint->GetLocalToWorld()); } if (eyeSitePointer.GetCurrent()) { return (eyeSitePointer.GetCurrent()->GetLocalToWorld()); } Point3D p(GetLocalToWorld()); p.y += 1.0f; return (p); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::ReactToHit(const Entity__TakeDamageMessage *message,Adept::DamageObject *part_hit) { Check_Object(this); Check_Object(message); if (g_nMR == 2) return; if (IsDestroyed()) return; #ifdef LAB_ONLY if ((GetOwner() != 0) && (MW4AI::Statistics::Enabled() == true)) { Connection *connection = Network::GetInstance()->GetConnection(message->inflictingEntityID.connectionID); if (connection == NULL) return; Replicator* r = connection->FindReplicator(message->inflictingEntityID); if (r != 0) { Verify(r->IsDerivedFrom(Entity::DefaultData)); Entity* e = Cast_Object(Entity*,r); MW4AI::Statistics::NotifyDamageTaken(objectID,e->objectID,message->amountOfDamage,message->typeOfDamage); } } #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Point3D& MWObject::EstimateFuturePosition( Stuff::Point3D* new_position, Stuff::Scalar seconds, bool consider_terrain ) { Check_Object(this); return *new_position = GetLocalToWorld(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::Reuse( const CreateMessage *message, ReplicatorID *base_id ) { Check_Object(this); Check_Object(message); STOP(("Not implemented")); BaseClass::Reuse(message, base_id); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::ToggleSearchLight() { Check_Object(this); Check_Object(Mission::GetInstance()); if(Mission::GetInstance()->DoesAllowSearchLights()) { if(searchLight) { if(IsSearchLightOn()) { // // [johnyo] 08/27/00 PreviousSearchLight code is experimental code that I have checked in to keep a backup // of only. It may be ripped out shortly if the effect that it was intended to have isn't // put into the game // // if (IsPlayerVehicle()) // Mission::GetInstance()->ResetMissionLights(); searchLight->HideBeam(); // SetSearchLightMode(true); } else { // if (IsPlayerVehicle()) // Mission::GetInstance()->SetSearchLightMissionLights(); searchLight->ShowBeam(); // SetSearchLightMode(false); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::TurnOnSearchLight() { Check_Object(this); Check_Object(Mission::GetInstance()); // MSL 5.02 SearchLight // if(Mission::GetInstance()->m_isNightMission) if(Mission::GetInstance()->DoesAllowSearchLights()) { // if (IsPlayerVehicle()) // Mission::GetInstance()->SetSearchLightMissionLights(); if(searchLight) searchLight->ShowBeam(); // SetSearchLightMode(true); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::TurnOffSearchLight() { Check_Object(this); // MWMission *mw_mission = Cast_Object(MWMission *, MWMission::GetInstance()); // mw_mission->ResetMissionLights(); if(searchLight) searchLight->HideBeam(); // SetSearchLightMode(false); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MWObject::IsSearchLightOn() { Check_Object(this); if(searchLight) return searchLight->isLightOn; return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar MWObject::FriendlyFireDamageMultiplier() const { return (1); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::TakeDamageMessageHandler(const TakeDamageMessage *message) { Check_Object(this); Check_Object(message); Verify(message->messageID == TakeDamageMessageID); if(damageObject) { damageObject->TakeDamage((TakeDamageMessage *)message, this); } DamageObject *damage_object; SortedChainIteratorOf iterator(&damageObjects); while((damage_object = iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); if(damage_object != damageObject) { damage_object->TakeDamage((TakeDamageMessage *)message, NULL); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // char* MWObject::GetObjectName() { Check_Object(this); Check_Object(MWApplication::GetInstance()); if(m_doesHaveInstanceName) { if((m_localizeIndex > -1) && (!isPlayerVehicle)) { return MWApplication::GetInstance()->GetLocString(m_localizeIndex); } else { return (char *)instanceName; } } else { if(isPlayerVehicle) return (char *)instanceName; } const GameModel *model = GetGameModel(); Check_Object(model); return MWApplication::GetInstance()->GetLocString(model->m_nameIndex); } char* MWObject::GetModelName() { Check_Object(this); Check_Object(MWApplication::GetInstance()); const GameModel *model = GetGameModel(); Check_Object(model); return MWApplication::GetInstance()->GetLocString(model->m_nameIndex); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MWObject::GetVisibleOnSensors() const { return (m_VisibleOnSensors); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MWObject::SetVisibleOnSensors(bool visible) { m_VisibleOnSensors = visible; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool MWObject::DoesHaveAvailableTonage(Stuff::Scalar tons) { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); return (tonage + tons) <= model->maxVehicleTonnage + 0.01f; } void MWObject::EngineDead (void) { STOP (("Only a drop ship should handle this function")); } #ifdef _DEBUG Adept::Site* MWObject::FindSite(const char *site_name) { Check_Object(this); Check_Pointer(site_name); Adept::Site* pSite = m_sites.Find(site_name); if (pSite) { Check_Object(pSite->GetParent()); } return pSite; } #endif // _DEBUG void MWObject::SetDmgModifier (int nIdx, int nDmgFactor) { // nIdx : 0: default, 1: splash gosASSERT((0 <= nIdx) && (nIdx < 2)); // nDmgFactor: < 0 - restore // nDmgFactor: == 0 - store // nDmgFactor: > 0 - set damage modifier as (nDmgFactor/10000.0) Check_Pointer(this); SortedChainIteratorOf iterator(&damageObjects); DamageObject *damage_object; nIdx *= 2; if (nDmgFactor < 0) { // restore while((damage_object = iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); damage_object->SetDamageModifier(nIdx, damage_object->GetDamageModifier(nIdx + 1)); } } else if (nDmgFactor == 0) { while((damage_object = iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); damage_object->SetDamageModifier(nIdx + 1, damage_object->GetDamageModifier(nIdx)); } } else { Stuff::Scalar f = static_cast(nDmgFactor / 10000.0); while((damage_object = iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); damage_object->SetDamageModifier(nIdx, f); } } } void MWObject::RepairDamage (Stuff::Scalar fRepair) { // jcem Check_Pointer(this); if (fRepair <= 0.0f) return; if (1.0f < fRepair) fRepair = 1.0f; SortedChainIteratorOf iterator(&damageObjects); DamageObject *damage_object; while((damage_object = iterator.ReadAndNext()) != NULL) { Check_Object(damage_object); damage_object->RepairDamage(fRepair); } }