From 5bbbdc24293ad1138a0b93628f7d28f8b249b92d Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 25 Jan 2015 20:24:40 +0000 Subject: Added support for default player characters when joining a game. --- src/game/base/Makefile.am | 2 + src/game/base/character.cc | 75 ++++++++++ src/game/base/character.h | 119 ++++++++++++++++ src/game/base/game.cc | 332 +++++++++++++++++++++++++++++++++------------ src/game/base/game.h | 8 ++ src/game/base/savegame.cc | 2 +- src/game/base/shipmodel.cc | 6 - 7 files changed, 449 insertions(+), 95 deletions(-) create mode 100644 src/game/base/character.cc create mode 100644 src/game/base/character.h diff --git a/src/game/base/Makefile.am b/src/game/base/Makefile.am index 5ac64c8..80e2bd8 100644 --- a/src/game/base/Makefile.am +++ b/src/game/base/Makefile.am @@ -6,6 +6,7 @@ noinst_LTLIBRARIES = libbase.la noinst_HEADERS = \ cargo.h \ cargopod.h \ + character.h \ game.h \ faction.h \ jumppoint.h \ @@ -29,6 +30,7 @@ noinst_HEADERS = \ libbase_la_SOURCES = \ cargo.cc \ cargopod.cc \ + character.cc \ faction.cc \ game.cc \ jumppoint.cc \ diff --git a/src/game/base/character.cc b/src/game/base/character.cc new file mode 100644 index 0000000..ceb5ff4 --- /dev/null +++ b/src/game/base/character.cc @@ -0,0 +1,75 @@ +/* + base/character.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "base/character.h" + +namespace game +{ + +Character::Character() : core::Label() +{ + _spawn = 0; + _faction = 0; + _shipmodel = 0; + _cannon = 0; + _turret = 0; + + _level = 1; + _credits = 0; +} + +Character::Character(const Character & other) : core::Label(other) +{ + _spawn = other._spawn; + _faction = other._faction; + _shipmodel = other._shipmodel; + _cannon = other._cannon; + _turret = other._turret; + + _level = other._level; + _credits = other._credits; +} + +Character::~Character() +{ +} + +void Character::set_spawn(core::Entity *spawn) +{ + _spawn = spawn; +} + +void Character::set_faction(const Faction *faction) +{ + _faction = faction; +} + +void Character::set_shipmodel(const ShipModel *shipmodel) +{ + _shipmodel = shipmodel; +} + +void Character::set_cannon(const Weapon *cannon) +{ + _cannon = cannon; +} + +void Character::set_turret(const Weapon *turret) +{ + _turret = turret; +} + +void Character::set_level(const core::Level level) +{ + _level = level; +} + +void Character::set_credits(const long credits) +{ + _credits = credits; +} + +} // namespace game \ No newline at end of file diff --git a/src/game/base/character.h b/src/game/base/character.h new file mode 100644 index 0000000..7940c73 --- /dev/null +++ b/src/game/base/character.h @@ -0,0 +1,119 @@ +/* + base/character.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_BASE_CHARACTER_H__ +#define __INCLUDED_BASE_CHARACTER_H__ + +#include "core/label.h" +#include "core/level.h" + +namespace core +{ + +class Entity; + +}; // namespace core + +namespace game +{ + +class Faction; +class ShipModel; +class Weapon; + +/** + * @brief contaisn default settings for new Player or NPC characters. + * */ +class Character : public core::Label +{ +public: + /** + * @brief default constructor + * */ + Character(); + /** + * @brief copy constructor + * */ + Character(const Character & other); + /** + * @brief destructor + * */ + ~Character(); + + /* --- inspectors ------------------------------------------ */ + + inline core::Entity *spawn() const + { + return _spawn; + } + + inline const Faction *faction() const + { + return _faction; + } + + inline const ShipModel *shipmodel() const + { + return _shipmodel; + } + + inline const Weapon *cannon() const + { + return _cannon; + } + + inline const Weapon *turret() const + { + return _turret; + } + + inline const core::Level level() const + { + return _level; + } + + inline const long credits() const + { + return _credits; + } + + /* --- mutators -------------------------------------------- */ + + void set_spawn(core::Entity *spawn); + + void set_faction(const Faction *faction); + + void set_shipmodel(const ShipModel *shipmodel); + + void set_cannon(const Weapon *cannon); + + void set_turret(const Weapon *turret); + + void set_level(const core::Level level); + + void set_credits(const long credits); + + /* --- actors ---------------------------------------------- */ + +private: + core::Entity *_spawn; + + const Faction *_faction; + + const ShipModel *_shipmodel; + const Weapon *_cannon; + const Weapon *_turret; + + core::Level _level; + + long _credits; + +}; // class Character + +} // namespace game + +#endif // __INCLUDED_BASE_CHARACTER_H__ + diff --git a/src/game/base/game.cc b/src/game/base/game.cc index 531d4b1..77917f6 100644 --- a/src/game/base/game.cc +++ b/src/game/base/game.cc @@ -21,6 +21,7 @@ #include "base/game.h" #include "base/cargo.h" #include "base/cargopod.h" +#include "base/character.h" #include "base/faction.h" #include "base/navpoint.h" #include "base/jumppoint.h" @@ -41,22 +42,31 @@ namespace game /* -- class Default ----------------------------------------------- */ + // default player settings core::Zone *Default::zone = 0; +/* core::Entity *Default::view = 0; ShipModel *Default::shipmodel = 0; Weapon *Default::cannonmodel = 0; Weapon *Default::turretmodel = 0; long Default::credits = 0; +*/ + +Default::Characters Default::characters; void Default::clear() { - zone = 0; - view = 0; - shipmodel = 0; - cannonmodel = 0; - turretmodel = 0; - credits = 0; + for (Characters::iterator it = characters.begin(); it != characters.end(); ++it) + { + Character *character = (*it); + if (character) + { + delete character; + (*it) = 0; + } + } + characters.clear(); } /* -- class Game static members ----------------------------------- */ @@ -78,7 +88,10 @@ core::Module *factory() void Game::func_join(core::Player *player, std::string const &args) { if (player->control()) + { + // already joined return; + } std::string message("^B"); message.append(player->name()); @@ -87,69 +100,137 @@ void Game::func_join(core::Player *player, std::string const &args) // load existing player data core::server()->module()->player_load(player); + if (player->control()) + { + // player data loaded from savegame + player->set_dirty(); + return; + } - if (!player->control()) { - player->set_credits(Default::credits); - Ship *ship = new Ship(player, Default::shipmodel); - ship->set_zone(player->zone()); - player->set_control(ship); - - // load weapons - for (core::Slots::iterator it = ship->slots()->begin(); it != ship->slots()->end(); ++it) + // find requested character + std::string character_label; + std::istringstream is(args); + if (!(is >> character_label)) + { + character_label.assign("default"); + } + else + { + aux::to_label(character_label); + } + + const Character *character = 0; + + for (Default::Characters::const_iterator it = Default::characters.begin(); it != Default::characters.end();) + { + if (character_label.compare((*it)->label()) == 0) { - core::Slot *slot = (*it); - Weapon *weapon = 0; - - if (slot->type() == model::Slot::Cannon) - { - weapon = Default::cannonmodel; - } - else if (slot->type() == model::Slot::Turret) - { - weapon = Default::turretmodel; - } - - if (weapon && (weapon->volume() <= ship->inventory()->capacity_available())) - { - // add weapon to inventory - core::Item *item = new core::Item(weapon); - item->set_flag(core::Item::Unique); - item->set_flag(core::Item::Mountable); - item->set_flag(core::Item::Unrestricted); - item->set_amount(1); - - ship->inventory()->add(item); - - // mount weapon - slot->set_item(item); - slot->set_flag(core::Slot::Active); - slot->set_flag(core::Slot::Mounted); - item->set_flag(core::Item::Mounted); - } + character = *it; + it = Default::characters.end(); } - ship->inventory()->set_dirty(); - - // dock ship at default base - core::Entity *dock = ship->zone()->default_view(); - if (dock) + else { - ship->set_dock(dock); - player->set_view(dock); + ++it; } + + } - ship->reset(); + if (!character) + { + std::ostringstream strmsg; + strmsg << "^WPlayer character definition '" << character_label << "' not found!"; + player->send(strmsg.str()); - player->send("^BYou received " + aux::article(Default::shipmodel->name())); - player->sound("game/buy-ship"); + con_print << strmsg.str() << std::endl; + return; + } + + // set player credits + player->set_credits(character->credits()); + + // set player zone + player->set_zone(character->spawn()->zone()); + + // add a new ship + Ship *ship = new Ship(player, character->shipmodel()); + ship->set_zone(character->spawn()->zone()); + + player->set_control(ship); + + // dock ship at spawn + if (character->spawn()) + { + if (character->spawn()->has_flag(core::Entity::Dockable)) + { + ship->set_dock(character->spawn()); + player->set_view(character->spawn()); + } + else + { + ship->set_location(character->spawn()->location()); + ship->set_axis(character->spawn()->axis()); + ship->nudge(); + player->set_view(0); + } + } + ship->reset(); + + // load default weapons + for (core::Slots::iterator it = ship->slots()->begin(); it != ship->slots()->end(); ++it) + { + core::Slot *slot = (*it); + const Weapon *weapon = 0; - player->reputation().clear(); - Faction::apply_default(player->reputation()); + if (slot->type() == model::Slot::Cannon) + { + weapon = character->cannon(); + } + else if (slot->type() == model::Slot::Turret) + { + weapon = character->turret(); + } + + if (weapon && (weapon->volume() <= ship->inventory()->capacity_available())) + { + // add weapon to inventory + core::Item *item = new core::Item(weapon); + item->set_flag(core::Item::Unique); + item->set_flag(core::Item::Mountable); + item->set_flag(core::Item::Unrestricted); + item->set_amount(1); + ship->inventory()->add(item); + + // mount weapon + slot->set_item(item); + slot->set_flag(core::Slot::Active); + slot->set_flag(core::Slot::Mounted); + item->set_flag(core::Item::Mounted); + } + } + ship->inventory()->set_dirty(); + + player->send("^BYou received " + aux::article(character->shipmodel()->name())); + player->sound("game/buy-ship"); + + player->reputation().clear(); + + // TODO - applay character faction reputation + Faction::apply_default(player->reputation()); + + if (character->faction()) + { + // override default reputation with faction reputation + for (core::Reputation::FactionReps::const_iterator rip = character->faction()->reputation().factionreps().begin(); rip != character->faction()->reputation().factionreps().end(); ++rip) { + player->reputation().set_reputation((*rip)->faction(), (*rip)->reputation()); + } - // reset player timestamps - player->set_time_wasted(0); - player->set_time_joined(); + player->reputation().set_reputation(character->faction(), 100.0f); } - + + // reset player timestamps + player->set_time_wasted(0); + player->set_time_joined(); + player->set_dirty(); } @@ -2910,18 +2991,22 @@ bool Game::load_settings() } long l; - std::string strval; + std::string str; + Character *character = 0; while (inifile.getline()) { if (inifile.got_section()) { - if (inifile.got_section("player")) + if (inifile.got_section("world")) { + character = 0; continue; } - else if (inifile.got_section("cargo")) + else if (inifile.got_section("character")) { + character = new Character(); + Default::characters.push_back(character); continue; } else @@ -2931,54 +3016,111 @@ bool Game::load_settings() } else if (inifile.got_key()) { - if (inifile.in_section("player")) + if (inifile.in_section("world")) { - if (inifile.got_key_long("credits", l)) + if (inifile.got_key_label("zone", str)) { - Default::credits = l; + Default::zone = core::Zone::find(str); } - else if (inifile.got_key_label("zone", strval)) + else { - Default::zone = core::Zone::find(strval); - + inifile.unknown_key(); } - else if (inifile.got_key_label("ship", strval)) + } + else if (inifile.in_section("character")) + { + if (inifile.got_key_label("label", str)) { - Default::shipmodel = ShipModel::find(strval); + character->set_label(str); } - else if (inifile.got_key_label("cannon", strval)) + else if (inifile.got_key_string("name", str)) { - Weapon *cannon = Weapon::find(strval); + aux::strip_quotes(str); + character->set_name(str); + } + else if (inifile.got_key_long("credits", l)) + { + character->set_credits(l); + } + else if (inifile.got_key_label("ship", str)) + { + character->set_shipmodel(ShipModel::find(str)); + } + else if (inifile.got_key_label("faction", str)) + { + character->set_faction(Faction::find(str)); + } + else if (inifile.got_key_label("cannon", str)) + { + Weapon *cannon = Weapon::find(str); if (!cannon) { - inifile.unknown_error("unknown weapon type '" + strval + "'"); + inifile.unknown_error("unknown weapon type '" + str + "'"); } else if (cannon->subtype() != Weapon::Cannon) { - inifile.unknown_error("weapon type '" + strval + "' is not a cannon"); + inifile.unknown_error("weapon type '" + str + "' is not a cannon"); } else { - Default::cannonmodel = cannon; + character->set_cannon(cannon); } } - else if (inifile.got_key_label("turret", strval)) + else if (inifile.got_key_label("turret", str)) { - Weapon *turret = Weapon::find(strval); + Weapon *turret = Weapon::find(str); if (!turret) { - inifile.unknown_error("unknown weapon type '" + strval + "'"); + inifile.unknown_error("unknown weapon type '" + str + "'"); } else if (turret->subtype() != Weapon::Turret) { - inifile.unknown_error("weapon type '" + strval + "' is not a turret"); + inifile.unknown_error("weapon type '" + str + "' is not a turret"); } else { - Default::turretmodel = turret; + character->set_turret(turret); } } + else if (inifile.got_key_string("spawn", str)) + { + if (!str.size()) { + continue; + } else if (str.size() < 3) { + inifile.unknown_error("spawn with invalid label '" + str + "'"); + continue; + } + size_t pos = str.find(':'); + if ((pos == std::string::npos) || (pos < 1) || (pos >= (str.size() - 1))) { + inifile.unknown_error("spawn with invalid label '" + str + "'"); + continue; + } + std::string zonelabel(str.substr(0, pos)); + std::string entitylabel(str.substr(pos + 1, str.size() - pos)); + + aux::to_label(zonelabel); + aux::to_label(entitylabel); + + core::Zone *spawn_zone = core::Zone::find(zonelabel); + if (!spawn_zone) { + inifile.unknown_error("spawn with invalid zone'" + zonelabel + "'"); + continue; + } + + core::Entity *spawn_entity = spawn_zone->find_entity(entitylabel); + if (!spawn_entity) { + inifile.unknown_error("spawn with invalid entity'" + str + "'"); + continue; + } + + if (!spawn_entity->has_flag(core::Entity::Dockable)) { + inifile.unknown_error("spawn '" + str + "' is not dockable"); + continue; + } + + character->set_spawn(spawn_entity); + } else { inifile.unknown_key(); @@ -2988,6 +3130,28 @@ bool Game::load_settings() } inifile.close(); + + // validate character entries + for (Default::Characters::const_iterator it = Default::characters.begin(); it != Default::characters.end(); ++it) + { + const Character *character = (*it); + + if (!character->label().size()) + { + con_error << "Character definition without label!\n"; + return false; + } + else if (!character->spawn()) + { + con_error << "Character definition '" + character->label() + "' without spawn!\n"; + return false; + } + else if (!character->shipmodel()) + { + con_error << "Character definition '" + character->label() + "' without shipmodel!\n"; + return false; + } + } if (!Default::zone) { @@ -3001,14 +3165,6 @@ bool Game::load_settings() return false; } - Default::view = Default::zone->default_view(); - - if (!Default::shipmodel) - { - con_error << "No default ship model found!\n"; - return false; - } - return true; } diff --git a/src/game/base/game.h b/src/game/base/game.h index 5a93272..25d3cb1 100644 --- a/src/game/base/game.h +++ b/src/game/base/game.h @@ -49,6 +49,7 @@ const float jump_timer_delay = 5.0f; const float jump_cooldown_delay = 2.0f; const float impulse_timer_delay = 3.0f; +class Character; class ShipModel; class Weapon; @@ -56,14 +57,21 @@ class Weapon; class Default { public: + typedef std::vector Characters; + static core::Zone *zone; + + /* static core::Entity *view; static ShipModel *shipmodel; static Weapon *cannonmodel; static Weapon *turretmodel; static long credits; + */ static void clear(); + + static Characters characters; }; /// the base Project::OSiRiON game model diff --git a/src/game/base/savegame.cc b/src/game/base/savegame.cc index 28f0ddb..ab2ecc2 100644 --- a/src/game/base/savegame.cc +++ b/src/game/base/savegame.cc @@ -286,7 +286,7 @@ void SaveGame::load_game(core::Player *player, filesystem::IniFile & inifile) ship->set_spawn(zone->default_view()); } if (!ship->spawn()) { - ship->set_spawn(Default::view); + ship->set_spawn(Default::zone->default_view()); } if (ship_is_docked) { diff --git a/src/game/base/shipmodel.cc b/src/game/base/shipmodel.cc index 275514f..7159c09 100644 --- a/src/game/base/shipmodel.cc +++ b/src/game/base/shipmodel.cc @@ -210,12 +210,6 @@ bool ShipModel::init() // add a new shipmodel shipmodel = new ShipModel(); - // the first ship model is set as default, game.ini can override this later - if (!Default::shipmodel) - { - Default::shipmodel = shipmodel; - } - shipmodel_count++; } else if (inifile.got_section()) -- cgit v1.2.3