From: <tz...@us...> - 2009-03-30 00:31:53
|
Revision: 2954 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=2954&view=rev Author: tzlaine Date: 2009-03-30 00:31:49 +0000 (Mon, 30 Mar 2009) Log Message: ----------- - Added new Missile class to OpenSteer code. - Set speed of Missiles, Fighters, and Ships based on PartType stats/ ShipDesign. - Corrected a problem in the calculation of ship weapon range. FrationalHealth() is now taken into account. Modified Paths: -------------- trunk/FreeOrion/SConscript trunk/FreeOrion/combat/OpenSteer/CombatFighter.cpp trunk/FreeOrion/combat/OpenSteer/CombatShip.cpp trunk/FreeOrion/combat/OpenSteer/CombatShip.h Added Paths: ----------- trunk/FreeOrion/combat/OpenSteer/Missile.cpp trunk/FreeOrion/combat/OpenSteer/Missile.h Modified: trunk/FreeOrion/SConscript =================================================================== --- trunk/FreeOrion/SConscript 2009-03-29 21:55:25 UTC (rev 2953) +++ trunk/FreeOrion/SConscript 2009-03-30 00:31:49 UTC (rev 2954) @@ -7,6 +7,7 @@ 'combat/OpenSteer/AsteroidBeltObstacle.cpp', 'combat/OpenSteer/CombatFighter.cpp', 'combat/OpenSteer/CombatShip.cpp', + 'combat/OpenSteer/Missile.cpp', 'combat/OpenSteer/Obstacle.cpp', 'combat/OpenSteer/PathingEngine.cpp', 'combat/OpenSteer/SimpleVehicle.cpp', Modified: trunk/FreeOrion/combat/OpenSteer/CombatFighter.cpp =================================================================== --- trunk/FreeOrion/combat/OpenSteer/CombatFighter.cpp 2009-03-29 21:55:25 UTC (rev 2953) +++ trunk/FreeOrion/combat/OpenSteer/CombatFighter.cpp 2009-03-30 00:31:49 UTC (rev 2954) @@ -304,8 +304,8 @@ } SimpleVehicle::reset(); - SimpleVehicle::setMaxForce(27); - SimpleVehicle::setMaxSpeed(9); + SimpleVehicle::setMaxForce(3.0 * 9.0); + SimpleVehicle::setMaxSpeed(m_stats.m_speed); // TODO: setMass() @@ -353,7 +353,7 @@ } void CombatFighter::Damage(double d) -{ m_health = (std::max)(0.0, m_health - d); } +{ m_health = std::max(0.0, m_health - d); } void CombatFighter::SetFormation(const CombatFighterFormationPtr& formation) { m_formation = formation; } @@ -401,7 +401,7 @@ const float DEFAULT_MISSION_WEIGHT = 12.0; const float MAX_MISSION_WEIGHT = 48.0; - const float AT_DESTINATION = 3.0; + const float AT_DESTINATION = std::max(3.0f, speed()); const float AT_DEST_SQUARED = AT_DESTINATION * AT_DESTINATION; bool print_needed = false; @@ -700,11 +700,11 @@ OpenSteer::AVGroup neighbors; OpenSteer::AVGroup nonfighters; if (m_leader) { - const float FIGHTER_RADIUS = (std::max)(SEPARATION_RADIUS, - (std::max)(ALIGNMENT_RADIUS, - COHESION_RADIUS)); - const float NONFIGHTER_RADIUS = (std::max)(NONFIGHTER_OBSTACLE_AVOIDANCE_RADIUS, - POINT_DEFENSE_AVOIDANCE_RADIUS); + const float FIGHTER_RADIUS = std::max(SEPARATION_RADIUS, + std::max(ALIGNMENT_RADIUS, + COHESION_RADIUS)); + const float NONFIGHTER_RADIUS = std::max(NONFIGHTER_OBSTACLE_AVOIDANCE_RADIUS, + POINT_DEFENSE_AVOIDANCE_RADIUS); m_pathing_engine->GetProximityDB().FindInRadius( position(), FIGHTER_RADIUS, neighbors, FIGHTER_FLAGS, EmpireFlag(m_empire_id)); m_pathing_engine->GetProximityDB().FindInRadius( @@ -761,7 +761,7 @@ away_vec /= away_vec_length; point_defense_evasion_vec += away_vec * ship->AntiFighterStrength(); float collision_avoidance_scale_factor = - (std::max)(0.0f, NONFIGHTER_OBSTACLE_AVOIDANCE_RADIUS - away_vec_length) / + std::max(0.0f, NONFIGHTER_OBSTACLE_AVOIDANCE_RADIUS - away_vec_length) / NONFIGHTER_OBSTACLE_AVOIDANCE_RADIUS; nonfighter_obstacle_evasion_vec += away_vec * collision_avoidance_scale_factor; if (OBSTACLE_AVOIDANCE_TIME * speed() < away_vec_length) Modified: trunk/FreeOrion/combat/OpenSteer/CombatShip.cpp =================================================================== --- trunk/FreeOrion/combat/OpenSteer/CombatShip.cpp 2009-03-29 21:55:25 UTC (rev 2953) +++ trunk/FreeOrion/combat/OpenSteer/CombatShip.cpp 2009-03-30 00:31:49 UTC (rev 2954) @@ -22,11 +22,8 @@ namespace { - const float NO_PD_FIGHTER_ATACK_SCALE_FACTOR = 50.0; + const float NO_PD_FIGHTER_ATTACK_SCALE_FACTOR = 50.0; - const double PD_VS_SHIP_FACTOR = 1.0 / 50.0; - const double NON_PD_VS_FIGHTER_FACTOR = 1.0 / 50.0; - template <class Stats> struct CopyStatPtr { @@ -45,10 +42,12 @@ for (CombatShip::DFVec::reverse_iterator it = unfired_SR_weapons.rbegin(); it != unfired_SR_weapons.rend(); ++it) { - if (range_squared < (*it)->m_range * (*it)->m_range) { + double weapon_range = (*it)->m_range * health_factor; + double weapon_range_squared = weapon_range * weapon_range; + if (range_squared < weapon_range_squared) { double damage = (*it)->m_damage * (*it)->m_ROF * health_factor; if (fighter) - damage *= NON_PD_VS_FIGHTER_FACTOR; + damage *= CombatShip::NON_PD_VS_FIGHTER_FACTOR; target->Damage(damage); } else { unfired_SR_weapons.resize(std::distance(it, unfired_SR_weapons.rend())); @@ -58,10 +57,12 @@ for (CombatShip::LRVec::reverse_iterator it = unfired_LR_weapons.rbegin(); it != unfired_LR_weapons.rend(); ++it) { - if (range_squared < (*it)->m_range * (*it)->m_range) { + double weapon_range = (*it)->m_range * health_factor; + double weapon_range_squared = weapon_range * weapon_range; + if (range_squared < weapon_range_squared) { double damage = (*it)->m_damage * (*it)->m_ROF * health_factor; if (fighter) - damage *= NON_PD_VS_FIGHTER_FACTOR; + damage *= CombatShip::NON_PD_VS_FIGHTER_FACTOR; target->Damage(damage); } else { unfired_LR_weapons.resize(std::distance(it, unfired_LR_weapons.rend())); @@ -71,12 +72,14 @@ for (CombatShip::DFVec::reverse_iterator it = unfired_PD_weapons.rbegin(); it != unfired_PD_weapons.rend(); ++it) { - if (range_squared < (*it)->m_range * (*it)->m_range) { + double weapon_range = (*it)->m_range * health_factor; + double weapon_range_squared = weapon_range * weapon_range; + if (range_squared < weapon_range_squared) { double damage = (*it)->m_damage * (*it)->m_ROF * health_factor; if (fighter) fighter->Formation()->Damage(damage); else - target->Damage(damage * PD_VS_SHIP_FACTOR); + target->Damage(damage * CombatShip::PD_VS_SHIP_FACTOR); } else { unfired_PD_weapons.resize(std::distance(it, unfired_PD_weapons.rend())); break; @@ -105,6 +108,9 @@ //////////////////////////////////////////////////////////////////////////////// // CombatShip //////////////////////////////////////////////////////////////////////////////// +const double CombatShip::PD_VS_SHIP_FACTOR = 1.0 / 50.0; +const double CombatShip::NON_PD_VS_FIGHTER_FACTOR = 1.0 / 50.0; + CombatShip::CombatShip() : m_proximity_token(0), m_empire_id(-1), @@ -291,6 +297,9 @@ double CombatShip::MinNonPDWeaponRange() const { return m_ship->Design()->MinNonPDWeaponRange() * FractionalHealth(); } +double CombatShip::MaxPDRange() const +{ return m_ship->Design()->MaxPDRange() * FractionalHealth(); } + void CombatShip::Init(const OpenSteer::Vec3& position_, const OpenSteer::Vec3& direction) { m_proximity_token = @@ -298,7 +307,7 @@ SimpleVehicle::reset(); SimpleVehicle::setMaxForce(3.0); - SimpleVehicle::setMaxSpeed(8.0); + SimpleVehicle::setMaxSpeed(m_ship->Design()->Speed()); // TODO: setMass() @@ -383,7 +392,7 @@ const float DEFAULT_MISSION_WEIGHT = 12.0; const float MAX_MISSION_WEIGHT = 48.0; - const float AT_DESTINATION = 3.0; + const float AT_DESTINATION = std::max(3.0f, speed()); const float AT_DEST_SQUARED = AT_DESTINATION * AT_DESTINATION; bool print_needed = false; @@ -579,7 +588,11 @@ void CombatShip::FirePDDefensively(DFVec& unfired_PD_weapons) { - // TODO + OpenSteer::AVGroup all; + // TODO: NotEmpireFlag() should become EnemyOfEmpireFlag() + m_pathing_engine->GetProximityDB().FindAll( + all, MISSILE_FLAG | FIGHTER_FLAGS, NotEmpireFlag(m_empire_id)); + } void CombatShip::FireAtHostiles() @@ -678,7 +691,7 @@ INTERCEPTOR_SCALE_FACTOR : BOMBER_SCALE_FACTOR); strength /= (1.0 + AntiFighterStrength()); if (AntiFighterStrength()) - strength *= NO_PD_FIGHTER_ATACK_SCALE_FACTOR; + strength *= NO_PD_FIGHTER_ATTACK_SCALE_FACTOR; } else if (ship = boost::dynamic_pointer_cast<CombatShip>(it->second.lock())) { strength = ship->HealthAndShield() * (1.0 + ship->AntiShipStrength(shared_from_this())); Modified: trunk/FreeOrion/combat/OpenSteer/CombatShip.h =================================================================== --- trunk/FreeOrion/combat/OpenSteer/CombatShip.h 2009-03-29 21:55:25 UTC (rev 2953) +++ trunk/FreeOrion/combat/OpenSteer/CombatShip.h 2009-03-30 00:31:49 UTC (rev 2954) @@ -50,11 +50,15 @@ virtual void Damage(double d); + static const double PD_VS_SHIP_FACTOR; + static const double NON_PD_VS_FIGHTER_FACTOR; + private: CombatShip(); double MaxWeaponRange() const; double MinNonPDWeaponRange() const; + double MaxPDRange() const; void Init(const OpenSteer::Vec3& position_, const OpenSteer::Vec3& direction); void PushMission(const ShipMission& mission); Added: trunk/FreeOrion/combat/OpenSteer/Missile.cpp =================================================================== --- trunk/FreeOrion/combat/OpenSteer/Missile.cpp (rev 0) +++ trunk/FreeOrion/combat/OpenSteer/Missile.cpp 2009-03-30 00:31:49 UTC (rev 2954) @@ -0,0 +1,118 @@ +#include "Missile.h" + +#include "PathingEngine.h" + + +Missile::Missile() : + m_proximity_token(0), + m_empire_id(-1), + m_last_steer(), + m_stats(), + m_destination(), + m_target(), + m_health(0.0), + m_pathing_engine() +{} + +Missile::Missile(int empire_id, const PartType& part, CombatObjectPtr target, + const OpenSteer::Vec3& position, const OpenSteer::Vec3& direction, + PathingEngine& pathing_engine) : + m_proximity_token(0), + m_empire_id(empire_id), + m_last_steer(), + m_stats(boost::get<LRStats>(part.Stats())), + m_destination(target->position()), + m_target(target), + m_health(m_stats.m_health), + m_pathing_engine(&pathing_engine) +{ Init(position, direction); } + +Missile::~Missile() +{ delete m_proximity_token; } + +double Missile::HealthAndShield() const +{ return m_health; } + +double Missile::Health() const +{ return m_health; } + +double Missile::FractionalHealth() const +{ return 1.0; } + +double Missile::AntiFighterStrength() const +{ return 0.0; } + +double Missile::AntiShipStrength(CombatShipPtr target/* = CombatShipPtr()*/) const +{ return 0.0; } + +void Missile::update(const float /*current_time*/, const float elapsed_time) +{ + OpenSteer::Vec3 steer = m_last_steer; + if (m_pathing_engine->UpdateNumber() % PathingEngine::UPDATE_SETS == + serialNumber % PathingEngine::UPDATE_SETS) { + const float AT_DESTINATION = speed(); + const float AT_DEST_SQUARED = AT_DESTINATION * AT_DESTINATION; + float distance_squared = (m_destination - position()).lengthSquared(); + CombatObjectPtr target = m_target.lock(); + if (distance_squared < AT_DEST_SQUARED) { + if (target) { + if (CombatFighterPtr fighter = + boost::dynamic_pointer_cast<CombatFighter>(target)) + target->Damage(m_stats.m_damage * CombatShip::NON_PD_VS_FIGHTER_FACTOR); + else + target->Damage(m_stats.m_damage); + } + // TODO: Remove self from engine. + return; + } else { + if (target) + m_destination = target->position(); + } + steer = Steer(); + } + applySteeringForce(steer, elapsed_time); + m_last_steer = steer; + m_proximity_token->UpdatePosition(position()); +} + +void Missile::regenerateLocalSpace(const OpenSteer::Vec3& newVelocity, + const float elapsedTime) +{} + +void Missile::Damage(double d) +{ m_health = std::max(0.0, m_health - d); } + +void Missile::Init(const OpenSteer::Vec3& position_, const OpenSteer::Vec3& direction) +{ + m_proximity_token = + m_pathing_engine->GetProximityDB().Insert( + this, MISSILE_FLAG, EmpireFlag(m_empire_id)); + + SimpleVehicle::reset(); + SimpleVehicle::setMaxForce(9.0 * 18.0); + SimpleVehicle::setMaxSpeed(m_stats.m_speed); + + // TODO: setMass() + + SimpleVehicle::regenerateOrthonormalBasis(direction, OpenSteer::Vec3(0, 0, 1)); + + SimpleVehicle::setPosition(position_); + SimpleVehicle::setSpeed(0); + + m_proximity_token->UpdatePosition(position()); +} + +OpenSteer::Vec3 Missile::Steer() +{ + const float OBSTACLE_AVOIDANCE_TIME = 2.0; + + const OpenSteer::Vec3 avoidance = + steerToAvoidObstacles(OBSTACLE_AVOIDANCE_TIME, + m_pathing_engine->Obstacles().begin(), + m_pathing_engine->Obstacles().end()); + + if (avoidance != OpenSteer::Vec3::zero) + return avoidance; + + return (m_destination - position()).normalize(); +} Added: trunk/FreeOrion/combat/OpenSteer/Missile.h =================================================================== --- trunk/FreeOrion/combat/OpenSteer/Missile.h (rev 0) +++ trunk/FreeOrion/combat/OpenSteer/Missile.h 2009-03-30 00:31:49 UTC (rev 2954) @@ -0,0 +1,63 @@ +// -*- C++ -*- +#ifndef _Missile_h_ +#define _Missile_h_ + +#include "PathingEngineFwd.h" + +#include "CombatObject.h" +#include "../../universe/ShipDesign.h" + +#include <boost/enable_shared_from_this.hpp> + + +class Missile : + public CombatObject, + public boost::enable_shared_from_this<Missile> +{ +public: + Missile(int empire_id, const PartType& part, CombatObjectPtr target, + const OpenSteer::Vec3& position, const OpenSteer::Vec3& direction, + PathingEngine& pathing_engine); + ~Missile(); + + virtual double HealthAndShield() const; + virtual double Health() const; + virtual double FractionalHealth() const; + virtual double AntiFighterStrength() const; + virtual double AntiShipStrength(CombatShipPtr target = CombatShipPtr()) const; + + virtual void update(const float /*current_time*/, const float elapsed_time); + virtual void regenerateLocalSpace(const OpenSteer::Vec3& newVelocity, + const float elapsedTime); + + virtual void Damage(double d); + +private: + Missile(); + + void Init(const OpenSteer::Vec3& position_, const OpenSteer::Vec3& direction); + OpenSteer::Vec3 Steer(); + + ProximityDBToken* m_proximity_token; + int m_empire_id; + OpenSteer::Vec3 m_last_steer; + LRStats m_stats; + OpenSteer::Vec3 m_destination; // Only the X and Y values should be nonzero. + CombatObjectWeakPtr m_target; + double m_health; + PathingEngine* m_pathing_engine; + + friend class boost::serialization::access; + template <class Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(CombatObject) + & BOOST_SERIALIZATION_NVP(m_proximity_token) + & BOOST_SERIALIZATION_NVP(m_empire_id) + & BOOST_SERIALIZATION_NVP(m_destination) + & BOOST_SERIALIZATION_NVP(m_target) + & BOOST_SERIALIZATION_NVP(m_pathing_engine); + } +}; + +#endif |