Lephisto/src/ship.cpp
Rtch90 476fce2911 [Fix] Targetting bug when labels enabled.
[Fix] Bug also in docking..
2017-12-24 18:49:26 +00:00

275 lines
8.4 KiB
C++

#include "ship.h"
#include "frame.h"
#include "l3d.h"
#include "world_view.h"
#include "space.h"
#include "model_coll_mesh_data.h"
#include "space_station.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;
dockingTimer = 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();
SetModel(stype.sbreModel);
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);
}
vector3d Ship::CalcRotDamping(void) {
/* Rotation damping. */
const dReal* _av = dBodyGetAngularVel(m_body);
vector3d angVel(_av[0], _av[1], _av[2]);
matrix4x4d rot;
GetRotMatrix(rot);
angVel = rot.InverseOf() * angVel;
return angVel * 0.6;
}
void Ship::SetThrusterState(enum ShipType::Thruster t, float level) {
m_thrusters[t] = level;
}
void Ship::ClearThrusterState(void) {
SetAngThrusterState(0, 0.0f);
SetAngThrusterState(1, 0.0f);
SetAngThrusterState(2, 0.0f);
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) {
dockingTimer = (dockingTimer-timeStep > 0 ? dockingTimer-timeStep : 0);
/* 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) {
/*
* Position player in middle of docking bay, pointing out of it.
* TODO Need to do forced thrusting thingy.
* TODO ang vel not zeroed for some reason..
*/
matrix4x4d stationRot;
m_dockedWith->GetRotMatrix(stationRot);
vector3d port_y = vector3d::Cross(-m_dockedWith->port.horiz, m_dockedWith->port.normal);
matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(m_dockedWith->port.horiz, port_y, m_dockedWith->port.normal);
vector3d pos = m_dockedWith->GetPosition() + stationRot*m_dockedWith->port.center;
SetPosition(pos);
SetRotation(rot);
SetVelocity(vector3d(0, 0, 0));
SetAngVelocity(vector3d(0, 0, 0));
Enable();
m_dockedWith = 0;
} else {
m_dockedWith = s;
dockingTimer = 0.0f;
SetVelocity(vector3d(0, 0, 0));
SetAngVelocity(vector3d(0, 0, 0));
Disable();
}
}
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;
}
void Ship::SetNavTarget(Body* const target) {
m_navTarget = target;
L3D::world_view->UpdateCommsOptions();
}
void Ship::SetCombatTarget(Body* const target) {
m_combatTarget = target;
L3D::world_view->UpdateCommsOptions();
}
/* 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) {
if(!dBodyIsEnabled(m_body)) return;
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, &params);
glPushMatrix();
TransformToModelCoords(camFrame);
//render_coll_mesh(sbreCollMesh);
RenderLaserfire();
glPopMatrix();
}