From 1cfa18191844eb771918ee71dbce76603dd2b92f Mon Sep 17 00:00:00 2001 From: devZoGok Date: Fri, 5 Dec 2025 14:43:18 +0200 Subject: [PATCH] point defenses aim vertically towards missiles --- CMakeLists.txt | 8 +++--- cryoGun.cpp | 20 ++++++++++++++ cryoGun.h | 25 ++++++++++++++++++ unit.cpp | 11 ++++++-- weapon.cpp | 72 ++++++++++++++++++++++++++++---------------------- weapon.h | 18 +++---------- 6 files changed, 104 insertions(+), 50 deletions(-) create mode 100644 cryoGun.cpp create mode 100644 cryoGun.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cde6055..b5ee7c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,18 +24,20 @@ set(TRADING_BUTTONS activeStateBackButton.cpp playerTradeButton.cpp tradingScree set(MENU_BUTTONS mainMenuButton.cpp singlePlayerButton.cpp exitButton.cpp backButton.cpp playButton.cpp) set(MAP_EDITOR_BUTTONS mapEditorButton.cpp newMapButton.cpp loadMapButton.cpp exportButton.cpp) set(BUTTONS statsButton.cpp activeStateButton.cpp minimapButton.cpp ${TRADING_BUTTONS} ${OPTIONS_BUTTONS} ${MENU_BUTTONS} ${MAP_EDITOR_BUTTONS} ${UNIT_BUTTONS}) + set(LISTBOXES skyboxTextureListbox.cpp landTextureListbox.cpp gameObjectListbox.cpp mapListbox.cpp) set(GUI tooltip.cpp concreteGuiManager.cpp ${BUTTONS} ${LISTBOXES}) set(CONTROLLERS gameObjectFrameController.cpp cameraController.cpp) set(CONSOLE console.cpp abstractCommand.cpp addUnitCommand.cpp addResourceCommand.cpp addTechnologyCommand.cpp toggleDebugCommand.cpp) -set(CORE gameManager.cpp game.cpp environment.cpp fxManager.cpp defConfigs.cpp ${CONSOLE} ${CONTROLLERS}) +set(CORE gameManager.cpp game.cpp pathfinder.cpp environment.cpp fxManager.cpp defConfigs.cpp player.cpp trader.cpp ${CONSOLE} ${CONTROLLERS}) set(PROJECTILES projectile.cpp missile.cpp cruiseMissile.cpp shell.cpp) set(VEHICLES vehicle.cpp submarine.cpp engineer.cpp resourceRover.cpp freezer.cpp) set(STRUCTURES structure.cpp factory.cpp pointDefense.cpp extractor.cpp researchStruct.cpp iceSheet.cpp) -set(UNITS gameObjectFactory.cpp unit.cpp weapon.cpp ${STRUCTURES} ${VEHICLES}) -set(CONTENT player.cpp trader.cpp pathfinder.cpp map.cpp gameObject.cpp destructable.cpp gameObjectFrame.h resourceDeposit.cpp ${UNITS} ${PROJECTILES}) +set(WEAPONS weapon.cpp cryoGun.cpp) +set(UNITS unit.cpp ${WEAPONS} ${STRUCTURES} ${VEHICLES}) +set(CONTENT map.cpp gameObject.cpp destructable.cpp gameObjectFrame.h gameObjectFactory.cpp resourceDeposit.cpp ${UNITS} ${PROJECTILES}) set(UTIL util.cpp binds.h) diff --git a/cryoGun.cpp b/cryoGun.cpp new file mode 100644 index 0000000..d2fd9d7 --- /dev/null +++ b/cryoGun.cpp @@ -0,0 +1,20 @@ +#include "cryoGun.h" +#include "destructable.h" +#include "unit.h" + +namespace battleship{ + using namespace std; + using namespace vb01; + using namespace gameBase; + + CryoGun::CryoGun(Unit *u, sol::table unitTable, int wid) : Weapon(u, unitTable, wid){} + + void CryoGun::updateTarget(GameObject *target){ + if(canFreeze()){ + Destructable *destructTarg = target->getDestructable(); + destructTarg->setFreezeStatus(destructTarg->getFreezeStatus() + 1); + lastFreezeTime = getTime(); + } + } +} + diff --git a/cryoGun.h b/cryoGun.h new file mode 100644 index 0000000..e0fd381 --- /dev/null +++ b/cryoGun.h @@ -0,0 +1,25 @@ +#ifndef CRYOGUN_H +#define CRYOGUN_H + +#include "weapon.h" + +#include + +#include + +namespace battleship{ + class Unit; + + class CryoGun : public Weapon{ + public: + CryoGun(Unit*, sol::table, int); + private: + vb01::s64 lastFreezeTime = 0; + + void updateTarget(GameObject*); + inline bool canFreeze(){return vb01::getTime() - lastFreezeTime > rateOfFire;} + }; +} + +#endif + diff --git a/unit.cpp b/unit.cpp index 088031f..0fb6b40 100755 --- a/unit.cpp +++ b/unit.cpp @@ -13,6 +13,7 @@ #include #include "unit.h" +#include "cryoGun.h" #include "weapon.h" #include "util.h" #include "game.h" @@ -141,8 +142,14 @@ namespace battleship{ if(wtOpt != sol::nullopt) wt = unitTable[tblName][i + 1]["type"]; - Weapon *weapon = ((Weapon::Type)wt == Weapon::Type::FREEZER ? new CryoGun(this, unitTable, i) : new Weapon(this, unitTable, i)); - weapons.push_back(weapon); + switch((Weapon::Type)wt){ + case Weapon::Type::FREEZER: + weapons.push_back(new CryoGun(this, unitTable, i)); + break; + default: + weapons.push_back(new Weapon(this, unitTable, i)); + break; + } } } } diff --git a/weapon.cpp b/weapon.cpp index 3d32426..0d6d3a0 100644 --- a/weapon.cpp +++ b/weapon.cpp @@ -3,6 +3,7 @@ #include #include "map.h" +#include "unit.h" #include "util.h" #include "weapon.h" #include "player.h" @@ -19,11 +20,13 @@ namespace battleship{ Weapon::Weapon(Unit *u, sol::table unitTable, int wid) : unit(u), id(wid), + maxAngle(PI / 2 * .7), rateOfFire(unitTable["weapons"][wid + 1]["rateOfFire"]), damage(unitTable["weapons"][wid + 1]["damage"].get_or(0)) { sol::table weaponTable = unitTable["weapons"][wid + 1]; maxRange = weaponTable["maxRange"]; + maxFireAngle = weaponTable["maxFireAngle"].get_or(.4); orderType = (Order::TYPE)weaponTable["orderType"]; initProjectileData(weaponTable); @@ -49,7 +52,6 @@ namespace battleship{ for(int i = 0; i < numNodes; i++){ sol::table nodeTbl = weaponTable["nodes"][i + 1]; - maxFireAngle = nodeTbl["maxFireAngle"]; rotSpeed = nodeTbl["rotationSpeed"]; string name = nodeTbl["name"]; @@ -117,7 +119,7 @@ namespace battleship{ bool withinAngle = true; if(!nodes.empty()){ - Vector3 dirVec = nodes[0]->getGlobalAxis(2); + Vector3 dirVec = nodes[nodes.size() - 1]->getGlobalAxis(2); withinAngle = Vector3(dirVec.x, 0, dirVec.z).norm().getAngleBetween((targPos - unit->getPos()).norm()) <= maxFireAngle; } @@ -129,10 +131,8 @@ namespace battleship{ } void Weapon::useFx(FxManager::Fx *fx, Vector3 targPos, bool fire){ - if(fx && !fire) - FxManager::getSingleton()->addFx(fx); - else if(!fx) - return; + if(fx && !fire) FxManager::getSingleton()->addFx(fx); + else if(!fx) return; fx->toggleComponents(true); @@ -211,32 +211,42 @@ namespace battleship{ lastFireTime = getTime(); } + void Weapon::alignNode(Node *node, Vector3 targPos, bool vertical){ + Vector3 unitPos = unit->getPos(); + Vector3 unitUp = unit->getUpVec(); + Vector3 targDir = (targPos - unitPos).norm(); + + Vector3 compVec, rotAxis; + float rotAngle; + + if(vertical){ + compVec = getVecToPlane(unitPos, targDir, unitUp); + float angle1 = targDir.getAngleBetween(compVec); + float angle2 = node->getGlobalAxis(2).getAngleBetween(getVecToPlane(unitPos, node->getGlobalAxis(2), unitUp)); + float angleDiff = angle1 - angle2; + rotAngle = (rotSpeed < fabs(angleDiff) ? rotSpeed : fabs(angleDiff)) * (angleDiff > 0 ? -1 : 1); + + if(angle2 - rotAngle > maxAngle) + rotAngle = -(fabs(rotAngle) - (angle2 + fabs(rotAngle) - maxAngle)); + + rotAxis = Vector3::VEC_I; + } + else{ + targDir = getVecToPlane(unitPos, targDir, unitUp); + compVec = node->getGlobalAxis(2); + bool negate = (node->getGlobalAxis(0).getAngleBetween(targDir) < PI / 2); + float angle = compVec.getAngleBetween(targDir); + rotAngle = (negate ? 1 : -1) * (rotSpeed < angle ? rotSpeed : angle); + rotAxis = Vector3::VEC_J; + } + + Quaternion rot = Quaternion(rotAngle, rotAxis) * node->getOrientation(); + node->setOrientation(rot); + } + //TODO improve to allow for vertical alignment void Weapon::trackTarget(Vector3 targPos){ - if(nodes.empty()) return; - - Vector3 unitPos = unit->getPos(); - Vector3 targDir = (targPos - unitPos).norm(); - targDir = getVecToPlane(unitPos, targDir, unit->getUpVec()); - - Vector3 dirVec = getVecToPlane(unitPos, nodes[0]->getGlobalAxis(2), unit->getUpVec()); - Vector3 leftVec = nodes[0]->getGlobalAxis(0); - bool negate = (leftVec.getAngleBetween(targDir) < PI / 2); - - float angle = dirVec.getAngleBetween(targDir); - float rotAngle = (rotSpeed < angle ? rotSpeed : angle); - - Quaternion rot = Quaternion((negate ? 1 : -1) * rotAngle, Vector3::VEC_J) * nodes[0]->getOrientation(); - nodes[0]->setOrientation(rot); - } - - CryoGun::CryoGun(Unit *u, sol::table unitTable, int wid) : Weapon(u, unitTable, wid){} - - void CryoGun::updateTarget(GameObject *target){ - if(canFreeze()){ - Destructable *destructTarg = target->getDestructable(); - destructTarg->setFreezeStatus(destructTarg->getFreezeStatus() + 1); - lastFreezeTime = getTime(); - } + if(nodes.size() >= 1) alignNode(nodes[0], targPos, false); + if(nodes.size() >= 2) alignNode(nodes[1], targPos, true); } } diff --git a/weapon.h b/weapon.h index 91572e3..d9abd5f 100644 --- a/weapon.h +++ b/weapon.h @@ -1,14 +1,14 @@ #ifndef WEAPON_H #define WEAPON_H +#include "unit.h" + #include #include #include #include -#include "unit.h" - namespace vb01{ class Node; } @@ -37,12 +37,11 @@ namespace battleship{ Unit *unit = nullptr; Order::TYPE orderType; int id, projId = -1, damage = 0; - float minRange = 0, maxRange, rotSpeed, maxFireAngle; + float minRange = 0, maxRange, rotSpeed, maxFireAngle, horConstraint = 1.57, vertConstraint = 1.57, maxAngle; vb01::s64 lastFireTime = 0; FxManager::Fx *fireFx = nullptr; vb01::Quaternion projRot; vb01::Vector3 projPos; - float horConstraint = 1.57, vertConstraint = 1.57; std::vector nodes; vb01::Node *projPar = nullptr; static std::string LASER_FLAG; @@ -50,22 +49,13 @@ namespace battleship{ void initProjectileData(sol::table); void initNodes(sol::table); void useFx(FxManager::Fx*, vb01::Vector3, bool); + void alignNode(vb01::Node*, vb01::Vector3, bool); inline bool canFire(){return vb01::getTime() - lastFireTime > rateOfFire;} protected: int rateOfFire; virtual void updateTarget(GameObject*); }; - - class CryoGun : public Weapon{ - public: - CryoGun(Unit*, sol::table, int); - private: - vb01::s64 lastFreezeTime = 0; - - void updateTarget(GameObject*); - inline bool canFreeze(){return vb01::getTime() - lastFreezeTime > rateOfFire;} - }; } #endif