mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-04 09:56:30 +00:00
SCUMM HE: Added implementation for Sortie and DefenderUnit classes
This commit is contained in:
parent
412ae07efb
commit
e4de5bf9ce
@ -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"
|
||||
|
||||
|
@ -27,11 +27,11 @@
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class ScummEngine;
|
||||
class ScummEngine_v71he;
|
||||
|
||||
extern ScummEngine *_vm;
|
||||
extern ScummEngine_v71he *_vm;
|
||||
|
||||
typedef Common::List<int>::iterator intVecItr;
|
||||
typedef Common::Array<int>::iterator intVecItr;
|
||||
|
||||
enum {
|
||||
TERRAIN_TYPE_GOOD = 0,
|
||||
@ -182,8 +182,8 @@ int TempChooseTarget(int behavior);
|
||||
|
||||
int GetEnergyHogType();
|
||||
|
||||
extern Common::List<int> lastXCoord[];
|
||||
extern Common::List<int> lastYCoord[];
|
||||
extern Common::Array<int> lastXCoord[];
|
||||
extern Common::Array<int> lastYCoord[];
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
|
@ -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<Node *> _children;
|
||||
Common::Array<Node *> _children;
|
||||
|
||||
int _depth;
|
||||
static int _nodeCount;
|
||||
@ -88,7 +88,7 @@ public:
|
||||
void setContainedObject(IContainedObject *value) { _contents = value; }
|
||||
IContainedObject *getContainedObject() { return _contents; }
|
||||
|
||||
Common::List<Node *> getChildren() const { return _children; }
|
||||
Common::Array<Node *> getChildren() const { return _children; }
|
||||
int generateChildren();
|
||||
int generateNextChild();
|
||||
Node *popChild();
|
||||
|
557
engines/scumm/he/moonbase/ai_targetacquisition.cpp
Normal file
557
engines/scumm/he/moonbase/ai_targetacquisition.cpp
Normal file
@ -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<DefenseUnit *>::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<uint>(_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<DefenseUnit *> thisEnemyDefenses;
|
||||
|
||||
// Copy the defensive unit list from the parent
|
||||
for (Common::Array<DefenseUnit *>::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<int>(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<int>(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<DefenseUnit *>::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<DefenseUnit *>::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<DefenseUnit *>::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<DefenseUnit *> thisEnemyDefenses = getEnemyDefenses();
|
||||
|
||||
for (Common::Array<DefenseUnit *>::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<DefenseUnit *>::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<DefenseUnit *>::iterator i = _enemyDefenses.begin(); i != _enemyDefenses.end(); ++i) {
|
||||
warning("Unit %d - Type: %d, Armor: %d, Status: %d", (*i)->getID(), (*i)->getType(), static_cast<int>((*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
|
150
engines/scumm/he/moonbase/ai_targetacquisition.h
Normal file
150
engines/scumm/he/moonbase/ai_targetacquisition.h
Normal file
@ -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<DefenseUnit *> _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<DefenseUnit *> 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<DefenseUnit *> 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
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -141,6 +141,7 @@ MODULE_OBJS += \
|
||||
he/logic/soccer.o \
|
||||
he/moonbase/ai_defenseunit.o \
|
||||
he/moonbase/ai_node.o \
|
||||
he/moonbase/ai_targetacquisition.o \
|
||||
he/moonbase/ai_types.o \
|
||||
he/moonbase/ai_weapon.o \
|
||||
he/moonbase/moonbase.o \
|
||||
|
@ -119,7 +119,10 @@ protected:
|
||||
ArrayHeader *getArray(int array);
|
||||
byte *defineArray(int array, int type, int dim2, int dim1);
|
||||
int findFreeArrayId();
|
||||
public:
|
||||
void nukeArray(int array);
|
||||
|
||||
protected:
|
||||
virtual int readArray(int array, int index, int base);
|
||||
virtual void writeArray(int array, int index, int base, int value);
|
||||
void shuffleArray(int num, int minIdx, int maxIdx);
|
||||
|
Loading…
x
Reference in New Issue
Block a user