naev 0.11.5
land_shipyard.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <assert.h>
11#include <math.h>
12#include <stdio.h>
13#include <stdlib.h>
14
15#include "naev.h"
18#include "land_shipyard.h"
19
20#include "array.h"
21#include "cond.h"
22#include "dialogue.h"
23#include "hook.h"
24#include "log.h"
25#include "map_find.h"
26#include "ndata.h"
27#include "nstring.h"
28#include "player.h"
29#include "player_fleet.h"
30#include "space.h"
31#include "slots.h"
32#include "tk/toolkit_priv.h"
33#include "toolkit.h"
34
35#define SHIP_GFX_W 256
36#define SHIP_GFX_H 256
37
41typedef struct CstShipSlotWidget_ {
42 int mouseover;
43 const ShipOutfitSlot *slot;
44 double altx;
45 double alty;
47
48/*
49 * Vars.
50 */
51static Ship **shipyard_list = NULL;
52static Ship* shipyard_selected = NULL;
53static glTexture *shipyard_comm = NULL;
55/*
56 * Helper functions.
57 */
58static int shipyard_canAcquire( const Ship *ship, const Spob *spob, credits_t price );
59static void shipyard_buy( unsigned int wid, const char* str );
60static void shipyard_trade( unsigned int wid, const char* str );
61static void shipyard_rmouse( unsigned int wid, const char* widget_name );
62static void shipyard_renderSlots( double bx, double by, double bw, double bh, void *data );
63static void shipyard_renderSlotsRow( double bx, double by, double bw, const char *str, ShipOutfitSlot *s );
64static int shipyard_mouseSlots( unsigned int wid, const SDL_Event* event,
65 double x, double y, double w, double h, double rx, double ry, void *data );
66static void shipyard_renderSlotsOver( double bx, double by, double bw, double bh, void *data );
67static void shipyard_find( unsigned int wid, const char* str );
68
72void shipyard_open( unsigned int wid )
73{
74 ImageArrayCell *cships;
75 int nships;
76 int w, h, sw, sh;
77 int iw, ih;
78 int bw, bh, padding, off;
79 int iconsize;
81
82 /* Mark as generated. */
83 land_tabGenerate(LAND_WINDOW_SHIPYARD);
84
85 /* Init vars. */
87
88 /* Get window dimensions. */
89 window_dimWindow( wid, &w, &h );
90
91 /* Calculate image array dimensions. */
92 iw = 440 + (w - LAND_WIDTH);
93 ih = h - 60;
94
95 /* Ship image dimensions. */
96 sw = SHIP_GFX_W;
97 sh = SHIP_GFX_H;
98
99 /* Left padding + per-button padding * nbuttons */
100 padding = 40 + 20 * 4;
101
102 /* Calculate button dimensions. */
103 bw = (w - iw - padding) / 4;
104 bh = LAND_BUTTON_HEIGHT;
105
106 /* buttons */
107 off = -20;
108 window_addButtonKey( wid, off, 20,
109 bw, bh, "btnCloseShipyard",
110 _("Take Off"), land_buttonTakeoff, SDLK_t );
111 off -= 20+bw;
112 window_addButtonKey( wid, off, 20,
113 bw, bh, "btnTradeShip",
114 _("Trade-In"), shipyard_trade, SDLK_r );
115 off -= 20+bw;
116 window_addButtonKey( wid, off, 20,
117 bw, bh, "btnBuyShip",
118 _("Buy"), shipyard_buy, SDLK_b );
119 off -= 20+bw;
120 window_addButtonKey( wid, off, 20,
121 bw, bh, "btnFindShips",
122 _("Find Ships"), shipyard_find, SDLK_f );
123
124 /* target gfx */
125 window_addRect( wid, -40+4, -40+4, sw+8, sh+8, "rctTarget", &cBlack, 1 );
126 window_addImage( wid, -40, -40, sw, sh, "imgTarget", NULL, 0);
127
128 /* slot types */
129 data = calloc( 1, sizeof(CstShipSlotWidget) );
130 window_addCust( wid, -20, -sh-50, sw-10, 80, "cstSlots", 0.,
131 shipyard_renderSlots, shipyard_mouseSlots, NULL, NULL, data );
132 window_custSetOverlay( wid, "cstSlots", shipyard_renderSlotsOver );
133 window_custSetClipping( wid, "cstSlots", 0 );
134 window_canFocusWidget( wid, "cstSlots", 0 );
135 window_custAutoFreeData( wid, "cstSlots" );
136
137 /* stat text */
138 window_addText( wid, -4, -sw-50-70-20, sw, -sh-60-70-20+h-bh, 0, "txtStats",
139 &gl_smallFont, NULL, NULL );
140
141 /* Placeholder text-boxes, calculated properly in shipyard_update(). */
142 window_addText( wid, iw+40, -35, 133, 427, 0, "txtSDesc", &gl_defFont, &cFontGrey, NULL );
143 window_addText( wid, iw+173, -35, w-sw-iw-208, 427, 0, "txtDDesc", &gl_defFont, NULL, NULL );
144 window_addText( wid, 20+iw+20, -462, w-(iw+40) - (sw+40), -482+h-bh, 0, "txtDescription", &gl_defFont, NULL, NULL );
145
146 /* set up the ships to buy/sell */
148 nships = array_size( shipyard_list );
149 cships = calloc( MAX(1,nships), sizeof(ImageArrayCell) );
150 if (nships <= 0) {
151 cships[0].image = NULL;
152 cships[0].caption = strdup(_("None"));
153 nships = 1;
154 }
155 else {
156 for (int i=0; i<nships; i++) {
157 cships[i].caption = strdup( _(shipyard_list[i]->name) );
158 cships[i].image = gl_dupTexture(shipyard_list[i]->gfx_store);
159 cships[i].layers = gl_copyTexArray( shipyard_list[i]->gfx_overlays );
160 if (shipyard_list[i]->rarity > 0) {
161 glTexture *t = rarity_texture( shipyard_list[i]->rarity );
162 cships[i].layers = gl_addTexArray( cships[i].layers, t );
163 }
164 }
165 }
166
167 iconsize = 128;
168 if (!conf.big_icons) {
169 if (toolkit_simImageArrayVisibleElements(iw,ih,iconsize,iconsize) < nships)
170 iconsize = 96;
171 /*
172 if (toolkit_simImageArrayVisibleElements(iw,ih,iconsize,iconsize) < nships)
173 iconsize = 64;
174 */
175 }
176 window_addImageArray( wid, 20, 20,
177 iw, ih, "iarShipyard", iconsize, iconsize,
178 cships, nships, shipyard_update, shipyard_rmouse, NULL );
179
180 /* write the shipyard stuff */
181 shipyard_update(wid, NULL);
182 /* Set default keyboard focuse to the list */
183 window_setFocus( wid , "iarShipyard" );
184}
190void shipyard_update( unsigned int wid, const char* str )
191{
192 (void)str;
193 int i, tw, th, y, w, h, sw, iw, bh;
194 Ship* ship;
195 char lbl[STRMAX], buf[STRMAX], buf_price[ECON_CRED_STRLEN], buf_credits[ECON_CRED_STRLEN];
196 double aspect, gw, gh;
197 size_t k = 0, l = 0;
198 int blackmarket = ((land_spob!=NULL) && spob_hasService( land_spob, SPOB_SERVICE_BLACKMARKET ));
199
200 i = toolkit_getImageArrayPos( wid, "iarShipyard" );
201
202 /* No ships */
203 if (i < 0 || array_size(shipyard_list) == 0) {
205 shipyard_comm = NULL;
206 window_modifyImage( wid, "imgTarget", NULL, 0, 0 );
207 window_disableButton( wid, "btnBuyShip");
208 window_disableButton( wid, "btnTradeShip");
209 window_modifyImage( wid, "imgTarget", NULL, 0, 0 );
210 window_modifyText( wid, "txtStats", NULL );
211 window_modifyText( wid, "txtDescription", NULL );
212 window_modifyText( wid, "txtSDesc", NULL );
213 window_modifyText( wid, "txtDDesc", NULL );
214 return;
215 }
216
217 ship = shipyard_list[i];
218 shipyard_selected = ship;
219
220 /* update image */
222 shipyard_comm = NULL;
224 aspect = shipyard_comm->w / shipyard_comm->h;
225 gw = MIN( shipyard_comm->w, SHIP_GFX_W );
226 gh = MIN( shipyard_comm->h, SHIP_GFX_H );
227 if (aspect > 1.)
228 gh /= aspect;
229 else
230 gw /= aspect;
231 window_destroyWidget( wid, "imgTarget" );
232 window_addImage( wid, -40-(SHIP_GFX_W-gw)/2, -30-(SHIP_GFX_H-gh)/2, gw, gh, "imgTarget", NULL, 0 );
233 window_modifyImage( wid, "imgTarget", shipyard_comm, gw, gh );
234
235 /* update text */
236 window_modifyText( wid, "txtStats", ship->desc_stats );
237 price2str( buf_price, ship_buyPrice(ship), player.p->credits, 2 );
238 credits2str( buf_credits, player.p->credits, 2 );
239
240 k += scnprintf( &lbl[k], sizeof(lbl)-k, "%s", _("Model:") );
241 l += scnprintf( &buf[l], sizeof(buf)-l, "%s", _(ship->name) );
242 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Class:") );
243 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s", _(ship_classDisplay(ship)) );
244 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Fabricator:") );
245 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s", _(ship->fabricator) );
246 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Crew:") );
247 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%d", ship->crew );
248 if (player.fleet_capacity > 0) {
249 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Fleet Capacity:") );
250 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%d", ship->points );
251 }
252 /* Weapons & Manoeuvrability */
253 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n\n%s", _("Base Properties") );
254 l += scnprintf( &buf[l], sizeof(buf)-l, "\n\n%s", "");
255 if (ship->cpu > 0) {
256 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("CPU:") );
257 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%.0f %s", ship->cpu, UNIT_CPU );
258 }
259 if (ship->mass) {
260 char buf_mass[ECON_MASS_STRLEN];
261 tonnes2str( buf_mass, ship->mass );
262 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Mass:") );
263 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s", buf_mass );
264 }
265 if (ship->accel) {
266 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Accel:") );
267 l += scnprintf( &buf[l], sizeof(buf)-l, "\n");
268 l += scnprintf( &buf[l], sizeof(buf)-l, _("%.0f %s"), ship->accel, UNIT_ACCEL );
269 }
270 if (ship->speed) {
271 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Speed:") );
272 l += scnprintf( &buf[l], sizeof(buf)-l, "\n" );
273 l += scnprintf( &buf[l], sizeof(buf)-l, _("%.0f %s"), ship->speed, UNIT_SPEED );
274 }
275 if (ship->turn) {
276 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Turn:") );
277 l += scnprintf( &buf[l], sizeof(buf)-l, "\n" );
278 l += scnprintf( &buf[l], sizeof(buf)-l, _("%.0f %s"), ship->turn*180/M_PI, UNIT_ROTATION );
279 }
280 if (ship->dt_default != 1.) {
281 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Time Constant:") );
282 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%.0f%%", ship->dt_default*100. );
283 }
284 /* Misc */
285 if (ship->dmg_absorb) {
286 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Absorption:") );
287 l += scnprintf( &buf[l], sizeof(buf)-l, "\n" );
288 l += scnprintf( &buf[l], sizeof(buf)-l, _("%.0f%% damage"), ship->dmg_absorb*100. );
289 }
290 if (ship->shield || ship->shield_regen) {
291 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Shield:") );
292 l += scnprintf( &buf[l], sizeof(buf)-l, "\n" );
293 l += scnprintf( &buf[l], sizeof(buf)-l, _("%.0f %s (%.1f %s)"), ship->shield, UNIT_ENERGY, ship->shield_regen, UNIT_POWER );
294 }
295 if (ship->armour || ship->armour_regen) {
296 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Armour:") );
297 l += scnprintf( &buf[l], sizeof(buf)-l, "\n" );
298 l += scnprintf( &buf[l], sizeof(buf)-l, _("%.0f %s (%.1f %s)"), ship->armour, UNIT_ENERGY, ship->armour_regen, UNIT_POWER );
299 }
300 if (ship->energy || ship->energy_regen) {
301 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Energy:") );
302 l += scnprintf( &buf[l], sizeof(buf)-l, "\n" );
303 l += scnprintf( &buf[l], sizeof(buf)-l, _("%.0f %s (%.1f %s)"), ship->energy, UNIT_ENERGY, ship->energy_regen, UNIT_POWER );
304 }
305 if (ship->cap_cargo) {
306 char buf_cargo[ECON_MASS_STRLEN];
307 tonnes2str( buf_cargo, ship->cap_cargo );
308 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Cargo Space:") );
309 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s", buf_cargo );
310 }
311 if (ship->fuel) {
312 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Fuel:") );
313 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%d %s", ship->fuel, UNIT_UNIT );
314 }
315 if (ship->fuel_consumption != 100.) {
316 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Fuel Use:") );
317 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%d %s", ship->fuel_consumption, UNIT_UNIT );
318 }
319
320 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n\n%s", _("Price:") );
321 l += scnprintf( &buf[l], sizeof(buf)-l, "\n\n%s", buf_price );
322 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Money:") );
323 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s", buf_credits );
324 if (ship->license) {
325 int meets_reqs = player_hasLicense( ship->license );;
326 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("License:") );
327 if (blackmarket)
328 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s#0", _("Not Necessary (Blackmarket)") );
329 else
330 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s%s#0", meets_reqs ? "" : "#r", _(ship->license) );
331 }
332 if (ship->cond) {
333 int meets_reqs = 0;
334 if (land_spob != NULL)
335 meets_reqs = cond_check(ship->cond);
336 k += scnprintf( &lbl[k], sizeof(lbl)-k, "\n%s", _("Requires:") );
337 if (blackmarket)
338 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s#0", _("Not Necessary (Blackmarket)") );
339 else
340 l += scnprintf( &buf[l], sizeof(buf)-l, "\n%s%s#0", meets_reqs ? "" : "#r", _(ship->condstr) );
341 }
342
343 /* Calculate layout. */
344 window_dimWindow( wid, &w, &h );
345 iw = 440 + (w - LAND_WIDTH);
346 sw = SHIP_GFX_W;
347 bh = LAND_BUTTON_HEIGHT;
348 tw = gl_printWidthRaw( &gl_defFont, lbl );
349 th = gl_printHeightRaw( &gl_defFont, tw, lbl ) + gl_defFont.h;
350 y = -35;
351 window_modifyText( wid, "txtSDesc", lbl );
352 window_resizeWidget( wid, "txtSDesc", tw+20, th );
353 window_moveWidget( wid, "txtSDesc", 20+iw+20, y );
354 window_modifyText( wid, "txtDDesc", buf );
355 window_resizeWidget( wid, "txtDDesc", w-sw-40-(20+iw+20+128), th );
356 window_moveWidget( wid, "txtDDesc", 20+iw+20+tw+20, y );
357 y = MIN( y-th, -40-SHIP_GFX_H-20 );
358 if (ship->desc_extra) {
359 scnprintf( &buf[0], sizeof(buf), "%s\n%s", _(ship->description), _(ship->desc_extra) );
360 window_modifyText( wid, "txtDescription", buf );
361 }
362 else
363 window_modifyText( wid, "txtDescription", _(ship->description) );
364 window_resizeWidget( wid, "txtDescription", w-(20+iw+20) - (sw+40), y-20+h-bh );
365 window_moveWidget( wid, "txtDescription", 20+iw+20, y );
366
367 if (!shipyard_canBuy( ship, land_spob ))
368 window_disableButtonSoft( wid, "btnBuyShip");
369 else
370 window_enableButton( wid, "btnBuyShip");
371
372 if (!shipyard_canTrade( ship, land_spob ))
373 window_disableButtonSoft( wid, "btnTradeShip");
374 else
375 window_enableButton( wid, "btnTradeShip");
376}
377
382{
384 shipyard_list = NULL;
385 shipyard_selected = NULL;
387 shipyard_comm = NULL;
388}
389
395static void shipyard_find( unsigned int wid, const char* str )
396{
397 (void) str;
398 map_inputFindType(wid, "ship");
399}
400
406static void shipyard_rmouse( unsigned int wid, const char* widget_name )
407{
408 shipyard_buy(wid, widget_name);
409}
410
416static void shipyard_buy( unsigned int wid, const char* str )
417{
418 (void)str;
419 int i;
420 char buf[STRMAX_SHORT];
421 Ship* ship;
422 HookParam hparam[2];
423
424 i = toolkit_getImageArrayPos( wid, "iarShipyard" );
425 if (i < 0 || array_size(shipyard_list) == 0)
426 return;
427
428 ship = shipyard_list[i];
429
430 credits_t targetprice = ship_buyPrice(ship);
431
432 if (!shipyard_canBuy( ship, land_spob )) {
434 return;
435 }
436
437 credits2str( buf, targetprice, 2 );
438 if (dialogue_YesNo(_("Are you sure?"), /* confirm */
439 _("Do you really want to spend %s on a new ship?"), buf )==0)
440 return;
441
442 /* Player just got a new ship */
443 snprintf( buf, sizeof(buf), _("Bought at %s in the %s system."), spob_name(land_spob), _(cur_system->name) );
444 if (player_newShip( ship, NULL, 0, buf, 0 ) == NULL) {
445 /* Player actually aborted naming process. */
446 return;
447 }
448 player_modCredits( -targetprice ); /* ouch, paying is hard */
449
450 /* Update shipyard. */
451 shipyard_update(wid, NULL);
452
453 /* Run hook. */
454 hparam[0].type = HOOK_PARAM_SHIP;
455 hparam[0].u.ship = ship;
456 hparam[1].type = HOOK_PARAM_SENTINEL;
457 hooks_runParam( "ship_buy", hparam );
458 land_needsTakeoff( 1 );
459}
460
461static int shipyard_canAcquire( const Ship *ship, const Spob *spob, credits_t price )
462{
463 int failure = 0;
464 int blackmarket = ((spob != NULL) && spob_hasService(spob, SPOB_SERVICE_BLACKMARKET));
466
467 /* Must have the necessary license. */
468 if (!blackmarket && !player_hasLicense(ship->license)) {
469 land_errDialogueBuild( _("You need the '%s' license to buy this ship."), _(ship->license) );
470 failure = 1;
471 }
472
473 /* Must meet conditional requirement. */
474 if (!blackmarket && (ship->cond!=NULL) && !cond_check( ship->cond )) {
475 land_errDialogueBuild( "%s", _(ship->condstr) );
476 failure = 1;
477 }
478
479 /* Must have enough credits. */
480 if (!player_hasCredits( price )) {
481 char buf[ECON_CRED_STRLEN];
482 credits2str( buf, price - player.p->credits, 2 );
483 land_errDialogueBuild( _("You need %s more."), buf);
484 failure = 1;
485 }
486 return !failure;
487}
488
494int shipyard_canBuy( const Ship *ship, const Spob *spob )
495{
496 credits_t price = ship_buyPrice(ship);
497 return shipyard_canAcquire( ship, spob, price );
498}
499
505int shipyard_canTrade( const Ship *ship, const Spob *spob )
506{
507 credits_t price = ship_buyPrice(ship) - player_shipPrice(player.p->name,0);
509
511 land_errDialogueBuild( _("You can not trade in your ship when you have mission cargo!") );
512 return 0;
513 }
514 return shipyard_canAcquire( ship, spob, price );
515}
516
522static void shipyard_trade( unsigned int wid, const char* str )
523{
524 (void)str;
525 int i;
526 char buf[STRMAX_SHORT], buf2[ECON_CRED_STRLEN],
527 buf3[ECON_CRED_STRLEN], buf4[ECON_CRED_STRLEN];
528 Ship* ship;
529
530 i = toolkit_getImageArrayPos( wid, "iarShipyard" );
531 if (i < 0 || shipyard_list == NULL)
532 return;
533
534 ship = shipyard_list[i];
535
536 credits_t targetprice = ship_buyPrice(ship);
537 credits_t playerprice = player_shipPrice(player.p->name,0);
538
539 if (!shipyard_canTrade( ship, land_spob )) {
541 return;
542 }
543
544 credits2str( buf, targetprice, 2 );
545 credits2str( buf2, playerprice, 2 );
546 credits2str( buf3, targetprice - playerprice, 2 );
547 credits2str( buf4, playerprice - targetprice, 2 );
548
549 /* Display the correct dialogue depending on the new ship's price versus the player's. */
550 if ( targetprice == playerprice ) {
551 if (dialogue_YesNo(_("Are you sure?"), /* confirm */
552 _("Your %s is worth %s, exactly as much as the new ship, so no credits need be exchanged. Are you sure you want to trade your ship in?"),
553 _(player.p->ship->name), buf2)==0)
554 return;
555 }
556 else if ( targetprice < playerprice ) {
557 if (dialogue_YesNo(_("Are you sure?"), /* confirm */
558 _("Your %s is worth %s, more than the new ship. For your ship, you will get the new %s and %s. Are you sure you want to trade your ship in?"),
559 _(player.p->ship->name), buf2, _(ship->name), buf4)==0)
560 return;
561 }
562 else if ( targetprice > playerprice ) {
563 if (dialogue_YesNo(_("Are you sure?"), /* confirm */
564 _("Your %s is worth %s, so the new ship will cost %s. Are you sure you want to trade your ship in?"),
565 _(player.p->ship->name), buf2, buf3)==0)
566 return;
567 }
568
569 /* player just got a new ship */
570 snprintf( buf, sizeof(buf), _("Bought at %s in the %s system."), spob_name(land_spob), _(cur_system->name) );
571 if (player_newShip( ship, NULL, 1, buf, 0 ) == NULL)
572 return; /* Player aborted the naming process. */
573
574 player_modCredits( playerprice - targetprice ); /* Modify credits by the difference between ship values. */
575
576 land_refuel();
577
578 /* The newShip call will trigger a loadGUI that will recreate the land windows. Therefore the land ID will
579 * be void. We must reload in in order to properly update it again.*/
580 wid = land_getWid(LAND_WINDOW_SHIPYARD);
581
582 /* Update shipyard. */
583 shipyard_update(wid, NULL);
584}
585
589static void shipyard_renderSlots( double bx, double by, double bw, double bh, void *data )
590{
591 (void) data;
592 double y, w;
593 Ship *ship;
594
595 /* Make sure a valid ship is selected. */
596 ship = shipyard_selected;
597 if (ship == NULL)
598 return;
599
600 y = by + bh;
601
602 /* Draw rotated text. */
603 y -= 10+5;
604 gl_print( &gl_smallFont, bx, y, &cFontWhite, _("Slots:") );
605
606 w = bw - 10.;
607
608 /* Weapon slots. */
609 y -= 20;
610 shipyard_renderSlotsRow( bx, y, w, _(OUTFIT_LABEL_WEAPON), ship->outfit_weapon );
611
612 /* Utility slots. */
613 y -= 20;
614 shipyard_renderSlotsRow( bx, y, w, _(OUTFIT_LABEL_UTILITY), ship->outfit_utility );
615
616 /* Structure slots. */
617 y -= 20;
618 shipyard_renderSlotsRow( bx, y, w, _(OUTFIT_LABEL_STRUCTURE), ship->outfit_structure );
619}
620
624static void shipyard_renderSlotsRow( double bx, double by, double bw, const char *str, ShipOutfitSlot *s )
625{
626 (void) bw;
627 double x;
628
629 /* Print text. */
630 gl_printMidRaw( &gl_smallFont, 40, bx, by, &cFontWhite, -1, str );
631 x = bx+30.;
632
633 /* Draw squares. */
634 for (int i=0; i<array_size(s); i++) {
635 const glColour *c;
636 const glTexture *icon;
637 const int size = 14;
638
639 /* Ignore locked slots. */
640 if (s[i].locked)
641 continue;
642
643 /* Get the colour. */
644 c = outfit_slotSizeColour( &s[i].slot );
645 if (c == NULL)
646 c = &cBlack;
647
648 x += size+7.;
649 toolkit_drawRect( x, by, size, size, c, NULL );
650
651 /* Add colour stripe depending on required/exclusiveness. */
652 if (s[i].required)
653 toolkit_drawTriangle( x, by, x+size, by+size, x, by+size, &cBrightRed );
654 else if (s[i].exclusive)
655 toolkit_drawTriangle( x, by, x+size, by+size, x, by+size, &cWhite );
656 else if (s[i].slot.spid != 0)
657 toolkit_drawTriangle( x, by, x+size, by+size, x, by+size, &cBlack );
658
659 gl_renderRectEmpty( x, by, size, size, &cBlack );
660
661 /* Draw icon if applicable. */
662 icon = sp_icon( s[i].slot.spid );
663 if (icon != NULL) {
664 double sw = 12.;
665 double sh = 12.;
666 double sx = x+6;
667 double sy = by+6;
668 if (icon->flags & OPENGL_TEX_SDF)
669 gl_renderSDF( icon, sx, sy, sw, sh, &cWhite, 0., 1. );
670 else
671 gl_renderScaleAspect( icon, sx, sy, sw, sh, NULL );
672 }
673 }
674}
675
676static int shipyard_mouseSlots( unsigned int wid, const SDL_Event *event,
677 double mx, double my, double bw, double bh,
678 double rx, double ry, void *data )
679{
680 (void) wid;
681 (void) bw;
682 (void) rx;
683 (void) ry;
684 int x = floor((mx-30.-21.) / 21.);
685 int y = floor((bh-my-15.) / 20.);
687 ShipOutfitSlot *ps;
688 Ship *ship = shipyard_selected;
689
690 /* Need a selected ship. */
691 if (ship==NULL)
692 return 0;
693
694 /* Only care about motion. */
695 if (event->type != SDL_MOUSEMOTION)
696 return 0;
697
698 /* Find what row. */
699 switch (y) {
700 case 0:
701 ps = ship->outfit_weapon;
702 break;
703 case 1:
704 ps = ship->outfit_utility;
705 break;
706 case 2:
707 ps = ship->outfit_structure;
708 break;
709
710 default:
711 wgt->mouseover = 0;
712 return 1;
713 }
714 if ((x < 0) || (x >= array_size(ps))) {
715 wgt->mouseover = 0;
716 return 1;
717 }
718
719 /* Mark the slot. */
720 wgt->mouseover = 1;
721 wgt->slot = &ps[x];
722 wgt->alty = 30. + (2-y)*20.;
723 wgt->altx = 15. + (x+2)*21.;
724 return 1;
725}
726
727static void shipyard_renderSlotsOver( double bx, double by, double bw, double bh, void *data )
728{
729 (void) bw;
730 (void) bh;
731 char alt[STRMAX_SHORT];
732 int pos;
734 const ShipOutfitSlot *slot;
735
736 if (wgt->mouseover <= 0)
737 return;
738
739 slot = wgt->slot;
740 pos = 0;
741 if (slot->slot.spid) {
742 pos = scnprintf( alt, sizeof(alt),
743 "#o%s\n", _( sp_display( slot->slot.spid ) ) );
744 }
745 else
746 pos = 0;
747 pos += scnprintf( &alt[pos], sizeof(alt)-pos, _( "#%c%s #%c%s #0slot" ),
748 outfit_slotSizeColourFont( &slot->slot ), _(slotSize( slot->slot.size )),
749 outfit_slotTypeColourFont( &slot->slot ), _(slotName( slot->slot.type )) );
750
751 /* Draw the alt stuff. */
752 toolkit_drawAltText( bx + wgt->altx, by + wgt->alty, alt );
753}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:158
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:168
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
int dialogue_YesNo(const char *caption, const char *fmt,...)
Runs a dialogue with both yes and no options.
Definition dialogue.c:352
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_smallFont
Definition font.c:154
int gl_printWidthRaw(const glFont *ft_font, const char *text)
Gets the width that it would take to print some text.
Definition font.c:961
glFont gl_defFont
Definition font.c:153
int gl_printMidRaw(const glFont *ft_font, int width, double x, double y, const glColour *c, double outlineR, const char *text)
Displays text centered in position and width.
Definition font.c:788
void gl_print(const glFont *ft_font, const double x, const double y, const glColour *c, const char *fmt,...)
Prints text on screen like printf.
Definition font.c:691
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
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
void land_refuel(void)
Refuels the player's current ship, if possible.
Definition land.c:733
int land_errDisplay(void)
Displays an error if applicable.
Definition land.c:228
static void shipyard_renderSlotsRow(double bx, double by, double bw, const char *str, ShipOutfitSlot *s)
Renders a row of ship slots.
void shipyard_open(unsigned int wid)
Opens the shipyard window.
static void shipyard_find(unsigned int wid, const char *str)
Starts the map find with ship search selected.
static glTexture * shipyard_comm
static void shipyard_rmouse(unsigned int wid, const char *widget_name)
Player right-clicks on a ship.
void shipyard_cleanup(void)
Cleans up shipyard data.
int shipyard_canBuy(const Ship *ship, const Spob *spob)
Makes sure it's valid to buy a ship.
static Ship ** shipyard_list
static void shipyard_renderSlots(double bx, double by, double bw, double bh, void *data)
Custom widget render function for the slot widget.
static void shipyard_buy(unsigned int wid, const char *str)
Player attempts to buy a ship.
void shipyard_update(unsigned int wid, const char *str)
Updates the ships in the shipyard window.
int shipyard_canTrade(const Ship *ship, const Spob *spob)
Makes sure it's valid to buy a ship, trading the old one in simultaneously.
static void shipyard_trade(unsigned int wid, const char *str)
Player attempts to buy a ship, trading the current ship in.
static Ship * shipyard_selected
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:40
#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
void gl_renderSDF(const glTexture *texture, double x, double y, double w, double h, const glColour *c, double angle, double outline)
SDF Texture blitting backend.
void gl_renderScaleAspect(const glTexture *texture, double bx, double by, double bw, double bh, const glColour *c)
Blits a texture scaling it to fit a rectangle, but conserves aspect ratio.
void gl_renderRectEmpty(double x, double y, double w, double h, const glColour *c)
Renders a rectangle.
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.
void gl_freeTexture(glTexture *texture)
Frees a texture.
Definition opengl_tex.c:862
char outfit_slotTypeColourFont(const OutfitSlot *os)
Gets a font colour character that roughly matches an outfit slot type colour.
Definition outfit.c:425
char outfit_slotSizeColourFont(const OutfitSlot *os)
Gets a font colour character that roughly matches an outfit slot size colour.
Definition outfit.c:408
const char * slotName(const OutfitSlotType type)
Definition outfit.c:335
const char * slotSize(const OutfitSlotSize o)
Gets the slot size as a string.
Definition outfit.c:358
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_cargoUsedMission(const Pilot *p)
Gets how much mission cargo ship has on board.
int player_hasLicense(const char *license)
Checks to see if player has license.
Definition player.c:3039
credits_t player_shipPrice(const char *shipname, int count_unique)
Calculates the price of one of the player's ships.
Definition player.c:667
PlayerShip_t * player_newShip(const Ship *ship, const char *def_name, int trade, const char *acquired, int noname)
Creates a new ship for player.
Definition player.c:410
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
static const double c[]
Definition rng.c:264
const char * ship_classDisplay(const Ship *s)
Gets the ship's display class in human readable form.
Definition ship.c:176
credits_t ship_buyPrice(const Ship *s)
The ship buy price, includes default outfits.
Definition ship.c:274
glTexture * ship_loadCommGFX(const Ship *s)
Loads the ship's comm graphic.
Definition ship.c:303
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
StarSystem * cur_system
Definition space.c:106
const char * spob_name(const Spob *p)
Gets the translated name of a spob.
Definition space.c:1752
The actual hook parameter.
Definition hook.h:38
HookParamType type
Definition hook.h:39
union HookParam::@25 u
const Ship * ship
Definition hook.h:45
OutfitSlotSize size
Definition outfit.h:113
unsigned int spid
Definition outfit.h:110
OutfitSlotType type
Definition outfit.h:112
credits_t credits
Definition pilot.h:325
const Ship * ship
Definition pilot.h:226
char * name
Definition pilot.h:219
int big_icons
Definition conf.h:125
Pilot * p
Definition player.h:101
int fleet_capacity
Definition player.h:126
Ship outfit slot.
Definition ship.h:70
OutfitSlot slot
Definition ship.h:71
Represents a space ship.
Definition ship.h:94
double shield_regen
Definition ship.h:130
double dt_default
Definition ship.h:124
double cap_cargo
Definition ship.h:123
char * desc_extra
Definition ship.h:110
char * license
Definition ship.h:105
char * name
Definition ship.h:95
int fuel
Definition ship.h:121
char * fabricator
Definition ship.h:108
char * description
Definition ship.h:109
double energy_regen
Definition ship.h:132
double armour
Definition ship.h:127
int fuel_consumption
Definition ship.h:122
double armour_regen
Definition ship.h:128
int crew
Definition ship.h:118
double dmg_absorb
Definition ship.h:133
char * condstr
Definition ship.h:107
char * cond
Definition ship.h:106
int points
Definition ship.h:99
double cpu
Definition ship.h:120
double speed
Definition ship.h:115
ShipOutfitSlot * outfit_utility
Definition ship.h:155
double turn
Definition ship.h:114
char * desc_stats
Definition ship.h:163
double accel
Definition ship.h:113
ShipOutfitSlot * outfit_weapon
Definition ship.h:156
double energy
Definition ship.h:131
double shield
Definition ship.h:129
double mass
Definition ship.h:119
ShipOutfitSlot * outfit_structure
Definition ship.h:154
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition space.h:89
tech_group_t * tech
Definition space.h:118
int h
Definition font.h:18
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:36
double w
Definition opengl_tex.h:40
uint8_t flags
Definition opengl_tex.h:57
double h
Definition opengl_tex.h:41
Ship ** tech_getShip(const tech_group_t *tech)
Gets all of the ships associated to a tech group.
Definition tech.c:776
void window_setFocus(unsigned int wid, const char *wgtname)
Sets the focused widget in a window.
Definition toolkit.c:2471
void window_dimWindow(unsigned int wid, int *w, int *h)
Gets the dimensions of a window.
Definition toolkit.c:371
void toolkit_drawAltText(int bx, int by, const char *alt)
Draws an alt text.
Definition toolkit.c:1429
void window_canFocusWidget(unsigned int wid, const char *name, int canfocus)
Allows or disallows focusing a widget.
Definition toolkit.c:521
void toolkit_drawRect(int x, int y, int w, int h, const glColour *c, const glColour *lc)
Draws a rectangle.
Definition toolkit.c:1343
void window_moveWidget(unsigned int wid, const char *name, int x, int y)
Moves a widget.
Definition toolkit.c:465
void toolkit_drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, const glColour *c)
Draws a rectangle.
Definition toolkit.c:1391
void window_destroyWidget(unsigned int wid, const char *wgtname)
Destroys a widget in a window.
Definition toolkit.c:1165
void window_resizeWidget(unsigned int wid, const char *name, int w, int h)
Resizes a widget.
Definition toolkit.c:493