/*! \brief Enemies defeated the player * \author Josh Bolduc * \date created ???????? * \date updated * * Play some sad music and set the dead flag so that the game * will return to the main menu. */ static void enemies_win (void) { play_music ("rain.s3m", 0); battle_render (0, 0, 0); /* RB FIXME: rest()? */ blit2screen (0, 0); kq_wait (1000); sprintf (strbuf, _("%s was defeated!"), party[pidx[0]].name); menubox (double_buffer, 152 - (strlen (strbuf) * 4), 48, strlen (strbuf), 1, BLUE); print_font (double_buffer, 160 - (strlen (strbuf) * 4), 56, strbuf, FNORMAL); blit2screen (0, 0); wait_enter (); do_transition (TRANS_FADE_OUT, 4); alldead = 1; }
/*! \brief Activate the special skill * * This function activates the special skill for a hero, * including targetting etc. if required. * * \param attack_fighter_index Hero to process * \returns 1 if the skill was used, otherwise 0 */ int skill_use(size_t attack_fighter_index) { int tgt, found_item, a, b, c, p, cts, tx, ty, next_target = 0, nn[NUM_FIGHTERS]; size_t enemy_index; size_t fighter_index; std::unique_ptr<Raster> temp; tempa = Magic.status_adjust(attack_fighter_index); switch (pidx[attack_fighter_index]) { case SENSAR: tgt = select_enemy(attack_fighter_index, TGT_ENEMY_ONE); if (tgt == -1) { return 0; } enemy_index = (unsigned int)tgt; temp = std::unique_ptr<Raster>(new Raster(320, 240)); blit(Combat.backart, temp.get(), 0, 0, 0, 0, 320, 240); Draw.color_scale(temp.get(), Combat.backart, 16, 31); b = fighter[attack_fighter_index].mhp / 20; strcpy(attack_string, _("Rage")); display_attack_string = 1; tempa.stats[eStat::Attack] = fighter[attack_fighter_index].stats[eStat::Attack]; tempa.stats[eStat::Hit] = fighter[attack_fighter_index].stats[eStat::Hit]; if (fighter[enemy_index].crit == 1) { tempa.stats[eStat::Attack] += b; tempa.stats[eStat::Hit] += b; } Combat.fight(attack_fighter_index, enemy_index, 1); if (fighter[enemy_index].IsDead()) { for (fighter_index = PSIZE; fighter_index < PSIZE + Combat.GetNumEnemies(); fighter_index++) { if (fighter[fighter_index].IsAlive()) { nn[next_target] = fighter_index; next_target++; } } if (next_target > 0) { enemy_index = nn[kqrandom->random_range_exclusive(0, next_target)]; Combat.fight(attack_fighter_index, enemy_index, 1); } } fighter[attack_fighter_index].hp -= (b * 2); Combat.AdjustHealth(attack_fighter_index, b * 2); display_attack_string = 0; blit(temp.get(), Combat.backart, 0, 0, 0, 0, 320, 240); Effects.display_amount(attack_fighter_index, FONT_DECIDE, 0); if (fighter[attack_fighter_index].IsAlive() && fighter[attack_fighter_index].hp <= 0) { Combat.fkill(attack_fighter_index); Effects.death_animation(attack_fighter_index, 0); } break; case SARINA: fighter[attack_fighter_index].ctmem = 1000; strcpy(attack_string, _("Sweep")); display_attack_string = 1; tempa.stats[eStat::Attack] = tempa.stats[eStat::Attack] * 75 / 100; fighter[attack_fighter_index].aframe = 6; Combat.UnsetDatafileImageCoords(); Combat.battle_render(0, 0, 0); Draw.blit2screen(0, 0); kq_wait(150); Combat.multi_fight(attack_fighter_index); display_attack_string = 0; break; case CORIN: strcpy(attack_string, _("Elemental Infusion")); display_attack_string = 1; fighter[attack_fighter_index].aux = 2; if (combat_spell_menu(attack_fighter_index) == 1) { Effects.draw_castersprite( attack_fighter_index, eff[magic[fighter[attack_fighter_index].csmem].eff].kolor); Combat.UnsetDatafileImageCoords(); play_effect(22, 128); Draw.convert_cframes( attack_fighter_index, eff[magic[fighter[attack_fighter_index].csmem].eff].kolor - 3, eff[magic[fighter[attack_fighter_index].csmem].eff].kolor + 3, 0); Combat.battle_render(0, 0, 0); fullblit(double_buffer, back); for (p = 0; p < 2; p++) { for (a = 0; a < 16; a++) { tx = fighter[attack_fighter_index].cx + (fighter[attack_fighter_index].cw / 2); ty = fighter[attack_fighter_index].cy + (fighter[attack_fighter_index].cl / 2); if (p == 0) { circlefill( double_buffer, tx, ty, a, eff[magic[fighter[attack_fighter_index].csmem].eff].kolor); } else { circlefill( double_buffer, tx, ty, 15 - a, eff[magic[fighter[attack_fighter_index].csmem].eff].kolor); Combat.draw_fighter(attack_fighter_index, 0); } Draw.blit2screen(0, 0); kq_wait(50); fullblit(back, double_buffer); } } Draw.revert_cframes(attack_fighter_index, 0); Combat.battle_render(0, 0, 0); Draw.blit2screen(0, 0); infusion(attack_fighter_index, fighter[attack_fighter_index].csmem); c = Magic.mp_needed(attack_fighter_index, fighter[attack_fighter_index].csmem); if (c < 1) { c = 1; } fighter[attack_fighter_index].mp -= c; Combat.SetEtherEffectActive(attack_fighter_index, false); fighter[attack_fighter_index].aux = 1; } else { fighter[attack_fighter_index].aux = 0; display_attack_string = 0; return 0; } display_attack_string = 0; fighter[attack_fighter_index].SetInfuse(magic[fighter[attack_fighter_index].csmem].elem); break; case AJATHAR: if (fighter[attack_fighter_index].unl > 0) { strcpy(attack_string, _("Dispel Undead")); display_attack_string = 1; fullblit(double_buffer, back); for (a = 0; a < 14/*MagicNumber*/; a++) { Draw.convert_cframes(PSIZE, 1 + a, 15, 1); for (fighter_index = PSIZE; fighter_index < PSIZE + Combat.GetNumEnemies(); fighter_index++) { if (Effects.is_active(fighter_index)) { Combat.draw_fighter(fighter_index, 0); } } Draw.blit2screen(0, 0); kq_wait(50); fullblit(back, double_buffer); } Draw.revert_cframes(PSIZE, 1); display_attack_string = 0; b = fighter[attack_fighter_index].lvl * 15; for (fighter_index = PSIZE; fighter_index < PSIZE + Combat.GetNumEnemies(); fighter_index++) { if (fighter[fighter_index].IsAlive() && fighter[fighter_index].mhp > 0) { if (fighter[fighter_index].unl == 99 || fighter[fighter_index].unl == 0) { cts = 0; } else { a = (fighter[attack_fighter_index].lvl + 5) - fighter[fighter_index].unl; if (a > 0) { cts = a * 8; } else { cts = 0; } } if (kqrandom->random_range_exclusive(0, 100) < cts) { if (b >= fighter[fighter_index].hp) { b -= fighter[fighter_index].hp; Combat.SetShowDeathEffectAnimation(fighter_index, true); Combat.fkill(fighter_index); } } } } Effects.death_animation(PSIZE, 1); Combat.UnsetDatafileImageCoords(); Combat.battle_render(attack_fighter_index, attack_fighter_index, 0); } else { a = kqrandom->random_range_exclusive(0, 100); c = fighter[attack_fighter_index].lvl / 10 + 1; if (a < 25) { b = kqrandom->random_range_exclusive(0, 5 * c) + 1; } else { if (a < 90) { b = kqrandom->random_range_exclusive(0, 10 * c) + (20 * c); } else { b = kqrandom->random_range_exclusive(0, 25 * c) + (50 * c); } } strcpy(attack_string, _("Divine Cure")); display_attack_string = 1; Effects.draw_spellsprite(0, 1, 15, 1); display_attack_string = 0; for (fighter_index = 0; fighter_index < numchrs; fighter_index++) { if (!fighter[fighter_index].IsStone() && fighter[fighter_index].IsAlive()) { int amount = Magic.do_shell_check(fighter_index, b); Combat.AdjustHealth(fighter_index, amount); } } Effects.display_amount(0, FONT_YELLOW, 1); for (fighter_index = 0; fighter_index < numchrs; fighter_index++) { if (!fighter[fighter_index].IsStone() && fighter[fighter_index].IsAlive()) { Magic.adjust_hp(fighter_index, Combat.GetHealthAdjust(fighter_index)); } } } break; case CASANDRA: fighter[attack_fighter_index].atrack[0] = fighter[attack_fighter_index].stats[eStat::Aura]; fighter[attack_fighter_index].atrack[1] = fighter[attack_fighter_index].stats[eStat::Spirit]; fighter[attack_fighter_index].stats[eStat::Aura] = fighter[attack_fighter_index].stats[eStat::Aura] * 15 / 10; fighter[attack_fighter_index].stats[eStat::Spirit] = fighter[attack_fighter_index].stats[eStat::Spirit] * 15 / 10; fighter[attack_fighter_index].atrack[2] = fighter[attack_fighter_index].mrp; fighter[attack_fighter_index].mrp = fighter[attack_fighter_index].mrp * 15 / 10; if (combat_spell_menu(attack_fighter_index) == 1) { Combat.SetEtherEffectActive(attack_fighter_index, false); fighter[attack_fighter_index].aux = 1; fighter[attack_fighter_index].stats[eStat::Aura] = fighter[attack_fighter_index].atrack[0]; fighter[attack_fighter_index].stats[eStat::Spirit] = fighter[attack_fighter_index].atrack[1]; fighter[attack_fighter_index].mrp = fighter[attack_fighter_index].atrack[2]; } else { fighter[attack_fighter_index].stats[eStat::Aura] = fighter[attack_fighter_index].atrack[0]; fighter[attack_fighter_index].stats[eStat::Spirit] = fighter[attack_fighter_index].atrack[1]; fighter[attack_fighter_index].mrp = fighter[attack_fighter_index].atrack[2]; return 0; } break; case TEMMIN: fighter[attack_fighter_index].aux = 1; fighter[attack_fighter_index].defend = 1; break; case AYLA: tgt = select_enemy(attack_fighter_index, TGT_ENEMY_ONE); if (tgt == -1) { return 0; } enemy_index = (uint32_t)tgt; tx = fighter[attack_fighter_index].cx; ty = fighter[attack_fighter_index].cy; fighter[attack_fighter_index].cx = fighter[enemy_index].cx - 16; fighter[attack_fighter_index].cy = fighter[enemy_index].cy + fighter[enemy_index].cl - 40; fighter[attack_fighter_index].facing = 1; strcpy(attack_string, _("Steal")); display_attack_string = 1; Combat.battle_render(0, attack_fighter_index + 1, 0); Draw.blit2screen(0, 0); kq_wait(100); play_effect(SND_MENU, 128); kq_wait(500); display_attack_string = 0; Combat.battle_render(attack_fighter_index, attack_fighter_index, 0); found_item = 0; #ifdef DEBUGMODE if (debugging > 2) { if (fighter[enemy_index].steal_item_rare > 0) { /* This steals a rare item from monster, if there is one */ found_item = fighter[enemy_index].steal_item_rare; fighter[enemy_index].steal_item_rare = 0; } else if (fighter[enemy_index].steal_item_common > 0) { /* This steals a common item from a monster, if there is one */ found_item = fighter[enemy_index].steal_item_common; fighter[enemy_index].steal_item_common = 0; } if (found_item > 0) { if (check_inventory(found_item, 1) != 0) { sprintf(strbuf, _("%s taken!"), items[found_item].name); Draw.message(strbuf, items[found_item].icon, 0, 0, 0); } } else { if (fighter[enemy_index].steal_item_common == 0 && fighter[enemy_index].steal_item_rare == 0) { Draw.message(_("Nothing to steal!"), 255, 0, 0, 0); } else { Draw.message(_("Couldn't steal!"), 255, 0, 0, 0); } } } #else cts = party[pidx[attack_fighter_index]].lvl * 2 + 35; if (cts > 95) { cts = 95; } if (kqrandom->random_range_exclusive(0, 100) < cts) { if (fighter[enemy_index].steal_item_rare > 0 && (kqrandom->random_range_exclusive(0, 100) < 5)) { /* This steals a rare item from monster, if there is one */ found_item = fighter[enemy_index].steal_item_rare; fighter[enemy_index].steal_item_rare = 0; } else if (fighter[enemy_index].steal_item_common > 0 && (kqrandom->random_range_exclusive(0, 100) < 95)) { /* This steals a common item from a monster, if there is one */ found_item = fighter[enemy_index].steal_item_common; fighter[enemy_index].steal_item_common = 0; } if (found_item > 0) { if (check_inventory(found_item, 1) != 0) { sprintf(strbuf, _("%s taken!"), items[found_item].name); Draw.message(strbuf, items[found_item].icon, 0, 0, 0); } } else { if (fighter[enemy_index].steal_item_common == 0 && fighter[enemy_index].steal_item_rare == 0) { Draw.message(_("Nothing to steal!"), 255, 0, 0, 0); } else { Draw.message(_("Couldn't steal!"), 255, 0, 0, 0); } } } else { Draw.message(_("Couldn't steal!"), 255, 0, 0, 0); } #endif fighter[attack_fighter_index].cx = tx; fighter[attack_fighter_index].cy = ty; display_attack_string = 0; fighter[attack_fighter_index].facing = 0; Combat.battle_render(attack_fighter_index, attack_fighter_index, 0); Draw.blit2screen(0, 0); break; case NOSLOM: tgt = select_enemy(attack_fighter_index, TGT_ENEMY_ONE); if (tgt == -1) { return 0; } enemy_index = (uint32_t)tgt; reveal(enemy_index); break; default: break; } return 1; }
/*! \brief Main fighting routine * * I don't really need to describe this :p * * \author Josh Bolduc * \date created ???????? * \date updated * \param ar Attacker ID * \param dr Defender ID * \param sk If non-zero, override the attacker's stats. * \returns 1 if damage done, 0 otherwise */ int fight (int ar, int dr, int sk) { int a; int tx = -1; int ty = -1; int f; int ares; for (a = 0; a < NUM_FIGHTERS; a++) { deffect[a] = 0; ta[a] = 0; } /* check the 'sk' variable to see if we are over-riding the */ /* attackers stats with temporary ones... used for skills */ /* and such */ if (sk == 0) tempa = status_adjust (ar); tempd = status_adjust (dr); ares = attack_result (ar, dr); for (a = 0; a < 24; a++) fighter[dr].sts[a] = tempd.sts[a]; /* RB TODO: rest(20) or vsync() before the blit? */ if (ares == 2) { for (f = 0; f < 3; f++) { battle_render (dr + 1, 0, 0); blit2screen (0, 0); kq_wait (20); rectfill (double_buffer, 0, 0, 320, 240, 15); blit2screen (0, 0); kq_wait (20); } } if ((pidx[dr] == TEMMIN) && (fighter[dr].aux == 2)) { fighter[dr].aux = 1; a = 1 - dr; tx = fighter[dr].cx; ty = fighter[dr].cy; fighter[dr].cx = fighter[a].cx; fighter[dr].cy = fighter[a].cy - 16; } if (ar < PSIZE) fighter[ar].aframe = 7; else fighter[ar].cy += 10; fight_animation (dr, ar, 0); if (ar < PSIZE) fighter[ar].aframe = 0; else fighter[ar].cy -= 10; if ((tx != -1) && (ty != -1)) { fighter[dr].cx = tx; fighter[dr].cy = ty; } if (ta[dr] != MISS) ta[dr] = do_shield_check (dr, ta[dr]); display_amount (dr, FDECIDE, 0); if (ta[dr] != MISS) { fighter[dr].hp += ta[dr]; if ((fighter[ar].imb_s > 0) && ((rand () % 5) == 0)) cast_imbued_spell (ar, fighter[ar].imb_s, fighter[ar].imb_a, dr); if ((fighter[dr].hp <= 0) && (fighter[dr].sts[S_DEAD] == 0)) { fkill (dr); death_animation (dr, 0); } if (fighter[dr].hp > fighter[dr].mhp) fighter[dr].hp = fighter[dr].mhp; if (fighter[dr].sts[S_SLEEP] > 0) fighter[dr].sts[S_SLEEP] = 0; if ((fighter[dr].sts[S_CHARM] > 0) && (ar == dr)) fighter[dr].sts[S_CHARM] = 0; return 1; } return 0; }
/*! \brief Really do combat once fighters have been inited * * \param bg Background image * \param mus Music * \param is_rnd If !=0 then this is a random combat * \returns 1 if battle occurred */ static int do_combat (char *bg, char *mus, int is_rnd) { int zoom_step; in_combat = 1; backart = load_datafile_object (PCX_DATAFILE, bg); if (is_rnd) { if ((numchrs == 1) && (pidx[0] == AYLA)) { hs = rand () % 100 + 1; ms = rand () % 3 + 1; } else { if (numchrs > 1 && (in_party (AYLA) > 0)) { hs = rand () % 20 + 1; ms = rand () % 5 + 1; } else { hs = rand () % 10 + 1; ms = rand () % 10 + 1; } } } else { hs = 10; ms = 10; } /* RB: do the zoom at the beginning of the combat. */ pause_music (); set_music_volume ((gmvol / 250.0) * 0.75); play_music (mus, 0); if (stretch_view == 2) { do_transition (TRANS_FADE_OUT, 2); clear_bitmap (double_buffer); do_transition (TRANS_FADE_IN, 64); } else /* TT TODO: * Change this so when we zoom into the battle, it won't just zoom into the middle * of the screen. Instead, it's going to zoom into the location where the player * is, so if he's on the side of the map somewhere... */ for (zoom_step = 0; zoom_step < 9; zoom_step++) { poll_music (); /* RB FIXME: stretching when 640x480, stretching when 320x240? */ /* shouldn't one of those be the "common" size, and */ /* therefore not needing to stretch it? */ /* 320x240 is the double_buffer size... */ if (stretch_view == 1) stretch_blit (double_buffer, screen, zoom_step * 16 + xofs, zoom_step * 12 + yofs, 320 - (zoom_step * 32), 240 - (zoom_step * 24), 0, 0, 640, 480); else stretch_blit (double_buffer, screen, zoom_step * 16 + xofs, zoom_step * 12 + yofs, 320 - (zoom_step * 32), 240 - (zoom_step * 24), 0, 0, 320, 240); /* RB FIXME: should we vsync here rather than rest? */ kq_wait (100); } snap_togrid (); roll_initiative (); curx = 0; cury = 0; vspell = 0; combatend = 0; /* RB: execute combat */ do_round (); unload_datafile_object (backart); set_music_volume (gmvol / 250.0); resume_music (); if (alldead) stop_music (); steps = 0; in_combat = 0; timer_count = 0; return (1); }
/*! \brief Player defeated the enemies * \author Josh Bolduc * \date Created ???????? * \date Updated * * Distribute the booty! */ static void heroes_win (void) { int tgp = 0; int index; int b; int c; int z; int nc = 0; int txp = 0; int found_item = 0; int nr = 0; int ent = 0; s_fighter t1; s_fighter t2; play_music ("rend5.s3m", 0); kq_wait (500); revert_equipstats (); for (index = 0; index < numchrs; index++) fighter[index].aframe = 4; battle_render (0, 0, 0); blit2screen (0, 0); kq_wait (250); for (index = 0; index < numchrs; index++) { if ((fighter[index].sts[S_STONE] == 0) && (fighter[index].sts[S_DEAD] == 0)) nc++; ta[index] = 0; } for (index = PSIZE; index < PSIZE + numens; index++) { txp += fighter[index].xp; tgp += fighter[index].gp; } /* JB: nc should never be zero if we won, but whatever */ if (nc > 0) txp /= nc; gp += tgp; if (tgp > 0) sprintf (strbuf, _("Gained %d xp and found %d gp."), txp, tgp); else sprintf (strbuf, _("Gained %d xp."), txp); menubox (double_buffer, 152 - (strlen (strbuf) * 4), 8, strlen (strbuf), 1, BLUE); print_font (double_buffer, 160 - (strlen (strbuf) * 4), 16, strbuf, FNORMAL); blit2screen (0, 0); blit (double_buffer, back, 0, 0, 0, 0, 352, 280); for (index = 0; index < numens; index++) { /* PH bug: (?) should found_item be reset to zero at the start of this loop? * If you defeat 2 enemies, you should (possibly) get 2 items, right? */ if ((rand () % 100) < fighter[index + PSIZE].dip) { if (fighter[index + PSIZE].defeat_item_common > 0) found_item = fighter[index + PSIZE].defeat_item_common; if (fighter[index + PSIZE].defeat_item_rare > 0) { if ((rand () % 100) < 5) found_item = fighter[index + PSIZE].defeat_item_rare; } if (found_item > 0) { if (check_inventory (found_item, 1) != 0) { sprintf (strbuf, _("%s found!"), items[found_item].name); menubox (double_buffer, 148 - (strlen (strbuf) * 4), nr * 24 + 48, strlen (strbuf) + 1, 1, BLUE); draw_icon (double_buffer, items[found_item].icon, 156 - (strlen (strbuf) * 4), nr * 24 + 56); print_font (double_buffer, 164 - (strlen (strbuf) * 4), nr * 24 + 56, strbuf, FNORMAL); nr++; } } } } if (nr > 0) { blit2screen (0, 0); wait_enter (); blit (back, double_buffer, 0, 0, 0, 0, 352, 280); } nr = 0; for (c = 0; c < numchrs; c++) { if ((party[pidx[c]].sts[S_STONE] == 0) && (party[pidx[c]].sts[S_DEAD] == 0)) { b = c * 160; player2fighter (pidx[c], &t1); if (give_xp (pidx[c], txp, 0) == 1) { menubox (double_buffer, b, 40, 18, 9, BLUE); player2fighter (pidx[c], &t2); print_font (double_buffer, b + 8, 48, _("Level up!"), FGOLD); print_font (double_buffer, b + 8, 56, _("Max HP"), FNORMAL); print_font (double_buffer, b + 8, 64, _("Max MP"), FNORMAL); print_font (double_buffer, b + 8, 72, _("Strength"), FNORMAL); print_font (double_buffer, b + 8, 80, _("Agility"), FNORMAL); print_font (double_buffer, b + 8, 88, _("Vitality"), FNORMAL); print_font (double_buffer, b + 8, 96, _("Intellect"), FNORMAL); print_font (double_buffer, b + 8, 104, _("Sagacity"), FNORMAL); sprintf (strbuf, "%3d>", t1.mhp); print_font (double_buffer, b + 96, 56, strbuf, FNORMAL); sprintf (strbuf, "%3d", t2.mhp); print_font (double_buffer, b + 128, 56, strbuf, FGREEN); sprintf (strbuf, "%3d>", t1.mmp); print_font (double_buffer, b + 96, 64, strbuf, FNORMAL); sprintf (strbuf, "%3d", t2.mmp); print_font (double_buffer, b + 128, 64, strbuf, FGREEN); for (z = 0; z < 5; z++) { sprintf (strbuf, "%3d>", t1.stats[z]); print_font (double_buffer, b + 96, z * 8 + 72, strbuf, FNORMAL); sprintf (strbuf, "%3d", t2.stats[z]); if (t2.stats[z] > t1.stats[z]) print_font (double_buffer, b + 128, z * 8 + 72, strbuf, FGREEN); else print_font (double_buffer, b + 128, z * 8 + 72, strbuf, FNORMAL); } nr++; } else menubox (double_buffer, b, 104, 18, 1, BLUE); sprintf (strbuf, _("Next level %7d"), party[pidx[c]].next - party[pidx[c]].xp); print_font (double_buffer, b + 8, 112, strbuf, FGOLD); } } blit2screen (0, 0); for (c = 0; c < numchrs; c++) if ((party[pidx[c]].sts[S_STONE] == 0) && (party[pidx[c]].sts[S_DEAD] == 0)) ent += learn_new_spells (pidx[c]); if (ent == 0) wait_enter (); }
/*! \brief Main menu screen * * This is the main menu... just display the opening and then the menu and * then wait for input. Also handles loading a saved game, and the config menu. * * \param c zero if the splash (the bit with the staff and the eight heroes) * should be displayed. * \returns 1 if new game, 0 if continuing, 2 if exit */ int start_menu (int skip_splash) { int stop = 0, ptr = 0, redraw = 1, a, b; DATAFILE *bg; BITMAP *staff, *dudes, *tdudes; #ifdef DEBUGMODE if (debugging == 0) { #endif play_music ("oxford.s3m", 0); /* Play splash (with the staff and the heroes in circle */ if (skip_splash == 0) { bg = load_datafile_object (PCX_DATAFILE, "KQT_PCX"); staff = create_bitmap_ex (8, 72, 226); dudes = create_bitmap_ex (8, 112, 112); tdudes = create_bitmap_ex (8, 112, 112); blit ((BITMAP *) bg->dat, staff, 0, 7, 0, 0, 72, 226); blit ((BITMAP *) bg->dat, dudes, 80, 0, 0, 0, 112, 112); clear_bitmap (double_buffer); blit (staff, double_buffer, 0, 0, 124, 22, 72, 226); blit2screen (0, 0); kq_wait (1000); for (a = 0; a < 42; a++) { stretch_blit (staff, double_buffer, 0, 0, 72, 226, 124 - (a * 32), 22 - (a * 96), 72 + (a * 64), 226 + (a * 192)); blit2screen (0, 0); kq_wait (100); } for (a = 0; a < 5; a++) { color_scale (dudes, tdudes, 53 - a, 53 + a); draw_sprite (double_buffer, tdudes, 106, 64); blit2screen (0, 0); kq_wait (100); } draw_sprite (double_buffer, dudes, 106, 64); blit2screen (0, 0); kq_wait (1000); destroy_bitmap (staff); destroy_bitmap (dudes); destroy_bitmap (tdudes); unload_datafile_object(bg); /* TODO: this fade should actually be to white if (_color_depth == 8) fade_from (pal, whp, 1); else */ do_transition (TRANS_FADE_WHITE, 1); } clear_to_color (double_buffer, 15); blit2screen (0, 0); set_palette (pal); bg = load_datafile_object (PCX_DATAFILE, "TITLE_PCX"); for (a = 0; a < 16; a++) { clear_to_color (double_buffer, 15 - a); masked_blit ((BITMAP *) bg->dat, double_buffer, 0, 0, 0, 60 - (a * 4), 320, 124); blit2screen (0, 0); kq_wait (a == 0 ? 500 : 100); } if (skip_splash == 0) kq_wait (500); #ifdef DEBUGMODE } else { set_palette (pal); bg = load_datafile_object (PCX_DATAFILE, "TITLE_PCX"); } #endif reset_world (); /* Draw menu and handle menu selection */ while (!stop) { if (redraw) { clear_bitmap (double_buffer); masked_blit ((BITMAP *) bg->dat, double_buffer, 0, 0, 0, 0, 320, 124); menubox (double_buffer, 112, 116, 10, 4, BLUE); print_font (double_buffer, 128, 124, _("Continue"), FNORMAL); print_font (double_buffer, 128, 132, _("New Game"), FNORMAL); print_font (double_buffer, 136, 140, _("Config"), FNORMAL); print_font (double_buffer, 144, 148, _("Exit"), FNORMAL); draw_sprite (double_buffer, menuptr, 112, ptr * 8 + 124); redraw = 0; } display_credits (); blit2screen (0, 0); readcontrols (); if (bhelp) { unpress (); show_help (); redraw = 1; } if (up) { unpress (); if (ptr > 0) ptr--; else ptr = 3; play_effect (SND_CLICK, 128); redraw = 1; } if (down) { unpress (); if (ptr < 3) ptr++; else ptr = 0; play_effect (SND_CLICK, 128); redraw = 1; } if (balt) { unpress (); if (ptr == 0) { /* User selected "Continue" */ if (snc[0] == 0 && snc[1] == 0 && snc[2] == 0 && snc[3] == 0 && snc[4] == 0) stop = 2; else if (saveload (0) == 1) stop = 1; redraw = 1; } else if (ptr == 1) { /* User selected "New Game" */ stop = 2; } else if (ptr == 2) { /* Config */ clear (double_buffer); config_menu (); redraw = 1; /* TODO: Save Global Settings Here */ } else if (ptr == 3) { /* Exit */ unload_datafile_object (bg); klog (_("Then exit you shall!")); return 2; } } } unload_datafile_object (bg); if (stop == 2) { /* New game init */ for (a = 0; a < MAXCHRS; a++) memcpy (&party[a], &players[a].plr, sizeof (s_player)); init_players (); memset (progress, 0, SIZE_PROGRESS); memset (treasure, 0, SIZE_TREASURE); numchrs = 0; for (a = 0; a < NUMSHOPS; a++) { for (b = 0; b < SHOPITEMS; b++) shops[a].items_current[b] = shops[a].items_max[b]; } for (b = 0; b < 2; b++) { for (a = 0; a < MAX_INV; a++) g_inv[a][b] = 0; } } return stop - 1; }
/*! \brief Play sample effect * * Play an effect... if possible/necessary. If the effect to * be played is the 'bad-move' effect, than do something visually * so that even if sound is off you know you did something bad :) * PH added explode effect. * * \param efc Effect to play (index in sfx[]) * \param panning Left/right pan - see Allegro's play_sample() */ void play_effect (int efc, int panning) { int a, s, xo = 1, yo = 1; static const int bx[8] = { -1, 0, 1, 0, -1, 0, 1, 0 }; static const int by[8] = { -1, 0, 1, 0, 1, 0, -1, 0 }; static const int sc[] = { 1, 2, 3, 5, 3, 3, 3, 2, 1 }; SAMPLE *samp; PALETTE whiteout, old; /* Patch provided by mattrope: */ /* sfx array is empty if sound is not initialized */ if (is_sound != 0) samp = (SAMPLE *) sfx[efc]->dat; else samp = NULL; /* PH not strictly needed but I added it */ switch (efc) { default: if (samp) play_sample (samp, gsvol, panning, 1000, 0); break; case SND_BAD: blit (double_buffer, fx_buffer, 0, 0, 0, 0, 352, 280); if (samp) play_sample (samp, gsvol, panning, 1000, 0); clear_bitmap (double_buffer); blit (fx_buffer, double_buffer, xofs, yofs, xofs, yofs, 320, 240); if (in_combat == 0) { xo = xofs; yo = yofs; } /* blit (fx_buffer, double_buffer, xo, yo, xo, yo, 320, 240); */ for (a = 0; a < 8; a++) { blit2screen (xo + bx[a], yo + by[a]); kq_wait (10); } blit (fx_buffer, double_buffer, 0, 0, 0, 0, 352, 280); break; case SND_EXPLODE: blit (double_buffer, fx_buffer, 0, 0, 0, 0, 352, 280); clear_bitmap (double_buffer); get_palette (old); for (a = 0; a < 256; ++a) { s = (old[a].r + old[a].g + old[a].b) > 40 ? 0 : 63; whiteout[a].r = whiteout[a].g = whiteout[a].b = s; } blit (fx_buffer, double_buffer, xofs, yofs, xofs, yofs, 320, 240); if (samp) { play_sample (samp, gsvol, panning, 1000, 0); } for (s = 0; s < (int) (sizeof (sc) / sizeof (*sc)); ++s) { if (s == 1) set_palette (whiteout); if (s == 6) set_palette (old); for (a = 0; a < 8; a++) { blit2screen (xofs + bx[a] * sc[s], yofs + by[a] * sc[s]); kq_wait (10); } } blit (fx_buffer, double_buffer, 0, 0, 0, 0, 352, 280); break; } }