/* base/faction.cc This file is part of the Osirion project and is distributed under the terms and conditions of the GNU General Public License version 2 */ #include "core/func.h" #include "core/parser.h" #include "core/range.h" #include "base/faction.h" #include #include namespace game { core::InfoType *Faction::faction_infotype = 0; Faction *Faction::faction_default = 0; void func_list_faction(const std::string &args) { if (args.size()) { std::istringstream is(args); std::string label; if (is >> label) { aux::to_label(label); Faction *faction = Faction::find(label); if (!faction) { con_warn << "Unknown faction '" << label << "'" << std::endl; } else { faction->print(); } } } else { Faction::list(); return; } } Faction *Faction::find(const std::string & label) { if (!label.size()) { return 0; } return (Faction *) core::Info::find(faction_infotype, label); } void Faction::list() { core::Info::list(faction_infotype); } void Faction::print() const { core::Info::print(); con_print << " ^BFaction repution" << std::endl; for (core::Reputation::FactionReps::const_iterator rip = reputation().factionreps().begin(); rip != reputation().factionreps().end(); ++rip) { con_print << " ^B" << std::setw(4) << (*rip)->reputation() << " ^N" << (*rip)->faction()->label() << std::endl; } } bool Faction::init() { // initialize faction InfoType faction_infotype = new core::InfoType("faction"); std::string inifilename("ini/factions"); filesystem::IniFile inifile; inifile.open(inifilename); if (!inifile.is_open()) { con_warn << "Could not open " << inifile.name() << std::endl; return false; } con_print << "^BLoading factions..." << std::endl; core::Func *func = core::Func::add("list_faction", func_list_faction); func->set_info("list available factions"); size_t count = 0; Faction *faction = 0; std::string strvalue; float floatvalue; math::Color colorvalue; std::string factionlabel; while (inifile.getline()) { if (inifile.got_section()) { if (inifile.got_section("faction")) { count++; faction = new Faction(); } else if (inifile.got_section("reputation")) { factionlabel.clear(); } else { inifile.unknown_section(); faction = 0; factionlabel.clear(); } } else if (inifile.got_key()) { if (inifile.in_section("faction")) { if (inifile.got_key_label("label", strvalue)) { faction->set_label(strvalue); continue; } else if (inifile.got_key_string("name", strvalue)) { faction->set_name(strvalue); continue; } else if (inifile.got_key_string("info", strvalue)) { faction->add_text(strvalue); continue; } else if (inifile.got_key_color("color", colorvalue)) { faction->set_color(colorvalue); continue; } else if (inifile.got_key_color("colorsecond", colorvalue)) { faction->set_color_second(colorvalue); continue; } else { inifile.unknown_key(); } } else if (inifile.in_section("reputation")) { if (faction) { if (inifile.got_key_label("faction", factionlabel)) { continue; } else if (inifile.got_key_float("reputation", floatvalue)) { if (factionlabel.size()) { faction->reputation().set_reputation(factionlabel, floatvalue); } else { inifile.unknown_error("reputation key without faction"); } continue; } else { inifile.unknown_key(); } } } } } inifile.close(); if (!count) { con_warn << "No factions found!" << std::endl; return true; // non-fatal } // create default faction faction_default = Faction::find("default"); if (!faction_default) { faction_default = new Faction(); faction_default->set_label("default"); faction_default->set_name("Default"); } else { faction_default->reputation().clear(); } // validate reputation for (core::Info::Registry::iterator it = core::Info::registry().begin(); it != core::Info::registry().end(); it++) { core::Info *info = (*it); if (info->type() == faction_infotype) { faction = static_cast(info); core::Reputation::FactionReps::iterator rip = faction->reputation().factionreps().begin(); while (rip != faction->reputation().factionreps().end()) { Faction *otherfaction = Faction::find((*rip)->label()); if (!otherfaction) { con_warn << " faction '" << faction->label() << "': unknown faction '" << (*rip)->label() << "' in reputation" << std::endl; faction->reputation().factionreps().erase(rip++); } else { if (otherfaction == faction_default) { faction_default->reputation().set_reputation(faction, (*rip)->reputation()); } (*rip)->set_faction(otherfaction); ++rip; } } } } // enforce reciprocal reputation for (core::Info::Registry::iterator it = core::Info::registry().begin(); it != core::Info::registry().end(); it++) { core::Info *info = (*it); if (info->type() == faction_infotype) { faction = static_cast(info); for (core::Reputation::FactionReps::iterator rip = faction->reputation().factionreps().begin(); rip != faction->reputation().factionreps().end(); ++rip) { Faction *otherfaction = Faction::find((*rip)->faction()->label()); otherfaction->reputation().set_reputation(faction, (*rip)->reputation()); } } } con_debug << " " << inifile.name() << " " << count << " factions" << std::endl; return true; } void Faction::done() { core::Func::remove("list_faction"); faction_default = 0; } Faction::Faction() : core::Info(faction_infotype), faction_color(), faction_color_second() { } Faction::~Faction() { } void Faction::apply(core::Entity *entity) const { assert(entity); // set primary color entity->set_color(color()); // set secondary color entity->set_color_second(color_second()); // set entity faction entity->set_faction(this); } void Faction::apply_kill(core::Player *player) const { assert(player); // a kill will cost the player 5 reputation points with this faction const float points = 5.0f; // a kill will cost the player 1 reputation point with this faction's friends and allies const float points_ally = 1.0f; // adjust current player reputation for this faction player->reputation().set_reputation(this, player->reputation(this) - points); // adjust player reputation for this factions's allies and enemies for (core::Reputation::FactionReps::const_iterator rip = faction_reputation.factionreps_begin(); rip != faction_reputation.factionreps_end(); ++rip) { assert((*rip)->faction()); if ((*rip)->faction() != faction_default) { const float other_faction_reputation = faction_reputation.reputation((*rip)->faction()); if (other_faction_reputation >= core::range::reputation_friendly) { // allied faction player->reputation().set_reputation((*rip)->faction(), player->reputation((*rip)->faction()) - points_ally); } else if (other_faction_reputation <= core::range::reputation_hostile) { //enemy faction player->reputation().set_reputation((*rip)->faction(), player->reputation((*rip)->faction()) + points_ally); } } } player->reputation().set_dirty(); } void Faction::apply_sale(core::Player *player, const float amount) const { assert(player); } void Faction::apply_default(core::Reputation & reputation) { // apply default reputation if (faction_default) { for (core::Reputation::FactionReps::const_iterator rip = faction_default->reputation().factionreps().begin(); rip != faction_default->reputation().factionreps().end(); ++rip) { // only add defaults the reputation doesn't have yet if (!reputation.find((*rip)->faction())) { reputation.set_reputation((*rip)->faction(), (*rip)->reputation()); } } } reputation.set_dirty(); } } // namespace game