naev 0.12.5
map_system.c
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
5#include <math.h>
6#include <stdio.h>
7#include <stdlib.h>
8
9#include "naev.h"
11
12#include "map.h"
13
14#include "array.h"
15#include "background.h"
16#include "colour.h"
17#include "dialogue.h"
18#include "economy.h"
19#include "faction.h"
20#include "land.h"
21#include "land_outfits.h"
22#include "log.h"
23#include "map_system.h"
24#include "nstring.h"
25#include "opengl.h"
26#include "player.h"
27#include "space.h"
28#include "toolkit.h"
29
30#define BUTTON_WIDTH 80
31#define BUTTON_HEIGHT 30
32
33static StarSystem *cur_sys_sel = NULL;
34static int cur_spob_sel = 0;
35static Spob *cur_spobObj_sel = NULL;
36static Outfit **cur_spob_sel_outfits = NULL;
37static Ship **cur_spob_sel_ships = NULL;
38static int pitch = 0;
39static int nameWidth = 0;
40static int nshow = 0;
41static char infobuf[STRMAX];
42static unsigned int focusedStar = 0;
43glTexture **starImages;
45 *bgImage;
46
47#define MAP_SYSTEM_WDWNAME "wdwSystemMap"
48#define MAPSYS_OUTFITS "mapSysOutfits"
49#define MAPSYS_SHIPS "mapSysShips"
50#define MAPSYS_TRADE "mapSysTrade"
51
52/*
53 * extern
54 */
55/*land.c*/
56// extern int landed;
57// extern Spob* land_spob;
58
59/*
60 * prototypes
61 */
62void map_system_cleanup( unsigned int wid, const char *str );
63int map_system_isOpen( void );
64
65/* Update. */
66void map_system_updateSelected( unsigned int wid );
67
68/* Render. */
69static void map_system_render( double bx, double by, double w, double h,
70 void *data );
71/* Mouse. */
72static int map_system_mouse( unsigned int wid, const SDL_Event *event,
73 double mx, double my, double w, double h,
74 double rx, double ry, void *data );
75/* Misc. */
76static int map_system_keyHandler( unsigned int wid, SDL_Keycode key,
77 SDL_Keymod mod, int isrepeat );
78void map_system_show( int wid, int x, int y, int w, int h );
79
80static void map_system_genOutfitsList( unsigned int wid, float goodsSpace,
81 float outfitSpace, float shipSpace );
82static void map_system_genShipsList( unsigned int wid, float goodsSpace,
83 float outfitSpace, float shipSpace );
84static void map_system_genTradeList( unsigned int wid, float goodsSpace,
85 float outfitSpace, float shipSpace );
86
87static void map_system_array_update( unsigned int wid, const char *str );
88
89void map_system_buyCommodPrice( unsigned int wid, const char *str );
90
96int map_system_init( void )
97{
98 return 0;
99}
100
106int map_system_load( void )
107{
108 return 0;
109}
110
114void map_system_exit( void )
115{
116 for ( int i = 0; i < array_size( starImages ); i++ )
117 gl_freeTexture( starImages[i] );
118 array_free( starImages );
119 starImages = NULL;
120 gl_freeTexture( bgImage );
121 bgImage = NULL;
122 array_free( cur_spob_sel_outfits );
123 cur_spob_sel_outfits = NULL;
124 array_free( cur_spob_sel_ships );
125 cur_spob_sel_ships = NULL;
126}
127
131void map_system_cleanup( unsigned int wid, const char *str )
132{
133 (void)wid;
134 (void)str;
135
136 if ( cur_sys_sel != cur_system )
137 space_gfxUnload( cur_sys_sel );
138
139 map_system_exit();
140}
141
145static int map_system_keyHandler( unsigned int wid, SDL_Keycode key,
146 SDL_Keymod mod, int isrepeat )
147{
148 (void)mod;
149 (void)isrepeat;
150 if ( key == SDLK_m ) {
151 window_close( wid, NULL );
152 return 1;
153 }
154 if ( key == SDLK_UP ) {
155 cur_spob_sel = MAX( cur_spob_sel - 1, 0 );
156 map_system_updateSelected( wid );
157 return 1;
158 }
159 if ( key == SDLK_DOWN ) {
160 cur_spob_sel = MIN( cur_spob_sel + 1, nshow );
161 map_system_updateSelected( wid );
162 return 1;
163 }
164 return 0;
165}
166
170void map_system_open( int sys_selected )
171{
172 unsigned int wid;
173 int w, h;
174 StarSystem *tmp_sys;
175 /* Destroy window if exists. */
176 wid = window_get( MAP_SYSTEM_WDWNAME );
177 if ( wid > 0 ) {
178 window_destroy( wid );
179 return;
180 }
181 cur_spobObj_sel = NULL;
182 memset( infobuf, 0, sizeof( infobuf ) );
183 pitch = 0;
184 nameWidth = 0;
185 nshow = 0;
186 focusedStar = 0;
187
188 /* get the selected system. */
189 cur_sys_sel = system_getIndex( sys_selected );
190 cur_spob_sel = 0;
191 /* Set up window size. */
192 w = MAX( 600, SCREEN_W - 140 );
193 h = MAX( 540, SCREEN_H - 140 );
194
195 /* create the window. */
196 wid = window_create( MAP_SYSTEM_WDWNAME, _( "System Info" ), -1, -1, w, h );
198 window_onClose( wid, map_system_cleanup );
199 window_handleKeys( wid, map_system_keyHandler );
200 window_addText( wid, 40, h - 30, 160, 20, 1, "txtSysname", &gl_defFont,
201 &cFontGreen, system_name( cur_sys_sel ) );
202 window_addImage( wid, -90 + 32, h - 30, 0, 0, "imgFaction", NULL, 0 );
203 /* Close button */
204 window_addButton( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnClose",
205 _( "Close" ), window_close );
206 /* commodity price purchase button */
207 window_addButton( wid, -40 - BUTTON_WIDTH, 20, BUTTON_WIDTH * 3,
208 BUTTON_HEIGHT, "btnBuyCommodPrice",
209 _( "Buy commodity price info" ),
210 map_system_buyCommodPrice );
211 window_disableButton( wid, "btnBuyCommodPrice" );
212
213 /* Load the spob gfx if necessary */
214 if ( cur_sys_sel != cur_system )
215 space_gfxLoad( cur_sys_sel );
216 /* get textures for the stars. The first will be the nebula */
217 /* There seems no other reliable way of getting the correct images -*/
218 /* these are determined by a random number generator in lua */
219 /* This is a bit nasty - luckily Naev is single threaded! */
220 tmp_sys = cur_system;
221 cur_system = cur_sys_sel;
222 /* load background images */
224 background_load( cur_system->background );
225 starImages = background_getStarTextures();
227 focusedStar = 0;
229 /* and reload the images for the current system */
230 cur_system = tmp_sys;
231 background_load( cur_system->background );
232
233 map_system_show( wid, 20, 60, w - 40, h - 100 );
234 map_system_updateSelected( wid );
235}
236
242int map_system_isOpen( void )
243{
244 return window_exists( MAP_SYSTEM_WDWNAME );
245}
246
257void map_system_show( int wid, int x, int y, int w, int h )
258{
259 window_addRect( wid, x, y, w, h, "rctMapSys", &cBlack, 0 );
260 window_addCust( wid, x, y, w, h, "cstMapSys", 1, map_system_render,
261 map_system_mouse, NULL, NULL, NULL );
262 window_custSetDynamic( wid, "cstMapSys", 1 );
263}
264
275static void map_system_render( double bx, double by, double w, double h,
276 void *data )
277{
278 (void)data;
279 int i, vis_index;
280 double iw, ih;
281 StarSystem *sys = cur_sys_sel;
282 Spob *p;
283 static int phase = 0;
284 glColour ccol;
285 char buf[STRMAX];
286 int cnt;
287 double ast_nb, ast_area;
288 double f;
289 int hasPresence = 0;
290 double unknownPresence = 0;
291 char t;
292 const glTexture *logo;
293 int offset;
294 int txtHeight;
295
296 vis_index = 0;
297 offset = h - pitch * nshow;
298 for ( i = 0; i < array_size( sys->spobs ); i++ ) {
299 p = sys->spobs[i];
300 if ( !spob_isKnown( p ) )
301 continue;
302 vis_index++;
303 if ( p->gfx_space == NULL )
304 WARN( _( "No gfx for %s…" ), p->name );
305 else {
306 ih = pitch;
307 iw = ih;
308 if ( p->gfx_space->w > p->gfx_space->h )
309 ih = ih * p->gfx_space->h / p->gfx_space->w;
310 else if ( p->gfx_space->w < p->gfx_space->h )
311 iw = iw * p->gfx_space->w / p->gfx_space->h;
312 gl_renderScale( p->gfx_space, bx + ( pitch - iw ) / 2 + 2,
313 by + ( nshow - vis_index - 1 ) * pitch +
314 ( pitch - ih ) / 2 + offset,
315 iw, ih, &cWhite );
316 }
317 gl_printRaw( &gl_smallFont, bx + 5 + pitch,
318 by + ( nshow - vis_index - 0.5 ) * pitch + offset,
319 ( cur_spob_sel == vis_index ? &cFontGreen : &cFontWhite ),
320 -1., spob_name( p ) );
321 }
322 /* draw the star */
323 ih = pitch;
324 iw = ih;
325 if ( array_size( starImages ) > 0 ) {
326 phase++;
327 if ( phase > 150 ) {
328 phase = 0;
329 focusedStar++;
330 focusedStar %= array_size( starImages );
331 }
332
333 if ( starImages[focusedStar]->w > starImages[focusedStar]->h )
334 ih = ih * starImages[focusedStar]->h / starImages[focusedStar]->w;
335 else if ( starImages[focusedStar]->w < starImages[focusedStar]->h )
336 iw = iw * starImages[focusedStar]->w / starImages[focusedStar]->h;
337 ccol.r = ccol.g = ccol.b = ccol.a = 1;
338 if ( phase > 120 && array_size( starImages ) > 1 )
339 ccol.a = cos( ( phase - 121 ) / 30. * M_PI / 2. );
340 gl_renderScale( starImages[focusedStar], bx + 2,
341 by + ( nshow - 1 ) * pitch + ( pitch - ih ) / 2 + offset,
342 iw, ih, &ccol );
343 if ( phase > 120 && array_size( starImages ) > 1 ) {
344 /* fade in the next star */
345 ih = pitch;
346 iw = ih;
347 i = ( focusedStar + 1 ) % array_size( starImages );
348 if ( starImages[i]->w > starImages[i]->h )
349 ih = ih * starImages[i]->h / starImages[i]->w;
350 else if ( starImages[i]->w < starImages[i]->h )
351 iw = iw * starImages[i]->w / starImages[i]->h;
352 ccol.a = 1 - ccol.a;
353 gl_renderScale( starImages[i], bx + 2,
354 by + ( nshow - 1 ) * pitch + ( pitch - ih ) / 2 +
355 offset,
356 iw, ih, &ccol );
357 }
358 } else if ( sys->nebu_density > 0. ) {
359 /* no nebula or star images - probably due to nebula */
360 txtHeight = gl_printHeightRaw( &gl_smallFont, pitch,
361 _( "Obscured by the nebula" ) );
362 gl_printTextRaw( &gl_smallFont, pitch, txtHeight, ( bx + 2 ),
363 ( by + ( nshow - 0.5 ) * pitch + offset ), 0, &cFontRed,
364 -1., _( "Obscured by the nebula" ) );
365 }
366 gl_printRaw( &gl_smallFont, bx + 5 + pitch,
367 by + ( nshow - 0.5 ) * pitch + offset,
368 ( cur_spob_sel == 0 ? &cFontGreen : &cFontWhite ), -1.,
369 system_name( sys ) );
370 if ( ( cur_spob_sel == 0 ) && bgImage != NULL ) {
371 double imgw, imgh, s;
372 iw = w - 50 - pitch - nameWidth;
373 ih = h;
374 imgw = bgImage->w;
375 imgh = bgImage->h;
376 s = MIN( iw / imgw, ih / imgh );
377 imgw *= s;
378 imgh *= s;
379 gl_renderScale( bgImage, bx + w - iw + ( iw - imgw ) * 0.5,
380 by + h - ih + ( ih - imgh ) * 0.5, imgw, imgh, &cWhite );
381 }
382 /* draw marker around currently selected spob */
383 ccol.r = 0;
384 ccol.g = 0.6 + 0.4 * sin( phase / 150. * 2 * M_PI );
385 ccol.b = 0;
386 ccol.a = 1;
387 ih = 15;
388 iw = 3;
389 gl_renderRect( bx + 1, by + ( nshow - cur_spob_sel - 1 ) * pitch + offset,
390 iw, ih, &ccol );
391 gl_renderRect( bx + 1, by + ( nshow - cur_spob_sel ) * pitch - ih + offset,
392 iw, ih, &ccol );
393 gl_renderRect( bx + pitch + 3 - iw,
394 by + ( nshow - cur_spob_sel - 1 ) * pitch + offset, iw, ih,
395 &ccol );
396 gl_renderRect( bx + pitch + 3 - iw,
397 by + ( nshow - cur_spob_sel ) * pitch - ih + offset, iw, ih,
398 &ccol );
399 gl_renderRect( bx + 1, by + ( nshow - cur_spob_sel - 1 ) * pitch + offset,
400 ih, iw, &ccol );
401 gl_renderRect( bx + 1, by + ( nshow - cur_spob_sel ) * pitch - iw + offset,
402 ih, iw, &ccol );
403 gl_renderRect( bx + pitch + 3 - ih,
404 by + ( nshow - cur_spob_sel - 1 ) * pitch + offset, ih, iw,
405 &ccol );
406 gl_renderRect( bx + pitch + 3 - ih,
407 by + ( nshow - cur_spob_sel ) * pitch - iw + offset, ih, iw,
408 &ccol );
409 cnt = 0;
410 buf[0] = '\0';
411 if ( cur_spob_sel == 0 ) {
412 int infopos = 0;
413 int stars = MAX( array_size( starImages ), 0 );
414 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt, _( "#nSystem:#0 %s\n" ),
415 system_name( sys ) );
416 /* display sun information */
417 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt,
418 n_( "%d-star system\n", "%d-star system\n", stars ),
419 stars );
420
421 /* Nebula. */
422 if ( sys->nebu_density > 0. ) {
423 double dmg = sys->nebu_volatility;
424 const char *sdmg, *adj;
425 char col;
426 char dmgstr[32];
427
428 /* Damage string. */
429 if ( sys_isFlag( sys, SYSTEM_HIDENEBULADAMAGE ) )
430 snprintf( dmgstr, sizeof( dmgstr ),
431 p_( "nebula_volatility", "??? %s" ), UNIT_POWER );
432 else
433 snprintf( dmgstr, sizeof( dmgstr ),
434 p_( "nebula_volatility", "%.1f %s" ),
435 sys->nebu_volatility, UNIT_POWER );
436
437 /* Volatility */
438 if ( dmg > SYS_VOLATILITY_VOLATILE ) {
439 col = 'r';
440 sdmg = p_( "nebula", "Volatile" );
441 } else if ( sys->nebu_volatility > SYS_VOLATILITY_DANGEROUS ) {
442 col = 'o';
443 sdmg = p_( "nebula", "Dangerous" );
444 } else if ( sys->nebu_volatility > 0. ) {
445 col = 'y';
446 sdmg = p_( "nebula", "Unstable" );
447 } else {
448 col = '0';
449 sdmg = p_( "nebula", "Stable" );
450 }
451
452 /* Density */
453 if ( sys->nebu_density > 700. )
454 adj = p_( "nebula", "Dense " );
455 else if ( sys->nebu_density < 300. )
456 adj = p_( "nebula", "Light " );
457 else
458 adj = "";
459
460 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt,
461 _( "#nNebula: #%c%s%s (%s)#0\n" ), col, adj, sdmg,
462 dmgstr );
463 }
464
465 /* Interference. */
466 if ( sys->interference > 0. ) {
467 double itf = sys->interference;
468 const char *sint;
469 char col;
470 if ( itf > 70. ) {
471 col = 'r';
472 sint = p_( "interference", "Dense" );
473 } else if ( itf > 30. ) {
474 col = 'o';
475 sint = p_( "interference", "Medium" );
476 } else {
477 col = 'y';
478 sint = p_( "interference", "Light" );
479 }
480 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt,
481 _( "#nInterference: #%c%s (%.0f%%)#0\n" ), col, sint,
482 itf );
483 }
484 /* Asteroids. */
485 if ( array_size( sys->asteroids ) > 0 ) {
486 ast_nb = ast_area = 0.;
487 for ( i = 0; i < array_size( sys->asteroids ); i++ ) {
488 ast_nb += sys->asteroids[i].nmax;
489 ast_area = MAX( ast_area, sys->asteroids[i].area );
490 }
491 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt,
492 _( "#nAsteroid field density:#0 %.2g\n" ),
493 ast_nb * ASTEROID_REF_AREA / ast_area );
494 }
495 /* Other features. */
496 if ( sys->features != NULL )
497 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt,
498 _( "#nOther:#0 %s\n" ), _( sys->features ) );
499 /* Faction */
500 f = -1;
501 for ( i = 0; i < array_size( sys->spobs ); i++ ) {
502 if ( spob_isKnown( sys->spobs[i] ) ) {
503 if ( ( f == -1 ) && ( sys->spobs[i]->presence.faction >= 0 ) ) {
504 f = sys->spobs[i]->presence.faction;
505 } else if ( f != sys->spobs[i]->presence.faction &&
506 ( sys->spobs[i]->presence.faction >= 0 ) ) {
507 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt,
508 _( "#nFaction:#0 Multiple\n" ) );
509 break;
510 }
511 }
512 }
513 if ( f == -1 ) {
514 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt,
515 _( "#nFaction:#0 N/A\n" ) );
516 } else {
517 if ( i ==
518 array_size( sys->spobs ) ) /* saw them all and all the same */
519 cnt +=
520 scnprintf( &buf[cnt], sizeof( buf ) - cnt,
521 _( "#nFaction:#0 %s\n#nStanding:#0 %s\n" ),
523 /* display the logo */
524 logo = faction_logo( f );
525 if ( logo != NULL ) {
526 gl_renderScale( logo, bx + pitch + nameWidth + 200, by + h - 21, 20,
527 20, &cWhite );
528 }
529 }
530 /* Get presence. */
531 hasPresence = 0;
532 unknownPresence = 0;
533 for ( i = 0; i < array_size( sys->presence ); i++ ) {
534 if ( sys->presence[i].value <= 0 )
535 continue;
536 hasPresence = 1;
537 if ( faction_isKnown( sys->presence[i].faction ) ) {
538 t = faction_reputationColourChar( sys->presence[i].faction );
539 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt, "#n%s: #%c%.0f\n",
540 faction_shortname( sys->presence[i].faction ), t,
541 sys->presence[i].value );
542 } else
543 unknownPresence += sys->presence[i].value;
544 }
545 if ( unknownPresence != 0 )
546 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt, "#n%s: #%c%.0f\n",
547 _( "Unknown" ), 'N', unknownPresence );
548 if ( hasPresence == 0 )
549 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt,
550 _( "#nPresence:#0 N/A\n" ) );
551 txtHeight = gl_printHeightRaw( &gl_smallFont,
552 ( w - nameWidth - pitch - 60 ) / 2, buf );
553 gl_printTextRaw( &gl_smallFont, ( w - nameWidth - pitch - 60 ) / 2,
554 txtHeight, bx + 10 + pitch + nameWidth,
555 by + h - 10 - txtHeight, 0, &cFontWhite, -1., buf );
556
557 /* Jumps. */
558 for ( i = 0; i < array_size( sys->jumps ); i++ ) {
559 if ( jp_isUsable( &sys->jumps[i] ) ) {
560 if ( infopos == 0 ) /* First jump */
561 infopos = scnprintf( infobuf, sizeof( infobuf ),
562 _( " #nJump points to:#0\n" ) );
563 if ( sys_isKnown( sys->jumps[i].target ) )
564 infopos +=
565 scnprintf( &infobuf[infopos], sizeof( infobuf ) - infopos,
566 " %s\n", system_name( sys->jumps[i].target ) );
567 else
568 infopos +=
569 scnprintf( &infobuf[infopos], sizeof( infobuf ) - infopos,
570 _( " Unknown system\n" ) );
571 }
572 }
573 } else {
574 /* Display spob info */
575 p = cur_spobObj_sel;
576 if ( p->presence.faction >= 0 ) { /* show the faction */
577 char factionBuf[64];
578 logo = faction_logo( p->presence.faction );
579 if ( logo != NULL )
580 gl_renderScale( logo, bx + pitch + nameWidth + 200, by + h - 21, 20,
581 20, &cWhite );
582
583 snprintf( factionBuf, 64, "%s",
584 faction_shortname( p->presence.faction ) );
585 gl_printTextRaw( &gl_smallFont, ( w - nameWidth - pitch - 60 ) / 2, 20,
586 bx + pitch + nameWidth + 230, by + h - 31, 0,
587 &cFontWhite, -1., factionBuf );
588 }
589
590 cnt +=
591 scnprintf( &buf[cnt], sizeof( buf ) - cnt,
592 _( "#nSpace Object:#0 %s\n#nPlanetary class:#0 %s "
593 "#nPopulation:#0 %s\n" ),
594 spob_name( p ), _( p->class ), space_populationStr( p ) );
595 if ( !spob_hasService( p, SPOB_SERVICE_INHABITED ) )
596 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt,
597 _( "No space port here\n" ) );
598 else if ( p->can_land )
599 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt, "#g%s#0",
600 _( "You can land here\n" ) );
601 else if ( areEnemies( FACTION_PLAYER, p->presence.faction ) )
602 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt, "#o%s#0",
603 _( "Not advisable to land here\n" ) );
604 else
605 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt, "#r%s#0",
606 _( "You cannot land here\n" ) );
607
608 /* Local features. */
609 if ( p->feature != NULL )
610 cnt += scnprintf( &buf[cnt], sizeof( buf ) - cnt, "%s\n",
611 _( p->feature ) );
612
613 if ( infobuf[0] == '\0' ) {
614 int infocnt = 0;
615
616 /* Add a description */
617 infocnt += scnprintf(
618 &infobuf[infocnt], sizeof( infobuf ) - infocnt, "%s\n\n",
619 ( p->description == NULL ? _( "No description available" )
620 : _( p->description ) ) );
621
622 /* show some additional information */
623 infocnt += scnprintf(
624 &infobuf[infocnt], sizeof( infobuf ) - infocnt,
625 "%s\n"
626 "%s\n%s%s%s%s",
627 /* Redundant information. */
628 // spob_hasService( p, SPOB_SERVICE_LAND) ? _("This object is
629 // landable") : _("This object is not landable"), spob_hasService(
630 // p, SPOB_SERVICE_INHABITED) ? _("This object is inhabited") :
631 // _("This object is not inhabited"),
632 spob_hasService( p, SPOB_SERVICE_REFUEL )
633 ? _( "You can refuel here" )
634 : _( "You cannot refuel here" ),
635 spob_hasService( p, SPOB_SERVICE_BAR ) ? _( "Has a bar" )
636 : _( "Does not have a bar" ),
637 spob_hasService( p, SPOB_SERVICE_MISSIONS )
638 ? _( "Offers missions" )
639 : _( "Does not offer missions" ),
640 spob_hasService( p, SPOB_SERVICE_COMMODITY )
641 ? ""
642 : _( "\nDoes not have a trade outlet" ),
643 spob_hasService( p, SPOB_SERVICE_OUTFITS )
644 ? ""
645 : _( "\nDoes not sell ship equipment" ),
646 spob_hasService( p, SPOB_SERVICE_SHIPYARD )
647 ? ""
648 : _( "\nDoes not sell ships" ) );
649 // if (p->bar_description && spob_hasService( p, SPOB_SERVICE_BAR ))
650 // infocnt += scnprintf( &infobuf[infocnt], sizeof(infobuf)-infocnt,
651 // "\n\n%s", _(p->bar_description) );
652 }
653
654 txtHeight = gl_printHeightRaw( &gl_smallFont,
655 ( w - nameWidth - pitch - 60 ) / 2, buf );
656
657 gl_printTextRaw( &gl_smallFont, ( w - nameWidth - pitch - 60 ) / 2,
658 txtHeight, bx + 10 + pitch + nameWidth,
659 by + h - 10 - txtHeight, 0, &cFontWhite, -1., buf );
660 }
661
662 /* show the trade/outfit/ship info */
663 if ( infobuf[0] != '\0' ) {
664 txtHeight = gl_printHeightRaw(
665 &gl_smallFont, ( w - nameWidth - pitch - 60 ) / 2, infobuf );
666 gl_printTextRaw( &gl_smallFont, ( w - nameWidth - pitch - 60 ) / 2,
667 txtHeight, bx + 10 + pitch + nameWidth, by + 10, 0,
668 &cFontGrey, -1., infobuf );
669 }
670}
671
682static int map_system_mouse( unsigned int wid, const SDL_Event *event,
683 double mx, double my, double w, double h,
684 double rx, double ry, void *data )
685{
686 (void)data;
687 (void)rx;
688 (void)ry;
689
690 switch ( event->type ) {
691 case SDL_MOUSEBUTTONDOWN:
692 /* Must be in bounds. */
693 if ( ( mx < 0. ) || ( mx > w ) || ( my < 0. ) || ( my > h ) )
694 return 0;
695 if ( mx < pitch && my > 0 ) {
696 if ( cur_spob_sel != ( h - my ) / pitch ) {
697 cur_spob_sel = ( h - my ) / pitch;
698 map_system_updateSelected( wid );
699 }
700 return 1;
701 }
702 break;
703 }
704 return 0;
705}
706
707static void map_system_array_update( unsigned int wid, const char *str )
708{
709 int i;
710 Ship *ship;
711 char buf_price[ECON_CRED_STRLEN], buf_license[STRMAX_SHORT],
712 buf_mass[ECON_MASS_STRLEN];
713 size_t l = 0;
714
715 infobuf[0] = '\0';
716 i = toolkit_getImageArrayPos( wid, str );
717 if ( i < 0 )
718 return;
719 if ( ( strcmp( str, MAPSYS_OUTFITS ) == 0 ) ) {
720 Outfit *outfit = cur_spob_sel_outfits[i];
721 double mass = outfit->mass;
722
723 /* new text */
724 price2str( buf_price, outfit->price, player.p->credits, 2 );
725 if ( outfit->license == NULL )
726 buf_license[0] = '\0';
727 else if ( player_hasLicense( outfit->license ) ||
728 ( cur_spobObj_sel != NULL &&
729 spob_hasService( cur_spobObj_sel,
730 SPOB_SERVICE_BLACKMARKET ) ) )
731 strncpy( buf_license, _( outfit->license ),
732 sizeof( buf_license ) - 1 );
733 else
734 snprintf( buf_license, sizeof( buf_license ), "#r%s#0",
735 _( outfit->license ) );
736
737 if ( outfit_isLauncher( outfit ) )
738 mass += outfit_amount( outfit ) * outfit->u.lau.ammo_mass;
739 else if ( outfit_isFighterBay( outfit ) )
740 mass += outfit_amount( outfit ) * outfit->u.bay.ship_mass;
741 snprintf( buf_mass, sizeof( buf_mass ),
742 n_( "%d t", "%d t", (int)round( mass ) ), (int)round( mass ) );
743
744 l +=
745 outfit_getNameWithClass( outfit, &infobuf[l], sizeof( infobuf ) - l );
746 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n%s\n\n",
747 pilot_outfitDescription( player.p, outfit ) );
748
749 /* FIXME: The point of this misery is to split desc_short into a 2-column
750 * layout. It works poorly, but if we don't do this, check out e.g. the
751 * TeraCom Medusa Launcher in a 720p window. */
752 char *desc_start = &infobuf[l];
753 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "%s\n\n",
754 pilot_outfitSummary( player.p, outfit, 0 ) );
755 while ( ( desc_start = strchr( desc_start, '\n' ) ) != NULL ) {
756 char *tab_pos = desc_start;
757 desc_start = strchr( &tab_pos[1], '\n' );
758 if ( desc_start == NULL )
759 break;
760 *tab_pos = '\t';
761 desc_start++;
762 }
763
764 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "#n%s#0 %d ",
765 _( "Owned:" ), player_outfitOwned( outfit ) );
766 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "#n%s#0 %s ",
767 _( "Mass:" ), buf_mass );
768 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "#n%s#0 %s ",
769 _( "Price:" ), buf_price );
770 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "%s", buf_license );
771 } else if ( ( strcmp( str, MAPSYS_SHIPS ) == 0 ) ) {
772 char buf_cargo[ECON_MASS_STRLEN];
773 ship = cur_spob_sel_ships[i];
774
775 /* update text */
776 price2str( buf_price, ship_buyPrice( ship ), player.p->credits, 2 );
777 tonnes2str( buf_mass, ship->mass );
778 tonnes2str( buf_cargo, ship->cap_cargo );
779 if ( ship->license == NULL )
780 strncpy( buf_license, _( "None" ), sizeof( buf_license ) - 1 );
781 else if ( player_hasLicense( ship->license ) ||
782 ( cur_spobObj_sel != NULL &&
783 spob_hasService( cur_spobObj_sel,
784 SPOB_SERVICE_BLACKMARKET ) ) )
785 strncpy( buf_license, _( ship->license ), sizeof( buf_license ) - 1 );
786 else
787 snprintf( buf_license, sizeof( buf_license ), "#r%s#0",
788 _( ship->license ) );
789
790 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "#n%s#0 %s",
791 _( "Model:" ), _( ship->name ) );
792 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, " #n%s#0 %s",
793 _( "Class:" ), _( ship_classDisplay( ship ) ) );
794 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n\n%s\n",
795 _( ship->description ) );
796 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 %s",
797 _( "Fabricator:" ), _( ship->fabricator ) );
798 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, " #n%s#0 %d",
799 _( "Crew:" ), ship->crew );
800 /* Weapons & Manoeuvrability */
801 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 %.0f %s",
802 _( "CPU:" ), ship->cpu, UNIT_CPU );
803 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, " #n%s#0 %s",
804 _( "Mass:" ), buf_mass );
805 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 ",
806 _( "Accel:" ) );
807 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, _( "%.0f %s" ),
808 ship->accel, UNIT_ACCEL );
809 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, " #n%s#0 ",
810 _( "Speed:" ) );
811 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, _( "%.0f %s" ),
812 ship->speed, UNIT_SPEED );
813 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 ",
814 _( "Turn:" ) );
815 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, _( "%.0f %s" ),
816 ship->turn * 180. / M_PI, UNIT_ROTATION );
817 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, " #n%s#0 %.0f%%",
818 _( "Time Constant:" ), ship->dt_default * 100. );
819 /* Misc */
820 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 ",
821 _( "Absorption:" ) );
822 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, _( "%.0f%% damage" ),
823 ship->dmg_absorb * 100. );
824 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 ",
825 _( "Shield:" ) );
826 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l,
827 _( "%.0f %s (%.1f %s)" ), ship->shield, UNIT_ENERGY,
828 ship->shield_regen, UNIT_POWER );
829 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, " #n%s#0 ",
830 _( "Armour:" ) );
831 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l,
832 _( "%.0f %s (%.1f %s)" ), ship->armour, UNIT_ENERGY,
833 ship->armour_regen, UNIT_POWER );
834 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 ",
835 _( "Energy:" ) );
836 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l,
837 _( "%.0f M%s(%.1f %s)" ), ship->energy, UNIT_ENERGY,
838 ship->energy_regen, UNIT_POWER );
839 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 %s",
840 _( "Cargo Space:" ), buf_cargo );
841 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 %d %s",
842 _( "Fuel:" ), ship->fuel, UNIT_UNIT );
843 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, " #n%s#0 %d %s",
844 _( "Fuel Use:" ), ship->fuel_consumption, UNIT_UNIT );
845 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 %s",
846 _( "Price:" ), buf_price );
847 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, " #n%s#0 %s",
848 _( "License:" ), buf_license );
849 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n%s",
850 ship->desc_stats );
851 } else if ( ( strcmp( str, MAPSYS_TRADE ) == 0 ) ) {
852 Commodity *com;
853 credits_t mean;
854 double std;
855 credits_t globalmean;
856 double globalstd;
857 char buf_mean[ECON_CRED_STRLEN], buf_globalmean[ECON_CRED_STRLEN];
858 char buf_std[ECON_CRED_STRLEN], buf_globalstd[ECON_CRED_STRLEN];
859 char buf_buy_price[ECON_CRED_STRLEN];
860 int owned, priceok;
861 com = cur_spobObj_sel->commodities[i];
862 economy_getAveragePrice( com, &globalmean, &globalstd );
863 priceok =
864 economy_getAverageSpobPrice( com, cur_spobObj_sel, &mean, &std );
865 credits2str( buf_mean, mean, -1 );
866 snprintf( buf_std, sizeof( buf_std ), "%.1f ¤",
867 std ); /* TODO credit2str could learn to do this... */
868 credits2str( buf_globalmean, globalmean, -1 );
869 snprintf( buf_globalstd, sizeof( buf_globalstd ), "%.1f ¤",
870 globalstd ); /* TODO credit2str could learn to do this... */
871 owned = pilot_cargoOwned( player.p, com );
872
873 l = scnprintf( infobuf, sizeof( infobuf ) - l, "%s\n\n%s\n\n",
874 _( com->name ), _( com->description ) );
875
876 if ( owned > 0 ) {
877 credits2str( buf_buy_price, com->lastPurchasePrice, -1 );
878 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l,
879 n_( "#nYou have:#0 %d tonne, purchased at %s/t\n",
880 "#nYou have:#0 %d tonnes, purchased at %s/t\n",
881 owned ),
882 owned, buf_buy_price );
883 } else
884 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l,
885 n_( "#nYou have:#0 %d tonne\n",
886 "#nYou have:#0 %d tonnes\n", owned ),
887 owned );
888
889 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "#n%s#0 ",
890 _( "Average price seen here:" ) );
891 if ( !priceok )
892 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, _( "%s/t ± %s/t" ),
893 buf_mean, buf_std );
894 else
895 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, _( "%s/t ± %s/t" ),
896 _( "??" ), _( "??" ) );
897 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n#n%s#0 ",
898 _( "Average price seen everywhere:" ) );
899 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, _( "%s/t ± %s/t" ),
900 buf_globalmean, buf_globalstd );
901 l += scnprintf( &infobuf[l], sizeof( infobuf ) - l, "\n%s", "" );
902 } else
903 WARN( _( "Unexpected call to map_system_array_update\n" ) );
904}
905
906void map_system_updateSelected( unsigned int wid )
907{
908 StarSystem *sys = cur_sys_sel;
909 Spob *last = NULL;
910 int spobObjChanged = 0;
911 int w, h;
912 Spob *p;
913 int textw;
914 int noutfits, nships, ngoods;
915 Outfit **outfits;
916 Ship **ships;
917 float g, o, s;
918 nameWidth = 0; /* get the widest spob/star name */
919 nshow = 1; /* start at 1 for the sun*/
920 infobuf[0] = '\0'; /* clear buffer. */
921 for ( int i = 0; i < array_size( sys->spobs ); i++ ) {
922 p = sys->spobs[i];
923 if ( spob_isKnown( p ) ) {
924 textw = gl_printWidthRaw( &gl_smallFont, spob_name( p ) );
925 if ( textw > nameWidth )
926 nameWidth = textw;
927 last = p;
928 if ( cur_spob_sel == nshow ) {
929 if ( cur_spobObj_sel != p )
930 spobObjChanged = 1;
931 cur_spobObj_sel = p;
932 }
933 nshow++;
934 }
935 }
936 /* get width of star name text */
937 textw = gl_printWidthRaw( &gl_smallFont, system_name( sys ) );
938 if ( textw > nameWidth )
939 nameWidth = textw;
940
941 window_dimWindow( wid, &w, &h );
942
943 pitch = ( h - 100 ) / nshow;
944 if ( pitch > w / 5 )
945 pitch = w / 5;
946
947 if ( cur_spob_sel >= nshow ) {
948 cur_spob_sel = nshow - 1;
949 if ( cur_spobObj_sel != last ) {
950 cur_spobObj_sel = last;
951 spobObjChanged = 1;
952 }
953 }
954 if ( cur_spob_sel <= 0 ) {
955 /* star selected */
956 cur_spob_sel = 0;
957 if ( cur_spobObj_sel != NULL ) {
958 cur_spobObj_sel = NULL;
959 spobObjChanged = 1;
960 }
961 }
962
963 if ( spobObjChanged ) {
964 infobuf[0] = '\0';
965 if ( cur_spobObj_sel == NULL ) {
966 /*The star*/
967 noutfits = 0;
968 nships = 0;
969 ngoods = 0;
970 window_disableButton( wid, "btnBuyCommodPrice" );
971 } else {
972 /* get number of each to decide how much space the lists can have */
973 outfits = tech_getOutfit( cur_spobObj_sel->tech );
974 noutfits = array_size( outfits );
975 array_free( outfits );
976 ships = tech_getShip( cur_spobObj_sel->tech );
977 nships = array_size( ships );
978 array_free( ships );
979 ngoods = array_size( cur_spobObj_sel->commodities );
980 /* to buy commodity info, need to be landed, and the selected system
981 * must sell them! */
982 if ( landed &&
983 spob_hasService( cur_spobObj_sel, SPOB_SERVICE_COMMODITY ) )
984 window_enableButton( wid, "btnBuyCommodPrice" );
985 else
986 window_disableButton( wid, "btnBuyCommodPrice" );
987 }
988 /* determine the ratio of space */
989 s = g = o = 0;
990 if ( ngoods != 0 )
991 g = 0.35;
992
993 if ( noutfits != 0 ) {
994 if ( nships != 0 ) {
995 s = 0.25;
996 o = 1 - g - s;
997 } else
998 o = 1 - g;
999 } else if ( nships != 0 )
1000 s = 1 - g;
1001 /* ensure total is ~1 */
1002 g += 1 - g - o - s;
1003 map_system_genOutfitsList( wid, g, o, s );
1004 map_system_genShipsList( wid, g, o, s );
1005 map_system_genTradeList( wid, g, o, s );
1006 }
1007}
1008
1014static void map_system_genOutfitsList( unsigned int wid, float goodsSpace,
1015 float outfitSpace, float shipSpace )
1016{
1017 int i;
1018 ImageArrayCell *coutfits;
1019 int noutfits;
1020 int w, h;
1021 int xpos, xw, ypos, yh;
1022 int iconsize;
1023 static Spob *spobDone = NULL;
1024
1025 window_dimWindow( wid, &w, &h );
1026 if ( spobDone == cur_spobObj_sel ) {
1027 if ( widget_exists( wid, MAPSYS_OUTFITS ) )
1028 return;
1029 } else {
1030 if ( widget_exists( wid, MAPSYS_OUTFITS ) ) {
1031 window_destroyWidget( wid, MAPSYS_OUTFITS );
1032 }
1033 }
1034 spobDone = cur_spobObj_sel;
1035
1036 /* Clean up array if exists. */
1037 array_free( cur_spob_sel_outfits );
1038 cur_spob_sel_outfits = NULL;
1039
1040 /* set up the outfits to buy/sell */
1041 if ( cur_spobObj_sel == NULL )
1042 return;
1043
1044 /* No outfitter. */
1045 if ( !spob_hasService( cur_spobObj_sel, SPOB_SERVICE_OUTFITS ) )
1046 return;
1047
1048 cur_spob_sel_outfits = tech_getOutfit( cur_spobObj_sel->tech );
1049 noutfits = array_size( cur_spob_sel_outfits );
1050
1051 if ( noutfits <= 0 )
1052 return;
1053 coutfits = outfits_imageArrayCells( (const Outfit **)cur_spob_sel_outfits,
1054 &noutfits, player.p, 1 );
1055
1056 xw = ( w - nameWidth - pitch - 60 ) / 2;
1057 xpos = 35 + pitch + nameWidth + xw;
1058 i = ( goodsSpace != 0 ) + ( outfitSpace != 0 ) + ( shipSpace != 0 );
1059 yh = ( h - 100 - ( i + 1 ) * 5 ) * outfitSpace;
1060 ypos = 65 + 5 * ( shipSpace != 0 ) + ( h - 100 - ( i + 1 ) * 5 ) * shipSpace;
1061
1062 iconsize = 64;
1063 if ( toolkit_simImageArrayVisibleElements( xw, yh, iconsize, iconsize ) <
1064 noutfits )
1065 iconsize = 48;
1066 window_addImageArray( wid, xpos, ypos, xw, yh, MAPSYS_OUTFITS, iconsize,
1067 iconsize, coutfits, noutfits, map_system_array_update,
1068 NULL, NULL );
1069 toolkit_unsetSelection( wid, MAPSYS_OUTFITS );
1070}
1071
1072static void map_system_genShipsList( unsigned int wid, float goodsSpace,
1073 float outfitSpace, float shipSpace )
1074{
1075 ImageArrayCell *cships;
1076 int nships;
1077 int xpos, ypos, xw, yh;
1078 static Spob *spobDone = NULL;
1079 int i, w, h, iconsize;
1080 window_dimWindow( wid, &w, &h );
1081
1082 /* set up the ships that can be bought here */
1083 if ( spobDone == cur_spobObj_sel ) {
1084 if ( widget_exists( wid, MAPSYS_SHIPS ) )
1085 return;
1086 } else {
1087 if ( widget_exists( wid, MAPSYS_SHIPS ) ) {
1088 window_destroyWidget( wid, MAPSYS_SHIPS );
1089 array_free( cur_spob_sel_ships );
1090 cur_spob_sel_ships = NULL;
1091 }
1092 assert( cur_spob_sel_ships == NULL );
1093 }
1094 spobDone = cur_spobObj_sel;
1095
1096 /* set up the outfits to buy/sell */
1097 if ( cur_spobObj_sel == NULL )
1098 return;
1099
1100 /* No shipyard. */
1101 if ( !spob_hasService( cur_spobObj_sel, SPOB_SERVICE_SHIPYARD ) )
1102 return;
1103
1104 cur_spob_sel_ships = tech_getShip( cur_spobObj_sel->tech );
1105 nships = array_size( cur_spob_sel_ships );
1106
1107 if ( nships <= 0 )
1108 return;
1109
1110 cships = calloc( nships, sizeof( ImageArrayCell ) );
1111 for ( i = 0; i < nships; i++ ) {
1112 cships[i].image = ship_gfxStore( cur_spob_sel_ships[i], 256, 0., 0., 0. );
1113 cships[i].caption = strdup( _( cur_spob_sel_ships[i]->name ) );
1114 }
1115 xw = ( w - nameWidth - pitch - 60 ) / 2;
1116 xpos = 35 + pitch + nameWidth + xw;
1117 i = ( goodsSpace != 0 ) + ( outfitSpace != 0 ) + ( shipSpace != 0 );
1118 yh = ( h - 100 - ( i + 1 ) * 5 ) * shipSpace;
1119 ypos = 65;
1120
1121 iconsize = 48;
1122 if ( toolkit_simImageArrayVisibleElements( xw, yh, iconsize, iconsize ) <
1123 nships )
1124 iconsize = 48;
1125 window_addImageArray( wid, xpos, ypos, xw, yh, MAPSYS_SHIPS, iconsize,
1126 iconsize, cships, nships, map_system_array_update,
1127 NULL, NULL );
1128 toolkit_unsetSelection( wid, MAPSYS_SHIPS );
1129}
1130
1131static void map_system_genTradeList( unsigned int wid, float goodsSpace,
1132 float outfitSpace, float shipSpace )
1133{
1134 static Spob *spobDone = NULL;
1135 int i, ngoods;
1136 ImageArrayCell *cgoods;
1137 int xpos, ypos, xw, yh, w, h, iconsize;
1138 window_dimWindow( wid, &w, &h );
1139
1140 /* set up the commodities that can be bought here */
1141 if ( spobDone == cur_spobObj_sel ) {
1142 if ( widget_exists( wid, MAPSYS_TRADE ) ) {
1143 return;
1144 }
1145 } else {
1146 if ( widget_exists( wid, MAPSYS_TRADE ) ) {
1147 window_destroyWidget( wid, MAPSYS_TRADE );
1148 }
1149 }
1150
1151 /* goods list */
1152 if ( cur_spobObj_sel == NULL )
1153 return;
1154
1155 /* No shipyard. */
1156 if ( !spob_hasService( cur_spobObj_sel, SPOB_SERVICE_COMMODITY ) )
1157 return;
1158
1159 spobDone = cur_spobObj_sel;
1160
1161 ngoods = array_size( cur_spobObj_sel->commodities );
1162
1163 if ( ngoods <= 0 )
1164 return;
1165 cgoods = calloc( ngoods, sizeof( ImageArrayCell ) );
1166 for ( i = 0; i < ngoods; i++ ) {
1167 cgoods[i].image =
1168 gl_dupTexture( cur_spobObj_sel->commodities[i]->gfx_store );
1169 cgoods[i].caption = strdup( _( cur_spobObj_sel->commodities[i]->name ) );
1170 }
1171 /* set up the goods to buy/sell */
1172 xw = ( w - nameWidth - pitch - 60 ) / 2;
1173 xpos = 35 + pitch + nameWidth + xw;
1174 i = ( goodsSpace != 0 ) + ( outfitSpace != 0 ) + ( shipSpace != 0 );
1175 yh = ( h - 100 - ( i + 1 ) * 5 ) * goodsSpace;
1176 ypos =
1177 60 + 5 * i + ( h - 100 - ( i + 1 ) * 5 ) * ( outfitSpace + shipSpace );
1178
1179 iconsize = 48;
1180 if ( toolkit_simImageArrayVisibleElements( xw, yh, iconsize, iconsize ) <
1181 ngoods )
1182 iconsize = 48;
1183 window_addImageArray( wid, xpos, ypos, xw, yh, MAPSYS_TRADE, iconsize,
1184 iconsize, cgoods, ngoods, map_system_array_update,
1185 NULL, NULL );
1186 toolkit_unsetSelection( wid, MAPSYS_TRADE );
1187}
1188
1192void map_system_buyCommodPrice( unsigned int wid, const char *str )
1193{
1194 (void)wid;
1195 (void)str;
1196 int njumps = 0;
1197 StarSystem **syslist;
1198 int cost;
1199 char coststr[ECON_CRED_STRLEN];
1200 ntime_t t = ntime_get();
1201
1202 /* find number of jumps */
1203 if ( ( strcmp( cur_system->name, cur_sys_sel->name ) == 0 ) ) {
1204 cost = 500;
1205 njumps = 0;
1206 } else {
1207 syslist =
1208 map_getJumpPath( cur_system, NULL, cur_sys_sel, 1, 0, NULL, NULL );
1209 if ( syslist == NULL ) {
1210 /* no route */
1211 dialogue_msg( _( "Unavailable" ),
1212 _( "Commodity prices for %s are not available here at "
1213 "the moment." ),
1214 _( cur_spobObj_sel->name ) );
1215 return;
1216 } else {
1217 cost = 500 + 300 * array_size( syslist );
1218 array_free( syslist );
1219 }
1220 }
1221
1222 /* get the time at which this purchase will be made (2 periods per jump
1223 * ago)*/
1224 t -= ( njumps * 2 + 0.2 ) * NT_PERIOD_SECONDS * 1000;
1225 credits2str( coststr, cost, -1 );
1226 if ( !player_hasCredits( cost ) )
1227 dialogue_msg( _( "Insufficient Credits" ),
1228 _( "You need %s to purchase this information." ), coststr );
1229 else if ( array_size( cur_spobObj_sel->commodities ) == 0 )
1230 dialogue_msgRaw( _( "No commodities sold here" ),
1231 _( "There are no commodities sold here." ) );
1232 else if ( cur_spobObj_sel->commodityPrice[0].updateTime >= t )
1234 _( "Already Up-to-date" ),
1235 _( "You have newer information that what is available." ) );
1236 else {
1237 int ret = dialogue_YesNo(
1238 _( "Purchase commodity prices?" ),
1239 _( "Purchase %g period old pricing information for %s for %s?" ),
1240 njumps * 2 + 0.2, _( cur_spobObj_sel->name ), coststr );
1241 if ( ret ) {
1242 player_modCredits( -cost );
1243 economy_averageSeenPricesAtTime( cur_spobObj_sel, t );
1244 map_system_array_update( wid, MAPSYS_TRADE );
1245 }
1246 }
1247}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:170
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:179
glTexture ** background_getStarTextures(void)
Returns an array (array.h) of star background images in the system background.
Definition background.c:629
void background_clear(void)
Cleans up the background stuff.
Definition background.c:570
glTexture * background_getAmbientTexture(void)
Returns an overall background image (nebula, for instance), or NULL if none exists.
Definition background.c:644
int background_load(const char *name)
Loads a background script by name.
Definition background.c:502
#define BUTTON_HEIGHT
Definition board.c:28
#define BUTTON_WIDTH
Definition board.c:27
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 price2str(char *str, credits_t price, credits_t credits, int decimals)
Given a price and on-hand credits, outputs a colourized string.
Definition commodity.c:111
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_YesNo(const char *caption, const char *fmt,...)
Runs a dialogue with both yes and no options.
Definition dialogue.c:352
int economy_getAveragePrice(const Commodity *com, credits_t *mean, double *std)
Gets the average price of a good as seen by the player (anywhere).
Definition economy.c:248
int economy_getAverageSpobPrice(const Commodity *com, const Spob *p, credits_t *mean, double *std)
Gets the average price of a good on a spob in a system, using a rolling average over the times the pl...
Definition economy.c:171
const char * faction_longname(int f)
Gets the faction's long name (formal, human-readable).
Definition faction.c:373
int faction_isKnown(int id)
Is the faction known?
Definition faction.c:300
const glTexture * faction_logo(int f)
Gets the faction's logo (ideally 256x256).
Definition faction.c:479
int areEnemies(int a, int b)
Checks whether two factions are enemies.
Definition faction.c:1450
const char * faction_shortname(int f)
Gets a factions short name (human-readable).
Definition faction.c:350
const char * faction_getStandingText(int f)
Gets the player's standing in human readable form.
Definition faction.c:1257
char faction_reputationColourChar(int f)
Gets the faction character associated to its standing with the player.
Definition faction.c:1228
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
void gl_printRaw(const glFont *ft_font, double x, double y, const glColour *c, double outlineR, const char *text)
Prints text on screen.
Definition font.c:646
int gl_printWidthRaw(const glFont *ft_font, const char *text)
Gets the width that it would take to print some text.
Definition font.c:984
glFont gl_defFont
Definition font.c:158
int gl_printTextRaw(const glFont *ft_font, const int width, const int height, double bx, double by, int line_height, const glColour *c, double outlineR, const char *text)
Prints a block of text that fits in the dimensions given.
Definition font.c:895
int landed
Definition land.c:78
ImageArrayCell * outfits_imageArrayCells(const Outfit **outfits, int *noutfits, const Pilot *p, int store)
Generates image array cells corresponding to outfits.
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:39
#define MAX(x, y)
Definition naev.h:37
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_get(void)
Gets the current time.
Definition ntime.c:113
void gl_renderRect(double x, double y, double w, double h, const glColour *c)
Renders a rectangle.
void gl_renderScale(const glTexture *texture, double bx, double by, double bw, double bh, const glColour *c)
Blits a texture scaling it.
glTexture * gl_dupTexture(const glTexture *texture)
Duplicates a texture.
Definition opengl_tex.c:891
void gl_freeTexture(glTexture *texture)
Frees a texture.
Definition opengl_tex.c:835
int outfit_isLauncher(const Outfit *o)
Checks if outfit is a weapon launcher.
Definition outfit.c:649
size_t outfit_getNameWithClass(const Outfit *outfit, char *buf, size_t size)
Gets a brief name/class description suitable for the title section of an outfitter screen.
Definition outfit.c:525
int outfit_isFighterBay(const Outfit *o)
Checks if outfit is a fighter bay.
Definition outfit.c:701
int outfit_amount(const Outfit *o)
Gets the amount an outfit can hold.
Definition outfit.c:850
int pilot_cargoOwned(const Pilot *pilot, const Commodity *cargo)
Gets how many of the commodity a pilot has.
Definition pilot_cargo.c:38
const char * pilot_outfitDescription(const Pilot *p, const Outfit *o)
Gets the description of an outfit for a given pilot.
const char * pilot_outfitSummary(const Pilot *p, const Outfit *o, int withname)
Gets the summary of an outfit for a give pilot.
int player_hasLicense(const char *license)
Checks to see if player has license.
Definition player.c:3207
credits_t player_modCredits(credits_t amount)
Modifies the amount of credits the player has.
Definition player.c:1047
Player_t player
Definition player.c:77
int player_hasCredits(credits_t amount)
Checks to see if the player has enough credits.
Definition player.c:1036
int player_outfitOwned(const Outfit *o)
Gets how many of the outfit the player owns.
Definition player.c:2882
const char * ship_classDisplay(const Ship *s)
Gets the ship's display class in human readable form.
Definition ship.c:203
credits_t ship_buyPrice(const Ship *s)
The ship buy price, includes default outfits.
Definition ship.c:303
glTexture * ship_gfxStore(const Ship *s, int size, double dir, double updown, double glow)
Get the store gfx.
Definition ship.c:383
void space_gfxUnload(StarSystem *sys)
Unloads all the graphics for a star system.
Definition space.c:2281
StarSystem * system_getIndex(int id)
Get the system by its index.
Definition space.c:1038
StarSystem * cur_system
Definition space.c:110
const char * spob_name(const Spob *p)
Gets the translated name of a spob.
Definition space.c:1834
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_gfxLoad(StarSystem *sys)
Loads all the graphics for a star system.
Definition space.c:2266
Represents a commodity.
Definition commodity.h:57
char * description
Definition commodity.h:59
char * name
Definition commodity.h:58
credits_t lastPurchasePrice
Definition commodity.h:73
A ship outfit, depends radically on the type.
Definition outfit.h:372
credits_t price
Definition outfit.h:391
union Outfit::@264277167364127137334024361374356236341374052147 u
OutfitLauncherData lau
Definition outfit.h:456
OutfitFighterBayData bay
Definition outfit.h:459
char * license
Definition outfit.h:381
double mass
Definition outfit.h:384
Represents a space ship.
Definition ship.h:97
double shield_regen
Definition ship.h:142
double dt_default
Definition ship.h:136
double cap_cargo
Definition ship.h:135
char * license
Definition ship.h:116
char * name
Definition ship.h:100
int fuel
Definition ship.h:133
char * fabricator
Definition ship.h:120
char * description
Definition ship.h:121
double energy_regen
Definition ship.h:144
double armour
Definition ship.h:139
int fuel_consumption
Definition ship.h:134
double armour_regen
Definition ship.h:140
int crew
Definition ship.h:130
double dmg_absorb
Definition ship.h:145
double cpu
Definition ship.h:132
double speed
Definition ship.h:127
double turn
Definition ship.h:126
char * desc_stats
Definition ship.h:180
double accel
Definition ship.h:125
double energy
Definition ship.h:143
double shield
Definition ship.h:141
double mass
Definition ship.h:131
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition space.h:102
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:43
Ship ** tech_getShip(const tech_group_t *tech)
Gets all of the ships associated to a tech group.
Definition tech.c:887
Outfit ** tech_getOutfit(const tech_group_t *tech)
Gets all of the outfits associated to a tech group.
Definition tech.c:839
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_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_destroyWidget(unsigned int wid, const char *wgtname)
Destroys a widget in a window.
Definition toolkit.c:1167
void window_handleKeys(unsigned int wid, int(*keyhandler)(unsigned int, SDL_Keycode, SDL_Keymod, int))
Sets the key handler for the window.
Definition toolkit.c:961
unsigned int window_get(const char *wdwname)
Gets the ID of a window.
Definition toolkit.c:662
int window_exists(const char *wdwname)
Checks to see if a window exists.
Definition toolkit.c:591
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