naev 0.12.5
land.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "physfs.h"
11#include <math.h>
12#include <stdio.h>
13#include <stdlib.h>
14
15#include "naev.h"
17
18#include "land.h"
19
20#include "array.h"
21#include "camera.h"
22#include "conf.h"
23#include "dialogue.h"
24#include "economy.h"
25#include "equipment.h"
26#include "event.h"
27#include "gui.h"
28#include "gui_omsg.h"
29#include "hook.h"
30#include "land_outfits.h"
31#include "land_shipyard.h"
32#include "land_trade.h"
33#include "log.h"
34#include "map.h"
35#include "menu.h"
36#include "mission.h"
37#include "music.h"
38#include "ndata.h"
39#include "news.h"
40#include "nlua.h"
41#include "nlua_tk.h"
42#include "npc.h"
43#include "nstring.h"
44#include "ntime.h"
45#include "ntracing.h"
46#include "player.h"
47#include "player_autonav.h"
48#include "player_fleet.h"
49#include "rng.h"
50#include "save.h"
51#include "sound.h"
52#include "toolkit.h"
53
54/*
55 * we use visited flags to not duplicate missions generated
56 */
57#define VISITED_LAND ( 1 << 0 )
58#define VISITED_COMMODITY \
59 ( 1 << 1 )
60
61#define VISITED_BAR ( 1 << 2 )
62#define VISITED_OUTFITS ( 1 << 3 )
63#define VISITED_SHIPYARD ( 1 << 4 )
64#define VISITED_EQUIPMENT ( 1 << 5 )
65#define VISITED_MISSION \
66 ( 1 << 6 )
67#define visited( f ) ( land_visited |= ( f ) )
68#define has_visited( f ) \
69 ( land_visited & ( f ) )
70static unsigned int land_visited = 0;
71
72/* Which tabs have been generated by their respective open functions. */
73unsigned int land_generated = 0;
74
75/*
76 * land variables
77 */
78int landed = 0;
79int land_loaded = 0;
80static int land_takeoff = 0;
82 0;
83unsigned int land_wid = 0;
84static int land_regen = 0;
85static int land_windowsMap[LAND_NUMWINDOWS];
86static unsigned int *land_windows = NULL;
87Spob *land_spob = NULL;
89 NULL;
90
91/*
92 * mission computer stack
93 */
94static Mission *mission_computer = NULL;
96 NULL;
98
99/*
100 * Bar stuff.
101 */
103
104/*
105 * player stuff
106 */
107static int last_window = 0;
108
109/*
110 * Error handling.
111 */
112static char errorlist[STRMAX_SHORT];
113static char errorreason[STRMAX_SHORT];
114static int errorappend;
115static char *errorlist_ptr;
116
117/*
118 * Rescue.
119 */
120static nlua_env rescue_env = LUA_NOREF;
121static void land_stranded( void );
122
123/*
124 * prototypes
125 */
126static int land_gc( void *unused );
127static int land_hasLocalMap( void );
128static void land_createMainTab( unsigned int wid );
129static void land_setupTabs( void );
130static void land_cleanupWindow( unsigned int wid, const char *name );
131static void land_changeTab( unsigned int wid, const char *wgt, int old,
132 int tab );
133/* spaceport bar */
134static void bar_getDim( int wid, int *w, int *h, int *iw, int *ih, int *bw,
135 int *bh );
136static void bar_open( unsigned int wid );
137static int bar_genList( unsigned int wid );
138static void bar_update( unsigned int wid, const char *str );
139static void bar_close( unsigned int wid, const char *str );
140static void bar_approach( unsigned int wid, const char *str );
141static int news_load( void );
142/* mission computer */
143static void misn_popdown( unsigned int wid, const char *str );
144static void misn_popdownActivate( unsigned int wid, const char *str );
145static void misn_popdownSelect( unsigned int wid, const char *str );
146static void misn_computerOptions( unsigned int wid, const char *str );
147static void misn_computerOptionsRegen( unsigned int wid, const char *str );
148static void misn_computerOptionsClose( unsigned int wid, const char *name );
149static void misn_open( unsigned int wid );
150static void misn_autonav( unsigned int wid, const char *str );
151static void misn_accept( unsigned int wid, const char *str );
152static void misn_genList( unsigned int wid );
153static void misn_update( unsigned int wid, const char *str );
154static void misn_popdown( unsigned int wid, const char *str );
155
160{
161 land_takeoff = 1;
162 land_takeoff_nosave = player_isFlag( PLAYER_NOSAVE );
163}
164
165void land_needsTakeoff( int delay )
166{
167 if ( land_takeoff )
169}
170
171/* Maps are only offered if the spob provides fuel. */
172static int land_hasLocalMap( void )
173{
174 if ( !spob_hasService( land_spob, SPOB_SERVICE_REFUEL ) )
175 return 0;
176 return 1;
177}
178
182int land_canSave( void )
183{
184 /* Overrided case. */
185 if ( player_isFlag( PLAYER_NOSAVE ) )
186 return 0;
187
188 /* If the current landed planet is refuelable, no need to check if can land.
189 */
190 if ( ( land_spob != NULL ) &&
191 spob_hasService( land_spob, SPOB_SERVICE_REFUEL ) )
192 return 1;
193
194 /* For other places we'll have to see if can land. */
195 for ( int i = 0; i < array_size( cur_system->spobs ); i++ ) {
196 Spob *p = cur_system->spobs[i];
197 spob_updateLand( p );
198 if ( spob_hasService( p, SPOB_SERVICE_REFUEL ) && p->can_land )
199 return 1;
200 }
201 return 0;
202}
203
208{
209 if ( landed && land_loaded )
210 return 1;
211 return 0;
212}
213
217void land_errClear( void )
218{
219 errorlist_ptr = NULL; /* Clear errors. */
220}
221
226void land_errDialogueBuild( const char *fmt, ... )
227{
228 va_list ap;
229
230 if ( fmt == NULL )
231 return;
232 va_start( ap, fmt );
233 vsnprintf( errorreason, sizeof( errorreason ), fmt, ap );
234 va_end( ap );
235
236 if ( errorlist_ptr == NULL ) /* Initialize on first run. */
237 errorappend =
238 scnprintf( errorlist, sizeof( errorlist ), "%s", errorreason );
239 else /* Append newest error to the existing list. */
240 scnprintf( &errorlist[errorappend], sizeof( errorlist ) - errorappend,
241 "\n%s", errorreason );
242 errorlist_ptr = errorlist;
243}
244
249{
250 if ( errorlist_ptr != NULL ) {
251 dialogue_alert( "%s", errorlist );
252 return 1;
253 }
254 return 0;
255}
256
260static void bar_getDim( int wid, int *w, int *h, int *iw, int *ih, int *bw,
261 int *bh )
262{
263 /* Get window dimensions. */
264 window_dimWindow( wid, w, h );
265
266 /* Calculate dimensions of portraits. */
267 *iw = 704 + ( *w - LAND_WIDTH );
268 *ih = *h - 60;
269
270 /* Calculate button dimensions. */
271 *bw = MIN( LAND_BUTTON_WIDTH, ( *w - *iw - 80 ) / 2 );
272 *bh = LAND_BUTTON_HEIGHT;
273}
274
277static void bar_open( unsigned int wid )
278{
279 int w, h, iw, ih, bw, bh, dh, th;
280 const char *desc;
281
282 /* Mark as generated. */
283 land_tabGenerate( LAND_WINDOW_BAR );
284
285 /* Set window functions. */
287
288 /* Get dimensions. */
289 desc = ( land_spob->bar_description != NULL )
290 ? _( land_spob->bar_description )
291 : "(NULL)";
292 bar_getDim( wid, &w, &h, &iw, &ih, &bw, &bh );
293 dh = gl_printHeightRaw( &gl_defFont, w - iw - 60, desc );
294
295 /* Approach when pressing enter */
297
298 /* Buttons */
299 window_addButtonKey( wid, -20, 20, bw, bh, "btnCloseBar", _( "Take Off" ),
300 land_buttonTakeoff, SDLK_t );
301 window_addButtonKey( wid, -20 - bw - 20, 20, bw, bh, "btnApproach",
302 p_( "bar", "Approach" ), bar_approach, SDLK_a );
303
304 /* Bar description. */
305 window_addText( wid, iw + 40, -40, w - iw - 60, dh, 0, "txtDescription",
306 &gl_defFont, NULL, desc );
307
308 /* Add portrait text. */
309 th = -40 - dh - 40;
310 window_addText( wid, iw + 40, th, w - iw - 60, gl_defFont.h, 1,
311 "txtPortrait", &gl_defFont, NULL, NULL );
312
313 /* Add mission description text. */
314 th -= 20 + PORTRAIT_HEIGHT + 20 + 20;
315 window_addText( wid, iw + 60, th, w - iw - 100, h + th - ( 2 * bh + 60 ), 0,
316 "txtMission", &gl_defFont, NULL, NULL );
317
318 /* Generate the mission list. */
319 bar_genList( wid );
320}
321
327static int bar_genList( unsigned int wid )
328{
329 ImageArrayCell *portraits;
330 int w, h, iw, ih, bw, bh;
331 int n, pos, marktab;
332
333 /* Validity check. */
334 if ( wid == 0 )
335 return 0;
336
337 /* Get dimensions. */
338 bar_getDim( wid, &w, &h, &iw, &ih, &bw, &bh );
339 marktab = 0;
340
341 /* Destroy widget if already exists. */
342 if ( widget_exists( wid, "iarMissions" ) ) {
343 /* Store position. */
344 pos = toolkit_getImageArrayPos( wid, "iarMissions" );
345 window_destroyWidget( wid, "iarMissions" );
346 } else
347 pos = -1;
348
349 /* We sort just in case. */
350 npc_sort();
351
352 /* Set up missions. */
353 if ( mission_portrait == NULL )
354 mission_portrait = gl_newImage( PORTRAIT_GFX_PATH "news.webp", 0 );
355 n = npc_getArraySize();
356 if ( n <= 0 ) {
357 n = 1;
358 portraits = calloc( 1, sizeof( ImageArrayCell ) );
359 portraits[0].image = gl_dupTexture( mission_portrait );
360 portraits[0].caption = strdup( _( "News" ) );
361 } else {
362 n = n + 1;
363 portraits = calloc( n, sizeof( ImageArrayCell ) );
364 portraits[0].image = gl_dupTexture( mission_portrait );
365 portraits[0].caption = strdup( _( "News" ) );
366 for ( int i = 0; i < npc_getArraySize(); i++ ) {
367 ImageArrayCell *p = &portraits[i + 1];
368 const glTexture *bg = npc_getBackground( i );
369 p->caption = strdup( npc_getName( i ) );
370 if ( bg != NULL ) {
371 p->image = gl_dupTexture( bg );
372 p->layers = gl_addTexArray( p->layers,
374 } else
375 p->image = gl_dupTexture( npc_getTexture( i ) );
376 if ( npc_isImportant( i ) ) {
377 p->layers = gl_addTexArray(
378 p->layers,
379 gl_newImage( OVERLAY_GFX_PATH "portrait_exclamation.webp", 0 ) );
380 marktab = 1;
381 }
382 }
383 }
384 window_addImageArray( wid, 20, -40, iw, ih, "iarMissions", 128, 96,
385 portraits, n, bar_update, bar_approach, bar_approach );
386
387 /* Restore position. */
388 toolkit_setImageArrayPos( wid, "iarMissions", pos );
389
390 /* write the outfits stuff */
391 bar_update( wid, NULL );
392
393 /* Set default keyboard focus. */
394 window_setFocus( wid, "iarMissions" );
395
396 /* Determine if we want to mark the spaceport bar tab. */
397 if ( marktab )
398 window_tabWinSetTabName( land_wid, "tabLand",
399 land_windowsMap[LAND_WINDOW_BAR],
400 _( "Spaceport Bar #r!!#0" ) );
401 else
402 window_tabWinSetTabName( land_wid, "tabLand",
403 land_windowsMap[LAND_WINDOW_BAR],
404 _( "Spaceport Bar" ) );
405
406 return 0;
407}
408
411void misn_patchMission( const Mission *misn )
412{
414 misn_regen();
415}
416
419void misn_regen( void )
420{
421 if ( !landed )
422 return;
423 if ( !land_loaded )
424 return;
425 if ( land_spob == NULL )
426 return;
427 misn_genList( land_getWid( LAND_WINDOW_MISSION ) );
428}
429
432void bar_regen( void )
433{
434 if ( !landed )
435 return;
436 if ( !land_loaded )
437 return;
438 if ( land_spob == NULL )
439 return;
440 NTracingZone( _ctx, 1 );
441 bar_genList( land_getWid( LAND_WINDOW_BAR ) );
442 NTracingZoneEnd( _ctx );
443}
444
449static void bar_update( unsigned int wid, const char *str )
450{
451 (void)str;
452 int pos;
453 int w, h, iw, ih, bw, bh, dh;
454
455 /* Get dimensions. */
456 bar_getDim( wid, &w, &h, &iw, &ih, &bw, &bh );
457 dh = gl_printHeightRaw( &gl_defFont, w - iw - 60,
458 _( land_spob->bar_description ) );
459
460 /* Get array. */
461 pos = toolkit_getImageArrayPos( wid, "iarMissions" );
462
463 /* See if is news. */
464 if ( pos == 0 ) { /* News selected. */
465 /* Destroy news widget if needed. */
466 if ( widget_exists( wid, "cstNews" ) )
467 window_destroyWidget( wid, "cstNews" );
468
469 /* Destroy portrait. */
470 if ( widget_exists( wid, "imgPortrait" ) )
471 window_destroyWidget( wid, "imgPortrait" );
472 if ( widget_exists( wid, "imgPortraitBG" ) )
473 window_destroyWidget( wid, "imgPortraitBG" );
474
475 /* Disable button. */
476 window_disableButton( wid, "btnApproach" );
477
478 /* Clear text. */
479 window_modifyText( wid, "txtPortrait", NULL );
480 window_modifyText( wid, "txtMission", NULL );
481
482 /* Create news. */
483 news_widget( wid, iw + 60, -40 - ( 40 + dh ), w - iw - 100,
484 h - 40 - ( dh + 20 ) - 40 - bh - 20 );
485 return;
486 }
487
488 /* Shift to ignore news now. */
489 pos--;
490
491 /* Destroy news widget if needed. */
492 if ( widget_exists( wid, "cstNews" ) )
493 window_destroyWidget( wid, "cstNews" );
494
495 /* Create widgets if needed. */
496 if ( !widget_exists( wid, "imgPortraitBG" ) ) /* Must be first */
497 window_addImage( wid, iw + 40 + ( w - iw - 60 - PORTRAIT_WIDTH ) / 2,
498 -( 40 + dh + 40 + gl_defFont.h + 20 + PORTRAIT_HEIGHT ),
499 0, 0, "imgPortraitBG", NULL, 1 );
500 if ( !widget_exists( wid, "imgPortrait" ) )
501 window_addImage( wid, iw + 40 + ( w - iw - 60 - PORTRAIT_WIDTH ) / 2,
502 -( 40 + dh + 40 + gl_defFont.h + 20 + PORTRAIT_HEIGHT ),
503 0, 0, "imgPortrait", NULL, 1 );
504
505 /* Enable button. */
506 window_enableButton( wid, "btnApproach" );
507
508 /* Set portrait. */
509 window_modifyText( wid, "txtPortrait", npc_getName( pos ) );
510 window_modifyImage( wid, "imgPortrait", npc_getTexture( pos ),
511 PORTRAIT_WIDTH, PORTRAIT_HEIGHT );
512 window_modifyImage( wid, "imgPortraitBG", npc_getBackground( pos ),
513 PORTRAIT_WIDTH, PORTRAIT_HEIGHT );
514
515 /* Set mission description. */
516 window_modifyText( wid, "txtMission", npc_getDesc( pos ) );
517}
518
523static void bar_close( unsigned int wid, const char *name )
524{
525 (void)wid;
526 (void)name;
527
528 /* Must not be regenerating. */
529 if ( land_regen ) {
530 land_regen--;
531 return;
532 }
533
535 mission_portrait = NULL;
536}
537
540static void bar_approach( unsigned int wid, const char *str )
541{
542 (void)str;
543 int pos, n;
544
545 /* Get position. */
546 pos = toolkit_getImageArrayPos( wid, "iarMissions" );
547
548 /* Should never happen, but in case news is selected */
549 if ( pos == 0 )
550 return;
551
552 /* Ignore news. */
553 pos--;
554
555 n = npc_getArraySize();
556 npc_approach( pos );
557 /* This check is necessary if the player quits the game in the middle of an
558 * NPC approach. */
559 if ( land_spob == NULL )
560 return;
561 bar_genList( wid ); /* Always just in case. */
562
563 /* Focus the news if the number of NPCs has changed. */
564 if ( n != npc_getArraySize() )
565 toolkit_setImageArrayPos( wid, "iarMissions", 0 );
566
567 /* Reset markers. */
569
570 /* Mission forced take off. */
571 land_needsTakeoff( 0 );
572}
573
578static int news_load( void )
579{
580 generate_news( land_spob->presence.faction );
581 return 0;
582}
583
587static void misn_open( unsigned int wid )
588{
589 int w, h, y;
590
591 /* Mark as generated. */
592 land_tabGenerate( LAND_WINDOW_MISSION );
593
594 /* Get window dimensions. */
595 window_dimWindow( wid, &w, &h );
596
597 /* buttons */
598 int bw = MIN( LAND_BUTTON_WIDTH, ( w / 2 - 80 ) / 3 );
599 window_addButtonKey( wid, -20, 20, bw, LAND_BUTTON_HEIGHT, "btnCloseMission",
600 _( "Take Off" ), land_buttonTakeoff, SDLK_t );
601 window_addButtonKey( wid, -20 - bw - 20, 20, bw, LAND_BUTTON_HEIGHT,
602 "btnAcceptMission", _( "Accept Mission" ), misn_accept,
603 SDLK_a );
604 window_addButtonKey( wid, -20 - 2 * ( bw + 20 ), 20, bw, LAND_BUTTON_HEIGHT,
605 "btnAutonavMission", _( "Autonav" ), misn_autonav,
606 SDLK_n );
607
608 /* text */
609 y = -60;
610 window_addText( wid, w / 2 + 10, y, w / 2 - 30, 40, 0, "txtSDate", NULL,
611 &cFontGrey,
612 _( "Date:\n"
613 "Free Space:" ) );
614 window_addText( wid, w / 2 + 110, y, w / 2 - 130, 40, 0, "txtDate", NULL,
615 NULL, NULL );
616 y -= 2 * gl_defFont.h + 30;
617 window_addText( wid, w / 2 + 10, y, w / 2 - 30, 50, 0, "txtHeader",
618 &gl_defFont, NULL, NULL );
619 y -= 50;
620 window_addText( wid, w / 2 + 10, y, w / 2 - 30,
621 y - 40 + h - 2 * LAND_BUTTON_HEIGHT, 0, "txtDesc",
622 &gl_defFont, NULL, NULL );
623
624 /* map */
625 map_show( wid, 20, 20, w / 2 - 30, h / 2 - 35, 0.75, 0., 0. );
626
627 misn_genList( wid );
628 space_clearComputerMarkers(); /* Don't want markers at the beginning. */
629}
630
635static void misn_autonav( unsigned int wid, const char *str )
636{
637 Mission *misn;
638 const StarSystem *sys;
639 int misn_ref;
640 (void)str;
641
642 /* Makes sure current mission has system */
643 misn_ref = mission_computer_filter[toolkit_getListPos( wid, "lstMission" )];
644 misn = &mission_computer[misn_ref];
645 sys = mission_sysComputerMark( misn );
646 if ( sys == NULL )
647 return;
648
649 /* Select mission's target system */
650 map_select( sys, 0 );
651
652 /* Autonav to target system */
655}
656
661static void misn_accept( unsigned int wid, const char *str )
662{
663 (void)str;
664 const char *misn_name = toolkit_getList( wid, "lstMission" );
665
666 /* Make sure you have missions. */
667 if ( strcmp( misn_name, _( "No Missions" ) ) == 0 )
668 return;
669
670 if ( dialogue_YesNo(
671 _( "Accept Mission" ),
672 _( "Are you sure you want to accept this mission?" ) ) ) {
673 int changed = 0;
674 int pos = toolkit_getListPos( wid, "lstMission" );
675 int misn_ref = mission_computer_filter[pos];
676 Mission *misn = &mission_computer[misn_ref];
677 int ret = mission_accept( misn );
678 if ( ret == -1 ) { /* Errored out. */
679 mission_cleanup( &mission_computer[misn_ref] );
680 changed = 1;
681 }
682 if ( ( ret == 2 ) || ( ret == 3 ) ) /* Deleted or accepted. */
683 changed = 1;
684
685 if ( changed ) {
687 &mission_computer[misn_ref + 1] );
688
689 /* Regenerate list. */
690 misn_genList( wid );
691 }
692
693 /* Reset markers. */
695 }
696}
697
701static int *misn_filter( const Mission *misn )
702{
703 int *filtered = array_create_size( int, array_size( misn ) );
704 for ( int i = 0; i < array_size( misn ); i++ ) {
705 if ( misn_opts.hideillegal && misn[i].illegal )
706 continue;
707 array_push_back( &filtered, i );
708 }
709 return filtered;
710}
711
715static int misn_cmp( const void *p1, const void *p2 )
716{
717 int r1 = *(const int *)p1;
718 int r2 = *(const int *)p2;
719 const Mission *m1 = &mission_computer[r1];
720 const Mission *m2 = &mission_computer[r2];
721 credits_t c;
722
723 switch ( misn_opts.sortby ) {
724 case MISNCOMPUTER_SORT_PRIORITY:
725 default:
726 /* Just fall through to default. */
727 break;
728
729 /* Case sorting by reward. */
730 case MISNCOMPUTER_SORT_REWARD:
731 c = m2->reward_value - m1->reward_value;
732 if ( c )
733 return c;
734 break;
735
736 case MISNCOMPUTER_SORT_DISTANCE:
737 c = m1->distance - m2->distance;
738 if ( c )
739 return c;
740 break;
741 }
742
743 /* Default search priority. */
744 if ( m1->data->avail.priority < m2->data->avail.priority )
745 return -1;
746 else if ( m1->data->avail.priority > m2->data->avail.priority )
747 return +1;
748
749 return strcmp( m1->data->name, m2->data->name );
750}
751
755static void misn_popdown( unsigned int wid, const char *str )
756{
757 const char *name = "lstMissionPopdown";
758 const char *sort[] = {
759 [MISNCOMPUTER_SORT_PRIORITY] = _( "Sort by Priority" ),
760 [MISNCOMPUTER_SORT_REWARD] = _( "Sort by Reward" ),
761 [MISNCOMPUTER_SORT_DISTANCE] = _( "Sort by Distance" ),
762 [MISNCOMPUTER_SORT_SETTINGS] = _( "Settings" ),
763 };
764 size_t n = sizeof( sort ) / sizeof( sort[0] );
765 char **sortlist;
766 int x, y, w, h;
767
768 if ( widget_exists( wid, name ) ) {
769 window_destroyWidget( wid, name );
770 return;
771 }
772
773 sortlist = malloc( sizeof( sort ) );
774 for ( size_t i = 0; i < n; i++ )
775 sortlist[i] = strdup( _( sort[i] ) );
776
777 window_dimWidget( wid, str, &w, &h );
778 window_posWidget( wid, str, &x, &y );
779 window_addList( wid, x + w, y - 120 + h, 350, 120, name, sortlist, n,
780 misn_opts.sortby, misn_popdownSelect, misn_popdownActivate );
781 window_setFocus( wid, name );
782}
783
784static void misn_popdownSelect( unsigned int wid, const char *str )
785{
786 MissionComputerSort p = toolkit_getListPos( wid, str );
787 if ( p == MISNCOMPUTER_SORT_SETTINGS ) {
788 misn_computerOptions( wid, str );
789 window_destroyWidget( wid, str );
790 return;
791 }
792
793 /* Change sort setting. */
794 if ( misn_opts.sortby != p ) {
795 misn_opts.sortby = p;
796 misn_genList( land_getWid( LAND_WINDOW_MISSION ) );
797 }
798}
799
800static void misn_popdownActivate( unsigned int wid, const char *str )
801{
802 misn_popdownSelect( wid, str );
803 window_destroyWidget( wid, str );
804}
805
806static void misn_computerOptionsRegen( unsigned int wid, const char *str )
807{
808 (void)str;
809 MissionComputerOptions opts = misn_opts;
810 misn_opts.sortby = toolkit_getListPos( wid, "lstSort" );
811 if ( widget_exists( wid, "chkHideIllegal" ) )
812 misn_opts.hideillegal = window_checkboxState( wid, "chkHideIllegal" );
813 /* Only regenerate if changed. */
814 if ( memcmp( &misn_opts, &opts, sizeof( MissionComputerOptions ) ) )
815 misn_genList( land_getWid( LAND_WINDOW_MISSION ) );
816}
817
823static void misn_computerOptionsClose( unsigned int wid, const char *name )
824{
825 misn_computerOptionsRegen( wid, name );
826 window_close( wid, name );
827}
828
832static void misn_computerOptions( unsigned int wid, const char *str )
833{
834 (void)wid;
835 (void)str;
836 int w = 240;
837 int h = 300;
838 const char *sort[] = {
839 [MISNCOMPUTER_SORT_PRIORITY] = _( "Priority (Default)" ),
840 [MISNCOMPUTER_SORT_REWARD] = _( "Reward" ),
841 [MISNCOMPUTER_SORT_DISTANCE] = _( "Distance" ),
842 };
843 size_t l = sizeof( sort ) / sizeof( sort[0] );
844 char **sortD;
845 int mwid;
846 int y;
847
848 /* Create the window. */
849 mwid = window_create( "wdwMisnPopdown", _( "Mission Computer Settings" ), -1,
850 -1, w, h );
853
854 /* Sorting. */
855 y = -40;
856 window_addText( mwid, 20, y, 100, h - LAND_BUTTON_HEIGHT, 0, "txtSSort",
857 &gl_defFont, NULL, _( "Sort by:" ) );
858 y -= 20;
859 sortD = malloc( sizeof( char * ) * l );
860 for ( size_t i = 0; i < l; i++ )
861 sortD[i] = strdup( sort[i] );
862 window_addList( mwid, 20, y, 200, 100, "lstSort", sortD, l, 0,
863 misn_computerOptionsRegen, NULL );
864 y -= 100 + 10;
865
866 /* Filtering. */
867 window_addCheckbox( mwid, 20, y, w - 40, 30, "chkHideIllegal",
868 _( "Hide Illegal Missions" ), misn_computerOptionsRegen,
869 misn_opts.hideillegal );
870
871 /* Close button. */
872 window_addButton( mwid, -20, 20, LAND_BUTTON_WIDTH, LAND_BUTTON_HEIGHT,
873 "btnClose", _( "Close" ), misn_computerOptionsClose );
874}
875
880static void misn_genList( unsigned int wid )
881{
882 char **misn_names;
883 int j, w, h, pos;
884
885 /* Validity check. */
886 if ( wid == 0 )
887 return;
888
889 if ( widget_exists( wid, "lstMission" ) ) {
890 pos = toolkit_getListPos( wid, "lstMission" );
891 window_destroyWidget( wid, "lstMission" );
892 window_destroyWidget( wid, "btnMissionFilter" );
893 } else
894 pos = -1;
895
896 /* Get window dimensions. */
897 window_dimWindow( wid, &w, &h );
898
899 /* Resort just in case. */
903 sizeof( int ), misn_cmp );
904
905 /* list */
906 j = 1; /* make sure we don't accidentally free the memory twice. */
907 misn_names = NULL;
908 if ( array_size( mission_computer_filter ) > 0 ) { /* there are missions */
909 misn_names =
910 malloc( sizeof( char * ) * array_size( mission_computer_filter ) );
911 j = 0;
912 for ( int i = 0; i < array_size( mission_computer_filter ); i++ ) {
913 int misn_ref = mission_computer_filter[i];
914 const Mission *misn = &mission_computer[misn_ref];
915 if ( misn->title != NULL )
916 misn_names[j++] = strdup( misn->title );
917 }
918 }
919 if ( ( misn_names == NULL ) ||
921 ( j == 0 ) ) { /* no missions. */
922 if ( j == 0 )
923 free( misn_names );
924 misn_names = malloc( sizeof( char *) );
925 misn_names[0] = strdup( _( "No Missions" ) );
926 j = 1;
927 }
928 window_addList( wid, 20, -40, w / 2 - 30, h / 2 - 35, "lstMission",
929 misn_names, j, 0, misn_update, misn_accept );
930
931 /* Set default keyboard focus. */
932 window_setFocus( wid, "lstMission" );
933
934 /* Add position persistancey after a mission has been accepted */
935 /* NOTE: toolkit_setListPos protects us from a bad position by clamping */
936 toolkit_setListPos( wid, "lstMission", pos );
937
938 /* Add popdown menu stuff. */
939 window_addButton( wid, 20 + w / 2 - 30 - 25, -35, 30, 30, "btnMissionFilter",
940 NULL, misn_popdown );
941 window_buttonCustomRender( wid, "btnMissionFilter",
942 window_buttonCustomRenderGear );
943}
944
949static void misn_update( unsigned int wid, const char *str )
950{
951 (void)str;
952 const char *active_misn;
953 Mission *misn;
954 int misn_ref;
955 const StarSystem *sys;
956 char txt[STRMAX_SHORT], *buf;
957 int cargofree = pfleet_cargoMissionFree();
958
959 /* Clear computer markers. */
961
962 /* Update date stuff. */
963 buf = ntime_pretty( 0, 2 );
964 snprintf( txt, sizeof( txt ),
965 n_( "%s\n%d Tonne", "%s\n%d Tonnes", cargofree ), buf, cargofree );
966 free( buf );
967 window_modifyText( wid, "txtDate", txt );
968
969 active_misn = toolkit_getList( wid, "lstMission" );
970 if ( strcmp( active_misn, _( "No Missions" ) ) == 0 ) {
971 window_modifyText( wid, "txtHeader", NULL );
972 window_modifyText( wid, "txtDesc",
973 _( "There are no missions available here." ) );
974 window_disableButton( wid, "btnAcceptMission" );
975 window_disableButton( wid, "btnAutonavMission" );
976 return;
977 }
978
979 misn_ref = mission_computer_filter[toolkit_getListPos( wid, "lstMission" )];
980 misn = &mission_computer[misn_ref];
981 sys = mission_sysComputerMark( misn );
982 if ( sys != NULL )
983 map_center( wid, sys->name );
984 snprintf( txt, sizeof( txt ), _( "%s\n#nReward:#0 %s" ), misn->title,
985 misn->reward );
986 window_modifyText( wid, "txtHeader", txt );
987 window_modifyText( wid, "txtDesc", misn->desc );
988 window_enableButton( wid, "btnAcceptMission" );
989 window_enableButton( wid, "btnAutonavMission" );
990}
991
995void land_refuel( void )
996{
997 unsigned int w;
998
999 /* Full fuel. */
1000 if ( player.p->fuel >= player.p->fuel_max )
1001 return;
1002
1003 /* No refuel service. */
1004 if ( ( land_spob == NULL ) ||
1005 !spob_hasService( land_spob, SPOB_SERVICE_REFUEL ) )
1006 return;
1007
1008 player.p->fuel = player.p->fuel_max;
1009
1010 w = land_getWid( LAND_WINDOW_EQUIPMENT );
1011 if ( w > 0 )
1012 equipment_updateShips( w, NULL ); /* Must update counter. */
1013}
1014
1018static void spaceport_buyMap( unsigned int wid, const char *str )
1019{
1020 (void)wid;
1021 (void)str;
1022 const Outfit *o = outfit_get( LOCAL_MAP_NAME );
1023 unsigned int w;
1024
1025 if ( o == NULL ) {
1026 WARN( _( "Outfit '%s' does not exist!" ), LOCAL_MAP_NAME );
1027 return;
1028 }
1029
1030 /* Make sure the map isn't already known, etc. */
1031 if ( !outfit_canBuy( o, -1 ) ) {
1033 return;
1034 }
1035
1036 player_modCredits( -o->price );
1037 player_addOutfit( o, 1 );
1038
1039 /* Disable the button. */
1040 window_disableButtonSoft( land_windows[0], "btnMap" );
1041
1042 /* Update map quantity in outfitter. */
1043 w = land_getWid( LAND_WINDOW_OUTFITS );
1044 if ( w > 0 )
1045 outfits_regenList( w, NULL );
1046
1047 /* Update main tab. */
1049}
1050
1055{
1056 char buf[STRMAX], cred[ECON_CRED_STRLEN], tons[STRMAX_SHORT];
1057 size_t l = 0;
1058 const Outfit *o;
1059
1060 /* Update credits. */
1061 tonnes2str( tons, player.p->cargo_free );
1062 credits2str( cred, player.p->credits, 2 );
1063 l += scnprintf( &buf[l], sizeof( buf ) - l, _( "%s (%s system)" ),
1064 spob_name( land_spob ), _( cur_system->name ) );
1065 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
1066 l +=
1067 scnprintf( &buf[l], sizeof( buf ) - l, _( "%s (%s-class)" ),
1068 spob_getClassName( land_spob->class ), _( land_spob->class ) );
1069 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s",
1070 land_spob->presence.faction >= 0
1071 ? _( faction_name( land_spob->presence.faction ) )
1072 : _( "None" ) );
1073 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s",
1075 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n\n%s", tons );
1076 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", cred );
1077 /* Show tags. */
1078 if ( conf.devmode ) {
1079 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
1080 for ( int i = 0; i < array_size( land_spob->tags ); i++ )
1081 l += scnprintf( &buf[l], sizeof( buf ) - l, "%s%s",
1082 ( ( i > 0 ) ? ", " : "" ), land_spob->tags[i] );
1083 }
1084
1085 window_modifyText( land_windows[0], "txtDInfo", buf );
1086
1087 /* Make sure maps are available. */
1088 if ( !land_hasLocalMap() )
1089 return;
1090
1091 if ( LOCAL_MAP_NAME != NULL ) {
1092 o = outfit_get( LOCAL_MAP_NAME );
1093 if ( o == NULL ) {
1094 WARN( _( "Outfit '%s' does not exist!" ), LOCAL_MAP_NAME );
1095 return;
1096 }
1097 } else
1098 return;
1099
1100 /* Just enable button if it exists. */
1101 if ( widget_exists( land_windows[0], "btnMap" ) )
1102 window_enableButton( land_windows[0], "btnMap" );
1103 /* Else create it. */
1104 else {
1105 /* Buy local map button. */
1106 credits2str( cred, o->price, 0 );
1107 snprintf( buf, sizeof( buf ), _( "Buy Local Map (%s)" ), cred );
1108 window_addButtonKey( land_windows[0], -20 - LAND_BUTTON_WIDTH - 20, 20,
1109 LAND_BUTTON_WIDTH, LAND_BUTTON_HEIGHT, "btnMap", buf,
1110 spaceport_buyMap, SDLK_b );
1111 }
1112
1113 /* Make sure player can click it. */
1114 if ( !outfit_canBuy( o, -1 ) )
1115 window_disableButtonSoft( land_windows[0], "btnMap" );
1116}
1117
1124void land_buttonTakeoff( unsigned int wid, const char *unused )
1125{
1126 (void)wid;
1127 (void)unused;
1128 /* We'll want the time delay. */
1129 takeoff( 1, player_isFlag( PLAYER_NOSAVE ) );
1130}
1131
1138static void land_cleanupWindow( unsigned int wid, const char *name )
1139{
1140 (void)wid;
1141 (void)name;
1142
1143 /* Must not be regenerating. */
1144 if ( land_regen ) {
1145 land_regen--;
1146 return;
1147 }
1148
1149 /* Clean up possible stray graphic. */
1150 if ( gfx_exterior != NULL ) {
1152 gfx_exterior = NULL;
1153 }
1154}
1155
1162unsigned int land_getWid( int window )
1163{
1164 if ( land_windowsMap[window] == -1 )
1165 return 0;
1166 return land_windows[land_windowsMap[window]];
1167}
1168
1172static void land_setupTabs( void )
1173{
1174 int j;
1175 const char *names[LAND_NUMWINDOWS];
1176
1177 /* Destroy if exists. */
1178 if ( widget_exists( land_wid, "tabLand" ) )
1179 window_destroyWidget( land_wid, "tabLand" );
1180
1181 /* Set window map to invalid. */
1182 for ( int i = 0; i < LAND_NUMWINDOWS; i++ )
1183 land_windowsMap[i] = -1;
1184
1185 /* See what is available. */
1186 j = 0;
1187 /* Main. */
1188 land_windowsMap[LAND_WINDOW_MAIN] = j;
1189 names[j++] = _( "Landing Main" );
1190 /* Bar. */
1191 if ( spob_hasService( land_spob, SPOB_SERVICE_BAR ) ) {
1192 land_windowsMap[LAND_WINDOW_BAR] = j;
1193 names[j++] = _( "Spaceport Bar" );
1194 }
1195 /* Missions. */
1196 if ( spob_hasService( land_spob, SPOB_SERVICE_MISSIONS ) ) {
1197 land_windowsMap[LAND_WINDOW_MISSION] = j;
1198 names[j++] = _( "Missions" );
1199 }
1200 /* Outfits. */
1201 if ( spob_hasService( land_spob, SPOB_SERVICE_OUTFITS ) ) {
1202 land_windowsMap[LAND_WINDOW_OUTFITS] = j;
1203 names[j++] = _( "Outfits" );
1204 }
1205 /* Shipyard. */
1206 if ( spob_hasService( land_spob, SPOB_SERVICE_SHIPYARD ) ) {
1207 land_windowsMap[LAND_WINDOW_SHIPYARD] = j;
1208 names[j++] = _( "Shipyard" );
1209 }
1210 /* Equipment. */
1211 if ( spob_hasService( land_spob, SPOB_SERVICE_REFUEL ) ||
1212 spob_hasService( land_spob, SPOB_SERVICE_OUTFITS ) ||
1213 spob_hasService( land_spob, SPOB_SERVICE_SHIPYARD ) ) {
1214 land_windowsMap[LAND_WINDOW_EQUIPMENT] = j;
1215 names[j++] = p_( "service", "Equipment" );
1216 }
1217 /* Commodity. */
1218 if ( spob_hasService( land_spob, SPOB_SERVICE_COMMODITY ) ) {
1219 land_windowsMap[LAND_WINDOW_COMMODITY] = j;
1220 names[j++] = _( "Commodity" );
1221 }
1222
1223 land_windows = window_addTabbedWindow( land_wid, -1, -1, -1, -1, "tabLand",
1224 j, names, 0 );
1225}
1226
1232void land_genWindows( int load )
1233{
1234 int w, h;
1235 Spob *p;
1236 int regen;
1237 unsigned int pntservices;
1238
1239 NTracingZone( _ctx, 1 );
1240
1241 /* Destroy old window if exists. */
1242 if ( land_wid > 0 ) {
1243 land_regen = 2; /* Mark we're regenning. */
1245
1246 /* Mark tabs as not generated. */
1247 land_generated = 0;
1248 }
1249 land_loaded = 0;
1250
1251 /* Get spob. */
1252 p = land_spob;
1253 regen = landed;
1254 pntservices = p->services;
1255
1256 /* Create window. */
1257 if ( SCREEN_W < LAND_WIDTH || SCREEN_H < LAND_HEIGHT ) {
1258 w = -1; /* Fullscreen. */
1259 h = -1;
1260 } else {
1261 w = LAND_WIDTH + 0.5 * ( SCREEN_W - LAND_WIDTH );
1262 h = LAND_HEIGHT + 0.5 * ( SCREEN_H - LAND_HEIGHT );
1263 }
1264 land_wid = window_create( "wdwLand", spob_name( p ), -1, -1, w, h );
1266
1267 /* Create tabbed window. */
1269
1270 /*
1271 * Order here is very important:
1272 *
1273 * 1) Create main tab - must have decent background.
1274 * 2) Set landed, play music and run land hooks - so hooks run well.
1275 * 3) Generate missions - so that campaigns are fluid.
1276 * 4) Create other tabs - lists depend on NPC and missions.
1277 */
1278 /* 1) Create main tab. */
1279 land_createMainTab( land_getWid( LAND_WINDOW_MAIN ) );
1280
1281 /* Add local system map button. */
1283
1284 /* 2) Set as landed and run hooks. */
1285 if ( !regen ) {
1286 landed = 1;
1288 "land" ); /* Must be before hooks in case hooks change music. */
1289
1290 NTracingZoneName( _ctx_landhooks, "hooks_run(\"land\")", 1 );
1291 /* We don't run the "land" hook when loading. If you want to have it do
1292 * stuff when loading, use the "load" hook. Note that you can use the same
1293 * function for both hooks. */
1294 if ( !load )
1295 hooks_run( "land" );
1296 else
1297 hooks_run(
1298 "load" ); /* Should be run before generating missions, so if the
1299 load hook cancels a mission, it can reappear. */
1300 NTracingZoneEnd( _ctx_landhooks );
1301 events_trigger( EVENT_TRIGGER_LAND );
1302
1303 /* An event, hook or the likes made Naev quit. */
1304 if ( naev_isQuit() ) {
1305 NTracingZoneEnd( _ctx );
1306 return;
1307 }
1308
1309 /* Make sure services didn't change or we have to do the tab window. */
1310 if ( land_spob->services != pntservices ) {
1312 land_createMainTab( land_getWid( LAND_WINDOW_MAIN ) );
1314 }
1315
1316 /* 3) Generate computer and bar missions. */
1317 /* Generate bar missions first for claims. */
1318 if ( spob_hasService( land_spob, SPOB_SERVICE_BAR ) )
1319 npc_generateMissions(); /* Generate bar npc. */
1320 if ( spob_hasService( land_spob, SPOB_SERVICE_MISSIONS ) )
1322 missions_genList( land_spob->presence.faction, land_spob,
1323 cur_system, MIS_AVAIL_COMPUTER );
1324 }
1325
1326 /* 4) Create other tabs. */
1327#define should_open( s, w ) \
1328 ( spob_hasService( land_spob, s ) && ( !land_tabGenerated( w ) ) )
1329
1330 /* Things get a bit hairy here. Hooks may have triggered a GUI reload via
1331 * e.g. player.swapShip, so the land tabs may have been generated already
1332 * and we need to check that before regenerating them.
1333 */
1334
1335 /* Basic - bar + missions */
1336 if ( should_open( SPOB_SERVICE_BAR, LAND_WINDOW_BAR ) )
1337 bar_open( land_getWid( LAND_WINDOW_BAR ) );
1338 if ( should_open( SPOB_SERVICE_MISSIONS, LAND_WINDOW_MISSION ) )
1339 misn_open( land_getWid( LAND_WINDOW_MISSION ) );
1340 /* Outfits. */
1341 if ( should_open( SPOB_SERVICE_OUTFITS, LAND_WINDOW_OUTFITS ) )
1342 outfits_open( land_getWid( LAND_WINDOW_OUTFITS ), NULL,
1343 spob_hasService( land_spob, SPOB_SERVICE_BLACKMARKET ) );
1344 /* Shipyard. */
1345 if ( should_open( SPOB_SERVICE_SHIPYARD, LAND_WINDOW_SHIPYARD ) )
1346 shipyard_open( land_getWid( LAND_WINDOW_SHIPYARD ) );
1347 /* Equipment. */
1348 if ( ( spob_hasService( land_spob, SPOB_SERVICE_REFUEL ) ||
1349 spob_hasService( land_spob, SPOB_SERVICE_OUTFITS ) ||
1350 spob_hasService( land_spob, SPOB_SERVICE_SHIPYARD ) ) &&
1351 !land_tabGenerated( LAND_WINDOW_EQUIPMENT ) )
1352 equipment_open( land_getWid( LAND_WINDOW_EQUIPMENT ) );
1353 /* Commodity. */
1354 if ( should_open( SPOB_SERVICE_COMMODITY, LAND_WINDOW_COMMODITY ) )
1355 commodity_exchange_open( land_getWid( LAND_WINDOW_COMMODITY ) );
1356#undef should_open
1357
1358 if ( !regen ) {
1359 /* Reset markers if needed. */
1361
1362 /* Check land missions. */
1363 if ( !has_visited( VISITED_LAND ) ) {
1364 missions_run( MIS_AVAIL_LAND, land_spob->presence.faction, land_spob,
1365 cur_system );
1367 }
1368 }
1369
1370 /* Go to last open tab. */
1371 window_tabWinOnChange( land_wid, "tabLand", land_changeTab );
1372 if ( !land_takeoff && land_windowsMap[last_window] != -1 )
1373 window_tabWinSetActive( land_wid, "tabLand",
1375
1376 /* Refresh the map button in case the player couldn't afford it prior to
1377 * mission payment. */
1379
1380 /* Refuel if necessary. */
1381 land_refuel();
1382
1383 /* Finished loading. */
1384 land_loaded = 1;
1385
1386 /* Necessary if player.land() was run in an abort() function. */
1387 if ( !load )
1389
1390 NTracingZoneEnd( _ctx );
1391}
1392
1399int land_setWindow( int window )
1400{
1401 if ( land_windowsMap[window] < 0 )
1402 return -1;
1403 last_window = window;
1404 window_tabWinSetActive( land_wid, "tabLand", land_windowsMap[window] );
1405 return 0;
1406}
1407
1413void land( Spob *p, int load )
1414{
1415 /* Do not land twice. */
1416 if ( landed )
1417 return;
1418
1419#if HAVE_TRACY
1420 char buf[STRMAX_SHORT];
1421 size_t l = snprintf( buf, sizeof( buf ), "Player landed on '%s'", p->name );
1422 NTracingMessage( buf, l );
1423#endif /* HAVE_TRACY */
1424 NTracingFrameMarkStart( "land" );
1425
1426 /* Increment times player landed. */
1427 if ( !load ) {
1428 player.landed_times++;
1429 player.ps.landed_times++;
1430 }
1431 /* Clear landing since we landed. */
1432 pilot_rmFlag( player.p, PILOT_LANDING );
1433
1434 /* Clear some unnecessary flags. */
1435 pilot_rmFlag( player.p, PILOT_COOLDOWN_BRAKE );
1436 pilot_rmFlag( player.p, PILOT_COOLDOWN );
1437
1438 /* Resets the player's heat. */
1440
1441 /* Heal the player so GUI shows player at full everything. */
1443
1444 player_addEscorts(); /* TODO only regenerate fleet if planet has a shipyard
1445 */
1446
1447 /* Stop player sounds. */
1449
1450 /* Clear message stuff. */
1451 free( player.p->comm_msg );
1452 player.p->comm_msg = NULL;
1453
1454 /* Clear some target stuff. */
1455 player.p->nav_spob = -1;
1456 gui_setNav();
1457 cam_vel( 0., 0. );
1458
1459 /* Load stuff */
1460 land_spob = p;
1461 gfx_exterior = gl_newImage( p->gfx_exterior, 0 );
1462
1463 /* Run outfits as necessary. */
1465
1466 /* Generate the news. */
1467 if ( spob_hasService( land_spob, SPOB_SERVICE_BAR ) )
1468 news_load();
1469
1470 /* Average economy prices that player has seen */
1471 economy_averageSeenPrices( p );
1472
1473 /* Clear the NPC. */
1474 npc_clear();
1475
1476 /* Create all the windows. */
1477 land_genWindows( load );
1478
1479 /* Just in case? */
1480 bar_regen();
1481
1482 /* Do a lua collection pass. Run in a hook since land can be called
1483 * indirectly from Lua. */
1484 hook_addFunc( land_gc, NULL, "safe" );
1485
1486 /* Mission forced take off. */
1487 land_needsTakeoff( 0 );
1488
1489 NTracingFrameMarkEnd( "land" );
1490}
1491
1495static int land_gc( void *unused )
1496{
1497 (void)unused;
1498 lua_gc( naevL, LUA_GCCOLLECT, 0 );
1499 return 0;
1500}
1501
1507static void land_createMainTab( unsigned int wid )
1508{
1509 int offset;
1510 int w, h, y, th;
1511 char buf[STRMAX_SHORT];
1512 size_t l = 0;
1513
1514 /* Get window dimensions. */
1515 window_dimWindow( wid, &w, &h );
1516
1517 /*
1518 * Faction logo.
1519 */
1520 offset = 20;
1521 if ( land_spob->presence.faction != -1 ) {
1522 const glTexture *logo = faction_logo( land_spob->presence.faction );
1523 if ( logo != NULL ) {
1524 int logow =
1525 logo->w * (double)FACTION_LOGO_SM / MAX( logo->w, logo->h );
1526 int logoh =
1527 logo->h * (double)FACTION_LOGO_SM / MAX( logo->w, logo->h );
1528 window_addImage( wid, 440 + ( w - 460 - logow ) / 2, -20, logow, logoh,
1529 "imgFaction", logo, 0 );
1530 offset += FACTION_LOGO_SM;
1531 }
1532 }
1533
1534 /*
1535 * Pretty display.
1536 */
1537 window_addImage( wid, 20, -40, 400, 400, "imgSpob", gfx_exterior, 1 );
1538 if ( land_spob->description != NULL )
1539 window_addText( wid, 440, -20 - offset, w - 460,
1540 h - 20 - offset - 60 - LAND_BUTTON_HEIGHT * 2, 0,
1541 "txtSpobDesc", &gl_defFont, NULL,
1542 _( land_spob->description ) );
1543
1544 /* Player stats. */
1545 l += scnprintf( &buf[l], sizeof( buf ) - l, "#n%s", _( "Stationed at:" ) );
1546 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Class:" ) );
1547 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Faction:" ) );
1548 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Population:" ) );
1549 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n\n%s", _( "Free Space:" ) );
1550 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Money:" ) );
1551 if ( conf.devmode )
1552 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Tags:" ) );
1553 th = gl_printHeightRaw( &gl_defFont, 200, buf );
1554 window_addText( wid, 20, 20, 200, th, 0, "txtSInfo", &gl_defFont, NULL,
1555 buf );
1556 window_addText( wid, 20 + 120, 20, w - 20 - ( 20 + 200 ) - LAND_BUTTON_WIDTH,
1557 th, 0, "txtDInfo", &gl_defFont, NULL, NULL );
1558
1559 /*
1560 * buttons
1561 */
1562 /* first column */
1563 window_addButtonKey( wid, -20, 20, LAND_BUTTON_WIDTH, LAND_BUTTON_HEIGHT,
1564 "btnTakeoff", _( "Take Off" ), land_buttonTakeoff,
1565 SDLK_t );
1566
1567 /* Additional notices if necessary. */
1568 l = 0;
1569 buf[0] = '\0';
1570 y = 20 + ( LAND_BUTTON_HEIGHT + 20 ) + 20;
1571 if ( land_hasLocalMap() )
1572 y += LAND_BUTTON_HEIGHT + 20;
1573 /* Add "no refueling" notice if needed. */
1574 if ( !spob_hasService( land_spob, SPOB_SERVICE_REFUEL ) )
1575 l +=
1576 scnprintf( &buf[l], sizeof( buf ) - l, _( "No refueling services." ) );
1577 if ( !land_canSave() ) {
1578 if ( l > 0 )
1579 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
1580 l += scnprintf( &buf[l], sizeof( buf ) - l, "#r%s#0",
1581 _( "Game will not be saved." ) );
1582 }
1583 if ( l > 0 ) {
1584 th = gl_printHeightRaw( &gl_defFont, 200, buf );
1585 window_addText( land_windows[0], -20, y, 200, th, 0, "txtPlayer",
1586 &gl_defFont, NULL, buf );
1587 }
1588}
1589
1598static void land_changeTab( unsigned int wid, const char *wgt, int old,
1599 int tab )
1600{
1601 (void)wid;
1602 (void)wgt;
1603 (void)old;
1604 unsigned int w;
1605 /* Safe defaults. */
1606 const char *torun_hook = NULL;
1607 unsigned int to_visit = 0;
1608
1609 /* Clear markers when not open. */
1610 if ( last_window == LAND_WINDOW_MISSION )
1612
1613 /* Find what switched. */
1614 for ( int i = 0; i < LAND_NUMWINDOWS; i++ ) {
1615 if ( land_windowsMap[i] != tab )
1616 continue;
1617 last_window = i;
1618 w = land_getWid( i );
1619
1620 /* Must regenerate outfits. */
1621 switch ( i ) {
1622 case LAND_WINDOW_MAIN:
1624 break;
1625 case LAND_WINDOW_OUTFITS:
1626 outfits_update( w, NULL );
1627 to_visit = VISITED_OUTFITS;
1628 torun_hook = "outfits";
1629 break;
1630 case LAND_WINDOW_SHIPYARD:
1631 shipyard_update( w, NULL );
1632 to_visit = VISITED_SHIPYARD;
1633 torun_hook = "shipyard";
1634 break;
1635 case LAND_WINDOW_BAR:
1636 bar_update( w, NULL );
1637 to_visit = VISITED_BAR;
1638 torun_hook = "bar";
1639 break;
1640 case LAND_WINDOW_MISSION:
1641 misn_update( w, NULL );
1642 to_visit = VISITED_MISSION;
1643 torun_hook = "mission";
1644 break;
1645 case LAND_WINDOW_COMMODITY:
1646 commodity_update( w, NULL );
1647 to_visit = VISITED_COMMODITY;
1648 torun_hook = "commodity";
1649 break;
1650 case LAND_WINDOW_EQUIPMENT:
1651 equipment_updateShips( w, NULL );
1652 equipment_updateOutfits( w, NULL );
1653 to_visit = VISITED_EQUIPMENT;
1654 torun_hook = "equipment";
1655 break;
1656
1657 default:
1658 break;
1659 }
1660
1661 /* Clear markers if closing Mission Computer. */
1662 if ( i != LAND_WINDOW_MISSION )
1664
1665 break;
1666 }
1667
1668 /* Check land missions - always run hooks. */
1669 /*if ((to_visit != 0) && !has_visited(to_visit)) {*/
1670 {
1671 /* Run hooks, run after music in case hook wants to change music. */
1672 if ( torun_hook != NULL )
1673 if ( hooks_run( torun_hook ) > 0 )
1674 bar_genList( land_getWid( LAND_WINDOW_BAR ) );
1675
1676 visited( to_visit );
1677
1678 if ( land_loaded )
1679 land_needsTakeoff( 1 );
1680 }
1681}
1682
1690void takeoff( int delay, int nosave )
1691{
1692 int h;
1693 char *nt;
1694 double a, r;
1695#if HAVE_TRACY
1696 const Spob *spb = land_spob;
1697#endif /* HAVE_TRACY */
1698
1699 if ( !landed )
1700 return;
1701
1702 /* Check to see if player fleet is ok. */
1703 if ( player.fleet_capacity > 0 ) {
1704 char badfleet_ships[STRMAX_SHORT];
1705 char overfleet_ships[STRMAX_SHORT];
1706 int l = 0;
1707 int badfleet = 0;
1708 int nships = 0;
1709 int overfleet = 0;
1710 int capused = player.p->ship->points;
1712
1713 /* Check to see if player's fleet is OK and count ships. */
1714 pfleet_update();
1715 badfleet_ships[0] = '\0';
1716 for ( int i = 0; i < array_size( pships ); i++ ) {
1717 const PlayerShip_t *pe = &pships[i];
1718 if ( !pe->deployed )
1719 continue;
1720 capused += pe->p->ship->points;
1721 if ( capused > player.fleet_capacity ) {
1722 overfleet = 1;
1723 l += scnprintf( &overfleet_ships[l], sizeof( overfleet_ships ) - l,
1724 "\n%s (%s)", pe->p->name, _( pe->p->ship->name ) );
1725 capused -= pe->p->ship->points;
1726 }
1727 if ( !pilot_isSpaceworthy( pe->p ) ) {
1728 badfleet = 1;
1729 l += scnprintf( &badfleet_ships[l], sizeof( badfleet_ships ) - l,
1730 "\n%s (%s)", pe->p->name, _( pe->p->ship->name ) );
1731 }
1732 nships++;
1733 }
1734 /* Only care if the player has a fleet deployed. */
1735 if ( nships > 0 ) {
1736 if ( player.fleet_used > player.fleet_capacity ) {
1737 if ( overfleet ) {
1738 char buf[STRMAX];
1739 snprintf( buf, sizeof( buf ), "%s\n%s",
1740 _( "You lack the fleet capacity to take off with all "
1741 "the selected ships. Do you wish to undeploy the "
1742 "following ships to be able to take off?" ),
1743 overfleet_ships );
1744 if ( !dialogue_YesNo( _( "Fleet not fit for flight" ), "%s",
1745 buf ) )
1746 return;
1747
1748 capused = player.p->ship->points;
1749 for ( int i = 0; i < array_size( pships ); i++ ) {
1750 PlayerShip_t *pe = &pships[i];
1751 if ( !pe->deployed )
1752 continue;
1753 if ( capused + pe->p->ship->points > player.fleet_capacity ) {
1754 pfleet_toggleDeploy( pe, 0 );
1755 continue;
1756 }
1757 capused += pe->p->ship->points;
1758 }
1759 }
1760 }
1761 if ( badfleet ) {
1762 if ( !dialogue_YesNo( _( "Fleet not fit for flight" ), "%s\n%s",
1763 _( "The following ships in your fleet are "
1764 "not space worthy, are you sure you want "
1765 "to take off without them?" ),
1766 badfleet_ships ) )
1767 return;
1768 }
1769 }
1770 }
1771
1772 /* Player's ship is not able to fly. */
1773 if ( !pilot_isSpaceworthy( player.p ) ) {
1774 char message[STRMAX_SHORT];
1775 pilot_reportSpaceworthy( player.p, message, sizeof( message ) );
1776 dialogue_msgRaw( _( "Ship not fit for flight" ), message );
1777
1778 /* Check whether the player needs rescuing. */
1779 land_stranded();
1780
1781 return;
1782 }
1783
1784 /* Clear queued takeoff. */
1785 land_takeoff = 0;
1787
1788 /* Refuel if needed. */
1789 land_refuel();
1790
1791 /* In case we had paused messy sounds. */
1792 sound_stopAll();
1793
1794 /* ze music */
1795 music_choose( "takeoff" );
1796
1797 /* to randomize the takeoff a bit */
1798 a = RNGF() * 2. * M_PI;
1799 r = RNGF() * land_spob->radius;
1800
1801 /* no longer authorized to land */
1802 player_rmFlag( PLAYER_LANDACK );
1803 pilot_rmFlag( player.p, PILOT_LANDING ); /* No longer landing. */
1804
1805 /* set player to another position with random facing direction and no vel */
1806 player_warp( land_spob->pos.x + r * cos( a ),
1807 land_spob->pos.y + r * sin( a ) );
1808 vec2_pset( &player.p->solid.vel, 0., 0. );
1809 player.p->solid.dir = RNGF() * 2. * M_PI;
1810 cam_setTargetPilot( player.p->id, 0 );
1811
1812 /* Clear spob target. Allows for easier autonav out of the system. */
1814
1815 /* Clear pilots other than player. */
1816 pilots_clean( 1 );
1817
1818 /* Clear omsg. */
1819 omsg_cleanup();
1820
1821 /* initialize the new space */
1822 h = player.p->nav_hyperspace;
1823 space_init( NULL, 1 );
1824 player.p->nav_hyperspace = h;
1825
1826 /* Only save when the player shouldn't get stranded. */
1827 if ( !nosave && land_canSave() &&
1828 ( save_all() < 0 ) ) /* must be before cleaning up spob */
1830 _( "Failed to save game! You should exit and check the log to see "
1831 "what happened and then file a bug report!" ) );
1832
1833 /* time goes by, triggers hook before takeoff */
1834 if ( delay ) {
1835 /* TODO should this depend on something else? */
1836 int stu = (int)( NT_PERIOD_SECONDS * player.p->stats.land_delay );
1837 ntime_inc( ntime_create( 0, 0, stu ) );
1838 }
1839 nt = ntime_pretty( 0, 2 );
1840 player_message( _( "#oTaking off from %s on %s." ), spob_name( land_spob ),
1841 nt );
1842 free( nt );
1843
1844 /* Hooks and stuff. */
1845 land_cleanup(); /* Cleanup stuff */
1846 hooks_run( "takeoff" ); /* Must be run after cleanup since we don't want the
1847 missions to think we are landed. */
1848 if ( menu_isOpen( MENU_MAIN ) )
1849 return;
1850
1851 /* Add escorts and heal up. */
1852 player_addEscorts(); /* TODO only regenerate fleet if planet has a shipyard
1853 */
1854 effect_clear( &player.p->effects );
1856
1857 hooks_run( "enter" );
1858 if ( menu_isOpen( MENU_MAIN ) )
1859 return;
1860 events_trigger( EVENT_TRIGGER_ENTER );
1861 missions_run( MIS_AVAIL_ENTER, -1, NULL, NULL );
1862 if ( menu_isOpen( MENU_MAIN ) )
1863 return;
1864
1865 /* Clear effects of all surviving pilots. */
1866 Pilot *const *plts = pilot_getAll();
1867 for ( int i = 0; i < array_size( plts ); i++ ) {
1868 Pilot *p = plts[i];
1869 if ( pilot_isFlag( p, PILOT_DELETE ) )
1870 continue;
1871
1872 effect_clear( &p->effects );
1873 pilot_calcStats( p );
1874
1875 /* Update lua stuff. */
1877
1878 /* Normal pilots stop here. */
1879 if ( !pilot_isWithPlayer( p ) )
1880 continue;
1881
1883
1884 /* Set take off stuff. */
1885 p->landing_delay = PILOT_TAKEOFF_DELAY * player_dt_default();
1886 p->ptimer = p->landing_delay;
1887 pilot_setFlag( p, PILOT_TAKEOFF );
1888 pilot_setAccel( p, 0. );
1889 pilot_setTurn( p, 0. );
1890 }
1891
1892 /* Reset speed */
1894
1895 /* Landing is a special case where the player's gear can change and trigger
1896 * all sorts of things. We have to refresh the GUI to reflect those changes.
1897 * This is particular important for Lua-side mechanics such as flow. */
1898 gui_setSystem();
1899
1900#if HAVE_TRACY
1901 char buf[STRMAX_SHORT];
1902 size_t l =
1903 snprintf( buf, sizeof( buf ), "Player took off from '%s'", spb->name );
1904 NTracingMessage( buf, l );
1905#endif /* HAVE_TRACY */
1906}
1907
1911static void land_stranded( void )
1912{
1913 /* Nothing to do if there's no rescue script. */
1914 if ( !PHYSFS_exists( RESCUE_PATH ) )
1915 return;
1916
1917 if ( rescue_env == LUA_NOREF ) {
1918 char *buf;
1919 size_t bufsize;
1920
1921 rescue_env = nlua_newEnv( RESCUE_PATH );
1924
1925 buf = ndata_read( RESCUE_PATH, &bufsize );
1926 if ( buf == NULL ) {
1927 WARN( _( "File '%s' not found!" ), RESCUE_PATH );
1928 return;
1929 }
1930 if ( nlua_dobufenv( rescue_env, buf, bufsize, RESCUE_PATH ) != 0 ) {
1931 WARN( _( "Error loading file: %s\n"
1932 "%s\n"
1933 "Most likely Lua file has improper syntax, please check" ),
1934 RESCUE_PATH, lua_tostring( naevL, -1 ) );
1935 free( buf );
1936 return;
1937 }
1938 free( buf );
1939 }
1940
1941 /* Run Lua. */
1942 nlua_getenv( naevL, rescue_env, "rescue" );
1943 if ( nlua_pcall( rescue_env, 0, 0 ) ) { /* error has occurred */
1944 WARN( _( "Rescue: 'Ys' : '%s'" ), "rescue", lua_tostring( naevL, -1 ) );
1945 lua_pop( naevL, 1 );
1946 }
1947}
1948
1952void land_cleanup( void )
1953{
1954 /* Clean up default stuff. */
1955 land_regen = 0;
1956 land_spob = NULL;
1957 landed = 0;
1958 land_visited = 0;
1959 land_generated = 0;
1960
1961 /* Destroy window. */
1962 if ( land_wid > 0 )
1964 land_wid = 0;
1965
1966 /* Clean up possible stray graphic. */
1967 if ( gfx_exterior != NULL )
1969 gfx_exterior = NULL;
1970
1971 /* Remove computer markers just in case. */
1973
1974 /* Clean up mission computer. */
1975 for ( int i = 0; i < array_size( mission_computer ); i++ )
1978 mission_computer = NULL;
1981
1982 /* Clean up bar missions. */
1983 npc_clear();
1984
1985 /* Clean up shipyard. */
1987
1988 /* Clean up rescue Lua. */
1989 nlua_freeEnv( rescue_env );
1990 rescue_env = LUA_NOREF;
1991
1992 /* Deselect stuff. */
1993 equipment_slotDeselect( NULL );
1994}
1995
1999void land_exit( void )
2000{
2001 land_cleanup();
2004 commodity_exchange_cleanup();
2005}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:170
#define array_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
Definition array.h:102
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
Definition array.h:148
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:179
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition array.h:134
void cam_setTargetPilot(unsigned int follow, int soft_over)
Sets the target to follow.
Definition camera.c:158
void cam_vel(double vx, double vy)
Sets the camera velocity.
Definition camera.c:149
void credits2str(char *str, credits_t credits, int decimals)
Converts credits to a usable string for displaying.
Definition commodity.c:75
void tonnes2str(char *str, int tonnes)
Converts tonnes to a usable string for displaying.
Definition commodity.c:131
void dialogue_alert(const char *fmt,...)
Displays an alert popup with only an ok button and a message.
Definition dialogue.c:130
void dialogue_msgRaw(const char *caption, const char *msg)
Opens a dialogue window with an ok button and a fixed message.
Definition dialogue.c:269
int dialogue_YesNo(const char *caption, const char *fmt,...)
Runs a dialogue with both yes and no options.
Definition dialogue.c:352
void effect_clear(Effect **efxlist)
Clears an effect list, removing all active effects.
Definition effect.c:524
void equipment_slotDeselect(CstSlotWidget *wgt)
Deselects equipment stuff.
Definition equipment.c:2823
void equipment_cleanup(void)
Cleans up after the equipment stuff.
Definition equipment.c:2810
void equipment_updateOutfits(unsigned int wid, const char *str)
Updates the player's outfit list.
Definition equipment.c:2307
void equipment_updateShips(unsigned int wid, const char *str)
Updates the player's ship window.
Definition equipment.c:1992
void equipment_open(unsigned int wid)
Opens the player's equipment window.
Definition equipment.c:329
void events_trigger(EventTrigger_t trigger)
Runs all the events matching a trigger.
Definition event.c:319
const glTexture * faction_logo(int f)
Gets the faction's logo (ideally 256x256).
Definition faction.c:479
const char * faction_name(int f)
Gets a factions "real" (internal) name.
Definition faction.c:331
int gl_printHeightRaw(const glFont *ft_font, const int width, const char *text)
Gets the height of a non-formatted string.
Definition font.c:1050
glFont gl_defFont
Definition font.c:158
unsigned int land_wid
Definition land.c:83
void gui_setSystem(void)
Player just changed their system.
Definition gui.c:1888
void gui_setNav(void)
Player just changed their nav computer target.
Definition gui.c:1864
void player_message(const char *fmt,...)
Adds a mesg to the queue to be displayed on screen.
Definition gui.c:353
int hooks_run(const char *stack)
Runs all the hooks of stack.
Definition hook.c:1049
unsigned int hook_addFunc(int(*func)(void *), void *data, const char *stack)
Adds a function hook to be run.
Definition hook.c:634
void bar_regen(void)
Regenerates the bar list.
Definition land.c:432
static void land_changeTab(unsigned int wid, const char *wgt, int old, int tab)
Saves the last place the player was.
Definition land.c:1598
void land_queueTakeoff(void)
Queue a takeoff.
Definition land.c:159
static int land_takeoff_nosave
Definition land.c:81
static int land_windowsMap[LAND_NUMWINDOWS]
Definition land.c:85
static int last_window
Definition land.c:107
#define visited(f)
Definition land.c:67
void takeoff(int delay, int nosave)
Makes the player take off if landed.
Definition land.c:1690
static void misn_autonav(unsigned int wid, const char *str)
Autonav to selected mission.
Definition land.c:635
static void land_cleanupWindow(unsigned int wid, const char *name)
Cleans up the land window.
Definition land.c:1138
static void bar_close(unsigned int wid, const char *str)
Closes the mission computer window.
Definition land.c:523
void misn_patchMission(const Mission *misn)
Patches a mission into the mission computer.
Definition land.c:411
#define VISITED_EQUIPMENT
Definition land.c:64
static unsigned int * land_windows
Definition land.c:86
static void bar_update(unsigned int wid, const char *str)
Updates the missions in the spaceport bar.
Definition land.c:449
#define VISITED_MISSION
Definition land.c:65
int land_setWindow(int window)
Sets the land window tab.
Definition land.c:1399
static void bar_approach(unsigned int wid, const char *str)
Approaches guy in mission computer.
Definition land.c:540
unsigned int land_getWid(int window)
Gets the WID of a window by type.
Definition land.c:1162
static void land_stranded(void)
Runs the rescue script if players are stuck.
Definition land.c:1911
static int land_regen
Definition land.c:84
static void spaceport_buyMap(unsigned int wid, const char *str)
Buys a local system map.
Definition land.c:1018
static int misn_cmp(const void *p1, const void *p2)
Used to sort available mission computer missions.
Definition land.c:715
#define VISITED_COMMODITY
Definition land.c:58
#define VISITED_LAND
Definition land.c:57
int land_loaded
Definition land.c:79
static void misn_open(unsigned int wid)
Opens the mission computer window.
Definition land.c:587
void land_cleanup(void)
Cleans up some land-related variables.
Definition land.c:1952
static Mission * mission_computer
Definition land.c:94
#define VISITED_BAR
Definition land.c:61
int landed
Definition land.c:78
int land_doneLoading(void)
Check to see if finished loading.
Definition land.c:207
static int land_takeoff
Definition land.c:80
void land(Spob *p, int load)
Opens up all the land dialogue stuff.
Definition land.c:1413
static int bar_genList(unsigned int wid)
Generates the mission list for the bar.
Definition land.c:327
static int * mission_computer_filter
Definition land.c:95
void land_errDialogueBuild(const char *fmt,...)
Generates error dialogues used by several landing tabs.
Definition land.c:226
static void misn_computerOptionsClose(unsigned int wid, const char *name)
Closes the mission computer window.
Definition land.c:823
static int news_load(void)
Loads the news.
Definition land.c:578
void land_exit(void)
Exits all the landing stuff.
Definition land.c:1999
static void bar_getDim(int wid, int *w, int *h, int *iw, int *ih, int *bw, int *bh)
Gets the dimensions of the spaceport bar window.
Definition land.c:260
void land_genWindows(int load)
Recreates the land windows.
Definition land.c:1232
void land_updateMainTab(void)
Adds the "Buy Local Map" button if needed and updates info.
Definition land.c:1054
static unsigned int land_visited
Definition land.c:70
Spob * land_spob
Definition land.c:87
static int * misn_filter(const Mission *misn)
Hides missions we don't want to look at.
Definition land.c:701
static void bar_open(unsigned int wid)
Opens the spaceport bar window.
Definition land.c:277
static void misn_genList(unsigned int wid)
Generates the mission list.
Definition land.c:880
static void misn_computerOptions(unsigned int wid, const char *str)
Do the popdown options.
Definition land.c:832
void land_errClear(void)
Clear error dialogues.
Definition land.c:217
int land_canSave(void)
Whether or not the player can save.
Definition land.c:182
static glTexture * mission_portrait
Definition land.c:102
static void misn_popdown(unsigned int wid, const char *str)
Opens the small pop-down menu.
Definition land.c:755
static void land_setupTabs(void)
Sets up the tabs for the window.
Definition land.c:1172
void misn_regen(void)
Regenerates the mission list.
Definition land.c:419
#define VISITED_SHIPYARD
Definition land.c:63
void land_buttonTakeoff(unsigned int wid, const char *unused)
Wrapper for takeoff mission button.
Definition land.c:1124
void land_refuel(void)
Refuels the player's current ship, if possible.
Definition land.c:995
#define VISITED_OUTFITS
Definition land.c:62
static glTexture * gfx_exterior
Definition land.c:88
static void misn_update(unsigned int wid, const char *str)
Updates the mission list.
Definition land.c:949
int land_errDisplay(void)
Displays an error if applicable.
Definition land.c:248
#define has_visited(f)
Definition land.c:68
static int land_gc(void *unused)
Runs Lua garbage collection.
Definition land.c:1495
static void misn_accept(unsigned int wid, const char *str)
Accepts the selected mission.
Definition land.c:661
static void land_createMainTab(unsigned int wid)
Creates the main tab.
Definition land.c:1507
static nlua_env rescue_env
Definition land.c:120
void outfits_regenList(unsigned int wid, const char *str)
Regenerates the outfit list.
int outfit_canBuy(const Outfit *outfit, int wid)
Checks to see if the player can buy the outfit.
void outfits_cleanup(void)
Cleans up outfit globals.
void outfits_open(unsigned int wid, const Outfit **outfits, int blackmarket)
Opens the outfit exchange center window.
void outfits_update(unsigned int wid, const char *str)
Updates the outfits in the outfit window.
void shipyard_open(unsigned int wid)
Opens the shipyard window.
void shipyard_cleanup(void)
Cleans up shipyard data.
void shipyard_update(unsigned int wid, const char *str)
Updates the ships in the shipyard window.
void commodity_exchange_open(unsigned int wid)
Opens the local market window.
Definition land_trade.c:63
void commodity_update(unsigned int wid, const char *str)
Updates the commodity window.
Definition land_trade.c:242
Handles the important game menus.
#define MENU_MAIN
Definition menu.h:9
#define menu_isOpen(f)
Definition menu.h:16
int mission_accept(Mission *mission)
Small wrapper for misn_run.
Definition mission.c:210
void mission_cleanup(Mission *misn)
Cleans up a mission.
Definition mission.c:779
Mission * missions_genList(int faction, const Spob *pnt, const StarSystem *sys, MissionAvailability loc)
Generates a mission list. This runs create() so won't work with all missions.
Definition mission.c:954
const StarSystem * mission_sysComputerMark(const Mission *misn)
Marks the system of the computer mission to reflect where it will head to.
Definition mission.c:642
void mission_sysMark(void)
Marks all active systems that need marking.
Definition mission.c:616
void missions_run(MissionAvailability loc, int faction, const Spob *pnt, const StarSystem *sys)
Runs missions matching location, all Lua side and one-shot.
Definition mission.c:326
int music_choose(const char *situation)
Actually runs the music stuff, based on situation.
Definition music.c:426
int naev_isQuit(void)
Get if Naev is trying to quit.
Definition naev.c:153
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:39
#define MAX(x, y)
Definition naev.h:37
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
Definition ndata.c:207
int * generate_news(int faction)
Generates news from newslist from specific faction AND Generic news.
Definition news.c:202
void news_widget(unsigned int wid, int x, int y, int w, int h)
Creates a news widget.
Definition news.c:273
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
Definition nlua.c:914
lua_State * naevL
Definition nlua.c:54
int nlua_loadTk(nlua_env env)
Loads the Toolkit Lua library.
Definition nlua_tk.c:98
const char * npc_getDesc(int i)
Gets the NPC description.
Definition npc.c:574
void npc_generateMissions(void)
Generates the bar missions.
Definition npc.c:366
glTexture * npc_getTexture(int i)
Get the texture of an NPC.
Definition npc.c:562
int npc_approach(int i)
Approaches the NPC.
Definition npc.c:635
void npc_clear(void)
Cleans up the spaceport bar NPC.
Definition npc.c:477
int npc_getArraySize(void)
Get the size of the npc array.
Definition npc.c:504
glTexture * npc_getBackground(int i)
Get the background of an NPC.
Definition npc.c:524
int npc_isImportant(int i)
Checks to see if the NPC is important or not.
Definition npc.c:586
const char * npc_getName(int i)
Get the name of an NPC.
Definition npc.c:512
void npc_sort(void)
Sorts the NPCs.
Definition npc.c:357
int scnprintf(char *text, size_t maxlen, const char *fmt,...)
Like snprintf(), but returns the number of characters ACTUALLY "printed" into the buffer....
Definition nstring.c:102
ntime_t ntime_create(int scu, int stp, int stu)
Creates a time structure.
Definition ntime.c:99
char * ntime_pretty(ntime_t t, int d)
Gets the time in a pretty human readable format.
Definition ntime.c:178
void ntime_inc(ntime_t t)
Sets the time relatively.
Definition ntime.c:243
glTexture * gl_dupTexture(const glTexture *texture)
Duplicates a texture.
Definition opengl_tex.c:891
glTexture ** gl_addTexArray(glTexture **tex, glTexture *t)
Adds an element to a texture array.
glTexture * gl_newImage(const char *path, const unsigned int flags)
Loads an image as a texture.
Definition opengl_tex.c:587
void gl_freeTexture(glTexture *texture)
Frees a texture.
Definition opengl_tex.c:835
const Outfit * outfit_get(const char *name)
Gets an outfit by name.
Definition outfit.c:223
void pilots_clean(int persist)
Cleans up the pilot stack - leaves the player.
Definition pilot.c:4052
void pilot_setAccel(Pilot *p, double accel)
Sets the pilot's accel.
Definition pilot.c:680
void pilot_setTurn(Pilot *p, double turn)
Sets the pilot's turn.
Definition pilot.c:688
Pilot *const * pilot_getAll(void)
Gets the pilot stack.
Definition pilot.c:93
void pilot_heatReset(Pilot *p)
Resets a pilot's heat.
Definition pilot_heat.c:103
void pilot_healLanded(Pilot *pilot)
Cures the pilot as if he was landed.
void pilot_outfitLOntakeoff(Pilot *pilot)
Runs Lua outfits when pilot takes off from a spob.
void pilot_calcStats(Pilot *pilot)
Recalculates the pilot's stats based on his outfits.
int pilot_reportSpaceworthy(const Pilot *p, char *buf, int bufSize)
Pilot safety report - makes sure stats are safe.
void pilot_outfitLOnland(Pilot *pilot)
Runs Lua outfits when pilot lands on a spob.
int pilot_isSpaceworthy(const Pilot *p)
Pilot safety check - makes sure stats are safe.
void pilot_outfitLInitAll(Pilot *pilot)
Runs the pilot's Lua outfits init script.
int player_addOutfit(const Outfit *o, int quantity)
Adds an outfit to the player outfit stack.
Definition player.c:2988
void player_warp(double x, double y)
Warps the player to the new position.
Definition player.c:1007
const PlayerShip_t * player_getShipStack(void)
Gets the array (array.h) of the player's ships.
Definition player.c:2804
void player_hyperspacePreempt(int preempt)
Enables or disables jump points preempting spobs in autoface and target clearing.
Definition player.c:1980
double player_dt_default(void)
Returns the player's total default time delta based on time dilation stuff.
Definition player.c:2001
int player_addEscorts(void)
Adds the player's escorts.
Definition player.c:3288
void player_soundStop(void)
Stops playing player sounds.
Definition player.c:966
credits_t player_modCredits(credits_t amount)
Modifies the amount of credits the player has.
Definition player.c:1047
void player_targetSpobSet(int id)
Sets the player's target spob.
Definition player.c:1559
Player_t player
Definition player.c:77
void player_autonavResetSpeed(void)
Resets the game speed.
void player_autonavStart(void)
Starts autonav.
int pfleet_toggleDeploy(PlayerShip_t *ps, int deploy)
Toggles a player ship as deployed.
int pfleet_cargoMissionFree(void)
Gets the free mission cargo space in the player's fleet.
void pfleet_update(void)
Updates the used fleet capacity of the player.
static const double c[]
Definition rng.c:256
int save_all(void)
Saves the current game.
Definition save.c:97
void sound_stopAll(void)
Stops all the playing voices.
Definition sound.c:1049
void space_init(const char *sysname, int do_simulate)
Initializes the system.
Definition space.c:1620
StarSystem * cur_system
Definition space.c:110
void spob_updateLand(Spob *p)
Updates the land possibilities of a spob.
Definition space.c:2031
const char * spob_name(const Spob *p)
Gets the translated name of a spob.
Definition space.c:1834
const char * spob_getClassName(const char *class)
Gets the long class name for a spob.
Definition space.c:226
const char * space_populationStr(const Spob *spb)
Gets the population in an approximated string. Note this function changes the string value each call,...
Definition space.c:4743
void space_clearComputerMarkers(void)
Clears all the system computer markers.
Definition space.c:3984
MissionComputerSort sortby
Definition land.h:33
char * name
Definition mission.h:65
MissionAvail_t avail
Definition mission.h:67
Represents an active mission.
Definition mission.h:83
unsigned int distance
Definition mission.h:101
int illegal
Definition mission.h:102
char * reward
Definition mission.h:92
char * desc
Definition mission.h:91
char * title
Definition mission.h:90
const MissionData * data
Definition mission.h:84
credits_t reward_value
Definition mission.h:100
A ship outfit, depends radically on the type.
Definition outfit.h:372
credits_t price
Definition outfit.h:391
The representation of an in-game pilot.
Definition pilot.h:263
const Ship * ship
Definition pilot.h:274
char * name
Definition pilot.h:265
Player ship.
Definition player.h:72
int deployed
Definition player.h:80
Pilot * p
Definition player.h:73
char * name
Definition ship.h:100
int points
Definition ship.h:110
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition space.h:102
char * name
Definition space.h:105
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:43
double w
Definition opengl_tex.h:47
double h
Definition opengl_tex.h:48
unsigned int window_create(const char *name, const char *displayname, const int x, const int y, const int w, const int h)
Creates a window.
Definition toolkit.c:688
void window_dimWidget(unsigned int wid, const char *name, int *w, int *h)
Gets the dimensions of a widget.
Definition toolkit.c:415
void window_setFocus(unsigned int wid, const char *wgtname)
Sets the focused widget in a window.
Definition toolkit.c:2488
void window_setAccept(unsigned int wid, void(*accept)(unsigned int, const char *))
Sets the default accept function of the window.
Definition toolkit.c:846
void window_dimWindow(unsigned int wid, int *w, int *h)
Gets the dimensions of a window.
Definition toolkit.c:370
void window_setCancel(unsigned int wid, void(*cancel)(unsigned int, const char *))
Sets the default cancel function of the window.
Definition toolkit.c:868
void window_onClose(unsigned int wid, void(*fptr)(unsigned int, const char *))
Sets the default close function of the window.
Definition toolkit.c:824
void window_posWidget(unsigned int wid, const char *name, int *x, int *y)
Gets a widget's position.
Definition toolkit.c:441
void window_destroyWidget(unsigned int wid, const char *wgtname)
Destroys a widget in a window.
Definition toolkit.c:1167
void window_lower(unsigned int wid)
Lowers a window (causes all other windows to appear above it).
Definition toolkit.c:2577
int widget_exists(unsigned int wid, const char *wgtname)
Checks to see if a widget exists.
Definition toolkit.c:1144
void window_close(unsigned int wid, const char *str)
Helper function to automatically close the window calling it.
Definition toolkit.c:1028
void window_destroy(unsigned int wid)
Kills the window.
Definition toolkit.c:1039