diff options
-rw-r--r-- | src/game/base/Makefile.am | 2 | ||||
-rw-r--r-- | src/game/base/game.cc | 81 | ||||
-rw-r--r-- | src/game/base/npctype.cc | 71 | ||||
-rw-r--r-- | src/game/base/npctype.h | 122 | ||||
-rw-r--r-- | src/game/base/patrol.cc | 114 | ||||
-rw-r--r-- | src/game/base/patrol.h | 9 | ||||
-rw-r--r-- | src/game/base/shipmodel.cc | 3 | ||||
-rw-r--r-- | src/game/base/shipmodel.h | 21 |
8 files changed, 354 insertions, 69 deletions
diff --git a/src/game/base/Makefile.am b/src/game/base/Makefile.am index 634a571..7289545 100644 --- a/src/game/base/Makefile.am +++ b/src/game/base/Makefile.am @@ -11,6 +11,7 @@ noinst_HEADERS = \ jumppoint.h \ navpoint.h \ npc.h \ + npctype.h \ patrol.h \ planet.h \ racetrack.h \ @@ -31,6 +32,7 @@ libbase_la_SOURCES = \ jumppoint.cc \ navpoint.cc \ npc.cc \ + npctype.cc \ patrol.cc \ planet.cc \ racetrack.cc \ diff --git a/src/game/base/game.cc b/src/game/base/game.cc index f2db00c..46151f9 100644 --- a/src/game/base/game.cc +++ b/src/game/base/game.cc @@ -1833,6 +1833,7 @@ bool Game::load_zone(core::Zone *zone) Patrol *patrol = 0; Patrol::WayPoint *patrol_waypoint = 0; + NPCType *patrol_npctype = 0; bool b; long l; @@ -1897,18 +1898,31 @@ bool Game::load_zone(core::Zone *zone) patrol->set_zone(zone); patrol_waypoint = 0; + patrol_npctype = 0; } else if (zoneini.got_section("waypoint")) { patrol_waypoint = 0; + patrol_npctype = 0; - if (!entity || !patrol) { + if (!entity || !patrol || (patrol != entity)) { zoneini.unknown_error("waypoint definition without patrol"); } else if ((entity->moduletype() != patrol_enttype)) { zoneini.unknown_error("waypoint definition for invalid entity type"); } else { patrol_waypoint = patrol->add_waypoint(); } - + } else if (zoneini.got_section("npc")) { + patrol_waypoint = 0; + patrol_npctype = 0; + + if (!entity || !patrol || (patrol != entity)) { + zoneini.unknown_error("npc definition without patrol"); + } else if ((entity->moduletype() != patrol_enttype)) { + zoneini.unknown_error("npc definition for invalid entity type"); + } else { + patrol_npctype = patrol->add_npctype(); + } + } else if (zoneini.got_section("planet")) { planet = new Planet(); entity = planet; @@ -1951,7 +1965,7 @@ bool Game::load_zone(core::Zone *zone) if (!entity) { zoneini.unknown_error("ship definition without entity"); - } else if ((entity->moduletype() != planet_enttype) && (entity->moduletype() != station_enttype) && (entity->moduletype() != patrol_enttype)) { + } else if ((entity->moduletype() != planet_enttype) && (entity->moduletype() != station_enttype)) { zoneini.unknown_error("ship definition for invalid entity type"); } else { inventory = entity->inventory(); @@ -2104,7 +2118,7 @@ bool Game::load_zone(core::Zone *zone) } } else if (zoneini.in_section("waypoint")) { - if (!patrol_waypoint) { + if (!patrol || (patrol != entity) || !patrol_waypoint ) { continue; } else if (zoneini.got_key_string("target", strval)) { patrol_waypoint->set_target_label(strval); @@ -2122,6 +2136,52 @@ bool Game::load_zone(core::Zone *zone) } else { zoneini.unknown_key(); } + + } else if (zoneini.in_section("npc")) { + if (!patrol || (patrol != entity) || !patrol_npctype) { + continue; + } else if (zoneini.got_key_string("name", strval)) { + aux::strip_quotes(strval); + patrol_npctype->set_name(strval); + } else if (zoneini.got_key_long("amount", l)) { + patrol_npctype->set_amount(l); + } else if (zoneini.got_key_bool("merchant", b)) { + patrol_npctype->set_merchant(b); + } else if (zoneini.got_key_label("ship", strval)) { + ShipModel *shipmodel = ShipModel::find(strval); + if (!shipmodel) { + zoneini.unknown_error("unknown ship type '" + strval + "'"); + } else { + patrol_npctype->set_shipmodel(shipmodel); + } + } else if (zoneini.got_key_label("faction", strval)) { + Faction *faction = Faction::find(strval); + if (!faction) { + zoneini.unknown_error("unknown faction '" + strval + "'"); + } else { + patrol_npctype->set_faction(faction); + } + } else if (zoneini.got_key_label("cannon", strval)) { + Weapon *cannon = Weapon::find(strval); + if (!cannon) { + zoneini.unknown_error("unknown weapon type '" + strval + "'"); + } else if (cannon->subtype() != Weapon::Cannon) { + zoneini.unknown_error("weapon type '" + strval + "' is not a cannon"); + } else { + patrol_npctype->set_cannon(cannon); + } + } else if (zoneini.got_key_label("turret", strval)) { + Weapon *turret = Weapon::find(strval); + if (!turret) { + zoneini.unknown_error("unknown weapon type '" + strval + "'"); + } else if (turret->subtype() != Weapon::Turret) { + zoneini.unknown_error("weapon type '" + strval + "' is not a turret"); + } else { + patrol_npctype->set_turret(turret); + } + } else { + zoneini.unknown_key(); + } } else if (zoneini.in_section("planet")) { if (core::Parser::got_entity_key(zoneini, planet)) { @@ -2333,21 +2393,14 @@ bool Game::load_zone(core::Zone *zone) if (!item) { item = new core::Item(shipmodel); - if ((entity->moduletype() == patrol_enttype)) { - item->set_amount(1); - } else { - item->set_amount(-1); - } + item->set_amount(-1); item->set_price(shipmodel->price()); inventory->add(item); } } else { zoneini.unknown_error("unknown ship type '" + strval + "'"); } - } else if ((entity->moduletype() == patrol_enttype) && zoneini.got_key_long("amount", l)) { - if (item) { - item->set_amount(l); - } + } else if (zoneini.got_key_long("price", l)) { if (item) { item->set_price(l); @@ -2446,7 +2499,7 @@ bool Game::generate_entity_menus(core::Entity *entity) size_t nbweapon = 0; size_t nbships = 0; - for (core::Inventory::Items::const_iterator it = entity->inventory()->items().begin(); it != entity->inventory()->items().end(); it++) { + for (core::Inventory::Items::const_iterator it = entity->inventory()->items().begin(); it != entity->inventory()->items().end(); ++it) { core::Item *item = (*it); if (item->info()->type() == Cargo::infotype()) { diff --git a/src/game/base/npctype.cc b/src/game/base/npctype.cc new file mode 100644 index 0000000..f44cc1f --- /dev/null +++ b/src/game/base/npctype.cc @@ -0,0 +1,71 @@ +/* + base/npctype.h + 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 "base/npctype.h" + +namespace game +{ + +NPCType::NPCType() : + npctype_name() +{ + npctype_amount = 1; + npctype_merchant = false; + + npctype_faction = 0; + npctype_shipmodel = 0; + + npctype_cannon = 0; + npctype_turret = 0; +} + + +NPCType::~NPCType() +{ + // clear pointers + npctype_faction = 0; + npctype_shipmodel = 0; + + npctype_cannon = 0; + npctype_turret = 0; +} + +void NPCType::set_name(const std::string &name) +{ + npctype_name.assign(name); +} + +void NPCType::set_amount(const long amount) +{ + npctype_amount = amount; +} + +void NPCType::set_merchant(const bool is_merchant) +{ + npctype_merchant = is_merchant; +} + +void NPCType::set_faction(const Faction *faction) +{ + npctype_faction = faction; +} + +void NPCType::set_shipmodel(const ShipModel *shipmodel) +{ + npctype_shipmodel = shipmodel; +} + +void NPCType::set_cannon(const Weapon *cannon) +{ + npctype_cannon = cannon; +} + +void NPCType::set_turret(const Weapon *turret) +{ + npctype_turret = turret; +} + +} // namespace game diff --git a/src/game/base/npctype.h b/src/game/base/npctype.h new file mode 100644 index 0000000..fd9515f --- /dev/null +++ b/src/game/base/npctype.h @@ -0,0 +1,122 @@ +/* + base/npctype.h + This file is part of the Osirion project and is distributed under + the terms and conditions of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_BASE_NPCTYPE_H__ +#define __INCLUDED_BASE_NPCTYPE_H__ + +#include "base/faction.h" +#include "base/shipmodel.h" +#include "base/weapon.h" + +namespace game +{ + +/** + * @brief NPC generation information + * Used by Patrols to generate NPC instances + * */ +class NPCType { + +public: + /** + * @brief constructor + * */ + NPCType(); + + /** + * @brief destructor + * */ + ~NPCType(); + + /* --- inspectors ------------------------------------------ */ + + /** + * @brief entity name to be used by the NPC + * */ + inline const std::string &name() const + { + return npctype_name; + } + + /** + * @brief the maximal amount of NPCs of this type to generate + * */ + inline const long amount() const + { + return npctype_amount; + } + + /** + * @brief true if the NPC will buy cargo + * */ + inline const bool is_merchant() const + { + return npctype_merchant; + } + + /** + * @brief the faction the NPC will belong to + * */ + inline const Faction *faction() const + { + return npctype_faction; + } + + /** + * @brief the shipmodel the NPC will use + * */ + inline const ShipModel *shipmodel() const + { + return npctype_shipmodel; + } + + /** + * @brief the type of cannons the NPC will use + * */ + inline const Weapon *cannon() const + { + return npctype_cannon; + } + + /** + * @brief the type of turrets the NPC will use + * */ + inline const Weapon *turret() const + { + return npctype_turret; + } + + /* --- mutators -------------------------------------------- */ + + void set_name(const std::string &name); + + void set_amount(const long amount); + + void set_merchant(const bool is_merchant = false); + + void set_faction(const Faction *faction); + + void set_shipmodel(const ShipModel *shipmodel); + + void set_cannon(const Weapon *cannon); + + void set_turret(const Weapon *turret); + +private: + std::string npctype_name; + long npctype_amount; + bool npctype_merchant; + + const Faction *npctype_faction; + const ShipModel *npctype_shipmodel; + + const Weapon *npctype_cannon; + const Weapon *npctype_turret; +}; + +} // namespace game + +#endif // __INCLUDED_BASE_NPCTYPE_H__ diff --git a/src/game/base/patrol.cc b/src/game/base/patrol.cc index 850efb9..f3cfa07 100644 --- a/src/game/base/patrol.cc +++ b/src/game/base/patrol.cc @@ -79,6 +79,13 @@ Patrol::~Patrol() } patrol_waypoints.clear(); + // delete npc types + for (NPCTypes::iterator it = patrol_npctypes.begin(); it != patrol_npctypes.end(); ++it) { + delete(*it); + (*it) = 0; + } + patrol_npctypes.clear(); + // detach and delete remaining members for (Members::iterator it = patrol_members.begin(); it != patrol_members.end(); ++it) { NPC *member = (*it); @@ -167,22 +174,12 @@ void Patrol::validate() ++it; } } - - size_t nbships = 0; - for (core::Inventory::Items::const_iterator it = inventory()->items().begin(); it != inventory()->items().end(); it++) { - core::Item *item = (*it); - - if (item->info()->type() == ShipModel::infotype()) { - nbships++; - } - } - + if (patrol_waypoints.size() == 0) { con_warn << " Patrol '" << label() << "' without waypoints" << "\n"; - die(); - - } else if (nbships == 0) { - con_warn << " Patrol '" << label() << "' without ship types" << "\n"; + die(); + } else if (patrol_npctypes.size() == 0) { + con_warn << " Patrol '" << label() << "' without NPC types" << "\n"; die(); } else if (!(*patrol_waypoints.begin())->target()->has_flag(core::Entity::Dockable)) { con_warn << " Patrol '" << label() << "' spawn set to non-dockable target" << "\n"; @@ -194,10 +191,10 @@ void Patrol::validate() // spawn waypoint is current patrol_waypoint_current = patrol_waypoints.begin(); - con_debug << " " << label() << " patrol " << patrol_waypoints.size() << " " << aux::plural("waypoint", patrol_waypoints.size()) << " " - << nbships << " ship " << aux::plural("type", nbships) << std::endl; + con_debug << " " << label() << " patrol " + << patrol_waypoints.size() << " " << aux::plural("waypoint", patrol_waypoints.size()) << " " + << patrol_npctypes.size() << " npc " << aux::plural("type", patrol_npctypes.size()) << std::endl; } - } Patrol::WayPoint *Patrol::add_waypoint() @@ -209,6 +206,15 @@ Patrol::WayPoint *Patrol::add_waypoint() return waypoint; } +NPCType *Patrol::add_npctype() +{ + NPCType *npctype = new NPCType(); + + patrol_npctypes.push_back(npctype); + + return npctype; +} + void Patrol::add_member(NPC *npc) { npc->set_patrol(this); @@ -279,33 +285,34 @@ void Patrol::frame(const unsigned long elapsed) if (spawn->has_flag(core::Entity::Dockable)) { - // create NPC members for every ship in the patrol's inventory - for (core::Inventory::Items::const_iterator it = inventory()->items().begin(); it != inventory()->items().end(); it++) { - core::Item *item = (*it); - - if (item->info()->type() != ShipModel::infotype()) { + // create NPC members for every NPC type + for (NPCTypes::const_iterator it = patrol_npctypes.begin(); it != patrol_npctypes.end(); ++it) { + + NPCType *npctype = (*it); + + if (!npctype->shipmodel()) { continue; } - // find shipmodel - ShipModel *shipmodel = ShipModel::find(item->info()->label()); - if (!shipmodel) { + if (npctype->amount() <= 0) { continue; } - const size_t nbships = 1 + math::randomi(item->amount()); + const size_t nbships = 1 + math::randomi((unsigned int) npctype->amount()); for (size_t i = 0; i < nbships; i++) { // add NPC - NPC *npc = new NPC(patrol_profile, shipmodel); + NPC *npc = new NPC(patrol_profile, npctype->shipmodel()); // set NPC name - if (shipmodel->npc_name().size()) { - npc->set_name(shipmodel->npc_name()); + if (npctype->name().size()) { + npc->set_name(npctype->name()); } // set NPC color - if (faction()) { + if (npctype->faction()) { + npctype->faction()->apply(npc); + } else if (faction()) { faction()->apply(npc); } @@ -313,13 +320,57 @@ void Patrol::frame(const unsigned long elapsed) if (npc->has_flag(core::Entity::Dockable)) { unset_flag(core::Entity::Dockable); // delete menus - for (Menus::iterator mit = npc->menus().begin(); mit != npc->menus().end(); mit++) { + for (Menus::iterator mit = npc->menus().begin(); mit != npc->menus().end(); ++mit) { delete (*mit); (*mit) = 0; } npc->menus().clear(); } + // install inventory + if (!npc->inventory()) { + npc->add_inventory(); + } + + // install slots + if (!npc->slots()) { + npc->add_slots(); + slots()->load(model()); + } + + // install weapons + for (core::Slots::iterator slit = npc->slots()->begin(); slit != npc->slots()->end(); ++slit) { + core::Slot *slot = (*slit); + + core::Item *item = 0; + + if (slot->type() == model::Weapon::Cannon) { + if (npctype->cannon()) { + item = new core::Item(npctype->cannon()); + } + } else if (slot->type() == model::Weapon::Turret) { + if (npctype->turret()) { + item = new core::Item(npctype->turret()); + } + } + + if (item) { + // add item + item->set_flag(core::Item::Unique); + item->set_flag(core::Item::Mountable); + item->set_flag(core::Item::Unrestricted); + item->set_amount(1); + npc->inventory()->add(item); + + // mount weapon + slot->set_item(item); + slot->set_flag(core::Slot::Active); + slot->set_flag(core::Slot::Mounted); + } + } + + npc->inventory()->recalculate(); + // dock npc at spawn npc->set_zone(spawn->zone()); npc->set_dock(spawn); @@ -362,6 +413,7 @@ void Patrol::frame(const unsigned long elapsed) NPC *member = (*mit); // buy cargo if requested + // FIXME apply NPCType is_merchant if (waypoint()->dock() && waypoint()->cargo() && member->inventory()) { // erase all cargo from inventory diff --git a/src/game/base/patrol.h b/src/game/base/patrol.h index 0e03234..e4ba19b 100644 --- a/src/game/base/patrol.h +++ b/src/game/base/patrol.h @@ -11,6 +11,7 @@ #include "base/faction.h" #include "base/cargo.h" #include "base/npc.h" +#include "base/npctype.h" namespace game { @@ -76,6 +77,8 @@ public: typedef std::list<WayPoint *> WayPoints; + typedef std::list<NPCType *> NPCTypes; + typedef std::list<NPC *> Members; Patrol(); @@ -106,6 +109,8 @@ public: void set_faction(Faction *faction); WayPoint *add_waypoint(); + + NPCType *add_npctype(); virtual void validate(); @@ -113,7 +118,7 @@ public: void add_member(NPC *npc); - void erase_member(NPC *npc); + void erase_member(NPC *npc); private: void set_leader(); @@ -126,6 +131,8 @@ private: Members patrol_members; + NPCTypes patrol_npctypes; + NPC::Profile patrol_profile; NPC *patrol_leader; diff --git a/src/game/base/shipmodel.cc b/src/game/base/shipmodel.cc index 3582517..6fd809b 100644 --- a/src/game/base/shipmodel.cc +++ b/src/game/base/shipmodel.cc @@ -74,9 +74,6 @@ bool ShipModel::init() } else if (inifile.got_key_string("name", str)) { shipmodel->set_name(str); continue; - } else if (inifile.got_key_string("npcname", str)) { - shipmodel->set_npc_name(str); - continue; } else if (inifile.got_key_string("info", str)) { shipmodel->add_text(str); continue; diff --git a/src/game/base/shipmodel.h b/src/game/base/shipmodel.h index 2231fea..9849cd0 100644 --- a/src/game/base/shipmodel.h +++ b/src/game/base/shipmodel.h @@ -114,14 +114,6 @@ public: return shipmodel_radius; } - /** - * @brief name used for NPCs with this ship model - * */ - inline const std::string & npc_name() const - { - return shipmodel_npc_name; - } - /// entity template inline const Template *model_template() const { @@ -238,15 +230,7 @@ protected: { shipmodel_angular_damping = angular_damping; } - - /** - * @brief set the name used for NPCs with this ship model - * */ - inline void set_npc_name(const std::string name) - { - shipmodel_npc_name.assign(name); - } - + public: /** * @brief generate specifications info. @@ -285,7 +269,6 @@ private: float shipmodel_turn_force; float shipmodel_roll_force; -// float shipmodel_maxspeed; float shipmodel_maxcargo; float shipmodel_maxarmor; float shipmodel_maxshield; @@ -295,8 +278,6 @@ private: const Template *shipmodel_template; - std::string shipmodel_npc_name; - /* --- static ----------------------------------------------------- */ static core::InfoType *shipmodel_infotype; |