From 7bdab72e2ddf145a4692ae92b22110c2e7febe67 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Mon, 11 Nov 2013 00:41:33 +0000 Subject: Support for station weapons. --- src/game/base/Makefile.am | 2 + src/game/base/game.cc | 20 ++++- src/game/base/game.h | 44 ++++++----- src/game/base/platform.cc | 189 ++++++++++++++++++++++++++++++++++++++++++++++ src/game/base/platform.h | 75 ++++++++++++++++++ src/game/base/ship.cc | 4 +- src/game/base/station.cc | 49 ++++++------ src/game/base/station.h | 4 +- 8 files changed, 340 insertions(+), 47 deletions(-) create mode 100644 src/game/base/platform.cc create mode 100644 src/game/base/platform.h (limited to 'src/game/base') diff --git a/src/game/base/Makefile.am b/src/game/base/Makefile.am index 7444b73..42a7f5c 100644 --- a/src/game/base/Makefile.am +++ b/src/game/base/Makefile.am @@ -14,6 +14,7 @@ noinst_HEADERS = \ npctype.h \ patrol.h \ planet.h \ + platform.h \ racetrack.h \ savegame.h \ ship.h \ @@ -36,6 +37,7 @@ libbase_la_SOURCES = \ npctype.cc \ patrol.cc \ planet.cc \ + platform.cc \ racetrack.cc \ savegame.cc \ ship.cc \ diff --git a/src/game/base/game.cc b/src/game/base/game.cc index 54c59b7..f41b9b2 100644 --- a/src/game/base/game.cc +++ b/src/game/base/game.cc @@ -2245,7 +2245,7 @@ bool Game::load_zone(core::Zone *zone) zoneini.unknown_error("weapon type '" + strval + "' is not a turret"); } else { patrol_npctype->set_turret(turret); - } + } } else { zoneini.unknown_key(); } @@ -2303,6 +2303,24 @@ bool Game::load_zone(core::Zone *zone) } else { shipmodel->apply(station); } + } 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 { + station->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 { + station->set_turret(turret); + } } else { zoneini.unknown_key(); } diff --git a/src/game/base/game.h b/src/game/base/game.h index bd8d402..81d5339 100644 --- a/src/game/base/game.h +++ b/src/game/base/game.h @@ -11,39 +11,47 @@ #include #include "base/ship.h" -#include "base/shipmodel.h" -#include "base/star.h" +#include "base/faction.h" + #include "core/module.h" +#include "core/range.h" #include "core/application.h" #include "core/gameinterface.h" + #include "filesystem/inifile.h" + #include "sys/sys.h" -/// the base game module -/** the base game module contains the game-specific code for Project::OSiRiON - */ +/** + * @brief the base game module + * the base game module contains the game-specific code for Project::OSiRiON + **/ namespace game { -// entity type constants -const unsigned int ship_enttype = 256; -const unsigned int star_enttype = 257; -const unsigned int planet_enttype = 258; -const unsigned int navpoint_enttype = 259; -const unsigned int jumppoint_enttype = 260; -const unsigned int jumpgate_enttype = 261; -const unsigned int station_enttype = 262; -const unsigned int cargopod_enttype = 263; -const unsigned int spacemine_enttype = 264; -const unsigned int race_enttype = 280; -const unsigned int patrol_enttype = 512; +// entity module type constants +const unsigned int star_enttype = 100; +const unsigned int planet_enttype = 101; + +const unsigned int platform_enttype = 200; +const unsigned int station_enttype = 201; + +const unsigned int navpoint_enttype = 302; +const unsigned int jumppoint_enttype = 303; +const unsigned int jumpgate_enttype = 304; +const unsigned int race_enttype = 305; + +const unsigned int patrol_enttype = 500; +const unsigned int ship_enttype = 501; + +const unsigned int cargopod_enttype = 600; +const unsigned int spacemine_enttype = 601; // ship engine delay times const float jump_timer_delay = 5.0f; const float jump_cooldown_delay = 2.0f; const float impulse_timer_delay = 3.0f; - /// default player settings class Default { diff --git a/src/game/base/platform.cc b/src/game/base/platform.cc new file mode 100644 index 0000000..15c7576 --- /dev/null +++ b/src/game/base/platform.cc @@ -0,0 +1,189 @@ +/* + base/platform.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/gameserver.h" +#include "core/entityprojectile.h" + +#include "base/game.h" +#include "base/faction.h" +#include "base/platform.h" +#include "base/weapon.h" +#include "sys/sys.h" + +namespace game +{ + +Platform::Platform() : Entity() +{ + entity_moduletypeid = platform_enttype; + + platform_cannon = 0; + platform_turret = 0; +} + +Platform::~Platform() +{ + +} + +void Platform::set_cannon(const Weapon *cannon) +{ + platform_cannon = cannon; +} + +void Platform::set_turret(const Weapon *turret) +{ + platform_turret = turret; +} + +void Platform::frame(const unsigned long elapsed) +{ + const float weapon_range = math::max((cannon() ? cannon()->projectile_range() : 0.0f), (turret() ? turret()->projectile_range() : 0.0f)); + + if ((weapon_range > 0.0f) && slots() && zone()->keepalive_run()) { + + // create list of potential enemies + std::list enemylist; + + for (core::Zone::Content::iterator zit = zone()->content().begin(); zit != zone()->content().end(); ++zit) { + if ((*zit)->moduletype() == ship_enttype) { + Ship *ship = static_cast((*zit)); + + if ((ship->state() != Normal) && (ship->state() != ImpulseInitiate) && (ship->state() != Impulse)) { + continue; + } + + const float d = math::distance(location(), ship->location()); + const float r = radius() + ship->radius(); + + // too far + if (d > weapon_range + r) { + continue; + } + + float reputation = 0.0f; + if (ship->owner()) { + // check owner reputation for the faction the NPC belongs to + reputation = ship->owner()->reputation(faction()); + + } else if (faction() && (faction()->type() == Faction::infotype())) { + //check my faction reputation for the other ships's faction + reputation = static_cast(faction())->reputation(ship->faction()); + } + + // reputation threshold to get attacked + if (reputation > core::range::reputation_hostile) { + continue; + } + enemylist.push_back(ship); + + } + } + + // platforms do not need weapons in inventory to fire + if (enemylist.size()) { + + const float modelscale = radius() / (model() ? model()->radius() : 1.0f); + + for (core::Slots::iterator it = slots()->begin(); it != slots()->end(); it++) { + core::Slot *slot = (*it); + + // found out if this slot is a cannon or a turret + const Weapon *weapon = 0; + if (slot->type() == model::Weapon::Cannon) { + weapon = cannon(); + + } else if (slot->type() == model::Weapon::Turret) { + weapon = turret(); + } + + if ((!weapon) || (weapon->projectile_interval() == 0)) { + continue; + } + + if ((slot->last_fired() + weapon->projectile_interval() > core::server()->timestamp())) { + continue; + } + + // location of the slot in world coordinates + const math::Vector3f slot_location(location() + (axis() * slot->location() * modelscale)); + + // find a target for this slot + Ship *current_enemy = 0; + float current_distance = 0.0f; + + const float projectile_radius = core::PROJECTILE_RADIUS; + math::Axis projectile_axis(axis() * slot->axis()); + const math::Vector3f projectile_location(slot_location + projectile_axis.forward() * projectile_radius); + + math::Vector3f projectile_direction; + math::Vector3f aim_location; + + // we only need half the cone angle for the cosine calculation + const float conecos = cosf(slot->cone() * 0.5f); + + for (std::list::const_iterator enemy_it = enemylist.begin(); enemy_it != enemylist.end(); enemy_it++) { + + const float d = math::distance((*enemy_it)->location(), projectile_location); + + if (d > weapon->projectile_range() + (*enemy_it)->radius()) { + continue; + } + if ((current_distance > 0) && (d > current_distance)) { + continue; + } + + aim_location.assign((*enemy_it)->location() + (*enemy_it)->axis().forward() * ( (*enemy_it)->radius() * 0.25f)); + projectile_direction.assign(aim_location - projectile_location); + projectile_direction.normalize(); + + const float cosa = math::dotproduct(projectile_direction, projectile_axis.forward()); + + // check if the ship is in the slot's cone if fire + if (cosa >= conecos) { + current_distance = d; + current_enemy = (*enemy_it); + } + } + + if (current_enemy) { + aim_location.assign(current_enemy->location() + current_enemy->axis().forward() * (current_enemy->radius() * 0.25f)); + projectile_direction.assign(aim_location - projectile_location); + projectile_direction.normalize(); + + const float cosa = math::dotproduct(projectile_direction, projectile_axis.forward()); + + // point the projectile into the fire direction + math::Vector3f normal(math::crossproduct(projectile_direction, projectile_axis.forward())); + if (normal.length() > MIN_DELTA) { + float sina = sqrt(1.0f - cosa * cosa); + + normal.normalize(); + projectile_axis.rotate(normal, cosa, sina); + } + + // spawn a new projectile + core::EntityProjectile *projectile = new core::EntityProjectile(this); + + projectile->set_damage(weapon->damage()); + projectile->set_lifespan(weapon->projectile_lifespan()); + projectile->set_projectile_modelname(weapon->projectile_modelname()); + projectile->set_projectile_soundname(weapon->projectile_soundname()); + + projectile->set_axis(projectile_axis); + projectile->set_location(projectile_location); + projectile->set_speed(weapon->projectile_speed()); + + projectile->reset(); + slot->set_last_fired(core::server()->timestamp()); + } + } + + } + } +} + +} diff --git a/src/game/base/platform.h b/src/game/base/platform.h new file mode 100644 index 0000000..3a8bddf --- /dev/null +++ b/src/game/base/platform.h @@ -0,0 +1,75 @@ +/* + base/platform.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_PLATFORM_H__ +#define __INCLUDED_BASE_PLATFORM_H__ + +#include "base/weapon.h" + +namespace game +{ + +/** + * @brief a weapons platform + * This class also serves as base class for the Station class, + **/ +class Platform : public core::Entity +{ +public: + /** + * @brief constructor + * */ + Platform(); + + /** + * @brief destructor + * */ + virtual ~Platform(); + + /* -- inspectors ------------------------------------------- */ + + /** + * @brief the type of cannons the Platform will use + * */ + inline const Weapon *cannon() const + { + return platform_cannon; + } + + /** + * @brief the type of turrets the Platform will use + * */ + inline const Weapon *turret() const + { + return platform_turret; + } + + /* -- mutators --------------------------------------------- */ + + /** + * @brief set the type of cannons the Platform will use + * */ + void set_cannon(const Weapon *cannon); + + /** + * @brief set the type of turrets the Platform will use + * */ + void set_turret(const Weapon *turret); + + /** + * @brief run a game frame + * */ + virtual void frame(const unsigned long elapsed); + +private: + const Weapon *platform_cannon; + const Weapon *platform_turret; +}; + +} + +#endif // __INCLUDED_BASE_SHIPDEALER_H__ + diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index 368fc11..d947139 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -1131,9 +1131,9 @@ void Ship::frame(const unsigned long elapsed) EntityControlable::frame(elapsed); // fire weapons - if (model() && slots() && (state() == core::Entity::Normal) && has_target_controlflag(core::EntityControlable::ControlFlagFire)) { + if (slots() && (state() == core::Entity::Normal) && has_target_controlflag(core::EntityControlable::ControlFlagFire)) { - const float modelscale = radius() / model()->radius(); + const float modelscale = radius() / (model() ? model()->radius() : 1.0f); for (core::Slots::iterator it = slots()->begin(); it != slots()->end(); it++) { core::Slot *slot = (*it); diff --git a/src/game/base/station.cc b/src/game/base/station.cc index 31e6b3e..6b451a9 100644 --- a/src/game/base/station.cc +++ b/src/game/base/station.cc @@ -12,7 +12,7 @@ namespace game { -Station::Station() : Entity() +Station::Station() : Platform() { entity_moduletypeid = station_enttype; set_flag(core::Entity::Dockable); @@ -26,32 +26,31 @@ Station::~Station() void Station::upkeep(const unsigned long timestamp) { - if (!inventory()) - return; - - const unsigned long deplete = (Game::g_deplete ? 1000 * (unsigned long) Game::g_deplete->value() : 0); - - if (deplete > 0) { - bool dirty = false; - for (core::Inventory::Items::iterator it = inventory()->items().begin(); it != inventory()->items().end(); ) { - core::Item *item = (*it); - if ((item->amount() > 0) && (item->timestamp() + deplete < timestamp)) { - item->dec_amount(1); - dirty = true; + if (inventory()) { + const unsigned long deplete = (Game::g_deplete ? 1000 * (unsigned long) Game::g_deplete->value() : 0); + + if (deplete > 0) { + bool dirty = false; + for (core::Inventory::Items::iterator it = inventory()->items().begin(); it != inventory()->items().end(); ) { + core::Item *item = (*it); + if ((item->amount() > 0) && (item->timestamp() + deplete < timestamp)) { + item->dec_amount(1); + dirty = true; + } + + if ((item->info()->type() == Weapon::infotype()) && (item->amount() == 0)) { + delete (item); + (*it) = 0; + inventory()->items().erase(it++); + dirty = true; + } else { + ++it; + } } - if ((item->info()->type() == Weapon::infotype()) && (item->amount() == 0)) { - delete (item); - (*it) = 0; - inventory()->items().erase(it++); - dirty = true; - } else { - ++it; - } - } - - if (dirty) { - inventory()->set_dirty(); + if (dirty) { + inventory()->set_dirty(); + } } } } diff --git a/src/game/base/station.h b/src/game/base/station.h index 5f833c4..889d3f9 100644 --- a/src/game/base/station.h +++ b/src/game/base/station.h @@ -7,10 +7,12 @@ #ifndef __INCLUDED_BASE_STATION_H__ #define __INCLUDED_BASE_STATION_H__ +#include "base/platform.h" + namespace game { -class Station : public core::Entity +class Station : public Platform { public: Station(); -- cgit v1.2.3