/** * @brief Selects the system in the map. * * @param sys System to select. */ void map_select( StarSystem *sys ) { unsigned int wid; int i; wid = window_get(MAP_WDWNAME); if (sys == NULL) { map_selectCur(); } else { map_selected = sys - systems_stack; /* select the current system and make a path to it */ if (map_path) free(map_path); map_path = map_getJumpPath( &map_npath, cur_system->name, sys->name, 0 ); if (map_npath==0) hyperspace_target = -1; else { /* see if it is a valid hyperspace target */ for (i=0; i<cur_system->njumps; i++) { if (map_path[0]==system_getIndex(cur_system->jumps[i])) { planet_target = -1; /* override planet_target */ hyperspace_target = i; break; } } } } map_update(wid); }
/** * @brief Updates the map after a jump. */ void map_jump (void) { int j; /* set selected system to self */ map_selectCur(); map_xpos = cur_system->pos.x; map_ypos = cur_system->pos.y; /* update path if set */ if (map_path != NULL) { map_npath--; if (map_npath == 0) { /* path is empty */ free (map_path); map_path = NULL; planet_target = -1; hyperspace_target = -1; } else { /* get rid of bottom of the path */ memmove( &map_path[0], &map_path[1], sizeof(StarSystem*) * map_npath ); map_path = realloc( map_path, sizeof(StarSystem*) * map_npath ); /* set the next jump to be to the next in path */ for (j=0; j<cur_system->njumps; j++) { if (map_path[0]==system_getIndex(cur_system->jumps[j])) { planet_target = -1; /* override planet_target */ hyperspace_target = j; break; } } } } }
/** * @brief Updates the mission list. * @param wid Window of the mission computer. * @param str Unused. */ static void misn_update( unsigned int wid, char* str ) { (void) str; char *active_misn; Mission* misn; char txt[256], *buf; /* Clear computer markers. */ space_clearComputerMarkers(); /* Update date stuff. */ buf = ntime_pretty( 0, 2 ); snprintf( txt, sizeof(txt), "%s\n%d Tons", buf, player.p->cargo_free ); free(buf); window_modifyText( wid, "txtDate", txt ); active_misn = toolkit_getList( wid, "lstMission" ); if (strcmp(active_misn,"No Missions")==0) { window_modifyText( wid, "txtReward", "None" ); window_modifyText( wid, "txtDesc", "There are no missions available here." ); window_disableButton( wid, "btnAcceptMission" ); return; } misn = &mission_computer[ toolkit_getListPos( wid, "lstMission" ) ]; mission_sysComputerMark( misn ); if (misn->markers != NULL) map_center( system_getIndex( misn->markers[0].sys )->name ); window_modifyText( wid, "txtReward", misn->reward ); window_modifyText( wid, "txtDesc", misn->desc ); window_enableButton( wid, "btnAcceptMission" ); }
/** * @brief Updates the mission menu mission information based on what's selected. * @param str Unused. */ static void mission_menu_update( unsigned int wid, char* str ) { (void)str; char *active_misn; Mission* misn; active_misn = toolkit_getList( wid, "lstMission" ); if ((active_misn==NULL) || (strcmp(active_misn,"No Missions")==0)) { window_modifyText( wid, "txtReward", "None" ); window_modifyText( wid, "txtDesc", "You currently have no active missions." ); window_disableButton( wid, "btnAbortMission" ); return; } /* Modify the text. */ misn = &player_missions[ toolkit_getListPos(wid, "lstMission" ) ]; window_modifyText( wid, "txtReward", misn->reward ); window_modifyText( wid, "txtDesc", misn->desc ); window_enableButton( wid, "btnAbortMission" ); /* Select the system. */ if (misn->markers != NULL) map_center( system_getIndex( misn->markers[0].sys )->name ); }
/** * @brief Back-end for luaL_validjump. * * @param L Lua state to get jump from. * @param ind Index to check. * @param[out] offset How many Lua arguments were passed. * @param[out] sys System the jump exists in. * @return Jump found at the index in the state. * * @sa luaL_validjump */ static JumpPoint* luaL_validjumpSystem( lua_State *L, int ind, int *offset, StarSystem **outsys ) { LuaJump *lj; JumpPoint *jp; StarSystem *a, *b; /* Defaults. */ jp = NULL; a = NULL; b = NULL; if (lua_isjump(L, ind)) { lj = luaL_checkjump(L, ind); a = system_getIndex( lj->srcid ); b = system_getIndex( lj->destid ); if (offset != NULL) *offset = 1; } else if (lua_gettop(L) > 1) { if (lua_isstring(L, ind)) a = system_get( lua_tostring( L, ind )); else if (lua_issystem(L, ind)) a = system_getIndex( lua_tosystem(L, ind) ); if (lua_isstring(L, ind+1)) b = system_get( lua_tostring( L, ind+1 )); else if (lua_issystem(L, ind+1)) b = system_getIndex( lua_tosystem(L, ind+1) ); if (offset != NULL) *offset = 2; } else { luaL_typerror(L, ind, JUMP_METATABLE); return NULL; } if (b != NULL && a != NULL) jp = jump_getTarget( b, a ); if (jp == NULL) NLUA_ERROR(L, "Jump is invalid"); if (outsys != NULL) *outsys = a; return jp; }
/** * @brief Map custom widget mouse handling. * * @param wid Window sending events. * @param event Event window is sending. * @param mx Mouse X position. * @param my Mouse Y position. * @param w Width of the widget. * @param h Height of the widget. */ static void map_mouse( unsigned int wid, SDL_Event* event, double mx, double my, double w, double h ) { (void) wid; int i; double x,y, t; StarSystem *sys; t = 15.*15.; /* threshold */ mx -= w/2 - map_xpos; my -= h/2 - map_ypos; switch (event->type) { case SDL_MOUSEBUTTONDOWN: /* zooming */ if (event->button.button == SDL_BUTTON_WHEELUP) map_buttonZoom( 0, "btnZoomIn" ); else if (event->button.button == SDL_BUTTON_WHEELDOWN) map_buttonZoom( 0, "btnZoomOut" ); /* selecting star system */ else { for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* must be reachable */ if (!space_sysReachable(sys)) continue; /* get position */ x = sys->pos.x * map_zoom; y = sys->pos.y * map_zoom; if ((pow2(mx-x)+pow2(my-y)) < t) { map_select( sys ); break; } } map_drag = 1; } break; case SDL_MOUSEBUTTONUP: if (map_drag) map_drag = 0; break; case SDL_MOUSEMOTION: if (map_drag) { /* axis is inverted */ map_xpos -= event->motion.xrel; map_ypos += event->motion.yrel; } break; } }
/** * @brief Gets a jump. * * Possible values of params: <br/> * - string : Gets the jump by system name. <br/> * - system : Gets the jump by system. <br/> * * @usage j,r = jump.get( "Ogat", "Goddard" ) -- Returns the Ogat to Goddard and Goddard to Ogat jumps. * @luaparam param See description. * @luareturn Returns the jump and the inverse (where it exits). * @luafunc get( param ) */ static int jumpL_get( lua_State *L ) { LuaJump lj; StarSystem *a, *b; /* Defaults. */ a = NULL; b = NULL; if (lua_gettop(L) > 1) { if (lua_isstring(L, 1)) a = system_get( lua_tostring(L, 1)); else if (lua_issystem(L, 1)) a = system_getIndex( lua_tosystem(L, 1) ); if (lua_isstring(L, 2)) b = system_get( lua_tostring(L, 2)); else if (lua_issystem(L, 2)) b = system_getIndex( lua_tosystem(L, 2) ); if ((a == NULL) || (b == NULL)) { NLUA_ERROR(L, "No matching jump points found."); return 0; } if (jump_getTarget(b, a) != NULL) { lj.srcid = a->id; lj.destid = b->id; lua_pushjump(L, lj); /* The inverse. If it doesn't exist, there are bigger problems. */ lj.srcid = b->id; lj.destid = a->id; lua_pushjump(L, lj); return 2; } } else NLUA_INVALID_PARAMETER(L); return 0; }
/** * @brief Gets system at index raising an error if type doesn't match. * * @param L Lua state to get system from. * @param ind Index position of system. * @return The System at ind. */ StarSystem* luaL_validsystem( lua_State *L, int ind ) { LuaSystem *ls; StarSystem *s; ls = luaL_checksystem( L, ind ); s = system_getIndex( ls->id ); if (s == NULL) { NLUA_ERROR( L, "System is invalid" ); return NULL; } return s; }
/** * @brief Activates a claim on a system. * * @param claim Claim to activate. */ void claim_activate( SysClaim_t *claim ) { int i; /* Make sure something to activate. */ if (claim->ids == NULL) return; /* Add flags. */ for (i=0; i<array_size(claim->ids); i++) sys_setFlag( system_getIndex(claim->ids[i]), SYSTEM_CLAIMED ); }
/** * @brief Check to see if radius is mapped (known). * * @param targ_sys Name of the system in the center of the "known" circle. * @param r Radius to check (in jumps) if is mapped. * @return 1 if circle was already mapped, 0 if it wasn't. */ int map_isMapped( const char* targ_sys, int r ) { int i, dep, ret; StarSystem *sys, *jsys; SysNode *closed, *open, *cur, *neighbour; A_gc = NULL; open = closed = NULL; if (targ_sys == NULL) sys = cur_system; else sys = system_get( targ_sys ); open = A_newNode( sys, NULL ); open->r = 0; ret = 1; while ((cur = A_lowest(open)) != NULL) { /* Check if system is known. */ sys = cur->sys; dep = cur->r; if (!sys_isFlag(sys,SYSTEM_KNOWN)) { ret = 0; break; } /* We close the current system. */ open = A_rm( open, sys ); closed = A_add( closed, cur ); /* System is past the limit. */ if (dep+1 > r) continue; /* check it's jumps */ for (i=0; i<sys->njumps; i++) { jsys = system_getIndex( sys->jumps[i] ); /* SYstem has already been parsed. */ if (A_in(closed,jsys) != NULL) continue; /* create new node and such */ neighbour = A_newNode( jsys, NULL ); neighbour->r = dep+1; open = A_add( open, neighbour ); } } A_freeList(A_gc); return ret; }
/** * @brief Checks to see if a system name is already in use. * * @return 1 if system name is already in use. */ static int uniedit_checkName( char *name ) { int i; /* Avoid name collisions. */ for (i=0; i<systems_nstack; i++) { if (strcmp(name, system_getIndex(i)->name)==0) { dialogue_alert( "The Star System '%s' already exists!", name ); return 1; } } return 0; }
/** * @brief Marks the system of the computer mission to reflect where it will head to. * * Does not modify other markers. * * @param misn Mission to mark. */ void mission_sysComputerMark( Mission* misn ) { StarSystem *sys; int i, n; /* Clear markers. */ space_clearComputerMarkers(); /* Set all the markers. */ if (misn->markers != NULL) { n = array_size(misn->markers); for (i=0; i<n; i++) { sys = system_getIndex( misn->markers[i].sys ); sys_setFlag( sys,SYSTEM_CMARKED ); } } }
/** * @brief Tests to see if a system claim would have collisions. * * @param claim System to test. * @return 0 if no collision found, 1 if a collision was found. */ int claim_test( SysClaim_t *claim ) { int claimed; int i; /* Make sure something to activate. */ if (claim->ids == NULL) return 0; /* Check flags. */ for (i=0; i<array_size(claim->ids); i++) { claimed = sys_isFlag( system_getIndex(claim->ids[i]), SYSTEM_CLAIMED ); if (claimed) return 1; } return 0; }
/** * @brief Saves all the systems in a claim in XML. * * Use between xmlw_startElem and xmlw_endElem. * * @param writer XML Writer to use. * @param claim Claim to save. */ int claim_xmlSave( xmlTextWriterPtr writer, SysClaim_t *claim ) { int i; StarSystem *sys; if ((claim == NULL) || (claim->ids == NULL)) return 0; for (i=0; i<array_size(claim->ids); i++) { sys = system_getIndex( claim->ids[i] ); if (sys != NULL) { xmlw_elem( writer, "sys", "%s", sys->name ); } else WARN("System Claim has inexistent system."); } return 0; }
/** * @brief Marks maps around a radius of currenty system as known. * * @param targ_sys System at center of the "known" circle. * @param r Radius (in jumps) to mark as known. * @return 0 on success. */ int map_map( const char* targ_sys, int r ) { int i, dep; StarSystem *sys, *jsys; SysNode *closed, *open, *cur, *neighbour; A_gc = NULL; open = closed = NULL; if (targ_sys == NULL) sys = cur_system; else sys = system_get( targ_sys ); sys_setFlag(sys,SYSTEM_KNOWN); open = A_newNode( sys, NULL ); open->r = 0; while ((cur = A_lowest(open)) != NULL) { /* mark system as known and go to next */ sys = cur->sys; dep = cur->r; sys_setFlag(sys,SYSTEM_KNOWN); open = A_rm( open, sys ); closed = A_add( closed, cur ); /* check it's jumps */ for (i=0; i<sys->njumps; i++) { jsys = system_getIndex( cur->sys->jumps[i] ); /* System has already been parsed or is too deep */ if ((A_in(closed,jsys) != NULL) || (dep+1 > r)) continue; /* create new node and such */ neighbour = A_newNode( jsys, NULL ); neighbour->r = dep+1; open = A_add( open, neighbour ); } } A_freeList(A_gc); return 0; }
/** * @brief Gets system (or system name) at index raising an error if type doesn't match. * * @param L Lua state to get system from. * @param ind Index position of system. * @return The System at ind. */ StarSystem* luaL_validsystem( lua_State *L, int ind ) { LuaSystem *ls; StarSystem *s; if (lua_issystem(L, ind)) { ls = luaL_checksystem(L, ind); s = system_getIndex( ls->id ); } else if (lua_isstring(L, ind)) s = system_get( lua_tostring(L, ind) ); else { luaL_typerror(L, ind, FACTION_METATABLE); return NULL; } if (s == NULL) NLUA_ERROR(L, "System is invalid"); return s; }
/** * @brief Shows a map at x, y (relative to wid) with size w,h. * * @param wid Window to show map on. * @param x X position to put map at. * @param y Y position to put map at. * @param w Width of map to open. * @param h Height of map to open. * @param zoom Default zoom to use. */ void map_show( int wid, int x, int y, int w, int h, double zoom ) { StarSystem *sys; /* mark systems as needed */ mission_sysMark(); /* Set position to focus on current system. */ map_xpos = cur_system->pos.x * zoom; map_ypos = cur_system->pos.y * zoom; /* Set zoom. */ map_setZoom(zoom); /* Make sure selected is sane. */ sys = system_getIndex( map_selected ); if (!(sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED)) && !sys_isKnown(sys) && !space_sysReachable(sys)) map_selectCur(); window_addCust( wid, x, y, w, h, "cstMap", 1, map_render, map_mouse, NULL ); }
/** * @brief System editor custom widget mouse handling. */ static void uniedit_mouse( unsigned int wid, SDL_Event* event, double mx, double my, double w, double h, void *data ) { (void) wid; (void) data; int i; double x,y, t; StarSystem *sys; SDLMod mod; t = 15.*15.; /* threshold */ /* Handle modifiers. */ mod = SDL_GetModState(); switch (event->type) { case SDL_MOUSEBUTTONDOWN: /* Must be in bounds. */ if ((mx < 0.) || (mx > w) || (my < 0.) || (my > h)) return; /* Zooming */ if (event->button.button == SDL_BUTTON_WHEELUP) uniedit_buttonZoom( 0, "btnZoomIn" ); else if (event->button.button == SDL_BUTTON_WHEELDOWN) uniedit_buttonZoom( 0, "btnZoomOut" ); /* selecting star system */ else { mx -= w/2 - uniedit_xpos; my -= h/2 - uniedit_ypos; if (uniedit_mode == UNIEDIT_NEWSYS) { uniedit_newSys( mx, my ); uniedit_mode = UNIEDIT_DEFAULT; return; } for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* get position */ x = sys->pos.x * uniedit_zoom; y = sys->pos.y * uniedit_zoom; if ((pow2(mx-x)+pow2(my-y)) < t) { /* Try to find in selected systems - begin drag move. */ for (i=0; i<uniedit_nsys; i++) { /* Must match. */ if (uniedit_sys[i] != sys) continue; /* Detect double click to open system. */ if ((SDL_GetTicks() - uniedit_dragTime < UNIEDIT_DRAG_THRESHOLD*2) && (uniedit_moved < UNIEDIT_MOVE_THRESHOLD)) { if (uniedit_nsys == 1) { sysedit_open( uniedit_sys[0] ); return; } } /* Handle normal click. */ if (uniedit_mode == UNIEDIT_DEFAULT) { uniedit_dragSys = 1; uniedit_tsys = sys; /* Check modifier. */ if (mod & (KMOD_LCTRL | KMOD_RCTRL)) uniedit_tadd = 0; else uniedit_tadd = -1; uniedit_dragTime = SDL_GetTicks(); uniedit_moved = 0; } return; } if (uniedit_mode == UNIEDIT_DEFAULT) { /* Add the system if not selected. */ if (mod & (KMOD_LCTRL | KMOD_RCTRL)) uniedit_selectAdd( sys ); else { uniedit_deselect(); uniedit_selectAdd( sys ); } uniedit_tsys = NULL; /* Start dragging anyway. */ uniedit_dragSys = 1; uniedit_dragTime = SDL_GetTicks(); uniedit_moved = 0; } else if (uniedit_mode == UNIEDIT_JUMP) { uniedit_toggleJump( sys ); uniedit_mode = UNIEDIT_DEFAULT; } return; } } /* Start dragging. */ if ((uniedit_mode == UNIEDIT_DEFAULT) && !(mod & (KMOD_LCTRL | KMOD_RCTRL))) { uniedit_drag = 1; uniedit_dragTime = SDL_GetTicks(); uniedit_moved = 0; uniedit_tsys = NULL; } return; } break; case SDL_MOUSEBUTTONUP: if (uniedit_drag) { if ((SDL_GetTicks() - uniedit_dragTime < UNIEDIT_DRAG_THRESHOLD) && (uniedit_moved < UNIEDIT_MOVE_THRESHOLD)) { if (uniedit_tsys == NULL) uniedit_deselect(); else uniedit_selectAdd( uniedit_tsys ); } uniedit_drag = 0; } if (uniedit_dragSys) { if ((SDL_GetTicks() - uniedit_dragTime < UNIEDIT_DRAG_THRESHOLD) && (uniedit_moved < UNIEDIT_MOVE_THRESHOLD) && (uniedit_tsys != NULL)) { if (uniedit_tadd == 0) uniedit_selectRm( uniedit_tsys ); else { uniedit_deselect(); uniedit_selectAdd( uniedit_tsys ); } } uniedit_dragSys = 0; for (i=0; i<uniedit_nsys; i++) { dsys_saveSystem(uniedit_sys[i]); } } break; case SDL_MOUSEMOTION: /* Update mouse positions. */ uniedit_mx = mx; uniedit_my = my; /* Handle dragging. */ if (uniedit_drag) { /* axis is inverted */ uniedit_xpos -= event->motion.xrel; uniedit_ypos += event->motion.yrel; /* Update mouse movement. */ uniedit_moved += ABS( event->motion.xrel ) + ABS( event->motion.yrel ); } else if (uniedit_dragSys && (uniedit_nsys > 0)) { if ((uniedit_moved > UNIEDIT_MOVE_THRESHOLD) || (SDL_GetTicks() - uniedit_dragTime > UNIEDIT_DRAG_THRESHOLD)) { for (i=0; i<uniedit_nsys; i++) { uniedit_sys[i]->pos.x += ((double)event->motion.xrel) / uniedit_zoom; uniedit_sys[i]->pos.y -= ((double)event->motion.yrel) / uniedit_zoom; } } /* Update mouse movement. */ uniedit_moved += ABS( event->motion.xrel ) + ABS( event->motion.yrel ); } break; } }
/** * @brief Persists the node on the top of the stack and pops it. * * @param L Lua state with node to persist on top of the stack. * @param writer XML Writer to use. * @param Are we parsing a node in a table? Avoids checking for extra __save. * @return 0 on success. */ static int nxml_persistDataNode( lua_State *L, xmlTextWriterPtr writer, int intable ) { int ret, b; LuaPlanet *p; LuaSystem *s; LuaFaction *f; LuaShip *sh; LuaTime *lt; Planet *pnt; StarSystem *ss; char buf[PATH_MAX]; const char *name, *str; int keynum; /* Default values. */ ret = 0; /* key, value */ /* Handle different types of keys. */ switch (lua_type(L, -2)) { case LUA_TSTRING: /* Can just tostring directly. */ name = lua_tostring(L,-2); /* Isn't a number key. */ keynum = 0; break; case LUA_TNUMBER: /* Can't tostring directly. */ lua_pushvalue(L,-2); name = lua_tostring(L,-1); lua_pop(L,1); /* Is a number key. */ keynum = 1; break; /* We only handle string or number keys, so ignore the rest. */ default: lua_pop(L,1); /* key */ return 0; } /* key, value */ /* Now handle the value. */ switch (lua_type(L, -1)) { /* Recursive for tables. */ case LUA_TTABLE: /* Check if should save -- only if not in table.. */ if (!intable) { lua_getfield(L, -1, "__save"); b = lua_toboolean(L,-1); lua_pop(L,1); if (!b) /* No need to save. */ break; } /* Start the table. */ xmlw_startElem(writer,"data"); xmlw_attr(writer,"type","table"); xmlw_attr(writer,"name","%s",name); if (keynum) xmlw_attr(writer,"keynum","1"); lua_pushnil(L); /* key, value, nil */ /* key, value, nil */ while (lua_next(L, -2) != 0) { /* key, value, key, value */ ret = nxml_persistDataNode( L, writer, 1 ); /* key, value, key */ } /* key, value */ xmlw_endElem(writer); /* "table" */ break; /* Normal number. */ case LUA_TNUMBER: nxml_saveData( writer, "number", name, lua_tostring(L,-1), keynum ); /* key, value */ break; /* Boolean is either 1 or 0. */ case LUA_TBOOLEAN: /* lua_tostring doesn't work on booleans. */ if (lua_toboolean(L,-1)) buf[0] = '1'; else buf[0] = '0'; buf[1] = '\0'; nxml_saveData( writer, "bool", name, buf, keynum ); /* key, value */ break; /* String is saved normally. */ case LUA_TSTRING: nxml_saveData( writer, "string", name, lua_tostring(L,-1), keynum ); /* key, value */ break; /* User data must be handled here. */ case LUA_TUSERDATA: if (lua_isplanet(L,-1)) { p = lua_toplanet(L,-1); pnt = planet_getIndex( p->id ); if (pnt != NULL) nxml_saveData( writer, "planet", name, pnt->name, keynum ); else WARN("Failed to save invalid planet."); /* key, value */ break; } else if (lua_issystem(L,-1)) { s = lua_tosystem(L,-1); ss = system_getIndex( s->id ); if (ss != NULL) nxml_saveData( writer, "system", name, ss->name, keynum ); else WARN("Failed to save invalid system."); /* key, value */ break; } else if (lua_isfaction(L,-1)) { f = lua_tofaction(L,-1); str = faction_name( f->f ); if (str == NULL) break; nxml_saveData( writer, "faction", name, str, keynum ); /* key, value */ break; } else if (lua_isship(L,-1)) { sh = lua_toship(L,-1); str = sh->ship->name; if (str == NULL) break; nxml_saveData( writer, "ship", name, str, keynum ); /* key, value */ break; } else if (lua_istime(L,-1)) { lt = lua_totime(L,-1); snprintf( buf, sizeof(buf), "%"PRId64, lt->t ); nxml_saveData( writer, "time", name, buf, keynum ); break; } /* Rest gets ignored, like functions, etc... */ default: /* key, value */ break; } lua_pop(L,1); /* key */ return ret; }
/** * @brief Teleports the player to a new system (only if not landed). * * Does not change the position nor velocity of the player.p, which will probably be wrong in the new system. * * @usage player.teleport( system.get("Arcanis") ) -- Teleports the player to arcanis. * @usage player.teleport( "Arcanis" ) -- Teleports the player to arcanis. * * @luaparam sys System or name of a system to teleport the player to. * @luafunc teleport( sys ) */ static int playerL_teleport( lua_State *L ) { LuaSystem *sys; const char *name; /* Must not be landed. */ if (landed) NLUA_ERROR(L,"Can not teleport the player while landed!"); if (comm_isOpen()) NLUA_ERROR(L,"Can not teleport the player while the comm is open!"); if (player_isBoarded()) NLUA_ERROR(L,"Can not teleport the player while he is boarded!"); /* Get a system. */ if (lua_issystem(L,1)) { sys = lua_tosystem(L,1); name = system_getIndex(sys->id)->name; } else if (lua_isstring(L,1)) name = lua_tostring(L,1); else NLUA_INVALID_PARAMETER(L); /* Check if system exists. */ if (!system_exists( name )) { NLUA_ERROR( L, "System '%s' does not exist.", name ); return 0; } /* Jump out hook is run first. */ hooks_run( "jumpout" ); /* Just in case remove hyperspace flags. */ pilot_rmFlag( player.p, PILOT_HYPERSPACE ); pilot_rmFlag( player.p, PILOT_HYP_BEGIN ); pilot_rmFlag( player.p, PILOT_HYP_BRAKE ); pilot_rmFlag( player.p, PILOT_HYP_PREP ); /* Free graphics. */ space_gfxUnload( cur_system ); /* Go to the new system. */ space_init( name ); /* Map gets deformed when jumping this way. */ map_clear(); /* Add the escorts. */ player_addEscorts(); /* Run hooks - order is important. */ hooks_run( "jumpin" ); hooks_run( "enter" ); events_trigger( EVENT_TRIGGER_ENTER ); /* Reset targets when teleporting */ player_targetPlanetSet( -1 ); player_targetHyperspaceSet( -1 ); gui_setNav(); return 0; }
/** * @brief Teleports the player to a new planet or system (only if not landed). * * If the destination is a system, the coordinates of the player will not change. * If the destination is a planet, the player will be placed over that planet. * * @usage player.teleport( system.get("Arcanis") ) -- Teleports the player to Arcanis. * @usage player.teleport( "Arcanis" ) -- Teleports the player to Arcanis. * @usage player.teleport( "Dvaer Prime" ) -- Teleports the player to Dvaer, and relocates him to Dvaer Prime. * * @luaparam dest System or name of a system or planet or name of a planet to teleport the player to. * @luafunc teleport( dest ) */ static int playerL_teleport( lua_State *L ) { Planet *pnt; StarSystem *sys; const char *name, *pntname; /* Must not be landed. */ if (landed) NLUA_ERROR(L,"Can not teleport the player while landed!"); if (comm_isOpen()) NLUA_ERROR(L,"Can not teleport the player while the comm is open!"); if (player_isBoarded()) NLUA_ERROR(L,"Can not teleport the player while he is boarded!"); pnt = NULL; /* Get a system. */ if (lua_issystem(L,1)) { sys = luaL_validsystem(L,1); name = system_getIndex(sys->id)->name; } /* Get a planet. */ else if (lua_isplanet(L,1)) { pnt = luaL_validplanet(L,1); name = planet_getSystem( pnt->name ); if (name == NULL) { NLUA_ERROR( L, "Planet '%s' does not belong to a system..", pnt->name ); return 0; } } /* Get destination from string. */ else if (lua_isstring(L,1)) { name = lua_tostring(L,1); if (!system_exists( name )) { if (!planet_exists( name )) { NLUA_ERROR( L, "'%s' is not a valid teleportation target.", name ); return 0; } /* No system found, assume destination string is the name of a planet. */ pntname = name; name = planet_getSystem( name ); pnt = planet_get( pntname ); if (name == NULL) { NLUA_ERROR( L, "Planet '%s' does not belong to a system..", pntname ); return 0; } } } else NLUA_INVALID_PARAMETER(L); /* Check if system exists. */ if (!system_exists( name )) { NLUA_ERROR( L, "System '%s' does not exist.", name ); return 0; } /* Jump out hook is run first. */ hooks_run( "jumpout" ); /* Just in case remove hyperspace flags. */ pilot_rmFlag( player.p, PILOT_HYPERSPACE ); pilot_rmFlag( player.p, PILOT_HYP_BEGIN ); pilot_rmFlag( player.p, PILOT_HYP_BRAKE ); pilot_rmFlag( player.p, PILOT_HYP_PREP ); /* Free graphics. */ space_gfxUnload( cur_system ); /* Go to the new system. */ space_init( name ); /* Map gets deformed when jumping this way. */ map_clear(); /* Add the escorts. */ player_addEscorts(); /* Run hooks - order is important. */ hooks_run( "jumpin" ); hooks_run( "enter" ); events_trigger( EVENT_TRIGGER_ENTER ); missions_run( MIS_AVAIL_SPACE, -1, NULL, NULL ); /* Reset targets when teleporting */ player_targetPlanetSet( -1 ); player_targetHyperspaceSet( -1 ); gui_setNav(); /* Move to planet. */ if (pnt != NULL) vectcpy( &player.p->solid->pos, &pnt->pos ); return 0; }
/** * @brief Saves the player's active missions. * * @param writer XML Write to use to save missions. * @return 0 on success. */ int missions_saveActive( xmlTextWriterPtr writer ) { int i,j,n; int nitems; char **items; xmlw_startElem(writer,"missions"); for (i=0; i<MISSION_MAX; i++) { if (player_missions[i]->id != 0) { xmlw_startElem(writer,"mission"); /* data and id are attributes because they must be loaded first */ xmlw_attr(writer,"data","%s",player_missions[i]->data->name); xmlw_attr(writer,"id","%u",player_missions[i]->id); xmlw_elem(writer,"title","%s",player_missions[i]->title); xmlw_elem(writer,"desc","%s",player_missions[i]->desc); xmlw_elem(writer,"reward","%s",player_missions[i]->reward); /* Markers. */ xmlw_startElem( writer, "markers" ); if (player_missions[i]->markers != NULL) { n = array_size( player_missions[i]->markers ); for (j=0; j<n; j++) { xmlw_startElem(writer,"marker"); xmlw_attr(writer,"id","%d",player_missions[i]->markers[j].id); xmlw_attr(writer,"type","%d",player_missions[i]->markers[j].type); xmlw_str(writer,"%s", system_getIndex(player_missions[i]->markers[j].sys)->name); xmlw_endElem(writer); /* "marker" */ } } xmlw_endElem( writer ); /* "markers" */ /* Cargo */ xmlw_startElem(writer,"cargos"); for (j=0; j<player_missions[i]->ncargo; j++) xmlw_elem(writer,"cargo","%u", player_missions[i]->cargo[j]); xmlw_endElem(writer); /* "cargos" */ /* OSD. */ if (player_missions[i]->osd > 0) { xmlw_startElem(writer,"osd"); /* Save attributes. */ items = osd_getItems(player_missions[i]->osd, &nitems); xmlw_attr(writer,"title","%s",osd_getTitle(player_missions[i]->osd)); xmlw_attr(writer,"nitems","%d",nitems); xmlw_attr(writer,"active","%d",osd_getActive(player_missions[i]->osd)); /* Save messages. */ for (j=0; j<nitems; j++) xmlw_elem(writer,"msg","%s",items[j]); xmlw_endElem(writer); /* "osd" */ } /* Claims. */ xmlw_startElem(writer,"claims"); claim_xmlSave( writer, player_missions[i]->claims ); xmlw_endElem(writer); /* "claims" */ /* Write Lua magic */ xmlw_startElem(writer,"lua"); nxml_persistLua( player_missions[i]->L, writer ); xmlw_endElem(writer); /* "lua" */ xmlw_endElem(writer); /* "mission" */ } } xmlw_endElem(writer); /* "missions" */ return 0; }
/** * @brief Updates the map window. * * @param wid Window id. */ static void map_update( unsigned int wid ) { int i; StarSystem* sys; int f, h, x, y; double standing, nstanding; unsigned int services; int l; int hasPresence, hasPlanets; char t; char buf[PATH_MAX]; int p; glTexture *logo; double w; double unknownPresence; /* Needs map to update. */ if (!map_isOpen()) return; /* Get selected system. */ sys = system_getIndex( map_selected ); /* Not known and no markers. */ if (!(sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED)) && !sys_isKnown(sys) && !space_sysReachable(sys)) { map_selectCur(); sys = system_getIndex( map_selected ); } /* * Right Text */ x = -70; /* Side bar X offset. */ w = ABS(x) + 60; /* Width of the side bar. */ y = -20 - 20 - 64 - gl_defFont.h; /* Initialized to position for txtSFaction. */ if (!sys_isKnown(sys)) { /* System isn't known, erase all */ /* * Right Text */ if (sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED)) window_modifyText( wid, "txtSysname", sys->name ); else window_modifyText( wid, "txtSysname", "Unknown" );; /* Faction */ window_modifyImage( wid, "imgFaction", NULL, 0, 0 ); window_moveWidget( wid, "txtSFaction", x, y); window_moveWidget( wid, "txtFaction", x + 50, y - gl_smallFont.h - 5 ); window_modifyText( wid, "txtFaction", "Unknown" ); y -= 2 * gl_smallFont.h + 5 + 15; /* Standing */ window_moveWidget( wid, "txtSStanding", x, y ); window_moveWidget( wid, "txtStanding", x + 50, y - gl_smallFont.h - 5 ); window_modifyText( wid, "txtStanding", "Unknown" ); y -= 2 * gl_smallFont.h + 5 + 15; /* Presence. */ window_moveWidget( wid, "txtSPresence", x, y ); window_moveWidget( wid, "txtPresence", x + 50, y - gl_smallFont.h - 5 ); window_modifyText( wid, "txtPresence", "Unknown" ); y -= 2 * gl_smallFont.h + 5 + 15; /* Planets */ window_moveWidget( wid, "txtSPlanets", x, y ); window_moveWidget( wid, "txtPlanets", x + 50, y - gl_smallFont.h - 5 ); window_modifyText( wid, "txtPlanets", "Unknown" ); y -= 2 * gl_smallFont.h + 5 + 15; /* Services */ window_moveWidget( wid, "txtSServices", x, y ); window_moveWidget( wid, "txtServices", x + 50, y -gl_smallFont.h - 5 ); window_modifyText( wid, "txtServices", "Unknown" ); /* * Bottom Text */ window_modifyText( wid, "txtSystemStatus", NULL ); return; } /* System is known */ window_modifyText( wid, "txtSysname", sys->name ); standing = 0.; nstanding = 0.; f = -1; for (i=0; i<sys->nplanets; i++) { if (sys->planets[i]->real != ASSET_REAL) continue; if (!planet_isKnown(sys->planets[i])) continue; if ((f==-1) && (sys->planets[i]->faction>0)) { f = sys->planets[i]->faction; standing += faction_getPlayer( f ); nstanding++; } else if (f != sys->planets[i]->faction && /** @todo more verbosity */ (sys->planets[i]->faction>0)) { nsnprintf( buf, PATH_MAX, "Multiple" ); break; } } if (f == -1) { window_modifyImage( wid, "imgFaction", NULL, 0, 0 ); window_modifyText( wid, "txtFaction", "N/A" ); window_modifyText( wid, "txtStanding", "N/A" ); h = gl_smallFont.h; } else { if (i==sys->nplanets) /* saw them all and all the same */ nsnprintf( buf, PATH_MAX, "%s", faction_longname(f) ); /* Modify the image. */ logo = faction_logoSmall(f); window_modifyImage( wid, "imgFaction", logo, 0, 0 ); if (logo != NULL) window_moveWidget( wid, "imgFaction", -90 + logo->w/2, -20 - 32 - 10 - gl_defFont.h + logo->h/2); /* Modify the text */ window_modifyText( wid, "txtFaction", buf ); window_modifyText( wid, "txtStanding", faction_getStanding( standing / nstanding ) ); h = gl_printHeightRaw( &gl_smallFont, w, buf ); } /* Faction */ window_moveWidget( wid, "txtSFaction", x, y); window_moveWidget( wid, "txtFaction", x + 50, y - gl_smallFont.h - 5 ); y -= gl_smallFont.h + h + 5 + 15; /* Standing */ window_moveWidget( wid, "txtSStanding", x, y ); window_moveWidget( wid, "txtStanding", x + 50, y - gl_smallFont.h - 5 ); y -= 2 * gl_smallFont.h + 5 + 15; /* Get presence. */ hasPresence = 0; buf[0] = '\0'; l = 0; unknownPresence = 0; for (i=0; i < sys->npresence; i++) { if (sys->presence[i].value <= 0) continue; hasPresence = 1; if (faction_isKnown( sys->presence[i].faction )) { t = faction_getColourChar(sys->presence[i].faction); /* Use map grey instead of default neutral colour */ l += nsnprintf( &buf[l], PATH_MAX-l, "%s\e0%s: \e%c%.0f", (l==0)?"":"\n", faction_shortname(sys->presence[i].faction), (t=='N')?'M':t, sys->presence[i].value); } else
/** * @brief Opens the map window. */ void map_open (void) { unsigned int wid; StarSystem *cur; int w, h, x, y, rw; /* Not under manual control. */ if (pilot_isFlag( player.p, PILOT_MANUAL_CONTROL )) return; /* Destroy window if exists. */ wid = window_get(MAP_WDWNAME); if (wid > 0) { window_destroy( wid ); return; } /* set position to focus on current system */ map_xpos = cur_system->pos.x; map_ypos = cur_system->pos.y; /* mark systems as needed */ mission_sysMark(); /* Attempt to select current map if none is selected */ if (map_selected == -1) map_selectCur(); /* get the selected system. */ cur = system_getIndex( map_selected ); /* Set up window size. */ w = MAX(600, SCREEN_W - 100); h = MAX(540, SCREEN_H - 100); /* create the window. */ wid = window_create( MAP_WDWNAME, -1, -1, w, h ); window_setCancel( wid, window_close ); window_handleKeys( wid, map_keyHandler ); /* * SIDE TEXT * * $System * * Faction: * $Faction (or Multiple) * * Status: * $Status * * Planets: * $Planet1, $Planet2, ... * * Services: * $Services * * ... * [Autonav] * [ Find ] * [ Close ] */ x = -70; /* Right column X offset. */ y = -20; rw = ABS(x) + 60; /* Right column indented width maximum. */ /* System Name */ window_addText( wid, -90 + 80, y, 160, 20, 1, "txtSysname", &gl_defFont, &cDConsole, cur->name ); y -= 10; /* Faction image */ window_addImage( wid, -90 + 32, y - 32, 0, 0, "imgFaction", NULL, 0 ); y -= 64 + 10; /* Faction */ window_addText( wid, x, y, 90, 20, 0, "txtSFaction", &gl_smallFont, &cDConsole, "Faction:" ); window_addText( wid, x + 50, y-gl_smallFont.h-5, rw, 100, 0, "txtFaction", &gl_smallFont, &cBlack, NULL ); y -= 2 * gl_smallFont.h + 5 + 15; /* Standing */ window_addText( wid, x, y, 90, 20, 0, "txtSStanding", &gl_smallFont, &cDConsole, "Standing:" ); window_addText( wid, x + 50, y-gl_smallFont.h-5, rw, 100, 0, "txtStanding", &gl_smallFont, &cBlack, NULL ); y -= 2 * gl_smallFont.h + 5 + 15; /* Presence. */ window_addText( wid, x, y, 90, 20, 0, "txtSPresence", &gl_smallFont, &cDConsole, "Presence:" ); window_addText( wid, x + 50, y-gl_smallFont.h-5, rw, 100, 0, "txtPresence", &gl_smallFont, &cBlack, NULL ); y -= 2 * gl_smallFont.h + 5 + 15; /* Planets */ window_addText( wid, x, y, 90, 20, 0, "txtSPlanets", &gl_smallFont, &cDConsole, "Planets:" ); window_addText( wid, x + 50, y-gl_smallFont.h-5, rw, 150, 0, "txtPlanets", &gl_smallFont, &cBlack, NULL ); y -= 2 * gl_smallFont.h + 5 + 15; /* Services */ window_addText( wid, x, y, 90, 20, 0, "txtSServices", &gl_smallFont, &cDConsole, "Services:" ); window_addText( wid, x + 50, y-gl_smallFont.h-5, rw, 100, 0, "txtServices", &gl_smallFont, &cBlack, NULL ); y -= 2 * gl_smallFont.h + 5 + 15; /* Close button */ window_addButton( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnClose", "Close", window_close ); /* Find button */ window_addButton( wid, -20 - (BUTTON_WIDTH+20), 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnFind", "Find", map_inputFind ); /* Autonav button */ window_addButton( wid, -20 - 2*(BUTTON_WIDTH+20), 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnAutonav", "Autonav", player_autonavStartWindow ); /* * Bottom stuff * * [+] [-] Nebula, Interference */ /* Zoom buttons */ window_addButton( wid, 40, 20, 30, 30, "btnZoomIn", "+", map_buttonZoom ); window_addButton( wid, 80, 20, 30, 30, "btnZoomOut", "-", map_buttonZoom ); /* Situation text */ window_addText( wid, 140, 10, w - 80 - 30 - 30, 30, 0, "txtSystemStatus", &gl_smallFont, &cBlack, NULL ); /* * The map itself. */ map_show( wid, 20, -40, w-200, h-100, 1. ); /* Reset zoom. */ map_update( wid ); /* * Disable Autonav button if player lacks fuel. */ if ((player.p->fuel < HYPERSPACE_FUEL) || pilot_isFlag( player.p, PILOT_NOJUMP)) window_disableButton( wid, "btnAutonav" ); }
/** * @brief Opens the map window. */ void map_open (void) { unsigned int wid; StarSystem *cur; int w,h; /* Destroy window if exists. */ wid = window_get(MAP_WDWNAME); if (wid > 0) { window_destroy( wid ); return; } /* set position to focus on current system */ map_xpos = cur_system->pos.x; map_ypos = cur_system->pos.y; /* mark systems as needed */ mission_sysMark(); /* Attempt to select current map if none is selected */ if (map_selected == -1) map_selectCur(); /* get the selected system. */ cur = system_getIndex( map_selected ); /* Set up window size. */ w = MAX(600, SCREEN_W - 100); h = MAX(540, SCREEN_H - 100); /* create the window. */ wid = window_create( MAP_WDWNAME, -1, -1, w, h ); window_setCancel( wid, window_close ); /* * SIDE TEXT * * $System * * Faction: * $Faction (or Multiple) * * Status: * $Status * * Planets: * $Planet1, $Planet2, ... * * Services: * $Services * * ... * * [Close] */ /* System Name */ window_addText( wid, -20, -20, 100, 20, 1, "txtSysname", &gl_defFont, &cDConsole, cur->name ); /* Faction */ window_addImage( wid, -20-64, -60-64, "imgFaction", NULL, 0 ); window_addText( wid, -20, -60, 90, 20, 0, "txtSFaction", &gl_smallFont, &cDConsole, "Faction:" ); window_addText( wid, -20, -60-gl_smallFont.h-5, 80, 100, 0, "txtFaction", &gl_smallFont, &cBlack, NULL ); /* Standing */ window_addText( wid, -20, -100, 90, 20, 0, "txtSStanding", &gl_smallFont, &cDConsole, "Standing:" ); window_addText( wid, -20, -100-gl_smallFont.h-5, 80, 100, 0, "txtStanding", &gl_smallFont, &cBlack, NULL ); /* Security. */ window_addText( wid, -20, -140, 90, 20, 0, "txtSSecurity", &gl_smallFont, &cDConsole, "Security:" ); window_addText( wid, -20, -140-gl_smallFont.h-5, 80, 100, 0, "txtSecurity", &gl_smallFont, &cBlack, NULL ); /* Planets */ window_addText( wid, -20, -180, 90, 20, 0, "txtSPlanets", &gl_smallFont, &cDConsole, "Planets:" ); window_addText( wid, -20, -180-gl_smallFont.h-5, 80, 100, 0, "txtPlanets", &gl_smallFont, &cBlack, NULL ); /* Services */ window_addText( wid, -20, -220, 90, 20, 0, "txtSServices", &gl_smallFont, &cDConsole, "Services:" ); window_addText( wid, -20, -220-gl_smallFont.h-5, 80, 100, 0, "txtServices", &gl_smallFont, &cBlack, NULL ); /* Close button */ window_addButton( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnClose", "Close", window_close ); /* * Bottom stuff * * [+] [-] Nebula, Asteroids, Interference */ /* Zoom buttons */ window_addButton( wid, 40, 20, 30, 30, "btnZoomIn", "+", map_buttonZoom ); window_addButton( wid, 80, 20, 30, 30, "btnZoomOut", "-", map_buttonZoom ); /* Situation text */ window_addText( wid, 140, 10, w - 80 - 30 - 30, 30, 0, "txtSystemStatus", &gl_smallFont, &cBlack, NULL ); /* * The map itself. */ map_show( wid, 20, -40, w-150, h-100, 1. ); /* Reset zoom. */ map_update( wid ); }
/** * @brief Renders the custom map widget. * * @param bx Base X position to render at. * @param by Base Y position to render at. * @param w Width of the widget. * @param h Height of the widget. */ static void map_render( double bx, double by, double w, double h ) { int i,j, n,m; double x,y,r, tx,ty; StarSystem *sys, *jsys, *hsys; glColour* col; r = 5.; x = (bx - map_xpos + w/2) * 1.; y = (by - map_ypos + h/2) * 1.; /* background */ COLOUR(cBlack); glBegin(GL_QUADS); glVertex2d( bx, by ); glVertex2d( bx, by+h ); glVertex2d( bx+w, by+h ); glVertex2d( bx+w, by ); glEnd(); /* GL_QUADS */ /* render the star systems */ for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* check to make sure system is known or adjacent to known (or marked) */ if (!sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED) && !space_sysReachable(sys)) continue; /* system colours */ if (sys==cur_system) col = &cRadar_tPlanet; else if (!sys_isKnown(sys) || (sys->nplanets==0)) col = &cInert; else col = faction_getColour( sys->faction); COLOUR(*col); /* draw the system */ tx = x + sys->pos.x*map_zoom; ty = y + sys->pos.y*map_zoom; gl_drawCircleInRect( tx, ty, r, bx, by, w, h ); /* draw the system name */ if (sys_isKnown(sys) && (map_zoom > 0.5 )) { tx = x + 7. + sys->pos.x * map_zoom; ty = y - 5. + sys->pos.y * map_zoom; gl_print( &gl_smallFont, tx + SCREEN_W/2., ty + SCREEN_H/2., &cWhite, sys->name ); } if (!sys_isKnown(sys)) continue; /* we don't draw hyperspace lines */ /* draw the hyperspace paths */ glShadeModel(GL_SMOOTH); /* cheaply use transparency instead of actually calculating * from where to where the line must go :) */ for (j=0; j<sys->njumps; j++) { jsys = system_getIndex( sys->jumps[j] ); if (hyperspace_target != -1) hsys = system_getIndex( cur_system->jumps[hyperspace_target] ); n = map_inPath(jsys); m = map_inPath(sys); /* set the colours */ /* is the route the current one? */ if ((hyperspace_target != -1) && ( ((cur_system==sys) && (j==hyperspace_target)) || ((cur_system==jsys) && (sys==hsys )))) { if (player->fuel < HYPERSPACE_FUEL) col = &cRed; else col = &cGreen; } /* is the route part of the path? */ else if ((n > 0) && (m > 0)) { if ((n == 2) || (m == 2)) /* out of fuel */ col = &cRed; else col = &cYellow; } else col = &cDarkBlue; glBegin(GL_LINE_STRIP); ACOLOUR(*col,0.); tx = x + sys->pos.x * map_zoom; ty = y + sys->pos.y * map_zoom; glVertex2d( tx, ty ); COLOUR(*col); tx += (jsys->pos.x - sys->pos.x)/2. * map_zoom; ty += (jsys->pos.y - sys->pos.y)/2. * map_zoom; glVertex2d( tx, ty ); ACOLOUR(*col,0.); tx = x + jsys->pos.x * map_zoom; ty = y + jsys->pos.y * map_zoom; glVertex2d( tx, ty ); glEnd(); /* GL_LINE_STRIP */ } glShadeModel(GL_FLAT); } /* Second pass to put markers. */ for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* We only care about marked now. */ if (!sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED)) continue; /* Get the position. */ tx = x + sys->pos.x*map_zoom; ty = y + sys->pos.y*map_zoom; /* Count markers. */ n = (sys_isFlag(sys, SYSTEM_CMARKED)) ? 1 : 0; n += sys->markers_misc; n += sys->markers_cargo; n += sys->markers_rush; /* Draw the markers. */ j = 0; if (sys_isFlag(sys, SYSTEM_CMARKED)) { map_drawMarker( tx, ty, r, n, j, 0 ); j++; } for (m=0; m<sys->markers_misc; m++) { map_drawMarker( tx, ty, r, n, j, 1 ); j++; } for (m=0; m<sys->markers_rush; m++) { map_drawMarker( tx, ty, r, n, j, 2 ); j++; } for (m=0; m<sys->markers_cargo; m++) { map_drawMarker( tx, ty, r, n, j, 3 ); j++; } } /* selected planet */ if (map_selected != -1) { sys = system_getIndex( map_selected ); COLOUR(cRed); gl_drawCircleInRect( x + sys->pos.x * map_zoom, y + sys->pos.y * map_zoom, r+3., bx, by, w, h ); } }
/** * @brief Map custom widget mouse handling. * * @param wid Window sending events. * @param event Event window is sending. * @param mx Mouse X position. * @param my Mouse Y position. * @param w Width of the widget. * @param h Height of the widget. */ static void map_mouse( unsigned int wid, SDL_Event* event, double mx, double my, double w, double h, void *data ) { (void) wid; (void) data; int i; double x,y, t; StarSystem *sys; t = 15.*15.; /* threshold */ switch (event->type) { case SDL_MOUSEBUTTONDOWN: /* Must be in bounds. */ if ((mx < 0.) || (mx > w) || (my < 0.) || (my > h)) return; /* Zooming */ if (event->button.button == SDL_BUTTON_WHEELUP) map_buttonZoom( 0, "btnZoomIn" ); else if (event->button.button == SDL_BUTTON_WHEELDOWN) map_buttonZoom( 0, "btnZoomOut" ); /* selecting star system */ else { mx -= w/2 - map_xpos; my -= h/2 - map_ypos; for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* must be reachable */ if (!sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED) && !space_sysReachable(sys)) continue; /* get position */ x = sys->pos.x * map_zoom; y = sys->pos.y * map_zoom; if ((pow2(mx-x)+pow2(my-y)) < t) { map_select( sys, (SDL_GetModState() & KMOD_SHIFT) ); break; } } map_drag = 1; } break; case SDL_MOUSEBUTTONUP: if (map_drag) map_drag = 0; break; case SDL_MOUSEMOTION: if (map_drag) { /* axis is inverted */ map_xpos -= event->motion.xrel; map_ypos += event->motion.yrel; } break; } }
/** * @brief Renders the custom map widget. * * @param bx Base X position to render at. * @param by Base Y position to render at. * @param w Width of the widget. * @param h Height of the widget. */ static void map_render( double bx, double by, double w, double h, void *data ) { (void) data; int i,j, n,m; double x,y,r, tx,ty, fuel; StarSystem *sys, *jsys, *hsys, *lsys; glColour *col, c; GLfloat vertex[8*(2+4)]; int sw, sh; /* Parameters. */ r = round(CLAMP(5., 15., 6.*map_zoom)); x = round((bx - map_xpos + w/2) * 1.); y = round((by - map_ypos + h/2) * 1.); /* background */ gl_renderRect( bx, by, w, h, &cBlack ); /* * First pass renders everything almost (except names and markers). */ for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* check to make sure system is known or adjacent to known (or marked) */ if (!sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED) && !space_sysReachable(sys)) continue; tx = x + sys->pos.x*map_zoom; ty = y + sys->pos.y*map_zoom; /* draws the disk representing the faction */ if (sys_isKnown(sys) && (sys->faction != -1)) { sw = gl_faction_disk->sw; sh = gl_faction_disk->sw; col = faction_colour(sys->faction); c.r = col->r; c.g = col->g; c.b = col->b; c.a = 0.7; gl_blitTexture( gl_faction_disk, tx - sw/2, ty - sh/2, sw, sh, 0., 0., gl_faction_disk->srw, gl_faction_disk->srw, &c ); } /* Draw the system. */ if (!sys_isKnown(sys) || (sys->nfleets==0)) col = &cInert; else if (sys->security >= 1.) col = &cGreen; else if (sys->security >= 0.6) col = &cOrange; else if (sys->security >= 0.3) col = &cRed; else col = &cDarkRed; gl_drawCircleInRect( tx, ty, r, bx, by, w, h, col, 0 ); /* If system is known fill it. */ if (sys_isKnown(sys) && (sys->nplanets > 0)) { /* Planet colours */ if (!sys_isKnown(sys)) col = &cInert; else if (sys->nplanets==0) col = &cInert; else col = faction_getColour( sys->faction); /* Radius slightly shorter. */ gl_drawCircleInRect( tx, ty, 0.5*r, bx, by, w, h, col, 1 ); } if (!sys_isKnown(sys)) continue; /* we don't draw hyperspace lines */ /* draw the hyperspace paths */ glShadeModel(GL_SMOOTH); col = &cDarkBlue; /* first we draw all of the paths. */ for (j=0; j<sys->njumps; j++) { jsys = system_getIndex( sys->jumps[j] ); if (hyperspace_target != -1) hsys = system_getIndex( cur_system->jumps[hyperspace_target] ); /* Draw the lines. */ vertex[0] = x + sys->pos.x * map_zoom; vertex[1] = y + sys->pos.y * map_zoom; vertex[2] = vertex[0] + (jsys->pos.x - sys->pos.x)/2. * map_zoom; vertex[3] = vertex[1] + (jsys->pos.y - sys->pos.y)/2. * map_zoom; vertex[4] = x + jsys->pos.x * map_zoom; vertex[5] = y + jsys->pos.y * map_zoom; vertex[6] = col->r; vertex[7] = col->g; vertex[8] = col->b; vertex[9] = 0.; vertex[10] = col->r; vertex[11] = col->g; vertex[12] = col->b; vertex[13] = col->a; vertex[14] = col->r; vertex[15] = col->g; vertex[16] = col->b; vertex[17] = 0.; gl_vboSubData( map_vbo, 0, sizeof(GLfloat) * 3*(2+4), vertex ); gl_vboActivateOffset( map_vbo, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( map_vbo, GL_COLOR_ARRAY, sizeof(GLfloat) * 2*3, 4, GL_FLOAT, 0 ); glDrawArrays( GL_LINE_STRIP, 0, 3 ); gl_vboDeactivate(); } glShadeModel( GL_FLAT ); } /* Now we'll draw over the lines with the new pathways. */ if (map_path != NULL) { lsys = cur_system; glShadeModel(GL_SMOOTH); col = &cGreen; fuel = player->fuel; for (j=0; j<map_npath; j++) { jsys = map_path[j]; if (fuel == player->fuel) col = &cGreen; else if (fuel < 100.) col = &cRed; else col = &cYellow; fuel -= 100; /* Draw the lines. */ vertex[0] = x + lsys->pos.x * map_zoom; vertex[1] = y + lsys->pos.y * map_zoom; vertex[2] = vertex[0] + (jsys->pos.x - lsys->pos.x)/2. * map_zoom; vertex[3] = vertex[1] + (jsys->pos.y - lsys->pos.y)/2. * map_zoom; vertex[4] = x + jsys->pos.x * map_zoom; vertex[5] = y + jsys->pos.y * map_zoom; vertex[6] = col->r; vertex[7] = col->g; vertex[8] = col->b; vertex[9] = 0.; vertex[10] = col->r; vertex[11] = col->g; vertex[12] = col->b; vertex[13] = col->a; vertex[14] = col->r; vertex[15] = col->g; vertex[16] = col->b; vertex[17] = 0.; gl_vboSubData( map_vbo, 0, sizeof(GLfloat) * 3*(2+4), vertex ); gl_vboActivateOffset( map_vbo, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( map_vbo, GL_COLOR_ARRAY, sizeof(GLfloat) * 2*3, 4, GL_FLOAT, 0 ); glDrawArrays( GL_LINE_STRIP, 0, 3 ); gl_vboDeactivate(); lsys = jsys; } glShadeModel( GL_FLAT ); } /* * Second pass - System names */ for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* Skip system. */ if (!sys_isKnown(sys) || (map_zoom <= 0.5 )) continue; tx = x + (sys->pos.x+11.) * map_zoom; ty = y + (sys->pos.y-5.) * map_zoom; gl_print( &gl_smallFont, tx + SCREEN_W/2., ty + SCREEN_H/2., &cWhite, sys->name ); } /* * Third pass - system markers */ for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* We only care about marked now. */ if (!sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED)) continue; /* Get the position. */ tx = x + sys->pos.x*map_zoom; ty = y + sys->pos.y*map_zoom; /* Count markers. */ n = (sys_isFlag(sys, SYSTEM_CMARKED)) ? 1 : 0; n += sys->markers_misc; n += sys->markers_cargo; n += sys->markers_rush; /* Draw the markers. */ j = 0; if (sys_isFlag(sys, SYSTEM_CMARKED)) { map_drawMarker( tx, ty, r, n, j, 0 ); j++; } for (m=0; m<sys->markers_misc; m++) { map_drawMarker( tx, ty, r, n, j, 1 ); j++; } for (m=0; m<sys->markers_rush; m++) { map_drawMarker( tx, ty, r, n, j, 2 ); j++; } for (m=0; m<sys->markers_cargo; m++) { map_drawMarker( tx, ty, r, n, j, 3 ); j++; } } /* Selected planet. */ if (map_selected != -1) { sys = system_getIndex( map_selected ); gl_drawCircleInRect( x + sys->pos.x * map_zoom, y + sys->pos.y * map_zoom, 1.5*r, bx, by, w, h, &cRed, 0 ); } /* Current planet. */ gl_drawCircleInRect( x + cur_system->pos.x * map_zoom, y + cur_system->pos.y * map_zoom, 1.5*r, bx, by, w, h, &cRadar_tPlanet, 0 ); }
/** * @brief Updates the map window. * * @param wid Window id. */ static void map_update( unsigned int wid ) { int i; StarSystem* sys; int f, y, h, multiple_faction; double standing, nstanding; unsigned int services; char buf[PATH_MAX]; int p; glTexture *logo; /* Needs map to update. */ if (!map_isOpen()) return; sys = system_getIndex( map_selected ); /* Not known and no markers. */ if (!(sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED)) && !sys_isKnown(sys) && !space_sysReachable(sys)) { map_selectCur(); sys = system_getIndex( map_selected ); } /* * Right Text */ if (!sys_isKnown(sys)) { /* System isn't known, erase all */ /* * Right Text */ if (sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED)) window_modifyText( wid, "txtSysname", sys->name ); else window_modifyText( wid, "txtSysname", "Unknown" ); window_modifyImage( wid, "imgFaction", NULL ); window_moveWidget( wid, "txtSFaction", -20, -60 ); window_moveWidget( wid, "txtFaction", -20, -60-gl_smallFont.h-5 ); window_modifyText( wid, "txtFaction", "Unknown" ); /* Standing */ window_moveWidget( wid, "txtSStanding", -20, -100 ); window_moveWidget( wid, "txtStanding", -20, -100-gl_smallFont.h-5 ); window_modifyText( wid, "txtStanding", "Unknown" ); /* Security. */ window_moveWidget( wid, "txtSSecurity", -20, -140 ); window_moveWidget( wid, "txtSecurity", -20, -140-gl_smallFont.h-5 ); window_modifyText( wid, "txtSecurity", "Unknown" ); /* Planets */ window_moveWidget( wid, "txtSPlanets", -20, -180 ); window_moveWidget( wid, "txtPlanets", -20, -180-gl_smallFont.h-5 ); window_modifyText( wid, "txtPlanets", "Unknown" ); /* Services */ window_moveWidget( wid, "txtSServices", -20, -220 ); window_moveWidget( wid, "txtServices", -20, -220-gl_smallFont.h-5 ); window_modifyText( wid, "txtServices", "Unknown" ); /* * Bottom Text */ window_modifyText( wid, "txtSystemStatus", NULL ); return; } /* System is known */ window_modifyText( wid, "txtSysname", sys->name ); standing = 0.; nstanding = 0.; f = -1; multiple_faction = 0; for (i=0; i<sys->nplanets; i++) { if ((f==-1) && (sys->planets[i]->faction>0)) { f = sys->planets[i]->faction; standing += faction_getPlayer( f ); nstanding++; } else if (f != sys->planets[i]->faction && /** @todo more verbosity */ (sys->planets[i]->faction>0)) { snprintf( buf, PATH_MAX, "Multiple" ); multiple_faction = 1; break; } } if (f == -1) { window_modifyImage( wid, "imgFaction", NULL ); window_moveWidget( wid, "txtSFaction", -20, -60 ); window_moveWidget( wid, "txtFaction", -20, -60-gl_smallFont.h-5 ); window_modifyText( wid, "txtFaction", "NA" ); window_moveWidget( wid, "txtSStanding", -20, -100 ); window_moveWidget( wid, "txtStanding", -20, -100-gl_smallFont.h-5 ); window_modifyText( wid, "txtStanding", "NA" ); y = -100; } else { if (i==sys->nplanets) /* saw them all and all the same */ snprintf( buf, PATH_MAX, "%s", faction_longname(f) ); y = -60; /* Modify the image. */ logo = faction_logoSmall(f); window_modifyImage( wid, "imgFaction", logo ); if (logo != NULL) { window_moveWidget( wid, "imgFaction", -(90-logo->w)/2-20-logo->w, y-(64-logo->h)/2-logo->h ); y -= 64 + 10; } /* Modify the text */ window_modifyText( wid, "txtFaction", buf ); window_modifyText( wid, "txtStanding", faction_getStanding( standing / nstanding ) ); /* Lower text if needed */ window_moveWidget( wid, "txtSFaction", -20, y ); window_moveWidget( wid, "txtFaction", -20, y-gl_smallFont.h-5 ); h = gl_printHeightRaw( &gl_smallFont, 80, buf ); window_moveWidget( wid, "txtSStanding", -20, y ); window_moveWidget( wid, "txtStanding", -20, y-gl_smallFont.h-5 ); y -= 40 + (h - gl_smallFont.h); window_moveWidget( wid, "txtSStanding", -20, y ); window_moveWidget( wid, "txtStanding", -20, y-gl_smallFont.h-5 ); } /* Get security. */ y -= 40; if (sys->nfleets == 0) snprintf(buf, PATH_MAX, "NA" ); else snprintf(buf, PATH_MAX, "%.0f %%", sys->security * 100.); window_moveWidget( wid, "txtSSecurity", -20, y ); window_moveWidget( wid, "txtSecurity", -20, y-gl_smallFont.h-5 ); window_modifyText( wid, "txtSecurity", buf ); /* Get planets */ if (sys->nplanets == 0) { strncpy( buf, "None", PATH_MAX ); window_modifyText( wid, "txtPlanets", buf ); } else { p = 0; buf[0] = '\0'; if (sys->nplanets > 0) p += snprintf( &buf[p], PATH_MAX-p, "%s", sys->planets[0]->name ); for (i=1; i<sys->nplanets; i++) { p += snprintf( &buf[p], PATH_MAX-p, ",\n%s", sys->planets[i]->name ); } window_modifyText( wid, "txtPlanets", buf ); } y -= 40; window_moveWidget( wid, "txtSPlanets", -20, y ); window_moveWidget( wid, "txtPlanets", -20, y-gl_smallFont.h-5 ); /* Get the services */ h = gl_printHeightRaw( &gl_smallFont, 80, buf ); y -= 40 + (h - gl_smallFont.h); window_moveWidget( wid, "txtSServices", -20, y ); window_moveWidget( wid, "txtServices", -20, y-gl_smallFont.h-5 ); services = 0; for (i=0; i<sys->nplanets; i++) services |= sys->planets[i]->services; buf[0] = '\0'; p = 0; /*snprintf(buf, sizeof(buf), "%f\n", sys->prices[0]);*/ /*Hack to control prices. */ if (services & PLANET_SERVICE_COMMODITY) p += snprintf( &buf[p], PATH_MAX-p, "Commodity\n"); if (services & PLANET_SERVICE_OUTFITS) p += snprintf( &buf[p], PATH_MAX-p, "Outfits\n"); if (services & PLANET_SERVICE_SHIPYARD) p += snprintf( &buf[p], PATH_MAX-p, "Shipyard\n"); if (buf[0] == '\0') p += snprintf( &buf[p], PATH_MAX-p, "None"); window_modifyText( wid, "txtServices", buf ); /* * System Status */ buf[0] = '\0'; p = 0; /* Nebula. */ if (sys->nebu_density > 0.) { /* Volatility */ if (sys->nebu_volatility > 700.) p += snprintf(&buf[p], PATH_MAX-p, " Volatile"); else if (sys->nebu_volatility > 300.) p += snprintf(&buf[p], PATH_MAX-p, " Dangerous"); else if (sys->nebu_volatility > 0.) p += snprintf(&buf[p], PATH_MAX-p, " Unstable"); /* Density */ if (sys->nebu_density > 700.) p += snprintf(&buf[p], PATH_MAX-p, " Dense"); else if (sys->nebu_density < 300.) p += snprintf(&buf[p], PATH_MAX-p, " Light"); p += snprintf(&buf[p], PATH_MAX-p, " Nebula"); } /* Interference. */ if (sys->interference > 0.) { if (buf[0] != '\0') p += snprintf(&buf[p], PATH_MAX-p, ","); /* Density. */ if (sys->interference > 700.) p += snprintf(&buf[p], PATH_MAX-p, " Dense"); else if (sys->interference < 300.) p += snprintf(&buf[p], PATH_MAX-p, " Light"); p += snprintf(&buf[p], PATH_MAX-p, " Interference"); } window_modifyText( wid, "txtSystemStatus", buf ); }