From 1d0bf8d34998d41ba050bda96538c90691d63192 Mon Sep 17 00:00:00 2001 From: devZoGok Date: Thu, 4 Dec 2025 15:03:35 +0200 Subject: [PATCH] using GameObject class as an order target Destructable made a member of GameObject cruise missiles can be shot down --- Assets/Scripts/Core/player.lua | 8 ++--- cruiseMissile.cpp | 9 ++++-- cruiseMissile.h | 4 +-- destructable.cpp | 31 +++++++++++------- destructable.h | 44 ++++++++++++++++---------- engineer.cpp | 11 ++++--- environment.cpp | 3 +- extractor.cpp | 31 +++++++++--------- factory.cpp | 3 +- freezer.cpp | 3 +- gameManager.cpp | 7 +++-- gameObject.cpp | 16 +--------- gameObject.h | 5 ++- missile.cpp | 9 ++++-- missile.h | 5 ++- player.cpp | 45 +++++++++++++++------------ player.h | 5 ++- projectile.cpp | 3 +- researchStruct.cpp | 13 ++++---- resourceRover.cpp | 11 ++++--- structure.cpp | 11 ++++--- unit.cpp | 57 +++++++++++++++++++--------------- unit.h | 15 ++++----- vehicle.cpp | 27 +++++++--------- weapon.cpp | 18 ++++++----- weapon.h | 6 ++-- 26 files changed, 219 insertions(+), 181 deletions(-) diff --git a/Assets/Scripts/Core/player.lua b/Assets/Scripts/Core/player.lua index 70b9b6c..db2d281 100644 --- a/Assets/Scripts/Core/player.lua +++ b/Assets/Scripts/Core/player.lua @@ -46,7 +46,7 @@ function Player:buildFort(arguments) angle = self.baseDir:getAngleBetween(Vector3:new(0, 0, 1)) * (right and -1 or 1) fort = GameObjectFactory.createUnit(self, UnitId.FORT, sp, Quaternion:new(angle, Vector3:new(0, 1, 0)), 0) self:addUnit(fort) - self:issueOrder(OrderType.BUILD, Vector3:new(0, 0, 0), {Target:new(fort, Vector3:new(0, 0, 0))}, false) + self:issueOrder(OrderType.BUILD, Vector3:new(0, 0, 0), {Target:new(fort:toGameObject(), Vector3:new(0, 0, 0))}, false) return BTNodeResult.RUNNING end @@ -84,7 +84,7 @@ function Player:buildStructure(engineer, buildingId, buildPos, buildAngle) building = GameObjectFactory.createUnit(self, buildingId, buildPos, Quaternion:new(1, 0, 0, 0), 0) self:addUnit(building) - self:issueOrder(OrderType.BUILD, Vector3:new(0, 0, 0), {Target:new(building, Vector3:new(0, 0, 0))}, false) + self:issueOrder(OrderType.BUILD, Vector3:new(0, 0, 0), {Target:new(building:toGameObject(), Vector3:new(0, 0, 0))}, false) end building = self:getUnitsByClass(unitClass, 1)[1] @@ -155,7 +155,7 @@ function Player:startHarvesting() self:deselectUnits() self:selectUnits({harvesters[1]}) - self:issueOrder(OrderType.SUPPLY, Vector3:new(0, 0, 0), {Target:new(extractor, Vector3:new(0, 0, 0))}, false) + self:issueOrder(OrderType.SUPPLY, Vector3:new(0, 0, 0), {Target:new(extractor:toGameObject(), Vector3:new(0, 0, 0))}, false) return BTNodeResult.SUCCESS end @@ -258,7 +258,7 @@ function Player:clearNearEnemies(arguments) if not taskForce.clearing and targUnit then self:deselectUnits() self:selectUnits(taskForce.units) - self:issueOrder(OrderType.MOVE, Vector3:new(0, 0, 0), {Target:new(targUnit, Vector3:new(0, 0, 0))}, false) + self:issueOrder(OrderType.MOVE, Vector3:new(0, 0, 0), {Target:new(targUnit:toGameObject(), Vector3:new(0, 0, 0))}, false) self.taskForces[arguments.tfId].clearing = true elseif taskForce.clearing and not targUnit then diff --git a/cruiseMissile.cpp b/cruiseMissile.cpp index 110c0f5..04884ac 100644 --- a/cruiseMissile.cpp +++ b/cruiseMissile.cpp @@ -1,4 +1,5 @@ #include "cruiseMissile.h" +#include "destructable.h" #include "player.h" #include "unit.h" #include "map.h" @@ -14,11 +15,10 @@ namespace battleship{ CruiseMissile::CruiseMissile(Unit *unit, int id, Vector3 tp, Vector3 pos, Quaternion rot) : Projectile(unit, id, pos, rot), - Destructable(unit->getPlayer(), id, GameObject::Type::PROJECTILE, pos, rot), targetPoint(tp), flightStage(FlightStage::ASCENT) { - Destructable::initProperties(); + destructable = new Destructable(this); Vector3 unitDir = unit->getDirVec(); Vector3 leftDir = unit->getLeftVec(); @@ -26,9 +26,11 @@ namespace battleship{ bool left = (leftDir.getAngleBetween(targDir) < PI / 2); float angle = unitDir.getAngleBetween(targDir) * (left ? 1 : -1); - Projectile::orientAt(Quaternion(angle, Vector3::VEC_J) * rot); + orientAt(Quaternion(angle, Vector3::VEC_J) * rot); } + CruiseMissile::~CruiseMissile(){delete destructable;} + void CruiseMissile::pitch(float rotAngle, Vector3 compVec){ float minHeight = 20; float angleToCompVec = Projectile::dirVec.getAngleBetween(compVec); @@ -56,6 +58,7 @@ namespace battleship{ void CruiseMissile::update(){ Projectile::update(); + destructable->update(); switch(flightStage){ case FlightStage::ASCENT: diff --git a/cruiseMissile.h b/cruiseMissile.h index b03b0c7..ff76db4 100644 --- a/cruiseMissile.h +++ b/cruiseMissile.h @@ -2,12 +2,12 @@ #define CRUISE_MISSILE_H #include "projectile.h" -#include "destructable.h" namespace battleship{ - class CruiseMissile : public Projectile, Destructable{ + class CruiseMissile : public Projectile{ public: CruiseMissile(Unit*, int, vb01::Vector3, vb01::Vector3, vb01::Quaternion); + ~CruiseMissile(); void update(); private: enum class FlightStage{ASCENT, CRUISE, DESCENT}; diff --git a/destructable.cpp b/destructable.cpp index cf1226d..a127a13 100644 --- a/destructable.cpp +++ b/destructable.cpp @@ -17,17 +17,20 @@ using namespace vb01; using namespace gameBase; namespace battleship{ - Destructable::Destructable(Player *player, int id, GameObject::Type type, vb01::Vector3 pos, vb01::Quaternion rot) : GameObject(type, id, player, pos, rot){} + Destructable::Destructable(GameObject *obj) : gameObject(obj){ + initProperties(); + } void Destructable::initProperties(){ - GameObject::initProperties(); + //GameObject::initProperties(); + int id = gameObject->getId(); sol::state_view SOL_LUA_VIEW = generateView(); - string objType = GameObject::getGameObjTableName(); - sol::table objTable = SOL_LUA_VIEW[objType][id + 1]; + string objType = gameObject->getGameObjTableName(); + sol::table objTable = SOL_LUA_VIEW[objType][gameObject->getId() + 1]; - vector currTechs = player->getTechnologies(); - health += Game::getSingleton()->calcAbilFromTech(Ability::Type::HEALTH, currTechs, (int)GameObject::type, id); + vector currTechs = gameObject->getPlayer()->getTechnologies(); + health += Game::getSingleton()->calcAbilFromTech(Ability::Type::HEALTH, currTechs, (int)gameObject->getType(), id); maxHealth = objTable["health"]; if(health == 0) health = maxHealth; @@ -47,14 +50,19 @@ namespace battleship{ } } + //TODO make this class a friend to GameObject void Destructable::update(){ - GameObject::update(); - if (health <= DEATH_HP){ - sol::table tbl = generateView()[getGameObjTableName()][id + 1]["deathFx"]; - FxManager::Fx *fx = FxManager::getSingleton()->initFx(tbl, model, false, pos); + gameObject->setRemove(true); + + sol::optional tblOpt = generateView()[gameObject->getGameObjTableName()][gameObject->getId() + 1]["deathFx"]; + + if(tblOpt == sol::nullopt) return; + + Vector3 pos = gameObject->getPos(); + sol::table tbl = generateView()[gameObject->getGameObjTableName()][gameObject->getId() + 1]["deathFx"]; + FxManager::Fx *fx = FxManager::getSingleton()->initFx(tbl, gameObject->getModel(), false, pos); Environment::explode(fx, Environment::Detonation::EXPLOSION, pos); - remove = true; } } @@ -81,6 +89,7 @@ namespace battleship{ if(render){ Vector3 offset3d = Vector3(offset.x, offset.y, 0); + Vector2 screenPos = gameObject->getScreenPos(); Quad *bgQuad = (Quad*)background->getMesh(0); Vector3 size = bgQuad->getSize(); diff --git a/destructable.h b/destructable.h index f3c403d..083b56e 100644 --- a/destructable.h +++ b/destructable.h @@ -1,30 +1,42 @@ #ifndef DESTRUCTABLE_H #define DESTRUCTABLE_H -#include "gameObject.h" +#include + +#include +#include + +namespace vb01{ + class Node; +} namespace battleship{ enum class Armor {CAST, COMBINED, MECHANIC, SHELL, STEEL}; - class Destructable : public GameObject{ - public: - Destructable(Player*, int, GameObject::Type, vb01::Vector3, vb01::Quaternion); - void update(); - virtual void initProperties(); - inline int getHealth(){return health;} - inline int getDeathHp(){return DEATH_HP;} - inline std::vector getArmorTypes(){return armorTypes;} - inline void takeDamage(int damage) {health -= damage * (1 + (freezeDmgFactor - 1) * freezeStatus * .01f);} - private: - std::vector armorTypes; - const int DEATH_HP = 0; - protected: - int health = 0, maxHealth, lenHpBar = 200, freezeStatus = 0, freezeDmgFactor = 10; - vb01::Node *hpBackgroundNode = nullptr, *hpForegroundNode = nullptr; + class GameObject; + class Destructable{ + public: + Destructable(GameObject*); + void update(); void removeBar(vb01::Node*); vb01::Node* createBar(vb01::Vector2, vb01::Vector2, vb01::Vector4); void displayStats(vb01::Node*, vb01::Node*, int, int, bool, vb01::Vector2 offset = vb01::Vector2::VEC_ZERO); + inline int getHealth(){return health;} + inline int getMaxHealth(){return maxHealth;} + inline int getDeathHp(){return DEATH_HP;} + inline void takeDamage(int damage) {health -= damage * (1 + (freezeDmgFactor - 1) * freezeStatus * .01f);} + inline GameObject* getGameObject(){return gameObject;} + inline std::vector getArmorTypes(){return armorTypes;} + inline void setFreezeStatus(int fs){this->freezeStatus = std::clamp(fs, 0, 100);} + inline int getFreezeStatus(){return freezeStatus;} + private: + std::vector armorTypes; + const int DEATH_HP = 0; + int health = 0, maxHealth, freezeStatus = 0, freezeDmgFactor = 10; + GameObject *gameObject = nullptr; + + void initProperties(); }; } diff --git a/engineer.cpp b/engineer.cpp index 7ed407d..e8755e9 100644 --- a/engineer.cpp +++ b/engineer.cpp @@ -1,5 +1,6 @@ #include "engineer.h" #include "activeGameState.h" +#include "destructable.h" #include "structure.h" #include "player.h" #include "game.h" @@ -21,13 +22,13 @@ namespace battleship{ hackRange = generateView()["units"][id + 1]["hackRange"]; hackRange += game->calcAbilFromTech(Ability::Type::HACK_RANGE, currTechs, (int)GameObject::type, id); Vector2 size = Vector2(lenHpBar, 10); - hackStatusBackground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); - hackStatusForeground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(1, 0, 1, 1)); + hackStatusBackground = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); + hackStatusForeground = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(1, 0, 1, 1)); } Engineer::~Engineer(){ - removeBar(hackStatusBackground); - removeBar(hackStatusForeground); + destructable->removeBar(hackStatusBackground); + destructable->removeBar(hackStatusForeground); } void Engineer::update(){ @@ -40,7 +41,7 @@ namespace battleship{ bool mainPlayerSelecting = (activeState && find(selectingPlayers.begin(), selectingPlayers.end(), mainPlayer) != selectingPlayers.end()); if(hackStatus < 100) - Unit::displayStats(hackStatusForeground, hackStatusBackground, hackStatus, 100, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); + destructable->displayStats(hackStatusForeground, hackStatusBackground, hackStatus, 100, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); else{ hackStatusBackground->setVisible(false); hackStatusForeground->setVisible(false); diff --git a/environment.cpp b/environment.cpp index 57971f2..28480cb 100644 --- a/environment.cpp +++ b/environment.cpp @@ -3,6 +3,7 @@ #include "player.h" #include "unit.h" #include "game.h" +#include "destructable.h" #include #include @@ -36,7 +37,7 @@ namespace battleship{ if(distance < radius){ switch(det){ case Detonation::EXPLOSION: - un->takeDamage(int(damage * (1.f - distance / radius))); + un->getDestructable()->takeDamage(int(damage * (1.f - distance / radius))); break; case Detonation::EMP: un->setCondition(Unit::Condition::EM_JAMMED); diff --git a/extractor.cpp b/extractor.cpp index 73f5736..e88de35 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -1,6 +1,7 @@ #include "extractor.h" #include "player.h" #include "game.h" +#include "destructable.h" #include "activeGameState.h" #include "resourceDeposit.h" @@ -12,25 +13,25 @@ namespace battleship{ using namespace gameBase; Extractor::Extractor(Player *player, int id, Vector3 pos, Quaternion rot, int buildStatus, ResourceDeposit *rd, Unit::State state) : Structure(player, id, pos, rot, buildStatus, state){ - if(!rd) - for(ResourceDeposit *dep : Game::getSingleton()->getCivilianPlayer()->getResourceDeposits()) - if(dep->getPos().getDistanceFrom(pos) < .001){ - deposit = dep; - deposit->setExtractor(this); - break; - } - Vector2 size = Vector2(lenHpBar, 10); - ammountBackground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); - ammountForeground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 1, 1)); + ammountBackground = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); + ammountForeground = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 1, 1)); + + if(rd) return; + + for(ResourceDeposit *dep : Game::getSingleton()->getCivilianPlayer()->getResourceDeposits()) + if(dep->getPos().getDistanceFrom(pos) < .001){ + deposit = dep; + deposit->setExtractor(this); + break; + } } Extractor::~Extractor(){ - if(deposit) - deposit->setExtractor(nullptr); + if(deposit) deposit->setExtractor(nullptr); - removeBar(ammountForeground); - removeBar(ammountBackground); + destructable->removeBar(ammountForeground); + destructable->removeBar(ammountBackground); } void Extractor::initProperties(){ @@ -58,7 +59,7 @@ namespace battleship{ initAmmount = deposit->getInitAmmount(); } - Unit::displayStats(ammountForeground, ammountBackground, ammount, initAmmount, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); + destructable->displayStats(ammountForeground, ammountBackground, ammount, initAmmount, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); } void Extractor::draw(){ diff --git a/factory.cpp b/factory.cpp index 1d2ae5c..aacf115 100644 --- a/factory.cpp +++ b/factory.cpp @@ -1,6 +1,7 @@ #include "factory.h" #include "player.h" #include "game.h" +#include "destructable.h" #include "gameObjectFactory.h" #include "activeGameState.h" @@ -56,7 +57,7 @@ namespace battleship{ vector selectingPlayers = getSelectingPlayers(); bool mainPlayerSelecting = (activeState && find(selectingPlayers.begin(), selectingPlayers.end(), mainPlayer) != selectingPlayers.end()); - Unit::displayStats(buildStatusForeground, buildStatusBackground, trainingStatus, 100, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); + destructable->displayStats(buildStatusForeground, buildStatusBackground, trainingStatus, 100, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); sol::table targTable = generateView()["units"][unitQueue[0] + 1]; int costRate = (int)targTable["cost"] / 100, trainRate = (int)targTable["buildTime"] / 100; diff --git a/freezer.cpp b/freezer.cpp index 15ae721..d3df3ab 100644 --- a/freezer.cpp +++ b/freezer.cpp @@ -1,4 +1,5 @@ #include "freezer.h" +#include "destructable.h" namespace battleship{ using namespace vb01; @@ -9,7 +10,7 @@ namespace battleship{ void Freezer::attack(Order order){ Vehicle::attack(order); - Unit *target = (Unit*)order.targets[0].unit; + Destructable *target = order.targets[0].unit->getDestructable(); if(target && target->getFreezeStatus() == 100) removeOrder(0); diff --git a/gameManager.cpp b/gameManager.cpp index 5d9cc8b..73d031a 100755 --- a/gameManager.cpp +++ b/gameManager.cpp @@ -16,6 +16,7 @@ #include "player.h" #include "factory.h" #include "engineer.h" +#include "destructable.h" #include "pointDefense.h" #include "resourceDeposit.h" @@ -44,7 +45,7 @@ namespace battleship{ ); SOL_LUA_STATE.new_usertype( - "Target", sol::constructors(), + "Target", sol::constructors(), "unit", &Order::Target::unit, "pos", &Order::Target::pos ); @@ -58,6 +59,7 @@ namespace battleship{ SOL_LUA_STATE.new_usertype( "Unit", sol::constructors(), "setState", &Unit::setState, + "getDestructable", &Unit::getDestructable, "getOrder", &Unit::getOrder, "getNumOrders", &Unit::getNumOrders, "getPos", &GameObject::getPos, @@ -66,7 +68,8 @@ namespace battleship{ "toEngineer", &Unit::toEngineer, "toPointDefense", &Unit::toPointDefense, "toStructure", &Unit::toStructure, - "toFactory", &Unit::toFactory + "toFactory", &Unit::toFactory, + "toGameObject", &Unit::toGameObject ); SOL_LUA_STATE.new_usertype( diff --git a/gameObject.cpp b/gameObject.cpp index 5904786..e9bac8f 100644 --- a/gameObject.cpp +++ b/gameObject.cpp @@ -1,5 +1,6 @@ #include "gameObject.h" #include "gameManager.h" +#include "destructable.h" #include "defConfigs.h" #include "player.h" #include "game.h" @@ -222,19 +223,4 @@ namespace battleship{ return "resources"; } } - - void GameObject::updateGameStats(Unit *targetUnit){ - if(targetUnit->getHealth() <= targetUnit->getDeathHp()){ - Player *targUnitPlayer = targetUnit->getPlayer(); - - if(targetUnit->isVehicle()){ - player->incVehiclesDestroyed(); - targUnitPlayer->incVehiclesLost(); - } - else{ - player->incStructuresDestroyed(); - targUnitPlayer->incStructuresLost(); - } - } - } } diff --git a/gameObject.h b/gameObject.h index aeb501c..e095f7d 100644 --- a/gameObject.h +++ b/gameObject.h @@ -13,6 +13,7 @@ namespace sf{ namespace battleship{ class Player; class Unit; + class Destructable; class GameObject{ public: @@ -26,7 +27,6 @@ namespace battleship{ virtual void placeAt(vb01::Vector3); void orientAt(vb01::Quaternion); std::string getGameObjTableName(); - void updateGameStats(Unit*); static sf::Sound* prepareSfx(sf::SoundBuffer*, std::string); bool pointWithinObj(vb01::Vector3, float = 0, float = 0, bool = false, float = 0); void changePlayer(Player *newPlayer); @@ -50,7 +50,9 @@ namespace battleship{ inline int getId() {return id;} inline Type getType(){return type;} inline vb01::Node* getHitbox(){return hitbox;} + inline void setRemove(bool rm){this->remove = rm;} inline bool isRemove(){return remove;} + inline Destructable* getDestructable(){return destructable;} protected: virtual void useColor(vb01::Material*); virtual void initProperties(); @@ -64,6 +66,7 @@ namespace battleship{ Type type; int id; Player *player; + Destructable *destructable = nullptr; vb01::Model *model = nullptr; vb01::Node *hitbox = nullptr; vb01::Vector3 pos = vb01::Vector3(0, 0, 0), upVec = vb01::Vector3(0, 1, 0), dirVec = vb01::Vector3(0, 0, 1), leftVec = vb01::Vector3(1, 0, 0), corners[8]; diff --git a/missile.cpp b/missile.cpp index 3d7a252..434ec14 100644 --- a/missile.cpp +++ b/missile.cpp @@ -1,24 +1,27 @@ #include "missile.h" #include "unit.h" +#include "destructable.h" namespace battleship{ using namespace vb01; Missile::Missile(Unit *un, int id, Vector3 tp, Vector3 pos, Quaternion rot) : Projectile(un, id, pos, rot), - Destructable(un->getPlayer(), id, GameObject::Type::PROJECTILE, pos, rot), targetPos(tp) { - Destructable::initProperties(); + destructable = new Destructable(this); } + Missile::~Missile(){delete destructable;} + void Missile::update(){ Vector3 targDir = (targetPos - Projectile::pos).norm(); float angle = targDir.getAngleBetween(Projectile::dirVec); float ra = (rotAngle < angle ? rotAngle : angle); - Projectile::orientAt(Quaternion(ra, Projectile::dirVec.cross(targDir)) * Projectile::rot); + orientAt(Quaternion(ra, Projectile::dirVec.cross(targDir)) * Projectile::rot); Projectile::update(); + destructable->update(); checkCollision(); } } diff --git a/missile.h b/missile.h index a0a82bb..1ef06de 100644 --- a/missile.h +++ b/missile.h @@ -2,13 +2,12 @@ #define MISSILE_H #include "projectile.h" -#include "destructable.h" namespace battleship{ - class Missile : public Projectile, Destructable{ + class Missile : public Projectile{ public: Missile(Unit*, int, vb01::Vector3, vb01::Vector3, vb01::Quaternion); - ~Missile(){} + ~Missile(); void update(); private: vb01::Vector3 targetPos; diff --git a/player.cpp b/player.cpp index b4c840b..18cfd97 100755 --- a/player.cpp +++ b/player.cpp @@ -6,6 +6,7 @@ #include "structure.h" #include "projectile.h" #include "tradeOffer.h" +#include "destructable.h" #include "activeGameState.h" #include "resourceDeposit.h" @@ -256,29 +257,33 @@ namespace battleship{ } } - vector Player::getDestructableProjectiles(){ - vector destProj; + vector Player::getDestructables(){ + vector destructables; - for(Projectile *proj : projectiles) - switch(proj->getProjectileClass()){ - case ProjectileClass::CRUISE_MISSILE: - case ProjectileClass::MISSILE: - destProj.push_back(proj); - break; - } + for(Projectile *p : projectiles) + if(p->getDestructable()) + destructables.push_back(p); - return destProj; - } - - vector Player::getDestructables(){ - vector destProj = getDestructableProjectiles(); - vector destructables; - - for(Projectile *p : destProj) - destructables.push_back((Destructable*)p); - - destructables.insert(destructables.end(), units.begin(), units.end()); + for(Unit *unit : units) + destructables.push_back((GameObject*)unit); return destructables; } + + void Player::updateGameStats(Unit *targetUnit){ + Destructable *destructTarg = targetUnit->getDestructable(); + + if(destructTarg->getHealth() <= destructTarg->getDeathHp()){ + Player *targUnitPlayer = targetUnit->getPlayer(); + + if(targetUnit->isVehicle()){ + incVehiclesDestroyed(); + targUnitPlayer->incVehiclesLost(); + } + else{ + incStructuresDestroyed(); + targUnitPlayer->incStructuresLost(); + } + } + } } diff --git a/player.h b/player.h index 447ed81..d2f68b8 100755 --- a/player.h +++ b/player.h @@ -10,7 +10,6 @@ namespace battleship{ class ResourceDeposit; - class Destructable; class Projectile; class Unit; struct TradeOffer; @@ -38,8 +37,8 @@ namespace battleship{ void addTradeOffer(Player*, TradeOffer*); std::vector getTradeOffers(Player*); void deselectUnit(Unit*); - std::vector getDestructableProjectiles(); - std::vector getDestructables(); + std::vector getDestructables(); + void updateGameStats(Unit*); inline int getResource(ResourceType rt){return resources[(int)rt];} inline void updateResource(ResourceType rt, int amount, bool add){resources[(int)rt] = (add ? resources[(int)rt] + amount : amount);} inline Trader* getTrader(){return trader;} diff --git a/projectile.cpp b/projectile.cpp index 3c44a50..8835615 100755 --- a/projectile.cpp +++ b/projectile.cpp @@ -13,6 +13,7 @@ #include "environment.h" #include "projectile.h" #include "defConfigs.h" +#include "destructable.h" #include "resourceDeposit.h" #include "inGameAppState.h" @@ -72,7 +73,7 @@ namespace battleship{ } void Projectile::detonate(Unit *target){ - if(target) target->takeDamage(directHitDamage); + if(target) target->getDestructable()->takeDamage(directHitDamage); sol::table tbl = generateView()[getGameObjTableName()][id + 1]["explosion"]; FxManager::Fx *fx = FxManager::getSingleton()->initFx(tbl["fx"], model, false, pos); diff --git a/researchStruct.cpp b/researchStruct.cpp index 9ecd9aa..398b307 100644 --- a/researchStruct.cpp +++ b/researchStruct.cpp @@ -1,5 +1,6 @@ #include "researchStruct.h" #include "activeGameState.h" +#include "destructable.h" #include "player.h" #include "game.h" @@ -17,13 +18,13 @@ namespace battleship{ researchCost = unitTable["researchCost"]; Vector2 size = Vector2(lenHpBar, 10); - researchStatusBackground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); - researchStatusForeground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(1, 0, 1, 1)); + researchStatusBackground = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); + researchStatusForeground = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(1, 0, 1, 1)); } ResearchStruct::~ResearchStruct(){ - removeBar(researchStatusBackground); - removeBar(researchStatusForeground); + destructable->removeBar(researchStatusBackground); + destructable->removeBar(researchStatusForeground); } void ResearchStruct::update(){ @@ -38,7 +39,7 @@ namespace battleship{ bool mainPlayerSelecting = (activeState && find(selectingPlayers.begin(), selectingPlayers.end(), mainPlayer) != selectingPlayers.end()); if(researchQueue.empty()){ - if(health > .3 * maxHealth && player->getResource(ResourceType::REFINEDS) >= researchCost && canUpdateResearch()){ + if(destructable->getHealth() > .3 * destructable->getMaxHealth() && player->getResource(ResourceType::REFINEDS) >= researchCost && canUpdateResearch()){ player->updateResource(ResourceType::RESEARCH, generationSpeed, true); player->updateResource(ResourceType::REFINEDS, -researchCost, true); lastUpdateTime = getTime(); @@ -48,7 +49,7 @@ namespace battleship{ researchStatusForeground->setVisible(false); } else if(!researchQueue.empty()){ - Unit::displayStats(researchStatusForeground, researchStatusBackground, researchStatus, 100, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); + destructable->displayStats(researchStatusForeground, researchStatusBackground, researchStatus, 100, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); int techCost = Game::getSingleton()->getTechnology(researchQueue[0]).cost; int playerResearch = player->getResource(ResourceType::RESEARCH); diff --git a/resourceRover.cpp b/resourceRover.cpp index ef0aadd..fe68a65 100644 --- a/resourceRover.cpp +++ b/resourceRover.cpp @@ -1,5 +1,6 @@ #include "resourceRover.h" #include "resourceDeposit.h" +#include "destructable.h" #include "map.h" #include "game.h" #include "player.h" @@ -16,15 +17,15 @@ namespace battleship{ ResourceRover::ResourceRover(Player *player, int id, Vector3 pos, Quaternion rot, Unit::State state) : Vehicle(player, id, pos, rot, state) { Vector2 size = Vector2(lenHpBar, 10); - loadBackground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); - loadForeground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(1, 1, 0, 1)); + loadBackground = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); + loadForeground = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(1, 1, 0, 1)); initProperties(); } ResourceRover::~ResourceRover(){ - removeBar(loadForeground); - removeBar(loadBackground); + destructable->removeBar(loadForeground); + destructable->removeBar(loadBackground); } void ResourceRover::initProperties(){ @@ -166,7 +167,7 @@ namespace battleship{ vector selectingPlayers = getSelectingPlayers(); bool mainPlayerSelecting = (activeState && find(selectingPlayers.begin(), selectingPlayers.end(), mainPlayer) != selectingPlayers.end()); - Unit::displayStats(loadForeground, loadBackground, calcTotalLoad(), capacity, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); + destructable->displayStats(loadForeground, loadBackground, calcTotalLoad(), capacity, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); } Unit* ResourceRover::getClosestUnit(vector structs){ diff --git a/structure.cpp b/structure.cpp index 5785b24..3926dae 100644 --- a/structure.cpp +++ b/structure.cpp @@ -1,5 +1,6 @@ #include "structure.h" #include "activeGameState.h" +#include "destructable.h" #include @@ -12,13 +13,13 @@ using namespace std; namespace battleship{ Structure::Structure(Player *player, int id, Vector3 pos, Quaternion rot, int bldSt, Unit::State state) : Unit(player, id, pos, rot, state), buildStatus(bldSt){ Vector2 size = Vector2(lenHpBar, 10); - buildStatusBackground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); - buildStatusForeground = Unit::createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 1, 1)); + buildStatusBackground = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); + buildStatusForeground = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 1, 1)); } Structure::~Structure(){ - removeBar(buildStatusForeground); - removeBar(buildStatusBackground); + destructable->removeBar(buildStatusForeground); + destructable->removeBar(buildStatusBackground); } void Structure::update(){ @@ -31,7 +32,7 @@ namespace battleship{ bool mainPlayerSelecting = (activeState && find(selectingPlayers.begin(), selectingPlayers.end(), mainPlayer) != selectingPlayers.end()); if(buildStatus < 100) - Unit::displayStats(buildStatusForeground, buildStatusBackground, buildStatus, 100, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); + destructable->displayStats(buildStatusForeground, buildStatusBackground, buildStatus, 100, mainPlayer == player && mainPlayerSelecting, Vector2(0, -10)); else{ buildStatusBackground->setVisible(false); buildStatusForeground->setVisible(false); diff --git a/unit.cpp b/unit.cpp index e923bdc..088031f 100755 --- a/unit.cpp +++ b/unit.cpp @@ -18,6 +18,7 @@ #include "game.h" #include "map.h" #include "vehicle.h" +#include "destructable.h" #include "gameObjectFactory.h" #include "activeGameState.h" #include "gameManager.h" @@ -32,9 +33,15 @@ using namespace gameBase; using namespace std; namespace battleship{ - Unit::Unit(Player *player, int id, Vector3 pos, Quaternion rot, State st) : Destructable(player, id, GameObject::Type::UNIT, pos, rot), state(st){ + //TODO move restartTime to unitData.lua + Unit::Unit(Player *player, int id, Vector3 pos, Quaternion rot, State st) : + GameObject(GameObject::Type::UNIT, id, player, pos, rot), + state(st), + restartTime(2000) + { selectable = true; - restartTime = 2000; + + destructable = new Destructable(this); Unit::initProperties(); initModel(); @@ -45,14 +52,14 @@ namespace battleship{ orientAt(rot); Vector2 size = Vector2(lenHpBar, 10); - hpBackgroundNode = createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); - hpForegroundNode = createBar(Vector2::VEC_ZERO, size, Vector4(0, 1, 0, 1)); + hpBackgroundNode = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(0, 0, 0, 1)); + hpForegroundNode = destructable->createBar(Vector2::VEC_ZERO, size, Vector4(0, 1, 0, 1)); } Unit::~Unit() { Map::getSingleton()->unblockCells(this); - removeBar(hpBackgroundNode); - removeBar(hpForegroundNode); + destructable->removeBar(hpBackgroundNode); + destructable->removeBar(hpForegroundNode); destroyWeapons(); destroySound(); destroyHitbox(); @@ -60,7 +67,7 @@ namespace battleship{ } void Unit::initProperties(){ - Destructable::initProperties(); + GameObject::initProperties(); sol::state_view SOL_LUA_VIEW = generateView(); string objType = GameObject::getGameObjTableName(); @@ -94,8 +101,8 @@ namespace battleship{ for(int i = 0; i < numGarrisonSlots; i++){ Vector2 size = 10 * Vector2::VEC_IJ; Vector2 pos = Vector2(1.5 * size.x * i, 20); - Node *bg = createBar(pos, size, Vector4(0, 0, 0, 1)); - Node *fg = createBar(pos, size, Vector4(0, 1, 0, 1)); + Node *bg = destructable->createBar(pos, size, Vector4(0, 0, 0, 1)); + Node *fg = destructable->createBar(pos, size, Vector4(0, 1, 0, 1)); int category = unitTable[tblName][i + 1]; garrisonSlots.push_back(GarrisonSlot(bg, fg, pos, category)); } @@ -240,19 +247,15 @@ namespace battleship{ if(!orders.empty()) return; vector players = Game::getSingleton()->getPlayers(); - vector targets; + vector targets; for(Player *pl : players) if(!(pl == player || pl->getTeam() == player->getTeam())){ - vector un = pl->getUnits(); - targets.insert(targets.end(), un.begin(), un.end()); - vector dp = pl->getDestructableProjectiles(); - - for(Projectile *p : dp) - targets.push_back((Destructable*)p); + vector targs = pl->getDestructables(); + targets.insert(targets.end(), targs.begin(), targs.end()); } - for(Destructable *targ : targets) + for(GameObject *targ : targets) if(targ->getPos().getDistanceFrom(pos) < lineOfSight){ receiveOrder(Order(Order::TYPE::ATTACK, vector{Order::Target(targ)}, Vector3::VEC_ZERO, -1, false), false); break; @@ -260,12 +263,13 @@ namespace battleship{ } void Unit::update() { - Destructable::update(); + GameObject::update(); + destructable->update(); if(condition == Condition::EM_JAMMED && getTime() - lastJamTime > restartTime) condition = Condition::ABLE; - if(freezeStatus >= 100) condition = Condition::FROZEN; + if(destructable->getFreezeStatus() >= 100) condition = Condition::FROZEN; if(state != State::HOLD_FIRE) autoAttackTargets(); @@ -279,10 +283,10 @@ namespace battleship{ renderOrderLine(renderSelectables); executeOrders(); - displayStats(hpForegroundNode, hpBackgroundNode, health, maxHealth, mainPlayerSelecting); + destructable->displayStats(hpForegroundNode, hpBackgroundNode, destructable->getHealth(), destructable->getMaxHealth(), mainPlayerSelecting); for(GarrisonSlot &slot : garrisonSlots) - displayStats(slot.foreground, slot.background, (int)((bool)slot.vehicle), (int)true, renderSelectables, slot.offset); + destructable->displayStats(slot.foreground, slot.background, (int)((bool)slot.vehicle), (int)true, renderSelectables, slot.offset); for(Weapon *weapon : weapons) weapon->update(); @@ -356,10 +360,10 @@ namespace battleship{ } void Unit::attack(Order order){ - vector targets; + vector targets; for(Player *pl : Game::getSingleton()->getPlayers()){ - vector targs = pl->getDestructables(); + vector targs = pl->getDestructables(); targets.insert(targets.end(), targs.begin(), targs.end()); } @@ -380,8 +384,11 @@ namespace battleship{ bool Unit::validateOrder(Order order){ switch (order.type) { - case Order::TYPE::ATTACK: - return !getWeaponsByOrder(Order::TYPE::ATTACK).empty(); + case Order::TYPE::ATTACK:{ + GameObject *target = order.targets[0].unit; + bool destructTarg = (!target || (target && target->getDestructable())); + return destructTarg && !getWeaponsByOrder(Order::TYPE::ATTACK).empty(); + } case Order::TYPE::BUILD: return (unitClass == UnitClass::ENGINEER || unitClass == UnitClass::FREEZER); case Order::TYPE::PATROL: diff --git a/unit.h b/unit.h index e5ba8c9..29df120 100755 --- a/unit.h +++ b/unit.h @@ -8,7 +8,7 @@ #include -#include "destructable.h" +#include "gameObject.h" #include "buildableUnit.h" #include "fxManager.h" @@ -36,15 +36,16 @@ namespace battleship{ class Engineer; class PointDefense; class Projectile; + class GameObject; struct Order { enum class TYPE {ATTACK, BUILD, MOVE, GARRISON, EJECT, PATROL, LAUNCH, SUPPLY, LOAD, UNLOAD, HACK}; struct Target{ - Destructable *unit = nullptr; + GameObject *unit = nullptr; vb01::Vector3 pos; Target(){} - Target(Destructable *u, vb01::Vector3 p = vb01::Vector3::VEC_ZERO) : unit(u), pos(p){} + Target(GameObject *u, vb01::Vector3 p = vb01::Vector3::VEC_ZERO) : unit(u), pos(p){} }; TYPE type; @@ -89,7 +90,7 @@ namespace battleship{ ICE_SHEET }; - class Unit : public Destructable{ + class Unit : public GameObject{ public: struct GarrisonSlot{ Vehicle *vehicle = nullptr; @@ -122,6 +123,7 @@ namespace battleship{ inline Factory* toFactory(){return (Factory*)this;} inline Cruiser* toCruiser(){return (Cruiser*)this;} inline PointDefense* toPointDefense(){return (PointDefense*)this;} + inline GameObject* toGameObject(){return (GameObject*)this;} inline int getNumGarrisonSlots(){return garrisonSlots.size();} inline const std::vector& getGarrisonSlots(){return garrisonSlots;} inline float getLineOfSight() {return lineOfSight;} @@ -135,8 +137,6 @@ namespace battleship{ inline std::string getGuiScreen(){return guiScreen;} inline BuildableUnit getBuildableUnit(int i){return buildableUnits[i];} inline vb01::Node* getLosLightNode(){return losLightNode;} - inline void setFreezeStatus(int fs){this->freezeStatus = std::clamp(fs, 0, 100);} - inline int getFreezeStatus(){return freezeStatus;} inline Condition getCondition(){return condition;} inline void setCondition(Condition cond){ this->condition = cond; @@ -161,13 +161,14 @@ namespace battleship{ UnitClass unitClass; std::vector orders; std::string guiScreen = ""; - int playerId, restartTime; + int playerId, restartTime, lenHpBar = 200; vb01::s64 orderLineDispTime = 0, lastFireTime = 0, lastJamTime = 0; float lineOfSight; std::vector weapons; std::vector garrisonSlots; std::vector buildableUnits; State state = State::STAND_GROUND; + vb01::Node *hpBackgroundNode = nullptr, *hpForegroundNode = nullptr; void placeAt(vb01::Vector3); std::vector getSelectingPlayers(); diff --git a/vehicle.cpp b/vehicle.cpp index e5b4e25..7b88bd0 100644 --- a/vehicle.cpp +++ b/vehicle.cpp @@ -10,6 +10,7 @@ #include #include "pathfinder.h" +#include "destructable.h" #include "defConfigs.h" #include "structure.h" #include "vehicle.h" @@ -425,22 +426,18 @@ namespace battleship{ void Vehicle::build(Order order){ if(pathPoints.empty()){ - if(!order.targets[0].unit) - player->addUnit((Unit*)order.targets[0].unit); - else { - Structure *structure = (Structure*)order.targets[0].unit; - sol::table targTable = generateView()["units"][structure->getId()]; - int costRate = (int)targTable["cost"] / 100, buildRate = (int)targTable["buildTime"] / 100; + Structure *structure = (Structure*)order.targets[0].unit; + sol::table targTable = generateView()["units"][structure->getId()]; + int costRate = (int)targTable["cost"] / 100, buildRate = (int)targTable["buildTime"] / 100; - if(structure->getBuildStatus() < 100 && player->getResource(ResourceType::REFINEDS) >= costRate && getTime() - lastBuildTime > buildRate){ - structure->incrementBuildStatus(); - player->updateResource(ResourceType::REFINEDS, -costRate, true); - lastBuildTime = getTime(); - } - else if(structure->getBuildStatus() >= 100){ - removeOrder(0); - player->incStructuresBuilt(); - } + if(structure->getBuildStatus() < 100 && player->getResource(ResourceType::REFINEDS) >= costRate && getTime() - lastBuildTime > buildRate){ + structure->incrementBuildStatus(); + player->updateResource(ResourceType::REFINEDS, -costRate, true); + lastBuildTime = getTime(); + } + else if(structure->getBuildStatus() >= 100){ + removeOrder(0); + player->incStructuresBuilt(); } } else navigate(0.5 * Map::getSingleton()->getCellSize().x); diff --git a/weapon.cpp b/weapon.cpp index f02d363..3d32426 100644 --- a/weapon.cpp +++ b/weapon.cpp @@ -7,6 +7,7 @@ #include "weapon.h" #include "player.h" #include "fxManager.h" +#include "destructable.h" #include "gameObjectFactory.h" #include "projectile.h" @@ -106,10 +107,10 @@ namespace battleship{ int numOrders = unit->getNumOrders(); int ordTp = (numOrders > 0 ? (int)unit->getOrder(0).type : -1); - Destructable *targUnit = (ordTp != -1 ? unit->getOrder(0).targets[0].unit : nullptr); + GameObject *targDestruct = (ordTp != -1 ? unit->getOrder(0).targets[0].unit : nullptr); if(ordTp == (int)orderType){ - Vector3 targPos = (targUnit ? targUnit->getPos() : unit->getOrder(0).targets[0].pos); + Vector3 targPos = (targDestruct ? targDestruct->getPos() : unit->getOrder(0).targets[0].pos); float targDist = unit->getPos().getDistanceFrom(targPos); bool withinRange = (minRange <= targDist && targDist <= maxRange); @@ -164,18 +165,18 @@ namespace battleship{ } } - void Weapon::updateTarget(Destructable *target){ - target->takeDamage(damage); + void Weapon::updateTarget(GameObject *target){ + target->getDestructable()->takeDamage(damage); if(target->getType() == GameObject::Type::UNIT) - unit->updateGameStats((Unit*)target); + unit->getPlayer()->updateGameStats((Unit*)target); } //TODO replace the 'laser' flag literal void Weapon::fire(Order order){ if(!canFire()) return; - Destructable *target = order.targets[0].unit; + GameObject *target = order.targets[0].unit; Vector3 targPos = (target ? target->getPos() : order.targets[0].pos); if(fireFx) useFx(fireFx, targPos, true); @@ -231,9 +232,10 @@ namespace battleship{ CryoGun::CryoGun(Unit *u, sol::table unitTable, int wid) : Weapon(u, unitTable, wid){} - void CryoGun::updateTargetUnit(Unit *targetUnit){ + void CryoGun::updateTarget(GameObject *target){ if(canFreeze()){ - targetUnit->setFreezeStatus(targetUnit->getFreezeStatus() + 1); + Destructable *destructTarg = target->getDestructable(); + destructTarg->setFreezeStatus(destructTarg->getFreezeStatus() + 1); lastFreezeTime = getTime(); } } diff --git a/weapon.h b/weapon.h index 4ef585e..91572e3 100644 --- a/weapon.h +++ b/weapon.h @@ -15,7 +15,7 @@ namespace vb01{ namespace battleship{ class FxManager; - class Destructable; + class GameObject; class Weapon{ public: @@ -54,7 +54,7 @@ namespace battleship{ protected: int rateOfFire; - virtual void updateTarget(Destructable*); + virtual void updateTarget(GameObject*); }; class CryoGun : public Weapon{ @@ -63,7 +63,7 @@ namespace battleship{ private: vb01::s64 lastFreezeTime = 0; - void updateTargetUnit(Unit*); + void updateTarget(GameObject*); inline bool canFreeze(){return vb01::getTime() - lastFreezeTime > rateOfFire;} }; }