int CMap::Select(int x1, int y1, int x2, int y2, CUnit *table[], const int tablesize) { // Reduce to map limits. Vec2i ltpos = {std::max<int>(x1, 0), std::max<int>(y1, 0)}; Vec2i rbpos = {std::min<int>(x2, Info.MapWidth - 1), std::min<int>(y2, Info.MapHeight - 1)}; return SelectFixed(ltpos, rbpos, table, tablesize); }
/** ** Cast demolish ** @param caster Unit that casts the spell ** @param spell Spell-type pointer ** @param target Target unit that spell is addressed to ** @param goalPos tilePos of target spot when/if target does not exist ** ** @return =!0 if spell should be repeated, 0 if not */ /* virtual */ int Spell_Demolish::Cast(CUnit &caster, const SpellType &, CUnit *, const Vec2i &goalPos) { // Allow error margins. (Lame, I know) const Vec2i offset(this->Range + 2, this->Range + 2); //Wyrmgus start // Vec2i minpos = goalPos - offset; // Vec2i maxpos = goalPos + offset; Vec2i minpos = caster.tilePos - offset; Vec2i maxpos = caster.tilePos + Vec2i(caster.Type->TileWidth - 1, caster.Type->TileHeight - 1) + offset; //Wyrmgus end Map.FixSelectionArea(minpos, maxpos); // // Terrain effect of the explosion // //Wyrmgus start /* Vec2i ipos; for (ipos.x = minpos.x; ipos.x <= maxpos.x; ++ipos.x) { for (ipos.y = minpos.y; ipos.y <= maxpos.y; ++ipos.y) { const CMapField &mf = *Map.Field(ipos); if (SquareDistance(ipos, goalPos) > square(this->Range)) { // Not in circle range continue; } else if (mf.isAWall()) { Map.RemoveWall(ipos); } else if (mf.RockOnMap()) { Map.ClearRockTile(ipos); } else if (mf.ForestOnMap()) { Map.ClearWoodTile(ipos); } } } */ if (this->DamageTerrain) { Vec2i ipos; for (ipos.x = minpos.x; ipos.x <= maxpos.x; ++ipos.x) { for (ipos.y = minpos.y; ipos.y <= maxpos.y; ++ipos.y) { const CMapField &mf = *Map.Field(ipos); //Wyrmgus start // if (SquareDistance(ipos, caster.tilePos) > square(this->Range)) { if (caster.MapDistanceTo(ipos) > this->Range) { //Wyrmgus end // Not in circle range continue; } else if (mf.isAWall()) { Map.RemoveWall(ipos); } else if (mf.RockOnMap()) { Map.ClearRockTile(ipos); } else if (mf.ForestOnMap()) { Map.ClearWoodTile(ipos); } } } } //Wyrmgus end // // Effect of the explosion on units. Don't bother if damage is 0 // //Wyrmgus start //if (this->Damage) { if (this->Damage || this->BasicDamage || this->PiercingDamage || this->FireDamage || this->ColdDamage || this->ArcaneDamage || this->LightningDamage || this->AirDamage || this->EarthDamage || this->WaterDamage) { //Wyrmgus end std::vector<CUnit *> table; SelectFixed(minpos, maxpos, table); for (size_t i = 0; i != table.size(); ++i) { CUnit &unit = *table[i]; if (unit.Type->UnitType != UnitTypeFly && unit.IsAlive() //Wyrmgus start // && unit.MapDistanceTo(goalPos) <= this->Range) { // Don't hit flying units! // HitUnit(&caster, unit, this->Damage); && unit.MapDistanceTo(caster) <= this->Range && (UnitNumber(unit) != UnitNumber(caster) || this->DamageSelf) && (caster.IsEnemy(unit) || this->DamageFriendly)) { int damage = 0; if (this->BasicDamage || this->PiercingDamage || this->FireDamage || this->ColdDamage || this->ArcaneDamage || this->LightningDamage || this->AirDamage || this->EarthDamage || this->WaterDamage) { damage = std::max<int>(this->BasicDamage - unit.Variable[ARMOR_INDEX].Value, 1); damage += this->PiercingDamage; //apply resistances if (this->HackDamage) { damage *= 100 - unit.Variable[HACKRESISTANCE_INDEX].Value; damage /= 100; } else if (this->PierceDamage) { damage *= 100 - unit.Variable[PIERCERESISTANCE_INDEX].Value; damage /= 100; } else if (this->BluntDamage) { damage *= 100 - unit.Variable[BLUNTRESISTANCE_INDEX].Value; damage /= 100; } //apply fire and cold damage damage += this->FireDamage * (100 - unit.Variable[FIRERESISTANCE_INDEX].Value) / 100; damage += this->ColdDamage * (100 - unit.Variable[COLDRESISTANCE_INDEX].Value) / 100; damage += this->ArcaneDamage * (100 - unit.Variable[ARCANERESISTANCE_INDEX].Value) / 100; damage += this->LightningDamage * (100 - unit.Variable[LIGHTNINGRESISTANCE_INDEX].Value) / 100; damage += this->AirDamage * (100 - unit.Variable[AIRRESISTANCE_INDEX].Value) / 100; damage += this->EarthDamage * (100 - unit.Variable[EARTHRESISTANCE_INDEX].Value) / 100; damage += this->WaterDamage * (100 - unit.Variable[WATERRESISTANCE_INDEX].Value) / 100; damage -= SyncRand() % ((damage + 2) / 2); } HitUnit(&caster, unit, this->Damage + damage); //Wyrmgus end } } } return 1; }