From 4e1d951705204899ee99d7fcedf582b25b86b506 Mon Sep 17 00:00:00 2001
From: Stijn Buys <ingar@osirion.org>
Date: Sun, 28 Dec 2008 12:33:04 +0000
Subject: generic docking API, race activating requires docking

---
 src/game/base/game.cc      | 34 +++---------------------
 src/game/base/jumppoint.cc | 54 ++++++++++++++++++++++++++++++++++---
 src/game/base/jumppoint.h  | 12 ++++++---
 src/game/base/planet.cc    | 23 ++++++++++++++++
 src/game/base/planet.h     |  3 +++
 src/game/base/racetrack.cc | 66 ++++++++++++++++++++++++++--------------------
 src/game/base/racetrack.h  | 22 ++++++++++++----
 src/game/base/station.cc   | 22 ++++++++++++++++
 src/game/base/station.h    |  4 +++
 9 files changed, 169 insertions(+), 71 deletions(-)

(limited to 'src/game/base')

diff --git a/src/game/base/game.cc b/src/game/base/game.cc
index 8a096b2..756985c 100644
--- a/src/game/base/game.cc
+++ b/src/game/base/game.cc
@@ -169,7 +169,7 @@ void Game::func_impulse(core::Player *player, std::string const &args)
 }
 
 // a player sends a docking request
-void Game::func_dock(core::Player *player,core::Entity *entity)
+void Game::func_dock(core::Player *player, core::Entity *entity)
 {
 	if (!player->control())
 		return;
@@ -180,37 +180,11 @@ void Game::func_dock(core::Player *player,core::Entity *entity)
 	if ((entity->flags() & core::Entity::Dockable) == 0)
 		return;
 
-	if (player->control()->eventstate() == core::Entity::Docked)
+	if (player->control()->eventstate() != core::Entity::Normal)
 		return;
 
-	if (math::distance(entity->location(), player->control()->location()) > 2.0f * (entity->radius()+player->control()->radius())) {
-		player->send("Target out of range");
-		return;
-	}
-
-	if (entity->moduletype() == jumpgate_enttype) {
-		JumpGate *jumpgate = static_cast<JumpGate *>(entity);
-		if (jumpgate->target()) {
-			if (jumpgate->activated()) {
-				player->send("Jumpgate in use");
-				return;
-			}
-			player->set_view(jumpgate);
-			Ship * ship = static_cast<Ship *>(player->control());
-			ship->initiate_jump(jumpgate);
-			jumpgate->activate();
-			if (jumpgate->target()->moduletype() == jumpgate_enttype) {
-				static_cast<JumpGate *>(jumpgate->target())->activate();
-			}
-		} else {
-			player->send("Jumpgate inactive.");
-		}
-	} else {
-	
-		player->control()->location().assign(entity->location());
-		player->control()->set_eventstate(core::Entity::Docked);
-		player->set_view(entity);
-		player->send("^BDocking at " + entity->name());
+	if ((entity->flags() & core::Entity::Dockable) == core::Entity::Dockable) {
+		entity->dock(player->control());
 	}
 }
 
diff --git a/src/game/base/jumppoint.cc b/src/game/base/jumppoint.cc
index fcf20d6..e943c24 100644
--- a/src/game/base/jumppoint.cc
+++ b/src/game/base/jumppoint.cc
@@ -12,7 +12,7 @@ namespace game
 
 /* ---- class JumpPoint -------------------------------------------- */
 
-JumpPoint::JumpPoint() : core::EntityDynamic(core::Entity::Static | core::Entity::Bright)
+JumpPoint::JumpPoint() : core::EntityDynamic(core::Entity::Bright)
 {
 	entity_shape = core::Entity::Diamond;
 	entity_color.assign(0.0f, 0.8f, 0.8f, 1.0f);
@@ -68,7 +68,7 @@ void JumpPoint::validate()
 	}
 
 	jumppoint_target = static_cast<JumpPoint *>(targetentity);
-
+	
 	//con_debug << "  Jumppoint " << zone->label() << ":" << label() << " with target " << targetlabel() << std::endl;
 }
 
@@ -79,8 +79,6 @@ JumpGate::JumpGate() : JumpPoint()
 	unset_flag(core::Entity::Bright);
 	entity_radius = 1.0f;
 	entity_moduletypeid = jumpgate_enttype;
-	set_flag(core::Entity::Dockable);
-
 	entity_eventstate = core::Entity::NoPower;
 }
 
@@ -88,6 +86,53 @@ JumpGate::~JumpGate()
 {
 }
 
+void JumpGate::validate()
+{
+	JumpPoint::validate();
+	if (target()) {
+		set_flag(core::Entity::Dockable);
+	} else {
+		unset_flag(core::Entity::Dockable);
+	}
+}
+
+void JumpGate::dock(core::Entity *entity)
+{
+	if (entity->moduletype() != ship_enttype)
+		return;
+
+	Ship * ship = static_cast<Ship *>(entity);
+
+	if (math::distance(location(), ship->location()) > radius() + ship->radius()) {
+		if (ship->owner())
+			ship->owner()->send("Jumpgate out of range");
+		return;
+	}
+
+	con_debug << name() << " received docking request from " << entity->name() << std::endl;
+	if (target()) {
+		if (activated()) {
+			if (ship->owner())
+				ship->owner()->send("Jumpgate in use");
+			return;
+		}
+
+		ship->initiate_jump(this);
+		activate();
+		if (target()->moduletype() == jumpgate_enttype) {
+			static_cast<JumpGate *>(target())->activate();
+		}
+
+		if (ship->owner() && ship->owner()->control() == ship) {
+			ship->owner()->set_view(this);
+		}
+	} else {
+		if (ship->owner())
+			ship->owner()->send("Jumpgate inactive");
+		return;
+	}	
+}
+
 void JumpGate::activate()
 {
 	jumpgate_timer = 10.0f;
@@ -101,6 +146,7 @@ void JumpGate::frame(float elapsed)
 
 	if (jumpgate_timer < 0) {
 		entity_eventstate = core::Entity::NoPower;
+		jumpgate_timer = 0;
 	}
 }
 
diff --git a/src/game/base/jumppoint.h b/src/game/base/jumppoint.h
index 4bab7db..900f1f3 100644
--- a/src/game/base/jumppoint.h
+++ b/src/game/base/jumppoint.h
@@ -16,8 +16,8 @@ namespace game {
 
 /// a jumppoint
 /**
- * jumppoints are used to define hyperspace routes between systems
- * when a ship actives the jump drive, a jump point will be opened
+ * jumppoints are used to define hyperspace routes between systems.
+ * If a ship actives its jump drive, a jump point will be opened
  * between the current system and the target of the nearest jumppoint.
  *
  */
@@ -34,7 +34,7 @@ public:
 	void set_targetlabel(const std::string &label);
 
 	/// validate the targetlabel and set target()
-	void validate();
+	virtual void validate();
 
 private:
 	std::string	jumppoint_targetlabel;
@@ -47,6 +47,12 @@ public:
 	JumpGate();
 	virtual ~JumpGate();
 
+	/// validate the targetlabel and set target()
+	virtual void validate();
+
+	/// entity received a docking request
+	virtual void dock(core::Entity *entity);
+
 	inline bool activated() const { return (jumpgate_timer > 0); }
 
 	void activate();
diff --git a/src/game/base/planet.cc b/src/game/base/planet.cc
index 684b9dc..f63552c 100644
--- a/src/game/base/planet.cc
+++ b/src/game/base/planet.cc
@@ -36,4 +36,27 @@ void Planet::set_shipdealer(ShipDealer *shipdealer)
 	planet_shipdealer = shipdealer;
 }
 
+
+void Planet::dock(core::Entity *entity)
+{
+	if (entity->moduletype() != ship_enttype)
+		return;
+
+	Ship * ship = static_cast<Ship *>(entity);
+
+	if (math::distance(location(), ship->location()) > radius() + ship->radius() + 50.0f ) {
+		if (ship->owner())
+			ship->owner()->send("Planet out of range");
+		return;
+	}
+
+	ship->location().assign(entity->location());
+	ship->set_eventstate(core::Entity::Docked);
+
+	if (ship->owner() && ship->owner()->control() == ship) {	
+		ship->owner()->set_view(this);
+		ship->owner()->send("^BDocking at " + entity->name());
+	}
+}
+
 } // namespace game
diff --git a/src/game/base/planet.h b/src/game/base/planet.h
index e6fa41a..efc5332 100644
--- a/src/game/base/planet.h
+++ b/src/game/base/planet.h
@@ -25,6 +25,9 @@ public:
 
 	void set_shipdealer(ShipDealer *shipdealer);
 
+	/// entity received a docking request
+	virtual void dock(core::Entity *entity);
+
 private:
 	ShipDealer		*planet_shipdealer;
 
diff --git a/src/game/base/racetrack.cc b/src/game/base/racetrack.cc
index 46a7c86..b543c9c 100644
--- a/src/game/base/racetrack.cc
+++ b/src/game/base/racetrack.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <sstream>
 
+#include "base/game.h"
 #include "base/racetrack.h"
 #include "core/gameserver.h"
 
@@ -42,6 +43,7 @@ RaceTrack::RaceTrack() : EntityDynamic()
 	track_checkpointtime = 0;
 
 	entity_eventstate = core::Entity::NoPower;
+	set_flag(core::Entity::Dockable);
 }
 
 RaceTrack::~RaceTrack()
@@ -70,40 +72,46 @@ void RaceTrack::reset()
 	set_eventstate(core::Entity::NoPower);
 }
 
-void RaceTrack::frame(float seconds)
+void RaceTrack::dock(core::Entity *entity)
 {
-	if (!track_checkpoints.size())
+	
+	if (entity->moduletype() != ship_enttype)
 		return;
+	Ship * ship = static_cast<Ship *>(entity);
 
-	if (!track_player) {
-
-		// FIXME this should go through proper collision detection
-		for (core::GameServer::Players::iterator it = core::server()->players().begin(); it != core::server()->players().end(); ++it) {
-			if ((*it)->control() && (*it)->control()->zone() == zone()) {
-				if (math::distance((*it)->control()->location(), location()) <= 1) {
-					track_player = (*it);
-
-					track_racestart = core::server()->time();
-					set_eventstate(core::Entity::Normal);
-
-					for (CheckPoints::iterator cpit = track_checkpoints.begin(); cpit != track_checkpoints.end(); ++cpit) {
-						set_eventstate(core::Entity::Normal);
-					}
-					
-					entity_timer = 5.0f;
-					std::string message("^B");
-					message.append(track_player->name());
-					message.append(" ^Bactivated the race! Race starts in 5...");
-					core::server()->broadcast(message);
-					track_player->set_mission_target(this);
-					return;
-				}
-			}
-		}
+	if (math::distance(location(), ship->location()) > radius()) {
+		ship->owner()->send("Target out of range");
+		return;
+	}
 
+	if (track_player) {
+		ship->owner()->send("Race in use");
 		return;
 	}
 
+	track_player = ship->owner();
+	track_racestart = core::server()->time();
+	set_eventstate(core::Entity::Normal);
+
+	for (CheckPoints::iterator cpit = track_checkpoints.begin(); cpit != track_checkpoints.end(); ++cpit) {
+		set_eventstate(core::Entity::Normal);
+	}
+	
+	entity_timer = 5.0f;
+	std::string message("^B" + track_player->name() + " ^Bactivated the race! Race starts in 5...");
+	core::server()->broadcast(message);
+	track_player->set_mission_target(this);
+	return;
+}
+
+void RaceTrack::frame(float seconds)
+{
+	if (!track_checkpoints.size())
+		return;
+
+	if (!track_player)
+		return;
+
 	// FIXME this should go into a proper general function
 	// validate current player
 	core::Player *player = 0;
@@ -125,7 +133,7 @@ void RaceTrack::frame(float seconds)
 
 	if (entity_timer) {
 
-		if (math::distance(player->control()->location(), location()) > 1) {
+		if (math::distance(location(), player->control()->location()) > radius()) {
 			std::string message("^BNo cheating!");
 			core::server()->broadcast(message);
 			reset();
@@ -167,7 +175,7 @@ void RaceTrack::frame(float seconds)
 			return;
 		}
 
-		if (math::distance(track_player->control()->location(), (*track_checkpoint)->location()) <= 1) {
+		if (math::distance(track_player->control()->location(), (*track_checkpoint)->location()) < radius()) {
 			CheckPoints::iterator next_checkpoint = track_checkpoint;
 			next_checkpoint++;
 
diff --git a/src/game/base/racetrack.h b/src/game/base/racetrack.h
index 922a94f..80a5766 100644
--- a/src/game/base/racetrack.h
+++ b/src/game/base/racetrack.h
@@ -19,23 +19,34 @@ class CheckPoint;
 
 /* ---- class RaceTrack -------------------------------------------- */
 
+/// a race track entity
 class RaceTrack : public core::EntityDynamic {
 
 public:
-	typedef std::list<CheckPoint *>  CheckPoints ;
-
+	/// default constructor
 	RaceTrack();
+
+	/// default destructor
 	virtual ~RaceTrack();
 
+	/// list of racetrack checkpoints
+	typedef std::list<CheckPoint *>  CheckPoints ;
+
+	/// the player who activated the race
+	inline core::Player *player() { return track_player; }
+
+	/// add a checkpoint to the racetrack
 	void add_checkpoint(CheckPoint *checkpoint);
 
 	/// reset the race track
 	void reset();
 
-	virtual void frame(float elapsed);
-
-	inline core::Player *player() { return track_player; }
+	/// entity received a docking request
+	virtual void dock(core::Entity *entity);
 
+	/// run one time frame
+	virtual void frame(float elapsed);
+	
 private:
 	CheckPoints 		track_checkpoints;
 	core::Player		*track_player;
@@ -47,6 +58,7 @@ private:
 
 /* ---- class CheckPoint ------------------------------------------- */
 
+/// a checkpoint for the race track
 class CheckPoint : public core::EntityDynamic  {
 public:
 	CheckPoint(RaceTrack *parent);
diff --git a/src/game/base/station.cc b/src/game/base/station.cc
index 4efd662..59f51ac 100644
--- a/src/game/base/station.cc
+++ b/src/game/base/station.cc
@@ -31,5 +31,27 @@ void Station::set_shipdealer(ShipDealer *shipdealer)
 	station_shipdealer = shipdealer;
 }
 
+
+void Station::dock(core::Entity *entity)
+{
+	if (entity->moduletype() != ship_enttype)
+		return;
+
+	Ship * ship = static_cast<Ship *>(entity);
+
+	if (math::distance(location(), ship->location()) > radius() + ship->radius()) {
+		if (ship->owner())
+			ship->owner()->send("Target out of range");
+		return;
+	}
+
+	ship->location().assign(entity->location());
+	ship->set_eventstate(core::Entity::Docked);
+
+	if (ship->owner() && ship->owner()->control() == ship) {	
+		ship->owner()->set_view(this);
+		ship->owner()->send("^BDocking at " + entity->name());
+	}
 }
 
+}
diff --git a/src/game/base/station.h b/src/game/base/station.h
index 0495ee6..3fc2158 100644
--- a/src/game/base/station.h
+++ b/src/game/base/station.h
@@ -21,6 +21,10 @@ public:
 
 	void set_shipdealer(ShipDealer *shipdealer);
 
+	/// entity received a docking request
+	virtual void dock(core::Entity *entity);
+
+
 private:
 	ShipDealer		*station_shipdealer;
 
-- 
cgit v1.2.3