/** * Returns to the previous screen. * @param action Pointer to an action. */ void BaseDefenseState::btnOkClick(Action *) { _timer->stop(); _game->setPalette(_game->getResourcePack()->getPalette("PALETTES.DAT_0")->getColors()); _game->popState(); if(_ufo->getStatus() != Ufo::DESTROYED) { if (_base->getAvailableSoldiers(true) > 0) { size_t month = _game->getSavedGame()->getMonthsPassed(); if (month > _game->getRuleset()->getAlienItemLevels().size()-1) month = _game->getRuleset()->getAlienItemLevels().size()-1; SavedBattleGame *bgame = new SavedBattleGame(); _game->getSavedGame()->setBattleGame(bgame); bgame->setMissionType("STR_BASE_DEFENSE"); BattlescapeGenerator bgen = BattlescapeGenerator(_game); bgen.setBase(_base); bgen.setAlienRace(_ufo->getAlienRace()); bgen.setAlienItemlevel(_game->getRuleset()->getAlienItemLevels().at(month).at(RNG::generate(0,9))); bgen.run(); _state->musicStop(); _game->pushState(new BriefingState(_game, 0, _base)); } else { _game->pushState(new BaseDestroyedState(_game, _base)); } } // Whatever happens in the base defense, the UFO has finished its duty _ufo->setStatus(Ufo::DESTROYED); }
/* * Animate explosion sprites. If their animation is finished remove them from the list. * If the list is empty, this states is finished. */ void ExplosionBState::think() { for (std::set<Explosion*>::const_iterator i = _parent->getMap()->getExplosions()->begin(), inext = i; i != _parent->getMap()->getExplosions()->end(); i = inext) { ++inext; if(!(*i)->animate()) { _parent->getMap()->getExplosions()->erase((*i)); if (_parent->getMap()->getExplosions()->empty()) { bool terrainExplosion = false; SavedBattleGame *save = _parent->getSave(); // after the animation is done, the real explosion takes place if (_item) { save->getTileEngine()->explode(_center, _item->getRules()->getPower(), _item->getRules()->getDamageType(), _item->getRules()->getExplosionRadius(), _unit); } if (_tile) { save->getTileEngine()->explode(_center, _tile->getExplosive(), DT_HE, 100, _unit); } if (!_tile && !_item) { // explosion of a cyberdisc save->getTileEngine()->explode(_center, 120, DT_HE, 8, _unit); terrainExplosion = true; } // now check for new casualties _parent->checkForCasualties(_item, _unit, false, terrainExplosion); // if this explosion was caused by a unit shooting, now it's the time to put the gun down if (_unit && !_unit->isOut()) { _unit->aim(false); } _parent->getMap()->cacheUnits(); _parent->popState(); // check for terrain explosions Tile *t = save->getTileEngine()->checkForTerrainExplosions(); if (t) { Position p = Position(t->getPosition().x * 16, t->getPosition().y * 16, t->getPosition().z * 24); _parent->statePushNext(new ExplosionBState(_parent, p, 0, _unit, t)); } return; } } } }
/* * Animate explosion sprites. If their animation is finished remove them from the list. * If the list is empty, this states is finished. */ void ExplosionBState::think() { for (std::set<Explosion*>::const_iterator i = _parent->getMap()->getExplosions()->begin(), inext = i; i != _parent->getMap()->getExplosions()->end(); i = inext) { ++inext; if(!(*i)->animate()) { _parent->getMap()->getExplosions()->erase((*i)); if (_parent->getMap()->getExplosions()->empty()) { SavedBattleGame *save = _parent->getGame()->getSavedGame()->getBattleGame(); // after the animation is done, the real explosion takes place if (_item) { save->getTerrainModifier()->explode(_center, _item->getRules()->getPower(), _item->getRules()->getDamageType(), 100, _unit); } if (_tile) { save->getTerrainModifier()->explode(_center, _tile->getExplosive(), DT_HE, 100, _unit); } // now check for new casualties _parent->checkForCasualties(_item, _unit); // if this explosion was caused by a unit shooting, now it's the time to put the gun down and put the camera back on the shooter if (_unit && !_unit->isOut()) { _unit->aim(false); if (_parent->getMap()->didCameraFollow()) { _parent->getMap()->centerOnPosition(_unit->getPosition()); } } _parent->getMap()->cacheUnits(); _parent->popState(); // check for terrain explosions Tile *t = save->getTerrainModifier()->checkForTerrainExplosions(); if (t) { Position p = Position(t->getPosition().x * 16, t->getPosition().y * 16, t->getPosition().z * 24); _parent->statePushNext(new ExplosionBState(_parent, p, 0, _unit, t)); } return; } } } }
/** * Returns to the previous screen. * @param action Pointer to an action. */ void ConfirmCydoniaState::btnYesClick(Action *) { _game->popState(); _game->popState(); SavedBattleGame *bgame = new SavedBattleGame(); _game->getSavedGame()->setBattleGame(bgame); bgame->setMissionType("STR_MARS_CYDONIA_LANDING"); BattlescapeGenerator bgen = BattlescapeGenerator(_game); bgen.setCraft(_craft); bgen.setAlienRace("STR_SECTOID"); bgen.setWorldShade(15); bgen.run(); _game->pushState(new BriefingState(_game, _craft)); }
/** * Enters the mission. * @param action Pointer to an action. */ void ConfirmLandingState::btnYesClick(Action *) { _game->popState(); _state->musicStop(); Ufo* u = dynamic_cast<Ufo*>(_craft->getDestination()); TerrorSite* t = dynamic_cast<TerrorSite*>(_craft->getDestination()); AlienBase* b = dynamic_cast<AlienBase*>(_craft->getDestination()); size_t month = _game->getSavedGame()->getMonthsPassed(); if (month > _game->getRuleset()->getAlienItemLevels().size()-1) month = _game->getRuleset()->getAlienItemLevels().size()-1; SavedBattleGame *bgame = new SavedBattleGame(); _game->getSavedGame()->setBattleGame(bgame); BattlescapeGenerator bgen = BattlescapeGenerator(_game); bgen.setWorldTexture(_texture); bgen.setWorldShade(_shade); bgen.setCraft(_craft); if (u != 0) { if(u->getStatus() == Ufo::CRASHED) bgame->setMissionType("STR_UFO_CRASH_RECOVERY"); else bgame->setMissionType("STR_UFO_GROUND_ASSAULT"); bgen.setUfo(u); bgen.setAlienRace(u->getAlienRace()); } else if (t != 0) { bgame->setMissionType("STR_TERROR_MISSION"); bgen.setTerrorSite(t); bgen.setAlienRace(t->getAlienRace()); } else if (b != 0) { bgame->setMissionType("STR_ALIEN_BASE_ASSAULT"); bgen.setAlienBase(b); bgen.setAlienRace(b->getAlienRace()); } else { throw Exception("No mission available!"); } bgen.setAlienItemlevel(_game->getRuleset()->getAlienItemLevels().at(month).at(RNG::generate(0,9))); bgen.run(); _game->pushState(new BriefingState(_game, _craft)); }
/** * Enters the mission. * @param action Pointer to an action. */ void ConfirmLandingState::btnYesClick(Action *action) { _game->popState(); Ufo* u = dynamic_cast<Ufo*>(_craft->getDestination()); TerrorSite* t = dynamic_cast<TerrorSite*>(_craft->getDestination()); AlienBase* b = dynamic_cast<AlienBase*>(_craft->getDestination()); if (u != 0) { SavedBattleGame *bgame = new SavedBattleGame(); _game->getSavedGame()->setBattleGame(bgame); if(u->getStatus() == Ufo::CRASHED) bgame->setMissionType("STR_UFO_CRASH_RECOVERY"); else bgame->setMissionType("STR_UFO_GROUND_ASSAULT"); BattlescapeGenerator bgen = BattlescapeGenerator(_game); bgen.setWorldTexture(_texture); bgen.setWorldShade(_shade); bgen.setCraft(_craft); bgen.setUfo(u); bgen.setAlienRace(u->getAlienRace()); bgen.setAlienItemlevel(0); bgen.run(); _game->pushState(new BriefingState(_game, _craft)); } else if (t != 0) { SavedBattleGame *bgame = new SavedBattleGame(); _game->getSavedGame()->setBattleGame(bgame); bgame->setMissionType("STR_TERROR_MISSION"); BattlescapeGenerator bgen = BattlescapeGenerator(_game); bgen.setWorldTexture(_texture); bgen.setWorldShade(_shade); bgen.setCraft(_craft); bgen.setTerrorSite(t); bgen.setAlienRace(t->getAlienRace()); bgen.setAlienItemlevel(0); bgen.run(); _game->pushState(new BriefingState(_game, _craft)); } else if (b != 0) { SavedBattleGame *bgame = new SavedBattleGame(); _game->getSavedGame()->setBattleGame(bgame); bgame->setMissionType("STR_ALIEN_BASE_ASSAULT"); BattlescapeGenerator bgen = BattlescapeGenerator(_game); bgen.setWorldTexture(_texture); bgen.setWorldShade(_shade); bgen.setCraft(_craft); bgen.setAlienBase(b); bgen.setAlienRace(b->getAlienRace()); bgen.setAlienItemlevel(0); bgen.run(); _game->pushState(new BriefingState(_game, _craft)); } }
/** * Enters the mission. * @param action Pointer to an action. */ void ConfirmLandingState::btnYesClick(Action *) { _game->popState(); Ufo* u = dynamic_cast<Ufo*>(_craft->getDestination()); MissionSite* m = dynamic_cast<MissionSite*>(_craft->getDestination()); AlienBase* b = dynamic_cast<AlienBase*>(_craft->getDestination()); SavedBattleGame *bgame = new SavedBattleGame(); _game->getSavedGame()->setBattleGame(bgame); BattlescapeGenerator bgen(_game); bgen.setWorldTexture(_texture); bgen.setWorldShade(_shade); bgen.setCraft(_craft); if (u != 0) { if (u->getStatus() == Ufo::CRASHED) bgame->setMissionType("STR_UFO_CRASH_RECOVERY"); else bgame->setMissionType("STR_UFO_GROUND_ASSAULT"); bgen.setUfo(u); bgen.setAlienRace(u->getAlienRace()); } else if (m != 0) { bgame->setMissionType(m->getDeployment()->getType()); bgen.setMissionSite(m); bgen.setAlienRace(m->getAlienRace()); } else if (b != 0) { bgame->setMissionType(b->getDeployment()->getType()); bgen.setAlienBase(b); bgen.setAlienRace(b->getAlienRace()); bgen.setWorldTexture(0); } else { throw Exception("No mission available!"); } bgen.run(); _game->pushState(new BriefingState(_craft)); }
/** * Returns to the previous screen. * @param action Pointer to an action. */ void ConfirmCydoniaState::btnYesClick(Action *) { _game->popState(); _game->popState(); SavedBattleGame *bgame = new SavedBattleGame(); _game->getSavedGame()->setBattleGame(bgame); BattlescapeGenerator bgen = BattlescapeGenerator(_game); for (std::vector<std::string>::const_iterator i = _game->getRuleset()->getDeploymentsList().begin(); i != _game->getRuleset()->getDeploymentsList().end(); ++i) { AlienDeployment *deployment = _game->getRuleset()->getDeployment(*i); if (deployment->isFinalDestination()) { bgame->setMissionType(*i); bgen.setAlienRace(deployment->getRace()); break; } } bgen.setCraft(_craft); bgen.run(); _game->pushState(new BriefingState(_craft)); }
void ExplosionBState::explode() { bool terrainExplosion = false; SavedBattleGame *save = _parent->getSave(); // after the animation is done, the real explosion/hit takes place if (_item) { if (_areaOfEffect) { save->getTileEngine()->explode(_center, _power, _item->getRules()->getDamageType(), _item->getRules()->getExplosionRadius(), _unit); } else { BattleUnit *victim = save->getTileEngine()->hit(_center, _power, _item->getRules()->getDamageType(), _unit); // check if this unit turns others into zombies if (!_unit->getZombieUnit().empty() && victim) { // converts the victim to a zombie _parent->convertUnit(victim, _unit->getZombieUnit()); } } } if (_tile) { save->getTileEngine()->explode(_center, _power, DT_HE, 100); } if (!_tile && !_item) { // explosion not caused by terrain or an item, must be by a unit (cyberdisc) save->getTileEngine()->explode(_center, _power, DT_HE, 8); terrainExplosion = true; } // now check for new casualties _parent->checkForCasualties(_item, _unit, false, terrainExplosion); // if this explosion was caused by a unit shooting, now it's the time to put the gun down if (_unit && !_unit->isOut()) { _unit->aim(false); } _parent->getMap()->cacheUnits(); _parent->popState(); // check for terrain explosions Tile *t = save->getTileEngine()->checkForTerrainExplosions(); if (t) { Position p = Position(t->getPosition().x * 16, t->getPosition().y * 16, t->getPosition().z * 24); _parent->statePushNext(new ExplosionBState(_parent, p, 0, _unit, t)); } }
/** * Calculates the effects of the explosion. */ void ExplosionBState::explode() { bool terrainExplosion = false; SavedBattleGame *save = _parent->getSave(); // after the animation is done, the real explosion/hit takes place if (_item) { if (!_unit && _item->getPreviousOwner()) { _unit = _item->getPreviousOwner(); } BattleUnit *victim = 0; if (_areaOfEffect) { save->getTileEngine()->explode(_center, _power, _item->getRules()->getDamageType(), _item->getRules()->getExplosionRadius(), _unit); } else if (!_cosmetic) { ItemDamageType type = _item->getRules()->getDamageType(); victim = save->getTileEngine()->hit(_center, _power, type, _unit); } // check if this unit turns others into zombies if (!_item->getRules()->getZombieUnit().empty() && victim && victim->getArmor()->getSize() == 1 && (victim->getGeoscapeSoldier() || victim->getUnitRules()->getRace() == "STR_CIVILIAN") && victim->getSpawnUnit().empty()) { // converts the victim to a zombie on death victim->setRespawn(true); victim->setSpawnUnit(_item->getRules()->getZombieUnit()); } } if (_tile) { ItemDamageType DT; switch (_tile->getExplosiveType()) { case 0: DT = DT_HE; break; case 5: DT = DT_IN; break; case 6: DT = DT_STUN; break; default: DT = DT_SMOKE; break; } if (DT != DT_HE) { _tile->setExplosive(0,0,true); } save->getTileEngine()->explode(_center, _power, DT, _power/10); terrainExplosion = true; } if (!_tile && !_item) { int radius = 6; // explosion not caused by terrain or an item, must be by a unit (cyberdisc) if (_unit && (_unit->getSpecialAbility() == SPECAB_EXPLODEONDEATH || _unit->getSpecialAbility() == SPECAB_BURN_AND_EXPLODE)) { radius = _parent->getMod()->getItem(_unit->getArmor()->getCorpseGeoscape())->getExplosionRadius(); } save->getTileEngine()->explode(_center, _power, DT_HE, radius); terrainExplosion = true; } if (!_cosmetic) { // now check for new casualties _parent->checkForCasualties(_item, _unit, false, terrainExplosion); } // if this explosion was caused by a unit shooting, now it's the time to put the gun down if (_unit && !_unit->isOut() && _lowerWeapon) { _unit->aim(false); _unit->setCache(0); } _parent->getMap()->cacheUnits(); _parent->popState(); // check for terrain explosions Tile *t = save->getTileEngine()->checkForTerrainExplosions(); if (t) { Position p = Position(t->getPosition().x * 16, t->getPosition().y * 16, t->getPosition().z * 24); p += Position(8,8,0); _parent->statePushFront(new ExplosionBState(_parent, p, 0, _unit, t)); } if (_item && (_item->getRules()->getBattleType() == BT_GRENADE || _item->getRules()->getBattleType() == BT_PROXIMITYGRENADE)) { for (std::vector<BattleItem*>::iterator j = _parent->getSave()->getItems()->begin(); j != _parent->getSave()->getItems()->end(); ++j) { if (_item->getId() == (*j)->getId()) { _parent->getSave()->removeItem(_item); break; } } } }
/** * Prepares debriefing: gathers Aliens, Corpses, Artefacts, UFO Components. * Adds the items to the craft. * Also calculates the soldiers experience, and possible promotions. * If aborted, only the things on the exit area are recovered. */ void DebriefingState::prepareDebriefing() { _stats.push_back(new DebriefingStat("STR_ALIENS_KILLED", false)); _stats.push_back(new DebriefingStat("STR_ALIEN_CORPSES_RECOVERED", false)); _stats.push_back(new DebriefingStat("STR_LIVE_ALIENS_RECOVERED", false)); _stats.push_back(new DebriefingStat("STR_ALIEN_ARTIFACTS_RECOVERED", false)); _stats.push_back(new DebriefingStat("STR_ALIEN_BASE_CONTROL_DESTROYED", false)); _stats.push_back(new DebriefingStat("STR_CIVILIANS_KILLED_BY_ALIENS", false)); _stats.push_back(new DebriefingStat("STR_CIVILIANS_KILLED_BY_XCOM_OPERATIVES", false)); _stats.push_back(new DebriefingStat("STR_CIVILIANS_SAVED", false)); _stats.push_back(new DebriefingStat("STR_XCOM_OPERATIVES_KILLED", false)); //_stats.push_back(new DebriefingStat("STR_XCOM_OPERATIVES_RETIRED_THROUGH_INJURY", false)); _stats.push_back(new DebriefingStat("STR_XCOM_OPERATIVES_MISSING_IN_ACTION", false)); _stats.push_back(new DebriefingStat("STR_TANKS_DESTROYED", false)); _stats.push_back(new DebriefingStat("STR_XCOM_CRAFT_LOST", false)); _stats.push_back(new DebriefingStat("STR_UFO_POWER_SOURCE", true)); _stats.push_back(new DebriefingStat("STR_UFO_NAVIGATION", true)); _stats.push_back(new DebriefingStat("STR_UFO_CONSTRUCTION", true)); _stats.push_back(new DebriefingStat("STR_ALIEN_FOOD", true)); _stats.push_back(new DebriefingStat("STR_ALIEN_REPRODUCTION", true)); _stats.push_back(new DebriefingStat("STR_ALIEN_ENTERTAINMENT", true)); _stats.push_back(new DebriefingStat("STR_ALIEN_SURGERY", true)); _stats.push_back(new DebriefingStat("STR_EXAMINATION_ROOM", true)); _stats.push_back(new DebriefingStat("STR_ALIEN_ALLOYS", true)); _stats.push_back(new DebriefingStat("STR_ELERIUM_115", true)); SavedGame *save = _game->getSavedGame(); SavedBattleGame *battle = save->getBattleGame(); bool aborted = battle->isAborted(); Craft* craft = 0; std::vector<Craft*>::iterator craftIterator; Base* base = 0; int playerInExitArea = 0; // if this stays 0 the craft is lost... int playersSurvived = 0; // if this stays 0 the craft is lost... for (std::vector<Base*>::iterator i = save->getBases()->begin(); i != save->getBases()->end(); ++i) { // in case we have a craft - check which craft it is about for (std::vector<Craft*>::iterator j = (*i)->getCrafts()->begin(); j != (*i)->getCrafts()->end(); ++j) { if ((*j)->isInBattlescape()) { craft = (*j); base = (*i); craftIterator = j; craft->returnToBase(); craft->setLowFuel(true); craft->setInBattlescape(false); } } } // UFO crash/landing site disappears for (std::vector<Ufo*>::iterator i = save->getUfos()->begin(); i != save->getUfos()->end(); ++i) { if ((*i)->isInBattlescape()) { delete *i; save->getUfos()->erase(i); break; } } // lets see what happens with units for (std::vector<BattleUnit*>::iterator j = battle->getUnits()->begin(); j != battle->getUnits()->end(); ++j) { UnitStatus status = (*j)->getStatus(); UnitFaction faction = (*j)->getFaction(); int value = (*j)->getValue(); Soldier *soldier = save->getSoldier((*j)->getId()); if (status == STATUS_DEAD) { if (faction == FACTION_HOSTILE) { addStat("STR_ALIENS_KILLED", 1, value); } if (faction == FACTION_PLAYER) { if (soldier != 0) { addStat("STR_XCOM_OPERATIVES_KILLED", 1, -value); for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end(); ++i) { if ((*i) == soldier) { delete (*i); base->getSoldiers()->erase(i); break; } } } else { // non soldier player = tank addStat("STR_TANKS_DESTROYED", 1, -value); } } } else if (status == STATUS_UNCONSCIOUS) { if (faction == FACTION_HOSTILE && (!aborted || (*j)->isInExitArea())) { addStat("STR_LIVE_ALIENS_RECOVERED", 1, value); } } else if (faction == FACTION_PLAYER) { playersSurvived++; if ((*j)->isInExitArea() || !aborted) { playerInExitArea++; (*j)->postMissionProcedures(save); } else { addStat("STR_XCOM_OPERATIVES_MISSING_IN_ACTION", 1, -value); for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end(); ++i) { if ((*i) == soldier) { delete (*i); base->getSoldiers()->erase(i); break; } } } } } if (((playerInExitArea == 0 && aborted) || (playersSurvived == 0)) && craft != 0) { addStat("STR_XCOM_CRAFT_LOST", 1, -200); delete craft; base->getCrafts()->erase(craftIterator); for (std::vector<Soldier*>::iterator i = base->getSoldiers()->begin(); i != base->getSoldiers()->end();) { if ((*i)->getCraft() == craft) { delete (*i); i = base->getSoldiers()->erase(i); } else { ++i; } } _txtTitle->setText(_game->getLanguage()->getString("STR_CRAFT_IS_LOST")); return; } if (!aborted && playersSurvived > 0) // RECOVER UFO : run through all tiles to recover UFO components and items { if (battle->getMissionType() == "STR_BASE_DEFENCE") { _txtTitle->setText(_game->getLanguage()->getString("STR_BASE_IS_SAVED")); } else { _txtTitle->setText(_game->getLanguage()->getString("STR_UFO_IS_RECOVERED")); } for (int i = 0; i < battle->getHeight() * battle->getLength() * battle->getWidth(); ++i) { for (int part = 0; part < 4; part++) { if (battle->getTiles()[i]->getMapData(part)) { switch (battle->getTiles()[i]->getMapData(part)->getSpecialType()) { case UFO_POWER_SOURCE: addStat("STR_UFO_POWER_SOURCE", 1, 1); break; case DESTROY_OBJECTIVE:break; // this is the brain case UFO_NAVIGATION: addStat("STR_UFO_NAVIGATION", 1, 1); break; case ALIEN_FOOD: addStat("STR_ALIEN_FOOD", 1, 1); break; case ALIEN_REPRODUCTION: addStat("STR_ALIEN_REPRODUCTION", 1, 1); break; case ALIEN_ENTERTAINMENT: addStat("STR_ALIEN_ENTERTAINMENT", 1, 1); break; case ALIEN_SURGERY: addStat("STR_ALIEN_SURGERY", 1, 1); break; case UNKNOWN09: addStat("STR_UFO_CONSTRUCTION", 1, 1); break; case ALIEN_ALLOYS: addStat("STR_ALIEN_ALLOYS", 1, 1); break; case EXAM_ROOM: addStat("STR_EXAMINATION_ROOM", 1, 1); break; } } } } // alien alloys recovery values are divided by 10 or divided by 150 in case of an alien base int divider = battle->getMissionType()=="STR_ALIEN_BASE_ASSAULT"?150:10; for (std::vector<DebriefingStat*>::iterator i = _stats.begin(); i != _stats.end(); ++i) { if ((*i)->item == "STR_ALIEN_ALLOYS") { (*i)->qty = (*i)->qty / divider; (*i)->score = (*i)->score / divider; break; } /*if ((*i)->recovery && (*i)->qty > 0) { base->getItems()->addItem((*i)->item, (*i)->qty); }*/ } } else { if (battle->getMissionType() == "STR_BASE_DEFENCE") { _txtTitle->setText(_game->getLanguage()->getString("STR_BASE_IS_LOST")); } else { _txtTitle->setText(_game->getLanguage()->getString("STR_UFO_IS_NOT_RECOVERED")); } } }
/** * Calculates the effects of the explosion. */ void ExplosionBState::explode() { bool terrainExplosion = false; SavedBattleGame *save = _parent->getSave(); // after the animation is done, the real explosion/hit takes place if (_item) { if (!_unit && _item->getPreviousOwner()) { _unit = _item->getPreviousOwner(); } if (_areaOfEffect) { save->getTileEngine()->explode(_center, _power, _item->getRules()->getDamageType(), _item->getRules()->getExplosionRadius(), _unit); } else { BattleUnit *victim = save->getTileEngine()->hit(_center, _power, _item->getRules()->getDamageType(), _unit); // check if this unit turns others into zombies if (!_unit->getZombieUnit().empty() && victim && victim->getArmor()->getSize() == 1 && victim->getSpawnUnit().empty() && victim->getOriginalFaction() != FACTION_HOSTILE) { // converts the victim to a zombie on death victim->setSpecialAbility(SPECAB_RESPAWN); victim->setSpawnUnit(_unit->getZombieUnit()); } } } if (_tile) { save->getTileEngine()->explode(_center, _power, DT_HE, _power/10); terrainExplosion = true; } if (!_tile && !_item) { // explosion not caused by terrain or an item, must be by a unit (cyberdisc) save->getTileEngine()->explode(_center, _power, DT_HE, 6); terrainExplosion = true; } // now check for new casualties _parent->checkForCasualties(_item, _unit, false, terrainExplosion); // if this explosion was caused by a unit shooting, now it's the time to put the gun down if (_unit && !_unit->isOut() && _lowerWeapon) { _unit->aim(false); } _parent->getMap()->cacheUnits(); _parent->popState(); // check for terrain explosions Tile *t = save->getTileEngine()->checkForTerrainExplosions(); if (t) { Position p = Position(t->getPosition().x * 16, t->getPosition().y * 16, t->getPosition().z * 24); _parent->statePushFront(new ExplosionBState(_parent, p, 0, _unit, t)); } if (_item && (_item->getRules()->getBattleType() == BT_GRENADE || _item->getRules()->getBattleType() == BT_PROXIMITYGRENADE)) { for (std::vector<BattleItem*>::iterator j = _parent->getSave()->getItems()->begin(); j != _parent->getSave()->getItems()->end(); ++j) { if (_item->getId() == (*j)->getId()) { delete *j; _parent->getSave()->getItems()->erase(j); break; } } } }
/** * Starts the battle. * @param action Pointer to an action. */ void NewBattleState::btnOkClick(Action *) { save(); if (_missionTypes[_cbxMission->getSelected()] != "STR_BASE_DEFENSE" && _craft->getNumSoldiers() == 0 && _craft->getNumVehicles() == 0) { return; } SavedBattleGame *bgame = new SavedBattleGame(); _game->getSavedGame()->setBattleGame(bgame); bgame->setMissionType(_missionTypes[_cbxMission->getSelected()]); BattlescapeGenerator bgen = BattlescapeGenerator(_game); Base *base = 0; bgen.setTerrain(_game->getMod()->getTerrain(_terrainTypes[_cbxTerrain->getSelected()])); // base defense if (_missionTypes[_cbxMission->getSelected()] == "STR_BASE_DEFENSE") { base = _craft->getBase(); bgen.setBase(base); _craft = 0; } // alien base else if (_game->getMod()->getDeployment(bgame->getMissionType())->isAlienBase()) { AlienBase *b = new AlienBase(_game->getMod()->getDeployment(bgame->getMissionType())); b->setId(1); b->setAlienRace(_alienRaces[_cbxAlienRace->getSelected()]); _craft->setDestination(b); bgen.setAlienBase(b); _game->getSavedGame()->getAlienBases()->push_back(b); } // ufo assault else if (_craft && _game->getMod()->getUfo(_missionTypes[_cbxMission->getSelected()])) { Ufo *u = new Ufo(_game->getMod()->getUfo(_missionTypes[_cbxMission->getSelected()])); u->setId(1); _craft->setDestination(u); bgen.setUfo(u); // either ground assault or ufo crash if (RNG::generate(0,1) == 1) { u->setStatus(Ufo::LANDED); bgame->setMissionType("STR_UFO_GROUND_ASSAULT"); } else { u->setStatus(Ufo::CRASHED); bgame->setMissionType("STR_UFO_CRASH_RECOVERY"); } _game->getSavedGame()->getUfos()->push_back(u); } // mission site else { const AlienDeployment *deployment = _game->getMod()->getDeployment(bgame->getMissionType()); const RuleAlienMission *mission = _game->getMod()->getAlienMission(_game->getMod()->getAlienMissionList().front()); // doesn't matter MissionSite *m = new MissionSite(mission, deployment); m->setId(1); m->setAlienRace(_alienRaces[_cbxAlienRace->getSelected()]); _craft->setDestination(m); bgen.setMissionSite(m); _game->getSavedGame()->getMissionSites()->push_back(m); } if (_craft) { _craft->setSpeed(0); bgen.setCraft(_craft); } _game->getSavedGame()->setDifficulty((GameDifficulty)_cbxDifficulty->getSelected()); bgen.setWorldShade(_slrDarkness->getValue()); bgen.setAlienRace(_alienRaces[_cbxAlienRace->getSelected()]); bgen.setAlienItemlevel(_slrAlienTech->getValue()); bgame->setDepth(_slrDepth->getValue()); bgen.run(); _game->popState(); _game->popState(); _game->pushState(new BriefingState(_craft, base)); _craft = 0; }
/** * Calculates the effects of the explosion. */ void ExplosionBState::explode() { bool terrainExplosion = false; SavedBattleGame *save = _parent->getSave(); // last minute adjustment: determine if we actually if (_hit) { if (_unit && !_unit->isOut()) { _unit->aim(false); } if (_power <= 0) { _parent->popState(); return; } int sound = _item->getRules()->getMeleeHitSound(); if (!_pistolWhip) { // melee weapon with ammo BattleItem *ammo = _item->getAmmoItem(); if (ammo) { optValue(sound, ammo->getRules()->getMeleeHitSound()); } } _parent->playSound(sound, _action.target); } // after the animation is done, the real explosion/hit takes place if (_item) { if (!_unit && _item->getPreviousOwner()) { _unit = _item->getPreviousOwner(); } } bool range = !(_hit || (_item && _item->getRules()->getBattleType() == BT_PSIAMP)); if (_areaOfEffect) { save->getTileEngine()->explode(_center, _power, _damageType, _radius, _unit, _item, range); } else { BattleUnit *victim = save->getTileEngine()->hit(_center, _power, _damageType, _unit, _item, range); // check if this unit turns others into zombies if (!_item->getRules()->getZombieUnit().empty() && RNG::percent(_item->getRules()->getSpecialChance()) && victim && victim->getArmor()->getZombiImmune() == false && victim->getSpawnUnit().empty() && victim->getOriginalFaction() != FACTION_HOSTILE) { // converts the victim to a zombie on death victim->setRespawn(true); victim->setSpawnUnit(_item->getRules()->getZombieUnit()); } } if (_tile) { terrainExplosion = true; } if (!_tile && !_item) { terrainExplosion = true; } // now check for new casualties _parent->checkForCasualties(_item ? _damageType : 0, _item, _unit, false, terrainExplosion); // revive units if damage could give hp or reduce stun _parent->getSave()->reviveUnconsciousUnits(true); // if this explosion was caused by a unit shooting, now it's the time to put the gun down if (_unit && !_unit->isOut() && _lowerWeapon) { _unit->aim(false); } if (_item && (_item->getRules()->getBattleType() == BT_GRENADE || _item->getRules()->getBattleType() == BT_PROXIMITYGRENADE)) { _parent->getSave()->removeItem(_item); } _parent->popState(); // check for terrain explosions Tile *t = save->getTileEngine()->checkForTerrainExplosions(); if (t) { Position p = t->getPosition().toVexel(); p += Position(8,8,0); _parent->statePushFront(new ExplosionBState(_parent, p, BA_NONE, 0, _unit, t)); } }
/** * Calculates the effects of the explosion. */ void ExplosionBState::explode() { bool terrainExplosion = false; SavedBattleGame *save = _parent->getSave(); // last minute adjustment: determine if we actually if (_hit) { save->getBattleGame()->getCurrentAction()->type = BA_NONE; BattleUnit *targetUnit = save->getTile(_center / Position(16, 16, 24))->getUnit(); if (_unit && !_unit->isOut()) { _unit->aim(false); _unit->setCache(0); } if (!RNG::percent(_unit->getFiringAccuracy(BA_HIT, _item))) { _parent->getMap()->cacheUnits(); _parent->popState(); return; } else if (targetUnit && targetUnit->getOriginalFaction() == FACTION_HOSTILE && _unit->getOriginalFaction() == FACTION_PLAYER) { _unit->addMeleeExp(); } if (_item->getRules()->getMeleeHitSound() != -1) { _parent->getResourcePack()->getSoundByDepth(_parent->getDepth(), _item->getRules()->getMeleeHitSound())->play(); } } // after the animation is done, the real explosion/hit takes place if (_item) { if (!_unit && _item->getPreviousOwner()) { _unit = _item->getPreviousOwner(); } if (_areaOfEffect) { save->getTileEngine()->explode(_center, _power, _item->getRules()->getDamageType(), _item->getRules()->getExplosionRadius(), _unit); } else { ItemDamageType type = _item->getRules()->getDamageType(); if (_pistolWhip) { type = DT_STUN; } BattleUnit *victim = save->getTileEngine()->hit(_center, _power, type, _unit); // check if this unit turns others into zombies if (!_item->getRules()->getZombieUnit().empty() && victim && victim->getArmor()->getSize() == 1 && victim->getSpawnUnit().empty() && victim->getOriginalFaction() != FACTION_HOSTILE) { // converts the victim to a zombie on death victim->setSpecialAbility(SPECAB_RESPAWN); victim->setSpawnUnit(_item->getRules()->getZombieUnit()); } } } if (_tile) { save->getTileEngine()->explode(_center, _power, DT_HE, _power/10); terrainExplosion = true; } if (!_tile && !_item) { int radius = 6; // explosion not caused by terrain or an item, must be by a unit (cyberdisc) if (_unit && _unit->getSpecialAbility() == SPECAB_EXPLODEONDEATH) { radius = _parent->getRuleset()->getItem(_unit->getArmor()->getCorpseGeoscape())->getExplosionRadius(); } save->getTileEngine()->explode(_center, _power, DT_HE, radius); terrainExplosion = true; } // now check for new casualties _parent->checkForCasualties(_item, _unit, false, terrainExplosion); // if this explosion was caused by a unit shooting, now it's the time to put the gun down if (_unit && !_unit->isOut() && _lowerWeapon) { _unit->aim(false); _unit->setCache(0); } _parent->getMap()->cacheUnits(); _parent->popState(); // check for terrain explosions Tile *t = save->getTileEngine()->checkForTerrainExplosions(); if (t) { Position p = Position(t->getPosition().x * 16, t->getPosition().y * 16, t->getPosition().z * 24); p += Position(8,8,0); _parent->statePushFront(new ExplosionBState(_parent, p, 0, _unit, t)); } if (_item && (_item->getRules()->getBattleType() == BT_GRENADE || _item->getRules()->getBattleType() == BT_PROXIMITYGRENADE)) { for (std::vector<BattleItem*>::iterator j = _parent->getSave()->getItems()->begin(); j != _parent->getSave()->getItems()->end(); ++j) { if (_item->getId() == (*j)->getId()) { delete *j; _parent->getSave()->getItems()->erase(j); break; } } } }
/** * Calculates the effects of the explosion. */ void ExplosionBState::explode() { bool terrainExplosion = false; SavedBattleGame *save = _parent->getSave(); // last minute adjustment: determine if we actually if (_hit) { if (_attack.attacker && !_attack.attacker->isOut()) { _attack.attacker->aim(false); } if (_power <= 0) { _parent->popState(); return; } int sound = _attack.weapon_item->getRules()->getMeleeHitSound(); if (_attack.weapon_item != _attack.damage_item) { // melee weapon with ammo optValue(sound, _attack.damage_item->getRules()->getMeleeHitSound()); } _parent->playSound(sound, _center.toTile()); } bool range = !(_hit || (_attack.weapon_item && _attack.weapon_item->getRules()->getBattleType() == BT_PSIAMP)); // after the animation is done, the real explosion/hit takes place /*if (_item) { if (!_unit && _item->getPreviousOwner()) { _unit = _item->getPreviousOwner(); }*/ if (_areaOfEffect) { save->getTileEngine()->explode(_attack, _center, _power, _damageType, _radius, range); } else //if (!_cosmetic) { if (_damageType->ResistType == DT_TELEPORT) { Tile *destination = _tile ? _tile : save->getTile(Position(_center.x / 16, _center.y / 16, _center.z / 24)); if (_attack.attacker && destination && !destination->getUnit()) { save->getTile(_attack.attacker->getPosition())->setUnit(0); const Position& oldPosition = _attack.attacker->getPosition(); _attack.attacker->setPosition(destination->getPosition()); destination->setUnit(_attack.attacker); save->getTileEngine()->calculateFOV(oldPosition); save->getTileEngine()->calculateFOV(destination->getPosition()); } } else { BattleUnit *victim = save->getTileEngine()->hit(_attack, _center, _power, _action.type, _damageType, range); const RuleItem *hitItem = _attack.damage_item->getRules(); // check if this unit turns others into zombies if (!hitItem->getZombieUnit().empty() && RNG::percent(hitItem->getSpecialChance()) && victim && victim->getArmor()->getZombiImmune() == false && victim->getSpawnUnit().empty() && victim->getOriginalFaction() != FACTION_HOSTILE) { // converts the victim to a zombie on death victim->setRespawn(true); victim->setSpawnUnit(hitItem->getZombieUnit()); } } } //} if (_tile) { /*ItemDamageType DT; switch (_tile->getExplosiveType()) { case 0: DT = DT_HE; break; case 5: DT = DT_IN; break; case 6: DT = DT_STUN; break; default: DT = DT_SMOKE; break; } if (DT != DT_HE) { _tile->setExplosive(0, 0, true); } save->getTileEngine()->explode(_center, _power, _parent->getCurrentAction()->type, DT, _power / 10, 0);*/ terrainExplosion = true; } if (!_tile && !_attack.damage_item) { /*int radius = 6; // explosion not caused by terrain or an item, must be by a unit (cyberdisc) if (_unit && (_unit->getSpecialAbility() == SPECAB_EXPLODEONDEATH || _unit->getSpecialAbility() == SPECAB_BURN_AND_EXPLODE)) { radius = _parent->getMod()->getItem(_unit->getArmor()->getCorpseGeoscape(), true)->getExplosionRadius(); } save->getTileEngine()->explode(_center, _power, _parent->getCurrentAction()->type, DT_HE, radius, 0);*/ terrainExplosion = true; } // now check for new casualties _parent->checkForCasualties(_damageType, _attack, false, terrainExplosion, _subState); // revive units if damage could give hp or reduce stun _parent->getSave()->reviveUnconsciousUnits(true); // if this explosion was caused by a unit shooting, now it's the time to put the gun down if (_attack.attacker && !_attack.attacker->isOut() && _lowerWeapon) { _attack.attacker->aim(false); } if (_attack.damage_item && (_attack.damage_item->getRules()->getBattleType() == BT_GRENADE || _attack.damage_item->getRules()->getBattleType() == BT_PROXIMITYGRENADE)) { _parent->getSave()->removeItem(_attack.damage_item); } //_finished = true; //if(!_subState) _parent->popState(); // check for terrain explosions Tile *t = save->getTileEngine()->checkForTerrainExplosions(); if (t) { Position p = t->getPosition().toVexel(); p += Position(8, 8, 0); { //_parent->statePushFront(new ExplosionBState(_parent, p, BattleActionAttack{ BA_NONE, _attack.attacker, }, t)); if (!_subState) { _parent->statePushFront(new ExplosionBState(_parent, p, BattleActionAttack{ BA_NONE, _attack.attacker, }, t)); } else { _terrainExplosion = new ExplosionBState(_parent, p, BattleActionAttack{ BA_NONE, _attack.attacker, }, t, false, false, true); } } } }