Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/base/npc.cc')
-rw-r--r--src/game/base/npc.cc148
1 files changed, 148 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
+