Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/base/npc.cc148
-rw-r--r--src/game/base/npc.h102
2 files changed, 250 insertions, 0 deletions
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__
+