Update the SpaceStationType code to use the JSON definition files.

Refactor into class with private members at same time.
master
Andrew Copland 2014-11-20 19:26:57 +00:00
parent f82d2924ba
commit 81a5fa45a8
7 changed files with 142 additions and 149 deletions

View File

@ -345,18 +345,15 @@ static int l_space_spawn_ship_parked(lua_State *l)
Ship *ship = new Ship(type);
assert(ship);
double parkDist = station->GetStationType()->parkingDistance;
parkDist -= ship->GetPhysRadius(); // park inside parking radius
double parkOffset = 0.5 * station->GetStationType()->parkingGapSize;
parkOffset += ship->GetPhysRadius(); // but outside the docking gap
const double parkDist = station->GetStationType()->ParkingDistance() - ship->GetPhysRadius(); // park inside parking radius
const double parkOffset = (0.5 * station->GetStationType()->ParkingGapSize()) + ship->GetPhysRadius(); // but outside the docking gap
double xpos = (slot == 0 || slot == 3) ? -parkOffset : parkOffset;
double zpos = (slot == 0 || slot == 1) ? -parkOffset : parkOffset;
vector3d parkPos = vector3d(xpos, parkDist, zpos);
parkPos = station->GetPosition() + station->GetOrient() * parkPos;
const vector3d parkPos = station->GetPosition() + station->GetOrient() * vector3d(xpos, parkDist, zpos);
// orbital stations have Y as axis of rotation
matrix3x3d rot = matrix3x3d::RotateX(M_PI/2) * station->GetOrient();
const matrix3x3d rot = matrix3x3d::RotateX(M_PI/2) * station->GetOrient();
ship->SetFrame(station->GetFrame());
ship->SetVelocity(vector3d(0.0));

View File

@ -662,7 +662,6 @@ void Pi::Quit()
Shields::Uninit();
Sfx::Uninit();
Sound::Uninit();
SpaceStation::Uninit();
CityOnPlanet::Uninit();
BaseSphere::Uninit();
FaceParts::Uninit();

View File

@ -522,7 +522,7 @@ static double MaxEffectRad(Body *body, Ship *ship)
if(!body) return 0.0;
if(!body->IsType(Object::TERRAINBODY)) {
if (!body->IsType(Object::SPACESTATION)) return body->GetPhysRadius() + 1000.0;
return static_cast<SpaceStation*>(body)->GetStationType()->parkingDistance + 1000.0;
return static_cast<SpaceStation*>(body)->GetStationType()->ParkingDistance() + 1000.0;
}
return std::max(body->GetPhysRadius(), sqrt(G * body->GetMass() / ship->GetAccelUp()));
}
@ -923,7 +923,7 @@ bool AICmdDock::TimeStepUpdate()
m_dockdir = dockpos.zaxis.Normalized();
m_dockupdir = dockpos.yaxis.Normalized(); // don't trust these enough
if (type->dockMethod == SpaceStationType::ORBITAL) {
if (type->IsOrbitalStation()) {
m_dockupdir = -m_dockupdir;
} else if (m_state == eDockingComplete) {
m_dockpos -= m_dockupdir * (m_ship->GetAabb().min.y + 1.0);
@ -943,14 +943,14 @@ bool AICmdDock::TimeStepUpdate()
// second docking waypoint
m_ship->SetWheelState(true);
vector3d targpos = GetPosInFrame(m_ship->GetFrame(), m_target->GetFrame(), m_dockpos);
vector3d relpos = targpos - m_ship->GetPosition();
vector3d reldir = relpos.NormalizedSafe();
vector3d relvel = -m_target->GetVelocityRelTo(m_ship);
const vector3d targpos = GetPosInFrame(m_ship->GetFrame(), m_target->GetFrame(), m_dockpos);
const vector3d relpos = targpos - m_ship->GetPosition();
const vector3d reldir = relpos.NormalizedSafe();
const vector3d relvel = -m_target->GetVelocityRelTo(m_ship);
double maxdecel = m_ship->GetAccelUp() - GetGravityAtPos(m_target->GetFrame(), m_dockpos);
double ispeed = calc_ivel(relpos.Length(), 0.0, maxdecel);
vector3d vdiff = ispeed*reldir - relvel;
const double maxdecel = m_ship->GetAccelUp() - GetGravityAtPos(m_target->GetFrame(), m_dockpos);
const double ispeed = calc_ivel(relpos.Length(), 0.0, maxdecel);
const vector3d vdiff = ispeed*reldir - relvel;
m_ship->AIChangeVelDir(vdiff * m_ship->GetOrient());
if (vdiff.Dot(reldir) < 0) {
m_ship->SetDecelerating(true);
@ -965,7 +965,7 @@ bool AICmdDock::TimeStepUpdate()
trot = trot * matrix3x3d::Rotate(ang, axis);
}
double af;
if (m_target->GetStationType()->dockMethod == SpaceStationType::ORBITAL) {
if (m_target->GetStationType()->IsOrbitalStation()) {
af = m_ship->AIFaceDirection(trot * m_dockdir);
} else {
af = m_ship->AIFaceDirection(m_ship->GetPosition().Cross(m_ship->GetOrient().VectorX()));

View File

@ -29,11 +29,6 @@ void SpaceStation::Init()
SpaceStationType::Init();
}
void SpaceStation::Uninit()
{
SpaceStationType::Uninit();
}
void SpaceStation::Save(Serializer::Writer &wr, Space *space)
{
ModelBody::Save(wr, space);
@ -138,32 +133,28 @@ void SpaceStation::InitStation()
m_adjacentCity = 0;
for(int i=0; i<NUM_STATIC_SLOTS; i++) m_staticSlot[i] = false;
Random rand(m_sbody->GetSeed());
bool ground = m_sbody->GetType() == SystemBody::TYPE_STARPORT_ORBITAL ? false : true;
if (ground) {
m_type = &SpaceStationType::surfaceStationTypes[ rand.Int32(SpaceStationType::surfaceStationTypes.size()) ];
} else {
m_type = &SpaceStationType::orbitalStationTypes[ rand.Int32(SpaceStationType::orbitalStationTypes.size()) ];
}
const bool ground = m_sbody->GetType() == SystemBody::TYPE_STARPORT_ORBITAL ? false : true;
m_type = SpaceStationType::RandomStationType(rand, ground);
if(m_shipDocking.empty()) {
m_shipDocking.reserve(m_type->numDockingPorts);
for (unsigned int i=0; i<m_type->numDockingPorts; i++) {
m_shipDocking.reserve(m_type->NumDockingPorts());
for (unsigned int i=0; i<m_type->NumDockingPorts(); i++) {
m_shipDocking.push_back(shipDocking_t());
}
// only (re)set these if we've not come from the ::Load method
m_doorAnimationStep = m_doorAnimationState = 0.0;
}
assert(m_shipDocking.size() == m_type->numDockingPorts);
assert(m_shipDocking.size() == m_type->NumDockingPorts());
// This SpaceStation's bay ports are an instance of...
m_ports = m_type->m_ports;
m_ports = m_type->Ports();
SetStatic(ground); // orbital stations are dynamic now
// XXX hack. if we loaded a game then ModelBody::Load already restored the
// model and we shouldn't overwrite it
if (!GetModel())
SetModel(m_type->modelName.c_str());
SetModel(m_type->ModelName().c_str());
SceneGraph::Model *model = GetModel();
@ -221,7 +212,7 @@ int SpaceStation::NumShipsDocked() const
int SpaceStation::GetFreeDockingPort(const Ship *s) const
{
assert(s);
for (unsigned int i=0; i<m_type->numDockingPorts; i++) {
for (unsigned int i=0; i<m_type->NumDockingPorts(); i++) {
if (m_shipDocking[i].ship == 0) {
// fwing
// initial unoccupied check
@ -246,7 +237,7 @@ void SpaceStation::SetDocked(Ship *ship, const int port)
{
assert(m_shipDocking.size() > Uint32(port));
m_shipDocking[port].ship = ship;
m_shipDocking[port].stage = m_type->numDockingStages+1;
m_shipDocking[port].stage = m_type->NumDockingStages()+1;
// have to do this crap again in case it was called directly (Ship::SetDockWith())
ship->SetFlightState(Ship::DOCKED);
@ -297,7 +288,7 @@ bool SpaceStation::LaunchShip(Ship *ship, const int port)
bool SpaceStation::GetDockingClearance(Ship *s, std::string &outMsg)
{
assert(m_shipDocking.size() == m_type->numDockingPorts);
assert(m_shipDocking.size() == m_type->NumDockingPorts());
for (Uint32 i=0; i<m_shipDocking.size(); i++) {
if (m_shipDocking[i].ship == s) {
outMsg = stringf(Lang::CLEARANCE_ALREADY_GRANTED_BAY_N, formatarg("bay", i+1));
@ -357,7 +348,7 @@ bool SpaceStation::OnCollision(Object *b, Uint32 flags, double relVel)
}
// if there is more docking port anim to do, don't set docked yet
if (m_type->numDockingStages >= 2) {
if (m_type->NumDockingStages() >= 2) {
shipDocking_t &sd = m_shipDocking[port];
sd.ship = s;
sd.stage = 2;
@ -400,8 +391,8 @@ void SpaceStation::DockingUpdate(const double timeStep)
for (Uint32 i=0; i<m_shipDocking.size(); i++) {
shipDocking_t &dt = m_shipDocking[i];
if (!dt.ship) continue;
// docked stage is m_type->numDockingPorts + 1 => ship docked
if (dt.stage > m_type->numDockingStages) continue;
// docked stage is m_type->NumDockingPorts() + 1 => ship docked
if (dt.stage > m_type->NumDockingStages()) continue;
double stageDuration = (dt.stage > 0 ?
m_type->GetDockAnimStageDuration(dt.stage-1) :
@ -437,25 +428,25 @@ void SpaceStation::DockingUpdate(const double timeStep)
else dt.stage--;
}
if (dt.stage < -m_type->shipLaunchStage && dt.ship->GetFlightState() != Ship::FLYING) {
if (dt.stage < -m_type->ShipLaunchStage() && dt.ship->GetFlightState() != Ship::FLYING) {
// launch ship
dt.ship->SetFlightState(Ship::FLYING);
dt.ship->SetAngVelocity(GetAngVelocity());
if (m_type->dockMethod == SpaceStationType::SURFACE) {
if (m_type->IsSurfaceStation()) {
dt.ship->SetThrusterState(1, 1.0); // up
} else {
dt.ship->SetThrusterState(2, -1.0); // forward
}
LuaEvent::Queue("onShipUndocked", dt.ship, this);
}
if (dt.stage < -m_type->numUndockStages) {
if (dt.stage < -m_type->NumUndockStages()) {
// undock animation finished, clear port
dt.stage = 0;
dt.ship = 0;
LockPort(i, false);
m_doorAnimationStep = -0.3; // close door
}
else if (dt.stage > m_type->numDockingStages) {
else if (dt.stage > m_type->NumDockingStages()) {
// set docked
dt.ship->SetDockedWith(this, i);
LuaEvent::Queue("onShipDocked", dt.ship, this);
@ -479,7 +470,7 @@ void SpaceStation::PositionDockedShip(Ship *ship, int port) const
ship->SetPosition(GetPosition() + GetOrient()*dport.pos);
// Still in docking animation process?
if (dt.stage <= m_type->numDockingStages) {
if (dt.stage <= m_type->NumDockingStages()) {
matrix3x3d wantRot = matrix3x3d::FromVectors(dport.xaxis, dport.yaxis, dport.zaxis);
// use quaternion spherical linear interpolation to do
// rotation smoothly
@ -503,7 +494,7 @@ void SpaceStation::StaticUpdate(const float timeStep)
void SpaceStation::TimeStepUpdate(const float timeStep)
{
// rotate the thing
double len = m_type->angVel * timeStep;
double len = m_type->AngVel() * timeStep;
if (!is_zero_exact(len)) {
matrix3x3d r = matrix3x3d::RotateY(-len); // RotateY is backwards
SetOrient(r * GetOrient());
@ -511,7 +502,7 @@ void SpaceStation::TimeStepUpdate(const float timeStep)
m_oldAngDisplacement = len;
// reposition the ships that are docked or docking here
for (unsigned int i=0; i<m_type->numDockingPorts; i++) {
for (unsigned int i=0; i<m_type->NumDockingPorts(); i++) {
const shipDocking_t &dt = m_shipDocking[i];
if (!dt.ship) { //free
m_navLights->SetColor(i+1, NavLights::NAVLIGHT_GREEN);
@ -543,7 +534,7 @@ void SpaceStation::UpdateInterpTransform(double alpha)
bool SpaceStation::IsGroundStation() const
{
return (m_type->dockMethod == SpaceStationType::SURFACE);
return m_type->IsSurfaceStation();
}
// Renders space station and adjacent city if applicable
@ -615,12 +606,12 @@ vector3d SpaceStation::GetTargetIndicatorPosition(const Frame *relTo) const
// return the next waypoint if permission has been granted for player,
// and the docking point's position once the docking anim starts
for (Uint32 i=0; i<m_shipDocking.size(); i++) {
if (i >= m_type->numDockingPorts) break;
if (i >= m_type->NumDockingPorts()) break;
if ((m_shipDocking[i].ship == Pi::player) && (m_shipDocking[i].stage > 0)) {
SpaceStationType::positionOrient_t dport;
if (!m_type->GetShipApproachWaypoints(i, m_shipDocking[i].stage+1, dport))
PiVerify(m_type->GetDockAnimPositionOrient(i, m_type->numDockingStages,
PiVerify(m_type->GetDockAnimPositionOrient(i, m_type->NumDockingStages(),
1.0f, vector3d(0.0), dport, m_shipDocking[i].ship));
vector3d v = GetInterpPositionRelTo(relTo);

View File

@ -28,13 +28,12 @@ class SpaceStation: public ModelBody {
public:
OBJDEF(SpaceStation, ModelBody, SPACESTATION);
static void Init();
static void Uninit();
// Should point to SystemBody in Pi::currentSystem
SpaceStation(const SystemBody *);
SpaceStation() {}
virtual ~SpaceStation();
virtual vector3d GetAngVelocity() const { return vector3d(0,m_type->angVel,0); }
virtual vector3d GetAngVelocity() const { return vector3d(0,m_type->AngVel(),0); }
virtual bool OnCollision(Object *b, Uint32 flags, double relVel);
virtual void Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform);
virtual void StaticUpdate(const float timeStep);
@ -53,7 +52,7 @@ public:
void SwapDockedShipsPort(const int oldPort, const int newPort);
bool GetDockingClearance(Ship *s, std::string &outMsg);
int GetDockingPortCount() const { return m_type->numDockingPorts; }
int GetDockingPortCount() const { return m_type->NumDockingPorts(); }
int GetFreeDockingPort(const Ship *s) const; // returns -1 if none free
int GetMyDockingPort(const Ship *s) const;
int NumShipsDocked() const;

View File

@ -3,37 +3,69 @@
#include "SpaceStationType.h"
#include "FileSystem.h"
#include "Lua.h"
#include "LuaVector.h"
#include "LuaVector.h"
#include "LuaTable.h"
#include "Pi.h"
#include "MathUtil.h"
#include "Ship.h"
#include "StringF.h"
#include "scenegraph/Model.h"
#include "OS.h"
#include "json/json.h"
#include <algorithm>
static lua_State *s_lua;
static std::string s_currentStationFile = "";
std::vector<SpaceStationType> SpaceStationType::surfaceStationTypes;
std::vector<SpaceStationType> SpaceStationType::orbitalStationTypes;
std::vector<SpaceStationType> SpaceStationType::surfaceTypes;
std::vector<SpaceStationType> SpaceStationType::orbitalTypes;
SpaceStationType::SpaceStationType()
: id("")
, model(0)
, modelName("")
, angVel(0.f)
, dockMethod(SURFACE)
, numDockingPorts(0)
, numDockingStages(0)
, numUndockStages(0)
, shipLaunchStage(3)
, parkingDistance(0)
, parkingGapSize(0)
{}
SpaceStationType::SpaceStationType(const std::string &id_, const std::string &path_)
: id(id_)
, model(0)
, modelName("")
, angVel(0.f)
, dockMethod(SURFACE)
, numDockingPorts(0)
, numDockingStages(0)
, numUndockStages(0)
, shipLaunchStage(3)
, parkingDistance(0)
, parkingGapSize(0)
{
Json::Reader reader;
Json::Value data;
auto fd = FileSystem::gameDataFiles.ReadFile(path_);
if (!fd) {
Output("couldn't open station def '%s'\n", path_.c_str());
return;
}
if (!reader.parse(fd->GetData(), fd->GetData()+fd->GetSize(), data)) {
Output("couldn't read station def '%s': %s\n", path_.c_str(), reader.getFormattedErrorMessages().c_str());
return;
}
modelName = data.get("model", "").asString();
const std::string type(data.get("type", "").asString());
if (type == "surface")
dockMethod = SURFACE;
else if (type == "orbital")
dockMethod = ORBITAL;
else {
Output("couldn't parse station def '%s': unknown type '%s'\n", path_.c_str(), type.c_str());
return;
}
angVel = data.get("angular_velocity", 0.0f).asFloat();
parkingDistance = data.get("parking_distance", 0.0f).asFloat();
parkingGapSize = data.get("parking_gap_size", 0.0f).asFloat();
padOffset = data.get("pad_offset", 150.f).asFloat();
model = Pi::FindModel(modelName);
assert(model);
OnSetupComplete();
}
void SpaceStationType::OnSetupComplete()
{
@ -357,77 +389,35 @@ bool SpaceStationType::GetDockAnimPositionOrient(const unsigned int port, int st
return gotOrient;
}
static int _define_station(lua_State *L, SpaceStationType &station)
{
station.id = s_currentStationFile;
LUA_DEBUG_START(L);
LuaTable t(L, -1);
station.modelName = t.Get<std::string>("model");
station.angVel = t.Get("angular_velocity", 0.f);
station.parkingDistance = t.Get("parking_distance", 5000.f);
station.parkingGapSize = t.Get("parking_gap_size", 2000.f);
station.padOffset = t.Get("pad_offset", 150.f);
LUA_DEBUG_END(L, 0);
assert(!station.modelName.empty());
station.model = Pi::FindModel(station.modelName);
station.OnSetupComplete();
return 0;
}
static int define_orbital_station(lua_State *L)
{
SpaceStationType station;
station.dockMethod = SpaceStationType::ORBITAL;
_define_station(L, station);
SpaceStationType::orbitalStationTypes.push_back(station);
return 0;
}
static int define_surface_station(lua_State *L)
{
SpaceStationType station;
station.dockMethod = SpaceStationType::SURFACE;
_define_station(L, station);
SpaceStationType::surfaceStationTypes.push_back(station);
return 0;
}
/*static*/
void SpaceStationType::Init()
{
assert(s_lua == 0);
if (s_lua != 0) return;
s_lua = luaL_newstate();
lua_State *L = s_lua;
LUA_DEBUG_START(L);
pi_lua_open_standard_base(L);
LuaVector::Register(L);
LUA_DEBUG_CHECK(L, 0);
lua_register(L, "define_orbital_station", define_orbital_station);
lua_register(L, "define_surface_station", define_surface_station);
static bool isInitted = false;
if (isInitted)
return;
isInitted = true;
// load all station definitions
namespace fs = FileSystem;
for (fs::FileEnumerator files(fs::gameDataFiles, "stations", fs::FileEnumerator::Recurse);
!files.Finished(); files.Next()) {
for (fs::FileEnumerator files(fs::gameDataFiles, "stations", 0); !files.Finished(); files.Next()) {
const fs::FileInfo &info = files.Current();
if (ends_with_ci(info.GetPath(), ".lua")) {
const std::string name = info.GetName();
s_currentStationFile = name.substr(0, name.size()-4);
pi_lua_dofile(L, info.GetPath());
s_currentStationFile.clear();
if (ends_with_ci(info.GetPath(), ".json")) {
const std::string id(info.GetName().substr(0, info.GetName().size()-5));
SpaceStationType st = SpaceStationType(id, info.GetPath());
switch (st.dockMethod) {
case SURFACE: surfaceTypes.push_back(st); break;
case ORBITAL: orbitalTypes.push_back(st); break;
}
}
}
LUA_DEBUG_END(L, 0);
}
void SpaceStationType::Uninit()
/*static*/
const SpaceStationType* SpaceStationType::RandomStationType(Random &random, const bool bIsGround)
{
lua_close(s_lua); s_lua = 0;
if (bIsGround) {
return &surfaceTypes[ random.Int32(SpaceStationType::surfaceTypes.size()) ];
}
return &orbitalTypes[ random.Int32(SpaceStationType::orbitalTypes.size()) ];
}

View File

@ -11,7 +11,8 @@
class Ship;
namespace SceneGraph { class Model; }
struct SpaceStationType {
class SpaceStationType {
public:
typedef std::map<Uint32, matrix4x4f> TMapBayIDMat;
struct PortPath
{
@ -19,7 +20,6 @@ struct SpaceStationType {
TMapBayIDMat m_leaving;
};
typedef std::map<Uint32, PortPath> PortPathMap;
PortPathMap m_portPaths;
struct SPort {
static const int BAD_PORT_ID = -1;
@ -33,6 +33,14 @@ struct SpaceStationType {
};
typedef std::vector<SPort> TPorts;
struct positionOrient_t {
vector3d pos;
vector3d xaxis;
vector3d yaxis;
vector3d zaxis;
};
private:
std::string id;
SceneGraph::Model *model;
std::string modelName;
@ -44,17 +52,15 @@ struct SpaceStationType {
int shipLaunchStage;
float parkingDistance;
float parkingGapSize;
PortPathMap m_portPaths;
TPorts m_ports;
float padOffset;
struct positionOrient_t {
vector3d pos;
vector3d xaxis;
vector3d yaxis;
vector3d zaxis;
};
static std::vector<SpaceStationType> surfaceTypes;
static std::vector<SpaceStationType> orbitalTypes;
SpaceStationType();
public:
SpaceStationType(const std::string &id, const std::string &path);
void OnSetupComplete();
const SPort* FindPortByBay(const int zeroBaseBayID) const;
@ -71,10 +77,21 @@ struct SpaceStationType {
* ship has been released and is under player control again */
bool GetDockAnimPositionOrient(const unsigned int port, int stage, double t, const vector3d &from, positionOrient_t &outPosOrient, const Ship *ship) const;
const std::string& ModelName() const { return modelName; }
float AngVel() const { return angVel; }
bool IsSurfaceStation() const { return (SURFACE==dockMethod); }
bool IsOrbitalStation() const { return (ORBITAL==dockMethod); }
unsigned int NumDockingPorts() const { return numDockingPorts; }
int NumDockingStages() const { return numDockingStages; }
int NumUndockStages() const { return numUndockStages; }
int ShipLaunchStage() const { return shipLaunchStage; }
float ParkingDistance() const { return parkingDistance; }
float ParkingGapSize() const { return parkingGapSize; }
const TPorts& Ports() const { return m_ports; }
static void Init();
static void Uninit();
static std::vector<SpaceStationType> surfaceStationTypes;
static std::vector<SpaceStationType> orbitalStationTypes;
static const SpaceStationType* RandomStationType(Random &random, const bool bIsGround);
};
#endif