Skip to content
Permalink
Browse files

Merge pull request #1212 from MeridianOXC/november-fixes

Fix unconscious unit handling on stage change
  • Loading branch information
Warboy1982 committed Jan 30, 2019
2 parents 4251ab7 + e9f2098 commit 59f9f0ebf7fab0ae256b66d4534083e8f6c3caca
@@ -192,17 +192,44 @@ void BattlescapeGenerator::setMissionSite(MissionSite *mission)
*/
void BattlescapeGenerator::nextStage()
{
// preventively drop all units from soldier's inventory (makes handling easier)
// 1. no alien/civilian living, dead or unconscious is allowed to transition
// 2. no dead xcom unit is allowed to transition
// 3. only living or unconscious xcom units can transition
for (std::vector<BattleUnit*>::iterator unit = _save->getUnits()->begin(); unit != _save->getUnits()->end(); ++unit)
{
if ((*unit)->getOriginalFaction() == FACTION_PLAYER && !(*unit)->isOut())
{
std::vector<BattleItem*> unitsToDrop;
for (std::vector<BattleItem*>::iterator item = (*unit)->getInventory()->begin(); item != (*unit)->getInventory()->end(); ++item)
{
if ((*item)->getUnit())
{
unitsToDrop.push_back(*item);
}
}
for (std::vector<BattleItem*>::iterator corpseItem = unitsToDrop.begin(); corpseItem != unitsToDrop.end(); ++corpseItem)
{
(*corpseItem)->moveToOwner(0);
(*unit)->getTile()->addItem(*corpseItem, (*corpseItem)->getSlot());
}
}
}

int aliensAlive = 0;
// send all enemy units, or those not in endpoint area (if aborted) to time out
for (std::vector<BattleUnit*>::iterator i = _save->getUnits()->begin(); i != _save->getUnits()->end(); ++i)
{
(*i)->clearVisibleUnits();
(*i)->clearVisibleTiles();

Tile *tmpTile = _save->getTile((*i)->getPosition());
bool isInExit = (*i)->isInExitArea(END_POINT) || (*i)->liesInExitArea(tmpTile, END_POINT);

if ((*i)->getStatus() != STATUS_DEAD // if they're not dead
&& (((*i)->getOriginalFaction() == FACTION_PLAYER // and they're a soldier
&& _save->isAborted() // and you aborted
&& !(*i)->isInExitArea(END_POINT)) // and they're not on the exit
&& !isInExit) // and they're not on the exit
|| (*i)->getOriginalFaction() != FACTION_PLAYER)) // or they're not a soldier
{
if ((*i)->getOriginalFaction() == FACTION_HOSTILE && !(*i)->isOut())
@@ -309,7 +336,17 @@ void BattlescapeGenerator::nextStage()
// on the exit grid? it goes to stage two.
else if (tile->getMapData(O_FLOOR)->getSpecialType() == END_POINT)
{
toContainer = &takeToNextStage;
// apply similar logic (for units) as in protocol 1
if ((*i)->getUnit() &&
((*i)->getUnit()->getOriginalFaction() != FACTION_PLAYER ||
(*i)->getUnit()->getStatus() == STATUS_DEAD))
{
toContainer = takeHomeConditional;
}
else
{
toContainer = &takeToNextStage;
}
}
}
}
@@ -806,6 +806,7 @@ void DebriefingState::prepareDebriefing()
int playersSurvived = 0; // if this stays 0 the craft is lost...
int playersUnconscious = 0;
int playersInEntryArea = 0;
int playersMIA = 0;

_stats.push_back(new DebriefingStat("STR_ALIENS_KILLED", false));
_stats.push_back(new DebriefingStat("STR_ALIEN_CORPSES_RECOVERED", false));
@@ -987,6 +988,11 @@ void DebriefingState::prepareDebriefing()
{
playersUnconscious++;
}
else if ((*j)->getStatus() == STATUS_IGNORE_ME && (*j)->getStunlevel() >= (*j)->getHealth())
{
// even for ignored xcom units, we need to know if they're conscious or unconscious
playersUnconscious++;
}
else if ((*j)->isInExitArea(END_POINT))
{
playersInExitArea++;
@@ -995,20 +1001,36 @@ void DebriefingState::prepareDebriefing()
{
playersInEntryArea++;
}
else if (aborted)
{
// if aborted, conscious xcom unit that is not on start/end point counts as MIA
playersMIA++;
}
playersSurvived++;
}
else if ((*j)->getOriginalFaction() == FACTION_PLAYER && (*j)->getStatus() == STATUS_DEAD)
deadSoldiers++;
}
// if all our men are unconscious, the aliens get to have their way with them.
if (playersUnconscious == playersSurvived)
if (playersUnconscious + playersMIA == playersSurvived)
{
playersSurvived = 0;
playersSurvived = playersMIA;
for (std::vector<BattleUnit*>::iterator j = battle->getUnits()->begin(); j != battle->getUnits()->end(); ++j)
{
if ((*j)->getOriginalFaction() == FACTION_PLAYER && (*j)->getStatus() != STATUS_DEAD)
{
(*j)->instaKill();
if ((*j)->getStatus() == STATUS_UNCONSCIOUS || (*j)->getFaction() == FACTION_HOSTILE)
{
(*j)->instaKill();
}
else if ((*j)->getStatus() == STATUS_IGNORE_ME && (*j)->getStunlevel() >= (*j)->getHealth())
{
(*j)->instaKill();
}
else
{
// do nothing, units will be marked MIA later
}
}
}
}
@@ -2103,6 +2103,17 @@ bool BattleUnit::isInExitArea(SpecialTileType stt) const
return _tile && _tile->getMapData(O_FLOOR) && (_tile->getMapData(O_FLOOR)->getSpecialType() == stt);
}

/**
* Check if this unit lies (e.g. unconscious) in the exit area.
* @param tile Unit's location.
* @param stt Type of exit tile to check for.
* @return Is in the exit area?
*/
bool BattleUnit::liesInExitArea(Tile *tile, SpecialTileType stt) const
{
return tile && tile->getMapData(O_FLOOR) && (tile->getMapData(O_FLOOR)->getSpecialType() == stt);
}

/**
* Gets the unit height taking into account kneeling/standing.
* @return Unit's height.
@@ -309,6 +309,7 @@ class BattleUnit
bool checkAmmo();
/// Check if this unit is in the exit area
bool isInExitArea(SpecialTileType stt = START_POINT) const;
bool liesInExitArea(Tile *tile, SpecialTileType stt = START_POINT) const;
/// Gets the unit height taking into account kneeling/standing.
int getHeight() const;
/// Gets the unit floating elevation.

0 comments on commit 59f9f0e

Please sign in to comment.