hyperspace cloud analyzer. arrival clouds are not created yet so you can't follow ships

git-svn-id: https://pioneer.svn.sourceforge.net/svnroot/pioneer/trunk@475 e632f14b-6550-0410-b89e-a82653faca30
master
tompox 2009-11-04 15:06:36 +00:00
parent 0db47d2c3e
commit 347874217e
29 changed files with 327 additions and 77 deletions

BIN
icons/hypercloud_anal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -10,6 +10,7 @@
#include "Player.h"
#include "Projectile.h"
#include "Missile.h"
#include "HyperspaceCloud.h"
Body::Body()
{
@ -22,8 +23,6 @@ Body::Body()
Body::~Body()
{
// Do not call delete body. Call Space::KillBody(body).
assert(m_dead);
}
void Body::Save()
@ -59,6 +58,7 @@ void Body::Serialize()
case Object::MISSILE:
case Object::CARGOBODY:
case Object::PROJECTILE:
case Object::HYPERSPACECLOUD:
Save();
break;
default:
@ -92,6 +92,8 @@ Body *Body::Unserialize()
b = new Projectile(); break;
case Object::CARGOBODY:
b = new CargoBody(); break;
case Object::HYPERSPACECLOUD:
b = new HyperspaceCloud(); break;
default:
assert(0);
}

View File

@ -29,6 +29,7 @@ public:
virtual void SetFrame(Frame *f) { m_frame = f; }
// return true if to do collision response and apply damage
virtual bool OnCollision(Object *o, Uint32 flags, double relVel) { return false; }
// Attacker may be null
virtual bool OnDamage(Object *attacker, float kgDamage) { return false; }
virtual void OnHaveKilled(Body *guyWeKilled) {}
virtual void TimeStepUpdate(const float timeStep) {}
@ -36,8 +37,9 @@ public:
// StaticUpdate() is called. Good for special collision testing (Projectiles)
// as you can't test for collisions if different objects are on different 'steps'
virtual void StaticUpdate(const float timeStep) {}
// Override to clear any pointers you hold to the dying body.
virtual void NotifyDeath(const Body* const dyingBody) {}
// Note: Does not mean killed, just deleted.
// Override to clear any pointers you hold to the body
virtual void NotifyDeleted(const Body* const deletedBody) {}
vector3d GetVelocityRelativeTo(const Body *other) const;
vector3d GetVelocityRelativeTo(const Frame *f) const;
// for putting on planet surface, oriented +y up

View File

@ -162,6 +162,12 @@ const EquipType EquipType::types[Equip::TYPE_MAX] = {
Equip::SLOT_RADARMAPPER, {},
90000, 1, 1,
0, 3
},{
"Hypercloud Analyzer",
"Analyze hyperspace clouds to determine destination and time of arrival or departure.",
Equip::SLOT_HYPERCLOUD, {},
150000, 1, 1,
0, 3
},{
"Interplanetary Drive",0,
Equip::SLOT_ENGINE, {},

View File

@ -2,11 +2,11 @@
#define _EQUIPTYPE_H
namespace Equip {
enum Slot { SLOT_CARGO, SLOT_ENGINE, SLOT_LASER, SLOT_MISSILE, SLOT_ECM, SLOT_SCANNER, SLOT_RADARMAPPER, SLOT_MAX };
enum Slot { SLOT_CARGO, SLOT_ENGINE, SLOT_LASER, SLOT_MISSILE, SLOT_ECM, SLOT_SCANNER, SLOT_RADARMAPPER, SLOT_HYPERCLOUD, SLOT_MAX };
enum Type { NONE, HYDROGEN, LIQUID_OXYGEN, METAL_ORE, CARBON_ORE, METAL_ALLOYS, PLASTICS, FRUIT_AND_VEG, ANIMAL_MEAT, LIQUOR, GRAIN, TEXTILES, FERTILIZER, WATER, MEDICINES, CONSUMER_GOODS, COMPUTERS, ROBOTS, PRECIOUS_METALS, INDUSTRIAL_MACHINERY, FARM_MACHINERY, MINING_MACHINERY, AIR_PROCESSORS, HAND_WEAPONS, BATTLE_WEAPONS, NERVE_GAS, NARCOTICS,
MISSILE_UNGUIDED, MISSILE_GUIDED, MISSILE_SMART, MISSILE_NAVAL, ECM_BASIC, SCANNER, ECM_ADVANCED, SHIELD_GENERATOR,
RADAR_MAPPER,
RADAR_MAPPER, HYPERCLOUD_ANALYZER,
DRIVE_INTERPLANETARY, DRIVE_CLASS1, DRIVE_CLASS2, DRIVE_CLASS3, DRIVE_CLASS4, DRIVE_CLASS5, DRIVE_CLASS6, DRIVE_CLASS7,
PULSECANNON_1MW, PULSECANNON_DUAL_1MW, PULSECANNON_2MW, PULSECANNON_4MW, PULSECANNON_10MW, PULSECANNON_20MW, TYPE_MAX,
FIRST_COMMODITY=HYDROGEN, LAST_COMMODITY=NARCOTICS,

80
src/HyperspaceCloud.cpp Normal file
View File

@ -0,0 +1,80 @@
#include "libs.h"
#include "HyperspaceCloud.h"
#include "Pi.h"
#include "Ship.h"
#include "Serializer.h"
#include "Shader.h"
HyperspaceCloud::HyperspaceCloud(Ship *s, double dueDate)
{
m_ship = s;
m_pos = vector3d(0,0,0);
m_birthdate = Pi::GetGameTime();
m_due = dueDate;
}
HyperspaceCloud::HyperspaceCloud()
{
m_ship = 0;
m_pos = vector3d(0,0,0);
}
HyperspaceCloud::~HyperspaceCloud()
{
if (m_ship) delete m_ship;
}
vector3d HyperspaceCloud::GetPosition() const
{
return m_pos;
}
void HyperspaceCloud::SetPosition(vector3d p)
{
m_pos = p;
}
void HyperspaceCloud::Save()
{
using namespace Serializer::Write;
Body::Save();
wr_vector3d(m_pos);
wr_double(m_birthdate);
wr_double(m_due);
m_ship->Serialize();
}
void HyperspaceCloud::Load()
{
using namespace Serializer::Read;
Body::Load();
m_pos = rd_vector3d();
m_birthdate = rd_double();
m_due = rd_double();
m_ship = (Ship*)Body::Unserialize();
}
void HyperspaceCloud::PostLoadFixup()
{
m_ship->PostLoadFixup();
}
void HyperspaceCloud::Render(const Frame *a_camFrame)
{
Shader::EnableVertexProgram(Shader::VPROG_SIMPLE);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glPushMatrix();
vector3d fpos = GetPositionRelTo(a_camFrame);
glTranslatef((float)fpos.x, (float)fpos.y, (float)fpos.z);
glColor4f(1.0,1.0,1.0,0.5);
gluSphere(Pi::gluQuadric, 25.0, 20, 20);
glColor4f(.5,.5,1.0,0.5);
gluSphere(Pi::gluQuadric, 50.0, 20, 20);
glColor4f(0,0,1.0,0.5);
gluSphere(Pi::gluQuadric, 100.0, 20, 20);
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_LIGHTING);
Shader::DisableVertexProgram();
}

32
src/HyperspaceCloud.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef _HYPERSPACECLOUD_H
#define _HYPERSPACECLOUD_H
#include "Body.h"
class Frame;
class Ship;
class HyperspaceCloud: public Body {
public:
OBJDEF(HyperspaceCloud, Body, HYPERSPACECLOUD);
HyperspaceCloud(Ship *, double dateDue);
HyperspaceCloud();
virtual ~HyperspaceCloud();
virtual void SetPosition(vector3d p);
virtual vector3d GetPosition() const;
virtual double GetRadius() const { return 10.0; }
virtual void Render(const Frame *camFrame);
virtual void PostLoadFixup();
Ship *GetShip() { return m_ship; }
double GetDueDate() const { return m_due; }
protected:
virtual void Save();
virtual void Load();
private:
Ship *m_ship;
vector3d m_pos;
double m_birthdate;
double m_due;
};
#endif /* _HYPERSPACECLOUD_H */

View File

@ -13,7 +13,7 @@ include_HEADERS = Body.h Frame.h GenericSystemView.h glfreetype.h GuiButton.h Gu
NameGenerator.h perlin.h GeoSphere.h GuiBox.h ShipFlavour.h GuiTextLayout.h Mission.h pirates.h Polit.h \
CityOnPlanet.h Shader.h ShipCpanelMultiFuncDisplays.h Projectile.h Render.h Sound.h GuiRepeaterButton.h \
CommodityTradeWidget.h GenericChatForm.h PoliceChatForm.h SysLoc.h PersistSystemData.h GalacticView.h \
Galaxy.h GameMenuView.h GuiTextEntry.h Missile.h
Galaxy.h GameMenuView.h GuiTextEntry.h Missile.h HyperspaceCloud.h
libgui_a_SOURCES = GuiButton.cpp Gui.cpp GuiFixed.cpp GuiScreen.cpp GuiLabel.cpp GuiToolTip.cpp GuiToggleButton.cpp GuiRadioButton.cpp \
GuiRadioGroup.cpp GuiImageButton.cpp GuiImage.cpp GuiImageRadioButton.cpp GuiMultiStateImageButton.cpp GuiWidget.cpp \
@ -28,7 +28,7 @@ pioneer_SOURCES = main.cpp glfreetype.cpp Body.cpp Space.cpp Ship.cpp Player.cpp
EquipType.cpp CargoBody.cpp NameGenerator.cpp perlin.cpp GeoSphere.cpp Pi.cpp ShipFlavour.cpp \
Mission.cpp pirates.cpp Polit.cpp CityOnPlanet.cpp Shader.cpp ShipCpanelMultiFuncDisplays.cpp \
Projectile.cpp Render.cpp Sound.cpp CommodityTradeWidget.cpp GenericChatForm.cpp PoliceChatForm.cpp \
SysLoc.cpp GalacticView.cpp Galaxy.cpp GameMenuView.cpp Missile.cpp
SysLoc.cpp GalacticView.cpp Galaxy.cpp GameMenuView.cpp Missile.cpp HyperspaceCloud.cpp
pioneer_LDADD = sbre/libsbre.a collider/libcollider.a missions/libmissions.a libgui.a
sbreviewer_SOURCES = SbreViewer.cpp glfreetype.cpp ModelCollMeshData.cpp

View File

@ -81,12 +81,12 @@ void Missile::Explode()
Sfx::Add(this, Sfx::TYPE_EXPLOSION);
}
void Missile::NotifyDeath(const Body* const dyingBody)
void Missile::NotifyDeleted(const Body* const deletedBody)
{
if (m_owner == dyingBody) {
if (m_owner == deletedBody) {
Explode();
}
else if (m_target == dyingBody) {
else if (m_target == deletedBody) {
Explode();
}
}

View File

@ -13,7 +13,7 @@ public:
virtual ~Missile() {}
void TimeStepUpdate(const float timeStep);
bool OnDamage(Object *attacker, float kgDamage);
virtual void NotifyDeath(const Body* const dyingBody);
virtual void NotifyDeleted(const Body* const deletedBody);
virtual void PostLoadFixup();
void ECMAttack(int power_val);
protected:

View File

@ -3,13 +3,13 @@
class Object {
public:
enum Type { OBJECT, BODY, MODELBODY, DYNAMICBODY, SHIP, PLAYER, SPACESTATION, PLANET, STAR, CARGOBODY, CITYONPLANET, PROJECTILE, MISSILE };
virtual Type GetType() { return OBJECT; }
virtual bool IsType(Type c) { return GetType() == c; }
enum Type { OBJECT, BODY, MODELBODY, DYNAMICBODY, SHIP, PLAYER, SPACESTATION, PLANET, STAR, CARGOBODY, CITYONPLANET, PROJECTILE, MISSILE, HYPERSPACECLOUD };
virtual Type GetType() const { return OBJECT; }
virtual bool IsType(Type c) const { return GetType() == c; }
};
#define OBJDEF(__thisClass,__parentClass,__TYPE) \
virtual Object::Type GetType() { return Object::__TYPE; } \
virtual bool IsType(Type c) { \
virtual Object::Type GetType() const { return Object::__TYPE; } \
virtual bool IsType(Type c) const { \
if (__thisClass::GetType() == (c)) return true; \
else return __parentClass::IsType(c); }
#endif /* _OBJECT_H */

View File

@ -71,7 +71,7 @@ bool Pi::showDebugInfo;
int Pi::statSceneTris;
bool Pi::isGameStarted = false;
struct DetailLevel Pi::detail = { 1, 1 };
const float Pi::timeAccelRates[] = { 0.0, 1.0, 10.0, 100.0, 1000.0, 10000.0 };
const float Pi::timeAccelRates[] = { 0.0, 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0 };
const char * const Pi::combatRating[] = {
"Harmless",
"Mostly harmless",
@ -324,10 +324,15 @@ void Pi::HandleEvents()
ship->SetFrame(Pi::player->GetFrame());
ship->SetPosition(Pi::player->GetPosition()+100.0*dir);
ship->SetVelocity(Pi::player->GetVelocity());
ship->m_equipment.Add(Equip::DRIVE_CLASS1);
ship->m_equipment.Add(Equip::DRIVE_CLASS2);
ship->m_equipment.Add(Equip::RADAR_MAPPER);
ship->m_equipment.Add(Equip::SCANNER);
ship->m_equipment.Add(Equip::SHIELD_GENERATOR);
ship->m_equipment.Add(Equip::HYDROGEN);
ship->m_equipment.Add(Equip::HYDROGEN);
ship->m_equipment.Add(Equip::HYDROGEN);
ship->m_equipment.Add(Equip::HYDROGEN);
ship->m_equipment.Add(Equip::HYDROGEN);
Space::AddBody(ship);
}
}

View File

@ -41,7 +41,6 @@ void Player::Save()
}
wr_int(m_killCount);
wr_int(m_knownKillCount);
m_hyperspaceTarget.Serialize();
}
void Player::Load()
@ -65,7 +64,6 @@ void Player::Load()
m_killCount = 0;
m_knownKillCount = 0;
}
SBodyPath::Unserialize(&m_hyperspaceTarget);
}
void Player::OnHaveKilled(Body *guyWeKilled)
@ -91,12 +89,6 @@ void Player::TakeMission(Mission *m)
Pi::onPlayerMissionListChanged.emit();
}
void Player::SetHyperspaceTarget(const SBodyPath *path)
{
m_hyperspaceTarget = *path;
Pi::onPlayerChangeHyperspaceTarget.emit();
}
void Player::SetFlightControlState(enum FlightControlState s)
{
m_flightControlState = s;

View File

@ -22,8 +22,6 @@ public:
FlightControlState GetFlightControlState() const { return m_flightControlState; }
void SetFlightControlState(FlightControlState s);
float GetSetSpeed() const { return m_setSpeed; }
const SBodyPath *GetHyperspaceTarget() const { return &m_hyperspaceTarget; }
void SetHyperspaceTarget(const SBodyPath *path);
void TakeMission(Mission *);
const std::list<Mission*> &GetMissions() const { return m_missions; }
virtual bool OnDamage(Object *attacker, float kgDamage);
@ -40,7 +38,6 @@ private:
float m_setSpeed;
int m_killCount;
int m_knownKillCount; // updated on docking
SBodyPath m_hyperspaceTarget;
};
#endif /* _PLAYER_H */

View File

@ -55,6 +55,11 @@ void Projectile::SetPosition(vector3d p)
m_orient[14] = p.z;
}
void Projectile::NotifyDeleted(const Body* const deletedBody)
{
if (m_parent == deletedBody) m_parent = 0;
}
void Projectile::TimeStepUpdate(const float timeStep)
{
m_age += timeStep;

View File

@ -20,6 +20,7 @@ public:
virtual void Render(const Frame *camFrame);
void TimeStepUpdate(const float timeStep);
void StaticUpdate(const float timeStep);
virtual void NotifyDeleted(const Body* const deletedBody);
virtual void PostLoadFixup();
protected:

View File

@ -305,7 +305,8 @@ void SectorView::Update()
char buf[256];
SBodyPath sbody_path(m_secx, m_secy, m_selected);
int fuelRequired;
bool canJump = Pi::player->CanHyperspaceTo(&sbody_path, fuelRequired);
double dur;
bool canJump = Pi::player->CanHyperspaceTo(&sbody_path, fuelRequired, dur);
if (canJump) {
snprintf(buf, sizeof(buf), "Dist. %.2f light years (fuel required: %dt)", dist, fuelRequired);
} else if (fuelRequired) {

View File

@ -4,7 +4,7 @@
#include "Player.h"
#include "perlin.h"
void Ship::AIBodyHasDied(const Body* const body)
void Ship::AIBodyDeleted(const Body* const body)
{
for (std::list<AIInstruction>::iterator i = m_todo.begin(); i != m_todo.end(); ) {
switch ((*i).cmd) {
@ -107,6 +107,7 @@ bool Ship::AICmdKamikaze(const Ship *enemy)
return false;
}
#include "Space.h"
bool Ship::AICmdKill(const Ship *enemy)
{
SetGunState(0,0);
@ -124,7 +125,9 @@ bool Ship::AICmdKill(const Ship *enemy)
GetRotMatrix(rot);
const vector3d zaxis = vector3d(-rot[8], -rot[9], -rot[10]);
const float dot = vector3d::Dot(dir, vector3d(-rot[8], -rot[9], -rot[10]));
if (dot > 0.95f) SetGunState(0,1);
if (dot > 0.95f) {
SetGunState(0,1);
}
} else {
// if too close turn away!
AIFaceDirection(-dir);

View File

@ -48,6 +48,10 @@ void Ship::Save()
wr_float(m_launchLockTimeout);
wr_bool(m_testLanded);
wr_int((int)m_flightState);
m_hyperspace.dest.Serialize();
wr_float(m_hyperspace.countdown);
for (int i=0; i<ShipType::GUNMOUNT_MAX; i++) {
wr_int(m_gunState[i]);
wr_float(m_gunRecharge[i]);
@ -90,6 +94,10 @@ void Ship::Load()
m_launchLockTimeout = rd_float();
m_testLanded = rd_bool();
m_flightState = (FlightState) rd_int();
SBodyPath::Unserialize(&m_hyperspace.dest);
m_hyperspace.countdown = rd_float();
for (int i=0; i<ShipType::GUNMOUNT_MAX; i++) {
m_gunState[i] = rd_int();
if (IsOlderThan(3)) m_gunRecharge[i] = 0;
@ -158,6 +166,7 @@ Ship::Ship(ShipType::Type shipType): DynamicBody()
m_shipFlavour = ShipFlavour(shipType);
m_angThrusters[0] = m_angThrusters[1] = m_angThrusters[2] = 0;
m_equipment.InitSlotSizes(shipType);
m_hyperspace.countdown = 0;
for (int i=0; i<ShipType::GUNMOUNT_MAX; i++) {
m_gunState[i] = 0;
m_gunRecharge[i] = 0;
@ -169,6 +178,12 @@ Ship::Ship(ShipType::Type shipType): DynamicBody()
Init();
}
void Ship::SetHyperspaceTarget(const SBodyPath *path)
{
m_hyperspace.dest = *path;
if (this == (Ship*)Pi::player) Pi::onPlayerChangeHyperspaceTarget.emit();
}
float Ship::GetPercentHull() const
{
const ShipType &stype = GetShipType();
@ -208,7 +223,7 @@ bool Ship::OnDamage(Object *attacker, float kgDamage)
}
m_stats.hull_mass_left -= dam;
if (m_stats.hull_mass_left < 0) {
if (attacker->IsType(Object::BODY)) static_cast<Body*>(attacker)->OnHaveKilled(this);
if (attacker && attacker->IsType(Object::BODY)) static_cast<Body*>(attacker)->OnHaveKilled(this);
Space::KillBody(this);
Sfx::Add(this, Sfx::TYPE_EXPLOSION);
} else {
@ -301,17 +316,18 @@ static float distance_to_system(const SBodyPath *dest)
void Ship::UseHyperspaceFuel(const SBodyPath *dest)
{
int fuel_cost;
bool hscheck = CanHyperspaceTo(dest, fuel_cost);
double dur;
bool hscheck = CanHyperspaceTo(dest, fuel_cost, dur);
assert(hscheck);
m_equipment.Remove(Equip::HYDROGEN, fuel_cost);
}
bool Ship::CanHyperspaceTo(const SBodyPath *dest, int &fuelRequired)
bool Ship::CanHyperspaceTo(const SBodyPath *dest, int &outFuelRequired, double &outDurationSecs)
{
Equip::Type t = m_equipment.Get(Equip::SLOT_ENGINE);
float hyperclass = (float)EquipType::types[t].pval;
int fuel = m_equipment.Count(Equip::SLOT_CARGO, Equip::HYDROGEN);
fuelRequired = 0;
outFuelRequired = 0;
if (hyperclass == 0) return false;
float dist;
@ -322,17 +338,35 @@ bool Ship::CanHyperspaceTo(const SBodyPath *dest, int &fuelRequired)
}
this->CalcStats();
fuelRequired = (int)ceil(hyperclass*hyperclass*dist / m_stats.hyperspace_range_max);
if (fuelRequired > hyperclass*hyperclass) fuelRequired = hyperclass*hyperclass;
if (fuelRequired < 1) fuelRequired = 1;
outFuelRequired = (int)ceil(hyperclass*hyperclass*dist / m_stats.hyperspace_range_max);
if (outFuelRequired > hyperclass*hyperclass) outFuelRequired = hyperclass*hyperclass;
if (outFuelRequired < 1) outFuelRequired = 1;
if (dist > m_stats.hyperspace_range) {
fuelRequired = 0;
outFuelRequired = 0;
return false;
} else {
return fuelRequired <= fuel;
// 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.
outDurationSecs = (dist / m_stats.hyperspace_range) * 60.0 * 60.0 * 24.0 * 7.0;
return outFuelRequired <= fuel;
}
}
void Ship::TryHyperspaceTo(const SBodyPath *dest)
{
int fuelUsage;
double dur;
if (m_hyperspace.countdown) return;
if (!CanHyperspaceTo(dest, fuelUsage, dur)) return;
if (Pi::currentSystem->IsSystem(dest->sectorX, dest->sectorY, dest->systemIdx)) {
return;
}
m_hyperspace.countdown = 2.5;
m_hyperspace.dest = *dest;
}
float Ship::GetECMRechargeTime()
{
const Equip::Type t = m_equipment.Get(Equip::SLOT_ECM);
@ -553,15 +587,27 @@ void Ship::StaticUpdate(const float timeStep)
}
if (m_testLanded) TestLanded();
// After calling StartHyperspaceTo this Ship must not spawn objects
// holding references to it (eg missiles), as StartHyperspaceTo
// removes the ship from Space::bodies and so the missile will not
// have references to this cleared by NotifyDeleted()
if (m_hyperspace.countdown) {
m_hyperspace.countdown = MAX(m_hyperspace.countdown - timeStep, 0);
printf("Hyperspacing! %f\n", m_hyperspace.countdown);
if (m_hyperspace.countdown == 0) {
Space::StartHyperspaceTo(this, &m_hyperspace.dest);
}
}
}
void Ship::NotifyDeath(const Body* const dyingBody)
void Ship::NotifyDeleted(const Body* const deletedBody)
{
if(GetNavTarget() == dyingBody)
if(GetNavTarget() == deletedBody)
SetNavTarget(0);
if(GetCombatTarget() == dyingBody)
if(GetCombatTarget() == deletedBody)
SetCombatTarget(0);
AIBodyHasDied(dyingBody);
AIBodyDeleted(deletedBody);
}
const ShipType &Ship::GetShipType() const

View File

@ -7,10 +7,11 @@
#include "sbre/sbre.h"
#include "MarketAgent.h"
#include "ShipFlavour.h"
// only for SBodyPath
#include "StarSystem.h"
#include <list>
class SpaceStation;
struct SBodyPath;
struct shipstats_t {
int max_capacity;
@ -52,7 +53,7 @@ public:
void Blastoff();
virtual void TimeStepUpdate(const float timeStep);
virtual void StaticUpdate(const float timeStep);
virtual void NotifyDeath(const Body* const dyingBody);
virtual void NotifyDeleted(const Body* const deletedBody);
virtual bool OnCollision(Object *o, Uint32 flags, double relVel);
virtual bool OnDamage(Object *attacker, float kgDamage);
enum FlightState { FLYING, LANDED, DOCKING };
@ -60,7 +61,10 @@ public:
void SetFlightState(FlightState s) { m_flightState = s; }
float GetWheelState() const { return m_wheelState; }
bool Jettison(Equip::Type t);
bool CanHyperspaceTo(const SBodyPath *dest, int &fuelRequired);
const SBodyPath *GetHyperspaceTarget() const { return &m_hyperspace.dest; }
void SetHyperspaceTarget(const SBodyPath *path);
void TryHyperspaceTo(const SBodyPath *dest);
bool CanHyperspaceTo(const SBodyPath *dest, int &outFuelRequired, double &outDurationSecs);
void UseHyperspaceFuel(const SBodyPath *dest);
void UseECM();
void AIFaceDirection(const vector3d &dir);
@ -122,6 +126,13 @@ private:
Body* m_navTarget;
Body* m_combatTarget;
shipstats_t m_stats;
struct HyperspacingOut {
SBodyPath dest;
// > 0 means active
float countdown;
} m_hyperspace;
class AIInstruction {
public:
AICommand cmd;
@ -129,7 +140,7 @@ private:
AIInstruction(AICommand c, void *a): cmd(c), arg(a) {}
};
std::list<AIInstruction> m_todo;
void AIBodyHasDied(const Body* const body);
void AIBodyDeleted(const Body* const body);
bool AICmdKill(const Ship *);
bool AICmdKamikaze(const Ship *);
bool AICmdFlyTo(const Body *);

View File

@ -177,7 +177,7 @@ void ShipCpanel::Update()
}
// make requested but not selected icon blink
if (timeAccel != requested) {
m_timeAccelButtons[requested]->SetSelected(SDL_GetTicks() & 0x200);
m_timeAccelButtons[CLAMP(requested,0,5)]->SetSelected(SDL_GetTicks() & 0x200);
}
m_scanner->Update();

View File

@ -5,6 +5,8 @@
#include "Pi.h"
#include "Player.h"
#include "Missile.h"
#include "HyperspaceCloud.h"
#include "Sector.h"
#define SCANNER_SCALE 0.01f
#define SCANNER_YSHRINK 0.75f
@ -292,6 +294,27 @@ void UseEquipWidget::UseRadarMapper()
}
}
void UseEquipWidget::UseHypercloudAnalyzer()
{
Body *target = Pi::player->GetNavTarget();
if ((!target) || (!target->IsType(Object::HYPERSPACECLOUD))) {
Pi::cpan->MsgLog()->Message("", "Hypercloud Analyzer: You must target a hyperspace cloud");
return;
}
HyperspaceCloud *cloud = static_cast<HyperspaceCloud*>(target);
const SBodyPath *dest = cloud->GetShip()->GetHyperspaceTarget();
Sector s(dest->sectorX, dest->sectorY);
Pi::cpan->MsgLog()->Message("", stringf(512,
"Hyperspace departure cloud: Ship mass %dt\n"
"Destination: %s\n"
"Date due: %s\n",
cloud->GetShip()->CalcStats()->total_mass,
s.m_systems[dest->systemIdx].name.c_str(),
format_date(cloud->GetDueDate()).c_str()
));
}
void UseEquipWidget::UpdateEquip()
{
DeleteAllChildren();
@ -347,6 +370,15 @@ void UseEquipWidget::UpdateEquip()
Add(b, 64, 0);
}
}
{
const Equip::Type t = Pi::player->m_equipment.Get(Equip::SLOT_HYPERCLOUD);
if (t != Equip::NONE) {
Gui::Button *b = new Gui::ImageButton("icons/hypercloud_anal.png");
b->onClick.connect(sigc::mem_fun(this, &UseEquipWidget::UseHypercloudAnalyzer));
Add(b, 96, 0);
}
}
}
void UseEquipWidget::Update()

View File

@ -69,6 +69,7 @@ public:
private:
void UpdateEquip();
void UseRadarMapper();
void UseHypercloudAnalyzer();
enum { MAX_MISSILE_SLOTS = 8 };
sigc::connection m_onPlayerEquipChangedCon;

View File

@ -14,7 +14,7 @@ const ShipType ShipType::types[] = {
{ vector3f(0,-0.5,0), vector3f(0,0,-1) },
{ vector3f(0,0,0), vector3f(0,0,1) }
},
{ 20, 1, 1, 3, 1, 1, 1 },
{ 20, 1, 1, 3, 1, 1, 1, 1 },
20, 5, 4000000,
Equip::DRIVE_CLASS1,
}, {
@ -28,7 +28,7 @@ const ShipType ShipType::types[] = {
{ vector3f(0,-0.5,0), vector3f(0,0,-1) },
{ vector3f(0,-0.5,0), vector3f(0,0,1) }
},
{ 90, 1, 2, 8, 1, 1, 1 },
{ 90, 1, 2, 8, 1, 1, 1, 1 },
90, 20, 16000000,
Equip::DRIVE_CLASS3,
}, {
@ -41,7 +41,7 @@ const ShipType ShipType::types[] = {
{ vector3f(0,-0.5,0), vector3f(0,0,-1) },
{ vector3f(0,0,0), vector3f(0,0,1) }
},
{ 60, 1, 1, 2, 1, 1, 1 },
{ 60, 1, 1, 2, 1, 1, 1, 1 },
60, 15, 8700000,
Equip::DRIVE_CLASS2,
}, {
@ -53,7 +53,7 @@ const ShipType ShipType::types[] = {
{ vector3f(0,-0.5,0), vector3f(0,0,-1) },
{ vector3f(0,0,0), vector3f(0,0,1) }
},
{ 240, 1, 1, 4, 1, 1, 1 },
{ 240, 1, 1, 4, 1, 1, 1, 1 },
240, 55, 56000000,
Equip::DRIVE_CLASS4,
}, {
@ -65,7 +65,7 @@ const ShipType ShipType::types[] = {
{ vector3f(0,-0.5,0), vector3f(0,0,-1) },
{ vector3f(0,0,0), vector3f(0,0,1) }
},
{ 320, 1, 1, 6, 1, 1, 1 },
{ 320, 1, 1, 6, 1, 1, 1, 1 },
320, 80, 35000000,
Equip::DRIVE_CLASS5,
}, {
@ -77,7 +77,7 @@ const ShipType ShipType::types[] = {
{ vector3f(0,-0.5,0), vector3f(0,0,-1) },
{ vector3f(0,0,0), vector3f(0,0,1) }
},
{ 500, 1, 2, 4, 1, 1, 1 },
{ 500, 1, 2, 4, 1, 1, 1, 1 },
500, 125, 55000000,
Equip::DRIVE_CLASS6,
}, {

View File

@ -16,6 +16,7 @@
#include "pirates.h"
#include "Sfx.h"
#include "Missile.h"
#include "HyperspaceCloud.h"
namespace Space {
@ -29,6 +30,7 @@ static void ApplyGravity();
static std::list<Body*> corpses;
static SBodyPath *hyperspacingTo;
static float hyperspaceAnim;
static double hyperspaceEndTime;
void Init()
{
@ -101,6 +103,7 @@ void Serialize()
wr_byte(1);
hyperspacingTo->Serialize();
wr_float(hyperspaceAnim);
wr_double(hyperspaceEndTime);
}
}
@ -121,6 +124,7 @@ void Unserialize()
hyperspacingTo = new SBodyPath;
SBodyPath::Unserialize(hyperspacingTo);
hyperspaceAnim = rd_float();
hyperspaceEndTime = rd_double();
}
// bodies with references to others must fix these up
Serializer::IndexBodies();
@ -566,11 +570,16 @@ void ApplyGravity()
void TimeStep(float step)
{
if (hyperspacingTo) {
Pi::RequestTimeAccel(6);
hyperspaceAnim += step;
if (hyperspaceAnim > 1.0) {
if (Pi::GetGameTime() > hyperspaceEndTime) {
DoHyperspaceTo(0);
Pi::RequestTimeAccel(1);
hyperspaceAnim = 0;
}
// don't take a physics step at this mental time accel
return;
}
ApplyGravity();
@ -595,7 +604,7 @@ void PruneCorpses()
{
for (bodiesIter_t corpse = corpses.begin(); corpse != corpses.end(); ++corpse) {
for (bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i)
(*i)->NotifyDeath(*corpse);
(*i)->NotifyDeleted(*corpse);
bodies.remove(*corpse);
delete *corpse;
}
@ -607,22 +616,46 @@ static bool jumped_within_same_system;
/*
* Called during play to initiate hyperspace sequence.
*/
void StartHyperspaceTo(const SBodyPath *dest)
void StartHyperspaceTo(Ship *ship, const SBodyPath *dest)
{
int fuelUsage;
if (!Pi::player->CanHyperspaceTo(dest, fuelUsage)) return;
double duration;
if (!ship->CanHyperspaceTo(dest, fuelUsage, duration)) return;
if (Pi::currentSystem->IsSystem(dest->sectorX, dest->sectorY, dest->systemIdx)) {
return;
}
Space::Clear();
Pi::player->UseHyperspaceFuel(dest);
Pi::player->DisableBodyOnly();
if (!hyperspacingTo) hyperspacingTo = new SBodyPath;
*hyperspacingTo = *dest;
hyperspaceAnim = 0.0f;
printf("Started hyperspacing...\n");
ship->UseHyperspaceFuel(dest);
ship->DisableBodyOnly();
if (Pi::player == ship) {
Space::Clear();
if (!hyperspacingTo) hyperspacingTo = new SBodyPath;
*hyperspacingTo = *dest;
hyperspaceAnim = 0.0f;
hyperspaceEndTime = Pi::GetGameTime() + duration;
printf("Started hyperspacing...\n");
} else {
HyperspaceCloud *cloud = new HyperspaceCloud(ship, Pi::GetGameTime() + duration);
cloud->SetFrame(ship->GetFrame());
cloud->SetPosition(ship->GetPosition());
// need to swap ship out of bodies list, replacing it with
// cloud
for (bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) {
if (*i == ship) {
*i = cloud;
break;
}
}
// Hyperspacing ship must drop references to all other bodies,
// and they must all drop references to it.
// make other objects drop their references to this dude
for (bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) {
if (*i != cloud) {
(*i)->NotifyDeleted(ship);
ship->NotifyDeleted(*i);
}
}
}
}
/*

View File

@ -26,7 +26,7 @@ namespace Space {
extern void DoECM(const Frame *f, const vector3d &pos, int power_val);
extern float GetHyperspaceAnim();
extern void Render(const Frame *cam_frame);
extern void StartHyperspaceTo(const SBodyPath *);
extern void StartHyperspaceTo(Ship *s, const SBodyPath *);
extern void DoHyperspaceTo(const SBodyPath *);
// make sure SBody* is in Pi::currentSystem
extern Frame *GetFrameWithSBody(const SBody *b);

View File

@ -728,10 +728,10 @@ bool SpaceStation::OnCollision(Object *b, Uint32 flags, double relVel)
}
}
void SpaceStation::NotifyDeath(const Body* const dyingBody)
void SpaceStation::NotifyDeleted(const Body* const deletedBody)
{
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
if (m_shipDocking[i].ship == dyingBody) {
if (m_shipDocking[i].ship == deletedBody) {
m_shipDocking[i].ship = 0;
}
}

View File

@ -56,7 +56,7 @@ public:
// does not dealloc
bool BBRemoveMission(Mission *m);
virtual void PostLoadFixup();
virtual void NotifyDeath(const Body* const dyingBody);
virtual void NotifyDeleted(const Body* const deletedBody);
void PositionDockedShip(Ship *ship, int port);
sigc::signal<void> onShipsForSaleChanged;
sigc::signal<void> onBulletinBoardChanged;

View File

@ -208,7 +208,7 @@ void WorldView::OnClickBlastoff()
void WorldView::OnClickHyperspace()
{
const SBodyPath *path = Pi::player->GetHyperspaceTarget();
Space::StartHyperspaceTo(path);
Pi::player->TryHyperspaceTo(path);
}
void WorldView::DrawBgStars()
@ -256,7 +256,7 @@ void WorldView::DrawBgStars()
vtx[i*12+5] = s_bgstar[i].b;
vector3d v(s_bgstar[i].x, s_bgstar[i].y, s_bgstar[i].z);
v += pz*hyperspaceAnim*200.0;
v += pz*hyperspaceAnim*0.001;
vtx[i*12+6] = v.x;
vtx[i*12+7] = v.y;
@ -510,7 +510,8 @@ void WorldView::OnChangeHyperspaceTarget()
delete system;
int fuelReqd;
if (Pi::player->CanHyperspaceTo(path, fuelReqd)) m_hyperspaceButton->Show();
double dur;
if (Pi::player->CanHyperspaceTo(path, fuelReqd, dur)) m_hyperspaceButton->Show();
else m_hyperspaceButton->Hide();
}