Esempio n. 1
0
/**
**  Check if the unit's container has an adjacent unit owned by another non-neutral player
**
**  @return  true if the unit is now sheltered (or if exited a shelter), false otherwise
*/
static bool LeaveShelter(CUnit &unit)
{
	if (
		!unit.Container
		|| (unit.Container->Type->BoolFlag[ATTACKFROMTRANSPORTER_INDEX].value && unit.Type->BoolFlag[ATTACKFROMTRANSPORTER_INDEX].value)
		|| (!unit.Player->AiEnabled && !(unit.Type->BoolFlag[FAUNA_INDEX].value && unit.Player->Type == PlayerNeutral))
		|| unit.Container->CanMove() //is a transporter, not a shelter
		|| !unit.Container->Type->CanTransport() //is not a garrisonable building
		|| (unit.Container->Type->BoolFlag[RECRUITHEROES_INDEX].value && unit.Character && unit.Player->Type == PlayerNeutral) //if is a hireable hero in a hero recruitment building, don't leave it
	) {
		return false;
	}
	
	std::vector<CUnit *> table;
	if (unit.Type->BoolFlag[FAUNA_INDEX].value) {
		SelectAroundUnit(*unit.Container, 1, table, HasNotSamePlayerAs(*unit.Player));
	} else {
		SelectAroundUnit(*unit.Container, unit.CurrentSightRange, table, MakeAndPredicate(IsEnemyWith(*unit.Player), HasNotSamePlayerAs(Players[PlayerNumNeutral])));
	}

	if (table.size() > 0) {
		CommandUnload(*unit.Container, unit.Container->tilePos, &unit, FlushCommands, unit.Container->MapLayer->ID);
		return true;
	}

	return false;
}
Esempio n. 2
0
/**
**  Death-Coil class. Damages organic units and gives to the caster.
**
**  @todo  do it configurable.
*/
void MissileDeathCoil::Action()
{
	this->Wait = this->Type->Sleep;
	if (PointToPointMissile(*this)) {
		Assert(this->SourceUnit != NULL);
		CUnit &source = *this->SourceUnit;

		if (source.Destroyed) {
			return;
		}
		// source unit still exists
		//
		// Target unit still exists and casted on a special target
		//
		if (this->TargetUnit && !this->TargetUnit->Destroyed
			&& this->TargetUnit->CurrentAction() == UnitActionDie) {
			HitUnit(&source, *this->TargetUnit, this->Damage);
			if (source.CurrentAction() != UnitActionDie) {
				source.Variable[HP_INDEX].Value += this->Damage;
				if (source.Variable[HP_INDEX].Value > source.Variable[HP_INDEX].Max) {
					source.Variable[HP_INDEX].Value = source.Variable[HP_INDEX].Max;
				}
			}
		} else {
			//
			// No target unit -- try enemies in range 5x5 // Must be parametrable
			//
			std::vector<CUnit *> table;
			const Vec2i destPos = Map.MapPixelPosToTilePos(this->destination);
			const Vec2i range(2, 2);
			Select(destPos - range, destPos + range, table, IsEnemyWith(*source.Player));

			if (table.empty()) {
				return;
			}
			const size_t n = table.size();  // enemy count
			const int damage = std::min<int>(1, this->Damage / n);

			// disperse damage between them
			for (size_t i = 0; i != n; ++i) {
				HitUnit(&source, *table[i], damage);
			}
			if (source.CurrentAction() != UnitActionDie) {
				source.Variable[HP_INDEX].Value += this->Damage;
				if (source.Variable[HP_INDEX].Value > source.Variable[HP_INDEX].Max) {
					source.Variable[HP_INDEX].Value = source.Variable[HP_INDEX].Max;
				}
			}
		}
		this->TTL = 0;
	}
}