From 22efe13cd7a489c13e91f166cff80cbae350785b Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 13 Oct 2013 18:57:40 +0000 Subject: Added the actual NPC class files. --- src/game/base/npc.cc | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/game/base/npc.h | 102 +++++++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 src/game/base/npc.cc create mode 100644 src/game/base/npc.h (limited to 'src') diff --git a/src/game/base/npc.cc b/src/game/base/npc.cc new file mode 100644 index 0000000..2cd193b --- /dev/null +++ b/src/game/base/npc.cc @@ -0,0 +1,148 @@ +/* + base/npc.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "base/npc.h" +#include "base/game.h" + +namespace game { + +// NPC Wingman factory function +NPC *NPC::add_wingman(Ship *leader) +{ + if (!leader) { + return 0; + } + + if (leader->state() != Entity::Normal) { + return 0; + } + + NPC *npc = new NPC(ProfileWingman, leader->shipmodel()); + + npc->set_leader(leader); + npc->set_owner(leader->owner()); + npc->set_name("Wingman"); + npc->set_mood(MoodFormation); + + npc->set_color(npc->leader()->color()); + npc->set_color_second(npc->leader()->color_second()); + + npc->set_location(leader->location() - leader->axis().forward() * 2.0f * (leader->radius() + npc->radius())); + + npc->set_axis(leader->axis()); + npc->set_zone(leader->zone()); + + npc->reset(); + + return npc; +} + +NPC::NPC(const Profile profile, const ShipModel *shipmodel) : Ship(0, shipmodel) +{ + npc_profile = profile; + npc_mood = MoodWander; + npc_destroyed_timestamp = 0; +} + +void NPC::set_mood(const Mood mood) +{ + npc_mood = mood; +} + +void NPC::set_leader(Ship *leader) +{ + npc_leader = leader; +} + +void NPC::frame(const unsigned long elapsed) +{ + if (state() == core::Entity::Destroyed) { + + if (!npc_destroyed_timestamp) { + npc_destroyed_timestamp = core::game()->time(); + + } else if (npc_destroyed_timestamp + 10.0f < core::game()->time()) { + // stay alive for 10 more seconds while explosion particles are drawn + + die(); + } + + } else { + + // FIXME verify the leader is still alive + + // TODO pilot magic and mood witchcraft + + if (leader()) { + + // verify leader still exists + if (!core::Entity::find(leader())) { + + set_leader(0); + explode(); + npc_destroyed_timestamp = core::game()->time(); + + } else if (leader()->zone() == zone()) { + + // rotate towards leader: direction + math::Vector3f d(leader()->location() - location()); + float distance = d.length(); + + d.normalize(); + + float direction_angle = math::dotproduct(axis().forward(), d); + float direction_sign = math::sgnf(math::dotproduct(axis().left(), d)); + + if (direction_sign < 0 ) { + target_direction = direction_sign; + } else if (direction_angle + MIN_DELTA < 1.0f ) { + target_direction = direction_sign * direction_angle; + } else { + target_direction = 0.0f; + } + + // rotate towards leader: pitch + direction_angle = math::dotproduct(axis().forward(), d); + direction_sign = math::sgnf(math::dotproduct(axis().up(), d)); + + if (direction_sign < 0 ) { + target_pitch = direction_sign; + } else if (direction_angle + MIN_DELTA < 1.0f ) { + target_pitch = direction_sign * direction_angle; + } else { + target_pitch = 0.0f; + } + + const float r = 2.0f * (radius() + leader()->radius()); + + if (distance > 2.0f * r) { + target_thrust = 1.0f; + } else if (distance > r) { + target_thrust = (distance - r ) / r; + } else { + target_thrust = 0.0f; + } + + } else { + + target_direction = 0; + target_pitch = 0; + target_roll = 0; + target_strafe = 0.0f; + target_vstrafe = 0.0f; + + target_afterburner = 0.0f; + target_thrust = 0; + } + } + } + + // run a ship game frame + Ship::frame(elapsed); +} + +} // namespace game + diff --git a/src/game/base/npc.h b/src/game/base/npc.h new file mode 100644 index 0000000..4a89529 --- /dev/null +++ b/src/game/base/npc.h @@ -0,0 +1,102 @@ +/* + base/npc.h + This file is part of the Osirion project and is distributed under + the terms and conditions of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_BASE_NPC_H__ +#define __INCLUDED_BASE_NPC_H__ + +#include "base/ship.h" + +namespace game +{ + +class NPC : public Ship { + +public: + /** + * @brief Definse the general profile of the NPC + * The NPC profile is set at creating time and can not be altered. + * + * Freelancer fallback value + * Trader Trade convoy member, prefers trade routes + * Military Police or military, prefers patrol routes + * Wingman wingman, prefers protecting its leader + * */ + enum Profile { ProfileFreelancer = 0, ProfileTrader = 1, ProfileMilitary = 2, ProfilePirate = 3, ProfileWingman = 4 }; + + /** + * @brief Defines the general moode of the NPC + * Wander Wamder around + * Formation Follow the leader in formation + * */ + enum Mood { MoodWander = 0, MoodFormation = 1 }; + + NPC(const Profile profile, const ShipModel *shipmodel); + + /* ---- inspectors ----------------------------------------- */ + + /** + * @brief Treturns te general profile of the NPC + * The NPC profile is set at creating time and can not be altered. + * */ + inline const Profile profile() const + { + return npc_profile; + } + + /** + * @brief returns the general moode of the NPC + * */ + inline const Mood mood() const + { + return npc_mood; + } + + /** + * @brief returns this NPC's leader. + * */ + inline Ship *leader() + { + return npc_leader; + } + + /* ---- mutators ------------------------------------------- */ + + /** + * @brief Set the general moode of the NPC + * */ + void set_mood(const Mood mood); + + /** + * @brief set the NPC's leader + * */ + void set_leader(Ship *leader); + + /** + * @brief game frame + * */ + virtual void frame(const unsigned long elapsed); + + + /** + * @brief factory function for wingman NPCs + * */ + static NPC *add_wingman(Ship *leader); + +private: + Profile npc_profile; + + Mood npc_mood; + + Ship *npc_leader; + + unsigned long npc_destroyed_timestamp; + +}; // class NPC + +} // namespace game + +#endif // __INCLUDED_BASE_NPC_H__ + -- cgit v1.2.3