/** * init sequence: * - check if shot is valid * - calculate base accuracy */ void ProjectileFlyBState::init() { if (_initialized) return; _initialized = true; BattleItem *weapon = _action.weapon; _projectileItem = 0; if (!weapon) // can't shoot without weapon { _parent->popState(); return; } if (!_parent->getSave()->getTile(_action.target)) // invalid target position { _parent->popState(); return; } if (_parent->getPanicHandled() && _action.actor->getTimeUnits() < _action.TU) { _action.result = "STR_NOT_ENOUGH_TIME_UNITS"; _parent->popState(); return; } _unit = _action.actor; _ammo = weapon->getAmmoItem(); if (_unit->isOut()) { // something went wrong - we can't shoot when dead or unconscious _parent->popState(); return; } // reaction fire if (_unit->getFaction() != _parent->getSave()->getSide()) { // no ammo or target is dead: give the time units back and cancel the shot. if (_ammo == 0 || !_parent->getSave()->getTile(_action.target)->getUnit() || _parent->getSave()->getTile(_action.target)->getUnit()->isOut()) { _unit->setTimeUnits(_unit->getTimeUnits() + _unit->getActionTUs(_action.type, _action.weapon)); _parent->popState(); return; } } // autoshot will default back to snapshot if it's not possible if (weapon->getRules()->getAccuracyAuto() == 0 && _action.type == BA_AUTOSHOT) _action.type = BA_SNAPSHOT; // snapshot defaults to "hit" if it's a melee weapon // (in case of reaction "shots" with a melee weapon) if (weapon->getRules()->getBattleType() == BT_MELEE && _action.type == BA_SNAPSHOT) _action.type = BA_HIT; switch (_action.type) { case BA_SNAPSHOT: case BA_AIMEDSHOT: case BA_AUTOSHOT: case BA_LAUNCH: if (_ammo == 0) { _action.result = "STR_NO_AMMUNITION_LOADED"; _parent->popState(); return; } if (_ammo->getAmmoQuantity() == 0) { _action.result = "STR_NO_ROUNDS_LEFT"; _parent->popState(); return; } break; case BA_THROW: if (!validThrowRange(&_action)) { // out of range _action.result = "STR_OUT_OF_RANGE"; _parent->popState(); return; } _projectileItem = weapon; break; case BA_HIT: if (!_parent->getTileEngine()->validMeleeRange(_action.actor->getPosition(), _action.actor->getDirection(), _action.actor->getArmor()->getSize(), 0)) { _action.result = "STR_THERE_IS_NO_ONE_THERE"; _parent->popState(); return; } break; case BA_PANIC: case BA_MINDCONTROL: _parent->statePushFront(new ExplosionBState(_parent, Position((_action.target.x*16)+8,(_action.target.y*16)+8,(_action.target.z*24)+10), weapon, _action.actor)); return; default: _parent->popState(); return; } createNewProjectile(); }
/** * init sequence: * - check if shot is valid * - calculate base accuracy */ void ProjectileFlyBState::init() { if (_initialized) return; _initialized = true; BattleItem *weapon = _action.weapon; _projectileItem = 0; _autoshotCounter = 0; if (!weapon) // can't shoot without weapon return; if (!_parent->getSave()->getTile(_action.target)) // invalid target position return; if (_action.actor->getTimeUnits() < _action.TU && !_parent->dontSpendTUs()) { _action.result = "STR_NOT_ENOUGH_TIME_UNITS"; _parent->popState(); return; } _unit = _action.actor; _ammo = weapon->getAmmoItem(); if (_unit->isOut()) { // something went wrong - we can't shoot when dead or unconscious _parent->popState(); return; } // autoshot will default back to snapshot if it's not possible if (weapon->getRules()->getAccuracyAuto() == 0 && _action.type == BA_AUTOSHOT) _action.type = BA_SNAPSHOT; // snapshot defaults to "hit" if it's a melee weapon // (in case of reaction "shots" with a melee weapon) if (weapon->getRules()->getBattleType() == BT_MELEE && _action.type == BA_SNAPSHOT) _action.type = BA_HIT; switch (_action.type) { case BA_SNAPSHOT: case BA_AIMEDSHOT: case BA_AUTOSHOT: case BA_LAUNCH: if (_ammo == 0) { _action.result = "STR_NO_AMMUNITION_LOADED"; _parent->popState(); return; } if (_ammo->getAmmoQuantity() == 0) { _action.result = "STR_NO_ROUNDS_LEFT"; _parent->popState(); return; } break; case BA_THROW: if (!validThrowRange(&_action)) { // out of range _action.result = "STR_OUT_OF_RANGE"; _parent->popState(); return; } _projectileItem = weapon; break; case BA_HIT: if (!validMeleeRange(&_action)) { _action.result = "STR_THERE_IS_NO_ONE_THERE"; _parent->popState(); return; } break; case BA_PANIC: case BA_MINDCONTROL: _parent->statePushFront(new ExplosionBState(_parent, Position((_action.target.x*16)+8,(_action.target.y*16)+8,(_action.target.z*24)+10), weapon, _action.actor)); return; default: _parent->popState(); return; } if (createNewProjectile() == true) { BattleAction action; BattleUnit *potentialVictim = _parent->getSave()->getTile(_action.target)->getUnit(); if (potentialVictim && potentialVictim->getFaction() != _unit->getFaction()) { if (_parent->getSave()->getTileEngine()->checkReactionFire(_unit, &action, potentialVictim, false)) { _parent->statePushBack(new ProjectileFlyBState(_parent, action)); } } } }
/** * init sequence: * - check if shot is valid * - calculate base accuracy */ void ProjectileFlyBState::init() { if (_initialized) return; _initialized = true; BattleItem *weapon = _action.weapon; _projectileItem = 0; _autoshotCounter = 0; if (!weapon) // can't shoot without weapon return; if (_action.actor->getTimeUnits() < _action.TU && !_parent->dontSpendTUs()) { _result = "STR_NOT_ENOUGH_TIME_UNITS"; _parent->popState(); return; } _unit = _action.actor; _ammo = weapon->getAmmoItem(); if (_unit->isOut()) { // something went wrong _parent->popState(); return; } if (_action.type != BA_THROW) { if (_ammo == 0) { _result = "STR_NO_AMMUNITION_LOADED"; _parent->popState(); return; } if (_ammo->getAmmoQuantity() == 0) { _result = "STR_NO_ROUNDS_LEFT"; _parent->popState(); return; } } // action specific initialisation switch (_action.type) { case BA_AUTOSHOT: _baseAcc = weapon->getRules()->getAccuracyAuto(); break; case BA_SNAPSHOT: _baseAcc = weapon->getRules()->getAccuracySnap(); break; case BA_AIMEDSHOT: _baseAcc = weapon->getRules()->getAccuracyAimed(); break; case BA_THROW: if (!validThrowRange()) { // out of range _result = "STR_OUT_OF_RANGE"; _parent->popState(); return; } _baseAcc = (int)(_unit->getThrowingAccuracy()*100.0); _projectileItem = weapon; break; default: _baseAcc = 0; } createNewProjectile(); BattleAction action; BattleUnit *potentialVictim = _parent->getGame()->getSavedGame()->getBattleGame()->getTile(_action.target)->getUnit(); if (potentialVictim && potentialVictim->getFaction() != _unit->getFaction()) { if (_parent->getGame()->getSavedGame()->getBattleGame()->getTileEngine()->checkReactionFire(_unit, &action, potentialVictim, false)) { _parent->statePushBack(new ProjectileFlyBState(_parent, action)); } } }