From d455debea6b595909dd30f80f7bbb9eceda066ef Mon Sep 17 00:00:00 2001 From: Rtch90 Date: Fri, 13 Apr 2018 23:30:34 +0100 Subject: [PATCH] [Add] Mkay, ships can take damage and die now. --- src/body.h | 2 ++ src/collider/collision_space.cpp | 6 +++- src/l3d.h | 1 + src/main.cpp | 62 ++++++++++++++++++++++++++++++-- src/sbre/models.cpp | 34 ++++++++++++++++++ src/sbre/sbre_models.h | 4 +-- src/ship.cpp | 47 ++++++++++++++++-------- src/ship.h | 2 ++ src/space.cpp | 7 ++++ 9 files changed, 145 insertions(+), 20 deletions(-) diff --git a/src/body.h b/src/body.h index 8263649..1b4159c 100644 --- a/src/body.h +++ b/src/body.h @@ -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 }; diff --git a/src/collider/collision_space.cpp b/src/collider/collision_space.cpp index d682435..258abfd 100644 --- a/src/collider/collision_space.cpp +++ b/src/collider/collision_space.cpp @@ -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(); diff --git a/src/l3d.h b/src/l3d.h index eeeb071..239f93f 100644 --- a/src/l3d.h +++ b/src/l3d.h @@ -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); diff --git a/src/main.cpp b/src/main.cpp index 3d0ae2a..77873f3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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, ¶ms); + 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 }; diff --git a/src/sbre/models.cpp b/src/sbre/models.cpp index bf767e1..4837f64 100644 --- a/src/sbre/models.cpp +++ b/src/sbre/models.cpp @@ -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 } } }; + diff --git a/src/sbre/sbre_models.h b/src/sbre/sbre_models.h index 7c97735..8c66476 100644 --- a/src/sbre/sbre_models.h +++ b/src/sbre/sbre_models.h @@ -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 }; diff --git a/src/ship.cpp b/src/ship.cpp index f9c989f..d99c138 100644 --- a/src/ship.cpp +++ b/src/ship.cpp @@ -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(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(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(c.userData1); - printf("Hit %s\n", hit->GetLabel().c_str()); - } else { - printf("Hit nothing..\n"); + hit->OnDamage(this, 1000.0); } } diff --git a/src/ship.h b/src/ship.h index 168b8df..39ed215 100644 --- a/src/ship.h +++ b/src/ship.h @@ -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; } diff --git a/src/space.cpp b/src/space.cpp index 61dbffc..e0f4129 100644 --- a/src/space.cpp +++ b/src/space.cpp @@ -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(); }