From 41fcb9f3915db02c9255dc62f03d6b4a55e5b6d3 Mon Sep 17 00:00:00 2001
From: Stijn Buys <ingar@osirion.org>
Date: Sat, 9 Nov 2013 00:29:58 +0000
Subject: Nudge ships on launch and cargopods on creation to prevent them from
 spawning inside other objects.

---
 src/core/entity.cc    | 27 +++++++++++++++++++++++++++
 src/core/entity.h     |  5 +++++
 src/game/base/ship.cc | 11 ++++++++---
 3 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/src/core/entity.cc b/src/core/entity.cc
index 89e494a..4c4c35b 100644
--- a/src/core/entity.cc
+++ b/src/core/entity.cc
@@ -757,6 +757,33 @@ void EntityDynamic::set_state(int state)
 	}
 }
 
+void EntityDynamic::nudge()
+{
+	if (!zone()) {
+		return;
+	}
+	
+	for (Zone::Content::const_iterator it = zone()->content().begin(); it != zone()->content().end(); it++) {
+		const Entity *other = (*it);
+		if ((other->type() != Projectile) && (other != this)) {
+			// check distance
+			const float d = math::distance(location(), other->location());
+			const float r = radius() + other->radius();
+			
+			if ( d < r ) {
+				// nudge into randomize direction
+				math::Axis nudge_axis(axis());
+				nudge_axis.change_direction(math::randomf(60.0f) - 30.0f);
+				nudge_axis.change_pitch(math::randomf(60.0f) - 30.0f);
+				set_location(location() + nudge_axis.forward() * (r - d + 0.001f));
+				
+				// restart search
+				it = zone()->content().begin();
+			}
+		}
+	}
+}
+
 void EntityDynamic::reset()
 {
 	// no bullet physics on NonSolid entities
diff --git a/src/core/entity.h b/src/core/entity.h
index adeac0f..a1de121 100644
--- a/src/core/entity.h
+++ b/src/core/entity.h
@@ -673,6 +673,11 @@ public:
 	 */
 	virtual void reset();
 	
+	/**
+	 * @brief nudge the entity out of the radius of other entities in its current zune
+	 */
+	void nudge();
+	
 	/**
 	 * @brief physics collision callback
 	 * This funcion is called by the physics engine if the entity collides with another entity.
diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc
index 05edf9c..08838ad 100644
--- a/src/game/base/ship.cc
+++ b/src/game/base/ship.cc
@@ -381,7 +381,9 @@ void Ship::eject(core::Item *item, const long eject_amount, const bool eject_mes
 			owner()->sound("game/eject");
 		}
 		
-		// reset cargopod physics		
+		// reset cargopod physics
+		pod->nudge();
+		
 		pod->reset();
 		
 		assert(pod->body());
@@ -528,10 +530,13 @@ void Ship::launch()
 	
 	get_axis().assign(ship_dock->axis());
 	
-	if (ship_dock->type() == core::Entity::Globe)
+	if (ship_dock->type() == core::Entity::Globe) {
 		get_location().assign(ship_dock->location() + (ship_dock->axis().forward() * (PLANET_SAFE_DISTANCE + this->radius() + ship_dock->radius())));
-	else
+	} else {
 		get_location().assign(ship_dock->location() + (ship_dock->axis().forward() * (this->radius() + ship_dock->radius())));
+	}
+	
+	nudge();
 	
 	ship_dock = 0;
 	
-- 
cgit v1.2.3