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