#include "rp.h" #pragma hdrstop #include "weapsys.h" #include "rivet.h" #include "demopack.h" #include "..\munga\line.h" #include "..\munga\explode.h" #include "..\munga\boxsolid.h" #include "vtvmppr.h" #include "vtv.h" #include "..\munga\app.h" //############################################################################# // Shared Data Support // GenericGun::SharedData GenericGun::DefaultData( GenericGun::GetClassDerivations(), GenericGun::MessageHandlers, GenericGun::GetAttributeIndex(), GenericGun::StateCount ); Derivation* GenericGun::GetClassDerivations() { static Derivation classDerivations(VTVSubsystem::GetClassDerivations(), "GenericGun"); return &classDerivations; } //############################################################################# // Messaging Support // const Receiver::HandlerEntry GenericGun::MessageHandlerEntries[]= { MESSAGE_ENTRY(GenericGun, ConfigureMappables), MESSAGE_ENTRY(GenericGun, ChooseButton) }; Receiver::MessageHandlerSet GenericGun::MessageHandlers( ELEMENTS(GenericGun::MessageHandlerEntries), GenericGun::MessageHandlerEntries, VTVSubsystem::GetMessageHandlers() ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GenericGun::ConfigureMappablesMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); //--------------------------------------------------------------------- // If the hardwired button was pressed, process presses of the mappable // buttons, otherwise it was released, so erase any temporary mappings //--------------------------------------------------------------------- if (message->dataContents > 0) { EnterConfiguration( &triggerState, // direct target this, // receiver (Receiver::MessageID) 0, // activation message ID (none here) ChooseButtonMessageID // configuration message ID ); } else { ExitConfiguration(); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GenericGun::ChooseButtonMessageHandler( ReceiverDataMessageOf *message ) { if (message->dataContents > 0) { // //--------------------------------------------------------------------- // Find the control manager of the vehicle, and have it turn off an // existing mapping of a given type if it is there, otherwise it should // create a new one //--------------------------------------------------------------------- // VTV* vtv = GetEntity(); Check(vtv); VTVControlsMapper* controls = Cast_Object( VTVControlsMapper*, vtv->GetSubsystem(VTV::ControlsMapperSubsystem) ); Check(controls); controls->AddOrErase(message->dataContents, &triggerState); } Check_Fpu(); } //############################################################################# // Attribute Support // const GenericGun::IndexEntry GenericGun::AttributePointers[]= { ATTRIBUTE_ENTRY(GenericGun, TriggerState, triggerState), ATTRIBUTE_ENTRY(GenericGun, PercentDone, percentDone) }; GenericGun::AttributeIndexSet& GenericGun::GetAttributeIndex() { static GenericGun::AttributeIndexSet attributeIndex(ELEMENTS(GenericGun::AttributePointers), GenericGun::AttributePointers, VTVSubsystem::GetAttributeIndex() ); return attributeIndex; } //############################################################################# // Model Support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GenericGun::CalcAmmoOrigin(Origin *ammo_origin) { Check(this); VTV *vtv = GetEntity(); Check(vtv); // //------------------------------- // Check if we are looking behind //------------------------------- // VTVControlsMapper *ctrl_sub = (VTVControlsMapper *) vtv->GetSubsystem(VTV::ControlsMapperSubsystem); LinearMatrix site_transform; if(ctrl_sub->lookBehind > 0) { site_transform = siteRearTransform; } else { site_transform = siteFrontTransform; } LinearMatrix temp; temp.Multiply(site_transform, vtv->localToWorld); *ammo_origin = temp; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void GenericGun::GenericGunSimulation(Scalar) { VTV *vtv = GetEntity(); Check(vtv); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // General Firing Simulation //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // if ( (triggerState > 0) && (vtv->GetSimulationState() != VTV::BurningState) ) { Fire(); SetSimulationState(Firing); } else { SetSimulationState(DefaultState); } Check_Fpu(); } //############################################################################# // Construction And Destruction // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // GenericGun::GenericGun( VTV *owner, int subsystem_ID, SubsystemResource *sub_res, SharedData &shared_data ): VTVSubsystem( owner, subsystem_ID, sub_res, shared_data, &triggerState, // direct mapping for controls (Receiver::MessageID) 0 // assumes no event mapping ) { Check(owner); Check_Pointer(sub_res); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Get the Resource Variables //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ammoVideoResourceID = sub_res->ammoVideoResourceID; // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Initialize the Trigger to Released //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // triggerState = -1; oldTriggerState = triggerState; SetPerformance(&GenericGun::GenericGunSimulation); SetSimulationState(DefaultState); percentDone = 0.0f; // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Assumption: No Joints in between a Gun and the // root node of a vtv, so we can get the // transformation matrix to get to the // position of the site so we know where // the bullet is to come out of //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // EntitySegment *site_front_segment = owner->GetSegment(sub_res->segmentIndex); Check(site_front_segment); siteFrontTransform = site_front_segment->GetSegmentToEntity(); if(sub_res->rearSiteIndex == -1) { siteRearTransform = siteFrontTransform; } else { EntitySegment *site_rear_segment = owner->GetSegment(sub_res->rearSiteIndex); Check(site_rear_segment); siteRearTransform = site_rear_segment->GetSegmentToEntity(); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // GenericGun::~GenericGun() { Check(this); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical GenericGun::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CreateStreamedSubsystem // int GenericGun::CreateStreamedSubsystem( NotationFile *model_file, const char *model_name, const char *subsystem_name, SubsystemResource *subsystem_resource, NotationFile *subsystem_file, ResourceFile *resource_file, const ResourceDirectories *directories ) { Check(model_file); Check_Pointer(model_name); Check_Pointer(subsystem_name); Check_Pointer(subsystem_resource); Check(subsystem_file); Check(resource_file); Check_Pointer(directories); if ( !Subsystem::CreateStreamedSubsystem( model_file, model_name, subsystem_name, subsystem_resource, subsystem_file, directories ) ) { Check_Fpu(); return False; } // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Save the model size and classID //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); subsystem_resource->classID = RegisteredClass::RivetGunClassID; // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Get the name of the ammo model file which holds // all the info about the type of ammo this gun shoots //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // const char *ammo_model_file; if( !subsystem_file->GetEntry( subsystem_name, "AmmoModelFile", &ammo_model_file ) ) { DEBUG_STREAM << subsystem_name << "missing AmmoModelFile!\n" << std::flush; Check_Fpu(); return False; } // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Find the description of the ammo in the current resource file // Note: The ammo must be build before the gun which uses it //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ResourceDescription *rivet_desc = resource_file->FindResourceDescription( ammo_model_file, ResourceDescription::ModelListResourceType ); if(!rivet_desc) { DEBUG_STREAM << ammo_model_file << " must be std::declared before "<< model_name << " in the .bld file" << std::endl << std::flush; Check_Fpu(); return False; } subsystem_resource->ammoVideoResourceID = rivet_desc->resourceID; const char *rear_site_name; if( !subsystem_file->GetEntry( subsystem_name, "RearSiteName", &rear_site_name ) ) { subsystem_resource->rearSiteIndex = -1; } else { subsystem_resource->rearSiteIndex = Get_Segment_Index( model_file, model_name, directories, rear_site_name); } Check_Fpu(); return True; } //############################################################################ //################ Class Rivet Gun ################################## //############################################################################ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Shared Data Support // RivetGun::SharedData RivetGun::DefaultData( RivetGun::GetClassDerivations(), RivetGun::MessageHandlers, RivetGun::GetAttributeIndex(), RivetGun::StateCount ); Derivation* RivetGun::GetClassDerivations() { static Derivation classDerivations(GenericGun::GetClassDerivations(), "RivetGun"); return &classDerivations; } //############################################################################# // Attribute Support // const RivetGun::IndexEntry RivetGun::AttributePointers[]= { ATTRIBUTE_ENTRY(RivetGun, TimeToLoaded, timeToLoaded), ATTRIBUTE_ENTRY(RivetGun, AmmoCount, ammoCount) }; RivetGun::AttributeIndexSet& RivetGun::GetAttributeIndex() { static RivetGun::AttributeIndexSet attributeIndex(ELEMENTS(RivetGun::AttributePointers), RivetGun::AttributePointers, GenericGun::GetAttributeIndex() ); return attributeIndex; } //############################################################################# // Construction And Destruction // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // RivetGun::RivetGun( VTV *owner, int subsystem_ID, SubsystemResource *sub_res, SharedData &shared_data ) : GenericGun(owner, subsystem_ID, sub_res, shared_data) { Check(owner); Check_Pointer(sub_res); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Get Resource Info //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // maxAmmoCount = sub_res->ammoCount; ammoCount = maxAmmoCount; loadTime = sub_res->loadTime; muzzleVelocity = sub_res->muzzleVelocity; timeToLoaded = loadTime; SetPerformance(&RivetGun::RivetGunSimulation); SetSimulationState(Loading); Check_Fpu(); } RivetGun::~RivetGun() { Check(this); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical RivetGun::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void RivetGun::CalcAmmoMotion(Motion *ammo_motion) { Check(this); VTV *vtv = GetEntity(); Check(vtv); *ammo_motion = vtv->localVelocity; ammo_motion->linearMotion.x += muzzleVelocity.x; ammo_motion->linearMotion.y += muzzleVelocity.y; ammo_motion->linearMotion.z -= muzzleVelocity.z; ammo_motion->angularMotion = Vector3D::Identity; Check_Fpu(); } //############################################################################# // Damage Support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void RivetGun::DeathReset(int reset_command) { // //--------------------------------------------------- // Make sure we are not firing and reset variables //--------------------------------------------------- // Check(this); if (reset_command == VTV::FootballReset) { ammoCount = maxAmmoCount; timeToLoaded = 0.0f; SetSimulationState(Loaded); } else { SetSimulationState(Loading); } Check_Fpu(); } //############################################################################# // Model Support // void RivetGun::RivetGunSimulation(Scalar time_slice) { Check(this); VTV *vtv = GetEntity(); Check(vtv); percentDone = (loadTime - timeToLoaded)/ loadTime; Check_Fpu(); if(percentDone > 1.0f) { percentDone = 1.0f; } if(percentDone < 0.0f) { percentDone = 0.0f; } Verify(percentDone >= 0.0f); Verify(percentDone <= 1.0f); switch(GetSimulationState()) { case NoAmmo: Gun_NoAmmo: // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // If there is no ammo and we are trying to fire--Misfire //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // if( (triggerState > 0) && (vtv->GetSimulationState() != VTV::BurningState) ) { SetSimulationState(MisFire); SetSimulationState(NoAmmo); } break; case Loading: Gun_Loading: { // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // See if there is any Ammo Left //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // if(ammoCount <= 0) { SetSimulationState(NoAmmo); goto Gun_NoAmmo; } // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Ensure we don't run over our time slice //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar time_left = time_slice - timeToLoaded; timeToLoaded -= time_slice; // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // If we are done loading update the time slice // and goto the firing state //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // if(timeToLoaded <= 0.0f) { timeToLoaded = 0.0f; time_slice = time_left; SetSimulationState(Loaded); goto Gun_Loaded; } break; } case Loaded: Gun_Loaded: if( (triggerState > 0) && (vtv->GetSimulationState() != VTV::BurningState) ) { goto Gun_Firing; } break; case Firing: Gun_Firing: SetSimulationState(Firing); Fire(); SetSimulationState(Loading); goto Gun_Loading; } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int RivetGun::Fire() { Check(this); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // std::decrement ammoCount and reset the loadTime //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // --ammoCount; timeToLoaded = loadTime; // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Get the entity and it's current position // Add this to the siteTransform to determine // where to shoot the rivet from //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Motion rivet_motion; CalcAmmoMotion(&rivet_motion); // //----------------------------- // Move the rivet to the site //----------------------------- // Origin rivet_localOrigin; CalcAmmoOrigin(&rivet_localOrigin); VTV *vtv = GetEntity(); Check(vtv); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Create a New Rivet Whose properties are listed in the // Resource File //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Rivet::MakeMessage create_rivet( Rivet::MakeMessageID, sizeof(Rivet::MakeMessage), (Entity::ClassID) Rivet::RivetClassID, RivetGunClassID, ammoVideoResourceID, Rivet::DefaultFlags, rivet_localOrigin, rivet_motion, Motion::Identity, vtv->GetEntityID() ); #if DEBUG_LEVEL>0 Rivet* my_rivet = Rivet::Make(&create_rivet); Register_Object(my_rivet); #else Rivet::Make(&create_rivet); #endif Check_Fpu(); return 1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CreateStreamedSubsystem // int RivetGun::CreateStreamedSubsystem( NotationFile *model_file, const char *model_name, const char *subsystem_name, SubsystemResource *subsystem_resource, NotationFile *subsystem_file, ResourceFile *resource_file, const ResourceDirectories *directories ) { if ( !GenericGun::CreateStreamedSubsystem( model_file, model_name, subsystem_name, subsystem_resource, subsystem_file, resource_file, directories ) ) { Check_Fpu(); return False; } subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); subsystem_resource->classID = RegisteredClass::RivetGunClassID; if( !subsystem_file->GetEntry( subsystem_name, "LoadTime", &subsystem_resource->loadTime ) ) { DEBUG_STREAM << subsystem_name << "missing LoadTime!\n" << std::flush; return False; } if( !subsystem_file->GetEntry( subsystem_name, "AmmoCount", &subsystem_resource->ammoCount ) ) { DEBUG_STREAM << subsystem_name << "missing AmmoCount!\n" << std::flush; Check_Fpu(); return False; } const char* muzzle_velocity; if( !subsystem_file->GetEntry( subsystem_name, "MuzzleVelocity", &muzzle_velocity ) ) { DEBUG_STREAM << subsystem_name << "missing MuzzleVelocity!\n" << std::flush; Check_Fpu(); return False; } else { Convert_From_Ascii(muzzle_velocity, &subsystem_resource->muzzleVelocity); } Check_Fpu(); return True; } //############################################################################ //################ Class Laser Gun ################################## //############################################################################ //############################################################################# // Shared Data Support // LaserGun::SharedData LaserGun::DefaultData( LaserGun::GetClassDerivations(), LaserGun::MessageHandlers, LaserGun::GetAttributeIndex(), LaserGun::StateCount ); Derivation* LaserGun::GetClassDerivations() { static Derivation classDerivations(GenericGun::GetClassDerivations(), "LaserGun"); return &classDerivations; } //############################################################################# // Attribute Support // const LaserGun::IndexEntry LaserGun::AttributePointers[]= { ATTRIBUTE_ENTRY(LaserGun, FrontLaserOn, frontLaserOn), ATTRIBUTE_ENTRY(LaserGun, RearLaserOn, rearLaserOn), ATTRIBUTE_ENTRY(LaserGun, LaserScale, laserScale) }; LaserGun::AttributeIndexSet& LaserGun::GetAttributeIndex() { static LaserGun::AttributeIndexSet attributeIndex(ELEMENTS(LaserGun::AttributePointers), LaserGun::AttributePointers, GenericGun::GetAttributeIndex() ); return attributeIndex; } //############################################################################# // Model Support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LaserGun::ReadUpdateRecord(Simulation::UpdateRecord *update_record) { Check(this); Check_Pointer(update_record); GenericGun::ReadUpdateRecord(update_record); UpdateRecord *laser_update = (UpdateRecord*) update_record; laserScale = laser_update->laserScale; frontLaserOn = laser_update->frontLaserOn; rearLaserOn = laser_update->rearLaserOn; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LaserGun::WriteUpdateRecord( Simulation::UpdateRecord *update_record, int update_model ) { Check(this); Check_Pointer(update_record); GenericGun::WriteUpdateRecord(update_record, update_model); UpdateRecord *laser_update = (UpdateRecord*) update_record; laser_update->recordLength = sizeof(*laser_update); laser_update->laserScale = laserScale; laser_update->frontLaserOn = frontLaserOn; laser_update->rearLaserOn = rearLaserOn; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LaserGun::CalcPercentDone() { percentDone = chargeLevel / maxChargeLevel; Verify(percentDone >= 0.0f); Verify(percentDone <= 1.0f); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LaserGun::ChargingSimulation(Scalar time_slice) { Check(this); VTV *vtv = GetEntity(); Check(vtv); chargeLevel += chargePerSecond * time_slice; if (chargeLevel >= maxChargeLevel) { chargeLevel = maxChargeLevel; SetSimulationState(DefaultState); } if (triggerState > 0 && vtv->GetSimulationState() != VTV::BurningState) { Fire(); } CalcPercentDone(); // Check_Fpu(); See CalcPercentDone, above. } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LaserGun::PulseFiringSimulation(Scalar time_slice) { Check(this); VTV *vtv = GetEntity(); Check(vtv); pulseDuration -= time_slice; if (pulseDuration <= 0.0f) { if (triggerState > 0 && vtv->GetSimulationState() != VTV::BurningState) { Fire(); } else { frontLaserOn = False; rearLaserOn = False; ForceUpdate(); SetSimulationState(Charging); SetPerformance(&LaserGun::ChargingSimulation); } } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LaserGun::FiringSimulation(Scalar time_slice) { // //----------------------------------------------------------------------- // If our time with the laser is done, look at the trigger state and jump // to either the charging or pulsing state //----------------------------------------------------------------------- // laserDuration -= time_slice; if (laserDuration <= 0.0f) { SetSimulationState(PulseFiring); SetPerformance(&LaserGun::PulseFiringSimulation); pulseDuration = maxPulseDuration; frontLaserOn = False; rearLaserOn = False; ForceUpdate(); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical LaserGun::Fire() { Check(this); // //--------------------------------------------- // Make sure we have enough power before firing //--------------------------------------------- // Scalar drain = drainPerSecond; if (chargeLevel < drain) { SetSimulationState(Misfire); return False; } chargeLevel -= drain; SetPerformance(&LaserGun::FiringSimulation); laserDuration = maxLaserDuration; SetSimulationState(Firing); ForceUpdate(); // //------------------------------ // Calculate the max laser line //----------------------------- // Origin laser_origin; CalcAmmoOrigin(&laser_origin); // //------------------------------- // Check if we are looking behind //------------------------------- // Vector3D z_axis; VTV *vtv = GetEntity(); Check(vtv); VTVControlsMapper *ctrl_sub = (VTVControlsMapper *) vtv->GetSubsystem(VTV::ControlsMapperSubsystem); if (ctrl_sub->lookBehind > 0) { z_axis.x = 0.0; z_axis.y = 0.0f; z_axis.z = 1.0; rearLaserOn = True; } else { z_axis.x = 0.0f; z_axis.y = 0.0f; z_axis.z = -1.0f; frontLaserOn = True; } Vector3D line_direction; line_direction.Multiply( z_axis , vtv->localToWorld); UnitVector unit_direction; unit_direction = line_direction; Line laser_line(laser_origin.linearPosition, unit_direction, maxLaserLength); Check(&laser_line); // //------------------------------------ // See if the laser line hit anything //------------------------------------ // BoxedSolid* target = vtv->FindBoxedSolidHitBy(&laser_line, vtv); laserScale.z = laser_line.length / 100.0f; Check_Fpu(); if (target) { // //----------------------- // Find the entity we hit //----------------------- // Simulation *sim = target->GetOwningSimulation(); Check(sim); Entity *entity; if (sim->IsDerivedFrom(*Subsystem::GetClassDerivations())) { Subsystem *subsys = (Subsystem*)sim; Check(subsys); entity = subsys->GetEntity(); } else { entity = (Entity*)sim; } Check(entity); // //-------------------------------------------- // Make the explosion at the end of the laser //-------------------------------------------- // Origin explode_origin = laser_origin; laser_line.FindEnd(&explode_origin.linearPosition); // //------------------ // Make an Explosion //------------------ // Check(application); ResourceFile *resource_file = application->GetResourceFile(); Check(resource_file); ResourceDescription *explosion_res = resource_file->FindResourceDescription(explosionResourceID); Check(explosion_res); explosion_res->Lock(); Explosion::MakeMessage exp_message( Explosion::MakeMessageID, sizeof(Explosion::MakeMessage), ExplosionClassID, EntityID::Null, explosion_res->resourceID, Explosion::DefaultFlags, explode_origin, entity->GetEntityID(), owningEntity->GetEntityID() ); explosion_res->Unlock(); #if DEBUG_LEVEL>0 Explosion *exp = #endif Explosion::Make(&exp_message); Register_Object(exp); // //-------------------------------------------------------- // Initialize the Positional info in the damage structure //-------------------------------------------------------- // damageData.damageForce = Vector3D::Identity; damageData.impactPoint = explode_origin.linearPosition; // //------------------------------------------ // Send a damage message to the thing we hit //------------------------------------------ // Entity::TakeDamageMessage take_damage( Entity::TakeDamageMessageID, sizeof(Entity::TakeDamageMessage), vtv->GetEntityID(), 0, damageData ); entity->Dispatch(&take_damage); Check_Fpu(); return True; } else { Check_Fpu(); return False; } } //############################################################################# // Damage Support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LaserGun::DeathReset(int reset_command) { Check(this); if (reset_command == VTV::FootballReset) { chargeLevel = maxChargeLevel; } frontLaserOn = False; rearLaserOn = False; laserScale.x = 1.0f; laserScale.y = 1.0f; laserScale.z = 1.0f; SetSimulationState(Charging); SetPerformance(&LaserGun::ChargingSimulation); ForceUpdate(); Check_Fpu(); } //############################################################################# // Construction And Destruction // LaserGun::LaserGun( VTV *owner, int subsystem_ID, SubsystemResource *sub_res, SharedData &shared_data ) : GenericGun(owner, subsystem_ID, sub_res, shared_data) { Check(owner); Check_Pointer(&sub_res); // //------------------------------------ // get values from subsystem resource //------------------------------------ // maxChargeLevel = 1.0f; maxLaserLength = sub_res->laserLength; fullChargeDuration = sub_res->fullChargeDuration; chargePerSecond = sub_res->chargePerSecond; explosionResourceID = sub_res->explosionResourceID; maxLaserDuration = sub_res->laserDuration; maxPulseDuration = sub_res->pulseDuration; Scalar cycle_time = maxLaserDuration + maxPulseDuration; damageData = sub_res->damageData; damageData.damageAmount *= cycle_time; drainPerSecond = sub_res->drainPerSecond * cycle_time; // //----------------------- // Init local variables //----------------------- // chargeLevel = 1.0f; percentDone = 1.0f; laserDuration = 0.0f; hitSomething = False; frontLaserOn = False; rearLaserOn = False; laserScale.x = 1.0f; laserScale.y = 1.0f; laserScale.z = 1.0f; pulseDuration = 0.0f; SetPerformance(&LaserGun::ChargingSimulation); if (owner->GetInstance() == VTV::ReplicantInstance) { ExecuteOnUpdate(); } SetSimulationState(Charging); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LaserGun::~LaserGun() { } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical LaserGun::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CreateStreamedSubsystem // int LaserGun::CreateStreamedSubsystem( NotationFile *model_file, const char *model_name, const char *subsystem_name, SubsystemResource *subsystem_resource, NotationFile *subsystem_file, ResourceFile *resource_file, const ResourceDirectories *directories ) { if ( !GenericGun::CreateStreamedSubsystem( model_file, model_name, subsystem_name, subsystem_resource, subsystem_file, resource_file, directories ) ) { Check_Fpu(); return False; } subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); subsystem_resource->classID = RegisteredClass::LaserDrillClassID; if( !subsystem_file->GetEntry( subsystem_name, "ChargePerSecond", &subsystem_resource->chargePerSecond ) ) { DEBUG_STREAM << subsystem_name << "missing ChargePerSecond!\n" << std::flush; Check_Fpu(); return False; } if( !subsystem_file->GetEntry( subsystem_name, "DrainPerSecond", &subsystem_resource->drainPerSecond ) ) { DEBUG_STREAM << subsystem_name << "missing DrainPerSecond!\n" << std::flush; Check_Fpu(); return False; } if( !subsystem_file->GetEntry( subsystem_name, "DamageAmount", &subsystem_resource->damageData.damageAmount ) ) { DEBUG_STREAM << subsystem_name << "missing DamageAmount!\n" << std::flush; Check_Fpu(); return False; } else { // //------------------------- // Initialize damage fields //------------------------- // subsystem_resource->damageData.damageType = Damage::LaserDamageType; subsystem_resource->damageData.damageForce = Vector3D::Identity; subsystem_resource->damageData.surfaceNormal.x = 0.0f; subsystem_resource->damageData.surfaceNormal.y = 1.0f; subsystem_resource->damageData.surfaceNormal.z = 0.0f; subsystem_resource->damageData.impactPoint = Vector3D::Identity; } if( !subsystem_file->GetEntry( subsystem_name, "FullChargeDuration", &subsystem_resource->fullChargeDuration ) ) { DEBUG_STREAM << subsystem_name << "missing FullChargeDuration!\n" << std::flush; Check_Fpu(); return False; } else { // //----------------- // Calc chargeLevel //----------------- // subsystem_resource->chargeLevel = subsystem_resource->fullChargeDuration / subsystem_resource->drainPerSecond; } if( !subsystem_file->GetEntry( subsystem_name, "PulseDuration", &subsystem_resource->pulseDuration ) ) { DEBUG_STREAM << subsystem_name << "missing PulseDuration!\n" << std::flush; Check_Fpu(); return False; } if( !subsystem_file->GetEntry( subsystem_name, "LaserLength", &subsystem_resource->laserLength ) ) { DEBUG_STREAM << subsystem_name << "missing LaserLength!\n" << std::flush; Check_Fpu(); return False; } if( !subsystem_file->GetEntry( subsystem_name, "LaserDuration", &subsystem_resource->laserDuration ) ) { DEBUG_STREAM << subsystem_name << "missing LaserDuration!\n" << std::flush; Check_Fpu(); return False; } // //---------------------------------------------------------------------- // Read in the Model Filename of the Explosion renderable, then find its // resource ID in the resource file //---------------------------------------------------------------------- // const char *explosion; if( !subsystem_file->GetEntry( subsystem_name, "ExplosionModelFile", &explosion ) ) { std::cout << model_name << " missing ExplosionModelFile!\n" << std::flush; Check_Fpu(); return False; } ResourceDescription *res = resource_file->FindResourceDescription( explosion, ResourceDescription::ModelListResourceType ); if (!res) { std::cout << model_name << " cannot find " << explosion << " in resource file!\n" << std::flush; Check_Fpu(); return False; } subsystem_resource->explosionResourceID = res->resourceID; return True; } //############################################################################ //################ Class DemolitionPackDropper ######################## //############################################################################ //############################################################################# // Shared Data Support // DemolitionPackDropper::SharedData DemolitionPackDropper::DefaultData( DemolitionPackDropper::GetClassDerivations(), DemolitionPackDropper::MessageHandlers, DemolitionPackDropper::GetAttributeIndex(), DemolitionPackDropper::StateCount ); Derivation* DemolitionPackDropper::GetClassDerivations() { static Derivation classDerivations(RivetGun::GetClassDerivations(), "DemolitionPackDropper"); return &classDerivations; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void DemolitionPackDropper::DeathReset(int) { // //--------------------------------------------------- // Make sure we are not firing and reset variables //--------------------------------------------------- // Check(this); SetSimulationState(Loading); Check_Fpu(); } //############################################################################# // Construction And Destruction // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // DemolitionPackDropper::DemolitionPackDropper( VTV *owner, int subsystem_ID, SubsystemResource *sub_res, SharedData &shared_data ) : RivetGun(owner, subsystem_ID, sub_res, shared_data) { } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // DemolitionPackDropper::~DemolitionPackDropper() { Check(this); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical DemolitionPackDropper::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int DemolitionPackDropper::Fire() { Check(this); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // std::decrement ammoCount and reset the loadTime //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // --ammoCount; timeToLoaded = loadTime; // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Get the entity and it's current position // Add this to the siteTransform to determine // where to shoot the rivet from //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Motion mine_motion; CalcAmmoMotion(&mine_motion); // //----------------------------- // Move the rivet to the site //----------------------------- // Origin mine_localOrigin; CalcAmmoOrigin(&mine_localOrigin); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Create a New Mine Whose properties are listed in the // Resource File //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // VTV *vtv = GetEntity(); Check(vtv); DemolitionPack::MakeMessage create_mine( DemolitionPack::MakeMessageID, sizeof(Rivet::MakeMessage), (Entity::ClassID) DemolitionPack::DemolitionPackClassID, DemolitionPackDropperClassID, ammoVideoResourceID, DemolitionPack::DefaultFlags, mine_localOrigin, mine_motion, Motion::Identity, vtv->GetEntityID() ); #if DEBUG_LEVEL>0 DemolitionPack* my_mine = DemolitionPack::Make(&create_mine); Register_Object(my_mine); #else DemolitionPack::Make(&create_mine); #endif Check_Fpu(); return 1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CreateStreamedSubsystem // int DemolitionPackDropper::CreateStreamedSubsystem( NotationFile *model_file, const char *model_name, const char *subsystem_name, SubsystemResource *subsystem_resource, NotationFile *subsystem_file, ResourceFile *resource_file, const ResourceDirectories *directories ) { if ( !RivetGun::CreateStreamedSubsystem( model_file, model_name, subsystem_name, subsystem_resource, subsystem_file, resource_file, directories ) ) { Check_Fpu(); return False; } subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); subsystem_resource->classID = RegisteredClass::DemolitionPackDropperClassID; Check_Fpu(); return True; }