/** * Spawn an alien base. * @param globe The earth globe, required to get access to land checks. * @param engine The game engine, required to get access to game data and game rules. * @param zone The mission zone, required for determining the base coordinates. */ void AlienMission::spawnAlienBase(const Globe &globe, Game &engine, int zone) { SavedGame &game = *engine.getSavedGame(); const Ruleset &ruleset = *engine.getRuleset(); // Once the last UFO is spawned, the aliens build their base. const RuleRegion ®ionRules = *ruleset.getRegion(_region); std::pair<double, double> pos = getLandPoint(globe, regionRules, zone); AlienBase *ab = new AlienBase(); ab->setAlienRace(_race); ab->setId(game.getId("STR_ALIEN_BASE")); ab->setLongitude(pos.first); ab->setLatitude(pos.second); game.getAlienBases()->push_back(ab); addScore(pos.first, pos.second, game); }
/** * This function is called when one of the mission's UFOs has finished it's time on the ground. * It takes care of sending the UFO to the next waypoint and marking them for removal as required. * It must set the game data in a way that the rest of the code understands what to do. * @param ufo The UFO that reached it's waypoint. * @param engine The game engine, required to get access to game data and game rules. * @param globe The earth globe, required to get access to land checks. */ void AlienMission::ufoLifting(Ufo &ufo, Game &engine, const Globe &globe) { const Ruleset &rules = *engine.getRuleset(); switch (ufo.getStatus()) { case Ufo::FLYING: assert(0 && "Ufo is already on the air!"); break; case Ufo::LANDED: { if ((ufo.getRules()->getType() == "STR_HARVESTER" && _rule.getType() == "STR_ALIEN_HARVEST") || (ufo.getRules()->getType() == "STR_ABDUCTOR" && _rule.getType() == "STR_ALIEN_ABDUCTION")) { addScore(ufo.getLongitude(), ufo.getLatitude(), engine); } assert(ufo.getTrajectoryPoint() != ufo.getTrajectory().getWaypointCount() - 1); ufo.setSpeed((int)(ufo.getRules()->getMaxSpeed() * ufo.getTrajectory().getSpeedPercentage(ufo.getTrajectoryPoint()))); ufo.setAltitude("STR_VERY_LOW"); // Set next waypoint. Waypoint *wp = new Waypoint(); RuleRegion *region = rules.getRegion(_region); std::pair<double, double> pos; if (ufo.getTrajectory().getAltitude(ufo.getTrajectoryPoint() + 1) == "STR_GROUND") { pos = getLandPoint(globe, *region, ufo.getTrajectory().getZone(ufo.getTrajectoryPoint() + 1)); } else { pos = region->getRandomPoint(ufo.getTrajectory().getZone(ufo.getTrajectoryPoint() + 1)); } wp->setLongitude(pos.first); wp->setLatitude(pos.second); ufo.setDestination(wp); ufo.setTrajectoryPoint(ufo.getTrajectoryPoint() + 1); } break; case Ufo::CRASHED: // Mission expired ufo.setDetected(false); ufo.setStatus(Ufo::DESTROYED); break; case Ufo::DESTROYED: assert(0 && "UFO can't fly!"); break; } }
/** * This function is called when one of the mission's UFOs arrives at it's current destination. * It takes care of sending the UFO to the next waypoint, landing UFOs and * marking them for removal as required. It must set the game data in a way that the rest of the code * understands what to do. * @param ufo The UFO that reached it's waypoint. * @param engine The game engine, required to get access to game data and game rules. * @param globe The earth globe, required to get access to land checks. */ void AlienMission::ufoReachedWaypoint(Ufo &ufo, Game &engine, const Globe &globe) { const Ruleset &rules = *engine.getRuleset(); SavedGame &game = *engine.getSavedGame(); if (ufo.getTrajectoryPoint() == ufo.getTrajectory().getWaypointCount() - 1) { ufo.setDetected(false); ufo.setStatus(Ufo::DESTROYED); return; } ufo.setAltitude(ufo.getTrajectory().getAltitude(ufo.getTrajectoryPoint() + 1)); if (ufo.getAltitude() != "STR_GROUND") { if (ufo.getLandId() != 0) { ufo.setLandId(0); } ufo.setTrajectoryPoint(ufo.getTrajectoryPoint() + 1); // Set next waypoint. Waypoint *wp = new Waypoint(); RuleRegion *region = rules.getRegion(_region); ufo.setSpeed((int)(ufo.getRules()->getMaxSpeed() * ufo.getTrajectory().getSpeedPercentage(ufo.getTrajectoryPoint()))); std::pair<double, double> pos; if (ufo.getTrajectory().getAltitude(ufo.getTrajectoryPoint()) == "STR_GROUND") { pos = getLandPoint(globe, *region, ufo.getTrajectory().getZone(ufo.getTrajectoryPoint())); } else { pos = region->getRandomPoint(ufo.getTrajectory().getZone(ufo.getTrajectoryPoint())); } wp->setLongitude(pos.first); wp->setLatitude(pos.second); ufo.setDestination(wp); } else { // UFO landed. if (ufo.getRules()->getType() == "STR_TERROR_SHIP" && _rule.getType() == "STR_ALIEN_TERROR" && ufo.getTrajectory().getZone(ufo.getTrajectoryPoint()) == 0) { // Specialized: STR_ALIEN_TERROR // Remove UFO, replace with TerrorSite. addScore(ufo.getLongitude(), ufo.getLatitude(), engine); ufo.setStatus(Ufo::DESTROYED); TerrorSite *terrorSite = new TerrorSite(); terrorSite->setLongitude(ufo.getLongitude()); terrorSite->setLatitude(ufo.getLatitude()); terrorSite->setId(game.getId("STR_TERROR_SITE")); terrorSite->setSecondsRemaining(4 * 3600 + RNG::generate(0, 6) * 3600); terrorSite->setAlienRace(_race); const City *city = rules.locateCity(ufo.getLongitude(), ufo.getLatitude()); assert(city); game.getTerrorSites()->push_back(terrorSite); for (std::vector<Target*>::iterator t = ufo.getFollowers()->begin(); t != ufo.getFollowers()->end();) { Craft* c = dynamic_cast<Craft*>(*t); if (c && c->getNumSoldiers() != 0) { c->setDestination(terrorSite); t = ufo.getFollowers()->begin(); } else { ++t; } } } else if (_rule.getType() == "STR_ALIEN_RETALIATION" && ufo.getTrajectory().getID() == "__RETALIATION_ASSAULT_RUN") { // Ignore what the trajectory might say, this is a base assault. // Remove UFO, replace with Base defense. ufo.setDetected(false); std::vector<Base *>::const_iterator found = std::find_if(game.getBases()->begin(), game.getBases()->end(), MatchBaseCoordinates(ufo.getLongitude(), ufo.getLatitude())); if (found == game.getBases()->end()) { ufo.setStatus(Ufo::DESTROYED); // Only spawn mission if the base is still there. return; } ufo.setDestination(*found); } else { // Set timer for UFO on the ground. ufo.setSecondsRemaining(ufo.getTrajectory().groundTimer()); if (ufo.getDetected() && ufo.getLandId() == 0) { ufo.setLandId(engine.getSavedGame()->getId("STR_LANDING_SITE")); } } } }
/** * This function will spawn a UFO according the the mission rules. * Some code is duplicated between cases, that's ok for now. It's on different * code paths and the function is MUCH easier to read written this way. * @param game The saved game information. * @param ruleset The ruleset. * @param globe The globe, for land checks. * @param ufoRule The rule for the desired UFO. * @param trajectory The rule for the desired trajectory. * @return Pointer to the spawned UFO. If the mission does not desire to spawn a UFO, 0 is returned. */ Ufo *AlienMission::spawnUfo(const SavedGame &game, const Ruleset &ruleset, const Globe &globe, const RuleUfo &ufoRule, const UfoTrajectory &trajectory) { if (_rule.getType() == "STR_ALIEN_RETALIATION") { const RuleRegion ®ionRules = *ruleset.getRegion(_region); std::vector<Base *>::const_iterator found = std::find_if(game.getBases()->begin(), game.getBases()->end(), FindMarkedXCOMBase(regionRules)); if (found != game.getBases()->end()) { // Spawn a battleship straight for the XCOM base. const RuleUfo &battleshipRule = *ruleset.getUfo("STR_BATTLESHIP"); const UfoTrajectory &assaultTrajectory = *ruleset.getUfoTrajectory("__RETALIATION_ASSAULT_RUN"); Ufo *ufo = new Ufo(const_cast<RuleUfo*>(&battleshipRule)); ufo->setMissionInfo(this, &assaultTrajectory); std::pair<double, double> pos; if (trajectory.getAltitude(0) == "STR_GROUND") { pos = getLandPoint(globe, regionRules, trajectory.getZone(0)); } else { pos = regionRules.getRandomPoint(trajectory.getZone(0)); } ufo->setAltitude(assaultTrajectory.getAltitude(0)); ufo->setSpeed(assaultTrajectory.getSpeedPercentage(0) * ufoRule.getMaxSpeed()); ufo->setLongitude(pos.first); ufo->setLatitude(pos.second); Waypoint *wp = new Waypoint(); wp->setLongitude((*found)->getLongitude()); wp->setLatitude((*found)->getLatitude()); ufo->setDestination(wp); return ufo; } } else if (_rule.getType() == "STR_ALIEN_SUPPLY") { Log(LOG_DEBUG) << __FILE__ << ':' << __LINE__ << ' ' << _base; if (ufoRule.getType() == "STR_SUPPLY_SHIP" && !_base) { // No base to supply! return 0; } // Our destination is always an alien base. Ufo *ufo = new Ufo(const_cast<RuleUfo*>(&ufoRule)); ufo->setMissionInfo(this, &trajectory); const RuleRegion ®ionRules = *ruleset.getRegion(_region); std::pair<double, double> pos; if (trajectory.getAltitude(0) == "STR_GROUND") { pos = getLandPoint(globe, regionRules, trajectory.getZone(0)); } else { pos = regionRules.getRandomPoint(trajectory.getZone(0)); } ufo->setAltitude(trajectory.getAltitude(0)); ufo->setSpeed(trajectory.getSpeedPercentage(0) * ufoRule.getMaxSpeed()); ufo->setLongitude(pos.first); ufo->setLatitude(pos.second); Waypoint *wp = new Waypoint(); if (trajectory.getAltitude(1) == "STR_GROUND") { if (ufoRule.getType() == "STR_SUPPLY_SHIP") { // Supply ships on supply missions land on bases, ignore trajectory zone. pos.first = _base->getLongitude(); pos.second = _base->getLatitude(); } else { // Other ships can land where they want. pos = getLandPoint(globe, regionRules, trajectory.getZone(1)); } } else { pos = regionRules.getRandomPoint(trajectory.getZone(1)); } wp->setLongitude(pos.first); wp->setLatitude(pos.second); ufo->setDestination(wp); return ufo; } // Spawn according to sequence. Ufo *ufo = new Ufo(const_cast<RuleUfo*>(&ufoRule)); ufo->setMissionInfo(this, &trajectory); const RuleRegion ®ionRules = *ruleset.getRegion(_region); std::pair<double, double> pos; if (trajectory.getAltitude(0) == "STR_GROUND") { pos = getLandPoint(globe, regionRules, trajectory.getZone(0)); } else { pos = regionRules.getRandomPoint(trajectory.getZone(0)); } ufo->setAltitude(trajectory.getAltitude(0)); ufo->setSpeed(trajectory.getSpeedPercentage(0) * ufoRule.getMaxSpeed()); ufo->setLongitude(pos.first); ufo->setLatitude(pos.second); Waypoint *wp = new Waypoint(); if (trajectory.getAltitude(1) == "STR_GROUND") { pos = getLandPoint(globe, regionRules, trajectory.getZone(1)); } else { pos = regionRules.getRandomPoint(trajectory.getZone(1)); } wp->setLongitude(pos.first); wp->setLatitude(pos.second); ufo->setDestination(wp); return ufo; }
/** * This function will spawn a UFO according the the mission rules. * Some code is duplicated between cases, that's ok for now. It's on different * code paths and the function is MUCH easier to read written this way. * @param game The saved game information. * @param ruleset The ruleset. * @param globe The globe, for land checks. * @param wave The wave for the desired UFO. * @param trajectory The rule for the desired trajectory. * @return Pointer to the spawned UFO. If the mission does not desire to spawn a UFO, 0 is returned. */ Ufo *AlienMission::spawnUfo(const SavedGame &game, const Ruleset &ruleset, const Globe &globe, const MissionWave &wave, const UfoTrajectory &trajectory) { RuleUfo &ufoRule = *ruleset.getUfo(wave.ufoType); if (_rule.getObjective() == OBJECTIVE_RETALIATION) { const RuleRegion ®ionRules = *ruleset.getRegion(_region); std::vector<Base *>::const_iterator found = std::find_if (game.getBases()->begin(), game.getBases()->end(), FindMarkedXCOMBase(regionRules)); if (found != game.getBases()->end()) { // Spawn a battleship straight for the XCOM base. const RuleUfo &battleshipRule = *ruleset.getUfo(_rule.getSpawnUfo()); const UfoTrajectory &assaultTrajectory = *ruleset.getUfoTrajectory("__RETALIATION_ASSAULT_RUN"); Ufo *ufo = new Ufo(&battleshipRule); ufo->setMissionInfo(this, &assaultTrajectory); std::pair<double, double> pos; if (trajectory.getAltitude(0) == "STR_GROUND") { pos = getLandPoint(globe, regionRules, trajectory.getZone(0)); } else { pos = regionRules.getRandomPoint(trajectory.getZone(0)); } ufo->setAltitude(assaultTrajectory.getAltitude(0)); ufo->setSpeed(assaultTrajectory.getSpeedPercentage(0) * battleshipRule.getMaxSpeed()); ufo->setLongitude(pos.first); ufo->setLatitude(pos.second); Waypoint *wp = new Waypoint(); wp->setLongitude((*found)->getLongitude()); wp->setLatitude((*found)->getLatitude()); ufo->setDestination(wp); return ufo; } } else if (_rule.getObjective() == OBJECTIVE_SUPPLY) { if (wave.objective && !_base) { // No base to supply! return 0; } // Our destination is always an alien base. Ufo *ufo = new Ufo(&ufoRule); ufo->setMissionInfo(this, &trajectory); const RuleRegion ®ionRules = *ruleset.getRegion(_region); std::pair<double, double> pos; if (trajectory.getAltitude(0) == "STR_GROUND") { pos = getLandPoint(globe, regionRules, trajectory.getZone(0)); } else { pos = regionRules.getRandomPoint(trajectory.getZone(0)); } ufo->setAltitude(trajectory.getAltitude(0)); ufo->setSpeed(trajectory.getSpeedPercentage(0) * ufoRule.getMaxSpeed()); ufo->setLongitude(pos.first); ufo->setLatitude(pos.second); Waypoint *wp = new Waypoint(); if (trajectory.getAltitude(1) == "STR_GROUND") { if (wave.objective) { // Supply ships on supply missions land on bases, ignore trajectory zone. pos.first = _base->getLongitude(); pos.second = _base->getLatitude(); } else { // Other ships can land where they want. pos = getLandPoint(globe, regionRules, trajectory.getZone(1)); } } else { pos = regionRules.getRandomPoint(trajectory.getZone(1)); } wp->setLongitude(pos.first); wp->setLatitude(pos.second); ufo->setDestination(wp); return ufo; } // Spawn according to sequence. Ufo *ufo = new Ufo(&ufoRule); ufo->setMissionInfo(this, &trajectory); const RuleRegion ®ionRules = *ruleset.getRegion(_region); std::pair<double, double> pos = getWaypoint(trajectory, 0, globe, regionRules); ufo->setAltitude(trajectory.getAltitude(0)); if (trajectory.getAltitude(0) == "STR_GROUND") { ufo->setSecondsRemaining(trajectory.groundTimer()*5); } ufo->setSpeed(trajectory.getSpeedPercentage(0) * ufoRule.getMaxSpeed()); ufo->setLongitude(pos.first); ufo->setLatitude(pos.second); Waypoint *wp = new Waypoint(); pos = getWaypoint(trajectory, 1, globe, regionRules); wp->setLongitude(pos.first); wp->setLatitude(pos.second); ufo->setDestination(wp); return ufo; }