234 lines
7.1 KiB
C++
234 lines
7.1 KiB
C++
#include "ship.h"
|
|
#include "objimport.h"
|
|
#include "frame.h"
|
|
#include "l3d.h"
|
|
#include "world_view.h"
|
|
#include "space.h"
|
|
#include "model_coll_mesh_data.h"
|
|
|
|
static ObjParams params = {
|
|
{ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f },
|
|
|
|
/* pColor[3] */
|
|
{
|
|
{ { 1.0f, 0.0f, 1.0f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
|
|
{ { 0.8f, 0.6f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
|
|
{ { 0.5f, 0.5f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 }
|
|
},
|
|
|
|
/* pText[3][256] */
|
|
{ "IR-L33T", "ME TOO" },
|
|
};
|
|
|
|
Ship::Ship(ShipType::Type shipType) : DynamicBody() {
|
|
m_wheelTransition = 0;
|
|
m_wheelState = 0;
|
|
m_dockedWith = 0;
|
|
m_navTarget = 0;
|
|
m_combatTarget = 0;
|
|
m_shipType = shipType;
|
|
m_angThrusters[0] = m_angThrusters[1] = m_angThrusters[2] = 0;
|
|
m_laserCollisionObj.owner = this;
|
|
m_equipment = EquipSet(shipType);
|
|
for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) {
|
|
m_tempLaserGeom[i] = 0;
|
|
m_gunState[i] = 0;
|
|
}
|
|
memset(m_thrusters, 0, sizeof(m_thrusters));
|
|
const ShipType& stype = GetShipType();
|
|
SetGeomFromSBREModel(stype.sbreModel, ¶ms);
|
|
SetMassDistributionFromCollMesh(GetModelSBRECollMesh(stype.sbreModel));
|
|
GeomsSetBody(m_body);
|
|
UpdateMass();
|
|
}
|
|
|
|
void Ship::UpdateMass(void) {
|
|
shipstats_t s;
|
|
CalcStats(&s);
|
|
dMassAdjust(&m_mass, s.total_mass*1000);
|
|
dBodySetMass(m_body, &m_mass);
|
|
}
|
|
|
|
void Ship::SetThrusterState(enum ShipType::Thruster t, float level) {
|
|
m_thrusters[t] = level;
|
|
}
|
|
|
|
void Ship::ClearThrusterState(void) {
|
|
for(int i = 0; i < ShipType::THRUSTER_MAX; i++) m_thrusters[i] = 0;
|
|
}
|
|
|
|
/* Hyperspace range is:
|
|
* (200 * hyperspace_class^2) / total_mass (in tonnes)
|
|
*/
|
|
void Ship::CalcStats(shipstats_t* stats) {
|
|
const ShipType& stype = GetShipType();
|
|
stats->max_capacity = stype.capacity;
|
|
stats->used_capacity = 0;
|
|
|
|
for(int i = 0; i < Equip::SLOT_MAX; i++) {
|
|
for(int j = 0; j < stype.equipSlotCapacity[i]; j++) {
|
|
Equip::Type t = m_equipment.Get((Equip::Slot)i, j);
|
|
if(t) stats->used_capacity += EquipType::types[t].mass;
|
|
}
|
|
}
|
|
stats->free_capacity = stats->max_capacity - stats->used_capacity;
|
|
stats->total_mass = stats->used_capacity + stype.hullMass;
|
|
|
|
Equip::Type t = m_equipment.Get(Equip::SLOT_ENGINE);
|
|
float hyperclass = EquipType::types[t].pval;
|
|
stats->hyperspace_range = 200 * hyperclass * hyperclass / stats->total_mass;
|
|
}
|
|
|
|
void Ship::TimeStepUpdate(const float timeStep) {
|
|
/* ODE tri mesh likes to know our old position. */
|
|
TriMeshUpdateLastPos();
|
|
const ShipType& stype = GetShipType();
|
|
for(int i = 0; i < ShipType::THRUSTER_MAX; i++) {
|
|
float force = timeStep * stype.linThrust[i] * m_thrusters[i];
|
|
switch(i) {
|
|
case ShipType::THRUSTER_REAR:
|
|
case ShipType::THRUSTER_FRONT:
|
|
dBodyAddRelForce(m_body, 0, 0, force); break;
|
|
case ShipType::THRUSTER_TOP:
|
|
case ShipType::THRUSTER_BOTTOM:
|
|
dBodyAddRelForce(m_body, 0, force, 0); break;
|
|
case ShipType::THRUSTER_LEFT:
|
|
case ShipType::THRUSTER_RIGHT:
|
|
dBodyAddRelForce(m_body, force, 0, 0); break;
|
|
}
|
|
}
|
|
dBodyAddRelTorque(m_body, stype.angThrust*m_angThrusters[0],
|
|
stype.angThrust*m_angThrusters[1],
|
|
stype.angThrust*m_angThrusters[2]);
|
|
|
|
/* LASERZ!! */
|
|
for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) {
|
|
/* Free old temp laser geoms. */
|
|
if(m_tempLaserGeom[i]) dGeomDestroy(m_tempLaserGeom[i]);
|
|
m_tempLaserGeom[i] = 0;
|
|
if(!m_gunState[i]) continue;
|
|
dGeomID ray = dCreateRay(GetFrame()->GetSpaceID(), 10000);
|
|
const vector3d pos = GetPosition();
|
|
const vector3f _dir = stype.gunMount[i].dir;
|
|
vector3d dir = vector3d(_dir.x, _dir.y, _dir.z);
|
|
matrix4x4d m;
|
|
GetRotMatrix(m);
|
|
dir = m.ApplyRotationOnly(dir);
|
|
dGeomRaySet(ray, pos.x, pos.y, pos.z, dir.x, dir.y, dir.z);
|
|
dGeomSetData(ray, static_cast<Object*>(&m_laserCollisionObj));
|
|
m_tempLaserGeom[i] = ray;
|
|
}
|
|
|
|
if(m_wheelTransition != 0.0f) {
|
|
m_wheelState += m_wheelTransition*timeStep;
|
|
m_wheelState = CLAMP(m_wheelState, 0, 1);
|
|
if((m_wheelState == 0) || (m_wheelState == 1)) m_wheelTransition = 0;
|
|
}
|
|
}
|
|
|
|
void Ship::NotifyDeath(const Body* const dyingBody) {
|
|
if(GetNavTarget() == dyingBody)
|
|
SetNavTarget(0);
|
|
if(GetCombatTarget() == dyingBody)
|
|
SetCombatTarget(0);
|
|
}
|
|
|
|
const ShipType& Ship::GetShipType(void) {
|
|
return ShipType::types[m_shipType];
|
|
}
|
|
|
|
void Ship::SetDockedWith(SpaceStation* s) {
|
|
if(m_dockedWith && !s) {
|
|
/* Launching. */
|
|
printf("Buhbai!\n");
|
|
m_dockedWith = 0;
|
|
vector3d pos = GetPosition();
|
|
pos.x += 5000;
|
|
SetPosition(pos);
|
|
} else {
|
|
m_dockedWith = s;
|
|
SetVelocity(vector3d(0, 0, 0));
|
|
SetAngVelocity(vector3d(0, 0, 0));
|
|
}
|
|
}
|
|
|
|
void Ship::SetGunState(int idx, int state) {
|
|
m_gunState[idx] = state;
|
|
}
|
|
|
|
void Ship::SetWheelState(bool down) {
|
|
if(down) m_wheelTransition = 1;
|
|
else m_wheelTransition = -1;
|
|
}
|
|
|
|
/* Assumed to be at model coords. */
|
|
void Ship::RenderLaserfire(void) {
|
|
const ShipType& stype = GetShipType();
|
|
glDisable(GL_LIGHTING);
|
|
for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) {
|
|
if(!m_gunState[i]) continue;
|
|
glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT);
|
|
glColor3f(1, 0, 0);
|
|
glLineWidth(2.0f);
|
|
glBegin(GL_LINES);
|
|
vector3f pos = stype.gunMount[i].pos;
|
|
glVertex3f(pos.x, pos.y, pos.z);
|
|
glVertex3fv(&((10000)*stype.gunMount[i].dir)[0]);
|
|
glEnd();
|
|
glPopAttrib();
|
|
}
|
|
glEnable(GL_LIGHTING);
|
|
}
|
|
|
|
static void render_coll_mesh(const CollMesh* m) {
|
|
glDisable(GL_LIGHTING);
|
|
glColor3f(1, 0, 1);
|
|
glBegin(GL_TRIANGLES);
|
|
for(int i = 0; i < m->ni; i += 3) {
|
|
glVertex3fv(&m->pVertex[3*m->pIndex[i]]);
|
|
glVertex3fv(&m->pVertex[3*m->pIndex[i+1]]);
|
|
glVertex3fv(&m->pVertex[3*m->pIndex[i+2]]);
|
|
}
|
|
glEnd();
|
|
glColor3f(1,1,1);
|
|
glDepthRange(0, 1.0f-0.0002f);
|
|
for(int i = 0; i < m->ni; i += 3) {
|
|
glBegin(GL_LINE_LOOP);
|
|
glVertex3fv(&m->pVertex[3*m->pIndex[i]]);
|
|
glVertex3fv(&m->pVertex[3*m->pIndex[i+1]]);
|
|
glVertex3fv(&m->pVertex[3*m->pIndex[i+2]]);
|
|
glEnd();
|
|
}
|
|
glDepthRange(0.0, 1.0);
|
|
glEnable(GL_LIGHTING);
|
|
}
|
|
|
|
void Ship::Render(const Frame* camFrame) {
|
|
const ShipType& stype = GetShipType();
|
|
params.angthrust[0] = m_angThrusters[0];
|
|
params.angthrust[1] = m_angThrusters[1];
|
|
params.angthrust[2] = m_angThrusters[2];
|
|
params.linthrust[0] = m_thrusters[ShipType::THRUSTER_RIGHT] - m_thrusters[ShipType::THRUSTER_LEFT];
|
|
params.linthrust[1] = m_thrusters[ShipType::THRUSTER_TOP] - m_thrusters[ShipType::THRUSTER_BOTTOM];
|
|
params.linthrust[2] = m_thrusters[ShipType::THRUSTER_REAR] - m_thrusters[ShipType::THRUSTER_FRONT];
|
|
params.pAnim[ASRC_SECFRAC] = L3D::GetGameTime();
|
|
params.pAnim[ASRC_MINFRAC] = L3D::GetGameTime() / 60;
|
|
params.pAnim[ASRC_HOURFRAC] = L3D::GetGameTime() / 3600.0f;
|
|
params.pAnim[ASRC_DAYFRAC] = L3D::GetGameTime() / (24*3600.0f);
|
|
params.pAnim[ASRC_GEAR] = m_wheelState;
|
|
params.pFlag[AFLAG_GEAR] = m_wheelState != 0.0f;
|
|
|
|
strncpy(params.pText[0], GetLabel().c_str(), sizeof(params.pText));
|
|
|
|
RenderSbreModel(camFrame, stype.sbreModel, ¶ms);
|
|
|
|
glPushMatrix();
|
|
TransformToModelCoords(camFrame);
|
|
//render_coll_mesh(sbreCollMesh);
|
|
RenderLaserfire();
|
|
glPopMatrix();
|
|
}
|
|
|