From a89f47d30649fbad9918b032cef40cf3a6293f8a Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Fri, 28 Oct 2016 16:28:34 +0200 Subject: [PATCH] Added support for mark >1 expertise abilities --- serverdata/player/expertise_abilities.sdb | 50 +++++++++++ src/services/experience/ExpertiseService.java | 90 ++++++++++++++++--- 2 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 serverdata/player/expertise_abilities.sdb diff --git a/serverdata/player/expertise_abilities.sdb b/serverdata/player/expertise_abilities.sdb new file mode 100644 index 00000000..b67ce524 --- /dev/null +++ b/serverdata/player/expertise_abilities.sdb @@ -0,0 +1,50 @@ +skill chains +TEXT PRIMARY KEY TEXT +expertise_bh_armor_duelist_1 bh_armor_duelist_2;bh_armor_duelist_3;bh_armor_duelist_4;bh_armor_duelist_5 +expertise_bh_intimidate_1 bh_intimidate_2;bh_intimidate_3;bh_intimidate_4;bh_intimidate_5;bh_intimidate_6 +expertise_bh_sniper_1 bh_sniper_2;bh_sniper_3;bh_sniper_4;bh_sniper_5;bh_sniper_6 +expertise_bh_stun_1 bh_stun_2;bh_stun_3;bh_stun_4;bh_stun_5 +expertise_bh_surprise_1 bh_dm_crit_3;bh_dm_crit_4;bh_dm_crit_5;bh_dm_crit_6;bh_dm_crit_7;bh_dm_crit_8 +expertise_bh_taunt_1 bh_taunt_2;bh_taunt_3;bh_taunt_4;bh_taunt_5;bh_taunt_6 +expertise_co_focus_beam_1 co_hw_dm_2;co_hw_dm_3;co_hw_dm_4;co_hw_dm_5;co_hw_dm_6 +expertise_co_lethal_beam_1 co_hw_dm_crit_2;co_hw_dm_crit_3;co_hw_dm_crit_4;co_hw_dm_crit_5;co_hw_dm_crit_6 +expertise_en_heal_1 en_heal_2;en_heal_3;en_heal_4 +expertise_en_project_will_1 en_project_will_1;en_project_will_2;en_project_will_3;en_project_will_4;en_project_will_5;en_project_will_6 +expertise_en_spiral_kick_1 en_spiral_kick_1;en_spiral_kick_2;en_spiral_kick_3;en_spiral_kick_4 +expertise_en_strike_1 en_strike_1;en_strike_2;en_strike_3;en_strike_4;en_strike_5;en_strike_6 +expertise_en_sweeping_pirouette_1 en_sweeping_pirouette_1;en_sweeping_pirouette_2;en_sweeping_pirouette_3;en_sweeping_pirouette_4;en_sweeping_pirouette_5 +expertise_en_thrill_1 en_thrill_1;en_thrill_2 +expertise_en_void_dance_1 en_void_dance_2;en_void_dance_3 +expertise_fs_general_force_shockwave_1 fs_dm_cc_crit_2;fs_dm_cc_crit_3;fs_dm_cc_crit_4;fs_dm_cc_crit_5 +expertise_fs_path_dark_lightning_1 fs_ae_dm_cc_2;fs_ae_dm_cc_3;fs_ae_dm_cc_4;fs_ae_dm_cc_5;fs_ae_dm_cc_6 +expertise_fs_path_flurry fs_flurry_2;fs_flurry_3;fs_flurry_4;fs_flurry_5;fs_flurry_6;fs_flurry_7 +expertise_fs_path_force_choke_1 fs_dm_cc_2;fs_dm_cc_3;fs_dm_cc_4;fs_dm_cc_5;fs_dm_cc_6 +expertise_fs_path_force_drain_1 fs_drain_2;fs_drain_3;fs_drain_4;fs_drain_5 +expertise_fs_path_maelstrom_1 fs_maelstrom_2;fs_maelstrom_3;fs_maelstrom_4;fs_maelstrom_5 +expertise_me_bacta_bomb_1 me_bacta_bomb_2;me_bacta_bomb_3;me_bacta_bomb_4;me_bacta_bomb_5 +expertise_me_bacta_grenade_1 me_bacta_grenade_2;me_bacta_grenade_3;me_bacta_grenade_4;me_bacta_grenade_5 +expertise_me_burst_1 me_burst_2;me_burst_3;me_burst_4;me_burst_5 +expertise_me_cranial_smash_1 me_cranial_smash_2;me_cranial_smash_3;me_cranial_smash_4;me_cranial_smash_5 +expertise_me_enhance_agility_1 me_enhance_agility_2;me_enhance_agility_3 +expertise_me_enhance_precision_1 me_enhance_precision_2;me_enhance_precision_3 +expertise_me_enhance_strength_1 me_enhance_strength_2;me_enhance_strength_3 +expertise_me_enhancement_specialist_1 me_enhance_action_2;me_enhance_action_3|me_buff_health_2;me_buff_health_3 +expertise_of_advanced_paint_1 of_deb_def_4;of_deb_def_5;of_deb_def_6;of_deb_def_7;of_deb_def_8 +expertise_of_advanced_tactics_1 of_buff_def_4;of_buff_def_5;of_buff_def_6;of_buff_def_7;of_buff_def_8;of_buff_def_9 +expertise_of_decapitate_1 of_decapitate_2;of_decapitate_3;of_decapitate_4;of_decapitate_5;of_decapitate_6 +expertise_of_focus_fire_1 of_focus_fire_2;of_focus_fire_3;of_focus_fire_4;of_focus_fire_5;of_focus_fire_6 +expertise_of_inspiration_1 of_inspiration_2;of_inspiration_3;of_inspiration_4;of_inspiration_5;of_inspiration_6 +expertise_of_leg_strike_1 of_leg_strike_2;of_leg_strike_3;of_leg_strike_4;of_leg_strike_5;of_leg_strike_6;of_leg_strike_7 +expertise_of_medical_sup_1 of_medical_sup_2;of_medical_sup_3;of_medical_sup_4;of_medical_sup_5;of_medical_sup_6 +expertise_of_reinforcements_1 of_reinforcements_2;of_reinforcements_3;of_reinforcements_4;of_reinforcements_5 +expertise_of_vortex_1 of_vortex_2;of_vortex_3;of_vortex_4;of_vortex_5 +expertise_sm_general_bad_odds_1 sm_bad_odds_2;sm_bad_odds_3;sm_bad_odds_4;sm_bad_odds_5 +expertise_sm_general_narrow_escape_1 sm_narrow_escape_2;sm_narrow_escape_3;sm_narrow_escape_4 +expertise_sm_general_spot_a_sucker_1 sm_spot_a_sucker_2;sm_spot_a_sucker_3;sm_spot_a_sucker_4 +expertise_sm_path_pistol_whip_1 sm_pistol_whip_2;sm_pistol_whip_3;sm_pistol_whip_4 +expertise_sm_path_shoot_first_1 sm_shoot_first_2;sm_shoot_first_3;sm_shoot_first_4;sm_shoot_first_5 +expertise_sp_cloaked_attacks_1 sp_stealth_melee_1;sp_stealth_melee_2;sp_stealth_melee_3;sp_stealth_melee_4;sp_stealth_melee_5;sp_stealth_melee_6|sp_stealth_melee_1;sp_stealth_ranged_2;sp_stealth_ranged_3;sp_stealth_ranged_4;sp_stealth_ranged_5;sp_stealth_ranged_6 +expertise_sp_cloaked_recovery_1 sp_cloaked_recovery_1;sp_cloaked_recovery_2;sp_cloaked_recovery_3;sp_cloaked_recovery_4 +expertise_sp_hidden_daggers_1 sp_hd_melee_1;sp_hd_melee_2;sp_hd_melee_3;sp_hd_melee_4;sp_hd_melee_5;sp_hd_melee_6|sp_hd_ranged_1;sp_hd_ranged_2;sp_hd_ranged_3;sp_hd_ranged_4;sp_hd_ranged_5;sp_hd_ranged_6 +expertise_sp_improved_arachnids_web_1 sp_improved_cc_dot_2;sp_improved_cc_dot_3;sp_improved_cc_dot_4 +expertise_sp_improved_spys_fang_1 sp_dot_1;sp_dot_2;sp_dot_3;sp_dot_4;sp_dot_5 diff --git a/src/services/experience/ExpertiseService.java b/src/services/experience/ExpertiseService.java index bb9b0cce..02ef4ec5 100644 --- a/src/services/experience/ExpertiseService.java +++ b/src/services/experience/ExpertiseService.java @@ -30,10 +30,17 @@ package services.experience; import intents.experience.GrantSkillIntent; import intents.experience.LevelChangedIntent; import intents.network.GalacticPacketIntent; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import network.packets.Packet; import network.packets.swg.zone.ExpertiseRequestMessage; +import resources.Location; import resources.client_info.ClientFactory; import resources.client_info.visitors.DatatableData; import resources.control.Intent; @@ -42,6 +49,8 @@ import resources.objects.creature.CreatureObject; import resources.objects.player.PlayerObject; import resources.player.Player; import resources.server_info.Log; +import resources.server_info.RelationalDatabase; +import resources.server_info.RelationalServerFactory; /** * @@ -49,13 +58,17 @@ import resources.server_info.Log; */ public final class ExpertiseService extends Service { + private static final String EXPERTISE_ABILITIES_QUERY = "SELECT * FROM expertise_abilities"; + private final Map expertiseSkills; // Expertise skill to tree ID private final Map> trees; // Tree ID to tree + private final Map> expertiseAbilities; // Expertise skill to abilities private final Map pointsForLevel; // Level to points available public ExpertiseService() { trees = new HashMap<>(); expertiseSkills = new HashMap<>(); + expertiseAbilities = new HashMap<>(); pointsForLevel = new HashMap<>(); registerForIntent(GalacticPacketIntent.TYPE); @@ -75,7 +88,7 @@ public final class ExpertiseService extends Service { public boolean initialize() { loadTrees(); loadPointsForLevel(); - return super.initialize() && loadExpertise(); + return super.initialize() && loadExpertise() && loadAbilities(); } private void loadTrees() { @@ -122,6 +135,40 @@ public final class ExpertiseService extends Service { return true; } + private boolean loadAbilities() { + Log.i(this, "Loading expertise abilities..."); + long startTime = System.nanoTime(); + int abilityCount = 0; + + try (RelationalDatabase abilityDatabase = RelationalServerFactory.getServerData("player/expertise_abilities.db", "expertise_abilities")) { + try (ResultSet set = abilityDatabase.executeQuery(EXPERTISE_ABILITIES_QUERY)) { + while (set.next()) { + String skill = set.getString("skill"); + String[] chains = set.getString("chains").split("\\|"); + + Collection abilityChains = new ArrayList<>(); + + for (int i = 0; i < chains.length; i++) { + String chain = chains[i]; + String[] abilities = chain.split(";"); + + abilityChains.add(abilities); + abilityCount += abilities.length; + } + + expertiseAbilities.put(skill, abilityChains); + } + } catch (SQLException e) { + Log.e(this, e); + return false; + } + } + + Log.i(this, "Finished loading %d expertise abilities in %fms", abilityCount, (System.nanoTime() - startTime) / 1E6); + + return true; + } + private void loadPointsForLevel() { DatatableData playerLevelTable = (DatatableData) ClientFactory.getInfoFromFile("datatables/player/player_level.iff", false); int points = 0; @@ -169,7 +216,6 @@ public final class ExpertiseService extends Service { continue; } - // TODO below actually works, but the GrantSkillIntent from the previous iteration hasn't necessarily been processed yet! This can cause the check below to fail int requiredTreePoints = (expertise.getTier() - 1) * 4; if (requiredTreePoints > getPointsInTree(tree, creatureObject)) { @@ -181,6 +227,8 @@ public final class ExpertiseService extends Service { intent.broadcast(); while(!intent.isComplete()); // Block until the GrantSkillIntent has been processed } + + checkExtraAbilities(creatureObject); } private void handleLevelChangedIntent(LevelChangedIntent i) { @@ -192,23 +240,45 @@ public final class ExpertiseService extends Service { creatureObject.addSkill("expertise"); } - grantExtraAbilities(creatureObject); + checkExtraAbilities(creatureObject); } private void handleGrantSkillIntent(GrantSkillIntent i) { - if (i.getIntentType() != GrantSkillIntent.IntentType.GIVEN) { + if (i.getIntentType() == GrantSkillIntent.IntentType.GIVEN) { return; } - grantExtraAbilities(i.getTarget()); + // Let's check if this is an expertise skill that gives them additional commands + checkExtraAbilities(i.getTarget()); } - private void grantExtraAbilities(CreatureObject creatureObject) { - // based on their level, they may have unlocked new marks of the abilities given by this expertise skill - // TODO We need to grant ability commands if they have the correct skill. Algorithm if possible, SDB otherwise + private void checkExtraAbilities(CreatureObject creatureObject) { + creatureObject.getSkills().stream() + .filter(expertiseAbilities::containsKey) // We only want to check skills that give additional abilities + .forEach(expertise -> grantExtraAbilities(creatureObject, expertise)); + } + + private boolean isQualified(CreatureObject creatureObject, int abilityIndex) { + int baseRequirement = 18; + int levelDifference = 12; // Amount of levels between each ability + int level = creatureObject.getLevel(); + int requiredLevel = baseRequirement + abilityIndex * levelDifference; - // Loop over expertise skills - // For each expertise skill, check if this level unlocks ability marks + // TODO what if requiredLevel goes above the maximum level possible for a player? + System.out.println("required level: " + requiredLevel); + return level >= requiredLevel; + } + + private void grantExtraAbilities(CreatureObject creatureObject, String expertise) { + expertiseAbilities.get(expertise).forEach(chain -> { + for (int abilityIndex = 1; abilityIndex <= chain.length; abilityIndex++) { + String ability = chain[abilityIndex - 1]; + + if (isQualified(creatureObject, abilityIndex) && !creatureObject.hasAbility(ability)) { + creatureObject.addAbility(ability); + } + } + }); } private String formatProfession(String profession) {