~ubuntu-branches/ubuntu/lucid/meritous/lucid

« back to all changes in this revision

Viewing changes to src/levelblit.c

  • Committer: Bazaar Package Importer
  • Author(s): Dylan R. E. Moonfire
  • Date: 2008-02-11 13:45:02 UTC
  • Revision ID: james.westby@ubuntu.com-20080211134502-8o235kfyej0lrag8
Tags: upstream-1.2+dfsg
ImportĀ upstreamĀ versionĀ 1.2+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
//   levelblit.c
 
3
//
 
4
//   Copyright 2007, 2008 Lancer-X/ASCEAI
 
5
//
 
6
//   This file is part of Meritous.
 
7
//
 
8
//   Meritous is free software: you can redistribute it and/or modify
 
9
//   it under the terms of the GNU General Public License as published by
 
10
//   the Free Software Foundation, either version 3 of the License, or
 
11
//   (at your option) any later version.
 
12
//
 
13
//   Meritous is distributed in the hope that it will be useful,
 
14
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
//   GNU General Public License for more details.
 
17
//
 
18
//   You should have received a copy of the GNU General Public License
 
19
//   along with Meritous.  If not, see <http://www.gnu.org/licenses/>.
 
20
//
 
21
 
 
22
#include <stdio.h>
 
23
#include <stdlib.h>
 
24
#include <string.h>
 
25
#include <math.h>
 
26
#include <time.h>
 
27
#include <SDL.h>
 
28
#include <SDL_image.h>
 
29
#include <assert.h>
 
30
 
 
31
#include "mapgen.h"
 
32
#include "demon.h"
 
33
#include "gamemap.h"
 
34
#include "tiles.h"
 
35
#include "save.h"
 
36
#include "help.h"
 
37
#include "audio.h"
 
38
#include "boss.h"
 
39
#include "ending.h"
 
40
 
 
41
#define PLAYERW 16
 
42
#define PLAYERH 24
 
43
 
 
44
#define MERITOUS_VERSION "v 1.1"
 
45
int RECORDING = 0;
 
46
int PLAYBACK = 0;
 
47
 
 
48
int expired_ms = 0;
 
49
int frame_len = 33;
 
50
int WriteBitmaps = 0;
 
51
int WB_StartRange = 0;
 
52
int WB_EndRange = 1000000;
 
53
int training = 0;
 
54
int game_paused = 0;
 
55
int show_ending = 0;
 
56
int voluntary_exit = 0;
 
57
int tele_select = 0;
 
58
int enter_room_x = 0, enter_room_y = 0;
 
59
 
 
60
int agate_knife_loc = -1;
 
61
 
 
62
FILE *record_file;
 
63
char record_filename[256];
 
64
 
 
65
void DrawLevel(int off_x, int off_y, int hide_not_visited, int fog_of_war);
 
66
void DrawPlayer(int x, int y, int pl_dir, int pl_frm);
 
67
void LoadLevel();
 
68
void ActivateRoom(int room);
 
69
 
 
70
void DrawCircuit();
 
71
void ReleaseCircuit();
 
72
void DrawCircle(int x, int y, int r, unsigned char c);
 
73
 
 
74
void DrawArtifacts();
 
75
 
 
76
void HandleEvents();
 
77
 
 
78
void text_init();
 
79
void draw_text(int x, int y, char *str, Uint8 tcol);
 
80
unsigned char font_data[128][8][8];
 
81
 
 
82
void DrawShield();
 
83
 
 
84
int key_held[10] = {0};
 
85
int game_running = 1;
 
86
 
 
87
int player_x;
 
88
int player_y;
 
89
int player_dying;
 
90
int magic_circuit;
 
91
int circuit_range;
 
92
int release_range;
 
93
int release_x;
 
94
int release_y;
 
95
int release_str;
 
96
 
 
97
int shield_hp;
 
98
int shield_recover;
 
99
int player_gems;
 
100
int checkpoints_found;
 
101
int circuit_size;
 
102
int first_game;
 
103
int player_hp;
 
104
int player_lives = 5;
 
105
int player_lives_part = 0;
 
106
 
 
107
int player_room;
 
108
int player_dir;
 
109
int player_wlk;
 
110
int player_walk_speed;
 
111
int wlk_wait;
 
112
int circuit_release;
 
113
int scroll_home;
 
114
int enter_pressed;
 
115
 
 
116
int opening_door_x, opening_door_y, opening_door_i = 0, opening_door_n;
 
117
 
 
118
int checkpoint_x;
 
119
int checkpoint_y;
 
120
 
 
121
int explored = 0;
 
122
//#define DEBUG_STATS 1
 
123
 
 
124
int artifacts[12];
 
125
SDL_Surface *artifact_spr = NULL;
 
126
 
 
127
int player_shield;
 
128
int circuit_fillrate;
 
129
int circuit_recoverrate;
 
130
 
 
131
int scroll_x, scroll_y;
 
132
 
 
133
int map_enabled;
 
134
 
 
135
int prv_player_room;
 
136
 
 
137
int specialmessage;
 
138
int specialmessagetimer;
 
139
 
 
140
int timer_ps = 0;
 
141
int timer_v[10];
 
142
 
 
143
float RandomDir()
 
144
{
 
145
        return (float)(rand()%256)*M_PI*2.0/256.0;
 
146
}
 
147
 
 
148
int UpgradePrice(int t);
 
149
 
 
150
void PlayerDefaultStats()
 
151
{
 
152
        int i;
 
153
        
 
154
        player_dying = 0;
 
155
        magic_circuit = 0;
 
156
        circuit_range = 100;
 
157
        release_range = 100;
 
158
        shield_hp = 0;
 
159
        shield_recover = 0;
 
160
        player_gems = 0;
 
161
        checkpoints_found = 0;
 
162
        circuit_size = 1000;
 
163
        first_game = 1;
 
164
        player_hp = 3;
 
165
        
 
166
        explored = 0;
 
167
        
 
168
        voluntary_exit = 0;
 
169
        player_room = 0;
 
170
        player_dir = 0;
 
171
        player_wlk = 0;
 
172
        player_walk_speed = 5;
 
173
        player_lives = 5;
 
174
        player_lives_part = 0;
 
175
        wlk_wait = 8;
 
176
        circuit_release = 0;
 
177
        scroll_home = 0;
 
178
        enter_pressed = 0;
 
179
        show_ending = 0;
 
180
        
 
181
        game_paused = 0;
 
182
        
 
183
        player_shield = 0;
 
184
        circuit_fillrate = 2;
 
185
        circuit_recoverrate = 3;
 
186
        
 
187
        prv_player_room = -1;
 
188
 
 
189
        specialmessage = 0;
 
190
        specialmessagetimer = 0;
 
191
        
 
192
        opening_door_i = 0;
 
193
 
 
194
        map_enabled = 0;
 
195
        
 
196
        for (i = 0; i < 12; i++) {
 
197
                artifacts[i] = 0;
 
198
        }
 
199
        
 
200
        #ifdef DEBUG_STATS
 
201
        
 
202
        player_shield = 24;
 
203
        circuit_fillrate = 24;
 
204
        circuit_recoverrate = 24;
 
205
        
 
206
        for (i = 0; i < 12; i++) {
 
207
                artifacts[i] = 1;
 
208
        }
 
209
        
 
210
        #endif
 
211
}
 
212
 
 
213
 
 
214
void ScrollTo(int x, int y);
 
215
#define K_UP 0
 
216
#define K_DN 1
 
217
#define K_LT 2
 
218
#define K_RT 3
 
219
#define K_SP 4
 
220
 
 
221
SDL_Surface *screen;
 
222
 
 
223
void SetGreyscalePalette();
 
224
void SetTonedPalette(float pct);
 
225
void SetTitlePalette(int curve_start, int curve_end);
 
226
void SetTitlePalette2(int t);
 
227
int TouchTile(int ix, int iy);
 
228
void SpecialTile(int x, int y);
 
229
void DrawRect(int x, int y, int w, int h, unsigned char c);
 
230
 
 
231
void DrawCircleEx(int x, int y, int r, int r2, unsigned char c);
 
232
 
 
233
void ThinLine(SDL_Surface *scr, int x1, int y1, int x2, int y2, Uint8 col);
 
234
void LockDoors(int r);
 
235
 
 
236
#define SCREEN_W 640
 
237
#define SCREEN_H 480
 
238
 
 
239
void VideoUpdate()
 
240
{
 
241
        static int bmp = 0;
 
242
        char bmp_name[256];
 
243
        
 
244
        SDL_UpdateRect(screen, 0, 0, 0, 0);
 
245
        if (WriteBitmaps) {
 
246
                if ((bmp >= WB_StartRange)&&(bmp < WB_EndRange)) {
 
247
                        sprintf(bmp_name, "v/bmp%d.bmp", bmp);
 
248
                        SDL_SaveBMP(screen, bmp_name);
 
249
                }
 
250
                bmp++;
 
251
        }
 
252
}
 
253
 
 
254
void EndCycle(int n)
 
255
{
 
256
        static int last_ticks;
 
257
        int tick_delta;
 
258
        tick_delta = SDL_GetTicks() - last_ticks;
 
259
        
 
260
        if (n == 0) n = frame_len;
 
261
 
 
262
        if (tick_delta < n) {
 
263
                SDL_Delay(n-tick_delta);
 
264
        }
 
265
        
 
266
        if (!game_paused) expired_ms += n;
 
267
                
 
268
        last_ticks = SDL_GetTicks();
 
269
}
 
270
 
 
271
void WritePlayerData()
 
272
{
 
273
        int i;
 
274
 
 
275
        FWInt(expired_ms);
 
276
        FWInt(checkpoint_x);
 
277
        FWInt(checkpoint_y);
 
278
        FWInt(scroll_x);
 
279
        FWInt(scroll_y);
 
280
        FWInt(magic_circuit);
 
281
        FWInt(checkpoint_x);
 
282
        FWInt(checkpoint_y);
 
283
        FWInt(player_walk_speed);
 
284
        FWInt(wlk_wait);
 
285
        FWInt(circuit_fillrate);
 
286
        FWInt(circuit_recoverrate);
 
287
        FWInt(explored);
 
288
        FWInt(player_shield);
 
289
        FWInt(shield_recover);
 
290
        FWInt(shield_hp);
 
291
        FWInt(player_gems);
 
292
        FWInt(checkpoints_found);
 
293
        FWInt(player_hp);
 
294
        FWInt(player_lives);
 
295
        FWInt(player_lives_part);
 
296
        FWInt(current_boss);
 
297
        FWInt(training);
 
298
        FWInt(agate_knife_loc);
 
299
 
 
300
        for (i = 0; i < 12; i++) {
 
301
                FWChar(artifacts[i]);
 
302
        }
 
303
}
 
304
 
 
305
void ReadPlayerData()
 
306
{
 
307
        int i;
 
308
 
 
309
        expired_ms = FRInt();
 
310
        player_x = FRInt();
 
311
        player_y = FRInt();
 
312
        scroll_x = FRInt();
 
313
        scroll_y = FRInt();
 
314
        magic_circuit = FRInt();
 
315
        checkpoint_x = FRInt();
 
316
        checkpoint_y = FRInt();
 
317
        player_walk_speed = FRInt();
 
318
        wlk_wait = FRInt();
 
319
        circuit_fillrate = FRInt();
 
320
        circuit_recoverrate = FRInt();
 
321
        explored = FRInt();
 
322
        player_shield = FRInt();
 
323
        shield_recover = FRInt();
 
324
        shield_hp = FRInt();
 
325
        player_gems = FRInt();
 
326
        checkpoints_found = FRInt();
 
327
        player_hp = FRInt();
 
328
        player_lives = FRInt();
 
329
        player_lives_part = FRInt();
 
330
        current_boss = FRInt();
 
331
        training = FRInt();
 
332
 
 
333
        agate_knife_loc = FRInt();
 
334
 
 
335
        for (i = 0; i < 12; i++) {
 
336
                artifacts[i] = FRChar();
 
337
        }
 
338
}
 
339
 
 
340
int min(int x, int y)
 
341
{
 
342
        if (x<y) return x;
 
343
        return y;
 
344
}
 
345
 
 
346
void DummyEventPoll()
 
347
{
 
348
        SDL_Event e;
 
349
        SDL_PollEvent(&e);
 
350
}
 
351
 
 
352
int DungeonPlay(char *fname);
 
353
 
 
354
Uint8 Uint8_Bound(int c)
 
355
{
 
356
        if (c<0) return 0;
 
357
        if (c>255) return 255;
 
358
        return c;
 
359
}
 
360
 
 
361
int dist(int x1, int y1, int x2, int y2)
 
362
{
 
363
        int dx, dy;
 
364
        dx = x2 - x1;
 
365
        dy = y2 - y1;
 
366
 
 
367
        return sqrt((dx*dx)+(dy*dy));
 
368
}
 
369
 
 
370
void ClearInput()
 
371
{
 
372
        key_held[K_SP] = 0;
 
373
        key_held[K_UP] = 0;
 
374
        key_held[K_DN] = 0;
 
375
        key_held[K_LT] = 0;
 
376
        key_held[K_RT] = 0;
 
377
}
 
378
 
 
379
int main(int argc, char **argv)
 
380
{
 
381
        int on_title = 1;
 
382
        int executable_running = 1;
 
383
        SDL_Surface *title, *title_pr, *asceai;
 
384
        SDL_Surface *wm_icon;
 
385
        Uint8 *src_p, *col_p;
 
386
        Uint8 wm_mask[128];
 
387
        int i;
 
388
        int light = 0;
 
389
        int x, y;
 
390
        int pulse[SCREEN_W * SCREEN_H];
 
391
        int precalc_sine[400];
 
392
        int tick = 10000000;
 
393
        int option = 0;
 
394
        int can_continue = 0;
 
395
        int maxoptions;
 
396
        
 
397
        int last_key = 0;
 
398
        
 
399
        int fullscreen = 0;
 
400
        int ticker_tick = 0;
 
401
        unsigned int stime = 0;
 
402
        
 
403
        FILE *wm_mask_file;
 
404
 
 
405
        if (argc > 1) {
 
406
                for (i = 1; i < argc; i++) {
 
407
                        if (!strcasecmp(argv[i], "fullscreen")) {
 
408
                                fullscreen = 1;
 
409
                        }
 
410
/*                      if (!strcasecmp(argv[i], "record")) {
 
411
                                RECORDING = 1;
 
412
                                strcpy(record_filename, argv[i+1]);
 
413
                        }
 
414
                        if (!strcasecmp(argv[i], "play")) {
 
415
                                PLAYBACK = 1;
 
416
                                strcpy(record_filename, argv[i+1]);
 
417
                        }
 
418
                        if (!strcasecmp(argv[i], "framedelay")) {
 
419
                                frame_len = atoi(argv[i+1]);
 
420
                        }
 
421
                        if (!strcasecmp(argv[i], "bmpwrite")) {
 
422
                                WriteBitmaps = 1;
 
423
                        }
 
424
                        if (!strcasecmp(argv[i], "bmpstart")) {
 
425
                                WB_StartRange = atoi(argv[i+1]);
 
426
                        }
 
427
                        if (!strcasecmp(argv[i], "bmpend")) {
 
428
                                WB_EndRange = atoi(argv[i+1]);
 
429
                        } */
 
430
                }
 
431
        }
 
432
 
 
433
        if ((RECORDING) && (PLAYBACK)) {
 
434
                exit(1);
 
435
        }
 
436
        srand(time(NULL));
 
437
        if (RECORDING) {
 
438
                record_file = fopen(record_filename, "wb");
 
439
                stime = time(NULL);
 
440
                
 
441
                fputc(stime & 0x000000FF, record_file);
 
442
                fputc((stime & 0x0000FF00) >> 8, record_file);
 
443
                fputc((stime & 0x00FF0000) >> 16, record_file);
 
444
                fputc((stime & 0xFF000000) >> 24, record_file);
 
445
                
 
446
                srand(stime);
 
447
        }
 
448
        if (PLAYBACK) {
 
449
                record_file = fopen(record_filename, "rb");
 
450
                stime = fgetc(record_file);
 
451
                stime |= fgetc(record_file) << 8;
 
452
                stime |= fgetc(record_file) << 16;
 
453
                stime |= fgetc(record_file) << 24;
 
454
                
 
455
                srand(stime);
 
456
        }
 
457
        
 
458
        asceai = IMG_Load("dat/i/asceai.png");
 
459
        wm_icon = IMG_Load("dat/i/icon.png");
 
460
        
 
461
        screen = SDL_SetVideoMode(SCREEN_W, SCREEN_H, 8, SDL_SWSURFACE | (SDL_FULLSCREEN * fullscreen));
 
462
        
 
463
        wm_mask_file = fopen("dat/d/icon_bitmask.dat", "rb");
 
464
        fread(wm_mask, 1, 128, wm_mask_file);
 
465
        fclose(wm_mask_file);
 
466
        SDL_WM_SetCaption("~ m e r i t o u s ~", "MT");
 
467
        SDL_WM_SetIcon(wm_icon, wm_mask);
 
468
        InitAudio();
 
469
        
 
470
        text_init();
 
471
        for (i = 0; i < 400; i++) {
 
472
                precalc_sine[i] = sin((float)i / 400 * M_PI * 2)*24+24;
 
473
        }
 
474
        
 
475
                
 
476
        for (i = 0; i < screen->w * screen->h; i++) {
 
477
                x = i % SCREEN_W;
 
478
                y = i / SCREEN_W;
 
479
 
 
480
                pulse[i] = dist(x, y, SCREEN_W / 2, SCREEN_H / 2);
 
481
        }
 
482
        SetGreyscalePalette();
 
483
        
 
484
        // asceai logo
 
485
        SDL_BlitSurface(asceai, NULL, screen, NULL);
 
486
        
 
487
        for (i = 0; i < 75; i++) {
 
488
                SetTitlePalette(i * 5 - 375, i * 5 - 120);
 
489
                VideoUpdate();
 
490
                DummyEventPoll();
 
491
                EndCycle(20);
 
492
        }
 
493
        SDL_Delay(500);
 
494
        for (i = 0; i < 50; i++) {
 
495
                SetTitlePalette(i * 5, 255 - (i * 5));
 
496
                VideoUpdate();
 
497
                DummyEventPoll();
 
498
                EndCycle(20);
 
499
        }
 
500
        SDL_Delay(500);
 
501
        for (i = 0; i < 50; i++) {
 
502
                SetTitlePalette(255, (i * 5)+5);
 
503
                VideoUpdate();
 
504
                DummyEventPoll();
 
505
                EndCycle(20);
 
506
        }
 
507
        
 
508
        while (executable_running) {
 
509
                ticker_tick = 0;
 
510
                TitleScreenMusic();
 
511
                
 
512
                if (IsSaveFile()) {
 
513
                        can_continue = 1;
 
514
                } else {
 
515
                        can_continue = 0;
 
516
                }
 
517
                
 
518
                maxoptions = 2 + can_continue;
 
519
        
 
520
                title = IMG_Load("dat/i/title.png");
 
521
                title_pr = IMG_Load("dat/i/title.png");
 
522
                
 
523
                while (on_title) {
 
524
                        SetTitlePalette2(ticker_tick);
 
525
                        col_p = (Uint8 *)title_pr->pixels;
 
526
                        src_p = (Uint8 *)title->pixels;
 
527
                        if ((tick % 10) == 0) {
 
528
                                for (i = 0; i < 640*480; i++) {
 
529
                                        *(col_p++) = Uint8_Bound(*(src_p++)+precalc_sine[(pulse[i]+tick)%400]);
 
530
                                }
 
531
                        }
 
532
                        SDL_BlitSurface(title_pr, NULL, screen, NULL);
 
533
                        
 
534
                        draw_text(17, 156, MERITOUS_VERSION, 225 + sin((float)ticker_tick / 15)*30);
 
535
                        if (can_continue) draw_text((SCREEN_W - 14*8)/2, 310, "Continue", 255);
 
536
                        draw_text((SCREEN_W - 14*8)/2, 310 + can_continue*10, "New Game", 255);
 
537
                        draw_text((SCREEN_W - 14*8)/2, 320 + can_continue*10, "New Game (Wuss mode)", 255);
 
538
                        
 
539
                        if (ticker_tick >= 30) {
 
540
                                draw_text((SCREEN_W - 14*8)/2 - 17, 310 + option * 10, "-", 205 + sin((float)ticker_tick / 5.0)*24);
 
541
                                draw_text((SCREEN_W - 14*8)/2 - 20, 310 + option * 10, " >", 205 + sin((float)ticker_tick / 5.0)*24);
 
542
                                draw_text((SCREEN_W - 14*8)/2 - 19, 310 + option * 10, " >", 190 + sin((float)ticker_tick / 5.0)*24);
 
543
                                draw_text((SCREEN_W - 14*8)/2 - 21, 310 + option * 10, " >", 190 + sin((float)ticker_tick / 5.0)*24);
 
544
                                draw_text((SCREEN_W - 14*8)/2 - 18, 310 + option * 10, " >", 165 + sin((float)ticker_tick / 5.0)*24);
 
545
                                draw_text((SCREEN_W - 14*8)/2 - 22, 310 + option * 10, " >", 165 + sin((float)ticker_tick / 5.0)*24);
 
546
                        }
 
547
        
 
548
                        VideoUpdate();
 
549
                        
 
550
                        if (ticker_tick++ > 30) {
 
551
                                HandleEvents();
 
552
                
 
553
                                if (key_held[K_UP]) {
 
554
                                        if (last_key != 1)
 
555
                                                if (option > 0) option--;
 
556
                                        last_key = 1;
 
557
                                } else {
 
558
                                        if (key_held[K_DN]) {
 
559
                                                if (last_key != 2)
 
560
                                                        if (option < maxoptions-1) option++;
 
561
                                                last_key = 2;
 
562
                                        } else {
 
563
                                                last_key = 0;
 
564
                                                if (key_held[K_SP] || enter_pressed) {
 
565
                                                        on_title = 0;
 
566
                                                }
 
567
                                        }
 
568
                                }
 
569
                                
 
570
                                if (voluntary_exit) {
 
571
                                        executable_running = 0;
 
572
                                        on_title = 0;
 
573
                                        SDL_Quit();
 
574
                                        exit(0);
 
575
                                }
 
576
                        }
 
577
                        
 
578
                        EndCycle(10);
 
579
        
 
580
                        light = 0;
 
581
                        tick -= 2;
 
582
                }
 
583
                
 
584
                ClearInput();
 
585
                
 
586
                if (executable_running == 1) {
 
587
                        SDL_FreeSurface(title);
 
588
                        SDL_FreeSurface(title_pr);
 
589
                        if ((option == 0) && can_continue) {
 
590
                                DungeonPlay("SaveFile.sav");
 
591
                        } else {
 
592
                                if (option == (0 + can_continue)) {
 
593
                                        training = 0;
 
594
                                        DungeonPlay("");
 
595
                                } else {
 
596
                                        training = 1;
 
597
                                        DungeonPlay("");
 
598
                                }
 
599
                        }
 
600
                        // clean up
 
601
                        ClearInput();
 
602
                        DestroyDungeon();
 
603
                        DestroyThings();
 
604
                        on_title = 1;
 
605
                        game_load = 0;
 
606
                        
 
607
                        game_running = 1;
 
608
                }
 
609
        }
 
610
 
 
611
//      if (argc >= 2) DungeonPlay(argv[1]);
 
612
//      else DungeonPlay("");
 
613
 
 
614
        SDL_Quit();
 
615
        return 0;
 
616
}
 
617
 
 
618
void DrawMeter(int x, int y, int n)
 
619
{
 
620
        static SDL_Surface *meter = NULL;
 
621
        SDL_Rect drawfrom, drawto;
 
622
        if (meter == NULL) {
 
623
                meter = IMG_Load("dat/i/meter.png");
 
624
                SDL_SetColorKey(meter, SDL_SRCCOLORKEY | SDL_RLEACCEL, 0);
 
625
        }
 
626
        
 
627
        drawfrom.x = 0;
 
628
        drawfrom.y = 6;
 
629
        drawfrom.w = 150;
 
630
        drawfrom.h = 6;
 
631
        
 
632
        drawto.x = x;
 
633
        drawto.y = y;
 
634
        
 
635
        SDL_BlitSurface(meter, &drawfrom, screen, &drawto);
 
636
        
 
637
        drawfrom.w = n*6;
 
638
        drawfrom.y = 0;
 
639
        
 
640
        SDL_BlitSurface(meter, &drawfrom, screen, &drawto);
 
641
}
 
642
 
 
643
void ProgressBarScreen(int part, float progress, char *message, float t_parts)
 
644
{
 
645
        memset(screen->pixels, 0, 640*480);
 
646
        
 
647
        DrawRect(200, 217, 240, 50, 80);
 
648
        DrawRect(202, 219, 236, 46, 20);
 
649
        draw_text(232, 228, message, 255);
 
650
        DrawRect(232, 244, 176, 12, 128);
 
651
        DrawRect(234, 246, 172, 8, 0);
 
652
        
 
653
        if ((int)(172.0 * progress / t_parts + (172.0 / t_parts * part)) > 0) {
 
654
                DrawRect(234, 246, (int)(172.0 * progress / t_parts + (172.0 / t_parts * part)), 8, 200);
 
655
        }
 
656
        VideoUpdate();
 
657
        DummyEventPoll();
 
658
}
 
659
 
 
660
void LoadingScreen(int part, float progress)
 
661
{
 
662
        float t_parts;
 
663
        
 
664
        if (game_load) t_parts = 5.0;
 
665
        else t_parts = 3.0;
 
666
        
 
667
        ProgressBarScreen(part, progress, "Loading... please wait", t_parts);
 
668
        ClearInput();
 
669
}
 
670
 
 
671
void SavingScreen(int part, float progress)
 
672
{
 
673
        ProgressBarScreen(part, progress, "Saving... please wait", 4.0);
 
674
        ClearInput();
 
675
}
 
676
 
 
677
void Arc(SDL_Surface *s, int x, int y, int r, float dir)
 
678
{
 
679
        int bright;
 
680
        int i, c;
 
681
        float pdir, cdir, ndir;
 
682
        
 
683
        int l_x = x, l_y = y;
 
684
        int cx, cy, c1x, c1y, c2x, c2y;
 
685
        
 
686
        bright = rand()%128+63;
 
687
        i = 0;
 
688
        while (i < r) {
 
689
                i += rand()%5+25;
 
690
                pdir = dir + (float)(rand()%16)/16.0*2.0*(M_PI / 15.0);
 
691
                ndir = dir - (float)(rand()%16)/16.0*2.0*(M_PI / 15.0);
 
692
                cdir = dir + (float)(rand()%16)/16.0*2.0*(M_PI / 20.0) - (float)(rand()%16)/16.0*2.0*(M_PI / 20.0);
 
693
 
 
694
                bright += rand()%30;
 
695
                bright -= rand()%30;
 
696
                
 
697
                if (bright < 0) bright = 0;
 
698
                if (bright > 255) bright = 255;
 
699
                
 
700
                c1x = x + cos(pdir) * i;
 
701
                c1y = y + sin(pdir) * i;
 
702
                ThinLine(s, l_x, l_y, c1x, c1y, bright);
 
703
                c2x = x + cos(ndir) * i;
 
704
                c2y = y + sin(ndir) * i;
 
705
                ThinLine(s, l_x, l_y, c2x, c2y, bright);
 
706
                
 
707
                for (c = 0; c < 5; c++) {
 
708
                        DrawRect(x + cos(dir - (M_PI / 10.0) + (float)(rand()%16)/16.0*2.0*(M_PI / 10.0)) * i, y + sin(dir - (M_PI / 10.0) +
 
709
                                          (float)(rand()%16)/16.0*2.0*(M_PI / 10.0)) * i, 1, 1, rand()%128+63);
 
710
                }
 
711
                
 
712
                i += rand()%5+25;
 
713
                cx = x + cos(cdir) * i;
 
714
                cy = y + sin(cdir) * i;
 
715
                ThinLine(s, c1x, c1y, cx, cy, bright);
 
716
                ThinLine(s, c2x, c2y, cx, cy, bright);
 
717
                l_x = cx;
 
718
                l_y = cy;
 
719
        }
 
720
        
 
721
}
 
722
 
 
723
int DungeonPlay(char *fname)
 
724
{
 
725
        int ix,  iy;
 
726
        int off_x, off_y;
 
727
        int t = 0;
 
728
        int i, j;
 
729
        int lost_gems;
 
730
        int rg_x, rg_y, rg_v;
 
731
        int max_dist;
 
732
        int last_killed = 0;
 
733
        int n_arcs = 0;
 
734
        int can_move;
 
735
        
 
736
        float arcdir;
 
737
        
 
738
        char buf[50];
 
739
        
 
740
        expired_ms = 0;
 
741
        LoadingScreen(0, 0.0);
 
742
        if (fname[0] != 0) {
 
743
                LoadGame(fname);
 
744
        }
 
745
 
 
746
        RandomGenerateMap();
 
747
        InitEnemies();
 
748
        InitBossVars();
 
749
 
 
750
        PlayerDefaultStats();
 
751
        if (game_load) {
 
752
                first_game = 0;
 
753
                ReadPlayerData();
 
754
                //Paint(rooms[0].x+1, rooms[0].y+1, rooms[0].w-2, rooms[0].h-2, "dat/d/fbossroom.loc");
 
755
        } else {
 
756
                player_x = map.w * 32 / 2 - PLAYERW/2;
 
757
                player_y = map.h * 32 / 2 - PLAYERH/2;
 
758
        }
 
759
 
 
760
        InitAutomap();
 
761
 
 
762
        if (game_load) CloseFile();
 
763
 
 
764
        max_dist = 0;
 
765
        for (i = 0; i < 3000; i++) {
 
766
                if (rooms[i].s_dist > max_dist) {
 
767
                        max_dist = rooms[i].s_dist;
 
768
                }
 
769
        }
 
770
        
 
771
        game_running = 1;
 
772
        while (game_running) {
 
773
                //sprintf(buf, "X: %d  Y: %d", (player_x + PLAYERW/2)/32*32 + PLAYERW/2, (player_y + PLAYERH/2)/32*32 + PLAYERH/2);
 
774
                //SDL_WM_SetCaption(buf, "MT");
 
775
                if (!game_paused) {
 
776
                        if (player_dying > 30) {
 
777
                                player_hp--;
 
778
                                
 
779
                                if (player_hp <= 0) {
 
780
                                        if (!training) player_lives--;
 
781
                                        lost_gems = player_gems / 3;
 
782
                                        player_gems -= lost_gems;
 
783
                
 
784
                                        lost_gems = lost_gems * 95 / 100;
 
785
                                        while (lost_gems > 0) {
 
786
                                                rg_x = rooms[player_room].x * 32 + 32 + rand()%(rooms[player_room].w*32-64);
 
787
                                                rg_y = rooms[player_room].y * 32 + 32 + rand()%(rooms[player_room].h*32-64);
 
788
                                                rg_v = rand() % (lost_gems / 4 + 2);
 
789
                                                CreateGem(rg_x, rg_y, player_room, rg_v);
 
790
                                                lost_gems -= rg_v;
 
791
                                        }
 
792
                
 
793
                                        player_dying = 0;
 
794
                                        shield_hp = 0;
 
795
                                        
 
796
                                        if ( (current_boss == 3) && (boss_fight_mode != 0) ) {
 
797
                                                player_x = enter_room_x;
 
798
                                                player_y = enter_room_y;
 
799
                                                prv_player_room = 1;
 
800
                                        } else {
 
801
                                                player_x = checkpoint_x;
 
802
                                                player_y = checkpoint_y;
 
803
                                        }
 
804
                                        scroll_home = 1;
 
805
                                        CircuitBullets(player_x, player_y, 100);
 
806
                                        player_hp = 3 + (player_shield == 30)*3;
 
807
                                } else {
 
808
                                        player_dying = 0;
 
809
                                }
 
810
                        }
 
811
                }
 
812
                
 
813
                circuit_size = 250 + 50*(circuit_fillrate + circuit_recoverrate);
 
814
                
 
815
                if (magic_circuit > 0) {
 
816
                        circuit_range = (sqrt(magic_circuit + 1) * 6 + min(magic_circuit / 2, 50))*1.66;
 
817
                        if (artifacts[3]) circuit_range += circuit_range / 2.4;
 
818
                } else circuit_range = -1;
 
819
                player_room = GetRoom(player_x/32, player_y/32);
 
820
 
 
821
                if (player_room != prv_player_room) {
 
822
                        SetTonedPalette((float)rooms[player_room].s_dist / (float)max_dist);
 
823
                        prv_player_room = player_room;
 
824
                        RecordRoom(player_room);
 
825
                        
 
826
                        enter_room_x = player_x;
 
827
                        enter_room_y = player_y;
 
828
                                                
 
829
                        if (rooms[player_room].room_type == 2) {
 
830
                                // lock the doors
 
831
                                LockDoors(player_room);
 
832
                                // it's a boss room
 
833
                                BossRoom(player_room);
 
834
                        }
 
835
                        if (((rooms[player_room].checkpoint)||(player_room==0))&&(!artifacts[11])) {
 
836
                                checkpoint_x = rooms[player_room].x * 32 + (rooms[player_room].w / 2 * 32) + 8;
 
837
                                checkpoint_y = rooms[player_room].y * 32 + (rooms[player_room].h / 2 * 32) + 4;
 
838
                        }
 
839
                        if (rooms[player_room].visited == 0) {
 
840
                                rooms[player_room].visited = 1;
 
841
                                explored++;
 
842
                                
 
843
                                if (explored == 3000) {
 
844
                                        agate_knife_loc = player_room;
 
845
                                }
 
846
                                
 
847
                                ActivateRoom(player_room);
 
848
                        }
 
849
                }
 
850
                
 
851
                if (last_killed != killed_enemies) {
 
852
                        SetTonedPalette((float)rooms[player_room].s_dist / (float)max_dist);
 
853
                        last_killed = killed_enemies;
 
854
                } else {
 
855
                        if ((player_room == 0)&&(artifacts[11] == 1)) {
 
856
                                SetTonedPalette(0);
 
857
                        }
 
858
                }
 
859
 
 
860
                if (!map_enabled) {
 
861
                        ScrollTo(player_x + PLAYERW/2 - 320, player_y + PLAYERH/2 - 240);
 
862
                        DrawLevel(scroll_x, scroll_y, 1, 1);
 
863
                        //DrawLevel(player_x + 8 - 320, player_y + 12 - 240);
 
864
        
 
865
                        if (player_dying == 0) {
 
866
                                DrawShield();
 
867
                                
 
868
                                if (magic_circuit > 0) {
 
869
                                        if (player_dying == 0) {
 
870
                                                if (circuit_release == 0) {
 
871
                                                        arcdir = RandomDir();
 
872
                                                        n_arcs = 1 + (circuit_size / 200 + 2) * magic_circuit / circuit_size;
 
873
                                                        for (i = 0; i < n_arcs; i++) {
 
874
                                                                Arc(screen, player_x - scroll_x + PLAYERW/2, player_y - scroll_y + PLAYERH/2, circuit_range, arcdir);
 
875
                                                                arcdir += (float)(rand()%16) / 16.0 * (M_PI*2/(float)n_arcs);
 
876
                                                        }
 
877
                                                }
 
878
                                        }
 
879
                                }
 
880
                        
 
881
                                DrawPlayer(312, 228, player_dir, player_wlk / wlk_wait);
 
882
                        } else {
 
883
                                if (t % 2 == 0) DrawPlayer(312, 228, player_dir, player_wlk / wlk_wait);
 
884
        
 
885
                                if (!game_paused)
 
886
                                        player_dying++;
 
887
                        }
 
888
                        t++;
 
889
                        if ((boss_fight_mode != 0)&&(boss_fight_mode < 23)&&(!game_paused)) {
 
890
                                BossControl();
 
891
                        }
 
892
                        DrawEntities();
 
893
                        if (!game_paused) MoveEntities();
 
894
                        
 
895
                        if (boss_fight_mode == 2) {
 
896
                                DrawBossHP(100);
 
897
                        }
 
898
                        
 
899
                        if (rooms[player_room].room_type == 5) {
 
900
                                DrawPowerObject();
 
901
                        }
 
902
                        if ( (rooms[player_room].room_type == 6) && (current_boss == 3) ) {
 
903
                                DrawPowerObject();
 
904
                        }
 
905
                        if ((rooms[player_room].room_type == 4) && ((player_room % 1000) == 999)) {
 
906
                                DrawPowerObject();
 
907
                        }
 
908
                        if (player_room == agate_knife_loc) {
 
909
                                {
 
910
                                        static float agate_t = 0.0;
 
911
                                        static SDL_Surface *agate_knife = NULL;
 
912
                                        int xpos, ypos;
 
913
                                        int room_w, room_h;
 
914
                                        int room_x, room_y;
 
915
                                        
 
916
                                        room_x = rooms[player_room].x * 32 + 32;
 
917
                                        room_y = rooms[player_room].y * 32 + 32;
 
918
                                        room_w = rooms[player_room].w * 32 - 64;
 
919
                                        room_h = rooms[player_room].h * 32 - 64;
 
920
                                        
 
921
                                        SDL_Rect draw_to;
 
922
                                        if (agate_knife == NULL) {
 
923
                                                agate_knife = IMG_Load("dat/i/agate.png");
 
924
                                                SDL_SetColorKey(agate_knife, SDL_SRCCOLORKEY | SDL_RLEACCEL, 0);
 
925
                                        }
 
926
                                        xpos = (int)((sin(agate_t * 1.33)*0.5+0.5) * (float)room_w) + room_x;
 
927
                                        ypos = (int)((cos(agate_t * 0.7)*0.5+0.5) * (float)room_h) + room_y;
 
928
                                        
 
929
                                        if (dist(player_x, player_y, xpos, ypos) < 20) {
 
930
                                                agate_knife_loc = -1;
 
931
                                                specialmessage = 50;
 
932
                                                specialmessagetimer = 150;
 
933
                                                SND_Pos("dat/a/crystal2.wav", 128, 0);
 
934
                                                
 
935
                                                player_shield = 30;
 
936
                                                circuit_fillrate = 30;
 
937
                                                circuit_recoverrate = 30;
 
938
                                                player_hp = 6;
 
939
                                        }
 
940
                                        draw_to.x = xpos - 16 - scroll_x;
 
941
                                        draw_to.y = ypos - 16 - scroll_y;
 
942
                                        
 
943
                                        SDL_BlitSurface(agate_knife, NULL, screen, &draw_to);
 
944
                                                                                
 
945
                                        agate_t += 0.05;
 
946
                                }
 
947
                        }
 
948
                        
 
949
                        if (opening_door_i > 0) {
 
950
                                DrawArtifactOverhead(opening_door_n);
 
951
                                for (i = 0; i < 5; i++) {
 
952
                                        j = i * 50 - 250 + (opening_door_i * 5);
 
953
                                        if (j > 0) {
 
954
                                                DrawCircle(player_x - scroll_x, player_y - scroll_y, j, 255);
 
955
                                        }
 
956
                                }
 
957
                                
 
958
                                if (!game_paused) {
 
959
                                        opening_door_i++;
 
960
                                        if (opening_door_i >= 100) {
 
961
                                                opening_door_i = 0;
 
962
                                                Put(opening_door_x, opening_door_y, Get(opening_door_x, opening_door_y) - 38 + 13, GetRoom(opening_door_x, opening_door_y));
 
963
                                        }
 
964
                                }
 
965
                        }
 
966
        
 
967
                        if (circuit_release > 0) {
 
968
                                DrawCircle(release_x - player_x + 320, release_y - player_y + 240, circuit_release * release_range / 20, sin((float)circuit_release / 20.0)*127+127);
 
969
                                if (!game_paused) {
 
970
                                        CircuitBullets(release_x, release_y, circuit_release * release_range / 20);
 
971
                                        //HurtEnemies(release_x, release_y, circuit_release * release_range / 20, release_str);
 
972
                                        circuit_release+=2;
 
973
                
 
974
                                        if (circuit_release > 24) {
 
975
                                                circuit_release = 0;
 
976
                                                HurtEnemies(release_x, release_y, release_range, release_str);
 
977
                                                if (boss_fight_mode == 2) TryHurtBoss(release_x, release_y, release_range, release_str);
 
978
                                        }
 
979
                                }
 
980
                        }
 
981
        
 
982
                        if (!game_paused) {
 
983
                                if (shield_hp < player_shield) {
 
984
                                        shield_recover += player_shield * 3 / (3 - training - (player_shield == 30));
 
985
                                        if (artifacts[1]) shield_recover += player_shield * 3 / (3 - training - (player_shield == 30));
 
986
                                        if (shield_recover >= 50) {
 
987
                                                shield_hp++;
 
988
                                                shield_recover -= 50 - (player_shield == 30)*25;
 
989
                                        }
 
990
                                }
 
991
                        }
 
992
                }
 
993
                
 
994
                DrawRect(0, 0, 640, 29, 0);
 
995
                DrawRect(1, 1, 638, 27, 32);
 
996
                DrawRect(2, 2, 636, 25, 64);
 
997
                
 
998
                if (!tele_select) {
 
999
                        sprintf(buf, "Psi Crystals: %d", player_gems);
 
1000
                        draw_text(3, 3, buf, 200);
 
1001
                        sprintf(buf, "Explored: %.1f%% (%d/%d rooms)", (float)explored/30.0, explored, 3000);
 
1002
                        draw_text(3, 11, buf, 200);
 
1003
                        sprintf(buf, "Cleared: %.1f%% (%d/%d monsters)", (float)killed_enemies/(float)total_enemies*100.0, killed_enemies, total_enemies);
 
1004
                        draw_text(3, 19, buf, 200);
 
1005
                        
 
1006
                        draw_text(316, 3, "Reflect shield", (player_gems >= UpgradePrice(0))&&(player_shield!=30) ? (231 + (t%13)*2) : 200);
 
1007
                        DrawMeter(434, 3, player_shield);
 
1008
                        
 
1009
                        draw_text(316, 11, "Circuit charge", (player_gems >= UpgradePrice(1))&&(circuit_fillrate!=30) ? (231 + (t%13)*2) : 200);
 
1010
                        DrawMeter(434, 11, circuit_fillrate);
 
1011
                        
 
1012
                        draw_text(316, 19, "Circuit refill", (player_gems >= UpgradePrice(2))&&(circuit_recoverrate!=30) ? (231 + (t%13)*2) : 200);
 
1013
                        DrawMeter(434, 19, circuit_recoverrate);
 
1014
                        
 
1015
                } else {
 
1016
                        draw_text(80, 11-6, "Use the movement keys to locate a checkpoint. Press ENTER to", 240);
 
1017
                        draw_text(52, 11+6, "teleport to this checkpoint. Press ESCAPE or TAB once you are done.", 240);
 
1018
                }
 
1019
                
 
1020
                if (!training) {
 
1021
                        buf[0] = 30;
 
1022
                
 
1023
                        if (player_lives <= 99) {
 
1024
                                if (player_lives < 10) {
 
1025
                                        sprintf(buf+1, " %d", player_lives);
 
1026
                                } else {
 
1027
                                        sprintf(buf+1, "%d", player_lives);
 
1028
                                }
 
1029
                        } else {
 
1030
                                sprintf(buf+1, "**");
 
1031
                        }
 
1032
                        
 
1033
                        draw_text(615, 4, buf, 200);
 
1034
                        
 
1035
                        DrawRect(615, 13, 24, 4, 240);
 
1036
                        DrawRect(616, 14, 22, 2, 0);
 
1037
                        i = (player_lives_part * 22 / 88);
 
1038
                        if (i > 0) {
 
1039
                                DrawRect(616, 14, i, 2, 160 + (t % 40));
 
1040
                        }
 
1041
                }
 
1042
                
 
1043
                if (player_shield != 30) {
 
1044
                        for (i = 0; i < player_hp; i++) {
 
1045
                                buf[i] = 3;
 
1046
                        }
 
1047
                        buf[player_hp]=0;
 
1048
                } else {
 
1049
                        for (i = 0; i < (player_hp / 2); i++) {
 
1050
                                buf[i] = 3;
 
1051
                        }
 
1052
                        if ((player_hp % 2) == 1) {
 
1053
                                buf[(player_hp + 1) / 2 - 1] = 2;
 
1054
                        }
 
1055
                        buf[(player_hp+1)/2]=0;
 
1056
                }
 
1057
                
 
1058
                draw_text(615, 18 - (5*training), buf, 200);
 
1059
 
 
1060
                DrawRect(0, 466, 640, 14, 0);
 
1061
                DrawRect(1, 467, 638, 12, 32);
 
1062
                DrawRect(2, 468, 636, 10, 64);
 
1063
                
 
1064
                DrawCircuit();
 
1065
                DrawArtifacts();
 
1066
                
 
1067
                SpecialTile((player_x+PLAYERW/2)/32, (player_y+PLAYERH/2)/32);
 
1068
 
 
1069
                if (map_enabled) DisplayAutomap();
 
1070
                
 
1071
                if ((boss_fight_mode != 0)&&(boss_fight_mode == 23)&&(!game_paused)) {
 
1072
                        BossControl();
 
1073
                }
 
1074
                if ( (boss_dlg != 0) && (!game_paused)) {
 
1075
                        BossDialog();
 
1076
                }
 
1077
                
 
1078
                if (game_paused && (!map_enabled) && (!voluntary_exit)) {
 
1079
                        for (i = 0; i < 10; i++) {
 
1080
                                DrawRect((640 - 6 * 8) / 2 - i, (480 - 8) / 2 - i, 6*8 + 2*i, 8 + 2*i, 64 - i*5);
 
1081
                        }
 
1082
                        draw_text((640 - 6 * 8) / 2, (480 - 8) / 2, "Paused", 255);
 
1083
                        
 
1084
                        {
 
1085
                                int t_days;
 
1086
                                int t_hours;
 
1087
                                int t_minutes;
 
1088
                                int t_seconds;
 
1089
                                
 
1090
                                t_seconds = (expired_ms / 1000) % 60;
 
1091
                                t_minutes = ((expired_ms / 1000) / 60) % 60;
 
1092
                                t_hours = (((expired_ms / 1000) / 60) / 60) % 24;
 
1093
                                t_days = (((expired_ms / 1000) / 60) / 60) / 24;
 
1094
                                
 
1095
                                if (t_days > 0) {
 
1096
                                        sprintf(buf, "%dd %dh %dm %ds", t_days, t_hours, t_minutes, t_seconds);
 
1097
                                } else {
 
1098
                                        if (t_hours > 0) {
 
1099
                                                sprintf(buf, "%dh %dm %ds", t_hours, t_minutes, t_seconds);
 
1100
                                        } else {
 
1101
                                                sprintf(buf, "%dm %ds", t_minutes, t_seconds);
 
1102
                                        }
 
1103
                                }
 
1104
                                draw_text(636 - strlen(buf)*8, 470, buf, 255);
 
1105
                        }
 
1106
                }
 
1107
                
 
1108
                if (voluntary_exit) {
 
1109
                        DrawRect(152, 200, 336, 80, 128);
 
1110
                        DrawRect(160, 208, 320, 64, 64);
 
1111
                        draw_text((640 - 30 * 8) / 2, (480 - 8) / 2 - 4, "Are you sure you want to quit?", 255);
 
1112
                        draw_text((640 - 23 * 8) / 2, (480 - 8) / 2 + 4, "Press enter to confirm.", 255);
 
1113
                }
 
1114
                
 
1115
                VideoUpdate();
 
1116
                
 
1117
                MusicUpdate();
 
1118
                
 
1119
                EndCycle(0);
 
1120
                
 
1121
                can_move = 1;
 
1122
                
 
1123
                if ((player_dying != 0) && (player_hp <= 1)) can_move = 0;
 
1124
                if (rooms[player_room].room_type == 5)
 
1125
                        if (CanGetArtifact())
 
1126
                                if (Get((player_x+PLAYERW/2)/32, (player_y+PLAYERH/2)/32)==42)
 
1127
                                        if (rooms[player_room].enemies == 0)
 
1128
                                                can_move = 0;
 
1129
                                                
 
1130
                if (rooms[player_room].room_type == 6)
 
1131
                        if (CanGetArtifact())
 
1132
                                if (PlayerDist(rooms[player_room].w * 16 + rooms[player_room].x * 32,
 
1133
                                                        rooms[player_room].h * 16 + rooms[player_room].y * 32) < 32)
 
1134
                                        if (rooms[player_room].enemies == 0)
 
1135
                                                if (current_boss == 3)
 
1136
                                                        can_move = 0;
 
1137
                                        
 
1138
                if (scroll_home != 0) can_move = 0;
 
1139
                if (boss_fight_mode == 1) can_move = 0;
 
1140
                if (boss_fight_mode >= 3) can_move = 0;
 
1141
                if (opening_door_i != 0) can_move = 0;
 
1142
                if (game_paused) can_move = 0;
 
1143
                
 
1144
                HandleEvents();
 
1145
                if (map_enabled) {
 
1146
                        game_paused = 1;
 
1147
                }
 
1148
                
 
1149
                if (can_move) {
 
1150
                        
 
1151
                        ix = player_x;
 
1152
                        iy = player_y;
 
1153
                        off_x = 0;
 
1154
                        off_y = 0;
 
1155
                        if (key_held[K_UP] && !key_held[K_DN]) {
 
1156
                                iy -= player_walk_speed * (artifacts[4]?1.4:1);
 
1157
                                player_dir = 0;
 
1158
                        }
 
1159
                        if (key_held[K_DN] && !key_held[K_UP]) {
 
1160
                                iy += player_walk_speed * (artifacts[4]?1.4:1);;
 
1161
                                player_dir = 1;
 
1162
                                off_y = 24;
 
1163
                        }
 
1164
                        if (key_held[K_LT] && !key_held[K_RT]) {
 
1165
                                ix -= player_walk_speed * (artifacts[4]?1.4:1);;
 
1166
                                if (!(key_held[K_UP] || key_held[K_DN])) {
 
1167
                                        player_dir = 3;
 
1168
                                }
 
1169
                        }
 
1170
                        if (key_held[K_RT] && !key_held[K_LT]) {
 
1171
                                off_x = 16;
 
1172
                                ix += player_walk_speed * (artifacts[4]?1.4:1);;
 
1173
                                if (!(key_held[K_UP] || key_held[K_DN])) {
 
1174
                                        player_dir = 2;
 
1175
                                        
 
1176
                                }
 
1177
                        }
 
1178
                        if ((key_held[K_SP])&&(magic_circuit >= 0)) {
 
1179
                                magic_circuit += (circuit_fillrate * (3+training+(circuit_fillrate==30))/3);
 
1180
                        } else {
 
1181
                                if (magic_circuit < 0) {
 
1182
                                        magic_circuit += (circuit_recoverrate * (3+training+(circuit_recoverrate==30))/3);
 
1183
                                        if (magic_circuit > 0) magic_circuit = 0;
 
1184
                                } else {
 
1185
                                        if (magic_circuit > 0) {
 
1186
                                                ReleaseCircuit();
 
1187
                                        }
 
1188
                                }
 
1189
                        }
 
1190
 
 
1191
                        if (magic_circuit > circuit_size) magic_circuit = circuit_size;
 
1192
                        
 
1193
                        if ((ix!=player_x)||(iy!=player_y)) {
 
1194
                                // Are we changing to a new square?
 
1195
                                if (((player_x / 32)!=((ix+off_x) / 32)) || ((player_y / 32)!=((iy+off_y) / 32))) {
 
1196
                                        //printf("%d\n", tile);
 
1197
                                        if (TouchTile(ix, iy)) {
 
1198
                                                player_wlk = (player_wlk + 1 + artifacts[4]*3) % (4*wlk_wait);
 
1199
                                        } else {
 
1200
                                                if (TouchTile(player_x, iy)) {
 
1201
                                                        player_wlk = (player_wlk + 1 + artifacts[4]*3) % (4*wlk_wait);
 
1202
                                                } else {
 
1203
                                                        if (TouchTile(ix, player_y)) {
 
1204
                                                                player_wlk = (player_wlk + 1 + artifacts[4]*3) % (4*wlk_wait);
 
1205
                                                                if (off_x > 0) player_dir = 2;
 
1206
                                                                else player_dir = 3;
 
1207
                                                        }
 
1208
                                                }
 
1209
                                                
 
1210
                                        }
 
1211
                                } else {
 
1212
                                        player_x = ix;
 
1213
                                        player_y = iy;
 
1214
                                        
 
1215
                                        player_wlk = (player_wlk + 1 + artifacts[4]*3) % (4*wlk_wait);
 
1216
                                }
 
1217
                        }
 
1218
                }
 
1219
                
 
1220
                if ((t % (33 * 10))==(33 * 10 - 1)) {
 
1221
                        ActivateRand();
 
1222
                }
 
1223
                
 
1224
                if (voluntary_exit && enter_pressed) {
 
1225
                        voluntary_exit = 0;
 
1226
                        game_running = 0;
 
1227
                        game_paused = 0;
 
1228
                }
 
1229
                
 
1230
                if ((player_lives == 0) && (!training)) {
 
1231
                        break;
 
1232
                }
 
1233
                if (show_ending) {
 
1234
                        break;
 
1235
                }
 
1236
        }
 
1237
        
 
1238
        if (show_ending) {
 
1239
                show_ending = 0;
 
1240
                ShowEnding();
 
1241
        }
 
1242
        
 
1243
        if ((player_lives == 0) && (!training)) {
 
1244
                SDL_FillRect(screen, NULL, 0);
 
1245
                draw_text(252, 236, "G A M E   O V E R", 255);
 
1246
                VideoUpdate();
 
1247
                SDL_Delay(2000);
 
1248
        }
 
1249
        
 
1250
        return 0;
 
1251
}
 
1252
 
 
1253
void UpRoom()
 
1254
{
 
1255
        int i, nd;
 
1256
        
 
1257
        nd = rooms[player_room].s_dist + 1;
 
1258
        
 
1259
        for (i = 0; i < 3000; i++) {
 
1260
                if (rooms[i].s_dist == nd) {
 
1261
                        player_x = rooms[i].x * 32 + 64;
 
1262
                        player_y = rooms[i].y * 32 + 64;
 
1263
                }
 
1264
        }
 
1265
}
 
1266
 
 
1267
void CancelVoluntaryExit()
 
1268
{
 
1269
        if (voluntary_exit) {
 
1270
                voluntary_exit = 0;
 
1271
                game_paused = 0;
 
1272
        }
 
1273
}
 
1274
 
 
1275
void HandleEvents()
 
1276
{
 
1277
        unsigned short db;
 
1278
        static SDL_Event event;
 
1279
        int pressed_tab = 0;
 
1280
        
 
1281
        if (PLAYBACK) {
 
1282
                db = fgetc(record_file);
 
1283
                db |= fgetc(record_file) << 8;
 
1284
                
 
1285
                key_held[K_UP] = (db & 0x0001)>0;
 
1286
                key_held[K_DN] = (db & 0x0002)>0;
 
1287
                key_held[K_LT] = (db & 0x0004)>0;
 
1288
                key_held[K_RT] = (db & 0x0008)>0;
 
1289
                key_held[K_SP] = (db & 0x0010)>0;
 
1290
                enter_pressed  = (db & 0x0020)>0;
 
1291
                map_enabled    = (db & 0x0040)>0;
 
1292
                game_running   = (db & 0x0080)>0;
 
1293
                game_paused    = (db & 0x0100)>0;
 
1294
                voluntary_exit = (db & 0x0200)>0;
 
1295
                pressed_tab    = (db & 0x0400)>0;
 
1296
                tele_select    = (db & 0x0800)>0;
 
1297
 
 
1298
                return;
 
1299
        }
 
1300
        
 
1301
        if (pressed_tab) {
 
1302
                c_scroll_x = player_x;
 
1303
                c_scroll_y = player_y;
 
1304
        }
 
1305
        
 
1306
        enter_pressed = 0;
 
1307
                while (SDL_PollEvent(&event)) {
 
1308
                        if (event.type == SDL_KEYDOWN) {
 
1309
                                switch (event.key.keysym.sym) {
 
1310
                                        case SDLK_w:
 
1311
                                        case SDLK_UP:
 
1312
                                                key_held[K_UP] = 1;
 
1313
                                                CancelVoluntaryExit();
 
1314
                                                break;
 
1315
                                        case SDLK_s:
 
1316
                                        case SDLK_DOWN:
 
1317
                                                key_held[K_DN] = 1;
 
1318
                                                CancelVoluntaryExit();
 
1319
                                                break;
 
1320
                                        case SDLK_a:
 
1321
                                        case SDLK_LEFT:
 
1322
                                                key_held[K_LT] = 1;
 
1323
                                                CancelVoluntaryExit();
 
1324
                                                break;
 
1325
                                        case SDLK_d:
 
1326
                                        case SDLK_RIGHT:
 
1327
                                                key_held[K_RT] = 1;
 
1328
                                                CancelVoluntaryExit();
 
1329
                                                break;
 
1330
                                        case SDLK_SPACE:
 
1331
                                                key_held[K_SP] = 1;
 
1332
                                                CancelVoluntaryExit();
 
1333
                                                break;
 
1334
                                        case SDLK_RETURN:
 
1335
                                                enter_pressed = 1;
 
1336
                                                break;
 
1337
                                        case SDLK_ESCAPE:
 
1338
                                                if (map_enabled) {
 
1339
                                                        map_enabled = 0;
 
1340
                                                        game_paused = 0;
 
1341
                                                        tele_select = 0;
 
1342
                                                } else {
 
1343
                                                        voluntary_exit ^= 1;
 
1344
                                                        game_paused = voluntary_exit;
 
1345
                                                }
 
1346
                                                break;
 
1347
                                        case SDLK_TAB:
 
1348
                                                if (tele_select) {
 
1349
                                                        map_enabled = 0;
 
1350
                                                        game_paused = 0;
 
1351
                                                        tele_select = 0;
 
1352
                                                } else {
 
1353
                                                        pressed_tab = 1;
 
1354
                                                        map_enabled ^= 1;
 
1355
                                                        game_paused = map_enabled;
 
1356
                                                        c_scroll_x = player_x;
 
1357
                                                        c_scroll_y = player_y;
 
1358
                                                }
 
1359
                                                CancelVoluntaryExit();
 
1360
                                                break;
 
1361
                                        case SDLK_h:
 
1362
                                                CancelVoluntaryExit();
 
1363
                                                ShowHelp();
 
1364
                                                break;
 
1365
                                        case SDLK_p:
 
1366
                                                game_paused ^= 1;
 
1367
                                                CancelVoluntaryExit();
 
1368
                                                break;
 
1369
                                                
 
1370
                                                
 
1371
                                        /*
 
1372
                                        case SDLK_j:
 
1373
                                                {
 
1374
                                                        player_shield = 20;
 
1375
                                                        circuit_recoverrate = 20;
 
1376
                                                        circuit_fillrate = 20;
 
1377
                                                }
 
1378
                                                break;
 
1379
                                        case SDLK_k:
 
1380
                                                {
 
1381
                                                        int i, n, j;
 
1382
                                                        for (j = 0; j < 1; j++) {
 
1383
                                                                for (i = 0; i < 50000; i++) {
 
1384
                                                                        n = rand()%3000;
 
1385
                                                                        if (rooms[n].visited == 0) {
 
1386
                                                                                player_x = rooms[n].x * 32 + rooms[n].w * 16;
 
1387
                                                                                player_y = rooms[n].y * 32 + rooms[n].h * 16;
 
1388
                                                                                rooms[n].visited = 1;
 
1389
                                                                                explored++;
 
1390
                                                                                break;
 
1391
                                                                        }
 
1392
                                                                }
 
1393
                                                        }
 
1394
                                                }
 
1395
                                                break;
 
1396
 
 
1397
                                        case SDLK_m:
 
1398
                                                {
 
1399
                                                        int i;
 
1400
                                                        for (i = 0; i < 8; i++) {
 
1401
                                                                artifacts[i] = 1;
 
1402
                                                        }
 
1403
                                                        for (i = 8; i < 11; i++) {
 
1404
                                                                artifacts[i] = 0;
 
1405
                                                        }
 
1406
                                                        artifacts[11] = 0;
 
1407
                                                }
 
1408
                                                break;
 
1409
                                                
 
1410
                                        case SDLK_n:
 
1411
                                                {
 
1412
                                                        current_boss = 3;
 
1413
                                                        expired_ms = 1000000;
 
1414
                                                }
 
1415
                                                break;
 
1416
                                        */
 
1417
                                        default:
 
1418
                                                break;
 
1419
                                }
 
1420
                        }
 
1421
                        if (event.type == SDL_KEYUP) {
 
1422
                                switch (event.key.keysym.sym) {
 
1423
                                        case SDLK_w:
 
1424
                                        case SDLK_UP:
 
1425
                                                key_held[K_UP] = 0;
 
1426
                                                break;
 
1427
                                        case SDLK_s:
 
1428
                                        case SDLK_DOWN:
 
1429
                                                key_held[K_DN] = 0;
 
1430
                                                break;
 
1431
                                        case SDLK_a:
 
1432
                                        case SDLK_LEFT:
 
1433
                                                key_held[K_LT] = 0;
 
1434
                                                break;
 
1435
                                        case SDLK_d:
 
1436
                                        case SDLK_RIGHT:
 
1437
                                                key_held[K_RT] = 0;
 
1438
                                                break;
 
1439
                                        case SDLK_SPACE:
 
1440
                                                key_held[K_SP] = 0;
 
1441
                                                break;
 
1442
                                        default:
 
1443
                                                break;
 
1444
                                }
 
1445
                        }
 
1446
                        if (event.type == SDL_QUIT) {
 
1447
                                voluntary_exit = 1;
 
1448
                        }
 
1449
                }
 
1450
                
 
1451
        if (RECORDING) {
 
1452
                db = 0;
 
1453
                
 
1454
                db |= 0x0001 * key_held[K_UP];
 
1455
                db |= 0x0002 * key_held[K_DN];
 
1456
                db |= 0x0004 * key_held[K_LT];
 
1457
                db |= 0x0008 * key_held[K_RT];
 
1458
                db |= 0x0010 * key_held[K_SP];
 
1459
                db |= 0x0020 * enter_pressed;
 
1460
                db |= 0x0040 * map_enabled;
 
1461
                db |= 0x0080 * game_running;
 
1462
                db |= 0x0100 * game_paused;
 
1463
                db |= 0x0200 * voluntary_exit;
 
1464
                db |= 0x0400 * pressed_tab;
 
1465
                db |= 0x0800 * tele_select;
 
1466
                
 
1467
                fputc(db & 0x00FF, record_file);
 
1468
                fputc((db & 0xFF00)>>8, record_file);
 
1469
                return;
 
1470
        }
 
1471
        
 
1472
}
 
1473
 
 
1474
void DrawLevel(int off_x, int off_y, int hide_not_visited, int fog_of_war)
 
1475
{
 
1476
        static SDL_Surface *tiles = NULL;
 
1477
        static SDL_Surface *fog = NULL;
 
1478
        Uint8 *pp;
 
1479
        SDL_Rect tilerec, screenrec;
 
1480
        int x, y, i;
 
1481
        int resolve_x, resolve_y;
 
1482
        
 
1483
        DrawRect(0, 0, 640, 480, 255);
 
1484
        
 
1485
        if (tiles == NULL) {
 
1486
                tiles = IMG_Load("dat/i/tileset.png");
 
1487
                fog = IMG_Load("dat/i/tileset.png");
 
1488
                                
 
1489
                pp = fog->pixels;
 
1490
                
 
1491
                for (i = 0; i < fog->w*fog->h; i++) {
 
1492
                        *pp = *pp / 2 + 128;
 
1493
                        pp++;
 
1494
                }
 
1495
        }
 
1496
        for (y = 0; y < 16; y++) {
 
1497
                for (x = 0; x < 21; x++) {
 
1498
                        resolve_x = x + (off_x/32);
 
1499
                        resolve_y = y + (off_y/32);
 
1500
                        
 
1501
                        if ((GetVisited(resolve_x, resolve_y) == 0)&&(player_room != GetRoom(resolve_x, resolve_y))&&(hide_not_visited)) {
 
1502
                                tilerec.x = 17 * 32;
 
1503
                        } else {
 
1504
                                tilerec.x = Get(resolve_x, resolve_y) * 32;
 
1505
                        }
 
1506
                        tilerec.y = 0;
 
1507
                        tilerec.w = 32;
 
1508
                        tilerec.h = 32;
 
1509
                        
 
1510
                        screenrec.x = x*32 - ( (off_x) %32);
 
1511
                        screenrec.y = y*32 - ( (off_y) %32);
 
1512
                        
 
1513
                        if ((player_room != GetRoom(resolve_x, resolve_y))&&(fog_of_war)) {
 
1514
                                SDL_BlitSurface(fog, &tilerec, screen, &screenrec);
 
1515
                        } else {
 
1516
                                SDL_BlitSurface(tiles, &tilerec, screen, &screenrec);
 
1517
                        }
 
1518
                }
 
1519
        }
 
1520
}
 
1521
 
 
1522
void DrawPlayer(int x, int y, int pl_dir, int pl_frm)
 
1523
{
 
1524
        static SDL_Surface *playersprite = NULL;
 
1525
        SDL_Rect playerrec, screenrec;
 
1526
        
 
1527
        if (playersprite == NULL) {
 
1528
                playersprite = IMG_Load("dat/i/player.png");
 
1529
                SDL_SetColorKey(playersprite, SDL_SRCCOLORKEY | SDL_RLEACCEL, 0);
 
1530
        }
 
1531
        
 
1532
        playerrec.x = pl_frm * 16;
 
1533
        playerrec.y = pl_dir * 24;
 
1534
        playerrec.w = 16;
 
1535
        playerrec.h = 24;
 
1536
        
 
1537
        screenrec.x = x;
 
1538
        screenrec.y = y;
 
1539
        
 
1540
        SDL_BlitSurface(playersprite, &playerrec, screen, &screenrec);
 
1541
}
 
1542
 
 
1543
void SetGreyscalePalette()
 
1544
{
 
1545
        SDL_Color grey[256];
 
1546
        SDL_Color pal[256];
 
1547
        int i;
 
1548
        
 
1549
        float ip;
 
1550
        
 
1551
        for (i = 0; i < 256; i++) {
 
1552
                grey[i].r = grey[i].g = grey[i].b = i;
 
1553
        }
 
1554
        
 
1555
        for (i = 0; i < 256; i++) {
 
1556
                ip = (float)i / 255.0;
 
1557
                pal[i].r = (cos(ip * M_PI / 2.0 + M_PI) + 1.0) * 255;
 
1558
                pal[i].g = (sin(ip * M_PI / 2.0) * 255 + i) / 2;
 
1559
                pal[i].b = sin(ip * M_PI / 2.0) * 255;
 
1560
        }
 
1561
        
 
1562
        SDL_SetPalette(screen, SDL_LOGPAL, grey, 0, 256);
 
1563
        SDL_SetPalette(screen, SDL_PHYSPAL, pal, 0, 256);
 
1564
}
 
1565
 
 
1566
void SetTonedPalette(float dct)
 
1567
{
 
1568
        SDL_Color pal[256];
 
1569
        float pct = 1.0 - dct;
 
1570
        float rp_dct, rp_pct;
 
1571
        float ip;
 
1572
        int ec;
 
1573
        int i;
 
1574
        static int tk = 0;
 
1575
        
 
1576
        ec = rooms[player_room].enemies;
 
1577
        
 
1578
        if (ec < 50) {
 
1579
                rp_dct = (float)ec / 50.0;
 
1580
        } else {
 
1581
                rp_dct = 1.0;
 
1582
        }
 
1583
        rp_pct = 1.0 - rp_dct;
 
1584
        
 
1585
        if ( (player_room == 0) && (current_boss == 3) && (boss_fight_mode >= 3) ) {
 
1586
                if (boss_fight_mode == 23) {
 
1587
                        for (i = 0; i < 256; i++) {
 
1588
                                pal[i].r = i;
 
1589
                                pal[i].g = i;
 
1590
                                pal[i].b = i;
 
1591
                        }
 
1592
                } else {
 
1593
                        tk++;
 
1594
                        pct = sin((float)tk / 20.0 * M_PI) * (0.5 - (float)(boss_fight_mode-3)*0.025) + (0.5 - (float)(boss_fight_mode-3)*0.025);
 
1595
                        
 
1596
                        if (magic_circuit < 0.1) pct = 1.0;
 
1597
 
 
1598
                        for (i = 0; i < 256; i++) {
 
1599
                                ip = (float)i / 255.0;
 
1600
                                pal[i].r = 255 - (255 - (cos(ip * M_PI / 2.0 + M_PI) + 1.0) * 255)*pct;
 
1601
                                pal[i].g = 255 - (255 - i)*pct;
 
1602
                                pal[i].b = 255 - (255 - sin(ip * M_PI / 2.0) * 255) * pct;
 
1603
                        }
 
1604
                        
 
1605
                        
 
1606
                        pal[1].r = 0;
 
1607
                        pal[1].g = 0;
 
1608
                        pal[1].b = 0;
 
1609
                }
 
1610
        } else {
 
1611
                if (artifacts[11]) {
 
1612
                        if (player_room == 0) {
 
1613
                                tk++;
 
1614
                                pct = sin((float)tk / 33.0 * M_PI) * 0.5 + 0.5;
 
1615
                                for (i = 0; i < 256; i++) {
 
1616
                                        pal[i].r = i;
 
1617
                                        pal[i].g = (i / 3)*pct;
 
1618
                                        pal[i].b = (i * 2 / 3)*pct;
 
1619
                                }
 
1620
                        } else {
 
1621
                                for (i = 0; i < 256; i++) {
 
1622
                                        ip = (float)i / 255.0;
 
1623
                                        pal[i].r = i;
 
1624
                                        pal[i].g = i * dct;
 
1625
                                        pal[i].b = (cos(ip * M_PI / 2.0 + M_PI) + 1.0) * 255 * dct;
 
1626
                                }
 
1627
                        }
 
1628
                        
 
1629
                        if ( (current_boss == 3) && (player_shield == 30) && (player_room == 0)) {
 
1630
                                if (boss_lives <= 1) {
 
1631
                                        tk++;
 
1632
                                        for (i = 0; i < 256; i++) {
 
1633
                                                pct = sin((float) (tk + i) / 24.0 * M_PI) * 0.5 + 0.5;
 
1634
                                                
 
1635
                                                pal[i].r = (i * 0.5 + 128)*pct;
 
1636
                                                pal[i].g = i * 0.5 + 128;
 
1637
                                                pal[i].b = (i * 0.5 + 128)*pct;
 
1638
                                        }
 
1639
                                }
 
1640
                        }
 
1641
                } else {
 
1642
                        for (i = 0; i < 256; i++) {
 
1643
                                ip = (float)i / 255.0;
 
1644
                                pal[i].r = (((cos(ip * M_PI / 2.0 + M_PI) + 1.0) * 255)*pct + i*dct)*rp_pct + (sin(ip * M_PI / 2.0) * 207 + 48)*rp_dct;
 
1645
                                pal[i].g = (i)*rp_pct + ((cos(ip * M_PI / 2.0 + M_PI) + 1.0) * 255)*rp_dct;
 
1646
                                pal[i].b = ((sin(ip * M_PI / 2.0) * 255 * pct)+((cos(ip * M_PI / 2.0 + M_PI) + 1.0) * 255 * dct))*rp_pct + ((cos(ip * M_PI / 2.0 + M_PI) + 1.0) * 255)*rp_dct;
 
1647
                        }
 
1648
                }
 
1649
        }
 
1650
        
 
1651
        SDL_SetPalette(screen, SDL_PHYSPAL, pal, 0, 256);
 
1652
}
 
1653
 
 
1654
void SetTitlePalette(int curve_start, int curve_end)
 
1655
{
 
1656
        SDL_Color pal[256];
 
1657
        int ec;
 
1658
        int i;
 
1659
        
 
1660
        for (i = 0; i < 256; i++) {
 
1661
                ec = (i - curve_start) * 255 / (curve_end-curve_start);
 
1662
                if (ec < 0) ec = 0;
 
1663
                if (ec > 255) ec = 255;
 
1664
                
 
1665
                pal[i].r = ec;
 
1666
                pal[i].g = ec;
 
1667
                pal[i].b = ec;
 
1668
        }
 
1669
        
 
1670
        SDL_SetPalette(screen, SDL_PHYSPAL, pal, 0, 256);
 
1671
}
 
1672
 
 
1673
void SetTitlePalette2(int t)
 
1674
{
 
1675
        SDL_Color pal[256];
 
1676
        int i;
 
1677
        
 
1678
        float ip;
 
1679
        float bright;
 
1680
        float b_coeff;
 
1681
        
 
1682
        bright = 1 - ((float)t / 30.0);
 
1683
        if (bright < 0.0) bright = 0.0;
 
1684
        b_coeff = 1 - bright;
 
1685
        
 
1686
        for (i = 0; i < 256; i++) {
 
1687
                ip = (float)i / 255.0;
 
1688
                pal[i].r = (cos(ip * M_PI / 2.0 + M_PI) + 1.0) * 255 * b_coeff + 255*bright;
 
1689
                pal[i].g = (sin(ip * M_PI / 2.0) * 255 + i) / 2 * b_coeff + 255*bright;
 
1690
                pal[i].b = sin(ip * M_PI / 2.0) * 255 * b_coeff + 255*bright;
 
1691
        }
 
1692
        
 
1693
        SDL_SetPalette(screen, SDL_PHYSPAL, pal, 0, 256);
 
1694
}
 
1695
 
 
1696
int IsSolid(unsigned char tile)
 
1697
{
 
1698
        return TileData[tile].Is_Solid;
 
1699
}
 
1700
 
 
1701
void ActivateBossDoor(int x, int y)
 
1702
{
 
1703
        static int bd_timer = 0;
 
1704
        int bx = x, by = y;
 
1705
        
 
1706
        // find boss room
 
1707
        if (rooms[GetRoom(x+1, y)].room_type == 2) {
 
1708
                bx += 1;
 
1709
        } else
 
1710
                if (rooms[GetRoom(x-1, y)].room_type == 2) {
 
1711
                bx -= 1;
 
1712
        } else
 
1713
                if (rooms[GetRoom(x, y+1)].room_type == 2) {
 
1714
                by += 1;
 
1715
        } else
 
1716
                if (rooms[GetRoom(x, y-1)].room_type == 2) {
 
1717
                by -= 1;
 
1718
        } else
 
1719
                return;
 
1720
        
 
1721
        if (artifacts[8 + rooms[GetRoom(bx, by)].room_param]) {
 
1722
                opening_door_x = x;
 
1723
                opening_door_y = y;
 
1724
                opening_door_i = 1;
 
1725
                opening_door_n = rooms[GetRoom(bx, by)].room_param;
 
1726
                if ((SDL_GetTicks() - bd_timer) > 100) {
 
1727
                        SND_Pos("dat/a/crystal2.wav", 100, 0);
 
1728
                        bd_timer = SDL_GetTicks();
 
1729
                }
 
1730
        }
 
1731
}
 
1732
 
 
1733
int TouchTile(int ix, int iy)
 
1734
{
 
1735
                int i;
 
1736
                int off_x, off_y;
 
1737
                int ret = 1;
 
1738
                unsigned char tile;
 
1739
                
 
1740
                for (i = 0; i < 4; i++) {
 
1741
                        off_x = 15*(i%2);
 
1742
                        off_y = 23*(i/2);
 
1743
 
 
1744
                        tile = Get((ix+off_x)/32, (iy+off_y)/32);
 
1745
                        switch (tile) {
 
1746
                                case 38:
 
1747
                                case 39:
 
1748
                                case 40:
 
1749
                                case 41:
 
1750
                                        ActivateBossDoor((ix+off_x)/32, (iy+off_y)/32);
 
1751
                                        ret = 0;
 
1752
                                        break;
 
1753
                                case 13:
 
1754
                                        player_x = (ix + off_x) / 32 * 32 + 8;
 
1755
                                        player_y = (iy/32 + 2)*32 + 32;
 
1756
                                        return 1;
 
1757
                                        break;
 
1758
                                case 14:
 
1759
                                        player_x = (ix + off_x) / 32 * 32 + 8;
 
1760
                                        player_y = (iy/32 - 2)*32 + 8;
 
1761
                                        return 1;
 
1762
                                        break;
 
1763
                                case 15:
 
1764
                                        player_x = (ix/32 + 2)*32 + 32;
 
1765
                                        player_y = (iy + off_y) / 32 * 32 + 4;
 
1766
                                        return 1;
 
1767
                                        break;
 
1768
                                case 16:
 
1769
                                        player_x = (ix/32 - 2)*32 + 16;
 
1770
                                        player_y = (iy + off_y) / 32 * 32 + 4;
 
1771
                                        return 1;
 
1772
                                        break;
 
1773
                                default:
 
1774
                                        if (TileData[tile].Is_Solid) ret = 0;
 
1775
                                        //ret = 0;
 
1776
                                        break;
 
1777
                        }
 
1778
                }
 
1779
                if (ret == 1) {
 
1780
                        player_x = ix;
 
1781
                        player_y = iy;
 
1782
                }
 
1783
                return ret;
 
1784
}
 
1785
 
 
1786
void text_init()
 
1787
{
 
1788
        FILE *font_data_file;
 
1789
        int chr, x, y;
 
1790
        font_data_file = fopen("dat/d/font.dat", "rb");
 
1791
        
 
1792
        for (chr = 0; chr < 128; chr++) {
 
1793
                for (y = 0; y < 8; y++) {
 
1794
                        for (x = 0; x < 8; x++) {
 
1795
                                font_data[chr][x][y] = fgetc(font_data_file);
 
1796
                        }
 
1797
                }
 
1798
        }
 
1799
 
 
1800
        fclose(font_data_file);
 
1801
}
 
1802
 
 
1803
void draw_char(int cur_x, int cur_y, int c, Uint8 tcol)
 
1804
{
 
1805
        int px, py;
 
1806
        Uint8 *pix;
 
1807
        
 
1808
        for (py = 0; py < 8; py++) {
 
1809
                pix = (Uint8 *)screen->pixels;
 
1810
                pix += (py+cur_y)*screen->w;
 
1811
                pix += cur_x;
 
1812
                
 
1813
                if ((cur_x >= 0)&&(py+cur_y >= 0)&&(cur_x < screen->w-8)&&(py+cur_y < screen->h)) {
 
1814
                        for (px = 0; px < 8; px++) {
 
1815
                                if (font_data[c][px][py] == 255) {
 
1816
                                        *pix = tcol;
 
1817
                                }
 
1818
                                if ((font_data[c][px][py] < 255)&&(font_data[c][px][py] > 0)) {
 
1819
                                        *pix = ((int)tcol * font_data[c][px][py] / 256) + ((int)*pix * (256-font_data[c][px][py]) / 256);
 
1820
                                }
 
1821
                                pix++;
 
1822
                        }
 
1823
                }
 
1824
        }
 
1825
}
 
1826
 
 
1827
void draw_text(int x, int y, char *str, Uint8 tcol)
 
1828
{
 
1829
        int c, cur_x, cur_y;
 
1830
        
 
1831
        cur_x = x;
 
1832
        cur_y = y;
 
1833
 
 
1834
        while (*str != 0) {
 
1835
                c = *(str++);
 
1836
                if (c == '\n') {
 
1837
                        cur_x = x;
 
1838
                        cur_y+=10;
 
1839
                } else {
 
1840
                        draw_char(cur_x, cur_y, c, tcol);
 
1841
                        cur_x+=8;
 
1842
                }
 
1843
        }
 
1844
}
 
1845
 
 
1846
void draw_text_ex(int x, int y, char *str, Uint8 tcol, SDL_Surface *srf)
 
1847
{
 
1848
        Uint8 *pix;
 
1849
        int c, cur_x, cur_y, px, py;
 
1850
        
 
1851
        cur_x = x;
 
1852
        cur_y = y;
 
1853
 
 
1854
        while (*str != 0) {
 
1855
                c = *(str++);
 
1856
                if (c == '\n') {
 
1857
                        cur_x = x;
 
1858
                        cur_y+=8;
 
1859
                } else {
 
1860
                        for (py = 0; py < 8; py++) {
 
1861
                                pix = (Uint8 *)srf->pixels;
 
1862
                                pix += (py+cur_y)*srf->w;
 
1863
                                pix += cur_x;
 
1864
                                for (px = 0; px < 8; px++) {
 
1865
                                        if (font_data[c][px][py]) {
 
1866
                                                *pix = tcol;
 
1867
                                        }
 
1868
                                        pix++;
 
1869
                                }
 
1870
                        }
 
1871
                        cur_x+=8;
 
1872
                }
 
1873
        }
 
1874
}
 
1875
 
 
1876
void LockDoors(int r)
 
1877
{
 
1878
        //printf("Locking room %d...", r);
 
1879
        int x, y;
 
1880
        int rx, ry;
 
1881
        int rt;
 
1882
        int rcount = 0;
 
1883
        
 
1884
        for (y = 0; y < rooms[r].h; y++) {
 
1885
                for (x = 0; x < rooms[r].w; x++) {
 
1886
                        rx = x + rooms[r].x;
 
1887
                        ry = y + rooms[r].y;
 
1888
                        rt = Get(rx, ry);
 
1889
                        
 
1890
                        if ((rt >= 13) && (rt <= 16)) {
 
1891
                                rcount++;
 
1892
                                Put(rx, ry, rt - 13 + 21, r);
 
1893
                        }
 
1894
                }
 
1895
        }
 
1896
        //printf("locked %d doors\n", rcount);
 
1897
}
 
1898
 
 
1899
void ActivateRoom(int room)
 
1900
{
 
1901
        //printf("Activating room %d (type %d)\n", room, rooms[room].room_type);
 
1902
        if (rooms[room].checkpoint) {
 
1903
                checkpoints_found++;
 
1904
        }
 
1905
        if (rooms[room].room_type == 3) {
 
1906
                // lock the doors!
 
1907
                LockDoors(room);
 
1908
        }
 
1909
        ActivateEnemies(room);
 
1910
}
 
1911
 
 
1912
void DrawRect(int x, int y, int w, int h, unsigned char c)
 
1913
{
 
1914
        SDL_Rect r;
 
1915
 
 
1916
        r.x = x;
 
1917
        r.y = y;
 
1918
        r.w = w;
 
1919
        r.h = h;
 
1920
 
 
1921
        SDL_FillRect(screen, &r, c);
 
1922
}
 
1923
 
 
1924
void DrawCircuit()
 
1925
{
 
1926
        int vd = 520;
 
1927
        char buf[20];
 
1928
 
 
1929
        if (magic_circuit != 0) {
 
1930
                DrawRect(110, 469, 8+abs(magic_circuit) * vd / circuit_size, 9, (magic_circuit > 0) ? 159 : 72);
 
1931
                DrawRect(111, 470, 6+abs(magic_circuit) * vd / circuit_size, 7, (magic_circuit > 0) ? 183 : 80);
 
1932
                DrawRect(112, 471, 4+abs(magic_circuit) * vd / circuit_size, 5, (magic_circuit > 0) ? 207 : 96);
 
1933
                DrawRect(113, 472, 2+abs(magic_circuit) * vd / circuit_size, 3, (magic_circuit > 0) ? 231 : 112);
 
1934
                DrawRect(114, 473, abs(magic_circuit) * vd / circuit_size, 1, (magic_circuit > 0) ? 255 : 128);
 
1935
        }
 
1936
        sprintf(buf, "%.1f", fabs((float)magic_circuit / 100.0));
 
1937
        draw_text(115, 470, buf, 0);
 
1938
        draw_text(3, 469, "Psi Circuit", 200);
 
1939
}
 
1940
 
 
1941
void ReleaseCircuit()
 
1942
{
 
1943
        circuit_release = 1;
 
1944
        release_range = circuit_range;
 
1945
        release_x = player_x;
 
1946
        release_y = player_y;
 
1947
        release_str = magic_circuit;
 
1948
        if (circuit_fillrate==30) {
 
1949
                release_str *= 1.25;
 
1950
        }
 
1951
        
 
1952
        SND_CircuitRelease(release_str);
 
1953
        magic_circuit *= -1;
 
1954
}
 
1955
 
 
1956
void DrawCircle(int x, int y, int r, unsigned char c)
 
1957
{
 
1958
        int circ_y;
 
1959
 
 
1960
        int len_x, outer_len_x, inner_len_x;
 
1961
 
 
1962
        int inner_r = r - 10;
 
1963
        if (inner_r < 1) inner_r = 1;
 
1964
 
 
1965
        if (r < 1) return;
 
1966
        // a^2 + b^2 = c^2
 
1967
        for (circ_y = 0; circ_y < r; circ_y++) {
 
1968
                if (circ_y < (r-10)) {
 
1969
                        outer_len_x = sqrt(r*r - circ_y*circ_y);
 
1970
                        inner_len_x = sqrt((r-10)*(r-10) - circ_y*circ_y);
 
1971
                        DrawRect(x - outer_len_x, y - circ_y, (outer_len_x - inner_len_x), 1, c);
 
1972
                        DrawRect(x + inner_len_x, y - circ_y, (outer_len_x - inner_len_x), 1, c);
 
1973
                        DrawRect(x - outer_len_x, y + circ_y, (outer_len_x - inner_len_x), 1, c);
 
1974
                        DrawRect(x + inner_len_x, y + circ_y, (outer_len_x - inner_len_x), 1, c);
 
1975
                } else {
 
1976
                        len_x = sqrt(r*r - circ_y*circ_y);
 
1977
                
 
1978
                        DrawRect(x - len_x, y - circ_y, len_x*2, 1, c);
 
1979
                        DrawRect(x - len_x, y + circ_y, len_x*2, 1, c);
 
1980
                }
 
1981
        }
 
1982
}
 
1983
 
 
1984
void DrawCircleEx(int x, int y, int r, int r2, unsigned char c)
 
1985
{
 
1986
        int circ_y;
 
1987
 
 
1988
        int len_x, outer_len_x, inner_len_x;
 
1989
 
 
1990
        int inner_r = r2;
 
1991
        int diffi = r-r2;
 
1992
        if (inner_r < 1) inner_r = 1;
 
1993
 
 
1994
 
 
1995
 
 
1996
        if (r < 1) return;
 
1997
        // a^2 + b^2 = c^2
 
1998
        for (circ_y = 0; circ_y < r; circ_y++) {
 
1999
                if (circ_y < (r-diffi)) {
 
2000
                        outer_len_x = sqrt(r*r - circ_y*circ_y);
 
2001
                        inner_len_x = sqrt((r-diffi)*(r-diffi) - circ_y*circ_y);
 
2002
                        DrawRect(x - outer_len_x, y - circ_y, (outer_len_x - inner_len_x), 1, c);
 
2003
                        DrawRect(x + inner_len_x, y - circ_y, (outer_len_x - inner_len_x), 1, c);
 
2004
                        DrawRect(x - outer_len_x, y + circ_y, (outer_len_x - inner_len_x), 1, c);
 
2005
                        DrawRect(x + inner_len_x, y + circ_y, (outer_len_x - inner_len_x), 1, c);
 
2006
                } else {
 
2007
                        len_x = sqrt(r*r - circ_y*circ_y);
 
2008
                
 
2009
                        DrawRect(x - len_x, y - circ_y, len_x*2, 1, c);
 
2010
                        DrawRect(x - len_x, y + circ_y, len_x*2, 1, c);
 
2011
                }
 
2012
        }
 
2013
}
 
2014
 
 
2015
void DrawShield()
 
2016
{
 
2017
        static int t=0;
 
2018
        int s_size;
 
2019
        int belts = 0;
 
2020
        int i, bpos;
 
2021
        t++;
 
2022
        
 
2023
        if (player_shield == 0) return;
 
2024
        if (shield_hp == 0) return;
 
2025
        
 
2026
        s_size = shield_hp;
 
2027
        if (s_size > 15) {
 
2028
                belts = s_size - 15;
 
2029
                s_size = 15;
 
2030
        }
 
2031
        DrawCircleEx(320, 240, 28+s_size, 28-s_size, 128 + (shield_hp*127/player_shield) - (50*(shield_hp<player_shield) + shield_recover) - 45 + ((t%4)*15));
 
2032
        
 
2033
        for (i = 0; i < belts; i++) {
 
2034
                bpos = 13 + (30 * (i+1) / (belts+1));
 
2035
                DrawCircleEx(320, 240, bpos + 1, bpos - 1, ((i+t)%6*12));
 
2036
        }
 
2037
}
 
2038
 
 
2039
void ST_Teleport()
 
2040
{
 
2041
}
 
2042
 
 
2043
int UpgradePrice(int t)
 
2044
{
 
2045
        int price = 0;
 
2046
        switch (t) {
 
2047
                case 0:
 
2048
                        price = (100 - training*50) * player_shield + (5<<player_shield) * (5 - training*2);
 
2049
                        break;
 
2050
                case 1:
 
2051
                        price = (80 - training*40) * circuit_fillrate + (5<<circuit_fillrate) * (4 - training*2);
 
2052
                        break;
 
2053
                case 2:
 
2054
                        price = (80 - training*40) * circuit_recoverrate + (5<<circuit_recoverrate) * (4 - training*2);
 
2055
                        break;
 
2056
                default:
 
2057
                        price = 123;
 
2058
                        break;
 
2059
        }
 
2060
 
 
2061
        return price;
 
2062
}
 
2063
 
 
2064
void RoomTreasure(int room, int typ)
 
2065
{
 
2066
        int treasure;
 
2067
        int given_treasure = 0;
 
2068
        
 
2069
        if (typ == 0) {
 
2070
                // Treasure
 
2071
                treasure = rooms[room].room_param;
 
2072
                artifacts[treasure] = 1;
 
2073
                specialmessage = treasure + 1;
 
2074
                specialmessagetimer = 30;
 
2075
                SND_Pos("dat/a/crystal2.wav", 128, 0);
 
2076
        }
 
2077
        if (typ == 1) {
 
2078
                // Reward
 
2079
                while (!given_treasure) {
 
2080
                        treasure = rand() % 4;
 
2081
                        
 
2082
                        switch (treasure) {
 
2083
                                case 0:
 
2084
                                        specialmessage = 20;
 
2085
                                        player_gems += rand()%((1 << (rooms[room].s_dist / 7)) * 1500);
 
2086
                                        given_treasure = 1;
 
2087
                                        SND_Pos("dat/a/tone.wav", 128, 0);
 
2088
                                        break;
 
2089
                                case 1:
 
2090
                                        if (player_shield < 25) {
 
2091
                                                specialmessage = 10;
 
2092
                                                player_shield += 1;
 
2093
                                                given_treasure = 1;
 
2094
                                                SND_Pos("dat/a/tone.wav", 128, 0);
 
2095
                                        }
 
2096
                                        break;
 
2097
                                case 2:
 
2098
                                        if (circuit_fillrate < 25) {
 
2099
                                                specialmessage = 11;
 
2100
                                                circuit_fillrate += 1;
 
2101
                                                given_treasure = 1;
 
2102
                                                SND_Pos("dat/a/tone.wav", 128, 0);
 
2103
                                        }
 
2104
                                        break;
 
2105
                                case 3:
 
2106
                                        if (circuit_recoverrate < 25) {
 
2107
                                                specialmessage = 12;
 
2108
                                                circuit_recoverrate += 1;
 
2109
                                                given_treasure = 1;
 
2110
                                                SND_Pos("dat/a/tone.wav", 128, 0);
 
2111
                                        }
 
2112
                                        break;
 
2113
                                default:
 
2114
                                        break;
 
2115
                        }
 
2116
                }
 
2117
                specialmessagetimer = 30;
 
2118
        }
 
2119
}
 
2120
 
 
2121
int GetNearestCheckpoint(int nx, int ny)
 
2122
{
 
2123
        int i;
 
2124
        int nearest_checkpoint = -1;
 
2125
        int nearest_dist = 10000000;
 
2126
        int cp_x, cp_y, cp_dist;
 
2127
        int room_chk[3000] = {0};
 
2128
        int x, y, rx, ry;
 
2129
 
 
2130
        i = GetRoom(nx/32, ny/32);
 
2131
        if (i != -1) {
 
2132
                room_chk[i] = 1;
 
2133
                if ((rooms[i].checkpoint != 0)&&(rooms[i].visited!=0)) {
 
2134
                        nearest_checkpoint = i;
 
2135
                }
 
2136
        }
 
2137
        if (nearest_checkpoint == -1) {
 
2138
                                
 
2139
                for (y = 0; y < 54;) {
 
2140
                        for (x = 0; x < 54;) {
 
2141
                                rx = nx/32 - 27 + x;
 
2142
                                ry = ny/32 - 27 + y;
 
2143
                                
 
2144
                                i = GetRoom(rx, ry);
 
2145
                                if (i != -1) {
 
2146
                                        if (room_chk[i] == 0) {
 
2147
                                                room_chk[i] = 1;
 
2148
                                                if ((rooms[i].checkpoint != 0)&&(rooms[i].visited!=0)) {
 
2149
                                                        cp_x = rooms[i].x * 32 + rooms[i].w * 16;
 
2150
                                                        cp_y = rooms[i].y * 32 + rooms[i].h * 16;
 
2151
                                                        cp_dist = dist(cp_x, cp_y, nx, ny);
 
2152
                                                        if (cp_dist < nearest_dist) {
 
2153
                                                                nearest_dist = cp_dist;
 
2154
                                                                nearest_checkpoint = i;
 
2155
                                                        }
 
2156
                                                }
 
2157
                                        }
 
2158
                                }
 
2159
                                x += 2;
 
2160
                        }
 
2161
                        y += 2;
 
2162
                }
 
2163
                
 
2164
        }
 
2165
        
 
2166
        return nearest_checkpoint;
 
2167
}
 
2168
 
 
2169
void TeleportPlayerToRoom(int c_room)
 
2170
{
 
2171
        if (c_room == 0) {
 
2172
                player_x = 8232;
 
2173
                player_y = 8108;
 
2174
        } else {
 
2175
                player_x = rooms[c_room].x * 32 + (rooms[c_room].w / 2 * 32) + 8;
 
2176
                player_y = rooms[c_room].y * 32 + (rooms[c_room].h / 2 * 32) + 4;
 
2177
        }
 
2178
        c_scroll_x = player_x;
 
2179
        c_scroll_y = player_y;
 
2180
        scroll_home = 1;
 
2181
}
 
2182
 
 
2183
 
 
2184
void TeleportPlayerToNextRoom()
 
2185
{
 
2186
        int c_room;
 
2187
        c_room = (player_room + 1) % 3000;
 
2188
        while (! ((rooms[c_room].checkpoint!=0)&&(rooms[c_room].visited!=0))) {
 
2189
                c_room = (c_room + 1) % 3000;
 
2190
        }
 
2191
        
 
2192
        if (c_room == 0) {
 
2193
                player_x = 8232;
 
2194
                player_y = 8108;
 
2195
        } else {
 
2196
                player_x = rooms[c_room].x * 32 + (rooms[c_room].w / 2 * 32) + 8;
 
2197
                player_y = rooms[c_room].y * 32 + (rooms[c_room].h / 2 * 32) + 4;
 
2198
        }
 
2199
        c_scroll_x = player_x;
 
2200
        c_scroll_y = player_y;
 
2201
        scroll_home = 1;
 
2202
}
 
2203
 
 
2204
void ActivateTile(unsigned char tile, int x, int y)
 
2205
{
 
2206
        int c_room;
 
2207
        
 
2208
        enter_pressed = 0;
 
2209
        switch (tile) {
 
2210
                case 25:
 
2211
                        if (artifacts[11]) break;
 
2212
 
 
2213
                        c_room = GetNearestCheckpoint(c_scroll_x, c_scroll_y);
 
2214
                        if (tele_select) {
 
2215
                                if (c_room != -1) {
 
2216
                                        if (c_room == player_room) {
 
2217
                                                TeleportPlayerToNextRoom();
 
2218
                                        } else {
 
2219
                                                TeleportPlayerToRoom(c_room);
 
2220
                                        }
 
2221
                                }
 
2222
                        } else {
 
2223
                                map_enabled = 1;
 
2224
                                game_paused = 1;
 
2225
                                tele_select = 1;
 
2226
                                
 
2227
                                c_scroll_x = player_x;
 
2228
                                c_scroll_y = player_y;
 
2229
                        }
 
2230
                        
 
2231
                        break;
 
2232
                case 26:
 
2233
                        RoomTreasure(GetRoom(x, y), (x+y)%2);
 
2234
                        Put(x, y, 27, GetRoom(x, y));
 
2235
                        break;
 
2236
                case 28:
 
2237
                        if (player_shield >= 24) return;
 
2238
                        if (player_gems >= UpgradePrice(0)) {
 
2239
                                player_gems -= UpgradePrice(0);
 
2240
                                player_shield += 1;
 
2241
                                SND_Pos("dat/a/crystal.wav", 128, 0);
 
2242
                        }
 
2243
                        break;
 
2244
                case 29:
 
2245
                        if (circuit_fillrate >= 24) return;
 
2246
                        if (player_gems >= UpgradePrice(1)) {
 
2247
                                player_gems -= UpgradePrice(1);
 
2248
                                circuit_fillrate += 1;
 
2249
                                SND_Pos("dat/a/crystal.wav", 128, 0);
 
2250
                        }
 
2251
                        break;
 
2252
                case 30:
 
2253
                        if (circuit_recoverrate >= 24) return;
 
2254
                        if (player_gems >= UpgradePrice(2)) {
 
2255
                                player_gems -= UpgradePrice(2);
 
2256
                                circuit_recoverrate += 1;
 
2257
                                SND_Pos("dat/a/crystal.wav", 128, 0);
 
2258
                        }
 
2259
                        break;
 
2260
                case 31:
 
2261
                        DoSaveGame();
 
2262
                        break;
 
2263
                case 32:
 
2264
                        CrystalSummon();
 
2265
                        SND_Pos("dat/a/crystal.wav", 80, 0);
 
2266
                        break;
 
2267
                default:
 
2268
                        break;
 
2269
        }
 
2270
}
 
2271
 
 
2272
void CompassPoint()
 
2273
{
 
2274
        int nearest = 1000000;
 
2275
        int n_room = -1;
 
2276
        int i;
 
2277
        int loc_x, loc_y;
 
2278
        int cdist;
 
2279
        int rplx, rply;
 
2280
        int bosses_defeated = current_boss;
 
2281
        float pdir_1 = 0;
 
2282
        float pdir_2 = 0;
 
2283
        int pdir_1t = 0, pdir_2t = 0;
 
2284
        
 
2285
        rplx = player_x + PLAYERW/2;
 
2286
        rply = player_y + PLAYERH/2;
 
2287
        // Find the nearest SIGNIFICANT LOCATION for the player
 
2288
        
 
2289
        // Look at the three artifacts
 
2290
        // Unless the player is going for the place of power
 
2291
        
 
2292
        if (current_boss < 3) {
 
2293
                for (i = 0; i < 3; i++) {
 
2294
                        // Has the player got this artifact already?
 
2295
                        if (artifacts[8+i] == 0) { // no
 
2296
                                // Has the player already destroyed the boss?
 
2297
                                if (rooms[i * 1000 + 999].room_type == 2) { // no
 
2298
                                        // Can the player get the artifact?
 
2299
                                        if (CanGetArtifact()) {
 
2300
                                                // Point player to this artifact room, if it is the nearest
 
2301
                                                loc_x = rooms[i * 1000 + 499].x * 32 + rooms[i * 1000 + 499].w * 16;
 
2302
                                                loc_y = rooms[i * 1000 + 499].y * 32 + rooms[i * 1000 + 499].h * 16;
 
2303
                                                cdist = dist(rplx, rply, loc_x, loc_y);
 
2304
                                                if (cdist < nearest) {
 
2305
                                                        nearest = cdist;
 
2306
                                                        n_room = i * 1000 + 499;
 
2307
                                                }
 
2308
                                        }
 
2309
                                }
 
2310
                        } else { // has artifact
 
2311
                                // Has the player already destroyed the boss?
 
2312
                                if (rooms[i * 1000 + 999].room_type == 2) { // no
 
2313
                                        // Point player to the boss room, if it is the nearest
 
2314
                                        loc_x = rooms[i * 1000 + 999].x * 32 + rooms[i * 1000 + 999].w * 16;
 
2315
                                        loc_y = rooms[i * 1000 + 999].y * 32 + rooms[i * 1000 + 999].h * 16;
 
2316
                                        cdist = dist(rplx, rply, loc_x, loc_y);
 
2317
                                        if (cdist < nearest) {
 
2318
                                                nearest = cdist;
 
2319
                                                n_room = i * 1000 + 999;
 
2320
                                        }
 
2321
                                } else { // yes
 
2322
                                        bosses_defeated++;
 
2323
                                }
 
2324
                        }
 
2325
                }
 
2326
        }
 
2327
        // If, on the other hand, the player has destroyed all three bosses, point them towards the
 
2328
        // PLACE OF POWER
 
2329
        if (bosses_defeated == 3) {
 
2330
                // If the player already has the seal, point them to home
 
2331
                if (artifacts[11] == 1) {
 
2332
                        loc_x = rooms[0].x * 32 + rooms[0].w * 16;
 
2333
                        loc_y = rooms[0].y * 32 + rooms[0].h * 16;
 
2334
                        cdist = dist(rplx, rply, loc_x, loc_y);
 
2335
                        if (cdist < nearest) {
 
2336
                                nearest = cdist;
 
2337
                                n_room = 0;
 
2338
                        }
 
2339
                } else {
 
2340
                        // Can the player touch the seal?
 
2341
                        if (CanGetArtifact()) {
 
2342
                                loc_x = rooms[place_of_power].x * 32 + rooms[place_of_power].w * 16;
 
2343
                                loc_y = rooms[place_of_power].y * 32 + rooms[place_of_power].h * 16;
 
2344
                                cdist = dist(rplx, rply, loc_x, loc_y);
 
2345
                                if (cdist < nearest) {
 
2346
                                        nearest = cdist;
 
2347
                                        n_room = place_of_power;
 
2348
                                }
 
2349
                        }
 
2350
                }
 
2351
        }
 
2352
        
 
2353
        // Did we find a room? If so, point to it
 
2354
        
 
2355
        if (n_room != -1) {
 
2356
                loc_x = rooms[n_room].x * 32 + rooms[n_room].w * 16;
 
2357
                loc_y = rooms[n_room].y * 32 + rooms[n_room].h * 16;
 
2358
        
 
2359
                pdir_1 = PlayerDir(loc_x, loc_y) + M_PI;
 
2360
                pdir_1t = 1;
 
2361
                
 
2362
                n_room = -1;
 
2363
        }
 
2364
        
 
2365
        nearest = 1000000;
 
2366
        // Find the nearest uncleared artifact room
 
2367
        for (i = 0; i < 3000; i++) {
 
2368
                if (rooms[i].room_type == 3) {
 
2369
                        loc_x = rooms[i].x * 32 + rooms[i].w * 16;
 
2370
                        loc_y = rooms[i].y * 32 + rooms[i].h * 16;
 
2371
                        cdist = dist(rplx, rply, loc_x, loc_y);
 
2372
                        if (cdist < nearest) {
 
2373
                                nearest = cdist;
 
2374
                                n_room = i;
 
2375
                        }
 
2376
                }
 
2377
        }
 
2378
        
 
2379
        if (n_room != -1) {
 
2380
                loc_x = rooms[n_room].x * 32 + rooms[n_room].w * 16;
 
2381
                loc_y = rooms[n_room].y * 32 + rooms[n_room].h * 16;
 
2382
        
 
2383
                pdir_2 = PlayerDir(loc_x, loc_y) + M_PI;
 
2384
                pdir_2t = 1;
 
2385
                
 
2386
                n_room = -1;
 
2387
        }
 
2388
        
 
2389
        // Did we find at least one thing to point to? If not, abort
 
2390
        if (!(pdir_1t || pdir_2t))
 
2391
                return;
 
2392
        
 
2393
        DrawCircleEx(rplx - scroll_x, rply - scroll_y, 200, 190, 255);
 
2394
        if (pdir_1t)
 
2395
                DrawCircleEx(rplx - scroll_x + cos(pdir_1) * 170, rply - scroll_y + sin(pdir_1) * 170, 30, 20, 255);
 
2396
        if (pdir_2t)
 
2397
                DrawCircleEx(rplx - scroll_x + cos(pdir_2) * 170, rply - scroll_y + sin(pdir_2) * 170, 30, 20, 195);
 
2398
                
 
2399
        for (i = 0; i < 50; i++) {
 
2400
                if (pdir_1t)
 
2401
                        DrawCircle(rplx - scroll_x + cos(pdir_1) * (25 + i * 4), rply - scroll_y + sin(pdir_1) * (25 + i * 4), 5, 255);
 
2402
                if (pdir_2t)
 
2403
                        DrawCircle(rplx - scroll_x + cos(pdir_2) * (25 + i * 4), rply - scroll_y + sin(pdir_2) * (25 + i * 4), 5, 195);
 
2404
        }
 
2405
        DrawCircleEx(rplx - scroll_x, rply - scroll_y, 30, 20, 255);
 
2406
        
 
2407
        DrawCircleEx(rplx - scroll_x, rply - scroll_y, 197, 193, 128);
 
2408
        if (pdir_1t)
 
2409
                DrawCircleEx(rplx - scroll_x + cos(pdir_1) * 170, rply - scroll_y + sin(pdir_1) * 170, 27, 23, 128);
 
2410
        if (pdir_2t)
 
2411
                DrawCircleEx(rplx - scroll_x + cos(pdir_2) * 170, rply - scroll_y + sin(pdir_2) * 170, 27, 23, 78);
 
2412
        
 
2413
        for (i = 0; i < 50; i++) {
 
2414
                if (pdir_1t)
 
2415
                        DrawCircle(rplx - scroll_x + cos(pdir_1) * (25 + i * 4), rply - scroll_y + sin(pdir_1) * (25 + i * 4), 3, 128);
 
2416
                if (pdir_2t)
 
2417
                        DrawCircle(rplx - scroll_x + cos(pdir_2) * (25 + i * 4), rply - scroll_y + sin(pdir_2) * (25 + i * 4), 3, 78);
 
2418
        }
 
2419
        DrawCircleEx(rplx - scroll_x, rply - scroll_y, 27, 23, 128);
 
2420
}
 
2421
 
 
2422
void SpecialTile(int x, int y)
 
2423
{
 
2424
        static int otext = 0;
 
2425
        static int t = 0;
 
2426
        unsigned char tile;
 
2427
        char message[100] = "";
 
2428
 
 
2429
        tile = Get(x, y);
 
2430
        switch (tile) {
 
2431
                case 25:
 
2432
                        if (artifacts[11]) {
 
2433
                                sprintf(message, "This is a checkpoint, but it doesn't seem to be working");
 
2434
                                break;
 
2435
                        }
 
2436
                        if (checkpoints_found <= 1) {
 
2437
                                sprintf(message, "This is a checkpoint. You will return here when you die.");
 
2438
                        } else {
 
2439
                                sprintf(message, "Press ENTER to teleport between checkpoints.");
 
2440
                        }
 
2441
                        break;
 
2442
                case 26:
 
2443
                        sprintf(message, "Press ENTER to open the storage chest");
 
2444
                        break;
 
2445
                case 28:
 
2446
                        if (player_shield >= 25) {
 
2447
                                sprintf(message, "Your shield is already at full efficiency");
 
2448
                        } else {
 
2449
                                sprintf(message, "Press ENTER to upgrade shields (%d crystals)", UpgradePrice(0));
 
2450
                        }
 
2451
                        break;
 
2452
                case 29:
 
2453
                        if (circuit_fillrate >= 25) {
 
2454
                                sprintf(message, "Your circuit charge rate is already at its highest");
 
2455
                        } else {
 
2456
                                sprintf(message, "Press ENTER to upgrade circuit charge (%d crystals)", UpgradePrice(1));
 
2457
                        }
 
2458
                        break;
 
2459
                case 30:
 
2460
                        if (circuit_recoverrate >= 25) {
 
2461
                                sprintf(message, "Your circuit refill rate is already at its highest");
 
2462
                        } else {
 
2463
                                sprintf(message, "Press ENTER to upgrade circuit refill (%d crystals)", UpgradePrice(2));
 
2464
                        }
 
2465
                        break;
 
2466
                case 31:
 
2467
                        sprintf(message, "Press ENTER to record your progress");
 
2468
                        break;
 
2469
                case 32:
 
2470
                        if (total_gems == 0) {
 
2471
                                sprintf(message, "This is a crystal device. It isn't working at the moment.");
 
2472
                        } else {
 
2473
                                sprintf(message, "Press ENTER to activate the crystal device");
 
2474
                        }
 
2475
                        break;
 
2476
                case 42:
 
2477
                        if (rooms[player_room].room_type == 5) {
 
2478
                                if (CanGetArtifact(rooms[player_room].room_param)) {
 
2479
                                        
 
2480
                                } else {
 
2481
                                        sprintf(message, "The artifact is tainted with shadow. You must slay more of the shadow first.");
 
2482
                                }
 
2483
                        }
 
2484
                        break;
 
2485
                case 53:
 
2486
                        CompassPoint();
 
2487
                        break;
 
2488
                default:
 
2489
                        if (first_game) {
 
2490
                                if (otext < 60) {
 
2491
                                        sprintf(message, "Press H to read the help file");
 
2492
                                        otext++;
 
2493
                                }
 
2494
                        }
 
2495
                        break;
 
2496
        }
 
2497
        
 
2498
        if (message[0] == 0) {
 
2499
                if (specialmessage != 0) {
 
2500
                        switch (specialmessage) {
 
2501
                                case 1: sprintf(message, "Ancient artifact: Complete Map"); break;
 
2502
                                case 2: sprintf(message, "Ancient artifact: Shield boost"); break;
 
2503
                                case 3: sprintf(message, "Ancient artifact: Extra crystal efficiency"); break;
 
2504
                                case 4: sprintf(message, "Ancient artifact: Circuit booster"); break;
 
2505
                                case 5: sprintf(message, "Ancient artifact: Metabolism increase"); break;
 
2506
                                case 6: sprintf(message, "Ancient artifact: Dodge enhancer"); break;
 
2507
                                case 7: sprintf(message, "Ancient artifact: Ethereal Monocle"); break;
 
2508
                                case 8: sprintf(message, "Ancient artifact: Crystal gatherer"); break;
 
2509
                                
 
2510
                                case 10: sprintf(message, "Enhancement: Shield upgrade"); break;
 
2511
                                case 11: sprintf(message, "Enhancement: Circuit charge upgrade"); break;
 
2512
                                case 12: sprintf(message, "Enhancement: Circuit refill upgrade"); break;
 
2513
                                
 
2514
                                case 20: sprintf(message, "Reward: Psi crystals"); break;
 
2515
                                
 
2516
                                case 30: sprintf(message, "Holy Sword 'Balmung' answers your call"); break;
 
2517
                                case 31: sprintf(message, "Mystic Halberd 'Amenonuhoko' answers your call"); break;
 
2518
                                case 32: sprintf(message, "Divine Bow 'Gandiva' answers your call"); break;
 
2519
                                case 33: sprintf(message, "You capture the cursed seal. Return to the entrance"); break;
 
2520
                                
 
2521
                                case 40: sprintf(message, "Balmung will remain here, where the ley lines are strong"); break;
 
2522
                                case 41: sprintf(message, "Amenonuhoko will remain here, where the ley lines are strong"); break;
 
2523
                                case 42: sprintf(message, "Gandiva will remain here, where the ley lines are strong"); break;
 
2524
                                
 
2525
                                case 50: sprintf(message, ". . . . . .   retrieved 'Agate Knife'"); break;
 
2526
                                
 
2527
                                default: sprintf(message, "ERROR: NO MESSAGE VALUE GIVEN"); break;
 
2528
                        }
 
2529
                        specialmessagetimer--;
 
2530
                        if (specialmessagetimer <= 0) {
 
2531
                                specialmessage = 0;
 
2532
                        }
 
2533
                }
 
2534
        }
 
2535
        
 
2536
        if (message[0] == 0) return;
 
2537
        
 
2538
        DrawRect(320 - strlen(message)*8 / 2 - 20, 100, strlen(message)*8+40, 48, 200);
 
2539
        DrawRect(320 - strlen(message)*8 / 2 - 15, 105, strlen(message)*8+30, 38, 32);
 
2540
        DrawRect(320 - strlen(message)*8 / 2 - 10, 110, strlen(message)*8+20, 28, 64);
 
2541
 
 
2542
        draw_text(320 - strlen(message)*8 / 2, 120, message, t%16<8 ? 255 : 192);
 
2543
        t++;
 
2544
        if (enter_pressed) {
 
2545
                ActivateTile(tile, x, y);
 
2546
        }
 
2547
}
 
2548
 
 
2549
void ScrollTo(int x, int y)
 
2550
{
 
2551
        static int scrollspeed_x = 1, scrollspeed_y = 1;
 
2552
        if (scroll_home == 0) {
 
2553
                scroll_x = x;
 
2554
                scroll_y = y;
 
2555
                return;
 
2556
        }
 
2557
 
 
2558
        if (scroll_home == 1) {
 
2559
                scrollspeed_x = (x - scroll_x)/20;
 
2560
                scrollspeed_y = (y - scroll_y)/20;
 
2561
                scroll_home = 2;
 
2562
        }
 
2563
 
 
2564
        if (scroll_home == 2) {
 
2565
                scroll_x += (x - scroll_x)/2;
 
2566
                scroll_y += (y - scroll_y)/2;
 
2567
 
 
2568
                if ((abs(scroll_x-x)<2)&&(abs(scroll_y-y)<2)) {
 
2569
                        scroll_x = x;
 
2570
                        scroll_y = y;
 
2571
                        scroll_home = 0;
 
2572
                }
 
2573
        }
 
2574
}
 
2575
 
 
2576
void DrawArtifacts()
 
2577
{
 
2578
        int i;
 
2579
        SDL_Rect from, to;
 
2580
        
 
2581
        if (artifact_spr == NULL) {
 
2582
                artifact_spr = IMG_Load("dat/i/artifacts.png");
 
2583
                SDL_SetColorKey(artifact_spr, SDL_SRCCOLORKEY | SDL_RLEACCEL, 0);
 
2584
        }
 
2585
        
 
2586
        for (i = 0; i < 12; i++) {
 
2587
                if (artifacts[i]) {
 
2588
                        from.x = i * 32;
 
2589
                        from.y = 0;
 
2590
                        from.w = 32;
 
2591
                        from.h = 32;
 
2592
                        
 
2593
                        to.x = 608;
 
2594
                        to.y = 47 + i * 35;
 
2595
                        SDL_BlitSurface(artifact_spr, &from, screen, &to);
 
2596
                }
 
2597
        }
 
2598
}
 
2599
 
 
2600
void Swap(int *a, int *b)
 
2601
{
 
2602
        *a ^= *b ^= *a ^= *b;
 
2603
}
 
2604
 
 
2605
void ThinLine(SDL_Surface *scr, int x1, int y1, int x2, int y2, Uint8 col)
 
2606
{
 
2607
        int dx, dy, dm;
 
2608
        int i, j;
 
2609
        
 
2610
        dx = (x2 - x1);
 
2611
        dy = (y2 - y1);
 
2612
        
 
2613
        dm = abs(dx) > abs(dy) ? dx : dy;
 
2614
        
 
2615
        if (dm == 0) return;
 
2616
        
 
2617
        if (dm < 0) {
 
2618
                Swap(&x1, &x2);
 
2619
                Swap(&y1, &y2);
 
2620
                dx = (x2 - x1);
 
2621
                dy = (y2 - y1);
 
2622
                
 
2623
                dm = dm * -1;
 
2624
        }
 
2625
 
 
2626
        if (dm == dx) {
 
2627
                if (dy == 0) {
 
2628
                        DrawRect(x1, y1, x2-x1+1, 1, col);
 
2629
                        return;
 
2630
                }
 
2631
                for (i = 0; i < dm; i++) {
 
2632
                        j = (dy * i / dm);
 
2633
                        DrawRect(i+x1, j+y1, 1, 1, col);
 
2634
                }
 
2635
        }
 
2636
        if (dm == dy) {
 
2637
                if (dx == 0) {
 
2638
                        DrawRect(x1, y1, 1, y2-y1+1, col);
 
2639
                        return;
 
2640
                }
 
2641
                for (i = 0; i < dm; i++) {
 
2642
                        j = (dx * i / dm);
 
2643
                        DrawRect(j+x1, i+y1, 1, 1, col);
 
2644
                }
 
2645
        }
 
2646
}