@@ -146,14 +146,14 @@ void UnitFallBState::think()
tilesToFallInto.push_back (tileTarget);
}
}
std::list<BattleUnit*> *fallingUnits = _parent-> getSave ()-> getFallingUnits ();
// Check each tile for units that need moving out of the way.
for (std::vector<Tile*>::iterator i = tilesToFallInto.begin (); i < tilesToFallInto.end (); ++i)
{
BattleUnit *unitBelow = (*i)->getUnit ();
if (unitBelow
&& (*unit) != unitBelow // falling units do not fall on themselves
&& !(std::find (unitsToMove.begin (), unitsToMove.end (), unitBelow) != unitsToMove.end ())) // already added
&& !( std::find (fallingUnits-> begin (), fallingUnits-> end (), unitBelow) != fallingUnits-> end ()) // ignore falling units (including self)
&& !(std::find (unitsToMove.begin (), unitsToMove.end (), unitBelow) != unitsToMove.end ())) // ignore already added units
{
unitsToMove.push_back (unitBelow);
}
@@ -166,89 +166,6 @@ void UnitFallBState::think()
&& (*unit)->getMovementType () != MT_FLY
&& (*unit)->getWalkingPhase () == 0 ;
// Find somewhere to move the unit(s) endanger of being squashed.
if (!unitsToMove.empty ())
{
std::vector<Tile*> escapeTiles;
for (std::vector<BattleUnit*>::iterator ub = unitsToMove.begin (); ub < unitsToMove.end (); )
{
BattleUnit *unitBelow = (*ub);
bool escapeFound = false ;
// We need to move all sections of the unit out of the way.
std::vector<Position> bodySections;
for (int x = unitBelow->getArmor ()->getSize () - 1 ; x >= 0 ; --x)
{
for (int y = unitBelow->getArmor ()->getSize () - 1 ; y >= 0 ; --y)
{
Position bs = unitBelow->getPosition () + Position (x, y, 0 );
bodySections.push_back (bs);
}
}
// Check in each compass direction.
for (int dir = 0 ; dir < Pathfinding::DIR_UP && !escapeFound; dir++)
{
Position offset;
Pathfinding::directionToVector (dir, &offset);
for (std::vector<Position>::iterator bs = bodySections.begin (); bs < bodySections.end (); )
{
Position originalPosition = (*bs);
Position endPosition = originalPosition + offset;
Tile *t = _parent->getSave ()->getTile (endPosition);
Tile *bt = _parent->getSave ()->getTile (endPosition + Position (0 ,0 ,-1 ));
bool aboutToBeOccupiedFromAbove = t && std::find (tilesToFallInto.begin (), tilesToFallInto.end (), t) != tilesToFallInto.end ();
bool alreadyTaken = t && std::find (escapeTiles.begin (), escapeTiles.end (), t) != escapeTiles.end ();
bool alreadyOccupied = t && t->getUnit () && (t->getUnit () != unitBelow);
bool movementBlocked = _parent->getSave ()->getPathfinding ()->getTUCost (originalPosition, dir, &endPosition, *ub, 0 , false ) == 255 ;
bool hasFloor = t && !t->hasNoFloor (bt);
bool unitCanFly = unitBelow->getMovementType () == MT_FLY;
bool canMoveToTile = t && !alreadyOccupied && !alreadyTaken && !aboutToBeOccupiedFromAbove && !movementBlocked && (hasFloor || unitCanFly);
if (canMoveToTile)
{
// Check next section of the unit.
++bs;
}
else
{
// Try next direction.
break ;
}
// If all sections of the fallen onto unit can be moved, then we move it.
if (bs == bodySections.end ())
{
if (_parent->getSave ()->addFallingUnit (unitBelow))
{
escapeFound = true ;
// Now ensure no other unit escapes to here too.
for (int x = unitBelow->getArmor ()->getSize () - 1 ; x >= 0 ; --x)
{
for (int y = unitBelow->getArmor ()->getSize () - 1 ; y >= 0 ; --y)
{
Tile *et = _parent->getSave ()->getTile (t->getPosition () + Position (x,y,0 ));
escapeTiles.push_back (et);
}
}
Tile *bu = _parent->getSave ()->getTile (originalPosition + Position (0 ,0 ,-1 ));
unitBelow->startWalking (dir, unitBelow->getPosition () + offset, bu, onScreen);
ub = unitsToMove.erase (ub);
}
}
}
}
if (!escapeFound)
{
unitBelow->knockOut (_parent);
ub = unitsToMove.erase (ub);
}
}
_parent->checkForCasualties (0 ,*unit);
}
// we are just standing around, we are done falling.
if ((*unit)->getStatus () == STATUS_STANDING)
{
@@ -295,6 +212,93 @@ void UnitFallBState::think()
}
}
// Find somewhere to move the unit(s) In danger of being squashed.
if (!unitsToMove.empty ())
{
std::vector<Tile*> escapeTiles;
for (std::vector<BattleUnit*>::iterator ub = unitsToMove.begin (); ub < unitsToMove.end (); )
{
BattleUnit *unitBelow = (*ub);
bool escapeFound = false ;
// We need to move all sections of the unit out of the way.
std::vector<Position> bodySections;
for (int x = unitBelow->getArmor ()->getSize () - 1 ; x >= 0 ; --x)
{
for (int y = unitBelow->getArmor ()->getSize () - 1 ; y >= 0 ; --y)
{
Position bs = unitBelow->getPosition () + Position (x, y, 0 );
bodySections.push_back (bs);
}
}
// Check in each compass direction.
for (int dir = 0 ; dir < Pathfinding::DIR_UP && !escapeFound; dir++)
{
Position offset;
Pathfinding::directionToVector (dir, &offset);
for (std::vector<Position>::iterator bs = bodySections.begin (); bs < bodySections.end (); )
{
Position originalPosition = (*bs);
Position endPosition = originalPosition + offset;
Tile *t = _parent->getSave ()->getTile (endPosition);
Tile *bt = _parent->getSave ()->getTile (endPosition + Position (0 ,0 ,-1 ));
bool aboutToBeOccupiedFromAbove = t && std::find (tilesToFallInto.begin (), tilesToFallInto.end (), t) != tilesToFallInto.end ();
bool alreadyTaken = t && std::find (escapeTiles.begin (), escapeTiles.end (), t) != escapeTiles.end ();
bool alreadyOccupied = t && t->getUnit () && (t->getUnit () != unitBelow);
bool movementBlocked = _parent->getSave ()->getPathfinding ()->getTUCost (originalPosition, dir, &endPosition, *ub, 0 , false ) == 255 ;
bool hasFloor = t && !t->hasNoFloor (bt);
bool unitCanFly = unitBelow->getMovementType () == MT_FLY;
bool canMoveToTile = t && !alreadyOccupied && !alreadyTaken && !aboutToBeOccupiedFromAbove && !movementBlocked && (hasFloor || unitCanFly);
if (canMoveToTile)
{
// Check next section of the unit.
++bs;
}
else
{
// Try next direction.
break ;
}
// If all sections of the fallen onto unit can be moved, then we move it.
if (bs == bodySections.end ())
{
if (_parent->getSave ()->addFallingUnit (unitBelow))
{
escapeFound = true ;
// Now ensure no other unit escapes to here too.
for (int x = unitBelow->getArmor ()->getSize () - 1 ; x >= 0 ; --x)
{
for (int y = unitBelow->getArmor ()->getSize () - 1 ; y >= 0 ; --y)
{
Tile *et = _parent->getSave ()->getTile (t->getPosition () + Position (x,y,0 ));
escapeTiles.push_back (et);
}
}
Tile *bu = _parent->getSave ()->getTile (originalPosition + Position (0 ,0 ,-1 ));
unitBelow->startWalking (dir, unitBelow->getPosition () + offset, bu,
(unitBelow->getVisible () && _parent->getMap ()->getCamera ()->isOnScreen (unitBelow->getPosition (), true , unitBelow->getArmor ()->getSize (), false )));
ub = unitsToMove.erase (ub);
}
}
}
}
if (!escapeFound)
{
// STOMP THAT GOOMBAH!
unitBelow->knockOut (_parent);
ub = unitsToMove.erase (ub);
}
}
_parent->checkForCasualties (0 ,0 );
}
if (_parent->getSave ()->getFallingUnits ()->empty ())
{
tilesToFallInto.clear ();
You have bug there, param
size
should have0
or1
not1
and2
fromarmor->size()
. Overall, should not this function be refactored and getting onlyunit
? This hole expression is repeated multiple times (withunitBelow->getVisible()
).