/** * @brief Loads a loading screen. */ void loadscreen_load (void) { unsigned int i; char file_path[PATH_MAX]; char **loadscreens; uint32_t nload; /* Count the loading screens */ loadscreens = ndata_list( "gfx/loading/", &nload ); /* Must have loading screens */ if (nload==0) { WARN("No loading screens found!"); loading = NULL; return; } /* Set the zoom. */ gl_cameraZoom( conf.zoom_far ); /* Load the texture */ snprintf( file_path, PATH_MAX, "gfx/loading/%s", loadscreens[ RNG_SANE(0,nload-1) ] ); loading = gl_newImage( file_path, 0 ); /* Create the stars. */ space_initStars( 1000 ); /* Clean up. */ for (i=0; i<nload; i++) free(loadscreens[i]); free(loadscreens); }
/** * @brief Opens a texture. * * @usage t = tex.open( "no_sprites.png" ) * @usage t = tex.open( "spritesheet.png", 6, 6 ) * * @luaparam path Path to open. * @luaparam sx Optional number of x sprites (defaults 1). * @luaparam sy Optional number of y sprites (defaults 1). * @luareturn The opened texture or nil on error. * @luafunc open( path, sx, sy ) */ static int texL_open( lua_State *L ) { const char *path; LuaTex lt; int sx, sy; /* Defaults. */ sx = 0; sy = 0; /* Get path. */ path = luaL_checkstring( L, 1 ); if (lua_gettop(L)>1) { sx = luaL_checkinteger(L,2); sy = luaL_checkinteger(L,3); if ((sx < 0 ) || (sy < 0)) NLUA_ERROR( L, "Spritesheet dimensions must be positive" ); } /* Push new texture. */ if ((sx <=0 ) || (sy <= 0)) lt.tex = gl_newImage( path, 0 ); else lt.tex = gl_newSprite( path, sx, sy, 0 ); if (lt.tex == NULL) return 0; lua_pushtex( L, lt ); return 1; }
/** * @brief Opens up all the land dialogue stuff. * @param p Planet to open stuff for. * @param load Whether or not loading the game. */ void land( Planet* p, int load ) { /* Do not land twice. */ if (landed) return; /* Stop player sounds. */ player_soundStop(); /* Load stuff */ land_planet = p; gfx_exterior = gl_newImage( p->gfx_exterior, 0 ); /* Generate the news. */ if (planet_hasService(land_planet, PLANET_SERVICE_BAR)) news_load(); /* Clear the NPC. */ npc_clear(); /* Create all the windows. */ land_genWindows( load, 0 ); /* Mission forced take off. */ if (land_takeoff) takeoff(0); }
/** * @brief Opens up all the land dialogue stuff. * @param p Planet to open stuff for. * @param load Whether or not loading the game. */ void land( Planet* p, int load ) { /* Do not land twice. */ if (landed) return; /* Resets the player's heat. */ pilot_heatReset( player.p ); /* Stop player sounds. */ player_soundStop(); /* Load stuff */ land_planet = p; gfx_exterior = gl_newImage( p->gfx_exterior, 0 ); /* Generate the news. */ if (planet_hasService(land_planet, PLANET_SERVICE_BAR)) news_load(); /* Clear the NPC. */ npc_clear(); /* Create all the windows. */ land_genWindows( load, 0 ); /* Hack so that load can run player.takeoff(). */ if (load) hooks_run( "load" ); /* Mission forced take off. */ if (land_takeoff) takeoff(0); }
/** * @brief Gets the texture of the planet in exterior. * * @uasge gfx = p:gfxExterior() * @luatparam Planet p Planet Planet to get texture of. * @luatreturn Tex The exterior texture of the planet. * @luafunc gfxExterior( p ) */ static int planetL_gfxExterior( lua_State *L ) { Planet *p; p = luaL_validplanet(L,1); lua_pushtex( L, gl_newImage( p->gfx_exterior, 0 ) ); return 1; }
/** * @brief Gets the texture of the planet in exterior. * * @uasge gfx = p:gfxExterior() * @luaparam p Planet to get texture of. * @luareturn The exterior texture of the planet. * @luafunc gfxExterior( p ) */ static int planetL_gfxExterior( lua_State *L ) { Planet *p; LuaTex lt; p = luaL_validplanet(L,1); lt.tex = gl_newImage( p->gfx_exterior, 0 ); lua_pushtex( L, lt ); return 1; }
/** * @brief Generates the mission list for the bar. * * @param wid Window to create mission list for. */ static int bar_genList( unsigned int wid ) { glTexture **portraits; char **names, *focused; int w, h, iw, ih, bw, bh; int n; /* Get dimensions. */ bar_getDim( wid, &w, &h, &iw, &ih, &bw, &bh ); /* Save focus. */ focused = strdup(window_getFocus(wid)); /* Destroy widget if already exists. */ if (widget_exists( wid, "iarMissions" )) window_destroyWidget( wid, "iarMissions" ); /* We sort just in case. */ npc_sort(); /* Set up missions. */ if (mission_portrait == NULL) mission_portrait = gl_newImage( PORTRAIT_GFX_PATH"news.png", 0 ); n = npc_getArraySize(); if (n <= 0) { n = 1; portraits = malloc(sizeof(glTexture*)); portraits[0] = mission_portrait; names = malloc(sizeof(char*)); names[0] = strdup("News"); } else { n = n+1; portraits = malloc( sizeof(glTexture*) * n ); portraits[0] = mission_portrait; npc_getTextureArray( &portraits[1], n-1 ); names = malloc( sizeof(char*) * n ); names[0] = strdup("News"); npc_getNameArray( &names[1], n-1 ); } window_addImageArray( wid, 20, -40, iw, ih, "iarMissions", 100, 75, portraits, names, n, bar_update, NULL ); /* write the outfits stuff */ bar_update( wid, NULL ); /* Restore focus. */ window_setFocus( wid, focused ); free(focused); return 0; }
/** * @brief Gets the texture of the planet in space. * * @uasge gfx = p:gfxSpace() * @luaparam p Planet to get texture of. * @luareturn The space texture of the planet. * @luafunc gfxSpace( p ) */ static int planetL_gfxSpace( lua_State *L ) { Planet *p; LuaTex lt; p = luaL_validplanet(L,1); if (p->gfx_space == NULL) /* Not loaded. */ lt.tex = gl_newImage( p->gfx_spaceName, OPENGL_TEX_MIPMAPS ); else lt.tex = gl_dupTexture( p->gfx_space ); lua_pushtex( L, lt ); return 1; }
/** * @brief Fade an image in. * * @brief side Present image being displayed. * @brief transition Image in transition or on deck. * @brief img_file Path to the PNG on disk. */ static void intro_fade_image_in( intro_img_t *side, intro_img_t *transition, const char *img_file ) { if (NULL == side->tex) { /* Simple fade-in. */ side->tex = gl_newImage( img_file, 0 ); side->y = (double)SCREEN_H / 2.0 - (side->tex->h / 2.0); side->c.a = 0.0; side->fade_rate = 0.1; } else { /* * Transition or on-deck. The difference is whether one image is * replacing the other (transition), or whether the first must fade out * completely before the second comes in (on-deck). * * We can determine which is the case by seeing whether [fadeout] has been * called. I.e., is side->fade_rate < 0? */ if (NULL != transition->tex) { /* Scrolling is happening faster than fading... */ WARN( "Intro scrolling too fast!" ); gl_freeTexture( transition->tex ); } transition->tex = gl_newImage( img_file, 0 ); transition->y = (double)SCREEN_H / 2.0 - (transition->tex->h / 2.0); transition->c.a = 0.0; if (side->fade_rate < 0.0) transition->fade_rate = 0.0; /* put an image on deck. */ else { /* transition. */ transition->fade_rate = 0.1; side->fade_rate = -0.1; /* begin fading out. */ side->c.a = 0.99; } } }
/** * @brief Opens a texture. * * @luaparam path Path to open. * @luareturn The opened texture or nil on error. * @luafunc open( path ) */ static int texL_open( lua_State *L ) { const char *path; LuaTex lt; /* Get path. */ path = luaL_checkstring( L, 1 ); /* Push new texture. */ lt.tex = gl_newImage( path, 0 ); if (lt.tex == NULL) return 0; lua_pushtex( L, lt ); return 1; }
/** * @brief Parses a single faction, but doesn't set the allies/enemies bit. * * @param temp Faction to load data into. * @param parent Parent node to extract faction from. * @return Faction created from parent node. */ static int faction_parse( Faction* temp, xmlNodePtr parent ) { xmlNodePtr node; int player; char buf[PATH_MAX]; /* Clear memory. */ memset( temp, 0, sizeof(Faction) ); temp->name = xml_nodeProp(parent,"name"); if (temp->name == NULL) WARN("Faction from "FACTION_DATA" has invalid or no name"); player = 0; node = parent->xmlChildrenNode; do { /* Can be 0 or negative, so we have to take that into account. */ if (xml_isNode(node,"player")) { temp->player_def = xml_getFloat(node); player = 1; continue; } xmlr_strd(node,"longname",temp->longname); if (xml_isNode(node, "colour")) temp->colour = col_fromName(xml_raw(node)); if (xml_isNode(node,"logo")) { snprintf( buf, PATH_MAX, FACTION_LOGO_PATH"%s_small.png", xml_get(node)); temp->logo_small = gl_newImage(buf, 0); continue; } if (xml_isNode(node,"static")) { faction_setFlag(temp, FACTION_STATIC); continue; } if (xml_isNode(node,"invisible")) { faction_setFlag(temp, FACTION_INVISIBLE); continue; } } while (xml_nextNode(node)); if (player==0) DEBUG("Faction '%s' missing player tag.", temp->name); return 0; }
/** * @brief Adds a event NPC to the mission computer. */ unsigned int npc_add_event( unsigned int evt, const char *func, const char *name, int priority, const char *portrait, const char *desc ) { NPC_t npc; /* The data. */ npc.type = NPC_TYPE_EVENT; npc.name = strdup( name ); npc.priority = priority; npc.portrait = gl_newImage( portrait, 0 ); npc.desc = strdup( desc ); npc.u.e.id = evt; npc.u.e.func = strdup( func ); return npc_add( &npc ); }
/** * @brief Adds a mission NPC to the mission computer. */ unsigned int npc_add_mission( Mission *misn, const char *func, const char *name, int priority, const char *portrait, const char *desc ) { NPC_t npc; /* The data. */ npc.type = NPC_TYPE_MISSION; npc.name = strdup( name ); npc.priority = priority; npc.portrait = gl_newImage( portrait, 0 ); npc.desc = strdup( desc ); npc.u.m.misn = misn; npc.u.m.func = strdup( func ); return npc_add( &npc ); }
/** * @brief Opens a dialogue window with an ok button, a fixed message and an image. * * @param caption Window title. * @param msg Message to display. * @param width Width of the image. Negative uses image width. * @param height Height of the image. Negative uses image height. */ void dialogue_msgImgRaw( const char* caption, const char *msg, const char *img, int width, int height ) { int w, h, img_width, img_height; glFont* font; unsigned int msg_wid; int done; glTexture *gfx; char buf[PATH_MAX]; /* Get the desired texture */ /* IMPORTANT : texture must not be freed here, it will be freed when the widget closes */ nsnprintf( buf, sizeof(buf), "%s%s", GFX_PATH, img ); gfx = gl_newImage( buf, 0 ); /* Find the popup's dimensions from text and image */ img_width = (width < 0) ? gfx->w : width; img_height = (height < 0) ? gfx->h : height; font = dialogue_getSize( caption, msg, &w, &h ); if (h < img_width) { h = img_width; } /* Create the window */ msg_wid = window_create( caption, -1, -1, img_width + w, 110 + h ); window_setData( msg_wid, &done ); /* Add the text box */ window_addText( msg_wid, img_width+40, -40, w-40, h, 0, "txtMsg", font, &cBlack, msg ); /* Add a placeholder rectangle for the image */ window_addRect( msg_wid, 20, -40, img_width, img_height, "rctGFX", &cGrey10, 1 ); /* Actually add the texture in the rectangle */ window_addImage( msg_wid, 20, -40, img_width, img_height, "ImgGFX", gfx, 0 ); /* Add the OK button */ window_addButton( msg_wid, (img_width+w -50)/2, 20, 50, 30, "btnOK", "OK", dialogue_close ); dialogue_open++; toolkit_loop( &done ); }
/** * @brief Sets the current mission NPC. * * This is used in bar missions where you talk to a person. The portraits are * the ones found in gfx/portraits without the png extension. So for * gfx/portraits/none.png you would just use "none". * * @usage misn.setNPC( "Invisible Man", "none" ) * * @luaparam name Name of the NPC. * @luaparam portrait Name of the portrait to use for the NPC. * @luafunc setNPC( name, portrait ) */ static int misn_setNPC( lua_State *L ) { char buf[PATH_MAX]; const char *name, *str; Mission *cur_mission; cur_mission = misn_getFromLua(L); /* Free if portrait is already set. */ if (cur_mission->portrait != NULL) { gl_freeTexture(cur_mission->portrait); cur_mission->portrait = NULL; } /* Free NPC name. */ if (cur_mission->npc != NULL) { free(cur_mission->npc); cur_mission->npc = NULL; } /* For no parameters just leave having freed NPC. */ if (lua_gettop(L) == 0) return 0; /* Get parameters. */ name = luaL_checkstring(L,1); str = luaL_checkstring(L,2); /* Set NPC name. */ cur_mission->npc = strdup(name); /* Set portrait. */ nsnprintf( buf, PATH_MAX, "gfx/portraits/%s.png", str ); cur_mission->portrait = gl_newImage( buf, 0 ); return 0; }
/** * @brief Opens the main menu (titlescreen). */ void menu_main (void) { int offset_logo, offset_wdw, freespace; unsigned int bwid, wid; glTexture *tex; /* Play load music. */ music_choose("load"); /* Load background and friends. */ tex = gl_newImage( "gfx/NAEV.png", 0 ); main_naevLogo = tex; nebu_prep( 300., 0. ); /* Needed for nebula to not spaz out */ /* Calculate Logo and window offset. */ freespace = SCREEN_H - tex->sh - MAIN_HEIGHT; if (freespace < 0) { /* Not enough freespace, this can get ugly. */ offset_logo = SCREEN_W - tex->sh; offset_wdw = 0; } else { /* We'll want a maximum seperation of 30 between logo and text. */ if (freespace/3 > 25) { freespace -= 25; offset_logo = -25; offset_wdw = -25 - tex->sh - 25; } /* Otherwise space evenly. */ else { offset_logo = -freespace/3; offset_wdw = freespace/3; } } /* create background image window */ bwid = window_create( "BG", -1, -1, SCREEN_W, SCREEN_H ); window_onClose( bwid, menu_main_cleanBG ); window_addRect( bwid, 0, 0, SCREEN_W, SCREEN_H, "rctBG", &cBlack, 0 ); window_addCust( bwid, 0, 0, SCREEN_W, SCREEN_H, "cstBG", 0, menu_main_nebu, NULL, &menu_main_lasttick ); window_addImage( bwid, (SCREEN_W-tex->sw)/2., offset_logo, "imgLogo", tex, 0 ); window_addText( bwid, 0., 10, SCREEN_W, 30., 1, "txtBG", NULL, &cWhite, naev_version(1) ); /* create menu window */ wid = window_create( "Main Menu", -1, offset_wdw, MAIN_WIDTH, MAIN_HEIGHT ); window_addButton( wid, 20, 20 + (BUTTON_HEIGHT+20)*4, BUTTON_WIDTH, BUTTON_HEIGHT, "btnLoad", "Load Game", menu_main_load ); window_addButton( wid, 20, 20 + (BUTTON_HEIGHT+20)*3, BUTTON_WIDTH, BUTTON_HEIGHT, "btnNew", "New Game", menu_main_new ); window_addButton( wid, 20, 20 + (BUTTON_HEIGHT+20)*2, BUTTON_WIDTH, BUTTON_HEIGHT, "btnOptions", "Options", menu_options_button ); window_addButton( wid, 20, 20 + (BUTTON_HEIGHT+20), BUTTON_WIDTH, BUTTON_HEIGHT, "btnCredits", "Credits", menu_main_credits ); window_addButton( wid, 20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnExit", "Exit", menu_exit ); /* Make the background window a parent of the menu. */ window_setParent( bwid, wid ); /* Reset timer. */ menu_main_lasttick = SDL_GetTicks(); menu_Open(MENU_MAIN); }
/** * @brief Opens the main menu (titlescreen). */ void menu_main (void) { int offset_logo, offset_wdw, freespace; unsigned int bwid, wid; glTexture *tex; int h, y; if (menu_isOpen(MENU_MAIN)) { WARN( _("Menu main is already open.") ); return; } /* Clean up GUI - must be done before using SCREEN_W or SCREEN_H. */ gui_cleanup(); player_soundStop(); /* Stop sound. */ /* Play load music. */ music_choose("load"); /* Load background and friends. */ tex = gl_newImage( GFX_PATH"Naev.png", 0 ); main_naevLogo = tex; menu_main_bkg_system(); /* Set dimensions */ y = 20 + (BUTTON_HEIGHT+20)*5; h = y + 80; if (conf.devmode) { h += BUTTON_HEIGHT + 20; y += BUTTON_HEIGHT + 20; } /* Calculate Logo and window offset. */ freespace = SCREEN_H - tex->sh - h; if (freespace < 0) { /* Not enough freespace, this can get ugly. */ offset_logo = SCREEN_W - tex->sh; offset_wdw = 0; } /* Otherwise space evenly. */ else { offset_logo = -freespace/4; offset_wdw = freespace/2; } /* create background image window */ bwid = window_create( "BG", -1, -1, -1, -1 ); window_onClose( bwid, menu_main_cleanBG ); window_setBorder( bwid, 0 ); window_addImage( bwid, (SCREEN_W-tex->sw)/2., offset_logo, 0, 0, "imgLogo", tex, 0 ); window_addText( bwid, 0, 10, SCREEN_W, 30., 1, "txtBG", NULL, &cWhite, naev_version(1) ); /* create menu window */ wid = window_create( "Main Menu", -1, offset_wdw, MAIN_WIDTH, h ); window_setCancel( wid, main_menu_promptClose ); /* Buttons. */ window_addButtonKey( wid, 20, y, BUTTON_WIDTH, BUTTON_HEIGHT, "btnLoad", _("Load Game"), menu_main_load, SDLK_l ); y -= BUTTON_HEIGHT+20; window_addButtonKey( wid, 20, y, BUTTON_WIDTH, BUTTON_HEIGHT, "btnNew", _("New Game"), menu_main_new, SDLK_n ); y -= BUTTON_HEIGHT+20; window_addButtonKey( wid, 20, y, BUTTON_WIDTH, BUTTON_HEIGHT, "btnTutorial", _("Tutorial"), menu_main_tutorial, SDLK_t ); y -= BUTTON_HEIGHT+20; if (conf.devmode) { window_addButtonKey( wid, 20, y, BUTTON_WIDTH, BUTTON_HEIGHT, "btnEditor", _("Editors"), menu_editors_open, SDLK_e ); y -= BUTTON_HEIGHT+20; } window_addButtonKey( wid, 20, y, BUTTON_WIDTH, BUTTON_HEIGHT, "btnOptions", _("Options"), menu_options_button, SDLK_o ); y -= BUTTON_HEIGHT+20; window_addButtonKey( wid, 20, y, BUTTON_WIDTH, BUTTON_HEIGHT, "btnCredits", _("Credits"), menu_main_credits, SDLK_c ); y -= BUTTON_HEIGHT+20; window_addButtonKey( wid, 20, y, BUTTON_WIDTH, BUTTON_HEIGHT, "btnExit", _("Exit"), menu_exit, SDLK_x ); /* Disable load button if there are no saves. */ if (!save_hasSave()) window_disableButton( wid, "btnLoad" ); /* Make the background window a child of the menu. */ window_setParent( bwid, wid ); unpause_game(); menu_Open(MENU_MAIN); }
/** * @brief Parses a single faction, but doesn't set the allies/enemies bit. * * @param temp Faction to load data into. * @param parent Parent node to extract faction from. * @return Faction created from parent node. */ static int faction_parse( Faction* temp, xmlNodePtr parent ) { xmlNodePtr node; int player; char buf[PATH_MAX], *dat; uint32_t ndat; /* Clear memory. */ memset( temp, 0, sizeof(Faction) ); temp->name = xml_nodeProp(parent,"name"); if (temp->name == NULL) WARN("Faction from "FACTION_DATA_PATH" has invalid or no name"); player = 0; node = parent->xmlChildrenNode; do { /* Only care about nodes. */ xml_onlyNodes(node); /* Can be 0 or negative, so we have to take that into account. */ if (xml_isNode(node,"player")) { temp->player_def = xml_getFloat(node); player = 1; continue; } xmlr_strd(node,"longname",temp->longname); xmlr_strd(node,"display",temp->displayname); if (xml_isNode(node, "colour")) { temp->colour = col_fromName(xml_raw(node)); continue; } if (xml_isNode(node, "spawn")) { if (temp->sched_state != NULL) WARN("Faction '%s' has duplicate 'spawn' tag.", temp->name); nsnprintf( buf, sizeof(buf), "dat/factions/spawn/%s.lua", xml_raw(node) ); temp->sched_state = nlua_newState(); nlua_loadStandard( temp->sched_state, 0 ); dat = ndata_read( buf, &ndat ); if (luaL_dobuffer(temp->sched_state, dat, ndat, buf) != 0) { WARN("Failed to run spawn script: %s\n" "%s\n" "Most likely Lua file has improper syntax, please check", buf, lua_tostring(temp->sched_state,-1)); lua_close( temp->sched_state ); temp->sched_state = NULL; } free(dat); continue; } if (xml_isNode(node, "standing")) { if (temp->state != NULL) WARN("Faction '%s' has duplicate 'standing' tag.", temp->name); nsnprintf( buf, sizeof(buf), "dat/factions/standing/%s.lua", xml_raw(node) ); temp->state = nlua_newState(); nlua_loadStandard( temp->state, 0 ); dat = ndata_read( buf, &ndat ); if (luaL_dobuffer(temp->state, dat, ndat, buf) != 0) { WARN("Failed to run standing script: %s\n" "%s\n" "Most likely Lua file has improper syntax, please check", buf, lua_tostring(temp->state,-1)); lua_close( temp->state ); temp->state = NULL; } free(dat); continue; } if (xml_isNode(node, "known")) { faction_setFlag(temp, FACTION_KNOWN); continue; } if (xml_isNode(node, "equip")) { if (temp->equip_state != NULL) WARN("Faction '%s' has duplicate 'equip' tag.", temp->name); nsnprintf( buf, sizeof(buf), "dat/factions/equip/%s.lua", xml_raw(node) ); temp->equip_state = nlua_newState(); nlua_loadStandard( temp->equip_state, 0 ); dat = ndata_read( buf, &ndat ); if (luaL_dobuffer(temp->equip_state, dat, ndat, buf) != 0) { WARN("Failed to run equip script: %s\n" "%s\n" "Most likely Lua file has improper syntax, please check", buf, lua_tostring(temp->equip_state,-1)); lua_close( temp->equip_state ); temp->equip_state = NULL; } free(dat); continue; } if (xml_isNode(node,"logo")) { if (temp->logo_small != NULL) WARN("Faction '%s' has duplicate 'logo' tag.", temp->name); nsnprintf( buf, PATH_MAX, FACTION_LOGO_PATH"%s_small.png", xml_get(node)); temp->logo_small = gl_newImage(buf, 0); nsnprintf( buf, PATH_MAX, FACTION_LOGO_PATH"%s_tiny.png", xml_get(node)); temp->logo_tiny = gl_newImage(buf, 0); continue; } if (xml_isNode(node,"static")) { faction_setFlag(temp, FACTION_STATIC); continue; } if (xml_isNode(node,"invisible")) { faction_setFlag(temp, FACTION_INVISIBLE); continue; } /* Avoid warnings. */ if (xml_isNode(node,"allies") || xml_isNode(node,"enemies")) continue; DEBUG("Unknown node '%s' in faction '%s'",node->name,temp->name); } while (xml_nextNode(node)); if (player==0) DEBUG("Faction '%s' missing player tag.", temp->name); if ((temp->state!=NULL) && faction_isFlag( temp, FACTION_STATIC )) WARN("Faction '%s' has Lua and is static!", temp->name); if ((temp->state==NULL) && !faction_isFlag( temp, FACTION_STATIC )) WARN("Faction '%s' has no Lua and isn't static!", temp->name); return 0; }