mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-09-25 10:12:52 -04:00
3425 lines
119 KiB
C++
Executable File
3425 lines
119 KiB
C++
Executable File
//======================================================================
|
|
//
|
|
// ShipObject_Components.cpp
|
|
// copyright (c) 2004 Sony Online Entertainment
|
|
//
|
|
//======================================================================
|
|
|
|
#include "serverGame/FirstServerGame.h"
|
|
#include "serverGame/ShipObject_Components.h"
|
|
|
|
#include "UnicodeUtils.h"
|
|
#include "serverGame/Chat.h"
|
|
#include "serverGame/ContainerInterface.h"
|
|
#include "serverGame/CreatureObject.h"
|
|
#include "serverGame/MissileManager.h"
|
|
#include "serverGame/PlayerObject.h"
|
|
#include "serverGame/ResourceTypeObject.h"
|
|
#include "serverGame/ServerObjectTemplate.h"
|
|
#include "serverGame/ServerResourceClassObject.h"
|
|
#include "serverGame/ServerUniverse.h"
|
|
#include "serverGame/ServerWorld.h"
|
|
#include "serverGame/ShipComponentDataEngine.h"
|
|
#include "serverGame/ShipComponentDataManager.h"
|
|
#include "serverScript/GameScriptObject.h"
|
|
#include "serverScript/ScriptFunctionTable.h"
|
|
#include "serverScript/ScriptParameters.h"
|
|
#include "sharedFoundation/ConstCharCrcLowerString.h"
|
|
#include "sharedFoundation/ConstCharCrcString.h"
|
|
#include "sharedFoundation/Timer.h"
|
|
#include "sharedGame/SharedStringIds.h"
|
|
#include "sharedGame/ShipChassis.h"
|
|
#include "sharedGame/ShipChassisSlot.h"
|
|
#include "sharedGame/ShipChassisSlotType.h"
|
|
#include "sharedGame/ShipComponentAttachmentManager.h"
|
|
#include "sharedGame/ShipComponentData.h"
|
|
#include "sharedGame/ShipComponentDescriptor.h"
|
|
#include "sharedGame/ShipComponentFlags.h"
|
|
#include "sharedGame/ShipComponentWeaponManager.h"
|
|
#include "sharedGame/ShipTurretManager.h"
|
|
#include "sharedLog/Log.h"
|
|
#include "sharedObject/Appearance.h"
|
|
#include "sharedObject/AppearanceTemplate.h"
|
|
#include "sharedObject/AppearanceTemplateList.h"
|
|
#include "sharedObject/Hardpoint.h"
|
|
#include "sharedObject/NetworkIdManager.h"
|
|
#include "sharedObject/ObjectTemplateList.h"
|
|
#include "sharedObject/PortalProperty.h"
|
|
#include "sharedObject/PortalPropertyTemplate.h"
|
|
#include "sharedObject/VolumeContainer.h"
|
|
|
|
|
|
// ======================================================================
|
|
|
|
namespace ShipObjectNamespace
|
|
{
|
|
ConstCharCrcString const s_turretPitchHardpoint("turretpitch1");
|
|
}
|
|
using namespace ShipObjectNamespace;
|
|
|
|
// ======================================================================
|
|
|
|
uint32 ShipObject::getChassisType () const
|
|
{
|
|
return m_chassisType.get ();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Returns [0.0, 1.0] relating to the hitpoints of the chassis and all installed components
|
|
* 1.0 == pristine, 0.0 == totally broken (though there are other rules to determine if a ship is flyable)
|
|
*/
|
|
float ShipObject::getOverallHealth() const
|
|
{
|
|
float total = 0.0f;
|
|
int numComponents = 0;
|
|
if(getMaximumChassisHitPoints() > 0.0)
|
|
{
|
|
total += getCurrentChassisHitPoints() / getMaximumChassisHitPoints();
|
|
++numComponents;
|
|
}
|
|
|
|
for(int i = ShipChassisSlotType::SCST_first; i != ShipChassisSlotType::SCST_num_types; ++i)
|
|
{
|
|
if(isSlotInstalled(i))
|
|
{
|
|
if(getComponentHitpointsMaximum(i) > 0.0f)
|
|
{
|
|
total += getComponentHitpointsCurrent(i) / getComponentHitpointsMaximum(i);
|
|
++numComponents;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(numComponents <= 0)
|
|
return 0.0f;
|
|
else
|
|
return clamp(0.0f, total / numComponents, 1.0f);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getOverallHealthWithShieldsAndArmor() const
|
|
{
|
|
int numberObjectsToWeight = 0;
|
|
|
|
float total = getOverallHealth();
|
|
++numberObjectsToWeight;
|
|
|
|
float const shieldHitpointsFrontMaximum = getShieldHitpointsFrontMaximum();
|
|
if (shieldHitpointsFrontMaximum != 0.0)
|
|
{
|
|
total += getShieldHitpointsFrontCurrent() / shieldHitpointsFrontMaximum;
|
|
++numberObjectsToWeight;
|
|
}
|
|
|
|
float const shieldHitpointsBackMaximum = getShieldHitpointsBackMaximum();
|
|
if (shieldHitpointsBackMaximum != 0.0)
|
|
{
|
|
total += getShieldHitpointsBackCurrent() / shieldHitpointsBackMaximum;
|
|
++numberObjectsToWeight;
|
|
}
|
|
|
|
float const componentArmorHitpointsMaximum0 = getComponentArmorHitpointsMaximum(ShipChassisSlotType::SCST_armor_0);
|
|
if (componentArmorHitpointsMaximum0 != 0.0)
|
|
{
|
|
total += getComponentArmorHitpointsCurrent(ShipChassisSlotType::SCST_armor_0) / componentArmorHitpointsMaximum0;
|
|
++numberObjectsToWeight;
|
|
}
|
|
|
|
float const componentArmorHitpointsMaximum1 = getComponentArmorHitpointsMaximum(ShipChassisSlotType::SCST_armor_1);
|
|
if (componentArmorHitpointsMaximum1 != 0.0)
|
|
{
|
|
total += getComponentArmorHitpointsCurrent(ShipChassisSlotType::SCST_armor_1) / componentArmorHitpointsMaximum1;
|
|
++numberObjectsToWeight;
|
|
}
|
|
|
|
return clamp(0.0f, total / static_cast<float>(numberObjectsToWeight), 1.0f);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getComponentArmorHitpointsMaximum (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_componentArmorHitpointsMaximum.find (chassisSlot);
|
|
if (it != m_componentArmorHitpointsMaximum.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getComponentArmorHitpointsCurrent (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_componentArmorHitpointsCurrent.find (chassisSlot);
|
|
if (it != m_componentArmorHitpointsCurrent.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getComponentEfficiencyGeneral (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_componentEfficiencyGeneral.find (chassisSlot);
|
|
if (it != m_componentEfficiencyGeneral.end ())
|
|
return (*it).second;
|
|
return 1.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getComponentEfficiencyEnergy (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_componentEfficiencyEnergy.find (chassisSlot);
|
|
if (it != m_componentEfficiencyEnergy.end ())
|
|
return (*it).second;
|
|
return 1.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getComponentEnergyMaintenanceRequirement (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_componentEnergyMaintenanceRequirement.find (chassisSlot);
|
|
if (it != m_componentEnergyMaintenanceRequirement.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getComponentMass (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_componentMass.find (chassisSlot);
|
|
if (it != m_componentMass.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
uint32 ShipObject::getComponentCrc (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, uint32>::const_iterator const it = m_componentCrc.find (chassisSlot);
|
|
if (it != m_componentCrc.end ())
|
|
return (*it).second;
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getComponentHitpointsCurrent (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_componentHitpointsCurrent.find (chassisSlot);
|
|
if (it != m_componentHitpointsCurrent.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getComponentHitpointsMaximum (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_componentHitpointsMaximum.find (chassisSlot);
|
|
if (it != m_componentHitpointsMaximum.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int ShipObject::getComponentFlags (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, int>::const_iterator const it = m_componentFlags.find (chassisSlot);
|
|
if (it != m_componentFlags.end ())
|
|
return (*it).second;
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
Unicode::String const &ShipObject::getComponentName(int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, Unicode::String>::const_iterator const it = m_componentNames.find (chassisSlot);
|
|
if (it != m_componentNames.end() && !(*it).second.empty())
|
|
return (*it).second;
|
|
|
|
return Unicode::emptyString;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
NetworkId const &ShipObject::getComponentCreator(int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, NetworkId>::const_iterator const it = m_componentCreators.find (chassisSlot);
|
|
if (it != m_componentCreators.end())
|
|
return (*it).second;
|
|
|
|
return NetworkId::cms_invalid;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponDamageMaximum (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_weaponDamageMaximum.find (chassisSlot);
|
|
if (it != m_weaponDamageMaximum.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponDamageMinimum (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_weaponDamageMinimum.find (chassisSlot);
|
|
if (it != m_weaponDamageMinimum.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponEffectivenessShields (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_weaponEffectivenessShields.find (chassisSlot);
|
|
if (it != m_weaponEffectivenessShields.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponEffectivenessArmor (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_weaponEffectivenessArmor.find (chassisSlot);
|
|
if (it != m_weaponEffectivenessArmor.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponEnergyPerShot (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_weaponEnergyPerShot.find (chassisSlot);
|
|
if (it != m_weaponEnergyPerShot.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponActualEnergyPerShot(int chassisSlot) const
|
|
{
|
|
float const weaponEfficiencyEnergy = std::max(0.1f, getComponentEfficiencyEnergy(chassisSlot));
|
|
return getWeaponEnergyPerShot(chassisSlot) / weaponEfficiencyEnergy;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponRefireRate (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_weaponRefireRate.find (chassisSlot);
|
|
if (it != m_weaponRefireRate.end ())
|
|
return (*it).second;
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponActualRefireRate (int chassisSlot) const
|
|
{
|
|
if (!isSlotInstalled(chassisSlot))
|
|
return 0.0f;
|
|
|
|
float const eff = clamp(0.1f, getWeaponEfficiencyRefireRate(chassisSlot), 10.0f);
|
|
return getWeaponRefireRate(chassisSlot) / eff;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponEfficiencyRefireRate (int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, float>::const_iterator const it = m_weaponEfficiencyRefireRate.find (chassisSlot);
|
|
if (it != m_weaponEfficiencyRefireRate.end ())
|
|
return (*it).second;
|
|
return 1.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int ShipObject::getWeaponAmmoCurrent(int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, int>::const_iterator const it = m_weaponAmmoCurrent.find (chassisSlot);
|
|
if (it != m_weaponAmmoCurrent.end ())
|
|
return (*it).second;
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int ShipObject::getWeaponAmmoMaximum(int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, int>::const_iterator const it = m_weaponAmmoMaximum.find (chassisSlot);
|
|
if (it != m_weaponAmmoMaximum.end ())
|
|
return (*it).second;
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
uint32 ShipObject::getWeaponAmmoType(int chassisSlot) const
|
|
{
|
|
Archive::AutoDeltaMap<int, uint32>::const_iterator const it = m_weaponAmmoType.find (chassisSlot);
|
|
if (it != m_weaponAmmoType.end ())
|
|
return (*it).second;
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShieldHitpointsFrontCurrent () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_shield_0))
|
|
return m_shieldHitpointsFrontCurrent.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShieldHitpointsFrontMaximum () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_shield_0))
|
|
return m_shieldHitpointsFrontMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShieldHitpointsBackCurrent () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_shield_0))
|
|
return m_shieldHitpointsBackCurrent.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShieldHitpointsBackMaximum () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_shield_0))
|
|
return m_shieldHitpointsBackMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShieldRechargeRate () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_shield_0))
|
|
return m_shieldRechargeRate.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getCapacitorEnergyCurrent () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_capacitor))
|
|
return m_capacitorEnergyCurrent.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getCapacitorEnergyMaximum () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_capacitor))
|
|
return m_capacitorEnergyMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getCapacitorEnergyEffectiveMaximum () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_capacitor) && isComponentFunctional(ShipChassisSlotType::SCST_capacitor))
|
|
return m_capacitorEnergyMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getCapacitorEnergyRechargeRate () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_capacitor))
|
|
return m_capacitorEnergyRechargeRate.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEngineAccelerationRate () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_engineAccelerationRate.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEngineDecelerationRate () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_engineDecelerationRate.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEnginePitchAccelerationRate () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_enginePitchAccelerationRate.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEngineYawAccelerationRate () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_engineYawAccelerationRate.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEngineRollAccelerationRate () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_engineRollAccelerationRate.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEnginePitchRateMaximum () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_enginePitchRateMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEngineYawRateMaximum () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_engineYawRateMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEngineRollRateMaximum () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_engineRollRateMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEngineSpeedMaximum () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_engineSpeedMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEngineSpeedRotationFactorMaximum() const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_engineSpeedRotationFactorMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEngineSpeedRotationFactorMinimum() const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_engineSpeedRotationFactorMinimum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getEngineSpeedRotationFactorOptimal() const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
return m_engineSpeedRotationFactorOptimal.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getReactorEnergyGenerationRate () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_reactor))
|
|
return m_reactorEnergyGenerationRate.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getBoosterEnergyCurrent () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_booster))
|
|
return m_boosterEnergyCurrent.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getBoosterEnergyMaximum () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_booster))
|
|
return m_boosterEnergyMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getBoosterEnergyRechargeRate () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_booster))
|
|
return m_boosterEnergyRechargeRate.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getBoosterEnergyConsumptionRate () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_booster))
|
|
return m_boosterEnergyConsumptionRate.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getBoosterAcceleration () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_booster))
|
|
return m_boosterAcceleration.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getBoosterSpeedMaximum () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_booster))
|
|
return m_boosterSpeedMaximum.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getDroidInterfaceCommandSpeed () const
|
|
{
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_droid_interface))
|
|
return m_droidInterfaceCommandSpeed.get ();
|
|
return 0.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::hasSlot (int chassisSlot) const
|
|
{
|
|
ShipChassis const * const shipChassis = ShipChassis::findShipChassisByCrc (getChassisType ());
|
|
return shipChassis && shipChassis->getSlot (static_cast<ShipChassisSlotType::Type>(chassisSlot));
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentArmorHitpointsMaximum (int chassisSlot, float componentArmorHitpointsMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentArmorHitpointsMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentArmorHitpointsMaximum () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_componentArmorHitpointsMaximum.set (chassisSlot, componentArmorHitpointsMaximum);
|
|
//-- force update of current hitpoints
|
|
IGNORE_RETURN(setComponentArmorHitpointsCurrent (chassisSlot, getComponentArmorHitpointsCurrent (chassisSlot)));
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentArmorHitpointsCurrent (int chassisSlot, float componentArmorHitpointsCurrent)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentArmorHitpointsCurrent () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentArmorHitpointsCurrent () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
componentArmorHitpointsCurrent = std::min (getComponentArmorHitpointsMaximum (chassisSlot), componentArmorHitpointsCurrent);
|
|
m_componentArmorHitpointsCurrent.set (chassisSlot, componentArmorHitpointsCurrent);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentEfficiencyGeneral (int chassisSlot, float componentEfficiencyGeneral)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentEfficiencyGeneral () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentEfficiencyGeneral () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
componentEfficiencyGeneral = clamp (0.1f, componentEfficiencyGeneral, 10.0f);
|
|
m_componentEfficiencyGeneral.set (chassisSlot, componentEfficiencyGeneral);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentEfficiencyEnergy (int chassisSlot, float componentEfficiencyEnergy)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentEfficiencyEnergy () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentEfficiencyEnergy () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
componentEfficiencyEnergy = clamp (0.1f, componentEfficiencyEnergy, 10.0f);
|
|
m_componentEfficiencyEnergy.set (chassisSlot, componentEfficiencyEnergy);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentEnergyMaintenanceRequirement (int chassisSlot, float componentEnergyMaintenanceRequirement)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentEnergyMaintenanceRequirement () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentEnergyMaintenanceRequirement () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_componentEnergyMaintenanceRequirement.set (chassisSlot, componentEnergyMaintenanceRequirement);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentMass (int chassisSlot, float componentMass)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentMass () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentMass () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_componentMass.set (chassisSlot, componentMass);
|
|
|
|
internalSetChassisComponentMassCurrent(computeChassisComponentMassCurrent());
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Setting a component template crc to zero removes the component
|
|
*/
|
|
|
|
void ShipObject::setComponentCrc (int chassisSlot, uint32 componentCrc)
|
|
{
|
|
if (componentCrc == 0)
|
|
{
|
|
IGNORE_RETURN (m_componentArmorHitpointsMaximum.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentArmorHitpointsCurrent.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentEfficiencyGeneral.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentEfficiencyEnergy.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentEnergyMaintenanceRequirement.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentMass.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentCrc.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentCrcForClient.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentHitpointsCurrent.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentHitpointsMaximum.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentFlags.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentNames.erase (chassisSlot));
|
|
IGNORE_RETURN (m_weaponDamageMaximum.erase (chassisSlot));
|
|
IGNORE_RETURN (m_weaponDamageMinimum.erase (chassisSlot));
|
|
IGNORE_RETURN (m_weaponEffectivenessShields.erase (chassisSlot));
|
|
IGNORE_RETURN (m_weaponEffectivenessArmor.erase (chassisSlot));
|
|
IGNORE_RETURN (m_weaponEnergyPerShot.erase (chassisSlot));
|
|
IGNORE_RETURN (m_weaponRefireRate.erase (chassisSlot));
|
|
IGNORE_RETURN (m_componentCreators.erase (chassisSlot));
|
|
|
|
internalSetChassisComponentMassCurrent(computeChassisComponentMassCurrent());
|
|
}
|
|
else
|
|
{
|
|
m_componentCrc.set (chassisSlot, componentCrc);
|
|
m_componentCrcForClient.set (chassisSlot, componentCrc);
|
|
|
|
//-- all components start out at low power so script gets the first power up pulse
|
|
IGNORE_RETURN(setComponentLowPower (chassisSlot, true));
|
|
|
|
internalSetChassisComponentMassCurrent(computeChassisComponentMassCurrent());
|
|
}
|
|
|
|
if (ShipChassisSlotType::isWeaponChassisSlot(static_cast<ShipChassisSlotType::Type>(chassisSlot)))
|
|
{
|
|
// Cache the turret positions
|
|
{
|
|
int const weaponIndex = ShipChassisSlotType::getWeaponIndex(static_cast<ShipChassisSlotType::Type>(chassisSlot));
|
|
|
|
if (ShipTurretManager::isTurret(getChassisType(), weaponIndex))
|
|
{
|
|
m_turretWeaponIndices->setBit(weaponIndex);
|
|
}
|
|
else
|
|
{
|
|
m_turretWeaponIndices->clearBit(weaponIndex);
|
|
}
|
|
}
|
|
|
|
// Cache for the fastest projectile weapon speed
|
|
{
|
|
m_fastestWeaponProjectileSpeed = 0.0f;
|
|
|
|
for (int weaponIndex = 0; weaponIndex < ShipChassisSlotType::cms_numWeaponIndices; ++weaponIndex)
|
|
{
|
|
if (isProjectile(weaponIndex))
|
|
{
|
|
m_fastestWeaponProjectileSpeed = std::max(m_fastestWeaponProjectileSpeed, getWeaponProjectileSpeed(weaponIndex));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentHitpointsCurrent (int chassisSlot, float componentHitpointsCurrent)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentHitpointsCurrent () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentHitpointsCurrent () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
float const maxHp = getComponentHitpointsMaximum(chassisSlot);
|
|
|
|
componentHitpointsCurrent = std::min (maxHp, componentHitpointsCurrent);
|
|
m_componentHitpointsCurrent.set (chassisSlot, componentHitpointsCurrent);
|
|
|
|
bool const isDemolished = isComponentDemolished(chassisSlot);
|
|
|
|
if (componentHitpointsCurrent <= 0.0f && maxHp > 0.0f && !isDemolished)
|
|
IGNORE_RETURN(setComponentDemolished(chassisSlot, true));
|
|
else if (isDemolished)
|
|
IGNORE_RETURN(setComponentDemolished(chassisSlot, false));
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentHitpointsMaximum (int chassisSlot, float componentHitpointsMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentHitpointsMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentHitpointsMaximum () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_componentHitpointsMaximum.set (chassisSlot, componentHitpointsMaximum);
|
|
IGNORE_RETURN(setComponentHitpointsCurrent (chassisSlot, getComponentHitpointsCurrent (chassisSlot)));
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentFlags (int chassisSlot, int componentFlags)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentFlags () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentFlags () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_componentFlags.set (chassisSlot, componentFlags);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentName(int chassisSlot, Unicode::String const & componentName)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentName () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentName () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_componentNames.set (chassisSlot, componentName);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentCreator(int chassisSlot, NetworkId const & componentCreator)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentName () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentCreator () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
if (componentCreator != NetworkId::cms_invalid)
|
|
m_componentCreators.set (chassisSlot, componentCreator);
|
|
else
|
|
m_componentCreators.erase(chassisSlot);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentDisabled (int chassisSlot, bool componentDisabled)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentDisabled () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentDisabled () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
int const flags = getComponentFlags (chassisSlot);
|
|
|
|
if (componentDisabled)
|
|
{
|
|
IGNORE_RETURN(setComponentFlags(chassisSlot, flags | static_cast<int>(ShipComponentFlags::F_disabled)));
|
|
IGNORE_RETURN(setComponentLowPower(chassisSlot, true));
|
|
IGNORE_RETURN(setComponentActive(chassisSlot, false));
|
|
}
|
|
else
|
|
{
|
|
IGNORE_RETURN(setComponentFlags (chassisSlot, flags & ~static_cast<int>(ShipComponentFlags::F_disabled)));
|
|
IGNORE_RETURN(setComponentDisabledNeedsPower(chassisSlot, false));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentDisabledNeedsPower(int chassisSlot, bool componentDisabledNeedsPower)
|
|
{
|
|
FATAL(isInitialized() && !isAuthoritative(), ("ShipObject::setComponentDisabledNeedsPower() called on non-auth object."));
|
|
if (!isSlotInstalled(chassisSlot))
|
|
{
|
|
WARNING(true, ("ShipObject::setComponentDisabledNeedsPower() called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
int const flags = getComponentFlags(chassisSlot);
|
|
|
|
if (componentDisabledNeedsPower)
|
|
IGNORE_RETURN(setComponentFlags(chassisSlot, flags | static_cast<int>(ShipComponentFlags::F_disabledNeedsPower)));
|
|
else
|
|
IGNORE_RETURN(setComponentFlags(chassisSlot, flags & ~static_cast<int>(ShipComponentFlags::F_disabledNeedsPower)));
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentLowPower (int chassisSlot, bool componentLowPower)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentLowPower () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentLowPower () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
int const flags = getComponentFlags (chassisSlot);
|
|
|
|
if (componentLowPower)
|
|
IGNORE_RETURN(setComponentFlags (chassisSlot, flags | static_cast<int>(ShipComponentFlags::F_lowPower)));
|
|
else
|
|
IGNORE_RETURN(setComponentFlags (chassisSlot, flags & ~static_cast<int>(ShipComponentFlags::F_lowPower)));
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentActive (int chassisSlot, bool componentActive)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentActive() called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentActive() called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
int const flags = getComponentFlags (chassisSlot);
|
|
|
|
if (componentActive)
|
|
IGNORE_RETURN(setComponentFlags (chassisSlot, flags | static_cast<int>(ShipComponentFlags::F_active)));
|
|
else
|
|
IGNORE_RETURN(setComponentFlags (chassisSlot, flags & ~static_cast<int>(ShipComponentFlags::F_active)));
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setComponentDemolished(int chassisSlot, bool const componentDemolished)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setComponentDemolished() called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setComponentDemolished() called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
int const flags = getComponentFlags (chassisSlot);
|
|
|
|
if (componentDemolished)
|
|
IGNORE_RETURN(setComponentFlags (chassisSlot, flags | static_cast<int>(ShipComponentFlags::F_demolished)));
|
|
else
|
|
IGNORE_RETURN(setComponentFlags (chassisSlot, flags & ~static_cast<int>(ShipComponentFlags::F_demolished)));
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setWeaponDamageMaximum (int chassisSlot, float weaponDamageMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponDamageMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setWeaponDamageMaximum () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_weaponDamageMaximum.set (chassisSlot, weaponDamageMaximum);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setWeaponDamageMinimum (int chassisSlot, float weaponDamageMinimum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponDamageMinimum () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setWeaponDamageMinimum () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_weaponDamageMinimum.set (chassisSlot, weaponDamageMinimum);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setWeaponEffectivenessShields (int chassisSlot, float weaponEffectivenessShields)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponEffectivenessShields () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setWeaponEffectivenessShields () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_weaponEffectivenessShields.set (chassisSlot, weaponEffectivenessShields);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setWeaponEffectivenessArmor (int chassisSlot, float weaponEffectivenessArmor)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponEffectivenessArmor () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setWeaponEffectivenessArmor () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_weaponEffectivenessArmor.set (chassisSlot, weaponEffectivenessArmor);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setWeaponEnergyPerShot (int chassisSlot, float weaponEnergyPerShot)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponEnergyPerShot () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setWeaponEnergyPerShot () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_weaponEnergyPerShot.set (chassisSlot, weaponEnergyPerShot);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setWeaponRefireRate (int chassisSlot, float weaponRefireRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponRefireRate () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setWeaponRefireRate () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_weaponRefireRate.set (chassisSlot, weaponRefireRate);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setWeaponEfficiencyRefireRate (int chassisSlot, float weaponEfficiencyRefireRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponEfficiencyRefireRate () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setWeaponEfficiencyRefireRate () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_weaponEfficiencyRefireRate.set (chassisSlot, weaponEfficiencyRefireRate);
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Set a weapon's refire timer to have the specified percentage of its time
|
|
* already elapsed. For example, 0.25 will prevent the weapon from firing
|
|
* again until 75% of its regular refire time has elapsed. This setting
|
|
* applies to the next shot only; future shots will use the regular refire rate.
|
|
*/
|
|
void ShipObject::setWeaponRefireTimerPercent(int weaponIndex, float refireTimerPercent)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponRefireTimerPercent () called on non-auth object."));
|
|
m_weaponRefireTimers[weaponIndex].setElapsedTime(refireTimerPercent * getWeaponActualRefireRate(static_cast<int>(ShipChassisSlotType::SCST_weapon_first) + weaponIndex));
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setWeaponAmmoCurrent(int chassisSlot, int weaponAmmoCurrent)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponProjectileSpeed () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setWeaponAmmoCurrent () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_weaponAmmoCurrent.set (chassisSlot, weaponAmmoCurrent);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setWeaponAmmoMaximum(int chassisSlot, int weaponAmmoMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponProjectileSpeed () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setWeaponAmmoMaximum () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_weaponAmmoMaximum.set (chassisSlot, weaponAmmoMaximum);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setWeaponAmmoType(int chassisSlot, uint32 weaponAmmoType)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setWeaponProjectileSpeed () called on non-auth object."));
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::setWeaponAmmoType () called on slot [%d] with nothing installed.", chassisSlot));
|
|
return false;
|
|
}
|
|
|
|
m_weaponAmmoType.set (chassisSlot, weaponAmmoType);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setShieldHitpointsFrontCurrent (float shieldHitpointsCurrent)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setShieldHitpointsFrontCurrent () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_shield_0)))
|
|
{
|
|
WARNING (true, ("ShipObject::setShieldHitpointsFrontCurrent () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_shield_0)));
|
|
return false;
|
|
}
|
|
|
|
shieldHitpointsCurrent = std::min (getShieldHitpointsFrontMaximum (), shieldHitpointsCurrent);
|
|
m_shieldHitpointsFrontCurrent.set (shieldHitpointsCurrent);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setShieldHitpointsFrontMaximum (float shieldHitpointsMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setShieldHitpointsFrontMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_shield_0)))
|
|
{
|
|
WARNING (true, ("ShipObject::setShieldHitpointsFrontMaximum () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_shield_0)));
|
|
return false;
|
|
}
|
|
|
|
m_shieldHitpointsFrontMaximum.set (shieldHitpointsMaximum);
|
|
IGNORE_RETURN(setShieldHitpointsFrontCurrent (getShieldHitpointsFrontCurrent ()));
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setShieldHitpointsBackCurrent (float shieldHitpointsCurrent)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setShieldHitpointsBackCurrent () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_shield_0)))
|
|
{
|
|
WARNING (true, ("ShipObject::setShieldHitpointsBackCurrent () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_shield_0)));
|
|
return false;
|
|
}
|
|
|
|
shieldHitpointsCurrent = std::min (getShieldHitpointsBackMaximum (), shieldHitpointsCurrent);
|
|
m_shieldHitpointsBackCurrent.set (shieldHitpointsCurrent);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setShieldHitpointsBackMaximum (float shieldHitpointsMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setShieldHitpointsBackMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_shield_0)))
|
|
{
|
|
WARNING (true, ("ShipObject::setShieldHitpointsBackMaximum () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_shield_0)));
|
|
return false;
|
|
}
|
|
|
|
m_shieldHitpointsBackMaximum.set (shieldHitpointsMaximum);
|
|
IGNORE_RETURN(setShieldHitpointsBackCurrent (getShieldHitpointsBackCurrent ()));
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setShieldRechargeRate (float shieldRechargeRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setShieldRechargeRate () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_shield_0)))
|
|
{
|
|
WARNING (true, ("ShipObject::setShieldRechargeRate () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_shield_0)));
|
|
return false;
|
|
}
|
|
|
|
m_shieldRechargeRate.set (shieldRechargeRate);
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setCapacitorEnergyCurrent (float capacitorEnergyCurrent)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setCapacitorEnergyCurrent () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_capacitor)))
|
|
{
|
|
WARNING (true, ("ShipObject::setCapacitorEnergyCurrent () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_capacitor)));
|
|
return false;
|
|
}
|
|
|
|
float const capacitorEnergyMaximum = getCapacitorEnergyEffectiveMaximum () * getComponentEfficiencyGeneral(ShipChassisSlotType::SCST_capacitor);
|
|
capacitorEnergyCurrent = std::min (capacitorEnergyMaximum, capacitorEnergyCurrent);
|
|
m_capacitorEnergyCurrent = capacitorEnergyCurrent;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setCapacitorEnergyMaximum (float capacitorEnergyMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setCapacitorEnergyMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_capacitor)))
|
|
{
|
|
WARNING (true, ("ShipObject::setCapacitorEnergyMaximum () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_capacitor)));
|
|
return false;
|
|
}
|
|
|
|
m_capacitorEnergyMaximum = capacitorEnergyMaximum;
|
|
IGNORE_RETURN(setCapacitorEnergyCurrent (getCapacitorEnergyCurrent ()));
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setCapacitorEnergyRechargeRate (float capacitorEnergyRechargeRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setCapacitorEnergyRechargeRate () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_capacitor)))
|
|
{
|
|
WARNING (true, ("ShipObject::setCapacitorEnergyRechargeRate () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_capacitor)));
|
|
return false;
|
|
}
|
|
|
|
m_capacitorEnergyRechargeRate = capacitorEnergyRechargeRate;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEngineAccelerationRate (float engineAccelerationRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEngineAccelerationRate () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEngineAccelerationRate () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_engineAccelerationRate = engineAccelerationRate;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEngineDecelerationRate (float engineDecelerationRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEngineDecelerationRate () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEngineDecelerationRate () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_engineDecelerationRate = engineDecelerationRate;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEnginePitchAccelerationRate (float enginePitchAccelerationRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEnginePitchAccelerationRate () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEnginePitchAccelerationRate () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_enginePitchAccelerationRate = enginePitchAccelerationRate;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEngineYawAccelerationRate (float engineYawAccelerationRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEngineYawAccelerationRate () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEngineYawAccelerationRate () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_engineYawAccelerationRate = engineYawAccelerationRate;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEngineRollAccelerationRate (float engineRollAccelerationRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEngineRollAccelerationRate () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEngineRollAccelerationRate () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_engineRollAccelerationRate = engineRollAccelerationRate;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEnginePitchRateMaximum (float enginePitchRateMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEnginePitchRateMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEnginePitchRateMaximum () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_enginePitchRateMaximum = enginePitchRateMaximum;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEngineYawRateMaximum (float engineYawRateMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEngineYawRateMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEngineYawRateMaximum () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_engineYawRateMaximum = engineYawRateMaximum;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEngineRollRateMaximum (float engineRollRateMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEngineRollRateMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEngineRollRateMaximum () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_engineRollRateMaximum = engineRollRateMaximum;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEngineSpeedMaximum (float engineSpeedMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEngineSpeedMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEngineSpeedMaximum () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_engineSpeedMaximum = engineSpeedMaximum;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEngineSpeedRotationFactorMaximum(float engineSpeedRotationFactor)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEngineSpeedRotationFactorMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEngineSpeedRotationFactorMaximum () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_engineSpeedRotationFactorMaximum = engineSpeedRotationFactor;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEngineSpeedRotationFactorMinimum(float engineSpeedRotationFactorMin)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEngineSpeedRotationFactorMinimum() called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEngineSpeedRotationFactorMinimum() called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_engineSpeedRotationFactorMinimum = engineSpeedRotationFactorMin;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setEngineSpeedRotationFactorOptimal(float engineSpeedRotationFactorOptimal)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setEngineSpeedRotationFactorOptimal() called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_engine)))
|
|
{
|
|
WARNING (true, ("ShipObject::setEngineSpeedRotationFactorOptimal() called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_engine)));
|
|
return false;
|
|
}
|
|
|
|
m_engineSpeedRotationFactorOptimal = engineSpeedRotationFactorOptimal;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setReactorEnergyGenerationRate (float reactorEnergyGenerationRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setReactorEnergyGenerationRate () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_reactor)))
|
|
{
|
|
WARNING (true, ("ShipObject::setReactorEnergyGenerationRate () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_reactor)));
|
|
return false;
|
|
}
|
|
|
|
m_reactorEnergyGenerationRate = reactorEnergyGenerationRate;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setBoosterEnergyCurrent (float boosterEnergyCurrent)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setBoosterEnergyCurrent () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_booster)))
|
|
{
|
|
WARNING (true, ("ShipObject::setBoosterEnergyCurrent () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_booster)));
|
|
return false;
|
|
}
|
|
|
|
boosterEnergyCurrent = std::min (getBoosterEnergyMaximum (), boosterEnergyCurrent);
|
|
m_boosterEnergyCurrent = boosterEnergyCurrent;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setBoosterEnergyMaximum (float boosterEnergyMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setBoosterEnergyMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_booster)))
|
|
{
|
|
WARNING (true, ("ShipObject::setBoosterEnergyMaximum () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_booster)));
|
|
return false;
|
|
}
|
|
|
|
m_boosterEnergyMaximum = boosterEnergyMaximum;
|
|
IGNORE_RETURN(setBoosterEnergyCurrent (getBoosterEnergyCurrent ()));
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setBoosterEnergyRechargeRate (float boosterEnergyRechargeRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setBoosterEnergyRechargeRate () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_booster)))
|
|
{
|
|
WARNING (true, ("ShipObject::setBoosterEnergyRechargeRate () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_booster)));
|
|
return false;
|
|
}
|
|
|
|
m_boosterEnergyRechargeRate = boosterEnergyRechargeRate;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setBoosterEnergyConsumptionRate (float boosterEnergyConsumptionRate)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setBoosterEnergyConsumptionRate () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_booster)))
|
|
{
|
|
WARNING (true, ("ShipObject::setBoosterEnergyConsumptionRate () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_booster)));
|
|
return false;
|
|
}
|
|
|
|
m_boosterEnergyConsumptionRate = boosterEnergyConsumptionRate;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setBoosterAcceleration (float boosterAcceleration)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setBoosterAcceleration () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_booster)))
|
|
{
|
|
WARNING (true, ("ShipObject::setBoosterAcceleration () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_booster)));
|
|
return false;
|
|
}
|
|
|
|
m_boosterAcceleration = boosterAcceleration;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setBoosterSpeedMaximum (float boosterSpeedMaximum)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setBoosterSpeedMaximum () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_booster)))
|
|
{
|
|
WARNING (true, ("ShipObject::setBoosterSpeedMaximum () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_booster)));
|
|
return false;
|
|
}
|
|
|
|
m_boosterSpeedMaximum = boosterSpeedMaximum;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setDroidInterfaceCommandSpeed (float droidInterfaceCommandSpeed)
|
|
{
|
|
FATAL (isInitialized () && !isAuthoritative (), ("ShipObject::setDroidInterfaceCommandSpeed () called on non-auth object."));
|
|
if (!isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_droid_interface)))
|
|
{
|
|
WARNING (true, ("ShipObject::setDroidInterfaceCommandSpeed () called on slot [%d] with nothing installed.", static_cast<int>(ShipChassisSlotType::SCST_droid_interface)));
|
|
return false;
|
|
}
|
|
|
|
m_droidInterfaceCommandSpeed = droidInterfaceCommandSpeed;
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::canInstallComponent (int chassisSlot, TangibleObject const & component) const
|
|
{
|
|
ShipComponentData const * const shipComponentData = ShipComponentDataManager::create (component);
|
|
if (!shipComponentData)
|
|
{
|
|
WARNING (true, ("ShipObject::canInstallComponent failed for [%s] because a ShipComponentData could not be constructed.", component.getNetworkId ().getValueString ().c_str ()));
|
|
return false;
|
|
}
|
|
|
|
if (chassisSlot < static_cast<int>(ShipChassisSlotType::SCST_first) ||
|
|
chassisSlot >= static_cast<int>(ShipChassisSlotType::SCST_num_types))
|
|
{
|
|
WARNING (true, ("ShipObject::canInstallComponent failed for [%s] because a chassisSlot was invalid.", component.getNetworkId ().getValueString ().c_str ()));
|
|
return false;
|
|
}
|
|
|
|
ShipChassis const * const shipChassis = ShipChassis::findShipChassisByCrc (getChassisType ());
|
|
if (shipChassis)
|
|
{
|
|
int effectiveCompatibilitySlot = chassisSlot;
|
|
// weapon slots beyond 7 wrap back to slot 0 for the purposes of compatibility checking on captial ships
|
|
if (isCapitalShip() && chassisSlot >= ShipChassisSlotType::SCST_num_explicit_types && chassisSlot <= ShipChassisSlotType::SCST_weapon_last)
|
|
effectiveCompatibilitySlot = ShipChassisSlotType::SCST_weapon_first+((chassisSlot-ShipChassisSlotType::SCST_weapon_first)&7);
|
|
|
|
ShipChassisSlot const * const slot = shipChassis->getSlot (static_cast<ShipChassisSlotType::Type>(effectiveCompatibilitySlot));
|
|
|
|
if (slot != nullptr)
|
|
{
|
|
if (slot->canAcceptComponent (shipComponentData->getDescriptor ()))
|
|
{
|
|
//-- check for mass availability
|
|
float const massAvailable = getChassisComponentMassMaximum() - getChassisComponentMassCurrent();
|
|
return massAvailable >= shipComponentData->m_mass;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
/**
|
|
* This function destroys the component
|
|
*/
|
|
|
|
bool ShipObject::installComponent (NetworkId const & installerId, int chassisSlot, TangibleObject & component)
|
|
{
|
|
if (!canInstallComponent (chassisSlot, component))
|
|
{
|
|
WARNING (true, ("ShipObject::installComponent failed for [%s] because the component can't go here.", component.getNetworkId ().getValueString ().c_str ()));
|
|
return false;
|
|
}
|
|
|
|
if (isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::installComponent failed for [%s] because the slot is occupied.", component.getNetworkId ().getValueString ().c_str ()));
|
|
return false;
|
|
}
|
|
|
|
ShipComponentData const * const shipComponentData = ShipComponentDataManager::create (component);
|
|
if (!shipComponentData)
|
|
{
|
|
WARNING (true, ("ShipObject::installComponent failed for [%s] because a ShipComponentData could not be constructed.", component.getNetworkId ().getValueString ().c_str ()));
|
|
return false;
|
|
}
|
|
|
|
if(getScriptObject())
|
|
{
|
|
ScriptParams p;
|
|
p.addParam(installerId);
|
|
p.addParam(component.getNetworkId ());
|
|
p.addParam(chassisSlot);
|
|
|
|
if (getScriptObject()->trigAllScripts(Scripting::TRIG_SHIP_COMPONENT_INSTALLING, p) == SCRIPT_OVERRIDE)
|
|
return false;
|
|
}
|
|
|
|
shipComponentData->writeDataToShip (chassisSlot, *this);
|
|
|
|
LOG(
|
|
"CustomerService",
|
|
(
|
|
"ShipComponents: %s (%s), [%s]: added to %s (%s) by %s",
|
|
Unicode::wideToNarrow(component.getObjectName()).c_str(),
|
|
component.getNetworkId().getValueString().c_str(),
|
|
component.getObjectTemplateName(),
|
|
Unicode::wideToNarrow(getObjectName()).c_str(),
|
|
getNetworkId().getValueString().c_str(),
|
|
PlayerObject::getAccountDescription(getOwnerId()).c_str()));
|
|
|
|
IGNORE_RETURN (component.permanentlyDestroy (DeleteReasons::Consumed));
|
|
|
|
if(getScriptObject())
|
|
{
|
|
ScriptParams p;
|
|
p.addParam(installerId);
|
|
p.addParam (chassisSlot);
|
|
|
|
IGNORE_RETURN (getScriptObject()->trigAllScripts(Scripting::TRIG_SHIP_COMPONENT_INSTALLED, p));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void ShipObject::purgeComponent (int chassisSlot)
|
|
{
|
|
IGNORE_RETURN (internalUninstallComponent (NetworkId::cms_invalid, chassisSlot, nullptr));
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
TangibleObject * ShipObject::internalUninstallComponent (NetworkId const & uninstallerId, int chassisSlot, ServerObject * containerTarget, bool allowOverload)
|
|
{
|
|
if (!isSlotInstalled (chassisSlot))
|
|
{
|
|
WARNING (true, ("ShipObject::internalUninstallComponent failed... no component installed in slot"));
|
|
return nullptr;
|
|
}
|
|
|
|
ShipComponentData * const shipComponentData = createShipComponentData (chassisSlot);
|
|
|
|
if (shipComponentData == nullptr)
|
|
{
|
|
WARNING (true, ("ShipObject::internalUninstallComponent failed nullptr data"));
|
|
delete shipComponentData;
|
|
return nullptr;
|
|
}
|
|
|
|
if(getScriptObject())
|
|
{
|
|
ScriptParams p;
|
|
p.addParam(uninstallerId);
|
|
p.addParam (chassisSlot);
|
|
p.addParam (containerTarget ? containerTarget->getNetworkId () : NetworkId::cms_invalid);
|
|
|
|
if (getScriptObject()->trigAllScripts(Scripting::TRIG_SHIP_COMPONENT_UNINSTALLING, p) == SCRIPT_OVERRIDE)
|
|
return nullptr;
|
|
}
|
|
|
|
TangibleObject * tangible = 0;
|
|
|
|
if (containerTarget)
|
|
{
|
|
uint32 const objectTemplateCrc = shipComponentData->getDescriptor ().getObjectTemplateCrc ();
|
|
|
|
ServerObject * obj = 0;
|
|
if (allowOverload)
|
|
{
|
|
|
|
VolumeContainer * volContainer = ContainerInterface::getVolumeContainer(*containerTarget);
|
|
if (volContainer == nullptr)
|
|
return 0;
|
|
|
|
int oldCapacity = volContainer->debugDoNotUseSetCapacity(-1);
|
|
|
|
obj = ServerWorld::createNewObject(objectTemplateCrc, *containerTarget, true, true);
|
|
|
|
volContainer->debugDoNotUseSetCapacity(oldCapacity);
|
|
volContainer->recalculateVolume();
|
|
}
|
|
else
|
|
{
|
|
obj = safe_cast<ServerObject *>(ServerWorld::createNewObject (objectTemplateCrc, *containerTarget, true));
|
|
}
|
|
|
|
if (obj == nullptr)
|
|
{
|
|
WARNING (true, ("ShipObject::internalUninstallComponent failed for slot [%d] because ServerWorld could not create an object for [%d], or container is full", chassisSlot, objectTemplateCrc));
|
|
delete shipComponentData;
|
|
return nullptr;
|
|
}
|
|
|
|
tangible = obj->asTangibleObject ();
|
|
|
|
if (tangible == nullptr)
|
|
{
|
|
WARNING (true, ("ShipObject::internalUninstallComponent failed for slot [%d] because object template [%d] is not tangible", chassisSlot, objectTemplateCrc));
|
|
delete shipComponentData;
|
|
IGNORE_RETURN (obj->permanentlyDestroy (DeleteReasons::SetupFailed));
|
|
return nullptr;
|
|
}
|
|
|
|
shipComponentData->writeDataToComponent (*tangible);
|
|
|
|
LOG(
|
|
"CustomerService",
|
|
(
|
|
"ShipComponents: %s (%s), [%s]: removed from %s (%s) by %s",
|
|
Unicode::wideToNarrow(tangible->getObjectName()).c_str(),
|
|
tangible->getNetworkId().getValueString().c_str(),
|
|
tangible->getObjectTemplateName(),
|
|
Unicode::wideToNarrow(getObjectName()).c_str(),
|
|
getNetworkId().getValueString().c_str(),
|
|
PlayerObject::getAccountDescription(getOwnerId()).c_str()));
|
|
}
|
|
|
|
switch (chassisSlot)
|
|
{
|
|
case ShipChassisSlotType::SCST_reactor:
|
|
IGNORE_RETURN(setReactorEnergyGenerationRate (0.0f));
|
|
break;
|
|
case ShipChassisSlotType::SCST_engine:
|
|
IGNORE_RETURN(setEngineAccelerationRate (0.0f));
|
|
IGNORE_RETURN(setEngineDecelerationRate (0.0f));
|
|
IGNORE_RETURN(setEnginePitchAccelerationRate (0.0f));
|
|
IGNORE_RETURN(setEngineYawAccelerationRate (0.0f));
|
|
IGNORE_RETURN(setEngineRollAccelerationRate (0.0f));
|
|
IGNORE_RETURN(setEnginePitchRateMaximum (0.0f));
|
|
IGNORE_RETURN(setEngineYawRateMaximum (0.0f));
|
|
IGNORE_RETURN(setEngineRollRateMaximum (0.0f));
|
|
IGNORE_RETURN(setEngineSpeedMaximum (0.0f));
|
|
break;
|
|
|
|
case ShipChassisSlotType::SCST_capacitor:
|
|
IGNORE_RETURN(setCapacitorEnergyCurrent (0.0f));
|
|
IGNORE_RETURN(setCapacitorEnergyMaximum (0.0f));
|
|
IGNORE_RETURN(setCapacitorEnergyRechargeRate (0.0f));
|
|
break;
|
|
|
|
case ShipChassisSlotType::SCST_shield_0:
|
|
IGNORE_RETURN(setShieldHitpointsFrontCurrent (0.0f));
|
|
IGNORE_RETURN(setShieldHitpointsFrontMaximum (0.0f));
|
|
IGNORE_RETURN(setShieldHitpointsBackCurrent (0.0f));
|
|
IGNORE_RETURN(setShieldHitpointsBackMaximum (0.0f));
|
|
IGNORE_RETURN(setShieldRechargeRate (0.0f));
|
|
break;
|
|
|
|
case ShipChassisSlotType::SCST_booster:
|
|
IGNORE_RETURN(setBoosterEnergyCurrent (0.0f));
|
|
IGNORE_RETURN(setBoosterEnergyMaximum (0.0f));
|
|
IGNORE_RETURN(setBoosterEnergyRechargeRate (0.0f));
|
|
IGNORE_RETURN(setBoosterEnergyConsumptionRate (0.0f));
|
|
IGNORE_RETURN(setBoosterAcceleration (0.0f));
|
|
IGNORE_RETURN(setBoosterSpeedMaximum (0.0f));
|
|
break;
|
|
|
|
case ShipChassisSlotType::SCST_droid_interface:
|
|
IGNORE_RETURN(setDroidInterfaceCommandSpeed (0.0f));
|
|
break;
|
|
|
|
case ShipChassisSlotType::SCST_cargo_hold:
|
|
{
|
|
m_cargoHoldContents.clear();
|
|
setCargoHoldContentsCurrent(0);
|
|
setCargoHoldContentsMaximum(0);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
setComponentCrc (chassisSlot, 0);
|
|
|
|
delete shipComponentData;
|
|
|
|
if(getScriptObject())
|
|
{
|
|
ScriptParams p;
|
|
p.addParam(uninstallerId);
|
|
p.addParam (tangible ? tangible->getNetworkId () : NetworkId::cms_invalid);
|
|
p.addParam (chassisSlot);
|
|
p.addParam (containerTarget ? containerTarget->getNetworkId () : NetworkId::cms_invalid);
|
|
|
|
IGNORE_RETURN (getScriptObject()->trigAllScripts(Scripting::TRIG_SHIP_COMPONENT_UNINSTALLED, p));
|
|
}
|
|
|
|
return tangible;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
TangibleObject * ShipObject::uninstallComponent (NetworkId const & uninstallerId, int chassisSlot, ServerObject & containerTarget, bool allowOverload)
|
|
{
|
|
return internalUninstallComponent (uninstallerId, chassisSlot, &containerTarget, allowOverload);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::installComponentFromData(int chassisSlot, ShipComponentData const & shipComponentData)
|
|
{
|
|
ShipChassis const * const shipChassis = ShipChassis::findShipChassisByCrc (getChassisType ());
|
|
if (shipChassis == nullptr)
|
|
{
|
|
DEBUG_WARNING (true, ("Ship [%s] chassis [%d] is invalid for installing component [%s]",
|
|
getNetworkId().getValueString().c_str(),
|
|
static_cast<int>(getChassisType ()),
|
|
shipComponentData.getDescriptor().getName().getString()));
|
|
return false;
|
|
}
|
|
|
|
if (isSlotInstalled (chassisSlot))
|
|
{
|
|
DEBUG_WARNING (true, ("Ship [%s] chassis [%s] slot [%s] is already filled, cannot install [%s]",
|
|
getNetworkId().getValueString().c_str(),
|
|
shipChassis->getName().getString(),
|
|
ShipChassisSlotType::getNameFromType(static_cast<ShipChassisSlotType::Type>(chassisSlot)).c_str(),
|
|
shipComponentData.getDescriptor().getName().getString()));
|
|
return false;
|
|
}
|
|
|
|
int effectiveCompatibilitySlot = chassisSlot;
|
|
// weapon slots beyond 7 wrap back to slot 0 for the purposes of compatibility checking on captial ships
|
|
if (isCapitalShip() && chassisSlot >= ShipChassisSlotType::SCST_num_explicit_types && chassisSlot <= ShipChassisSlotType::SCST_weapon_last)
|
|
effectiveCompatibilitySlot = ShipChassisSlotType::SCST_weapon_first+((chassisSlot-ShipChassisSlotType::SCST_weapon_first)&7);
|
|
|
|
ShipChassisSlot const * const slot = shipChassis->getSlot (static_cast<ShipChassisSlotType::Type>(effectiveCompatibilitySlot));
|
|
if (slot == nullptr)
|
|
{
|
|
DEBUG_WARNING (true, ("Ship [%s] chassis [%s] does not support slot [%s] for installing component [%s]",
|
|
getNetworkId().getValueString().c_str(),
|
|
shipChassis->getName().getString(),
|
|
ShipChassisSlotType::getNameFromType(static_cast<ShipChassisSlotType::Type>(chassisSlot)).c_str(),
|
|
shipComponentData.getDescriptor().getName().getString()));
|
|
return false;
|
|
}
|
|
|
|
if (!slot->canAcceptComponent(shipComponentData.getDescriptor()))
|
|
{
|
|
//this chassis check, in the warning, is to suppress output related to the npe tutorial falcon instance, as it seems "special"
|
|
std::string chassis = shipChassis->getName().getString();
|
|
|
|
DEBUG_WARNING ((chassis != "player_yt1300"), ("Component [%s], compat [%s] cannot be installed in ship [%s] chassis [%s], slot [%s], compats [%s].",
|
|
shipComponentData.getDescriptor().getName().getString(),
|
|
shipComponentData.getDescriptor().getCompatibility().getString(),
|
|
getNetworkId().getValueString().c_str(),
|
|
chassis.c_str(),
|
|
ShipChassisSlotType::getNameFromType(static_cast<ShipChassisSlotType::Type>(chassisSlot)).c_str(),
|
|
slot->getCompatibilityString().c_str()));
|
|
return false;
|
|
}
|
|
|
|
shipComponentData.writeDataToShip (chassisSlot, *this);
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::pseudoInstallComponent(int chassisSlot, uint32 componentCrc)
|
|
{
|
|
ShipComponentDescriptor const * const shipComponentDescriptor = ShipComponentDescriptor::findShipComponentDescriptorByCrc (componentCrc);
|
|
if (shipComponentDescriptor == nullptr)
|
|
{
|
|
WARNING (true, ("Invalid component name"));
|
|
return false;
|
|
}
|
|
|
|
ShipComponentData * const shipComponentData = ShipComponentDataManager::create (*shipComponentDescriptor);
|
|
|
|
if (shipComponentData == nullptr)
|
|
{
|
|
WARNING(true, ("ShipObject::pseudoInstallComponent invalid descriptor"));
|
|
return false;
|
|
}
|
|
|
|
bool const retval = installComponentFromData(chassisSlot, *shipComponentData);
|
|
|
|
delete shipComponentData;
|
|
|
|
return retval;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
ShipComponentData * ShipObject::createShipComponentData (int chassisSlot) const
|
|
{
|
|
ShipComponentDescriptor const * shipComponentDescriptor = nullptr;
|
|
|
|
uint32 const componentCrc = getComponentCrc (chassisSlot);
|
|
if (componentCrc)
|
|
{
|
|
shipComponentDescriptor = ShipComponentDescriptor::findShipComponentDescriptorByCrc (componentCrc);
|
|
if (shipComponentDescriptor == nullptr)
|
|
{
|
|
WARNING (true, ("ShipObject::createShipComponentData failed for slot [%d] because component crc [%d] could not map to a component descriptor", chassisSlot, componentCrc));
|
|
return nullptr;
|
|
}
|
|
}
|
|
else
|
|
return nullptr;
|
|
|
|
ShipComponentData * const shipComponentData = ShipComponentDataManager::create (*shipComponentDescriptor);
|
|
if (shipComponentData == nullptr)
|
|
{
|
|
WARNING (true, ("ShipObject::createShipComponentData failed for slot [%d] ship Component data could not be constructed", chassisSlot));
|
|
delete(shipComponentData);
|
|
return nullptr;
|
|
}
|
|
|
|
if (!shipComponentData->readDataFromShip (chassisSlot, *this))
|
|
WARNING (true, ("ShipObject::createShipComponentData failed for read data from the ship"));
|
|
|
|
return shipComponentData;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isSlotInstalled (int chassisSlot) const
|
|
{
|
|
return getComponentCrc (chassisSlot) != 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isBoosterInstalled() const
|
|
{
|
|
return isSlotInstalled(ShipChassisSlotType::SCST_booster);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isBoosterActive() const
|
|
{
|
|
if (isBoosterInstalled())
|
|
{
|
|
return isComponentActive(ShipChassisSlotType::SCST_booster);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void ShipObject::setBoosterActive(bool const active)
|
|
{
|
|
if (isSlotInstalled(ShipChassisSlotType::SCST_booster))
|
|
IGNORE_RETURN(setComponentActive(ShipChassisSlotType::SCST_booster, active));
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeShipActualAccelerationRate () const
|
|
{
|
|
float rate = 0.0f;
|
|
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine) && isComponentFunctional(ShipChassisSlotType::SCST_engine))
|
|
{
|
|
float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
rate = getEngineAccelerationRate () * efficiency;
|
|
}
|
|
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_booster) && isBoosterActive () && isComponentFunctional(ShipChassisSlotType::SCST_booster))
|
|
{
|
|
float const boosterEfficiency = computeActualComponentEfficiencyGeneral (ShipChassisSlotType::SCST_booster);
|
|
rate += getBoosterAcceleration () * boosterEfficiency;
|
|
}
|
|
|
|
//-- @todo: divide rate by mass
|
|
|
|
rate = rate * m_movementPercent;
|
|
|
|
return rate;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeShipActualDecelerationRate () const
|
|
{
|
|
float rate = 0.0f;
|
|
|
|
float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine) && isComponentFunctional(ShipChassisSlotType::SCST_engine))
|
|
rate = getEngineDecelerationRate () * efficiency;
|
|
else
|
|
rate = getShipDataEngine().m_engineDecelerationRate;
|
|
|
|
//-- @todo: divide rate by mass
|
|
|
|
rate = rate * m_movementPercent;
|
|
|
|
return rate;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeSpeedRotationFactor() const
|
|
{
|
|
//-- compute rotational factor
|
|
float const engineSpeedRotationFactorBaseMax = getEngineSpeedRotationFactorMaximum();
|
|
float const engineSpeedRotationFactorBaseMin = getEngineSpeedRotationFactorMinimum();
|
|
float const engineSpeedRotationFactorOptimal = getEngineSpeedRotationFactorOptimal();
|
|
|
|
float const speedMax = getShipActualSpeedMaximum();
|
|
float const speedCur = getCurrentSpeed();
|
|
float const speedPercent = (speedMax > 0.0f) ? (speedCur / speedMax) : 0.0f;
|
|
float engineSpeedRotationFactor = 1.0f;
|
|
|
|
if (speedPercent < engineSpeedRotationFactorOptimal || engineSpeedRotationFactorOptimal >= 1.0f)
|
|
{
|
|
float const speedPercentToOptimal = speedPercent / engineSpeedRotationFactorOptimal;
|
|
engineSpeedRotationFactor = linearInterpolate(engineSpeedRotationFactorBaseMin, 1.0f, speedPercentToOptimal);
|
|
}
|
|
else
|
|
{
|
|
float const speedPercentFromOptimal = (speedPercent - engineSpeedRotationFactorOptimal) / (1.0f - engineSpeedRotationFactorOptimal);
|
|
engineSpeedRotationFactor = linearInterpolate(1.0f, engineSpeedRotationFactorBaseMax, speedPercentFromOptimal);
|
|
}
|
|
|
|
// snap to discreet values, to avoid constant change
|
|
return floorf((engineSpeedRotationFactor * 10.f) + 0.5f) / 10.f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeShipActualPitchAccelerationRate () const
|
|
{
|
|
//float rate = 0.0f;
|
|
//
|
|
//float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
//
|
|
//if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
//{
|
|
// rate = getEnginePitchAccelerationRate () * efficiency;
|
|
//
|
|
// if (isComponentDisabled(ShipChassisSlotType::SCST_engine))
|
|
// {
|
|
// //-- player ships are allowed to stop spinning
|
|
// if (isPlayerShip())
|
|
// rate *= 0.5f;
|
|
// else
|
|
// rate = 0.0f;
|
|
// }
|
|
//}
|
|
float rate = 0.0f;
|
|
|
|
float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine) && isComponentFunctional(ShipChassisSlotType::SCST_engine))
|
|
rate = getEnginePitchAccelerationRate () * efficiency;
|
|
else
|
|
rate = getShipDataEngine().m_enginePitchAccelerationRate;
|
|
|
|
//-- @todo: divide rate by rotational inertia
|
|
|
|
return rate;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeShipActualYawAccelerationRate () const
|
|
{
|
|
//float rate = 0.0f;
|
|
//
|
|
//float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
//
|
|
//if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
//{
|
|
// rate = getEngineYawAccelerationRate () * efficiency;
|
|
//
|
|
// if (isComponentDisabled(ShipChassisSlotType::SCST_engine))
|
|
// {
|
|
// //-- player ships are allowed to stop spinning
|
|
// if (isPlayerShip())
|
|
// rate *= 0.5f;
|
|
// else
|
|
// rate = 0.0f;
|
|
// }
|
|
//}
|
|
float rate = 0.0f;
|
|
|
|
float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine) && isComponentFunctional(ShipChassisSlotType::SCST_engine))
|
|
rate = getEngineYawAccelerationRate () * efficiency;
|
|
else
|
|
rate = getShipDataEngine().m_engineYawAccelerationRate;
|
|
|
|
//-- @todo: divide rate by rotational inertia
|
|
|
|
return rate;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeShipActualRollAccelerationRate () const
|
|
{
|
|
//float rate = 0.0f;
|
|
//
|
|
//float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
//
|
|
//if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
//{
|
|
// rate = getEngineRollAccelerationRate () * efficiency;
|
|
//
|
|
// if (isComponentDisabled(ShipChassisSlotType::SCST_engine))
|
|
// {
|
|
// //-- player ships are allowed to stop spinning
|
|
// if (isPlayerShip())
|
|
// rate *= 0.5f;
|
|
// else
|
|
// rate = 0.0f;
|
|
// }
|
|
//}
|
|
|
|
float rate = 0.0f;
|
|
|
|
float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine) && isComponentFunctional(ShipChassisSlotType::SCST_engine))
|
|
rate = getEngineRollAccelerationRate () * efficiency;
|
|
else
|
|
rate = getShipDataEngine().m_engineRollAccelerationRate;
|
|
|
|
//-- @todo: divide rate by rotational inertia
|
|
|
|
return rate;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeShipActualPitchRateMaximum () const
|
|
{
|
|
//float rate = 0.0f;
|
|
//
|
|
//float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
//
|
|
//if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
//{
|
|
// rate = getEnginePitchRateMaximum () * efficiency;
|
|
//
|
|
// if (isComponentDisabled(ShipChassisSlotType::SCST_engine))
|
|
// {
|
|
// //-- player ships have zero max rotation rates so the ship will come to a stop
|
|
// if (isPlayerShip())
|
|
// rate = 0.0f;
|
|
// }
|
|
//}
|
|
float rate = 0.0f;
|
|
|
|
float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine) && isComponentFunctional(ShipChassisSlotType::SCST_engine))
|
|
rate = getEnginePitchRateMaximum () * efficiency;
|
|
|
|
rate *= computeSpeedRotationFactor();
|
|
|
|
return rate;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeShipActualYawRateMaximum () const
|
|
{
|
|
//float rate = 0.0f;
|
|
//
|
|
//float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
//
|
|
//if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
//{
|
|
// rate = getEngineYawRateMaximum () * efficiency;
|
|
//
|
|
// if (isComponentDisabled(ShipChassisSlotType::SCST_engine))
|
|
// {
|
|
// //-- player ships have zero max rotation rates so the ship will come to a stop
|
|
// if (isPlayerShip())
|
|
// rate = 0.0f;
|
|
// }
|
|
//}
|
|
float rate = 0.0f;
|
|
|
|
float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine) && isComponentFunctional(ShipChassisSlotType::SCST_engine))
|
|
rate = getEngineYawRateMaximum () * efficiency;
|
|
|
|
rate *= computeSpeedRotationFactor();
|
|
|
|
return rate;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeShipActualRollRateMaximum () const
|
|
{
|
|
//float rate = 0.0f;
|
|
//
|
|
//float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
//
|
|
//if (isSlotInstalled (ShipChassisSlotType::SCST_engine))
|
|
//{
|
|
// rate = getEngineRollRateMaximum () * efficiency;
|
|
//
|
|
// if (isComponentDisabled(ShipChassisSlotType::SCST_engine))
|
|
// {
|
|
// //-- player ships have zero max rotation rates so the ship will come to a stop
|
|
// if (isPlayerShip())
|
|
// rate = 0.0f;
|
|
// }
|
|
//}
|
|
float rate = 0.0f;
|
|
|
|
float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine) && isComponentFunctional(ShipChassisSlotType::SCST_engine))
|
|
rate = getEngineRollRateMaximum () * efficiency;
|
|
|
|
return rate;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeShipActualSpeedMaximum () const
|
|
{
|
|
float rate = 0.0f;
|
|
|
|
if (isSlotInstalled (ShipChassisSlotType::SCST_engine) && isComponentFunctional(ShipChassisSlotType::SCST_engine))
|
|
{
|
|
float const efficiency = computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_engine);
|
|
rate = getEngineSpeedMaximum () * efficiency;
|
|
}
|
|
|
|
if (isSlotInstalled(ShipChassisSlotType::SCST_booster) && isBoosterActive() && isComponentFunctional(ShipChassisSlotType::SCST_booster))
|
|
rate += getBoosterSpeedMaximum () * computeActualComponentEfficiencyGeneral(ShipChassisSlotType::SCST_booster);
|
|
|
|
if (hasWings() && hasCondition(TangibleObject::C_wingsOpened))
|
|
{
|
|
ShipChassis const * const shipChassis = ShipChassis::findShipChassisByCrc(getChassisType());
|
|
if (nullptr != shipChassis)
|
|
{
|
|
float const wingOpenSpeedFactor = shipChassis->getWingOpenSpeedFactor();
|
|
rate *= wingOpenSpeedFactor;
|
|
}
|
|
}
|
|
|
|
rate *= m_chassisSpeedMaximumModifier.get();
|
|
|
|
rate = std::min(512.0f, rate * m_movementPercent);
|
|
|
|
return rate;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShipActualAccelerationRate () const
|
|
{
|
|
return m_shipActualAccelerationRate.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShipActualDecelerationRate () const
|
|
{
|
|
return m_shipActualDecelerationRate.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShipActualPitchAccelerationRate () const
|
|
{
|
|
return m_shipActualPitchAccelerationRate.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShipActualYawAccelerationRate () const
|
|
{
|
|
return m_shipActualYawAccelerationRate.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShipActualRollAccelerationRate () const
|
|
{
|
|
return m_shipActualRollAccelerationRate.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShipActualPitchRateMaximum () const
|
|
{
|
|
return m_shipActualPitchRateMaximum.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShipActualYawRateMaximum () const
|
|
{
|
|
return m_shipActualYawRateMaximum.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShipActualRollRateMaximum () const
|
|
{
|
|
return m_shipActualRollRateMaximum.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShipActualYprRateMaximum() const
|
|
{
|
|
return std::max(std::max(m_shipActualPitchRateMaximum.get(), m_shipActualYawRateMaximum.get()), m_shipActualRollRateMaximum.get());
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getShipActualSpeedMaximum () const
|
|
{
|
|
return m_shipActualSpeedMaximum.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isComponentDisabled (int chassisSlot) const
|
|
{
|
|
return (getComponentFlags (chassisSlot) & static_cast<int>(ShipComponentFlags::F_disabled)) != 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isComponentDisabledNeedsPower(int chassisSlot) const
|
|
{
|
|
return (getComponentFlags (chassisSlot) & static_cast<int>(ShipComponentFlags::F_disabledNeedsPower)) != 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isComponentLowPower (int chassisSlot) const
|
|
{
|
|
return (getComponentFlags (chassisSlot) & static_cast<int>(ShipComponentFlags::F_lowPower)) != 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isComponentActive(int chassisSlot) const
|
|
{
|
|
return (getComponentFlags (chassisSlot) & static_cast<int>(ShipComponentFlags::F_active)) != 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isComponentDemolished(int chassisSlot) const
|
|
{
|
|
return (getComponentFlags(chassisSlot) & ShipComponentFlags::F_demolished) != 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void ShipObject::handlePowerPulse (float timeElapsedSecs)
|
|
{
|
|
PROFILER_AUTO_BLOCK_DEFINE("ShipObject::handlePowerPulse");
|
|
|
|
DEBUG_FATAL (!isAuthoritative(), ("ShipObject::handlePowerPulse called on non-auth ship object"));
|
|
|
|
//-- handle componentized power system
|
|
|
|
ShipChassis const * const shipChassis = ShipChassis::findShipChassisByCrc (getChassisType ());
|
|
if (!shipChassis)
|
|
return;
|
|
|
|
CreatureObject * const pilot = getPilot();
|
|
|
|
float powerGenerated = 0.0f;
|
|
|
|
if (isSlotInstalled (static_cast<int>(ShipChassisSlotType::SCST_reactor)) && isComponentFunctional(ShipChassisSlotType::SCST_reactor))
|
|
{
|
|
powerGenerated = getReactorEnergyGenerationRate () * computeActualComponentEfficiencyGeneral (static_cast<int>(ShipChassisSlotType::SCST_reactor)) * timeElapsedSecs;
|
|
powerGenerated += (powerGenerated * m_nebulaEffectReactor);
|
|
powerGenerated = std::max (0.0f, powerGenerated);
|
|
}
|
|
|
|
//-- discharge the capacitor if it is disabled (because the power logic below is skipped for disabled components)
|
|
if (isSlotInstalled(ShipChassisSlotType::SCST_capacitor) && !isComponentFunctional(ShipChassisSlotType::SCST_capacitor))
|
|
IGNORE_RETURN(setCapacitorEnergyCurrent(0.0f));
|
|
|
|
for (int i = static_cast<int>(ShipChassisSlotType::SCST_first); i < static_cast<int>(ShipChassisSlotType::SCST_num_types); ++i)
|
|
{
|
|
ShipChassisSlotType::Type const slotType = shipChassis->getSlotPowerPriority (i);
|
|
if (slotType == ShipChassisSlotType::SCST_num_types || slotType == ShipChassisSlotType::SCST_reactor)
|
|
continue;
|
|
|
|
int const slotIndex = static_cast<int>(slotType);
|
|
|
|
if (!isSlotInstalled (slotIndex))
|
|
continue;
|
|
|
|
if (isComponentDemolished(slotIndex))
|
|
continue;
|
|
|
|
if (isComponentDisabled(slotIndex))
|
|
{
|
|
if (!isComponentDisabledNeedsPower(slotIndex))
|
|
continue;
|
|
}
|
|
|
|
float const baseComponentEnergyRequired = getComponentEnergyMaintenanceRequirement (slotIndex) * timeElapsedSecs;
|
|
|
|
float oo_componentEfficiencyEnergy = getComponentEfficiencyEnergy (slotIndex);
|
|
if (oo_componentEfficiencyEnergy > 0.0f)
|
|
oo_componentEfficiencyEnergy = RECIP (oo_componentEfficiencyEnergy);
|
|
|
|
float const energyRequired = baseComponentEnergyRequired * oo_componentEfficiencyEnergy;
|
|
|
|
//-- first consume the base energy requirement for the component
|
|
|
|
float energyInsufficiencyPercent = 0.0f;
|
|
|
|
//-- insufficient power
|
|
if (energyRequired > powerGenerated)
|
|
{
|
|
if(getScriptObject())
|
|
{
|
|
ScriptParams p;
|
|
p.addParam (slotIndex);
|
|
p.addParam (energyRequired);
|
|
p.addParam (powerGenerated);
|
|
|
|
IGNORE_RETURN(getScriptObject()->trigAllScripts(Scripting::TRIG_SHIP_COMPONENT_POWER_INSUFFICIENT, p));
|
|
|
|
//-- script has for some reason removed the component, stop processing it
|
|
if (!isSlotInstalled(slotIndex))
|
|
continue;
|
|
}
|
|
|
|
//-- energy req cannot be zero
|
|
energyInsufficiencyPercent = 1.0f - powerGenerated / energyRequired;
|
|
IGNORE_RETURN(setComponentLowPower (slotIndex, true));
|
|
}
|
|
//-- sufficient power
|
|
else
|
|
{
|
|
if (isComponentLowPower (slotIndex))
|
|
{
|
|
if(getScriptObject())
|
|
{
|
|
ScriptParams p;
|
|
p.addParam (slotIndex);
|
|
p.addParam (energyRequired);
|
|
|
|
IGNORE_RETURN(getScriptObject()->trigAllScripts(Scripting::TRIG_SHIP_COMPONENT_POWER_SUFFICIENT, p));
|
|
|
|
//-- script has for some reason removed the component, stop processing it
|
|
if (!isSlotInstalled(slotIndex))
|
|
continue;
|
|
}
|
|
|
|
IGNORE_RETURN(setComponentLowPower (slotIndex, false));
|
|
}
|
|
}
|
|
|
|
powerGenerated = std::max (0.0f, powerGenerated - energyRequired);
|
|
|
|
//--
|
|
if (isComponentDisabled(slotIndex))
|
|
continue;
|
|
|
|
float const efficiencyGeneral = computeActualComponentEfficiencyGeneral(slotIndex);
|
|
|
|
switch (slotType)
|
|
{
|
|
//--
|
|
//-- recharge or decay the shields
|
|
//--
|
|
|
|
case ShipChassisSlotType::SCST_shield_0:
|
|
{
|
|
float const hpFrontCurrent = getShieldHitpointsFrontCurrent ();
|
|
float const hpFrontMaximum = getShieldHitpointsFrontMaximum ();
|
|
float const hpBackCurrent = getShieldHitpointsBackCurrent ();
|
|
float const hpBackMaximum = getShieldHitpointsBackMaximum ();
|
|
|
|
//-- recharge the shields
|
|
if (!isComponentLowPower(slotIndex))
|
|
{
|
|
float shieldRechargeRateHps = getShieldRechargeRate () * efficiencyGeneral * timeElapsedSecs;
|
|
shieldRechargeRateHps += (shieldRechargeRateHps * m_nebulaEffectShields);
|
|
|
|
if (shieldRechargeRateHps > 0.0f)
|
|
{
|
|
float const hpFrontNeeded = std::max (0.0f, std::min (hpFrontMaximum - hpFrontCurrent, shieldRechargeRateHps));
|
|
float const hpBackNeeded = std::max (0.0f, std::min (hpBackMaximum - hpBackCurrent, shieldRechargeRateHps));
|
|
|
|
if (hpFrontNeeded > 0.0f || hpBackNeeded > 0.0f)
|
|
{
|
|
if (hpFrontNeeded)
|
|
IGNORE_RETURN(setShieldHitpointsFrontCurrent(hpFrontCurrent + hpFrontNeeded));
|
|
if (hpBackNeeded)
|
|
IGNORE_RETURN(setShieldHitpointsBackCurrent(hpBackCurrent + hpBackNeeded));
|
|
}
|
|
}
|
|
}
|
|
//-- decay the shields to some percentage
|
|
else if (energyInsufficiencyPercent > 0.0f)
|
|
{
|
|
float const shieldDecayRateHps = std::max (1.0f, (getShieldRechargeRate () * timeElapsedSecs) * energyInsufficiencyPercent);
|
|
|
|
float const minShieldsFront = (1.0f - energyInsufficiencyPercent) * getShieldHitpointsFrontMaximum();
|
|
float const minShieldsBack = (1.0f - energyInsufficiencyPercent) * getShieldHitpointsBackMaximum();
|
|
|
|
if (hpFrontCurrent > minShieldsFront)
|
|
IGNORE_RETURN(setShieldHitpointsFrontCurrent(std::max(minShieldsFront, hpFrontCurrent - shieldDecayRateHps)));
|
|
if (hpBackCurrent > minShieldsBack)
|
|
IGNORE_RETURN(setShieldHitpointsBackCurrent(std::max(minShieldsFront, hpBackCurrent - shieldDecayRateHps)));
|
|
}
|
|
}
|
|
break;
|
|
|
|
//--
|
|
//-- recharge or decay the capacitor
|
|
//--
|
|
|
|
case ShipChassisSlotType::SCST_capacitor:
|
|
{
|
|
float capacitorEnergyCurrent = getCapacitorEnergyCurrent ();
|
|
float const capacitorEnergyMaximum = getCapacitorEnergyEffectiveMaximum () * getComponentEfficiencyGeneral(ShipChassisSlotType::SCST_capacitor);
|
|
|
|
//-- the efficiency might cause the current charge to exceed the max
|
|
if (capacitorEnergyCurrent > capacitorEnergyMaximum)
|
|
{
|
|
IGNORE_RETURN(setCapacitorEnergyCurrent (capacitorEnergyMaximum));
|
|
capacitorEnergyCurrent = getCapacitorEnergyCurrent ();
|
|
}
|
|
|
|
//-- recharge the capacitor
|
|
if (!isComponentLowPower(slotIndex))
|
|
{
|
|
float const rechargeRate = getCapacitorEnergyRechargeRate () * efficiencyGeneral * timeElapsedSecs;
|
|
float const capacitorEnergyRechargeNeeded = std::min (capacitorEnergyMaximum - capacitorEnergyCurrent, rechargeRate);
|
|
|
|
if (capacitorEnergyRechargeNeeded > 0.0f)
|
|
{
|
|
IGNORE_RETURN(setCapacitorEnergyCurrent (capacitorEnergyCurrent + capacitorEnergyRechargeNeeded));
|
|
}
|
|
}
|
|
//-- decay the capacitors to some percentage
|
|
else if (energyInsufficiencyPercent > 0.0f)
|
|
{
|
|
float const decayRate = std::max (1.0f, (getCapacitorEnergyRechargeRate () * timeElapsedSecs) * energyInsufficiencyPercent);
|
|
|
|
float const minLevel = (1.0f - energyInsufficiencyPercent) * getCapacitorEnergyEffectiveMaximum();
|
|
|
|
if (capacitorEnergyCurrent > minLevel)
|
|
IGNORE_RETURN(setCapacitorEnergyCurrent (std::max(minLevel, capacitorEnergyCurrent - decayRate)));
|
|
}
|
|
}
|
|
break;
|
|
|
|
//--
|
|
//-- recharge or decay the booster
|
|
//--
|
|
|
|
case ShipChassisSlotType::SCST_booster:
|
|
{
|
|
float boosterEnergyCurrent = getBoosterEnergyCurrent();
|
|
|
|
if (isBoosterActive())
|
|
{
|
|
float const boosterEnergyUsed = (getBoosterEnergyConsumptionRate() * timeElapsedSecs) * oo_componentEfficiencyEnergy;
|
|
|
|
IGNORE_RETURN(setBoosterEnergyCurrent(std::max(0.0f, boosterEnergyCurrent - boosterEnergyUsed)));
|
|
boosterEnergyCurrent = getBoosterEnergyCurrent();
|
|
|
|
//-- when the booster runs out of energy, kill it
|
|
if (boosterEnergyCurrent <= 0.0f)
|
|
{
|
|
IGNORE_RETURN(setComponentActive(ShipChassisSlotType::SCST_booster, false));
|
|
if (pilot != nullptr)
|
|
Chat::sendSystemMessage(*pilot, SharedStringIds::booster_energy_depleted, Unicode::emptyString);
|
|
|
|
restartBoosterTimer();
|
|
}
|
|
break;
|
|
}
|
|
|
|
float const boosterEnergyMaximum = getBoosterEnergyMaximum ();
|
|
|
|
//recharge the booster
|
|
if (!isComponentLowPower(slotIndex))
|
|
{
|
|
float const rechargeRate = getBoosterEnergyRechargeRate () * efficiencyGeneral * timeElapsedSecs;
|
|
float const boosterEnergyRechargeNeeded = std::min (boosterEnergyMaximum - boosterEnergyCurrent, rechargeRate);
|
|
|
|
if (boosterEnergyRechargeNeeded > 0.0f)
|
|
{
|
|
|
|
float const boosterEnergyRequired = boosterEnergyRechargeNeeded * oo_componentEfficiencyEnergy;
|
|
|
|
IGNORE_RETURN(setBoosterEnergyCurrent (boosterEnergyCurrent + boosterEnergyRequired));
|
|
}
|
|
}
|
|
//-- decay the boosters to some percentage
|
|
else if (energyInsufficiencyPercent > 0.0f)
|
|
{
|
|
float const decayRate = std::max (1.0f, (getBoosterEnergyRechargeRate () * timeElapsedSecs) * energyInsufficiencyPercent);
|
|
|
|
float const minLevel = (1.0f - energyInsufficiencyPercent) * getBoosterEnergyMaximum();
|
|
|
|
if (boosterEnergyCurrent > minLevel)
|
|
IGNORE_RETURN(setBoosterEnergyCurrent (std::max(minLevel, boosterEnergyCurrent - decayRate)));
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
} //lint !e788 //switch cases not used
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int ShipObject::getProjectileIndexForWeapon(int const weaponIndex) const
|
|
{
|
|
if (weaponIndex < 0 || weaponIndex >= ShipChassisSlotType::cms_numWeaponIndices)
|
|
return -1;
|
|
|
|
ShipChassisSlotType::Type const weaponChassisSlotType = static_cast<ShipChassisSlotType::Type>(weaponIndex + static_cast<int>(ShipChassisSlotType::SCST_weapon_0));
|
|
|
|
uint32 const componentCrc = getComponentCrc(weaponChassisSlotType);
|
|
if (componentCrc == 0)
|
|
return -1;
|
|
|
|
return ShipComponentWeaponManager::getProjectileIndex(componentCrc);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponRange(int weaponIndex) const
|
|
{
|
|
if (weaponIndex < 0 || weaponIndex >= ShipChassisSlotType::cms_numWeaponIndices)
|
|
return 0.0f;
|
|
|
|
ShipChassisSlotType::Type const weaponChassisSlotType = static_cast<ShipChassisSlotType::Type>(weaponIndex + static_cast<int>(ShipChassisSlotType::SCST_weapon_0));
|
|
|
|
uint32 const componentCrc = getComponentCrc(weaponChassisSlotType);
|
|
if (componentCrc == 0)
|
|
return 0.0f;
|
|
|
|
float range = 0.0f;
|
|
|
|
if (ShipComponentWeaponManager::isMissile(componentCrc))
|
|
{
|
|
int const missileTypeId = static_cast<int>(getWeaponAmmoType(weaponChassisSlotType));
|
|
range = MissileManager::getInstance().getRangeByMissileType(missileTypeId);
|
|
}
|
|
else
|
|
{
|
|
range = ShipComponentWeaponManager::getRange(componentCrc);
|
|
}
|
|
|
|
return range;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getWeaponProjectileSpeed(int weaponIndex) const
|
|
{
|
|
if (weaponIndex < 0 || weaponIndex >= ShipChassisSlotType::cms_numWeaponIndices)
|
|
return 0.0f;
|
|
|
|
ShipChassisSlotType::Type const weaponChassisSlotType = static_cast<ShipChassisSlotType::Type>(weaponIndex + static_cast<int>(ShipChassisSlotType::SCST_weapon_0));
|
|
|
|
uint32 const componentCrc = getComponentCrc(weaponChassisSlotType);
|
|
if (componentCrc == 0)
|
|
return 0.0f;
|
|
|
|
float speed = 0.0f;
|
|
|
|
if (ShipComponentWeaponManager::isMissile(componentCrc))
|
|
{
|
|
int const missileTypeId = static_cast<int>(getWeaponAmmoType(weaponChassisSlotType));
|
|
speed = MissileManager::getInstance().getSpeedByMissileType(missileTypeId);
|
|
}
|
|
else
|
|
{
|
|
speed = ShipComponentWeaponManager::getProjectileSpeed(componentCrc);
|
|
}
|
|
|
|
return speed;
|
|
}
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeWeaponProjectileTimeToLive(int weaponIndex) const
|
|
{
|
|
if (weaponIndex < 0 || weaponIndex >= ShipChassisSlotType::cms_numWeaponIndices)
|
|
return 0.0f;
|
|
|
|
ShipChassisSlotType::Type const weaponChassisSlotType = static_cast<ShipChassisSlotType::Type>(weaponIndex + static_cast<int>(ShipChassisSlotType::SCST_weapon_0));
|
|
|
|
uint32 const componentCrc = getComponentCrc(weaponChassisSlotType);
|
|
if (componentCrc == 0)
|
|
return 0.0f;
|
|
|
|
float timeToLive = 0.0f;
|
|
|
|
if (ShipComponentWeaponManager::isMissile(componentCrc))
|
|
{
|
|
int const missileTypeId = static_cast<int>(getWeaponAmmoType(weaponChassisSlotType));
|
|
timeToLive = MissileManager::getInstance().getMaxTimeByMissileType(missileTypeId);
|
|
}
|
|
else
|
|
{
|
|
float const range = ShipComponentWeaponManager::getRange(componentCrc);
|
|
float const projectileSpeed = ShipComponentWeaponManager::getProjectileSpeed(componentCrc);
|
|
timeToLive = (projectileSpeed <= 0.0f) ? 0.0f : range / projectileSpeed;
|
|
}
|
|
|
|
return timeToLive;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeActualComponentEfficiencyGeneral(int chassisType) const
|
|
{
|
|
float efficiency = getComponentEfficiencyGeneral(chassisType);
|
|
float nebulaEffect = 0.0f;
|
|
|
|
switch (chassisType)
|
|
{
|
|
case ShipChassisSlotType::SCST_engine:
|
|
nebulaEffect = m_nebulaEffectEngine;
|
|
break;
|
|
case ShipChassisSlotType::SCST_reactor:
|
|
nebulaEffect = m_nebulaEffectReactor;
|
|
break;
|
|
case ShipChassisSlotType::SCST_shield_0:
|
|
nebulaEffect = m_nebulaEffectShields;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
efficiency = clamp(0.1f, efficiency + nebulaEffect, 10.0f);
|
|
return efficiency;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void ShipObject::setSlotTargetable(ShipChassisSlotType::Type slot)
|
|
{
|
|
BitArray tmp(m_targetableSlotBitfield.get());
|
|
tmp.setBit(slot);
|
|
m_targetableSlotBitfield = tmp;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void ShipObject::clearSlotTargetable(ShipChassisSlotType::Type slot)
|
|
{
|
|
BitArray tmp(m_targetableSlotBitfield.get());
|
|
tmp.clearBit(slot);
|
|
m_targetableSlotBitfield = tmp;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::getSlotTargetable(ShipChassisSlotType::Type slot) const
|
|
{
|
|
return m_targetableSlotBitfield.get().testBit(slot);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isValidTargetableSlot (ShipChassisSlotType::Type slot) const
|
|
{
|
|
if(getSlotTargetable(slot))
|
|
{
|
|
if(isSlotInstalled(slot))
|
|
{
|
|
if(isComponentFunctional(slot))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void ShipObject::setPilotLookAtTargetSlot(ShipChassisSlotType::Type slot)
|
|
{
|
|
if(isAuthoritative() && isValidTargetableSlot(slot))
|
|
{
|
|
m_pilotLookAtTargetSlot.set(slot);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void ShipObject::setTurretTarget(int weaponIndex, CachedNetworkId const & target)
|
|
{
|
|
if (isAuthoritative())
|
|
{
|
|
DEBUG_FATAL(!isTurret(weaponIndex), ("Assigning a target(%s) to a weaponIndex(%d) that is not a turret", target.getValueString().c_str(), weaponIndex));
|
|
|
|
if (!target.isValid())
|
|
IGNORE_RETURN(m_turretTargets.erase(weaponIndex));
|
|
else
|
|
m_turretTargets[weaponIndex] = target;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
CachedNetworkId const & ShipObject::getTurretTarget(int weaponIndex) const
|
|
{
|
|
if (isAuthoritative())
|
|
{
|
|
DEBUG_FATAL(!isTurret(weaponIndex), ("Requesting the target of an weaponIndex(%d) that is not a turret", weaponIndex));
|
|
|
|
std::map<int, CachedNetworkId>::const_iterator const it = m_turretTargets.find(weaponIndex);
|
|
if (it != m_turretTargets.end())
|
|
return (*it).second;
|
|
}
|
|
return CachedNetworkId::cms_cachedInvalid;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
Transform const ShipObject::getTurretTransform(int weaponIndex) const
|
|
{
|
|
int const chassisSlot = static_cast<int>(ShipChassisSlotType::SCST_weapon_0) + weaponIndex;
|
|
uint32 const componentCrc = getComponentCrc(chassisSlot);
|
|
|
|
if (componentCrc != 0)
|
|
{
|
|
AppearanceTemplate const * exteriorAppearanceTemplate = 0;
|
|
|
|
PortalProperty const * const portalProperty = getPortalProperty();
|
|
if (portalProperty)
|
|
{
|
|
char const * const exteriorAppearanceName = portalProperty->getPortalPropertyTemplate().getExteriorAppearanceName();
|
|
if (exteriorAppearanceName)
|
|
exteriorAppearanceTemplate = AppearanceTemplateList::fetch(exteriorAppearanceName);
|
|
}
|
|
else
|
|
{
|
|
Appearance const * const appearance = getAppearance();
|
|
if (appearance)
|
|
exteriorAppearanceTemplate = appearance->getAppearanceTemplate();
|
|
}
|
|
|
|
if (exteriorAppearanceTemplate)
|
|
{
|
|
ShipComponentAttachmentManager::TemplateHardpointPairVector const &attachments = ShipComponentAttachmentManager::getAttachmentsForShip(getChassisType(), componentCrc, chassisSlot);
|
|
if (!attachments.empty())
|
|
{
|
|
ShipComponentAttachmentManager::TemplateHardpointPair const &templateHardpointPair = *attachments.begin();
|
|
int const turretYawHardpointIndex = exteriorAppearanceTemplate->getHardpointIndex(templateHardpointPair.second, true);
|
|
WARNING(turretYawHardpointIndex == -1, ("Ship %s references hardpoint '%s' which could not be found.", getDebugInformation().c_str(), templateHardpointPair.second.getString()));
|
|
if (turretYawHardpointIndex != -1)
|
|
{
|
|
Hardpoint const &turretYawHardpoint = exteriorAppearanceTemplate->getHardpoint(turretYawHardpointIndex);
|
|
// we now need to find a weapon hardpoint on this attachment
|
|
SharedObjectTemplate const * const objectTemplate = safe_cast<SharedObjectTemplate const *>(ObjectTemplateList::fetch(templateHardpointPair.first));
|
|
if (objectTemplate)
|
|
{
|
|
AppearanceTemplate const * const appearanceTemplate = AppearanceTemplateList::fetch(objectTemplate->getAppearanceFilename().c_str());
|
|
if (appearanceTemplate)
|
|
{
|
|
int const turretPitchHardpointIndex = appearanceTemplate->getHardpointIndex(s_turretPitchHardpoint, true);
|
|
if (turretPitchHardpointIndex != -1)
|
|
{
|
|
Hardpoint const &turretPitchHardpoint = appearanceTemplate->getHardpoint(turretPitchHardpointIndex);
|
|
return getTransform_o2p().rotateTranslate_l2p(turretYawHardpoint.getTransform().rotateTranslate_l2p(turretPitchHardpoint.getTransform()));
|
|
}
|
|
}
|
|
}
|
|
// we couldn't find a turret pitch hardpoint, so the turret yaw hardpoint is for the object which pitches also
|
|
return getTransform_o2p().rotateTranslate_l2p(turretYawHardpoint.getTransform());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// we couldn't find an attachment hardpoint, so assume we fire forward from the ship center
|
|
return getTransform_o2p();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isMissile(int const weaponIndex) const
|
|
{
|
|
bool ismissile = false;
|
|
|
|
if(weaponIndex >= 0 && weaponIndex < ShipChassisSlotType::cms_numWeaponIndices)
|
|
{
|
|
int const chassisSlot = static_cast<int>(ShipChassisSlotType::SCST_weapon_first) + weaponIndex;
|
|
uint32 const componentCrc = getComponentCrc(chassisSlot);
|
|
if (componentCrc != 0)
|
|
{
|
|
ismissile = ShipComponentWeaponManager::isMissile(componentCrc);
|
|
}
|
|
}
|
|
|
|
return ismissile;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isTurret(int const weaponIndex) const
|
|
{
|
|
DEBUG_FATAL(!ShipChassisSlotType::isWeaponIndex(weaponIndex), ("weaponIndex(%d) is out of range [0...%d]", weaponIndex, ShipChassisSlotType::cms_numWeaponIndices - 1));
|
|
|
|
return m_turretWeaponIndices->testBit(weaponIndex);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isCountermeasure(int const weaponIndex) const
|
|
{
|
|
ShipChassisSlotType::Type const shipChassisSlotType = static_cast<ShipChassisSlotType::Type>(static_cast<int>(ShipChassisSlotType::SCST_weapon_0) + weaponIndex);
|
|
if (isSlotInstalled(shipChassisSlotType))
|
|
{
|
|
uint32 const componentCrc = getComponentCrc(shipChassisSlotType);
|
|
return ShipComponentWeaponManager::isCountermeasure(componentCrc);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::isProjectile(int const weaponIndex) const
|
|
{
|
|
bool missile = isMissile(weaponIndex);
|
|
bool turret = isTurret(weaponIndex);
|
|
bool countermeasure = isCountermeasure(weaponIndex);
|
|
|
|
return (!missile && !turret && !countermeasure);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::computeChassisComponentMassCurrent() const
|
|
{
|
|
float massCurrent = 0.0f;
|
|
|
|
for (int chassisSlot = static_cast<int>(ShipChassisSlotType::SCST_first); chassisSlot < static_cast<int>(ShipChassisSlotType::SCST_num_types); ++chassisSlot)
|
|
{
|
|
if (!isSlotInstalled (chassisSlot))
|
|
continue;
|
|
|
|
massCurrent += getComponentMass(chassisSlot);
|
|
}
|
|
|
|
return massCurrent;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getChassisComponentMassMaximum() const
|
|
{
|
|
return m_chassisComponentMassMaximum.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
float ShipObject::getChassisComponentMassCurrent() const
|
|
{
|
|
return m_chassisComponentMassCurrent.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void ShipObject::setChassisComponentMassMaximum(float massMaximum)
|
|
{
|
|
m_chassisComponentMassMaximum.set(massMaximum);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void ShipObject::internalSetChassisComponentMassCurrent(float massCurrent)
|
|
{
|
|
m_chassisComponentMassCurrent.set(massCurrent);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Check whether a turret can fire towards a particular location without
|
|
* exceeding its rotation limits.
|
|
*/
|
|
bool ShipObject::canTurretFireTowardsLocation_p(int weaponIndex, Vector const & targetLocation_p) const
|
|
{
|
|
Transform turretTransform_o2p(getTurretTransform(weaponIndex));
|
|
|
|
uint32 const chassisCrc = getChassisType();
|
|
float const minYaw = ShipTurretManager::getTurretMinYaw(chassisCrc, weaponIndex);
|
|
float const maxYaw = ShipTurretManager::getTurretMaxYaw(chassisCrc, weaponIndex);
|
|
float const minPitch = ShipTurretManager::getTurretMinPitch(chassisCrc, weaponIndex);
|
|
float const maxPitch = ShipTurretManager::getTurretMaxPitch(chassisCrc, weaponIndex);
|
|
|
|
Vector const turretToTarget = turretTransform_o2p.rotateTranslate_p2l(targetLocation_p);
|
|
|
|
float yaw=turretToTarget.theta();
|
|
float pitch=turretToTarget.phi();
|
|
|
|
// if yaw and pitch are limited for this turret, check that the desired yaw/pitch is within the range
|
|
|
|
if ((maxYaw-minYaw)+0.001 < PI_TIMES_2)
|
|
if (yaw > maxYaw || yaw < minYaw)
|
|
return false;
|
|
|
|
if ((maxPitch-minPitch)+0.001 < PI_TIMES_2)
|
|
if (pitch > maxPitch || pitch < minPitch)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Given a position on the ship, figure out which targettable chassis slot covers
|
|
* that position. Used to determine which component a projectile hit.
|
|
*/
|
|
int ShipObject::findTargetChassisSlotByPosition(Vector const & position_o) const
|
|
{
|
|
DEBUG_FATAL(!isCapitalShip(),("Programmer bug: findChassisSlotByPosition() should only be called on capital ships"));
|
|
|
|
AppearanceTemplate const * exteriorAppearanceTemplate = 0;
|
|
|
|
PortalProperty const * const portalProperty = getPortalProperty();
|
|
if (portalProperty)
|
|
{
|
|
char const * const exteriorAppearanceName = portalProperty->getPortalPropertyTemplate().getExteriorAppearanceName();
|
|
if (exteriorAppearanceName)
|
|
exteriorAppearanceTemplate = AppearanceTemplateList::fetch(exteriorAppearanceName);
|
|
}
|
|
else
|
|
{
|
|
Appearance const * const appearance = getAppearance();
|
|
if (appearance)
|
|
exteriorAppearanceTemplate = appearance->getAppearanceTemplate();
|
|
}
|
|
NOT_NULL(exteriorAppearanceTemplate);
|
|
if (!exteriorAppearanceTemplate) //lint !e774 only always false in debug mode
|
|
return ShipChassisSlotType::SCST_invalid;
|
|
|
|
ShipChassisSlotType::Type closestSlot = ShipChassisSlotType::SCST_invalid;
|
|
float closestDistance = 0.0f;
|
|
|
|
for (int chassisSlotIterator = static_cast<int>(ShipChassisSlotType::SCST_first); chassisSlotIterator != static_cast<int>(ShipChassisSlotType::SCST_num_types); ++chassisSlotIterator)
|
|
{
|
|
ShipChassisSlotType::Type chassisSlot = static_cast<ShipChassisSlotType::Type>(chassisSlotIterator);
|
|
uint32 const componentCrc = getComponentCrc(chassisSlot);
|
|
|
|
//DEBUG_REPORT_LOG(componentCrc != 0 && !getSlotTargetable(chassisSlot),("Skipping slot %i because it is not targettable\n",chassisSlot));
|
|
|
|
if (componentCrc != 0 && getSlotTargetable(chassisSlot))
|
|
{
|
|
float hitRange = ShipComponentAttachmentManager::getComponentHitRange(getChassisType(), componentCrc, chassisSlot);
|
|
{
|
|
// First look at regular attachments
|
|
ShipComponentAttachmentManager::TemplateHardpointPairVector const &attachments = ShipComponentAttachmentManager::getAttachmentsForShip(getChassisType(), componentCrc, chassisSlot);
|
|
for (ShipComponentAttachmentManager::TemplateHardpointPairVector::const_iterator i=attachments.begin(); i!=attachments.end(); ++i)
|
|
{
|
|
ShipComponentAttachmentManager::TemplateHardpointPair const &templateHardpointPair = *i;
|
|
|
|
int const hardpointIndex = exteriorAppearanceTemplate->getHardpointIndex(templateHardpointPair.second, true);
|
|
WARNING(hardpointIndex == -1, ("Ship %s references hardpoint '%s' which could not be found.", getDebugInformation().c_str(), templateHardpointPair.second.getString()));
|
|
if (hardpointIndex != -1)
|
|
{
|
|
Hardpoint const & hardpoint = exteriorAppearanceTemplate->getHardpoint(hardpointIndex);
|
|
Transform const & transform_o = hardpoint.getTransform();
|
|
float const distanceSquared = (position_o - transform_o.getPosition_p()).magnitudeSquared();
|
|
|
|
if (distanceSquared < sqr(hitRange) &&
|
|
((closestSlot == ShipChassisSlotType::SCST_invalid) || (distanceSquared < closestDistance)))
|
|
{
|
|
closestSlot = chassisSlot;
|
|
closestDistance = distanceSquared;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
{
|
|
// Second look at "extra" hardpoints (hardpoints that exist for the sake of targeting only
|
|
ShipComponentAttachmentManager::HardpointVector const &extraHardpoints = ShipComponentAttachmentManager::getExtraHardpointsForComponent(getChassisType(), componentCrc, chassisSlot);
|
|
for (ShipComponentAttachmentManager::HardpointVector::const_iterator i=extraHardpoints.begin(); i!=extraHardpoints.end(); ++i)
|
|
{
|
|
int const hardpointIndex = exteriorAppearanceTemplate->getHardpointIndex(*i, true);
|
|
WARNING(hardpointIndex == -1, ("Ship %s references hardpoint '%s' which could not be found.", getDebugInformation().c_str(), (*i).getString()));
|
|
if (hardpointIndex != -1)
|
|
{
|
|
Hardpoint const & hardpoint = exteriorAppearanceTemplate->getHardpoint(hardpointIndex);
|
|
Transform const & transform_o = hardpoint.getTransform();
|
|
float const distanceSquared = (position_o - transform_o.getPosition_p()).magnitudeSquared();
|
|
|
|
if (distanceSquared < sqr(hitRange) &&
|
|
((closestSlot == ShipChassisSlotType::SCST_invalid) || (distanceSquared < closestDistance)))
|
|
{
|
|
closestSlot = chassisSlot;
|
|
closestDistance = distanceSquared;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return closestSlot;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
void ShipObject::findTransformsForComponent(int const chassisSlot, std::vector<Transform> & transforms) const
|
|
{
|
|
transforms.clear();
|
|
AppearanceTemplate const * const exteriorAppearanceTemplate = getExteriorAppearance();
|
|
if (!exteriorAppearanceTemplate)
|
|
return;
|
|
uint32 const componentCrc = getComponentCrc(chassisSlot);
|
|
|
|
{
|
|
// First look at regular attachments
|
|
ShipComponentAttachmentManager::TemplateHardpointPairVector const &attachments = ShipComponentAttachmentManager::getAttachmentsForShip(getChassisType(), componentCrc, chassisSlot);
|
|
for (ShipComponentAttachmentManager::TemplateHardpointPairVector::const_iterator i=attachments.begin(); i!=attachments.end(); ++i)
|
|
{
|
|
ShipComponentAttachmentManager::TemplateHardpointPair const &templateHardpointPair = *i;
|
|
|
|
int const hardpointIndex = exteriorAppearanceTemplate->getHardpointIndex(templateHardpointPair.second, true);
|
|
WARNING(hardpointIndex == -1, ("Ship %s references hardpoint '%s' which could not be found.", getDebugInformation().c_str(), templateHardpointPair.second.getString()));
|
|
if (hardpointIndex != -1)
|
|
{
|
|
Hardpoint const & hardpoint = exteriorAppearanceTemplate->getHardpoint(hardpointIndex);
|
|
Transform const & transform_o = hardpoint.getTransform();
|
|
transforms.push_back(transform_o);
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
// Second look at "extra" hardpoints (hardpoints that exist for the sake of targeting only
|
|
ShipComponentAttachmentManager::HardpointVector const &extraHardpoints = ShipComponentAttachmentManager::getExtraHardpointsForComponent(getChassisType(), componentCrc, chassisSlot);
|
|
for (ShipComponentAttachmentManager::HardpointVector::const_iterator i=extraHardpoints.begin(); i!=extraHardpoints.end(); ++i)
|
|
{
|
|
int const hardpointIndex = exteriorAppearanceTemplate->getHardpointIndex(*i, true);
|
|
WARNING(hardpointIndex == -1, ("Ship %s references hardpoint '%s' which could not be found.", getDebugInformation().c_str(), (*i).getString()));
|
|
if (hardpointIndex != -1)
|
|
{
|
|
Hardpoint const & hardpoint = exteriorAppearanceTemplate->getHardpoint(hardpointIndex);
|
|
Transform const & transform_o = hardpoint.getTransform();
|
|
transforms.push_back(transform_o);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
AppearanceTemplate const * ShipObject::getExteriorAppearance() const
|
|
{
|
|
AppearanceTemplate const * exteriorAppearanceTemplate = 0;
|
|
|
|
PortalProperty const * const portalProperty = getPortalProperty();
|
|
if (portalProperty)
|
|
{
|
|
char const * const exteriorAppearanceName = portalProperty->getPortalPropertyTemplate().getExteriorAppearanceName();
|
|
if (exteriorAppearanceName)
|
|
exteriorAppearanceTemplate = AppearanceTemplateList::fetch(exteriorAppearanceName);
|
|
}
|
|
else
|
|
{
|
|
Appearance const * const appearance = getAppearance();
|
|
if (appearance)
|
|
exteriorAppearanceTemplate = appearance->getAppearanceTemplate();
|
|
}
|
|
NOT_NULL(exteriorAppearanceTemplate);
|
|
return exteriorAppearanceTemplate;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
float ShipObject::getFastestWeaponProjectileSpeed() const
|
|
{
|
|
return m_fastestWeaponProjectileSpeed;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int ShipObject::getCargoHoldContentsMaximum() const
|
|
{
|
|
return m_cargoHoldContentsMaximum.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setCargoHoldContentsMaximum(int contents)
|
|
{
|
|
if (isSlotInstalled(static_cast<int>(ShipChassisSlotType::SCST_cargo_hold)))
|
|
{
|
|
m_cargoHoldContentsMaximum = contents;
|
|
setCargoHoldContentsCurrent(getCargoHoldContentsCurrent());
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int ShipObject::getCargoHoldContentsCurrent() const
|
|
{
|
|
return m_cargoHoldContentsCurrent.get();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
bool ShipObject::setCargoHoldContentsCurrent(int contents)
|
|
{
|
|
if (isSlotInstalled(static_cast<int>(ShipChassisSlotType::SCST_cargo_hold)))
|
|
{
|
|
int const maximum = getCargoHoldContentsMaximum();
|
|
m_cargoHoldContentsCurrent = std::min(contents, maximum);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
ShipObject::NetworkIdIntMap const & ShipObject::getCargoHoldContents() const
|
|
{
|
|
return m_cargoHoldContents.getMap();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void ShipObject::setCargoHoldContents(NetworkIdIntMap const & contents)
|
|
{
|
|
if (isSlotInstalled(static_cast<int>(ShipChassisSlotType::SCST_cargo_hold)))
|
|
{
|
|
m_cargoHoldContents.clear();
|
|
|
|
NetworkIdIntMap::const_iterator const end = contents.end();
|
|
for (NetworkIdIntMap::const_iterator it = contents.begin(); it != end; ++it)
|
|
{
|
|
m_cargoHoldContents.insert(it->first, it->second);
|
|
}
|
|
|
|
setCargoHoldContentsCurrent(computeCargoHoldContentsCurrent());
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void ShipObject::setCargoHoldContent(NetworkId const & resourceTypeId, int amount)
|
|
{
|
|
if (isSlotInstalled(static_cast<int>(ShipChassisSlotType::SCST_cargo_hold)))
|
|
{
|
|
if (amount <= 0)
|
|
{
|
|
m_cargoHoldContents.erase(resourceTypeId);
|
|
m_cargoHoldContentsResourceTypeInfo.erase(resourceTypeId);
|
|
}
|
|
else
|
|
{
|
|
ResourceTypeObject const * const resourceTypeObject = ServerUniverse::getInstance().getResourceTypeById(resourceTypeId);
|
|
if (nullptr == ServerUniverse::getInstance().getResourceTypeById(resourceTypeId))
|
|
{
|
|
WARNING(true, ("ShipObject::setCargoHoldContent invalid resource type [%s]", resourceTypeId.getValueString().c_str()));
|
|
return;
|
|
}
|
|
|
|
bool alreadyHasThisResource = getCargoHoldContent(resourceTypeId) > 0;
|
|
|
|
if (!alreadyHasThisResource)
|
|
{
|
|
m_cargoHoldContentsResourceTypeInfo.set(
|
|
resourceTypeId,
|
|
ResourceTypeInfoPair(Unicode::narrowToWide(resourceTypeObject->getResourceName()), resourceTypeObject->getParentClass().getResourceClassName()));
|
|
}
|
|
|
|
m_cargoHoldContents.set(resourceTypeId, amount);
|
|
|
|
}
|
|
|
|
setCargoHoldContentsCurrent(computeCargoHoldContentsCurrent());
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int ShipObject::getCargoHoldContent(NetworkId const & resourceTypeId) const
|
|
{
|
|
if (isSlotInstalled(static_cast<int>(ShipChassisSlotType::SCST_cargo_hold)))
|
|
{
|
|
NetworkIdIntMap::const_iterator const it = m_cargoHoldContents.find(resourceTypeId);
|
|
if (it != m_cargoHoldContents.end())
|
|
{
|
|
return (*it).second;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int ShipObject::computeCargoHoldContentsCurrent() const
|
|
{
|
|
int total = 0;
|
|
NetworkIdIntMap::const_iterator const end = m_cargoHoldContents.end();
|
|
for (NetworkIdIntMap::const_iterator it = m_cargoHoldContents.begin(); it != end; ++it)
|
|
{
|
|
total += (*it).second;
|
|
}
|
|
|
|
return total;
|
|
}
|
|
|
|
//======================================================================
|