From 8b9e997dcd0e1e01bfa0e44c7d08fe214bffd9d1 Mon Sep 17 00:00:00 2001 From: Robosturm Date: Thu, 12 Oct 2023 17:29:01 +0200 Subject: [PATCH] #1703 --- CMakeLists.txt | 1 + ai/coreai.cpp | 15 +++ ai/coreai.h | 6 ++ ai/coreai_predefinedai.cpp | 4 +- ai/heavyai/heavyAiEnums.h | 9 ++ ai/heavyai/heavyai.cpp | 101 ++++++++++++++++++++ ai/heavyai/heavyai.h | 36 +++++++ ai/heavyai/situationevaluator.cpp | 2 +- ai/normalai.cpp | 3 +- ai/targetedunitpathfindingsystem.cpp | 2 +- game/unit.cpp | 5 + game/unit.h | 10 +- menue/gamemenue.cpp | 1 - resources/scripts/actions/ACTION_EXPLODE.js | 17 +++- resources/scripts/actions/ACTION_FLARE.js | 7 +- 15 files changed, 204 insertions(+), 15 deletions(-) create mode 100644 ai/heavyai/heavyAiEnums.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b7fd0564..8ba4c5cbf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -729,6 +729,7 @@ set(${PROJECT_NAME}_SRCS ai/proxyai.cpp ai/proxyai.h ai/normalai.cpp ai/normalai.h ai/heavyai/heavyai.cpp ai/heavyai/heavyai.h + ai/heavyai/heavyAiEnums.h ai/heavyai/situationevaluator.h ai/heavyai/situationevaluator.cpp ai/influencefrontmap.cpp ai/influencefrontmap.h ai/dummyai.h ai/dummyai.cpp diff --git a/ai/coreai.cpp b/ai/coreai.cpp index 9fe9e309f..61a5b2986 100644 --- a/ai/coreai.cpp +++ b/ai/coreai.cpp @@ -93,6 +93,21 @@ CoreAI::CoreAI(GameMap* pMap, GameEnums::AiTypes aiType, QString jsName) { m_flareInfo.unfogRange = erg.toNumber(); } + + + const QString funcGetDamage = "getDamage"; + erg = pInterpreter->doFunction(ACTION_EXPLODE, funcGetDamage); + if (erg.isNumber()) + { + m_explodeInfo.damage = erg.toNumber(); + } + const QString funcGetRange = "getRange"; + erg = pInterpreter->doFunction(ACTION_EXPLODE, funcGetRange); + if (erg.isNumber()) + { + m_explodeInfo.range = erg.toNumber(); + } + CONSOLE_PRINT("Creating core ai", GameConsole::eDEBUG); } diff --git a/ai/coreai.h b/ai/coreai.h index b3954b7d5..0afe3f5d9 100644 --- a/ai/coreai.h +++ b/ai/coreai.h @@ -853,5 +853,11 @@ public slots: qint32 unfogRange{0}; }; FlareInfo m_flareInfo; + struct ExplodeInfo + { + qint32 range{0}; + qint32 damage{0}; + }; + ExplodeInfo m_explodeInfo; QStringList m_iniFiles; }; diff --git a/ai/coreai_predefinedai.cpp b/ai/coreai_predefinedai.cpp index 8b8781d2c..894b47d60 100644 --- a/ai/coreai_predefinedai.cpp +++ b/ai/coreai_predefinedai.cpp @@ -127,7 +127,7 @@ bool CoreAI::moveBlackBombs(spQmlVectorUnit & pUnits, spQmlVectorUnit & pEnemyUn { UnitPathFindingSystem turnPfs(m_pMap, pUnit); turnPfs.explore(); - spQmlVectorPoint pPoints = GlobalUtils::getSpCircle(1, 3); + spQmlVectorPoint pPoints = GlobalUtils::getSpCircle(1, m_explodeInfo.range); auto targets = turnPfs.getAllNodePointsFast(); qint32 maxDamage = 0; std::vector bestTargets; @@ -135,7 +135,7 @@ bool CoreAI::moveBlackBombs(spQmlVectorUnit & pUnits, spQmlVectorUnit & pEnemyUn pAction->setTarget(QPoint(pUnit->Unit::getX(), pUnit->Unit::getY())); for (auto & target : targets) { - qint32 damageDone = m_pPlayer->getRocketTargetDamage(target.x(), target.y(), pPoints.get(), 5, 1.2f, GameEnums::RocketTarget_Money, true); + qint32 damageDone = m_pPlayer->getRocketTargetDamage(target.x(), target.y(), pPoints.get(), m_explodeInfo.damage, 1.2f, GameEnums::RocketTarget_Money, true); if (damageDone > maxDamage) { bestTargets.clear(); diff --git a/ai/heavyai/heavyAiEnums.h b/ai/heavyai/heavyAiEnums.h new file mode 100644 index 000000000..2d64fdf9f --- /dev/null +++ b/ai/heavyai/heavyAiEnums.h @@ -0,0 +1,9 @@ +#pragma once + +enum class AiCache +{ + MovementPoints, + MinFirerange, + MaxFirerange, + Max, +}; diff --git a/ai/heavyai/heavyai.cpp b/ai/heavyai/heavyai.cpp index 4ca5f1f89..c3b91f66b 100644 --- a/ai/heavyai/heavyai.cpp +++ b/ai/heavyai/heavyai.cpp @@ -4,6 +4,7 @@ #include "coreengine/globalutils.h" #include "ai/heavyai/heavyai.h" +#include "ai/heavyai/heavyAiEnums.h" #include "game/player.h" #include "game/gameaction.h" @@ -28,7 +29,107 @@ HeavyAi::HeavyAi(GameMap* pMap, QString type, GameEnums::AiTypes aiType) CONSOLE_PRINT("Creating heavy ai", GameConsole::eDEBUG); } +void HeavyAi::toggleAiPause() +{ + m_pause = !m_pause; +} + +void HeavyAi::showIslandMap(QString unitId) +{ + Unit unit(unitId, m_pPlayer, false, m_pMap); + qint32 unitIslandIdx = getIslandIndex(&unit); + if (unitIslandIdx >= 0 && unitIslandIdx < m_IslandMaps.size()) + { + m_IslandMaps[unitIslandIdx]->show(); + } +} + +void HeavyAi::hideIslandMap(QString unitId) +{ + Unit unit(unitId, m_pPlayer, false, m_pMap); + qint32 unitIslandIdx = getIslandIndex(&unit); + if (unitIslandIdx >= 0 && unitIslandIdx < m_IslandMaps.size()) + { + m_IslandMaps[unitIslandIdx]->hide(); + } +} + void HeavyAi::process() { + AI_CONSOLE_PRINT("NormalAi::process()", GameConsole::eDEBUG); + if (m_pause) + { + m_timer.start(1000); + return; + } + else + { + m_timer.stop(); + } + + spQmlVectorBuilding pBuildings = m_pPlayer->getSpBuildings(); + pBuildings->randomize(); + spQmlVectorUnit pUnits = m_pPlayer->getSpUnits(); + spQmlVectorUnit pEnemyUnits = m_pPlayer->getSpEnemyUnits(); + pEnemyUnits->pruneEnemies(pUnits.get(), m_enemyPruneRange); + qint32 cost = 0; + m_pPlayer->getSiloRockettarget(2, 3, cost); + m_missileTarget = (cost >= m_minSiloDamage); + updateUnitCache(pUnits); + updateUnitCache(pEnemyUnits); + if (useBuilding(pBuildings, pUnits)) + { + clearUnitCache(pUnits); + clearUnitCache(pEnemyUnits); + } + else + { + m_IslandMaps.clear(); + m_turnMode = GameEnums::AiTurnMode_EndOfDay; + if (useCOPower(pUnits, pEnemyUnits)) + { + m_usedTransportSystem = false; + m_usedPredefinedAi = false; + m_turnMode = GameEnums::AiTurnMode_DuringDay; + } + else + { + m_turnMode = GameEnums::AiTurnMode_StartOfDay; + finishTurn(); + } + } +} + +void HeavyAi::updateUnitCache(spQmlVectorUnit & pUnits) +{ + for(auto & pUnit : pUnits->getVector()) + { + auto & cache = pUnit->getAiCache(); + if (cache.size() != static_cast(AiCache::Max)) + { + QPoint pos = pUnit->getPosition(); + cache.resize(static_cast(AiCache::Max)); + cache[static_cast(AiCache::MovementPoints)] = pUnit->getMovementpoints(pos); + cache[static_cast(AiCache::MinFirerange)] = pUnit->getMinRange(pos); + cache[static_cast(AiCache::MaxFirerange)] = pUnit->getMaxRange(pos); + } + } + rebuildIsland(pUnits); +} + +void HeavyAi::clearUnitCache(spQmlVectorUnit & pUnits) +{ + for(auto & pUnit : pUnits->getVector()) + { + pUnit->getAiCache().clear(); + } +} +void HeavyAi::finishTurn() +{ + auto pUnits = m_pPlayer->getSpUnits(); + clearUnitCache(pUnits); + pUnits = m_pPlayer->getSpEnemyUnits(); + clearUnitCache(pUnits); + CoreAI::finishTurn(); } diff --git a/ai/heavyai/heavyai.h b/ai/heavyai/heavyai.h index 771539c4e..85e6d45a4 100644 --- a/ai/heavyai/heavyai.h +++ b/ai/heavyai/heavyai.h @@ -13,11 +13,47 @@ class HeavyAi final : public CoreAI explicit HeavyAi(GameMap* pMap, QString type, GameEnums::AiTypes aiType); virtual ~HeavyAi() = default; + /*******************************************************************/ + // debugging section + /*******************************************************************/ + /** + * @brief toggleAiPause for debugging + */ + Q_INVOKABLE void toggleAiPause(); + /** + * @brief showIslandMap + * @param unitId + */ + Q_INVOKABLE void showIslandMap(QString unitId); + /** + * @brief showIslandMap + * @param unitId + */ + Q_INVOKABLE void hideIslandMap(QString unitId); + public slots: /** * @brief process */ virtual void process() override; +protected: + /** + * @brief finishTurn + */ + virtual void finishTurn() override; + /** + * @brief clearUnitCache + */ + void clearUnitCache(spQmlVectorUnit & pUnits); + /** + * @brief updateUnitCache + * @param pUnits + */ + void updateUnitCache(spQmlVectorUnit & pUnits); +private: + double m_minSiloDamage{7000}; + QTimer m_timer; + bool m_pause{false}; }; Q_DECLARE_INTERFACE(HeavyAi, "HeavyAi"); diff --git a/ai/heavyai/situationevaluator.cpp b/ai/heavyai/situationevaluator.cpp index d44f6d103..4a70d4db1 100644 --- a/ai/heavyai/situationevaluator.cpp +++ b/ai/heavyai/situationevaluator.cpp @@ -66,7 +66,7 @@ void SituationEvaluator::getUnitsInRange(GameMap* pMap, const QPoint & searchPoi if (pTerrain != nullptr) { Unit* pUnit = pTerrain->getUnit(); - if (pUnit != nullptr) + if (pUnit != nullptr && pUnit->getHpRounded() > 0) { if (m_pOwner->isEnemyUnit(pUnit)) { diff --git a/ai/normalai.cpp b/ai/normalai.cpp index ccd8ba96c..376ad1281 100644 --- a/ai/normalai.cpp +++ b/ai/normalai.cpp @@ -190,8 +190,7 @@ void NormalAi::process() } spQmlVectorBuilding pBuildings = m_pPlayer->getSpBuildings(); pBuildings->randomize(); - spQmlVectorUnit pUnits; - pUnits = m_pPlayer->getSpUnits(); + spQmlVectorUnit pUnits = m_pPlayer->getSpUnits(); spQmlVectorUnit pEnemyUnits; spQmlVectorBuilding pEnemyBuildings; qint32 cost = 0; diff --git a/ai/targetedunitpathfindingsystem.cpp b/ai/targetedunitpathfindingsystem.cpp index 3821eb21d..60a896cf4 100644 --- a/ai/targetedunitpathfindingsystem.cpp +++ b/ai/targetedunitpathfindingsystem.cpp @@ -30,7 +30,7 @@ TargetedUnitPathFindingSystem::TargetedUnitPathFindingSystem(GameMap* pMap, Unit if (m_Targets.size() > maxTargets) { m_Targets.resize(maxTargets); - } + } setMovepoints(m_pUnit->getFuel() * 2); } diff --git a/game/unit.cpp b/game/unit.cpp index 7fd0bd7b8..e8be34d9c 100644 --- a/game/unit.cpp +++ b/game/unit.cpp @@ -626,6 +626,11 @@ qint32 Unit::getCoBonus(QPoint position, const QString & function, qint32(Player return bonus; } +QVector & Unit::getAiCache() +{ + return m_aiCache; +} + GameMap *Unit::getMap() const { return m_pMap; diff --git a/game/unit.h b/game/unit.h index 271fb56cb..6976009a7 100644 --- a/game/unit.h +++ b/game/unit.h @@ -183,7 +183,11 @@ class Unit final : public Tooltip, public FileSerializable, public JsThis * @return */ bool isStatusStealthedAndInvisible(Player* pPlayer, bool & terrainHide); - + /** + * @brief getAiCache + * @return + */ + QVector & getAiCache(); // js invokable functions /** * @brief getX @@ -1223,6 +1227,10 @@ class Unit final : public Tooltip, public FileSerializable, public JsThis * @brief m_sortValues values sto */ QVector m_sortValues; + /** + * @brief m_aiCache + */ + QVector m_aiCache; }; Q_DECLARE_INTERFACE(Unit, "Unit"); diff --git a/menue/gamemenue.cpp b/menue/gamemenue.cpp index b6a835882..b16769c32 100644 --- a/menue/gamemenue.cpp +++ b/menue/gamemenue.cpp @@ -1269,7 +1269,6 @@ void GameMenue::disconnected(quint64 socketID) { CONSOLE_PRINT("Handling player GameMenue::disconnect()", GameConsole::eDEBUG); bool showDisconnect = !m_pNetworkInterface->getIsServer(); - removeSyncSocket(socketID); auto & observer = m_pMap->getGameRules()->getObserverList(); bool observerDisconnect = observer.contains(socketID); if (observerDisconnect) diff --git a/resources/scripts/actions/ACTION_EXPLODE.js b/resources/scripts/actions/ACTION_EXPLODE.js index 090721cc2..1fb71d252 100644 --- a/resources/scripts/actions/ACTION_EXPLODE.js +++ b/resources/scripts/actions/ACTION_EXPLODE.js @@ -69,12 +69,23 @@ var Constructor = function() ACTION_EXPLODE.postAnimationTargetX = action.readDataInt32(); ACTION_EXPLODE.postAnimationTargetY = action.readDataInt32(); }; + + + this.getDamage = function() + { + return 4; + }; + this.getRange = function() + { + return 2; + }; + this.performPostAnimation = function(postAnimation, map) { var owner = ACTION_EXPLODE.postAnimationUnit.getOwner(); var x = ACTION_EXPLODE.postAnimationTargetX; var y = ACTION_EXPLODE.postAnimationTargetY; - var fields = globals.getCircle(1, 2); + var fields = globals.getCircle(1, ACTION_EXPLODE.getRange()); var size = fields.size(); for (var i = 0; i < size; i++) { @@ -85,7 +96,7 @@ var Constructor = function() var unit = terrain.getUnit(); if (unit !== null) { - unit.setHp(unit.getHpRounded() - 4); + unit.setHp(unit.getHpRounded() - ACTION_EXPLODE.getDamage()); if (unit.getHp() <= 0) { // we destroyed a unit @@ -95,7 +106,7 @@ var Constructor = function() } } } - var animation = GameAnimationFactory.createAnimation(map, x - 2, y - 3); + var animation = GameAnimationFactory.createAnimation(map, x - 2, y - 2); animation.addSprite("explosion+black_bomb", map.getImageSize() / 2, map.getImageSize() / 2, 0, 1.875); animation.setSound("explosion+land.wav"); // we destroyed a unit diff --git a/resources/scripts/actions/ACTION_FLARE.js b/resources/scripts/actions/ACTION_FLARE.js index 58de0cbec..9881cb3be 100644 --- a/resources/scripts/actions/ACTION_FLARE.js +++ b/resources/scripts/actions/ACTION_FLARE.js @@ -43,16 +43,15 @@ var Constructor = function() this.getMinRange = function() { return 1; - } - + }; this.getMaxRange = function() { return 5; - } + }; this.getUnfogRange = function() { return 2; - } + }; this.getStepData = function(action, data, map) {