palpic2png.c: improve, make usable with ppic binary files
[rofl0r-openDOW.git] / weapon_shop.c
blob99a1be28bca4b942fbe9a9f669f961e8bb53bfe5
1 #include "video.h"
2 #include "palpic.h"
3 #include "spritemaps.h"
4 #include "maps.h"
5 #include "font.h"
6 #include "audio.h"
7 #include "music.h"
8 #include "SDL/SDL.h"
9 #include "weapon.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;
22 return ry * 5 + rx;
25 static void draw_ws_grid() {
26 unsigned i,y,x;
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);
40 #undef X
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() {
107 unsigned img = 0;
108 const struct palpic* p = spritemaps[SI_WEAPONSHOP];
109 unsigned y,yy,x,xx;
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);
113 img++;
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) {
124 char buf[8];
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[] = {
139 [0] = WP_COLT45,
140 [1] = WP_BROWNING,
141 [2] = WP_SA80,
142 [3] = WP_MP5,
143 [4] = WP_UZI,
144 [5] = WP_STEYR,
145 [6] = WP_AK47,
146 [7] = WP_M16A2,
147 //[0] = WP_M203,
148 [8] = WP_RPK,
149 [9] = WP_L7A2,
150 [10] = WP_HK21,
151 [11] = WP_M60,
152 [12] = WP_MG42,
153 [13] = WP_M134,
154 [14] = WP_RPG7,
155 [15] = WP_LAW,
156 [16] = WP_MAW,
157 [17] = WP_ABC,
159 static const enum ammo_id ammo_lut[] = {
160 [0] = AMMO_GRENADE,
161 [1] = AMMO_556,
162 [2] = AMMO_762,
163 [3] = AMMO_45ACP,
164 [4] = AMMO_9MMPARABELLUM,
165 [5] = AMMO_10MM,
166 [6] = AMMO_ROCKET83MM,
167 // 7 : view button
168 [8] = AMMO_ROCKET40MM,
169 [9] = AMMO_K200GRENADE40MM,
170 [10] = AMMO_GAS
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;
193 name = ammo_name(a);
194 } else if (w != WP_INVALID) {
195 cost = weapons[w].price;
196 name = weapon_name(w);
197 } else
198 return;
200 print_ws_info(0, name);
201 print_ws_cost(cost);
204 static void draw_ws_stuff() {
205 clear_screen();
206 draw_ws_grid();
207 draw_ws_text_sprites();
208 draw_ws_weapons();
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]);
212 video_update();
215 static void shop_tick(void) {
216 draw_ws_stuff();
217 if (audio_process() == -1) music_restart();
218 SDL_Delay(20);
221 /* returns 1 if successful */
222 static int purchase_weapon(enum weapon_id w) {
223 int cost = weapons[w].price;
224 int playerno = 0, i;
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;
230 return 1;
233 static int purchase_ammo(enum ammo_id a) {
234 int cost = ammunition[a].price;
235 int playerno = 0;
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);
240 return 1;
243 static void print_ws_stats() {
244 int playerno = 0, i;
245 const char* str;
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));
260 char buf[8];
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() {
267 clear_screen();
268 print_ws_stats();
269 video_update();
270 SDL_ShowCursor(0);
272 while(1) {
273 SDL_Event sdl_event;
274 while (SDL_PollEvent(&sdl_event)) {
275 switch (sdl_event.type) {
276 case SDL_QUIT:
277 case SDL_MOUSEBUTTONDOWN:
278 goto dun;
279 default:;
282 if (audio_process() == -1) music_restart();
283 SDL_Delay(20);
285 dun:
286 SDL_ShowCursor(1);
289 /* returns 1 if exit was clicked, otherwise 0 */
290 static int process_ws_click(void) {
291 int wp_index = ws_cursor_on();
292 int player_no = 0;
293 if(wp_index < 0 || wp_index >= 30) return 0;
294 if(wp_index == 29) {
295 if(weapon_count[player_no]) return 1;
296 else goto fail; /* player must purchase at least one weapon */
298 if(wp_index == 25) {
299 show_weapons();
300 return 0;
303 enum ammo_id a = ws_ammo_from_index(wp_index);
304 enum weapon_id w = ws_weapon_from_index(wp_index);
305 int success;
307 if(a != AMMO_INVALID) {
308 success = purchase_ammo(a);
309 } else if (w != WP_INVALID) {
310 success = purchase_weapon(w);
311 } else {
312 return 0;
315 if(success) {
316 audio_play_wave_resource(wavesounds[WS_SUCCESS]);
317 } else {
318 fail:;
319 audio_play_wave_resource(wavesounds[WS_FAIL]);
322 return 0;
325 static void weapon_shop(void) {
326 SDL_Event sdl_event;
327 while(1) {
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;
333 break;
334 case SDL_MOUSEBUTTONDOWN:
335 if(process_ws_click()) goto dun_goofed;
336 break;
337 case SDL_QUIT:
338 goto dun_goofed;
339 case SDL_KEYDOWN:
340 switch(sdl_event.key.keysym.sym) {
341 case SDLK_RETURN:
342 if((sdl_event.key.keysym.mod & KMOD_LALT) ||
343 (sdl_event.key.keysym.mod & KMOD_RALT)) {
344 toggle_fullscreen();
345 SDL_Delay(1);
347 break;
348 case SDLK_ESCAPE:
349 goto dun_goofed;
350 default:
351 break;
353 default:
354 break;
358 shop_tick();
360 dun_goofed:
361 clear_screen();
362 video_update();