#include "MW4Headers.hpp" #include "AI_FocusFireSquad.hpp" #include "AI_Groups.hpp" #include "AI_UserConstants.hpp" #include "ai_squadorders.hpp" #include "CombatAI.hpp" #include #include "Sensor.hpp" #pragma warning(disable : 4284) #pragma warning (push) #include #pragma warning (pop) using namespace MW4AI; using namespace MW4AI::Squad; using namespace MechWarrior4; const Stuff::Scalar min_target_update_time = 2.0f; //________________________________________________________________________________________________________________ namespace MW4AI { namespace Squad { class FocusFireSquad; }; }; class FocusFireSquadOrders : public SquadOrders { public: FocusFireSquadOrders(FocusFireSquad& squad, MechWarrior4::Group& group, int alignment); virtual void Update(); virtual bool PointIsValid(const Stuff::Point3D& point) const; virtual void IssueCommand(Stuff::Auto_Ptr& command); virtual void NotifyShotFired(); virtual MWObject* GetAutoTarget() const; virtual bool GetExtendedSensorData(std::vector& sensor_data_list) const; virtual Stuff::Scalar GetLeastSquaredSensorDistance(const Stuff::Point3D& point) const; private: FocusFireSquad& m_Squad; MechWarrior4::Group& m_Group; int m_Alignment; }; FocusFireSquadOrders::FocusFireSquadOrders(FocusFireSquad& squad, MechWarrior4::Group& group, int alignment) : m_Squad(squad) , m_Group(group) , m_Alignment(alignment) { } void FocusFireSquadOrders::Update() { } bool FocusFireSquadOrders::PointIsValid(const Stuff::Point3D& point) const { return (true); } void FocusFireSquadOrders::IssueCommand(Stuff::Auto_Ptr& command) { } void FocusFireSquadOrders::NotifyShotFired() { } MWObject* FocusFireSquadOrders::GetAutoTarget() const { return (m_Squad.GetAutoTarget()); } bool FocusFireSquadOrders::GetExtendedSensorData(std::vector& sensor_data_list) const { std::vector members; m_Group.GetMembers(members); {for (std::vector::const_iterator i_members = members.begin(); i_members != members.end(); ++i_members) { if ((*i_members)->GetSensor() != 0) { {for (int i_sensor = 0; i_sensor < (*i_members)->GetSensor()->RefreshAndGetSensorData().GetLength(); ++i_sensor) { MechWarrior4::SensorData* d = (*i_members)->GetSensor()->RefreshAndGetSensorData()[i_sensor]; if (d != 0) { Adept::Entity* current = d->object.GetCurrent(); if ((current != 0) && (current->IsDestroyed() == false) && (current->IsDerivedFrom(MWObject::DefaultData) == true)) { MWObject* target = Cast_Object(MWObject*,current); if ((target->GetAlignment() != m_Alignment) && (std::find(members.begin(),members.end(),target) == members.end()) && (std::find(sensor_data_list.begin(),sensor_data_list.end(),target) == sensor_data_list.end())) { sensor_data_list.push_back(target); } } } }} } }} return (true); } Stuff::Scalar FocusFireSquadOrders::GetLeastSquaredSensorDistance(const Stuff::Point3D& point) const { std::vector members; m_Group.GetMembers(members); Stuff::Scalar least_distance = 0; {for (std::vector::const_iterator i_members = members.begin(); i_members != members.end(); ++i_members) { Stuff::Scalar distance(GetLengthSquared((Stuff::Point3D)((*i_members)->GetLocalToWorld()),point)); if ((least_distance == 0) || (distance < least_distance)) { least_distance = distance; } }} return (least_distance); } //________________________________________________________________________________________________________________ FocusFireSquad::FocusFireSquad() : m_AutoTarget(-2) , m_LastTargetUpdateTime(0) { } ID FocusFireSquad::GetID() const { return (GROUPAI_FOCUSFIRESQUAD); } template X GetMostFrequentElement(const std::multiset& m) { std::set s(m.begin(),m.end()); std::multiset::size_type best_count = 0; X best_element = 0; {for (std::set::const_iterator i = s.begin(); i != s.end(); ++i) { std::multiset::size_type count = m.count(*i); if (count > best_count) { best_element = *i; best_count = count; } }} return (best_element); } void FocusFireSquad::Update(MechWarrior4::Group& group, MechWarrior4::CombatAI& combat_ai) { inherited::Update(group,combat_ai); if (m_LastTargetUpdateTime + min_target_update_time > (Stuff::Scalar)gos_GetElapsedTime()) { return; } m_LastTargetUpdateTime = (Stuff::Scalar)gos_GetElapsedTime(); m_AutoTarget = -2; std::multiset potential_targets; std::vector members; group.GetMembers(members); {for (std::vector::iterator i = members.begin(); i != members.end(); ++i) { if (((*i)->GetAI() != 0) && ((*i)->GetAI()->IsDerivedFrom(CombatAI::DefaultData) == true)) { CombatAI* combat_ai = Cast_Object(CombatAI*,(*i)->GetAI()); MWObject* target = combat_ai->FindBestAutoTarget(); if (target != 0) { potential_targets.insert(target->objectID); } } }} if (potential_targets.size() == 0) { return; } m_AutoTarget = GetMostFrequentElement(potential_targets); } void FocusFireSquad::NotifyShot(MechWarrior4::Group& group, Adept::ObjectID id) { inherited::NotifyShot(group,id); } void FocusFireSquad::NotifyShotFired(MechWarrior4::Group& group, const Stuff::Line3D& line, MechWarrior4::MWObject& at_who, MechWarrior4::MWObject& shooter) { inherited::NotifyShotFired(group,line,at_who,shooter); } void FocusFireSquad::NotifyMemberAdded(MechWarrior4::Group& group, MechWarrior4::MWObject& who) { inherited::NotifyMemberAdded(group,who); if ((who.GetAI() != 0) && (who.GetAI()->IsDerivedFrom(CombatAI::DefaultData) == true)) { CombatAI* combat_ai = Cast_Object(CombatAI*,who.GetAI()); #pragma warning(disable:4239) FocusFireSquadOrders* new_squad_orders = new FocusFireSquadOrders(*this,group,who.GetAlignment()); combat_ai->SetSquadOrders(Stuff::Auto_Ptr(new_squad_orders)); #pragma warning(default:4239) } } void FocusFireSquad::NotifyMemberRemoved(MechWarrior4::Group& group, MechWarrior4::MWObject& who) { inherited::NotifyMemberRemoved(group,who); if ((who.GetAI() != 0) && (who.GetAI()->IsDerivedFrom(CombatAI::DefaultData) == true)) { CombatAI* combat_ai = Cast_Object(CombatAI*,who.GetAI()); #pragma warning(disable:4239) combat_ai->SetSquadOrders(Stuff::Auto_Ptr(0)); #pragma warning(default:4239) } } void FocusFireSquad::SetEntityToIgnore(Adept::ObjectID objectid) { } MWObject* FocusFireSquad::GetAutoTarget() { if (m_AutoTarget < 0) { return (0); } Entity* entity = Adept::NameTable::GetInstance()->FindData(m_AutoTarget); if ((entity == 0) || (entity->IsDestroyed() == true) || (entity->IsDerivedFrom(MWObject::DefaultData) == false)) { m_AutoTarget = -2; return (0); } return (Cast_Object(MWObject*,entity)); }