Example #1
0
void Ship::EnterHyperspace() {
	assert(GetFlightState() != Ship::HYPERSPACE);

	const SystemPath dest = GetHyperspaceDest();

	int fuel_cost;
	Ship::HyperjumpStatus status = CheckHyperspaceTo(dest, fuel_cost, m_hyperspace.duration);
	if (status != HYPERJUMP_OK) {
		// XXX something has changed (fuel loss, mass change, whatever).
		// could report it to the player but better would be to cancel the
		// countdown before this is reached. either way do something
		return;
	}

	Equip::Type fuelType = GetHyperdriveFuelType();
	m_equipment.Remove(fuelType, fuel_cost);
	if (fuelType == Equip::MILITARY_FUEL) {
		m_equipment.Add(Equip::RADIOACTIVES, fuel_cost);
	}
	UpdateEquipStats();

	LuaEvent::Queue("onLeaveSystem", this);

	SetFlightState(Ship::HYPERSPACE);

	// virtual call, do class-specific things
	OnEnterHyperspace();
}
Example #2
0
bool Ship::CanHyperspaceTo(const SystemPath *dest, int &outFuelRequired, double &outDurationSecs, enum HyperjumpStatus *outStatus) 
{
	Equip::Type t = m_equipment.Get(Equip::SLOT_ENGINE);
	Equip::Type fuelType = GetHyperdriveFuelType();
	int hyperclass = EquipType::types[t].pval;
	int fuel = m_equipment.Count(Equip::SLOT_CARGO, fuelType);
	outFuelRequired = 0;
	if (hyperclass == 0) {
		if (outStatus) *outStatus = HYPERJUMP_NO_DRIVE;
		return false;
	}

	if (Pi::currentSystem && Pi::currentSystem->GetPath().IsSameSystem(*dest)) {
		if (outStatus) *outStatus = HYPERJUMP_CURRENT_SYSTEM;
		return false;
	}

	float dist = distance_to_system(dest);

	this->CalcStats();
	outFuelRequired = int(ceil(hyperclass*hyperclass*dist / m_stats.hyperspace_range_max));
	double m_totalmass = m_stats.total_mass;
	if (outFuelRequired > hyperclass*hyperclass) outFuelRequired = hyperclass*hyperclass;
	if (outFuelRequired < 1) outFuelRequired = 1;
	if (dist > m_stats.hyperspace_range_max) {
		outFuelRequired = 0;
		if (outStatus) *outStatus = HYPERJUMP_OUT_OF_RANGE;
		return false;
	} else if (fuel < outFuelRequired) {
		if (outStatus) *outStatus = HYPERJUMP_INSUFFICIENT_FUEL;
		return false;
	} else {
		// Old comments:
		// take at most a week. why a week? because a week is a
		// fundamental physical unit in the same sense that the planck length
		// is, and so it is very probable that future hyperspace
		// technologies will involve travelling a week through time.

		// Now mass has more of an effect on the time taken, this is mainly
		// for gameplay considerations for courier missions and the like.
		outDurationSecs = ((dist * dist * 0.5) / (m_stats.hyperspace_range_max *
			hyperclass)) * 
			(60.0 * 60.0 * 24.0 * sqrt(m_totalmass));
		//float hours = outDurationSecs * 0.0002778;
		//printf("%f LY in %f hours OR %d seconds \n", dist, hours, outDurationSecs);
		//printf("%d seconds\n", outDurationSecs);
		if (outFuelRequired <= fuel) {
			if (outStatus) *outStatus = HYPERJUMP_OK;
			return true;
		} else {
			if (outStatus) *outStatus = HYPERJUMP_INSUFFICIENT_FUEL;
			return false;
		}
	}
}
Example #3
0
void Ship::UseHyperspaceFuel(const SystemPath *dest)
{
	int fuel_cost;
	Equip::Type fuelType = GetHyperdriveFuelType();
	double dur;
	bool hscheck = CanHyperspaceTo(dest, fuel_cost, dur);
	assert(hscheck);
	m_equipment.Remove(fuelType, fuel_cost);
	if (fuelType == Equip::MILITARY_FUEL) {
		m_equipment.Add(Equip::RADIOACTIVES, fuel_cost);
	}
}
Example #4
0
Ship::HyperjumpStatus Ship::GetHyperspaceDetails(const SystemPath &dest, int &outFuelRequired, double &outDurationSecs)
{
	assert(dest.HasValidSystem());

	outFuelRequired = 0;
	outDurationSecs = 0.0;

	UpdateStats();

	if (GetFlightState() == HYPERSPACE)
		return HYPERJUMP_DRIVE_ACTIVE;

	Equip::Type t = m_equipment.Get(Equip::SLOT_ENGINE);
	Equip::Type fuelType = GetHyperdriveFuelType();
	int hyperclass = Equip::types[t].pval;
	int fuel = m_equipment.Count(Equip::SLOT_CARGO, fuelType);
	if (hyperclass == 0)
		return HYPERJUMP_NO_DRIVE;

	StarSystem *s = Pi::game->GetSpace()->GetStarSystem().Get();
	if (s && s->GetPath().IsSameSystem(dest))
		return HYPERJUMP_CURRENT_SYSTEM;

	float dist = distance_to_system(dest);

	outFuelRequired = Pi::CalcHyperspaceFuelOut(hyperclass, dist, m_stats.hyperspace_range_max);
	double m_totalmass = GetMass()/1000;
	if (dist > m_stats.hyperspace_range_max) {
		outFuelRequired = 0;
		return HYPERJUMP_OUT_OF_RANGE;
	} else if (fuel < outFuelRequired) {
		return HYPERJUMP_INSUFFICIENT_FUEL;
	} else {
		outDurationSecs = Pi::CalcHyperspaceDuration(hyperclass, m_totalmass, dist);

		if (outFuelRequired <= fuel) {
			return HYPERJUMP_OK;
		} else {
			return HYPERJUMP_INSUFFICIENT_FUEL;
		}
	}
}
Example #5
0
void Ship::UpdateEquipStats()
{
	const ShipType &stype = GetShipType();

	m_stats.max_capacity = stype.capacity;
	m_stats.used_capacity = 0;
	m_stats.used_cargo = 0;

	for (int i=0; i<Equip::SLOT_MAX; i++) {
		for (int j=0; j<stype.equipSlotCapacity[i]; j++) {
			Equip::Type t = m_equipment.Get(Equip::Slot(i), j);
			if (t) m_stats.used_capacity += Equip::types[t].mass;
			if (Equip::Slot(i) == Equip::SLOT_CARGO) m_stats.used_cargo += Equip::types[t].mass;
		}
	}
	m_stats.free_capacity = m_stats.max_capacity - m_stats.used_capacity;
	m_stats.total_mass = m_stats.used_capacity + stype.hullMass;

	m_stats.shield_mass = TONS_HULL_PER_SHIELD * float(m_equipment.Count(Equip::SLOT_SHIELD, Equip::SHIELD_GENERATOR));

	UpdateMass();
	UpdateFuelStats();

	Equip::Type fuelType = GetHyperdriveFuelType();

	if (stype.equipSlotCapacity[Equip::SLOT_ENGINE]) {
		Equip::Type t = m_equipment.Get(Equip::SLOT_ENGINE);
		int hyperclass = Equip::types[t].pval;
		if (!hyperclass) { // no drive
			m_stats.hyperspace_range = m_stats.hyperspace_range_max = 0;
		} else {
			m_stats.hyperspace_range_max = Pi::CalcHyperspaceRangeMax(hyperclass, GetMass()/1000);
			m_stats.hyperspace_range = Pi::CalcHyperspaceRange(hyperclass, GetMass()/1000, m_equipment.Count(Equip::SLOT_CARGO, fuelType));
		}
	} else {
		m_stats.hyperspace_range = m_stats.hyperspace_range_max = 0;
	}
}
Example #6
0
const shipstats_t *Ship::CalcStats()
{
	const ShipType &stype = GetShipType();
	m_stats.max_capacity = stype.capacity;
	m_stats.used_capacity = 0;
	m_stats.used_cargo = 0;
	Equip::Type fuelType = GetHyperdriveFuelType();

	for (int i=0; i<Equip::SLOT_MAX; i++) {
		for (int j=0; j<stype.equipSlotCapacity[i]; j++) {
			Equip::Type t = m_equipment.Get(Equip::Slot(i), j);
			if (t) m_stats.used_capacity += EquipType::types[t].mass;
			if (Equip::Slot(i) == Equip::SLOT_CARGO) m_stats.used_cargo += EquipType::types[t].mass;
		}
	}
	m_stats.free_capacity = m_stats.max_capacity - m_stats.used_capacity;
	m_stats.total_mass = m_stats.used_capacity + stype.hullMass;

	m_stats.shield_mass = TONS_HULL_PER_SHIELD * float(m_equipment.Count(Equip::SLOT_SHIELD, Equip::SHIELD_GENERATOR));

	if (stype.equipSlotCapacity[Equip::SLOT_ENGINE]) {
		Equip::Type t = m_equipment.Get(Equip::SLOT_ENGINE);
		int hyperclass = EquipType::types[t].pval;
		if (!hyperclass) { // no drive
			m_stats.hyperspace_range = m_stats.hyperspace_range_max = 0;
		} else {
			// for the sake of hyperspace range, we count ships mass as 60% of original.
			m_stats.hyperspace_range_max = Pi::CalcHyperspaceRange(hyperclass, m_stats.total_mass); 
			m_stats.hyperspace_range = std::min(m_stats.hyperspace_range_max, m_stats.hyperspace_range_max * m_equipment.Count(Equip::SLOT_CARGO, fuelType) /
				(hyperclass * hyperclass));
		}
	} else {
		m_stats.hyperspace_range = m_stats.hyperspace_range_max = 0;
	}
	return &m_stats;
}