naev 0.11.5
land_outfits.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <math.h>
11#include <stdio.h>
12#include <stdlib.h>
13
14#include "naev.h"
17#include "land_outfits.h"
18
19#include "array.h"
20#include "cond.h"
21#include "dialogue.h"
22#include "equipment.h"
23#include "hook.h"
24#include "log.h"
25#include "map.h"
26#include "map_find.h"
27#include "nstring.h"
28#include "nlua.h"
29#include "outfit.h"
30#include "pilot_outfit.h"
31#include "player.h"
32#include "player_gui.h"
33#include "slots.h"
34#include "space.h"
35#include "toolkit.h"
36#include "utf8.h"
37
38#define OUTFITS_IAR "iarOutfits"
39#define OUTFITS_TAB "tabOutfits"
40#define OUTFITS_FILTER "inpFilterOutfits"
41#define OUTFITS_NTABS 7
42
45typedef struct LandOutfitData_ {
46 const Outfit **outfits;
49
50static iar_data_t iar_data[OUTFITS_NTABS];
51static Outfit **iar_outfits[OUTFITS_NTABS];
52static int outfit_Mode = 0;
55/* Modifier for buying and selling quantity. */
56static int outfits_mod = 1;
57
58/*
59 * Helper functions.
60 */
61static void outfits_getSize( unsigned int wid, int *w, int *h,
62 int *iw, int *ih, int *bw, int *bh );
63static void outfits_buy( unsigned int wid, const char *str );
64static void outfits_sell( unsigned int wid, const char *str );
65static int outfits_getMod (void);
66static void outfits_rmouse( unsigned int wid, const char* widget_name );
67static void outfits_find( unsigned int wid, const char *str );
68static const char *outfit_getPrice( const Outfit *outfit, credits_t *price, int *canbuy, int *cansell );
69static void outfit_Popdown( unsigned int wid, const char* str );
70static void outfits_genList( unsigned int wid );
71static void outfits_changeTab( unsigned int wid, const char *wgt, int old, int tab );
72static void outfits_onClose( unsigned int wid, const char *str );
73static void outfit_modifiers( unsigned int wid );
74static int outfit_events( unsigned int wid, SDL_Event *evt );
75
79static void outfits_getSize( unsigned int wid, int *w, int *h,
80 int *iw, int *ih, int *bw, int *bh )
81{
82 int padding;
83
84 /* Get window dimensions. */
85 window_dimWindow( wid, w, h );
86
87 /* Calculate image array dimensions. */
88 if (iw != NULL)
89 *iw = 680 + (*w - LAND_WIDTH);
90 if (ih != NULL)
91 *ih = *h - 60;
92
93 /* Left padding + per-button padding * nbuttons */
94 padding = 40 + 20 * 4;
95
96 /* Calculate button dimensions. */
97 if (bw != NULL)
98 *bw = (*w - (iw!=NULL?*iw:0) - padding) / 4;
99 if (bh != NULL)
100 *bh = LAND_BUTTON_HEIGHT;
101}
102
103static void outfit_modifiers( unsigned int wid )
104{
105 int q = outfits_getMod();
106 if (q != outfits_mod) {
108 outfits_mod = q;
109 if (q==1) {
110 window_buttonCaption( wid, "btnBuyOutfit", _("Buy") );
111 window_buttonCaption( wid, "btnSellOutfit", _("Sell") );
112 }
113 else {
114 char buf[STRMAX_SHORT];
115 snprintf( buf, sizeof(buf), _("Buy (%dx)"), q );
116 window_buttonCaption( wid, "btnBuyOutfit", buf );
117 snprintf( buf, sizeof(buf), _("Sell (%dx)"), q );
118 window_buttonCaption( wid, "btnSellOutfit", buf );
119 }
121 }
122}
123
127static int outfit_events( unsigned int wid, SDL_Event *evt )
128{
129 (void) evt; /* For constness warning. */
130 if ((evt->type==SDL_KEYDOWN) || (evt->type==SDL_KEYUP))
131 outfit_modifiers( wid );
132 return 0;
133}
134
138static void outfits_onClose( unsigned int wid, const char *str )
139{
140 (void) str;
141 LandOutfitData *data = window_getData( wid );
142 if (data != NULL) {
143 array_free( data->outfits );
144 free( data );
145 }
146}
147
156void outfits_open( unsigned int wid, const Outfit **outfits, int blackmarket )
157{
158 int w, h, iw, ih, bw, bh, off;
159 LandOutfitData *data = NULL;
160
161 /* Clear sold outfits. */
163 outfits_sold = NULL;
164
165 /* initialize the outfit mode. */
166 outfit_Mode = 0;
167 data = malloc( sizeof( LandOutfitData ) );
168 data->outfits = outfits;
169 data->blackmarket = blackmarket;
170 window_setData( wid, data );
172
173 /* Mark as generated. */
174 if (outfits==NULL)
175 land_tabGenerate(LAND_WINDOW_OUTFITS);
176
177 /* Get dimensions. */
178 outfits_getSize( wid, &w, &h, &iw, &ih, &bw, &bh );
179
180 /* Initialize stored positions. */
181 for (int i=0; i<OUTFITS_NTABS; i++) {
182 toolkit_initImageArrayData( &iar_data[i] );
184 }
185 memset( iar_outfits, 0, sizeof(Outfit**) * OUTFITS_NTABS );
186
187 /* will allow buying from keyboard */
189
190 /* handle multipliers. */
192 window_setOnFocus( wid, outfit_modifiers );
193
194 /* buttons */
195 off = -20;
196 if (data->outfits==NULL) {
197 window_addButtonKey( wid, off, 20,
198 bw, bh, "btnCloseOutfits",
199 _("Take Off"), land_buttonTakeoff, SDLK_t );
200 }
201 else {
202 window_addButtonKey( wid, off, 20,
203 bw, bh, "btnCloseOutfits",
204 _("Close"), window_close, SDLK_t );
205 }
206 off -= 20+bw;
207 window_addButtonKey( wid, off, 20,
208 bw, bh, "btnSellOutfit",
209 _("Sell"), outfits_sell, SDLK_s );
210 off -= 20+bw;
211 window_addButtonKey( wid, off, 20,
212 bw, bh, "btnBuyOutfit",
213 _("Buy"), outfits_buy, SDLK_b );
214 off -= 20+bw;
215 window_addButtonKey( wid, off, 20,
216 bw, bh, "btnFindOutfits",
217 _("Find Outfits"), outfits_find, SDLK_f );
218
219 /* fancy 256x256 image */
220 window_addRect( wid, -40+4, -40+4, 264, 264, "rctImage", &cBlack, 1 );
221 window_addImage( wid, -40, -40, 256, 256, "imgOutfit", NULL, 0 );
222
223 /* the descriptive text */
224 window_addText( wid, 20 + iw + 20, -40,
225 w - (20 + iw + 20) - 264 - 40, 160, 0, "txtOutfitName", &gl_defFont, NULL, NULL );
226 window_addText( wid, 20 + iw + 20, -40 - gl_defFont.h*2. - 30,
227 w - (20 + iw + 20) - 264 - 40, 400, 0, "txtDescShort", &gl_defFont, NULL, NULL );
228
229 window_addText( wid, 20 + iw + 20, 0,
230 90, 160, 0, "txtSDesc", &gl_defFont, &cFontGrey, NULL );
231 window_addText( wid, 20 + iw + 20 + 90, 0,
232 w - (20 + iw + 20 + 90), 160, 0, "txtDDesc", &gl_defFont, NULL, NULL );
233 window_addText( wid, 20 + iw + 20, 0,
234 w-(iw+80), h, /* TODO: Size exactly and resize instead of moving? */
235 0, "txtDescription", &gl_defFont, NULL, NULL );
236
237 /* Create the image array. */
238 outfits_genList( wid );
239
240 /* Set default keyboard focus to the list */
241 window_setFocus( wid , OUTFITS_IAR );
242}
243
250void outfits_regenList( unsigned int wid, const char *str )
251{
252 (void) str;
253 int tab;
254 char *focused;
255 LandOutfitData *data;
256
257 /* If local or not. */
258 data = window_getData( wid );
259
260 /* Must exist. */
261 if ((data->outfits==NULL) && (land_getWid( LAND_WINDOW_OUTFITS ) == 0))
262 return;
263
264 /* Save focus. */
265 focused = window_getFocus( wid );
266
267 /* Save positions. */
268 tab = window_tabWinGetActive( wid, OUTFITS_TAB );
269 toolkit_saveImageArrayData( wid, OUTFITS_IAR, &iar_data[tab] );
270 window_destroyWidget( wid, OUTFITS_IAR );
271
272 outfits_genList( wid );
273
274 /* Restore positions. */
275 toolkit_loadImageArrayData( wid, OUTFITS_IAR, &iar_data[tab] );
276 outfits_update( wid, NULL );
277
278 /* Restore focus. */
279 window_setFocus( wid, focused );
280 free(focused);
281}
282
287static int outfitLand_filter( const Outfit *o ) {
288 Pilot *p;
289 const PlayerShip_t *ps;
290
291 switch (outfit_Mode) {
292 case 0:
293 return 1;
294
295 case 1: /* Fits any ship of the player. */
296 ps = player_getShipStack();
297 for (int j=0; j < array_size(ps); j++) {
298 p = ps[j].p;
299 for (int i=0; i < array_size(p->outfits); i++) {
300 if (outfit_fitsSlot( o, &p->outfits[i]->sslot->slot ))
301 return 1;
302 }
303 }
304 return 0;
305
306 case 2: /* Fits currently selected ship. */
307 p = player.p;
308 if (p==NULL)
309 return 1;
310 for (int i=0; i < array_size(p->outfits); i++) {
311 if (outfit_fitsSlot( o, &p->outfits[i]->sslot->slot ))
312 return 1;
313 }
314 return 0;
315
316 case 3:
317 return (o->slot.size==OUTFIT_SLOT_SIZE_LIGHT);
318 case 4:
319 return (o->slot.size==OUTFIT_SLOT_SIZE_MEDIUM);
320 case 5:
321 return (o->slot.size==OUTFIT_SLOT_SIZE_HEAVY);
322 }
323 return 1;
324}
325static int outfitLand_filterWeapon( const Outfit *o ) {
326 return outfitLand_filter(o) && outfit_filterWeapon(o);
327}
328static int outfitLand_filterUtility( const Outfit *o ) {
329 return outfitLand_filter(o) && outfit_filterUtility(o);
330}
331static int outfitLand_filterStructure( const Outfit *o ) {
332 return outfitLand_filter(o) && outfit_filterStructure(o);
333}
334static int outfitLand_filterCore( const Outfit *o ) {
335 return outfitLand_filter(o) && outfit_filterCore(o);
336}
337
343static void outfits_genList( unsigned int wid )
344{
345 int (*tabfilters[])( const Outfit *o ) = {
347 outfitLand_filterWeapon,
348 outfitLand_filterUtility,
349 outfitLand_filterStructure,
350 outfitLand_filterCore,
351 outfit_filterOther,
353 };
354
355 int active;
356 ImageArrayCell *coutfits;
357 int noutfits;
358 int w, h, iw, ih;
359 const char *filtertext;
360 LandOutfitData *data;
361 int iconsize;
362
363 /* Get dimensions. */
364 outfits_getSize( wid, &w, &h, &iw, &ih, NULL, NULL );
365
366 /* Create tabbed window. */
367 if (!widget_exists( wid, OUTFITS_TAB )) {
368 int fx, fy, fw, fh, barw; /* Input filter. */
369 const char *tabnames[] = {
370 _("All"), _(OUTFIT_LABEL_WEAPON), _(OUTFIT_LABEL_UTILITY), _(OUTFIT_LABEL_STRUCTURE), _(OUTFIT_LABEL_CORE), _("#rOther"), _("Owned"),
371 };
372
373 window_addTabbedWindow( wid, 20, 20 + ih - 30, iw, 30,
374 OUTFITS_TAB, OUTFITS_NTABS, tabnames, 1 );
375
376 barw = window_tabWinGetBarWidth( wid, OUTFITS_TAB );
377 fw = CLAMP(0, 150, iw - barw - 30);
378 fh = 30;
379
380 fx = iw - fw + 15;
381 fy = ih - 25 -1 + 20;
382
383 /* Only create the filter widgets if it will be a reasonable size. */
384 if (iw >= 65) {
385 /* Add popdown menu stuff. */
386 window_addButton( wid, fx+fw-30, fy, 30, 30, "btnOutfitFilter", NULL, outfit_Popdown );
387 window_buttonCustomRender( wid, "btnOutfitFilter", window_buttonCustomRenderGear );
388 fw -= 35;
389
390 /* Set text filter. */
391 window_addInput( wid, fx, fy, fw, fh, OUTFITS_FILTER, 32, 1, &gl_defFont );
392 inp_setEmptyText( wid, OUTFITS_FILTER, _("Filter…") );
393 window_setInputCallback( wid, OUTFITS_FILTER, outfits_regenList );
394 }
395 }
396
397 window_tabWinOnChange( wid, OUTFITS_TAB, outfits_changeTab );
398 active = window_tabWinGetActive( wid, OUTFITS_TAB );
399
400 /* Widget must not already exist. */
401 if (widget_exists( wid, OUTFITS_IAR ))
402 return;
403
404 filtertext = NULL;
405 if (widget_exists( wid, OUTFITS_FILTER )) {
406 filtertext = window_getInput( wid, OUTFITS_FILTER );
407 if (strlen(filtertext) == 0)
408 filtertext = NULL;
409 }
410
411 /* Set up the outfits to buy/sell */
412 data = window_getData( wid );
413 array_free( iar_outfits[active] );
414
415 if (active==6) {
416 /* Show player their owned outfits. */
417 const PlayerOutfit_t *po = player_getOutfits();
418 iar_outfits[active] = array_create( Outfit* );
419 for (int i=0; i<array_size(po); i++)
420 array_push_back( &iar_outfits[active], (Outfit*) po[i].o );
421 /* Also add stuff they sold. */
422 for (int i=0; i<array_size(outfits_sold); i++) {
424 int found = 0;
425 for (int j=0; j<array_size(po); j++) {
426 if (po[j].o == os->o) {
427 found = 1;
428 break;
429 }
430 }
431 if (!found)
432 array_push_back( &iar_outfits[active], (Outfit*) os->o );
433 }
434 qsort( iar_outfits[active], array_size(iar_outfits[active]), sizeof(Outfit*), outfit_compareTech );
435 }
436 else {
437 /* Use custom list; default to landed outfits. */
438 iar_outfits[active] = (data->outfits!=NULL) ? array_copy( Outfit*, data->outfits ) : tech_getOutfit( land_spob->tech );
439 }
440 noutfits = outfits_filter( (const Outfit**)iar_outfits[active], array_size(iar_outfits[active]), tabfilters[active], filtertext );
441 coutfits = outfits_imageArrayCells( (const Outfit**)iar_outfits[active], &noutfits, player.p, 1 );
442
443 iconsize = 128;
444 if (!conf.big_icons) {
445 if (toolkit_simImageArrayVisibleElements(iw,ih-34,iconsize,iconsize) < noutfits)
446 iconsize = 96;
447 if (toolkit_simImageArrayVisibleElements(iw,ih-34,iconsize,iconsize) < noutfits)
448 iconsize = 64;
449 }
450 window_addImageArray( wid, 20, 20,
451 iw, ih - 34, OUTFITS_IAR, iconsize, iconsize,
452 coutfits, noutfits, outfits_update, outfits_rmouse, NULL );
453
454 /* write the outfits stuff */
455 outfits_update( wid, NULL );
456}
457
463void outfits_update( unsigned int wid, const char *str )
464{
465 (void) str;
466 int i, active;
467 Outfit* outfit;
468 char buf[STRMAX], lbl[STRMAX], buf_credits[ECON_CRED_STRLEN], buf_mass[ECON_MASS_STRLEN];
469 const char *buf_price;
470 credits_t price;
471 size_t l = 0, k = 0;
472 int iw, ih, w, h, blackmarket, canbuy, cansell, sw, th;
473 double mass;
474 const char *summary;
475
476 /* Get dimensions. */
477 outfits_getSize( wid, &w, &h, &iw, &ih, NULL, NULL );
478
479 /* See if black market. */
480 const LandOutfitData *data = window_getData( wid );
481 blackmarket = data->blackmarket;
482
483 /* Set up keys. */
484 k += scnprintf( &lbl[k], sizeof(lbl)-k, "%s", _("Owned:") );
485 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Mass:") );
486 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Price:") );
487 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Money:") );
488
489 /* Get and set parameters. */
490 active = window_tabWinGetActive( wid, OUTFITS_TAB );
491 i = toolkit_getImageArrayPos( wid, OUTFITS_IAR );
492 if (i < 0 || array_size(iar_outfits[active]) == 0) { /* No outfits */
493 window_modifyImage( wid, "imgOutfit", NULL, 256, 256 );
494 window_disableButton( wid, "btnBuyOutfit" );
495 window_disableButton( wid, "btnSellOutfit" );
496 l += scnprintf( &buf[l], sizeof(buf)-l, "%s", _("N/A") );
497 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s", _("N/A") );
498 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s", _("N/A") );
499 /*l +=*/ scnprintf( &buf[l], sizeof(buf)-l, "\n%s", _("N/A") );
500 window_modifyText( wid, "txtSDesc", buf );
501 window_modifyText( wid, "txtDDesc", buf );
502 window_modifyText( wid, "txtOutfitName", _("None") );
503 window_modifyText( wid, "txtDescShort", NULL );
504 window_modifyText( wid, "txtDescription", NULL );
505 /* Reposition. */
506 th = 260;
507 window_moveWidget( wid, "txtSDesc", 20+iw+20, -40-th-30-32 );
508 window_moveWidget( wid, "txtDDesc", 20+iw+20+90, -40-th-30-32 );
509 window_moveWidget( wid, "txtDescription", 20+iw+20, -240-32);
510 return;
511 }
512
513 i = MIN( i, array_size(iar_outfits[active])-1 );
514 outfit = iar_outfits[active][i];
515
516 /* new image */
517 window_modifyImage( wid, "imgOutfit", outfit->gfx_store, 256, 256 );
518
519 /* new text */
520 if (outfit->slot.type == OUTFIT_SLOT_INTRINSIC) {
521 scnprintf( buf, sizeof(buf), "%s\n\n#o%s#0",
522 _(outfit->desc_raw),
523 _("This is an intrinsic outfit that will be directly equipped on the current ship and can not be moved."));
524 window_modifyText( wid, "txtDescription", buf );
525 }
526 else
527 window_modifyText( wid, "txtDescription", _(outfit->desc_raw) );
528 buf_price = outfit_getPrice( outfit, &price, &canbuy, &cansell );
529 credits2str( buf_credits, player.p->credits, 2 );
530
531 /* gray out sell button */
532 if ((outfit_canSell(outfit) > 0) && cansell)
533 window_enableButton( wid, "btnSellOutfit" );
534 else
535 window_disableButtonSoft( wid, "btnSellOutfit" );
536
537 if ((outfit_canBuy( outfit, wid ) > 0) && canbuy) {
538 window_enableButton( wid, "btnBuyOutfit" );
539 }
540 else
541 window_disableButtonSoft( wid, "btnBuyOutfit" );
542
543 mass = outfit->mass;
544 if (outfit_isLauncher(outfit))
545 mass += outfit_amount(outfit) * outfit->u.lau.ammo_mass;
546 else if (outfit_isFighterBay(outfit))
547 mass += outfit_amount(outfit) * outfit->u.bay.ship_mass;
548 tonnes2str( buf_mass, (int)round( mass ) );
549
550 outfit_getNameWithClass( outfit, buf, sizeof(buf) );
551 window_modifyText( wid, "txtOutfitName", buf );
552 window_dimWidget( wid, "txtOutfitName", &sw, NULL );
553 th = gl_printHeightRaw( &gl_defFont, sw, buf )+gl_defFont.h/2;
554 l = 0;
555 l += scnprintf( &buf[l], sizeof(buf)-l, "%d", player_outfitOwned(outfit) );
556 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s", buf_mass );
557 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s", buf_price );
558 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s", buf_credits );
559 if (outfit->license) {
560 int meets_reqs = player_hasLicense( outfit->license );
561 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("License:") );
562 if (blackmarket)
563 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s#0", _("Not Necessary (Blackmarket)") );
564 else
565 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s%s#0", meets_reqs ? "" : "#r", _(outfit->license) );
566 }
567 if (outfit->cond) {
568 int meets_reqs = 0;
569 if (land_spob != NULL)
570 meets_reqs = cond_check(outfit->cond);
571 /*k +=*/ scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Requires:") );
572 if (blackmarket)
573 /*l +=*/ scnprintf( &buf[l], sizeof(buf)-l, "\n%s#0", _("Not Necessary (Blackmarket)") );
574 else
575 /*l +=*/ scnprintf( &buf[l], sizeof(buf)-l, "\n%s%s#0", meets_reqs ? "" : "#r", _(outfit->condstr) );
576 }
577 window_modifyText( wid, "txtSDesc", lbl );
578 window_modifyText( wid, "txtDDesc", buf );
579 summary = pilot_outfitSummary( player.p, outfit, 0 );
580 window_modifyText( wid, "txtDescShort", summary );
581 window_moveWidget( wid, "txtDescShort", 20+iw+20, -40-th );
582 window_dimWidget( wid, "txtDescShort", &sw, NULL );
583 th += gl_printHeightRaw( &gl_defFont, sw, summary );
584 th = MAX( th+gl_defFont.h/2, 240 );
585 window_moveWidget( wid, "txtSDesc", 20+iw+20, -40-th );
586 window_moveWidget( wid, "txtDDesc", 20+iw+20+90, -40-th );
587 window_dimWidget( wid, "txtDDesc", &sw, NULL );
588 th += gl_printHeightRaw( &gl_defFont, sw, buf );
589 th = MAX( th+gl_defFont.h/2, 256+10 );
590 window_moveWidget( wid, "txtDescription", 20+iw+20, -40-th );
591}
592
597{
598 if (landed && land_doneLoading()) {
599 if (spob_hasService(land_spob, SPOB_SERVICE_OUTFITS)) {
600 int ow = land_getWid( LAND_WINDOW_OUTFITS );
601 outfits_regenList( ow, NULL );
602 }
603 else if (!spob_hasService(land_spob, SPOB_SERVICE_SHIPYARD))
604 return;
605
606 int ew = land_getWid( LAND_WINDOW_EQUIPMENT );
608 equipment_regenLists( ew, 1, 0 );
609 }
610}
611
620static void outfits_changeTab( unsigned int wid, const char *wgt, int old, int tab )
621{
622 (void) wgt;
623 iar_data_t old_data;
624
625 toolkit_saveImageArrayData( wid, OUTFITS_IAR, &iar_data[old] );
626
627 /* Store the currently-saved positions for the new tab. */
628 old_data = iar_data[tab];
629
630 /* Resetting the input will cause the outfit list to be regenerated. */
631 if (widget_exists(wid, OUTFITS_FILTER))
632 window_setInput(wid, OUTFITS_FILTER, NULL);
633 else
634 outfits_regenList( wid, NULL );
635
636 /* Set positions for the new tab. This is necessary because the stored
637 * position for the new tab may have exceeded the size of the old tab,
638 * resulting in it being clipped. */
639 toolkit_loadImageArrayData( wid, OUTFITS_IAR, &old_data );
640
641 /* Focus the outfit image array. */
642 window_setFocus( wid, OUTFITS_IAR );
643}
644
654int outfits_filter( const Outfit **outfits, int n,
655 int(*filter)( const Outfit* ), const char *name )
656{
657 int j = 0;
658 for (int i=0; i<n; i++) {
659 const Outfit *o = outfits[i];
660
661 /* First run filter. */
662 if ((filter != NULL) && !filter(outfits[i]))
663 continue;
664
665 /* Try to match name somewhere. */
666 if (name!=NULL) {
667 if ((SDL_strcasestr(_(o->name), name)==NULL) &&
668 (SDL_strcasestr(_(outfit_getType(o)), name)==NULL))
669 continue;
670 }
671
672 /* Shift matches downward. */
673 outfits[j++] = o;
674 }
675
676 return j;
677}
678
684static void outfits_find( unsigned int wid, const char *str )
685{
686 (void) str;
687 map_inputFindType(wid, "outfit");
688}
689
693static const char *outfit_getPrice( const Outfit *outfit, credits_t *price, int *canbuy, int *cansell )
694{
695 static char pricestr[STRMAX_SHORT];
696 unsigned int q = outfits_getMod();
697 if (outfit->lua_price == LUA_NOREF) {
698 price2str( pricestr, outfit->price * q, player.p->credits, 2 );
699 *price = outfit->price * q;
700 *canbuy = 1;
701 *cansell = 1;
702 return pricestr;
703 }
704 const char *str;
705
706 lua_rawgeti(naevL, LUA_REGISTRYINDEX, outfit->lua_price);
707 lua_pushinteger(naevL, q);
708 if (nlua_pcall( outfit->lua_env, 1, 3 )) { /* */
709 WARN(_("Outfit '%s' failed to run '%s':\n%s"),outfit->name,"price",lua_tostring(naevL,-1));
710 *price = 0;
711 *canbuy = 0;
712 *cansell = 0;
713 lua_pop(naevL, 1);
714 return pricestr;
715 }
716
717 str = luaL_checkstring( naevL, -3 );
718 strncpy( pricestr, str, sizeof(pricestr)-1 );
719 *price = 0;
720 *canbuy = lua_toboolean( naevL, -2 );
721 *cansell = lua_toboolean( naevL, -1 );
722 lua_pop(naevL, 3);
723
724 return pricestr;
725}
726
730int outfit_altText( char *buf, int n, const Outfit *o, const Pilot *plt )
731{
732 int p;
733 double mass;
734
735 /* Compute total mass of launcher and ammo if necessary. */
736 mass = o->mass;
737 if (outfit_isLauncher(o))
738 mass += outfit_amount(o) * o->u.lau.ammo_mass;
739 else if (outfit_isFighterBay(o))
740 mass += outfit_amount(o) * o->u.bay.ship_mass;
741
742 p = outfit_getNameWithClass( o, buf, n );
743 p += scnprintf( &buf[p], n-p, "\n" );
744 if (outfit_isProp(o, OUTFIT_PROP_UNIQUE))
745 p += scnprintf( &buf[p], n-p, "#o%s#0\n", _("Unique") );
746 if (o->limit != NULL)
747 p += scnprintf( &buf[p], n-p, "#r%s#0\n", _("Only 1 of type per ship") );
748 if (o->slot.spid != 0)
749 p += scnprintf( &buf[p], n-p, "#o%s#0\n",
750 _(sp_display( o->slot.spid) ) );
751 p += scnprintf( &buf[p], n-p, "%s", pilot_outfitSummary( plt, o, 0 ) );
752 if ((o->mass > 0.) && (p < n)) {
753 char buf_mass[ECON_MASS_STRLEN];
754 tonnes2str( buf_mass, (int)round( mass ) );
755 scnprintf( &buf[p], n-p, "\n%s", buf_mass );
756 }
757 return 0;
758}
759
763ImageArrayCell *outfits_imageArrayCells( const Outfit **outfits, int *noutfits, const Pilot *p, int store )
764{
765 ImageArrayCell *coutfits = calloc( MAX(1,*noutfits), sizeof(ImageArrayCell) );
766
767 if (*noutfits == 0) {
768 *noutfits = 1;
769 coutfits[0].image = NULL;
770 coutfits[0].caption = strdup( _("None") );
771 }
772 else {
773 /* Set alt text. */
774 for (int i=0; i<*noutfits; i++) {
775 const glColour *c;
776 glTexture *t;
777 const Outfit *o = outfits[i];
778
779 coutfits[i].image = gl_dupTexture( o->gfx_store );
780 coutfits[i].caption = strdup( _(o->name) );
781 if (!store && outfit_isProp(o, OUTFIT_PROP_UNIQUE))
782 coutfits[i].quantity = -1; /* Don't display. */
783 else
784 coutfits[i].quantity = player_outfitOwned(o);
785 coutfits[i].sloticon = sp_icon( o->slot.spid );
786
787 /* Background colour. */
789 if (c == NULL)
790 c = &cBlack;
791 col_blend( &coutfits[i].bg, c, &cGrey70, 1 );
792
793 /* Short description. */
794 coutfits[i].alt = strdup( pilot_outfitSummary( p, o, 1 ) );
795
796 /* Slot type. */
797 if ( (strcmp(outfit_slotName(o), "N/A") != 0)
798 && (strcmp(outfit_slotName(o), "NULL") != 0) ) {
799 size_t sz = 0;
800 const char *typename = _(outfit_slotName(o));
801 u8_inc( typename, &sz );
802 coutfits[i].slottype = malloc( sz+1 );
803 memcpy( coutfits[i].slottype, typename, sz );
804 coutfits[i].slottype[sz] = '\0';
805 }
806
807 /* Layers. */
808 coutfits[i].layers = gl_copyTexArray( o->gfx_overlays );
809 if (o->rarity > 0) {
810 t = rarity_texture( o->rarity );
811 coutfits[i].layers = gl_addTexArray( coutfits[i].layers, t );
812 }
813 }
814 }
815 return coutfits;
816}
817
822static void outfit_PopdownSelect( unsigned int wid, const char *str )
823{
824 int m = toolkit_getListPos( wid, str );
825 if (m == outfit_Mode)
826 return;
827
828 outfit_Mode = m;
829 outfits_regenList( wid, NULL );
830}
831
832static void outfit_PopdownActivate( unsigned int wid, const char *str )
833{
834 outfit_PopdownSelect( wid, str );
835 window_destroyWidget( wid, str );
836}
837
838static void outfit_Popdown( unsigned int wid, const char* str )
839{
840 const char *name = "lstOutfitPopdown";
841 const char *modes[] = {
842 N_("Show all outfits"),
843 N_("Show only outfits equipable on any of your ships"),
844 N_("Show only outfits equipable on current ship"),
845 N_("Show only light outfits"),
846 N_("Show only medium outfits"),
847 N_("Show only heavy outfits"),
848 };
849 char **modelist;
850 const size_t n = sizeof(modes) / sizeof(const char*);
851 int x, y, w, h;
852
853 if (widget_exists( wid, name )) {
854 window_destroyWidget( wid, name );
855 return;
856 }
857
858 modelist = malloc(sizeof(modes));
859 for (size_t i=0; i<n; i++)
860 modelist[i] = strdup( _(modes[i]) );
861
862 window_dimWidget( wid, str, &w, &h );
863 window_posWidget( wid, str, &x, &y );
864 window_addList( wid, x+w, y-120+h, 350, 120, name, modelist, n, outfit_Mode, outfit_PopdownSelect, outfit_PopdownActivate );
865 window_setFocus( wid, name );
866}
867
868static int outfit_isSold( const Outfit *outfit, int wid )
869{
870 LandOutfitData *data = NULL;
871 if (wid>=0)
872 data = window_getData( wid );
873 if ((data!=NULL) && (data->outfits!=NULL)) {
874 for (int i=0; i<array_size(data->outfits); i++) {
875 if (data->outfits[i]==outfit)
876 return 1;
877 }
878 return 0;
879 }
880 else if ((land_spob!=NULL) && tech_checkOutfit( land_spob->tech, outfit ))
881 return 1;
882 return 0;
883}
884
890int outfit_canBuy( const Outfit *outfit, int wid )
891{
892 int failure, canbuy, cansell;
893 credits_t price;
894 LandOutfitData *data = NULL;
895 if (wid>=0)
896 data = window_getData( wid );
897 int blackmarket = (data!=NULL) ? data->blackmarket : 0;
898 const Outfit *omap = outfit_get( LOCAL_MAP_NAME );
899
901 failure = 0;
902 outfit_getPrice( outfit, &price, &canbuy, &cansell );
903
904 /* Special exception for local map. */
905 if (outfit!=omap) {
906 int sold = 0;
907 /* See if the player previously sold it. */
908 for (int i=0; i<array_size(outfits_sold); i++) {
909 if (outfits_sold[i].o == outfit ) {
910 sold = outfits_sold[i].q;
911 break;
912 }
913 }
914
915 /* Not sold at planet. */
916 if (!sold && !outfit_isSold( outfit, wid )) {
917 land_errDialogueBuild( _("Outfit not sold here!") );
918 return 0;
919 }
920 }
921
922 /* Unique. */
923 if (outfit_isProp(outfit, OUTFIT_PROP_UNIQUE) && (player_outfitOwnedTotal(outfit)>0)) {
924 land_errDialogueBuild( _("You can only own one of this outfit.") );
925 return 0;
926 }
927
928 /* Intrinsic. */
929 if (outfit->slot.type==OUTFIT_SLOT_INTRINSIC) {
930 if (pilot_hasOutfitLimit( player.p, outfit->limit )) {
931 land_errDialogueBuild( _("You can only equip one of this outfit type.") );
932 return 0;
933 }
934 }
935
936 /* Map already mapped */
937 if ((outfit_isMap(outfit) && map_isUseless(outfit)) ||
938 (outfit_isLocalMap(outfit) && localmap_isUseless(outfit))) {
939 land_errDialogueBuild( _("You already know of everything this map contains.") );
940 return 0;
941 }
942 /* GUI already owned */
943 if (outfit_isGUI(outfit) && player_guiCheck(outfit->u.gui.gui)) {
944 land_errDialogueBuild( _("You already own this GUI.") );
945 return 0;
946 }
947 /* Already has license. */
948 if (outfit_isLicense(outfit) && player_hasLicense(outfit->u.lic.provides)) {
949 land_errDialogueBuild( _("You already have this license.") );
950 return 0;
951 }
952 /* Not enough $$ */
953 if (!player_hasCredits(price)) {
954 char buf[ECON_CRED_STRLEN];
955 credits2str( buf, price - player.p->credits, 2 );
956 land_errDialogueBuild( _("You need %s more."), buf);
957 failure = 1;
958 }
959 /* Needs license. */
960 if (!blackmarket && !player_hasLicense(outfit->license)) {
961 land_errDialogueBuild( _("You need the '%s' license to buy this outfit."),
962 _(outfit->license) );
963 failure = 1;
964 }
965 /* Needs requirements. */
966 if (!blackmarket && (outfit->cond!=NULL) && !cond_check(outfit->cond)) {
967 land_errDialogueBuild( "%s", _(outfit->condstr) );
968 failure = 1;
969 }
970 /* Custom condition failed. */
971 if (!canbuy) {
972 land_errDialogueBuild( _("You lack the resources to buy this outfit.") );
973 failure = 1;
974 }
975
976 return !failure;
977}
978
984static void outfits_rmouse( unsigned int wid, const char* widget_name )
985{
986 outfits_buy( wid, widget_name );
987}
988
994static void outfits_buy( unsigned int wid, const char *str )
995{
996 (void) str;
997 int i, active;
998 Outfit* outfit;
999 int q;
1000 PlayerOutfit_t *sold = NULL;
1001 HookParam hparam[3];
1002
1003 active = window_tabWinGetActive( wid, OUTFITS_TAB );
1004 i = toolkit_getImageArrayPos( wid, OUTFITS_IAR );
1005 if (i < 0 || array_size(iar_outfits[active]) == 0)
1006 return;
1007
1008 outfit = iar_outfits[active][i];
1009 q = outfits_getMod();
1010 /* Can only get one unique item. */
1011 if (outfit_isProp(outfit, OUTFIT_PROP_UNIQUE) ||
1012 (outfit->slot.type==OUTFIT_SLOT_INTRINSIC) ||
1013 outfit_isMap(outfit) || outfit_isLocalMap(outfit) ||
1014 outfit_isGUI(outfit) || outfit_isLicense(outfit))
1015 q = MIN(q,1);
1016
1017 /* Can buy the outfit? */
1018 if (!outfit_canBuy( outfit, wid )) {
1020 return;
1021 }
1022
1023 /* See if the player previously sold it, and limit it to that amount. */
1024 for (int j=0; j<array_size(outfits_sold); j++) {
1025 if (outfits_sold[j].o == outfit) {
1026 sold = &outfits_sold[j];
1027 q = MIN( q, outfits_sold[j].q );
1028 break;
1029 }
1030 }
1031
1032 /* Give dialogue when trying to buy intrinsic. */
1033 if (outfit->slot.type==OUTFIT_SLOT_INTRINSIC)
1034 if (!dialogue_YesNo( _("Buy Intrinsic Outfit?"), _("Are you sure you wish to buy '%s'? It will be automatically equipped on your current ship '%s'."), _(outfit->name), player.p->name ))
1035 return;
1036
1037 /* Try Lua. */
1038 if (outfit->lua_buy != LUA_NOREF) {
1039 lua_rawgeti(naevL, LUA_REGISTRYINDEX, outfit->lua_buy);
1040 lua_pushinteger(naevL, q);
1041 if (nlua_pcall( outfit->lua_env, 1, 2 )) { /* */
1042 WARN(_("Outfit '%s' failed to run '%s':\n%s"),outfit->name,"price",lua_tostring(naevL,-1));
1043 lua_pop(naevL, 1);
1044 }
1045
1046 int bought = lua_toboolean(naevL,-2);
1047
1048 if (!bought) {
1049 dialogue_alert( "%s", lua_tostring(naevL,-1) );
1050 lua_pop(naevL, 2);
1051 return;
1052 }
1053 q = luaL_checkinteger(naevL,-1);
1054 player_addOutfit( outfit, q );
1055
1056 lua_pop(naevL, 2);
1057 }
1058 else
1059 player_modCredits( -outfit->price * player_addOutfit( outfit, q ) );
1060
1061 /* Actually buy the outfit. */
1063 hparam[0].type = HOOK_PARAM_OUTFIT;
1064 hparam[0].u.outfit= outfit;
1065 hparam[1].type = HOOK_PARAM_NUMBER;
1066 hparam[1].u.num = q;
1067 hparam[2].type = HOOK_PARAM_SENTINEL;
1068 hooks_runParam( "outfit_buy", hparam );
1069 land_needsTakeoff( 1 );
1070
1071 /* Mark it that it was sold. */
1072 if (sold != NULL)
1073 sold->q -= q;
1074
1075 /* Regenerate list. */
1076 outfits_regenList( wid, NULL );
1077}
1082int outfit_canSell( const Outfit *outfit )
1083{
1084 int failure = 0;
1085 int canbuy, cansell;
1086 credits_t price;
1087
1088 land_errClear();
1089 outfit_getPrice( outfit, &price, &canbuy, &cansell );
1090
1091 /* Unique item. */
1092 if (outfit_isProp(outfit, OUTFIT_PROP_UNIQUE)) {
1093 land_errDialogueBuild(_("You can't sell a unique outfit."));
1094 failure = 1;
1095 }
1096 /* Map check. */
1097 if (outfit_isMap(outfit) || outfit_isLocalMap(outfit)) {
1098 land_errDialogueBuild(_("You can't sell a map."));
1099 failure = 1;
1100 }
1101 /* GUI check. */
1102 if (outfit_isGUI(outfit)) {
1103 land_errDialogueBuild(_("You can't sell a GUI."));
1104 failure = 1;
1105 }
1106 /* License check. */
1107 if (outfit_isLicense(outfit)) {
1108 land_errDialogueBuild(_("You can't sell a license."));
1109 failure = 1;
1110 }
1111 /* has no outfits to sell */
1112 if (!pilot_hasIntrinsic(player.p,outfit) && (player_outfitOwned(outfit) <= 0)) {
1113 land_errDialogueBuild( _("You can't sell something you don't have!") );
1114 failure = 1;
1115 }
1116 /* Custom condition failed. */
1117 if (!cansell) {
1118 land_errDialogueBuild(_("You are unable to sell this outfit!"));
1119 failure = 1;
1120 }
1121
1122 return !failure;
1123}
1129static void outfits_sell( unsigned int wid, const char *str )
1130{
1131 (void)str;
1132 int i, active;
1133 Outfit* outfit;
1134 int q;
1135 HookParam hparam[3];
1136
1137 active = window_tabWinGetActive( wid, OUTFITS_TAB );
1138 i = toolkit_getImageArrayPos( wid, OUTFITS_IAR );
1139 if (i < 0 || array_size(iar_outfits[active]) == 0)
1140 return;
1141
1142 outfit = iar_outfits[active][i];
1143
1144 q = outfits_getMod();
1145
1146 /* Check various failure conditions. */
1147 if (!outfit_canSell( outfit )) {
1149 return;
1150 }
1151
1152 /* Try Lua. */
1153 if (outfit->lua_sell != LUA_NOREF) {
1154 lua_rawgeti(naevL, LUA_REGISTRYINDEX, outfit->lua_sell);
1155 lua_pushinteger(naevL, q);
1156 if (nlua_pcall( outfit->lua_env, 1, 2 )) { /* */
1157 WARN(_("Outfit '%s' failed to run '%s':\n%s"),outfit->name,"price",lua_tostring(naevL,-1));
1158 lua_pop(naevL, 1);
1159 }
1160
1161 int bought = lua_toboolean(naevL,-2);
1162
1163 if (!bought) {
1164 dialogue_alert( "%s", lua_tostring(naevL,-1) );
1165 lua_pop(naevL, 2);
1166 return;
1167 }
1168 q = luaL_checkinteger(naevL,-1);
1169
1170 lua_pop(naevL, 2);
1171 }
1172 else {
1173 q = player_rmOutfit( outfit, q );
1174 player_modCredits( outfit->price * q );
1175 }
1176
1178 hparam[0].type = HOOK_PARAM_OUTFIT;
1179 hparam[0].u.outfit= outfit;
1180 hparam[1].type = HOOK_PARAM_NUMBER;
1181 hparam[1].u.num = q;
1182 hparam[2].type = HOOK_PARAM_SENTINEL;
1183 hooks_runParam( "outfit_sell", hparam );
1184 land_needsTakeoff( 1 );
1185
1186 /* Update sold outfits list. */
1187 if (!outfit_isSold( outfit, wid )) {
1188 int found = 0;
1189 if (outfits_sold==NULL)
1191 for (int j=0; j<array_size(outfits_sold); j++) {
1192 PlayerOutfit_t *poi = &outfits_sold[j];
1193 if (poi->o == outfit ) {
1194 poi->q += q;
1195 found = 1;
1196 break;
1197 }
1198 }
1199 if (!found) {
1200 PlayerOutfit_t po = {
1201 .o = outfit,
1202 .q = q,
1203 };
1205 }
1206 }
1207
1208 /* Regenerate list. */
1209 outfits_regenList( wid, NULL );
1210}
1215static int outfits_getMod (void)
1216{
1217 SDL_Keymod mods = SDL_GetModState();
1218 int q = 1;
1219 if (mods & (KMOD_LCTRL | KMOD_RCTRL))
1220 q *= 5;
1221 if (mods & (KMOD_LSHIFT | KMOD_RSHIFT))
1222 q *= 10;
1223 return q;
1224}
1225
1230{
1231 /* Free stored positions. */
1232 for (int i=0; i<OUTFITS_NTABS; i++)
1233 array_free( iar_outfits[i] );
1234 memset( iar_outfits, 0, sizeof(Outfit**) * OUTFITS_NTABS );
1235}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:158
#define array_copy(basic_type, ptr_array)
Returns a shallow copy of the input array.
Definition array.h:218
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:168
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition array.h:129
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
void col_blend(glColour *blend, const glColour *fg, const glColour *bg, float alpha)
Blends two colours.
Definition colour.c:192
void credits2str(char *str, credits_t credits, int decimals)
Converts credits to a usable string for displaying.
Definition commodity.c:59
void tonnes2str(char *str, int tonnes)
Converts tonnes to a usable string for displaying.
Definition commodity.c:108
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:89
int cond_check(const char *cond)
Checks to see if a condition is true.
Definition cond.c:98
void dialogue_alert(const char *fmt,...)
Displays an alert popup with only an ok button and a message.
Definition dialogue.c:132
int dialogue_YesNo(const char *caption, const char *fmt,...)
Runs a dialogue with both yes and no options.
Definition dialogue.c:352
void equipment_regenLists(unsigned int wid, int outfits, int ships)
Regenerates the equipment window lists.
Definition equipment.c:1261
void equipment_addAmmo(void)
Adds all the ammo it can to the player.
Definition equipment.c:1400
int gl_printHeightRaw(const glFont *ft_font, const int width, const char *text)
Gets the height of a non-formatted string.
Definition font.c:1027
glFont gl_defFont
Definition font.c:153
int hooks_runParam(const char *stack, const HookParam *param)
Runs all the hooks of stack.
Definition hook.c:979
unsigned int land_getWid(int window)
Gets the WID of a window by type.
Definition land.c:889
int landed
Definition land.c:75
int land_doneLoading(void)
Check to see if finished loading.
Definition land.c:189
void land_errDialogueBuild(const char *fmt,...)
Generates error dialogues used by several landing tabs.
Definition land.c:208
Spob * land_spob
Definition land.c:83
void land_errClear(void)
Clear error dialogues.
Definition land.c:199
void land_buttonTakeoff(unsigned int wid, const char *unused)
Wrapper for takeoff mission button.
Definition land.c:851
int land_errDisplay(void)
Displays an error if applicable.
Definition land.c:228
static void outfits_sell(unsigned int wid, const char *str)
Attempts to sell the selected outfit the player has.
static int outfits_getMod(void)
Gets the current modifier status.
int outfit_altText(char *buf, int n, const Outfit *o, const Pilot *plt)
Computes the alt text for an outfit.
static void outfits_onClose(unsigned int wid, const char *str)
For when the widget closes.
static void outfits_genList(unsigned int wid)
Generates the outfit list.
static int outfitLand_filter(const Outfit *o)
void outfits_regenList(unsigned int wid, const char *str)
Regenerates the outfit list.
static void outfits_find(unsigned int wid, const char *str)
Starts the map find with outfit search selected.
static void outfits_getSize(unsigned int wid, int *w, int *h, int *iw, int *ih, int *bw, int *bh)
Gets the size of the outfits window.
int outfit_canBuy(const Outfit *outfit, int wid)
Checks to see if the player can buy the outfit.
void outfits_cleanup(void)
Cleans up outfit globals.
ImageArrayCell * outfits_imageArrayCells(const Outfit **outfits, int *noutfits, const Pilot *p, int store)
Generates image array cells corresponding to outfits.
static int outfit_events(unsigned int wid, SDL_Event *evt)
void outfits_open(unsigned int wid, const Outfit **outfits, int blackmarket)
Opens the outfit exchange center window.
static iar_data_t iar_data[OUTFITS_NTABS]
static Outfit ** iar_outfits[OUTFITS_NTABS]
void outfits_updateEquipmentOutfits(void)
Updates the outfitter and equipment outfit image arrays.
static void outfits_buy(unsigned int wid, const char *str)
Attempts to buy the outfit that is selected.
void outfits_update(unsigned int wid, const char *str)
Updates the outfits in the outfit window.
static int outfit_Mode
static PlayerOutfit_t * outfits_sold
int outfits_filter(const Outfit **outfits, int n, int(*filter)(const Outfit *), const char *name)
Applies a filter function and string to a list of outfits.
static void outfit_PopdownSelect(unsigned int wid, const char *str)
int outfit_canSell(const Outfit *outfit)
Checks to see if the player can sell the selected outfit.
static const char * outfit_getPrice(const Outfit *outfit, credits_t *price, int *canbuy, int *cansell)
Returns the price of an outfit (subject to quantity modifier)
static void outfits_rmouse(unsigned int wid, const char *widget_name)
Player right-clicks on an outfit.
static void outfits_changeTab(unsigned int wid, const char *wgt, int old, int tab)
Ensures the tab's selected item is reflected in the ship slot list.
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:40
#define CLAMP(a, b, x)
Definition naev.h:41
#define MAX(x, y)
Definition naev.h:39
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:99
glTexture * gl_dupTexture(const glTexture *texture)
Duplicates a texture.
Definition opengl_tex.c:917
glTexture ** gl_addTexArray(glTexture **tex, glTexture *t)
Adds an element to a texture array.
glTexture ** gl_copyTexArray(glTexture **tex)
Copy a texture array.
const Outfit * outfit_get(const char *name)
Gets an outfit by name.
Definition outfit.c:166
int outfit_isLauncher(const Outfit *o)
Checks if outfit is a weapon launcher.
Definition outfit.c:564
int outfit_isLocalMap(const Outfit *o)
Checks if outfit is a local space map.
Definition outfit.c:634
int outfit_compareTech(const void *outfit1, const void *outfit2)
Function meant for use with C89, C99 algorithm qsort().
Definition outfit.c:243
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:444
int outfit_fitsSlot(const Outfit *o, const OutfitSlot *s)
Checks to see if an outfit fits a slot.
Definition outfit.c:1047
int outfit_isFighterBay(const Outfit *o)
Checks if outfit is a fighter bay.
Definition outfit.c:616
int outfit_isMap(const Outfit *o)
Checks if outfit is a space map.
Definition outfit.c:625
int outfit_isLicense(const Outfit *o)
Checks if outfit is a license.
Definition outfit.c:643
int outfit_amount(const Outfit *o)
Gets the amount an outfit can hold.
Definition outfit.c:746
const char * outfit_getType(const Outfit *o)
Gets the outfit's specific type.
Definition outfit.c:945
int outfit_isGUI(const Outfit *o)
Checks if outfit is a GUI.
Definition outfit.c:652
const char * outfit_slotName(const Outfit *o)
Gets the name of the slot type of an outfit.
Definition outfit.c:327
glTexture * rarity_texture(int rarity)
Definition outfit.c:3035
const glColour * outfit_slotSizeColour(const OutfitSlot *os)
Gets the slot size colour for an outfit slot.
Definition outfit.c:391
int pilot_hasOutfitLimit(const Pilot *p, const char *limit)
Checks to see if a pilot has an outfit with a specific outfit type.
int pilot_hasIntrinsic(const Pilot *pilot, const Outfit *outfit)
Gets how many copies of an intrinsic a pilot has.
const char * pilot_outfitSummary(const Pilot *p, const Outfit *o, int withname)
Gets the summary of an outfit for a give pilot.
int player_rmOutfit(const Outfit *o, int quantity)
Remove an outfit from the player's outfit stack.
Definition player.c:2890
int player_hasLicense(const char *license)
Checks to see if player has license.
Definition player.c:3039
int player_addOutfit(const Outfit *o, int quantity)
Adds an outfit to the player outfit stack.
Definition player.c:2828
const PlayerShip_t * player_getShipStack(void)
Gets the array (array.h) of the player's ships.
Definition player.c:2644
int player_outfitOwnedTotal(const Outfit *o)
Definition player.c:2754
credits_t player_modCredits(credits_t amount)
Modifies the amount of credits the player has.
Definition player.c:975
Player_t player
Definition player.c:74
int player_hasCredits(credits_t amount)
Checks to see if the player has enough credits.
Definition player.c:964
int player_outfitOwned(const Outfit *o)
Gets how many of the outfit the player owns.
Definition player.c:2722
const PlayerOutfit_t * player_getOutfits(void)
Gets an array (array.h) of the player's outfits.
Definition player.c:2782
int player_guiCheck(const char *name)
Check if player has a GUI.
Definition player_gui.c:88
static const double c[]
Definition rng.c:264
const glTexture * sp_icon(unsigned int spid)
Gets the icon associated with the slot.
Definition slots.c:209
const char * sp_display(unsigned int spid)
Gets the display name of a slot property (in English).
Definition slots.c:159
The actual hook parameter.
Definition hook.h:38
HookParamType type
Definition hook.h:39
union HookParam::@25 u
const Outfit * outfit
Definition hook.h:46
double num
Definition hook.h:41
Data for handling the widget.
const Outfit ** outfits
char * gui
Definition outfit.h:315
char * provides
Definition outfit.h:322
OutfitSlotSize size
Definition outfit.h:113
unsigned int spid
Definition outfit.h:110
OutfitSlotType type
Definition outfit.h:112
A ship outfit, depends radically on the type.
Definition outfit.h:328
credits_t price
Definition outfit.h:347
char * limit
Definition outfit.h:342
char * cond
Definition outfit.h:338
OutfitLauncherData lau
Definition outfit.h:406
char * desc_raw
Definition outfit.h:348
int lua_buy
Definition outfit.h:398
glTexture * gfx_store
Definition outfit.h:353
int rarity
Definition outfit.h:332
int lua_price
Definition outfit.h:397
OutfitGUIData gui
Definition outfit.h:412
char * condstr
Definition outfit.h:339
union Outfit::@12 u
OutfitSlot slot
Definition outfit.h:336
OutfitFighterBayData bay
Definition outfit.h:409
int lua_sell
Definition outfit.h:399
nlua_env lua_env
Definition outfit.h:371
char * license
Definition outfit.h:337
glTexture ** gfx_overlays
Definition outfit.h:354
double mass
Definition outfit.h:340
char * name
Definition outfit.h:329
OutfitLicenseData lic
Definition outfit.h:413
The representation of an in-game pilot.
Definition pilot.h:217
credits_t credits
Definition pilot.h:325
char * name
Definition pilot.h:219
int big_icons
Definition conf.h:125
Wrapper for outfits.
Definition player.h:65
const Outfit * o
Definition player.h:66
Player ship.
Definition player.h:73
Pilot * p
Definition player.h:74
Pilot * p
Definition player.h:101
tech_group_t * tech
Definition space.h:118
int h
Definition font.h:18
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:36
int tech_checkOutfit(const tech_group_t *tech, const Outfit *o)
Checks to see if there is an outfit in the tech group.
Definition tech.c:869
Outfit ** tech_getOutfit(const tech_group_t *tech)
Gets all of the outfits associated to a tech group.
Definition tech.c:728
void window_setOnFocus(unsigned int wid, void(*focus)(unsigned int))
Sets the focus function of the window.
Definition toolkit.c:888
void window_dimWidget(unsigned int wid, const char *name, int *w, int *h)
Gets the dimensions of a widget.
Definition toolkit.c:416
void window_setFocus(unsigned int wid, const char *wgtname)
Sets the focused widget in a window.
Definition toolkit.c:2471
void window_setAccept(unsigned int wid, void(*accept)(unsigned int, const char *))
Sets the default accept function of the window.
Definition toolkit.c:847
void window_dimWindow(unsigned int wid, int *w, int *h)
Gets the dimensions of a window.
Definition toolkit.c:371
void window_onClose(unsigned int wid, void(*fptr)(unsigned int, const char *))
Sets the default close function of the window.
Definition toolkit.c:826
void window_moveWidget(unsigned int wid, const char *name, int x, int y)
Moves a widget.
Definition toolkit.c:465
void window_posWidget(unsigned int wid, const char *name, int *x, int *y)
Gets a widget's position.
Definition toolkit.c:442
void window_destroyWidget(unsigned int wid, const char *wgtname)
Destroys a widget in a window.
Definition toolkit.c:1165
void toolkit_rerender(void)
Marks the toolkit for needing a full rerender.
Definition toolkit.c:1661
void * window_getData(unsigned int wid)
Gets the custom data of a window.
Definition toolkit.c:922
void window_setData(unsigned int wid, void *data)
Sets custom data for a window.
Definition toolkit.c:905
int widget_exists(unsigned int wid, const char *wgtname)
Checks to see if a widget exists.
Definition toolkit.c:1142
void window_close(unsigned int wid, const char *str)
Helper function to automatically close the window calling it.
Definition toolkit.c:1026
char * window_getFocus(unsigned int wid)
Gets the focused widget in a window (does strdup!!).
Definition toolkit.c:2497
void window_handleEvents(unsigned int wid, int(*eventhandler)(unsigned int, SDL_Event *))
Sets the event handler for the window.
Definition toolkit.c:977