3 #include "spritemaps.h"
11 #define GRID_START_X (0*SCALE)
12 #define GRID_START_Y (SCREEN_MIN_Y + 16*SCALE)
14 static struct { int x
, y
; } ws_cursor
;
16 /* returns -1 if not on any clickable item, 0 - 29 otherwise */
17 static int ws_cursor_on(void) {
18 if(ws_cursor
.x
< GRID_START_X
+3*SCALE
|| ws_cursor
.y
< GRID_START_Y
+ 5*SCALE
) return -1;
19 int rx
= (ws_cursor
.x
- (GRID_START_X
+3*SCALE
)) / (64*SCALE
);
20 int ry
= (ws_cursor
.y
- (GRID_START_Y
+5*SCALE
)) / (23*SCALE
);
21 if(rx
> 4 || ry
> 5) return -1;
25 static void draw_ws_grid() {
27 for(i
= 0, y
= GRID_START_Y
; i
< 9; i
++, y
+=23*SCALE
) {
28 if(i
== 7) y
+=21*SCALE
;
29 else if(i
== 8) y
-=8*SCALE
;
30 blit_sprite(GRID_START_X
, y
, &video
, SCALE
, spritemaps
[SI_WS_HBAR6
], 0, 0);
31 blit_sprite(GRID_START_X
+(6+308)*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_HBAR6
], 1, 0);
33 #define X (GRID_START_X+6*SCALE)
34 for(i
= 0, y
= GRID_START_Y
-1*SCALE
; i
< 9; i
++, y
+=23*SCALE
) {
35 if(i
== 7) y
+=21*SCALE
;
36 else if(i
== 8) y
-=8*SCALE
;
37 for(x
=X
; x
<X
+308*SCALE
;x
+=SCALE
)
38 blit_sprite(x
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 0, 0);
41 for(i
= 0, y
= GRID_START_Y
+3*SCALE
; i
< 8; i
++, y
+=23*SCALE
) {
42 if(i
== 7) y
+=21*SCALE
;
43 blit_sprite(GRID_START_X
+1*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 1, 0);
44 blit_sprite(GRID_START_X
+(1+317)*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 1, 0);
46 for(i
= 0, y
= GRID_START_Y
+19*SCALE
; i
< 8; i
++, y
+=23*SCALE
) {
47 if(i
== 6) y
+=21*SCALE
;
48 else if(i
== 7) y
-=8*SCALE
;
49 blit_sprite(GRID_START_X
+1*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 2, 0);
50 blit_sprite(GRID_START_X
+(1+317)*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 2, 0);
52 for(i
= 0, y
= GRID_START_Y
+7*SCALE
; i
< 8; i
++, y
+=23*SCALE
) {
53 if(i
== 7) y
+=21*SCALE
;
54 blit_sprite(GRID_START_X
+1*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 3, 0);
55 blit_sprite(GRID_START_X
+(1+317)*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 3, 0);
57 for(i
= 0, y
= GRID_START_Y
+11*SCALE
; i
< 7; i
++, y
+=23*SCALE
) {
58 blit_sprite(GRID_START_X
+1*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 3, 0);
59 blit_sprite(GRID_START_X
+(1+317)*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 3, 0);
61 for(i
= 0, y
= GRID_START_Y
+15*SCALE
; i
< 7; i
++, y
+=23*SCALE
) {
62 blit_sprite(GRID_START_X
+1*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 3, 0);
63 blit_sprite(GRID_START_X
+(1+317)*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 3, 0);
65 for(i
= 0, y
= GRID_START_Y
+(138+3+4+3*4)*SCALE
; i
< 6; i
++, y
+=4*SCALE
) {
66 if(i
== 5) y
-=3*SCALE
;
67 blit_sprite(GRID_START_X
+1*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 3, 0);
68 blit_sprite(GRID_START_X
+(1+317)*SCALE
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR1
], 3, 0);
70 for(i
= 0, y
= GRID_START_Y
+21*SCALE
; i
< 5; i
++, y
+=23*SCALE
) {
71 for(x
=GRID_START_X
+61*SCALE
; x
<260*SCALE
;x
+=64*SCALE
)
72 blit_sprite(x
, y
, &video
, SCALE
, spritemaps
[SI_WS_BOLT
], 0, 0);
74 for(i
= 0, y
= GRID_START_Y
+23*SCALE
; i
< 5; i
++, y
+=23*SCALE
) {
75 for(x
=GRID_START_X
+51*SCALE
; x
<260*SCALE
;x
+=64*SCALE
)
76 blit_sprite(x
, y
, &video
, SCALE
, spritemaps
[SI_WS_HBAR10
], 0, 0);
78 for(i
= 0, y
= GRID_START_Y
+23*SCALE
; i
< 5; i
++, y
+=23*SCALE
) {
79 for(x
=GRID_START_X
+68*SCALE
; x
<280*SCALE
;x
+=64*SCALE
)
80 blit_sprite(x
, y
, &video
, SCALE
, spritemaps
[SI_WS_HBAR10
], 1, 0);
83 for(x
= GRID_START_X
+63*SCALE
; x
<GRID_START_X
+280*SCALE
; x
+=64*SCALE
) {
84 blit_sprite(x
, GRID_START_Y
+3*SCALE
, &video
, SCALE
, spritemaps
[SI_WS_VBAR3
], 2, 0);
86 for(x
= GRID_START_X
+63*SCALE
; x
<GRID_START_X
+280*SCALE
; x
+=64*SCALE
) {
87 blit_sprite(x
, GRID_START_Y
+128*SCALE
, &video
, SCALE
, spritemaps
[SI_WS_VBAR3
], 3, 0);
89 for(i
= 0, y
= GRID_START_Y
+13*SCALE
; i
< 5; i
++, y
+=23*SCALE
) {
90 for(x
= GRID_START_X
+63*SCALE
; x
<GRID_START_X
+280*SCALE
; x
+=64*SCALE
) {
91 blit_sprite(x
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR3
], 1, 0);
94 for(i
= 0, y
= GRID_START_Y
+26*SCALE
; i
< 5; i
++, y
+=23*SCALE
) {
95 for(x
= GRID_START_X
+63*SCALE
; x
<GRID_START_X
+280*SCALE
; x
+=64*SCALE
) {
96 blit_sprite(x
, y
, &video
, SCALE
, spritemaps
[SI_WS_VBAR3
], 0, 0);
101 static void draw_ws_text_sprites() {
102 blit_sprite(GRID_START_X
+31*SCALE
, GRID_START_Y
+186*SCALE
, &video
, SCALE
, spritemaps
[SI_WS_COSTCREDIT
], 0, 0);
103 blit_sprite(GRID_START_X
+150*SCALE
, GRID_START_Y
+186*SCALE
, &video
, SCALE
, spritemaps
[SI_WS_COSTCREDIT
], 1, 0);
106 static void draw_ws_weapons() {
108 const struct palpic
* p
= spritemaps
[SI_WEAPONSHOP
];
110 for(yy
= 0, y
= GRID_START_Y
+5*SCALE
; yy
< 6; y
+=23*SCALE
, yy
++) {
111 for(xx
= 0, x
= GRID_START_X
+3*SCALE
; xx
< 5; x
+=64*SCALE
, xx
++) {
112 blit_sprite(x
, y
, &video
, SCALE
, p
, img
, 0);
118 static void print_ws_info(unsigned line
, const char* text
) {
119 font_print(GRID_START_X
+16*SCALE
, GRID_START_Y
+144*SCALE
+line
*9*SCALE
,
120 text
, strlen(text
), SCALE
, PRGB(0x00,0x88,0xee));
123 static void print_ws_num(unsigned num
, int x
) {
125 snprintf(buf
, sizeof buf
, "%.6u", num
);
126 font_print(GRID_START_X
+x
*SCALE
, GRID_START_Y
+187*SCALE
,
127 buf
, 6, SCALE
, PRGB(0xff,0xdd,0x55));
130 static void print_ws_cost(unsigned cost
) {
131 print_ws_num(cost
, 88);
134 static void print_ws_credit(unsigned credit
) {
135 print_ws_num(credit
, 224);
138 static const enum weapon_id wp_lut
[] = {
159 static const enum ammo_id ammo_lut
[] = {
164 [4] = AMMO_9MMPARABELLUM
,
166 [6] = AMMO_ROCKET83MM
,
168 [8] = AMMO_ROCKET40MM
,
169 [9] = AMMO_K200GRENADE40MM
,
173 static enum ammo_id
ws_ammo_from_index(int index
) {
174 assert(index
< 30 && index
>= 0);
175 if((unsigned) index
< ARRAY_SIZE(wp_lut
) ||
176 index
== ARRAY_SIZE(wp_lut
) + 7 ||
177 (unsigned) index
>= ARRAY_SIZE(wp_lut
) + ARRAY_SIZE(ammo_lut
)) return AMMO_INVALID
;
178 return ammo_lut
[index
- ARRAY_SIZE(wp_lut
)];
181 static enum weapon_id
ws_weapon_from_index(int index
) {
182 assert(index
< 30 && index
>= 0);
183 if((unsigned) index
>= ARRAY_SIZE(wp_lut
)) return WP_INVALID
;
184 return wp_lut
[index
];
187 static void draw_ws_weapon_info(int index
) {
188 enum ammo_id a
= ws_ammo_from_index(index
);
189 enum weapon_id w
= ws_weapon_from_index(index
);
190 const char* name
; unsigned cost
;
191 if(a
!= AMMO_INVALID
) {
192 cost
= ammunition
[a
].price
;
194 } else if (w
!= WP_INVALID
) {
195 cost
= weapons
[w
].price
;
196 name
= weapon_name(w
);
200 print_ws_info(0, name
);
204 static void draw_ws_stuff() {
207 draw_ws_text_sprites();
209 int wp_index
= ws_cursor_on();
210 if(wp_index
!= -1) draw_ws_weapon_info(wp_index
);
211 print_ws_credit(player_cash
[0]);
215 static void shop_tick(void) {
217 if (audio_process() == -1) music_restart();
221 /* returns 1 if successful */
222 static int purchase_weapon(enum weapon_id w
) {
223 int cost
= weapons
[w
].price
;
225 if(cost
> player_cash
[playerno
]) return 0;
226 for(i
= 0; i
< weapon_count
[playerno
]; i
++)
227 if(player_weapons
[playerno
][i
] == w
) return 0;
228 player_cash
[playerno
] -= cost
;
229 player_weapons
[playerno
][weapon_count
[playerno
]++] = w
;
233 static int purchase_ammo(enum ammo_id a
) {
234 int cost
= ammunition
[a
].price
;
236 if(cost
> player_cash
[playerno
]) return 0;
237 player_cash
[playerno
] -= cost
;
238 player_ammo
[playerno
][a
] += ammunition
[a
].rounds
;
239 if(a
== AMMO_GRENADE
) purchase_weapon(WP_GRENADES
);
243 static void print_ws_stats() {
247 font_print(28*SCALE
,32*SCALE
,"WEAPONS",7,SCALE
,PRGB(0xff,0xff,0xbb));
248 for(i
= 0; i
< weapon_count
[playerno
]; i
++) {
249 enum weapon_id w
= player_weapons
[playerno
][i
];
250 str
= weapon_name(w
);
251 font_print(28*SCALE
, 47*SCALE
+i
*9*SCALE
, str
, strlen(str
), SCALE
, PRGB(0xdd,0x33,0x11));
254 font_print(172*SCALE
,32*SCALE
,"AMMUNITION ROUNDS",17,SCALE
,PRGB(0xff,0xff,0xbb));
256 for(i
= 0; i
< AMMO_MAX
; i
++) {
257 str
= ammo_name((enum ammo_id
) i
);
258 font_print(180*SCALE
,47*SCALE
+i
*9*SCALE
,str
,strlen(str
),SCALE
,PRGB(0x11,0xbb,0x55));
259 font_print(246*SCALE
,47*SCALE
+i
*9*SCALE
,":",1,SCALE
,PRGB(0x11,0xbb,0x55));
261 snprintf(buf
, sizeof buf
, "%.5d", (int) player_ammo
[playerno
][i
]);
262 font_print(260*SCALE
,47*SCALE
+i
*9*SCALE
,buf
,5,SCALE
,PRGB(0x11,0x77,0xff));
266 static void show_weapons() {
274 while (SDL_PollEvent(&sdl_event
)) {
275 switch (sdl_event
.type
) {
277 case SDL_MOUSEBUTTONDOWN
:
282 if (audio_process() == -1) music_restart();
289 /* returns 1 if exit was clicked, otherwise 0 */
290 static int process_ws_click(void) {
291 int wp_index
= ws_cursor_on();
293 if(wp_index
< 0 || wp_index
>= 30) return 0;
295 if(weapon_count
[player_no
]) return 1;
296 else goto fail
; /* player must purchase at least one weapon */
303 enum ammo_id a
= ws_ammo_from_index(wp_index
);
304 enum weapon_id w
= ws_weapon_from_index(wp_index
);
307 if(a
!= AMMO_INVALID
) {
308 success
= purchase_ammo(a
);
309 } else if (w
!= WP_INVALID
) {
310 success
= purchase_weapon(w
);
316 audio_play_wave_resource(wavesounds
[WS_SUCCESS
]);
319 audio_play_wave_resource(wavesounds
[WS_FAIL
]);
325 static void weapon_shop(void) {
328 while (SDL_PollEvent(&sdl_event
)) {
329 switch (sdl_event
.type
) {
330 case SDL_MOUSEMOTION
:
331 ws_cursor
.x
= sdl_event
.motion
.x
;
332 ws_cursor
.y
= sdl_event
.motion
.y
;
334 case SDL_MOUSEBUTTONDOWN
:
335 if(process_ws_click()) goto dun_goofed
;
340 switch(sdl_event
.key
.keysym
.sym
) {
342 if((sdl_event
.key
.keysym
.mod
& KMOD_LALT
) ||
343 (sdl_event
.key
.keysym
.mod
& KMOD_RALT
)) {