From e4de5bf9ce8d447e5ab000aa354aafa513dc080b Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 20 May 2016 22:02:02 +0200 Subject: SCUMM HE: Added implementation for Sortie and DefenderUnit classes --- engines/scumm/he/moonbase/ai_defenseunit.cpp | 2 +- engines/scumm/he/moonbase/ai_main.h | 10 +- engines/scumm/he/moonbase/ai_node.h | 6 +- engines/scumm/he/moonbase/ai_targetacquisition.cpp | 557 +++++++++++++++++++++ engines/scumm/he/moonbase/ai_targetacquisition.h | 150 ++++++ engines/scumm/he/moonbase/moonbase.cpp | 6 + engines/scumm/he/moonbase/moonbase.h | 2 + engines/scumm/he/moonbase/moonbase_fow.cpp | 4 +- 8 files changed, 725 insertions(+), 12 deletions(-) create mode 100644 engines/scumm/he/moonbase/ai_targetacquisition.cpp create mode 100644 engines/scumm/he/moonbase/ai_targetacquisition.h (limited to 'engines/scumm/he') diff --git a/engines/scumm/he/moonbase/ai_defenseunit.cpp b/engines/scumm/he/moonbase/ai_defenseunit.cpp index 1312752fef..783c7c70ed 100644 --- a/engines/scumm/he/moonbase/ai_defenseunit.cpp +++ b/engines/scumm/he/moonbase/ai_defenseunit.cpp @@ -22,7 +22,7 @@ #include "common/rect.h" #include "common/util.h" -#include "scumm/scumm.h" +#include "scumm/he/intern_he.h" #include "scumm/he/moonbase/ai_defenseunit.h" #include "scumm/he/moonbase/ai_main.h" diff --git a/engines/scumm/he/moonbase/ai_main.h b/engines/scumm/he/moonbase/ai_main.h index d35cf8ec5a..cfd3aadc8a 100644 --- a/engines/scumm/he/moonbase/ai_main.h +++ b/engines/scumm/he/moonbase/ai_main.h @@ -27,11 +27,11 @@ namespace Scumm { -class ScummEngine; +class ScummEngine_v71he; -extern ScummEngine *_vm; +extern ScummEngine_v71he *_vm; -typedef Common::List::iterator intVecItr; +typedef Common::Array::iterator intVecItr; enum { TERRAIN_TYPE_GOOD = 0, @@ -182,8 +182,8 @@ int TempChooseTarget(int behavior); int GetEnergyHogType(); -extern Common::List lastXCoord[]; -extern Common::List lastYCoord[]; +extern Common::Array lastXCoord[]; +extern Common::Array lastYCoord[]; } // End of namespace Scumm diff --git a/engines/scumm/he/moonbase/ai_node.h b/engines/scumm/he/moonbase/ai_node.h index 00800c2129..454b98e0b5 100644 --- a/engines/scumm/he/moonbase/ai_node.h +++ b/engines/scumm/he/moonbase/ai_node.h @@ -23,7 +23,7 @@ #ifndef SCUMM_HE_MOONBASE_AI_NODE_H #define SCUMM_HE_MOONBASE_AI_NODE_H -#include "common/list.h" +#include "common/array.h" namespace Scumm { @@ -65,7 +65,7 @@ public: class Node { private: Node *_parent; - Common::List _children; + Common::Array _children; int _depth; static int _nodeCount; @@ -88,7 +88,7 @@ public: void setContainedObject(IContainedObject *value) { _contents = value; } IContainedObject *getContainedObject() { return _contents; } - Common::List getChildren() const { return _children; } + Common::Array getChildren() const { return _children; } int generateChildren(); int generateNextChild(); Node *popChild(); diff --git a/engines/scumm/he/moonbase/ai_targetacquisition.cpp b/engines/scumm/he/moonbase/ai_targetacquisition.cpp new file mode 100644 index 0000000000..0eebaef465 --- /dev/null +++ b/engines/scumm/he/moonbase/ai_targetacquisition.cpp @@ -0,0 +1,557 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "scumm/he/intern_he.h" +#include "scumm/he/moonbase/moonbase.h" + +#include "scumm/he/moonbase/ai_targetacquisition.h" +#include "scumm/he/moonbase/ai_main.h" +#include "scumm/he/moonbase/ai_weapon.h" + +namespace Scumm { + +int Sortie::_sSourceX = 0; +int Sortie::_sSourceY = 0; + +int Sortie::_sTargetX = 0; +int Sortie::_sTargetY = 0; + +Sortie::~Sortie() { + for (Common::Array::iterator k = _enemyDefenses.begin(); k != _enemyDefenses.end(); ++k) { + delete *k; + } +} + +void Sortie::setEnemyDefenses(int enemyDefensesScummArray, int defendX, int defendY) { + DefenseUnit *thisUnit; + int currentPlayer = GetCurrentPlayer(); + + for (int i = 0; i < 200; ++i) { + int thisElement = _vm->_moonbase->readFromArray(enemyDefensesScummArray, 0, i); + + if (thisElement) { + if (GetBuildingOwner(thisElement)) { + if (GetPlayerTeam(currentPlayer) != GetBuildingTeam(thisElement)) { + int type = GetBuildingType(thisElement); + + switch (type) { + case BUILDING_ANTI_AIR: + thisUnit = new AntiAirUnit(); + break; + + case BUILDING_SHIELD: + thisUnit = new ShieldUnit(); + break; + + case BUILDING_EXPLOSIVE_MINE: + if (GetDistance(GetHubX(thisElement), GetHubY(thisElement), defendX, defendY) < 90) + thisUnit = new MineUnit(); + else + thisUnit = NULL; + + break; + + case BUILDING_CRAWLER: + thisUnit = NULL; + break; + + default: + thisUnit = NULL; + break; + } + + if (thisUnit != NULL) { + thisUnit->setID(thisElement); + thisUnit->setPos(GetHubX(thisElement), GetHubY(thisElement)); + + if (GetBuildingState(thisElement)) thisUnit->setState(DUS_OFF); + + _enemyDefenses.push_back(thisUnit); + } + } + } + } else { + i = 200; + } + } +} + +int *Sortie::getShotPos() const { + int *retVal = new int[2]; + + retVal[0] = _shotPosX; + retVal[1] = _shotPosY; + + return retVal; +} + +int Sortie::numChildrenToGen() { + int retVal = MAX(_enemyDefenses.size(), 1) * NUM_SHOT_POSITIONS * NUM_WEAPONS; + return retVal; +} + +IContainedObject *Sortie::createChildObj(int index, int &completionFlag) { + float thisDamage; + Sortie *retSortie = new Sortie; + int activeDefenses = 0; + + Common::Array thisEnemyDefenses; + + // Copy the defensive unit list from the parent + for (Common::Array::iterator k = _enemyDefenses.begin(); k != _enemyDefenses.end(); ++k) { + DefenseUnit *temp; + + switch ((*k)->getType()) { + case DUT_ANTI_AIR: + temp = new AntiAirUnit(*k); + break; + + case DUT_SHIELD: + temp = new ShieldUnit(*k); + break; + + case DUT_MINE: + temp = new MineUnit(*k); + break; + + case DUT_CRAWLER: + temp = new CrawlerUnit(*k); + break; + + default: + temp = new ShieldUnit(*k); + break; + } + + thisEnemyDefenses.push_back(temp); + } + + // Calculate the current target from the index + DefenseUnit *currentTarget = *(thisEnemyDefenses.begin() + static_cast(index / (NUM_WEAPONS * NUM_SHOT_POSITIONS))); + + assert(currentTarget); + + // Pick correct weapon according to index + Weapon *currentWeapon = new Weapon(currentTarget->selectWeapon(index % NUM_WEAPONS)); + retSortie->setUnitType(currentWeapon->getTypeID()); + + // Calculate distance from target to source hub + int distance = GetDistance(currentTarget->getPosX(), currentTarget->getPosY(), getSourcePosX(), getSourcePosY()); + + // Pick correct shot position according to index + Common::Point *targetCoords; + targetCoords = currentTarget->createTargetPos((static_cast(index / NUM_WEAPONS) % NUM_SHOT_POSITIONS), distance, currentWeapon->getTypeID(), getSourcePosX(), getSourcePosY()); + retSortie->setShotPos(targetCoords->x, targetCoords->y); + + // Set the g value based on cost of the weapon + retSortie->setValueG(getG() + currentWeapon->getCost()); + + int AAcounter = 3; + + // Loop through defensive units, toggling anti-air units and deciding if this weapon will land safely + for (Common::Array::iterator i = thisEnemyDefenses.begin(); i != thisEnemyDefenses.end(); ++i) { + distance = GetDistance((*i)->getPosX(), (*i)->getPosY(), targetCoords->x, targetCoords->y); + + // Check to see if we're within an active defense's radius + if ((distance < (*i)->getRadius()) && ((*i)->getState() == DUS_ON)) { + activeDefenses++; + + // Turn off this anti-air and drop the coverage count + if (((*i)->getType() == DUT_ANTI_AIR)) { + (*i)->setState(DUS_OFF); + + if (currentWeapon->getTypeID() == ITEM_CLUSTER) + AAcounter--; + else + AAcounter = 0; + } + + // Essentially disable this weapon choice, due to its impact with a shield, or untriggered anti-air + if (((*i)->getType() == DUT_SHIELD) || !AAcounter) { + retSortie->setValueG(1000); + i = thisEnemyDefenses.end() - 1; + } + } else { + // Turn on any anti-airs that were off the previous turn + if (((*i)->getType() == DUT_ANTI_AIR) && ((*i)->getState() == DUS_OFF)) + (*i)->setState(DUS_ON); + } + } + + // Turn on all the non-anti-air units in preparation for emp's and the next turn + for (Common::Array::iterator i = thisEnemyDefenses.begin(); i != thisEnemyDefenses.end(); ++i) { + if ((*i)->getType() != DUT_ANTI_AIR) { + (*i)->setState(DUS_ON); + } + } + + // If this weapon is still valid + if (retSortie->getValueG() < 1000) { + // Apply emp effects and damage to all units in range of weapon + for (Common::Array::iterator i = thisEnemyDefenses.begin(); i != thisEnemyDefenses.end(); ) { + // Special simulated crawler detonation location used, since it walks a bit + if (currentWeapon->getTypeID() == ITEM_CRAWLER) + distance = GetDistance((*i)->getPosX(), (*i)->getPosY(), currentTarget->getPosX(), currentTarget->getPosY()); + // Normal detonation location used here + else { + distance = GetDistance((*i)->getPosX(), (*i)->getPosY(), targetCoords->x, targetCoords->y); + } + + if (distance < currentWeapon->getRadius()) { + // Apply damage + thisDamage = currentWeapon->getDamage(); + + if ((AAcounter != 3) && (currentWeapon->getTypeID() == ITEM_CLUSTER)) + thisDamage = 0; + + if (!_vm->_rnd.getRandomNumber(4)) + currentWeapon->setTypeID(ITEM_MINE); + + (*i)->setDamage(thisDamage); + + // Apply emp effect + if (currentWeapon->getTypeID() == ITEM_EMP) { + (*i)->setState(DUS_OFF); + } + + // Remove destroyed defenses + if ((*i)->getArmor() <= 0) { + delete *i; + i = thisEnemyDefenses.erase(i); + } else { + ++i; + } + } else { + ++i; + } + } + } + + retSortie->setEnemyDefenses(thisEnemyDefenses); + + delete targetCoords; + delete currentWeapon; + return retSortie; +} + +float Sortie::calcH() { + float retValue = 0; + Common::Array thisEnemyDefenses = getEnemyDefenses(); + + for (Common::Array::iterator i = thisEnemyDefenses.begin(); i != thisEnemyDefenses.end(); ++i) { + if ((*i)->getState() == DUS_ON) { + switch ((*i)->getType()) { + case DUT_ANTI_AIR: + retValue += 1; + + case DUT_MINE: + retValue += 1; + break; + + case DUT_SHIELD: + retValue += 1; + break; + } + } + } + + return retValue; +} + +int Sortie::checkSuccess() { + if (!_enemyDefenses.size()) return SUCCESS; + + int targetX = getTargetPosX(); + int targetY = getTargetPosY(); + + int targetCheck = 0; + + for (Common::Array::iterator i = _enemyDefenses.begin(); i != _enemyDefenses.end(); ++i) { + if (((*i)->getState() == DUS_ON) && ((*i)->getType() != DUT_HUB)) { + return 0; + } + + if (((*i)->getPosX() == targetX) && ((*i)->getPosY() == targetY)) targetCheck = 1; + } + + if (!targetCheck) + return SUCCESS; + + // If shot pos == target pos return SUCCESS; + if ((targetX == getShotPosX()) && (getTargetPosY() == getShotPosY())) { + return SUCCESS; + } + + return 0; +} + +float Sortie::calcT() { + return (checkSuccess() != SUCCESS) ? (getG() + calcH()) : SUCCESS; +} + +IContainedObject *Sortie::duplicate() { + return this; +} + + +void Sortie::printEnemyDefenses() { + for (Common::Array::iterator i = _enemyDefenses.begin(); i != _enemyDefenses.end(); ++i) { + warning("Unit %d - Type: %d, Armor: %d, Status: %d", (*i)->getID(), (*i)->getType(), static_cast((*i)->getArmor()), (*i)->getState()); + } +} + +int Defender::calculateDefenseUnitPosition(int targetX, int targetY, int index) { + int currentPlayer = GetCurrentPlayer(); + + //Get list of near hubs + int unitsArray = GetUnitsWithinRadius(targetX + 5, targetY, 480); + + const int NUM_HUBS = 10; + //Order on dist + int hubArray[NUM_HUBS] = { 0 }; + int hubIndex = 0; + + for (int i = 0; i < 200; ++i) { + int thisUnit = _vm->_moonbase->readFromArray(unitsArray, 0, i); + + if (thisUnit) { + if (((GetBuildingType(thisUnit) == BUILDING_MAIN_BASE) || (GetBuildingType(thisUnit) == BUILDING_OFFENSIVE_LAUNCHER)) && (GetBuildingOwner(thisUnit) == currentPlayer)) { + for (int j = 0; j < NUM_HUBS; ++j) { + if (hubArray[j]) { + int distCurrent = GetDistance(targetX, targetY, GetHubX(thisUnit), GetHubY(thisUnit)); + int distSaved = GetDistance(targetX, targetY, GetHubX(hubArray[j]), GetHubY(hubArray[j])); + + if (distCurrent < distSaved) { + hubArray[hubIndex] = hubArray[j]; + hubArray[j] = thisUnit; + ++hubIndex; + j = 100; + } + } else { + hubArray[j] = thisUnit; + ++hubIndex; + j = 100; + } + } + } + } + + if (hubIndex >= NUM_HUBS) { + hubIndex = NUM_HUBS; + i = 200; + } + } + + _vm->nukeArray(unitsArray); + + //Check if repair is needed + int targetUnit = GetClosestUnit(targetX + 5, targetY, 15, currentPlayer, 1, 0, 0, 0); + + if (targetUnit && (targetUnit != BUILDING_CRAWLER) && (GetBuildingTeam(targetUnit) == GetPlayerTeam(currentPlayer))) { + int armor = GetBuildingArmor(targetUnit); + + if (armor < GetBuildingMaxArmor(targetUnit)) { + unitsArray = GetUnitsWithinRadius(targetX + 5, targetY, 170); + int defCount = 0; + + for (int i = 0; i < 200; ++i) { + int thisUnit = _vm->_moonbase->readFromArray(unitsArray, 0, i); + + if (thisUnit) { + if (((GetBuildingType(thisUnit) == BUILDING_SHIELD) || (GetBuildingType(thisUnit) == BUILDING_ANTI_AIR)) && (GetBuildingOwner(thisUnit) == currentPlayer) && (GetBuildingState(thisUnit) == 0)) { + ++defCount; + i = 200; + } + } + } + + _vm->nukeArray(unitsArray); + + if (defCount) { + //repair + int hubUnit = GetClosestUnit(targetX, targetY, 480, currentPlayer, 1, BUILDING_MAIN_BASE, 1, 110); + + if (hubUnit && (hubUnit != targetUnit)) { + int powAngle = abs(GetPowerAngleFromPoint(GetHubX(hubUnit), GetHubY(hubUnit), targetX, targetY, 20)); + int power = powAngle / 360; + int angle = powAngle - (power * 360); + + setTargetX(targetX); + setTargetY(targetY); + + setSourceUnit(hubUnit); + setUnit(ITEM_REPAIR); + setPower(power); + setAngle(angle); + + return 1; + } + } + } + } + + //For each hub + for (int i = 0; i < MIN(NUM_HUBS, hubIndex); ++i) { + int hubX = GetHubX(hubArray[i]); + int hubY = GetHubY(hubArray[i]); + //Get angle to hub + int directAngleToHub = 0; + + //If this hub is the target + if ((hubX == targetX) && (hubY == targetY)) { + //make the angle seed point at the closest enemy + int enemyUnit = GetClosestUnit(hubX, hubY, GetMaxX(), currentPlayer, 0, 0, 0); + directAngleToHub = GetAngle(targetX, targetY, GetHubX(enemyUnit), GetHubY(enemyUnit)); + } else { + directAngleToHub = GetAngle(targetX, targetY, hubX, hubY); + } + + //Number of random chances to land + for (int j = 0; j < 3; ++j) { + //Pick random angle and dist within semicircle (-90 to +90) and (40 to 150) + int randAngle = directAngleToHub + _vm->_rnd.getRandomNumber(179) - 90; + int randDist = _vm->_rnd.getRandomNumber(109) + 40; + + int x = targetX + randDist * cos(degToRad(randAngle)); + int y = targetY + randDist * sin(degToRad(randAngle)); + + int powAngle = GetPowerAngleFromPoint(hubX, hubY, x, y, 20); + + if (powAngle < 0) + continue; + + int power = powAngle / 360; + int angle = powAngle - (power * 360); + + int coords = 0; + coords = SimulateBuildingLaunch(hubX, hubY, power, angle, 100, 0); + + //if valid, return + if (coords > 0) { + //warning("The prospective launching hub for this defensive unit is: %d", hubArray[i]); + + setSourceX(hubX); + setSourceY(hubY); + setTargetX((x + GetMaxX()) % GetMaxX()); + setTargetY((y + GetMaxY()) % GetMaxY()); + setSourceUnit(hubArray[i]); + + int unitsArray2 = GetUnitsWithinRadius(targetX + 5, targetY, 200); + int shieldCount = 0; + + for (int k = 0; k < 200; ++k) { + int thisUnit = _vm->_moonbase->readFromArray(unitsArray2, 0, k); + + if (thisUnit) { + if ((GetBuildingType(thisUnit) == BUILDING_SHIELD) && (GetBuildingOwner(thisUnit) == currentPlayer)) + shieldCount++; + + if ((GetBuildingType(thisUnit) == BUILDING_BRIDGE) && (GetBuildingOwner(thisUnit) == currentPlayer)) { + shieldCount--; + shieldCount = MAX(-1, shieldCount); + } + } + } + + if ((_vm->_rnd.getRandomNumber((int)pow(3, shieldCount + 1) - 1) == 0) && (GetPlayerEnergy() > 6)) + setUnit(ITEM_SHIELD); + else + setUnit(ITEM_ANTIAIR); + + setPower(power); + setAngle(angle); + + _vm->nukeArray(unitsArray2); + return 1; + } + + if (coords < 0) { + //drop a bridge for the cord + int yCoord = -coords / GetMaxX(); + int xCoord = -coords - (yCoord * GetMaxX()); + + if (CheckIfWaterState(xCoord, yCoord)) { + + int terrainSquareSize = GetTerrainSquareSize(); + xCoord = ((xCoord / terrainSquareSize * terrainSquareSize) + (terrainSquareSize / 2)); + yCoord = ((yCoord / terrainSquareSize * terrainSquareSize) + (terrainSquareSize / 2)); + + int xDist = xCoord - x; + int yDist = yCoord - y; + x = xCoord + (terrainSquareSize * 1.414 * (xDist / (abs(xDist) + 1))); + y = yCoord + (terrainSquareSize * 1.414 * (yDist / (abs(yDist) + 1))); + + setTargetX(x); + setTargetY(y); + + int nextUnit = GetClosestUnit(x, y, 480, GetCurrentPlayer(), 1, BUILDING_MAIN_BASE, 1, 120); + powAngle = GetPowerAngleFromPoint(GetHubX(nextUnit), GetHubY(nextUnit), x, y, 15); + + powAngle = abs(powAngle); + power = powAngle / 360; + angle = powAngle - (power * 360); + + setSourceUnit(nextUnit); + setUnit(ITEM_BRIDGE); + setPower(power); + setAngle(angle); + + return 1; + } + } + } + } + + // Else create new hub + int count = 0; + int coords = 0; + + if (hubIndex == 0) return -3; + + do { + int sourceHub = hubArray[_vm->_rnd.getRandomNumber(hubIndex - 1)]; + + setSourceX(GetHubX(sourceHub)); + setSourceY(GetHubY(sourceHub)); + setSourceUnit(sourceHub); + setUnit(ITEM_HUB); + setPower(_vm->_rnd.getRandomNumber(299) + 200); + setAngle(_vm->_rnd.getRandomNumber(359)); + count++; + + if (count > (NUM_HUBS * 3)) break; + + coords = SimulateBuildingLaunch(getSourceX(), getSourceY(), getPower(), getAngle(), 100, 0); + } while (coords <= 0); + + if (coords > 0) { + setTargetX(coords % GetMaxX()); + setTargetY(coords / GetMaxX()); + } else { + setTargetX(0); + setTargetY(0); + } + + return -1; +} + +} // End of namespace Scumm diff --git a/engines/scumm/he/moonbase/ai_targetacquisition.h b/engines/scumm/he/moonbase/ai_targetacquisition.h new file mode 100644 index 0000000000..cf8f295c70 --- /dev/null +++ b/engines/scumm/he/moonbase/ai_targetacquisition.h @@ -0,0 +1,150 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SCUMM_HE_MOONBASE_AI_TARGETACQUISITION_H +#define SCUMM_HE_MOONBASE_AI_TARGETACQUISITION_H + +#include "scumm/he/moonbase/ai_defenseunit.h" +#include "scumm/he/moonbase/ai_node.h" +#include "scumm/he/moonbase/ai_tree.h" + +namespace Scumm { + +const int NUM_IMPT_UNITS = 3; +const int NUM_SHOT_POSITIONS = 1; +const int NUM_WEAPONS = 3; + +class Sortie : public IContainedObject { +private: + static int _sSourceX; + static int _sSourceY; + + static int _sTargetX; + static int _sTargetY; + + int _unitType; + int _shotPosX, _shotPosY; + Common::Array _enemyDefenses; + + +public: + Sortie() {} + virtual ~Sortie(); + + static void setSourcePos(int x, int y) { + _sSourceX = x; + _sSourceY = y; + } + static void setTargetPos(int x, int y) { + _sTargetX = x; + _sTargetY = y; + } + + void setUnitType(int unitType) { _unitType = unitType; } + + void setShotPosX(int shotPosX) { _shotPosX = shotPosX; } + void setShotPosY(int shotPosY) { _shotPosY = shotPosY; } + void setShotPos(int shotPosX, int shotPosY) { + _shotPosX = shotPosX; + _shotPosY = shotPosY; + } + + void setEnemyDefenses(Common::Array enemyDefenses) { + _enemyDefenses = enemyDefenses; + } + void setEnemyDefenses(int enemyDefensesScummArray, int defendX, int defendY); + + void printEnemyDefenses(); + + static int getSourcePosX() { return _sSourceX; } + static int getSourcePosY() { return _sSourceY; } + static int getTargetPosX() { return _sTargetX; } + static int getTargetPosY() { return _sTargetY; } + + int getUnitType() const { return _unitType; } + + int getShotPosX() const { return _shotPosX; } + int getShotPosY() const { return _shotPosY; } + int *getShotPos() const; + + Common::Array getEnemyDefenses() const { return _enemyDefenses; } + + virtual IContainedObject *duplicate(); + + virtual int numChildrenToGen(); + virtual IContainedObject *createChildObj(int, int &completionFlag); + + + virtual float calcH(); + virtual int checkSuccess(); + virtual float calcT(); +}; + +class Defender { +private: + int _sourceX; + int _sourceY; + int _targetX; + int _targetY; + int _sourceUnit; + int _power; + int _angle; + int _unit; + +public: + void setSourceX(int sourceX) { _sourceX = sourceX; } + void setSourceY(int sourceY) { _sourceY = sourceY; } + void setTargetX(int targetX) { _targetX = targetX; } + void setTargetY(int targetY) { _targetY = targetY; } + void setSourceUnit(int sourceUnit) { _sourceUnit = sourceUnit; } + void setPower(int power) { _power = power; } + void setAngle(int angle) { _angle = angle; } + void setUnit(int unit) { _unit = unit; } + + int getSourceX() const { return _sourceX; } + int getSourceY() const { return _sourceY; } + int getTargetX() const { return _targetX; } + int getTargetY() const { return _targetY; } + int getSourceUnit() const { return _sourceUnit; } + int getPower() const { return _power; } + int getAngle() const { return _angle; } + int getUnit() const { return _unit; } + + int calculateDefenseUnitPosition(int targetX, int targetY, int index); +}; + +class defenseUnitCompare { +public: + bool operator()(DefenseUnit *x, DefenseUnit *y) { + //disabled units go at the end + if (x->getState() == DUS_OFF) { + warning("OFF"); + return 0; + } + + return x->getDistanceTo() < y->getDistanceTo(); + } +}; + +} // End of namespace Scumm + +#endif diff --git a/engines/scumm/he/moonbase/moonbase.cpp b/engines/scumm/he/moonbase/moonbase.cpp index 34d4368725..9cc5040ea6 100644 --- a/engines/scumm/he/moonbase/moonbase.cpp +++ b/engines/scumm/he/moonbase/moonbase.cpp @@ -32,6 +32,12 @@ Moonbase::Moonbase(ScummEngine_v71he *vm) : _vm(vm) { Moonbase::~Moonbase() { } +int Moonbase::readFromArray(int array, int y, int x) { + _vm->VAR(116) = array; + + return _vm->readArray(116, y, x); +} + void Moonbase::blitT14WizImage(uint8 *dst, int dstw, int dsth, int dstPitch, const Common::Rect *clipBox, uint8 *wizd, int x, int y, int rawROP, int paramROP) { bool premulAlpa = false; diff --git a/engines/scumm/he/moonbase/moonbase.h b/engines/scumm/he/moonbase/moonbase.h index 0b47ba6dc3..7b2bdeb46b 100644 --- a/engines/scumm/he/moonbase/moonbase.h +++ b/engines/scumm/he/moonbase/moonbase.h @@ -34,6 +34,8 @@ public: Moonbase(ScummEngine_v71he *vm); ~Moonbase(); + int readFromArray(int array, int y, int x); + void blitT14WizImage(uint8 *dst, int dstw, int dsth, int dstPitch, const Common::Rect *clipBox, uint8 *wizd, int srcx, int srcy, int rawROP, int paramROP); diff --git a/engines/scumm/he/moonbase/moonbase_fow.cpp b/engines/scumm/he/moonbase/moonbase_fow.cpp index 3f3730b6f1..48c2219926 100644 --- a/engines/scumm/he/moonbase/moonbase_fow.cpp +++ b/engines/scumm/he/moonbase/moonbase_fow.cpp @@ -158,9 +158,7 @@ enum FOWElement { }; int Moonbase::readFOWVisibilityArray(int array, int y, int x) { - _vm->VAR(116) = array; - - if (_vm->readArray(116, y, x) > 0) + if (readFromArray(array, y, x) > 0) return FOW_EMPTY; return FOW_SOLID; -- cgit v1.2.3