diff options
Diffstat (limited to 'src/game/base')
| -rw-r--r-- | src/game/base/npc.cc | 75 | ||||
| -rw-r--r-- | src/game/base/ship.cc | 142 | ||||
| -rw-r--r-- | src/game/base/ship.h | 12 | 
3 files changed, 168 insertions, 61 deletions
diff --git a/src/game/base/npc.cc b/src/game/base/npc.cc index bb4c180..dba7929 100644 --- a/src/game/base/npc.cc +++ b/src/game/base/npc.cc @@ -71,11 +71,8 @@ void NPC::frame(const unsigned long elapsed)  		}  	} else { -	 -		// FIXME verify the leader is still alive -		 -		// TODO pilot magic and mood witchcraft +		// TODO pilot magic and mood witchcraft		  		if (leader()) {  			// verify leader still exists @@ -87,66 +84,22 @@ void NPC::frame(const unsigned long elapsed)  			} 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 + 50.0f) { -					if (state() == core::Entity::Normal) { -						// enable impulse drive -						func_impulse(); -					} -				} else { -					if (state() == core::Entity::Impulse) { -						 -						if (leader()->state() != core::Entity::Impulse) { -							// disbable impulse drive -							func_impulse(); -						} -						 -					} else if (state() == core::Entity::Normal) { -						 -						if ((leader()->state() == core::Entity::Impulse) || (leader()->state() == core::Entity::ImpulseInitiate)) { -							// enable impulse drive -							func_impulse(); -						} +				if (leader()->state() == Docked) { +					 +					// TODO dock where the leader is docked +					if (leader()->dock()) { +						frame_autopilot_goto(elapsed, leader()->dock());  					} -				} -				 -				if (distance > 2.0f * r) { -					target_thrust = 1.0f; -				} else if (distance > r) { -					target_thrust = (distance - r ) / r;  				} else { -					target_thrust = 0.0f; +					 +					if (math::distance(location(), leader()->location()) > 4.0f * ( radius() + leader()->radius())) { +						// goto the leader +						frame_autopilot_goto(elapsed, leader()); +					} else { +						// formatian flying +						frame_autopilot_formation(elapsed, leader()); +					}  				}  			} else { diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index 6c5598e..23baa5d 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -990,4 +990,146 @@ void Ship::frame(const unsigned long elapsed)  } +void Ship::frame_autopilot_goto(const unsigned long elapsed, const core::Entity *target) +{	 +	// reference radius used in calculations +	const float r = radius() + target->radius(); +	 +	// desired direction +	math::Vector3f direction(target->location() - location()); +	const float distance = direction.length(); +	direction.normalize(); +	 +	// transform direction from world coordinates to local entity coordinates +	direction = axis().transpose() * direction; + +	if (direction.x() < 0) { +		// target is behind the ship +		target_direction = math::sgnf(direction.y()); +		target_pitch = 0.0f; +		 +	} else if (direction.x() + MIN_DELTA < 1.0f) { +		// target is in front of the ship +		target_direction = direction.y(); +		target_pitch = direction.z(); +	} else { +		target_direction = 0.0f; +		target_pitch = 0.0f; +	} +	 +	target_roll = 0.0f; + +	// impulse or thruster +	if (distance > r + 50.0f) { +		 +		if (state() == core::Entity::Normal) { +			// enable impulse drive +			func_impulse(); +		} +		 +	} else { +		 +		if (target->type() == core::Entity::Controlable) { +			 +			const core::EntityControlable *controlable = static_cast<const core::EntityControlable *>(target); +		 +			if (state() == core::Entity::Impulse) { +				 +				if (controlable->state() != core::Entity::Impulse) { +					// disbable impulse drive +					func_impulse(); +				} +				 +			} else if (state() == core::Entity::Normal) { +				 +				if ((controlable->state() == core::Entity::Impulse) || (controlable->state() == core::Entity::ImpulseInitiate)) { +					// enable impulse drive +					func_impulse(); +				} +			} +			 +		} else { +			 +			if (state() == core::Entity::Impulse) { +				func_impulse(); +			} +		} +	} +	 +	// thruster +	if (distance > 4.0f * r) { +		target_thrust = 1.0f; +		 +	} else if (distance > 2.0f * r ) { +		target_thrust = (distance - 2.0f * r ) / 2.0f * r; +		 +	} else { +		target_thrust = 0.0f; +		 +		// TODO autolevel +	} +} + +void Ship::frame_autopilot_formation(const unsigned long elapsed, const core::Entity *target) +{ +	// transform the target's axis into local coordinates +	const math::Axis reference(axis().transpose() * target->axis()); +	 +	//const float distance = math::distance(location(), target->location()); +	//const float r = radius() + target->radius(); +	 +	if (reference.forward().x() < 0) { +		// target is behind the ship +		target_direction = math::sgnf(reference.forward().y()); +		target_pitch = 0.0f; +		target_roll = 0.0f; +		 +	} else if (reference.forward().x() + MIN_DELTA < 1.0f) { +		// target is in front of the ship +		target_direction = reference.forward().y(); +		target_pitch = reference.forward().z(); +		target_roll = 0.0f; +		 +	} else { +		target_direction = 0.0f; +		target_pitch = 0.0f; +		 +		if (reference.up().z() < 0) { +			// upward-down +			target_roll = math::sgnf(reference.up().y()); +		} else { +			target_roll = reference.up().y(); +		}	 +	} +	 +	if (target->type() == core::Entity::Controlable) { +			 +		const core::EntityControlable *controlable = static_cast<const core::EntityControlable *>(target); +		 +		target_thrust = controlable->thrust(); +		 +		if (state() == core::Entity::Impulse) { +			 +			if (controlable->state() != core::Entity::Impulse) { +				// disbable impulse drive +				func_impulse(); +			} +			 +		} else if (state() == core::Entity::Normal) { +			 +			if ((controlable->state() == core::Entity::Impulse) || (controlable->state() == core::Entity::ImpulseInitiate)) { +				// enable impulse drive +				func_impulse(); +			} +		} +		 +	} else { +		if (state() == core::Entity::Impulse) { +			// disable impulse drive +			func_impulse(); +		} +	} +	 +} +  } // namespace game diff --git a/src/game/base/ship.h b/src/game/base/ship.h index 1de208d..ad2c71b 100644 --- a/src/game/base/ship.h +++ b/src/game/base/ship.h @@ -181,6 +181,18 @@ public:  	void set_spawn(core::Entity *spawn); +protected: +	 +	/** +	 * @brief autopilot goto target +	 * */ +	void frame_autopilot_goto(const unsigned long elapsed, const core::Entity *target); + +	/** +	 * @brief autopilot formation flying +	 * */ +	void frame_autopilot_formation(const unsigned long elapsed, const core::Entity *target); +	  private:  	JumpPoint *find_closest_jumppoint();  | 
