1 /**
2 * Common code for FreeDink and FreeDinkedit
3
4 * Copyright (C) 1997, 1998, 1999, 2002, 2003 Seth A. Robinson
5 * Copyright (C) 2003 Shawn Betts
6 * Copyright (C) 2005, 2006 Dan Walma
7 * Copyright (C) 2005, 2007, 2008, 2009, 2010, 2012 Sylvain Beucler
8
9 * This file is part of GNU FreeDink
10
11 * GNU FreeDink is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 3 of the
14 * License, or (at your option) any later version.
15
16 * GNU FreeDink is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see
23 * <http://www.gnu.org/licenses/>.
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #define WIN32_LEAN_AND_MEAN
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <strings.h> /* strncasecmp */
35 #include <ctype.h>
36 #include <time.h>
37
38 #ifdef _WIN32
39 /* GetWindowsDirectory */
40 #include <windows.h>
41 #endif
42 /* #include <windowsx.h> */
43 /* #include <direct.h> */
44 /* #include <io.h> */
45 #include <fcntl.h>
46 /* #include <process.h> */
47
48
49 /* #include <mmsystem.h> */
50 /* #define DIRECTINPUT_VERSION 0x0700 */
51 /* #include <dinput.h> */
52 /* #include <ddraw.h> */
53
54 #include "SDL.h"
55 #include "SDL_image.h"
56 #include "SDL_framerate.h"
57
58 #include "game_engine.h"
59 #include "screen.h"
60 #include "dinkini.h"
61 #include "input.h"
62
63 /* #include "ddutil.h" */
64 #include "fastfile.h"
65 #include "io_util.h"
66
67
68 #include "freedink.h"
69 #include "dinkvar.h"
70 #include "gfx.h"
71 #include "gfx_tiles.h"
72 #include "gfx_sprites.h"
73 #include "gfx_palette.h"
74 /* for DinkC's initfonts(): */
75 #include "gfx_fonts.h"
76 #include "bgm.h"
77 #include "sfx.h"
78 #include "dinkc.h"
79 #include "dinkc_bindings.h"
80
81 #include "str_util.h"
82 #include "paths.h"
83 #include "log.h"
84
85 //if true, will close app as soon as the message pump is empty
86 int g_b_kill_app = 0;
87
88 int dinkspeed = 3;
89 int show_inventory = 0; // display inventory?
90
91 void update_status_all(void);
92 int add_sprite(int x1, int y, int brain,int pseq, int pframe );
93
94 void add_exp(int num, int h);
95 void draw_status_all(void);
96 void check_seq_status(int h);
97
98 int realhard(int tile);
99 int flub_mode = -500;
100 int draw_map_tiny = -1;
101
102 int walk_off_screen = /*false*/0;
103
104 /* Skip flipping the double buffer for this frame only - used when
105 setting up show_bmp and copy_bmp */
106 /*bool*/int abort_this_flip = /*false*/0;
107
108
109 #define SEQ_LEVEL_NUMS 442
110
111
112 struct show_bmp showb;
113
114 int keep_mouse = 0;
115
116
117 struct attackinfo_struct bow;
118
119 int screenlock = 0;
120
121 struct talk_struct talk;
122
123 unsigned long mold;
124
125 int mbase_count;
126
127
128 int push_active = 1;
129
130
131 #define TEXT_MIN 2700
132 #define TEXT_TIMER 77
133
134 int stop_entire_game;
135 const int max_game = 20;
136 /*bool*/int in_enabled = /*false*/0;
137 char *in_string;
138
139
140
141
142 /* If true, and if the engine is executing a screen's attached script,
143 and if main() loads new graphics (preload_seq()...), then
144 load_sprites and load_sprite_pak will display a "Please Wait"
145 animation. */
146 /*bool*/int no_running_main = /*false*/0;
147
148 char dir[80];
149
150
151 //defaults
152
153
154
155
156 int show_dot = /*FALSE*/0;
157
158 unsigned long timer = 0;
159 char *command_line;
160 /*bool*/int dinkedit = /*false*/0;
161 int base_timing = 0;
162 int weapon_script = 0;
163 int magic_script = 0;
164
165 int sp_mode = 0;
166 int fps,fps_final = 0;
167 int move_screen = 0;
168 int move_counter = 0;
169 int playx = 620;
170 /*bool*/int windowed = /*false*/0; /* TODO: move to gfx.c? */
171 int playl = 20;
172
173 /*bool*/int mouse1 = /*false*/0;
174 int playy = 400;
175 int cur_map;
176
177 /* Number of ms since an arbitrarily fixed point */
178 Uint32 thisTickCount,lastTickCount;
179 /* SDL_gfx accurate framerate */
180 FPSmanager framerate_manager;
181
182 unsigned long timecrap;
183 rect math,box_crap,box_real;
184
185
186 int mode;
187
188 struct small_map pam;
189
190
191 /*bool*/int trig_man = /*false*/0;
192 /*bool*/int total_trigger = /*false*/0;
193
194 struct player_info play;
195
196
197
198
199 /* LPDIRECTDRAWSURFACE game[max_game]; // Game pieces */
200 /* LPDIRECTDRAWPALETTE lpDDPal = NULL; // The primary surface palette */
201 /* PALETTEENTRY pe[256]; */
202
203 int bActive = /*false*/0; // is application active/foreground?
204 //LPDIRECTINPUT lpDI;
205
206
207 //direct input stuff for mouse reading
208
209 /* LPDIRECTINPUT g_pdi = NULL; */
210 /* LPDIRECTINPUTDEVICE g_pMouse = NULL; */
211 /* #define DINPUT_BUFFERSIZE 16 */
212
213 /* HANDLE g_hevtMouse = NULL; */
214
215
216 //LPCDIDATAFORMAT lpc;
217
218 unsigned char torusColors[256]; // Marks the colors used in the torus
219
220
221 /* HWND hWndMain = NULL; */
222 struct hardness hmap;
223
clear_talk(void)224 void clear_talk(void)
225 {
226 memset(&talk, 0, sizeof(talk));
227 play.mouse = 0;
228 }
229
230
lmon(long money,char * dest)231 char * lmon(long money, char *dest)
232 {
233 char ho[30];
234 int k,c;
235 char lmon1[30];
236 char buffer[30];
237 /*BOOL*/int quit1;
238 quit1 = /*FALSE*/0;
239
240 sprintf(buffer, "%ld", money);
241 strcpy(lmon1, buffer);
242 // prf("ORG IS '%s'",lmon1);
243
244 if (strlen(lmon1) < 4)
245 {
246 strcpy(dest, lmon1);
247 return(dest);
248 }
249
250 sprintf(buffer, "%ld", money);
251 strcpy(ho, buffer);
252 k = strlen(ho);
253 c = -1;
254 lmon1[0]=0;
255 do {
256 strchar(lmon1,ho[k]);
257 k--;
258 c++;
259 if (c == 3)
260 {
261 if (k > -1)
262 {
263 strchar(lmon1,',');
264 c = 0;
265 }
266 }
267 if (k < 0) quit1 = /*TRUE*/1;
268 }while (quit1 == /*FALSE*/0);
269 reverse(lmon1);
270
271 strcpy(dest, lmon1);
272 return(dest);
273 }
274
275
276
277 /* void dderror(HRESULT hErr) */
278 /* { */
279 /* switch (hErr) */
280 /* { */
281 /* case DDERR_ALREADYINITIALIZED: */
282 /* Msg("DDERR_ALREADYINITIALIZED"); break; */
283 /* case DDERR_CANNOTATTACHSURFACE: */
284 /* Msg("DDERR_CANNOTATTACHSURFACE"); break; */
285 /* case DDERR_CANNOTDETACHSURFACE: */
286 /* Msg("DDERR_CANNOTDETACHSURFACE"); break; */
287 /* case DDERR_CURRENTLYNOTAVAIL: */
288 /* Msg("DDERR_CURRENTLYNOTAVAIL"); break; */
289 /* case DDERR_EXCEPTION: */
290 /* Msg("DDERR_EXCEPTION"); break; */
291 /* case DDERR_GENERIC: */
292 /* Msg("DDERR_GENERIC"); break; */
293 /* case DDERR_HEIGHTALIGN: */
294 /* Msg("DDERR_HEIGHTALIGN"); break; */
295 /* case DDERR_INCOMPATIBLEPRIMARY: */
296 /* Msg("DDERR_INCOMPATIBLEPRIMARY"); break; */
297 /* case DDERR_INVALIDCAPS: */
298 /* Msg("DDERR_INVALIDCAPS"); break; */
299 /* case DDERR_INVALIDCLIPLIST: */
300 /* Msg("DDERR_INVALIDCLIPLIST"); break; */
301 /* case DDERR_INVALIDMODE: */
302 /* Msg("DDERR_INVALIDMODE"); break; */
303 /* case DDERR_INVALIDOBJECT: */
304 /* Msg("DDERR_INVALIDOBJECT"); break; */
305 /* case DDERR_INVALIDPARAMS: */
306 /* Msg("DDERR_INVALIDPARAMS"); break; */
307 /* case DDERR_INVALIDPIXELFORMAT: */
308 /* Msg("DDERR_INVALIDPIXELFORMAT"); break; */
309 /* case DDERR_INVALIDRECT: */
310 /* Msg("DDERR_INVALIDRECT"); break; */
311 /* case DDERR_LOCKEDSURFACES: */
312 /* Msg("DDERR_LOCKEDSURFACES"); break; */
313 /* case DDERR_NO3D: */
314 /* Msg("DDERR_NO3D"); break; */
315 /* case DDERR_NOALPHAHW: */
316 /* Msg("DDERR_NOALPHAHW"); break; */
317 /* case DDERR_NOCLIPLIST: */
318 /* Msg("DDERR_NOCLIPLIST"); break; */
319 /* case DDERR_NOCOLORCONVHW: */
320 /* Msg("DDERR_NOCOLORCONVHW"); break; */
321 /* case DDERR_NOCOOPERATIVELEVELSET: */
322 /* Msg("DDERR_NOCOOPERATIVELEVELSET"); break; */
323 /* case DDERR_NOCOLORKEY: */
324 /* Msg("DDERR_NOCOLORKEY"); break; */
325 /* case DDERR_NOCOLORKEYHW: */
326 /* Msg("DDERR_NOCOLORKEYHW"); break; */
327 /* case DDERR_NODIRECTDRAWSUPPORT: */
328 /* Msg("DDERR_NODIRECTDRAWSUPPORT"); break; */
329 /* case DDERR_NOEXCLUSIVEMODE: */
330 /* Msg("DDERR_NOEXCLUSIVEMODE"); break; */
331 /* case DDERR_NOFLIPHW: */
332 /* Msg("DDERR_NOFLIPHW"); break; */
333 /* case DDERR_NOGDI: */
334 /* Msg("DDERR_NOGDI"); break; */
335 /* case DDERR_NOMIRRORHW: */
336 /* Msg("DDERR_NOMIRRORHW"); break; */
337 /* case DDERR_NOTFOUND: */
338 /* Msg("DDERR_NOTFOUND"); break; */
339 /* case DDERR_NOOVERLAYHW: */
340 /* Msg("DDERR_NOOVERLAYHW"); break; */
341 /* case DDERR_NORASTEROPHW: */
342 /* Msg("DDERR_NORASTEROPHW"); break; */
343 /* case DDERR_NOROTATIONHW: */
344 /* Msg("DDERR_NOROTATIONHW"); break; */
345 /* case DDERR_NOSTRETCHHW: */
346 /* Msg("DDERR_NOSTRETCHHW"); break; */
347 /* case DDERR_NOT4BITCOLOR: */
348 /* Msg("DDERR_NOT4BITCOLOR"); break; */
349 /* case DDERR_NOT4BITCOLORINDEX: */
350 /* Msg("DDERR_NOT4BITCOLORINDEX"); break; */
351 /* case DDERR_NOT8BITCOLOR: */
352 /* Msg("DDERR_NOT8BITCOLOR"); break; */
353 /* case DDERR_NOTEXTUREHW: */
354 /* Msg("DDERR_NOTEXTUREHW"); break; */
355 /* case DDERR_NOVSYNCHW: */
356 /* Msg("DDERR_NOVSYNCHW"); break; */
357 /* case DDERR_NOZBUFFERHW: */
358 /* Msg("DDERR_NOZBUFFERHW"); break; */
359 /* case DDERR_NOZOVERLAYHW: */
360 /* Msg("DDERR_NOZOVERLAYHW"); break; */
361 /* case DDERR_OUTOFCAPS: */
362 /* Msg("DDERR_OUTOFCAPS"); break; */
363 /* case DDERR_OUTOFMEMORY: */
364 /* Msg("DDERR_OUTOFMEMORY"); break; */
365 /* case DDERR_OUTOFVIDEOMEMORY: */
366 /* Msg("DDERR_OUTOFVIDEOMEMORY"); break; */
367 /* case DDERR_OVERLAYCANTCLIP: */
368 /* Msg("DDERR_OVERLAYCANTCLIP"); break; */
369 /* case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: */
370 /* Msg("DDERR_OVERLAYCOLORKEYONLYONEACTIVE"); break; */
371 /* case DDERR_PALETTEBUSY: */
372 /* Msg("DDERR_PALETTEBUSY"); break; */
373 /* case DDERR_COLORKEYNOTSET: */
374 /* Msg("DDERR_COLORKEYNOTSET"); break; */
375 /* case DDERR_SURFACEALREADYATTACHED: */
376 /* Msg("DDERR_SURFACEALREADYATTACHED"); break; */
377 /* case DDERR_SURFACEALREADYDEPENDENT: */
378 /* Msg("DDERR_SURFACEALREADYDEPENDENT"); break; */
379 /* case DDERR_SURFACEBUSY: */
380 /* Msg("DDERR_SURFACEBUSY"); break; */
381 /* case DDERR_CANTLOCKSURFACE: */
382 /* Msg("DDERR_CANTLOCKSURFACE"); break; */
383 /* case DDERR_SURFACEISOBSCURED: */
384 /* Msg("DDERR_SURFACEISOBSCURED"); break; */
385 /* case DDERR_SURFACELOST: */
386 /* Msg("DDERR_SURFACELOST"); break; */
387 /* case DDERR_SURFACENOTATTACHED: */
388 /* Msg("DDERR_SURFACENOTATTACHED"); break; */
389 /* case DDERR_TOOBIGHEIGHT: */
390 /* Msg("DDERR_TOOBIGHEIGHT"); break; */
391 /* case DDERR_TOOBIGSIZE: */
392 /* Msg("DDERR_TOOBIGSIZE"); break; */
393 /* case DDERR_TOOBIGWIDTH: */
394 /* Msg("DDERR_TOOBIGWIDTH"); break; */
395 /* case DDERR_UNSUPPORTED: */
396 /* Msg("DDERR_UNSUPPORTED"); break; */
397 /* case DDERR_UNSUPPORTEDFORMAT: */
398 /* Msg("DDERR_UNSUPPORTEDFORMAT"); break; */
399 /* case DDERR_UNSUPPORTEDMASK: */
400 /* Msg("DDERR_UNSUPPORTEDMASK"); break; */
401 /* case DDERR_VERTICALBLANKINPROGRESS: */
402 /* Msg("DDERR_VERTICALBLANKINPROGRESS"); break; */
403 /* case DDERR_WASSTILLDRAWING: */
404 /* Msg("DDERR_WASSTILLDRAWING"); break; */
405 /* case DDERR_XALIGN: */
406 /* Msg("DDERR_XALIGN"); break; */
407 /* case DDERR_INVALIDDIRECTDRAWGUID: */
408 /* Msg("DDERR_INVALIDDIRECTDRAWGUID"); break; */
409 /* case DDERR_DIRECTDRAWALREADYCREATED: */
410 /* Msg("DDERR_DIRECTDRAWALREADYCREATED"); break; */
411 /* case DDERR_NODIRECTDRAWHW: */
412 /* Msg("DDERR_NODIRECTDRAWHW"); break; */
413 /* case DDERR_PRIMARYSURFACEALREADYEXISTS: */
414 /* Msg("DDERR_PRIMARYSURFACEALREADYEXISTS"); break; */
415 /* case DDERR_NOEMULATION: */
416 /* Msg("DDERR_NOEMULATION"); break; */
417 /* case DDERR_REGIONTOOSMALL: */
418 /* Msg("DDERR_REGIONTOOSMALL"); break; */
419 /* case DDERR_CLIPPERISUSINGHWND: */
420 /* Msg("DDERR_CLIPPERISUSINGHWND"); break; */
421 /* case DDERR_NOCLIPPERATTACHED: */
422 /* Msg("DDERR_NOCLIPPERATTACHED"); break; */
423 /* case DDERR_NOHWND: */
424 /* Msg("DDERR_NOHWND"); break; */
425 /* case DDERR_HWNDSUBCLASSED: */
426 /* Msg("DDERR_HWNDSUBCLASSED"); break; */
427 /* case DDERR_HWNDALREADYSET: */
428 /* Msg("DDERR_HWNDALREADYSET"); break; */
429 /* case DDERR_NOPALETTEATTACHED: */
430 /* Msg("DDERR_NOPALETTEATTACHED"); break; */
431 /* case DDERR_NOPALETTEHW: */
432 /* Msg("DDERR_NOPALETTEHW"); break; */
433 /* case DDERR_BLTFASTCANTCLIP: */
434 /* Msg("DDERR_BLTFASTCANTCLIP"); break; */
435 /* case DDERR_NOBLTHW: */
436 /* Msg("DDERR_NOBLTHW"); break; */
437 /* case DDERR_NODDROPSHW: */
438 /* Msg("DDERR_NODDROPSHW"); break; */
439 /* case DDERR_OVERLAYNOTVISIBLE: */
440 /* Msg("DDERR_OVERLAYNOTVISIBLE"); break; */
441 /* case DDERR_NOOVERLAYDEST: */
442 /* Msg("DDERR_NOOVERLAYDEST"); break; */
443 /* case DDERR_INVALIDPOSITION: */
444 /* Msg("DDERR_INVALIDPOSITION"); break; */
445 /* case DDERR_NOTAOVERLAYSURFACE: */
446 /* Msg("DDERR_NOTAOVERLAYSURFACE"); break; */
447 /* case DDERR_EXCLUSIVEMODEALREADYSET: */
448 /* Msg("DDERR_EXCLUSIVEMODEALREADYSET"); break; */
449 /* case DDERR_NOTFLIPPABLE: */
450 /* Msg("DDERR_NOTFLIPPABLE"); break; */
451 /* case DDERR_CANTDUPLICATE: */
452 /* Msg("DDERR_CANTDUPLICATE"); break; */
453 /* case DDERR_NOTLOCKED: */
454 /* Msg("DDERR_NOTLOCKED"); break; */
455 /* case DDERR_CANTCREATEDC: */
456 /* Msg("DDERR_CANTCREATEDC"); break; */
457 /* case DDERR_NODC: */
458 /* Msg("DDERR_NODC"); break; */
459 /* case DDERR_WRONGMODE: */
460 /* Msg("DDERR_WRONGMODE"); break; */
461 /* case DDERR_IMPLICITLYCREATED: */
462 /* Msg("DDERR_IMPLICITLYCREATED"); break; */
463 /* case DDERR_NOTPALETTIZED: */
464 /* Msg("DDERR_NOTPALETTIZED"); break; */
465 /* case DDERR_UNSUPPORTEDMODE: */
466 /* Msg("DDERR_UNSUPPORTEDMODE"); break; */
467 /* case DDERR_NOMIPMAPHW: */
468 /* Msg("DDERR_NOMIPMAPHW"); break; */
469 /* case DDERR_INVALIDSURFACETYPE: */
470 /* Msg("DDERR_INVALIDSURFACETYPE"); break; */
471 /* case DDERR_DCALREADYCREATED: */
472 /* Msg("DDERR_DCALREADYCREATED"); break; */
473 /* case DDERR_CANTPAGELOCK: */
474 /* Msg("DDERR_CANTPAGELOCK"); break; */
475 /* case DDERR_CANTPAGEUNLOCK: */
476 /* Msg("DDERR_CANTPAGEUNLOCK"); break; */
477 /* case DDERR_NOTPAGELOCKED: */
478 /* Msg("DDERR_NOTPAGELOCKED"); break; */
479 /* case DDERR_NOTINITIALIZED: */
480 /* Msg("DDERR_NOTINITIALIZED"); break; */
481 /* default: */
482 /* Msg("Unknown Error"); break; */
483 /* } */
484 /* Msg("\n"); */
485 /* } */
486
487
488 //add hardness from a sprite
489
490 /**
491 * Get the current graphic (current sequence/current frame) for sprite
492 * 'sprite_no'
493 */
getpic(int sprite_no)494 int getpic(int sprite_no)
495 {
496 if (spr[sprite_no].pseq == 0)
497 return 0;
498
499 if (spr[sprite_no].pseq >= MAX_SEQUENCES)
500 {
501 log_error("Sequence %d? But max is %d!", spr[sprite_no].pseq, MAX_SEQUENCES);
502 return 0;
503 }
504
505 return seq[spr[sprite_no].pseq].frame[spr[sprite_no].pframe];
506 }
507
508
add_hardness(int sprite,int num)509 void add_hardness (int sprite, int num)
510 {
511 int xx;
512 for (xx = spr[sprite].x + k[getpic(sprite)].hardbox.left; xx < spr[sprite].x + k[getpic(sprite)].hardbox.right; xx++)
513 {
514 int yy;
515 for (yy = spr[sprite].y + k[getpic(sprite)].hardbox.top; yy < spr[sprite].y + k[getpic(sprite)].hardbox.bottom; yy++)
516 {
517 if ( (xx-20 > 600) | (xx-20 < 0)| (yy > 400) | (yy < 0))
518 ; /* Nothing */
519 else
520 hm.x[xx-20].y[yy] = num;
521 }
522 }
523 }
524
525
526
527
528 /**
529 * Check whether planned new position (x1,y1) is solid
530 *
531 * Only used in 'check_if_move_is_legal'
532 */
get_hard(int x1,int y1)533 unsigned char get_hard(int x1, int y1)
534 {
535 if (screenlock)
536 {
537 if (x1 < 0) x1 = 0;
538 else if (x1 > 599) x1 = 599;
539
540 if (y1 < 0) y1 = 0;
541 else if (y1 > 399) y1 = 399;
542 }
543 if ((x1 < 0) || (y1 < 0) || (x1 > 599) || (y1 > 399))
544 return 0;
545
546 int value = hm.x[x1].y[y1];
547 return(value);
548 }
549
550 /**
551 * Check whether planned new position (x1,y1) is solid
552 *
553 * Does something weird when hard value is > 100??
554 *
555 * Only used in 'human_brain'
556 */
get_hard_play(int h,int x1,int y1)557 unsigned char get_hard_play(int h, int x1, int y1)
558 {
559 x1 -= 20;
560
561 if (screenlock)
562 {
563 if (x1 < 0) x1 = 0;
564 else if (x1 > 599) x1 = 599;
565
566 if (y1 < 0) y1 = 0;
567 else if (y1 > 399) y1 = 399;
568 }
569 if ((x1 < 0) || (y1 < 0) || (x1 > 599) || (y1 > 399))
570 return 0;
571
572 int value = hm.x[x1].y[y1];
573 if (value > 100 && pam.sprite[value-100].is_warp != 0)
574 {
575 flub_mode = value;
576 value = 0;
577 }
578 return(value);
579 }
580
581
get_hard_map(int h,int x1,int y1)582 unsigned char get_hard_map(int h,int x1, int y1)
583 {
584
585
586 if ((x1 < 0) || (y1 < 0)) return(0);
587 if ((x1 > 599) ) return(0);
588 if (y1 > 399) return(0);
589
590
591 int til = (x1 / 50) + ( ((y1 / 50)) * 12);
592 //til++;
593
594 int offx = x1 - ((x1 / 50) * 50);
595
596
597 int offy = y1 - ((y1 / 50) * 50);
598
599 //Msg("tile %d ",til);
600
601 return( hmap.htile[ realhard(til ) ].x[offx].y[offy]);
602
603 }
604
605
606
fill_hardxy(rect box)607 void fill_hardxy(rect box)
608 {
609 int x1, y1;
610 //Msg("filling hard of %d %d %d %d", box.top, box.left, box.right, box.bottom);
611
612 if (box.right > 600) box.right = 600;
613 if (box.top < 0) box.top = 0;
614 if (box.bottom > 400) box.bottom = 400;
615 if (box.left < 0) box.left = 0;
616
617 for (x1 = box.left; x1 < box.right; x1++)
618 for (y1 = box.top; y1 < box.bottom; y1++)
619 hm.x[x1].y[y1] = get_hard_map(0,x1,y1);
620 }
621
622
623 /**
624 * Add experience - no "did the player really kill this enemy?"
625 * checks
626 */
add_exp_force(int num,int source_sprite)627 void add_exp_force(int num, int source_sprite)
628 {
629 if (num > 0)
630 {
631 //add experience
632 *pexper += num;
633
634 int crap2 = add_sprite(spr[source_sprite].x, spr[source_sprite].y, 8, 0, 0);
635 spr[crap2].y -= k[seq[spr[source_sprite].pseq].frame[spr[source_sprite].pframe]].yoffset;
636 spr[crap2].x -= k[seq[spr[source_sprite].pseq].frame[spr[source_sprite].pframe]].xoffset;
637 spr[crap2].y -= k[seq[spr[source_sprite].pseq].frame[spr[source_sprite].pframe]].box.bottom / 3;
638 spr[crap2].x += k[seq[spr[source_sprite].pseq].frame[spr[source_sprite].pframe]].box.right / 5;
639 spr[crap2].y -= 30;
640 spr[crap2].speed = 1;
641 spr[crap2].hard = 1;
642 spr[crap2].brain_parm = 5000;
643 spr[crap2].my = -1;
644 spr[crap2].kill = 1000;
645 spr[crap2].dir = 8;
646 spr[crap2].damage = num;
647
648 if (*pexper > 99999)
649 *pexper = 99999;
650 }
651 }
652
add_exp(int num,int killed_sprite)653 void add_exp(int num, int killed_sprite)
654 {
655 if (spr[killed_sprite].last_hit != 1)
656 return;
657
658 add_exp_force(num, killed_sprite);
659 }
660
661 /**
662 * Return hardness index for this screen tile, either its default
663 * hardness, or the replaced/alternative hardness. Tile is in [0,95].
664 */
realhard(int tile)665 int realhard(int tile)
666 {
667 if (pam.t[tile].althard > 0)
668 return(pam.t[tile].althard);
669 else
670 return(hmap.btile_default[pam.t[tile].square_full_idx0]);
671 }
672
673
fill_whole_hard(void)674 void fill_whole_hard(void)
675 {
676 int til;
677 for (til=0; til < 96; til++)
678 {
679 int offx = (til * 50 - ((til / 12) * 600));
680 int offy = (til / 12) * 50;
681 int x, y;
682 for (x = 0; x < 50; x++)
683 for (y = 0; y < 50; y++)
684 hm.x[offx +x].y[offy+y] = hmap.htile[ realhard(til) ].x[x].y[y];
685 }
686 }
687
688 /* Draw harness. Used by freedinkedit and updateFrame() in hard-coded
689 cheat mode. */
drawallhard(void)690 void drawallhard( void)
691 {
692 /* rect box_crap; */
693 /* int ddrval; */
694 /* DDBLTFX ddbltfx; */
695 int x1, y1;
696
697 /* TODO: test me! Then factor the code */
698 for (x1=0; x1 < 600; x1++)
699 for (y1=0; y1 < 400; y1++)
700 {
701 if (hm.x[x1].y[y1] == 1)
702 {
703 /* ddbltfx.dwFillColor = 1; */
704 /* ddbltfx.dwSize = sizeof(ddbltfx); */
705 /* box_crap.top = y1; */
706 /* box_crap.bottom = y1+1; */
707 /* box_crap.left = x1+playl; //20 is to compensate for the border */
708 /* box_crap.right = x1+1+playl; */
709 /* ddrval = lpDDSBack->Blt(&box_crap ,NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); */
710 /* if (ddrval != DD_OK) Msg("There was an error!"); */
711 // GFX
712 {
713 SDL_Rect GFX_box_crap;
714 GFX_box_crap.x = x1 + playl;
715 GFX_box_crap.y = y1;
716 GFX_box_crap.w = 1;
717 GFX_box_crap.h = 1;
718 SDL_FillRect(GFX_lpDDSBack, &GFX_box_crap,
719 SDL_MapRGB(GFX_lpDDSBack->format,
720 GFX_real_pal[1].r,
721 GFX_real_pal[1].g,
722 GFX_real_pal[1].b));
723 }
724 }
725
726 if (hm.x[x1].y[y1] == 2)
727 {
728 /* ddbltfx.dwFillColor = 128; */
729 /* ddbltfx.dwSize = sizeof(ddbltfx); */
730 /* box_crap.top = y1; */
731 /* box_crap.bottom = y1+1; */
732 /* box_crap.left = x1+playl; //20 is to compensate for the border */
733 /* box_crap.right = x1+1+playl; */
734 /* ddrval = lpDDSBack->Blt(&box_crap ,NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); */
735 /* if (ddrval != DD_OK) Msg("There was an error!"); */
736 // GFX
737 {
738 SDL_Rect GFX_box_crap;
739 GFX_box_crap.x = x1 + playl;
740 GFX_box_crap.y = y1;
741 GFX_box_crap.w = 1;
742 GFX_box_crap.h = 1;
743 SDL_FillRect(GFX_lpDDSBack, &GFX_box_crap,
744 SDL_MapRGB(GFX_lpDDSBack->format,
745 GFX_real_pal[128].r,
746 GFX_real_pal[128].g,
747 GFX_real_pal[128].b));
748 }
749 }
750
751 if (hm.x[x1].y[y1] == 3)
752 {
753 /* ddbltfx.dwFillColor = 45; */
754 /* ddbltfx.dwSize = sizeof(ddbltfx); */
755 /* box_crap.top = y1; */
756 /* box_crap.bottom = y1+1; */
757 /* box_crap.left = x1+playl; //20 is to compensate for the border */
758 /* box_crap.right = x1+1+playl; */
759 /* ddrval = lpDDSBack->Blt(&box_crap ,NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); */
760 /* if (ddrval != DD_OK) Msg("There was an error!"); */
761 // GFX
762 {
763 SDL_Rect GFX_box_crap;
764 GFX_box_crap.x = x1 + playl;
765 GFX_box_crap.y = y1;
766 GFX_box_crap.w = 1;
767 GFX_box_crap.h = 1;
768 SDL_FillRect(GFX_lpDDSBack, &GFX_box_crap,
769 SDL_MapRGB(GFX_lpDDSBack->format,
770 GFX_real_pal[45].r,
771 GFX_real_pal[45].g,
772 GFX_real_pal[45].b));
773 }
774 }
775
776 if (hm.x[x1].y[y1] > 100)
777 {
778
779 if (pam.sprite[ (hm.x[x1].y[y1]) - 100].is_warp == 1)
780 {
781 //draw a little pixel
782 /* ddbltfx.dwFillColor = 20; */
783 /* ddbltfx.dwSize = sizeof(ddbltfx); */
784 /* box_crap.top = y1; */
785 /* box_crap.bottom = y1+1; */
786 /* box_crap.left = x1+playl; //20 is to compensate for the border */
787 /* box_crap.right = x1+1+playl; */
788 /* ddrval = lpDDSBack->Blt(&box_crap ,NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); */
789 /* if (ddrval != DD_OK) Msg("There was an error!"); */
790 // GFX
791 {
792 SDL_Rect GFX_box_crap;
793 GFX_box_crap.x = x1 + playl;
794 GFX_box_crap.y = y1;
795 GFX_box_crap.w = 1;
796 GFX_box_crap.h = 1;
797 SDL_FillRect(GFX_lpDDSBack, &GFX_box_crap,
798 SDL_MapRGB(GFX_lpDDSBack->format,
799 GFX_real_pal[20].r,
800 GFX_real_pal[20].g,
801 GFX_real_pal[20].b));
802 }
803 }
804 else
805 {
806 //draw a little pixel
807 /* ddbltfx.dwFillColor = 23; */
808 /* ddbltfx.dwSize = sizeof(ddbltfx); */
809 /* box_crap.top = y1; */
810 /* box_crap.bottom = y1+1; */
811 /* box_crap.left = x1+playl; //20 is to compensate for the border */
812 /* box_crap.right = x1+1+playl; */
813 /* ddrval = lpDDSBack->Blt(&box_crap ,NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); */
814 /* if (ddrval != DD_OK) Msg("There was an error!"); */
815 // GFX
816 {
817 SDL_Rect GFX_box_crap;
818 GFX_box_crap.x = x1 + playl;
819 GFX_box_crap.y = y1;
820 GFX_box_crap.w = 1;
821 GFX_box_crap.h = 1;
822 SDL_FillRect(GFX_lpDDSBack, &GFX_box_crap,
823 SDL_MapRGB(GFX_lpDDSBack->format,
824 GFX_real_pal[23].r,
825 GFX_real_pal[23].g,
826 GFX_real_pal[23].b));
827 }
828 }
829 }
830 }
831 }
832
833
834 /**
835 * Resurrect sprites that were temporarily disabled
836 * (editor_type(6/7/8))
837 */
fix_dead_sprites()838 void fix_dead_sprites()
839 {
840 int i;
841 if (dinkedit) return;
842
843 for (i = 1; i < 100; i++)
844 {
845 int type = play.spmap[*pmap].type[i];
846
847 // Resurrect sprites after 5mn
848 if (type == 6)
849 {
850 if ((thisTickCount > (play.spmap[*pmap].last_time + 300000))
851 || (thisTickCount + 400000 < play.spmap[*pmap].last_time + 300000))
852 {
853 //this sprite can come back online now
854 play.spmap[*pmap].type[i] = 0;
855 }
856 }
857
858 // Resurrect sprites after 3mn
859 if (type == 7)
860 {
861 if (thisTickCount > (play.spmap[*pmap].last_time + 180000))
862 {
863 //this sprite can come back online now
864 play.spmap[*pmap].type[i] = 0;
865 }
866 }
867
868 // Resurrect sprites after 1mn
869 if (type == 8)
870 {
871 if (thisTickCount > (play.spmap[*pmap].last_time + 60000))
872 {
873 //this sprite can come back online now
874 play.spmap[*pmap].type[i] = 0;
875 }
876 }
877 }
878 }
879
880 /**
881 * Load 1 screen from specified map.dat in specified memory buffer
882 */
load_map_to(char * path,const int num,struct small_map * screen)883 int load_map_to(char* path, const int num, struct small_map* screen)
884 {
885 /* Instead of using 'fseek(...)' when we want to skip a little bit
886 of data, we read it to this buffer - this is much faster on PSP
887 (1000ms -> 60ms), probably related to cache validation. No
888 noticeable change on PC (<1ms). */
889 char skipbuf[10000]; // more than any fseek we do
890
891 FILE *f = NULL;
892 long holdme,lsize;
893 f = paths_dmodfile_fopen(path, "rb");
894 if (!f)
895 {
896 log_error("Cannot find %s file!!!", path);
897 return -1;
898 }
899 lsize = 31280; // sizeof(struct small_map); // under ia32, not portable
900 holdme = (lsize * (num-1));
901 fseek(f, holdme, SEEK_SET);
902 //Msg("Trying to read %d bytes with offset of %d",lsize,holdme);
903
904 /* Portably load map structure from disk */
905 int i = 0;
906 fread(skipbuf, 20, 1, f); // unused 'name' field
907 for (i = 0; i < 97; i++)
908 {
909 screen->t[i].square_full_idx0 = read_lsb_int(f);
910 fread(skipbuf, 4, 1, f); // unused 'property' field
911 screen->t[i].althard = read_lsb_int(f);
912 fread(skipbuf, 6, 1, f); // unused 'more2', 'more3', 'more4' fields
913 fread(skipbuf, 2, 1, f); // reproduce memory alignment
914 fread(skipbuf, 60, 1, f); // unused 'buff' field
915 }
916 // offset 7780
917
918 fread(skipbuf, 160, 1, f); // unused 'v' field
919 fread(skipbuf, 80, 1, f); // unused 's' field
920 // offset 8020
921
922 /* struct sprite_placement sprite[101]; */
923 /* size = 220 */
924 for (i = 0; i < 101; i++)
925 {
926 screen->sprite[i].x = read_lsb_int(f);
927 screen->sprite[i].y = read_lsb_int(f);
928 screen->sprite[i].seq = read_lsb_int(f);
929 screen->sprite[i].frame = read_lsb_int(f);
930 screen->sprite[i].type = read_lsb_int(f);
931 screen->sprite[i].size = read_lsb_int(f);
932
933 screen->sprite[i].active = fgetc(f);
934 fread(skipbuf, 3, 1, f); // reproduce memory alignment
935 // offset 28
936
937 screen->sprite[i].rotation = read_lsb_int(f);
938 screen->sprite[i].special = read_lsb_int(f);
939 screen->sprite[i].brain = read_lsb_int(f);
940
941 fread(screen->sprite[i].script, 14, 1, f);
942 screen->sprite[i].script[14-1] = '\0'; // safety
943 fread(skipbuf, 38, 1, f); // unused hit/die/talk fields
944 // offset 92
945
946 screen->sprite[i].speed = read_lsb_int(f);
947 screen->sprite[i].base_walk = read_lsb_int(f);
948 screen->sprite[i].base_idle = read_lsb_int(f);
949 screen->sprite[i].base_attack = read_lsb_int(f);
950 screen->sprite[i].base_hit = read_lsb_int(f);
951 screen->sprite[i].timer = read_lsb_int(f);
952 screen->sprite[i].que = read_lsb_int(f);
953 screen->sprite[i].hard = read_lsb_int(f);
954 // offset 124
955
956 screen->sprite[i].alt.left = read_lsb_int(f);
957 screen->sprite[i].alt.top = read_lsb_int(f);
958 screen->sprite[i].alt.right = read_lsb_int(f);
959 screen->sprite[i].alt.bottom = read_lsb_int(f);
960 // offset 140
961
962 screen->sprite[i].is_warp = read_lsb_int(f);
963 screen->sprite[i].warp_map = read_lsb_int(f);
964 screen->sprite[i].warp_x = read_lsb_int(f);
965 screen->sprite[i].warp_y = read_lsb_int(f);
966 screen->sprite[i].parm_seq = read_lsb_int(f);
967 // offset 160
968
969 screen->sprite[i].base_die = read_lsb_int(f);
970 screen->sprite[i].gold = read_lsb_int(f);
971 screen->sprite[i].hitpoints = read_lsb_int(f);
972 screen->sprite[i].strength = read_lsb_int(f);
973 screen->sprite[i].defense = read_lsb_int(f);
974 screen->sprite[i].exp = read_lsb_int(f);
975 screen->sprite[i].sound = read_lsb_int(f);
976 screen->sprite[i].vision = read_lsb_int(f);
977 screen->sprite[i].nohit = read_lsb_int(f);
978 screen->sprite[i].touch_damage = read_lsb_int(f);
979 // offset 200
980
981 int j = 0;
982 for (j = 0; j < 5; j++)
983 screen->sprite[i].buff[j] = read_lsb_int(f);
984 }
985 // offset 30204
986
987 fread(screen->script, 21, 1, f);
988 screen->script[21-1] = '\0'; // safety
989 fread(skipbuf, 1018, 1, f); // unused hit/die/talk fields
990 fread(skipbuf, 1, 1, f); // reproduce memory alignment
991 // offset 31280
992
993 fclose(f);
994 return 0;
995 }
996
997 /**
998 * Load 1 screen from map.dat, which contains all 768 game screens
999 */
load_map(const int num)1000 int load_map(const int num)
1001 {
1002 if (load_map_to(current_map, num, &pam) < 0)
1003 return -1;
1004
1005 spr[1].move_active = 0;
1006 if (dversion >= 108)
1007 spr[1].move_nohard = 0;
1008 spr[1].freeze = 0;
1009 screenlock = 0;
1010 fill_whole_hard();
1011 fix_dead_sprites();
1012
1013 if (!dinkedit)
1014 check_midi();
1015
1016 // draw_map_game();
1017 return 0;
1018 }
1019
1020 /**
1021 * Save screen number 'num' in the map. Only used by the editor.
1022 */
save_map(const int num)1023 void save_map(const int num)
1024 {
1025 /* Instead of using 'fseek(...)' when we want to skip a little bit
1026 of data, we read it to this buffer - this is much faster on PSP
1027 (1000ms -> 60ms), probably related to cache validation. No
1028 noticeable change on PC (<1ms). */
1029 char skipbuf[10000]; // more than any fseek we do
1030 memset(skipbuf, 0, 10000);
1031
1032 FILE *f = NULL;
1033 long holdme,lsize;
1034
1035 log_info("Saving map data..");
1036 if (num > 0)
1037 {
1038 f = paths_dmodfile_fopen(current_map, "r+b");
1039 if (f == NULL)
1040 {
1041 perror("Cannot save map");
1042 return;
1043 }
1044 lsize = 31280; // sizeof(struct small_map); // under ia32, not portable
1045 holdme = (lsize * (num-1));
1046 fseek(f, holdme, SEEK_SET);
1047
1048
1049 /* Portably dump map structure */
1050 int i = 0;
1051 char name[20] = "Smallwood";
1052 fwrite(name, 20, 1, f);
1053 for (i = 0; i < 97; i++)
1054 {
1055 write_lsb_int(pam.t[i].square_full_idx0, f);
1056 fwrite(skipbuf, 4, 1, f); // unused 'property' field
1057 write_lsb_int(pam.t[i].althard, f);
1058 fwrite(skipbuf, 6, 1, f); // unused 'more2', 'more3', 'more4' fields
1059 fwrite(skipbuf, 2, 1, f); // reproduce memory alignment
1060 fwrite(skipbuf, 60, 1, f); // unused 'buff' field
1061 }
1062 // offset 7780
1063
1064 fwrite(skipbuf, 160, 1, f); // unused 'v' field
1065 fwrite(skipbuf, 80, 1, f); // unused 's' field
1066 // offset 8020
1067
1068 /* struct sprite_placement sprite[101]; */
1069 /* size = 220 */
1070 for (i = 0; i < 101; i++)
1071 {
1072 write_lsb_int(pam.sprite[i].x, f);
1073 write_lsb_int(pam.sprite[i].y, f);
1074 write_lsb_int(pam.sprite[i].seq, f);
1075 write_lsb_int(pam.sprite[i].frame, f);
1076 write_lsb_int(pam.sprite[i].type, f);
1077 write_lsb_int(pam.sprite[i].size, f);
1078
1079 fputc(pam.sprite[i].active, f);
1080 fwrite(skipbuf, 3, 1, f); // reproduce memory alignment
1081 // offset 28
1082
1083 write_lsb_int(pam.sprite[i].rotation, f);
1084 write_lsb_int(pam.sprite[i].special, f);
1085 write_lsb_int(pam.sprite[i].brain, f);
1086
1087 fwrite(pam.sprite[i].script, 14, 1, f);
1088 fwrite(skipbuf, 38, 1, f); // reproduce memory alignment
1089 // offset 92
1090
1091 write_lsb_int(pam.sprite[i].speed, f);
1092 write_lsb_int(pam.sprite[i].base_walk, f);
1093 write_lsb_int(pam.sprite[i].base_idle, f);
1094 write_lsb_int(pam.sprite[i].base_attack, f);
1095 write_lsb_int(pam.sprite[i].base_hit, f);
1096 write_lsb_int(pam.sprite[i].timer, f);
1097 write_lsb_int(pam.sprite[i].que, f);
1098 write_lsb_int(pam.sprite[i].hard, f);
1099 // offset 124
1100
1101 write_lsb_int(pam.sprite[i].alt.left, f);
1102 write_lsb_int(pam.sprite[i].alt.top, f);
1103 write_lsb_int(pam.sprite[i].alt.right, f);
1104 write_lsb_int(pam.sprite[i].alt.bottom, f);
1105 // offset 140
1106
1107 write_lsb_int(pam.sprite[i].is_warp, f);
1108 write_lsb_int(pam.sprite[i].warp_map, f);
1109 write_lsb_int(pam.sprite[i].warp_x, f);
1110 write_lsb_int(pam.sprite[i].warp_y, f);
1111 write_lsb_int(pam.sprite[i].parm_seq, f);
1112 // offset 160
1113
1114 write_lsb_int(pam.sprite[i].base_die, f);
1115 write_lsb_int(pam.sprite[i].gold, f);
1116 write_lsb_int(pam.sprite[i].hitpoints, f);
1117 write_lsb_int(pam.sprite[i].strength, f);
1118 write_lsb_int(pam.sprite[i].defense, f);
1119 write_lsb_int(pam.sprite[i].exp, f);
1120 write_lsb_int(pam.sprite[i].sound, f);
1121 write_lsb_int(pam.sprite[i].vision, f);
1122 write_lsb_int(pam.sprite[i].nohit, f);
1123 write_lsb_int(pam.sprite[i].touch_damage, f);
1124 // offset 200
1125
1126 int j = 0;
1127 for (j = 0; j < 5; j++)
1128 write_lsb_int(pam.sprite[i].buff[j], f);
1129 }
1130 // offset 30204
1131
1132 fwrite(pam.script, 21, 1, f);
1133 fwrite(skipbuf, 1018, 1, f); // unused random/load/buffer fields
1134 fwrite(skipbuf, 1, 1, f); // reproduce memory alignment
1135 // offset 31280
1136
1137 fclose(f);
1138 }
1139
1140 log_info("Done saving map data..");
1141 }
1142
1143
1144
1145 /**
1146 * Save dink.dat (index of map offsets + midi# + indoor/outdoor)
1147 */
save_info(void)1148 void save_info(void)
1149 {
1150 FILE *f = paths_dmodfile_fopen(current_dat, "wb");
1151 if (f == NULL)
1152 {
1153 perror("Cannot save dink.dat");
1154 return;
1155 }
1156
1157 /* Portably dump struct map_info to disk */
1158 int i = 0;
1159 char name[20] = "Smallwood";
1160 fwrite(name, 20, 1, f);
1161 for (i = 0; i < 769; i++)
1162 write_lsb_int(map.loc[i], f);
1163 for (i = 0; i < 769; i++)
1164 write_lsb_int(map.music[i], f);
1165 for (i = 0; i < 769; i++)
1166 write_lsb_int(map.indoor[i], f);
1167 fseek(f, 2240, SEEK_CUR); // unused field
1168
1169 fclose(f);
1170 }
1171
1172
1173
load_game(int num)1174 /*bool*/int load_game(int num)
1175 {
1176 /* Instead of using 'fseek(...)' when we want to skip a little bit
1177 of data, we read it to this buffer - this is much faster on PSP
1178 (1000ms -> 60ms), probably related to cache validation. No
1179 noticeable change on PC (<1ms). */
1180 char skipbuf[10000]; // more than any fseek we do
1181
1182 FILE *f = NULL;
1183
1184 //lets get rid of our magic and weapon scripts
1185 if (weapon_script != 0)
1186 {
1187 if (locate(weapon_script, "DISARM"))
1188 {
1189 run_script(weapon_script);
1190 }
1191 }
1192
1193 if (magic_script != 0 && locate(magic_script, "DISARM"))
1194 run_script(magic_script);
1195
1196 bow.active = /*false*/0;
1197 weapon_script = 0;
1198 magic_script = 0;
1199 midi_active = /*true*/1;
1200
1201 if (last_saved_game > 0)
1202 {
1203 log_info("Modifying saved game.");
1204 if (!add_time_to_saved_game(last_saved_game))
1205 log_error("Error modifying saved game.");
1206 }
1207 StopMidi();
1208
1209 f = paths_savegame_fopen(num, "rb");
1210 if (!f)
1211 {
1212 log_error("Couldn't load save game %d", num);
1213 return /*false*/0;
1214 }
1215
1216
1217 /* Portably load struct player_info play from disk */
1218 int i = 0;
1219 // TODO: check 'version' field and warn/upgrade/downgrade if
1220 // savegame version != dversion
1221 fread(skipbuf, 4, 1, f);
1222 fread(skipbuf, 77+1, 1, f); // skip save_game_info, cf. save_game_small(...)
1223 fread(skipbuf, 118, 1, f); // unused
1224 // offset 200
1225 play.minutes = read_lsb_int(f);
1226 spr[1].x = read_lsb_int(f);
1227 spr[1].y = read_lsb_int(f);
1228 fread(skipbuf, 4, 1, f); // unused 'die' field
1229 spr[1].size = read_lsb_int(f);
1230 spr[1].defense = read_lsb_int(f);
1231 spr[1].dir = read_lsb_int(f);
1232 spr[1].pframe = read_lsb_int(f);
1233 spr[1].pseq = read_lsb_int(f);
1234 spr[1].seq = read_lsb_int(f);
1235 spr[1].frame = read_lsb_int(f);
1236 spr[1].strength = read_lsb_int(f);
1237 spr[1].base_walk = read_lsb_int(f);
1238 spr[1].base_idle = read_lsb_int(f);
1239 spr[1].base_hit = read_lsb_int(f);
1240 spr[1].que = read_lsb_int(f);
1241 // offset 264
1242
1243 // skip first originally unused mitem entry
1244 fread(skipbuf, 20, 1, f);
1245 for (i = 0; i < NB_MITEMS; i++)
1246 {
1247 play.mitem[i].active = fgetc(f);
1248 fread(play.mitem[i].name, 11, 1, f);
1249 /* The item script could overflow, overwriting 'seq'; if */
1250 play.mitem[i].name[11-1] = '\0'; // safety
1251 play.mitem[i].seq = read_lsb_int(f);
1252 play.mitem[i].frame = read_lsb_int(f);
1253 }
1254 // skip first originally unused item entry
1255 fread(skipbuf, 20, 1, f);
1256 for (i = 0; i < NB_ITEMS; i++)
1257 {
1258 play.item[i].active = fgetc(f);
1259 fread(play.item[i].name, 11, 1, f);
1260 play.item[i].name[11-1] = '\0'; // safety
1261 play.item[i].seq = read_lsb_int(f);
1262 play.item[i].frame = read_lsb_int(f);
1263 }
1264 // offset 784
1265
1266 play.curitem = read_lsb_int(f) - 1;
1267 fread(skipbuf, 4, 1, f); // reproduce unused 'unused' field
1268 fread(skipbuf, 4, 1, f); // reproduce unused 'counter' field
1269 fread(skipbuf, 1, 1, f); // reproduce unused 'idle' field
1270 fread(skipbuf, 3, 1, f); // reproduce memory alignment
1271 // offset 796
1272
1273 for (i = 0; i < 769; i++)
1274 {
1275 /* Thoses are char arrays, not null-terminated strings */
1276 int j = 0;
1277 fread(play.spmap[i].type, 100, 1, f);
1278 for (j = 0; j < 100; j++)
1279 play.spmap[i].seq[j] = read_lsb_short(f);
1280 fread(play.spmap[i].frame, 100, 1, f);
1281 play.spmap[i].last_time = read_lsb_int(f);
1282 }
1283
1284 /* Here's we'll perform a few tricks to respect a misconception in
1285 the original savegame format */
1286 // skip first originally unused play.button entry
1287 fread(skipbuf, 4, 1, f);
1288 // first play.var entry (cf. below) was overwritten by
1289 // play.button[10], writing 10 play.button entries:
1290 for (i = 0; i < 10; i++) // use fixed 10 rather than NB_BUTTONS
1291 input_set_button_action(i, read_lsb_int(f));
1292 // skip the rest of first unused play.var entry
1293 fread(skipbuf, 32-4, 1, f);
1294
1295 // reading the rest of play.var
1296 for (i = 1; i < MAX_VARS; i++)
1297 {
1298 play.var[i].var = read_lsb_int(f);
1299 fread(play.var[i].name, 20, 1, f);
1300 play.var[i].name[20-1] = '\0'; // safety
1301 play.var[i].scope = read_lsb_int(f);
1302 play.var[i].active = fgetc(f);
1303 fread(skipbuf, 3, 1, f); // reproduce memory alignment
1304 }
1305
1306 play.push_active = fgetc(f);
1307 fread(skipbuf, 3, 1, f); // reproduce memory alignment
1308 play.push_dir = read_lsb_int(f);
1309
1310 play.push_timer = read_lsb_int(f);
1311
1312 play.last_talk = read_lsb_int(f);
1313 play.mouse = read_lsb_int(f);
1314 play.item_magic = fgetc(f);
1315 fread(skipbuf, 3, 1, f); // reproduce memory alignment
1316 play.last_map = read_lsb_int(f);
1317 fread(skipbuf, 4, 1, f); // reproduce unused 'crap' field
1318 fread(skipbuf, 95 * 4, 1, f); // reproduce unused 'buff' field
1319 fread(skipbuf, 20 * 4, 1, f); // reproduce unused 'dbuff' field
1320 fread(skipbuf, 10 * 4, 1, f); // reproduce unused 'lbuff' field
1321
1322 /* v1.08: use wasted space for storing file location of map.dat,
1323 dink.dat, palette, and tiles */
1324 /* char cbuff[6000]; */
1325 /* Thoses are char arrays, not null-terminated strings */
1326 fread(play.mapdat, 50, 1, f);
1327 fread(play.dinkdat, 50, 1, f);
1328 fread(play.palette, 50, 1, f);
1329
1330 for (i = 0; i < GFX_TILES_NB_SETS+1; i++)
1331 {
1332 fread(play.tile[i].file, 50, 1, f);
1333 play.tile[i].file[50-1] = '\0'; // safety
1334 }
1335 for (i = 0; i < 100; i++)
1336 {
1337 fread(play.func[i].file, 10, 1, f);
1338 play.func[i].file[10-1] = '\0'; // safety
1339 fread(play.func[i].func, 20, 1, f);
1340 play.func[i].func[20-1] = '\0'; // safety
1341 }
1342 /* Remains 750 unused chars at the end of the file. */
1343 /* fread(play.cbuff, 750, 1, f); */
1344
1345 fclose(f);
1346
1347
1348 if (dversion >= 108)
1349 {
1350 // new map, if exist
1351 if (strlen (play.mapdat) > 0 && strlen (play.dinkdat) > 0)
1352 {
1353 strcpy (current_map, play.mapdat);
1354 strcpy (current_dat, play.dinkdat);
1355 load_info();
1356 }
1357
1358 // load palette
1359 if (strlen(play.palette) > 0)
1360 {
1361 if (gfx_palette_set_from_bmp(play.palette) < 0)
1362 log_error("Couldn't load palette from '%s': %s", play.palette, SDL_GetError());
1363 gfx_palette_get_phys(GFX_real_pal);
1364 }
1365
1366 /* Reload tiles */
1367 tiles_load_default();
1368
1369 /* Replace with custom tiles if needed */
1370 for (i = 1; i <= GFX_TILES_NB_SETS; i++)
1371 if (strlen(play.tile[i].file) > 0)
1372 tiles_load_slot(play.tile[i].file, i);
1373 }
1374
1375
1376 spr[1].damage = 0;
1377 walk_off_screen = 0;
1378 spr[1].nodraw = 0;
1379 push_active = 1;
1380
1381 time(&time_start);
1382
1383 int script = load_script("main", 0, /*true*/1);
1384 locate(script, "main");
1385 run_script(script);
1386 //lets attach our vars to the scripts
1387
1388 attach();
1389 log_debug("Attached vars.");
1390 dinkspeed = 3;
1391
1392 if (*pcur_weapon >= 1 && *pcur_weapon <= NB_ITEMS)
1393 {
1394 if (play.item[*pcur_weapon - 1].active == 0)
1395 {
1396 *pcur_weapon = 1;
1397 weapon_script = 0;
1398 log_error("Loadgame error: Player doesn't have armed weapon - changed to 1.");
1399 }
1400 else
1401 {
1402 weapon_script = load_script(play.item[*pcur_weapon - 1].name, 1000, /*false*/0);
1403 if (locate(weapon_script, "DISARM"))
1404 run_script(weapon_script);
1405 weapon_script = load_script(play.item[*pcur_weapon - 1].name, 1000, /*false*/0);
1406 if (locate(weapon_script, "ARM"))
1407 run_script(weapon_script);
1408 }
1409 }
1410 if (*pcur_magic >= 1 && *pcur_magic <= NB_MITEMS)
1411 {
1412 if (play.item[*pcur_magic - 1].active == /*false*/0)
1413 {
1414 *pcur_magic = 0;
1415 magic_script = 0;
1416 log_error("Loadgame error: Player doesn't have armed magic - changed to 0.");
1417 }
1418 else
1419 {
1420
1421 magic_script = load_script(play.mitem[*pcur_magic - 1].name, 1000, /*false*/0);
1422 if (locate(magic_script, "DISARM"))
1423 run_script(magic_script);
1424 magic_script = load_script(play.mitem[*pcur_magic - 1].name, 1000, /*false*/0);
1425 if (locate(magic_script, "ARM"))
1426 run_script(magic_script);
1427 }
1428 }
1429 kill_repeat_sounds_all();
1430 load_map(map.loc[*pmap]);
1431 log_info("Loaded map.");
1432 draw_map_game();
1433 log_info("Map drawn.");
1434
1435 last_saved_game = num;
1436
1437 return /*true*/1;
1438 }
1439
add_time_to_saved_game(int num)1440 /*bool*/int add_time_to_saved_game(int num)
1441 {
1442 FILE *f = NULL;
1443
1444 f = paths_savegame_fopen(num, "rb");
1445 if (!f)
1446 {
1447 log_error("Couldn't load save game %d", num);
1448 return /*false*/0;
1449 }
1450
1451 int minutes = 0;
1452 int minutes_offset = 200;
1453 fseek(f, minutes_offset, SEEK_SET);
1454 minutes = read_lsb_int(f);
1455 fclose(f);
1456
1457 //great, now let's resave it with added time
1458 log_info("Ok, adding time.");
1459 time_t ct;
1460
1461 time(&ct);
1462 minutes += (int) (difftime(ct,time_start) / 60);
1463
1464 f = paths_savegame_fopen(num, "rb+");
1465 if (f)
1466 {
1467 fseek(f, minutes_offset, SEEK_SET);
1468 write_lsb_int(minutes, f);
1469 fclose(f);
1470 }
1471 log_info("Wrote it.(%d of time)", minutes);
1472
1473 return /*true*/1;
1474 }
1475
save_game(int num)1476 void save_game(int num)
1477 {
1478 /* Instead of using 'fseek(...)' when we want to skip a little bit
1479 of data, we read it to this buffer - this is much faster on PSP
1480 (1000ms -> 60ms), probably related to cache validation. No
1481 noticeable change on PC (<1ms). */
1482 char skipbuf[10000]; // more than any fseek we do
1483 memset(skipbuf, 0, 10000);
1484
1485 FILE *f;
1486
1487 //lets set some vars first
1488 time_t ct;
1489 time(&ct);
1490 play.minutes += (int) (difftime(ct,time_start) / 60);
1491 //reset timer
1492 time(&time_start);
1493
1494 // save game things for storing new map, palette, and tile
1495 // information
1496 strncpy (play.mapdat, current_map, 50);
1497 strncpy (play.dinkdat, current_dat, 50);
1498
1499 last_saved_game = num;
1500 f = paths_savegame_fopen(num, "wb");
1501 if (f == NULL)
1502 {
1503 perror("Cannot save game");
1504 return;
1505 }
1506
1507 /* Portably dump struct player_info play to disk */
1508 int i = 0;
1509 write_lsb_int(dversion, f);
1510 // set_save_game_info() support:
1511 {
1512 char* info_temp = strdup(save_game_info);
1513 decipher_string(&info_temp, 0);
1514 fwrite(info_temp, 77+1, 1, f);
1515 free(info_temp);
1516 }
1517 fwrite(skipbuf, 118, 1, f); // unused
1518 // offset 200
1519 write_lsb_int(play.minutes, f);
1520 write_lsb_int(spr[1].x, f);
1521 write_lsb_int(spr[1].y, f);
1522 fwrite(skipbuf, 4, 1, f); // unused 'die' field
1523 write_lsb_int(spr[1].size, f);
1524 write_lsb_int(spr[1].defense, f);
1525 write_lsb_int(spr[1].dir, f);
1526 write_lsb_int(spr[1].pframe, f);
1527 write_lsb_int(spr[1].pseq, f);
1528 write_lsb_int(spr[1].seq, f);
1529 write_lsb_int(spr[1].frame, f);
1530 write_lsb_int(spr[1].strength, f);
1531 write_lsb_int(spr[1].base_walk, f);
1532 write_lsb_int(spr[1].base_idle, f);
1533 write_lsb_int(spr[1].base_hit, f);
1534 write_lsb_int(spr[1].que, f);
1535 // offset 264
1536
1537 // skip first originally unused mitem entry
1538 fwrite(skipbuf, 20, 1, f);
1539 for (i = 0; i < NB_MITEMS; i++)
1540 {
1541 fputc(play.mitem[i].active, f);
1542 fwrite(play.mitem[i].name, 11, 1, f);
1543 write_lsb_int(play.mitem[i].seq, f);
1544 write_lsb_int(play.mitem[i].frame, f);
1545 }
1546 // skip first originally unused item entry
1547 fwrite(skipbuf, 20, 1, f);
1548 for (i = 0; i < NB_ITEMS; i++)
1549 {
1550 fputc(play.item[i].active, f);
1551 fwrite(play.item[i].name, 11, 1, f);
1552 write_lsb_int(play.item[i].seq, f);
1553 write_lsb_int(play.item[i].frame, f);
1554 }
1555 // offset 784
1556
1557 write_lsb_int(play.curitem + 1, f);
1558 fwrite(skipbuf, 4, 1, f); // reproduce unused 'unused' field
1559 fwrite(skipbuf, 4, 1, f); // reproduce unused 'counter' field
1560 fwrite(skipbuf, 1, 1, f); // reproduce unused 'idle' field
1561 fwrite(skipbuf, 3, 1, f); // reproduce memory alignment
1562 // offset 796
1563
1564 for (i = 0; i < 769; i++)
1565 {
1566 int j = 0;
1567 fwrite(play.spmap[i].type, 100, 1, f);
1568 for (j = 0; j < 100; j++)
1569 write_lsb_short(play.spmap[i].seq[j], f);
1570 fwrite(play.spmap[i].frame, 100, 1, f);
1571 write_lsb_int(play.spmap[i].last_time, f);
1572 }
1573
1574 /* Here's we'll perform a few tricks to respect a misconception in
1575 the original savegame format */
1576 // skip first originally unused play.button entry
1577 fwrite(skipbuf, 4, 1, f);
1578 // first play.var entry (cf. below) was overwritten by
1579 // play.button[10], writing 10 play.button entries:
1580 for (i = 0; i < 10; i++) // use fixed 10 rather than NB_BUTTONS
1581 write_lsb_int(input_get_button_action(i), f);
1582 // skip the rest of first unused play.var entry
1583 fwrite(skipbuf, 32-4, 1, f);
1584
1585 // writing the rest of play.var
1586 for (i = 1; i < MAX_VARS; i++)
1587 {
1588 write_lsb_int(play.var[i].var, f);
1589 fwrite(play.var[i].name, 20, 1, f);
1590 write_lsb_int(play.var[i].scope, f);
1591 fputc(play.var[i].active, f);
1592 fwrite(skipbuf, 3, 1, f); // reproduce memory alignment
1593 }
1594
1595 fputc(play.push_active, f);
1596 fwrite(skipbuf, 3, 1, f); // reproduce memory alignment
1597 write_lsb_int(play.push_dir, f);
1598
1599 write_lsb_int(play.push_timer, f);
1600
1601 write_lsb_int(play.last_talk, f);
1602 write_lsb_int(play.mouse, f);
1603 fputc(play.item_magic, f);
1604 fwrite(skipbuf, 3, 1, f); // reproduce memory alignment
1605 write_lsb_int(play.last_map, f);
1606 fwrite(skipbuf, 4, 1, f); // reproduce unused 'crap' field
1607 fwrite(skipbuf, 95 * 4, 1, f); // reproduce unused 'buff' field
1608 fwrite(skipbuf, 20 * 4, 1, f); // reproduce unused 'dbuff' field
1609 fwrite(skipbuf, 10 * 4, 1, f); // reproduce unused 'lbuff' field
1610
1611 /* v1.08: use wasted space for storing file location of map.dat,
1612 dink.dat, palette, and tiles */
1613 /* char cbuff[6000];*/
1614 fwrite(play.mapdat, 50, 1, f);
1615 fwrite(play.dinkdat, 50, 1, f);
1616 fwrite(play.palette, 50, 1, f);
1617
1618 for (i = 0; i < GFX_TILES_NB_SETS+1; i++)
1619 fwrite(play.tile[i].file, 50, 1, f);
1620 for (i = 0; i < 100; i++)
1621 {
1622 fwrite(play.func[i].file, 10, 1, f);
1623 fwrite(play.func[i].func, 20, 1, f);
1624 }
1625 fwrite(skipbuf, 750, 1, f);
1626
1627 fclose(f);
1628 }
1629
1630
1631
kill_all_vars()1632 void kill_all_vars()
1633 {
1634 memset(&play, 0, sizeof(play));
1635 }
1636
kill_cur_item()1637 void kill_cur_item()
1638 {
1639 if (*pcur_weapon >= 1 && *pcur_weapon <= NB_ITEMS)
1640 {
1641 if (play.item[*pcur_weapon - 1].active == 1)
1642 {
1643 if (weapon_script != 0 && locate(weapon_script, "DISARM"))
1644 run_script(weapon_script);
1645 weapon_script = load_script(play.item[*pcur_weapon - 1].name, 0, /*false*/0);
1646 play.item[*pcur_weapon - 1].active = 0;
1647 *pcur_weapon = 0;
1648 if (weapon_script != 0 && locate(weapon_script, "HOLDINGDROP"))
1649 run_script(weapon_script);
1650 if (weapon_script != 0 && locate(weapon_script, "DROP"))
1651 run_script(weapon_script);
1652 weapon_script = 0;
1653 }
1654 else
1655 {
1656 log_error("Can't kill cur item, none armed.");
1657 }
1658 }
1659 }
1660
kill_item_script(char * name)1661 void kill_item_script(char* name)
1662 {
1663 int select = 0;
1664 {
1665 int i = 0;
1666 for (; i < NB_ITEMS; i++)
1667 {
1668 if (play.item[i].active)
1669 if (compare(play.item[i].name, name))
1670 {
1671 select = i;
1672 goto found;
1673 }
1674 }
1675 }
1676 return;
1677
1678 found:
1679 if (*pcur_weapon - 1 == select)
1680 {
1681 //holding it right now
1682 if (locate(weapon_script, "HOLDINGDROP"))
1683 run_script(weapon_script);
1684 if (locate(weapon_script, "DISARM"))
1685 run_script(weapon_script);
1686
1687 *pcur_weapon = 0;
1688 weapon_script = 0;
1689 }
1690
1691 int script = load_script(play.item[select].name, 0, /*false*/0);
1692 play.item[select].active = /*false*/0;
1693
1694 if (locate(script, "DROP"))
1695 run_script(script);
1696
1697 draw_status_all();
1698 }
1699
1700
kill_mitem_script(char * name)1701 void kill_mitem_script(char* name)
1702 {
1703 int select = 0;
1704 {
1705 int i = 0;
1706 for (; i < NB_MITEMS; i++)
1707 {
1708 if (play.mitem[i].active)
1709 if (compare(play.mitem[i].name, name))
1710 {
1711 select = i;
1712 goto found;
1713 }
1714 }
1715 }
1716 return;
1717
1718 found:
1719 if (*pcur_magic - 1 == select)
1720 {
1721 //holding it right now
1722 if (locate(magic_script, "HOLDINGDROP"))
1723 run_script(magic_script);
1724 if (locate(magic_script, "DISARM"))
1725 run_script(magic_script);
1726
1727 // TODO: this should be *pcur_magic; keeping for compatibility
1728 // for now:
1729 *pcur_weapon = 0;
1730 magic_script = 0;
1731 }
1732
1733 int script = load_script(play.mitem[select].name, 0, /*false*/0);
1734 play.mitem[select].active = 0;
1735
1736 if (locate(script, "DROP"))
1737 run_script(script);
1738
1739 draw_status_all();
1740 }
1741
1742
kill_cur_magic()1743 void kill_cur_magic()
1744 {
1745 if (*pcur_magic >= 1 && *pcur_magic <= NB_MITEMS)
1746 {
1747 if (play.mitem[*pcur_magic - 1].active == 1)
1748 {
1749 if (magic_script != 0 && locate(magic_script, "DISARM"))
1750 run_script(magic_script);
1751 magic_script = load_script(play.mitem[*pcur_magic - 1].name, 0, /*false*/0);
1752 play.mitem[*pcur_magic - 1].active = /*false*/0;
1753 *pcur_magic = 0;
1754
1755 if (magic_script != 0 && locate(magic_script, "HOLDINGDROP"))
1756 run_script(magic_script);
1757 if (magic_script != 0 && locate(magic_script, "DROP"))
1758 run_script(magic_script);
1759 magic_script = 0;
1760 }
1761 else
1762 {
1763 log_error("Can't kill cur magic, none armed.");
1764 }
1765 }
1766 }
1767
1768
1769 /**
1770 * Remember last time we entered this screen (so we can disable
1771 * sprites for some minutes, e.g. monsters)
1772 */
update_screen_time()1773 void update_screen_time()
1774 {
1775 //Msg("Cur time is %d", play.spmap[*pmap].last_time);
1776 //Msg("Map is %d..", *pmap);
1777 play.spmap[*pmap].last_time = thisTickCount;
1778 //Msg("Time was saved as %d", play.spmap[*pmap].last_time);
1779 }
1780
1781
1782 /**
1783 * Load dink.dat to specified memory buffer
1784 */
load_info_to(char * path,struct map_info * mymap)1785 int load_info_to(char* path, struct map_info *mymap)
1786 {
1787 FILE *f = NULL;
1788
1789 f = paths_dmodfile_fopen(path, "rb");
1790 if (!f)
1791 return -1;
1792
1793 log_info("World data loaded.");
1794
1795 /* Portably load struct map_info from disk */
1796 int i = 0;
1797 fseek(f, 20, SEEK_CUR); // unused 'name' field
1798 for (i = 0; i < 769; i++)
1799 mymap->loc[i] = read_lsb_int(f);
1800 for (i = 0; i < 769; i++)
1801 mymap->music[i] = read_lsb_int(f);
1802 for (i = 0; i < 769; i++)
1803 mymap->indoor[i] = read_lsb_int(f);
1804 fseek(f, 2240, SEEK_CUR); // unused space
1805
1806 fclose(f);
1807
1808 return 0;
1809 }
1810
1811 /**
1812 * Load dink.dat, an offsets index to screens stored in map.dat, with
1813 * some metadata (midi #, indoor/outdoor)
1814 */
load_info(void)1815 void load_info(void)
1816 {
1817 int result = load_info_to(current_dat, &map);
1818 if (result < 0)
1819 {
1820 //make new data file
1821 save_info();
1822 return;
1823 }
1824 }
1825
1826 /***
1827 * Saves hard.dat (only used from the editor)
1828 */
save_hard(void)1829 void save_hard(void)
1830 {
1831 /* Instead of using 'fseek(...)' when we want to skip a little bit
1832 of data, we read it to this buffer - this is much faster on PSP
1833 (1000ms -> 60ms), probably related to cache validation. No
1834 noticeable change on PC (<1ms). */
1835 char skipbuf[10000]; // more than any fseek we do
1836 memset(skipbuf, 0, 10000);
1837
1838 FILE *f = paths_dmodfile_fopen("hard.dat", "wb");
1839 if (!f)
1840 {
1841 perror("Couldn't save hard.dat");
1842 return;
1843 }
1844
1845 /* Portably dump struct hardness hmap to disk */
1846 int i = 0;
1847 for (i = 0; i < HARDNESS_NB_TILES; i++)
1848 {
1849 int j = 0;
1850 for (j = 0; j < 51; j++)
1851 fwrite(hmap.htile[i].x[j].y, 51, 1, f);
1852 fputc(hmap.htile[i].used, f);
1853 fwrite(skipbuf, 2, 1, f); // reproduce memory alignment
1854 fwrite(skipbuf, 4, 1, f); // unused 'hold' field
1855 }
1856 for (i = 0; i < GFX_TILES_NB_SQUARES; i++)
1857 write_lsb_int(hmap.btile_default[i], f);
1858 fseek(f, (8000-GFX_TILES_NB_SQUARES)*4, SEEK_CUR); // reproduce unused data
1859
1860 fclose(f);
1861 }
1862
1863
1864 /**
1865 * Load hard.dat which contains tile hardness information.
1866 *
1867 * Unlike 1.08, don't reset and save hard.dat during game in case
1868 * e.g. it was just being written by an external editor.
1869 */
load_hard(void)1870 void load_hard(void)
1871 {
1872 /* Instead of using 'fseek(...)' when we want to skip a little bit
1873 of data, we read it to this buffer - this is much faster on PSP
1874 (1000ms -> 60ms), probably related to cache validation. No
1875 noticeable change on PC (<1ms). */
1876 char skipbuf[10000]; // more than any fseek we do
1877
1878 FILE *f = NULL;
1879
1880 /* Try loading the D-Mod hard.dat */
1881 f = paths_dmodfile_fopen("hard.dat", "rb");
1882
1883 /* Fallback to the default hard.dat */
1884 if (f == NULL)
1885 f = paths_fallbackfile_fopen("hard.dat", "rb");
1886
1887 if (f == NULL)
1888 {
1889 //make new data file
1890 memset(&hmap, 0, sizeof(struct hardness));
1891 return;
1892 }
1893
1894 /* Portably load struct hardness hmap from disk */
1895 int i = 0;
1896 for (i = 0; i < HARDNESS_NB_TILES; i++)
1897 {
1898 int j = 0;
1899 for (j = 0; j < 51; j++)
1900 fread(hmap.htile[i].x[j].y, 51, 1, f);
1901 hmap.htile[i].used = fgetc(f);
1902 fread(skipbuf, 2, 1, f); // reproduce memory alignment
1903 fread(skipbuf, 4, 1, f); // unused 'hold' field
1904 }
1905 for (i = 0; i < GFX_TILES_NB_SQUARES; i++)
1906 hmap.btile_default[i] = read_lsb_int(f);
1907 fseek(f, (8000-GFX_TILES_NB_SQUARES)*4, SEEK_CUR); // reproduce unused data
1908
1909 fclose(f);
1910 }
1911
1912
1913
1914 /**
1915 * Parse a dink.ini line, and store instructions for later processing
1916 * (used in game initialization through 'load_batch')
1917 */
pre_figure_out(char * line)1918 void pre_figure_out(char* line)
1919 {
1920 int i;
1921 char* ev[10];
1922 memset(&ev, 0, sizeof(ev));
1923 for (i = 0; i < 10; i++)
1924 ev[i] = separate_string(line, i+1, ' ');
1925 char *command = ev[0];
1926
1927 // PLAYMIDI filename
1928 if (compare(command, "playmidi"))
1929 {
1930 char* midi_filename = ev[1];
1931 if (!dinkedit)
1932 PlayMidi(midi_filename);
1933 }
1934
1935 // LOAD_SEQUENCE_NOW path seq BLACK
1936 // LOAD_SEQUENCE_NOW path seq LEFTALIGN
1937 // LOAD_SEQUENCE_NOW path seq NOTANIM
1938 // LOAD_SEQUENCE_NOW path seq speed
1939 // LOAD_SEQUENCE_NOW path seq speed offsetx offsety hard.left hard.top hard.right hard.bottom
1940 else if (compare(command, "LOAD_SEQUENCE_NOW"))
1941 {
1942 rect hardbox;
1943 memset(&hardbox, 0, sizeof(rect));
1944
1945 int myseq = atol(ev[2]);
1946 seq[myseq].is_active = 1;
1947 seq_set_ini(myseq, line);
1948
1949 int flags = 0;
1950 if (compare(ev[3], "BLACK"))
1951 {
1952 flags = DINKINI_NOTANIM | DINKINI_BLACK;
1953 }
1954 else if (compare(ev[3], "LEFTALIGN"))
1955 {
1956 flags = DINKINI_LEFTALIGN;
1957 }
1958 else if (compare(ev[3], "NOTANIM"))
1959 {
1960 //not an animation!
1961 flags = 0;
1962 }
1963 else
1964 {
1965 //yes, an animation!
1966 hardbox.left = atol(ev[6]);
1967 hardbox.top = atol(ev[7]);
1968 hardbox.right = atol(ev[8]);
1969 hardbox.bottom = atol(ev[9]);
1970
1971 flags = DINKINI_NOTANIM;
1972 }
1973
1974 load_sprites(ev[1],atol(ev[2]),atol(ev[3]),atol(ev[4]),atol(ev[5]),
1975 hardbox, flags);
1976
1977
1978 /* In the original engine, due to a bug, make_idata() modifies
1979 unused sequence #0, but this isn't really important because
1980 sequence was already configured in was already done in
1981 'load_sprites'. This is consistent with 'figure_out', which
1982 doesn't call 'make_idata' at all. */
1983 /* We still call 'make_idata' for compatibility, to use the same
1984 number of idata, hence preserving the same max_idata. */
1985 make_idata(IDATA_SPRITE_INFO, 0,0, 0,0, hardbox);
1986 }
1987
1988 // LOAD_SEQUENCE path seq BLACK
1989 // LOAD_SEQUENCE path seq LEFTALIGN
1990 // LOAD_SEQUENCE path seq NOTANIM
1991 // LOAD_SEQUENCE path seq speed
1992 // LOAD_SEQUENCE path seq speed offsetx offsety hard.left hard.top hard.right hard.bottom
1993 else if (compare(command, "LOAD_SEQUENCE"))
1994 {
1995 int myseq = atol(ev[2]);
1996 seq_set_ini(myseq, line);
1997 seq[myseq].is_active = 1;
1998 }
1999
2000 else if (compare(command, "SET_SPRITE_INFO"))
2001 {
2002 // name seq speed offsetx offsety hardx hardy
2003 //if (k[seq[myseq].frame[myframe]].frame = 0) Msg("Changing sprite that doesn't exist...");
2004
2005 rect hardbox;
2006 int myseq = atol(ev[1]);
2007 int myframe = atol(ev[2]);
2008 rect_set(&hardbox, atol(ev[5]), atol(ev[6]), atol(ev[7]), atol(ev[8]));
2009 make_idata(IDATA_SPRITE_INFO, myseq, myframe,atol(ev[3]), atol(ev[4]),hardbox);
2010 }
2011
2012 else if (compare(command, "SET_FRAME_SPECIAL"))
2013 {
2014 rect hardbox;
2015 int myseq = atol(ev[1]);
2016 int myframe = atol(ev[2]);
2017 int special = atol(ev[3]);
2018 make_idata(IDATA_FRAME_SPECIAL, myseq, myframe, special, 0, hardbox);
2019 }
2020
2021 else if (compare(command, "SET_FRAME_DELAY"))
2022 {
2023 rect hardbox;
2024 int myseq = atol(ev[1]);
2025 int myframe = atol(ev[2]);
2026 int delay = atol(ev[3]);
2027 make_idata(IDATA_FRAME_DELAY, myseq, myframe, delay, 0, hardbox);
2028 }
2029
2030 // SET_FRAME_FRAME seq frame new_seq new_frame
2031 // SET_FRAME_FRAME seq frame -1
2032 else if (compare(command, "SET_FRAME_FRAME"))
2033 {
2034 rect hardbox;
2035 int myseq = atol(ev[1]);
2036 int myframe = atol(ev[2]);
2037 int new_seq = atol(ev[3]);
2038 int new_frame = atol(ev[4]);
2039
2040 make_idata(IDATA_FRAME_FRAME, myseq, myframe, new_seq, new_frame, hardbox);
2041 }
2042
2043 /* Clean-up */
2044 for (i = 0; i < 10; i++)
2045 free(ev[i]);
2046 }
2047
2048 /**
2049 * Parse a delayed seq[].ini or a DinkC init("...") , and act
2050 * immediately
2051 */
figure_out(char * line)2052 void figure_out(char* line)
2053 {
2054 int myseq = 0, myframe = 0;
2055 int special = 0;
2056 int special2 = 0;
2057 int i;
2058 char* ev[10];
2059 memset(&ev, 0, sizeof(ev));
2060 for (i = 0; i < 10; i++)
2061 {
2062 ev[i] = separate_string(line, i+1, ' ');
2063 if (ev[i] == NULL)
2064 ev[i] = strdup("");
2065 }
2066 char *command = ev[0];
2067
2068 // LOAD_SEQUENCE_NOW path seq BLACK
2069 // LOAD_SEQUENCE_NOW path seq LEFTALIGN
2070 // LOAD_SEQUENCE_NOW path seq NOTANIM
2071 // LOAD_SEQUENCE_NOW path seq speed offsetx offsety hard.left hard.top hard.right hard.bottom
2072 if (compare(command, "LOAD_SEQUENCE_NOW") ||
2073 compare(command, "LOAD_SEQUENCE"))
2074 {
2075 rect hardbox;
2076 memset(&hardbox, 0, sizeof(rect));
2077
2078 int myseq = atol(ev[2]);
2079 seq[myseq].is_active = 1;
2080 seq_set_ini(myseq, line);
2081
2082 int flags = 0;
2083
2084 if (compare(ev[3], "BLACK"))
2085 {
2086 flags = DINKINI_NOTANIM | DINKINI_BLACK;
2087 }
2088 else if (compare(ev[3], "LEFTALIGN"))
2089 {
2090 flags = DINKINI_LEFTALIGN;
2091 }
2092 else if (compare(ev[3], "NOTANIM"))
2093 {
2094 //not an animation!
2095 flags = 0;
2096 }
2097 else
2098 {
2099 //yes, an animation!
2100 hardbox.left = atol(ev[6]);
2101 hardbox.top = atol(ev[7]);
2102 hardbox.right = atol(ev[8]);
2103 hardbox.bottom = atol(ev[9]);
2104
2105 flags = DINKINI_NOTANIM;
2106 }
2107
2108 load_sprites(ev[1],atol(ev[2]),atol(ev[3]),atol(ev[4]),atol(ev[5]),
2109 hardbox, flags);
2110
2111 program_idata();
2112 }
2113
2114 else if (compare(command, "SET_SPRITE_INFO"))
2115 {
2116 // name seq speed offsetx offsety hardx hardy
2117 myseq = atol(ev[1]);
2118 myframe = atol(ev[2]);
2119 k[seq[myseq].frame[myframe]].xoffset = atol(ev[3]);
2120 k[seq[myseq].frame[myframe]].yoffset = atol(ev[4]);
2121 k[seq[myseq].frame[myframe]].hardbox.left = atol(ev[5]);
2122 k[seq[myseq].frame[myframe]].hardbox.top = atol(ev[6]);
2123 k[seq[myseq].frame[myframe]].hardbox.right = atol(ev[7]);
2124 k[seq[myseq].frame[myframe]].hardbox.bottom = atol(ev[8]);
2125 }
2126
2127 else if (compare(command, "SET_FRAME_SPECIAL"))
2128 {
2129 // name seq speed offsetx offsety hardx hardy
2130 myseq = atol(ev[1]);
2131 myframe = atol(ev[2]);
2132 special = atol(ev[3]);
2133
2134 seq[myseq].special[myframe] = special;
2135 log_debug("Set special. %d %d %d", myseq, myframe, special);
2136 }
2137
2138 else if (compare(command, "SET_FRAME_DELAY"))
2139 {
2140 // name seq speed offsetx offsety hardx hardy
2141 myseq = atol(ev[1]);
2142 myframe = atol(ev[2]);
2143 special = atol(ev[3]);
2144
2145 seq[myseq].delay[myframe] = special;
2146 log_debug("Set delay. %d %d %d",myseq, myframe, special);
2147 }
2148
2149 else if (compare(command, "SET_FRAME_FRAME"))
2150 {
2151 // name seq speed offsetx offsety hardx hardy
2152 myseq = atol(ev[1]);
2153 myframe = atol(ev[2]);
2154 special = atol(ev[3]);
2155 special2 = atol(ev[4]);
2156
2157 if (special == -1)
2158 seq[myseq].frame[myframe] = special;
2159 else
2160 seq[myseq].frame[myframe] = seq[special].frame[special2];
2161 log_debug("Set frame. %d %d %d", myseq, myframe, special);
2162 }
2163
2164 /* Clean-up */
2165 for (i = 0; i < 10; i++)
2166 free(ev[i]);
2167 }
2168
2169
draw_num(int mseq,char nums[50],int mx,int my)2170 int draw_num(int mseq, char nums[50], int mx, int my)
2171 {
2172 int length = 0;
2173 /* HRESULT ddrval; */
2174 int rnum = 0;
2175 int i;
2176
2177 for (i=0; i < strlen(nums); i++)
2178 {
2179 if (nums[i] == '0') rnum = 10;
2180 else if (nums[i] == '1') rnum = 1;
2181 else if (nums[i] == '2') rnum = 2;
2182 else if (nums[i] == '3') rnum = 3;
2183 else if (nums[i] == '4') rnum = 4;
2184 else if (nums[i] == '5') rnum = 5;
2185 else if (nums[i] == '6') rnum = 6;
2186 else if (nums[i] == '7') rnum = 7;
2187 else if (nums[i] == '8') rnum = 8;
2188 else if (nums[i] == '9') rnum = 9;
2189 else if (nums[i] == '/') rnum = 11;
2190 /* again: */
2191 if ((rnum != 11) && (!(mseq == SEQ_LEVEL_NUMS)))
2192 {
2193 /* ddrval = lpDDSTwo->BltFast(mx+length, my, k[seq[mseq].frame[rnum]].k, */
2194 /* &k[seq[mseq].frame[rnum]].box, DDBLTFAST_NOCOLORKEY); */
2195 // GFX
2196 {
2197 SDL_Rect dst = {mx+length, my};
2198 gfx_blit_nocolorkey(GFX_k[seq[mseq].frame[rnum]].k, NULL, GFX_lpDDSTwo, &dst);
2199 }
2200 }
2201 else
2202 {
2203 /* ddrval = lpDDSTwo->BltFast(mx+length, my, k[seq[mseq].frame[rnum]].k, */
2204 /* &k[seq[mseq].frame[rnum]].box, DDBLTFAST_SRCCOLORKEY); */
2205 /* Draw experience level number _with_ transparency */
2206 // GFX
2207 {
2208 SDL_Rect dst = {mx+length, my};
2209 SDL_BlitSurface(GFX_k[seq[mseq].frame[rnum]].k, NULL, GFX_lpDDSTwo, &dst);
2210 }
2211 }
2212
2213
2214 /* if (ddrval != DD_OK) */
2215 /* { */
2216 /* if (ddrval == DDERR_WASSTILLDRAWING) goto again; */
2217 /* //dderror(ddrval); */
2218 /* } */
2219 /* else */
2220 /* { */
2221 length += k[seq[mseq].frame[rnum]].box.right;
2222 /* } */
2223 }
2224 return(length);
2225 }
2226
next_raise(void)2227 int next_raise(void)
2228 {
2229 int crap = *plevel;
2230 int num = ((100 * crap) * crap);
2231
2232 if (num > 99999) num = 99999;
2233 return(num);
2234
2235 }
2236
2237
draw_exp()2238 void draw_exp()
2239 {
2240 char buffer[30];
2241 char nums[30];
2242 char final[30];
2243
2244 //Msg("Drawing exp.. which is %d and %d",fexp, *pexp);
2245 strcpy(final, "");
2246 sprintf(buffer, "%d", fexp);
2247 strcpy(nums, buffer);
2248 if (strlen(nums) < 5)
2249 {
2250 int i;
2251 for (i = 1; i < (6 - strlen(nums)); i++)
2252 strcat(final, "0");
2253 }
2254 strcat(final, nums);
2255 strcat(final,"/");
2256
2257 sprintf(buffer, "%d", fraise);
2258 strcpy(nums, buffer);
2259 if (strlen(nums) < 5)
2260 {
2261 int i;
2262 for (i = 1; i < (6 - strlen(nums)); i++)
2263 strcat(final, "0");
2264 }
2265 strcat(final, nums);
2266 draw_num(181, final, 404, 459);
2267
2268 }
2269
2270
draw_strength()2271 void draw_strength()
2272 {
2273 char final[30];
2274 char buffer[30];
2275 char nums[30];
2276 //Msg("Drawing exp.. which is %d and %d",fexp, *pexp);
2277 strcpy(final, "");
2278
2279 sprintf(buffer, "%d", fstrength);
2280 strcpy(nums, buffer);
2281 if (strlen(nums) < 3)
2282 {
2283 int i;
2284 for (i = 1; i < (4 - strlen(nums)); i++)
2285 strcat(final, "0");
2286 }
2287 strcat(final, nums);
2288 //Msg("Drawing %s..",final);
2289 draw_num(182, final, 81, 415);
2290 }
2291
2292
draw_defense()2293 void draw_defense()
2294 {
2295 char final[30];
2296 char buffer[30];
2297 char nums[30];
2298 //Msg("Drawing exp.. which is %d and %d",fexp, *pexp);
2299 strcpy(final, "");
2300 sprintf(buffer, "%d", fdefense);
2301 strcpy(nums, buffer);
2302 if (strlen(nums) < 3)
2303 {
2304 int i;
2305 for (i = 1; i < (4 - strlen(nums)); i++)
2306 strcat(final, "0");
2307 }
2308 strcat(final, nums);
2309 draw_num(183, final, 81, 437);
2310 }
2311
2312
draw_magic()2313 void draw_magic()
2314 {
2315 char final[30];
2316 char buffer[30];
2317 char nums[30];
2318 //Msg("Drawing exp.. which is %d and %d",fexp, *pexp);
2319 strcpy(final, "");
2320 sprintf(buffer, "%d", fmagic);
2321 strcpy(nums, buffer);
2322 if (strlen(nums) < 3)
2323 {
2324 int i;
2325 for (i = 1; i < (4 - strlen(nums)); i++)
2326 strcat(final, "0");
2327 }
2328 strcat(final, nums);
2329 draw_num(184, final, 81, 459);
2330 }
2331
2332
draw_level()2333 void draw_level()
2334 {
2335 char final[30];
2336 char buffer[30];
2337 //*plevel = 15;
2338 //Msg("Drawing level.. which is %d ",*plevel);
2339 sprintf(buffer, "%d", *plevel);
2340 strcpy(final, buffer);
2341
2342 if (strlen(final) == 1)
2343
2344 draw_num(SEQ_LEVEL_NUMS, final, 528, 456); else
2345 draw_num(SEQ_LEVEL_NUMS, final, 523, 456);
2346
2347 }
2348
2349
draw_gold()2350 void draw_gold()
2351 {
2352 char final[30];
2353 char buffer[30];
2354 char nums[30];
2355 //Msg("Drawing exp.. which is %d and %d",fexp, *pexp);
2356 strcpy(final, "");
2357 sprintf(buffer, "%d", fgold);
2358 strcpy(nums, buffer);
2359 if (strlen(nums) < 5)
2360 {
2361 int i;
2362 for (i = 1; i < (6 - strlen(nums)); i++)
2363 strcat(final, "0");
2364 }
2365 strcat(final, nums);
2366 draw_num(185, final, 298, 457);
2367 }
2368
2369
draw_bar(int life,int seqman)2370 void draw_bar(int life, int seqman)
2371 {
2372 int cur = 0;
2373 int curx = 284;
2374 int cury = 412;
2375 int rnum = 3;
2376 int curx_start = curx;
2377
2378 rect box;
2379 while(1)
2380 {
2381 cur++;
2382 if (cur > life)
2383 {
2384 cur--;
2385 int rem = (cur) - (cur / 10) * 10;
2386 if (rem != 0)
2387 {
2388 rect_copy(&box, &k[seq[seqman].frame[rnum]].box);
2389 //Msg("Drawing part bar . cur is %d", rem);
2390 box.right = (box.right * ((rem) * 10)/100);
2391 //woah, there is part of a bar remaining. Lets do it.
2392 /* again: */
2393 /* ddrval = lpDDSTwo->BltFast(curx, cury, k[seq[seqman].frame[rnum]].k, */
2394 /* &box, DDBLTFAST_NOCOLORKEY); */
2395 /* if (ddrval == DDERR_WASSTILLDRAWING) */
2396 /* goto again; */
2397 // GFX
2398 {
2399 SDL_Rect src, dst;
2400 src.x = 0; src.y = 0;
2401 src.w = GFX_k[seq[seqman].frame[rnum]].k->w * (rem * 10) / 100;
2402 src.h = GFX_k[seq[seqman].frame[rnum]].k->h;
2403 dst.x = curx; dst.y = cury;
2404 gfx_blit_nocolorkey(GFX_k[seq[seqman].frame[rnum]].k, &src, GFX_lpDDSTwo, &dst);
2405 }
2406 }
2407 //are we done?
2408 return;
2409 }
2410
2411 rnum = 2;
2412 if (cur < 11) rnum = 1;
2413 if (cur == *plifemax) rnum = 3;
2414
2415 if ((cur / 10) * 10 == cur)
2416 {
2417 /* again2: */
2418 /* ddrval = lpDDSTwo->BltFast( curx, cury, k[seq[seqman].frame[rnum]].k, */
2419 /* &k[seq[seqman].frame[rnum]].box , DDBLTFAST_NOCOLORKEY); */
2420 /* if (ddrval == DDERR_WASSTILLDRAWING) goto again2; */
2421 // GFX
2422 {
2423 SDL_Rect dst;
2424 dst.x = curx;
2425 dst.y = cury;
2426 gfx_blit_nocolorkey(GFX_k[seq[seqman].frame[rnum]].k, NULL, GFX_lpDDSTwo, &dst);
2427 }
2428
2429 //if (ddrval != DD_OK) dderror(ddrval);
2430 curx += k[seq[seqman].frame[rnum]].box.right;
2431 if (cur == 110)
2432 {cury += k[seq[seqman].frame[rnum]].box.bottom+5;
2433 curx = curx_start;
2434
2435 }
2436
2437 if (cur == 220) return;
2438 }
2439 }
2440 }
2441
2442
draw_health(void)2443 void draw_health( void )
2444 {
2445 flifemax = *plifemax;
2446 draw_bar(flifemax, 190);
2447 flife = *plife;
2448 draw_bar(flife, 451);
2449 }
2450
draw_icons()2451 void draw_icons()
2452 {
2453 if (*pcur_weapon >= 1 && *pcur_weapon <= NB_ITEMS && play.item[*pcur_weapon - 1].active)
2454 {
2455 //disarm old weapon
2456 check_seq_status(play.item[*pcur_weapon - 1].seq);
2457 SDL_Rect dst = {557, 413};
2458 SDL_BlitSurface(GFX_k[seq[play.item[*pcur_weapon - 1].seq].frame[play.item[*pcur_weapon - 1].frame]].k, NULL,
2459 GFX_lpDDSTwo, &dst);
2460 }
2461
2462 if (*pcur_magic >= 1 && *pcur_magic <= NB_MITEMS && play.mitem[*pcur_magic - 1].active)
2463 {
2464 //disarm old weapon
2465 check_seq_status(play.mitem[*pcur_magic - 1].seq);
2466 SDL_Rect dst = {153, 413};
2467 SDL_BlitSurface(GFX_k[seq[play.mitem[*pcur_magic - 1].seq].frame[play.mitem[*pcur_magic - 1].frame]].k, NULL,
2468 GFX_lpDDSTwo, &dst);
2469 }
2470 }
2471
2472
2473 /** draw_virtical, draw_hor, draw_virt2, draw_hor2: used to draw the
2474 magic jauge (in that order) (dinkvar.cpp:draw_mlevel() only) **/
2475
draw_virtical(int percent,int mx,int my,int mseq,int mframe)2476 void draw_virtical(int percent, int mx, int my, int mseq, int mframe)
2477 {
2478 int cut;
2479 if (percent > 25) percent = 25;
2480 percent = (percent * 4);
2481 rect myrect;
2482 rect_copy(&myrect, &k[seq[mseq].frame[mframe]].box);
2483 int full = myrect.bottom;
2484 cut = (full * percent) / 100;
2485 myrect.bottom = cut;
2486
2487 my += (full - cut);
2488
2489 /* ddrval = lpDDSTwo->BltFast(mx, my, k[seq[mseq].frame[mframe]].k, */
2490 /* &myrect, DDBLTFAST_NOCOLORKEY); */
2491 // GFX
2492 {
2493 /* TODO: test me! */
2494 SDL_Rect src, dst;
2495 src.x = src.y = 0;
2496 src.w = GFX_k[seq[mseq].frame[mframe]].k->w;
2497 src.h = GFX_k[seq[mseq].frame[mframe]].k->h * percent / 100;
2498 dst.x = mx;
2499 dst.y = my;
2500 gfx_blit_nocolorkey(GFX_k[seq[mseq].frame[mframe]].k, &src, GFX_lpDDSTwo, &dst);
2501 }
2502 }
2503
draw_virt2(int percent,int mx,int my,int mseq,int mframe)2504 void draw_virt2(int percent, int mx, int my, int mseq, int mframe)
2505 {
2506 int cut;
2507 if (percent > 25) percent = 25;
2508 percent = (percent * 4);
2509 rect myrect;
2510 rect_copy(&myrect, &k[seq[mseq].frame[mframe]].box);
2511 int full = myrect.bottom;
2512 cut = (full * percent) / 100;
2513 myrect.bottom = cut;
2514
2515 /* again: */
2516 /* ddrval = lpDDSTwo->BltFast( mx, my, k[seq[mseq].frame[mframe]].k, */
2517 /* &myrect, DDBLTFAST_NOCOLORKEY); */
2518 /* if (ddrval == DDERR_WASSTILLDRAWING) goto again; */
2519 // GFX
2520 {
2521 SDL_Rect src, dst;
2522 src.x = src.y = 0;
2523 src.w = GFX_k[seq[mseq].frame[mframe]].k->w;
2524 src.h = GFX_k[seq[mseq].frame[mframe]].k->h * percent / 100;
2525 dst.x = mx; dst.y = my;
2526 gfx_blit_nocolorkey(GFX_k[seq[mseq].frame[mframe]].k, &src, GFX_lpDDSTwo, &dst);
2527 }
2528 }
2529
draw_hor(int percent,int mx,int my,int mseq,int mframe)2530 void draw_hor(int percent, int mx, int my, int mseq, int mframe)
2531 {
2532 int cut;
2533 if (percent > 25) percent = 25;
2534 percent = (percent * 4);
2535 rect myrect;
2536 rect_copy(&myrect, &k[seq[mseq].frame[mframe]].box);
2537 int full = myrect.right;
2538 cut = (full * percent) / 100;
2539 full = cut;
2540 myrect.right = full;
2541 /* again: */
2542 /* ddrval = lpDDSTwo->BltFast( mx, my, k[seq[mseq].frame[mframe]].k, */
2543 /* &myrect, DDBLTFAST_NOCOLORKEY); */
2544 /* if (ddrval == DDERR_WASSTILLDRAWING) goto again; */
2545 // GFX
2546 {
2547 /* TODO: test me! */
2548 SDL_Rect src, dst;
2549 src.x = src.y = 0;
2550 src.w = GFX_k[seq[mseq].frame[mframe]].k->w * percent / 100;
2551 src.h = GFX_k[seq[mseq].frame[mframe]].k->h;
2552 dst.x = mx; dst.y = my;
2553 gfx_blit_nocolorkey(GFX_k[seq[mseq].frame[mframe]].k, &src, GFX_lpDDSTwo, &dst);
2554 }
2555 }
2556
draw_hor2(int percent,int mx,int my,int mseq,int mframe)2557 void draw_hor2(int percent, int mx, int my, int mseq, int mframe)
2558 {
2559 int cut;
2560 if (percent > 25) percent = 25;
2561 percent = (percent * 4);
2562 rect myrect;
2563 rect_copy(&myrect, &k[seq[mseq].frame[mframe]].box);
2564 int full = myrect.right;
2565 cut = (full * percent) / 100;
2566
2567 myrect.right = cut;
2568 mx += (full - cut);
2569
2570 /* again: */
2571 /* ddrval = lpDDSTwo->BltFast( mx, my, k[seq[mseq].frame[mframe]].k, */
2572 /* &myrect, DDBLTFAST_NOCOLORKEY); */
2573 /* if (ddrval == DDERR_WASSTILLDRAWING) goto again; */
2574 // GFX
2575 {
2576 SDL_Rect src, dst;
2577 src.x = src.y = 0;
2578 src.w = GFX_k[seq[mseq].frame[mframe]].k->w * percent / 100;
2579 src.h = GFX_k[seq[mseq].frame[mframe]].k->h;
2580 dst.x = mx;
2581 dst.y = my;
2582 gfx_blit_nocolorkey(GFX_k[seq[mseq].frame[mframe]].k, &src, GFX_lpDDSTwo, &dst);
2583 }
2584 }
2585
draw_mlevel(int percent)2586 void draw_mlevel(int percent)
2587 {
2588 //if (*pmagic_level < 1) return;
2589
2590 int mseq = 180;
2591 int bary = 6;
2592 int barx = 7;
2593
2594 if (percent > 0) draw_virtical(percent, 149, 411, mseq, bary);
2595 percent -= 25;
2596 if (percent > 0) draw_hor(percent, 149, 409, mseq, barx);
2597 percent -= 25;
2598 if (percent > 0) draw_virt2(percent, 215, 411, mseq, bary);
2599 percent -= 25;
2600 if (percent > 0) draw_hor2(percent, 149, 466, mseq, barx);
2601 }
2602
2603
2604 /* Draw the status bar and the magic jauge */
draw_status_all(void)2605 void draw_status_all(void)
2606 {
2607 /* RECT rcRect; */
2608 /* rcRect.left = 0; */
2609 /* rcRect.top = 0; */
2610 /* rcRect.right = 640; */
2611 /* rcRect.bottom = 80; */
2612 /* again: */
2613 /* ddrval = lpDDSTwo->BltFast(0, 400, k[seq[180].frame[3]].k, */
2614 /* &rcRect, DDBLTFAST_NOCOLORKEY); */
2615 /* if (ddrval == DDERR_WASSTILLDRAWING) goto again; */
2616 // GFX
2617 {
2618 SDL_Rect src = {0, 0, 640, 80}, dst = {0, 400};
2619 gfx_blit_nocolorkey(GFX_k[seq[180].frame[3]].k, &src, GFX_lpDDSTwo, &dst);
2620 }
2621
2622 /* rcRect.left = 0; */
2623 /* rcRect.top = 0; */
2624 /* rcRect.right = 20; */
2625 /* rcRect.bottom = 400; */
2626 /* again2: */
2627 /* ddrval = lpDDSTwo->BltFast(0, 0, k[seq[180].frame[1]].k, */
2628 /* &rcRect, DDBLTFAST_NOCOLORKEY); */
2629 /* if (ddrval == DDERR_WASSTILLDRAWING) goto again2; */
2630 /* again3: */
2631 /* ddrval = lpDDSTwo->BltFast(620, 0, k[seq[180].frame[2]].k, */
2632 /* &rcRect, DDBLTFAST_NOCOLORKEY); */
2633 /* if (ddrval == DDERR_WASSTILLDRAWING) goto again3; */
2634 // GFX
2635 {
2636 SDL_Rect src = {0, 0, 20, 400}, dst1 = {0, 0}, dst2 = {620, 0};
2637 gfx_blit_nocolorkey(GFX_k[seq[180].frame[1]].k, &src, GFX_lpDDSTwo, &dst1);
2638 gfx_blit_nocolorkey(GFX_k[seq[180].frame[2]].k, &src, GFX_lpDDSTwo, &dst2);
2639 }
2640
2641 fraise = next_raise();
2642 if (*pexper < fraise)
2643 fexp = *pexper;
2644 else
2645 fexp = fraise - 1;
2646 fstrength = *pstrength;
2647 fmagic = *pmagic;
2648 fgold = *pgold;
2649 fdefense = *pdefense;
2650 last_magic_draw = 0;
2651 draw_exp();
2652 draw_health();
2653 draw_strength();
2654 draw_defense();
2655 draw_magic();
2656 draw_gold();
2657 draw_level();
2658 draw_icons();
2659 if (*pmagic_cost > 0 && *pmagic_level > 0)
2660 draw_mlevel(*pmagic_level * 100 / *pmagic_cost);
2661 }
2662
2663
2664
inside_box(int x1,int y1,rect box)2665 /*bool*/int inside_box(int x1, int y1, rect box)
2666 {
2667
2668 if (x1 > box.right) return(/*false*/0);
2669 if (x1 < box.left) return(/*false*/0);
2670
2671 if (y1 > box.bottom) return(/*false*/0);
2672 if (y1 < box.top) return(/*false*/0);
2673
2674 return(/*true*/1);
2675
2676 }
2677
2678
2679
add_sprite_dumb(int x1,int y,int brain,int pseq,int pframe,int size)2680 int add_sprite_dumb(int x1, int y, int brain,int pseq, int pframe,int size )
2681 {
2682 int x;
2683 for (x = 1; x < MAX_SPRITES_AT_ONCE; x++)
2684 {
2685 if (spr[x].active == /*FALSE*/0)
2686 {
2687 memset(&spr[x], 0, sizeof(spr[x]));
2688
2689 //Msg("Making sprite %d.",x);
2690 spr[x].active = /*TRUE*/1;
2691 spr[x].x = x1;
2692 spr[x].y = y;
2693 spr[x].my = 0;
2694 spr[x].mx = 0;
2695 spr[x].speed = 0;
2696 spr[x].brain = brain;
2697 spr[x].frame = 0;
2698 spr[x].pseq = pseq;
2699 spr[x].pframe = pframe;
2700 spr[x].size = size;
2701 spr[x].seq = 0;
2702 if (x > last_sprite_created)
2703 last_sprite_created = x;
2704
2705 spr[x].timer = 0;
2706 spr[x].wait = 0;
2707 spr[x].lpx[0] = 0;
2708 spr[x].lpy[0] = 0;
2709 spr[x].moveman = 0;
2710 spr[x].seq_orig = 0;
2711
2712
2713 spr[x].base_hit = -1;
2714 spr[x].base_walk = -1;
2715 spr[x].base_die = -1;
2716 spr[x].base_idle = -1;
2717 spr[x].base_attack = -1;
2718 spr[x].last_sound = 0;
2719 spr[x].hard = 1;
2720
2721 rect_set(&spr[x].alt, 0,0,0,0);
2722 spr[x].althard = 0;
2723 spr[x].sp_index = 0;
2724 spr[x].nocontrol = 0;
2725 spr[x].idle = 0;
2726 spr[x].strength = 0;
2727 spr[x].damage = 0;
2728 spr[x].defense = 0;
2729
2730 if (dversion >= 108)
2731 {
2732 if (spr[x].custom == NULL)
2733 {
2734 spr[x].custom = dinkc_sp_custom_new();
2735 }
2736 else
2737 {
2738 dinkc_sp_custom_clear(spr[x].custom);
2739 }
2740 }
2741
2742 return(x);
2743 }
2744
2745 }
2746
2747 return(0);
2748 }
2749
2750
get_box(int h,rect * box_scaled,rect * box_real)2751 /*bool*/int get_box (int h, rect * box_scaled, rect * box_real)
2752 {
2753 int x_offset, y_offset;
2754
2755 int mplayx = playx;
2756 int mplayl = playl;
2757 int mplayy = playy;
2758
2759 if (spr[h].noclip)
2760 {
2761 mplayx = 640;
2762 mplayl = 0;
2763 mplayy = 480;
2764 }
2765
2766 // added to fix frame-not-in-memory immediately
2767 if (getpic(h) < 1)
2768 {
2769 if (spr[h].pseq != 0)
2770 check_seq_status(spr[h].pseq);
2771 }
2772
2773 // if frame is still not in memory:
2774 if (getpic(h) < 1)
2775 {
2776 if (dinkedit)
2777 log_warn("Yo, sprite %d has a bad pic. (Map %d) Seq %d, Frame %d",
2778 h, cur_map, spr[h].pseq, spr[h].pframe);
2779 else
2780 log_warn("Yo, sprite %d has a bad pic. (Map %d) Seq %d, Frame %d",
2781 h, *pmap, spr[h].pseq, spr[h].pframe);
2782 goto nodraw;
2783 }
2784
2785 *box_real = k[getpic(h)].box;
2786
2787 /* This doesn't really make sense, but that's the way the game was
2788 released, so we keep it for compatibility */
2789 {
2790 rect krect;
2791 rect_copy(&krect, &k[getpic(h)].box);
2792
2793 double size_ratio = spr[h].size / 100.0;
2794 int x_compat = krect.right * (size_ratio - 1) / 2;
2795 int y_compat = krect.bottom * (size_ratio - 1) / 2;
2796
2797 int center_x = k[getpic(h)].xoffset;
2798 int center_y = k[getpic(h)].yoffset;
2799 box_scaled->left = spr[h].x - center_x - x_compat;
2800 box_scaled->top = spr[h].y - center_y - y_compat;
2801
2802 box_scaled->right = box_scaled->left + krect.right * size_ratio;
2803 box_scaled->bottom = box_scaled->top + krect.bottom * size_ratio;
2804 }
2805
2806 if (spr[h].alt.right != 0 || spr[h].alt.left != 0 || spr[h].alt.top != 0)
2807 {
2808 // checks for correct box stuff
2809 if (spr[h].alt.left < 0)
2810 spr[h].alt.left = 0;
2811 if (spr[h].alt.left > k[getpic(h)].box.right)
2812 spr[h].alt.left = k[getpic(h)].box.right;
2813
2814 if (spr[h].alt.top < 0)
2815 spr[h].alt.top = 0;
2816 if (spr[h].alt.top > k[getpic(h)].box.bottom)
2817 spr[h].alt.top = k[getpic(h)].box.bottom;
2818
2819 if (spr[h].alt.right < 0)
2820 spr[h].alt.right = 0;
2821 if (spr[h].alt.right > k[getpic(h)].box.right)
2822 spr[h].alt.right = k[getpic(h)].box.right;
2823
2824 if (spr[h].alt.bottom < 0)
2825 spr[h].alt.bottom = 0;
2826 if (spr[h].alt.bottom > k[getpic(h)].box.bottom)
2827 spr[h].alt.bottom = k[getpic(h)].box.bottom;
2828
2829 box_scaled->left += spr[h].alt.left;
2830 box_scaled->top += spr[h].alt.top;
2831 box_scaled->right = box_scaled->right - (k[getpic(h)].box.right - spr[h].alt.right);
2832 box_scaled->bottom = box_scaled->bottom - (k[getpic(h)].box.bottom - spr[h].alt.bottom);
2833
2834 rect_copy(box_real, &spr[h].alt);
2835 }
2836
2837 //********* Check to see if they need to be cut down and do clipping
2838
2839 if (spr[h].size == 0)
2840 spr[h].size = 100;
2841
2842 if (dinkedit && (mode == 1 || mode == 5) && draw_map_tiny < 1)
2843 goto do_draw;
2844
2845 if (box_scaled->left < mplayl)
2846 {
2847 x_offset = box_scaled->left * (-1) + mplayl;
2848 box_scaled->left = mplayl;
2849
2850 if (spr[h].size == 100)
2851 box_real->left += x_offset;
2852 else
2853 box_real->left += (x_offset * 100) / spr[h].size;
2854
2855 if (box_scaled->right - 1 < mplayl)
2856 goto nodraw;
2857 }
2858
2859 if (box_scaled->top < 0)
2860 {
2861 y_offset = box_scaled->top * (-1);
2862 box_scaled->top = 0;
2863
2864 if (spr[h].size == 100)
2865 box_real->top += y_offset;
2866 else
2867 box_real->top += (y_offset * 100) / spr[h].size;
2868
2869 if (box_scaled->bottom-1 < 0)
2870 goto nodraw;
2871 }
2872
2873 if (box_scaled->right > mplayx)
2874 {
2875 x_offset = (box_scaled->right) - mplayx;
2876 box_scaled->right = mplayx;
2877
2878 if (spr[h].size == 100)
2879 box_real->right -= x_offset;
2880 else
2881 box_real->right -= (x_offset * 100) / spr[h].size;
2882
2883 if (box_scaled->left+1 > mplayx)
2884 goto nodraw;
2885 }
2886
2887 if (box_scaled->bottom > mplayy)
2888 {
2889 y_offset = (box_scaled->bottom) - mplayy;
2890 box_scaled->bottom = mplayy;
2891
2892 if (spr[h].size == 100)
2893 box_real->bottom -= y_offset;
2894 else
2895 box_real->bottom -= (y_offset * 100) / spr[h].size;
2896
2897 if (box_scaled->top+1 > mplayy)
2898 goto nodraw;
2899 }
2900
2901 do_draw:
2902 return(/*true*/1);
2903
2904 nodraw:
2905 return(/*false*/0);
2906 }
2907
2908
2909 /* void reload_sprites(char name[100], int nummy, int junk) */
2910 /* { */
2911 /* HRESULT ddrval; */
2912 /* PALETTEENTRY holdpal[256]; */
2913
2914 /* char crap[100],hold[10]; */
2915 /* int n; */
2916 /* n = 0; */
2917
2918 /* lpDDPal->GetEntries(0,0,256,holdpal); */
2919 /* lpDDPal->SetEntries(0,0,256,real_pal); */
2920
2921
2922 /* for (int oo = index[nummy].s+1; oo <= index[nummy].s + index[nummy].last; oo++) */
2923 /* { */
2924 /* n++; */
2925
2926 // Msg( "%s", crap);
2927
2928 // initFail(hWndMain, crap);
2929 /* ddrval = k[oo].k->Restore(); */
2930 /* if( ddrval == DD_OK ) */
2931 /* { */
2932
2933
2934 /* if (n < 10) strcpy(hold, "0"); else strcpy(hold,""); */
2935 /* sprintf(crap, "%s%s%d.BMP",name,hold,n); */
2936
2937 /* DDReLoadBitmap(k[oo].k, crap); */
2938 //Msg("Sprite %s%d.bmp reloaded into area %d. ",name,n,oo);
2939
2940
2941 /* } */
2942 /* } */
2943 /* lpDDPal->SetEntries(0,0,256,holdpal); */
2944 /* } */
2945
2946
add_sprite(int x1,int y,int brain,int pseq,int pframe)2947 int add_sprite(int x1, int y, int brain,int pseq, int pframe )
2948 {
2949 int x;
2950 for (x = 1; x < MAX_SPRITES_AT_ONCE; x++)
2951 {
2952 if (spr[x].active == /*FALSE*/0)
2953 {
2954 memset(&spr[x], 0, sizeof(spr[x]));
2955
2956 spr[x].active = /*TRUE*/1;
2957 spr[x].x = x1;
2958 spr[x].y = y;
2959 spr[x].my = 0;
2960 spr[x].mx = 0;
2961 spr[x].speed = 1;
2962 spr[x].brain = brain;
2963 spr[x].frame = 0;
2964 spr[x].pseq = pseq;
2965 spr[x].pframe = pframe;
2966 spr[x].seq = 0;
2967 if (x > last_sprite_created)
2968 last_sprite_created = x;
2969 spr[x].timer = 33;
2970 spr[x].wait = 0;
2971 spr[x].lpx[0] = 0;
2972 spr[x].lpy[0] = 0;
2973 spr[x].moveman = 0;
2974 spr[x].size = 100;
2975 spr[x].que = 0;
2976 spr[x].strength = 0;
2977 spr[x].damage = 0;
2978 spr[x].defense = 0;
2979 spr[x].hard = 1;
2980
2981 if (dversion >= 108)
2982 {
2983 if (spr[x].custom == NULL)
2984 {
2985 spr[x].custom = dinkc_sp_custom_new();
2986 }
2987 else
2988 {
2989 dinkc_sp_custom_clear(spr[x].custom);
2990 }
2991 }
2992
2993 return(x);
2994 }
2995
2996 }
2997
2998 return(0);
2999 }
3000
3001 /* Editor only */
check_sprite_status(int h)3002 void check_sprite_status(int h)
3003 {
3004 /* HRESULT dderror; */
3005 /* char word1[80]; */
3006 //is sprite in memory?
3007 if (spr[h].pseq > 0)
3008 {
3009 // Msg("Smartload: Loading seq %d..", spr[h].seq);
3010 if (seq[spr[h].pseq].frame[1] == 0)
3011 {
3012 if (seq[spr[h].pseq].is_active)
3013 figure_out(seq[spr[h].pseq].ini);
3014 else
3015 log_error("Error: sprite %d on map %d references non-existent sequence %d",
3016 h, cur_map, spr[h].pseq);
3017 }
3018 else
3019 {
3020 //it's been loaded before.. is it lost or still there?
3021 //Msg("Sprite %d's seq is %d",h,spr[h].seq);
3022
3023 /* dderror = k[seq[spr[h].pseq].frame[1]].k->IsLost(); */
3024
3025 /* if (dderror == DDERR_SURFACELOST) */
3026 /* { */
3027 /* get_word(seq[spr[h].pseq].data, 2, word1); */
3028
3029 /* reload_sprites(word1, spr[h].pseq,0); */
3030 /* //Msg("Reloaded seq %d with path of %s should be %s", spr[h].seq, word1,seq[spr[h].seq].data ); */
3031 /* } */
3032
3033
3034 }
3035 }
3036
3037
3038
3039
3040 }
3041
3042 /* Editor only */
check_frame_status(int h,int frame)3043 void check_frame_status(int h, int frame)
3044
3045 {
3046 /* HRESULT dderror; */
3047 /* char word1[80]; */
3048
3049 if (!seq[h].is_active) return;
3050
3051 if (h > 0)
3052 {
3053 // Msg("Smartload: Loading seq %d..", spr[h].seq);
3054 if (seq[h].frame[1] == 0 || GFX_k[seq[h].frame[1]].k == NULL)
3055 {
3056 figure_out(seq[h].ini);
3057 }
3058 else
3059 {
3060 //it's been loaded before.. is it lost or still there?
3061 //Msg("Sprite %d's seq is %d",h,spr[h].seq);
3062
3063 /* dderror = k[seq[h].frame[1]].k->IsLost(); */
3064
3065 /* if (dderror == DDERR_SURFACELOST) */
3066 /* { */
3067 /* get_word(seq[h].data, 2, word1); */
3068
3069 /* reload_sprites(word1, h,0); */
3070 /* //Msg("Reloaded seq %d with path of %s should be %s", spr[h].seq, word1,seq[spr[h].seq].data ); */
3071 /* } */
3072 }
3073 }
3074
3075
3076 }
3077
3078 /**
3079 * Load sequence in memory if not already, using cached dink.ini info
3080 */
check_seq_status(int seq_no)3081 void check_seq_status(int seq_no)
3082 {
3083 if (seq_no > 0 && seq_no < MAX_SEQUENCES)
3084 {
3085 /* Skip empty/unused sequences */
3086 if (!seq[seq_no].is_active)
3087 return;
3088
3089 if (seq[seq_no].frame[1] == 0 || GFX_k[seq[seq_no].frame[1]].k == NULL)
3090 figure_out(seq[seq_no].ini);
3091 }
3092 else if (seq_no > 0)
3093 {
3094 log_error("Warning: check_seq_status: invalid sequence %d", seq_no);
3095 }
3096 }
3097
3098 /**
3099 * Load all +1->+9 sequences from base sequence 'base' in memory,
3100 * useful to load all of a moving sprite sequences
3101 */
check_base(int base)3102 void check_base(int base)
3103 {
3104 int i;
3105 for (i = 1; i < 10; i++)
3106 if (seq[base+i].is_active)
3107 check_seq_status(base+i);
3108 }
3109
3110 /**
3111 * Checks for all seq's used by the (base) commands
3112 */
check_sprite_status_full(int sprite_no)3113 void check_sprite_status_full(int sprite_no)
3114 {
3115 //is sprite in memory?
3116 check_seq_status(spr[sprite_no].pseq);
3117
3118 if (spr[sprite_no].base_walk > -1)
3119 check_base(spr[sprite_no].base_walk);
3120 }
3121
3122
3123 /* say_text, say_text_xy: used by the game only (not the editor) */
add_text_sprite(char * text,int script,int sprite_owner,int mx,int my)3124 int add_text_sprite(char* text, int script, int sprite_owner, int mx, int my)
3125 {
3126 int tsprite = add_sprite(mx, my, 8, 0, 0);
3127 if (tsprite == 0)
3128 {
3129 log_error("Couldn't say something, out of sprites.");
3130 return 0;
3131 }
3132
3133 strncpy(spr[tsprite].text, text, 200-1); // TODO: currently truncated to 199 chars
3134 spr[tsprite].text[200-1] = '\0';
3135
3136 *plast_text = tsprite;
3137 spr[tsprite].kill = strlen(text) * TEXT_TIMER;
3138 if (spr[tsprite].kill < TEXT_MIN)
3139 spr[tsprite].kill = TEXT_MIN;
3140 spr[tsprite].damage = -1;
3141 spr[tsprite].owner = sprite_owner;
3142 spr[tsprite].hard = 1;
3143 spr[tsprite].script = script;
3144 spr[tsprite].nohit = 1;
3145
3146 return tsprite;
3147 }
3148
say_text(char * text,int sprite_owner,int script)3149 int say_text(char* text, int sprite_owner, int script)
3150 {
3151 int tsprite;
3152 if (sprite_owner == 1000)
3153 tsprite = add_text_sprite(text, script, 1000, 100, 100);
3154 else
3155 tsprite = add_text_sprite(text, script, sprite_owner,
3156 spr[sprite_owner].x, spr[sprite_owner].y);
3157
3158 if (tsprite == 0)
3159 return 0;
3160
3161 //set X offset for text, using strength var since it's unused
3162 spr[tsprite].strength = 75;
3163 check_seq_status(spr[spr[tsprite].owner].seq);
3164 spr[tsprite].defense = ( ( k[getpic(spr[tsprite].owner)].box.bottom
3165 - k[getpic(spr[tsprite].owner)].yoffset )
3166 + 100 );
3167
3168 spr[tsprite].x = spr[spr[tsprite].owner].x - spr[tsprite].strength;
3169 spr[tsprite].y = spr[spr[tsprite].owner].y - spr[tsprite].defense;
3170
3171 return tsprite;
3172 }
3173
3174
say_text_xy(char * text,int mx,int my,int script)3175 int say_text_xy(char* text, int mx, int my, int script)
3176 {
3177 int sprite_owner = 1000;
3178 return add_text_sprite(text, script, sprite_owner, mx, my);
3179 }
3180
3181
3182
does_sprite_have_text(int sprite)3183 int does_sprite_have_text(int sprite)
3184 {
3185 int k;
3186 //Msg("getting callback # with %d..", sprite);
3187 for (k = 1; k <= MAX_SPRITES_AT_ONCE; k++)
3188 {
3189 if ( spr[k].active) if (spr[k].owner == sprite) if (spr[k].brain == 8)
3190 {
3191 //Msg("Found it! returning %d.", k);
3192
3193 return(k);
3194 }
3195
3196 }
3197
3198 return(0);
3199
3200 }
3201
3202
kill_text_owned_by(int sprite)3203 void kill_text_owned_by(int sprite)
3204 {
3205 int i;
3206 for (i = 1; i < MAX_SPRITES_AT_ONCE; i++)
3207 {
3208 if (spr[i].active && spr[i].brain == 8 && spr[i].owner == sprite)
3209 spr[i].active = /*false*/0;
3210 }
3211 }
3212
3213 /**
3214 * Is 'sprite' currently talking?
3215 * Returns 1 if a text sprite is owned by sprite number 'sprite'.
3216 */
text_owned_by(int sprite)3217 /*bool*/int text_owned_by(int sprite)
3218 {
3219 int i = 1;
3220 for (; i < MAX_SPRITES_AT_ONCE; i++)
3221 if (spr[i].active && spr[i].brain == 8 && spr[i].owner == sprite)
3222 return /*true*/1;
3223 return /*false*/0;
3224 }
3225
3226
kill_sprite_all(int sprite)3227 void kill_sprite_all (int sprite)
3228 {
3229 spr[sprite].active = /*false*/0;
3230
3231 kill_text_owned_by(sprite);
3232 kill_scripts_owned_by(sprite);
3233
3234 }
3235
3236
3237 /**
3238 * Find an editor sprite in active sprites
3239 */
find_sprite(int editor_sprite)3240 int find_sprite(int editor_sprite)
3241 {
3242 int k;
3243 for (k = 1; k <= last_sprite_created; k++)
3244 if (spr[k].sp_index == editor_sprite)
3245 return k;
3246 return 0;
3247 }
3248
3249
get_right(char line[200],char thing[100],char * ret)3250 void get_right(char line[200], char thing[100], char *ret)
3251 {
3252 char *dumb;
3253 int pos = strcspn(line, thing );
3254
3255
3256 if (pos == 0){ strcpy(ret, ""); return; }
3257
3258
3259 dumb = &ret[pos+1];
3260 strcpy(ret, dumb);
3261 }
3262
3263
3264
3265
change_sprite(int h,int val,int * change)3266 int change_sprite(int h, int val, int *change)
3267 {
3268 //Msg("Searching sprite %s with val %d. Cur is %d", h, val, *change);
3269 if (h < 1 || h >= MAX_SPRITES_AT_ONCE)
3270 {
3271 log_error("Error with an SP command - Sprite %d is invalid.", h);
3272 return -1;
3273 }
3274
3275 if (spr[h].active == 0)
3276 return -1;
3277
3278 if (val != -1)
3279 *change = val;
3280
3281 return *change;
3282
3283 }
3284
change_edit(int h,int val,unsigned short * change)3285 int change_edit(int h, int val, unsigned short* change)
3286 {
3287 //Msg("Searching sprite %s with val %d. Cur is %d", h, val, *change);
3288
3289 if (h < 1 || h > 99)
3290 return -1;
3291
3292 if (val != -1)
3293 *change = val;
3294
3295 return *change;
3296 }
3297
3298 /**
3299 * Sanity-check and set an editor variable (editor_type(),
3300 * editor_seq() and editor_frame())
3301 */
change_edit_char(int h,int val,unsigned char * change)3302 int change_edit_char(int h, int val, unsigned char* change)
3303 {
3304 //Msg("Searching sprite %s with val %d. Cur is %d", h, val, *change);
3305 // Msg("h is %d..",val);
3306 if (h < 1 || h > 99)
3307 return -1;
3308
3309 if (val != -1)
3310 *change = val;
3311
3312 return *change;
3313 }
3314
change_sprite_noreturn(int h,int val,int * change)3315 int change_sprite_noreturn(int h, int val, int* change)
3316 {
3317 //Msg("Searching sprite %s with val %d. Cur is %d", h, val, *change);
3318 if (h < 0
3319 || h >= MAX_SPRITES_AT_ONCE
3320 || spr[h].active == 0)
3321 return -1;
3322
3323 *change = val;
3324
3325 return(*change);
3326 }
3327
3328
draw_sprite_game(SDL_Surface * GFX_lpdest,int h)3329 void draw_sprite_game(SDL_Surface *GFX_lpdest, int h)
3330 {
3331 if (g_b_kill_app)
3332 return; //don't try, we're quitting
3333 if (spr[h].brain == 8)
3334 return; // text
3335 if (spr[h].nodraw == 1)
3336 return; // invisible
3337
3338 rect box_crap,box_real;
3339
3340 if (get_box(h, &box_crap, &box_real))
3341 {
3342 /* Generic scaling */
3343 /* Not perfectly accurate yet: move a 200% sprite to the border
3344 of the screen to it is clipped: it's scaled size will slighly
3345 vary. Maybe we need to clip the source zone before scaling
3346 it.. */
3347 // error checking for invalid rectangle
3348 if (box_crap.left >= box_crap.right || box_crap.top >= box_crap.bottom)
3349 return;
3350
3351 SDL_Rect src, dst;
3352 int retval = 0;
3353 src.x = box_real.left;
3354 src.y = box_real.top;
3355 src.w = box_real.right - box_real.left;
3356 src.h = box_real.bottom - box_real.top;
3357 dst.x = box_crap.left;
3358 dst.y = box_crap.top;
3359 dst.w = box_crap.right - box_crap.left;
3360 dst.h = box_crap.bottom - box_crap.top;
3361
3362 retval = gfx_blit_stretch(GFX_k[getpic(h)].k, &src, GFX_lpdest, &dst);
3363
3364 if (retval < 0) {
3365 log_error("Could not draw sprite %d: %s", getpic(h), SDL_GetError());
3366 /* If we failed, then maybe the sprite was actually loaded
3367 yet, let's try now */
3368 if (spr[h].pseq != 0)
3369 check_seq_status(spr[h].pseq);
3370 }
3371 }
3372 }
3373
3374
changedir(int dir1,int k,int base)3375 void changedir( int dir1, int k,int base)
3376 {
3377 int hspeed;
3378 int speed_hold = spr[k].speed;
3379 if (k > 1) if (spr[k].brain != 9) if (spr[k].brain != 10)
3380 {
3381 hspeed = spr[k].speed * (base_timing / 4);
3382 if (hspeed > 49)
3383 {
3384 log_debug("Speed was %d", hspeed);
3385 spr[k].speed = 49;
3386 } else
3387 spr[k].speed = hspeed;
3388 }
3389 int old_seq = spr[k].seq;
3390 spr[k].dir = dir1;
3391
3392 if (dir1 == 1)
3393 {
3394 spr[k].mx = (0 - spr[k].speed ) + (spr[k].speed / 3);
3395 spr[k].my = spr[k].speed - (spr[k].speed / 3);
3396
3397 if (base != -1)
3398 {
3399
3400
3401 spr[k].seq = base + 1;
3402 if (!seq[spr[k].seq].is_active)
3403 {
3404 spr[k].seq = base + 9;
3405
3406 }
3407
3408 }
3409
3410 if (old_seq != spr[k].seq)
3411 {
3412 spr[k].frame = 0;
3413 spr[k].delay = 0;
3414 }
3415
3416
3417 }
3418
3419 if (dir1 == 2)
3420 {
3421 spr[k].mx = 0;
3422 spr[k].my = spr[k].speed;
3423 if (base != -1)
3424 spr[k].seq = base + 2;
3425
3426 if (!seq[spr[k].seq].is_active && seq[base+3].is_active)
3427 spr[k].seq = base + 3;
3428 if (!seq[spr[k].seq].is_active && seq[base+1].is_active)
3429 spr[k].seq = base + 1;
3430
3431
3432 if (old_seq != spr[k].seq)
3433 {
3434 spr[k].frame = 0;
3435 spr[k].delay = 0;
3436 }
3437
3438
3439 }
3440 if (dir1 == 3)
3441 {
3442 spr[k].mx = spr[k].speed - (spr[k].speed / 3);
3443 spr[k].my = spr[k].speed - (spr[k].speed / 3);
3444 if (base != -1)
3445 {
3446 spr[k].seq = base + 3;
3447 if (!seq[spr[k].seq].is_active)
3448 spr[k].seq = base + 7;
3449
3450 }
3451
3452 if (old_seq != spr[k].seq)
3453 {
3454 spr[k].frame = 0;
3455 spr[k].delay = 0;
3456 }
3457
3458
3459 }
3460
3461 if (dir1 == 4)
3462 {
3463
3464 //Msg("Changing %d to four..",k);
3465 spr[k].mx = (0 - spr[k].speed);
3466 spr[k].my = 0;
3467 if (base != -1)
3468 spr[k].seq = base + 4;
3469 if (!seq[spr[k].seq].is_active && seq[base+7].is_active)
3470 spr[k].seq = base + 7;
3471 if (!seq[spr[k].seq].is_active && seq[base+1].is_active)
3472 spr[k].seq = base + 1;
3473 }
3474
3475 if (dir1 == 6)
3476 {
3477 spr[k].mx = spr[k].speed;
3478 spr[k].my = 0;
3479 if (base != -1)
3480 spr[k].seq = base + 6;
3481
3482 if (!seq[spr[k].seq].is_active && seq[base+3].is_active)
3483 spr[k].seq = base + 3;
3484 if (!seq[spr[k].seq].is_active && seq[base+9].is_active)
3485 spr[k].seq = base + 9;
3486
3487 }
3488
3489 if (dir1 == 7)
3490 {
3491 spr[k].mx = (0 - spr[k].speed) + (spr[k].speed / 3);
3492 spr[k].my = (0 - spr[k].speed)+ (spr[k].speed / 3);
3493 if (base != -1)
3494 {
3495 spr[k].seq = base + 7;
3496
3497
3498 if (!seq[spr[k].seq].is_active)
3499 spr[k].seq = base + 3;
3500 }
3501
3502 }
3503 if (dir1 == 8)
3504 {
3505 spr[k].mx = 0;
3506 spr[k].my = (0 - spr[k].speed);
3507 if (base != -1)
3508 spr[k].seq = base + 8;
3509
3510 if (!seq[spr[k].seq].is_active && seq[base+7].is_active)
3511 spr[k].seq = base + 7;
3512 if (!seq[spr[k].seq].is_active && seq[base+9].is_active)
3513 spr[k].seq = base + 9;
3514
3515 }
3516
3517
3518 if (dir1 == 9)
3519 {
3520 spr[k].mx = spr[k].speed- (spr[k].speed / 3);
3521 spr[k].my = (0 - spr[k].speed)+ (spr[k].speed / 3);
3522 if (base != -1)
3523 {
3524 spr[k].seq = base + 9;
3525 if (!seq[spr[k].seq].is_active)
3526 spr[k].seq = base + 1;
3527 }
3528 }
3529
3530
3531
3532 if (old_seq != spr[k].seq)
3533 {
3534 spr[k].frame = 0;
3535 spr[k].delay = 0;
3536 }
3537
3538
3539 if (!seq[spr[k].seq].is_active)
3540 {
3541 //spr[k].mx = 0;
3542 //spr[k].my = 0;
3543 spr[k].seq = old_seq;
3544
3545 }
3546
3547 //Msg("Leaving with %d..", spr[k].dir);
3548
3549 //Msg("Changedir: Tried to switch sprite %d to dir %d",k,dir1);
3550
3551 spr[k].speed = speed_hold;
3552
3553 }
3554
3555
update_play_changes(void)3556 void update_play_changes( void )
3557 {
3558 int j;
3559 for (j = 1; j < 100; j++)
3560 {
3561 if (pam.sprite[j].active)
3562 if (play.spmap[*pmap].type[j] != 0)
3563 {
3564 //lets make some changes, player has extra info
3565 if (play.spmap[*pmap].type[j] == 1)
3566 {
3567 pam.sprite[j].active = 0;
3568
3569 }
3570
3571 if (play.spmap[*pmap].type[j] == 2)
3572 {
3573 pam.sprite[j].type = 1;
3574 pam.sprite[j].hard = 1;
3575 }
3576 if (play.spmap[*pmap].type[j] == 3)
3577 {
3578
3579 // Msg("Changing sprite %d", j);
3580 pam.sprite[j].type = 0;
3581 pam.sprite[j].hard = 1;
3582
3583 }
3584
3585 if (play.spmap[*pmap].type[j] == 4)
3586 {
3587 pam.sprite[j].type = 1;
3588 pam.sprite[j].hard = 0;
3589 }
3590
3591 if (play.spmap[*pmap].type[j] == 5)
3592 {
3593 pam.sprite[j].type = 0;
3594 pam.sprite[j].hard = 0;
3595 }
3596
3597 if (play.spmap[*pmap].type[j] == 6)
3598 {
3599 pam.sprite[j].active = 0;
3600
3601 }
3602 if (play.spmap[*pmap].type[j] == 7)
3603 {
3604 pam.sprite[j].active = 0;
3605
3606 }
3607 if (play.spmap[*pmap].type[j] == 8)
3608 {
3609 pam.sprite[j].active = 0;
3610
3611 }
3612
3613 pam.sprite[j].seq = play.spmap[*pmap].seq[j];
3614 pam.sprite[j].frame = play.spmap[*pmap].frame[j];
3615 strcpy(pam.sprite[j].script, "");
3616
3617
3618 }
3619
3620
3621 }
3622 }
3623
update_status_all(void)3624 void update_status_all(void)
3625 {
3626 /*bool*/int drawexp = /*false*/0;
3627 int next = next_raise();
3628 int script;
3629 if (next != fraise)
3630 {
3631 fraise += next / 40;
3632
3633 if (fraise > next) fraise = next;
3634 //make noise here
3635 drawexp = /*true*/1;
3636 SoundPlayEffect( 13,15050, 0,0 ,0);
3637
3638
3639 }
3640
3641 if (*pexper != fexp
3642 && ((talk.active == 0 && show_inventory == 0 && spr[1].freeze == 0)
3643 || fexp + 10 < fraise))
3644
3645 {
3646 //update screen experience
3647 fexp += 10;
3648 //make noise here
3649
3650 if (fexp > *pexper) fexp = *pexper;
3651 drawexp = /*true*/1;
3652 SoundPlayEffect( 13,29050, 0,0 ,0);
3653
3654 if (fexp >= fraise)
3655 {
3656
3657 *pexper -= next;
3658 fexp = 0;
3659
3660 script = load_script("lraise", 1, /*false*/0);
3661 if (locate(script, "raise")) run_script(script);
3662 }
3663 }
3664
3665
3666
3667 if (drawexp)
3668 {
3669
3670
3671 draw_exp();
3672 }
3673
3674
3675 if ( (flifemax != *plifemax) || (flife != *plife) )
3676 {
3677 if (flifemax < *plifemax) flifemax++;
3678 if (flifemax > *plifemax) flifemax--;
3679 if (flife > *plife) flife--;
3680 if (flife < *plife) flife++;
3681 if (flife > *plife) flife--;
3682 if (flife < *plife) flife++;
3683 draw_bar(flifemax, 190);
3684 draw_bar(flife, 451);
3685 }
3686
3687 if ( fstrength != *pstrength)
3688 {
3689 if (fstrength < *pstrength) fstrength++;
3690 if (fstrength > *pstrength) fstrength--;
3691 SoundPlayEffect( 22,22050, 0,0 ,0);
3692
3693 draw_strength();
3694 }
3695
3696 if ( fdefense != *pdefense)
3697 {
3698 if (fdefense < *pdefense) fdefense++;
3699 if (fdefense > *pdefense) fdefense--;
3700 SoundPlayEffect( 22,22050, 0,0 ,0);
3701 draw_defense();
3702 }
3703 if ( fmagic != *pmagic)
3704 {
3705 if (fmagic < *pmagic) fmagic++;
3706 if (fmagic > *pmagic) fmagic--;
3707 SoundPlayEffect( 22,22050, 0,0 ,0);
3708 draw_magic();
3709 }
3710
3711 if (fgold != *pgold)
3712 {
3713 if (fgold < *pgold)
3714 {
3715 fgold += 20;
3716 if (fgold > *pgold) fgold = *pgold;
3717 }
3718
3719 if (fgold > *pgold)
3720 {
3721 fgold -= 20;
3722 if (fgold < *pgold) fgold = *pgold;
3723 }
3724 SoundPlayEffect( 14,22050, 0,0 ,0);
3725 draw_gold();
3726 }
3727
3728 if (*pmagic_level < *pmagic_cost)
3729 {
3730 if (show_inventory == 0)
3731 *pmagic_level += *pmagic;
3732 if (*pmagic_level > *pmagic_cost) *pmagic_level = *pmagic_cost;
3733 }
3734 if (*pmagic_cost > 0) if (*pmagic_level > 0)
3735 {
3736 int mnum = *pmagic_level * 100 / *pmagic_cost;
3737 if (mnum != last_magic_draw)
3738 {
3739
3740 draw_mlevel(mnum);
3741
3742 //draw_status_all();
3743 last_magic_draw = mnum;
3744
3745
3746 }
3747 }
3748
3749
3750 spr[1].strength = fstrength;
3751 spr[1].defense = fdefense;
3752
3753
3754 if (flife < 1)
3755 {
3756 script = load_script("dinfo", 1000, /*false*/0);
3757 if (locate(script, "die")) run_script(script);
3758 }
3759
3760 }
3761
3762
kill_last_sprite(void)3763 /*bool*/int kill_last_sprite(void)
3764 {
3765 int found = 0;
3766 /*bool*/int nosetlast = /*false*/0;
3767 int k;
3768 for (k=1; k < MAX_SPRITES_AT_ONCE; k++ )
3769 {
3770 if (spr[k].active)
3771 {
3772 if (spr[k].live)
3773 {
3774 nosetlast = /*true*/1;
3775 }
3776 else
3777 {
3778 found = k;
3779 }
3780 }
3781 }
3782
3783 if (found > 1)
3784 {
3785 spr[found].active = /*FALSE*/0;
3786 if (nosetlast == /*false*/0)
3787 last_sprite_created = found - 1;
3788 return(/*true*/1);
3789 }
3790
3791 //we didn't kill any sprites, only 1 remains
3792 return(/*false*/0);
3793 }
3794
3795
show_bmp(char * name,int showdot,int script)3796 void show_bmp(char* name, int showdot, int script)
3797 {
3798 char* fullpath = paths_dmodfile(name);
3799 SDL_Surface* image = IMG_Load(fullpath);
3800 if (image == NULL)
3801 {
3802 log_error("Couldn't load '%s': %s", name, SDL_GetError());
3803 return;
3804 }
3805
3806 /* Set physical screen palette */
3807 if (!truecolor)
3808 {
3809 gfx_palette_set_from_surface(image);
3810 SDL_Color phys_pal[256];
3811 gfx_palette_get_phys(phys_pal);
3812
3813 /* In case the DX bug messed the palette, let's convert the
3814 image to the new palette. This also converts 24->8bit if
3815 necessary. */
3816 {
3817 SDL_Surface* converted = SDL_DisplayFormat(image);
3818 SDL_SetPalette(converted, SDL_LOGPAL, phys_pal, 0, 256);
3819 SDL_BlitSurface(image, NULL, converted, NULL);
3820 SDL_FreeSurface(image);
3821 image = converted;
3822 }
3823
3824 /* Next blit without palette conversion */
3825 SDL_SetPalette(image, SDL_LOGPAL, GFX_real_pal, 0, 256);
3826 }
3827
3828 showb.active = /*true*/1;
3829 showb.showdot = showdot;
3830 showb.script = script;
3831
3832 SDL_BlitSurface(image, NULL, GFX_lpDDSTrick, NULL);
3833 SDL_FreeSurface(image);
3834
3835 // After show_bmp(), and before the flip_it() call in updateFrame(),
3836 // other parts of the code will draw sprites on lpDDSBack and mess
3837 // the showbmp(). So skip the next flip_it().
3838 abort_this_flip = /*true*/1;
3839 }
3840
3841
3842 /* Used to implement DinkC's copy_bmp_to_screen(). Difference with
3843 show_cmp: does not set showb.* (wait for button), install the image
3844 to lpDDSTwo (background) and not lpDDSBack (screen double
3845 buffer) */
copy_bmp(char * name)3846 void copy_bmp(char* name)
3847 {
3848 char* fullpath = paths_dmodfile(name);
3849 SDL_Surface* image = IMG_Load(fullpath);
3850 if (image == NULL)
3851 {
3852 log_error("Couldn't load '%s': %s", name, SDL_GetError());
3853 return;
3854 }
3855
3856 /* Set physical screen palette */
3857 if (!truecolor)
3858 {
3859 gfx_palette_set_from_surface(image);
3860 SDL_Color phys_pal[256];
3861 gfx_palette_get_phys(phys_pal);
3862
3863 /* In case the DX bug messed the palette, let's convert the
3864 image to the new palette. This also converts 24->8bit if
3865 necessary. */
3866 {
3867 SDL_Surface* converted = SDL_DisplayFormat(image);
3868 SDL_SetPalette(converted, SDL_LOGPAL, phys_pal, 0, 256);
3869 SDL_BlitSurface(image, NULL, converted, NULL);
3870 SDL_FreeSurface(image);
3871 image = converted;
3872 }
3873
3874 /* Next blit without palette conversion */
3875 SDL_SetPalette(image, SDL_LOGPAL, GFX_real_pal, 0, 256);
3876 }
3877
3878 SDL_BlitSurface(image, NULL, GFX_lpDDSTwo, NULL);
3879 SDL_FreeSurface(image);
3880
3881 abort_this_flip = /*true*/1;
3882 }
3883
hurt_thing(int h,int damage,int special)3884 int hurt_thing(int h, int damage, int special)
3885 {
3886 //lets hurt this sprite but good
3887 if (damage < 1) return(0);
3888 int num = damage - spr[h].defense;
3889
3890 // Msg("num is %d.. defense was %d.of sprite %d", num, spr[h].defense, h);
3891 if (num < 1) num = 0;
3892
3893 if (num == 0)
3894 {
3895 if ((rand() % 2)+1 == 1) num = 1;
3896 }
3897
3898 spr[h].damage += num;
3899 return(num);
3900 //draw blood here
3901 }
3902
random_blood(int mx,int my,int sprite)3903 void random_blood(int mx, int my, int sprite)
3904 {
3905 int myseq;
3906 /* v1.08 introduces custom blood sequence, as well as
3907 a slightly different default (select blood in range
3908 187-189 included, instead of 187-188 included) */
3909 int randy;
3910 if (spr[sprite].bloodseq > 0 && spr[sprite].bloodnum > 0)
3911 {
3912 myseq = spr[sprite].bloodseq;
3913 randy = spr[sprite].bloodnum;
3914 }
3915 else
3916 {
3917 myseq = 187;
3918 if (dversion >= 108)
3919 randy = 3;
3920 else
3921 randy = 2;
3922 }
3923 myseq += (rand () % randy);
3924
3925 int crap2 = add_sprite(mx,my,5,myseq,1);
3926 /* TODO: add_sprite might return 0, and the following
3927 would trash spr[0] - cf. bugs.debian.org/688934 */
3928 spr[crap2].speed = 0;
3929 spr[crap2].base_walk = -1;
3930 spr[crap2].nohit = 1;
3931 spr[crap2].seq = myseq;
3932 if (sprite > 0)
3933 spr[crap2].que = spr[sprite].y+1;
3934
3935 }
3936
3937
add_item(char * name,int mseq,int mframe,enum item_type type)3938 void add_item(char* name, int mseq, int mframe, enum item_type type)
3939 {
3940 if (type == ITEM_REGULAR)
3941 {
3942 //add reg item
3943 int i;
3944 for (i = 0; i < NB_ITEMS; i++)
3945 {
3946 if (play.item[i].active == 0)
3947 {
3948 log_info("Weapon/item %s added to inventory.", name);
3949 play.item[i].seq = mseq;
3950 play.item[i].frame = mframe;
3951 strncpy(play.item[i].name, name, sizeof(play.item[i].name));
3952 play.item[i].name[sizeof(play.item[i].name)-1] = '\0';
3953 play.item[i].active = 1;
3954
3955 int crap1 = load_script(play.item[i].name, 1000, /*false*/0);
3956 if (locate(crap1, "PICKUP"))
3957 run_script(crap1);
3958
3959 break;
3960 }
3961 }
3962 }
3963 else
3964 {
3965 //add magic item
3966 int i;
3967 for (i = 0; i < NB_MITEMS; i++)
3968 {
3969 if (play.mitem[i].active == 0)
3970 {
3971 log_info("Magic %s added to inventory.", name);
3972 play.mitem[i].seq = mseq;
3973 play.mitem[i].frame = mframe;
3974 strncpy(play.mitem[i].name, name, sizeof(play.mitem[i].name));
3975 play.mitem[i].name[sizeof(play.mitem[i].name)-1] = '\0';
3976 play.mitem[i].active = 1;
3977
3978 int crap = load_script(play.mitem[i].name, 1000, /*false*/0);
3979 if (locate(crap, "PICKUP"))
3980 run_script(crap);
3981
3982 break;
3983 }
3984 }
3985 }
3986 }
3987
fill_screen(int num)3988 void fill_screen(int num)
3989 {
3990 /* Warning: palette indexes 0 and 255 are hard-coded
3991 to black and white (cf. gfx_palette.c). */
3992 if (!truecolor)
3993 SDL_FillRect(GFX_lpDDSTwo, NULL, num);
3994 else
3995 SDL_FillRect(GFX_lpDDSTwo, NULL, SDL_MapRGB(GFX_lpDDSTwo->format,
3996 GFX_real_pal[num].r,
3997 GFX_real_pal[num].g,
3998 GFX_real_pal[num].b));
3999 }
4000
4001