/* core/gameinterface.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include #include #include "core/application.h" #include "core/cvar.h" #include "core/func.h" #include "core/gameinterface.h" #include "core/player.h" #include "model/model.h" #include "sys/sys.h" namespace core { void func_list_model(std::string const &args) { model::Model::list(); } Player GameInterface::game_localplayer; EntityControlable *localcontrol() { if (game()->localplayer()) return game()->localplayer()->control(); else return 0; } Player *localplayer() { return game()->localplayer(); } GameInterface::GameInterface() { clear(); game_localplayer.clear(); if (Cvar::sv_dedicated->value()) { game_localplayer.player_name.assign("Console"); } else { game_localplayer.player_name.assign("Player"); game_localplayer.update_info(); } core::Func::add("list_model", (core::FuncPtr) func_list_model); } GameInterface::~GameInterface() { core::Func::remove("list_model"); game_localplayer.clear(); clear(); } // clear all game related objects void GameInterface::clear() { //con_debug << "Clearing game data\n"; // remove all entities for (std::map::iterator it = Entity::registry.begin(); it != Entity::registry.end(); it++) { delete (*it).second; } Entity::registry.clear(); // remove all game functions for (std::map::iterator it = Func::registry.begin(); it != Func::registry.end(); it++) { if ( ((*it).second->flags() & Func::Game) == Func::Game) { delete (*it).second; Func::registry.erase(it); } } // remove all game cvars for (std::map::iterator it = Cvar::registry.begin(); it != Cvar::registry.end(); it++) { if ( ((*it).second->flags() & Cvar::Game) == Cvar::Game) { delete (*it).second; Cvar::registry.erase(it); } } // remove all models model::Model::clear(); game_previousframetime = 0; game_serverframetime = 0; game_clientframetime = 0; } void GameInterface::reset_clientstate(float servertime) { game_previousframetime = game_serverframetime; game_clientframetime = game_serverframetime; game_serverframetime = servertime; std::map::iterator it; for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { core::Entity *entity = (*it).second; if (entity->state() && !(entity->flags() & core::Entity::Static)) entity->state()->assign(entity); } } void GameInterface::update_clientstate(float seconds) { game_clientframetime += seconds; if (game_clientframetime > game_serverframetime) game_clientframetime = game_serverframetime; std::map::iterator it; for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { Entity *entity = (*it).second; // update client state if (!entity->state()) { entity->entity_clientstate = new core::ClientState(entity); } if (!(entity->flags() & core::Entity::Static)) { // clientstate location entity->state()->state_location = entity->state()->previouslocation() + (entity->location() - entity->state()->previouslocation()) * core::game()->timeoffset(); if (core::game()->clientframetime() < core::game()->serverframetime()) { // http://local.wasp.uwa.edu.au/~pbourke/geometry/planeline/ float cosangle; float angle; float side; float u; math::Vector3f n; math::Vector3f p; // clientstate axis: pitch // project entity->axis().up() into the plane with entity->state()->axis()->left() normal n = entity->state()->axis().left(); p = entity->axis().up(); u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); p = entity->axis().up() + u * n; side = entity->state()->axis().forward().x * p.x + entity->state()->axis().forward().y * p.y + entity->state()->axis().forward().z * p.z; if (fabs(side) > 0.00005f) { cosangle = math::dotproduct(p, entity->state()->axis().up()); if (fabs(cosangle) < 0.99995f) { angle = acos(cosangle) * 180.0f / M_PI; angle = math::sgnf(side) * angle * seconds / (core::game()->serverframetime() - core::game()->clientframetime()); entity->state()->state_axis.change_pitch(-angle); } } // clientstate axis: direction // project entity->axis().forward() into the plane with entity->state()->axis().up() normal n = entity->state()->axis().up(); p = entity->axis().forward(); u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); p = entity->axis().forward() + u * n; side = entity->state()->axis().left().x * p.x + entity->state()->axis().left().y * p.y + entity->state()->axis().left().z * p.z; if (fabs(side) > 0.00005f) { cosangle = math::dotproduct(p, entity->state()->axis().forward()); if (fabs(cosangle) < 0.99995f) { angle = acos(cosangle) * 180.0f / M_PI; angle = math::sgnf(side) * angle * seconds / (core::game()->serverframetime() - core::game()->clientframetime()); entity->state()->state_axis.change_direction(angle); } } // clientstate axis: roll // project entity->axis().up() into the plane with entity->state()->axis().forward() normal n = entity->state()->axis().forward(); p = entity->axis().up(); u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); p = entity->axis().up() + u * n; side = entity->state()->axis().left().x * p.x + entity->state()->axis().left().y * p.y + entity->state()->axis().left().z * p.z; if (fabs(side) > 0.00005f) { cosangle = math::dotproduct(p, entity->state()->axis().up()); angle = acos(cosangle) * 180.0f / M_PI; if (fabs(cosangle) < 0.99995f) { angle = math::sgnf(side) * angle * seconds / (core::game()->serverframetime() - core::game()->clientframetime()); entity->state()->state_axis.change_roll(angle); } } } } } } float GameInterface::timeoffset() { float d = game_serverframetime - game_previousframetime; if (d <= 0) return 0; float t = game_clientframetime - game_previousframetime; return t/d; } }