예제 #1
0
/**
 * Performs all the overall functions of the state, this code runs AFTER the explosion state pops.
 */
void MeleeAttackBState::think()
{
	_parent->getSave()->getBattleState()->clearMouseScrollingState();

	// if the unit burns floortiles, burn floortiles
	if (_unit->getSpecialAbility() == SPECAB_BURNFLOOR || _unit->getSpecialAbility() == SPECAB_BURN_AND_EXPLODE)
	{
		_parent->getSave()->getTile(_action.target)->ignite(15);
	}
	// Determine if the attack was successful
	// we do this here instead of letting the explosionBState take care of damage and casualty checking
	// this is because unlike regular bullet hits or explosions, melee attacks can MISS.
	// we also do it at this point instead of in performMeleeAttack because we want the scream to come AFTER the hit sound
	resolveHit();
		// aliens
	if (_unit->getFaction() != FACTION_PLAYER &&
		// not performing a reaction attack
		_unit->getFaction() == _parent->getSave()->getSide() &&
		// with enough TU for a second attack (*2 because they'll get charged for the initial attack when this state pops.)
		_unit->getTimeUnits() >= _unit->getActionTUs(BA_HIT, _action.weapon) * 2 &&
		// whose target is still alive or at least conscious
		_target && _target->getHealth() > 0 &&
		_target->getHealth() > _target->getStunlevel() &&
		// and we still have ammo to make the attack
		_weapon->getAmmoItem())
	{
		// spend the TUs immediately
		_unit->spendTimeUnits(_unit->getActionTUs(BA_HIT, _weapon));
		performMeleeAttack();
	}
	else
	{
		if (_action.cameraPosition.z != -1)
		{
			_parent->getMap()->getCamera()->setMapOffset(_action.cameraPosition);
			_parent->getMap()->invalidate();
		}
//		melee doesn't trigger a reaction, remove comments to enable.
//		if (!_parent->getSave()->getUnitsFalling())
//		{
//			_parent->getTileEngine()->checkReactionFire(_unit);
//		}
		
		if (_parent->getSave()->getSide() == FACTION_PLAYER || _parent->getSave()->getDebugMode())
		{
			_parent->setupCursor();
		}
		_parent->convertInfected();
		_parent->popState();
	}
}
예제 #2
0
/**
 * Performs all the overall functions of the state, this code runs AFTER the explosion state pops.
 */
void MeleeAttackBState::think()
{
	_parent->getSave()->getBattleState()->clearMouseScrollingState();
	if (_reaction && !_parent->getSave()->getUnitsFalling())
	{
		_reaction = false;
		if (_parent->getTileEngine()->checkReactionFire(_unit, _action))
		{
			return;
		}
	}

	// if the unit burns floortiles, burn floortiles
	if (_unit->getSpecialAbility() == SPECAB_BURNFLOOR || _unit->getSpecialAbility() == SPECAB_BURN_AND_EXPLODE)
	{
		_parent->getSave()->getTile(_action.target)->ignite(15);
	}
	if (_hitNumber > 0 &&
		// not performing a reaction attack
		_unit->getFaction() == _parent->getSave()->getSide() &&
		// whose target is still alive or at least conscious
		_target && !_target->isOutThresholdExceed() &&
		// and we still have ammo to make the attack
		_weapon->getAmmoForAction(BA_HIT) &&
		// spend the TUs immediately
		_action.spendTU())
	{
		--_hitNumber;
		performMeleeAttack();
	}
	else
	{
		if (_action.cameraPosition.z != -1)
		{
			_parent->getMap()->getCamera()->setMapOffset(_action.cameraPosition);
			_parent->getMap()->invalidate();
		}

		if (_parent->getSave()->getSide() == FACTION_PLAYER || _parent->getSave()->getDebugMode())
		{
			_parent->setupCursor();
		}
		_parent->convertInfected();
		_parent->popState();
	}
}
예제 #3
0
/**
 * Initializes the sequence.
 * does a lot of validity checking.
 */
void MeleeAttackBState::init()
{
	if (_initialized) return;
	_initialized = true;

	_weapon = _action.weapon;
	if (!_weapon) // can't hit without weapon
	{
		_parent->popState();
		return;
	}

	_unit = _action.actor;

	bool reactionShoot = _unit->getFaction() != _parent->getSave()->getSide();
	_ammo = _action.weapon->getAmmoForAction(BA_HIT, reactionShoot ? nullptr : &_action.result);
	if (!_ammo)
	{
		_parent->popState();
		return;
	}

	if (!_parent->getSave()->getTile(_action.target)) // invalid target position
	{
		_parent->popState();
		return;
	}

	if (_unit->isOut() || _unit->isOutThresholdExceed())
	{
		// something went wrong - we can't shoot when dead or unconscious, or if we're about to fall over.
		_parent->popState();
		return;
	}

	// reaction fire
	if (reactionShoot)
	{
		// no ammo or target is dead: give the time units back and cancel the shot.
		auto target = _parent->getSave()->getTile(_action.target)->getUnit();
		if (!target || target->isOut() || target->isOutThresholdExceed() || target != _parent->getSave()->getSelectedUnit())
		{
			_parent->popState();
			return;
		}
		_unit->lookAt(_action.target, _unit->getTurretType() != -1);
		while (_unit->getStatus() == STATUS_TURNING)
		{
			_unit->turn();
		}
	}

	//spend TU
	if (!_action.spendTU(&_action.result))
	{
		_parent->popState();
		return;
	}


	AIModule *ai = _unit->getAIModule();

	if (_unit->getFaction() == _parent->getSave()->getSide() &&
		_unit->getFaction() != FACTION_PLAYER &&
		_parent->_debugPlay == false &&
		ai && ai->getTarget())
	{
		_target = ai->getTarget();
	}
	else
	{
		_target = _parent->getSave()->getTile(_action.target)->getUnit();
	}

	int height = _target->getFloatHeight() + (_target->getHeight() / 2) - _parent->getSave()->getTile(_action.target)->getTerrainLevel();
	_voxel = _action.target.toVexel() + Position(8, 8, height);

	if (_unit->getFaction() == FACTION_HOSTILE)
	{
		_hitNumber = _weapon->getRules()->getAIMeleeHitCount() - 1;
	}

	performMeleeAttack();
}
예제 #4
0
/**
 * Initializes the sequence.
 * does a lot of validity checking.
 */
void MeleeAttackBState::init()
{
	if (_initialized) return;
	_initialized = true;

	_weapon = _action.weapon;
	_ammo = _weapon->getAmmoItem();

	if (!_weapon) // can't shoot without weapon
	{
		_parent->popState();
		return;
	}

	if (!_parent->getSave()->getTile(_action.target)) // invalid target position
	{
		_parent->popState();
		return;
	}

	_unit = _action.actor;
	
	if (_unit->isOut() || _unit->getHealth() == 0 || _unit->getHealth() < _unit->getStunlevel())
	{
		// something went wrong - we can't shoot when dead or unconscious, or if we're about to fall over.
		_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()
			|| _parent->getSave()->getTile(_action.target)->getUnit() != _parent->getSave()->getSelectedUnit())
		{
			_unit->setTimeUnits(_unit->getTimeUnits() + _unit->getActionTUs(_action.type, _action.weapon));
			_parent->popState();
			return;
		}
		_unit->lookAt(_action.target, _unit->getTurretType() != -1);
		while (_unit->getStatus() == STATUS_TURNING)
		{
			_unit->turn();
		}
	}

	
	AlienBAIState *ai = dynamic_cast<AlienBAIState*>(_unit->getCurrentAIState());

	if (_unit->getFaction() != FACTION_PLAYER && _parent->_debugPlay == false && ai && ai->getTarget())
	{
		_target = ai->getTarget();
	}
	else
	{
		_target = _parent->getSave()->getTile(_action.target)->getUnit();
	}

	int height = _target->getFloatHeight() + (_target->getHeight() / 2) - _parent->getSave()->getTile(_action.target)->getTerrainLevel();
	_voxel = _action.target * Position(16, 16, 24) + Position(8, 8, height);

	performMeleeAttack();
}