/* base/racetrack.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 #include #include "base/game.h" #include "base/racetrack.h" #include "core/gameserver.h" namespace game { /* ---- class CheckPoint ------------------------------------------- */ CheckPoint::CheckPoint(RaceTrack *parent) { set_state(core::Entity::NoPower); parent_track = parent; if (parent) { get_color().assign(parent->color()); get_color_second().assign(parent->color_second()); set_zone(parent->zone()); parent->add_checkpoint(this); } else { die(); } } CheckPoint::~CheckPoint() { } /* ---- class RaceTrack -------------------------------------------- */ RaceTrack::RaceTrack() : EntityDynamic() { track_player = 0; track_racestart = 0; track_checkpointtime = 0; set_state(core::Entity::NoPower); set_flag(core::Entity::Dockable); } RaceTrack::~RaceTrack() { track_checkpoints.clear(); } void RaceTrack::add_checkpoint(CheckPoint *checkpoint) { track_checkpoints.push_back(checkpoint); } void RaceTrack::reset() { if (track_player) { track_player->set_mission_target(0); } track_player = 0; track_racestart = 0; track_checkpointtime = 0; for (CheckPoints::iterator cpit = track_checkpoints.begin(); cpit != track_checkpoints.end(); ++cpit) { (*cpit)->set_state(core::Entity::NoPower); } set_state(core::Entity::NoPower); } void RaceTrack::dock(core::Entity *entity) { if (entity->moduletype() != ship_enttype) return; Ship * ship = static_cast(entity); if (math::distance(location(), ship->location()) > radius()) { ship->owner()->send("Target out of range"); return; } if (track_player) { ship->owner()->send("Race in use"); return; } track_player = ship->owner(); track_racestart = core::server()->time(); set_state(core::Entity::Normal); for (CheckPoints::iterator cpit = track_checkpoints.begin(); cpit != track_checkpoints.end(); ++cpit) { set_state(core::Entity::Normal); } entity_timer = 5.0f; std::string message("^B" + track_player->name() + " ^Bactivated the race! Race starts in 5..."); core::server()->broadcast(message); track_player->set_mission_target(this); return; } void RaceTrack::frame(float seconds) { if (!track_checkpoints.size()) return; if (!track_player) return; // FIXME this should go into a proper general function // validate current player core::Player *player = 0; for (core::GameServer::Players::iterator pit = core::server()->players().begin(); (!player) && (pit != core::server()->players().end()); ++pit) { if ((*pit) == track_player) { player = (*pit); } } if (!player) { reset(); return; } if (!player->control() || (player->control()->zone() != zone())) { reset(); return; } if (entity_timer) { if (math::distance(location(), player->control()->location()) > radius()) { std::string message("^BNo cheating!"); core::server()->broadcast(message); reset(); return; } if (track_racestart + 1.0f <= core::server()->time()) { entity_timer -= 1.0f; set_dirty(); if (entity_timer > 0) { std::stringstream msgstr; msgstr << "^B" << entity_timer << "..."; core::server()->broadcast(msgstr.str()); track_racestart = core::server()->time(); } else { for (CheckPoints::iterator cpit = track_checkpoints.begin(); cpit != track_checkpoints.end(); ++cpit) { (*cpit)->set_state(core::Entity::NoPower); } std::string message("^BGo!"); core::server()->broadcast(message); track_racestart = core::server()->time(); track_checkpointtime = core::server()->time() + 15.0f; track_checkpoint = track_checkpoints.begin(); (*track_checkpoint)->set_state(core::Entity::Normal); track_player->set_mission_target((*track_checkpoint)); } } } else { if (core::server()->time() > track_checkpointtime) { std::string message("^BToo slow, race lost!"); core::server()->broadcast(message); reset(); return; } if (math::distance(track_player->control()->location(), (*track_checkpoint)->location()) < radius()) { CheckPoints::iterator next_checkpoint = track_checkpoint; next_checkpoint++; if (next_checkpoint != track_checkpoints.end()) { std::string message("^BCheckpoint!"); core::server()->broadcast(message); track_checkpointtime = core::server()->time() + 15.0f; (*track_checkpoint)->set_state(core::Entity::NoPower); track_checkpoint++; (*track_checkpoint)->set_state(core::Entity::Normal); track_player->set_mission_target((*track_checkpoint)); } else { std::stringstream msgstr; msgstr << "^BRace completed in " << core::server()->time() - track_racestart << " seconds!"; core::server()->broadcast(msgstr.str()); // prize money unsigned long the_prize = (unsigned long) floorf(10000.0f / (core::server()->time() - track_racestart)); player->add_credits(the_prize); msgstr.clear(); msgstr.str(""); msgstr << "You receive " << the_prize << " credits."; player->send(msgstr.str()); player->sound("game/buy"); reset(); } } } } }