Skip to content

Commit ec242f1

Browse files
committed
another explosion fix
1 parent edf931c commit ec242f1

1 file changed

Lines changed: 89 additions & 86 deletions

File tree

src/Battlescape/TileEngine.cpp

Lines changed: 89 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,7 @@ void TileEngine::explode(const Position &center, int power, ItemDamageType type,
11181118

11191119
int exHeight = std::max(0, std::min(3, Options::battleExplosionHeight));
11201120
int vertdec = 1000; //default flat explosion
1121+
int dmgRng = (type == DT_HE || Options::TFTDDamage) ? 50 : 100;
11211122

11221123
switch (exHeight)
11231124
{
@@ -1131,7 +1132,6 @@ void TileEngine::explode(const Position &center, int power, ItemDamageType type,
11311132
vertdec = 5;
11321133
}
11331134

1134-
11351135
for (int fi = -90; fi <= 90; fi += 5)
11361136
{
11371137
// raytrace every 3 degrees makes sure we cover all tiles in a circle.
@@ -1160,7 +1160,6 @@ void TileEngine::explode(const Position &center, int power, ItemDamageType type,
11601160
ret = tilesAffected.insert(dest); // check if we had this tile already
11611161
if (ret.second)
11621162
{
1163-
int dmgRng = (type == DT_HE || Options::TFTDDamage) ? 50 : 100;
11641163
int min = power_ * (100 - dmgRng) / 100;
11651164
int max = power_ * (100 + dmgRng) / 100;
11661165
BattleUnit *bu = dest->getUnit();
@@ -1325,10 +1324,9 @@ void TileEngine::explode(const Position &center, int power, ItemDamageType type,
13251324
calculateFOV(center / Position(16,16,24));
13261325
}
13271326

1328-
13291327
/**
13301328
* Applies the explosive power to the tile parts. This is where the actual destruction takes place.
1331-
* Must affect 7 objects (6 box sides and the object inside).
1329+
* Must affect 9 objects (6 box sides and the object inside plus 2 outer walls).
13321330
* @param tile Tile affected.
13331331
* @return True if the objective was destroyed.
13341332
*/
@@ -1339,77 +1337,96 @@ bool TileEngine::detonate(Tile* tile)
13391337

13401338
tile->setExplosive(0,true);
13411339
bool objective = false;
1342-
Tile* tiles[7];
1343-
static const int parts[7]={0,1,2,0,1,2,3};
1340+
Tile* tiles[9];
1341+
static const int parts[9]={0,1,2,0,1,2,3,3,3}; //6th is the object of current
13441342
Position pos = tile->getPosition();
1343+
13451344
tiles[0] = _save->getTile(Position(pos.x, pos.y, pos.z+1)); //ceiling
13461345
tiles[1] = _save->getTile(Position(pos.x+1, pos.y, pos.z)); //east wall
13471346
tiles[2] = _save->getTile(Position(pos.x, pos.y+1, pos.z)); //south wall
13481347
tiles[3] = tiles[4] = tiles[5] = tiles[6] = tile;
1348+
tiles[7] = _save->getTile(Position(pos.x, pos.y-1, pos.z)); //north bigwall
1349+
tiles[8] = _save->getTile(Position(pos.x-1, pos.y, pos.z)); //west bigwall
13491350

13501351
// explosions create smoke which only stays 1 or 2 turns
13511352
// tile->setSmoke(std::max(1, std::min(tile->getSmoke() + RNG::generate(0,2), 15)));
13521353

13531354
int remainingPower, fireProof, fuel;
1354-
bool destroyed;
1355-
for (int i = 0; i < 7; ++i)
1356-
{
1357-
if(tiles[i] && tiles[i]->getMapData(parts[i]))
1358-
{
1359-
remainingPower = explosive;
1360-
destroyed = false;
1361-
int volume = 0;
1362-
int currentpart = parts[i], currentpart2, diemcd;
1363-
fireProof = tiles[i]->getFlammability(currentpart);
1364-
fuel = tiles[i]->getFuel(currentpart) + 1;
1365-
// get the volume of the object by checking it's loftemps objects.
1366-
for (int j=0; j < 12; j++)
1355+
bool destroyed, bigwalldestroyed = true;
1356+
for (int i = 8; i >=0; --i)
1357+
{
1358+
if (!tiles[i] || !tiles[i]->getMapData(parts[i]))
1359+
continue; //skip out of map and emptiness
1360+
int bigwall = tiles[i]->getMapData(parts[i])->getBigWall();
1361+
if (i > 6 && !( (bigwall==1) || (bigwall==8) || (i==8 && bigwall==6) || (i==7 && bigwall==7)))
1362+
continue;
1363+
if (!bigwalldestroyed && parts[i]==0) //when ground shouldn't be destroyed
1364+
continue;
1365+
remainingPower = explosive;
1366+
destroyed = false;
1367+
int volume = 0;
1368+
int currentpart = parts[i], currentpart2, diemcd;
1369+
fireProof = tiles[i]->getFlammability(currentpart);
1370+
fuel = tiles[i]->getFuel(currentpart) + 1;
1371+
// get the volume of the object by checking it's loftemps objects.
1372+
for (int j = 0; j < 12; j++)
1373+
{
1374+
if (tiles[i]->getMapData(currentpart)->getLoftID(j) != 0)
1375+
++volume;
1376+
}
1377+
if ( i == 6 &&
1378+
(bigwall == 2 || bigwall == 3) && //diagonals
1379+
(2 * tiles[i]->getMapData(currentpart)->getArmor()) > remainingPower) //not enough to destroy
1380+
{
1381+
bigwalldestroyed = false;
1382+
}
1383+
// iterate through tile armor and destroy if can
1384+
while ( tiles[i]->getMapData(currentpart) &&
1385+
(2 * tiles[i]->getMapData(currentpart)->getArmor()) <= remainingPower &&
1386+
tiles[i]->getMapData(currentpart)->getArmor() != 255)
1387+
{
1388+
if ( i == 6 && (bigwall == 2 || bigwall == 3)) //diagonals for the current tile
13671389
{
1368-
if (tiles[i]->getMapData(currentpart)->getLoftID(j) != 0)
1369-
++volume;
1390+
bigwalldestroyed = true;
13701391
}
1371-
// iterate through tile armor and destroy if can
1372-
while ( tiles[i]->getMapData(currentpart) &&
1373-
(2 * tiles[i]->getMapData(currentpart)->getArmor()) <= remainingPower &&
1374-
tiles[i]->getMapData(currentpart)->getArmor() != 255)
1392+
remainingPower -= 2 * tiles[i]->getMapData(currentpart)->getArmor();
1393+
destroyed = true;
1394+
if (_save->getMissionType() == "STR_BASE_DEFENSE" &&
1395+
tiles[i]->getMapData(currentpart)->isBaseModule())
13751396
{
1376-
remainingPower -= 2 * tiles[i]->getMapData(currentpart)->getArmor();
1377-
destroyed = true;
1378-
if (_save->getMissionType() == "STR_BASE_DEFENSE" &&
1379-
tiles[i]->getMapData(currentpart)->isBaseModule())
1380-
{
1381-
_save->getModuleMap()[tile->getPosition().x/10][tile->getPosition().y/10].second--;
1382-
}
1383-
//this trick is to follow transformed object parts (object can become a ground)
1384-
diemcd = tiles[i]->getMapData(currentpart)->getDieMCD();
1385-
if (diemcd!=0)
1386-
currentpart2 = tiles[i]->getMapData(currentpart)->getDataset()->getObjects()->at(diemcd)->getObjectType();
1387-
else
1388-
currentpart2 = currentpart;
1389-
if (tiles[i]->destroy(currentpart))
1390-
objective = true;
1391-
currentpart = currentpart2;
1392-
if (tiles[i]->getMapData(currentpart)) // take new values
1393-
{
1394-
fireProof = tiles[i]->getFlammability(currentpart);
1395-
fuel = tiles[i]->getFuel(currentpart) + 1;
1396-
}
1397+
_save->getModuleMap()[tile->getPosition().x/10][tile->getPosition().y/10].second--;
13971398
}
1398-
// set tile on fire
1399-
if ((2 * fireProof) < remainingPower)
1399+
//this trick is to follow transformed object parts (object can become a ground)
1400+
diemcd = tiles[i]->getMapData(currentpart)->getDieMCD();
1401+
if (diemcd!=0)
1402+
currentpart2 = tiles[i]->getMapData(currentpart)->getDataset()->getObjects()->at(diemcd)->getObjectType();
1403+
else
1404+
currentpart2 = currentpart;
1405+
if (tiles[i]->destroy(currentpart))
1406+
objective = true;
1407+
currentpart = currentpart2;
1408+
if (tiles[i]->getMapData(currentpart)) // take new values
14001409
{
1401-
// if (tiles[i]->getMapData(MapData::O_FLOOR) || tiles[i]->getMapData(MapData::O_OBJECT))
1402-
tiles[i]->setFire(fuel);
1410+
fireProof = tiles[i]->getFlammability(currentpart);
1411+
fuel = tiles[i]->getFuel(currentpart) + 1;
1412+
}
1413+
}
1414+
// set tile on fire
1415+
if ((2 * fireProof) < remainingPower)
1416+
{
1417+
if (tiles[i]->getMapData(MapData::O_FLOOR) || tiles[i]->getMapData(MapData::O_OBJECT))
1418+
{
1419+
tiles[i]->setFire(fuel);
14031420
tiles[i]->setSmoke(std::max(1, std::min(15 - (fireProof / 10), 12)));
14041421
}
1405-
// add some smoke if tile was destroyed and not set on fire
1406-
if (destroyed && !tiles[i]->getFire())
1422+
}
1423+
// add some smoke if tile was destroyed and not set on fire
1424+
if (destroyed && !tiles[i]->getFire())
1425+
{
1426+
int smoke = RNG::generate(1, (volume / 2) + 3) + (volume / 2);
1427+
if (smoke > tiles[i]->getSmoke())
14071428
{
1408-
int smoke = RNG::generate(1, (volume / 2) + 3) + (volume / 2);
1409-
if (smoke > tiles[i]->getSmoke())
1410-
{
1411-
tiles[i]->setSmoke(std::max(0, std::min(smoke, 15)));
1412-
}
1429+
tiles[i]->setSmoke(std::max(0, std::min(smoke, 15)));
14131430
}
14141431
}
14151432
}
@@ -1543,13 +1560,9 @@ int TileEngine::horizontalBlockage(Tile *startTile, Tile *endTile, ItemDamageTyp
15431560
block = (blockage(startTile,MapData::O_NORTHWALL, type) + blockage(endTile,MapData::O_WESTWALL, type))/2
15441561
+ (blockage(_save->getTile(startTile->getPosition() + oneTileEast),MapData::O_WESTWALL, type)
15451562
+ blockage(_save->getTile(startTile->getPosition() + oneTileEast),MapData::O_NORTHWALL, type))/2;
1546-
1547-
if (!endTile->getMapData(MapData::O_OBJECT))
1548-
{
1549-
block += (blockage(_save->getTile(startTile->getPosition() + oneTileEast),MapData::O_OBJECT, type, direction)
1550-
+ blockage(_save->getTile(startTile->getPosition() + oneTileNorth),MapData::O_OBJECT, type, 4)
1551-
+ blockage(_save->getTile(startTile->getPosition() + oneTileNorth),MapData::O_OBJECT, type, 2))/2;
1552-
}
1563+
1564+
block += (blockage(_save->getTile(startTile->getPosition() + oneTileNorth),MapData::O_OBJECT, type, 4)
1565+
+ blockage(_save->getTile(startTile->getPosition() + oneTileEast),MapData::O_OBJECT, type, 6))/2;
15531566
}
15541567
break;
15551568
case 2: // east
@@ -1571,12 +1584,8 @@ int TileEngine::horizontalBlockage(Tile *startTile, Tile *endTile, ItemDamageTyp
15711584
block = (blockage(endTile,MapData::O_WESTWALL, type) + blockage(endTile,MapData::O_NORTHWALL, type))/2
15721585
+ (blockage(_save->getTile(startTile->getPosition() + oneTileEast),MapData::O_WESTWALL, type)
15731586
+ blockage(_save->getTile(startTile->getPosition() + oneTileSouth),MapData::O_NORTHWALL, type))/2;
1574-
1575-
if (!endTile->getMapData(MapData::O_OBJECT))
1576-
{
1577-
block += (blockage(_save->getTile(startTile->getPosition() + oneTileSouth),MapData::O_OBJECT, type, 2)
1578-
+ blockage(_save->getTile(startTile->getPosition() + oneTileEast),MapData::O_OBJECT, type, 4))/2;
1579-
}
1587+
block += (blockage(_save->getTile(startTile->getPosition() + oneTileSouth),MapData::O_OBJECT, type, 0)
1588+
+ blockage(_save->getTile(startTile->getPosition() + oneTileEast),MapData::O_OBJECT, type, 6))/2;
15801589
}
15811590
break;
15821591
case 4: // south
@@ -1597,12 +1606,8 @@ int TileEngine::horizontalBlockage(Tile *startTile, Tile *endTile, ItemDamageTyp
15971606
block = (blockage(endTile,MapData::O_NORTHWALL, type) + blockage(startTile,MapData::O_WESTWALL, type))/2
15981607
+ (blockage(_save->getTile(startTile->getPosition() + oneTileSouth),MapData::O_WESTWALL, type)
15991608
+ blockage(_save->getTile(startTile->getPosition() + oneTileSouth),MapData::O_NORTHWALL, type))/2;
1600-
if (!endTile->getMapData(MapData::O_OBJECT))
1601-
{
1602-
block += (blockage(_save->getTile(startTile->getPosition() + oneTileSouth),MapData::O_OBJECT, type, direction)
1603-
+ blockage(_save->getTile(startTile->getPosition() + oneTileWest),MapData::O_OBJECT, type, 2)
1604-
+ blockage(_save->getTile(startTile->getPosition() + oneTileWest),MapData::O_OBJECT, type, 4))/2;
1605-
}
1609+
block += (blockage(_save->getTile(startTile->getPosition() + oneTileSouth),MapData::O_OBJECT, type, 0)
1610+
+ blockage(_save->getTile(startTile->getPosition() + oneTileWest),MapData::O_OBJECT, type, 2))/2;
16061611
}
16071612
break;
16081613
case 6: // west
@@ -1625,23 +1630,20 @@ int TileEngine::horizontalBlockage(Tile *startTile, Tile *endTile, ItemDamageTyp
16251630
block = (blockage(startTile,MapData::O_WESTWALL, type) + blockage(startTile,MapData::O_NORTHWALL, type))/2
16261631
+ (blockage(_save->getTile(startTile->getPosition() + oneTileNorth),MapData::O_WESTWALL, type)
16271632
+ blockage(_save->getTile(startTile->getPosition() + oneTileWest),MapData::O_NORTHWALL, type))/2;
1628-
1629-
if (!endTile->getMapData(MapData::O_OBJECT))
1630-
{
1631-
block += (blockage(_save->getTile(startTile->getPosition() + oneTileNorth),MapData::O_OBJECT, type, 4)
1632-
+ blockage(_save->getTile(startTile->getPosition() + oneTileWest),MapData::O_OBJECT, type, 2))/2;
1633-
}
1633+
block += (blockage(_save->getTile(startTile->getPosition() + oneTileNorth),MapData::O_OBJECT, type, 4)
1634+
+ blockage(_save->getTile(startTile->getPosition() + oneTileWest),MapData::O_OBJECT, type, 2))/2;
16341635
}
16351636
break;
16361637
}
16371638

1638-
block += blockage(startTile,MapData::O_OBJECT, type, direction, true);
1639+
block += blockage(startTile,MapData::O_OBJECT, type, direction);
16391640
if (type != DT_NONE)
16401641
{
16411642
direction += 4;
16421643
if (direction > 7)
16431644
direction -= 8;
1644-
block += blockage(endTile,MapData::O_OBJECT, type, direction);
1645+
if (endTile->isBigWall())
1646+
block += blockage(endTile,MapData::O_OBJECT, type, direction, true);
16451647
}
16461648
else
16471649
{
@@ -1650,7 +1652,7 @@ int TileEngine::horizontalBlockage(Tile *startTile, Tile *endTile, ItemDamageTyp
16501652
direction += 4;
16511653
if (direction > 7)
16521654
direction -= 8;
1653-
if (blockage(endTile,MapData::O_OBJECT, type, direction) > 127){
1655+
if (blockage(endTile,MapData::O_OBJECT, type, direction, true) > 127){
16541656
return -1; //hit bigwall, reveal bigwall tile
16551657
}
16561658
}
@@ -1680,7 +1682,8 @@ int TileEngine::blockage(Tile *tile, const int part, ItemDamageType type, int di
16801682
{
16811683
wall = tile->getMapData(MapData::O_OBJECT)->getBigWall();
16821684

1683-
if (checkingFromOrigin &&
1685+
if (type != DT_SMOKE &&
1686+
checkingFromOrigin &&
16841687
(wall == Pathfinding::BIGWALLNESW ||
16851688
wall == Pathfinding::BIGWALLNWSE))
16861689
{

0 commit comments

Comments
 (0)