[Add] Mkay, ships can take damage and die now.

This commit is contained in:
Rtch90 2018-04-13 23:30:34 +01:00
parent abfd826e73
commit d455debea6
9 changed files with 145 additions and 20 deletions

View File

@ -28,6 +28,7 @@ public:
virtual void SetFrame(Frame* f) { m_frame = f; }
/* return true if to we do collision response and apply damage. */
virtual bool OnCollision(Body* b, Uint32 flags) { return false; }
virtual bool OnDamage(Body* attacker, float kgDamage) { return false; }
virtual void TimeStepUpdate(const float timeStep) {}
/* Override to clear any pointers you hold to the dying body. */
virtual void NotifyDeath(const Body* const dyingBody) {}
@ -46,6 +47,7 @@ public:
void SetOnscreen(const bool onscreen) { m_onscreen = onscreen; }
/* Only Space::KillBody() should call this method. */
void MarkDead(void) { m_dead = true; }
bool IsDead(void) const { return m_dead; }
enum { FLAG_CAN_MOVE_FRAME = 1 };

View File

@ -76,7 +76,11 @@ void CollisionSpace::TraceRay(const vector3d& start, const vector3d& dir,
(*i)->GetGeomTree()->TraceRay(modelStart, modelDir, &isect);
if(isect.triIdx != -1) {
c->pos = start + dir*isect.dist;
c->normal = vector3d(0.0);
vector3f n = (*i)->GetGeomTree()->GetTriNormal(isect.triIdx);
c->normal = vector3d(n.x, n.y, n.z);
c->normal = (*i)->GetTransform().ApplyRotationOnly(c->normal);
c->depth = len - isect.dist;
c->triIdx = isect.triIdx;
c->userData1 = (*i)->GetUserData();

View File

@ -42,6 +42,7 @@ public:
static void Init(IniConfig& config);
static void Start(void);
static void MainLoop(void);
static void TombStoneLoop(void);
static void Quit(void);
static void Serialize(void);
static void Unserialize(void);

View File

@ -166,18 +166,20 @@ void L3D::HandleEvents(void) {
if(event.key.keysym.sym == SDLK_i) L3D::showDebugInfo = !L3D::showDebugInfo;
#ifdef DEBUG
if(event.key.keysym.sym == SDLK_F12) {
matrix4x4d m; L3D::player->GetRotMatrix(m);
vector3d dir = m*vector3d(0,0,-1);
if(KeyState(SDLK_LSHIFT)) {
SpaceStation* station = new SpaceStation(SpaceStation::JJHOOP);
station->SetLabel("Poemi-chan's Folly");
station->SetFrame(L3D::player->GetFrame());
station->SetRotMatrix(matrix4x4d::RotateZMatrix(M_PI));
station->SetPosition(L3D::player->GetPosition()+vector3d(0,0,-5000));
station->SetPosition(L3D::player->GetPosition()+5000.0*dir);
Space::AddBody(station);
} else {
Ship* body = new Ship(ShipType::LADYBIRD);
body->SetLabel("A Friend");
body->SetFrame(L3D::player->GetFrame());
body->SetPosition(L3D::player->GetPosition()+vector3d(0,0,-1000));
body->SetPosition(L3D::player->GetPosition()+1000.0*dir);
Space::AddBody(body);
}
}
@ -214,6 +216,62 @@ void L3D::HandleEvents(void) {
}
}
static void draw_tombstone(float _time) {
static float lightCol[4] = { 1, 1, 1, 0 };
static float lightDir[4] = { 0, 1, 0, 0 };
static ObjParams params = {
{ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 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, 1.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 },
},
{ "J00 ISH DEAD!" },
};
glPushAttrib(GL_ALL_ATTRIB_BITS);
sbreSetViewport(L3D::GetScrWidth(), L3D::GetScrHeight(), L3D::GetScrWidth()*0.5, 1.0f, 1000.0f, 0.0f, 1.0f);
sbreSetDirLight(lightCol, lightDir);
matrix4x4d rot = matrix4x4d::RotateYMatrix(_time*2);
Matrix m;
Vector p;
m.x1 = rot[0]; m.x2 = rot[4]; m.x3 = rot[ 8];
m.y1 = rot[1]; m.y2 = rot[5]; m.y3 = rot[ 9];
m.z1 = rot[2]; m.z2 = rot[6]; m.z3 = rot[10];
p.x = 0; p.y = 0; p.z = MAX(150 - 30*_time, 30);
sbreRenderModel(&p, &m, 91, &params);
glPopAttrib();
}
void L3D::TombStoneLoop(void) {
Uint32 last_time = SDL_GetTicks();
float _time = 0;
cpan->HideAll();
currentView->HideAll();
do {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
L3D::HandleEvents();
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
draw_tombstone(_time);
Gui::Draw();
glFlush();
SDL_GL_SwapBuffers();
L3D::frameTime = 0.001*(SDL_GetTicks() - last_time);
_time += L3D::frameTime;
last_time = SDL_GetTicks();
} while(!((_time > 2.0) && ((L3D::MouseButtonState(1)) || L3D::KeyState(SDLK_SPACE))));
}
static void draw_intro(float _time) {
static float lightCol[4] = { 1, 1, 1, 0 };
static float lightDir[4] = { 0, 1, 0, 0 };

View File

@ -1339,3 +1339,37 @@ static uint16 starport1data[] = {
Model starport1model = { 100.0f, 55.0f, 17, starport1vtx1, 17, 0, dummyvtx2, 1,
{ { 0, starport1data, 0, 0, 0 } } };
static PlainVertex tomestonevtx1[] = {
{ VTYPE_PLAIN, { 0.6f, 1.0f, -0.1f } }, /* Front quad. */
{ VTYPE_PLAIN, { 0.6f, -1.0f, -0.1f } },
{ VTYPE_PLAIN, { -0.6f, -1.0f, -0.1f } },
{ VTYPE_PLAIN, { -0.6f, 1.0f, -0.1f } },
{ VTYPE_PLAIN, { 0, 1, 0.1 } }, /* Cylinder. */
{ VTYPE_PLAIN, { 0, 1, -0.1 } },
{ VTYPE_PLAIN, { 0.6f, 1.0f, 0.1f } }, /* Rear quad. */
{ VTYPE_PLAIN, { 0.6f, -1.0f, 0.1f } },
{ VTYPE_PLAIN, { -0.6f, -1.0f, 0.1f } },
{ VTYPE_PLAIN, { -0.6f, 1.0f, 0.1f } },
{ VTYPE_PLAIN, { -0.5, 0.8, -0.1 } }, /* Text start. */
{ VTYPE_PLAIN, { 0.5, 0.8, 0.1 } }, /* Text start. */
};
static uint16 tomestonedata[] = {
PTYPE_MATFIXED, 50, 50, 50, 0, 0, 0, 100, 0, 0, 0,
PTYPE_QUADFLAT, 6, 7, 8, 9,
PTYPE_QUADFLAT, 15, 14, 13, 12,
PTYPE_QUADFLAT, 6, 12, 13, 7,
PTYPE_QUADFLAT, 9, 8, 14, 15,
PTYPE_QUADFLAT, 9, 7, 13, 14,
PTYPE_CYLINDER, 0x8000, 16, 10, 11, 1, 60,
PTYPE_MATFIXED, 100, 100, 100, 0, 0, 0, 100, 100, 100, 0,
PTYPE_ZBIAS, 16, 5, 0,
PTYPE_TEXT, 0, 0x8000, 16, 5, 0, 0, 0, 10,
PTYPE_ZBIAS, 17, 2, 0,
PTYPE_TEXT, 0, 0x8000, 17, 2, 3, 0, 0, 10,
PTYPE_END
};
Model tomestonemodel = { 10.0f, 2.0f, 18, tomestonevtx1, 18, 0, dummyvtx2, 1,
{ { 0, tomestonedata, 0, 0, 0 } } };

View File

@ -4,7 +4,7 @@
extern Model dishmodel, nosewheelmodel, nwunitmodel, mainwheelmodel, mwunitmodel;
extern Model wing1model, wing2model;
extern Model ship1model, ship2model, ship3model, ship4model, ship5model;
extern Model station1model, starport1model;
extern Model station1model, starport1model, tomestonemodel;
extern Model metalFrameTowerModel;
/* Common subobject indices. */
@ -53,7 +53,7 @@ Model* const ppModel[] = {
/* 80. */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 90, other people's ships. */
&starport1model, 0, 0, 0, 0, 0, 0, 0, 0, 0,
&starport1model, &tomestonemodel, 0, 0, 0, 0, 0, 0, 0, 0,
/* 100, more sub-objects. */
&metalFrameTowerModel
};

View File

@ -44,6 +44,7 @@ void Ship::Save(void) {
wr_int(m_dockedWithPort);
wr_int(Serializer::LookupBody(m_dockedWith));
printf("TODO: NOT SAVING SHIP EQUIPMENT YET!!\n");
wr_float(m_stats.hull_mass_left);
}
void Ship::Load(void) {
@ -71,6 +72,7 @@ void Ship::Load(void) {
/* TODO: */
m_equipment = EquipSet(m_shipType);
Init();
m_stats.hull_mass_left = rd_float(); /* Must be after Init();.. */
}
void Ship::Init(void) {
@ -78,6 +80,7 @@ void Ship::Init(void) {
SetModel(stype.sbreModel);
SetMassDistributionFromCollMesh(GetModelSBRECollMesh(stype.sbreModel));
UpdateMass();
m_stats.hull_mass_left = stype.hullMass;
}
void Ship::PostLoadFixup(void) {
@ -113,24 +116,40 @@ void Ship::UpdateMass(void) {
SetMass(m_stats.total_mass*1000);
}
bool Ship::OnDamage(Body* attacker, float kgDamage) {
m_stats.hull_mass_left -= kgDamage*0.001;
if(m_stats.hull_mass_left < 0) Space::KillBody(this);
printf("Auch! %s took %.1f kilos of damage from %s! (%.1f t hull left)\n",
GetLabel().c_str(), kgDamage, attacker->GetLabel().c_str(), m_stats.hull_mass_left);
return true;
}
#define KINETIC_ENERGY_MULT 0.01
bool Ship::OnCollision(Body* b, Uint32 flags) {
float kineticEnergy = 0;
if(b->IsType(Object::DYNAMICBODY)) {
const vector3d relVel = static_cast<DynamicBody*>(b)->GetVelocity() - GetVelocity();
const float v = relVel.Length();
kineticEnergy = KINETIC_ENERGY_MULT * m_stats.total_mass * v * v;
} else {
const float v = GetVelocity().Length();
kineticEnergy = KINETIC_ENERGY_MULT * m_stats.total_mass * v * v;
}
if(b->IsType(Object::SPACESTATION) && (flags & 0x10)) {
kineticEnergy = 0;
}
if(b->IsType(Object::PLANET)) {
/* Geoms still enabled when landed. */
if(m_flightState != FLYING) return false;
else m_testLanded = true;
}
if(b->IsType(Object::MODELBODY)) {
vector3d relVel;
if(b->IsType(Object::DYNAMICBODY)) {
relVel = static_cast<DynamicBody*>(b)->GetVelocity() - GetVelocity();
} else {
relVel = GetVelocity();
else {
if(GetVelocity().Length() < MAX_LANDING_SPEED) {
m_testLanded = true;
kineticEnergy = 0;
}
}
/* Crappy recalculation of all this... */
float v = relVel.Length();
float kineticEnergy = m_stats.total_mass * v * v;
printf("%f ek\n", kineticEnergy);
}
if(kineticEnergy) OnDamage(b, kineticEnergy);
return true;
}
@ -312,9 +331,7 @@ void Ship::TimeStepUpdate(const float timeStep) {
GetFrame()->GetCollisionSpace()->TraceRay(pos, dir, 10000.0, &c, GetGeom());
if(c.userData1) {
Body* hit = static_cast<Body*>(c.userData1);
printf("Hit %s\n", hit->GetLabel().c_str());
} else {
printf("Hit nothing..\n");
hit->OnDamage(this, 1000.0);
}
}

View File

@ -11,6 +11,7 @@ struct shipstats_t {
int used_capacity;
int free_capacity;
int total_mass; /* Cargo, equipment + hull. */
float hull_mass_left; /* Effectively hitpoints.. */
float hyperspace_range;
};
@ -41,6 +42,7 @@ public:
virtual void TimeStepUpdate(const float timeStep);
virtual void NotifyDeath(const Body* const dyingBody);
virtual bool OnCollision(Body* b, Uint32 flags);
virtual bool OnDamage(Body* attacker, float kgDamage);
enum FlightState { FLYING, LANDED };
FlightState GetFlightState(void) const { return m_flightState; }
float GetWheelState(void) const { return m_wheelState; }

View File

@ -403,6 +403,13 @@ void Space::TimeStep(float step) {
for(bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) {
(*i)->TimeStepUpdate(step);
}
if(L3D::player->IsDead()) {
printf("J00 IS DEAD!!\n");
L3D::TombStoneLoop();
L3D::Quit();
}
PruneCorpses();
}