/* sub_387FE */ static void PlaceCombatants() { ovr025.CountCombatTeamMembers(); for (int i = 1; i <= gbl.MaxCombatantCount; i++) { gbl.CombatMap[i].size = 0; } ovr033.setup_mapToPlayerIndex_and_playerScreen(); gbl.team_start_x[0] = 0; gbl.team_start_y[0] = 0; gbl.team_direction[0] = gbl.mapDirection / 2; gbl.team_start_x[1] = (gbl.area2_ptr.encounter_distance * gbl.MapDirectionXDelta[gbl.mapDirection]) + gbl.team_start_x[0]; gbl.team_start_y[1] = (gbl.area2_ptr.encounter_distance * gbl.MapDirectionYDelta[gbl.mapDirection]) + gbl.team_start_y[0]; gbl.team_direction[1] = ((gbl.mapDirection + 4) % 8) / 2; gbl.half_team_count[0] = (gbl.friends_count + 1) / 2; gbl.half_team_count[1] = (gbl.foe_count + 1) / 2; for (gbl.currentTeam = 0; gbl.currentTeam < 2; gbl.currentTeam++) { for (int var_C = 0; var_C < 4; var_C++) { int direction; if (var_C == 1) { direction = 4; } else { direction = gbl.team_direction[gbl.currentTeam]; } for (int var_2 = 0; var_2 < 6; var_2++) { for (int var_1 = 0; var_1 < 11; var_1++) { if (unk_16620[direction, var_2, 0] > var_1 || unk_16620[direction, var_2, 1] < var_1) { unk_1AB1C[gbl.currentTeam, var_C, var_2, var_1] = 0; } else { unk_1AB1C[gbl.currentTeam, var_C, var_2, var_1] = 1; } } } } } int loop_var = 1; gbl.CombatantCount = 0; List<Player> to_remove = new List<Player>(); foreach (Player player in gbl.TeamList) { seg043.clear_one_keypress(); gbl.player_array[loop_var] = player; gbl.currentTeam = (sbyte)player.combat_team; gbl.CombatMap[loop_var].size = player.field_DE & 7; if (place_combatant(loop_var) == true) { if (player.in_combat == false) { gbl.CombatMap[loop_var].size = 0; if (gbl.combat_type == CombatType.normal && player.actions.nonTeamMember == false) { var pos = gbl.CombatMap[loop_var].pos; var b = new Struct_1D183(); gbl.downedPlayers.Add(b); b.originalBackgroundTile = gbl.mapToBackGroundTile[pos]; b.target = player; b.map = pos; gbl.mapToBackGroundTile[pos] = 0x1F; } } gbl.CombatantCount++; ovr033.setup_mapToPlayerIndex_and_playerScreen(); loop_var++; } else { gbl.CombatMap[loop_var].size = 0; if (player.actions.nonTeamMember == true) { gbl.player_array[loop_var] = null; to_remove.Add(player); } else { gbl.CombatantCount++; } } } foreach (Player player in to_remove) { gbl.SelectedPlayer = ovr018.FreeCurrentPlayer(player, false, true); } }
/* camp_menu */ internal static void combat_menu(Player player) { int spell_id; Struct_1D183 var_D = new Struct_1D183(); char var_1; if (player.in_combat == true) { if (player.actions.spell_id > 0) { spell_id = player.actions.spell_id; player.actions.spell_id = 0; ovr023.sub_5D2E1(true, QuickFight.False, spell_id); ovr025.clear_actions(player); } else { bool var_2 = false; while (var_2 == false) { combat_menu(out var_1, player); if (gbl.displayInput_specialKeyPressed == false) { switch (var_1) { case 'Q': SetPlayerQuickFight(player); ovr027.ClearPromptArea(); seg043.clear_keyboard(); seg049.SysDelay(0x0C8); var_2 = true; ovr010.PlayerQuickFight(player); break; case 'M': sub_33B26(ref var_2, ' ', player); break; case 'V': var_2 = ovr020.viewPlayer(); ovr014.reclac_attacks(player); if (var_2 == false) { ovr025.RedrawCombatScreen(); } break; case 'A': var_2 = ovr014.aim_menu(var_D, true, false, true, -1, player); break; case 'U': gbl.menuSelectedWord = 2; ovr020.PlayerItemsMenu(ref var_2); ovr014.reclac_attacks(player); if (var_2 == false) { ovr025.RedrawCombatScreen(); } break; case 'C': ovr014.spell_menu3(out var_2, 0, 0); break; case 'T': ovr014.turns_undead(player); var_2 = true; ovr025.clear_actions(player); break; case 'D': delay_menu(ref var_2, player); break; case ' ': /* Turn off auto-fight. */ foreach (Player p in gbl.TeamList) { if (p.control_morale < Control.NPC_Base) { p.quick_fight = QuickFight.False; } } break; } } else { switch (var_1) { case 'G': case 'H': case 'K': case 'M': case 'O': case 'P': case 'Q': case 'I': sub_33B26(ref var_2, var_1, player); break; case '2': gbl.AutoPCsCastMagic = !gbl.AutoPCsCastMagic; if (gbl.AutoPCsCastMagic == true) { ovr025.string_print01("Magic On"); } else { ovr025.string_print01("Magic Off"); } break; case (char)0x10: player.actions.delay = 20; foreach (Player p in gbl.TeamList) { SetPlayerQuickFight(p); } ovr027.ClearPromptArea(); seg049.SysDelay(0x0C8); var_2 = true; break; case '-': if (ovr014.god_intervene() == true) { ovr033.RedrawCombatIfFocusOn(false, 3, player); var_2 = true; } else { ovr025.string_print01("That doesn't work"); } break; } } if (var_2 == false) { ovr033.RedrawCombatIfFocusOn(true, 2, player); gbl.display_hitpoints_ac = true; ovr025.CombatDisplayPlayerSummary(player); } } } } else { ovr025.clear_actions(player); } }
// sub_74E6F internal static void CombatantKilled(Player player) { if (gbl.game_state != GameState.Combat) { seg044.PlaySound(Sound.sound_5); seg041.GameDelay(); } else { bool downedPlayer = gbl.downedPlayers.Exists(cell => cell.target == player); if (!downedPlayer) { int player_index = GetPlayerIndex(player); var map = ovr033.PlayerMapPos(player); if (PlayerOnScreen(true, player) == false) { redrawCombatArea(8, 3, map); } RedrawPlayerBackground(player_index); seg044.PlaySound(Sound.sound_5); // Draw skull overlay DaxBlock attackIcon = gbl.combat_icons[24].GetIcon(Icon.Attack, 0); DaxBlock normalIcon = gbl.combat_icons[25].GetIcon(Icon.Normal, 0); var points = BuildSizeMap(gbl.CombatMap[player_index].size, gbl.CombatMap[player_index].screenPos); for (int var_3 = 0; var_3 <= 8; var_3++) { foreach (var pos in points) { if (CoordOnScreen(pos) == true) { DaxBlock tmp = ((var_3 & 1) == 0) ? attackIcon : normalIcon; seg040.OverlayBounded(tmp, 5, 0, (pos.y) * 3, (pos.x) * 3); } } seg040.DrawOverlay(); seg049.SysDelay(10); } // Add downed corpse for team players. if (player.actions.nonTeamMember == false) { var b = new Struct_1D183(); gbl.downedPlayers.Add(b); b.originalBackgroundTile = gbl.mapToBackGroundTile[map]; b.target = player; b.map = map; if (gbl.mapToBackGroundTile[map] != 0x1E) { gbl.mapToBackGroundTile[map] = 0x1F; } } // clean-up combat stuff seg041.GameDelay(); RedrawPlayerBackground(player_index); gbl.CombatMap[GetPlayerIndex(player)].size = 0; setup_mapToPlayerIndex_and_playerScreen(); redrawCombatArea(8, 3, gbl.mapToBackGroundTile.mapScreenTopLeft + Point.ScreenCenter); player.actions.delay = 0; player.actions.move = 0; player.actions.spell_id = 0; player.actions.guarding = false; } } }
/* sub_41B25 */ internal static bool aim_menu(Struct_1D183 arg_0, bool allowTarget, bool canTargetEmptyGround, bool showRange, int maxRange, Player attacker) { Player target; /* var_E5 */ ovr025.load_missile_dax(false, 0, 0, 0x19); arg_0.Clear(); bool arg_4 = false; if (maxRange == -1 || maxRange == 0xff) { if (attacker.activeItems.primaryWeapon != null) { maxRange = gbl.ItemDataTable[attacker.activeItems.primaryWeapon.type].range - 1; } else { maxRange = 1; } } if (maxRange == 0 || maxRange == -1 || maxRange == 0xff) { maxRange = 1; } SortedCombatant[] sorted_list = copy_sorted_players(attacker); int list_index = 1; int next_prev_step = 0; int target_step = 0; Point attackerPos = new Point(); target = step_combat_list(true, next_prev_step, ref list_index, ref attackerPos, sorted_list); next_prev_step = 1; char input = ' '; while (arg_4 == false && unk_41AE5.MemberOf(input) == false) { if (CanSeeTargetA(target, attacker) == false) { target = step_combat_list(false, next_prev_step, ref list_index, ref attackerPos, sorted_list); } else { input = aim_sub_menu(allowTarget, showRange, maxRange, target, attacker); if (gbl.displayInput_specialKeyPressed == false) { switch (input) { case 'N': next_prev_step = 1; target_step = 1; break; case 'P': next_prev_step = -1; target_step = -1; break; case 'M': case 'H': case 'K': case 'G': case 'O': case 'Q': case 'I': arg_4 = Target(arg_0, allowTarget, canTargetEmptyGround, showRange, maxRange, target, attacker); ovr025.load_missile_dax(false, 0, 0, 0x19); sorted_list = copy_sorted_players(attacker); target_step = 0; break; case 'T': arg_4 = sub_411D8(arg_0, showRange, target, attacker); ovr025.load_missile_dax(false, 0, 0, 0x19); sorted_list = copy_sorted_players(attacker); target_step = 0; break; case 'C': ovr033.redrawCombatArea(8, 0, ovr033.PlayerMapPos(target)); target_step = 0; break; } } else if (unk_41B05.MemberOf(input) == true) { arg_4 = Target(arg_0, allowTarget, canTargetEmptyGround, showRange, maxRange, target, attacker); ovr025.load_missile_dax(false, 0, 0, 0x19); sorted_list = copy_sorted_players(attacker); target_step = 0; } ovr033.RedrawPosition(ovr033.PlayerMapPos(target)); target = step_combat_list((arg_4 == false && unk_41AE5.MemberOf(input) == false), target_step, ref list_index, ref attackerPos, sorted_list); } } if (showRange) { seg037.draw8x8_clear_area(0x17, 0x27, 0x17, 0); } return arg_4; }
internal static bool Target(Struct_1D183 arg_0, bool allowTarget, bool canTargetEmptyGround, bool showRange, int maxRange, Player target, Player player01) { Item dummyItem; arg_0.Clear(); var pos = ovr033.PlayerMapPos(target); char input_key = ' '; byte dir = 8; bool arg_4 = false; gbl.mapToBackGroundTile.drawTargetCursor = true; gbl.mapToBackGroundTile.size = 1; while (asc_41342.MemberOf(input_key) == false) { ovr033.redrawCombatArea(dir, 3, pos); pos += gbl.MapDirectionDelta[dir]; pos.MapBoundaryTrunc(); int groundTile; int playerAtXY; ovr033.AtMapXY(out groundTile, out playerAtXY, pos); seg043.clear_keyboard(); bool can_target = false; int range = 255; if (ovr032.canReachTarget(ref range, pos, ovr033.PlayerMapPos(player01)) == true) { can_target = true; if (showRange) { string range_text = "Range = " + (range / 2).ToString() + " "; seg041.displayString(range_text, 0, 10, 0x17, 0); } } else { if (showRange) { seg037.draw8x8_clear_area(0x17, 0x27, 0x17, 0); } } range /= 2; target = null; if (can_target) { if (playerAtXY > 0) { target = gbl.player_array[playerAtXY]; } else if (groundTile == 0x1f) { var c = gbl.downedPlayers.Find(cell => cell.map == pos); if (c != null && c.target != null) { target = c.target; } } } if (target != null) { gbl.display_hitpoints_ac = true; ovr025.CombatDisplayPlayerSummary(target); } else { seg037.draw8x8_clear_area(TextRegion.CombatSummary); } if (range > maxRange || gbl.BackGroundTiles[groundTile].move_cost == 0xff) { can_target = false; } if (target != null) { if (CanSeeTargetA(target, player01) == false || allowTarget == false) { can_target = false; } if (showRange) { if (player01 == target || (playerAtXY == 0 && groundTile == 0x1f)) { can_target = false; } else if (ovr025.is_weapon_ranged(player01) == true && (ovr025.GetCurrentAttackItem(out dummyItem, player01) == false || (ovr025.BuildNearTargets(1, player01).Count > 0 && ovr025.is_weapon_ranged_melee(player01) == false))) { can_target = false; } } } else if (canTargetEmptyGround == false) { can_target = false; } string text = "Center Exit"; if (can_target) { text = "Target " + text; } input_key = ovr027.displayInput(false, 1, gbl.defaultMenuColors, text, "(Use Cursor keys) "); switch (input_key) { case '\r': case 'T': gbl.mapToBackGroundTile.drawTargetCursor = false; if (can_target) { arg_0.map = pos; if (target != null) { arg_0.target = target; } else { arg_0.target = null; } if (showRange) { arg_4 = sub_411D8(arg_0, showRange, arg_0.target, player01); } else { arg_4 = true; } } if (can_target == false || arg_4 == false) { ovr033.RedrawPosition(pos); arg_4 = false; arg_0.Clear(); } break; case 'H': dir = 0; break; case 'I': dir = 1; break; case 'M': dir = 2; break; case 'Q': dir = 3; break; case 'P': dir = 4; break; case 'O': dir = 5; break; case 'K': dir = 6; break; case 'G': dir = 7; break; case '\0': case 'E': ovr033.RedrawPosition(pos); arg_0.Clear(); arg_4 = false; break; case 'C': ovr033.redrawCombatArea(8, 0, pos); dir = 8; break; default: dir = 8; break; } } return arg_4; }
internal static bool target(QuickFight quick_fight, int spellId) { Struct_1D183 var_C = new Struct_1D183(); bool castSpell = true; gbl.spellTargets.Clear(); gbl.byte_1D2C7 = false; gbl.targetPos = ovr033.PlayerMapPos(gbl.SelectedPlayer); int tmp1 = gbl.spellCastingTable[spellId].field_6 & 0x0F; if (tmp1 == 0) { gbl.spellTargets.Clear(); gbl.spellTargets.Add(gbl.SelectedPlayer); } else if (tmp1 == 5) { int var_5 = 0; gbl.spellTargets.Clear(); int var_4; if (spellId == 0x4F) { var_4 = ovr025.spellMaxTargetCount(0x4F); } else { var_4 = ovr024.roll_dice(4, 2); } bool stop_loop = false; do { if (sub_4001C(var_C, false, quick_fight, spellId) == true) { bool found = gbl.spellTargets.Exists(st => st == var_C.target); if (found == false) { Player target = var_C.target; gbl.spellTargets.Add(target); gbl.targetPos = ovr033.PlayerMapPos(var_C.target); if (spellId != 0x4f) { byte hitDice = target.HitDice; if (hitDice == 0 || hitDice == 1) { var_5 += 1; } else if (hitDice == 2) { var_5 += 2; } else if (hitDice == 3) { var_5 += 4; } else { var_5 += 8; } } else { byte al = target.field_DE; if (al == 1) { var_5 += 1; } else if (al == 2 || al == 3) { var_5 += 2; } else if (al == 4) { var_5 += 4; } } if (gbl.spellTargets.Count > 0 && var_5 > var_4) { stop_loop = true; } } else { if (quick_fight != 0) { var_4 -= 1; } else { ovr025.string_print01("Already been targeted"); } } ovr033.RedrawPosition(ovr033.PlayerMapPos(var_C.target)); } else { stop_loop = true; } } while (stop_loop == false && var_4 != 0); } else if (tmp1 == 0x0F) { if (sub_4001C(var_C, false, quick_fight, spellId) == true) { if (gbl.SelectedPlayer.actions.target != null) { gbl.spellTargets.Clear(); gbl.spellTargets.Add(gbl.SelectedPlayer.actions.target); } else { /* TODO it doesn't make sense to mask the low nibble then shift it out */ var scl = ovr032.Rebuild_SortedCombatantList(1, (gbl.spellCastingTable[spellId].field_6 & 0x0f) >> 4, gbl.targetPos, sc => true); gbl.spellTargets.Clear(); foreach (var sc in scl) { gbl.spellTargets.Add(sc.player); } gbl.byte_1D2C7 = true; } } else { castSpell = false; } } else if (tmp1 >= 8 && tmp1 <= 0x0E) { if (sub_4001C(var_C, true, quick_fight, spellId) == true) { var scl = ovr032.Rebuild_SortedCombatantList(1, gbl.spellCastingTable[spellId].field_6 & 7, gbl.targetPos, sc => true); gbl.spellTargets.Clear(); foreach (var sc in scl) { gbl.spellTargets.Add(sc.player); } gbl.byte_1D2C7 = true; } else { castSpell = false; } } else { int max_targets = (gbl.spellCastingTable[spellId].field_6 & 3) + 1; gbl.spellTargets.Clear(); while (max_targets > 0) { if (sub_4001C(var_C, false, quick_fight, spellId) == true) { bool found = gbl.spellTargets.Exists(st => st == var_C.target); if (found == false) { gbl.spellTargets.Add(var_C.target); max_targets -= 1; gbl.targetPos = ovr033.PlayerMapPos(var_C.target); } else { if (quick_fight == 0) { ovr025.string_print01("Already been targeted"); } else { max_targets -= 1; } } ovr033.RedrawPosition(ovr033.PlayerMapPos(var_C.target)); } else { max_targets = 0; } } if (gbl.spellTargets.Count == 0) { castSpell = false; gbl.targetPos = new Point(); } //gbl.targetPos = ovr033.PlayerMapPos(gbl.spellTargets[gbl.spellTargets.Count-1]); } return castSpell; }
internal static bool sub_411D8(Struct_1D183 arg_0, bool showRange, Player target, Player attacker) { bool arg_4 = true; if (showRange && can_attack_target(target, attacker) == false) { arg_4 = false; } if (arg_4 == true) { arg_0.target = target; arg_0.map = ovr033.PlayerMapPos(target); gbl.mapToBackGroundTile.drawTargetCursor = false; ovr033.redrawCombatArea(8, 3, gbl.mapToBackGroundTile.mapScreenTopLeft + Point.ScreenCenter); if (showRange) { if (TrySweepAttack(target, attacker) == true) { arg_4 = true; ovr025.clear_actions(attacker); } else { RecalcAttacksReceived(target, attacker); Item rangedWeapon = null; if (ovr025.is_weapon_ranged(attacker) == true && ovr025.GetCurrentAttackItem(out rangedWeapon, attacker) == true && ovr025.is_weapon_ranged_melee(attacker) == true && ovr025.getTargetRange(target, attacker) == 0) { rangedWeapon = null; } arg_4 = AttackTarget(rangedWeapon, 0, target, attacker); } } } else { arg_0.Clear(); } return arg_4; }
internal static bool sub_4001C(Struct_1D183 arg_0, bool canTargetEmptyGround, QuickFight quick_fight, int spellId) { bool var_2 = false; if (quick_fight == QuickFight.False) { bool allowTarget = spellId != 0x53; var_2 = aim_menu(arg_0, allowTarget, canTargetEmptyGround, false, ovr023.SpellRange(spellId), gbl.SelectedPlayer); gbl.SelectedPlayer.actions.target = arg_0.target; } else if (gbl.spellCastingTable[spellId].field_E == 0) { arg_0.target = gbl.SelectedPlayer; if (spellId != 3 || find_healing_target(out arg_0.target, gbl.SelectedPlayer)) { arg_0.map = ovr033.PlayerMapPos(arg_0.target); var_2 = true; } } else { int var_9 = 1; while (var_9 > 0 && var_2 == false) { bool var_3 = true; if (find_target(true, 0, ovr023.SpellRange(spellId), gbl.SelectedPlayer) == true) { Player target = gbl.SelectedPlayer.actions.target; if (target.IsHeld() == true) { for (int i = 1; i <= 4; i++) { if (gbl.spellCastingTable[spellId].affect_id == unk_18ADB[i]) { var_3 = false; } } } if (var_3 == true) { arg_0.target = gbl.SelectedPlayer.actions.target; arg_0.map = ovr033.PlayerMapPos(arg_0.target); var_2 = true; } } var_9 -= 1; } } if (var_2 == true) { gbl.targetPos = arg_0.map; } else { arg_0.Clear(); } return var_2; }