void OnSolver::CreateModel(){ // delete old model DeleteModel(); // clear system body IDs (primer for traversal algorithm) system->ClearBodyIDs(); // error check for inertial frame Body* sysbasebody = system->bodies.GetHeadElement()->value; if( sysbasebody->GetType() != INERTIALFRAME ){ cerr << "ERROR: inertial frame not at head of bodies list" << endl; exit(1); } // setup the O(n) spanning tree numbodies = inertialframe.RecursiveSetup( (InertialFrame*) sysbasebody ); if(!numbodies){ cerr << "ERROR: unable to create O(n) model" << endl; exit(1); } bodyarray = new OnBody* [numbodies]; CreateTopologyArray(0,&inertialframe); CreateStateMatrixMaps(); }
bool Tweaker::Update() { if(s_isInit && s_enabled) { if(s_monitorMode && Pi::player) { Body* nt = Pi::player->GetNavTarget(); Body* ct = Pi::player->GetCombatTarget(); //Body* target = nt != nullptr ? nt : ct; // Prioritize navtarget over combat target Body* target = ct != nullptr ? ct : nt; // Prioritize combattarget since we only care about ships now // Check if target changed if(target != s_monitorCurrentTarget) { // Target changed. // Remove active monitor if necessary if( s_activeMonitor && target && s_monitorCurrentTarget && target->GetType() == s_monitorCurrentTarget->GetType()) { // Keep the same monitor } else { // Change monitor TwDeleteBar(s_activeMonitor); s_activeMonitor = nullptr; if(target) { // Only add new monitor if there is a valid target s_activeMonitor = CreateMonitor(target); } } s_monitorCurrentTarget = target; } // Updated monitors UpdateMonitor(target); } return true; } else { return false; } }
Game::Game(const SystemPath &path, double time) : m_galaxy(GalaxyGenerator::Create()), m_time(time), m_state(STATE_NORMAL), m_wantHyperspace(false), m_timeAccel(TIMEACCEL_1X), m_requestedTimeAccel(TIMEACCEL_1X), m_forceTimeAccel(false) { // Now that we have a Galaxy, check the starting location if (!path.IsBodyPath()) throw InvalidGameStartLocation("SystemPath is not a body path"); RefCountedPtr<const Sector> s = m_galaxy->GetSector(path); if (size_t(path.systemIndex) >= s->m_systems.size()) { char buf[128]; std::sprintf(buf, "System %u in sector <%d,%d,%d> does not exist", unsigned(path.systemIndex), int(path.sectorX), int(path.sectorY), int(path.sectorZ)); throw InvalidGameStartLocation(std::string(buf)); } RefCountedPtr<StarSystem> sys = m_galaxy->GetStarSystem(path); if (path.bodyIndex >= sys->GetNumBodies()) { char buf[256]; std::sprintf(buf, "Body %d in system <%d,%d,%d : %d ('%s')> does not exist", unsigned(path.bodyIndex), int(path.sectorX), int(path.sectorY), int(path.sectorZ), unsigned(path.systemIndex), sys->GetName().c_str()); throw InvalidGameStartLocation(std::string(buf)); } m_space.reset(new Space(this, m_galaxy, path)); Body *b = m_space->FindBodyForPath(&path); assert(b); m_player.reset(new Player("kanara")); m_space->AddBody(m_player.get()); m_player->SetFrame(b->GetFrame()); if (b->GetType() == Object::SPACESTATION) { m_player->SetDockedWith(static_cast<SpaceStation*>(b), 0); } else { const SystemBody *sbody = b->GetSystemBody(); m_player->SetPosition(vector3d(0, 1.5*sbody->GetRadius(), 0)); m_player->SetVelocity(vector3d(0,0,0)); } Polit::Init(m_galaxy); CreateViews(); EmitPauseState(IsPaused()); }
static int l_body_is_hyperspace_cloud(lua_State *l) { Body *body = LuaObject<Body>::CheckFromLua(1); LuaPush<bool>(l, body->GetType() == Object::Type::HYPERSPACECLOUD); return 1; }
static int l_body_is_ship(lua_State *l) { Body *body = LuaObject<Body>::CheckFromLua(1); LuaPush<bool>(l, body->GetType() == Object::Type::SHIP); return 1; }
static int l_body_is_cargo_container(lua_State *l) { Body *body = LuaObject<Body>::CheckFromLua(1); LuaPush<bool>(l, body->GetType() == Object::Type::CARGOBODY); return 1; }
static int l_body_is_missile(lua_State *l) { Body *body = LuaObject<Body>::CheckFromLua(1); LuaPush<bool>(l, body->GetType() == Object::Type::MISSILE); return 1; }
void Island::Solve(Profile* profile, const PTimeStep& step, const glm::vec2& gravity, bool allowSleep) { Time timer; real32 h = step.delta; // Integrate velocities and apply damping. Initialize the body state. for (s32 i = 0; i < m_bodyCount; ++i) { Body* b = m_bodies[i]; glm::vec2 c = b->m_sweep.c; real32 a = b->m_sweep.a; glm::vec2 v = b->m_linearVelocity; real32 w = b->m_angularVelocity; // Store positions for continuous collision. b->m_sweep.c0 = b->m_sweep.c; b->m_sweep.a0 = b->m_sweep.a; if (b->m_type == dynamicBody) { // Integrate velocities. v += h * (b->m_gravityScale * gravity + b->m_invMass * b->m_force); w += h * b->m_invI * b->m_torque; // Apply damping. // ODE: dv/dt + c * v = 0 // Solution: v(t) = v0 * exp(-c * t) // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt) // v2 = exp(-c * dt) * v1 // Pade approximation: // v2 = v1 * 1 / (1 + c * dt) v *= 1.0f / (1.0f + h * b->m_linearDamping); w *= 1.0f / (1.0f + h * b->m_angularDamping); } m_positions[i].c = c; m_positions[i].a = a; m_velocities[i].v = v; m_velocities[i].w = w; } auto captureTimer = Services::getPlatform()->getTime(); // Solver data SolverData solverData; solverData.step = step; solverData.positions = m_positions; solverData.velocities = m_velocities; // Initialize velocity constraints. ContactSolverDef contactSolverDef; contactSolverDef.step = step; contactSolverDef.contacts = m_contacts; contactSolverDef.count = m_contactCount; contactSolverDef.positions = m_positions; contactSolverDef.velocities = m_velocities; contactSolverDef.allocator = m_allocator; ContactSolver contactSolver(&contactSolverDef); contactSolver.InitializeVelocityConstraints(); if (step.warmStarting) { contactSolver.WarmStart(); } for (s32 i = 0; i < m_jointCount; ++i) { m_joints[i]->InitVelocityConstraints(solverData); } profile->solveInit = Services::getPlatform()->getTime()-captureTimer; // Solve velocity constraints captureTimer = Services::getPlatform()->getTime(); for (s32 i = 0; i < step.velocityIterations; ++i) { for (s32 j = 0; j < m_jointCount; ++j) { m_joints[j]->SolveVelocityConstraints(solverData); } contactSolver.SolveVelocityConstraints(); } // Store impulses for warm starting contactSolver.StoreImpulses(); profile->solveVelocity = Services::getPlatform()->getTime()-captureTimer; // Integrate positions for (s32 i = 0; i < m_bodyCount; ++i) { glm::vec2 c = m_positions[i].c; real32 a = m_positions[i].a; glm::vec2 v = m_velocities[i].v; real32 w = m_velocities[i].w; // Check for large velocities glm::vec2 translation = h * v; if (glm::dot(translation, translation) > maxTranslationSquared) { real32 ratio = maxTranslation / translation.length(); v *= ratio; } real32 rotation = h * w; if (rotation * rotation > maxRotationSquared) { real32 ratio = maxRotation / glm::abs(rotation); w *= ratio; } // Integrate c += h * v; a += h * w; m_positions[i].c = c; m_positions[i].a = a; m_velocities[i].v = v; m_velocities[i].w = w; } // Solve position constraints captureTimer = Services::getPlatform()->getTime(); bool positionSolved = false; for (s32 i = 0; i < step.positionIterations; ++i) { bool contactsOkay = contactSolver.SolvePositionConstraints(); bool jointsOkay = true; for (s32 i = 0; i < m_jointCount; ++i) { bool jointOkay = m_joints[i]->SolvePositionConstraints(solverData); jointsOkay = jointsOkay && jointOkay; } if (contactsOkay && jointsOkay) { // Exit early if the position errors are small. positionSolved = true; break; } } // Copy state buffers back to the bodies for (s32 i = 0; i < m_bodyCount; ++i) { Body* body = m_bodies[i]; body->m_sweep.c = m_positions[i].c; body->m_sweep.a = m_positions[i].a; body->m_linearVelocity = m_velocities[i].v; body->m_angularVelocity = m_velocities[i].w; body->SynchronizeTransform2D(); } profile->solvePosition = Services::getPlatform()->getTime()-captureTimer; Report(contactSolver.m_velocityConstraints); if (allowSleep) { real32 minSleepTime = FLT_MAX; const real32 linTolSqr = linearSleepTolerance * linearSleepTolerance; const real32 angTolSqr = angularSleepTolerance * angularSleepTolerance; for (s32 i = 0; i < m_bodyCount; ++i) { Body* b = m_bodies[i]; if (b->GetType() == staticBody) { continue; } if ((b->m_flags & Body::autoSleepFlag) == 0 || b->m_angularVelocity * b->m_angularVelocity > angTolSqr || glm::dot(b->m_linearVelocity, b->m_linearVelocity) > linTolSqr) { b->m_sleepTime = 0.0f; minSleepTime = 0.0f; } else { b->m_sleepTime += h; minSleepTime = glm::min(minSleepTime, b->m_sleepTime); } } if (minSleepTime >= timeToSleep && positionSolved) { for (s32 i = 0; i < m_bodyCount; ++i) { Body* b = m_bodies[i]; b->SetAwake(false); } } } }
static int l_body_is_more_important_than(lua_State *l) { Body *body = LuaObject<Body>::CheckFromLua(1); Body *other = LuaObject<Body>::CheckFromLua(2); // compare body and other // push true if body is "more important" than other // the most important body is shown on the hud and // bodies are sorted by importance in menus if(body == other) { LuaPush<bool>(l, false); return 1; } Object::Type a = body->GetType(); const SystemBody *sb_a = body->GetSystemBody(); bool a_gas_giant = sb_a && sb_a->GetSuperType() == SystemBody::SUPERTYPE_GAS_GIANT; bool a_planet = sb_a && sb_a->IsPlanet(); bool a_moon = sb_a && sb_a->IsMoon(); Object::Type b = other->GetType(); const SystemBody *sb_b = other->GetSystemBody(); bool b_gas_giant = sb_b && sb_b->GetSuperType() == SystemBody::SUPERTYPE_GAS_GIANT; bool b_planet = sb_b && sb_b->IsPlanet(); bool b_moon = sb_b && sb_b->IsMoon(); bool result = false; // if type is the same, just sort alphabetically // planets are different, because moons are // less important (but don't have their own type) if(a == b && a != Object::Type::PLANET) result = body->GetLabel() < other->GetLabel(); // a star is larger than any other object else if(a == Object::Type::STAR) result = true; // any (non-star) object is smaller than a star else if(b == Object::Type::STAR) result = false; // a gas giant is larger than anything but a star, // but remember to keep total order in mind: if both are // gas giants, order alphabetically else if(a_gas_giant) result = !b_gas_giant || body->GetLabel() < other->GetLabel(); // any (non-star, non-gas giant) object is smaller than a gas giant else if(b_gas_giant) result = false; // between two planets or moons, alphabetic else if(a_planet && b_planet) result = body->GetLabel() < other->GetLabel(); else if(a_moon && b_moon) result = body->GetLabel() < other->GetLabel(); // a planet is larger than any non-planet else if(a_planet) result = true; // a non-planet is smaller than any planet else if(b_planet) result = false; // a moon is larger than any non-moon else if(a_moon) result = true; // a non-moon is smaller than any moon else if(b_moon) result = false; // spacestation > city > ship > hyperspace cloud > cargo body > missile > projectile else if(a == Object::Type::SPACESTATION) result = true; else if(b == Object::Type::SPACESTATION) result = false; else if(a == Object::Type::CITYONPLANET) result = true; else if(b == Object::Type::CITYONPLANET) result = false; else if(a == Object::Type::SHIP) result = true; else if(b == Object::Type::SHIP) result = false; else if(a == Object::Type::HYPERSPACECLOUD) result = true; else if(b == Object::Type::HYPERSPACECLOUD) result = false; else if(a == Object::Type::CARGOBODY) result = true; else if(b == Object::Type::CARGOBODY) result = false; else if(a == Object::Type::MISSILE) result = true; else if(b == Object::Type::MISSILE) result = false; else if(a == Object::Type::PROJECTILE) result = true; else if(b == Object::Type::PROJECTILE) result = false; else Error("don't know how to compare %i and %i\n", a, b); LuaPush<bool>(l, result); return 1; }
const char *LuaSerializer::unpickle(lua_State *l, const char *pos) { LUA_DEBUG_START(l); char type = *pos++; switch (type) { case 'f': { char *end; double f = strtod(pos, &end); if (pos == end) throw SavedGameCorruptException(); lua_pushnumber(l, f); pos = end+1; // skip newline break; } case 'b': { if (*pos != '0' && *pos != '1') throw SavedGameCorruptException(); bool b = (*pos == '0') ? false : true; lua_pushboolean(l, b); pos++; break; } case 's': { char *end; int len = strtol(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); end++; // skip newline lua_pushlstring(l, end, len); pos = end + len; break; } case 't': { lua_newtable(l); lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs"); pos = unpickle(l, pos); lua_pushvalue(l, -3); lua_rawset(l, -3); lua_pop(l, 1); while (*pos != 'n') { pos = unpickle(l, pos); pos = unpickle(l, pos); lua_rawset(l, -3); } pos++; break; } case 'r': { pos = unpickle(l, pos); lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs"); lua_pushvalue(l, -2); lua_rawget(l, -2); if (lua_isnil(l, -1)) throw SavedGameCorruptException(); lua_insert(l, -3); lua_pop(l, 2); break; } case 'u': { const char *end = strchr(pos, '\n'); if (!end) throw SavedGameCorruptException(); int len = end - pos; end++; // skip newline if (len == 10 && strncmp(pos, "SystemPath", 10) == 0) { pos = end; Sint32 sectorX = strtol(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline Sint32 sectorY = strtol(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline Sint32 sectorZ = strtol(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline Uint32 systemNum = strtoul(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline Uint32 sbodyId = strtoul(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline SystemPath *sbp = new SystemPath(sectorX, sectorY, sectorZ, systemNum, sbodyId); LuaSystemPath::PushToLuaGC(sbp); break; } if (len == 4 && strncmp(pos, "Body", 4) == 0) { pos = end; Uint32 n = strtoul(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline Body *body = Pi::game->GetSpace()->GetBodyByIndex(n); if (pos == end) throw SavedGameCorruptException(); switch (body->GetType()) { case Object::BODY: LuaBody::PushToLua(body); break; case Object::SHIP: LuaShip::PushToLua(dynamic_cast<Ship*>(body)); break; case Object::SPACESTATION: LuaSpaceStation::PushToLua(dynamic_cast<SpaceStation*>(body)); break; case Object::PLANET: LuaPlanet::PushToLua(dynamic_cast<Planet*>(body)); break; case Object::STAR: LuaStar::PushToLua(dynamic_cast<Star*>(body)); break; case Object::PLAYER: LuaPlayer::PushToLua(dynamic_cast<Player*>(body)); break; default: throw SavedGameCorruptException(); } break; } throw SavedGameCorruptException(); } case 'o': { const char *end = strchr(pos, '\n'); if (!end) throw SavedGameCorruptException(); int len = end - pos; end++; // skip newline const char *cl = pos; // unpickle the object, and insert it beneath the method table value pos = unpickle(l, end); // get _G[typename] lua_rawgeti(l, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); lua_pushlstring(l, cl, len); lua_gettable(l, -2); lua_remove(l, -2); if (lua_isnil(l, -1)) { lua_pop(l, 2); break; } lua_getfield(l, -1, "Unserialize"); if (lua_isnil(l, -1)) { lua_pushlstring(l, cl, len); luaL_error(l, "No Unserialize method found for class '%s'\n", lua_tostring(l, -1)); } lua_insert(l, -3); lua_pop(l, 1); pi_lua_protected_call(l, 1, 1); break; } default: throw SavedGameCorruptException(); } LUA_DEBUG_END(l, 1); return pos; }
const char *LuaSerializer::unpickle(lua_State *l, const char *pos) { LUA_DEBUG_START(l); char type = *pos++; switch (type) { case 'f': { char *end; double f = strtod(pos, &end); if (pos == end) throw SavedGameCorruptException(); lua_pushnumber(l, f); pos = end+1; // skip newline break; } case 'b': { if (*pos != '0' && *pos != '1') throw SavedGameCorruptException(); bool b = (*pos == '0') ? false : true; lua_pushboolean(l, b); pos++; break; } case 's': { char *end; int len = strtod(pos, &end); if (pos == end) throw SavedGameCorruptException(); end++; // skip newline lua_pushlstring(l, end, len); pos = end + len; break; } case 't': { lua_newtable(l); while (*pos != 'n') { pos = unpickle(l, pos); pos = unpickle(l, pos); lua_rawset(l, -3); } pos++; break; } case 'u': { const char *end = strchr(pos, '\n'); if (!end) throw SavedGameCorruptException(); int len = end - pos; end++; // skip newline if (len == 10 && strncmp(pos, "SystemPath", 10) == 0) { pos = end; Sint32 sectorX = strtol(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline Sint32 sectorY = strtol(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline Sint32 sectorZ = strtol(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline Sint32 systemNum = strtol(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline Sint32 sbodyId = strtol(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline SystemPath *sbp = new SystemPath(sectorX, sectorY, sectorZ, systemNum, sbodyId); LuaSystemPath::PushToLuaGC(sbp); break; } if (len == 4 && strncmp(pos, "Body", 4) == 0) { pos = end; int n = strtol(pos, const_cast<char**>(&end), 0); if (pos == end) throw SavedGameCorruptException(); pos = end+1; // skip newline Body *body = Serializer::LookupBody(n); if (pos == end) throw SavedGameCorruptException(); switch (body->GetType()) { case Object::BODY: LuaBody::PushToLua(body); break; case Object::SHIP: LuaShip::PushToLua(dynamic_cast<Ship*>(body)); break; case Object::SPACESTATION: LuaSpaceStation::PushToLua(dynamic_cast<SpaceStation*>(body)); break; case Object::PLANET: LuaPlanet::PushToLua(dynamic_cast<Planet*>(body)); break; case Object::STAR: LuaStar::PushToLua(dynamic_cast<Star*>(body)); break; case Object::PLAYER: LuaPlayer::PushToLua(dynamic_cast<Player*>(body)); break; default: throw SavedGameCorruptException(); } break; } throw SavedGameCorruptException(); } default: throw SavedGameCorruptException(); } LUA_DEBUG_END(l, 1); return pos; }