diff options
Diffstat (limited to 'src/game/base/platform.cc')
-rw-r--r-- | src/game/base/platform.cc | 189 |
1 files changed, 189 insertions, 0 deletions
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<Ship *> enemylist; + + for (core::Zone::Content::iterator zit = zone()->content().begin(); zit != zone()->content().end(); ++zit) { + if ((*zit)->moduletype() == ship_enttype) { + Ship *ship = static_cast<Ship *>((*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<const Faction *>(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<Ship *>::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()); + } + } + + } + } +} + +} |