From 243ef412d9abb609ec1ad6ed296056c6c7c3a063 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Mon, 22 Dec 2014 21:03:32 +0000 Subject: Wingmen will try to repair their ship if the leader has a carrier and health drops below 25%. --- src/game/base/npc.cc | 106 +++++++++++++++++++++++++++++++++++++++++--------- src/game/base/npc.h | 2 + src/game/base/ship.cc | 29 +++++++------- src/game/base/ship.h | 5 +-- 4 files changed, 104 insertions(+), 38 deletions(-) diff --git a/src/game/base/npc.cc b/src/game/base/npc.cc index 0dd33c8..ec43ea0 100644 --- a/src/game/base/npc.cc +++ b/src/game/base/npc.cc @@ -14,6 +14,9 @@ namespace game { +const float NPC_WIMPY = 20.0f; // indicates the health percentage at which the NPC willtry to repair itself +const float NPC_REPAIR_ARMOR_PER_SECOND = 25.0f; // repair rate in units of armor per second + // NPC Wingman factory function NPC *NPC::add_wingman(Ship *leader) { @@ -77,6 +80,7 @@ NPC::NPC(const ShipModel *shipmodel) : Ship(0, shipmodel) { npc_mood = MoodWander; npc_destroyed_timestamp = 0; + npc_repair_timestamp = 0; npc_patrol = 0; npc_leader = 0; @@ -250,10 +254,11 @@ void NPC::frame(const unsigned long elapsed) explode(); npc_destroyed_timestamp = core::game()->time(); - } else if (leader()->zone() == zone()) { + } else if (leader()->zone() == zone()) { // leader is in this zone - if (leader()->state() == Docked) { + if (leader()->state() == Docked) + { if (state() != core::Entity::Docked) { @@ -279,27 +284,89 @@ void NPC::frame(const unsigned long elapsed) } else { - if (state() == core::Entity::Docked) { - // FIXME check launch conditions when docked at another player's ship - launch(); - - } else { - Ship *enemy = target_closest_enemy(); - - if (enemy && leader()->has_autopilot_flag(Ship::AutoPilotCombat)) { - set_autopilot_target(enemy); + if (state() == core::Entity::Docked) + { + if (!core::Entity::find(dock())) + { + // dock doesn't exist any more + set_dock(0); + npc_repair_timestamp = 0; + nudge(true); + set_state(Entity::Normal); + set_dirty(); - set_autopilot_flag(Ship::AutoPilotEnabled); - set_autopilot_flag(Ship::AutoPilotCombat); - unset_autopilot_flag(Ship::AutoPilotDock); - unset_autopilot_flag(Ship::AutoPilotFormation); } else { + // check if our dock might be noving + if (dock()->moduletype() == ship_enttype) + { + Ship *carrier = static_cast(dock()); + if (zone() != carrier->zone()) + { + set_zone(carrier->zone()); + } + set_location(carrier->location()); + set_axis(carrier->axis()); + + if (carrier->state() == core::Entity::Destroyed) + { + explode(); + + } else if ((carrier == leader()) && (armor() < maxarmor())) + { + // repair + const unsigned long now = core::game()->timestamp(); + + if (npc_repair_timestamp == 0) + { + npc_repair_timestamp = now; + } else { + while (npc_repair_timestamp + 1000 < now) + { + set_armor(armor() + NPC_REPAIR_ARMOR_PER_SECOND); + npc_repair_timestamp += 1000; + } + } + } else + { + npc_repair_timestamp = 0; + if (carrier->state() == core::Entity::Normal) + { + launch(); + } + } + } else { + launch(); + } + } + } else { + if (leader()->has_flag(core::Entity::Dockable) && (health() < NPC_WIMPY)) + { set_autopilot_target(leader()); - + set_autopilot_flag(Ship::AutoPilotEnabled); unset_autopilot_flag(Ship::AutoPilotCombat); - unset_autopilot_flag(Ship::AutoPilotDock); - set_autopilot_flag(Ship::AutoPilotFormation); + set_autopilot_flag(Ship::AutoPilotDock); + unset_autopilot_flag(Ship::AutoPilotFormation); + } else + { + Ship *enemy = target_closest_enemy(); + + if (enemy && leader()->has_autopilot_flag(Ship::AutoPilotCombat)) { + set_autopilot_target(enemy); + + set_autopilot_flag(Ship::AutoPilotEnabled); + set_autopilot_flag(Ship::AutoPilotCombat); + unset_autopilot_flag(Ship::AutoPilotDock); + unset_autopilot_flag(Ship::AutoPilotFormation); + } else + { + set_autopilot_target(leader()); + + set_autopilot_flag(Ship::AutoPilotEnabled); + unset_autopilot_flag(Ship::AutoPilotCombat); + unset_autopilot_flag(Ship::AutoPilotDock); + set_autopilot_flag(Ship::AutoPilotFormation); + } } } } @@ -318,7 +385,8 @@ void NPC::frame(const unsigned long elapsed) target_afterburner = 0.0f; target_thrust = 0; - if (state() == core::Entity::Impulse) { + if (state() == core::Entity::Impulse) + { func_impulse(); } diff --git a/src/game/base/npc.h b/src/game/base/npc.h index 411f807..4469517 100644 --- a/src/game/base/npc.h +++ b/src/game/base/npc.h @@ -114,6 +114,8 @@ private: unsigned long npc_destroyed_timestamp; + unsigned long npc_repair_timestamp; + float npc_weapon_range; core::Player *npc_commander; diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index 0dd5415..dbf8b19 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -121,12 +121,7 @@ Ship::Ship(core::Player *owner, const ShipModel *shipmodel) : core::EntityContro set_flag(core::Entity::Dockable); } - ship_armor = maxarmor(); - - // initialize physics - // FIXME probably should not be called here - //reset(); - //body()->setDamping(ship_shipmodel->linear_damping(), ship_shipmodel->angular_damping()); + set_armor(maxarmor()); } Ship::~Ship() @@ -423,7 +418,7 @@ void Ship::explode() entity_thrust = 0; - ship_armor = 0; + set_armor(0); set_state(core::Entity::Destroyed); @@ -589,7 +584,14 @@ void Ship::set_spawn(core::Entity *spawn) { ship_spawn = spawn; } - + +void Ship::set_armor(const float armor) +{ + ship_armor = armor; + math::clamp(ship_armor, 0.0f, maxarmor()); + entity_health = ship_armor * 100.0f / maxarmor(); +} + void Ship::action (btScalar seconds) { float engine_force = 0; @@ -678,11 +680,11 @@ void Ship::hit(core::Entity *other) // hit by a mine SpaceMine * spacemine = static_cast(other); if (spacemine->state() != core::Entity::Destroyed) { - ship_armor -= spacemine->damage(); + set_armor(armor() - spacemine->damage()); } // destroyed - if (ship_armor <= 0) { + if (armor() <= 0) { explode(); core::Player *assassin = 0; @@ -735,7 +737,7 @@ void Ship::hit(core::Entity *other) // don't hit self if ((projectile->state() != core::Entity::Destroyed) && (projectile->spawn_id() != id())) { - ship_armor -= projectile->damage(); + set_armor(armor() - projectile->damage()); core::Player *assassin = 0; @@ -744,7 +746,7 @@ void Ship::hit(core::Entity *other) } // destroyed - if (ship_armor <= 0) { + if (armor() <= 0) { explode(); if (owner()) { @@ -1070,9 +1072,6 @@ void Ship::frame(const unsigned long elapsed) } } - // current health - entity_health = armor() * 100.0f / maxarmor(); - /* -- SNAPPY ------------------------------------------ */ current_target_afterburner = target_afterburner; diff --git a/src/game/base/ship.h b/src/game/base/ship.h index 4b4ae61..db41ba0 100644 --- a/src/game/base/ship.h +++ b/src/game/base/ship.h @@ -179,10 +179,7 @@ public: } /// set current armor strength (current health) - inline void set_armor(const float armor) - { - ship_armor = armor; - } + void set_armor(const float armor); /// set maximal shield strength inline void set_maxshield(const float maxshield) -- cgit v1.2.3