153 lines
4.2 KiB
C++
153 lines
4.2 KiB
C++
// Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
|
|
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
|
|
|
#include "CargoBody.h"
|
|
|
|
#include "Game.h"
|
|
#include "GameSaveError.h"
|
|
#include "Pi.h"
|
|
#include "Sfx.h"
|
|
#include "Ship.h"
|
|
#include "Space.h"
|
|
#include "lua/LuaEvent.h"
|
|
|
|
CargoBody::CargoBody(const LuaRef &cargo, float selfdestructTimer) :
|
|
m_cargo(cargo)
|
|
{
|
|
SetModel("cargo");
|
|
Init();
|
|
SetMass(1.0);
|
|
m_selfdestructTimer = selfdestructTimer; // number of seconds to live
|
|
|
|
if (is_zero_exact(selfdestructTimer)) // turn off self destruct
|
|
m_hasSelfdestruct = false;
|
|
}
|
|
|
|
CargoBody::CargoBody(const char *modelName, const LuaRef &cargo, float selfdestructTimer) :
|
|
m_cargo(cargo)
|
|
{
|
|
SetModel(modelName);
|
|
Init();
|
|
SetMass(1.0);
|
|
m_selfdestructTimer = selfdestructTimer; // number of seconds to live
|
|
|
|
if (is_zero_exact(selfdestructTimer)) // turn off self destruct
|
|
m_hasSelfdestruct = false;
|
|
}
|
|
|
|
CargoBody::CargoBody(const Json &jsonObj, Space *space) :
|
|
DynamicBody(jsonObj, space)
|
|
{
|
|
GetModel()->SetLabel(GetLabel());
|
|
|
|
try {
|
|
Json cargoBodyObj = jsonObj["cargo_body"];
|
|
|
|
m_cargo.LoadFromJson(cargoBodyObj);
|
|
Init();
|
|
m_hitpoints = cargoBodyObj["hit_points"];
|
|
m_selfdestructTimer = cargoBodyObj["self_destruct_timer"];
|
|
m_hasSelfdestruct = cargoBodyObj["has_self_destruct"];
|
|
} catch (Json::type_error &) {
|
|
throw SavedGameCorruptException();
|
|
}
|
|
}
|
|
|
|
void CargoBody::SaveToJson(Json &jsonObj, Space *space)
|
|
{
|
|
DynamicBody::SaveToJson(jsonObj, space);
|
|
|
|
Json cargoBodyObj = Json::object(); // Create JSON object to contain cargo body data.
|
|
|
|
m_cargo.SaveToJson(cargoBodyObj);
|
|
cargoBodyObj["hit_points"] = m_hitpoints;
|
|
cargoBodyObj["self_destruct_timer"] = m_selfdestructTimer;
|
|
cargoBodyObj["has_self_destruct"] = m_hasSelfdestruct;
|
|
|
|
jsonObj["cargo_body"] = cargoBodyObj; // Add cargo body object to supplied object.
|
|
}
|
|
|
|
void CargoBody::Init()
|
|
{
|
|
m_hitpoints = 1.0f;
|
|
std::string cargoname = ScopedTable(m_cargo).CallMethod<std::string>("GetName"); // instead of switching to lua twice for the same value
|
|
SetLabel(cargoname);
|
|
SetMassDistributionFromModel();
|
|
m_hasSelfdestruct = true;
|
|
|
|
std::vector<Color> colors;
|
|
//metallic blue-orangeish color scheme
|
|
colors.push_back(Color(255, 198, 64));
|
|
colors.push_back(Color(0, 222, 255));
|
|
colors.push_back(Color(255, 255, 255));
|
|
|
|
SceneGraph::ModelSkin skin;
|
|
skin.SetColors(colors);
|
|
skin.SetDecal("pioneer");
|
|
skin.Apply(GetModel());
|
|
GetModel()->SetColors(colors);
|
|
|
|
Properties().Set("type", cargoname);
|
|
}
|
|
|
|
void CargoBody::TimeStepUpdate(const float timeStep)
|
|
{
|
|
|
|
// Suggestion: since cargo doesn't need thrust or AI, it could be
|
|
// converted into an idle object on orbital rails, set up to only take
|
|
// memory & save file space (not CPU power) when far from the player.
|
|
// Until then, we kill it after some time, to not clutter up the current
|
|
// star system.
|
|
|
|
if (m_hasSelfdestruct) {
|
|
m_selfdestructTimer -= timeStep;
|
|
if (m_selfdestructTimer <= 0) {
|
|
LuaEvent::Queue("onCargoDestroyed", this);
|
|
Pi::game->GetSpace()->KillBody(this);
|
|
SfxManager::Add(this, TYPE_EXPLOSION);
|
|
}
|
|
}
|
|
DynamicBody::TimeStepUpdate(timeStep);
|
|
}
|
|
|
|
bool CargoBody::OnDamage(Body *attacker, float kgDamage, const CollisionContact &contactData)
|
|
{
|
|
m_hitpoints -= kgDamage * 0.001f;
|
|
if (m_hitpoints < 0) {
|
|
if (attacker && attacker->IsType(ObjectType::BODY))
|
|
LuaEvent::Queue("onCargoDestroyed", this, dynamic_cast<Body *>(attacker));
|
|
else
|
|
LuaEvent::Queue("onCargoDestroyed", this);
|
|
Pi::game->GetSpace()->KillBody(this);
|
|
SfxManager::Add(this, TYPE_EXPLOSION);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CargoBody::OnCollision(Body *b, Uint32 flags, double relVel)
|
|
{
|
|
// ignore collision if its about to be scooped
|
|
if (b->IsType(ObjectType::SHIP)) {
|
|
int cargoscoop_cap = 0;
|
|
static_cast<Ship *>(b)->Properties().Get("cargo_scoop_cap", cargoscoop_cap);
|
|
if (cargoscoop_cap > 0) {
|
|
LuaEvent::Queue("onCargoDestroyed", this);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return DynamicBody::OnCollision(b, flags, relVel);
|
|
}
|
|
|
|
void CargoBody::Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform)
|
|
{
|
|
RenderModel(r, camera, viewCoords, viewTransform);
|
|
}
|
|
|
|
void CargoBody::SetLabel(const std::string &label)
|
|
{
|
|
assert(GetModel());
|
|
GetModel()->SetLabel(label);
|
|
Body::SetLabel(label);
|
|
}
|