2
* OpenTyrian: A modern cross-platform port of Tyrian
3
* Copyright (C) 2007-2009 The OpenTyrian Development Team
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25
#include "game_menu.h"
57
inline static void blit_enemy( SDL_Surface *surface, unsigned int i, signed int x_offset, signed int y_offset, signed int sprite_offset );
59
boss_bar_t boss_bar[2];
61
/* Level Event Data */
62
JE_boolean quit, loadLevelOk;
64
struct JE_EventRecType eventRec[EVENT_MAXIMUM]; /* [1..eventMaximum] */
65
JE_word levelEnemyMax;
66
JE_word levelEnemyFrequency;
67
JE_word levelEnemy[40]; /* [1..40] */
71
/* Data used for ItemScreen procedure to indicate items available */
72
JE_byte itemAvail[9][10]; /* [1..9, 1..10] */
73
JE_byte itemAvailMax[9]; /* [1..9] */
75
void JE_starShowVGA( void )
78
Uint8 *s = NULL; /* screen pointer, 8-bit specific */
80
int x, y, lightx, lighty, lightdist;
82
if (!playerEndLevel && !skipStarShowVGA)
85
s = VGAScreenSeg->pixels;
87
src = game_screen->pixels;
90
if (smoothScroll != 0 /*&& thisPlayerNum != 2*/)
93
setjasondelay(frameCountMax);
96
if (starShowVGASpecialCode == 1)
98
src += game_screen->pitch * 183;
99
for (y = 0; y < 184; y++)
101
memmove(s, src, 264);
102
s += VGAScreenSeg->pitch;
103
src -= game_screen->pitch;
106
else if (starShowVGASpecialCode == 2 && processorType >= 2)
108
lighty = 172 - player[0].y;
109
lightx = 281 - player[0].x;
111
for (y = 184; y; y--)
115
for (x = 320 - 56; x; x--)
117
*s = (*src & 0xf0) | ((*src >> 2) & 0x03);
124
for (x = 320 - 56; x; x--)
126
lightdist = abs(lightx - x) + lighty;
129
else if (lightdist - y <= 5)
130
*s = (*src & 0xf0) | (((*src & 0x0f) + (3 * (5 - (lightdist - y)))) / 4);
132
*s = (*src & 0xf0) | ((*src & 0x0f) >> 2);
137
s += 56 + VGAScreenSeg->pitch - 320;
138
src += 56 + VGAScreenSeg->pitch - 320;
143
for (y = 0; y < 184; y++)
145
memmove(s, src, 264);
146
s += VGAScreenSeg->pitch;
147
src += game_screen->pitch;
153
quitRequested = false;
154
skipStarShowVGA = false;
157
inline static void blit_enemy( SDL_Surface *surface, unsigned int i, signed int x_offset, signed int y_offset, signed int sprite_offset )
159
if (enemy[i].sprite2s == NULL)
161
fprintf(stderr, "warning: enemy %d sprite missing\n", i);
165
const int x = enemy[i].ex + x_offset + tempMapXOfs,
166
y = enemy[i].ey + y_offset;
167
const unsigned int index = enemy[i].egr[enemy[i].enemycycle - 1] + sprite_offset;
169
if (enemy[i].filter != 0)
170
blit_sprite2_filter(surface, x, y, *enemy[i].sprite2s, index, enemy[i].filter);
172
blit_sprite2(surface, x, y, *enemy[i].sprite2s, index);
175
void JE_drawEnemy( int enemyOffset ) // actually does a whole lot more than just drawing
179
for (int i = enemyOffset - 25; i < enemyOffset; i++)
181
if (enemyAvail[i] != 1)
183
enemy[i].mapoffset = tempMapXOfs;
185
if (enemy[i].xaccel && enemy[i].xaccel - 89u > mt_rand() % 11)
187
if (player[0].x > enemy[i].ex)
189
if (enemy[i].exc < enemy[i].xaccel - 89)
194
if (enemy[i].exc >= 0 || -enemy[i].exc < enemy[i].xaccel - 89)
199
if (enemy[i].yaccel && enemy[i].yaccel - 89u > mt_rand() % 11)
201
if (player[0].y > enemy[i].ey)
203
if (enemy[i].eyc < enemy[i].yaccel - 89)
208
if (enemy[i].eyc >= 0 || -enemy[i].eyc < enemy[i].yaccel - 89)
213
if (enemy[i].ex + tempMapXOfs > -29 && enemy[i].ex + tempMapXOfs < 300)
215
if (enemy[i].aniactive == 1)
217
enemy[i].enemycycle++;
219
if (enemy[i].enemycycle == enemy[i].animax)
220
enemy[i].aniactive = enemy[i].aniwhenfire;
221
else if (enemy[i].enemycycle > enemy[i].ani)
222
enemy[i].enemycycle = enemy[i].animin;
225
if (enemy[i].egr[enemy[i].enemycycle - 1] == 999)
228
if (enemy[i].size == 1) // 2x2 enemy
230
if (enemy[i].ey > -13)
232
blit_enemy(VGAScreen, i, -6, -7, 0);
233
blit_enemy(VGAScreen, i, 6, -7, 1);
235
if (enemy[i].ey > -26 && enemy[i].ey < 182)
237
blit_enemy(VGAScreen, i, -6, 7, 19);
238
blit_enemy(VGAScreen, i, 6, 7, 20);
243
if (enemy[i].ey > -13)
244
blit_enemy(VGAScreen, i, 0, 0, 0);
252
if (--enemy[i].exccw <= 0)
254
if (enemy[i].exc == enemy[i].exrev)
256
enemy[i].excc = -enemy[i].excc;
257
enemy[i].exrev = -enemy[i].exrev;
258
enemy[i].exccadd = -enemy[i].exccadd;
262
enemy[i].exc += enemy[i].exccadd;
263
enemy[i].exccw = enemy[i].exccwmax;
264
if (enemy[i].exc == enemy[i].exrev)
266
enemy[i].excc = -enemy[i].excc;
267
enemy[i].exrev = -enemy[i].exrev;
268
enemy[i].exccadd = -enemy[i].exccadd;
276
if (--enemy[i].eyccw <= 0)
278
if (enemy[i].eyc == enemy[i].eyrev)
280
enemy[i].eycc = -enemy[i].eycc;
281
enemy[i].eyrev = -enemy[i].eyrev;
282
enemy[i].eyccadd = -enemy[i].eyccadd;
286
enemy[i].eyc += enemy[i].eyccadd;
287
enemy[i].eyccw = enemy[i].eyccwmax;
288
if (enemy[i].eyc == enemy[i].eyrev)
290
enemy[i].eycc = -enemy[i].eycc;
291
enemy[i].eyrev = -enemy[i].eyrev;
292
enemy[i].eyccadd = -enemy[i].eyccadd;
298
enemy[i].ey += enemy[i].fixedmovey;
300
enemy[i].ex += enemy[i].exc;
301
if (enemy[i].ex < -80 || enemy[i].ex > 340)
304
enemy[i].ey += enemy[i].eyc;
305
if (enemy[i].ey < -112 || enemy[i].ey > 190)
308
goto enemy_still_exists;
311
/* enemy[i].egr[10] &= 0x00ff; <MXD> madness? */
318
if (enemy[i].ex <= enemy[i].xminbounce || enemy[i].ex >= enemy[i].xmaxbounce)
319
enemy[i].exc = -enemy[i].exc;
322
if (enemy[i].ey <= enemy[i].yminbounce || enemy[i].ey >= enemy[i].ymaxbounce)
323
enemy[i].eyc = -enemy[i].eyc;
325
/* Evalue != 0 - score item at boundary */
326
if (enemy[i].scoreitem)
328
if (enemy[i].ex < -5)
330
if (enemy[i].ex > 245)
334
enemy[i].ey += tempBackMove;
336
if (enemy[i].ex <= -24 || enemy[i].ex >= 296)
342
temp = enemy[i].enemytype;
345
if (enemy[i].edamaged == 1)
353
if (enemy[i].enemyground != 0)
355
enemy[i].filter = 0x09;
360
for (int j = 3; j > 0; j--)
362
if (enemy[i].freq[j-1])
364
temp3 = enemy[i].tur[j-1];
366
if (--enemy[i].eshotwait[j-1] == 0 && temp3)
368
enemy[i].eshotwait[j-1] = enemy[i].freq[j-1];
369
if (difficultyLevel > 2)
371
enemy[i].eshotwait[j-1] = (enemy[i].eshotwait[j-1] / 2) + 1;
372
if (difficultyLevel > 7)
373
enemy[i].eshotwait[j-1] = (enemy[i].eshotwait[j-1] / 2) + 1;
376
if (galagaMode && (enemy[i].eyc == 0 || (mt_rand() % 400) >= galagaShotFreq))
381
case 252: /* Savara Boss DualMissile */
382
if (enemy[i].ey > 20)
384
JE_setupExplosion(tempX - 8 + tempMapXOfs, tempY - 20 - backMove * 8, -2, 6, false, false);
385
JE_setupExplosion(tempX + 4 + tempMapXOfs, tempY - 20 - backMove * 8, -2, 6, false, false);
388
case 251:; /* Suck-O-Magnet */
389
const int attractivity = 4 - (abs(player[0].x - tempX) + abs(player[0].y - tempY)) / 100;
390
player[0].x_velocity += (player[0].x > tempX) ? -attractivity : attractivity;
392
case 253: /* Left ShortRange Magnet */
393
if (abs(player[0].x + 25 - 14 - tempX) < 24 && abs(player[0].y - tempY) < 28)
395
player[0].x_velocity += 2;
398
(abs(player[1].x - 14 - tempX) < 24 && abs(player[1].y - tempY) < 28))
400
player[1].x_velocity += 2;
403
case 254: /* Left ShortRange Magnet */
404
if (abs(player[0].x + 25 - 14 - tempX) < 24 && abs(player[0].y - tempY) < 28)
406
player[0].x_velocity -= 2;
409
(abs(player[1].x - 14 - tempX) < 24 && abs(player[1].y - tempY) < 28))
411
player[1].x_velocity -= 2;
414
case 255: /* Magneto RePulse!! */
415
if (difficultyLevel != 1) /*DIF*/
419
enemy[i].filter = 0x70;
423
const int repulsivity = 4 - (abs(player[0].x - tempX) + abs(player[0].y - tempY)) / 20;
425
player[0].x_velocity += (player[0].x > tempX) ? repulsivity : -repulsivity;
431
for (int tempCount = weapons[temp3].multi; tempCount > 0; tempCount--)
433
for (b = 0; b < ENEMY_SHOT_MAX; b++)
435
if (enemyShotAvail[b] == 1)
438
if (b == ENEMY_SHOT_MAX)
441
enemyShotAvail[b] = !enemyShotAvail[b];
443
if (weapons[temp3].sound > 0)
446
temp = mt_rand() % 8;
448
soundQueue[temp] = weapons[temp3].sound;
451
if (enemy[i].aniactive == 2)
452
enemy[i].aniactive = 1;
454
if (++enemy[i].eshotmultipos[j-1] > weapons[temp3].max)
455
enemy[i].eshotmultipos[j-1] = 1;
457
int tempPos = enemy[i].eshotmultipos[j-1] - 1;
462
enemyShot[b].sx = tempX + weapons[temp3].bx[tempPos] + tempMapXOfs;
463
enemyShot[b].sy = tempY + weapons[temp3].by[tempPos];
464
enemyShot[b].sdmg = weapons[temp3].attack[tempPos];
465
enemyShot[b].tx = weapons[temp3].tx;
466
enemyShot[b].ty = weapons[temp3].ty;
467
enemyShot[b].duration = weapons[temp3].del[tempPos];
468
enemyShot[b].animate = 0;
469
enemyShot[b].animax = weapons[temp3].weapani;
471
enemyShot[b].sgr = weapons[temp3].sg[tempPos];
475
enemyShot[b].syc = weapons[temp3].acceleration;
476
enemyShot[b].sxc = weapons[temp3].accelerationx;
478
enemyShot[b].sxm = weapons[temp3].sx[tempPos];
479
enemyShot[b].sym = weapons[temp3].sy[tempPos];
482
enemyShot[b].sxc = -weapons[temp3].acceleration;
483
enemyShot[b].syc = weapons[temp3].accelerationx;
485
enemyShot[b].sxm = -weapons[temp3].sy[tempPos];
486
enemyShot[b].sym = -weapons[temp3].sx[tempPos];
489
enemyShot[b].sxc = weapons[temp3].acceleration;
490
enemyShot[b].syc = -weapons[temp3].acceleration;
492
enemyShot[b].sxm = weapons[temp3].sy[tempPos];
493
enemyShot[b].sym = -weapons[temp3].sx[tempPos];
497
if (weapons[temp3].aim > 0)
499
int aim = weapons[temp3].aim;
502
if (difficultyLevel > 2)
504
aim += difficultyLevel - 2;
507
JE_word target_x = player[0].x;
508
JE_word target_y = player[0].y;
512
// fire at live player(s)
513
if (player[0].is_alive && !player[1].is_alive)
515
else if (player[1].is_alive && !player[0].is_alive)
518
temp = mt_rand() % 2;
522
target_x = player[1].x - 25;
523
target_y = player[1].y;
527
int relative_x = (target_x + 25) - tempX - tempMapXOfs - 4;
530
int relative_y = target_y - tempY;
533
const int longest_side = MAX(abs(relative_x), abs(relative_y));
534
enemyShot[b].sxm = roundf((float)relative_x / longest_side * aim);
535
enemyShot[b].sym = roundf((float)relative_y / longest_side * aim);
544
/* Enemy Launch Routine */
545
if (enemy[i].launchfreq)
547
if (--enemy[i].launchwait == 0)
549
enemy[i].launchwait = enemy[i].launchfreq;
551
if (enemy[i].launchspecial != 0)
553
/*Type 1 : Must be inline with player*/
554
if (abs(enemy[i].ey - player[0].y) > 5)
558
if (enemy[i].aniactive == 2)
560
enemy[i].aniactive = 1;
563
if (enemy[i].launchtype == 0)
566
tempW = enemy[i].launchtype;
567
b = JE_newEnemy(enemyOffset == 50 ? 75 : enemyOffset - 25, tempW, 0);
569
/*Launch Enemy Placement*/
572
struct JE_SingleEnemyType* e = &enemy[b-1];
575
e->ey = tempY + enemyDat[e->enemytype].startyc;
579
if (e->launchtype > 0 && e->launchfreq == 0)
581
if (e->launchtype > 90)
583
e->ex += mt_rand() % ((e->launchtype - 90) * 4) - (e->launchtype - 90) * 2;
587
int target_x = (player[0].x + 25) - tempX - tempMapXOfs - 4;
590
int tempI5 = player[0].y - tempY;
593
const int longest_side = MAX(abs(target_x), abs(tempI5));
594
e->exc = roundf(((float)target_x / longest_side) * e->launchtype);
595
e->eyc = roundf(((float)tempI5 / longest_side) * e->launchtype);
600
temp = mt_rand() % 8;
602
soundQueue[temp] = randomEnemyLaunchSounds[(mt_rand() % 3)];
604
if (enemy[i].launchspecial == 1
605
&& enemy[i].linknum < 100)
607
e->linknum = enemy[i].linknum;
624
int lastEnemyOnScreen;
626
/* NOTE: BEGIN MAIN PROGRAM HERE AFTER LOADING A GAME OR STARTING A NEW ONE */
628
/* ----------- GAME ROUTINES ------------------------------------- */
629
/* We need to jump to the beginning to make space for the routines */
630
/* --------------------------------------------------------------- */
631
goto start_level_first;
634
/*------------------------------GAME LOOP-----------------------------------*/
637
/* Startlevel is called after a previous level is over. If the first level
638
is started for a gaming session, startlevelfirst is called instead and
639
this code is skipped. The code here finishes the level and prepares for
640
the loadmap function. */
645
twoPlayerMode = false;
649
free_sprite2s(&eShapes[0]);
650
free_sprite2s(&eShapes[1]);
651
free_sprite2s(&eShapes[2]);
652
free_sprite2s(&eShapes[3]);
663
if (play_demo || record_demo)
676
wait_noinput(true, true, true);
680
difficultyLevel = oldDifficultyLevel; /*Return difficulty to normal*/
684
if ((!all_players_dead() || normalBonusLevelCurrent || bonusLevelCurrent) && !playerEndLevel)
686
mainLevel = nextLevel;
696
JE_loadGame(twoPlayerMode ? 22 : 11);
700
onePlayerAction = false;
701
player[0].items.super_arcade_mode = SA_NONE;
703
if (bonusLevelCurrent && !playerEndLevel)
705
mainLevel = nextLevel;
709
doNotSaveBackup = false;
716
set_volume(tyrMusicVolume, fxVolume);
719
reallyEndLevel = false;
720
playerEndLevel = false;
723
doNotSaveBackup = false;
726
if (mainLevel == 0) // if quit itemscreen
727
return; // back to titlescreen
731
for (uint i = 0; i < COUNTOF(player); ++i)
732
player[i].is_alive = true;
734
oldDifficultyLevel = difficultyLevel;
735
if (episodeNum == EPISODE_AVAILABLE)
737
if (difficultyLevel < 1)
746
assert(COUNTOF(player->old_x) == COUNTOF(player->old_y));
748
for (uint i = 0; i < COUNTOF(player); ++i)
750
for (uint j = 0; j < COUNTOF(player->old_x); ++j)
752
player[i].old_x[j] = player[i].x - (19 - j);
753
player[i].old_y[j] = player[i].y - 18;
756
player[i].last_x_shot_move = player[i].x;
757
player[i].last_y_shot_move = player[i].y;
760
JE_loadPic(VGAScreen, twoPlayerMode ? 6 : 3, false);
764
JE_outText(VGAScreen, 268, twoPlayerMode ? 76 : 118, levelName, 12, 4);
767
JE_gammaCorrect(&colors, gammaCorrection);
768
fade_palette(colors, 50, 0, 255);
770
free_sprite2s(&shapes6);
771
JE_loadCompShapes(&shapes6, '6'); // explosion sprites
773
/* MAPX will already be set correctly */
777
mapYPos = &megaData1.mainmap[mapY][0] - 1;
778
mapY2Pos = &megaData2.mainmap[mapY2][0] - 1;
779
mapY3Pos = &megaData3.mainmap[mapY3][0] - 1;
802
/* Setup player ship graphics */
805
for (uint i = 0; i < COUNTOF(player); ++i)
807
player[i].x_velocity = 0;
808
player[i].y_velocity = 0;
810
player[i].invulnerable_ticks = 100;
813
newkey = newmouse = false;
815
/* Initialize Level Data and Debug Mode */
820
warningColChange = 1;
821
warningSoundDelay = 0;
825
readyToEndLevel = false;
826
firstGameOver = true;
833
enemiesActive = true;
834
for(temp = 0; temp < 3; temp++)
836
button[temp] = false;
838
stopBackgrounds = false;
839
stopBackgroundNum = 0;
840
background3x1 = false;
841
background3x1b = false;
844
topEnemyOver = false;
845
skyEnemyOverAll = false;
846
smallEnemyAdjust = false;
848
enemyContinualDamage = false;
849
levelEnemyFrequency = 96;
850
quitRequested = false;
852
for (unsigned int i = 0; i < COUNTOF(boss_bar); i++)
853
boss_bar[i].link_num = 0;
855
forceEvents = false; /*Force events to continue if background movement = 0*/
857
superEnemy254Jump = 0; /*When Enemy with PL 254 dies*/
862
filterFadeStart = false;
864
levelBrightness = -14;
865
levelBrightnessChg = 1;
867
background2notTransparent = false;
869
uint old_weapon_bar[2] = { 0, 0 }; // only redrawn when they change
871
/* Initially erase power bars */
872
lastPower = power / 10;
875
JE_drawTextWindow(miscText[20]);
877
/* Setup Armor/Shield Data */
879
shieldT = shields[player[0].items.shield].tpwr * 20;
881
for (uint i = 0; i < COUNTOF(player); ++i)
883
player[i].shield = shields[player[i].items.shield].mpwr;
884
player[i].shield_max = player[i].shield * 2;
890
for (uint i = 0; i < COUNTOF(player); ++i)
891
player[i].superbombs = 0;
896
/* Secret Level Display */
901
play_song(levelSong - 1);
903
JE_drawPortConfigButtons();
905
/* --- MAIN LOOP --- */
912
JE_clearSpecialRequests();
917
initialize_starfield();
919
JE_setNewGameSpeed();
921
/* JE_setVol(tyrMusicVolume, fxPlayVol >> 2); NOTE: MXD killed this because it was broken */
924
if (!play_demo && !doNotSaveBackup)
926
temp = twoPlayerMode ? 22 : 11;
927
JE_saveGame(temp, "LAST LEVEL ");
930
if (!play_demo && record_demo)
932
Uint8 new_demo_num = 0;
936
sprintf(tempStr, "demorec.%d", new_demo_num++);
938
while (dir_file_exists(get_user_directory(), tempStr)); // until file doesn't exist
940
demo_file = dir_fopen_warn(get_user_directory(), tempStr, "wb");
944
efwrite(&episodeNum, 1, 1, demo_file);
945
efwrite(levelName, 1, 10, demo_file);
946
efwrite(&lvlFileNum, 1, 1, demo_file);
948
fputc(player[0].items.weapon[FRONT_WEAPON].id, demo_file);
949
fputc(player[0].items.weapon[REAR_WEAPON].id, demo_file);
950
fputc(player[0].items.super_arcade_mode, demo_file);
951
fputc(player[0].items.sidekick[LEFT_SIDEKICK], demo_file);
952
fputc(player[0].items.sidekick[RIGHT_SIDEKICK], demo_file);
953
fputc(player[0].items.generator, demo_file);
955
fputc(player[0].items.sidekick_level, demo_file);
956
fputc(player[0].items.sidekick_series, demo_file);
958
fputc(initial_episode_num, demo_file);
960
fputc(player[0].items.shield, demo_file);
961
fputc(player[0].items.special, demo_file);
962
fputc(player[0].items.ship, demo_file);
964
for (uint i = 0; i < 2; ++i)
965
fputc(player[0].items.weapon[i].power, demo_file);
967
for (uint i = 0; i < 3; ++i)
970
efwrite(&levelSong, 1, 1, demo_file);
976
twoPlayerLinked = false;
979
for (uint i = 0; i < COUNTOF(player); ++i)
980
calc_purple_balls_needed(&player[i]);
982
damageRate = 2; /*Normal Rate for Collision Damage*/
990
portConfigChange = false;
992
/*Destruction Ratio*/
998
superArcadePowerUp = 1;
1000
yourInGameMenuRequest = false;
1004
for (uint i = 0; i < COUNTOF(player); ++i)
1005
player[i].exploding_ticks = 0;
1012
memset(enemyAvail, 1, sizeof(enemyAvail));
1013
for (uint i = 0; i < COUNTOF(enemyShotAvail); i++)
1014
enemyShotAvail[i] = 1;
1016
/*Initialize Shots*/
1017
memset(playerShotData, 0, sizeof(playerShotData));
1018
memset(shotAvail, 0, sizeof(shotAvail));
1019
memset(shotMultiPos, 0, sizeof(shotMultiPos));
1020
memset(shotRepeat, 1, sizeof(shotRepeat));
1022
memset(button, 0, sizeof(button));
1024
memset(globalFlags, 0, sizeof(globalFlags));
1026
memset(explosions, 0, sizeof(explosions));
1027
memset(rep_explosions, 0, sizeof(rep_explosions));
1029
/* --- Clear Sound Queue --- */
1030
memset(soundQueue, 0, sizeof(soundQueue));
1031
soundQueue[3] = V_GOOD_LUCK;
1033
memset(enemyShapeTables, 0, sizeof(enemyShapeTables));
1034
memset(enemy, 0, sizeof(enemy));
1036
memset(SFCurrentCode, 0, sizeof(SFCurrentCode));
1037
memset(SFExecuted, 0, sizeof(SFExecuted));
1039
zinglonDuration = 0;
1041
nextSpecialWait = 0;
1042
optionAttachmentMove = 0; /*Launch the Attachments!*/
1043
optionAttachmentLinked = true;
1048
memset(smoothies, 0, sizeof(smoothies));
1051
randomExplosions = false;
1053
last_superpixel = 0;
1054
memset(superpixels, 0, sizeof(superpixels));
1056
returnActive = false;
1062
difficultyLevel = 2;
1066
JE_drawOptionLevel();
1068
// keeps map from scrolling past the top
1069
BKwrap1 = BKwrap1to = &megaData1.mainmap[1][0];
1070
BKwrap2 = BKwrap2to = &megaData2.mainmap[1][0];
1071
BKwrap3 = BKwrap3to = &megaData3.mainmap[1][0];
1075
//tempScreenSeg = game_screen; /* side-effect of game_screen */
1079
smoothies[9-1] = false;
1080
smoothies[6-1] = false;
1082
starShowVGASpecialCode = smoothies[9-1] + (smoothies[6-1] << 1);
1085
/*Background Wrapping*/
1086
if (mapYPos <= BKwrap1)
1088
mapYPos = BKwrap1to;
1090
if (mapY2Pos <= BKwrap2)
1092
mapY2Pos = BKwrap2to;
1094
if (mapY3Pos <= BKwrap3)
1096
mapY3Pos = BKwrap3to;
1100
allPlayersGone = all_players_dead() &&
1101
((*player[0].lives == 1 && player[0].exploding_ticks == 0) || (!onePlayerAction && !twoPlayerMode)) &&
1102
((*player[1].lives == 1 && player[1].exploding_ticks == 0) || !twoPlayerMode);
1105
/*-----MUSIC FADE------*/
1108
if (tempVolume > 10)
1111
set_volume(tempVolume, fxVolume);
1119
if (!allPlayersGone && levelEnd > 0 && endLevel)
1124
else if (!playing && firstGameOver)
1126
play_song(levelSong - 1);
1130
if (!endLevel) // draw HUD
1132
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */
1134
/*-----------------------Message Bar------------------------*/
1135
if (textErase > 0 && --textErase == 0)
1136
blit_sprite(VGAScreenSeg, 16, 189, OPTION_SHAPES, 36); // in-game message area
1138
/*------------------------Shield Gen-------------------------*/
1141
for (uint i = 0; i < COUNTOF(player); ++i)
1142
player[i].shield = 0;
1144
// spawned dragonwing died :(
1145
if (*player[1].lives == 0 || player[1].armor == 0)
1146
twoPlayerMode = false;
1148
if (player[0].cash >= (unsigned)galagaLife)
1150
soundQueue[6] = S_EXPLOSION_11;
1151
soundQueue[7] = S_SOUL_OF_ZINGLON;
1153
if (*player[0].lives < 11)
1154
++(*player[0].lives);
1156
player[0].cash += 1000;
1158
if (galagaLife == 10000)
1161
galagaLife += 25000;
1164
else // not galagaMode
1168
if (--shieldWait == 0)
1172
for (uint i = 0; i < COUNTOF(player); ++i)
1174
if (player[i].shield < player[i].shield_max && player[i].is_alive)
1181
else if (player[0].is_alive && player[0].shield < player[0].shield_max && power > shieldT)
1183
if (--shieldWait == 0)
1190
if (player[1].shield < player[0].shield_max)
1198
/*---------------------Weapon Display-------------------------*/
1199
for (uint i = 0; i < 2; ++i)
1201
uint item_power = player[twoPlayerMode ? i : 0].items.weapon[i].power;
1203
if (old_weapon_bar[i] != item_power)
1205
old_weapon_bar[i] = item_power;
1207
int x = twoPlayerMode ? 286 : 289,
1208
y = (i == 0) ? (twoPlayerMode ? 6 : 17) : (twoPlayerMode ? 100 : 38);
1210
fill_rectangle_xy(VGAScreenSeg, x, y, x + 1 + 10 * 2, y + 2, 0);
1212
for (uint j = 1; j <= item_power; ++j)
1214
JE_rectangle(VGAScreen, x, y, x + 1, y + 2, 115 + j); /* SEGa000 */
1220
/*------------------------Power Bar-------------------------*/
1221
if (twoPlayerMode || onePlayerAction)
1233
if (temp != lastPower)
1235
if (temp > lastPower)
1236
fill_rectangle_xy(VGAScreenSeg, 269, 113 - 11 - temp, 276, 114 - 11 - lastPower, 113 + temp / 7);
1238
fill_rectangle_xy(VGAScreenSeg, 269, 113 - 11 - lastPower, 276, 114 - 11 - temp, 0);
1244
oldMapX3Ofs = mapX3Ofs;
1249
/* use game_screen for all the generic drawing functions */
1250
VGAScreen = game_screen;
1252
/*---------------------------EVENTS-------------------------*/
1253
while (eventRec[eventLoc-1].eventtime <= curLoc && eventLoc <= maxEvent)
1256
if (isNetworkGame && reallyEndLevel)
1261
JE_checkSmoothies();
1263
VGAScreen = VGAScreen2; // this makes things complicated, but we do it anyway :(
1265
/* --- BACKGROUNDS --- */
1266
/* --- BACKGROUND 1 --- */
1268
if (forceEvents && !backMove)
1271
if (map1YDelayMax > 1 && backMove < 2)
1272
backMove = (map1YDelay == 1) ? 1 : 0;
1275
if (astralDuration == 0)
1276
draw_background_1(VGAScreen);
1278
JE_clr256(VGAScreen);
1280
/*Set Movement of background 1*/
1281
if (--map1YDelay == 0)
1283
map1YDelay = map1YDelayMax;
1287
backPos += backMove;
1293
mapYPos -= 14; /*Map Width*/
1297
if (starActive || astralDuration > 0)
1299
update_and_draw_starfield(VGAScreen, starfield_speed);
1302
if (processorType > 1 && smoothies[5-1])
1304
iced_blur_filter(game_screen, VGAScreen);
1305
VGAScreen = game_screen;
1308
/*-----------------------BACKGROUNDS------------------------*/
1309
/*-----------------------BACKGROUND 2------------------------*/
1310
if (background2over == 3)
1312
draw_background_2(VGAScreen);
1316
if (background2over == 0)
1318
if (!(smoothies[2-1] && processorType < 4) && !(smoothies[1-1] && processorType == 3))
1320
if (wild && !background2notTransparent)
1321
draw_background_2_blend(VGAScreen);
1323
draw_background_2(VGAScreen);
1327
if (smoothies[0] && processorType > 2 && smoothie_data[0] == 0)
1329
lava_filter(game_screen, VGAScreen);
1330
VGAScreen = game_screen;
1332
if (smoothies[2-1] && processorType > 2)
1334
water_filter(game_screen, VGAScreen);
1335
VGAScreen = game_screen;
1338
/*-----------------------Ground Enemy------------------------*/
1339
lastEnemyOnScreen = enemyOnScreen;
1341
tempMapXOfs = mapXOfs;
1342
tempBackMove = backMove;
1346
if (enemyOnScreen == 0 || enemyOnScreen == lastEnemyOnScreen)
1348
if (stopBackgroundNum == 1)
1349
stopBackgroundNum = 9;
1352
if (smoothies[0] && processorType > 2 && smoothie_data[0] > 0)
1354
lava_filter(game_screen, VGAScreen);
1355
VGAScreen = game_screen;
1361
JE_darkenBackground(neat);
1364
/*-----------------------BACKGROUNDS------------------------*/
1365
/*-----------------------BACKGROUND 2------------------------*/
1366
if (!(smoothies[2-1] && processorType < 4) &&
1367
!(smoothies[1-1] && processorType == 3))
1369
if (background2over == 1)
1371
if (wild && !background2notTransparent)
1372
draw_background_2_blend(VGAScreen);
1374
draw_background_2(VGAScreen);
1381
JE_darkenBackground(neat);
1384
if (background3over == 2)
1385
draw_background_3(VGAScreen);
1388
if (enemiesActive && mt_rand() % 100 > levelEnemyFrequency)
1390
tempW = levelEnemy[mt_rand() % levelEnemyMax];
1392
soundQueue[3] = S_WEAPON_7;
1393
b = JE_newEnemy(0, tempW, 0);
1396
if (processorType > 1 && smoothies[3-1])
1398
iced_blur_filter(game_screen, VGAScreen);
1399
VGAScreen = game_screen;
1401
if (processorType > 1 && smoothies[4-1])
1403
blur_filter(game_screen, VGAScreen);
1404
VGAScreen = game_screen;
1407
/* Draw Sky Enemy */
1408
if (!skyEnemyOverAll)
1410
lastEnemyOnScreen = enemyOnScreen;
1412
tempMapXOfs = mapX2Ofs;
1416
if (enemyOnScreen == lastEnemyOnScreen)
1418
if (stopBackgroundNum == 2)
1419
stopBackgroundNum = 9;
1423
if (background3over == 0)
1424
draw_background_3(VGAScreen);
1426
/* Draw Top Enemy */
1429
tempMapXOfs = (background3x1 == 0) ? oldMapX3Ofs : mapXOfs;
1430
tempBackMove = backMove3;
1434
/* Player Shot Images */
1435
for (int z = 0; z < MAX_PWEAPON; z++)
1437
if (shotAvail[z] != 0)
1439
bool is_special = false;
1440
int tempShotX = 0, tempShotY = 0;
1443
JE_word tempX2, tempY2;
1446
if (!player_shot_move_and_draw(z, &is_special, &tempShotX, &tempShotY, &damage, &temp2, &chain, &playerNum, &tempX2, &tempY2))
1448
goto draw_player_shot_loop_end;
1451
for (b = 0; b < 100; b++)
1453
if (enemyAvail[b] == 0)
1457
if (z == MAX_PWEAPON - 1)
1459
temp = 25 - abs(zinglonDuration - 25);
1460
collided = abs(enemy[b].ex + enemy[b].mapoffset - (player[0].x + 7)) < temp;
1465
else if (is_special)
1467
collided = ((enemy[b].enemycycle == 0) &&
1468
(abs(enemy[b].ex + enemy[b].mapoffset - tempShotX - tempX2) < (25 + tempX2)) &&
1469
(abs(enemy[b].ey - tempShotY - 12 - tempY2) < (29 + tempY2))) ||
1470
((enemy[b].enemycycle > 0) &&
1471
(abs(enemy[b].ex + enemy[b].mapoffset - tempShotX - tempX2) < (13 + tempX2)) &&
1472
(abs(enemy[b].ey - tempShotY - 6 - tempY2) < (15 + tempY2)));
1476
collided = ((enemy[b].enemycycle == 0) &&
1477
(abs(enemy[b].ex + enemy[b].mapoffset - tempShotX) < 25) && (abs(enemy[b].ey - tempShotY - 12) < 29)) ||
1478
((enemy[b].enemycycle > 0) &&
1479
(abs(enemy[b].ex + enemy[b].mapoffset - tempShotX) < 13) && (abs(enemy[b].ey - tempShotY - 6) < 15));
1486
shotMultiPos[SHOT_MISC] = 0;
1487
b = player_shot_create(0, SHOT_MISC, tempShotX, tempShotY, mouseX, mouseY, chain, playerNum);
1489
goto draw_player_shot_loop_end;
1492
infiniteShot = false;
1505
damage = damage - 250;
1506
infiniteShot = true;
1510
int armorleft = enemy[b].armorleft;
1512
temp = enemy[b].linknum;
1516
if (enemy[b].armorleft < 255)
1518
for (unsigned int i = 0; i < COUNTOF(boss_bar); i++)
1519
if (temp == boss_bar[i].link_num)
1520
boss_bar[i].color = 6;
1522
if (enemy[b].enemyground)
1523
enemy[b].filter = temp2;
1525
for (unsigned int e = 0; e < COUNTOF(enemy); e++)
1527
if (enemy[e].linknum == temp &&
1528
enemyAvail[e] != 1 &&
1529
enemy[e].enemyground != 0)
1532
enemy[e].iced = doIced;
1533
enemy[e].filter = temp2;
1538
if (armorleft > damage)
1540
if (z != MAX_PWEAPON - 1)
1542
if (enemy[b].armorleft != 255)
1544
enemy[b].armorleft -= damage;
1545
JE_setupExplosion(tempShotX, tempShotY, 0, 0, false, false);
1549
JE_doSP(tempShotX + 6, tempShotY + 6, damage / 2 + 3, damage / 4 + 2, temp2);
1553
soundQueue[5] = S_ENEMY_HIT;
1555
if ((armorleft - damage <= enemy[b].edlevel) &&
1556
((!enemy[b].edamaged) ^ (enemy[b].edani < 0)))
1559
for (temp3 = 0; temp3 < 100; temp3++)
1561
if (enemyAvail[temp3] != 1)
1563
int linknum = enemy[temp3].linknum;
1569
((enemy[temp3].edlevel > 0) && (linknum == temp)) ||
1571
(enemyContinualDamage && (temp - 100 == linknum)) ||
1572
((linknum > 40) && (linknum / 20 == temp / 20) && (linknum <= temp))
1578
enemy[temp3].enemycycle = 1;
1580
enemy[temp3].edamaged = !enemy[temp3].edamaged;
1582
if (enemy[temp3].edani != 0)
1584
enemy[temp3].ani = abs(enemy[temp3].edani);
1585
enemy[temp3].aniactive = 1;
1586
enemy[temp3].animax = 0;
1587
enemy[temp3].animin = enemy[temp3].edgr;
1588
enemy[temp3].enemycycle = enemy[temp3].animin - 1;
1591
else if (enemy[temp3].edgr > 0)
1593
enemy[temp3].egr[1-1] = enemy[temp3].edgr;
1594
enemy[temp3].ani = 1;
1595
enemy[temp3].aniactive = 0;
1596
enemy[temp3].animax = 0;
1597
enemy[temp3].animin = 1;
1601
enemyAvail[temp3] = 1;
1605
enemy[temp3].aniwhenfire = 0;
1607
if (enemy[temp3].armorleft > (unsigned char)enemy[temp3].edlevel)
1608
enemy[temp3].armorleft = enemy[temp3].edlevel;
1610
tempX = enemy[temp3].ex + enemy[temp3].mapoffset;
1611
tempY = enemy[temp3].ey;
1613
if (enemyDat[enemy[temp3].enemytype].esize != 1)
1614
JE_setupExplosion(tempX, tempY - 6, 0, 1, false, false);
1616
JE_setupExplosionLarge(enemy[temp3].enemyground, enemy[temp3].explonum / 2, tempX, tempY);
1625
if ((temp == 254) && (superEnemy254Jump > 0))
1626
JE_eventJump(superEnemy254Jump);
1628
for (temp2 = 0; temp2 < 100; temp2++)
1630
if (enemyAvail[temp2] != 1)
1632
temp3 = enemy[temp2].linknum;
1633
if ((temp2 == b) || (temp == 254) ||
1634
((temp != 255) && ((temp == temp3) || (temp - 100 == temp3)
1635
|| ((temp3 > 40) && (temp3 / 20 == temp / 20) && (temp3 <= temp)))))
1638
int enemy_screen_x = enemy[temp2].ex + enemy[temp2].mapoffset;
1640
if (enemy[temp2].special)
1642
assert((unsigned int) enemy[temp2].flagnum-1 < COUNTOF(globalFlags));
1643
globalFlags[enemy[temp2].flagnum-1] = enemy[temp2].setto;
1646
if ((enemy[temp2].enemydie > 0) &&
1647
!((superArcadeMode != SA_NONE) &&
1648
(enemyDat[enemy[temp2].enemydie].value == 30000)))
1651
tempW = enemy[temp2].enemydie;
1652
int enemy_offset = temp2 - (temp2 % 25);
1653
if (enemyDat[tempW].value > 30000)
1657
b = JE_newEnemy(enemy_offset, tempW, 0);
1659
if ((superArcadeMode != SA_NONE) && (enemy[b-1].evalue > 30000))
1661
superArcadePowerUp++;
1662
if (superArcadePowerUp > 5)
1663
superArcadePowerUp = 1;
1664
enemy[b-1].egr[1-1] = 5 + superArcadePowerUp * 2;
1665
enemy[b-1].evalue = 30000 + superArcadePowerUp;
1668
if (enemy[b-1].evalue != 0)
1669
enemy[b-1].scoreitem = true;
1671
enemy[b-1].scoreitem = false;
1673
enemy[b-1].ex = enemy[temp2].ex;
1674
enemy[b-1].ey = enemy[temp2].ey;
1679
if ((enemy[temp2].evalue > 0) && (enemy[temp2].evalue < 10000))
1681
if (enemy[temp2].evalue == 1)
1687
// in galaga mode player 2 is sidekick, so give cash to player 1
1688
player[galagaMode ? 0 : playerNum - 1].cash += enemy[temp2].evalue;
1692
if ((enemy[temp2].edlevel == -1) && (temp == temp3))
1694
enemy[temp2].edlevel = 0;
1695
enemyAvail[temp2] = 2;
1696
enemy[temp2].egr[1-1] = enemy[temp2].edgr;
1697
enemy[temp2].ani = 1;
1698
enemy[temp2].aniactive = 0;
1699
enemy[temp2].animax = 0;
1700
enemy[temp2].animin = 1;
1701
enemy[temp2].edamaged = true;
1702
enemy[temp2].enemycycle = 1;
1704
enemyAvail[temp2] = 1;
1708
if (enemyDat[enemy[temp2].enemytype].esize == 1)
1710
JE_setupExplosionLarge(enemy[temp2].enemyground, enemy[temp2].explonum, enemy_screen_x, enemy[temp2].ey);
1711
soundQueue[6] = S_EXPLOSION_9;
1715
JE_setupExplosion(enemy_screen_x, enemy[temp2].ey, 0, 1, false, false);
1716
soundQueue[6] = S_SELECT; // S_EXPLOSION_8
1727
else if (z != MAX_PWEAPON - 1)
1729
if (damage <= armorleft)
1732
goto draw_player_shot_loop_end;
1736
playerShotData[z].shotDmg -= armorleft;
1743
draw_player_shot_loop_end:
1748
/* Player movement indicators for shots that track your ship */
1749
for (uint i = 0; i < COUNTOF(player); ++i)
1751
player[i].last_x_shot_move = player[i].x;
1752
player[i].last_y_shot_move = player[i].y;
1755
/*=================================*/
1756
/*=======Collisions Detection======*/
1757
/*=================================*/
1759
for (uint i = 0; i < (twoPlayerMode ? 2 : 1); ++i)
1760
if (player[i].is_alive && !endLevel)
1761
JE_playerCollide(&player[i], i + 1);
1764
JE_mainGamePlayerFunctions(); /*--------PLAYER DRAW+MOVEMENT---------*/
1767
{ /*MAIN DRAWING IS STOPPED STARTING HERE*/
1769
/* Draw Enemy Shots */
1770
for (int z = 0; z < ENEMY_SHOT_MAX; z++)
1772
if (enemyShotAvail[z] == 0)
1774
enemyShot[z].sxm += enemyShot[z].sxc;
1775
enemyShot[z].sx += enemyShot[z].sxm;
1777
if (enemyShot[z].tx != 0)
1779
if (enemyShot[z].sx > player[0].x)
1781
if (enemyShot[z].sxm > -enemyShot[z].tx)
1786
if (enemyShot[z].sxm < enemyShot[z].tx)
1793
enemyShot[z].sym += enemyShot[z].syc;
1794
enemyShot[z].sy += enemyShot[z].sym;
1796
if (enemyShot[z].ty != 0)
1798
if (enemyShot[z].sy > player[0].y)
1800
if (enemyShot[z].sym > -enemyShot[z].ty)
1805
if (enemyShot[z].sym < enemyShot[z].ty)
1812
if (enemyShot[z].duration-- == 0 || enemyShot[z].sy > 190 || enemyShot[z].sy <= -14 || enemyShot[z].sx > 275 || enemyShot[z].sx <= 0)
1814
enemyShotAvail[z] = true;
1816
else // check if shot collided with player
1818
for (uint i = 0; i < (twoPlayerMode ? 2 : 1); ++i)
1820
if (player[i].is_alive &&
1821
enemyShot[z].sx > player[i].x - (signed)player[i].shot_hit_area_x &&
1822
enemyShot[z].sx < player[i].x + (signed)player[i].shot_hit_area_x &&
1823
enemyShot[z].sy > player[i].y - (signed)player[i].shot_hit_area_y &&
1824
enemyShot[z].sy < player[i].y + (signed)player[i].shot_hit_area_y)
1826
tempX = enemyShot[z].sx;
1827
tempY = enemyShot[z].sy;
1828
temp = enemyShot[z].sdmg;
1830
enemyShotAvail[z] = true;
1832
JE_setupExplosion(tempX, tempY, 0, 0, false, false);
1834
if (player[i].invulnerable_ticks == 0)
1836
if ((temp = JE_playerDamage(temp, &player[i])) > 0)
1838
player[i].x_velocity += (enemyShot[z].sxm * temp) / 2;
1839
player[i].y_velocity += (enemyShot[z].sym * temp) / 2;
1847
if (enemyShotAvail[z] == false)
1849
if (enemyShot[z].animax != 0)
1851
if (++enemyShot[z].animate >= enemyShot[z].animax)
1852
enemyShot[z].animate = 0;
1855
if (enemyShot[z].sgr >= 500)
1856
blit_sprite2(VGAScreen, enemyShot[z].sx, enemyShot[z].sy, shapesW2, enemyShot[z].sgr + enemyShot[z].animate - 500);
1858
blit_sprite2(VGAScreen, enemyShot[z].sx, enemyShot[z].sy, shapesC1, enemyShot[z].sgr + enemyShot[z].animate);
1866
if (background3over == 1)
1867
draw_background_3(VGAScreen);
1869
/* Draw Top Enemy */
1872
tempMapXOfs = (background3x1 == 0) ? oldMapX3Ofs : oldMapXOfs;
1873
tempBackMove = backMove3;
1877
/* Draw Sky Enemy */
1878
if (skyEnemyOverAll)
1880
lastEnemyOnScreen = enemyOnScreen;
1882
tempMapXOfs = mapX2Ofs;
1886
if (enemyOnScreen == lastEnemyOnScreen)
1888
if (stopBackgroundNum == 2)
1889
stopBackgroundNum = 9;
1893
/*-------------------------- Sequenced Explosions -------------------------*/
1894
enemyStillExploding = false;
1895
for (int i = 0; i < MAX_REPEATING_EXPLOSIONS; i++)
1897
if (rep_explosions[i].ttl != 0)
1899
enemyStillExploding = true;
1901
if (rep_explosions[i].delay > 0)
1903
rep_explosions[i].delay--;
1907
rep_explosions[i].y += backMove2 + 1;
1908
tempX = rep_explosions[i].x + (mt_rand() % 24) - 12;
1909
tempY = rep_explosions[i].y + (mt_rand() % 27) - 24;
1911
if (rep_explosions[i].big)
1913
JE_setupExplosionLarge(false, 2, tempX, tempY);
1915
if (rep_explosions[i].ttl == 1 || mt_rand() % 5 == 1)
1916
soundQueue[7] = S_EXPLOSION_11;
1918
soundQueue[6] = S_EXPLOSION_9;
1920
rep_explosions[i].delay = 4 + (mt_rand() % 3);
1924
JE_setupExplosion(tempX, tempY, 0, 1, false, false);
1926
soundQueue[5] = S_EXPLOSION_4;
1928
rep_explosions[i].delay = 3;
1931
rep_explosions[i].ttl--;
1935
/*---------------------------- Draw Explosions ----------------------------*/
1936
for (int j = 0; j < MAX_EXPLOSIONS; j++)
1938
if (explosions[j].ttl != 0)
1940
if (explosions[j].fixed_position != true)
1942
explosions[j].sprite++;
1943
explosions[j].y += explodeMove;
1945
else if (explosions[j].follow_player == true)
1947
explosions[j].x += explosionFollowAmountX;
1948
explosions[j].y += explosionFollowAmountY;
1950
explosions[j].y += explosions[j].delta_y;
1951
explosions[j].x += explosions[j].delta_x;
1953
if (explosions[j].y > 200 - 14)
1955
explosions[j].ttl = 0;
1959
if (explosionTransparent)
1960
blit_sprite2_blend(VGAScreen, explosions[j].x, explosions[j].y, shapes6, explosions[j].sprite + 1);
1962
blit_sprite2(VGAScreen, explosions[j].x, explosions[j].y, shapes6, explosions[j].sprite + 1);
1964
explosions[j].ttl--;
1969
if (!portConfigChange)
1970
portConfigDone = true;
1973
/*-----------------------BACKGROUNDS------------------------*/
1974
/*-----------------------BACKGROUND 2------------------------*/
1975
if (!(smoothies[2-1] && processorType < 4) &&
1976
!(smoothies[1-1] && processorType == 3))
1978
if (background2over == 2)
1980
if (wild && !background2notTransparent)
1981
draw_background_2_blend(VGAScreen);
1983
draw_background_2(VGAScreen);
1987
/*-------------------------Warning---------------------------*/
1988
if ((player[0].is_alive && player[0].armor < 6) ||
1989
(twoPlayerMode && !galagaMode && player[1].is_alive && player[1].armor < 6))
1991
int armor_amount = (player[0].is_alive && player[0].armor < 6) ? player[0].armor : player[1].armor;
1993
if (armorShipDelay > 0)
2000
b = JE_newEnemy(50, tempW, 0);
2003
enemy[b-1].enemydie = 560 + (mt_rand() % 3) + 1;
2004
enemy[b-1].eyc -= backMove3;
2005
enemy[b-1].armorleft = 4;
2007
armorShipDelay = 500;
2010
if ((player[0].is_alive && player[0].armor < 6 && (!isNetworkGame || thisPlayerNum == 1)) ||
2011
(twoPlayerMode && player[1].is_alive && player[1].armor < 6 && (!isNetworkGame || thisPlayerNum == 2)))
2014
tempW = armor_amount * 4 + 8;
2015
if (warningSoundDelay > tempW)
2016
warningSoundDelay = tempW;
2018
if (warningSoundDelay > 1)
2020
warningSoundDelay--;
2024
soundQueue[7] = S_WARNING;
2025
warningSoundDelay = tempW;
2028
warningCol += warningColChange;
2029
if (warningCol > 113 + (14 - (armor_amount * 2)))
2031
warningColChange = -warningColChange;
2032
warningCol = 113 + (14 - (armor_amount * 2));
2034
else if (warningCol < 113)
2036
warningColChange = -warningColChange;
2038
fill_rectangle_xy(VGAScreen, 24, 181, 138, 183, warningCol);
2039
fill_rectangle_xy(VGAScreen, 175, 181, 287, 183, warningCol);
2040
fill_rectangle_xy(VGAScreen, 24, 0, 287, 3, warningCol);
2042
JE_outText(VGAScreen, 140, 178, "WARNING", 7, (warningCol % 16) / 2);
2047
/*------- Random Explosions --------*/
2048
if (randomExplosions && mt_rand() % 10 == 1)
2049
JE_setupExplosionLarge(false, 20, mt_rand() % 280, mt_rand() % 180);
2051
/*=================================*/
2052
/*=======The Sound Routine=========*/
2053
/*=================================*/
2057
for (temp2 = 0; temp2 < SFX_CHANNELS; temp2++)
2059
if (soundQueue[temp2] != S_NONE)
2061
temp = soundQueue[temp2];
2064
else if (temp == 15)
2065
temp3 = fxPlayVol / 4;
2067
temp3 = fxPlayVol / 2;
2069
JE_multiSamplePlay(digiFx[temp-1], fxSize[temp-1], temp2, temp3);
2071
soundQueue[temp2] = S_NONE;
2076
if (returnActive && enemyOnScreen == 0)
2078
JE_eventJump(65535);
2079
returnActive = false;
2082
/*------- DEbug ---------*/
2083
debugTime = SDL_GetTicks();
2084
tempW = lastmouse_but;
2090
strcpy(tempStr, "");
2091
for (temp = 0; temp < 9; temp++)
2093
sprintf(tempStr, "%s%c", tempStr, smoothies[temp] + 48);
2095
sprintf(buffer, "SM = %s", tempStr);
2096
JE_outText(VGAScreen, 30, 70, buffer, 4, 0);
2098
sprintf(buffer, "Memory left = %d", -1);
2099
JE_outText(VGAScreen, 30, 80, buffer, 4, 0);
2100
sprintf(buffer, "Enemies onscreen = %d", enemyOnScreen);
2101
JE_outText(VGAScreen, 30, 90, buffer, 6, 0);
2103
debugHist = debugHist + abs((JE_longint)debugTime - (JE_longint)lastDebugTime);
2105
sprintf(tempStr, "%2.3f", 1000.0f / roundf(debugHist / debugHistCount));
2106
sprintf(buffer, "X:%d Y:%-5d %s FPS %d %d %d %d", (mapX - 1) * 12 + player[0].x, curLoc, tempStr, player[0].x_velocity, player[0].y_velocity, player[0].x, player[0].y);
2107
JE_outText(VGAScreen, 45, 175, buffer, 15, 3);
2108
lastDebugTime = debugTime;
2111
if (displayTime > 0)
2114
JE_outTextAndDarken(VGAScreen, 90, 10, miscText[59], 15, (JE_byte)flash - 8, FONT_SHAPES);
2115
flash += flashChange;
2116
if (flash > 4 || flash == 0)
2117
flashChange = -flashChange;
2120
/*Pentium Speed Mode?*/
2123
frameCountMax = (frameCountMax == 2) ? 3 : 2;
2126
/*-------- Level Timer ---------*/
2127
if (levelTimer && levelTimerCountdown > 0)
2129
levelTimerCountdown--;
2130
if (levelTimerCountdown == 0)
2131
JE_eventJump(levelTimerJumpTo);
2133
if (levelTimerCountdown > 200)
2135
if (levelTimerCountdown % 100 == 0)
2136
soundQueue[7] = S_WARNING;
2138
if (levelTimerCountdown % 10 == 0)
2139
soundQueue[6] = S_CLICK;
2141
else if (levelTimerCountdown % 20 == 0)
2143
soundQueue[7] = S_WARNING;
2146
JE_textShade (VGAScreen, 140, 6, miscText[66], 7, (levelTimerCountdown % 20) / 3, FULL_SHADE);
2147
sprintf(buffer, "%.1f", levelTimerCountdown / 100.0f);
2148
JE_dString (VGAScreen, 100, 2, buffer, SMALL_FONT_SHAPES);
2152
if (!constantPlay && !constantDie)
2156
if (player[0].exploding_ticks > 0 || player[1].exploding_ticks > 0)
2159
player[1].exploding_ticks = 0;
2165
if (play_demo || normalBonusLevelCurrent || bonusLevelCurrent)
2166
reallyEndLevel = true;
2168
JE_dString(VGAScreen, 120, 60, miscText[21], FONT_SHAPES); // game over
2170
set_mouse_position(159, 100);
2175
play_song(SONG_GAMEOVER);
2176
set_volume(tyrMusicVolume, fxVolume);
2178
firstGameOver = false;
2183
push_joysticks_as_keyboard();
2184
service_SDL_events(true);
2185
if ((newkey || button[0] || button[1] || button[2]) || newmouse)
2187
reallyEndLevel = true;
2192
reallyEndLevel = true;
2197
if (play_demo) // input kills demo
2199
push_joysticks_as_keyboard();
2200
service_SDL_events(false);
2202
if (newkey || newmouse)
2204
reallyEndLevel = true;
2206
stopped_demo = true;
2209
else // input handling for pausing, menu, cheats
2211
service_SDL_events(false);
2215
skipStarShowVGA = false;
2216
JE_mainKeyboardInput();
2218
if (skipStarShowVGA)
2224
pause_pressed = false;
2227
pauseRequest = true;
2232
if (ingamemenu_pressed)
2234
ingamemenu_pressed = false;
2238
inGameMenuRequest = true;
2242
yourInGameMenuRequest = true;
2244
skipStarShowVGA = true;
2253
if (!reallyEndLevel)
2255
Uint16 requests = (pauseRequest == true) |
2256
(inGameMenuRequest == true) << 1 |
2257
(skipLevelRequest == true) << 2 |
2258
(nortShipRequest == true) << 3;
2259
SDLNet_Write16(requests, &packet_state_out[0]->data[14]);
2261
SDLNet_Write16(difficultyLevel, &packet_state_out[0]->data[16]);
2262
SDLNet_Write16(player[0].x, &packet_state_out[0]->data[18]);
2263
SDLNet_Write16(player[1].x, &packet_state_out[0]->data[20]);
2264
SDLNet_Write16(player[0].y, &packet_state_out[0]->data[22]);
2265
SDLNet_Write16(player[1].y, &packet_state_out[0]->data[24]);
2266
SDLNet_Write16(curLoc, &packet_state_out[0]->data[26]);
2268
network_state_send();
2270
if (network_state_update())
2272
assert(SDLNet_Read16(&packet_state_in[0]->data[26]) == SDLNet_Read16(&packet_state_out[network_delay]->data[26]));
2274
requests = SDLNet_Read16(&packet_state_in[0]->data[14]) ^ SDLNet_Read16(&packet_state_out[network_delay]->data[14]);
2281
yourInGameMenuRequest = SDLNet_Read16(&packet_state_out[network_delay]->data[14]) & 2;
2283
yourInGameMenuRequest = false;
2285
reallyEndLevel = true;
2290
levelTimerCountdown = 0;
2294
if (requests & 8) // nortship
2296
player[0].items.ship = 12; // Nort Ship
2297
player[0].items.special = 13; // Astral Zone
2298
player[0].items.weapon[FRONT_WEAPON].id = 36; // NortShip Super Pulse
2299
player[0].items.weapon[REAR_WEAPON].id = 37; // NortShip Spreader
2303
for (int i = 0; i < 2; i++)
2305
if (SDLNet_Read16(&packet_state_in[0]->data[18 + i * 2]) != SDLNet_Read16(&packet_state_out[network_delay]->data[18 + i * 2]) || SDLNet_Read16(&packet_state_in[0]->data[20 + i * 2]) != SDLNet_Read16(&packet_state_out[network_delay]->data[20 + i * 2]))
2308
sprintf(temp, "Player %d is unsynchronized!", i + 1);
2310
JE_textShade(game_screen, 40, 110 + i * 10, temp, 9, 2, FULL_SHADE);
2316
JE_clearSpecialRequests();
2326
JE_filterScreen(levelFilter, levelBrightness);
2331
JE_inGameDisplays();
2333
VGAScreen = VGAScreenSeg; /* side-effect of game_screen */
2337
/*Start backgrounds if no enemies on screen
2338
End level if number of enemies left to kill equals 0.*/
2339
if (stopBackgroundNum == 9 && backMove == 0 && !enemyStillExploding)
2345
stopBackgroundNum = 0;
2346
stopBackgrounds = false;
2354
reallyEndLevel = true;
2358
if (!endLevel && enemyOnScreen == 0)
2360
if (readyToEndLevel && !enemyStillExploding)
2362
if (levelTimerCountdown > 0)
2366
readyToEndLevel = false;
2371
reallyEndLevel = true;
2374
if (stopBackgrounds)
2376
stopBackgrounds = false;
2385
/*Other Network Functions*/
2395
/* --- Load Level/Map Data --- */
2396
void JE_loadMap( void )
2402
JE_word mapSh[3][128]; /* [1..3, 0..127] */
2403
JE_byte *ref[3][128]; /* [1..3, 0..127] */
2406
JE_byte mapBuf[15 * 600]; /* [1..15 * 600] */
2411
Uint8 pic_buffer[320*200]; /* screen buffer, 8-bit specific */
2412
Uint8 *vga, *pic, *vga2; /* screen pointer, 8-bit specific */
2414
lastCubeMax = cubeMax;
2417
songBuy = DEFAULT_SONG_BUY; /*Item Screen default song*/
2419
/* Load LEVELS.DAT - Section = MAINLEVEL */
2420
saveLevel = mainLevel;
2424
useLastBank = false;
2434
FILE *ep_f = dir_fopen_die(data_dir(), episode_file, "rb");
2436
jumpSection = false;
2437
loadLevelOk = false;
2439
/* Seek Section # Mainlevel */
2441
while (x < mainLevel)
2443
read_encrypted_pascal_string(s, sizeof(s), ep_f);
2459
if (mainLevel == 0) // if quit itemscreen
2460
return; // back to title screen
2466
read_encrypted_pascal_string(s, sizeof(s), ep_f);
2473
JE_playAnim("tyrend.anm", 0, 7);
2477
mapOrigin = atoi(strnztcpy(buffer, s + 4, 2));
2478
mapPNum = atoi(strnztcpy(buffer, s + 7, 1));
2479
for (i = 0; i < mapPNum; i++)
2481
mapPlanet[i] = atoi(strnztcpy(buffer, s + 1 + (i + 1) * 8, 2));
2482
mapSection[i] = atoi(strnztcpy(buffer, s + 4 + (i + 1) * 8, 3));
2487
temp = atoi(strnztcpy(buffer, s + 4, 2));
2488
for (i = 0; i < temp; i++)
2490
cubeList[i] = atoi(strnztcpy(buffer, s + 3 + (i + 1) * 4, 3));
2497
cubeMax = atoi(strnztcpy(buffer, s + 4, 2)); /*Auto set CubeMax*/
2501
temp = atoi(strnztcpy(buffer, s + 4, 2));
2508
galagaMode = true; /*GALAGA mode*/
2510
player[1].items = player[0].items;
2511
player[1].items.weapon[REAR_WEAPON].id = 15; // Vulcan Cannon
2512
for (uint i = 0; i < COUNTOF(player[1].items.sidekick); ++i)
2513
player[1].items.sidekick[i] = 0; // None
2520
case 'e': // ENGAGE mode, used for mini-games
2521
doNotSaveBackup = true;
2522
constantDie = false;
2523
onePlayerAction = true;
2525
twoPlayerMode = false;
2529
player[0].items.ship = 13; // The Stalker 21.126
2530
player[0].items.weapon[FRONT_WEAPON].id = 39; // Atomic RailGun
2531
player[0].items.weapon[REAR_WEAPON].id = 0; // None
2532
for (uint i = 0; i < COUNTOF(player[0].items.sidekick); ++i)
2533
player[0].items.sidekick[i] = 0; // None
2534
player[0].items.generator = 2; // Advanced MR-12
2535
player[0].items.shield = 4; // Advanced Integrity Field
2536
player[0].items.special = 0; // None
2538
player[0].items.weapon[FRONT_WEAPON].power = 3;
2539
player[0].items.weapon[REAR_WEAPON].power = 1;
2542
case 'J': // section jump
2543
temp = atoi(strnztcpy(buffer, s + 3, 3));
2548
case '2': // two-player section jump
2549
temp = atoi(strnztcpy(buffer, s + 3, 3));
2550
if (twoPlayerMode || onePlayerAction)
2557
case 'w': // Stalker 21.126 section jump
2558
temp = atoi(strnztcpy(buffer, s + 3, 3)); /*Allowed to go to Time War?*/
2559
if (player[0].items.ship == 13)
2567
temp = atoi(strnztcpy(buffer, s + 3, 3));
2568
if (levelTimer && levelTimerCountdown == 0)
2576
temp = atoi(strnztcpy(buffer, s + 3, 3));
2577
if (!all_players_alive())
2585
saveLevel = mainLevel;
2586
break; /*store savepoint*/
2595
JE_saveGame(11, "LAST LEVEL ");
2599
temp = atoi(strnztcpy(buffer, s + 3, 3));
2603
case 'I': /*Load Items Available Information*/
2604
memset(&itemAvail, 0, sizeof(itemAvail));
2606
for (int i = 0; i < 9; ++i)
2608
read_encrypted_pascal_string(s, sizeof(s), ep_f);
2611
strncpy(buf, (strlen(s) > 8) ? s + 8 : "", sizeof(buf));
2614
while (str_pop_int(buf, &temp))
2615
itemAvail[i][j++] = temp;
2616
itemAvailMax[i] = j;
2623
nextLevel = atoi(strnztcpy(buffer, s + 9, 3));
2624
strnztcpy(levelName, s + 13, 9);
2625
levelSong = atoi(strnztcpy(buffer, s + 22, 2));
2628
nextLevel = mainLevel + 1;
2630
lvlFileNum = atoi(strnztcpy(buffer, s + 25, 2));
2632
bonusLevelCurrent = (strlen(s) > 28) & (s[28] == '$');
2633
normalBonusLevelCurrent = (strlen(s) > 27) & (s[27] == '$');
2634
gameJustLoaded = false;
2638
useLastBank = !useLastBank;
2643
temp = secretHint + (mt_rand() % 3) * 3;
2647
for (uint i = 0; i < 2; ++i)
2648
snprintf(levelWarningText[i], sizeof(*levelWarningText), "%s %lu", miscText[40], player[i].cash);
2649
strcpy(levelWarningText[2], "");
2650
levelWarningLines = 3;
2654
sprintf(levelWarningText[0], "%s %lu", miscText[37], JE_totalScore(&player[0]));
2655
strcpy(levelWarningText[1], "");
2656
levelWarningLines = 2;
2659
for (x = 0; x < temp - 1; x++)
2662
read_encrypted_pascal_string(s, sizeof(s), ep_f);
2663
while (s[0] != '#');
2668
read_encrypted_pascal_string(s, sizeof(s), ep_f);
2669
strcpy(levelWarningText[levelWarningLines], s);
2670
levelWarningLines++;
2672
while (s[0] != '#');
2673
levelWarningLines--;
2684
if (jumpBackToEpisode1 && !twoPlayerMode)
2686
JE_loadPic(VGAScreen, 1, false); // huh?
2687
JE_clr256(VGAScreen);
2691
// if completed Zinglon's Revenge, show SuperTyrian and Destruct codes
2692
// if completed SuperTyrian, show Nort-Ship Z code
2693
superArcadeMode = (initialDifficulty == 8) ? 8 : 1;
2696
if (superArcadeMode < SA_ENGAGE)
2698
if (SANextShip[superArcadeMode] == SA_ENGAGE)
2700
sprintf(buffer, "%s %s", miscTextB[4], pName[0]);
2701
JE_dString(VGAScreen, JE_fontCenter(buffer, FONT_SHAPES), 100, buffer, FONT_SHAPES);
2703
sprintf(buffer, "Or play... %s", specialName[7]);
2704
JE_dString(VGAScreen, 80, 180, buffer, SMALL_FONT_SHAPES);
2708
JE_dString(VGAScreen, JE_fontCenter(superShips[0], FONT_SHAPES), 30, superShips[0], FONT_SHAPES);
2709
JE_dString(VGAScreen, JE_fontCenter(superShips[SANextShip[superArcadeMode]], SMALL_FONT_SHAPES), 100, superShips[SANextShip[superArcadeMode]], SMALL_FONT_SHAPES);
2712
if (SANextShip[superArcadeMode] < SA_NORTSHIPZ)
2713
blit_sprite2x2(VGAScreen, 148, 70, shapes9, ships[SAShip[SANextShip[superArcadeMode]-1]].shipgraphic);
2714
else if (SANextShip[superArcadeMode] == SA_NORTSHIPZ)
2717
sprintf(buffer, "Type %s at Title", specialName[SANextShip[superArcadeMode]-1]);
2718
JE_dString(VGAScreen, JE_fontCenter(buffer, SMALL_FONT_SHAPES), 160, buffer, SMALL_FONT_SHAPES);
2721
fade_palette(colors, 50, 0, 255);
2724
wait_input(true, true, true);
2736
// back to titlescreen
2746
tempX = atoi(strnztcpy(buffer, s + 3, 3));
2749
memcpy(colors, palettes[pcxpal[tempX-1 - 900]], sizeof(colors));
2750
JE_clr256(VGAScreen);
2752
fade_palette(colors, 1, 0, 255);
2757
JE_loadPCX("tshp2.pcx");
2759
JE_loadPic(VGAScreen, tempX, false);
2762
fade_palette(colors, 10, 0, 255);
2770
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h);
2772
tempX = atoi(strnztcpy(buffer, s + 3, 3));
2773
JE_loadPic(VGAScreen, tempX, false);
2774
memcpy(pic_buffer, VGAScreen->pixels, sizeof(pic_buffer));
2776
service_SDL_events(true);
2778
for (int z = 0; z <= 199; z++)
2782
vga = VGAScreen->pixels;
2783
vga2 = VGAScreen2->pixels;
2784
pic = pic_buffer + (199 - z) * 320;
2786
setjasondelay(1); /* attempting to emulate JE_waitRetrace();*/
2788
for (y = 0; y <= 199; y++)
2792
memcpy(vga, pic, 320);
2797
memcpy(vga, vga2, VGAScreen->pitch);
2798
vga2 += VGAScreen->pitch;
2800
vga += VGAScreen->pitch;
2810
service_wait_delay();
2814
memcpy(VGAScreen->pixels, pic_buffer, sizeof(pic_buffer));
2822
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h);
2824
tempX = atoi(strnztcpy(buffer, s + 3, 3));
2825
JE_loadPic(VGAScreen, tempX, false);
2826
memcpy(pic_buffer, VGAScreen->pixels, sizeof(pic_buffer));
2828
service_SDL_events(true);
2829
for (int z = 0; z <= 199; z++)
2833
vga = VGAScreen->pixels;
2834
vga2 = VGAScreen2->pixels;
2837
setjasondelay(1); /* attempting to emulate JE_waitRetrace();*/
2839
for (y = 0; y < 199; y++)
2843
memcpy(vga, vga2, VGAScreen->pitch);
2844
vga2 += VGAScreen->pitch;
2848
memcpy(vga, pic, 320);
2851
vga += VGAScreen->pitch;
2861
service_wait_delay();
2865
memcpy(VGAScreen->pixels, pic_buffer, sizeof(pic_buffer));
2873
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h);
2875
tempX = atoi(strnztcpy(buffer, s + 3, 3));
2876
JE_loadPic(VGAScreen, tempX, false);
2877
memcpy(pic_buffer, VGAScreen->pixels, sizeof(pic_buffer));
2879
service_SDL_events(true);
2881
for (int z = 0; z <= 318; z++)
2885
vga = VGAScreen->pixels;
2886
vga2 = VGAScreen2->pixels;
2889
setjasondelay(1); /* attempting to emulate JE_waitRetrace();*/
2891
for(y = 0; y < 200; y++)
2893
memcpy(vga, vga2 + z, 319 - z);
2895
vga2 += VGAScreen2->pitch;
2896
memcpy(vga, pic, z + 1);
2908
service_wait_delay();
2912
memcpy(VGAScreen->pixels, pic_buffer, sizeof(pic_buffer));
2921
JE_clr256(VGAScreen);
2923
memcpy(colors, palettes[7], sizeof(colors));
2924
set_palette(colors, 0, 255);
2939
JE_clr256(VGAScreen);
2949
warningCol = 14 * 16 + 5;
2950
warningColChange = 1;
2951
warningSoundDelay = 0;
2952
levelWarningDisplay = (s[2] == 'y');
2953
levelWarningLines = 0;
2954
frameCountMax = atoi(strnztcpy(buffer, s + 4, 2));
2956
warningRed = frameCountMax / 10;
2957
frameCountMax = frameCountMax % 10;
2961
read_encrypted_pascal_string(s, sizeof(s), ep_f);
2965
strcpy(levelWarningText[levelWarningLines], s);
2966
levelWarningLines++;
2969
while (!(s[0] == '#'));
2978
if (initialDifficulty < 3)
2980
mainLevel = atoi(strnztcpy(buffer, s + 4, 3));
2986
if (initialDifficulty > 2)
2988
read_encrypted_pascal_string(s, sizeof(s), ep_f);
3004
temp = atoi(strnztcpy(buffer, s + 3, 3));
3005
play_song(temp - 1);
3010
/* TODO: Timed Battle ]T[ 43 44 45 46 47 */
3011
printf("]T[ 43 44 45 46 47 handle timed battle!");
3015
/* TODO: Timed Battle end */
3016
printf("handle timed battle end flag!");
3022
} while (!(loadLevelOk || jumpSection));
3027
} while (!loadLevelOk);
3035
FILE *level_f = dir_fopen_die(data_dir(), levelFile, "rb");
3036
fseek(level_f, lvlPos[(lvlFileNum-1) * 2], SEEK_SET);
3038
fgetc(level_f); // char_mapFile
3039
JE_char char_shapeFile = fgetc(level_f);
3040
efread(&mapX, sizeof(JE_word), 1, level_f);
3041
efread(&mapX2, sizeof(JE_word), 1, level_f);
3042
efread(&mapX3, sizeof(JE_word), 1, level_f);
3044
efread(&levelEnemyMax, sizeof(JE_word), 1, level_f);
3045
for (x = 0; x < levelEnemyMax; x++)
3047
efread(&levelEnemy[x], sizeof(JE_word), 1, level_f);
3050
efread(&maxEvent, sizeof(JE_word), 1, level_f);
3051
for (x = 0; x < maxEvent; x++)
3053
efread(&eventRec[x].eventtime, sizeof(JE_word), 1, level_f);
3054
efread(&eventRec[x].eventtype, sizeof(JE_byte), 1, level_f);
3055
efread(&eventRec[x].eventdat, sizeof(JE_integer), 1, level_f);
3056
efread(&eventRec[x].eventdat2, sizeof(JE_integer), 1, level_f);
3057
efread(&eventRec[x].eventdat3, sizeof(JE_shortint), 1, level_f);
3058
efread(&eventRec[x].eventdat5, sizeof(JE_shortint), 1, level_f);
3059
efread(&eventRec[x].eventdat6, sizeof(JE_shortint), 1, level_f);
3060
efread(&eventRec[x].eventdat4, sizeof(JE_byte), 1, level_f);
3062
eventRec[x].eventtime = 65500; /*Not needed but just in case*/
3064
/*debuginfo('Level loaded.');*/
3066
/*debuginfo('Loading Map');*/
3068
/* MAP SHAPE LOOKUP TABLE - Each map is directly after level */
3069
efread(mapSh, sizeof(JE_word), sizeof(mapSh) / sizeof(JE_word), level_f);
3070
for (temp = 0; temp < 3; temp++)
3072
for (temp2 = 0; temp2 < 128; temp2++)
3074
mapSh[temp][temp2] = SDL_Swap16(mapSh[temp][temp2]);
3078
/* Read Shapes.DAT */
3079
sprintf(tempStr, "shapes%c.dat", tolower((unsigned char)char_shapeFile));
3080
FILE *shpFile = dir_fopen_die(data_dir(), tempStr, "rb");
3082
for (int z = 0; z < 600; z++)
3084
JE_boolean shapeBlank = fgetc(shpFile);
3087
memset(shape, 0, sizeof(shape));
3089
efread(shape, sizeof(JE_byte), sizeof(shape), shpFile);
3092
for (int x = 0; x <= 71; ++x)
3094
if (mapSh[0][x] == z+1)
3096
memcpy(megaData1.shapes[x].sh, shape, sizeof(JE_DanCShape));
3098
ref[0][x] = (JE_byte *)megaData1.shapes[x].sh;
3103
for (int x = 0; x <= 71; ++x)
3105
if (mapSh[1][x] == z+1)
3107
if (x != 71 && !shapeBlank)
3109
memcpy(megaData2.shapes[x].sh, shape, sizeof(JE_DanCShape));
3112
for (yy = 0; yy < (24 * 28) >> 1; yy++)
3116
megaData2.shapes[x].fill = y;
3117
ref[1][x] = (JE_byte *)megaData2.shapes[x].sh;
3127
for (int x = 0; x <= 71; ++x)
3129
if (mapSh[2][x] == z+1)
3131
if (x < 70 && !shapeBlank)
3133
memcpy(megaData3.shapes[x].sh, shape, sizeof(JE_DanCShape));
3136
for (yy = 0; yy < (24 * 28) >> 1; yy++)
3140
megaData3.shapes[x].fill = y;
3141
ref[2][x] = (JE_byte *)megaData3.shapes[x].sh;
3153
efread(mapBuf, sizeof(JE_byte), 14 * 300, level_f);
3154
bufLoc = 0; /* MAP NUMBER 1 */
3155
for (y = 0; y < 300; y++)
3157
for (x = 0; x < 14; x++)
3159
megaData1.mainmap[y][x] = ref[0][mapBuf[bufLoc]];
3164
efread(mapBuf, sizeof(JE_byte), 14 * 600, level_f);
3165
bufLoc = 0; /* MAP NUMBER 2 */
3166
for (y = 0; y < 600; y++)
3168
for (x = 0; x < 14; x++)
3170
megaData2.mainmap[y][x] = ref[1][mapBuf[bufLoc]];
3175
efread(mapBuf, sizeof(JE_byte), 15 * 600, level_f);
3176
bufLoc = 0; /* MAP NUMBER 3 */
3177
for (y = 0; y < 600; y++)
3179
for (x = 0; x < 15; x++)
3181
megaData3.mainmap[y][x] = ref[2][mapBuf[bufLoc]];
3188
/* Note: The map data is automatically calculated with the correct mapsh
3189
value and then the pointer is calculated using the formula (MAPSH-1)*168.
3190
Then, we'll automatically add S2Ofs to get the exact offset location into
3191
the shape table! This makes it VERY FAST! */
3193
/*debuginfo('Map file done.');*/
3194
/* End of find loop for LEVEL??.DAT */
3197
bool JE_titleScreen( JE_boolean animate )
3202
const int menunum = 6;
3204
const int menunum = 7;
3207
unsigned int arcade_code_i[SA_ENGAGE] = { 0 };
3209
JE_word waitForDemo;
3211
JE_boolean redraw = true,
3214
JE_word temp; /* JE_byte temp; from varz.h will overflow in for loop */
3217
stopped_demo = false;
3223
jumpSection = false;
3228
JE_loadPic(VGAScreen, 2, false);
3229
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h);
3230
JE_dString(VGAScreen, JE_fontCenter("Waiting for other player.", SMALL_FONT_SHAPES), 140, "Waiting for other player.", SMALL_FONT_SHAPES);
3232
fade_palette(colors, 10, 0, 255);
3236
twoPlayerMode = true;
3237
if (thisPlayerNum == 1)
3241
if (select_episode() && select_difficulty())
3243
initialDifficulty = difficultyLevel;
3245
difficultyLevel++; /*Make it one step harder for 2-player mode!*/
3247
network_prepare(PACKET_DETAILS);
3248
SDLNet_Write16(episodeNum, &packet_out_temp->data[4]);
3249
SDLNet_Write16(difficultyLevel, &packet_out_temp->data[6]);
3250
network_send(8); // PACKET_DETAILS
3254
network_prepare(PACKET_QUIT);
3255
network_send(4); // PACKET QUIT
3257
network_tyrian_halt(0, true);
3262
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h);
3263
JE_dString(VGAScreen, JE_fontCenter(networkText[4-1], SMALL_FONT_SHAPES), 140, networkText[4-1], SMALL_FONT_SHAPES);
3266
// until opponent sends details packet
3269
service_SDL_events(false);
3272
if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_DETAILS)
3281
JE_initEpisode(SDLNet_Read16(&packet_in[0]->data[4]));
3282
difficultyLevel = SDLNet_Read16(&packet_in[0]->data[6]);
3283
initialDifficulty = difficultyLevel - 1;
3289
for (uint i = 0; i < COUNTOF(player); ++i)
3292
player[0].items.ship = 11; // Silver Ship
3294
while (!network_is_sync())
3296
service_SDL_events(false);
3308
defaultBrightness = -3;
3310
/* Animate instead of quickly fading in */
3313
play_song(SONG_TITLE);
3325
JE_loadPic(VGAScreen, 4, false);
3327
draw_font_hv_shadow(VGAScreen, 2, 192, opentyrian_version, small_font, left_aligned, 15, 0, false, 1);
3329
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h);
3331
temp = moveTyrianLogoUp ? 62 : 4;
3333
blit_sprite(VGAScreenSeg, 11, temp, PLANET_SHAPES, 146); // tyrian logo
3337
fade_palette(colors, 10, 0, 255 - 16);
3339
if (moveTyrianLogoUp)
3341
for (temp = 61; temp >= 4; temp -= 2)
3345
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h);
3347
blit_sprite(VGAScreenSeg, 11, temp, PLANET_SHAPES, 146); // tyrian logo
3351
service_wait_delay();
3353
moveTyrianLogoUp = false;
3356
strcpy(menuText[4], opentyrian_str); // OpenTyrian override
3358
/* Draw Menu Text on Screen */
3359
for (int i = 0; i < menunum; ++i)
3361
int x = VGAScreen->w / 2, y = 104 + i * 13;
3363
draw_font_hv(VGAScreen, x - 1, y - 1, menuText[i], normal_font, centered, 15, -10);
3364
draw_font_hv(VGAScreen, x + 1, y + 1, menuText[i], normal_font, centered, 15, -10);
3365
draw_font_hv(VGAScreen, x + 1, y - 1, menuText[i], normal_font, centered, 15, -10);
3366
draw_font_hv(VGAScreen, x - 1, y + 1, menuText[i], normal_font, centered, 15, -10);
3367
draw_font_hv(VGAScreen, x, y, menuText[i], normal_font, centered, 15, -3);
3372
fade_palette(colors, 20, 255 - 16 + 1, 255); // fade in menu items
3374
memcpy(VGAScreen2->pixels, VGAScreen->pixels, VGAScreen2->pitch * VGAScreen2->h);
3378
memcpy(VGAScreen->pixels, VGAScreen2->pixels, VGAScreen->pitch * VGAScreen->h);
3380
// highlight selected menu item
3381
draw_font_hv(VGAScreen, VGAScreen->w / 2, 104 + menu * 13, menuText[menu], normal_font, centered, 15, -1);
3392
JE_textMenuWait(&waitForDemo, false);
3394
if (waitForDemo == 1)
3399
switch (lastkey_sym)
3406
JE_playSampleNum(S_CURSOR);
3409
if (menu == menunum-1)
3413
JE_playSampleNum(S_CURSOR);
3420
for (unsigned int i = 0; i < SA_ENGAGE; i++)
3422
if (toupper(lastkey_char) == specialName[i][arcade_code_i[i]])
3425
arcade_code_i[i] = 0;
3427
if (arcade_code_i[i] > 0 && arcade_code_i[i] == strlen(specialName[i]))
3429
if (i+1 == SA_DESTRUCT)
3431
loadDestruct = true;
3433
else if (i+1 == SA_ENGAGE)
3437
JE_playSampleNum(V_DATA_CUBE);
3440
initialDifficulty = keysactive[SDLK_SCROLLOCK] ? 6 : 8;
3442
JE_clr256(VGAScreen);
3443
JE_outText(VGAScreen, 10, 10, "Cheat codes have been disabled.", 15, 4);
3444
if (initialDifficulty == 8)
3445
JE_outText(VGAScreen, 10, 20, "Difficulty level has been set to Lord of Game.", 15, 4);
3447
JE_outText(VGAScreen, 10, 20, "Difficulty level has been set to Suicide.", 15, 4);
3448
JE_outText(VGAScreen, 10, 30, "It is imperative that you discover the special codes.", 15, 4);
3449
if (initialDifficulty == 8)
3450
JE_outText(VGAScreen, 10, 40, "(Next time, for an easier challenge hold down SCROLL LOCK.)", 15, 4);
3451
JE_outText(VGAScreen, 10, 60, "Prepare to play...", 15, 4);
3453
char buf[10+1+15+1];
3454
snprintf(buf, sizeof(buf), "%s %s", miscTextB[4], pName[0]);
3455
JE_dString(VGAScreen, JE_fontCenter(buf, FONT_SHAPES), 110, buf, FONT_SHAPES);
3458
JE_playSampleNum(V_DANGER);
3461
wait_noinput(true, true, true);
3462
wait_input(true, true, true);
3465
constantDie = false;
3467
onePlayerAction = true;
3469
difficultyLevel = initialDifficulty;
3473
player[0].items.ship = 13; // The Stalker 21.126
3474
player[0].items.weapon[FRONT_WEAPON].id = 39; // Atomic RailGun
3478
player[0].items.ship = SAShip[i];
3481
if (select_episode() && select_difficulty())
3483
/* Start special mode! */
3485
JE_loadPic(VGAScreen, 1, false);
3486
JE_clr256(VGAScreen);
3487
JE_dString(VGAScreen, JE_fontCenter(superShips[0], FONT_SHAPES), 30, superShips[0], FONT_SHAPES);
3488
JE_dString(VGAScreen, JE_fontCenter(superShips[i+1], SMALL_FONT_SHAPES), 100, superShips[i+1], SMALL_FONT_SHAPES);
3489
tempW = ships[player[0].items.ship].shipgraphic;
3491
blit_sprite2x2(VGAScreen, 148, 70, shapes9, tempW);
3494
fade_palette(colors, 50, 0, 255);
3496
wait_input(true, true, true);
3498
twoPlayerMode = false;
3499
onePlayerAction = true;
3500
superArcadeMode = i+1;
3502
initialDifficulty = ++difficultyLevel;
3506
player[0].items.weapon[FRONT_WEAPON].id = SAWeapon[i][0];
3507
player[0].items.special = SASpecialWeapon[i];
3508
if (superArcadeMode == SA_NORTSHIPZ)
3510
for (uint i = 0; i < COUNTOF(player[0].items.sidekick); ++i)
3511
player[0].items.sidekick[i] = 24; // Companion Ship Quicksilver
3523
lastkey_char = '\0';
3527
switch (lastkey_sym)
3533
JE_playSampleNum(S_SELECT);
3536
case 0: /* New game */
3539
if (select_gameplay())
3541
if (select_episode() && select_difficulty())
3544
initialDifficulty = difficultyLevel;
3546
if (onePlayerAction)
3550
player[0].items.ship = 8; // Stalker
3552
else if (twoPlayerMode)
3554
for (uint i = 0; i < COUNTOF(player); ++i)
3557
player[0].items.ship = 11; // Silver Ship
3566
player[0].cash = 1000000;
3570
// allows player to smuggle arcade/super-arcade ships into full game
3572
ulong initial_cash[] = { 10000, 15000, 20000, 30000, 35000 };
3574
assert(episodeNum >= 1 && episodeNum <= EPISODE_AVAILABLE);
3575
player[0].cash = initial_cash[episodeNum-1];
3580
case 1: /* Load game */
3584
case 2: /* High scores */
3585
JE_highScoreScreen();
3588
case 3: /* Instructions */
3592
case 4: /* Ordering info, now OpenTyrian menu */
3616
while (!(quit || gameLoaded || jumpSection || play_demo || loadDestruct));
3625
void intro_logos( void )
3627
SDL_FillRect(VGAScreen, NULL, 0);
3631
JE_loadPic(VGAScreen, 10, false);
3634
fade_palette(colors, 50, 0, 255);
3637
wait_delayorinput(true, true, true);
3641
JE_loadPic(VGAScreen, 12, false);
3644
fade_palette(colors, 10, 0, 255);
3647
wait_delayorinput(true, true, true);
3652
void JE_readTextSync( void )
3654
return; // this function seems to be unnecessary
3656
JE_clr256(VGAScreen);
3658
JE_loadPic(VGAScreen, 1, true);
3660
JE_barShade(VGAScreen, 3, 3, 316, 196);
3661
JE_barShade(VGAScreen, 1, 1, 318, 198);
3662
JE_dString(VGAScreen, 10, 160, "Waiting for other player.", SMALL_FONT_SHAPES);
3675
} while (0 /* TODO: NETWORK */);
3679
void JE_displayText( void )
3681
/* Display Warning Text */
3687
for (temp = 0; temp < levelWarningLines; temp++)
3691
JE_outCharGlow(10, tempY, levelWarningText[temp]);
3701
if (frameCountMax != 0)
3708
textGlowFont = TINY_FONT;
3715
JE_outCharGlow(JE_fontCenter(miscText[4], TINY_FONT), tempW, miscText[4]);
3719
if (levelWarningDisplay)
3721
JE_updateWarning(VGAScreen);
3726
NETWORK_KEEP_ALIVE();
3730
} while (!(JE_anyButton() || (frameCountMax == 0 && temp == 1) || ESCPressed));
3731
levelWarningDisplay = false;
3734
Sint16 JE_newEnemy( int enemyOffset, Uint16 eDatI, Sint16 uniqueShapeTableI )
3736
for (int i = enemyOffset; i < enemyOffset + 25; ++i)
3738
if (enemyAvail[i] == 1)
3740
enemyAvail[i] = JE_makeEnemy(&enemy[i], eDatI, uniqueShapeTableI);
3748
uint JE_makeEnemy( struct JE_SingleEnemyType *enemy, Uint16 eDatI, Sint16 uniqueShapeTableI )
3752
JE_byte shapeTableI;
3754
if (superArcadeMode != SA_NONE && eDatI == 534)
3757
enemyShapeTables[5-1] = 21; /*Coins&Gems*/
3758
enemyShapeTables[6-1] = 26; /*Two-Player Stuff*/
3760
if (uniqueShapeTableI > 0)
3762
shapeTableI = uniqueShapeTableI;
3766
shapeTableI = enemyDat[eDatI].shapebank;
3769
Sprite2_array *sprite2s = NULL;
3770
for (uint i = 0; i < 6; ++i)
3771
if (shapeTableI == enemyShapeTables[i])
3772
sprite2s = &eShapes[i];
3774
if (sprite2s != NULL)
3775
enemy->sprite2s = sprite2s;
3777
// maintain buggy Tyrian behavior (use shape table value from previous enemy that occupied this index in the enemy array)
3778
fprintf(stderr, "warning: ignoring sprite from unloaded shape table %d\n", shapeTableI);
3780
enemy->enemydatofs = &enemyDat[eDatI];
3782
enemy->mapoffset = 0;
3784
for (uint i = 0; i < 3; ++i)
3786
enemy->eshotmultipos[i] = 0;
3789
enemy->enemyground = (enemyDat[eDatI].explosiontype & 1) == 0;
3790
enemy->explonum = enemyDat[eDatI].explosiontype >> 1;
3792
enemy->launchfreq = enemyDat[eDatI].elaunchfreq;
3793
enemy->launchwait = enemyDat[eDatI].elaunchfreq;
3794
enemy->launchtype = enemyDat[eDatI].elaunchtype % 1000;
3795
enemy->launchspecial = enemyDat[eDatI].elaunchtype / 1000;
3797
enemy->xaccel = enemyDat[eDatI].xaccel;
3798
enemy->yaccel = enemyDat[eDatI].yaccel;
3800
enemy->xminbounce = -10000;
3801
enemy->xmaxbounce = 10000;
3802
enemy->yminbounce = -10000;
3803
enemy->ymaxbounce = 10000;
3804
/*Far enough away to be impossible to reach*/
3806
for (uint i = 0; i < 3; ++i)
3808
enemy->tur[i] = enemyDat[eDatI].tur[i];
3811
enemy->ani = enemyDat[eDatI].ani;
3814
switch (enemyDat[eDatI].animate)
3817
enemy->enemycycle = 1;
3818
enemy->aniactive = 0;
3820
enemy->aniwhenfire = 0;
3823
enemy->enemycycle = 0;
3824
enemy->aniactive = 1;
3826
enemy->aniwhenfire = 0;
3829
enemy->enemycycle = 1;
3830
enemy->aniactive = 2;
3831
enemy->animax = enemy->ani;
3832
enemy->aniwhenfire = 2;
3836
if (enemyDat[eDatI].startxc != 0)
3837
enemy->ex = enemyDat[eDatI].startx + (mt_rand() % (enemyDat[eDatI].startxc * 2)) - enemyDat[eDatI].startxc + 1;
3839
enemy->ex = enemyDat[eDatI].startx + 1;
3841
if (enemyDat[eDatI].startyc != 0)
3842
enemy->ey = enemyDat[eDatI].starty + (mt_rand() % (enemyDat[eDatI].startyc * 2)) - enemyDat[eDatI].startyc + 1;
3844
enemy->ey = enemyDat[eDatI].starty + 1;
3846
enemy->exc = enemyDat[eDatI].xmove;
3847
enemy->eyc = enemyDat[eDatI].ymove;
3848
enemy->excc = enemyDat[eDatI].xcaccel;
3849
enemy->eycc = enemyDat[eDatI].ycaccel;
3850
enemy->exccw = abs(enemy->excc);
3851
enemy->exccwmax = enemy->exccw;
3852
enemy->eyccw = abs(enemy->eycc);
3853
enemy->eyccwmax = enemy->eyccw;
3854
enemy->exccadd = (enemy->excc > 0) ? 1 : -1;
3855
enemy->eyccadd = (enemy->eycc > 0) ? 1 : -1;
3856
enemy->special = false;
3859
if (enemyDat[eDatI].xrev == 0)
3861
else if (enemyDat[eDatI].xrev == -99)
3864
enemy->exrev = enemyDat[eDatI].xrev;
3866
if (enemyDat[eDatI].yrev == 0)
3868
else if (enemyDat[eDatI].yrev == -99)
3871
enemy->eyrev = enemyDat[eDatI].yrev;
3873
enemy->exca = (enemy->xaccel > 0) ? 1 : -1;
3874
enemy->eyca = (enemy->yaccel > 0) ? 1 : -1;
3876
enemy->enemytype = eDatI;
3878
for (uint i = 0; i < 3; ++i)
3880
if (enemy->tur[i] == 252)
3881
enemy->eshotwait[i] = 1;
3882
else if (enemy->tur[i] > 0)
3883
enemy->eshotwait[i] = 20;
3885
enemy->eshotwait[i] = 255;
3887
for (uint i = 0; i < 20; ++i)
3888
enemy->egr[i] = enemyDat[eDatI].egraphic[i];
3889
enemy->size = enemyDat[eDatI].esize;
3891
enemy->edamaged = enemyDat[eDatI].dani < 0;
3892
enemy->enemydie = enemyDat[eDatI].eenemydie;
3894
enemy->freq[1-1] = enemyDat[eDatI].freq[1-1];
3895
enemy->freq[2-1] = enemyDat[eDatI].freq[2-1];
3896
enemy->freq[3-1] = enemyDat[eDatI].freq[3-1];
3898
enemy->edani = enemyDat[eDatI].dani;
3899
enemy->edgr = enemyDat[eDatI].dgr;
3900
enemy->edlevel = enemyDat[eDatI].dlevel;
3902
enemy->fixedmovey = 0;
3904
enemy->filter = 0x00;
3907
if (enemyDat[eDatI].value > 1 && enemyDat[eDatI].value < 10000)
3909
switch (difficultyLevel)
3913
tempValue = enemyDat[eDatI].value * 0.75f;
3917
tempValue = enemyDat[eDatI].value;
3920
tempValue = enemyDat[eDatI].value * 1.125f;
3923
tempValue = enemyDat[eDatI].value * 1.5f;
3926
tempValue = enemyDat[eDatI].value * 2;
3929
tempValue = enemyDat[eDatI].value * 2.5f;
3933
tempValue = enemyDat[eDatI].value * 4;
3937
tempValue = enemyDat[eDatI].value * 8;
3940
if (tempValue > 10000)
3942
enemy->evalue = tempValue;
3946
enemy->evalue = enemyDat[eDatI].value;
3950
if (enemyDat[eDatI].armor > 0)
3952
if (enemyDat[eDatI].armor != 255)
3954
switch (difficultyLevel)
3958
tempArmor = enemyDat[eDatI].armor * 0.5f + 1;
3961
tempArmor = enemyDat[eDatI].armor * 0.75f + 1;
3964
tempArmor = enemyDat[eDatI].armor;
3967
tempArmor = enemyDat[eDatI].armor * 1.2f;
3970
tempArmor = enemyDat[eDatI].armor * 1.5f;
3973
tempArmor = enemyDat[eDatI].armor * 1.8f;
3976
tempArmor = enemyDat[eDatI].armor * 2;
3979
tempArmor = enemyDat[eDatI].armor * 3;
3982
tempArmor = enemyDat[eDatI].armor * 4;
3986
tempArmor = enemyDat[eDatI].armor * 8;
3990
if (tempArmor > 254)
4000
enemy->armorleft = tempArmor;
4003
enemy->scoreitem = false;
4008
enemy->armorleft = 255;
4009
if (enemy->evalue != 0)
4010
enemy->scoreitem = true;
4013
if (!enemy->scoreitem)
4015
totalEnemy++; /*Destruction ratio*/
4018
/* indicates what to set ENEMYAVAIL to */
4022
void JE_createNewEventEnemy( JE_byte enemyTypeOfs, JE_word enemyOffset, Sint16 uniqueShapeTableI )
4028
for(i = enemyOffset; i < enemyOffset + 25; i++)
4030
if (enemyAvail[i] == 1)
4042
tempW = eventRec[eventLoc-1].eventdat + enemyTypeOfs;
4044
enemyAvail[b-1] = JE_makeEnemy(&enemy[b-1], tempW, uniqueShapeTableI);
4046
if (eventRec[eventLoc-1].eventdat2 != -99)
4048
switch (enemyOffset)
4051
enemy[b-1].ex = eventRec[eventLoc-1].eventdat2 - (mapX - 1) * 24;
4052
enemy[b-1].ey -= backMove2;
4056
enemy[b-1].ex = eventRec[eventLoc-1].eventdat2 - (mapX - 1) * 24 - 12;
4057
enemy[b-1].ey -= backMove;
4062
enemy[b-1].ex = eventRec[eventLoc-1].eventdat2 - (mapX - 1) * 24 - 12;
4064
enemy[b-1].ex = eventRec[eventLoc-1].eventdat2 - mapX3 * 24 - 24 * 2 + 6;
4066
enemy[b-1].ey -= backMove3;
4074
enemy[b-1].ey = -28;
4075
if (background3x1b && enemyOffset == 50)
4081
if (smallEnemyAdjust && enemy[b-1].size == 0)
4083
enemy[b-1].ex -= 10;
4087
enemy[b-1].ey += eventRec[eventLoc-1].eventdat5;
4088
enemy[b-1].eyc += eventRec[eventLoc-1].eventdat3;
4089
enemy[b-1].linknum = eventRec[eventLoc-1].eventdat4;
4090
enemy[b-1].fixedmovey = eventRec[eventLoc-1].eventdat6;
4093
void JE_eventJump( JE_word jump )
4103
returnLoc = curLoc + 1;
4111
while (!(eventRec[tempW-1].eventtime >= curLoc));
4112
eventLoc = tempW - 1;
4115
bool JE_searchFor/*enemy*/( JE_byte PLType, JE_byte* out_index )
4119
for (int i = 0; i < 100; i++)
4121
if (enemyAvail[i] == 0 && enemy[i].linknum == PLType)
4126
enemy[i].evalue += enemy[i].evalue;
4131
if (found_id != -1) {
4133
*out_index = found_id;
4141
void JE_eventSystem( void )
4143
switch (eventRec[eventLoc-1].eventtype)
4146
starfield_speed = eventRec[eventLoc-1].eventdat;
4155
backMove = eventRec[eventLoc-1].eventdat;
4156
backMove2 = eventRec[eventLoc-1].eventdat2;
4159
explodeMove = backMove2;
4161
explodeMove = backMove;
4163
backMove3 = eventRec[eventLoc-1].eventdat3;
4166
stopBackgroundNum = 0;
4180
stopBackgrounds = true;
4181
switch (eventRec[eventLoc-1].eventdat)
4185
stopBackgroundNum = 1;
4188
stopBackgroundNum = 2;
4191
stopBackgroundNum = 3;
4196
case 5: // load enemy shape banks
4198
Uint8 newEnemyShapeTables[] =
4200
eventRec[eventLoc-1].eventdat > 0 ? eventRec[eventLoc-1].eventdat : 0,
4201
eventRec[eventLoc-1].eventdat2 > 0 ? eventRec[eventLoc-1].eventdat2 : 0,
4202
eventRec[eventLoc-1].eventdat3 > 0 ? eventRec[eventLoc-1].eventdat3 : 0,
4203
eventRec[eventLoc-1].eventdat4 > 0 ? eventRec[eventLoc-1].eventdat4 : 0,
4206
for (unsigned int i = 0; i < COUNTOF(newEnemyShapeTables); ++i)
4208
if (enemyShapeTables[i] != newEnemyShapeTables[i])
4210
if (newEnemyShapeTables[i] > 0)
4212
assert(newEnemyShapeTables[i] <= COUNTOF(shapeFile));
4213
JE_loadCompShapes(&eShapes[i], shapeFile[newEnemyShapeTables[i] - 1]);
4216
free_sprite2s(&eShapes[i]);
4218
enemyShapeTables[i] = newEnemyShapeTables[i];
4224
case 6: /* Ground Enemy */
4225
JE_createNewEventEnemy(0, 25, 0);
4228
case 7: /* Top Enemy */
4229
JE_createNewEventEnemy(0, 50, 0);
4240
case 10: /* Ground Enemy 2 */
4241
JE_createNewEventEnemy(0, 75, 0);
4245
if (allPlayersGone || eventRec[eventLoc-1].eventdat == 1)
4246
reallyEndLevel = true;
4250
readyToEndLevel = false;
4256
case 12: /* Custom 4x4 Ground Enemy */
4259
switch (eventRec[eventLoc-1].eventdat6)
4275
eventRec[eventLoc-1].eventdat6 = 0; /* We use EVENTDAT6 for the background */
4276
JE_createNewEventEnemy(0, temp, 0);
4277
JE_createNewEventEnemy(1, temp, 0);
4278
enemy[b-1].ex += 24;
4279
JE_createNewEventEnemy(2, temp, 0);
4280
enemy[b-1].ey -= 28;
4281
JE_createNewEventEnemy(3, temp, 0);
4282
enemy[b-1].ex += 24;
4283
enemy[b-1].ey -= 28;
4287
enemiesActive = false;
4291
enemiesActive = true;
4294
case 15: /* Sky Enemy */
4295
JE_createNewEventEnemy(0, 0, 0);
4299
if (eventRec[eventLoc-1].eventdat > 9)
4301
fprintf(stderr, "warning: event 16: bad event data\n");
4305
JE_drawTextWindow(outputs[eventRec[eventLoc-1].eventdat-1]);
4306
soundQueue[3] = windowTextSamples[eventRec[eventLoc-1].eventdat-1];
4310
case 17: /* Ground Bottom */
4311
JE_createNewEventEnemy(0, 25, 0);
4314
enemy[b-1].ey = 190 + eventRec[eventLoc-1].eventdat5;
4318
case 18: /* Sky Enemy on Bottom */
4319
JE_createNewEventEnemy(0, 0, 0);
4322
enemy[b-1].ey = 190 + eventRec[eventLoc-1].eventdat5;
4326
case 19: /* Enemy Global Move */
4328
int initial_i, max_i;
4331
if (eventRec[eventLoc-1].eventdat3 > 79 && eventRec[eventLoc-1].eventdat3 < 90)
4335
all_enemies = false;
4336
eventRec[eventLoc-1].eventdat4 = newPL[eventRec[eventLoc-1].eventdat3 - 80];
4340
switch (eventRec[eventLoc-1].eventdat3)
4345
all_enemies = false;
4370
for (int i = initial_i; i < max_i; i++)
4372
if (all_enemies || enemy[i].linknum == eventRec[eventLoc-1].eventdat4)
4374
if (eventRec[eventLoc-1].eventdat != -99)
4375
enemy[i].exc = eventRec[eventLoc-1].eventdat;
4377
if (eventRec[eventLoc-1].eventdat2 != -99)
4378
enemy[i].eyc = eventRec[eventLoc-1].eventdat2;
4380
if (eventRec[eventLoc-1].eventdat6 != 0)
4381
enemy[i].fixedmovey = eventRec[eventLoc-1].eventdat6;
4383
if (eventRec[eventLoc-1].eventdat6 == -99)
4384
enemy[i].fixedmovey = 0;
4386
if (eventRec[eventLoc-1].eventdat5 > 0)
4387
enemy[i].enemycycle = eventRec[eventLoc-1].eventdat5;
4393
case 20: /* Enemy Global Accel */
4394
if (eventRec[eventLoc-1].eventdat3 > 79 && eventRec[eventLoc-1].eventdat3 < 90)
4395
eventRec[eventLoc-1].eventdat4 = newPL[eventRec[eventLoc-1].eventdat3 - 80];
4397
for (temp = 0; temp < 100; temp++)
4399
if (enemyAvail[temp] != 1
4400
&& (enemy[temp].linknum == eventRec[eventLoc-1].eventdat4 || eventRec[eventLoc-1].eventdat4 == 0))
4402
if (eventRec[eventLoc-1].eventdat != -99)
4404
enemy[temp].excc = eventRec[eventLoc-1].eventdat;
4405
enemy[temp].exccw = abs(eventRec[eventLoc-1].eventdat);
4406
enemy[temp].exccwmax = abs(eventRec[eventLoc-1].eventdat);
4407
if (eventRec[eventLoc-1].eventdat > 0)
4408
enemy[temp].exccadd = 1;
4410
enemy[temp].exccadd = -1;
4413
if (eventRec[eventLoc-1].eventdat2 != -99)
4415
enemy[temp].eycc = eventRec[eventLoc-1].eventdat2;
4416
enemy[temp].eyccw = abs(eventRec[eventLoc-1].eventdat2);
4417
enemy[temp].eyccwmax = abs(eventRec[eventLoc-1].eventdat2);
4418
if (eventRec[eventLoc-1].eventdat2 > 0)
4419
enemy[temp].eyccadd = 1;
4421
enemy[temp].eyccadd = -1;
4424
if (eventRec[eventLoc-1].eventdat5 > 0)
4426
enemy[temp].enemycycle = eventRec[eventLoc-1].eventdat5;
4428
if (eventRec[eventLoc-1].eventdat6 > 0)
4430
enemy[temp].ani = eventRec[eventLoc-1].eventdat6;
4431
enemy[temp].animin = eventRec[eventLoc-1].eventdat5;
4432
enemy[temp].animax = 0;
4433
enemy[temp].aniactive = 1;
4440
background3over = 1;
4444
background3over = 0;
4447
case 23: /* Sky Enemy on Bottom */
4448
JE_createNewEventEnemy(0, 50, 0);
4450
enemy[b-1].ey = 180 + eventRec[eventLoc-1].eventdat5;
4453
case 24: /* Enemy Global Animate */
4454
for (temp = 0; temp < 100; temp++)
4456
if (enemy[temp].linknum == eventRec[eventLoc-1].eventdat4)
4458
enemy[temp].aniactive = 1;
4459
enemy[temp].aniwhenfire = 0;
4460
if (eventRec[eventLoc-1].eventdat2 > 0)
4462
enemy[temp].enemycycle = eventRec[eventLoc-1].eventdat2;
4463
enemy[temp].animin = enemy[temp].enemycycle;
4467
enemy[temp].enemycycle = 0;
4470
if (eventRec[eventLoc-1].eventdat > 0)
4471
enemy[temp].ani = eventRec[eventLoc-1].eventdat;
4473
if (eventRec[eventLoc-1].eventdat3 == 1)
4475
enemy[temp].animax = enemy[temp].ani;
4477
else if (eventRec[eventLoc-1].eventdat3 == 2)
4479
enemy[temp].aniactive = 2;
4480
enemy[temp].animax = enemy[temp].ani;
4481
enemy[temp].aniwhenfire = 2;
4487
case 25: /* Enemy Global Damage change */
4488
for (temp = 0; temp < 100; temp++)
4490
if (eventRec[eventLoc-1].eventdat4 == 0 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4)
4493
enemy[temp].armorleft = roundf(eventRec[eventLoc-1].eventdat * (difficultyLevel / 2));
4495
enemy[temp].armorleft = eventRec[eventLoc-1].eventdat;
4501
smallEnemyAdjust = eventRec[eventLoc-1].eventdat;
4504
case 27: /* Enemy Global AccelRev */
4505
if (eventRec[eventLoc-1].eventdat3 > 79 && eventRec[eventLoc-1].eventdat3 < 90)
4506
eventRec[eventLoc-1].eventdat4 = newPL[eventRec[eventLoc-1].eventdat3 - 80];
4508
for (temp = 0; temp < 100; temp++)
4510
if (eventRec[eventLoc-1].eventdat4 == 0 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4)
4512
if (eventRec[eventLoc-1].eventdat != -99)
4513
enemy[temp].exrev = eventRec[eventLoc-1].eventdat;
4514
if (eventRec[eventLoc-1].eventdat2 != -99)
4515
enemy[temp].eyrev = eventRec[eventLoc-1].eventdat2;
4516
if (eventRec[eventLoc-1].eventdat3 != 0 && eventRec[eventLoc-1].eventdat3 < 17)
4517
enemy[temp].filter = eventRec[eventLoc-1].eventdat3;
4523
topEnemyOver = false;
4527
topEnemyOver = true;
4536
backMove = eventRec[eventLoc-1].eventdat;
4537
backMove2 = eventRec[eventLoc-1].eventdat2;
4538
explodeMove = backMove2;
4539
backMove3 = eventRec[eventLoc-1].eventdat3;
4542
case 31: /* Enemy Fire Override */
4543
for (temp = 0; temp < 100; temp++)
4545
if (eventRec[eventLoc-1].eventdat4 == 99 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4)
4547
enemy[temp].freq[1-1] = eventRec[eventLoc-1].eventdat ;
4548
enemy[temp].freq[2-1] = eventRec[eventLoc-1].eventdat2;
4549
enemy[temp].freq[3-1] = eventRec[eventLoc-1].eventdat3;
4550
for (temp2 = 0; temp2 < 3; temp2++)
4552
enemy[temp].eshotwait[temp2] = 1;
4554
if (enemy[temp].launchtype > 0)
4556
enemy[temp].launchfreq = eventRec[eventLoc-1].eventdat5;
4557
enemy[temp].launchwait = 1;
4563
case 32: // create enemy
4564
JE_createNewEventEnemy(0, 50, 0);
4566
enemy[b-1].ey = 190;
4569
case 33: /* Enemy From other Enemies */
4570
if (!((eventRec[eventLoc-1].eventdat == 512 || eventRec[eventLoc-1].eventdat == 513) && (twoPlayerMode || onePlayerAction || superTyrian)))
4572
if (superArcadeMode != SA_NONE)
4574
if (eventRec[eventLoc-1].eventdat == 534)
4575
eventRec[eventLoc-1].eventdat = 827;
4577
else if (!superTyrian)
4579
const uint lives = *player[0].lives;
4581
if (eventRec[eventLoc-1].eventdat == 533 && (lives == 11 || (mt_rand() % 15) < lives))
4583
// enemy will drop random special weapon
4584
eventRec[eventLoc-1].eventdat = 829 + (mt_rand() % 6);
4587
if (eventRec[eventLoc-1].eventdat == 534 && superTyrian)
4588
eventRec[eventLoc-1].eventdat = 828 + superTyrianSpecials[mt_rand() % 4];
4590
for (temp = 0; temp < 100; temp++)
4592
if (enemy[temp].linknum == eventRec[eventLoc-1].eventdat4)
4593
enemy[temp].enemydie = eventRec[eventLoc-1].eventdat;
4598
case 34: /* Start Music Fade */
4602
tempVolume = tyrMusicVolume;
4606
case 35: /* Play new song */
4609
play_song(eventRec[eventLoc-1].eventdat - 1);
4610
set_volume(tyrMusicVolume, fxVolume);
4616
readyToEndLevel = true;
4620
levelEnemyFrequency = eventRec[eventLoc-1].eventdat;
4624
curLoc = eventRec[eventLoc-1].eventdat;
4625
int new_event_loc = 1;
4626
for (tempW = 0; tempW < maxEvent; tempW++)
4628
if (eventRec[tempW].eventtime <= curLoc)
4630
new_event_loc = tempW+1 - 1;
4633
eventLoc = new_event_loc;
4636
case 39: /* Enemy Global Linknum Change */
4637
for (temp = 0; temp < 100; temp++)
4639
if (enemy[temp].linknum == eventRec[eventLoc-1].eventdat)
4640
enemy[temp].linknum = eventRec[eventLoc-1].eventdat2;
4644
case 40: /* Enemy Continual Damage */
4645
enemyContinualDamage = true;
4649
if (eventRec[eventLoc-1].eventdat == 0)
4651
memset(enemyAvail, 1, sizeof(enemyAvail));
4655
for (x = 0; x <= 24; x++)
4661
background3over = 2;
4665
background2over = eventRec[eventLoc-1].eventdat;
4669
filterActive = (eventRec[eventLoc-1].eventdat > 0);
4670
filterFade = (eventRec[eventLoc-1].eventdat == 2);
4671
levelFilter = eventRec[eventLoc-1].eventdat2;
4672
levelBrightness = eventRec[eventLoc-1].eventdat3;
4673
levelFilterNew = eventRec[eventLoc-1].eventdat4;
4674
levelBrightnessChg = eventRec[eventLoc-1].eventdat5;
4675
filterFadeStart = (eventRec[eventLoc-1].eventdat6 == 0);
4678
case 45: /* arcade-only enemy from other enemies */
4681
const uint lives = *player[0].lives;
4683
if (eventRec[eventLoc-1].eventdat == 533 && (lives == 11 || (mt_rand() % 15) < lives))
4685
eventRec[eventLoc-1].eventdat = 829 + (mt_rand() % 6);
4687
if (twoPlayerMode || onePlayerAction)
4689
for (temp = 0; temp < 100; temp++)
4691
if (enemy[temp].linknum == eventRec[eventLoc-1].eventdat4)
4692
enemy[temp].enemydie = eventRec[eventLoc-1].eventdat;
4698
case 46: // change difficulty
4699
if (eventRec[eventLoc-1].eventdat3 != 0)
4700
damageRate = eventRec[eventLoc-1].eventdat3;
4702
if (eventRec[eventLoc-1].eventdat2 == 0 || twoPlayerMode || onePlayerAction)
4704
difficultyLevel += eventRec[eventLoc-1].eventdat;
4705
if (difficultyLevel < 1)
4706
difficultyLevel = 1;
4707
if (difficultyLevel > 10)
4708
difficultyLevel = 10;
4712
case 47: /* Enemy Global AccelRev */
4713
for (temp = 0; temp < 100; temp++)
4715
if (eventRec[eventLoc-1].eventdat4 == 0 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4)
4716
enemy[temp].armorleft = eventRec[eventLoc-1].eventdat;
4720
case 48: /* Background 2 Cannot be Transparent */
4721
background2notTransparent = true;
4728
tempDat2 = eventRec[eventLoc-1].eventdat;
4729
eventRec[eventLoc-1].eventdat = 0;
4730
tempDat = eventRec[eventLoc-1].eventdat3;
4731
eventRec[eventLoc-1].eventdat3 = 0;
4732
tempDat3 = eventRec[eventLoc-1].eventdat6;
4733
eventRec[eventLoc-1].eventdat6 = 0;
4734
enemyDat[0].armor = tempDat3;
4735
enemyDat[0].egraphic[1-1] = tempDat2;
4736
switch (eventRec[eventLoc-1].eventtype - 48)
4751
JE_createNewEventEnemy(0, temp, tempDat);
4752
eventRec[eventLoc-1].eventdat = tempDat2;
4753
eventRec[eventLoc-1].eventdat3 = tempDat;
4754
eventRec[eventLoc-1].eventdat6 = tempDat3;
4758
forceEvents = (eventRec[eventLoc-1].eventdat != 99);
4762
JE_eventJump(eventRec[eventLoc-1].eventdat);
4765
case 55: /* Enemy Global AccelRev */
4766
if (eventRec[eventLoc-1].eventdat3 > 79 && eventRec[eventLoc-1].eventdat3 < 90)
4767
eventRec[eventLoc-1].eventdat4 = newPL[eventRec[eventLoc-1].eventdat3 - 80];
4769
for (temp = 0; temp < 100; temp++)
4771
if (eventRec[eventLoc-1].eventdat4 == 0 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4)
4773
if (eventRec[eventLoc-1].eventdat != -99)
4774
enemy[temp].xaccel = eventRec[eventLoc-1].eventdat;
4775
if (eventRec[eventLoc-1].eventdat2 != -99)
4776
enemy[temp].yaccel = eventRec[eventLoc-1].eventdat2;
4781
case 56: /* Ground2 Bottom */
4782
JE_createNewEventEnemy(0, 75, 0);
4784
enemy[b-1].ey = 190;
4788
superEnemy254Jump = eventRec[eventLoc-1].eventdat;
4791
case 60: /*Assign Special Enemy*/
4792
for (temp = 0; temp < 100; temp++)
4794
if (enemy[temp].linknum == eventRec[eventLoc-1].eventdat4)
4796
enemy[temp].special = true;
4797
enemy[temp].flagnum = eventRec[eventLoc-1].eventdat;
4798
enemy[temp].setto = (eventRec[eventLoc-1].eventdat2 == 1);
4803
case 61: // if specific flag set to specific value, skip events
4804
if (globalFlags[eventRec[eventLoc-1].eventdat-1] == eventRec[eventLoc-1].eventdat2)
4805
eventLoc += eventRec[eventLoc-1].eventdat3;
4808
case 62: /*Play sound effect*/
4809
soundQueue[3] = eventRec[eventLoc-1].eventdat;
4812
case 63: // skip events if not in 2-player mode
4813
if (!twoPlayerMode && !onePlayerAction)
4814
eventLoc += eventRec[eventLoc-1].eventdat;
4818
if (!(eventRec[eventLoc-1].eventdat == 6 && twoPlayerMode && difficultyLevel > 2))
4820
smoothies[eventRec[eventLoc-1].eventdat-1] = eventRec[eventLoc-1].eventdat2;
4821
temp = eventRec[eventLoc-1].eventdat;
4824
smoothie_data[temp-1] = eventRec[eventLoc-1].eventdat3;
4829
background3x1 = (eventRec[eventLoc-1].eventdat == 0);
4832
case 66: /*If not on this difficulty level or higher then...*/
4833
if (initialDifficulty <= eventRec[eventLoc-1].eventdat)
4834
eventLoc += eventRec[eventLoc-1].eventdat2;
4838
levelTimer = (eventRec[eventLoc-1].eventdat == 1);
4839
levelTimerCountdown = eventRec[eventLoc-1].eventdat3 * 100;
4840
levelTimerJumpTo = eventRec[eventLoc-1].eventdat2;
4844
randomExplosions = (eventRec[eventLoc-1].eventdat == 1);
4848
for (uint i = 0; i < COUNTOF(player); ++i)
4849
player[i].invulnerable_ticks = eventRec[eventLoc-1].eventdat;
4853
if (eventRec[eventLoc-1].eventdat2 == 0)
4857
for (temp = 1; temp <= 19; temp++)
4858
found = found || JE_searchFor(temp, NULL);
4861
JE_eventJump(eventRec[eventLoc-1].eventdat);
4863
else if (!JE_searchFor(eventRec[eventLoc-1].eventdat2, NULL)
4864
&& (eventRec[eventLoc-1].eventdat3 == 0 || !JE_searchFor(eventRec[eventLoc-1].eventdat3, NULL))
4865
&& (eventRec[eventLoc-1].eventdat4 == 0 || !JE_searchFor(eventRec[eventLoc-1].eventdat4, NULL)))
4867
JE_eventJump(eventRec[eventLoc-1].eventdat);
4872
if (((((intptr_t)mapYPos - (intptr_t)&megaData1.mainmap) / sizeof(JE_byte *)) * 2) <= (unsigned)eventRec[eventLoc-1].eventdat2)
4874
JE_eventJump(eventRec[eventLoc-1].eventdat);
4879
background3x1b = (eventRec[eventLoc-1].eventdat == 1);
4883
skyEnemyOverAll = (eventRec[eventLoc-1].eventdat == 1);
4886
case 74: /* Enemy Global BounceParams */
4887
for (temp = 0; temp < 100; temp++)
4889
if (eventRec[eventLoc-1].eventdat4 == 0 || enemy[temp].linknum == eventRec[eventLoc-1].eventdat4)
4891
if (eventRec[eventLoc-1].eventdat5 != -99)
4892
enemy[temp].xminbounce = eventRec[eventLoc-1].eventdat5;
4894
if (eventRec[eventLoc-1].eventdat6 != -99)
4895
enemy[temp].yminbounce = eventRec[eventLoc-1].eventdat6;
4897
if (eventRec[eventLoc-1].eventdat != -99)
4898
enemy[temp].xmaxbounce = eventRec[eventLoc-1].eventdat;
4900
if (eventRec[eventLoc-1].eventdat2 != -99)
4901
enemy[temp].ymaxbounce = eventRec[eventLoc-1].eventdat2;
4907
bool temp_no_clue = false; // TODO: figure out what this is doing
4909
for (temp = 0; temp < 100; temp++)
4911
if (enemyAvail[temp] == 0
4912
&& enemy[temp].eyc == 0
4913
&& enemy[temp].linknum >= eventRec[eventLoc-1].eventdat
4914
&& enemy[temp].linknum <= eventRec[eventLoc-1].eventdat2)
4916
temp_no_clue = true;
4925
temp = (mt_rand() % (eventRec[eventLoc-1].eventdat2 + 1 - eventRec[eventLoc-1].eventdat)) + eventRec[eventLoc-1].eventdat;
4927
while (!(JE_searchFor(temp, &enemy_i) && enemy[enemy_i].eyc == 0));
4929
newPL[eventRec[eventLoc-1].eventdat3 - 80] = temp;
4933
newPL[eventRec[eventLoc-1].eventdat3 - 80] = 255;
4934
if (eventRec[eventLoc-1].eventdat4 > 0)
4936
curLoc = eventRec[eventLoc-1 + eventRec[eventLoc-1].eventdat4].eventtime - 1;
4937
eventLoc += eventRec[eventLoc-1].eventdat4 - 1;
4944
returnActive = true;
4948
mapYPos = &megaData1.mainmap[0][0];
4949
mapYPos += eventRec[eventLoc-1].eventdat / 2;
4950
if (eventRec[eventLoc-1].eventdat2 > 0)
4952
mapY2Pos = &megaData2.mainmap[0][0];
4953
mapY2Pos += eventRec[eventLoc-1].eventdat2 / 2;
4957
mapY2Pos = &megaData2.mainmap[0][0];
4958
mapY2Pos += eventRec[eventLoc-1].eventdat / 2;
4963
if (galagaShotFreq < 10)
4968
boss_bar[0].link_num = eventRec[eventLoc-1].eventdat;
4969
boss_bar[1].link_num = eventRec[eventLoc-1].eventdat2;
4972
case 80: // skip events if in 2-player mode
4974
eventLoc += eventRec[eventLoc-1].eventdat;
4978
BKwrap2 = &megaData2.mainmap[0][0];
4979
BKwrap2 += eventRec[eventLoc-1].eventdat / 2;
4980
BKwrap2to = &megaData2.mainmap[0][0];
4981
BKwrap2to += eventRec[eventLoc-1].eventdat2 / 2;
4984
case 82: /*Give SPECIAL WEAPON*/
4985
player[0].items.special = eventRec[eventLoc-1].eventdat;
4986
shotMultiPos[SHOT_SPECIAL] = 0;
4987
shotRepeat[SHOT_SPECIAL] = 0;
4988
shotMultiPos[SHOT_SPECIAL2] = 0;
4989
shotRepeat[SHOT_SPECIAL2] = 0;
4993
fprintf(stderr, "warning: ignoring unknown event %d\n", eventRec[eventLoc-1].eventtype);
5000
void JE_whoa( void )
5002
unsigned int i, j, color, offset, timer;
5003
unsigned int screenSize, topBorder, bottomBorder;
5004
Uint8 * TempScreen1, * TempScreen2, * TempScreenSwap;
5006
/* 'whoa' gets us that nifty screen fade used when you type in
5007
* 'engage'. We need two temporary screen buffers (char arrays can
5008
* work too, but these screens already exist) for our effect.
5009
* This could probably be a lot more efficient (there's probably a
5010
* way to get vgascreen as one of the temp buffers), but it's only called
5011
* once so don't worry about it. */
5013
TempScreen1 = game_screen->pixels;
5014
TempScreen2 = VGAScreen2->pixels;
5016
screenSize = VGAScreenSeg->h * VGAScreenSeg->pitch;
5017
topBorder = VGAScreenSeg->pitch * 4; /* Seems an arbitrary number of lines */
5018
bottomBorder = VGAScreenSeg->pitch * 7;
5020
/* Okay, one disadvantage to using other screens as temp buffers: they
5021
* need to be the right size. I doubt they'l ever be anything but 320x200,
5022
* but just in case, these asserts will clue in whoever stumbles across
5023
* the problem. You can fix it with the stack or malloc. */
5024
assert( (unsigned)VGAScreen2->h * VGAScreen2->pitch >= screenSize
5025
&& (unsigned)game_screen->h * game_screen->pitch >= screenSize);
5028
/* Clear the top and bottom borders. We don't want to process
5029
* them and we don't want to draw them. */
5030
memset((Uint8 *)VGAScreenSeg->pixels, 0, topBorder);
5031
memset((Uint8 *)VGAScreenSeg->pixels + screenSize - bottomBorder, 0, bottomBorder);
5033
/* Copy our test subject to one of the temporary buffers. Blank the other */
5034
memset(TempScreen1, 0, screenSize);
5035
memcpy(TempScreen2, VGAScreenSeg->pixels, VGAScreenSeg->h * VGAScreenSeg->pitch);
5038
service_SDL_events(true);
5039
timer = 300; /* About 300 rounds is enough to make the screen mostly black */
5045
/* This gets us our 'whoa' effect with pixel bleeding magic.
5046
* I'm willing to bet the guy who originally wrote the asm was goofing
5047
* around on acid and thought this looked good enough to use. */
5048
for (i = screenSize - bottomBorder, j = topBorder / 2; i > 0; i--, j++)
5050
offset = j + i/8192 - 4;
5051
color = (TempScreen2[offset ] * 12 +
5052
TempScreen1[offset-VGAScreenSeg->pitch] +
5053
TempScreen1[offset-1 ] +
5054
TempScreen1[offset+1 ] +
5055
TempScreen1[offset+VGAScreenSeg->pitch]) / 16;
5057
TempScreen1[j] = color;
5060
/* Now copy that mess to the buffer. */
5061
memcpy((Uint8 *)VGAScreenSeg->pixels + topBorder, TempScreen1 + topBorder, screenSize - bottomBorder);
5068
/* Flip the buffer. */
5069
TempScreenSwap = TempScreen1;
5070
TempScreen1 = TempScreen2;
5071
TempScreen2 = TempScreenSwap;
5073
} while (!(timer == 0 || JE_anyButton()));
5075
levelWarningLines = 4;
5078
void JE_barX( JE_word x1, JE_word y1, JE_word x2, JE_word y2, JE_byte col )
5080
fill_rectangle_xy(VGAScreen, x1, y1, x2, y1, col + 1);
5081
fill_rectangle_xy(VGAScreen, x1, y1 + 1, x2, y2 - 1, col );
5082
fill_rectangle_xy(VGAScreen, x1, y2, x2, y2, col - 1);
5085
void draw_boss_bar( void )
5087
for (unsigned int b = 0; b < COUNTOF(boss_bar); b++)
5089
if (boss_bar[b].link_num == 0)
5092
unsigned int armor = 256; // higher than armor max
5094
for (unsigned int e = 0; e < COUNTOF(enemy); e++) // find most damaged
5096
if (enemyAvail[e] != 1 && enemy[e].linknum == boss_bar[b].link_num)
5097
if (enemy[e].armorleft < armor)
5098
armor = enemy[e].armorleft;
5101
if (armor > 255 || armor == 0) // boss dead?
5102
boss_bar[b].link_num = 0;
5104
boss_bar[b].armor = (armor == 255) ? 254 : armor; // 255 would make the bar too long
5107
unsigned int bars = (boss_bar[0].link_num != 0 ? 1 : 0)
5108
+ (boss_bar[1].link_num != 0 ? 1 : 0);
5110
// if only one bar left, make it the first one
5111
if (bars == 1 && boss_bar[0].link_num == 0)
5113
memcpy(&boss_bar[0], &boss_bar[1], sizeof(boss_bar_t));
5114
boss_bar[1].link_num = 0;
5117
for (unsigned int b = 0; b < bars; b++)
5119
unsigned int x = (bars == 2)
5120
? ((b == 0) ? 125 : 185)
5121
: ((levelTimer) ? 250 : 155); // level timer and boss bar would overlap
5123
JE_barX(x - 25, 7, x + 25, 12, 115);
5124
JE_barX(x - (boss_bar[b].armor / 10), 7, x + (boss_bar[b].armor + 5) / 10, 12, 118 + boss_bar[b].color);
5126
if (boss_bar[b].color > 0)
5127
boss_bar[b].color--;