예제 #1
0
/**
 * Loads a ruleset's contents from a YAML file.
 * @param filename YAML filename.
 */
void Ruleset::load(const std::string &filename)
{
	std::string s = Options::getDataFolder() + "Ruleset/" + filename + ".rul";
	std::ifstream fin(s.c_str());
	if (!fin)
	{
		throw Exception("Failed to load ruleset");
	}
    YAML::Parser parser(fin);
	YAML::Node doc;

	parser.GetNextDocument(doc);
	for (YAML::Iterator i = doc.begin(); i != doc.end(); ++i)
	{
		std::string key;
		i.first() >> key;
		if (key == "countries")
		{
			for (YAML::Iterator j = i.second().begin(); j != i.second().end(); ++j)
			{
				std::string type;
				j.second()["type"] >> type;
				RuleCountry *rule;
				if (_countries.find(type) != _countries.end())
				{
					rule = _countries[type];
				}
				else
				{
					rule = new RuleCountry(type);
					_countries[type] = rule;
					_countriesIndex.push_back(type);
				}
				rule->load(j.second());
			}
		}
		else if (key == "regions")
		{
			for (YAML::Iterator j = i.second().begin(); j != i.second().end(); ++j)
			{
				std::string type;
				j.second()["type"] >> type;
				RuleRegion *rule;
				if (_regions.find(type) != _regions.end())
				{
					rule = _regions[type];
				}
				else
				{
					rule = new RuleRegion(type);
					_regions[type] = rule;
					_regionsIndex.push_back(type);
				}
				rule->load(j.second());
			}
		}
		else if (key == "facilities")
예제 #2
0
/**
 * Get starting values from the rules.
 * @param mod Pointer to the game mod.
 */
void AlienStrategy::init(const Mod *mod)
{
	std::vector<std::string> regions = mod->getRegionsList();
	for (std::vector<std::string>::const_iterator rr = regions.begin(); rr != regions.end(); ++rr)
	{
		RuleRegion *region = mod->getRegion(*rr);
		_regionChances.set(*rr, region->getWeight());
		WeightedOptions *missions = new WeightedOptions(region->getAvailableMissions());
		_regionMissions.insert(std::make_pair(*rr, missions));
	}
}
예제 #3
0
/**
 * 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;
	}
}
예제 #4
0
/**
 * Get a random point inside the given region zone.
 * The point will be used to land a UFO, so it HAS to be on land.
 */
std::pair<double, double> AlienMission::getLandPoint(const Globe &globe, const RuleRegion &region, size_t zone)
{
	int tries = 0;
	std::pair<double, double> pos;
	do
	{
		pos = region.getRandomPoint(zone);
		++tries;
	}
	while (!(globe.insideLand(pos.first, pos.second)
		&& region.insideRegion(pos.first, pos.second))
		&& tries < 100);
	if (tries == 100)
	{
		Log(LOG_DEBUG) << "Region: " << region.getType() << " Longitude: " << pos.first << " Lattitude: " << pos.second << " invalid zone: " << zone << " ufo forced to land on water!";
	}
	return pos;

}
예제 #5
0
/**
 * Select a destination based on the criteria of our trajectory and desired waypoint.
 * @param trajectory the trajectory in question.
 * @param nextWaypoint the next logical waypoint in sequence (0 for newly spawned UFOs)
 * @param globe The earth globe, required to get access to land checks.
 * @param region the ruleset for the region of our mission.
 * @return a set of lon and lat coordinates based on the criteria of the trajectory.
 */
std::pair<double, double> AlienMission::getWaypoint(const UfoTrajectory &trajectory, const size_t nextWaypoint, const Globe &globe, const RuleRegion &region)
{
	/* LOOK MA! NO HANDS!
	if (trajectory.getAltitude(nextWaypoint) == "STR_GROUND")
	{
		return getLandPoint(globe, region, trajectory.getZone(nextWaypoint));
	}
	else
	*/
		return region.getRandomPoint(trajectory.getZone(nextWaypoint));
}
예제 #6
0
/**
 * 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"));
			}
		}
	}
}
예제 #7
0
/**
 * Loads a ruleset's contents from a YAML file.
 * Rules that match pre-existing rules overwrite them.
 * @param filename YAML filename.
 */
void Ruleset::loadFile(const std::string &filename)
{
	YAML::Node doc = YAML::LoadFile(filename);

	for (YAML::const_iterator i = doc["countries"].begin(); i != doc["countries"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		RuleCountry *rule;
		if (_countries.find(type) != _countries.end())
		{
			rule = _countries[type];
		}
		else
		{
			rule = new RuleCountry(type);
			_countries[type] = rule;
			_countriesIndex.push_back(type);
		}
		rule->load(*i);
	}
 	for (YAML::const_iterator i = doc["regions"].begin(); i != doc["regions"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		RuleRegion *rule;
		if (_regions.find(type) != _regions.end())
		{
			rule = _regions[type];
		}
		else
		{
			rule = new RuleRegion(type);
			_regions[type] = rule;
			_regionsIndex.push_back(type);
		}
		rule->load(*i);
	}
 	for (YAML::const_iterator i = doc["facilities"].begin(); i != doc["facilities"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		RuleBaseFacility *rule;
		if (_facilities.find(type) != _facilities.end())
		{
			rule = _facilities[type];
		}
		else
		{
			rule = new RuleBaseFacility(type);
			_facilities[type] = rule;
			_facilitiesIndex.push_back(type);
		}
		_facilityListOrder += 100;
		rule->load(*i, _modIndex, _facilityListOrder);
	}
 	for (YAML::const_iterator i = doc["crafts"].begin(); i != doc["crafts"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		RuleCraft *rule;
		if (_crafts.find(type) != _crafts.end())
		{
			rule = _crafts[type];
		}
		else
		{
			rule = new RuleCraft(type);
			_crafts[type] = rule;
			_craftsIndex.push_back(type);
		}
		_craftListOrder += 100;
		rule->load(*i, this, _modIndex, _craftListOrder);
	}
 	for (YAML::const_iterator i = doc["craftWeapons"].begin(); i != doc["craftWeapons"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		RuleCraftWeapon *rule;
		if (_craftWeapons.find(type) != _craftWeapons.end())
		{
			rule = _craftWeapons[type];
		}
		else
		{
			rule = new RuleCraftWeapon(type);
			_craftWeapons[type] = rule;
			_craftWeaponsIndex.push_back(type);
		}
		rule->load(*i, _modIndex);
	}
 	for (YAML::const_iterator i = doc["items"].begin(); i != doc["items"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		RuleItem *rule;
		if (_items.find(type) != _items.end())
		{
			rule = _items[type];
		}
		else
		{
			rule = new RuleItem(type);
			_items[type] = rule;
			_itemsIndex.push_back(type);
		}
		_itemListOrder += 100;
		rule->load(*i, _modIndex, _itemListOrder);
	}
 	for (YAML::const_iterator i = doc["ufos"].begin(); i != doc["ufos"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		RuleUfo *rule;
		if (_ufos.find(type) != _ufos.end())
		{
			rule = _ufos[type];
		}
		else
		{
			rule = new RuleUfo(type);
			_ufos[type] = rule;
			_ufosIndex.push_back(type);
		}
		rule->load(*i, this);
	}
 	for (YAML::const_iterator i = doc["invs"].begin(); i != doc["invs"].end(); ++i)
	{
		std::string type = (*i)["id"].as<std::string>();
		RuleInventory *rule;
		if (_invs.find(type) != _invs.end())
		{
			rule = _invs[type];
		}
		else
		{
			rule = new RuleInventory(type);
			_invs[type] = rule;
		}
		rule->load(*i);
	}
 	for (YAML::const_iterator i = doc["terrains"].begin(); i != doc["terrains"].end(); ++i)
	{
		std::string type = (*i)["name"].as<std::string>();
		RuleTerrain *rule;
		if (_terrains.find(type) != _terrains.end())
		{
			rule = _terrains[type];
		}
		else
		{
			rule = new RuleTerrain(type);
			_terrains[type] = rule;
			_terrainIndex.push_back(type);
		}
		rule->load(*i, this);
	}
 	for (YAML::const_iterator i = doc["armors"].begin(); i != doc["armors"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		Armor *rule;
		if (_armors.find(type) != _armors.end())
		{
			rule = _armors[type];
		}
		else
		{
			rule = new Armor(type, "", 0);
			_armors[type] = rule;
			_armorsIndex.push_back(type);
		}
		rule->load(*i);
	}
 	for (YAML::const_iterator i = doc["soldiers"].begin(); i != doc["soldiers"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		RuleSoldier *rule;
		if (_soldiers.find(type) != _soldiers.end())
		{
			rule = _soldiers[type];
		}
		else
		{
			rule = new RuleSoldier(type);
			_soldiers[type] = rule;
		}
		rule->load(*i);
	}
 	for (YAML::const_iterator i = doc["units"].begin(); i != doc["units"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		Unit *rule;
		if (_units.find(type) != _units.end())
		{
			rule = _units[type];
		}
		else
		{
			rule = new Unit(type, "", "");
			_units[type] = rule;
		}
		rule->load(*i);
	}
 	for (YAML::const_iterator i = doc["alienRaces"].begin(); i != doc["alienRaces"].end(); ++i)
	{
		std::string type = (*i)["id"].as<std::string>();
		AlienRace *rule;
		if (_alienRaces.find(type) != _alienRaces.end())
		{
			rule = _alienRaces[type];
		}
		else
		{
			rule = new AlienRace(type);
			_alienRaces[type] = rule;
			_aliensIndex.push_back(type);
		}
		rule->load(*i);
	}
 	for (YAML::const_iterator i = doc["alienDeployments"].begin(); i != doc["alienDeployments"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		AlienDeployment *rule;
		if (_alienDeployments.find(type) != _alienDeployments.end())
		{
			rule = _alienDeployments[type];
		}
		else
		{
			rule = new AlienDeployment(type);
			_alienDeployments[type] = rule;
			_deploymentsIndex.push_back(type);
		}
		rule->load(*i);
	}
 	for (YAML::const_iterator i = doc["research"].begin(); i != doc["research"].end(); ++i)
	{
		std::string type = (*i)["name"].as<std::string>();
		RuleResearch *rule;
		if (_research.find(type) != _research.end())
		{
			rule = _research[type];
		}
		else
		{
			rule = new RuleResearch(type);
			_research[type] = rule;
			_researchIndex.push_back(type);
		}
		_researchListOrder += 100;
		rule->load(*i, _researchListOrder);
	}
 	for (YAML::const_iterator i = doc["manufacture"].begin(); i != doc["manufacture"].end(); ++i)
	{
		std::string type = (*i)["name"].as<std::string>();
		RuleManufacture *rule;
		if (_manufacture.find(type) != _manufacture.end())
		{
			rule = _manufacture[type];
		}
		else
		{
			rule = new RuleManufacture(type);
			_manufacture[type] = rule;
			_manufactureIndex.push_back(type);
		}
		_manufactureListOrder += 100;
		rule->load(*i, _manufactureListOrder);
	}
 	for (YAML::const_iterator i = doc["ufopaedia"].begin(); i != doc["ufopaedia"].end(); ++i)
	{
		std::string id = (*i)["id"].as<std::string>();
		ArticleDefinition *rule;
		if (_ufopaediaArticles.find(id) != _ufopaediaArticles.end())
		{
			rule = _ufopaediaArticles[id];
		}
		else
		{
			UfopaediaTypeId type = (UfopaediaTypeId)(*i)["type_id"].as<int>();
			switch (type)
			{
			case UFOPAEDIA_TYPE_CRAFT: rule = new ArticleDefinitionCraft(); break;
			case UFOPAEDIA_TYPE_CRAFT_WEAPON: rule = new ArticleDefinitionCraftWeapon(); break;
			case UFOPAEDIA_TYPE_VEHICLE: rule = new ArticleDefinitionVehicle(); break;
			case UFOPAEDIA_TYPE_ITEM: rule = new ArticleDefinitionItem(); break;
			case UFOPAEDIA_TYPE_ARMOR: rule = new ArticleDefinitionArmor(); break;
			case UFOPAEDIA_TYPE_BASE_FACILITY: rule = new ArticleDefinitionBaseFacility(); break;
			case UFOPAEDIA_TYPE_TEXTIMAGE: rule = new ArticleDefinitionTextImage(); break;
			case UFOPAEDIA_TYPE_TEXT: rule = new ArticleDefinitionText(); break;
			case UFOPAEDIA_TYPE_UFO: rule = new ArticleDefinitionUfo(); break;
			default: rule = 0; break;
			}
			_ufopaediaArticles[id] = rule;
			_ufopaediaIndex.push_back(id);
		}
		_ufopaediaListOrder += 100;
		rule->load(*i, _ufopaediaListOrder);
	}
 	//_startingBase->load(i->second, 0);
	if (doc["startingBase"])
		_startingBase = YAML::Node(doc["startingBase"]);
 	_startingTime.load(doc["startingTime"]);
 	_costSoldier = doc["costSoldier"].as<int>(_costSoldier);
 	_costEngineer = doc["costEngineer"].as<int>(_costEngineer);
 	_costScientist = doc["costScientist"].as<int>(_costScientist);
 	_timePersonnel = doc["timePersonnel"].as<int>(_timePersonnel);
 	for (YAML::const_iterator i = doc["ufoTrajectories"].begin(); i != doc["ufoTrajectories"].end(); ++i)
	{
		std::string id = (*i)["id"].as<std::string>();
		if (_ufoTrajectories.find(id) != _ufoTrajectories.end())
		{
			_ufoTrajectories[id]->load(*i);
		}
		else
		{
			std::auto_ptr<UfoTrajectory> rule(new UfoTrajectory);
			rule->load(*i);
			_ufoTrajectories[id] = rule.release();
		}
	}
 	for (YAML::const_iterator i = doc["alienMissions"].begin(); i != doc["alienMissions"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		if (_alienMissions.find(type) != _alienMissions.end())
		{
			_alienMissions[type]->load(*i);
		}
		else
		{
			std::auto_ptr<RuleAlienMission> rule(new RuleAlienMission());
			rule->load(*i);
			_alienMissions[type] = rule.release();
			_alienMissionsIndex.push_back(type);
		}
	}
 	_alienItemLevels.clear();
	for (YAML::const_iterator i = doc["alienItemLevels"].begin(); i != doc["alienItemLevels"].end(); ++i)
	{
		std::vector<int> type = (*i).as< std::vector<int> >();
		_alienItemLevels.push_back(type);
	}
 	for (YAML::const_iterator i = doc["MCDPatches"].begin(); i != doc["MCDPatches"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		if (_MCDPatches.find(type) != _MCDPatches.end())
		{
			_MCDPatches[type]->load(*i);
		}
		else
		{
			std::auto_ptr<MCDPatch> patch(new MCDPatch());
			patch->load(*i);
			_MCDPatches[type] = patch.release();
			_MCDPatchesIndex.push_back(type);
		}
	}
 	for (YAML::const_iterator i = doc["extraSprites"].begin(); i != doc["extraSprites"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		std::auto_ptr<ExtraSprites> extraSprites(new ExtraSprites());
		extraSprites->load(*i, _modIndex);
		_extraSprites.push_back(std::make_pair(type, extraSprites.release()));
		_extraSpritesIndex.push_back(type);
	}
 	for (YAML::const_iterator i = doc["extraSounds"].begin(); i != doc["extraSounds"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		std::auto_ptr<ExtraSounds> extraSounds(new ExtraSounds());
		extraSounds->load(*i, _modIndex);
		_extraSounds.push_back(std::make_pair(type, extraSounds.release()));
		_extraSoundsIndex.push_back(type);
	}
 	for (YAML::const_iterator i = doc["extraStrings"].begin(); i != doc["extraStrings"].end(); ++i)
	{
		std::string type = (*i)["type"].as<std::string>();
		if (_extraStrings.find(type) != _extraStrings.end())
		{
			_extraStrings[type]->load(*i);
		}
		else
		{
			std::auto_ptr<ExtraStrings> extraStrings(new ExtraStrings());
			extraStrings->load(*i);
			_extraStrings[type] = extraStrings.release();
			_extraStringsIndex.push_back(type);
		}
	}

	_modIndex += 1000;
}