diff --git a/dat/planet.xml b/dat/planet.xml index d766ed2..911a9a8 100644 --- a/dat/planet.xml +++ b/dat/planet.xml @@ -21,8 +21,8 @@ </planet> <planet name="SaraCraft"> <pos> - <x>125</x> - <y>-345</y> + <x>0</x> + <y>0</y> </pos> <general> <class>A</class> diff --git a/dat/ssys.xml b/dat/ssys.xml index c155b71..4e204e3 100644 --- a/dat/ssys.xml +++ b/dat/ssys.xml @@ -12,7 +12,6 @@ </general> <planets> <planet>KonoSphere</planet> - <planet>SaraCraft</planet> </planets> <fleets> <fleet chance="100">Enemy Test</fleet> @@ -23,6 +22,9 @@ <fleet chance="50">Sml Merchant Convoy</fleet> <fleet chance="40">Sml Merchant Convoy</fleet> </fleets> + <jumps> + <jump>KonoSys</jump> + </jumps> </ssys> <ssys name="KonoSys"> <pos> @@ -41,5 +43,9 @@ <fleet chance="80">Merchant Ship</fleet> <fleet chance="60">Merchant Ship</fleet> </fleets> + <jumps> + <jump>SaraSys</jump> + </jumps> </ssys> </Systems> + diff --git a/src/ai.c b/src/ai.c index bcc3be9..9d39d40 100644 --- a/src/ai.c +++ b/src/ai.c @@ -58,10 +58,6 @@ // Don't run the function if (n) params aren't passed. #define MIN_ARGS(n) if(lua_gettop(L) < n) return 0 -#define MIN_DIR_ERR 1.0*M_PI/180. -#define MAX_DIR_ERR 0.1*M_PI/180. -#define MIN_VEL_ERR 0.5 - // Ai flags. #define ai_setFlag(f) (pilot_flags |= f) #define ai_isFlag(f) (pilot_flags & f) diff --git a/src/ai.h b/src/ai.h index b4467e4..0ba1fdf 100644 --- a/src/ai.h +++ b/src/ai.h @@ -1,6 +1,11 @@ #pragma once #include "lua.h" +#define MIN_DIR_ERR 1.0*M_PI/180. +#define MAX_DIR_ERR 0.1*M_PI/180. +#define MIN_VEL_ERR 0.5 + + // Max number of AI timers. #define MAX_AI_TIMERS 2 diff --git a/src/input.c b/src/input.c index fcfb883..3661516 100644 --- a/src/input.c +++ b/src/input.c @@ -24,14 +24,13 @@ static Keybind** input_keybinds; // Contains the players keybindings. const char* keybindNames[] = { "accel", "left", "right", "reverse", // Movement. "primary", "target", "target_nearest", "face", "board", // Combat. "secondary", "secondary_next", // Secondary weapons. - "target_planet", "land", // Navigation. + "target_planet", "land", "thyperspace", "jump", // Navigation. "mapzoomin", "mapzoomout", "screenshot", "pause", "menu", // Misc. "end" }; // Must terminate at the end. // From player.c extern double player_turn; extern double player_acc; extern unsigned int player_target; -extern int planet_target; // Grabbed from main.c extern int show_fps; @@ -56,6 +55,9 @@ void input_setDefault(void) { // Space input_setKeybind("target_planet", KEYBIND_KEYBOARD, SDLK_p, 0); input_setKeybind("land", KEYBIND_KEYBOARD, SDLK_l, 0); + input_setKeybind("thyperspace", KEYBIND_KEYBOARD, SDLK_h, 0); + input_setKeybind("jump", KEYBIND_KEYBOARD, SDLK_j, 0); + // Misc. input_setKeybind("mapzoomin", KEYBIND_KEYBOARD, SDLK_UP, 0); input_setKeybind("mapzoomout", KEYBIND_KEYBOARD, SDLK_DOWN, 0); @@ -175,7 +177,7 @@ static void input_key(int keynum, double value, int abs) { else if(KEY("board") && !paused) { if(value == KEY_PRESS) player_board(); } - // Selecting secondary weapon. + // Shooting secondary weapon. else if(KEY("secondary") && !paused) { if(value == KEY_PRESS) player_setFlag(PLAYER_SECONDARY); else if(value == KEY_RELEASE) player_rmFlag(PLAYER_SECONDARY); @@ -184,15 +186,6 @@ static void input_key(int keynum, double value, int abs) { else if(KEY("secondary_next") && !paused) { if(value == KEY_PRESS) player_secondaryNext(); } - // Selecting secondary weapon. - else if(KEY("secondary")) { - if(value == KEY_PRESS) player_setFlag(PLAYER_SECONDARY); - else if(value == KEY_RELEASE) player_rmFlag(PLAYER_SECONDARY); - } - // Selecting secondary weapon. - else if(KEY("secondary_next") && !paused) { - if(value == KEY_PRESS) player_secondaryNext(); - } // Space. // Target planet (cycles just like target). else if(KEY("target_planet") && !paused) { @@ -202,6 +195,12 @@ static void input_key(int keynum, double value, int abs) { else if(KEY("land") && !paused) { if(value == KEY_PRESS) player_land(); } + else if(KEY("thyperspace") && !paused) { + if(value == KEY_PRESS) player_targetHyperspace(); + } + else if(KEY("jump") && !paused) { + if(value == KEY_PRESS) player_jump(); + } // Zoom in. else if(KEY("mapzoomin")) { if(value == KEY_PRESS) player_setRadarRel(1); diff --git a/src/land.c b/src/land.c index 9a96d65..024e147 100644 --- a/src/land.c +++ b/src/land.c @@ -144,8 +144,7 @@ void takeoff(void) { sh = planet->gfx_space->h; // Set player to another position with random facing direction and no velocity. - vect_cset(&player->solid->pos, - planet->pos.x + RNG(-sw/2, sw/2), planet->pos.y + RNG(-sh/2, sh/2)); + player_warp(planet->pos.x + RNG(-sw/2, sw/2), planet->pos.y + RNG(-sh/2, sh/2)); vect_pset(&player->solid->vel, 0., 0.); player->solid->dir = RNG(0, 359) * M_PI/180.; diff --git a/src/menu.h b/src/menu.h index 7e094ce..54eebfc 100644 --- a/src/menu.h +++ b/src/menu.h @@ -1,4 +1,4 @@ -#pragma one +#pragma once void menu_small(void); diff --git a/src/pilot.c b/src/pilot.c index caa21ee..acc5d2d 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -32,10 +32,12 @@ static int nfleets = 0; extern void ai_destroy(Pilot* p); // Ai. extern void ai_think(Pilot* pilot); // Ai.c extern void player_think(Pilot* pilot); // Player.c +extern void player_brokeHyperspace(void); // Player.c extern int gui_load(const char* name); // Player.c // Internal. static void pilot_shootWeapon(Pilot* p, PilotOutfit* w, const unsigned int t); static void pilot_update(Pilot* pilot, const double dt); +static void pilot_hyperspace(Pilot* pilot); void pilot_render(Pilot* pilot); static void pilot_free(Pilot* p); static Fleet* fleet_parse(const xmlNodePtr parent); @@ -107,6 +109,23 @@ Pilot* pilot_get(const unsigned int id) { return NULL; } +// Attempt to turn the pilot to face dir. +double pilot_face(Pilot* p, const float dir) { + double diff, turn; + + diff = angle_diff(p->solid->dir, dir); + + turn = -10.*diff; + if(turn > 1.) turn = 1.; + else if(turn < -1.) turn = -1.; + + p->solid->dir_vel = 0.; + if(turn) + p->solid->dir_vel -= p->ship->turn * turn; + + return diff; +} + // Mkay, this is how we shoot. Listen up. void pilot_shoot(Pilot* p, const unsigned int target, const int secondary) { int i; @@ -230,9 +249,40 @@ static void pilot_update(Pilot* pilot, const double dt) { // Update the solid. (*pilot->solid->update)(pilot->solid, dt); - if(VMOD(pilot->solid->vel) > pilot->ship->speed) { + if(!pilot_isFlag(pilot, PILOT_HYPERSPACE) && VMOD(pilot->solid->vel) > + pilot->ship->speed) // Should not go faster. vect_pset(&pilot->solid->vel, pilot->ship->speed, VANGLE(pilot->solid->vel)); +} + +// Pilot is getting ready or is in, hyperspace. +static void pilot_hyperspace(Pilot* p) { + if(pilot_isFlag(p, PILOT_HYPERSPACE)) { + // Pilot is actually in hyperspace. + if(SDL_GetTicks() > p->ptimer) { + if(p == player) { + player_brokeHyperspace(); + } else + pilot_setFlag(p, PILOT_DELETE); // Set flag to delete pilot. + return; + } + vect_pset(&p->solid->force, p->ship->thrust * 3., p->solid->dir); + } + else if(pilot_isFlag(p, PILOT_HYP_BEGIN)) { + if(SDL_GetTicks() > p->ptimer) { + // Engines are ready. + p->ptimer = SDL_GetTicks() + HYPERSPACE_FLY_DELAY; + pilot_setFlag(p, PILOT_HYPERSPACE); + } + } else { + double diff = pilot_face(p, VANGLE(player->solid->pos)); + + if(diff < MAX_DIR_ERR) { + // We can now prepare the jump. + p->solid->dir_vel = 0.; + p->ptimer = SDL_GetTicks() + HYPERSPACE_ENGINE_DELAY; + pilot_setFlag(p, PILOT_HYP_BEGIN); + } } } @@ -296,7 +346,7 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profi if(flags & PILOT_PLAYER) { pilot->think = player_think; // Players don't need to thing! :P - pilot->render = NULL; + pilot->render = NULL; // Render will be called from player_think pilot_setFlag(pilot, PILOT_PLAYER); // It's a player! player = pilot; gui_load(pilot->ship->gui); // Load the GUI. @@ -382,12 +432,19 @@ void pilots_clean(void) { void pilots_update(double dt) { int i; for(i = 0; i < pilots; i++) { - if(pilot_stack[i]->think && !pilot_isDisabled(pilot_stack[i])) - pilot_stack[i]->think(pilot_stack[i]); - if(pilot_stack[i]->update) - pilot_stack[i]->update(pilot_stack[i], dt); - if(pilot_stack[i]->render) - pilot_stack[i]->render(pilot_stack[i]); + if(pilot_stack[i]->think && !pilot_isDisabled(pilot_stack[i])) { + // Hyperspace gets special treatment. + if(pilot_isFlag(pilot_stack[i], PILOT_HYP_PREP)) + pilot_hyperspace(pilot_stack[i]); + else + pilot_stack[i]->think(pilot_stack[i]); + } + if(pilot_stack[i]->update) { + if(pilot_isFlag(pilot_stack[i], PILOT_DELETE)) + pilot_destroy(pilot_stack[i]); + else + pilot_stack[i]->update(pilot_stack[i], dt); + } } } diff --git a/src/pilot.h b/src/pilot.h index 1d2a50f..53b8bbd 100644 --- a/src/pilot.h +++ b/src/pilot.h @@ -8,6 +8,9 @@ #define PLAYER_ID 1 +#define HYPERSPACE_FLY_DELAY 5000 +#define HYPERSPACE_ENGINE_DELAY 3000 + // Aproximation for pilot size. #define PILOT_SIZE_APROX 0.8 #define PILOT_DISABLED_ARMOUR 0.2 // Based on armour percentage. @@ -21,8 +24,12 @@ // Dynamic. #define PILOT_HOSTILE (1<<1) // Pilot is hostile to the player. #define PILOT_COMBAT (1<<2) // Pilot is engaged in combat. -#define PILOT_HYPERSPACE (1<<3) // Pilot is in hyperspace. -#define PILOT_DISABLED (1<<4) // Pilot is disabled. +#define PILOT_HYP_PREP (1<<5) // Pilot is getting ready for hyperspace. +#define PILOT_HYP_BEGIN (1<<6) // Pilot is starting engines. +#define PILOT_HYPERSPACE (1<<7) // Pilot is in hyperspace. +#define PILOT_DISABLED (1<<9) // Pilot is disabled. +#define PILOT_DELETE (1<<10) // Pilot will get delete asap. + // Just makes life simpler. #define pilot_isPlayer(p) ((p)->flags & PILOT_PLAYER) #define pilot_isDisabled(p) ((p)->flags & PILOT_DISABLED) @@ -60,6 +67,7 @@ typedef struct Pilot { PilotOutfit* ammo; // Secondary ammo (if needed). unsigned int flags; // Used for AI etc. + unsigned int ptimer; // Generic timer for internal pilot use. // AI. AI_Profile* ai; // Ai personality profile. @@ -97,6 +105,7 @@ Fleet* fleet_get(const char* name); void pilot_shoot(Pilot* p, const unsigned int target, const int secondary); void pilot_hit(Pilot* p, const double damage_shield, const double damage_armour); void pilot_setAmmo(Pilot* p); +double pilot_face(Pilot* p, const float dir); // Creation. void pilot_init(Pilot* dest, Ship* ship, char* name, Faction* faction, AI_Profile* ai, diff --git a/src/player.c b/src/player.c index a526f5e..6ba2e69 100644 --- a/src/player.c +++ b/src/player.c @@ -35,12 +35,16 @@ unsigned int player_flags = 0; // Player flags. double player_turn = 0.; // Turn velocity from input. double player_acc = 0.; // Accel velocity from input. unsigned int player_target = PLAYER_ID; // Targetted pilot. -int planet_target = -1; // Targetted planet. +static int planet_target = -1; // Targetted planet. +static int hyperspace_target = -1; // Target hyperspace route. // Pilot stuff for GUI. extern Pilot** pilot_stack; extern int pilots; +// Space stuff for GUI. +extern StarSystem* systems; + // GUI crap. typedef struct { double x,y; // Position. @@ -196,10 +200,15 @@ void player_message(const char* fmt, ...) { msg_stack[0].t = SDL_GetTicks() + msg_timeout; } +void player_warp(const double x, const double y) { + vect_cset(&player->solid->pos, x, y); +} + // Clear the targets. void player_clear(void) { player_target = PLAYER_ID; planet_target = -1; + hyperspace_target = -1; } // Render the background player stuff, namely planet target @@ -320,8 +329,17 @@ void player_render(void) { gl_printMid(&gl_smallFont, (int)gui.nav.w, gui.nav.x, gui.nav.y - 10 - gl_smallFont.h, NULL, "%s", cur_system->planets[planet_target].name); } - else if(planet_target == -1) { - // No planet target. + else if(hyperspace_target >= 0) { + // Hyperspace target. + c = space_canHyperspace(player) ? &cConsole : NULL; + gl_printMid(NULL, (int)gui.nav.w, gui.nav.x, gui.nav.y - 5, + c, "Hyperspace"); + + gl_printMid(&gl_smallFont, (int)gui.nav.w, gui.nav.x, gui.nav.y - 10 - gl_smallFont.h, + NULL, "%s", systems[cur_system->jumps[hyperspace_target]].name); + } + else { + // No NAV target. gl_printMid(NULL, (int)gui.nav.w, gui.nav.x, gui.nav.y - 5, &cConsole, "Navigation"); gl_printMid(&gl_smallFont, (int)gui.nav.w, gui.nav.x, @@ -744,23 +762,21 @@ void gui_free(void) { // Used in pilot.c // Basically uses keyboard input instead of AI input. void player_think(Pilot* player) { - double diff; - if(player_isFlag(PLAYER_FACE) && (player_target != PLAYER_ID)) { - diff = angle_diff(player->solid->dir, + // PLAYER_FACE will take over navigation. + if(player_isFlag(PLAYER_FACE) && (player_target != PLAYER_ID)) + pilot_face(player, vect_angle(&player->solid->pos, &pilot_get(player_target)->solid->pos)); - player_turn = -10.*diff; - if(player_turn > 1.) player_turn = 1.; - else if(player_turn < -1.) player_turn = -1.; + + // PLAYER_REVERSE will take over navigation. + else if(player_isFlag(PLAYER_REVERSE) && (VMOD(player->solid->vel) > 0.)) + pilot_face(player, VANGLE(player->solid->vel) + M_PI); + + // Normal navigation sheme. + else { + player->solid->dir_vel = 0.; + if(player_turn) + player->solid->dir_vel -= player->ship->turn * player_turn; } - else if(player_isFlag(PLAYER_REVERSE) && (VMOD(player->solid->vel) > 0.)) { - diff = angle_diff(player->solid->dir, VANGLE(player->solid->vel)); - player_turn = 10.*diff; - if(player_turn >= 0.) player_turn = 1.; - else if(player_turn < 0.) player_turn = -1; - } - player->solid->dir_vel = 0.; - if(player_turn) - player->solid->dir_vel -= player->ship->turn * player_turn; if(player_isFlag(PLAYER_PRIMARY)) pilot_shoot(player, 0, 0); if(player_isFlag(PLAYER_SECONDARY)) // Needs a target. @@ -801,7 +817,7 @@ void player_board(void) { if((pow2(VX(player->solid->vel)-VX(p->solid->vel)) + pow2(VY(player->solid->vel)-VY(p->solid->vel))) > (double)pow2(MAX_HYPERSPACE_VEL)) { - player_message("You are going too fact to board the ship"); + player_message("You are going too fast to board the ship"); return; } player_message("Boarding ship %s", p->name); @@ -844,6 +860,8 @@ void player_secondaryNext(void) { // Cycle through planet targets. void player_targetPlanet(void) { + hyperspace_target = -1; + if((planet_target == -1) && (cur_system->nplanets > 0)) { // No target. planet_target = 0; @@ -894,6 +912,41 @@ void player_land(void) { } } +void player_targetHyperspace(void) { + planet_target = -1; // Remove planet target. + hyperspace_target++; + + if(hyperspace_target >= cur_system->njumps) + hyperspace_target = -1; +} + +// Actually attempt to jump into hyperspace. +void player_jump(void) { + if(hyperspace_target == -1) return; + + int i = space_hyperspace(player); + + if(i == -1) + player_message("You are too close to gravity centers to initiate hyperspace."); + else if(i == -2) + player_message("You are moving too fast to enter hyperspace."); + else + player_message("Preparing for hyperspace"); +} + +// Player actually broke hyperspace (Let's enter a new system). +void player_brokeHyperspace(void) { + // Enter the new system. + space_init(systems[cur_system->jumps[hyperspace_target]].name); + + // Set position, pilot_update will handle the lowering of velocity. + player_warp(-cos(player->solid->dir) * MIN_HYPERSPACE_DIST * 1.2, + -sin(player->solid->dir) * MIN_HYPERSPACE_DIST * 1.2); + + // Stop hyperspace. + pilot_rmFlag(player, PILOT_HYPERSPACE | PILOT_HYP_BEGIN | PILOT_HYP_PREP); +} + // Take a screenshot. void player_screenshot(void) { char filename[20]; diff --git a/src/player.h b/src/player.h index 5278627..cc27499 100644 --- a/src/player.h +++ b/src/player.h @@ -2,12 +2,12 @@ #include "pilot.h" // Flag definitions. -#define PLAYER_TURN_LEFT (1<<0) // Player is turning left. -#define PLAYER_TURN_RIGHT (1<<1) // Player is turning right. -#define PLAYER_REVERSE (1<<2) -#define PLAYER_FACE (1<<10) // Player is facing target. -#define PLAYER_PRIMARY (1<<11) // Player is shooting primary weapon. -#define PLAYER_SECONDARY (1<<12) // Player is shooting secondary weapon. +#define PLAYER_TURN_LEFT (1<<0) // Player is turning left. +#define PLAYER_TURN_RIGHT (1<<1) // Player is turning right. +#define PLAYER_REVERSE (1<<2) // Player is facint opposite vel. +#define PLAYER_FACE (1<<10) // Player is facing target. +#define PLAYER_PRIMARY (1<<11) // Player is shooting primary weapon. +#define PLAYER_SECONDARY (1<<12) // Player is shooting secondary weapon. // Flag functions. #define player_isFlag(f) (player_flags & f) @@ -33,6 +33,7 @@ void player_renderBG(void); // Render BG layer. // Misc. void player_message(const char* fmt, ...); void player_clear(void); +void player_warp(const double x, const double y); // Keybind actions. void player_setRadarRel(int mod); @@ -40,5 +41,7 @@ void player_board(void); void player_secondaryNext(void); void player_targetPlanet(void); void player_land(void); +void player_targetHyperspace(void); +void player_jump(void); void player_screenshot(void); diff --git a/src/space.c b/src/space.c index 58ce2c6..29c8ddb 100644 --- a/src/space.c +++ b/src/space.c @@ -35,7 +35,7 @@ #define FLAG_ASTEROIDSSET (1<<2) #define FLAG_INTEFERENCESET (1<<3) -static StarSystem* systems = NULL; +StarSystem* systems = NULL; static int nsystems = 0; StarSystem* cur_system = NULL; // Current star system. @@ -56,6 +56,7 @@ static int mstars = 0; // Intern static Planet* planet_get(const char* name); static StarSystem* system_parse(const xmlNodePtr parent); +static void system_parseJumps(const xmlNodePtr parent); static PlanetClass planetclass_get(const char a); // Extern. extern void player_message(const char* fmt, ...); @@ -151,24 +152,26 @@ static PlanetClass planetclass_get(const char a) { }; } -// Hyperspaces, return 0 if entering hyperspace, or distance otherwise. -int space_hyperspace(Pilot* p) { +// Check distance to ensure we can go into hyperspace. +int space_canHyperspace(Pilot* p) { int i; double d; for(i = 0; i < cur_system->nplanets; i++) { d = vect_dist(&p->solid->pos, &cur_system->planets[i].pos); if(d < MIN_HYPERSPACE_DIST) - return (int)(MIN_HYPERSPACE_DIST - d); + return 0; } - // Too fast. - if(VMOD(p->solid->vel) > MAX_HYPERSPACE_VEL) return -1; + return 1; +} - // TODO: All hyperspace worky work. - if(p == player) { - // Player crap. - } else { - - } +// Hyperspace, returns 0 if entering hyperspace, or the distance if not. +int space_hyperspace(Pilot* p) { + if(!space_canHyperspace(p)) return -1; + // Too fast. + if(VMOD(p->solid->vel) > MAX_HYPERSPACE_VEL) return -2; + + // Pilot is now going to get automatically ready for hyperspace. + pilot_setFlag(p, PILOT_HYP_PREP); return 0; } @@ -432,7 +435,47 @@ static StarSystem* system_parse(const xmlNodePtr parent) { return tmp; } +// Load the jumps into a system. +static void system_parseJumps(const xmlNodePtr parent) { + int i; + StarSystem* system; + char* name; + xmlNodePtr cur, node; + + name = xml_nodeProp(parent, "name"); // Already mallocs. + for(i = 0; i < nsystems; i++) + if(strcmp(systems[i].name, name)==0) { + system = &systems[i]; + break; + } + if(i == nsystems) WARN("System '%s' was not found in the stack for some reason", name); + free(name); // No need for it now. + + node = parent->xmlChildrenNode; + + do { + // Load the data. + if(xml_isNode(node, "jumps")) { + cur = node->children; + do { + if(xml_isNode(cur, "jump")) { + for(i = 0; i < nsystems; i++) + if(strcmp(systems[i].name, xml_get(cur))==0) { + system->njumps++; + system->jumps = realloc(system->jumps, system->njumps*sizeof(int)); + system->jumps[system->njumps-1] = i; + break; + } + if(i == nsystems) + WARN("System '%s' not found for jump linking", xml_get(cur)); + } + } while((cur = cur->next)); + } + } while((node = node->next)); +} + // Load the ENTIRE universe into RAM. -- WOAH! -- Wasn't that bad. :P +// -- Used a two system pass to first load the star systems and then set jump routes. int space_load(void) { uint32_t bufsize; char* buf = pack_readfile(DATA, SYSTEM_DATA, &bufsize); @@ -452,6 +495,7 @@ int space_load(void) { ERR("Malformed "SYSTEM_DATA" file: does not contain elements"); return -1; } + // Fist pass - Load all the star systems. do { if(xml_isNode(node, XML_SYSTEM_TAG)) { tmp = system_parse(node); @@ -461,6 +505,14 @@ int space_load(void) { } } while((node = node->next)); + // Second pass - Load all the jump routes. + node = doc->xmlChildrenNode->xmlChildrenNode; + do { + if(xml_isNode(node, XML_SYSTEM_TAG)) + system_parseJumps(node); // Automatically load the jumps into the system. + } while((node = node->next)); + + // Cleanup. xmlFreeDoc(doc); free(buf); xmlCleanupParser(); @@ -506,10 +558,17 @@ void space_exit(void) { free(systems[i].name); if(systems[i].fleets) free(systems[i].fleets); + if(systems[i].jumps) + free(systems[i].jumps); + for(j = 0; j < systems[i].nplanets; j++) { free(systems[i].planets[j].name); if(systems[i].planets[j].description) free(systems[i].planets[j].description); + if(systems[i].planets[j].bar_description) + free(systems[i].planets[j].bar_description); + + // Graphics. if(systems[i].planets[j].gfx_space) gl_freeTexture(systems[i].planets[j].gfx_space); if(systems[i].planets[j].gfx_exterior) diff --git a/src/space.h b/src/space.h index 8169e0b..9c0380e 100644 --- a/src/space.h +++ b/src/space.h @@ -4,7 +4,7 @@ #include "pilot.h" #define MIN_HYPERSPACE_DIST 1500 -#define MAX_HYPERSPACE_VEL 15 +#define MAX_HYPERSPACE_VEL 25 // Planet types. I didn't take them from Star Trek, I promise. typedef enum { @@ -72,6 +72,9 @@ typedef struct { SystemFleet* fleets; // Fleets that can appear in the current system. int nfleets; // Total number of fleets. + + int* jumps; // Adjacent star system index number. + int njumps; // Number of adjacent jumps. } StarSystem; extern StarSystem* cur_system; // Current star system. @@ -86,6 +89,7 @@ void space_render(double dt); void planets_render(void); // Misc. +int space_canHyperspace(Pilot* p); int space_hyperspace(Pilot* p); extern char* stardate; diff --git a/src/toolkit.c b/src/toolkit.c index dc88def..0b71861 100644 --- a/src/toolkit.c +++ b/src/toolkit.c @@ -7,7 +7,8 @@ typedef enum { WIDGET_NULL, WIDGET_BUTTON, WIDGET_TEXT, - WIDGET_IMAGE + WIDGET_IMAGE, + WIDGET_LIST } WidgetType; typedef enum { @@ -33,7 +34,7 @@ typedef struct { }; // Widget text. struct { - char* text; + char* text; // Use printMid for centered printText if not. glFont* font; glColour* colour; int centered; @@ -42,6 +43,12 @@ typedef struct { // Widget image. glTexture* image; }; + struct { + // Widget list. + char** options; // Pointer to the options. + int noptions; // total number of options. + int selected; // Currently selected option. + }; }; } Widget; @@ -139,6 +146,26 @@ void window_addImage(const unsigned int wid, const int x, const int y, else wgt->y = (double)y; } +void window_addList(const unsigned int wid, const int x, const int y, + const int w, const int h, char* name, char** items, int nitems, int defitem) { + + Window *wdw = window_wget(wid); + Widget* wgt = window_newWidget(wdw); + + wgt->type = WIDGET_LIST; + wgt->name = strdup(name); + + wgt->options = items; + wgt->noptions = nitems; + wgt->selected = defitem; // -1 would be none. + wgt->w = (double) w; + wgt->h = (double) h; + if(x < 0) wgt->x = wdw->w - wgt->w + x; + else wgt->x = (double) x; + if(y < 0) wgt->y = wdw->h - wgt->h + y; + else wgt->y = (double) y; +} + // Return pointer to newly allocated widget. static Widget* window_newWidget(Window* w) { Widget* wgt = NULL; @@ -458,6 +485,9 @@ static void window_render(Window* w) { case WIDGET_IMAGE: toolkit_renderImage(&w->widgets[i], x, y); break; + case WIDGET_LIST: + // TODO widget list rendering. + break; } } }