Ejemplo n.º 1
0
Ship::HyperjumpStatus Ship::CheckHyperjumpCapability() const {
	if (GetFlightState() == HYPERSPACE)
		return HYPERJUMP_DRIVE_ACTIVE;

	if (GetFlightState() != FLYING && GetFlightState() != JUMPING)
		return HYPERJUMP_SAFETY_LOCKOUT;

	return HYPERJUMP_OK;
}
Ejemplo n.º 2
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();
}
Ejemplo n.º 3
0
bool Ship::FireMissile(int idx, Ship *target)
{
	assert(target);

	if (GetFlightState() != FLYING) return false;

	const Equip::Type t = m_equipment.Get(Equip::SLOT_MISSILE, idx);
	if (t == Equip::NONE) {
		return false;
	}

	m_equipment.Set(Equip::SLOT_MISSILE, idx, Equip::NONE);
	UpdateEquipStats();

	ShipType::Id mtype;
	switch (t) {
		case Equip::MISSILE_SMART: mtype = ShipType::MISSILE_SMART; break;
		case Equip::MISSILE_NAVAL: mtype = ShipType::MISSILE_NAVAL; break;
		case Equip::MISSILE_UNGUIDED: mtype = ShipType::MISSILE_UNGUIDED; break;
		default:
		case Equip::MISSILE_GUIDED: mtype = ShipType::MISSILE_GUIDED; break;
	}
	Missile *missile = new Missile(mtype, this, target);
	missile->SetOrient(GetOrient());
	missile->SetFrame(GetFrame());
	// XXX DODGY! need to put it in a sensible location
	vector3d dir = -GetOrient().VectorZ();
	missile->SetPosition(GetPosition()+50.0*dir);
	missile->SetVelocity(GetVelocity());
	Pi::game->GetSpace()->AddBody(missile);
	return true;
}
Ejemplo n.º 4
0
void Player::StaticUpdate(const float timeStep)
{
	Body *b;
	vector3d v;
	matrix4x4d m;

	if (GetFlightState() == Ship::FLYING) {
		switch (m_flightControlState) {
		case CONTROL_FIXSPEED:
			if (Pi::GetView() == Pi::worldView) PollControls(timeStep);
			b = (GetCombatTarget() ? GetCombatTarget() : GetNavTarget());
			GetRotMatrix(m);
			v = m * vector3d(0, 0, -m_setSpeed);
			if (b) v += b->GetVelocityRelativeTo(this->GetFrame());
			AIMatchVel(v);
			break;
		case CONTROL_MANUAL:
			if (Pi::GetView() == Pi::worldView) PollControls(timeStep);
			break;
		case CONTROL_AUTOPILOT:
			break;
		}
	}
	Ship::StaticUpdate(timeStep);		// also calls autopilot AI
	if (m_flightControlState == CONTROL_AUTOPILOT && !AIIsActive()) {
		Pi::RequestTimeAccel(1);
		SetFlightControlState(CONTROL_MANUAL);		//FIXSPEED);
//		m_setSpeed = 0;
	}
		
	/* This wank probably shouldn't be in Player... */
	/* Ship engine noise. less loud inside */
	float v_env = (Pi::worldView->GetCamType() == WorldView::CAM_EXTERNAL ? 1.0f : 0.5f);
	static Sound::Event sndev;
	float volBoth = 0.0f;
	volBoth += 0.5f*fabs(GetThrusterState().y);
	volBoth += 0.5f*fabs(GetThrusterState().z);
	
	float targetVol[2] = { volBoth, volBoth };
	if (GetThrusterState().x > 0.0)
		targetVol[0] += 0.5f*(float)GetThrusterState().x;
	else targetVol[1] += -0.5f*(float)GetThrusterState().x;

	targetVol[0] = v_env * Clamp(targetVol[0], 0.0f, 1.0f);
	targetVol[1] = v_env * Clamp(targetVol[1], 0.0f, 1.0f);
	float dv_dt[2] = { 4.0f, 4.0f };
	if (!sndev.VolumeAnimate(targetVol, dv_dt)) {
		sndev.Play("Thruster_large", 0.0f, 0.0f, Sound::OP_REPEAT);
		sndev.VolumeAnimate(targetVol, dv_dt);
	}
	float angthrust = 0.1f * v_env * (float)Pi::player->GetAngThrusterState().Length();

	static Sound::Event angThrustSnd;
	if (!angThrustSnd.VolumeAnimate(angthrust, angthrust, 5.0f, 5.0f)) {
		angThrustSnd.Play("Thruster_Small", 0.0f, 0.0f, Sound::OP_REPEAT);
		angThrustSnd.VolumeAnimate(angthrust, angthrust, 5.0f, 5.0f);
	}
}
Ejemplo n.º 5
0
void Ship::EnterSystem() {
	assert(GetFlightState() == Ship::HYPERSPACE);

	// virtual call, do class-specific things
	OnEnterSystem();

	SetFlightState(Ship::FLYING);

	LuaEvent::Queue("onEnterSystem", this);
}
Ejemplo n.º 6
0
Ship::HyperjumpStatus Ship::CheckHyperspaceTo(const SystemPath &dest, int &outFuelRequired, double &outDurationSecs)
{
	assert(dest.HasValidSystem());

	outFuelRequired = 0;
	outDurationSecs = 0.0;

	if (GetFlightState() != FLYING)
		return HYPERJUMP_SAFETY_LOCKOUT;

	return GetHyperspaceDetails(dest, outFuelRequired, outDurationSecs);
}
Ejemplo n.º 7
0
Missile * Ship::SpawnMissile(ShipType::Id missile_type, int power) {
	if (GetFlightState() != FLYING)
		return 0;

	Missile *missile = new Missile(missile_type, this, power);
	missile->SetOrient(GetOrient());
	missile->SetFrame(GetFrame());
	const vector3d pos = GetOrient() * vector3d(0, GetAabb().min.y - 10, GetAabb().min.z);
	const vector3d vel = -40.0 * GetOrient().VectorZ();
	missile->SetPosition(GetPosition()+pos);
	missile->SetVelocity(GetVelocity()+vel);
	Pi::game->GetSpace()->AddBody(missile);
	return missile;
}
Ejemplo n.º 8
0
Missile * Ship::SpawnMissile(ShipType::Id missile_type, int power) {
	if (GetFlightState() != FLYING)
		return 0;

	Missile *missile = new Missile(missile_type, this, power);
	missile->SetOrient(GetOrient());
	missile->SetFrame(GetFrame());
	// XXX DODGY! need to put it in a sensible location
	vector3d dir = -GetOrient().VectorZ();
	missile->SetPosition(GetPosition()+50.0*dir);
	missile->SetVelocity(GetVelocity());
	Pi::game->GetSpace()->AddBody(missile);
	return missile;
}
Ejemplo n.º 9
0
Ship::HyperjumpStatus Ship::InitiateHyperjumpTo(const SystemPath &dest, int warmup_time, double duration, LuaRef checks) {
	if (!dest.HasValidSystem() || GetFlightState() != FLYING || warmup_time < 1)
		return HYPERJUMP_SAFETY_LOCKOUT;
	StarSystem *s = Pi::game->GetSpace()->GetStarSystem().Get();
	if (s && s->GetPath().IsSameSystem(dest))
		return HYPERJUMP_CURRENT_SYSTEM;

	m_hyperspace.dest = dest;
	m_hyperspace.countdown = warmup_time;
	m_hyperspace.now = false;
	m_hyperspace.duration = duration;
	m_hyperspace.checks = checks;

	return Ship::HYPERJUMP_OK;
}
Ejemplo n.º 10
0
void Ship::EnterHyperspace() {
	assert(GetFlightState() != Ship::HYPERSPACE);

	// Is it still a good idea, with the onLeaveSystem moved elsewhere?
	Ship::HyperjumpStatus status = CheckHyperjumpCapability();
	if (status != HYPERJUMP_OK && status != HYPERJUMP_INITIATED) {
		if (m_flightState == JUMPING)
			SetFlightState(FLYING);
		return;
	}

	// Clear ships cached list of nearby bodies so we don't try to access them.
	m_nearbyBodies.clear();

	SetFlightState(Ship::HYPERSPACE);

	// virtual call, do class-specific things
	OnEnterHyperspace();
}
Ejemplo n.º 11
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;
		}
	}
}
Ejemplo n.º 12
0
void Player::PollControls(const float timeStep)
{
	static bool stickySpeedKey = false;

	if (Pi::game->GetTimeAccel() == Game::TIMEACCEL_PAUSED || Pi::player->IsDead() || GetFlightState() != FLYING)
		return;

	// if flying 
	{
		ClearThrusterState();
		SetGunState(0,0);
		SetGunState(1,0);

		vector3d wantAngVel(0.0);
		double angThrustSoftness = 50.0;

		// have to use this function. SDL mouse position event is bugged in windows
		int mouseMotion[2];
		SDL_GetRelativeMouseState (mouseMotion+0, mouseMotion+1);	// call to flush
		if (Pi::MouseButtonState(SDL_BUTTON_RIGHT))
		{
			matrix4x4d rot; GetRotMatrix(rot);
			if (!m_mouseActive) {
				m_mouseDir = vector3d(-rot[8],-rot[9],-rot[10]);	// in world space
				m_mouseX = m_mouseY = 0;
				m_mouseActive = true;
			}
			vector3d objDir = m_mouseDir * rot;

			const double radiansPerPixel = 0.002;

			m_mouseX += mouseMotion[0] * radiansPerPixel;
			double modx = clipmouse(objDir.x, m_mouseX);			
			m_mouseX -= modx;

			const bool invertY = (Pi::IsMouseYInvert() ? !m_invertMouse : m_invertMouse);

			m_mouseY += mouseMotion[1] * radiansPerPixel * (invertY ? -1 : 1);
			double mody = clipmouse(objDir.y, m_mouseY);
			m_mouseY -= mody;

			if(!float_is_zero_general(modx) || !float_is_zero_general(mody)) {
				matrix4x4d mrot = matrix4x4d::RotateYMatrix(modx); mrot.RotateX(mody);
				m_mouseDir = (rot * (mrot * objDir)).Normalized();
			}
		}
		else m_mouseActive = false;

		// disable all keyboard controls while the console is active
		if (!Pi::IsConsoleActive()) {
			if (m_flightControlState == CONTROL_FIXSPEED) {
				double oldSpeed = m_setSpeed;
				if (stickySpeedKey) {
					if (!(KeyBindings::increaseSpeed.IsActive() || KeyBindings::decreaseSpeed.IsActive())) {
						stickySpeedKey = false;
					}
				}
				
				if (!stickySpeedKey) {
					if (KeyBindings::increaseSpeed.IsActive())
						m_setSpeed += std::max(fabs(m_setSpeed)*0.05, 1.0);
					if (KeyBindings::decreaseSpeed.IsActive())
						m_setSpeed -= std::max(fabs(m_setSpeed)*0.05, 1.0);
					if ( ((oldSpeed < 0.0) && (m_setSpeed >= 0.0)) ||
						 ((oldSpeed > 0.0) && (m_setSpeed <= 0.0)) ) {
						// flipped from going forward to backwards. make the speed 'stick' at zero
						// until the player lets go of the key and presses it again
						stickySpeedKey = true;
						m_setSpeed = 0;
					}
				}
			}

			if (KeyBindings::thrustForward.IsActive()) SetThrusterState(2, -1.0);
			if (KeyBindings::thrustBackwards.IsActive()) SetThrusterState(2, 1.0);
			if (KeyBindings::thrustUp.IsActive()) SetThrusterState(1, 1.0);
			if (KeyBindings::thrustDown.IsActive()) SetThrusterState(1, -1.0);
			if (KeyBindings::thrustLeft.IsActive()) SetThrusterState(0, -1.0);
			if (KeyBindings::thrustRight.IsActive()) SetThrusterState(0, 1.0);

			if (KeyBindings::fireLaser.IsActive() || (Pi::MouseButtonState(SDL_BUTTON_LEFT) && Pi::MouseButtonState(SDL_BUTTON_RIGHT))) {
					SetGunState(Pi::worldView->GetActiveWeapon(), 1);
			}

			if (KeyBindings::yawLeft.IsActive()) wantAngVel.y += 1.0;
			if (KeyBindings::yawRight.IsActive()) wantAngVel.y += -1.0;
			if (KeyBindings::pitchDown.IsActive()) wantAngVel.x += -1.0;
			if (KeyBindings::pitchUp.IsActive()) wantAngVel.x += 1.0;
			if (KeyBindings::rollLeft.IsActive()) wantAngVel.z += 1.0;
			if (KeyBindings::rollRight.IsActive()) wantAngVel.z -= 1.0;

			if (KeyBindings::fastRotate.IsActive())
				angThrustSoftness = 10.0;
		}

		vector3d changeVec;
		changeVec.x = KeyBindings::pitchAxis.GetValue();
		changeVec.y = KeyBindings::yawAxis.GetValue();
		changeVec.z = KeyBindings::rollAxis.GetValue();

		// Deadzone
		if(changeVec.LengthSqr() < m_joystickDeadzone)
			changeVec = vector3d(0.0);

		changeVec *= 2.0;
		wantAngVel += changeVec;

		double invTimeAccelRate = 1.0 / Pi::game->GetTimeAccelRate();
		for (int axis=0; axis<3; axis++)
			wantAngVel[axis] = Clamp(wantAngVel[axis], -invTimeAccelRate, invTimeAccelRate);
		
		if (m_mouseActive) AIFaceDirection(m_mouseDir);
		else AIModelCoordsMatchAngVel(wantAngVel, angThrustSoftness);
	}
}
Ejemplo n.º 13
0
void Player::StaticUpdate(const float timeStep)
{
	vector3d v;
	matrix4x4d m;

	Ship::StaticUpdate(timeStep);		// also calls autopilot AI

	if (GetFlightState() == Ship::FLYING) {
		switch (m_flightControlState) {
		case CONTROL_FIXSPEED:
			if (Pi::GetView() == Pi::worldView) PollControls(timeStep);
			if (IsAnyThrusterKeyDown()) break;
			GetRotMatrix(m);
			v = m * vector3d(0, 0, -m_setSpeed);
			if (m_setSpeedTarget) {
				v += m_setSpeedTarget->GetVelocityRelTo(GetFrame());
			}
			AIMatchVel(v);
			break;
		case CONTROL_MANUAL:
			if (Pi::GetView() == Pi::worldView) PollControls(timeStep);
			break;
		case CONTROL_AUTOPILOT:
			if (AIIsActive()) break;
			Pi::game->RequestTimeAccel(Game::TIMEACCEL_1X);
//			AIMatchVel(vector3d(0.0));			// just in case autopilot doesn't...
						// actually this breaks last timestep slightly in non-relative target cases
			AIMatchAngVelObjSpace(vector3d(0.0));
			if (GetFrame()->IsRotatingFrame()) SetFlightControlState(CONTROL_FIXSPEED);
			else SetFlightControlState(CONTROL_MANUAL);
			m_setSpeed = 0.0;
			break;
		}
	}
	else SetFlightControlState(CONTROL_MANUAL);
	
	/* This wank probably shouldn't be in Player... */
	/* Ship engine noise. less loud inside */
	float v_env = (Pi::worldView->GetCamType() == WorldView::CAM_EXTERNAL ? 1.0f : 0.5f) * Sound::GetSfxVolume();
	static Sound::Event sndev;
	float volBoth = 0.0f;
	volBoth += 0.5f*fabs(GetThrusterState().y);
	volBoth += 0.5f*fabs(GetThrusterState().z);
	
	float targetVol[2] = { volBoth, volBoth };
	if (GetThrusterState().x > 0.0)
		targetVol[0] += 0.5f*float(GetThrusterState().x);
	else targetVol[1] += -0.5f*float(GetThrusterState().x);

	targetVol[0] = v_env * Clamp(targetVol[0], 0.0f, 1.0f);
	targetVol[1] = v_env * Clamp(targetVol[1], 0.0f, 1.0f);
	float dv_dt[2] = { 4.0f, 4.0f };
	if (!sndev.VolumeAnimate(targetVol, dv_dt)) {
		sndev.Play("Thruster_large", 0.0f, 0.0f, Sound::OP_REPEAT);
		sndev.VolumeAnimate(targetVol, dv_dt);
	}
	float angthrust = 0.1f * v_env * float(Pi::player->GetAngThrusterState().Length());

	static Sound::Event angThrustSnd;
	if (!angThrustSnd.VolumeAnimate(angthrust, angthrust, 5.0f, 5.0f)) {
		angThrustSnd.Play("Thruster_Small", 0.0f, 0.0f, Sound::OP_REPEAT);
		angThrustSnd.VolumeAnimate(angthrust, angthrust, 5.0f, 5.0f);
	}
}
Ejemplo n.º 14
0
void Player::PollControls(const float timeStep)
{
	double time_accel = Pi::GetTimeAccel();
	double invTimeAccel = 1.0 / time_accel;
	static bool stickySpeedKey = false;

	if ((time_accel == 0) || GetDockedWith() || Pi::player->IsDead() ||
	    (GetFlightState() != FLYING)) {
		return;
	}

	// if flying 
	{
		ClearThrusterState();
		
		vector3d wantAngVel(0.0);

		// have to use this function. SDL mouse position event is bugged in windows
		int mouseMotion[2];
		SDL_GetRelativeMouseState (mouseMotion+0, mouseMotion+1);	// call to flush
		if (Pi::MouseButtonState(3))
		{
			matrix4x4d rot; GetRotMatrix(rot);
			if (!m_mouseActive) {
				m_mouseDir = vector3d(-rot[8],-rot[9],-rot[10]);	// in world space
				m_mouseX = m_mouseY = 0;
				m_mouseActive = true;
			}
			vector3d objDir = m_mouseDir * rot;

			m_mouseX += mouseMotion[0] * 0.002;
			double modx = clipmouse(objDir.x, m_mouseX);			
			m_mouseX -= modx;

			m_mouseY += mouseMotion[1] * 0.002;		// factor pixels => radians
			double mody = clipmouse(objDir.y, m_mouseY);
			m_mouseY -= mody;

			if(modx != 0.0 || mody != 0.0) {
				matrix4x4d mrot = matrix4x4d::RotateYMatrix(modx); mrot.RotateX(mody);
				m_mouseDir = (rot * (mrot * objDir)).Normalized();
			}
		}
		else m_mouseActive = false;
		
	
		if (m_flightControlState == CONTROL_FIXSPEED) {
			double oldSpeed = m_setSpeed;
			if (stickySpeedKey) {
				if (!(KeyBindings::increaseSpeed.IsActive() || KeyBindings::decreaseSpeed.IsActive())) {
					stickySpeedKey = false;
				}
			}
			
			if (!stickySpeedKey) {
				if (KeyBindings::increaseSpeed.IsActive()) m_setSpeed += std::max(m_setSpeed*0.05, 1.0);
				if (KeyBindings::decreaseSpeed.IsActive()) m_setSpeed -= std::max(m_setSpeed*0.05, 1.0);
				if ( ((oldSpeed < 0.0) && (m_setSpeed >= 0.0)) ||
				     ((oldSpeed > 0.0) && (m_setSpeed <= 0.0)) ) {
					// flipped from going forward to backwards. make the speed 'stick' at zero
					// until the player lets go of the key and presses it again
					stickySpeedKey = true;
					m_setSpeed = 0;
				}
			}
		}

		if (KeyBindings::thrustForward.IsActive()) SetThrusterState(2, -1.0);
		if (KeyBindings::thrustBackwards.IsActive()) SetThrusterState(2, 1.0);
		if (KeyBindings::thrustUp.IsActive()) SetThrusterState(1, 1.0);
		if (KeyBindings::thrustDown.IsActive()) SetThrusterState(1, -1.0);
		if (KeyBindings::thrustLeft.IsActive()) SetThrusterState(0, -1.0);
		if (KeyBindings::thrustRight.IsActive()) SetThrusterState(0, 1.0);
		
		SetGunState(0,0);
		SetGunState(1,0);
		if (KeyBindings::fireLaser.IsActive() || (Pi::MouseButtonState(1) && Pi::MouseButtonState(3))) {
				SetGunState(Pi::worldView->GetActiveWeapon(), 1);
		}

		if (KeyBindings::yawLeft.IsActive()) wantAngVel.y += 1.0;
		if (KeyBindings::yawRight.IsActive()) wantAngVel.y += -1.0;
		if (KeyBindings::pitchDown.IsActive()) wantAngVel.x += -1.0;
		if (KeyBindings::pitchUp.IsActive()) wantAngVel.x += 1.0;
		if (KeyBindings::rollLeft.IsActive()) wantAngVel.z += 1.0;
		if (KeyBindings::rollRight.IsActive()) wantAngVel.z -= 1.0;

		wantAngVel.x += 2 * KeyBindings::pitchAxis.GetValue();
		wantAngVel.y += 2 * KeyBindings::yawAxis.GetValue();
		wantAngVel.z += 2 * KeyBindings::rollAxis.GetValue();

		for (int axis=0; axis<3; axis++)
			wantAngVel[axis] = Clamp(wantAngVel[axis], -invTimeAccel, invTimeAccel);

//		matrix4x4d rot; GetRotMatrix(rot);
		const double angThrustSoftness = KeyBindings::fastRotate.IsActive() ? 10.0 : 50.0;
		
		if (m_mouseActive) AIFaceDirection(m_mouseDir);
		else AIModelCoordsMatchAngVel(wantAngVel, angThrustSoftness);
	}
}