2008-06-24 03:17:31 -07:00
|
|
|
#include "SpaceStation.h"
|
|
|
|
#include "Ship.h"
|
2009-07-18 07:09:31 -07:00
|
|
|
#include "Planet.h"
|
2008-09-07 16:32:16 -07:00
|
|
|
#include "gameconsts.h"
|
2008-09-18 19:23:48 -07:00
|
|
|
#include "StarSystem.h"
|
|
|
|
#include "Serializer.h"
|
2008-12-27 17:02:45 -08:00
|
|
|
#include "Frame.h"
|
2008-12-05 14:02:43 -08:00
|
|
|
#include "Pi.h"
|
2009-06-29 15:12:48 -07:00
|
|
|
#include "Mission.h"
|
2009-07-25 07:23:05 -07:00
|
|
|
#include "CityOnPlanet.h"
|
2009-07-28 08:36:37 -07:00
|
|
|
#include "Shader.h"
|
2009-08-07 07:34:14 -07:00
|
|
|
#include "Player.h"
|
2009-10-08 16:49:43 -07:00
|
|
|
#include "Polit.h"
|
2010-01-12 07:21:56 -08:00
|
|
|
#include "LmrModel.h"
|
2008-06-24 03:17:31 -07:00
|
|
|
|
2010-01-31 08:18:37 -08:00
|
|
|
|
|
|
|
|
2008-09-07 16:32:16 -07:00
|
|
|
struct SpaceStationType {
|
2010-01-17 12:25:52 -08:00
|
|
|
LmrModel *model;
|
|
|
|
const char *modelName;
|
2010-01-17 13:22:09 -08:00
|
|
|
float angVel;
|
2010-01-17 12:25:52 -08:00
|
|
|
enum DOCKMETHOD { SURFACE, ORBITAL } dockMethod;
|
2010-01-31 08:18:37 -08:00
|
|
|
int numDockingPorts;
|
|
|
|
int numDockingStages;
|
|
|
|
int numUndockStages;
|
|
|
|
struct positionOrient_t {
|
|
|
|
vector3d pos;
|
|
|
|
vector3d xaxis;
|
|
|
|
vector3d yaxis;
|
|
|
|
};
|
|
|
|
float *dockAnimStageDuration;
|
|
|
|
float *undockAnimStageDuration;
|
|
|
|
|
|
|
|
void _ReadStageDurations(const char *key, int *outNumStages, float **durationArray) {
|
|
|
|
lua_State *L = LmrGetLuaState();
|
|
|
|
model->PushAttributeToStack(key);
|
|
|
|
assert(lua_istable(L, -1));
|
|
|
|
|
|
|
|
int num = lua_objlen(L, -1);
|
|
|
|
*outNumStages = num;
|
|
|
|
if (num == 0) {
|
|
|
|
*durationArray = 0;
|
|
|
|
} else {
|
|
|
|
*durationArray = new float[num];
|
|
|
|
for (int i=1; i<=num; i++) {
|
|
|
|
lua_pushinteger(L, i);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
(*durationArray)[i-1] = lua_tonumber(L, -1);
|
|
|
|
printf("%f\n", (*durationArray)[i-1]);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
// read from lua model definition
|
|
|
|
void ReadStageDurations() {
|
|
|
|
_ReadStageDurations("dock_anim_stage_duration", &numDockingStages, &dockAnimStageDuration);
|
|
|
|
_ReadStageDurations("undock_anim_stage_duration", &numUndockStages, &undockAnimStageDuration);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetDockAnimPositionOrient(int stage, float t, const vector3d &from, positionOrient_t &outPosOrient)
|
|
|
|
{
|
|
|
|
lua_State *L = LmrGetLuaState();
|
|
|
|
// It's a function of form function(stage, t, from)
|
|
|
|
model->PushAttributeToStack("ship_dock_anim");
|
|
|
|
if (!lua_isfunction(L, -1)) {
|
|
|
|
fprintf(stderr, "Error: Spacestation model %s needs ship_dock_anim method\n", model->GetName());
|
|
|
|
Pi::Quit();
|
|
|
|
}
|
|
|
|
lua_pushinteger(L, stage);
|
|
|
|
lua_pushnumber(L, (double)t);
|
|
|
|
vector3f *_from = MyLuaVec::pushVec(L);
|
|
|
|
*_from = vector3f(from);
|
|
|
|
lua_call(L, 3, 1);
|
|
|
|
assert(lua_istable(L, -1));
|
|
|
|
|
|
|
|
lua_pushinteger(L, 1);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
outPosOrient.pos = vector3f(*MyLuaVec::checkVec(L, -1));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
lua_pushinteger(L, 2);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
outPosOrient.xaxis = vector3f(*MyLuaVec::checkVec(L, -1));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
lua_pushinteger(L, 3);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
outPosOrient.yaxis = vector3f(*MyLuaVec::checkVec(L, -1));
|
|
|
|
lua_pop(L, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-07 16:32:16 -07:00
|
|
|
};
|
|
|
|
|
2010-01-17 12:25:52 -08:00
|
|
|
static bool stationTypesInitted = false;
|
|
|
|
static std::vector<SpaceStationType> surfaceStationTypes;
|
|
|
|
static std::vector<SpaceStationType> orbitalStationTypes;
|
|
|
|
|
|
|
|
/* Must be called after LmrModel init is called */
|
|
|
|
void SpaceStation::Init()
|
|
|
|
{
|
|
|
|
if (stationTypesInitted) return;
|
|
|
|
stationTypesInitted = true;
|
|
|
|
for (int is_orbital=0; is_orbital<2; is_orbital++) {
|
|
|
|
std::vector<LmrModel*> models;
|
|
|
|
if (is_orbital) LmrGetModelsWithTag("orbital_station", models);
|
|
|
|
else LmrGetModelsWithTag("surface_station", models);
|
|
|
|
|
|
|
|
for (std::vector<LmrModel*>::iterator i = models.begin();
|
|
|
|
i != models.end(); ++i) {
|
|
|
|
SpaceStationType t;
|
|
|
|
t.modelName = (*i)->GetName();
|
2010-01-31 08:18:37 -08:00
|
|
|
t.model = LmrLookupModelByName(t.modelName);
|
2010-01-17 12:25:52 -08:00
|
|
|
t.dockMethod = (SpaceStationType::DOCKMETHOD) is_orbital;
|
2010-01-31 08:18:37 -08:00
|
|
|
t.numDockingPorts = (*i)->GetIntAttribute("num_docking_ports");
|
|
|
|
t.ReadStageDurations();
|
|
|
|
printf("%s: %d docking ports\n", t.modelName, t.numDockingPorts);
|
2010-01-17 13:22:09 -08:00
|
|
|
if (is_orbital) {
|
|
|
|
t.angVel = (*i)->GetFloatAttribute("angular_velocity");
|
|
|
|
orbitalStationTypes.push_back(t);
|
|
|
|
}
|
2010-01-17 12:25:52 -08:00
|
|
|
else surfaceStationTypes.push_back(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-07-02 04:44:19 -07:00
|
|
|
|
2010-01-17 13:22:09 -08:00
|
|
|
float SpaceStation::GetDesiredAngVel() const
|
|
|
|
{
|
|
|
|
return m_type->angVel;
|
|
|
|
}
|
|
|
|
|
2008-09-18 19:23:48 -07:00
|
|
|
void SpaceStation::Save()
|
|
|
|
{
|
|
|
|
using namespace Serializer::Write;
|
|
|
|
ModelBody::Save();
|
2008-12-18 09:35:25 -08:00
|
|
|
MarketAgent::Save();
|
2008-12-05 14:02:43 -08:00
|
|
|
for (int i=0; i<Equip::TYPE_MAX; i++) {
|
|
|
|
wr_int((int)m_equipmentStock[i]);
|
|
|
|
}
|
2009-06-22 06:02:59 -07:00
|
|
|
// save shipyard
|
|
|
|
wr_int(m_shipsOnSale.size());
|
|
|
|
for (std::vector<ShipFlavour>::iterator i = m_shipsOnSale.begin();
|
|
|
|
i != m_shipsOnSale.end(); ++i) {
|
|
|
|
(*i).Save();
|
|
|
|
}
|
2009-06-29 15:12:48 -07:00
|
|
|
// save bb missions
|
|
|
|
wr_int(m_bbmissions.size());
|
|
|
|
for (std::vector<Mission*>::iterator i = m_bbmissions.begin();
|
|
|
|
i != m_bbmissions.end(); ++i) {
|
|
|
|
(*i)->Save();
|
|
|
|
}
|
2009-08-02 05:40:09 -07:00
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
|
|
|
wr_int(Serializer::LookupBody(m_shipDocking[i].ship));
|
|
|
|
wr_int(m_shipDocking[i].stage);
|
|
|
|
wr_float(m_shipDocking[i].stagePos);
|
|
|
|
wr_vector3d(m_shipDocking[i].from);
|
2009-08-03 04:16:31 -07:00
|
|
|
|
|
|
|
wr_float(m_openAnimState[i]);
|
|
|
|
wr_float(m_dockAnimState[i]);
|
2009-08-02 05:40:09 -07:00
|
|
|
}
|
2009-06-22 06:02:59 -07:00
|
|
|
wr_double(m_lastUpdatedShipyard);
|
2009-07-02 04:39:14 -07:00
|
|
|
wr_int(Serializer::LookupSystemBody(m_sbody));
|
2008-09-18 19:23:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void SpaceStation::Load()
|
|
|
|
{
|
|
|
|
using namespace Serializer::Read;
|
|
|
|
ModelBody::Load();
|
2008-12-18 09:35:25 -08:00
|
|
|
MarketAgent::Load();
|
2010-01-17 12:25:52 -08:00
|
|
|
if (IsOlderThan(11)) rd_int();
|
2008-09-18 19:23:48 -07:00
|
|
|
m_numPorts = 0;
|
2008-12-05 14:02:43 -08:00
|
|
|
for (int i=0; i<Equip::TYPE_MAX; i++) {
|
|
|
|
m_equipmentStock[i] = static_cast<Equip::Type>(rd_int());
|
|
|
|
}
|
2009-06-22 06:02:59 -07:00
|
|
|
// load shityard
|
|
|
|
int numShipsForSale = rd_int();
|
|
|
|
for (int i=0; i<numShipsForSale; i++) {
|
|
|
|
ShipFlavour s;
|
|
|
|
s.Load();
|
|
|
|
m_shipsOnSale.push_back(s);
|
|
|
|
}
|
2009-06-29 15:12:48 -07:00
|
|
|
// load bbmissions
|
|
|
|
int numBBMissions = rd_int();
|
|
|
|
for (int i=0; i<numBBMissions; i++) {
|
|
|
|
Mission *m = Mission::Load();
|
|
|
|
m_bbmissions.push_back(m);
|
|
|
|
}
|
2009-08-02 05:40:09 -07:00
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
|
|
|
m_shipDocking[i].ship = (Ship*)rd_int();
|
|
|
|
m_shipDocking[i].stage = rd_int();
|
|
|
|
m_shipDocking[i].stagePos = rd_float();
|
|
|
|
m_shipDocking[i].from = rd_vector3d();
|
2009-08-03 04:16:31 -07:00
|
|
|
|
|
|
|
m_openAnimState[i] = rd_float();
|
|
|
|
m_dockAnimState[i] = rd_float();
|
2009-08-02 05:40:09 -07:00
|
|
|
}
|
2009-06-22 06:02:59 -07:00
|
|
|
m_lastUpdatedShipyard = rd_double();
|
2009-07-02 04:39:14 -07:00
|
|
|
m_sbody = Serializer::LookupSystemBody(rd_int());
|
2010-01-17 12:25:52 -08:00
|
|
|
InitStation();
|
2008-09-18 19:23:48 -07:00
|
|
|
}
|
|
|
|
|
2009-08-02 05:40:09 -07:00
|
|
|
void SpaceStation::PostLoadFixup()
|
|
|
|
{
|
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
|
|
|
m_shipDocking[i].ship = static_cast<Ship*>(Serializer::LookupBody((size_t)m_shipDocking[i].ship));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-18 06:57:04 -08:00
|
|
|
double SpaceStation::GetBoundingRadius() const
|
|
|
|
{
|
|
|
|
return ModelBody::GetBoundingRadius() + CITY_ON_PLANET_RADIUS;
|
|
|
|
}
|
|
|
|
|
2009-07-02 04:39:14 -07:00
|
|
|
SpaceStation::SpaceStation(const SBody *sbody): ModelBody()
|
2008-06-24 03:17:31 -07:00
|
|
|
{
|
2009-07-02 04:39:14 -07:00
|
|
|
m_sbody = sbody;
|
2008-09-10 07:15:20 -07:00
|
|
|
m_numPorts = 0;
|
2009-06-22 06:02:59 -07:00
|
|
|
m_lastUpdatedShipyard = 0;
|
2008-12-05 14:02:43 -08:00
|
|
|
for (int i=1; i<Equip::TYPE_MAX; i++) {
|
2009-09-29 06:58:32 -07:00
|
|
|
if (EquipType::types[i].slot == Equip::SLOT_CARGO) {
|
|
|
|
m_equipmentStock[i] = Pi::rng.Int32(0,100) * Pi::rng.Int32(1,100);
|
|
|
|
} else {
|
2009-11-01 06:04:17 -08:00
|
|
|
if (EquipType::types[i].techLevel <= Pi::currentSystem->m_techlevel)
|
|
|
|
m_equipmentStock[i] = Pi::rng.Int32(0,100);
|
2009-09-29 06:58:32 -07:00
|
|
|
}
|
2008-12-05 14:02:43 -08:00
|
|
|
}
|
2009-08-03 04:16:31 -07:00
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
|
|
|
m_shipDocking[i].ship = 0;
|
|
|
|
m_openAnimState[i] = 0;
|
|
|
|
m_dockAnimState[i] = 0;
|
|
|
|
}
|
2008-12-29 12:51:06 -08:00
|
|
|
SetMoney(1000000000);
|
2010-01-17 12:25:52 -08:00
|
|
|
InitStation();
|
2008-09-18 19:23:48 -07:00
|
|
|
}
|
|
|
|
|
2009-08-02 05:40:09 -07:00
|
|
|
/*
|
|
|
|
* So, positionOrient_t things for docking animations are stored in the model
|
|
|
|
* as two triangles with geomflag 0x8000+i (0x8010+i for stage2)
|
|
|
|
* tri(position, zerovec, zerovec)
|
|
|
|
* tri(zerovec, xaxis, yaxis)
|
|
|
|
* Since positionOrient triangles in subobjects will be scaled and translated,
|
|
|
|
* the xaxis and yaxis normals must be un-translated (xaxis minus translated
|
|
|
|
* zerovec), and re-normalized.
|
|
|
|
*/
|
|
|
|
static void SetPositionOrientFromTris(const vector3d v[6], SpaceStation::positionOrient_t &outOrient)
|
|
|
|
{
|
|
|
|
outOrient.pos = v[0];
|
|
|
|
outOrient.xaxis = (v[4] - v[1]).Normalized();
|
2010-01-30 10:56:37 -08:00
|
|
|
outOrient.yaxis = (v[5] - v[1]).Normalized();
|
2009-08-02 05:40:09 -07:00
|
|
|
}
|
|
|
|
|
2010-01-17 12:25:52 -08:00
|
|
|
void SpaceStation::InitStation()
|
2008-09-18 19:23:48 -07:00
|
|
|
{
|
2009-07-27 04:28:05 -07:00
|
|
|
m_adjacentCity = 0;
|
2010-01-17 12:25:52 -08:00
|
|
|
MTRand rand(m_sbody->seed);
|
|
|
|
if (m_sbody->type == SBody::TYPE_STARPORT_ORBITAL) {
|
|
|
|
m_type = &orbitalStationTypes[ rand.Int32(orbitalStationTypes.size()) ];
|
|
|
|
} else {
|
|
|
|
m_type = &surfaceStationTypes[ rand.Int32(surfaceStationTypes.size()) ];
|
|
|
|
}
|
2010-01-18 09:58:57 -08:00
|
|
|
GetLmrObjParams().argFloats[6] = 1.0f;
|
|
|
|
GetLmrObjParams().argFloats[14] = 1.0f;
|
|
|
|
GetLmrObjParams().argFloats[18] = 1.0f;
|
2010-01-17 12:25:52 -08:00
|
|
|
SetModel(m_type->modelName, true);
|
2010-01-12 07:21:56 -08:00
|
|
|
LmrCollMesh *mesh = GetLmrCollMesh();
|
2009-08-01 10:23:51 -07:00
|
|
|
int i=0;
|
2009-08-02 05:40:09 -07:00
|
|
|
for (i=0; i<MAX_DOCKING_PORTS; i++) {
|
|
|
|
port[i].exists = false;
|
|
|
|
port_s2[i].exists = false;
|
|
|
|
}
|
|
|
|
vector3d v[6];
|
|
|
|
for (i=0; i<MAX_DOCKING_PORTS; i++) {
|
2010-01-12 07:21:56 -08:00
|
|
|
if (mesh->GetTrisWithGeomflag(0x8000+i, 2, v) != 2) break;
|
2009-08-01 10:23:51 -07:00
|
|
|
// 0x8000+i tri gives position, xaxis, yaxis of docking port surface
|
2009-08-02 05:40:09 -07:00
|
|
|
port[i].exists = true;
|
|
|
|
SetPositionOrientFromTris(v, port[i]);
|
2009-08-06 08:13:48 -07:00
|
|
|
/*printf("%p port %d, %f,%f,%f, %f,%f,%f\n", this, i,
|
2009-08-02 05:40:09 -07:00
|
|
|
port[i].xaxis.x,
|
|
|
|
port[i].xaxis.y,
|
|
|
|
port[i].xaxis.z,
|
2010-01-30 10:56:37 -08:00
|
|
|
port[i].yaxis.x,
|
|
|
|
port[i].yaxis.y,
|
|
|
|
port[i].yaxis.z);*/
|
2010-01-12 07:21:56 -08:00
|
|
|
if (mesh->GetTrisWithGeomflag(0x8010+i, 2, v) != 2) continue;
|
2009-08-02 05:40:09 -07:00
|
|
|
port_s2[i].exists = true;
|
|
|
|
SetPositionOrientFromTris(v, port_s2[i]);
|
2010-01-12 07:21:56 -08:00
|
|
|
assert(mesh->GetTrisWithGeomflag(0x8020+i, 2, v)==2);
|
2009-08-07 07:34:14 -07:00
|
|
|
port_s3[i].exists = true;
|
|
|
|
SetPositionOrientFromTris(v, port_s3[i]);
|
2008-07-13 04:29:37 -07:00
|
|
|
}
|
2009-08-01 10:23:51 -07:00
|
|
|
m_numPorts = i;
|
|
|
|
|
|
|
|
assert(m_numPorts > 0);
|
2008-06-24 03:17:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
SpaceStation::~SpaceStation()
|
|
|
|
{
|
2009-06-29 15:12:48 -07:00
|
|
|
for (std::vector<Mission*>::iterator i = m_bbmissions.begin();
|
|
|
|
i != m_bbmissions.end(); ++i) {
|
|
|
|
delete *i;
|
|
|
|
}
|
2009-07-27 04:28:05 -07:00
|
|
|
if (m_adjacentCity) delete m_adjacentCity;
|
2008-06-24 03:17:31 -07:00
|
|
|
}
|
|
|
|
|
2009-06-22 09:44:17 -07:00
|
|
|
void SpaceStation::ReplaceShipOnSale(int idx, const ShipFlavour *with)
|
|
|
|
{
|
|
|
|
m_shipsOnSale[idx] = *with;
|
|
|
|
onShipsForSaleChanged.emit();
|
|
|
|
}
|
|
|
|
|
2009-06-22 06:02:59 -07:00
|
|
|
void SpaceStation::UpdateShipyard()
|
|
|
|
{
|
|
|
|
if (m_shipsOnSale.size() == 0) {
|
|
|
|
// fill shipyard
|
|
|
|
for (int i=Pi::rng.Int32(20); i; i--) {
|
|
|
|
ShipFlavour s;
|
|
|
|
ShipFlavour::MakeTrulyRandom(s);
|
|
|
|
m_shipsOnSale.push_back(s);
|
|
|
|
}
|
|
|
|
} else if (Pi::rng.Int32(2)) {
|
|
|
|
// add one
|
|
|
|
ShipFlavour s;
|
|
|
|
ShipFlavour::MakeTrulyRandom(s);
|
|
|
|
m_shipsOnSale.push_back(s);
|
|
|
|
} else {
|
|
|
|
// remove one
|
|
|
|
int pos = Pi::rng.Int32(m_shipsOnSale.size());
|
|
|
|
m_shipsOnSale.erase(m_shipsOnSale.begin() + pos);
|
|
|
|
}
|
|
|
|
onShipsForSaleChanged.emit();
|
|
|
|
}
|
|
|
|
|
2009-07-01 07:43:00 -07:00
|
|
|
/* does not dealloc */
|
|
|
|
bool SpaceStation::BBRemoveMission(Mission *m)
|
|
|
|
{
|
|
|
|
for (int i=m_bbmissions.size()-1; i>=0; i--) {
|
|
|
|
if (m_bbmissions[i] == m) {
|
|
|
|
m_bbmissions.erase(m_bbmissions.begin() + i);
|
|
|
|
onBulletinBoardChanged.emit();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-06-29 15:12:48 -07:00
|
|
|
void SpaceStation::UpdateBB()
|
|
|
|
{
|
|
|
|
if (m_bbmissions.size() == 0) {
|
|
|
|
// fill bb
|
|
|
|
for (int i=Pi::rng.Int32(20); i; i--) {
|
2009-07-01 07:43:00 -07:00
|
|
|
try {
|
|
|
|
Mission *m = Mission::GenerateRandom();
|
|
|
|
m_bbmissions.push_back(m);
|
|
|
|
} catch (CouldNotMakeMissionException) {
|
|
|
|
|
|
|
|
}
|
2009-06-29 15:12:48 -07:00
|
|
|
}
|
|
|
|
} else if (Pi::rng.Int32(2)) {
|
|
|
|
// add one
|
2009-07-01 07:43:00 -07:00
|
|
|
try {
|
|
|
|
Mission *m = Mission::GenerateRandom();
|
|
|
|
m_bbmissions.push_back(m);
|
|
|
|
} catch (CouldNotMakeMissionException) {
|
|
|
|
|
|
|
|
}
|
2009-06-29 15:12:48 -07:00
|
|
|
} else {
|
|
|
|
// remove one
|
|
|
|
int pos = Pi::rng.Int32(m_bbmissions.size());
|
2009-07-01 07:43:00 -07:00
|
|
|
delete m_bbmissions[pos];
|
2009-06-29 15:12:48 -07:00
|
|
|
m_bbmissions.erase(m_bbmissions.begin() + pos);
|
|
|
|
}
|
|
|
|
onBulletinBoardChanged.emit();
|
|
|
|
}
|
|
|
|
|
2009-08-06 08:13:48 -07:00
|
|
|
static void rotateBy(Ship *s, vector3d axis, const float timeStep)
|
2009-08-06 04:19:22 -07:00
|
|
|
{
|
|
|
|
double ang = timeStep;
|
|
|
|
if (ang == 0) return;
|
|
|
|
vector3d rotAxis = axis.Normalized();
|
|
|
|
matrix4x4d rotMatrix = matrix4x4d::RotateMatrix(ang, rotAxis.x, rotAxis.y, rotAxis.z);
|
|
|
|
|
|
|
|
matrix4x4d orient;
|
|
|
|
s->GetRotMatrix(orient);
|
|
|
|
orient = orient * rotMatrix;
|
|
|
|
s->SetRotMatrix(orient);
|
|
|
|
}
|
|
|
|
|
2009-08-06 08:13:48 -07:00
|
|
|
static void rotateTo(Ship *s, matrix4x4d &rot, const float timeStep)
|
2009-08-06 04:19:22 -07:00
|
|
|
{
|
|
|
|
matrix4x4d cur;
|
|
|
|
s->GetRotMatrix(cur);
|
|
|
|
vector3d cx(cur[0], cur[4], cur[8]);
|
|
|
|
vector3d rx(rot[0], rot[4], rot[8]);
|
|
|
|
vector3d cz(cur[2], cur[6], cur[10]);
|
|
|
|
vector3d rz(rot[2], rot[6], rot[10]);
|
|
|
|
double dx = vector3d::Dot(cx,rx);
|
|
|
|
double dz = vector3d::Dot(cz,rz);
|
|
|
|
if (dx < 0.999) {
|
|
|
|
vector3d xrot = vector3d::Cross(rx, cx);
|
|
|
|
rotateBy(s, xrot, timeStep);
|
|
|
|
} else if (dz < 0.999) {
|
|
|
|
vector3d zrot = vector3d::Cross(rz, cz);
|
|
|
|
rotateBy(s, zrot, timeStep);
|
|
|
|
} else {
|
|
|
|
s->SetRotMatrix(rot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-03 04:16:31 -07:00
|
|
|
void SpaceStation::DoDockingAnimation(const float timeStep)
|
2009-08-02 05:40:09 -07:00
|
|
|
{
|
2009-08-06 04:19:22 -07:00
|
|
|
matrix4x4d rot, wantRot;
|
2009-08-06 08:00:08 -07:00
|
|
|
vector3d p1, p2, zaxis;
|
2009-08-02 05:40:09 -07:00
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
|
|
|
shipDocking_t &dt = m_shipDocking[i];
|
2009-08-03 04:16:31 -07:00
|
|
|
if (!dt.ship) {
|
|
|
|
m_openAnimState[i] -= 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] -= 0.3*timeStep;
|
|
|
|
continue;
|
|
|
|
}
|
2009-08-06 08:00:08 -07:00
|
|
|
GetRotMatrix(rot);
|
2009-08-03 04:16:31 -07:00
|
|
|
|
2009-08-02 05:40:09 -07:00
|
|
|
switch (dt.stage) {
|
2009-08-06 08:00:08 -07:00
|
|
|
/* Launching stages */
|
|
|
|
case -1:
|
2009-08-07 07:34:14 -07:00
|
|
|
// open inner doors
|
|
|
|
dt.stagePos += timeStep*0.3;
|
|
|
|
m_openAnimState[i] -= 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] += 0.3*timeStep;
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case -2:
|
|
|
|
// move into inner region
|
|
|
|
dt.stagePos += timeStep*0.3;
|
|
|
|
p1 = GetPosition() + rot*port_s3[i].pos;
|
|
|
|
p2 = GetPosition() + rot*port_s2[i].pos;
|
2009-09-13 15:48:13 -07:00
|
|
|
dt.ship->SetPosition(p1 + (p2-p1)*(double)dt.stagePos);
|
2009-08-07 07:34:14 -07:00
|
|
|
///
|
2010-01-30 10:56:37 -08:00
|
|
|
zaxis = vector3d::Cross(port_s2[i].xaxis, port_s2[i].yaxis);
|
2009-08-07 07:34:14 -07:00
|
|
|
wantRot = matrix4x4d::MakeRotMatrix(
|
2010-01-30 10:56:37 -08:00
|
|
|
port_s2[i].xaxis, port_s2[i].yaxis, zaxis) * rot;
|
2009-08-07 07:34:14 -07:00
|
|
|
rotateTo(dt.ship, wantRot, timeStep);
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case -3:
|
|
|
|
// close inner doors and pretend an elevator is
|
|
|
|
// moving...
|
|
|
|
dt.stagePos += timeStep*0.2;
|
|
|
|
m_openAnimState[i] -= 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] -= 0.3*timeStep;
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case -4:
|
2009-08-06 08:00:08 -07:00
|
|
|
// open inner doors
|
|
|
|
dt.stagePos += timeStep*0.3;
|
|
|
|
m_openAnimState[i] -= 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] += 0.3*timeStep;
|
|
|
|
dt.ship->SetPosition(GetPosition() + rot*port_s2[i].pos);
|
|
|
|
///
|
2010-01-30 10:56:37 -08:00
|
|
|
zaxis = vector3d::Cross(port[i].xaxis, port[i].yaxis);
|
2009-08-06 08:00:08 -07:00
|
|
|
wantRot = matrix4x4d::MakeRotMatrix(
|
2010-01-30 10:56:37 -08:00
|
|
|
port[i].xaxis, port[i].yaxis, zaxis) * rot;
|
2009-08-06 08:00:08 -07:00
|
|
|
rotateTo(dt.ship, wantRot, timeStep);
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage--;
|
|
|
|
}
|
|
|
|
break;
|
2009-08-07 07:34:14 -07:00
|
|
|
case -5:
|
2009-08-06 08:00:08 -07:00
|
|
|
// move ship to outer section
|
|
|
|
p1 = GetPosition() + rot*port_s2[i].pos;
|
|
|
|
p2 = GetPosition() + rot*port[i].pos;
|
2009-09-13 15:48:13 -07:00
|
|
|
dt.ship->SetPosition(p1 + (p2-p1)*(double)dt.stagePos);
|
2009-08-06 08:00:08 -07:00
|
|
|
dt.stagePos += 0.2*timeStep;
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage--;
|
|
|
|
}
|
|
|
|
break;
|
2009-08-07 07:34:14 -07:00
|
|
|
case -6:
|
2009-08-06 08:00:08 -07:00
|
|
|
// close inner door
|
|
|
|
m_openAnimState[i] -= 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] -= 0.3*timeStep;
|
|
|
|
dt.stagePos += 0.3*timeStep;
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage--;
|
|
|
|
}
|
|
|
|
break;
|
2009-08-07 07:34:14 -07:00
|
|
|
case -7:
|
2009-08-06 08:00:08 -07:00
|
|
|
// open outer door
|
|
|
|
m_openAnimState[i] += 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] -= 0.3*timeStep;
|
|
|
|
dt.stagePos += 0.3*timeStep;
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.ship->Enable();
|
|
|
|
dt.ship->SetFlightState(Ship::FLYING);
|
|
|
|
dt.ship->SetVelocity(GetFrame()->GetStasisVelocityAtPosition(dt.ship->GetPosition()));
|
|
|
|
dt.ship->SetAngVelocity(GetFrame()->GetAngVelocity());
|
|
|
|
dt.ship->SetForce(vector3d(0,0,0));
|
|
|
|
dt.ship->SetTorque(vector3d(0,0,0));
|
|
|
|
dt.ship->SetThrusterState(ShipType::THRUSTER_REAR, 1.0);
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage--;
|
|
|
|
}
|
2009-08-07 07:34:14 -07:00
|
|
|
case -8:
|
2009-08-06 08:00:08 -07:00
|
|
|
// give the fucker some time to leave before closing doors
|
|
|
|
m_openAnimState[i] += 0.3*timeStep;
|
|
|
|
dt.stagePos += timeStep/30.0;
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.ship = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Docking stages */
|
2009-08-03 04:16:31 -07:00
|
|
|
case 0:
|
|
|
|
// docking has been granted but ship hasn't docked yet
|
2009-08-06 04:19:22 -07:00
|
|
|
dt.stagePos += timeStep/DOCKING_TIMEOUT_SECONDS;
|
2009-08-03 04:16:31 -07:00
|
|
|
m_openAnimState[i] += 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] -= 0.3*timeStep;
|
|
|
|
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
if (dt.ship == (Ship*)Pi::player) Pi::onDockingClearanceExpired.emit(this);
|
|
|
|
dt.ship = 0;
|
|
|
|
}
|
|
|
|
break;
|
2009-08-02 05:40:09 -07:00
|
|
|
case 1:
|
2009-08-06 08:13:48 -07:00
|
|
|
// close outer door, center ship
|
2009-08-02 05:40:09 -07:00
|
|
|
dt.stagePos += 0.3*timeStep;
|
2009-08-06 08:13:48 -07:00
|
|
|
p2 = GetPosition() + rot*port[i].pos;
|
2009-09-13 15:48:13 -07:00
|
|
|
dt.ship->SetPosition(dt.from + (p2-dt.from)*(double)dt.stagePos);
|
2009-08-03 04:16:31 -07:00
|
|
|
m_openAnimState[i] -= 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] -= 0.3*timeStep;
|
2009-08-06 04:19:22 -07:00
|
|
|
///
|
2010-01-30 10:56:37 -08:00
|
|
|
zaxis = vector3d::Cross(port[i].xaxis, port[i].yaxis);
|
2009-08-06 04:19:22 -07:00
|
|
|
wantRot = matrix4x4d::MakeRotMatrix(
|
2010-01-30 10:56:37 -08:00
|
|
|
port[i].xaxis, port[i].yaxis, zaxis) * matrix4x4d::RotateYMatrix(M_PI) * rot;
|
2009-08-06 04:19:22 -07:00
|
|
|
rotateTo(dt.ship, wantRot, timeStep);
|
|
|
|
///
|
2009-08-02 05:40:09 -07:00
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
2009-08-03 04:16:31 -07:00
|
|
|
// open inner door
|
|
|
|
dt.stagePos += 0.3*timeStep;
|
|
|
|
m_openAnimState[i] -= 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] += 0.3*timeStep;
|
2009-08-06 04:19:22 -07:00
|
|
|
/// XXX identical to code in step 1... XXX
|
2010-01-30 10:56:37 -08:00
|
|
|
zaxis = vector3d::Cross(port[i].xaxis, port[i].yaxis);
|
2009-08-06 04:19:22 -07:00
|
|
|
wantRot = matrix4x4d::MakeRotMatrix(
|
2010-01-30 10:56:37 -08:00
|
|
|
port[i].xaxis, port[i].yaxis, zaxis) * matrix4x4d::RotateYMatrix(M_PI) * rot;
|
2009-08-06 04:19:22 -07:00
|
|
|
rotateTo(dt.ship, wantRot, timeStep);
|
|
|
|
///
|
2009-08-03 04:16:31 -07:00
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
2009-08-02 05:40:09 -07:00
|
|
|
// move into inner region
|
2009-08-06 08:13:48 -07:00
|
|
|
p1 = GetPosition() + rot*port[i].pos;
|
2009-08-02 05:40:09 -07:00
|
|
|
p2 = GetPosition() + rot*port_s2[i].pos;
|
2009-09-13 15:48:13 -07:00
|
|
|
dt.ship->SetPosition(p1 + (p2-p1)*(double)dt.stagePos);
|
2009-08-06 08:00:08 -07:00
|
|
|
dt.stagePos += 0.2*timeStep;
|
2009-08-06 04:19:22 -07:00
|
|
|
|
|
|
|
///
|
2010-01-30 10:56:37 -08:00
|
|
|
zaxis = vector3d::Cross(port_s2[i].xaxis, port_s2[i].yaxis);
|
2009-08-06 04:19:22 -07:00
|
|
|
wantRot = matrix4x4d::MakeRotMatrix(
|
2010-01-30 10:56:37 -08:00
|
|
|
port_s2[i].xaxis, port_s2[i].yaxis, zaxis) * matrix4x4d::RotateYMatrix(M_PI) * rot;
|
2009-08-06 04:19:22 -07:00
|
|
|
rotateTo(dt.ship, wantRot, timeStep);
|
|
|
|
///
|
|
|
|
|
2009-08-02 05:40:09 -07:00
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage++;
|
|
|
|
}
|
|
|
|
break;
|
2009-08-03 04:16:31 -07:00
|
|
|
case 4:
|
2009-08-07 07:34:14 -07:00
|
|
|
// close inner door, rotate 180
|
2009-08-03 04:16:31 -07:00
|
|
|
dt.stagePos += 0.2*timeStep;
|
|
|
|
m_dockAnimState[i] -= 0.3*timeStep;
|
2009-08-06 04:19:22 -07:00
|
|
|
/// XXX same as codein stage3 XXX
|
2010-01-30 10:56:37 -08:00
|
|
|
zaxis = vector3d::Cross(port_s2[i].xaxis, port_s2[i].yaxis);
|
2009-08-06 04:19:22 -07:00
|
|
|
wantRot = matrix4x4d::MakeRotMatrix(
|
2010-01-30 10:56:37 -08:00
|
|
|
port_s2[i].xaxis, port_s2[i].yaxis, zaxis) * rot;
|
2009-08-06 04:19:22 -07:00
|
|
|
rotateTo(dt.ship, wantRot, timeStep);
|
|
|
|
///
|
2009-08-07 07:34:14 -07:00
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
// open inner doors, showing final resting place
|
|
|
|
dt.stagePos += 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] += 0.3*timeStep;
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
// enter
|
|
|
|
dt.stagePos += 0.3*timeStep;
|
|
|
|
// move into inner region
|
|
|
|
p1 = GetPosition() + rot*port_s2[i].pos;
|
|
|
|
p2 = GetPosition() + rot*port_s3[i].pos;
|
2009-09-13 15:48:13 -07:00
|
|
|
dt.ship->SetPosition(p1 + (p2-p1)*(double)dt.stagePos);
|
2009-08-07 07:34:14 -07:00
|
|
|
///
|
2010-01-30 10:56:37 -08:00
|
|
|
zaxis = vector3d::Cross(port_s3[i].xaxis, port_s3[i].yaxis);
|
2009-08-07 07:34:14 -07:00
|
|
|
wantRot = matrix4x4d::MakeRotMatrix(
|
2010-01-30 10:56:37 -08:00
|
|
|
port_s3[i].xaxis, port_s3[i].yaxis, zaxis) * rot;
|
2009-08-07 07:34:14 -07:00
|
|
|
rotateTo(dt.ship, wantRot, timeStep);
|
|
|
|
///
|
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.stagePos = 0;
|
|
|
|
dt.stage++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
// close door and dock
|
|
|
|
dt.stagePos += 0.3*timeStep;
|
|
|
|
m_dockAnimState[i] -= 0.3*timeStep;
|
2009-08-02 05:40:09 -07:00
|
|
|
if (dt.stagePos >= 1.0) {
|
|
|
|
dt.ship->SetDockedWith(this, i);
|
|
|
|
dt.ship = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2010-01-12 10:42:51 -08:00
|
|
|
}
|
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
2009-08-07 07:34:14 -07:00
|
|
|
m_openAnimState[i] = CLAMP(m_openAnimState[i], 0.0f, 1.0f);
|
|
|
|
m_dockAnimState[i] = CLAMP(m_dockAnimState[i], 0.0f, 1.0f);
|
2009-08-02 05:40:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-22 06:02:59 -07:00
|
|
|
void SpaceStation::TimeStepUpdate(const float timeStep)
|
|
|
|
{
|
|
|
|
if (Pi::GetGameTime() > m_lastUpdatedShipyard) {
|
2009-06-29 15:12:48 -07:00
|
|
|
UpdateBB();
|
2009-06-22 06:02:59 -07:00
|
|
|
UpdateShipyard();
|
|
|
|
// update again in an hour or two
|
|
|
|
m_lastUpdatedShipyard = Pi::GetGameTime() + 3600.0 + 3600.0*Pi::rng.Double();
|
|
|
|
}
|
2009-08-03 04:16:31 -07:00
|
|
|
DoDockingAnimation(timeStep);
|
2009-06-22 06:02:59 -07:00
|
|
|
}
|
|
|
|
|
2008-09-07 16:32:16 -07:00
|
|
|
bool SpaceStation::IsGroundStation() const
|
|
|
|
{
|
2010-01-17 12:25:52 -08:00
|
|
|
return (m_type->dockMethod == SpaceStationType::SURFACE);
|
2008-09-07 16:32:16 -07:00
|
|
|
}
|
|
|
|
|
2008-09-10 07:15:20 -07:00
|
|
|
void SpaceStation::OrientDockedShip(Ship *ship, int port) const
|
2008-09-07 16:32:16 -07:00
|
|
|
{
|
2009-08-02 05:40:09 -07:00
|
|
|
const positionOrient_t *dport = &this->port[port];
|
2010-01-17 12:25:52 -08:00
|
|
|
const int dockMethod = m_type->dockMethod;
|
2008-09-07 16:32:16 -07:00
|
|
|
if (dockMethod == SpaceStationType::SURFACE) {
|
|
|
|
matrix4x4d stationRot;
|
|
|
|
GetRotMatrix(stationRot);
|
2010-01-30 10:56:37 -08:00
|
|
|
vector3d port_z = vector3d::Cross(dport->xaxis, dport->yaxis);
|
|
|
|
matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(dport->xaxis, dport->yaxis, port_z);
|
2009-08-02 05:40:09 -07:00
|
|
|
vector3d pos = GetPosition() + stationRot*dport->pos;
|
2008-09-10 09:00:25 -07:00
|
|
|
|
|
|
|
// position with wheels perfectly on ground :D
|
|
|
|
Aabb aabb;
|
|
|
|
ship->GetAabb(aabb);
|
|
|
|
pos += stationRot*vector3d(0,-aabb.min.y,0);
|
|
|
|
|
|
|
|
ship->SetPosition(pos);
|
2008-09-07 16:32:16 -07:00
|
|
|
ship->SetRotMatrix(rot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-01 08:42:49 -07:00
|
|
|
void SpaceStation::PositionDockedShip(Ship *ship, int port)
|
2008-09-07 16:32:16 -07:00
|
|
|
{
|
2009-08-02 05:40:09 -07:00
|
|
|
const positionOrient_t *dport = &this->port[port];
|
2010-01-17 12:25:52 -08:00
|
|
|
const int dockMethod = m_type->dockMethod;
|
2008-09-07 16:32:16 -07:00
|
|
|
if (dockMethod == SpaceStationType::ORBITAL) {
|
2009-10-01 08:42:49 -07:00
|
|
|
matrix4x4d rot;
|
|
|
|
GetRotMatrix(rot);
|
|
|
|
vector3d p = GetPosition() + rot*port_s3[port].pos;
|
|
|
|
|
2009-08-02 05:40:09 -07:00
|
|
|
ship->SetFrame(GetFrame());
|
2009-10-01 08:42:49 -07:00
|
|
|
ship->SetPosition(p);
|
|
|
|
// duplicated from DoDockingAnimation()
|
2010-01-30 10:56:37 -08:00
|
|
|
vector3d zaxis = vector3d::Cross(port_s3[port].xaxis, port_s3[port].yaxis);
|
2009-10-01 08:42:49 -07:00
|
|
|
ship->SetRotMatrix(matrix4x4d::MakeRotMatrix(port_s3[port].xaxis,
|
2010-01-30 10:56:37 -08:00
|
|
|
port_s3[port].yaxis, zaxis) * rot);
|
2009-10-01 08:42:49 -07:00
|
|
|
} else {
|
2009-08-01 10:23:51 -07:00
|
|
|
Aabb aabb;
|
|
|
|
ship->GetAabb(aabb);
|
2008-09-07 16:32:16 -07:00
|
|
|
|
2009-08-01 10:23:51 -07:00
|
|
|
matrix4x4d stationRot;
|
2008-09-07 16:32:16 -07:00
|
|
|
GetRotMatrix(stationRot);
|
2010-01-30 10:56:37 -08:00
|
|
|
vector3d port_z = vector3d::Cross(dport->xaxis, dport->yaxis);
|
|
|
|
matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(dport->xaxis, dport->yaxis, port_z);
|
2009-08-01 10:23:51 -07:00
|
|
|
// position slightly (1m) off landing surface
|
2009-08-02 05:40:09 -07:00
|
|
|
vector3d pos = GetPosition() + stationRot*(dport->pos +
|
2010-01-30 10:56:37 -08:00
|
|
|
dport->yaxis -
|
|
|
|
dport->yaxis*aabb.min.y);
|
2009-08-01 10:23:51 -07:00
|
|
|
ship->SetPosition(pos);
|
2008-09-07 16:32:16 -07:00
|
|
|
ship->SetRotMatrix(rot);
|
2009-10-01 08:42:49 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpaceStation::LaunchShip(Ship *ship, int port)
|
|
|
|
{
|
2010-01-17 12:25:52 -08:00
|
|
|
const int dockMethod = m_type->dockMethod;
|
2009-10-01 08:42:49 -07:00
|
|
|
|
|
|
|
if (dockMethod == SpaceStationType::ORBITAL) {
|
|
|
|
shipDocking_t &sd = m_shipDocking[port];
|
|
|
|
sd.ship = ship;
|
|
|
|
sd.stage = -1;
|
|
|
|
sd.stagePos = 0;
|
|
|
|
ship->SetFlightState(Ship::DOCKING);
|
|
|
|
}
|
|
|
|
else if (dockMethod == SpaceStationType::SURFACE) {
|
|
|
|
ship->Blastoff();
|
2008-09-07 16:32:16 -07:00
|
|
|
} else {
|
|
|
|
assert(0);
|
|
|
|
}
|
2009-10-01 08:42:49 -07:00
|
|
|
PositionDockedShip(ship, port);
|
2008-09-07 16:32:16 -07:00
|
|
|
}
|
|
|
|
|
2009-08-03 04:16:31 -07:00
|
|
|
bool SpaceStation::GetDockingClearance(Ship *s, std::string &outMsg)
|
2008-08-11 08:45:25 -07:00
|
|
|
{
|
2009-08-03 04:16:31 -07:00
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
|
|
|
if (port[i].exists == false) continue;
|
|
|
|
if (m_shipDocking[i].ship == s) {
|
|
|
|
outMsg = stringf(256, "Clearance already granted. Proceed to docking bay %d.", i+1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
|
|
|
if (port[i].exists == false) continue;
|
|
|
|
if (m_shipDocking[i].ship != 0) continue;
|
|
|
|
shipDocking_t &sd = m_shipDocking[i];
|
|
|
|
sd.ship = s;
|
|
|
|
sd.stage = 0;
|
|
|
|
sd.stagePos = 0;
|
|
|
|
outMsg = stringf(256, "Clearance granted. Proceed to docking bay %d.", i+1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
outMsg = "Clearance denied. There are no free docking bays.";
|
|
|
|
return false;
|
2008-08-11 08:45:25 -07:00
|
|
|
}
|
|
|
|
|
2008-12-18 09:35:25 -08:00
|
|
|
/* MarketAgent shite */
|
|
|
|
void SpaceStation::Bought(Equip::Type t) {
|
|
|
|
m_equipmentStock[(int)t]++;
|
|
|
|
}
|
|
|
|
void SpaceStation::Sold(Equip::Type t) {
|
|
|
|
m_equipmentStock[(int)t]--;
|
|
|
|
}
|
|
|
|
bool SpaceStation::CanBuy(Equip::Type t) const {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool SpaceStation::CanSell(Equip::Type t) const {
|
|
|
|
return m_equipmentStock[(int)t] > 0;
|
|
|
|
}
|
2009-10-08 16:49:43 -07:00
|
|
|
bool SpaceStation::DoesSell(Equip::Type t) const {
|
|
|
|
return Polit::IsCommodityLegal(Pi::currentSystem, t);
|
|
|
|
}
|
|
|
|
|
2009-11-09 06:24:29 -08:00
|
|
|
Sint64 SpaceStation::GetPrice(Equip::Type t) const {
|
|
|
|
Sint64 mul = 100 + Pi::currentSystem->GetCommodityBasePriceModPercent(t);
|
|
|
|
return (mul * (Sint64)EquipType::types[t].basePrice) / 100;
|
2008-12-05 14:02:43 -08:00
|
|
|
}
|
|
|
|
|
2009-10-22 04:02:19 -07:00
|
|
|
bool SpaceStation::OnCollision(Object *b, Uint32 flags, double relVel)
|
2008-06-24 03:17:31 -07:00
|
|
|
{
|
2008-09-10 07:15:20 -07:00
|
|
|
if (flags & 0x10) {
|
2009-08-02 05:40:09 -07:00
|
|
|
positionOrient_t *dport = &port[flags & 0xf];
|
2008-07-13 02:32:40 -07:00
|
|
|
// hitting docking area of a station
|
2008-09-18 07:00:12 -07:00
|
|
|
if (b->IsType(Object::SHIP)) {
|
2008-07-13 02:32:40 -07:00
|
|
|
Ship *s = static_cast<Ship*>(b);
|
2008-09-07 16:32:16 -07:00
|
|
|
|
2008-11-07 08:50:24 -08:00
|
|
|
double speed = s->GetVelocity().Length();
|
2008-09-07 16:32:16 -07:00
|
|
|
|
|
|
|
// must be oriented sensibly and have wheels down
|
|
|
|
if (IsGroundStation()) {
|
|
|
|
matrix4x4d rot;
|
|
|
|
s->GetRotMatrix(rot);
|
|
|
|
matrix4x4d invRot = rot.InverseOf();
|
|
|
|
|
|
|
|
matrix4x4d stationRot;
|
|
|
|
GetRotMatrix(stationRot);
|
2010-01-30 10:56:37 -08:00
|
|
|
vector3d dockingNormal = stationRot*dport->yaxis;
|
2008-09-07 16:32:16 -07:00
|
|
|
|
|
|
|
// check player is sortof sensibly oriented for landing
|
2009-08-01 10:23:51 -07:00
|
|
|
const double dot = vector3d::Dot(vector3d(invRot[1], invRot[5], invRot[9]), dockingNormal);
|
2009-03-18 13:44:26 -07:00
|
|
|
if ((dot < 0.99) || (s->GetWheelState() != 1.0)) return true;
|
2008-09-07 16:32:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((speed < MAX_LANDING_SPEED) &&
|
|
|
|
(!s->GetDockedWith()) &&
|
2009-08-06 08:00:08 -07:00
|
|
|
(m_shipDocking[flags&0xf].ship == s) &&
|
|
|
|
(m_shipDocking[flags&0xf].stage == 0)) {
|
2009-08-02 05:40:09 -07:00
|
|
|
// if there is more docking port anim to do,
|
|
|
|
// don't set docked yet
|
|
|
|
if (port_s2[flags & 0xf].exists) {
|
|
|
|
shipDocking_t &sd = m_shipDocking[flags&0xf];
|
|
|
|
sd.ship = s;
|
|
|
|
sd.stage = 1;
|
|
|
|
sd.stagePos = 0;
|
|
|
|
sd.from = s->GetPosition();
|
2009-09-29 06:58:48 -07:00
|
|
|
s->Disable();
|
2009-08-02 05:40:09 -07:00
|
|
|
s->SetFlightState(Ship::DOCKING);
|
|
|
|
} else {
|
2009-08-03 04:16:31 -07:00
|
|
|
m_shipDocking[flags&0xf].ship = 0;
|
2009-08-02 05:40:09 -07:00
|
|
|
s->SetDockedWith(this, flags & 0xf);
|
|
|
|
}
|
2008-07-13 02:32:40 -07:00
|
|
|
}
|
2008-06-24 03:17:31 -07:00
|
|
|
}
|
2009-03-18 13:44:26 -07:00
|
|
|
if (!IsGroundStation()) return false;
|
2009-03-18 13:36:54 -07:00
|
|
|
return true;
|
2008-06-24 03:17:31 -07:00
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-04 07:06:36 -08:00
|
|
|
void SpaceStation::NotifyDeleted(const Body* const deletedBody)
|
2009-08-02 05:40:09 -07:00
|
|
|
{
|
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
2009-11-04 07:06:36 -08:00
|
|
|
if (m_shipDocking[i].ship == deletedBody) {
|
2009-08-02 05:40:09 -07:00
|
|
|
m_shipDocking[i].ship = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-17 12:25:52 -08:00
|
|
|
static std::vector<LmrModel*> s_advertModels;
|
2009-10-06 08:05:40 -07:00
|
|
|
|
2010-01-12 09:11:03 -08:00
|
|
|
#define ARG_STATION_BAY1_DOOR1 6
|
|
|
|
#define ARG_STATION_BAY1_DOOR2 10
|
|
|
|
#define ARG_STATION_BAY1_STAGE1 14
|
|
|
|
#define ARG_STATION_BAY1_STAGE2 18
|
|
|
|
|
2009-11-18 06:59:51 -08:00
|
|
|
void SpaceStation::Render(const vector3d &viewCoords, const matrix4x4d &viewTransform)
|
2008-06-24 03:17:31 -07:00
|
|
|
{
|
2009-10-06 08:05:40 -07:00
|
|
|
/* Well this is nice... */
|
|
|
|
static int poo=0;
|
|
|
|
if (!poo) {
|
|
|
|
poo = 1;
|
2010-01-17 12:25:52 -08:00
|
|
|
LmrGetModelsWithTag("advert", s_advertModels);
|
2009-10-06 08:05:40 -07:00
|
|
|
}
|
|
|
|
// it is silly to do this every render call
|
|
|
|
//
|
|
|
|
// random advert models in pFlag[16 .. 19]
|
|
|
|
// station name in pText[0]
|
|
|
|
// docking port in pText[1]
|
|
|
|
MTRand rand;
|
|
|
|
rand.seed(m_sbody->seed);
|
2010-01-17 12:25:52 -08:00
|
|
|
|
2010-01-18 09:58:57 -08:00
|
|
|
LmrObjParams ¶ms = GetLmrObjParams();
|
2010-01-17 12:25:52 -08:00
|
|
|
/* random advert models */
|
2010-01-18 09:58:57 -08:00
|
|
|
params.argStrings[4] = s_advertModels[rand.Int32(s_advertModels.size())]->GetName();
|
|
|
|
params.argStrings[5] = s_advertModels[rand.Int32(s_advertModels.size())]->GetName();
|
|
|
|
params.argStrings[6] = s_advertModels[rand.Int32(s_advertModels.size())]->GetName();
|
|
|
|
params.argStrings[7] = s_advertModels[rand.Int32(s_advertModels.size())]->GetName();
|
|
|
|
params.argStrings[0] = GetLabel().c_str();
|
2010-01-30 10:56:37 -08:00
|
|
|
SetLmrTimeParams();
|
2009-10-06 08:05:40 -07:00
|
|
|
|
2009-08-03 04:16:31 -07:00
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
2010-01-12 09:11:03 -08:00
|
|
|
params.argFloats[ARG_STATION_BAY1_DOOR1 + i] = m_openAnimState[i];
|
|
|
|
params.argFloats[ARG_STATION_BAY1_STAGE1 + i] = 1.0;
|
|
|
|
params.argFloats[ARG_STATION_BAY1_DOOR2 + i] = m_dockAnimState[i];
|
|
|
|
params.argFloats[ARG_STATION_BAY1_STAGE2 + i] = 1.0;
|
2009-08-07 07:34:14 -07:00
|
|
|
const int stage = m_shipDocking[i].stage;
|
|
|
|
|
|
|
|
/* nice */
|
|
|
|
if (
|
|
|
|
// if the player is in this docking bay draw its inner
|
|
|
|
// bits
|
|
|
|
((Pi::player->GetDockedWith() == this) &&
|
|
|
|
(Pi::player->GetDockingPort() == i))
|
|
|
|
||
|
|
|
|
// or if the player is at the bits of the docking
|
|
|
|
// sequence when they should be visible
|
|
|
|
((m_shipDocking[i].ship == (Ship*)Pi::player) &&
|
|
|
|
// during docking
|
|
|
|
( (stage >= 5) ||
|
|
|
|
// during launch
|
|
|
|
((stage >= -3) && (stage <= -1)) ))
|
|
|
|
) {
|
2010-01-12 09:11:03 -08:00
|
|
|
params.argFloats[ARG_STATION_BAY1_STAGE1 + i] = 0;
|
|
|
|
params.argFloats[ARG_STATION_BAY1_STAGE2 + i] = 1;
|
2009-08-07 07:34:14 -07:00
|
|
|
} else {
|
2010-01-12 09:11:03 -08:00
|
|
|
params.argFloats[ARG_STATION_BAY1_STAGE1 + i] = 1;
|
|
|
|
params.argFloats[ARG_STATION_BAY1_STAGE2 + i] = 0;
|
2009-08-07 07:34:14 -07:00
|
|
|
}
|
2009-08-03 04:16:31 -07:00
|
|
|
}
|
|
|
|
/*
|
2009-08-02 05:40:09 -07:00
|
|
|
for (int i=0; i<MAX_DOCKING_PORTS; i++) {
|
|
|
|
if (m_shipDocking[i].ship && (m_shipDocking[i].stage == 1)) {
|
2009-08-03 04:16:31 -07:00
|
|
|
params.pAnim[ASRC_STATION_DOCK_PORT1] = m_shipDocking[i].stagePos;
|
2009-08-02 05:40:09 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (m_shipDocking[i].ship && (m_shipDocking[i].stage == 2)) {
|
2009-08-03 04:16:31 -07:00
|
|
|
params.pAnim[ASRC_STATION_DOCK_PORT1] = 1.0;
|
2009-08-02 05:40:09 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (m_shipDocking[i].ship && (m_shipDocking[i].stage == 3)) {
|
2009-08-03 04:16:31 -07:00
|
|
|
params.pAnim[ASRC_STATION_DOCK_PORT1] = 1.0 - m_shipDocking[i].stagePos;
|
2009-08-02 05:40:09 -07:00
|
|
|
break;
|
|
|
|
}
|
2009-08-03 04:16:31 -07:00
|
|
|
}*/
|
2010-01-18 09:58:57 -08:00
|
|
|
RenderLmrModel(viewCoords, viewTransform);
|
2009-09-09 10:20:26 -07:00
|
|
|
|
|
|
|
/* don't render city if too far away */
|
2009-11-18 06:59:51 -08:00
|
|
|
if (viewCoords.Length() > 1000000.0) return;
|
2009-07-18 07:09:31 -07:00
|
|
|
|
|
|
|
// find planet Body*
|
|
|
|
Planet *planet;
|
|
|
|
{
|
|
|
|
Body *_planet = GetFrame()->m_astroBody;
|
|
|
|
if ((!_planet) || !_planet->IsType(Object::PLANET)) {
|
|
|
|
// orbital spaceport -- don't make city turds
|
2009-07-28 08:36:37 -07:00
|
|
|
} else {
|
|
|
|
planet = static_cast<Planet*>(_planet);
|
|
|
|
|
|
|
|
if (!m_adjacentCity) {
|
|
|
|
m_adjacentCity = new CityOnPlanet(planet, this, m_sbody->seed);
|
|
|
|
}
|
2009-08-02 05:40:09 -07:00
|
|
|
Shader::EnableVertexProgram(Shader::VPROG_SBRE);
|
2009-11-18 06:59:51 -08:00
|
|
|
m_adjacentCity->Render(this, viewCoords, viewTransform);
|
2009-08-02 05:40:09 -07:00
|
|
|
Shader::DisableVertexProgram();
|
2009-07-27 04:28:05 -07:00
|
|
|
}
|
2009-07-18 07:09:31 -07:00
|
|
|
}
|
2008-06-24 03:17:31 -07:00
|
|
|
}
|