naev 0.12.5
info.c
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "naev.h"
12
13#include "info.h"
14
15#include "array.h"
16#include "dialogue.h"
17#include "equipment.h"
18#include "hook.h"
19#include "land.h"
20#include "log.h"
21#include "map.h"
22#include "menu.h"
23#include "mission.h"
24#include "naevpedia.h"
25#include "nlua.h"
26#include "nstring.h"
27#include "ntime.h"
28#include "pilot.h"
29#include "player.h"
30#include "player_fleet.h"
31#include "player_inventory.h"
32#include "shiplog.h"
33#include "tk/toolkit_priv.h"
34#include "toolkit.h"
35
36#define BUTTON_WIDTH 135
37#define BUTTON_HEIGHT 30
38
39#define menu_Open( f ) ( menu_open |= ( f ) )
40#define menu_Close( f ) \
41 ( menu_open &= ~( f ) )
43
44#define INFO_WINDOWS 7
45
46#define INFO_WIN_MAIN 0
47#define INFO_WIN_SHIP 1
48#define INFO_WIN_WEAP 2
49#define INFO_WIN_CARGO 3
50#define INFO_WIN_MISN 4
51#define INFO_WIN_STAND 5
52#define INFO_WIN_SHIPLOG 6
53static const char *info_names[INFO_WINDOWS] = {
54 N_( "Main" ), N_( "Ship" ), N_( "Weapons" ), N_( "Cargo" ),
55 N_( "Missions" ), N_( "Standings" ), N_( "Ship log" ),
56};
57
61typedef struct InfoButton_s {
62 int id;
63 char *caption;
64 char *button;
66 /* Lua stuff .*/
67 nlua_env env;
68 int func;
69 SDL_Keycode key;
71static InfoButton_t *info_buttons = NULL;
72
73static unsigned int info_wid = 0;
74static unsigned int *info_windows = NULL;
75static int info_lastTab;
76
77static CstSlotWidget info_eq;
78static CstSlotWidget info_eq_weaps;
79static int *info_factions;
80
81static int selectedMission = 0;
82static int selectedLog = 0;
83static int selectedLogType = 0;
84static char **logTypes = NULL;
85static int ntypes = 0;
86static int nlogs = 0;
87static char **logs = NULL;
88static int *logIDs = NULL;
89static int logWidgetsReady = 0;
90
91/*
92 * prototypes
93 */
94/* information menu */
95static void info_close( unsigned int wid, const char *str );
96static void info_cleanup( unsigned int wid, const char *str );
97static void info_openMain( unsigned int wid );
98static void info_openShip( unsigned int wid );
99static void info_openWeapons( unsigned int wid );
100static void info_openCargo( unsigned int wid );
101static void info_openMissions( unsigned int wid );
102static void info_getDim( unsigned int wid, int *w, int *h, int *lw );
103static void info_buttonClick( unsigned int wid, const char *str );
104static void standings_close( unsigned int wid, const char *str );
105static void ship_update( unsigned int wid );
106static void weapons_genList( unsigned int wid );
107static void weapons_updateList( unsigned int wid, const char *str );
108static void weapons_toggleList( unsigned int wid, const char *str );
109static void weapons_clear( unsigned int wid, const char *str );
110static void weapons_clearAll( unsigned int wid, const char *str );
111static void weapons_autoweap( unsigned int wid, const char *str );
112static void weapons_inrange( unsigned int wid, const char *str );
113static void weapons_manual( unsigned int wid, const char *str );
114static void weapons_volley( unsigned int wid, const char *str );
115static void aim_lines( unsigned int wid, const char *str );
116static void weapons_renderLegend( double bx, double by, double bw, double bh,
117 void *data );
118static void weapons_help( unsigned int wid, const char *str );
119static void weapons_advanced( unsigned int wid, const char *str );
120static void info_openStandings( unsigned int wid );
121static void info_shiplogView( unsigned int wid, const char *str );
122static void standings_update( unsigned int wid, const char *str );
123static void cargo_genList( unsigned int wid );
124static void cargo_update( unsigned int wid, const char *str );
125static void cargo_jettison( unsigned int wid, const char *str );
126static void mission_menu_chk_hide( unsigned int wid, const char *str );
127static void mission_menu_chk_priority( unsigned int wid, const char *str );
128static void mission_menu_abort( unsigned int wid, const char *str );
129static void mission_menu_genList( unsigned int wid, int first );
130static void mission_menu_update( unsigned int wid, const char *str );
131static void info_openShipLog( unsigned int wid );
132static const char *info_getLogTypeFilter( int lstPos );
133static void info_changeTab( unsigned int wid, const char *str, int old,
134 int new );
135
136static int sort_buttons( const void *p1, const void *p2 )
137{
138 const InfoButton_t *b1 = p1;
139 const InfoButton_t *b2 = p2;
140 if ( b1->priority < b2->priority )
141 return -1;
142 else if ( b1->priority > b2->priority )
143 return +1;
144 return strcmp( b1->caption, b2->caption );
145}
146
147static void info_buttonFree( InfoButton_t *btn )
148{
149 free( btn->caption );
150 free( btn->button );
151 luaL_unref( naevL, LUA_REGISTRYINDEX, btn->func );
152}
153
154static void info_buttonRegen( void )
155{
156 int wid, w, h, rows, cols;
157 if ( !window_existsID( info_wid ) )
158 return;
159
160 wid = info_windows[INFO_WIN_MAIN];
161 window_dimWindow( wid, &w, &h );
162 cols = ( w - 20 ) / ( 20 + BUTTON_WIDTH );
163 rows = 1 + ( array_size( info_buttons ) ) / cols;
164
165 for ( int i = 0; i < array_size( info_buttons ); i++ ) {
166 const InfoButton_t *btn = &info_buttons[i];
167 int r = ( i + 1 ) / cols, c = ( i + 1 ) % cols;
168 if ( widget_exists( wid, btn->button ) )
169 window_destroyWidget( wid, btn->button );
170 window_addButtonKey( wid, -20 - c * ( 20 + BUTTON_WIDTH ),
171 20 + r * ( 20 + BUTTON_HEIGHT ), BUTTON_WIDTH,
172 BUTTON_HEIGHT, btn->button, btn->caption,
173 info_buttonClick, btn->key );
174 }
175 window_resizeWidget( wid, "lstInventory", w - 80 - 300 - 40 - 40,
176 h - 90 - rows * ( 20 + BUTTON_HEIGHT ) );
177 window_moveWidget( wid, "lstInventory", -20, -70 );
178}
179
189int info_buttonRegister( const char *caption, int priority, SDL_Keycode key )
190{
191 static int button_idgen = 0;
192 int id;
193 InfoButton_t *btn;
194
195 if ( info_buttons == NULL )
196 info_buttons = array_create( InfoButton_t );
197
198 btn = &array_grow( &info_buttons );
199 btn->id = ++button_idgen;
200 btn->caption = strdup( caption );
201 SDL_asprintf( &btn->button, "btnExtra::%s", caption );
202 btn->priority = priority;
203 btn->env = __NLUA_CURENV;
204 btn->func = luaL_ref( naevL, LUA_REGISTRYINDEX );
205 btn->key = key;
206
207 id = btn->id;
208 qsort( info_buttons, array_size( info_buttons ), sizeof( InfoButton_t ),
209 sort_buttons );
210
211 info_buttonRegen();
212 return id;
213}
214
222int info_buttonUnregister( int id )
223{
224 for ( int i = 0; i < array_size( info_buttons ); i++ ) {
225 InfoButton_t *btn = &info_buttons[i];
226 if ( btn->id != id )
227 continue;
228 if ( window_existsID( info_wid ) ) {
229 int wid = info_windows[INFO_WIN_MAIN];
230 if ( widget_exists( wid, btn->button ) )
231 window_destroyWidget( wid, btn->button );
232 }
233 info_buttonFree( btn );
234 array_erase( &info_buttons, btn, btn + 1 );
235 info_buttonRegen();
236 return 0;
237 }
238 return -1;
239}
240
245{
246 for ( int i = 0; i < array_size( info_buttons ); i++ ) {
247 InfoButton_t *btn = &info_buttons[i];
248 if ( window_existsID( info_wid ) ) {
249 int wid = info_windows[INFO_WIN_MAIN];
250 if ( widget_exists( wid, btn->button ) )
251 window_destroyWidget( wid, btn->button );
252 }
253 info_buttonFree( btn );
254 }
255 array_free( info_buttons );
256 info_buttons = NULL;
257 info_buttonRegen();
258}
259
260static void info_buttonClick( unsigned int wid, const char *str )
261{
262 (void)wid;
263 for ( int i = 0; i < array_size( info_buttons ); i++ ) {
264 InfoButton_t *btn = &info_buttons[i];
265 if ( strcmp( btn->button, str ) != 0 )
266 continue;
267
268 lua_rawgeti( naevL, LUA_REGISTRYINDEX, btn->func );
269 if ( nlua_pcall( btn->env, 0, 0 ) ) {
270 WARN( _( "Failure to run info button with id '%d':\n%s" ), btn->id,
271 lua_tostring( naevL, -1 ) );
272 lua_pop( naevL, 1 );
273 }
274 land_needsTakeoff( 1 ); /* Script said so? */
275 return;
276 }
277}
278
282void menu_info( int window )
283{
284 int w, h;
285 const char *names[INFO_WINDOWS];
286
287 /* Not under manual control. */
288 if ( pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ) )
289 return;
290
291 /* Open closes when previously opened. */
292 if ( menu_isOpen( MENU_INFO ) || dialogue_isOpen() ) {
293 if ( window_existsID( info_wid ) && !window_isTop( info_wid ) )
294 return;
295 info_close( 0, NULL );
296 return;
297 }
298
299 /* Dimensions. */
300 w = 700;
301 h = 700;
302
303 /* Create the window. */
304 info_wid = window_create( "wdwInfo", _( "Info" ), -1, -1, w, h );
305 window_setCancel( info_wid, info_close );
306 window_onClose( info_wid, info_cleanup );
307
308 /* Create tabbed window. */
309 for ( size_t i = 0; i < INFO_WINDOWS; i++ )
310 names[i] = _( info_names[i] );
311 info_windows = window_addTabbedWindow( info_wid, -1, -1, -1, -1, "tabInfo",
312 INFO_WINDOWS, names, 0 );
313
314 /* Open the subwindows. */
315 info_openMain( info_windows[INFO_WIN_MAIN] );
316 info_openShip( info_windows[INFO_WIN_SHIP] );
317 info_openWeapons( info_windows[INFO_WIN_WEAP] );
318 info_openCargo( info_windows[INFO_WIN_CARGO] );
319 info_openMissions( info_windows[INFO_WIN_MISN] );
320 info_openStandings( info_windows[INFO_WIN_STAND] );
321 info_openShipLog( info_windows[INFO_WIN_SHIPLOG] );
322
323 menu_Open( MENU_INFO );
324
325 /* Opening hooks. */
326 hooks_run( "info" );
327
328 /* Set active window. */
329 window_tabWinOnChange( info_wid, "tabInfo", info_changeTab );
330 if ( window == INFO_DEFAULT )
331 window = info_lastTab;
332 window_tabWinSetActive( info_wid, "tabInfo", CLAMP( 0, 6, window ) );
333}
334
338static void info_close( unsigned int wid, const char *str )
339{
340 (void)wid;
341 info_lastTab = window_tabWinGetActive( info_wid, "tabInfo" );
342 window_close( info_wid, str );
343}
344
345static void info_cleanup( unsigned int wid, const char *str )
346{
347 (void)wid;
348 (void)str;
349
350 if ( player.p != NULL ) {
351 /* Update weapon sets. */
353
354 /* Copy weapon sets over if changed. */
355 ws_copy( player.ps.weapon_sets, player.p->weapon_sets );
356 }
357
358 info_wid = 0;
359 info_windows = NULL;
360 logs = NULL;
361 menu_Close( MENU_INFO );
362}
363
367void info_update( void )
368{
369 if ( info_windows != NULL )
370 weapons_genList( info_windows[INFO_WIN_WEAP] );
371}
372
376static void info_openMain( unsigned int wid )
377{
378 const char **lic;
379 char str[STRMAX_SHORT], creds[ECON_CRED_STRLEN];
380 char **inventory;
381 char *nt;
382 int w, h, cargo_used, cargo_total, n;
383 unsigned int destroyed;
384 const PlayerItem *inv;
385 size_t k = 0, l = 0;
386
387 /* Get the dimensions. */
388 window_dimWindow( wid, &w, &h );
389
390 /* Compute ships destroyed. */
391 destroyed = 0;
392 for ( int i = 0; i < SHIP_CLASS_TOTAL; i++ )
393 destroyed += player.ships_destroyed[i];
394
395 /* pilot generics */
396 nt = ntime_pretty( ntime_get(), 2 );
397 k += scnprintf( &str[k], sizeof( str ) - k, "%s", _( "Pilot:" ) );
398 k += scnprintf( &str[k], sizeof( str ) - k, "\n%s", _( "Date:" ) );
399 k += scnprintf( &str[k], sizeof( str ) - k, "\n\n%s", _( "Money:" ) );
400 k += scnprintf( &str[k], sizeof( str ) - k, "\n%s", _( "Current Ship:" ) );
401 k += scnprintf( &str[k], sizeof( str ) - k, "\n%s", _( "Fuel:" ) );
402 k += scnprintf( &str[k], sizeof( str ) - k, "\n%s",
403 ( player.fleet_capacity > 0 ) ? _( "Cargo (fleet):" )
404 : _( "Cargo:" ) );
405 k += scnprintf( &str[k], sizeof( str ) - k, "\n\n%s", _( "Time played:" ) );
406 k += scnprintf( &str[k], sizeof( str ) - k, "\n%s", _( "Times died:" ) );
407 k += scnprintf( &str[k], sizeof( str ) - k, "\n%s", _( "Times jumped:" ) );
408 k += scnprintf( &str[k], sizeof( str ) - k, "\n%s", _( "Times landed:" ) );
409 k += scnprintf( &str[k], sizeof( str ) - k, "\n%s", _( "Damage done:" ) );
410 k += scnprintf( &str[k], sizeof( str ) - k, "\n%s", _( "Damage taken:" ) );
411 /*k +=*/scnprintf( &str[k], sizeof( str ) - k, "\n%s",
412 _( "Ships destroyed:" ) );
413 window_addText( wid, 20, 20, 160, h - 80, 0, "txtDPilot", &gl_smallFont,
414 &cFontGrey, str );
415
416 credits2str( creds, player.p->credits, 2 );
417 l += scnprintf( &str[l], sizeof( str ) - l, "%s", player.name );
418 l += scnprintf( &str[l], sizeof( str ) - l, "\n%s", nt );
419 l += scnprintf( &str[l], sizeof( str ) - l, "\n\n%s", creds );
420 l += scnprintf( &str[l], sizeof( str ) - l, "\n%s", player.p->name );
421 l += scnprintf( &str[l], sizeof( str ) - l, "\n%.0f %s (%d %s)",
422 player.p->fuel, UNIT_UNIT, pilot_getJumps( player.p ),
423 n_( "jump", "jumps", pilot_getJumps( player.p ) ) );
424 cargo_used = pfleet_cargoUsed();
425 cargo_total = cargo_used + pfleet_cargoFree();
426 l += scnprintf( &str[l], sizeof( str ) - l, "\n%d / %d %s", cargo_used,
427 cargo_total, UNIT_MASS );
428 l += scnprintf( &str[l], sizeof( str ) - l, "%s", "\n\n" );
429 l += scnprintf( &str[l], sizeof( str ) - l, _( "%.1f hours" ),
430 player.time_played / 3600. );
431 l += scnprintf( &str[l], sizeof( str ) - l, "\n%s",
432 num2strU( (double)player.death_counter, 0 ) );
433 l += scnprintf( &str[l], sizeof( str ) - l, "\n%s",
434 num2strU( (double)player.jumped_times, 0 ) );
435 l += scnprintf( &str[l], sizeof( str ) - l, "\n%s\n",
436 num2strU( (double)player.landed_times, 0 ) );
437 l +=
438 scnprintf( &str[l], sizeof( str ) - l, _( "%s %s" ),
439 num2strU( player.dmg_done_shield + player.dmg_done_armour, 0 ),
440 UNIT_ENERGY );
441 l += scnprintf( &str[l], sizeof( str ) - l, "\n" );
442 l += scnprintf(
443 &str[l], sizeof( str ) - l, _( "%s %s" ),
444 num2strU( player.dmg_taken_shield + player.dmg_taken_armour, 0 ),
445 UNIT_ENERGY );
446 /*l +=*/scnprintf( &str[l], sizeof( str ) - l, "\n%s",
447 num2strU( destroyed, 0 ) );
448 window_addText( wid, 200, 20, w - 80 - 200 - 40 + 20 - 180, h - 80, 0,
449 "txtPilot", &gl_smallFont, NULL, str );
450 free( nt );
451
452 /* menu */
453 window_addButtonKey( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnClose",
454 _( "Close" ), info_close, SDLK_c );
455
456 /* TODO probably add alt text with descriptions. */
457 lic = player_getLicenses();
458 inv = player_inventory();
459 n = array_size( lic ) + array_size( inv );
460 /* List. */
461 if ( n == 0 ) {
462 inventory = malloc( sizeof( char *) );
463 inventory[0] = strdup( _( "None" ) );
464 n = 1;
465 } else {
466 int nlic = array_size( lic );
467 int ninv = array_size( inv );
468 inventory = malloc( sizeof( char * ) * n );
469 for ( int i = 0; i < nlic; i++ )
470 SDL_asprintf( &inventory[i], "#n%s#0%s", _( "License: " ),
471 _( lic[i] ) );
472 qsort( inventory, nlic, sizeof( char * ), strsort );
473 for ( int i = 0; i < ninv; i++ ) {
474 const PlayerItem *pi = &inv[i];
475 if ( pi->quantity == 0 )
476 SDL_asprintf( &inventory[nlic + i], "%s", _( pi->name ) );
477 else
478 SDL_asprintf( &inventory[nlic + i], _( "%s (%s)" ), _( pi->name ),
479 num2strU( pi->quantity, 0 ) );
480 }
481 qsort( &inventory[nlic], ninv, sizeof( char * ), strsort );
482 }
483 window_addText( wid, -20, -40, w - 80 - 300 - 40 - 40, 20, 1, "txtList",
484 NULL, NULL, _( "Inventory" ) );
485 window_addList( wid, -20, -70, w - 80 - 300 - 40 - 40,
486 h - 110 - BUTTON_HEIGHT, "lstInventory", inventory, n, 0,
487 NULL, NULL );
488 window_setFocus( wid, "lstInventory" );
489
490 info_buttonRegen();
491}
492
498static void info_openShip( unsigned int wid )
499{
500 int w, h;
501 char buf[STRMAX];
502 size_t l = 0;
503
504 /* Get the dimensions. */
505 window_dimWindow( wid, &w, &h );
506
507 /* Buttons */
508 window_addButtonKey( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
509 "closeOutfits", _( "Close" ), info_close, SDLK_c );
510
511 /* Text. */
512 l += scnprintf( &buf[l], sizeof( buf ) - l, "%s", _( "Name:" ) );
513 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Model:" ) );
514 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Class:" ) );
515 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Crew:" ) );
516 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
517 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Mass:" ) );
518 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Jump Time:" ) );
519 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Accel:" ) );
520 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Speed:" ) );
521 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Turn:" ) );
522 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Time Constant:" ) );
523 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
524 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Absorption:" ) );
525 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Shield:" ) );
526 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Armour:" ) );
527 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Energy:" ) );
528 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Cargo Space:" ) );
529 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Fuel:" ) );
530 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
531 /*l +=*/scnprintf( &buf[l], sizeof( buf ) - l, "\n%s", _( "Stats:" ) );
532 window_addText( wid, 20, -40, 160, h - 60, 0, "txtSDesc", &gl_smallFont,
533 &cFontGrey, buf );
534 window_addText( wid, 200, -40, w - 20 - 20 - 20 - 200 - 180., h - 60, 0,
535 "txtDDesc", &gl_smallFont, NULL, NULL );
536
537 /* Custom widget. */
538 equipment_slotWidget( wid, -20, -40, 180, h - 60, &info_eq );
539 equipment_slotSelect( &info_eq, &player.ps );
540 info_eq.canmodify = 0;
541
542 /* Update ship. */
543 ship_update( wid );
544}
545
549static void ship_update( unsigned int wid )
550{
551 char buf[STRMAX_SHORT], *hyp_delay;
552 char sshield[NUM2STRLEN], sarmour[NUM2STRLEN], senergy[NUM2STRLEN];
553 char scargo[NUM2STRLEN], sfuel[NUM2STRLEN];
554 size_t l = 0;
555 int cargo = pilot_cargoUsed( player.p ) + pilot_cargoFree( player.p );
556
557 /* Some helpers. */
558 num2str( sshield, player.p->shield, 0 );
559 num2str( sarmour, player.p->armour, 0 );
560 num2str( senergy, player.p->energy, 0 );
561 num2str( scargo, pilot_cargoUsed( player.p ), 0 );
562 num2str( sfuel, player.p->fuel, 0 );
563
564 hyp_delay = ntime_pretty( pilot_hyperspaceDelay( player.p ), 2 );
565 /* Generic */
566 l += scnprintf( &buf[l], sizeof( buf ) - l, "%s", player.p->name );
567 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s",
568 _( player.p->ship->name ) );
569 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%s",
570 _( ship_class( player.p->ship ) ) );
571 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%d",
572 (int)floor( player.p->crew ) );
573 /* Movement. */
574 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n\n" );
575 l += scnprintf( &buf[l], sizeof( buf ) - l, _( "%s %s" ),
576 num2strU( player.p->solid.mass, 0 ), UNIT_MASS );
577 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
578 l += scnprintf( &buf[l], sizeof( buf ) - l, _( "%s average" ), hyp_delay );
579 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
580 l += scnprintf( &buf[l], sizeof( buf ) - l, _( "%.0f %s" ), player.p->accel,
581 UNIT_ACCEL );
582 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
583 l += scnprintf(
584 &buf[l], sizeof( buf ) - l, _( "%.0f %s (max %.0f %s)" ), player.p->speed,
585 UNIT_SPEED,
586 solid_maxspeed( &player.p->solid, player.p->speed, player.p->accel ),
587 UNIT_SPEED );
588 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
589 l += scnprintf( &buf[l], sizeof( buf ) - l, _( "%.0f %s" ),
590 player.p->turn * 180. / M_PI, UNIT_ROTATION );
591 l +=
592 scnprintf( &buf[l], sizeof( buf ) - l, "\n%.0f%%",
593 player.p->stats.time_mod * player.p->ship->dt_default * 100. );
594 /* Health. */
595 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
596 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n%.0f%%",
597 player.p->dmg_absorb * 100. );
598 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
599 l += scnprintf( &buf[l], sizeof( buf ) - l, _( "%s / %s %s" ), sshield,
600 num2strU( player.p->shield_max, 0 ), UNIT_ENERGY );
601 l += scnprintf( &buf[l], sizeof( buf ) - l, _( " (%s %s)" ),
602 num2strU( player.p->shield_regen, 1 ), UNIT_POWER );
603 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
604 l += scnprintf( &buf[l], sizeof( buf ) - l, _( "%s / %s %s" ), sarmour,
605 num2strU( player.p->armour_max, 0 ), UNIT_ENERGY );
606 l += scnprintf( &buf[l], sizeof( buf ) - l, _( " (%s %s)" ),
607 num2strU( player.p->armour_regen, 1 ), UNIT_POWER );
608 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
609 l += scnprintf( &buf[l], sizeof( buf ) - l, _( "%s / %s %s" ), senergy,
610 num2strU( player.p->energy_max, 0 ), UNIT_ENERGY );
611 l += scnprintf( &buf[l], sizeof( buf ) - l, _( " (%s %s)" ),
612 num2strU( player.p->energy_regen, 1 ), UNIT_POWER );
613 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
614 l += scnprintf( &buf[l], sizeof( buf ) - l, _( "%s / %s %s" ), scargo,
615 num2strU( cargo, 0 ), UNIT_MASS );
616 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n" );
617 l += scnprintf( &buf[l], sizeof( buf ) - l, _( "%s / %s %s (%d %s)" ), sfuel,
618 num2strU( player.p->fuel_max, 0 ), UNIT_UNIT,
620 n_( "jump", "jumps", pilot_getJumps( player.p ) ) );
621 l += scnprintf( &buf[l], sizeof( buf ) - l, "%s", "\n\n" );
622
623 equipment_shipStats( &buf[l], sizeof( buf ) - l, player.p, 0, 0 );
624 window_modifyText( wid, "txtDDesc", buf );
625 free( hyp_delay );
626}
627
631static void info_openWeapons( unsigned int wid )
632{
633 int w, h, x, y, wlen;
634 const int advanced = player.p->advweap;
635
636 /* Get the dimensions. */
637 window_dimWindow( wid, &w, &h );
638
639 /* Custom widget. */
640 equipment_slotWidget( wid, 20, -40, 180, h - 60, &info_eq_weaps );
641 equipment_slotSelect( &info_eq_weaps, &player.ps );
642 info_eq_weaps.weapons = 0;
643 info_eq_weaps.canmodify = 0;
644
645 /* Custom widget for legend. */
646 y = -290;
647 window_addCust( wid, 220, y, w - 200 - 60, 100, "cstLegend", 0,
648 weapons_renderLegend, NULL, NULL, NULL, NULL );
649
650 /* Checkboxes. */
651 wlen = w - 220 - 20;
652 x = 220;
653 y -= 75;
654 if ( advanced ) {
655 window_addButtonKey( wid, x + 10, y, BUTTON_WIDTH, BUTTON_HEIGHT,
656 "btnCycle", _( "Cycle Mode" ), weapons_toggleList,
657 SDLK_m );
658 x += BUTTON_WIDTH + 10;
659 }
660 window_addButtonKey( wid, x + 10 + ( BUTTON_WIDTH + 10 ) * 0, y,
661 BUTTON_WIDTH, BUTTON_HEIGHT, "btnClear", _( "Clear" ),
662 weapons_clear, SDLK_l );
663 window_addButtonKey( wid, x + 10 + ( BUTTON_WIDTH + 10 ) * 1, y,
664 BUTTON_WIDTH, BUTTON_HEIGHT, "btnClearAll",
665 _( "Clear All" ), weapons_clearAll, SDLK_a );
666 x = 220;
667 y -= BUTTON_HEIGHT + 10;
668 if ( advanced ) {
669 window_addText(
670 wid, x + 10, y, wlen, 100, 0, "txtSMode", NULL, NULL,
671 _( "Cycles through the following modes:\n"
672 "- Default: tap to toggle, hold to hold\n"
673 "- Hold: turns on the selected outfits as long as key is held\n"
674 "- Toggle: toggles the selected outfits to on or off state" ) );
675 y -= 8 + window_getTextHeight( wid, "txtSMode" );
676 }
677 window_addCheckbox(
678 wid, x + 10, y, wlen, BUTTON_HEIGHT, "chkManual",
679 _( "Enable manual aiming mode" ), weapons_manual,
680 pilot_weapSetManualCheck( player.p, info_eq_weaps.weapons ) );
681 y -= 28;
682 window_addCheckbox(
683 wid, x + 10, y, wlen, BUTTON_HEIGHT, "chkVolley",
684 _( "Enable volley mode (weapons fire jointly)" ), weapons_volley,
685 pilot_weapSetVolleyCheck( player.p, info_eq_weaps.weapons ) );
686 y -= 28;
687 window_addCheckbox(
688 wid, x + 10, y, wlen, BUTTON_HEIGHT, "chkInrange",
689 _( "Only shoot weapons that are in range" ), weapons_inrange,
690 pilot_weapSetInrangeCheck( player.p, info_eq_weaps.weapons ) );
691 y -= 28;
692 window_addCheckbox( wid, x + 10, y, wlen, BUTTON_HEIGHT, "chkHelper",
693 _( "Dogfight visual aiming helper (all sets)" ),
694 aim_lines, player.p->aimLines );
695 y -= 28;
696 if ( !advanced )
697 window_addCheckbox( wid, x + 10, y, wlen, BUTTON_HEIGHT, "chkAutoweap",
698 _( "Automatically handle all weapons sets" ),
699 weapons_autoweap, player.p->autoweap );
700
701 /* List. Has to be generated after checkboxes. */
702 weapons_genList( wid );
703
704 /* Buttons */
705 window_addButtonKey( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
706 "closeWeapons", _( "Close" ), info_close, SDLK_c );
707 window_addButtonKey( wid, -20 - 1 * ( BUTTON_WIDTH + 10 ), 20, BUTTON_WIDTH,
708 BUTTON_HEIGHT, "btnHelp", p_( "UI", "Help" ),
709 weapons_help, SDLK_h );
710 window_addButtonKey( wid, -20 - 2 * ( BUTTON_WIDTH + 10 ), 20, BUTTON_WIDTH,
711 BUTTON_HEIGHT, "btnAdvanced", p_( "UI", "Advanced" ),
712 weapons_advanced, SDLK_e );
713 if ( advanced )
714 window_buttonCaption( wid, "btnAdvanced", p_( "UI", "Simple" ) );
715}
716
720static void weapons_genList( unsigned int wid )
721{
722 char **buf, tbuf[STRMAX_SHORT];
723 int n, w, h;
724
725 /* Get the dimensions. */
726 window_dimWindow( wid, &w, &h );
727
728 /* Destroy widget if needed. */
729 if ( widget_exists( wid, "lstWeapSets" ) ) {
730 window_destroyWidget( wid, "lstWeapSets" );
731 n = toolkit_getListPos( wid, "lstWeapSets" );
732 } else
733 n = -1;
734
735 /* List */
736 buf = malloc( sizeof( char * ) * PILOT_WEAPON_SETS );
737 for ( int i = 0; i < PILOT_WEAPON_SETS; i++ ) {
738 const char *str = pilot_weapSetName( info_eq_weaps.selected->p, i );
739 if ( i < 2 )
740 snprintf( tbuf, sizeof( tbuf ), "#%c%s#0 - %s", ( i == 0 ) ? 'r' : 'y',
741 ( i == 0 ) ? _( "Primary" ) : _( "Secondary" ), str );
742 else
743 snprintf( tbuf, sizeof( tbuf ), _( "Weapset %d - %s" ),
744 ( i - 2 + 1 ) % 10, str );
745 buf[i] = strdup( tbuf );
746 }
747 window_addList( wid, 20 + 180 + 20, -40, w - ( 20 + 180 + 20 + 20 ), 250,
748 "lstWeapSets", buf, PILOT_WEAPON_SETS, 0, weapons_updateList,
749 weapons_toggleList );
750 window_setFocus( wid, "lstWeapSets" );
751
752 /* Restore position. */
753 if ( n >= 0 )
754 toolkit_setListPos( wid, "lstWeapSets", n );
755}
756
760static void weapons_updateList( unsigned int wid, const char *str )
761{
762 (void)str;
763 int pos;
764
765 /* Update the position. */
766 pos = toolkit_getListPos( wid, "lstWeapSets" );
767 if ( pos < 0 )
768 return;
769 info_eq_weaps.weapons = pos;
770
771 /* Update inrange. */
772 window_checkboxSet( wid, "chkInrange",
774
775 /* Update volley. */
776 window_checkboxSet( wid, "chkVolley",
778
779 /* Update manual aiming. */
780 window_checkboxSet( wid, "chkManual",
782
783 /* Update autoweap. */
784 if ( widget_exists( wid, "chkAutoweap" ) )
785 window_checkboxSet( wid, "chkAutoweap", player.p->autoweap );
786}
787
788static void weapons_toggleList( unsigned int wid, const char *str )
789{
790 int t, c;
791 (void)str;
792
793 /* See how to handle. */
794 t = pilot_weapSetTypeCheck( player.p, info_eq_weaps.weapons );
795 switch ( t ) {
796 case WEAPSET_TYPE_DEFAULT:
797 c = WEAPSET_TYPE_HOLD;
798 break;
799 case WEAPSET_TYPE_HOLD:
800 c = WEAPSET_TYPE_TOGGLE;
801 break;
802 case WEAPSET_TYPE_TOGGLE:
803 c = WEAPSET_TYPE_DEFAULT;
804 break;
805 default:
806 /* Shouldn't happen... but shuts up GCC */
807 c = WEAPSET_TYPE_HOLD;
808 break;
809 }
810 pilot_weapSetType( player.p, info_eq_weaps.weapons, c );
811
812 /* Must regen. */
813 weapons_genList( wid );
814}
815
819static void weapons_clear( unsigned int wid, const char *str )
820{
821 (void)str;
822 pilot_weapSetClear( player.p, info_eq_weaps.weapons );
823
824 /* Must regen. */
825 weapons_genList( wid );
826}
827
831static void weapons_clearAll( unsigned int wid, const char *str )
832{
833 (void)str;
834 int sure = dialogue_YesNoRaw(
835 _( "Clear All Weapon Sets?" ),
836 _( "Are you sure you want to clear all your current weapon sets?" ) );
837 if ( !sure )
838 return;
839
840 /* Clear them all. */
841 for ( int i = 0; i < PILOT_WEAPON_SETS; i++ )
843
844 /* Must regen. */
845 weapons_genList( wid );
846}
847
851static void weapons_autoweap( unsigned int wid, const char *str )
852{
853 /* Set state. */
854 int state = window_checkboxState( wid, str );
855
856 /* Run autoweapons if needed. */
857 if ( state ) {
858 int sure = dialogue_YesNoRaw(
859 _( "Enable autoweapons?" ),
860 _( "Are you sure you want to enable automatic weapon groups for the "
861 "ship?\n\nThis will overwrite all manually-tweaked weapons "
862 "groups." ) );
863 if ( !sure ) {
864 window_checkboxSet( wid, str, 0 );
865 return;
866 }
867 player.p->autoweap = 1;
869 weapons_genList( wid );
870 } else
871 player.p->autoweap = 0;
872}
873
877static void weapons_inrange( unsigned int wid, const char *str )
878{
879 int state = window_checkboxState( wid, str );
880 pilot_weapSetInrange( player.p, info_eq_weaps.weapons, state );
881 player.p->autoweap = 0;
882 if ( widget_exists( wid, "chkAutoweap" ) )
883 window_checkboxSet( wid, "chkAutoweap", player.p->autoweap );
884}
885
889static void weapons_manual( unsigned int wid, const char *str )
890{
891 int state = window_checkboxState( wid, str );
892 pilot_weapSetManual( player.p, info_eq_weaps.weapons, state );
893 player.p->autoweap = 0;
894 if ( widget_exists( wid, "chkAutoweap" ) )
895 window_checkboxSet( wid, "chkAutoweap", player.p->autoweap );
896}
897
901static void weapons_volley( unsigned int wid, const char *str )
902{
903 int state = window_checkboxState( wid, str );
904 pilot_weapSetVolley( player.p, info_eq_weaps.weapons, state );
905 player.p->autoweap = 0;
906 if ( widget_exists( wid, "chkAutoweap" ) )
907 window_checkboxSet( wid, "chkAutoweap", player.p->autoweap );
908}
909
913static void aim_lines( unsigned int wid, const char *str )
914{
915 int state = window_checkboxState( wid, str );
916 player.p->aimLines = state;
917}
918
922static void weapons_renderLegend( double bx, double by, double bw, double bh,
923 void *data )
924{
925 (void)data;
926 (void)bw;
927 (void)bh;
928 double y;
929
930 y = by + bh - 20;
931 gl_print( &gl_defFont, bx, y, &cFontWhite, p_( "info", "Legend" ) );
932
933 y -= 20.;
934 toolkit_drawRect( bx, y, 10, 10, &cFontBlue, NULL );
935 gl_print( &gl_smallFont, bx + 20, y, &cFontWhite,
936 _( "Outfit that can be activated" ) );
937
938 y -= 20.;
939 toolkit_drawRect( bx, y, 10, 10, &cFontRed, NULL );
940 gl_print( &gl_smallFont, bx + 20, y, &cFontWhite,
941 _( "Outfit that is enabled for the weapon set" ) );
942}
943
947static void weapons_help( unsigned int wid, const char *str )
948{
949 (void)wid;
950 (void)str;
951 naevpedia_open( "mechanics/weaponsets" );
952}
953
957static void weapons_advanced( unsigned int wid, const char *str )
958{
959 (void)str;
960 player.p->advweap = !player.p->advweap;
961
962 int n = toolkit_getListPos( wid, "lstWeapSets" );
963 window_clearWidgets( wid );
964 info_openWeapons( wid );
965 toolkit_setListPos( wid, "lstWeapSets", n );
966}
967
973static void info_openCargo( unsigned int wid )
974{
975 int w, h;
976
977 /* Get the dimensions. */
978 window_dimWindow( wid, &w, &h );
979
980 /* Buttons */
981 window_addButtonKey( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, "closeCargo",
982 _( "Close" ), info_close, SDLK_c );
983 window_addButtonKey( wid, -20 - BUTTON_WIDTH - 10, 20, BUTTON_WIDTH,
984 BUTTON_HEIGHT, "btnJettisonCargo", _( "Jettison" ),
985 cargo_jettison, SDLK_j );
986 window_disableButton( wid, "btnJettisonCargo" );
987
988 /* Description. */
989 window_addText( wid, 20, -40 - 200 - 20, w - 40, h - BUTTON_HEIGHT - 260, 0,
990 "txtCargoDesc", NULL, NULL, NULL );
991
992 /* Generate the list. */
993 cargo_genList( wid );
994}
998static void cargo_genList( unsigned int wid )
999{
1000 char **buf;
1001 int nbuf;
1002 int w, h;
1003 PilotCommodity *pclist = pfleet_cargoList();
1004
1005 /* Get the dimensions. */
1006 window_dimWindow( wid, &w, &h );
1007
1008 /* Destroy widget if needed. */
1009 if ( widget_exists( wid, "lstCargo" ) )
1010 window_destroyWidget( wid, "lstCargo" );
1011
1012 /* List */
1013 if ( array_size( pclist ) == 0 ) {
1014 /* No cargo */
1015 buf = malloc( sizeof( char *) );
1016 buf[0] = strdup( _( "None" ) );
1017 nbuf = 1;
1018 } else {
1019 /* List the player fleet's cargo. */
1020 buf = malloc( sizeof( char * ) * array_size( pclist ) );
1021 for ( int i = 0; i < array_size( pclist ); i++ ) {
1022 PilotCommodity *pc = &pclist[i];
1023 int misn = ( pc->id != 0 );
1024 int illegal = ( array_size( pc->commodity->illegalto ) > 0 );
1025
1026 SDL_asprintf( &buf[i], "%s %d%s%s", _( pc->commodity->name ),
1027 pc->quantity, misn ? _( " [#bMission#0]" ) : "",
1028 illegal ? _( " (#rillegal#0)" ) : "" );
1029 }
1030 nbuf = array_size( pclist );
1031 }
1032 array_free( pclist );
1033 window_addList( wid, 20, -40, w - 40, 200, "lstCargo", buf, nbuf, 0,
1034 cargo_update, NULL );
1035 window_setFocus( wid, "lstCargo" );
1036}
1041static void cargo_update( unsigned int wid, const char *str )
1042{
1043 (void)str;
1044 char desc[STRMAX];
1045 int pos, l;
1046 const Commodity *com;
1047 PilotCommodity *pclist = pfleet_cargoList();
1048
1049 if ( array_size( pclist ) <= 0 ) {
1050 window_modifyText( wid, "txtCargoDesc", NULL );
1051 array_free( pclist );
1052 return; /* No cargo, redundant check */
1053 }
1054
1055 /* Can jettison all but mission cargo when not landed. */
1056 if ( landed || pilot_isFlag( player.p, PILOT_LANDING ) )
1057 window_disableButton( wid, "btnJettisonCargo" );
1058 else
1059 window_enableButton( wid, "btnJettisonCargo" );
1060
1061 pos = toolkit_getListPos( wid, "lstCargo" );
1062 com = pclist[pos].commodity;
1063
1064 if ( !com->description )
1065 l = scnprintf( desc, sizeof( desc ), "%s", _( com->name ) );
1066 else
1067 l = scnprintf( desc, sizeof( desc ), "%s\n\n%s", _( com->name ),
1068 _( com->description ) );
1069
1070 /* Only add fleet information with fleet capacity. */
1071 if ( pclist[pos].id > 0 ) {
1072 l += scnprintf( &desc[l], sizeof( desc ) - l, "\n\n%s",
1073 _( "This is cargo related to a mission and can only be "
1074 "carried by your main ship." ) );
1075 } else if ( ( player.fleet_capacity > 0 ) && ( pclist[pos].quantity > 0 ) ) {
1076 l += scnprintf( &desc[l], sizeof( desc ) - l, "\n\n%s",
1077 _( "Carried by the following ships in your fleet:\n" ) );
1078 PFleetCargo *plist = pfleet_cargoListShips( com );
1079 for ( int i = 0; i < array_size( plist ); i++ )
1080 l += scnprintf( &desc[l], sizeof( desc ) - l, _( "\n - %s (%d)" ),
1081 plist[i].p->name, plist[i].q );
1082 array_free( plist );
1083 }
1084
1085 /* Add message on illegal outfits. */
1086 if ( array_size( com->illegalto ) > 0 ) {
1087 l += scnprintf( &desc[l], sizeof( desc ) - l, "\n\n%s",
1088 _( "Illegalized by the following factions:\n" ) );
1089 for ( int i = 0; i < array_size( com->illegalto ); i++ ) {
1090 int f = com->illegalto[i];
1091 if ( !faction_isKnown( f ) )
1092 continue;
1093
1094 l += scnprintf( &desc[l], sizeof( desc ) - l, _( "\n - %s" ),
1095 _( faction_name( f ) ) );
1096 }
1097 }
1098 window_modifyText( wid, "txtCargoDesc", desc );
1099
1100 array_free( pclist );
1101}
1106static void cargo_jettison( unsigned int wid, const char *str )
1107{
1108 (void)str;
1109 int pos;
1110 HookParam hparam[3];
1111 PilotCommodity *pclist = pfleet_cargoList();
1112
1113 if ( array_size( pclist ) <= 0 ) {
1114 array_free( pclist );
1115 return; /* No cargo, redundant check */
1116 }
1117
1118 pos = toolkit_getListPos( wid, "lstCargo" );
1119
1120 /* Special case mission cargo. */
1121 if ( pclist[pos].id != 0 ) {
1122 int f, ret;
1123 Mission *misn;
1124
1125 if ( !dialogue_YesNo(
1126 _( "Abort Mission" ),
1127 _( "Are you sure you want to abort this mission?" ) ) ) {
1128 array_free( pclist );
1129 return;
1130 }
1131
1132 /* Get the mission. */
1133 f = -1;
1134 for ( int i = 0; i < array_size( player_missions ); i++ ) {
1135 for ( int j = 0; j < array_size( player_missions[i]->cargo ); j++ ) {
1136 if ( player_missions[i]->cargo[j] == pclist[pos].id ) {
1137 f = i;
1138 break;
1139 }
1140 }
1141 if ( f >= 0 )
1142 break;
1143 }
1144 if ( f < 0 ) {
1145 WARN( _( "Cargo '%d' does not belong to any active mission." ),
1146 pclist[pos].id );
1147 array_free( pclist );
1148 return;
1149 }
1150 misn = player_missions[f];
1151
1152 /* We run the "abort" function if it's found. */
1153 ret = misn_tryRun( misn, "abort" );
1154
1155 /* Now clean up mission. */
1156 if ( ret != 2 ) {
1157 mission_cleanup( misn );
1158 mission_shift( pos );
1159 }
1160
1161 /* Reset markers. */
1163
1164 /* Reset claims. */
1166
1167 /* Regenerate list. */
1168 mission_menu_genList( info_windows[INFO_WIN_MISN], 0 );
1169 } else
1170 /* Remove the cargo */
1171 pfleet_cargoRm( pclist[pos].commodity, pclist[pos].quantity, 1 );
1172
1173 /* We reopen the menu to recreate the list now. */
1174 ship_update( info_windows[INFO_WIN_SHIP] );
1175 cargo_genList( wid );
1176 cargo_update( wid, NULL );
1177
1178 /* Run hooks. */
1179 hparam[0].type = HOOK_PARAM_COMMODITY;
1180 hparam[0].u.commodity =
1181 (Commodity *)pclist[pos].commodity; /* TODO not cast */
1182 hparam[1].type = HOOK_PARAM_NUMBER;
1183 hparam[1].u.num = pclist[pos].quantity;
1184 hparam[2].type = HOOK_PARAM_SENTINEL;
1185 hooks_runParam( "comm_jettison", hparam );
1186
1187 /* Clean up. */
1188 array_free( pclist );
1189}
1190
1194static void info_getDim( unsigned int wid, int *w, int *h, int *lw )
1195{
1196 /* Get the dimensions. */
1197 window_dimWindow( wid, w, h );
1198 *lw = *w - 60 - BUTTON_WIDTH - 190;
1199}
1200
1204static void standings_close( unsigned int wid, const char *str )
1205{
1206 (void)wid;
1207 (void)str;
1208 array_free( info_factions );
1209 info_factions = NULL;
1210}
1211
1212static int factionsSort( const void *p1, const void *p2 )
1213{
1214 int f1, f2;
1215 double v1, v2;
1216 f1 = *(int *)p1;
1217 f2 = *(int *)p2;
1218 v1 = round( faction_reputation( f1 ) );
1219 v2 = round( faction_reputation( f2 ) );
1220 if ( v1 < v2 )
1221 return 1;
1222 else if ( v1 > v2 )
1223 return -1;
1224 return strcmp( faction_longname( f1 ), faction_longname( f2 ) );
1225}
1229static void info_openStandings( unsigned int wid )
1230{
1231 char **str;
1232 int w, h, lw;
1233
1234 /* Update global standings just in case. */
1236
1237 /* Get dimensions. */
1238 info_getDim( wid, &w, &h, &lw );
1239
1240 /* On close. */
1241 window_onClose( wid, standings_close );
1242
1243 /* Buttons */
1244 window_addButtonKey( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
1245 "closeMissions", _( "Close" ), info_close, SDLK_c );
1246
1247 /* Graphics. */
1248 window_addImage( wid, 0, 0, 0, 0, "imgLogo", NULL, 0 );
1249
1250 /* Text. */
1251 window_addText( wid, lw + 40, 0, ( w - ( lw + 60 ) ), 20, 0, "txtName",
1252 &gl_defFont, NULL, NULL );
1253 window_addText( wid, lw + 40, 0, ( w - ( lw + 60 ) ), 40, 0, "txtStanding",
1254 &gl_defFont, NULL, NULL );
1255 window_addText( wid, lw + 40, 0, ( w - ( lw + 60 ) ), h - 80, 0,
1256 "txtDescription", &gl_defFont, NULL, NULL );
1257
1258 /* Gets the faction standings. */
1259 info_factions = faction_getKnown();
1260 str = malloc( sizeof( char *) * array_size( info_factions ) );
1261 qsort( info_factions, array_size( info_factions ), sizeof( int ),
1262 factionsSort );
1263
1264 /* Create list. */
1265 for ( int i = 0; i < array_size( info_factions ); i++ ) {
1266 double m = round( faction_reputation( info_factions[i] ) );
1267 SDL_asprintf( &str[i], p_( "standings", "%s [ #%c%+.0f%%#0 ]" ),
1268 faction_longname( info_factions[i] ),
1269 faction_reputationColourChar( info_factions[i] ), m );
1270 }
1271
1272 /* Display list. */
1273 window_addList( wid, 20, -40, lw, h - 60, "lstStandings", str,
1274 array_size( info_factions ), 0, standings_update, NULL );
1275 window_setFocus( wid, "lstStandings" );
1276}
1277
1281static void standings_update( unsigned int wid, const char *str )
1282{
1283 (void)str;
1284 int p, x, y;
1285 const glTexture *t;
1286 int w, h, lw, l;
1287 double m, ml;
1288 const int *flist;
1289 char buf[STRMAX];
1290
1291 /* Get dimensions. */
1292 info_getDim( wid, &w, &h, &lw );
1293
1294 /* Get faction. */
1295 p = toolkit_getListPos( wid, "lstStandings" );
1296
1297 /* Render logo. */
1298 x = lw + 40;
1299 y = -40;
1300 t = faction_logo( info_factions[p] );
1301 if ( t != NULL ) {
1302 int tw = t->w * (double)FACTION_LOGO_SM / MAX( t->w, t->h );
1303 int th = t->h * (double)FACTION_LOGO_SM / MAX( t->w, t->h );
1304 window_modifyImage( wid, "imgLogo", t, tw, th );
1305 window_moveWidget( wid, "imgLogo", x + ( FACTION_LOGO_SM - tw ),
1306 y - ( FACTION_LOGO_SM - th ) / 2 );
1307 x += FACTION_LOGO_SM + 20;
1308 // y -= FACTION_LOGO_SM;
1309 } else
1310 window_modifyImage( wid, "imgLogo", NULL, 0, 0 );
1311
1312 /* Modify text. */
1313 y -= 10;
1314 m = round( faction_reputation( info_factions[p] ) );
1315 l = snprintf( buf, sizeof( buf ), p_( "standings", "#%c%+.0f%%#0 [ %s ]" ),
1316 faction_reputationColourChar( info_factions[p] ), m,
1317 faction_getStandingText( info_factions[p] ) );
1318 ml = round( system_getReputationOrGlobal( cur_system, info_factions[p] ) );
1319 if ( ABS( ml - m ) > 1e-1 )
1320 snprintf(
1321 &buf[l], sizeof( buf ) - l,
1322 p_( "standings", "\n#%c%+.0f%%#0 #nin %s#0" ),
1323 faction_reputationColourCharSystem( info_factions[p], cur_system ), ml,
1324 system_name( cur_system ) );
1325 window_modifyText( wid, "txtName", faction_longname( info_factions[p] ) );
1326 window_moveWidget( wid, "txtName", x, y );
1327 y -= 20;
1328 window_modifyText( wid, "txtStanding", buf );
1329 window_moveWidget( wid, "txtStanding", x, y );
1330 y -= 50;
1331 l = scnprintf( buf, sizeof( buf ), "%s\n\n",
1332 faction_description( info_factions[p] ) );
1333 l += scnprintf(
1334 &buf[l], sizeof( buf ) - l,
1335 _( "You can have a maximum reputation of %.0f%% with this faction." ),
1336 round( faction_reputationMax( info_factions[p] ) ) );
1337
1338 flist = faction_getAllies( info_factions[p] );
1339 if ( array_size( flist ) > 0 ) {
1340 int added = 0;
1341 for ( int i = 0; i < array_size( flist ); i++ ) {
1342 int f = flist[i];
1343 if ( faction_isStatic( f ) || !faction_isKnown( f ) ||
1345 continue;
1346
1347 if ( added == 0 ) {
1348 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n\n%s",
1349 _( "Ally Factions:" ) );
1350 added = 1;
1351 }
1352 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n- %s",
1353 faction_longname( f ) );
1354 }
1355 }
1356 flist = faction_getEnemies( info_factions[p] );
1357 if ( array_size( flist ) > 0 ) {
1358 int added = 0;
1359 for ( int i = 0; i < array_size( flist ); i++ ) {
1360 int f = flist[i];
1361 if ( faction_isStatic( f ) || !faction_isKnown( f ) ||
1363 continue;
1364
1365 if ( added == 0 ) {
1366 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n\n%s",
1367 _( "Enemy Factions:" ) );
1368 added = 1;
1369 }
1370 l += scnprintf( &buf[l], sizeof( buf ) - l, "\n- %s",
1371 faction_longname( f ) );
1372 }
1373 }
1374
1375 window_modifyText( wid, "txtDescription", buf );
1376 window_moveWidget( wid, "txtDescription", lw + 40, y );
1377}
1378
1385static void info_openMissions( unsigned int wid )
1386{
1387 int w, h;
1388
1389 /* Get the dimensions. */
1390 window_dimWindow( wid, &w, &h );
1391
1392 /* buttons */
1393 window_addButtonKey( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
1394 "closeMissions", _( "Close" ), info_close, SDLK_c );
1395 window_addButtonKey( wid, -20 - BUTTON_WIDTH - 10, 20, BUTTON_WIDTH,
1396 BUTTON_HEIGHT, "btnAbortMission", _( "Abort" ),
1397 mission_menu_abort, SDLK_a );
1398
1399 /* Add a checkbox to hide the mission. */
1400 window_addCheckbox( wid, 300 + 40, 20 + BUTTON_HEIGHT + 10, w - 300 - 60,
1401 BUTTON_HEIGHT, "chkHide",
1402 _( "Hide mission on-screen display" ),
1403 mission_menu_chk_hide, 0 );
1404 /* Checkbox to make the mission be top. */
1405 window_addCheckbox(
1406 wid, 300 + 40, 20 + BUTTON_HEIGHT + 10 + gl_defFont.h + 10, w - 300 - 60,
1407 BUTTON_HEIGHT, "chkPrefer", _( "Prioritize the mission" ),
1408 mission_menu_chk_priority, 0 );
1409
1410 /* Mission Description */
1411 window_addText( wid, 300 + 40, -40, w - 300 - 60, h - BUTTON_HEIGHT - 120, 0,
1412 "txtDesc", NULL, NULL, NULL );
1413
1414 /* Put a map. */
1415 map_show( wid, 20, 20, 300, 260, 0.75, 0., 0. );
1416
1417 /* list */
1418 mission_menu_genList( wid, 1 );
1419}
1424static void mission_menu_genList( unsigned int wid, int first )
1425{
1426 int j;
1427 char **misn_names;
1428 int w, h;
1429
1430 if ( !first )
1431 window_destroyWidget( wid, "lstMission" );
1432
1433 /* Get the dimensions. */
1434 window_dimWindow( wid, &w, &h );
1435
1436 /* list */
1437 misn_names =
1438 malloc( sizeof( char * ) * MAX( 1, array_size( player_missions ) ) );
1439 selectedMission = -1;
1440 j = 0;
1441 for ( int i = 0; i < array_size( player_missions ); i++ )
1442 if ( player_missions[i]->id != 0 )
1443 misn_names[j++] = ( player_missions[i]->title != NULL )
1444 ? strdup( player_missions[i]->title )
1445 : NULL;
1446
1447 if ( j == 0 ) { /* no missions */
1448 misn_names[j++] = strdup( _( "No Missions" ) );
1449 window_modifyText( wid, "txtDesc",
1450 _( "You currently have no active missions." ) );
1451 window_disableButton( wid, "btnAbortMission" );
1452 window_disableCheckbox( wid, "chkHide" );
1453 window_disableCheckbox( wid, "chkPrefer" );
1454 selectedMission = 0; /* misn_menu_update should do nothing. */
1455 }
1456 window_addList( wid, 20, -40, 300, h - 340, "lstMission", misn_names, j,
1457 selectedMission, mission_menu_update, NULL );
1458 window_setFocus( wid, "lstMission" );
1459}
1464static void mission_menu_update( unsigned int wid, const char *str )
1465{
1466 (void)str;
1467 char buf[STRMAX];
1468 Mission *misn;
1469 const StarSystem *sys;
1470 int pos = toolkit_getListPos( wid, "lstMission" );
1471
1472 if ( pos < 0 || pos == selectedMission )
1473 return;
1474
1475 /* Modify the text. */
1476 selectedMission = pos;
1477 misn = player_missions[selectedMission];
1478 snprintf( buf, sizeof( buf ), _( "%s\n#nReward:#0 %s\n\n%s" ), misn->title,
1479 misn->reward, misn->desc );
1480 window_modifyText( wid, "txtDesc", buf );
1481 if ( pilot_isFlag( player.p, PILOT_LANDING ) )
1482 window_disableButton( wid, "btnAbortMission" );
1483 else
1484 window_enableButton( wid, "btnAbortMission" );
1485 window_enableCheckbox( wid, "chkHide" );
1486 window_enableCheckbox( wid, "chkPrefer" );
1487 window_checkboxSet( wid, "chkHide", misn_osdGetHide( misn ) );
1488 window_checkboxSet( wid, "chkPrefer",
1489 misn_osdGetPriority( misn ) !=
1490 misn->data->avail.priority );
1491
1492 /* Select the system. */
1493 sys = mission_getSystemMarker( misn );
1494 if ( sys != NULL )
1495 map_center( wid, sys->name );
1496}
1497static void mission_menu_chk_hide( unsigned int wid, const char *str )
1498{
1499 Mission *misn;
1500 int pos = toolkit_getListPos( wid, "lstMission" );
1501 if ( ( pos < 0 ) || ( pos > array_size( player_missions ) ) )
1502 return;
1503 misn = player_missions[pos];
1504
1505 if ( misn->osd == 0 )
1506 return;
1507 misn_osdSetHide( misn, window_checkboxState( wid, str ) );
1508}
1509static void mission_menu_chk_priority( unsigned int wid, const char *str )
1510{
1511 Mission *misn;
1512 int pos = toolkit_getListPos( wid, "lstMission" );
1513 if ( ( pos < 0 ) || ( pos > array_size( player_missions ) ) )
1514 return;
1515 misn = player_missions[pos];
1516
1517 if ( misn->osd == 0 )
1518 return;
1519 misn_osdSetPriority( misn, misn->data->avail.priority -
1520 100 * window_checkboxState( wid, str ) );
1521}
1526static void mission_menu_abort( unsigned int wid, const char *str )
1527{
1528 (void)str;
1529 int pos, ret;
1530 Mission *misn;
1531
1532 if ( !dialogue_YesNo( _( "Abort Mission" ),
1533 _( "Are you sure you want to abort this mission?" ) ) )
1534 return;
1535
1536 /* Get the mission. */
1537 pos = toolkit_getListPos( wid, "lstMission" );
1538 misn = player_missions[pos];
1539
1540 /* We run the "abort" function if it's found. */
1541 ret = misn_tryRun( misn, "abort" );
1542
1543 /* Now clean up mission. */
1544 if ( ret != 2 ) {
1545 mission_cleanup( misn );
1546 mission_shift( pos );
1547 }
1548
1549 /* Reset markers. */
1551
1552 /* Reset claims. */
1554
1555 /* Regenerate list. */
1556 mission_menu_genList( wid, 0 );
1557
1558 /* Regenerate bar if landed. */
1559 bar_regen();
1560}
1561
1562/* amount of screen available for logs: -20 below button, -20 above button, -40
1563 * from top, -20 x2 between logs.*/
1564#define LOGSPACING ( h - 120 - BUTTON_HEIGHT )
1565
1570static void shiplog_menu_update( unsigned int wid, const char *str )
1571{
1572 int w, h;
1573 int nentries;
1574 char **logentries;
1575
1576 if ( !logWidgetsReady )
1577 return;
1578
1579 /* This is called when something is selected.
1580 * If a new log type has been selected, need to regenerate the log lists.
1581 * If a new log has been selected, need to regenerate the entries. */
1582 if ( strcmp( str, "lstLogEntries" ) != 0 ) {
1583 int regenerateEntries = 0;
1584 int logType, log;
1585
1586 /* has selected a type of log or a log */
1587 window_dimWindow( wid, &w, &h );
1588 logWidgetsReady = 0;
1589
1590 logType = toolkit_getListPos( wid, "lstLogType" );
1591 log = toolkit_getListPos( wid, "lstLogs" );
1592
1593 if ( logType != selectedLogType ) {
1594 /* new log type selected */
1595 selectedLogType = logType;
1596 window_destroyWidget( wid, "lstLogs" );
1597 logs = NULL;
1598 shiplog_listLogsOfType( info_getLogTypeFilter( selectedLogType ),
1599 &nlogs, &logs, &logIDs, 1 );
1600 if ( selectedLog >= nlogs )
1601 selectedLog = 0;
1602 window_addList( wid, 20, 60 + BUTTON_HEIGHT + LOGSPACING / 2, w - 40,
1603 LOGSPACING / 4, "lstLogs", logs, nlogs, 0,
1604 shiplog_menu_update, NULL );
1605
1606 toolkit_setListPos( wid, "lstLogs", selectedLog );
1607 regenerateEntries = 1;
1608 }
1609 if ( regenerateEntries || selectedLog != log ) {
1610 selectedLog = CLAMP( 0, nlogs - 1, log );
1611 /* list log entries of selected log type */
1612 window_destroyWidget( wid, "lstLogEntries" );
1613 shiplog_listLog( logIDs[selectedLog],
1614 info_getLogTypeFilter( selectedLogType ), &nentries,
1615 &logentries, 1 );
1616 window_addList( wid, 20, 40 + BUTTON_HEIGHT, w - 40,
1617 LOGSPACING / 2 - 20, "lstLogEntries", logentries,
1618 nentries, 0, shiplog_menu_update, info_shiplogView );
1619 toolkit_setListPos( wid, "lstLogEntries", 0 );
1620 window_setFocus( wid, "lstLogEntries" );
1621 }
1622 logWidgetsReady = 1;
1623 }
1624}
1625
1629static const char *info_getLogTypeFilter( int lstPos )
1630{
1631 if ( lstPos < 1 )
1632 return NULL; /* "All" */
1633 return logTypes[lstPos];
1634}
1635
1640static void shiplog_menu_genList( unsigned int wid, int first )
1641{
1642 int w, h;
1643 int nentries;
1644 char **logentries;
1645
1646 /* Needs 3 lists:
1647 * 1. List of log types (and All)
1648 * 2. List of logs of the selected type (and All)
1649 * 3. Listing of the selected log
1650 */
1651 if ( !first ) {
1652 window_destroyWidget( wid, "lstLogType" );
1653 window_destroyWidget( wid, "lstLogs" );
1654 logs = NULL;
1655 window_destroyWidget( wid, "lstLogEntries" );
1656 }
1657 /* Get the dimensions. */
1658 window_dimWindow( wid, &w, &h );
1659
1660 /* list log types */
1661 shiplog_listTypes( &ntypes, &logTypes, 1 );
1662 if ( selectedLogType >= ntypes )
1663 selectedLogType = 0;
1664 /* list logs of selected type */
1665 shiplog_listLogsOfType( info_getLogTypeFilter( selectedLogType ), &nlogs,
1666 &logs, &logIDs, 1 );
1667 if ( selectedLog >= nlogs )
1668 selectedLog = 0;
1669 /* list log entries of selected log */
1670 shiplog_listLog( logIDs[selectedLog],
1671 info_getLogTypeFilter( selectedLogType ), &nentries,
1672 &logentries, 1 );
1673 logWidgetsReady = 0;
1674 window_addList( wid, 20, 80 + BUTTON_HEIGHT + 3 * LOGSPACING / 4, w - 40,
1675 LOGSPACING / 4, "lstLogType", logTypes, ntypes, 0,
1676 shiplog_menu_update, NULL );
1677 window_addList( wid, 20, 60 + BUTTON_HEIGHT + LOGSPACING / 2, w - 40,
1678 LOGSPACING / 4, "lstLogs", logs, nlogs, 0,
1679 shiplog_menu_update, NULL );
1680 window_addList( wid, 20, 40 + BUTTON_HEIGHT, w - 40, LOGSPACING / 2 - 20,
1681 "lstLogEntries", logentries, nentries, 0,
1682 shiplog_menu_update, info_shiplogView );
1683 window_setFocus( wid, "lstLogEntries" );
1684 logWidgetsReady = 1;
1685}
1686
1687static void info_shiplogMenuDelete( unsigned int wid, const char *str )
1688{
1689 (void)str;
1690 char buf[STRMAX_SHORT];
1691 int ret, logid;
1692
1693 if ( logIDs[selectedLog] == LOG_ID_ALL ) {
1694 dialogue_msg( "", _( "You are currently viewing all logs in the selected "
1695 "log type. Please select a log title to delete." ) );
1696 return;
1697 }
1698
1699 snprintf( buf, sizeof( buf ),
1700 _( "This will delete ALL \"%s\" log entries. This operation "
1701 "cannot be undone. Are you sure?" ),
1702 logs[selectedLog] );
1703 ret = dialogue_YesNoRaw( "", buf );
1704 if ( !ret )
1705 return;
1706 /* There could be several logs of the same name, so make sure we get the
1707 * correct one. */
1708 /* selectedLog-1 since not including the "All" */
1709 logid = shiplog_getIdOfLogOfType( info_getLogTypeFilter( selectedLogType ),
1710 selectedLog - 1 );
1711 if ( logid >= 0 )
1712 shiplog_delete( logid );
1713 selectedLog = 0;
1714 selectedLogType = 0;
1715 shiplog_menu_genList( wid, 0 );
1716}
1717
1718static void info_shiplogView( unsigned int wid, const char *str )
1719{
1720 char **logentries;
1721 int nentries;
1722 int pos;
1723 (void)str;
1724
1725 pos = toolkit_getListPos( wid, "lstLogEntries" );
1726 if ( pos < 0 )
1727 return;
1728 shiplog_listLog( logIDs[selectedLog],
1729 info_getLogTypeFilter( selectedLogType ), &nentries,
1730 &logentries, 1 );
1731
1732 if ( pos < nentries )
1733 dialogue_msgRaw( _( "Log message" ), logentries[pos] );
1734
1735 for ( int i = 0; i < nentries; i++ )
1736 free( logentries[i] );
1737 free( logentries );
1738}
1739
1746static void info_shiplogAdd( unsigned int wid, const char *str )
1747{
1748 char *tmp;
1749 int logType, log;
1750 (void)str;
1751
1752 logType = toolkit_getListPos( wid, "lstLogType" );
1753 log = toolkit_getListPos( wid, "lstLogs" );
1754 if ( log < 0 || logIDs[log] == LOG_ID_ALL ) {
1755 tmp = dialogue_inputRaw( _( "Add a log entry" ), 0, 4096,
1756 _( "Add an entry to your diary:" ) );
1757 if ( ( tmp != NULL ) && ( strlen( tmp ) > 0 ) ) {
1758 if ( shiplog_getID( "Diary" ) == -1 )
1759 shiplog_create( "Diary", _( "Your Diary" ), "Diary", 0, 0 );
1760 shiplog_append( "Diary", tmp );
1761 free( tmp );
1762 }
1763 } else {
1764 tmp = dialogue_input( _( "Add a log entry" ), 0, 4096,
1765 _( "Add an entry to the log titled '%s':" ),
1766 logs[log] );
1767 if ( ( tmp != NULL ) && ( strlen( tmp ) > 0 ) ) {
1768 int logid = shiplog_getIdOfLogOfType( info_getLogTypeFilter( logType ),
1769 log - 1 );
1770 if ( logid >= 0 )
1771 shiplog_appendByID( logid, tmp );
1772 else
1774 _( "Cannot add log" ),
1775 _( "Cannot find this log! Something went wrong here!" ) );
1776 free( tmp );
1777 }
1778 }
1779 shiplog_menu_genList( wid, 0 );
1780}
1781
1787static void info_openShipLog( unsigned int wid )
1788{
1789 int w, h, texth;
1790 /* re-initialise the statics */
1791 selectedLog = 0;
1792 selectedLogType = 0;
1793
1794 /* Get the dimensions. */
1795 window_dimWindow( wid, &w, &h );
1796 /* buttons */
1797 window_addButtonKey( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
1798 "closeShipLog", _( "Close" ), info_close, SDLK_c );
1799 window_addButtonKey( wid, -20 - 1 * ( 20 + BUTTON_WIDTH ), 20, BUTTON_WIDTH,
1800 BUTTON_HEIGHT, "btnDeleteLog", _( "Delete" ),
1801 info_shiplogMenuDelete, SDLK_d );
1802 window_addButtonKey( wid, -20 - 2 * ( 20 + BUTTON_WIDTH ), 20, BUTTON_WIDTH,
1803 BUTTON_HEIGHT, "btnViewLog", _( "View Entry" ),
1804 info_shiplogView, SDLK_v );
1805 window_addButtonKey( wid, -20 - 3 * ( 20 + BUTTON_WIDTH ), 20, BUTTON_WIDTH,
1806 BUTTON_HEIGHT, "btnAddLog", _( "Add Entry" ),
1807 info_shiplogAdd, SDLK_a );
1808 /* Description text */
1809 texth = gl_printHeightRaw( &gl_smallFont, w, "Select log type" );
1810 window_addText( wid, 20, 80 + BUTTON_HEIGHT + LOGSPACING, w - 40, texth, 0,
1811 "logDesc1", &gl_smallFont, NULL, _( "Select log type:" ) );
1812
1813 window_addText( wid, 20, 60 + BUTTON_HEIGHT + 3 * LOGSPACING / 4, w - 40,
1814 texth, 0, "logDesc2", &gl_smallFont, NULL,
1815 _( "Select log title:" ) );
1816
1817 window_addText( wid, 20, 25 + BUTTON_HEIGHT + LOGSPACING / 2, w - 40, texth,
1818 0, "logDesc3", &gl_smallFont, NULL, _( "Log entries:" ) );
1819
1820#undef LOGSPACING
1821 /* list */
1822 shiplog_menu_genList( wid, 1 );
1823}
1824
1828static void info_changeTab( unsigned int wid, const char *str, int old,
1829 int new )
1830{
1831 (void)wid;
1832 (void)str;
1833 (void)old;
1834 const char *hookname;
1835 switch ( new ) {
1836 case INFO_WIN_MAIN:
1837 hookname = "info_main";
1838 break;
1839 case INFO_WIN_SHIP:
1840 hookname = "info_ship";
1841 break;
1842 case INFO_WIN_WEAP:
1843 hookname = "info_weapons";
1844 break;
1845 case INFO_WIN_CARGO:
1846 hookname = "info_cargo";
1847 break;
1848 case INFO_WIN_MISN:
1849 hookname = "info_mission";
1850 break;
1851 case INFO_WIN_STAND:
1852 hookname = "info_standing";
1853 break;
1854 case INFO_WIN_SHIPLOG:
1855 hookname = "info_shiplog";
1856 break;
1857 default:
1858 WARN( _( "Invalid info tab ID: %d" ), new );
1859 return;
1860 }
1861 hooks_run( hookname );
1862}
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_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_grow(ptr_array)
Increases the number of elements by one and returns the last element.
Definition array.h:122
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
#define BUTTON_HEIGHT
Definition board.c:28
#define BUTTON_WIDTH
Definition board.c:27
void claim_activateAll(void)
Activates all the claims.
Definition claim.c:240
void credits2str(char *str, credits_t credits, int decimals)
Converts credits to a usable string for displaying.
Definition commodity.c:75
char * dialogue_inputRaw(const char *title, int min, int max, const char *msg)
Creates a dialogue that allows the player to write a message.
Definition dialogue.c:470
char * dialogue_input(const char *title, int min, int max, const char *fmt,...)
Creates a dialogue that allows the player to write a message.
Definition dialogue.c:441
int dialogue_YesNoRaw(const char *caption, const char *msg)
Runs a dialogue with both yes and no options.
Definition dialogue.c:373
void dialogue_msg(const char *caption, const char *fmt,...)
Opens a dialogue window with an ok button and a message.
Definition dialogue.c:227
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_isOpen(void)
Checks to see if a dialogue is open.
Definition dialogue.c:96
int dialogue_YesNo(const char *caption, const char *fmt,...)
Runs a dialogue with both yes and no options.
Definition dialogue.c:352
void equipment_slotWidget(unsigned int wid, double x, double y, double w, double h, CstSlotWidget *data)
Creates the slot widget and initializes it.
Definition equipment.c:462
int equipment_shipStats(char *buf, int max_len, const Pilot *s, int dpseps, int name)
Creates and allocates a string containing the ship stats.
Definition equipment.c:1604
const char * faction_longname(int f)
Gets the faction's long name (formal, human-readable).
Definition faction.c:373
const int * faction_getEnemies(int f)
Gets the list of enemies of a faction.
Definition faction.c:509
int faction_isKnown(int id)
Is the faction known?
Definition faction.c:300
void faction_updateGlobal(void)
Computes the global faction standing for each of the factions.
Definition faction.c:1907
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
const char * faction_getStandingText(int f)
Gets the player's standing in human readable form.
Definition faction.c:1257
int faction_isDynamic(int id)
Is faction dynamic.
Definition faction.c:308
const int * faction_getAllies(int f)
Gets the list of allies of a faction.
Definition faction.c:539
int * faction_getKnown()
Gets all the known factions in an array (array.h).
Definition faction.c:243
int faction_isInvisible(int id)
Is the faction invisible?
Definition faction.c:275
char faction_reputationColourChar(int f)
Gets the faction character associated to its standing with the player.
Definition faction.c:1228
double faction_reputationMax(int f)
Gets the maximum reputation of a faction.
Definition faction.c:1374
double faction_reputation(int f)
Gets the player's standing with a faction.
Definition faction.c:1129
const char * faction_description(int f)
Gets the faction's description (translated).
Definition faction.c:407
int faction_isStatic(int id)
Is the faction static?
Definition faction.c:267
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_smallFont
Definition font.c:159
glFont gl_defFont
Definition font.c:158
void gl_print(const glFont *ft_font, const double x, const double y, const glColour *c, const char *fmt,...)
Prints text on screen like printf.
Definition font.c:725
int hooks_runParam(const char *stack, const HookParam *param)
Runs all the hooks of stack.
Definition hook.c:1029
int hooks_run(const char *stack)
Runs all the hooks of stack.
Definition hook.c:1049
Handles the info menu.
#define INFO_DEFAULT
Definition info.h:16
void info_update(void)
Updates the info windows.
Definition info.c:367
void info_buttonClear(void)
Clears all the registered buttons.
Definition info.c:244
void bar_regen(void)
Regenerates the bar list.
Definition land.c:432
int landed
Definition land.c:78
Handles the important game menus.
#define menu_isOpen(f)
Definition menu.h:16
#define MENU_INFO
Definition menu.h:11
Mission ** player_missions
Definition mission.c:45
const StarSystem * mission_getSystemMarker(const Mission *misn)
Gets the first system that has been marked by a mission.
Definition mission.c:695
void mission_cleanup(Mission *misn)
Cleans up a mission.
Definition mission.c:779
void mission_sysMark(void)
Marks all active systems that need marking.
Definition mission.c:616
void mission_shift(int pos)
Puts the specified mission at the end of the player_missions array.
Definition mission.c:835
void misn_osdSetHide(Mission *misn, int hide)
Sets the hide state of the mission OSD.
Definition mission.c:521
Header file with generic functions and naev-specifics.
#define CLAMP(a, b, x)
Definition naev.h:41
#define ABS(x)
Definition naev.h:32
#define MAX(x, y)
Definition naev.h:37
nlua_env __NLUA_CURENV
Definition nlua.c:55
lua_State * naevL
Definition nlua.c:54
int num2str(char dest[NUM2STRLEN], double n, int decimals)
Converts a numeric value to a string.
Definition nstring.c:123
int strsort(const void *p1, const void *p2)
Sort function for sorting strings with qsort().
Definition nstring.c:83
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
const char * num2strU(double n, int decimals)
Unsafe version of num2str that uses an internal buffer. Every call overwrites the return value.
Definition nstring.c:163
ntime_t ntime_get(void)
Gets the current time.
Definition ntime.c:113
char * ntime_pretty(ntime_t t, int d)
Gets the time in a pretty human readable format.
Definition ntime.c:178
ntime_t pilot_hyperspaceDelay(const Pilot *p)
Calculates the hyperspace delay for a pilot.
Definition pilot.c:3243
int pilot_getJumps(const Pilot *p)
Gets the amount of jumps the pilot has left.
Definition pilot.c:1317
int pilot_cargoFree(const Pilot *p)
Gets the pilot's free cargo space.
Definition pilot_cargo.c:53
int pilot_cargoUsed(const Pilot *p)
Gets how much cargo ship has on board.
int pilot_weapSetTypeCheck(Pilot *p, int id)
Checks the current weapon set type.
void pilot_weapSetInrange(Pilot *p, int id, int inrange)
Changes the weapon set inrange property.
void pilot_weaponSafe(Pilot *p)
Sets the weapon set as safe.
void pilot_weapSetManual(Pilot *p, int id, int manual)
Changes the weapon set manual property.
void pilot_weapSetVolley(Pilot *p, int id, int volley)
Changes the weapon set volley property.
int pilot_weapSetManualCheck(Pilot *p, int id)
Checks the current weapon set manual property.
void ws_copy(PilotWeaponSet dest[PILOT_WEAPON_SETS], const PilotWeaponSet src[PILOT_WEAPON_SETS])
Copies a weapon set over.
int pilot_weapSetVolleyCheck(Pilot *p, int id)
Checks the current weapon set volley property.
void pilot_weapSetClear(Pilot *p, int id)
Clears a weapon set.
void pilot_weaponAuto(Pilot *p)
Tries to automatically set and create the pilot's weapon set.
int pilot_weapSetInrangeCheck(Pilot *p, int id)
Checks the current weapon set inrange property.
const char * pilot_weapSetName(Pilot *p, int id)
Gets the name of a weapon set.
void pilot_weapSetType(Pilot *p, int id, WeaponSetType type)
Changes the weapon sets mode.
const char ** player_getLicenses()
Gets the array (array.h) of license names in the player's inventory.
Definition player.c:3240
Player_t player
Definition player.c:77
PilotCommodity * pfleet_cargoList(void)
Gets a list of all the cargo in the fleet.
PFleetCargo * pfleet_cargoListShips(const Commodity *com)
Gets the list of ships that are carry a certain commodity in the player fleet and the amount they are...
int pfleet_cargoFree(void)
Gets the total amount of free cargo space in the player's fleet.
int pfleet_cargoRm(const Commodity *com, int q, int jet)
Removes some cargo from the player's fleet.
int pfleet_cargoUsed(void)
Gets the total cargo space used by the player's fleet.
static PlayerItem * inventory
const PlayerItem * player_inventory(void)
Gets the whole player inventory.
static const double c[]
Definition rng.c:256
const char * ship_class(const Ship *s)
Gets the ship's class name in human readable form.
Definition ship.c:192
int shiplog_appendByID(int logid, const char *msg)
Adds to the log file.
Definition shiplog.c:211
void shiplog_listLog(int logid, const char *type, int *nentries, char ***logentries, int incempty)
Get all log entries matching logid, or if logid==LOG_ID_ALL, matching type, or if type==NULL,...
Definition shiplog.c:635
void shiplog_listLogsOfType(const char *type, int *nlogs, char ***logsOut, int **logIDs, int includeAll)
Lists matching logs (which haven't expired via "removeAfter") into the provided arrays.
Definition shiplog.c:547
void shiplog_delete(int logid)
Deletes a log (e.g. a cancelled mission may wish to do this, or the user might).
Definition shiplog.c:277
int shiplog_append(const char *idstr, const char *msg)
Appends to the log file.
Definition shiplog.c:183
int shiplog_create(const char *idstr, const char *logname, const char *type, int overwrite, int maxLen)
Creates a new log with given title of given type.
Definition shiplog.c:56
int shiplog_getID(const char *idstr)
Checks to see if the log family exists.
Definition shiplog.c:696
double system_getReputationOrGlobal(const StarSystem *sys, int faction)
Gets the local reputation of the player in a system or returns the global standing.
Definition space.c:4518
StarSystem * cur_system
Definition space.c:110
Represents a commodity.
Definition commodity.h:57
char * description
Definition commodity.h:59
int * illegalto
Definition commodity.h:75
char * name
Definition commodity.h:58
The actual hook parameter.
Definition hook.h:40
HookParamType type
Definition hook.h:41
Commodity * commodity
Definition hook.h:49
union HookParam::@325330313164266255110350307176363262300250041145 u
double num
Definition hook.h:43
For use with registered info buttons.
Definition info.c:61
int func
Definition info.c:68
SDL_Keycode key
Definition info.c:69
char * button
Definition info.c:64
int priority
Definition info.c:65
char * caption
Definition info.c:63
nlua_env env
Definition info.c:67
int id
Definition info.c:62
MissionAvail_t avail
Definition mission.h:67
Represents an active mission.
Definition mission.h:83
unsigned int osd
Definition mission.h:112
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
Stores a pilot commodity.
Definition pilot.h:223
const Commodity * commodity
Definition pilot.h:224
unsigned int id
Definition pilot.h:226
Represents an item in the player inventory.
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_setFocus(unsigned int wid, const char *wgtname)
Sets the focused widget in a window.
Definition toolkit.c:2488
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
int window_existsID(unsigned int wid)
Checks to see if a window with a certain ID exists.
Definition toolkit.c:608
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 toolkit_drawRect(int x, int y, int w, int h, const glColour *c, const glColour *lc)
Draws a rectangle.
Definition toolkit.c:1370
void window_moveWidget(unsigned int wid, const char *name, int x, int y)
Moves a widget.
Definition toolkit.c:463
void window_destroyWidget(unsigned int wid, const char *wgtname)
Destroys a widget in a window.
Definition toolkit.c:1167
int window_isTop(unsigned int wid)
Checks to see if a window is at the top.
Definition toolkit.c:544
void window_resizeWidget(unsigned int wid, const char *name, int w, int h)
Resizes a widget.
Definition toolkit.c:490
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