//===========================================================================// // File: Weapon.cpp //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 09/09/98 JSE Inital base class based off of Shadowrun/Adept // // 09/24/98 BDB Inital Weapon subsytem class based off of Subsystem // //---------------------------------------------------------------------------// // Copyright (C) 1998, Fasa Interactive // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "MW4Headers.hpp" #include "Weapon.hpp" #include "GUIWeaponManager.hpp" #include "HeatManager.hpp" #include "SubsystemClassData.hpp" #include "MWApplication.hpp" #include "Torso.hpp" #include "MechLabHeaders.h" #include #include #include #include //############################################################################# //############################### Weapon ################################ //############################################################################# Weapon::ClassData* Weapon::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( WeaponClassID, "MechWarrior4::Weapon", Subsystem::DefaultData, 0, 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, (Subsystem::StreamCreate) CreateStream ); Register_Object(DefaultData); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, MuzzleFlashResource, muzzleFlashResource, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, EjectEffectResource, ejectEffectResource, ResourceID ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, Heat, heat, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, HeatSpreadTime, heatSpreadTime, Scalar ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, MaxAmmo, maxAmmoCount, int, IntClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, AmmoPerShot, ammoPerShot, int, IntClassID ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, HeatToDeal, heatToDeal, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, SplashRadius, splashRadius, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, PercentageOfDamageToDirectHit, percentageOfDamageToDirectHit, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, MinPercentageOfDamageToSphereHit, minPercentageOfDamageToSphereHit, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, MaxPercentageOfDamageToSphereHit, maxPercentageOfDamageToSphereHit, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, DamageAmount, damageAmount, Scalar ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, MaxDistance, maxDistance, Scalar ); // MSL 5.03 Min Distance // DIRECT_GAME_MODEL_ATTRIBUTE( // Weapon__GameModel, // MinDistance, // minDistance, // Scalar // ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, ReloadTime, reloadTime, Scalar, ); DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, LightAmpFlareOut, m_lightAmpFlareOut, Scalar ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, NumFire, numFire, int, IntClassID ); CUSTOM_DIRECT_GAME_MODEL_ATTRIBUTE( Weapon__GameModel, HudEffect, m_HudEffect, Scalar, ScalarClassID ); // jcem } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Weapon* Weapon::Make( CreateMessage *message, ReplicatorID *base_id ) { Check_Object(message); gos_PushCurrentHeap(Heap); Weapon *new_entity = new Weapon(DefaultData, message, base_id, NULL); gos_PopCurrentHeap(); Check_Object(new_entity); return new_entity; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Replicator::CreateMessage* Weapon::SaveMakeMessage(MemoryStream *stream, ResourceFile *res_file) { Check_Object(this); Check_Object(stream); stream->AllocateBytes(sizeof(CreateMessage)); Subsystem::SaveMakeMessage(stream, res_file); CreateMessage *message = Cast_Pointer(CreateMessage*, stream->GetPointer()); message->messageLength = sizeof(*message); Str_Copy(message->siteName, (char *)siteName, sizeof(message->siteName)); Str_Copy(message->ejectSiteName, (char *)ejectSiteName, sizeof(message->ejectSiteName)); message->groupIndex = groupIndexFlags; message->ammoCount = DECRYPT(encryptedAmmoCount); message->initialAmmoCount = initialAmmoCount; // MSL 5.04 Rear Firing Weapons message->m_weaponFacing = m_weaponFacing; return message; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Weapon::Weapon( ClassData *class_data, CreateMessage *message, ReplicatorID *base_id, ElementRenderer::Element *element ): Subsystem(class_data, message, base_id, element), guiWeapon(NULL), m_AI_WaitValue(0), m_AI_LastCountValue(0), m_AI_NonrandomWaitTimes(false) { Check_Pointer(this); Check_Object(message); // MSL 5.04 Rear Firing Weapons m_weaponFacing = message->m_weaponFacing; siteName = message->siteName; ejectSiteName = message->ejectSiteName; groupIndexFlags = message->groupIndex; sitePointer = NULL; ejectSitePointer = NULL; enginePointer = NULL; weaponID = -1; CommonCreation(message); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::CommonCreation(CreateMessage *message) { Check_Object(this); Check_Object(message); m_AI_LastTimeReadyToFire = gos_GetElapsedTime(); encryptedAmmoCount = ENCRYPT(message->ammoCount); initialAmmoCount = message->initialAmmoCount; vehicleInterface = NULL; m_PlayedRechargeSound = false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::Respawn(Entity::CreateMessage *message) { Check_Object(this); Check_Object(message); Subsystem::Respawn(message); CreateMessage *weapon_message = Cast_Pointer(CreateMessage *, message); CommonCreation(weapon_message); if(guiWeapon.GetCurrent()) { guiWeapon.GetCurrent()->SetStatus(GUIWeapon::ReadyStatus); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Weapon::~Weapon() { } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Weapon::ConnectSubsystem() { MWObject *mw_object = GetParentVehicle(); Check_Object(mw_object); enginePointer = NULL; heatPointer = mw_object->m_heatManager; sitePointer = mw_object->FindSite(siteName); Check_Object(sitePointer); ejectSitePointer = mw_object->FindSite(ejectSiteName); //Must call the inherited virtual function!!!! bool return_value = Subsystem::ConnectSubsystem(); //Only want to do this stuff if we did get connected. if(return_value) { int ammo_tonnage = 0; const GameModel *model = GetGameModel(); Check_Object(model); if((model->maxAmmoCount > 0) && (DECRYPT(encryptedAmmoCount) > 0)) ammo_tonnage = (DECRYPT(encryptedAmmoCount) / GetAmmoPerPack()) - 1; //subtract one because you get one free ton mw_object->AddTonage((Scalar)ammo_tonnage); } return return_value; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // bool Weapon::DisconnectSubsystem() { Check_Object(this); MWObject *parent_vehicle; parent_vehicle = GetParentVehicle(); Check_Object(parent_vehicle); const GameModel *model = GetGameModel(); Check_Object(model); int ammo_tonnage = 0; if((model->maxAmmoCount > 0) && (DECRYPT(encryptedAmmoCount) > 0)) ammo_tonnage = (DECRYPT(encryptedAmmoCount) / GetAmmoPerPack()) - 1; parent_vehicle->SubtractTonage((Scalar) ammo_tonnage); return Subsystem::DisconnectSubsystem(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::CreateMuzzleFlash() { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); if(model->muzzleFlashResource == ResourceID::Null) return; Resource muzzle_flash_resource(model->muzzleFlashResource); if(muzzle_flash_resource.DoesResourceExist()) { ClassID class_ID; class_ID = GetClassIDFromDataListID(model->muzzleFlashResource); Verify(class_ID != NullClassID); LinearMatrix4D effect_position = LinearMatrix4D::Identity; UnitVector3D unit_forward; Check_Object(sitePointer); LinearMatrix4D site_position = sitePointer->GetLocalToWorld(); site_position.GetLocalForwardInWorld(&unit_forward); effect_position.AlignLocalAxisToWorldVector(unit_forward, Y_Axis, X_Axis, Z_Axis); Point3D muzzle_translation; muzzle_translation = sitePointer->GetLocalToWorld(); effect_position.BuildTranslation(muzzle_translation); Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags, model->muzzleFlashResource, effect_position, 0.0f, ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Entity *entity; ReplicatorID beam_id = Connection::Hermit->GetNextReplicatorID(); entity = CreateEntity(&stream, &beam_id, false); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); Effect *effect; effect = Cast_Object(Effect *, entity); effect->SetFollowEntity(sitePointer); entity->SyncMatrices(true); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::CreateEjectEffect() { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); if(model->ejectEffectResource == ResourceID::Null) return; if(ejectSitePointer == NULL) return; Resource eject_effect_resource(model->ejectEffectResource); if(eject_effect_resource.DoesResourceExist()) { ClassID class_ID; class_ID = GetClassIDFromDataListID(model->ejectEffectResource); Verify(class_ID != NullClassID); LinearMatrix4D effect_position = LinearMatrix4D::Identity; UnitVector3D unit_forward; Check_Object(ejectSitePointer); LinearMatrix4D site_position = ejectSitePointer->GetLocalToWorld(); site_position.GetLocalForwardInWorld(&unit_forward); effect_position.AlignLocalAxisToWorldVector(unit_forward, Y_Axis, X_Axis, Z_Axis); Point3D muzzle_translation; muzzle_translation = ejectSitePointer->GetLocalToWorld(); effect_position.BuildTranslation(muzzle_translation); Effect::CreateMessage effect_create_message( sizeof(Effect::CreateMessage), DefaultEventPriority, CreateMessage::DefaultFlags, class_ID, Effect::DefaultFlags, model->ejectEffectResource, effect_position, 0.0f, ExecutionStateEngine::AlwaysExecuteState, NameTable::NullObjectID, Entity::DefaultAlignment ); MemoryStream stream(&effect_create_message, effect_create_message.messageLength); Entity *entity; ReplicatorID beam_id = Connection::Hermit->GetNextReplicatorID(); entity = CreateEntity(&stream, &beam_id, false); Check_Object(Map::GetInstance()); Map::GetInstance()->AddChild(entity); Effect *effect; effect = Cast_Object(Effect *, entity); effect->SetFollowEntity(ejectSitePointer); entity->SyncMatrices(true); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MechWarrior4::WeaponSecurityCheckStart() { _asm { nop } } // MSL 5.04 Rear Firing Weapons //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Weapon::CanFireForward() { Check_Object(this); Torso* torso = parentAsVehicle->GetTorso(); if ((torso->eyeYaw < 15.0f * Stuff::Radians_Per_Degree) || (torso->eyeYaw > -15.0f * Stuff::Radians_Per_Degree)) { if (m_weaponFacing != 1) return (true); } return (false); } // MSL 5.04 Rear Firing Weapons //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Weapon::CanFireRight() { Check_Object(this); if ((parentAsVehicle != 0) && (parentAsVehicle->IsDestroyed() == false) && (sitePointer != 0) && (sitePointer->GetParent() != 0) && (sitePointer->GetParent()->damageObject != 0) && (sitePointer->GetParent()->damageObject->internalDamageObject != 0)) { Torso* torso = parentAsVehicle->GetTorso(); if (torso != 0) { Adept::InternalDamageObject* ido = sitePointer->GetParent()->damageObject->internalDamageObject; if ((torso->lookDirection == Torso::LookRightDirection) && (ido->damageZone == Adept::InternalDamageObject::RightArmZone)) { return (true); } if (m_weaponFacing == 2) { return (true); } } } return (false); } // MSL 5.04 Rear Firing Weapons //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Weapon::CanFireLeft() { Check_Object(this); if ((parentAsVehicle != 0) && (parentAsVehicle->IsDestroyed() == false) && (sitePointer != 0) && (sitePointer->GetParent() != 0) && (sitePointer->GetParent()->damageObject != 0) && (sitePointer->GetParent()->damageObject->internalDamageObject != 0)) { Torso* torso = parentAsVehicle->GetTorso(); if (torso != 0) { Adept::InternalDamageObject* ido = sitePointer->GetParent()->damageObject->internalDamageObject; if ((torso->lookDirection == Torso::LookLeftDirection) && (ido->damageZone == Adept::InternalDamageObject::LeftArmZone)) { return (true); } if (m_weaponFacing == 2) { return (true); } } } return (false); } // MSL 5.04 Rear Firing Weapons //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Weapon::CanFireBackward() { Check_Object(this); if (m_weaponFacing == 1) return (true); return (false); } // MSL 5.04 Rear Firing Weapons //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Weapon::CanFireFromCurrentArm() { Check_Object(this); if ((parentAsVehicle != 0) && (parentAsVehicle->IsDestroyed() == false)) { Torso* torso = parentAsVehicle->GetTorso(); if (torso != 0) { switch (torso->lookDirection) { case Torso::LookBackDirection: if (CanFireBackward() == false) { return (false); } break; case Torso::LookLeftDirection: if (CanFireLeft() == false) { return (false); } break; case Torso::LookRightDirection: if (CanFireRight() == false) { return (false); } break; case Torso::LookForwardDirection: if (CanFireForward() == false) { return (false); } break; } } } return (true); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::FireWeapon(Adept::Entity::CollisionQuery *query, Stuff::Time time_locked, const Stuff::Point3D& lockedTargetEntityPartOffset) { if (CanFireFromCurrentArm() == false) { return; } if ((query != 0) && (GetParentVehicle() != 0)) { GetParentVehicle()->NotifyFired(*query); } Fire(query,time_locked, lockedTargetEntityPartOffset); GenerateAIWaitValue(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::QuickFireWeapon (Adept::Entity *target) { Verify(!Application::GetInstance()->InPreCollisionPhase()); QuickFire(target); GenerateAIWaitValue(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar Weapon::GetAIWaitValue() const { return (m_AI_WaitValue); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Time Weapon::GetLastTimeReadyToFire() const { return (m_AI_LastTimeReadyToFire); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::SetCount(Stuff::Scalar count) { if ((count == 0) && (m_AI_LastCountValue != 0)) { m_AI_LastTimeReadyToFire = gos_GetElapsedTime(); } if (guiWeapon.GetCurrent()) { Check_Object(guiWeapon.GetCurrent()); guiWeapon.GetCurrent()->SetCount(count); } m_AI_LastCountValue = count; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::ApplyHeat() { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); if(heatPointer) { Check_Object(heatPointer); heatPointer->AddHeat(model->heat); heatPointer->AddHeatObject(model->heatSpreadTime, model->heat); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Stuff::Scalar Weapon::GetTotalHeatGenerated() { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); return (model->heat * 2); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Weapon::DoesHaveAmmo() { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); // MSL 5.03 Bug Fix // -1 == Beam weapon...so should return a false unless it's a PPC if((DECRYPT(encryptedAmmoCount) == -1) && ((model->itemID == W_ClanERPPC) || (model->itemID == W_PPC) || (model->itemID == W_ERPPC))) return true; if(DECRYPT(encryptedAmmoCount) >= model->ammoPerShot) return true; return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::UseAmmo() { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); int ammo_count = DECRYPT(encryptedAmmoCount); NetMissionParameters::MWNetMissionParameters *params = MWApplication::GetInstance()->GetLocalNetParams(); if(ammo_count >= 0 && !params->m_unlimitedAmmo) { ammo_count -= model->ammoPerShot; if (ammo_count < model->ammoPerShot) { ammo_count = 0; } Min_Clamp(ammo_count, 0); encryptedAmmoCount = ENCRYPT(ammo_count); if (ammo_count == 0) { if (GetParentVehicle ()->vehicleInterface) { GetParentVehicle ()->vehicleInterface->ReactToEvent (VehicleInterface::OUT_OF_AMMO); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::SetMaxWaitValue() { m_AI_WaitValue = 1; m_AI_LastTimeReadyToFire = gos_GetElapsedTime(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::DestroySubsystem() { Check_Object(this); // MSL 5.02 Weapon Destroyed Betty Check_Object(executionState); if(GetParentVehicle()->vehicleInterface) { GetParentVehicle()->vehicleInterface->ReactToEvent (VehicleInterface::CRITICAL_HIT_WEAPON); } Subsystem::DestroySubsystem(); if(guiWeapon.GetCurrent()) { guiWeapon.GetCurrent()->SetStatus(GUIWeapon::DestroyedStatus); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Weapon::TakeCriticalHit() { Check_Object(this); Check_Object(executionState); // MSL 5.02 Weapon Destroyed Betty // if(GetParentVehicle()->vehicleInterface) // { // GetParentVehicle()->vehicleInterface->ReactToEvent (VehicleInterface::CRITICAL_HIT_WEAPON); // } return Subsystem::TakeCriticalHit(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MechWarrior4::WeaponSecurityCheckStop() { _asm { nop } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::CreateStream(ResourceID data_list, MemoryStream *stream) { Check_Pointer(stream); stream->AllocateBytes(sizeof(Weapon__CreateMessage)); Subsystem::CreateStream(data_list, stream); Weapon__CreateMessage *create_message = Cast_Pointer( Weapon__CreateMessage *, stream->GetPointer()); Str_Copy(create_message->siteName, "site_", sizeof(create_message->siteName)); Str_Copy(create_message->ejectSiteName, " ", sizeof(create_message->ejectSiteName)); create_message->groupIndex = 1; Resource model_resource; Entity::GetGameModelResourceFromDataListID(&model_resource, data_list); GameModel *model = Cast_Pointer(GameModel *, model_resource.GetPointer()); if((model->itemID >= FirstProjectileID) && (model->itemID <= LastProjectileID)) create_message->groupIndex = 2; if((model->itemID >= FirstMissileID) && (model->itemID <= LastMissileID)) create_message->groupIndex = 4; if(model->itemID == W_Flare) create_message->groupIndex = 32; if((model->itemID == W_NarcBeacon) || (model->itemID == W_ClanNarcBeacon)) create_message->groupIndex = 8; if(model->maxAmmoCount > 0) { Verify(model->totalSlotsTaken != 0); create_message->ammoCount = model->maxAmmoCount / (3 * model->totalSlotsTaken); create_message->initialAmmoCount = model->maxAmmoCount / (3 * model->totalSlotsTaken); } else { create_message->ammoCount = -1; create_message->initialAmmoCount = -1; } // MSL 5.04 Rear Firing Weapons create_message->m_weaponFacing = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::SetWeaponGroup(int group) { Check_Object(this); switch(group) { case 1: SetGroup1(); break; case 2: SetGroup2(); break; case 3: SetGroup3(); break; case 4: SetGroup4(); break; case 5: SetGroup5(); break; case 6: SetGroup6(); break; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::ClearWeaponGroup(int group) { Check_Object(this); switch(group) { case 1: ClearGroup1(); break; case 2: ClearGroup2(); break; case 3: ClearGroup3(); break; case 4: ClearGroup4(); break; case 5: ClearGroup5(); break; case 6: ClearGroup6(); break; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Weapon::AddAmmoPack() { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); if(DECRYPT(encryptedAmmoCount) < model->maxAmmoCount) { if(GetParentVehicle()->DoesHaveAvailableTonage(1.0f)) { int ammo_count = DECRYPT(encryptedAmmoCount); int added_ammo = GetAmmoPerPack(); ammo_count += added_ammo; Max_Clamp(ammo_count, model->maxAmmoCount); initialAmmoCount = ammo_count; if(added_ammo > 0) GetParentVehicle()->AddTonage(1.0f); encryptedAmmoCount = ENCRYPT(ammo_count); return true; } return false; } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Weapon::RemoveAmmoPack() { Check_Object(this); int ammo_count = DECRYPT(encryptedAmmoCount); int sub_ammo = GetAmmoPerPack(); if(ammo_count > sub_ammo) { ammo_count -= sub_ammo; Min_Clamp(ammo_count, sub_ammo); initialAmmoCount = ammo_count; encryptedAmmoCount = ENCRYPT(ammo_count); if(sub_ammo > 0) GetParentVehicle()->SubtractTonage(1.0f); return true; } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Weapon::GetAmmoPacks() { Check_Object(this); if(DECRYPT(encryptedAmmoCount) > 0) return DECRYPT(encryptedAmmoCount) / GetAmmoPerPack(); return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Weapon::GetAmmoPerPack() { Check_Object(this); const GameModel *model = GetGameModel(); Check_Object(model); Check_Object(model); Verify(model->totalSlotsTaken != 0); int value = model->maxAmmoCount / (3 * model->totalSlotsTaken); Min_Clamp(value, 0); return value; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::CreateLightAmpFlareOut() { Check_Object(this); Check_Object(GetParentVehicle()); if(GetParentVehicle()->vehicleInterface) { const GameModel *model = GetGameModel(); Check_Object(model); //Here is where we need to effect the Light Amp values GetParentVehicle()->vehicleInterface->SetLightAmpFlareOut(model->m_lightAmpFlareOut); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::SetNonrandomWaitTimes(bool use_nonrandom) { m_AI_NonrandomWaitTimes = use_nonrandom; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Weapon::GenerateAIWaitValue() { if (m_AI_NonrandomWaitTimes == true) { m_AI_WaitValue = 0.5f; } else { m_AI_WaitValue = Stuff::Random::GetFraction(); } }