2008-06-24 03:17:31 -07:00
|
|
|
#include "ShipType.h"
|
2010-03-30 05:44:20 -07:00
|
|
|
#include "LmrModel.h"
|
2008-11-24 13:05:28 -08:00
|
|
|
#include "Serializer.h"
|
2010-03-30 05:44:20 -07:00
|
|
|
#include "MyLuaMathTypes.h"
|
|
|
|
#include "Pi.h"
|
|
|
|
#include "utils.h"
|
2008-06-24 03:17:31 -07:00
|
|
|
|
2009-06-23 13:22:27 -07:00
|
|
|
const char *ShipType::gunmountNames[GUNMOUNT_MAX] = {
|
|
|
|
"Front", "Rear" };
|
|
|
|
|
2010-03-30 05:44:20 -07:00
|
|
|
std::map<ShipType::Type, ShipType> ShipType::types;
|
|
|
|
std::string ShipType::LADYBIRD = "Ladybird Starfighter";
|
|
|
|
std::string ShipType::SIRIUS_INTERDICTOR = "Sirius Interdictor";
|
2011-01-17 22:47:15 -08:00
|
|
|
std::string ShipType::EAGLE_LRF = "Eagle Long Range Fighter";
|
|
|
|
std::string ShipType::EAGLE_MK3 = "Eagle MK-III";
|
2010-03-30 05:44:20 -07:00
|
|
|
std::string ShipType::MISSILE_GUIDED = "MISSILE_GUIDED";
|
|
|
|
std::string ShipType::MISSILE_NAVAL = "MISSILE_NAVAL";
|
|
|
|
std::string ShipType::MISSILE_SMART = "MISSILE_SMART";
|
|
|
|
std::string ShipType::MISSILE_UNGUIDED = "MISSILE_UNGUIDED";
|
|
|
|
|
2011-01-15 23:06:26 -08:00
|
|
|
static void _get_string_attrib(lua_State *L, const char *key, std::string &output,
|
|
|
|
const char *default_output)
|
|
|
|
{
|
|
|
|
LUA_DEBUG_START(L)
|
|
|
|
lua_pushstring(L, key);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
if (lua_isnil(L, -1)) {
|
|
|
|
output = default_output;
|
|
|
|
} else {
|
|
|
|
output = lua_tostring(L,-1);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
LUA_DEBUG_END(L, 0)
|
|
|
|
}
|
2010-03-30 05:44:20 -07:00
|
|
|
|
2011-01-15 23:06:26 -08:00
|
|
|
static void _get_float_attrib(lua_State *L, const char *key, float &output,
|
|
|
|
const float default_output)
|
2010-03-30 05:44:20 -07:00
|
|
|
{
|
2011-01-15 23:06:26 -08:00
|
|
|
LUA_DEBUG_START(L)
|
|
|
|
lua_pushstring(L, key);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
if (lua_isnil(L, -1)) {
|
|
|
|
output = default_output;
|
|
|
|
} else {
|
|
|
|
output = lua_tonumber(L,-1);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
LUA_DEBUG_END(L, 0)
|
|
|
|
}
|
2010-03-30 05:44:20 -07:00
|
|
|
|
2011-01-15 23:06:26 -08:00
|
|
|
static void _get_int_attrib(lua_State *L, const char *key, int &output,
|
|
|
|
const int default_output)
|
|
|
|
{
|
|
|
|
LUA_DEBUG_START(L)
|
|
|
|
lua_pushstring(L, key);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
if (lua_isnil(L, -1)) {
|
|
|
|
output = default_output;
|
2010-03-30 05:44:20 -07:00
|
|
|
} else {
|
2011-01-15 23:06:26 -08:00
|
|
|
output = lua_tointeger(L,-1);
|
2010-03-30 05:44:20 -07:00
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
2011-01-15 23:06:26 -08:00
|
|
|
LUA_DEBUG_END(L, 0)
|
|
|
|
}
|
2010-03-30 05:44:20 -07:00
|
|
|
|
2011-01-15 23:06:26 -08:00
|
|
|
int ShipType::define_ship(lua_State *L, const char *model_name)
|
|
|
|
{
|
|
|
|
ShipType s;
|
|
|
|
s.lmrModelName = model_name;
|
|
|
|
|
|
|
|
LUA_DEBUG_START(L)
|
|
|
|
_get_string_attrib(L, "name", s.name, model_name);
|
|
|
|
_get_float_attrib(L, "reverse_thrust", s.linThrust[THRUSTER_REVERSE], 0.0f);
|
|
|
|
_get_float_attrib(L, "forward_thrust", s.linThrust[THRUSTER_FORWARD], 0.0f);
|
|
|
|
_get_float_attrib(L, "up_thrust", s.linThrust[THRUSTER_UP], 0.0f);
|
|
|
|
_get_float_attrib(L, "down_thrust", s.linThrust[THRUSTER_DOWN], 0.0f);
|
|
|
|
_get_float_attrib(L, "left_thrust", s.linThrust[THRUSTER_LEFT], 0.0f);
|
|
|
|
_get_float_attrib(L, "right_thrust", s.linThrust[THRUSTER_RIGHT], 0.0f);
|
|
|
|
_get_float_attrib(L, "angular_thrust", s.angThrust, 0.0f);
|
2011-03-12 21:15:58 -08:00
|
|
|
s.angThrust = s.angThrust / 2; // fudge
|
2011-01-15 23:06:26 -08:00
|
|
|
|
|
|
|
for (int i=0; i<(int)Equip::SLOT_MAX; i++) s.equipSlotCapacity[i] = 0;
|
|
|
|
_get_int_attrib(L, "max_cargo", s.equipSlotCapacity[Equip::SLOT_CARGO], 0);
|
|
|
|
_get_int_attrib(L, "max_engine", s.equipSlotCapacity[Equip::SLOT_ENGINE], 1);
|
|
|
|
_get_int_attrib(L, "max_laser", s.equipSlotCapacity[Equip::SLOT_LASER], 1);
|
|
|
|
_get_int_attrib(L, "max_missile", s.equipSlotCapacity[Equip::SLOT_MISSILE], 0);
|
|
|
|
_get_int_attrib(L, "max_ecm", s.equipSlotCapacity[Equip::SLOT_ECM], 1);
|
|
|
|
_get_int_attrib(L, "max_scanner", s.equipSlotCapacity[Equip::SLOT_SCANNER], 1);
|
|
|
|
_get_int_attrib(L, "max_radarmapper", s.equipSlotCapacity[Equip::SLOT_RADARMAPPER], 1);
|
|
|
|
_get_int_attrib(L, "max_hypercloud", s.equipSlotCapacity[Equip::SLOT_HYPERCLOUD], 1);
|
|
|
|
_get_int_attrib(L, "max_hullautorepair", s.equipSlotCapacity[Equip::SLOT_HULLAUTOREPAIR], 1);
|
|
|
|
_get_int_attrib(L, "max_energybooster", s.equipSlotCapacity[Equip::SLOT_ENERGYBOOSTER], 1);
|
|
|
|
_get_int_attrib(L, "max_atmoshield", s.equipSlotCapacity[Equip::SLOT_ATMOSHIELD], 1);
|
|
|
|
_get_int_attrib(L, "max_fuelscoop", s.equipSlotCapacity[Equip::SLOT_FUELSCOOP], 1);
|
|
|
|
_get_int_attrib(L, "max_lasercooler", s.equipSlotCapacity[Equip::SLOT_LASERCOOLER], 1);
|
|
|
|
_get_int_attrib(L, "max_cargolifesupport", s.equipSlotCapacity[Equip::SLOT_CARGOLIFESUPPORT], 1);
|
|
|
|
_get_int_attrib(L, "max_autopilot", s.equipSlotCapacity[Equip::SLOT_AUTOPILOT], 1);
|
|
|
|
|
|
|
|
_get_int_attrib(L, "capacity", s.capacity, 0);
|
|
|
|
_get_int_attrib(L, "hull_mass", s.hullMass, 100);
|
|
|
|
_get_int_attrib(L, "price", s.baseprice, 0);
|
|
|
|
s.baseprice *= 100; // in hundredths of credits
|
2010-03-30 05:44:20 -07:00
|
|
|
|
2011-01-15 23:06:26 -08:00
|
|
|
{
|
|
|
|
int hyperclass;
|
|
|
|
_get_int_attrib(L, "hyperdrive_class", hyperclass, 1);
|
|
|
|
if (!hyperclass) {
|
|
|
|
s.hyperdrive = Equip::NONE;
|
|
|
|
} else {
|
|
|
|
s.hyperdrive = (Equip::Type)((int)Equip::DRIVE_CLASS1+hyperclass-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lua_pushstring(L, "gun_mounts");
|
|
|
|
lua_gettable(L, -2);
|
2010-03-30 05:44:20 -07:00
|
|
|
if (lua_istable(L, -1)) {
|
|
|
|
for (unsigned int i=0; i<lua_objlen(L,-1); i++) {
|
|
|
|
lua_pushinteger(L, i+1);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
if (lua_istable(L, -1) && lua_objlen(L,-2) == 2) {
|
|
|
|
lua_pushinteger(L, 1);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
s.gunMount[i].pos = *MyLuaVec::checkVec(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_pushinteger(L, 2);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
s.gunMount[i].dir = *MyLuaVec::checkVec(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
2011-01-15 23:06:26 -08:00
|
|
|
LUA_DEBUG_END(L, 0)
|
2010-03-30 05:44:20 -07:00
|
|
|
|
|
|
|
types[s.name] = s;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShipType::Init()
|
|
|
|
{
|
|
|
|
static bool isInitted = false;
|
|
|
|
if (isInitted) return;
|
|
|
|
isInitted = true;
|
|
|
|
|
|
|
|
std::vector<LmrModel*> ship_models;
|
|
|
|
LmrGetModelsWithTag("ship", ship_models);
|
|
|
|
lua_State *L = LmrGetLuaState();
|
|
|
|
int num = 0;
|
|
|
|
|
|
|
|
for (std::vector<LmrModel*>::iterator i = ship_models.begin();
|
|
|
|
i != ship_models.end(); ++i) {
|
|
|
|
LmrModel *model = *i;
|
|
|
|
model->PushAttributeToLuaStack("ship_defs");
|
|
|
|
if (lua_isnil(L, -1)) {
|
2010-07-05 15:22:33 -07:00
|
|
|
Error("Model %s is tagged as ship but has no ship_defs.",
|
2010-03-30 05:44:20 -07:00
|
|
|
model->GetName());
|
|
|
|
} else if (lua_istable(L, -1)) {
|
|
|
|
// multiple ship-defs for 1 model
|
|
|
|
for (unsigned int i=0; i<lua_objlen(L,-1); i++) {
|
|
|
|
lua_pushinteger(L, i+1);
|
|
|
|
lua_gettable(L, -2);
|
|
|
|
define_ship(L, model->GetName());
|
|
|
|
num++;
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Error("Model %s: ships_def is malformed", model->GetName());
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
printf("%d ship types.\n", num);
|
|
|
|
}
|
|
|
|
|
|
|
|
ShipType::Type ShipType::GetRandomType() {
|
|
|
|
ShipType::Type type = "";
|
|
|
|
while (true) {
|
|
|
|
std::map<ShipType::Type, ShipType>::iterator iter = types.begin();
|
|
|
|
int idx = Pi::rng.Int32(types.size());
|
|
|
|
for (int i=0; i<=idx; i++) {
|
|
|
|
type = iter->first;
|
|
|
|
iter++;
|
|
|
|
}
|
|
|
|
// Don't include missiles
|
|
|
|
if (type.find("MISSILE")!=0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return type;
|
|
|
|
}
|
2008-06-24 03:17:31 -07:00
|
|
|
|
2010-05-22 10:26:25 -07:00
|
|
|
void EquipSet::Save(Serializer::Writer &wr)
|
2008-11-24 13:05:28 -08:00
|
|
|
{
|
2010-05-22 10:26:25 -07:00
|
|
|
wr.Int32(Equip::SLOT_MAX);
|
2008-11-24 13:05:28 -08:00
|
|
|
for (int i=0; i<Equip::SLOT_MAX; i++) {
|
2010-05-22 10:26:25 -07:00
|
|
|
wr.Int32(equip[i].size());
|
2008-11-24 13:05:28 -08:00
|
|
|
for (unsigned int j=0; j<equip[i].size(); j++) {
|
2010-05-22 10:26:25 -07:00
|
|
|
wr.Int32(static_cast<int>(equip[i][j]));
|
2008-11-24 13:05:28 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Should have initialised with EquipSet(ShipType::Type) first
|
|
|
|
*/
|
2010-05-22 10:26:25 -07:00
|
|
|
void EquipSet::Load(Serializer::Reader &rd)
|
2008-11-24 13:05:28 -08:00
|
|
|
{
|
2010-05-22 10:26:25 -07:00
|
|
|
const int numSlots = rd.Int32();
|
2009-11-08 10:27:38 -08:00
|
|
|
assert(numSlots <= Equip::SLOT_MAX);
|
|
|
|
for (int i=0; i<numSlots; i++) {
|
2010-05-22 10:26:25 -07:00
|
|
|
const int numItems = rd.Int32();
|
2009-11-08 10:27:38 -08:00
|
|
|
for (int j=0; j<numItems; j++) {
|
2010-07-12 16:08:55 -07:00
|
|
|
if (j < (signed)equip[i].size()) {
|
|
|
|
equip[i][j] = static_cast<Equip::Type>(rd.Int32());
|
|
|
|
} else {
|
|
|
|
// equipment slot sizes have changed. just
|
|
|
|
// dump the difference
|
|
|
|
rd.Int32();
|
|
|
|
}
|
2008-11-24 13:05:28 -08:00
|
|
|
}
|
|
|
|
}
|
2009-10-30 16:22:10 -07:00
|
|
|
onChange.emit();
|
2008-11-24 13:05:28 -08:00
|
|
|
}
|
|
|
|
|