/** * Animates the projectile (move to the next point in it's trajectory). * If the animation is finished the projectile sprite is removed from the map. * And this state is finished. */ void ProjectileFlyBState::think() { /* TODO refactoring : store the projectile in this state, instead of getting it from the map each time? */ if (_parent->getMap()->getProjectile() == 0) { if (_action.type == BA_AUTOSHOT && _autoshotCounter < 3 && !_action.actor->isOut() && _ammo->getAmmoQuantity() != 0) { createNewProjectile(); } else { _parent->popState(); } } else { if(!_parent->getMap()->getProjectile()->move()) { // impact ! if (_action.type == BA_THROW) { Position pos = _parent->getMap()->getProjectile()->getPosition(-1); pos.x /= 16; pos.y /= 16; pos.z /= 24; BattleItem *item = _parent->getMap()->getProjectile()->getItem(); _parent->getResourcePack()->getSoundSet("BATTLE.CAT")->getSound(38)->play(); if (Options::getBool("battleAltGrenade") && item->getRules()->getBattleType() == BT_GRENADE && item->getExplodeTurn() > 0) { // it's a hot grenade to explode immediately _parent->statePushFront(new ExplosionBState(_parent, _parent->getMap()->getProjectile()->getPosition(-1), item, _action.actor)); } else { _parent->dropItem(pos, item); } } else if (_action.type == BA_LAUNCH && _action.waypoints.size() > 1 && _projectileImpact == -1) { _origin = _action.waypoints.front(); _action.waypoints.pop_front(); _action.target = _action.waypoints.front(); // launch the next projectile in the waypoint cascade _parent->statePushBack(new ProjectileFlyBState(_parent, _action, _origin)); } else { if (_action.type == BA_LAUNCH && _ammo->spendBullet() == false) { _parent->getSave()->removeItem(_ammo); _action.weapon->setAmmoItem(0); } if (_projectileImpact != 5) // out of map { int offset = 0; // explosions impact not inside the voxel but one step back if (_ammo && ( _ammo->getRules()->getDamageType() == DT_HE || _ammo->getRules()->getDamageType() == DT_IN)) { offset = -1; } _parent->statePushFront(new ExplosionBState(_parent, _parent->getMap()->getProjectile()->getPosition(offset), _ammo, _action.actor)); } else { _unit->aim(false); _parent->getMap()->cacheUnits(); } } delete _parent->getMap()->getProjectile(); _parent->getMap()->setProjectile(0); } } }
/** * Animates the projectile (move to the next point in it's trajectory). * If the animation is finished the projectile sprite is removed from the map. * And this state is finished. */ void ProjectileFlyBState::think() { /* TODO refactoring : store the projectile in this state, instead of getting it from the map each time? */ if (_parent->getMap()->getProjectile() == 0) { if (_action.type == BA_AUTOSHOT && _action.autoShotCounter < 3 && !_action.actor->isOut() && _ammo->getAmmoQuantity() != 0) { createNewProjectile(); } else { if (_action.cameraPosition.z != -1) { _parent->getMap()->getCamera()->setMapOffset(_action.cameraPosition); } if (_action.type != BA_PANIC && _action.type != BA_MINDCONTROL) { _parent->getTileEngine()->checkReactionFire(_unit); } _unit->abortTurn(); _parent->popState(); } } else { if(!_parent->getMap()->getProjectile()->move()) { // impact ! if (_action.type == BA_THROW) { Position pos = _parent->getMap()->getProjectile()->getPosition(-1); pos.x /= 16; pos.y /= 16; pos.z /= 24; BattleItem *item = _parent->getMap()->getProjectile()->getItem(); _parent->getResourcePack()->getSound("BATTLE.CAT", 38)->play(); if (Options::getBool("battleInstantGrenade") && item->getRules()->getBattleType() == BT_GRENADE && item->getExplodeTurn() != 0 && item->getExplodeTurn() <= _parent->getSave()->getTurn()) { // it's a hot grenade to explode immediately _parent->statePushFront(new ExplosionBState(_parent, _parent->getMap()->getProjectile()->getPosition(-1), item, _action.actor)); } else { _parent->dropItem(pos, item); } } else if (_action.type == BA_LAUNCH && _action.waypoints.size() > 1 && _projectileImpact == -1) { _origin = _action.waypoints.front(); _action.waypoints.pop_front(); _action.target = _action.waypoints.front(); // launch the next projectile in the waypoint cascade _parent->statePushBack(new ProjectileFlyBState(_parent, _action, _origin)); } else { if (_ammo && _action.type == BA_LAUNCH && _ammo->spendBullet() == false) { _parent->getSave()->removeItem(_ammo); _action.weapon->setAmmoItem(0); } if (_projectileImpact != 5) // out of map { int offset = 0; // explosions impact not inside the voxel but two steps back (projectiles generally move 2 voxels at a time) if (_ammo && ( _ammo->getRules()->getDamageType() == DT_HE || _ammo->getRules()->getDamageType() == DT_IN)) { offset = -2; } _parent->statePushFront(new ExplosionBState(_parent, _parent->getMap()->getProjectile()->getPosition(offset), _ammo, _action.actor, 0, (_action.type != BA_AUTOSHOT || _action.autoShotCounter == 3|| !_action.weapon->getAmmoItem()))); if (_projectileImpact == 4) { BattleUnit *victim = _parent->getSave()->getTile(_parent->getMap()->getProjectile()->getPosition(offset) / Position(16,16,24))->getUnit(); if (victim && !victim->isOut() && victim->getFaction() == FACTION_HOSTILE) { AggroBAIState *aggro = dynamic_cast<AggroBAIState*>(victim->getCurrentAIState()); if (aggro == 0) { aggro = new AggroBAIState(_parent->getSave(), victim); victim->setAIState(aggro); } aggro->setAggroTarget(_action.actor); } } } else if (_action.type != BA_AUTOSHOT || _action.autoShotCounter == 3 || !_action.weapon->getAmmoItem()) { _unit->aim(false); _parent->getMap()->cacheUnits(); } } delete _parent->getMap()->getProjectile(); _parent->getMap()->setProjectile(0); } } }