/** * 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; } } } }
/** * 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; } } } }