void MissileHandlePierce(Missile &missile, const Vec2i &pos) { CUnit *unit = UnitOnMapTile(pos, -1); if (unit && unit->IsAliveOnMap() && (missile.Type->FriendlyFire || unit->IsEnemy(*missile.SourceUnit->Player))) { missile.MissileHit(unit); } }
void MissileHandlePierce(Missile &missile, const Vec2i &pos) { if (Map.Info.IsPointOnMap(pos) == false) { return; } std::vector<CUnit *> units; Select(pos, pos, units); for (std::vector<CUnit *>::iterator it = units.begin(); it != units.end(); ++it) { CUnit &unit = **it; if (unit.IsAliveOnMap() && (missile.Type->FriendlyFire == false || unit.IsEnemy(*missile.SourceUnit->Player))) { missile.MissileHit(&unit); } } }
/** ** Handle point to point missile. ** ** @param missile Missile pointer. ** ** @return true if goal is reached, false else. */ bool PointToPointMissile(Missile &missile) { MissileInitMove(missile); if (missile.TotalStep == 0) { return true; } Assert(missile.Type != NULL); Assert(missile.TotalStep != 0); const PixelPos diff = (missile.destination - missile.source); const PixelPrecise sign(diff.x >= 0 ? 1.0 : -1.0, diff.y >= 0 ? 1.0 : -1.0); // Remember sign to move into correct direction const PixelPrecise oldPos((double)missile.position.x, (double)missile.position.y); // Remember old position PixelPrecise pos(oldPos); missile.position = missile.source + diff * missile.CurrentStep / missile.TotalStep; for (; pos.x * sign.x <= missile.position.x * sign.x && pos.y * sign.y <= missile.position.y * sign.y; pos.x += (double)diff.x * missile.Type->SmokePrecision / missile.TotalStep, pos.y += (double)diff.y * missile.Type->SmokePrecision / missile.TotalStep) { const PixelPos position((int)pos.x + missile.Type->size.x / 2, (int)pos.y + missile.Type->size.y / 2); if (missile.Type->Smoke.Missile && (missile.CurrentStep || missile.State > 1)) { Missile *smoke = MakeMissile(*missile.Type->Smoke.Missile, position, position); if (smoke && smoke->Type->NumDirections > 1) { smoke->MissileNewHeadingFromXY(diff); } } if (missile.Type->SmokeParticle && (missile.CurrentStep || missile.State > 1)) { missile.Type->SmokeParticle->pushPreamble(); missile.Type->SmokeParticle->pushInteger(position.x); missile.Type->SmokeParticle->pushInteger(position.y); missile.Type->SmokeParticle->run(); } if (missile.Type->Pierce) { const PixelPos posInt((int)pos.x, (int)pos.y); MissileHandlePierce(missile, Map.MapPixelPosToTilePos(posInt)); } } // Handle wall blocking and kill first enemy for (pos = oldPos; pos.x * sign.x <= missile.position.x * sign.x && pos.y * sign.y <= missile.position.y * sign.y; pos.x += (double)diff.x / missile.TotalStep, pos.y += (double)diff.y / missile.TotalStep) { const PixelPos position((int)pos.x + missile.Type->size.x / 2, (int)pos.y + missile.Type->size.y / 2); const Vec2i tilePos(Map.MapPixelPosToTilePos(position)); if (Map.Info.IsPointOnMap(tilePos) && MissileHandleBlocking(missile, position)) { return true; } if (missile.Type->MissileStopFlags) { if (!Map.Info.IsPointOnMap(tilePos)) { // gone outside missile.TTL = 0; return false; } const CMapField &mf = *Map.Field(tilePos); if (missile.Type->MissileStopFlags & mf.Flags) { // incompatible terrain missile.position = position; missile.MissileHit(); missile.TTL = 0; return false; } } } if (missile.CurrentStep == missile.TotalStep) { missile.position = missile.destination; return true; } return false; }