package script.library; import script.*; import java.util.Iterator; import java.util.Vector; public class xp extends script.base_script { public xp() { } public static final float COMBAT_GENERAL_EXCHANGE_RATE = 0.10f; public static final float JEDI_GENERAL_EXCHANGE_RATE = 0.18f; public static final float SOCIAL_ENTERTAINER_EXCHANGE_RATE = 1.0f; public static final float CRAFTING_MERCHANT_EXCHANGE_RATE = 0.25f; public static final float SQUADLEADER_XP_RATIO = 1.0f; public static final float SOCIAL_COMBAT_XP_MOD = 1.0f; public static final String VAR_SQUADLEADER_BASE = "squadleader"; public static final String VAR_SQUADLEADER_XP = VAR_SQUADLEADER_BASE + ".xp"; public static final String VAR_SQUADLEADER_AT_CAP = VAR_SQUADLEADER_BASE + ".atCap"; public static final String VAR_SQUADLEADER_GROUP_SIZE = VAR_SQUADLEADER_BASE + ".groupSize"; public static final String XP = "xp"; public static final String WEAPON_TYPE = "weaponType"; public static final String GRANT_XP_RESULT_VALUE = "delta"; public static final String GRANT_XP_RETURN_DATA = "data"; public static final float FACTIONAL_WINNING_XP_BONUS = 1.15f; public static final String SCOUT = "scout"; public static final String TRAPPING = "trapping"; public static final String BOUNTYHUNTER = "bountyhunter"; public static final String SMUGGLER = "smuggler"; public static final String SQUADLEADER = "squadleader"; public static final String SLICING = "slicing"; public static final String IMAGEDESIGNER = "imagedesigner"; public static final String RANGER = "ranger"; public static final String FARMER = "farmer"; public static final String INDUSTRIALIST = "industralist"; public static final String BIO_ENGINEER = "bio_engineer"; public static final String BIO_ENGINEER_DNA_HARVESTING = "bio_engineer_dna_harvesting"; public static final String HARVEST_ORGANIC = "resource_harvesting_organic"; public static final String HARVEST_INORGANIC = "resource_harvesting_inorganic"; public static final String CRAFTING_GENERAL = "crafting_general"; public static final String CRAFTING_FOOD_GENERAL = "crafting_food_general"; public static final String CRAFTING_MEDICINE_GENERAL = "crafting_medical_general"; public static final String CRAFTING_CLOTHING_ARMOR = "crafting_clothing_armor"; public static final String CRAFTING_CLOTHING_GENERAL = "crafting_clothing_general"; public static final String CRAFTING_WEAPONS_GENERAL = "crafting_weapons_general"; public static final String CRAFTING_WEAPONS_MELEE = "crafting_weapons_melee"; public static final String CRAFTING_WEAPONS_RANGED = "crafting_weapons_ranged"; public static final String CRAFTING_WEAPONS_MUNITION = "crafting_weapons_munition"; public static final String CRAFTING_STRUCTURE_GENERAL = "crafting_structure_general"; public static final String CRAFTING_DROID_GENERAL = "crafting_droid_general"; public static final String CRAFTING_SHIPWRIGHT = "shipwright"; public static final String MERCHANT = "merchant"; public static final String CRAFTING_BIO_ENGINEER_CREATURE = "crafting_bio_engineer_creature"; public static final String CRAFTING_BIO_ENGINEER_TISSUE = "crafting_bio_engineer_tissue"; public static final String COMBAT_JEDI_ONEHANDLIGHTSABER = "combat_meleespecialize_onehandlightsaber"; public static final String COMBAT_JEDI_TWOHANDLIGHTSABER = "combat_meleespecialize_twohandlightsaber"; public static final String COMBAT_JEDI_POLEARMLIGHTSABER = "combat_meleespecialize_polearmlightsaber"; public static final String COMBAT_JEDI_FORCE_POWER = "jedi_force"; public static final String JEDI_GENERAL = "jedi_general"; public static final String COMBAT_GENERAL = "combat_general"; public static final String COMBAT_MELEESPECIALIZE_UNARMED = "combat_meleespecialize_unarmed"; public static final String COMBAT_MELEESPECIALIZE_ONEHAND = "combat_meleespecialize_onehand"; public static final String COMBAT_MELEESPECIALIZE_TWOHAND = "combat_meleespecialize_twohand"; public static final String COMBAT_MELEESPECIALIZE_POLEARM = "combat_meleespecialize_polearm"; public static final String COMBAT_RANGEDSPECIALIZE_RIFLE = "combat_rangedspecialize_rifle"; public static final String COMBAT_RANGEDSPECIALIZE_PISTOL = "combat_rangedspecialize_pistol"; public static final String COMBAT_RANGEDSPECIALIZE_CARBINE = "combat_rangedspecialize_carbine"; public static final String COMBAT_RANGEDSPECIALIZE_HEAVY = "combat_rangedspecialize_heavy"; public static final String COMBAT_THROWN = "combat_thrown"; public static final String COMBAT_GRENADE = "combat_grenade"; public static final String CREATUREHANDLER = "creaturehandler"; public static final String COMBATMEDIC = "combatmedic"; public static final String MEDICAL = "medical"; public static final String SPACE_COMBAT_GENERAL = "space_combat_general"; public static final String SPACE_PRESTIGE_IMPERIAL = "prestige_imperial"; public static final String SPACE_PRESTIGE_REBEL = "prestige_rebel"; public static final String SPACE_PRESTIGE_PILOT = "prestige_pilot"; public static final String MUSIC = "music"; public static final String DANCE = "dance"; public static final String JUGGLING = "juggling"; public static final String ENTERTAINER = "entertainer"; public static final String QUEST_SOCIAL = "quest_social"; public static final String QUEST_COMBAT = "quest_combat"; public static final String QUEST_CRAFTING = "quest_crafting"; public static final String QUEST_GENERAL = "quest_general"; public static final String APPRENTICESHIP = "apprenticeship"; public static final String PERMISSIONS_ONLY = "permissions_only"; public static final String RAW_COMBAT = "raw_combat"; public static final String PARTIAL_COMBAT = "partial_combat"; public static final String PET_DAMAGE = "pet_damage"; public static final String POLITICAL = "political"; public static final String UNKNOWN = "unknown"; public static final String STF_XP_N = "exp_n"; public static final string_id SID_SCOUT = new string_id(STF_XP_N, SCOUT); public static final string_id SID_HARVEST_ORGANIC = new string_id(STF_XP_N, HARVEST_ORGANIC); public static final string_id SID_HARVEST_INORGANIC = new string_id(STF_XP_N, HARVEST_INORGANIC); public static final string_id PROSE_GRANT_XP = new string_id("base_player", "prose_grant_xp"); public static final string_id PROSE_GRANT_GROUP_XP = new string_id("base_player", "prose_grant_group_xp"); public static final string_id PROSE_GRANT_BUFF_XP = new string_id("base_player", "prose_grant_buff_xp"); public static final string_id PROSE_GRANT_GROUP_BUFF_XP = new string_id("base_player", "prose_grant_group_buff_xp"); public static final string_id PROSE_REVOKE_XP = new string_id("base_player", "prose_revoke_xp"); public static final string_id PROSE_GRANT_XP_BONUS = new string_id("base_player", "prose_grant_xp_bonus"); public static final string_id PROSE_GRANT_XP1 = new string_id("base_player", "prose_grant_xp1"); public static final string_id PROSE_REVOKE_XP1 = new string_id("base_player", "prose_revoke_xp1"); public static final String VAR_CREDIT_FOR_KILLS = "creditForKills"; public static final String VAR_NPC_DAMAGE = VAR_CREDIT_FOR_KILLS + ".npcDamage"; public static final String VAR_ATTACKER_LIST = VAR_CREDIT_FOR_KILLS + ".attackerList"; public static final String VAR_DAMAGE_TALLY = VAR_CREDIT_FOR_KILLS + ".damageTally"; public static final String VAR_DAMAGE_COUNT = VAR_CREDIT_FOR_KILLS + ".damageCount"; public static final String VAR_COMBAT_TIMESTAMP = VAR_CREDIT_FOR_KILLS + ".timestamp"; public static final int MAX_PLAYERS = 30; public static final int MAX_DISTANCE = 190; public static final double PRIM_KILL_PERCENT = .2; public static final double PERCENT_ADJUSTER = .0; public static final double PLAYER_RATIO_ADJUST = .1; public static final float COMBAT_XP_EXCHANGE = .10f; public static final float MAX_NPC_DAMAGE_PERCENT = 0.65f; public static final float PERCENT_DAMAGE_BAR_BASE = 0.00f; public static final float GROUP_XP_BONUS = 0.35f; public static final float GROUP_XP_DIVIDER = 0.6f; public static final int MAX_GROUP_BONUS_COUNT = 8; public static final float TRADER_XP_MOD = 7.6f; public static final float ENTERTAINER_XP_MOD = 3.4f; public static final String VAR_COMBAT_RESULTS = "combatResults"; public static final String VAR_TOP_DAMAGE = VAR_COMBAT_RESULTS + ".top_damage"; public static final String VAR_TOP_GROUP = VAR_COMBAT_RESULTS + ".top_group"; public static final String VAR_TOP_DAMAGERS = VAR_COMBAT_RESULTS + ".top_damagers"; public static final String VAR_LANDED_DEATHBLOW = VAR_COMBAT_RESULTS + ".landed_deathblow"; public static final String HANDLER_XP_DELEGATED = "xpDelegated"; public static final String TBL_SKILL = "datatables/skill/skills.iff"; public static final String TBL_SPECIES_XP = "datatables/xp/species.iff"; public static final String TBL_PLAYER_LEVEL_XP = "datatables/player/player_level.iff"; public static final String CREATURES_TABLE = "datatables/mob/creatures.iff"; public static final string_id SID_INSPIRE_BONUS = new string_id("performance", "perform_inspire_xp_bonus"); public static final string_id SID_FLYTEXT_XP = new string_id("base_player", "prose_flytext_xp"); public static final string_id SID_FLYTEXT_XP_GROUP = new string_id("base_player", "prose_flytext_xp_group"); public static final int TRIAL_LEVEL_CAP = 25; public static final string_id SID_FREE_TRIAL_LEVEL_CAP = new string_id("base_player", "free_trial_level_cap"); public static int grant(obj_id target, String xp_type, int amt) throws InterruptedException { return grant(target, xp_type, amt, true, null, null, null); } public static int grant(obj_id target, String xp_type, int amt, String callback) throws InterruptedException { return grant(target, xp_type, amt, true, callback, new dictionary(), getSelf()); } public static int grant(obj_id target, String xp_type, int amt, String callback, dictionary callbackData) throws InterruptedException { return grant(target, xp_type, amt, true, callback, callbackData, getSelf()); } public static int grant(obj_id target, String xp_type, int amt, String callback, dictionary callbackData, obj_id callbackId) throws InterruptedException { return grant(target, xp_type, amt, true, callback, callbackData, callbackId); } public static int grant(obj_id target, String xp_type, int amt, boolean verbose) throws InterruptedException { return grant(target, xp_type, amt, verbose, null, null, null); } public static int grant(obj_id target, String xp_type, int amt, boolean verbose, String callback, dictionary callbackData) throws InterruptedException { return grant(target, xp_type, amt, verbose, callback, callbackData, getSelf()); } public static int grant(obj_id target, String xp_type, int amt, boolean verbose, String callback, dictionary callbackData, obj_id callbackId) throws InterruptedException { if (!isIdValid(target) || (xp_type == null) || (xp_type.equals(""))) { return 0; } if (xp_type.contains(" ")) { return 0; } amt = applySpeciesXpModifier(target, xp_type, amt); amt = applyInspirationBuffXpModifier(target, xp_type, amt); if (amt == 0) { return 0; } if (grantUnmodifiedExperience(target, xp_type, amt, verbose, callback, callbackData, callbackId)) { return amt; } else { return 0; } } public static boolean grantUnmodifiedExperience(obj_id target, String xp_type, int amt) throws InterruptedException { return grantUnmodifiedExperience(target, xp_type, amt, true, null, null, null); } public static boolean grantUnmodifiedExperience(obj_id target, String xp_type, int amt, boolean verbose) throws InterruptedException { return grantUnmodifiedExperience(target, xp_type, amt, verbose, null, null, null); } public static boolean grantUnmodifiedExperience(obj_id target, String xp_type, int amt, String callback) throws InterruptedException { return grantUnmodifiedExperience(target, xp_type, amt, true, callback, new dictionary(), getSelf()); } public static boolean grantUnmodifiedExperience(obj_id target, String xp_type, int amt, String callback, dictionary callbackData) throws InterruptedException { return grantUnmodifiedExperience(target, xp_type, amt, true, callback, callbackData, getSelf()); } public static boolean grantUnmodifiedExperience(obj_id target, String xp_type, int amt, String callback, dictionary callbackData, obj_id callbackId) throws InterruptedException { return grantUnmodifiedExperience(target, xp_type, amt, true, callback, callbackData, callbackId); } public static boolean grantUnmodifiedExperience(obj_id target, String xp_type, int amt, boolean verbose, String callback, dictionary callbackData, obj_id callbackId) throws InterruptedException { if (!isIdValid(target) || (xp_type == null) || (xp_type.equals(""))) { return false; } if (xp_type.contains(" ")) { return false; } dictionary params = new dictionary(); params.put("xp_type", xp_type); params.put("amt", amt); if (callback != null && callback.length() > 0) { params.put("fromId", callbackId); params.put("fromCallback", callback); if (callbackData == null) { callbackData = new dictionary(); } params.put("fromCallbackData", callbackData); } messageTo(target, "grantUnmodifiedExperienceOnSelf", params, 0.1f, !target.isAuthoritative()); if (verbose) { displayXpMsg(target, xp_type, amt); } int currentXp = getExperiencePoints(target, xp_type); int xpCap = getExperienceCap(target, xp_type); return currentXp < xpCap; } public static boolean _grantUnmodifiedExperience(obj_id target, String xp_type, int amt, String callback, dictionary callbackData, obj_id callbackId) throws InterruptedException { int delta = 0; int prior = getExperiencePoints(target, xp_type); boolean result = false; if (grantExperiencePoints(target, xp_type, amt) != XP_ERROR) { result = true; int current = getExperiencePoints(target, xp_type); delta = current - prior; if (skill_template.isQualifiedForWorkingSkill(target)) { skill_template.earnWorkingSkill(target); } metrics.doXpRateMetrics(target, xp_type, amt); } if (isIdValid(callbackId)) { dictionary returnParams = new dictionary(); returnParams.put(GRANT_XP_RESULT_VALUE, delta); if (callbackData != null) { returnParams.put(GRANT_XP_RETURN_DATA, callbackData); } messageTo(callbackId, callback, returnParams, 0.1f, !callbackId.isAuthoritative()); } return result; } public static boolean grantCraftingXpChance(obj_id item, obj_id user, int chance) throws InterruptedException { if (!isIdValid(item)) { return false; } removeObjVar(item, "crafting.creator.xp"); removeObjVar(item, "crafting.creator.pxp"); return true; } public static int applySpeciesXpModifier(obj_id target, String xp_type, int amt) throws InterruptedException { xp_type = toLower(xp_type); int mod_xp = (int)(amt * getSpeciesXpModifier(target, xp_type)); if (utils.hasScriptVar(target, "buff.dish_ormachek.value")) { float xp_mod = utils.getFloatScriptVar(target, "buff.dish_ormachek.value"); float f_mod = 1f + (xp_mod / 100f); int dur = 20; if (utils.hasScriptVar(target, "buff.dish_ormachek.duration")) { dur = (int)utils.getFloatScriptVar(target, "buff.dish_ormachek.duration"); } dur--; if (dur <= 0) { buff.removeBuff(target, "dish_ormachek"); } else { utils.setScriptVar(target, "buff.dish_ormachek.duration", dur); } mod_xp = (int)(mod_xp * f_mod); } return mod_xp; } public static int applyGroupXpModifier(obj_id target, int amt) throws InterruptedException { float mod = 1f; int modAmt = amt; if (amt > 0) { obj_id gid = getGroupObject(target); int activeGroupSize = getActiveGroupSize(gid); if (activeGroupSize <= 2) { return modAmt; } mod = getGroupXpModifier(target, activeGroupSize); modAmt = Math.round(amt * mod); modAmt = (int)(modAmt / (1 + ((activeGroupSize - 1) * GROUP_XP_DIVIDER))); } utils.setScriptVar(target, "combat.xp.groupBonus", mod); return modAmt; } public static int applyInspirationBuffXpModifier(obj_id target, String xp_type, int amt) throws InterruptedException { if (amt > 0) { float mod = getInspirationBuffXpModifier(target, xp_type); float modAmt = (float)amt * mod; return Math.round(modAmt); } else { return amt; } } public static float getGroupXpModifier(obj_id target, int activeGroupSize) throws InterruptedException { float bonusMod = 1f; float groupXPBonus = GROUP_XP_BONUS; if (activeGroupSize > 1) { bonusMod += groupXPBonus * activeGroupSize; } return bonusMod; } public static float getSpeciesXpModifier(obj_id target, String xp_type) throws InterruptedException { if (!isIdValid(target) || xp_type == null || xp_type.equals("")) { return 1f; } int species = getSpecies(target); String[] xpMods = dataTableGetStringColumn(TBL_SPECIES_XP, species); if (xpMods != null && xpMods.length > 0) { String[] s; for (String xpMod : xpMods) { if (xpMod.startsWith(xp_type)) { s = split(xpMod, ':'); if ((s != null) && (s.length == 2)) { int val = utils.stringToInt(s[1]); if (val != -1) { return (100f + val) / 100f; } } } } } return 1f; } public static float getInspirationBuffXpModifier(obj_id target, String xp_type) throws InterruptedException { float mod = 1f; if (utils.hasScriptVar(target, "buff.xpBonus.types")) { String[] xpList = utils.getStringArrayScriptVar(target, "buff.xpBonus.types"); if (xpList != null && xpList.length > 0) { for (String aXpList : xpList) { if (aXpList.equals(xp_type)) { mod += utils.getFloatScriptVar(target, "buff.xpBonus.value"); } } } } if (utils.hasScriptVar(target, "buff.xpBonusGeneral.types")) { String[] xpList = utils.getStringArrayScriptVar(target, "buff.xpBonusGeneral.types"); if (xpList != null && xpList.length > 0) { for (String aXpList : xpList) { if (aXpList.equals(xp_type)) { mod += utils.getFloatScriptVar(target, "buff.xpBonusGeneral.value"); } } } } return mod; } public static void grantSquadLeaderXp(obj_id player, int amt) throws InterruptedException { if (!isIdValid(player) || !player.isLoaded() || amt < 1 || !hasSkill(player, "class_officer_phase1_novice")) { return; } dictionary resultData = new dictionary(); resultData.put("player", player); resultData.put("amt", amt); grant(player, SQUADLEADER, amt, false, "grantSquadLeaderXpResult", resultData, player); } public static void grantSquadLeaderXpResult(obj_id player, int granted, int amt) throws InterruptedException { if (granted > 0) { int slxp = utils.getIntScriptVar(player, VAR_SQUADLEADER_XP); slxp += granted; utils.setScriptVar(player, VAR_SQUADLEADER_XP, slxp); if (granted < amt) { utils.setScriptVar(player, VAR_SQUADLEADER_AT_CAP, true); } notifySquadLeaderXp(player); } } public static void notifySquadLeaderXp(obj_id player) throws InterruptedException { if (!isIdValid(player) || !player.isLoaded()) { return; } string_id sid_xp = new string_id(STF_XP_N, SQUADLEADER); int slxp = utils.getIntScriptVar(player, VAR_SQUADLEADER_XP); if (slxp > 0) { prose_package pp = getXpProsePackage(SQUADLEADER, slxp); if (pp != null) { sendSystemMessageProse(player, pp); } } if (utils.hasScriptVar(player, VAR_SQUADLEADER_AT_CAP)) { prose_package ppAtCap = prose.getPackage(new string_id("base_player", "prose_hit_xp_cap"), sid_xp); sendSystemMessageProse(player, ppAtCap); } utils.removeScriptVarTree(player, VAR_SQUADLEADER_BASE); } public static int getRawCombatXP(obj_id player, obj_id npc) throws InterruptedException { if (isMob(npc) && (isPlayer(npc) || isIdValid(getMaster(npc)))) { return 0; } float baseCombatXP = getLevelBasedXP(player, npc); return Math.round(baseCombatXP); } public static int getActiveGroupSize(obj_id gid) throws InterruptedException { if (!group.isGroupObject(gid)) { return 1; } obj_id[] members = getGroupMemberIds(gid); if (members == null || members.length == 0) { return 1; } int count = 0; for (obj_id member : members) { if (member.isLoaded() && isPlayer(member)) { count++; } if (count >= MAX_GROUP_BONUS_COUNT) { break; } } return count; } public static int getLevelBasedXP(obj_id player, obj_id npc) throws InterruptedException { int level = getLevel(player); int levelDiff = combat.getAiLevelDiff(npc, player); if (levelDiff > 0) { level += levelDiff; } int xp = getLevelBasedXP(level); if (!isMob(npc)) { xp = getIntObjVar(npc, "combat.intCombatXP"); } float bonus = 0f; if (aiIsKiller(npc) || aiIsAggressive(npc) || aiIsAssist(npc)) { bonus += 0.05f; } xp += (int)(xp * bonus); if (levelDiff < 0) { float maxLevelDiff = 10f; if (level > 20) { maxLevelDiff += (level - 20) / 6; } xp += (int)(xp * (levelDiff / maxLevelDiff)); if (xp < 1) { xp = 1; } } return xp; } public static int getLevelBasedXP(int level) throws InterruptedException { if (level < 1) { level = 1; } return dataTableGetInt("datatables/mob/stat_balance.iff", level - 1, "XP"); } public static String getWeaponXpType(int weapon_type) throws InterruptedException { String xp_type; switch (weapon_type) { case WEAPON_TYPE_RIFLE: xp_type = COMBAT_RANGEDSPECIALIZE_RIFLE; break; case WEAPON_TYPE_LIGHT_RIFLE: xp_type = COMBAT_RANGEDSPECIALIZE_CARBINE; break; case WEAPON_TYPE_PISTOL: xp_type = COMBAT_RANGEDSPECIALIZE_PISTOL; break; case WEAPON_TYPE_HEAVY: case WEAPON_TYPE_GROUND_TARGETTING: case WEAPON_TYPE_DIRECTIONAL: xp_type = COMBAT_RANGEDSPECIALIZE_RIFLE; break; case WEAPON_TYPE_1HAND_MELEE: xp_type = COMBAT_MELEESPECIALIZE_ONEHAND; break; case WEAPON_TYPE_2HAND_MELEE: xp_type = COMBAT_MELEESPECIALIZE_TWOHAND; break; case WEAPON_TYPE_UNARMED: xp_type = COMBAT_MELEESPECIALIZE_UNARMED; break; case WEAPON_TYPE_POLEARM: xp_type = COMBAT_MELEESPECIALIZE_POLEARM; break; case WEAPON_TYPE_THROWN: xp_type = COMBAT_GRENADE; break; case WEAPON_TYPE_WT_1HAND_LIGHTSABER: xp_type = COMBAT_MELEESPECIALIZE_ONEHAND; break; case WEAPON_TYPE_WT_2HAND_LIGHTSABER: xp_type = COMBAT_MELEESPECIALIZE_TWOHAND; break; case WEAPON_TYPE_WT_POLEARM_LIGHTSABER: xp_type = COMBAT_MELEESPECIALIZE_POLEARM; break; case combat.WEAPON_TYPE_FORCE_POWER: xp_type = COMBAT_MELEESPECIALIZE_UNARMED; break; default: xp_type = UNKNOWN; break; } return xp_type; } public static String getWeaponStringFromXPType(String strXPType) throws InterruptedException { switch (strXPType) { case COMBAT_RANGEDSPECIALIZE_RIFLE: return "rifle"; case COMBAT_RANGEDSPECIALIZE_CARBINE: return "carbine"; case COMBAT_RANGEDSPECIALIZE_PISTOL: return "pistol"; case COMBAT_RANGEDSPECIALIZE_HEAVY: return "heavy"; case COMBAT_MELEESPECIALIZE_ONEHAND: return "onehandmelee"; case COMBAT_MELEESPECIALIZE_TWOHAND: return "twohandmelee"; case COMBAT_MELEESPECIALIZE_UNARMED: return "unarmed"; case COMBAT_MELEESPECIALIZE_POLEARM: return "polearm"; case COMBAT_JEDI_ONEHANDLIGHTSABER: return "onehandmelee"; case COMBAT_JEDI_TWOHANDLIGHTSABER: return "twohandmelee"; case COMBAT_JEDI_POLEARMLIGHTSABER: return "polearm"; } return ""; } public static boolean setupCreditForKills() throws InterruptedException { return true; } public static boolean cleanupCreditForKills() throws InterruptedException { utils.removeScriptVarTree(getSelf(), VAR_CREDIT_FOR_KILLS); return true; } public static void updateCombatXpList(obj_id target, obj_id attacker, obj_id wpn, int dam) throws InterruptedException { if (!isIdValid(target) || !isIdValid(attacker) || !isIdValid(wpn)) { return; } int weapon_type = getWeaponType(wpn); String strTemplateName = getTemplateName(wpn); if (strTemplateName == null || strTemplateName.equals("")) { LOG("DESIGNER_FATAL", "xp.updateCombatXpList: unable to getTemplateName(wpn) -> " + wpn + ":" + getName(wpn)); return; } else { if (hasObjVar(wpn, WEAPON_TYPE)) { weapon_type = getIntObjVar(wpn, WEAPON_TYPE); } } String xp_type = getWeaponXpType(weapon_type); if (xp_type == null || xp_type.equals("")) { LOG("DESIGNER_FATAL", "xp.updateCombatXpList: unable to getWeaponXpType(wpn) -> " + wpn + ":" + getName(wpn)); return; } updateCombatXpList(target, attacker, xp_type, dam); } public static void updateCombatXpList(obj_id target, obj_id attacker, String xp_type, int dam) throws InterruptedException { if (!isIdValid(target) || !isIdValid(attacker) || xp_type == null || xp_type.equals("")) { return; } if (!utils.hasScriptVar(target, VAR_COMBAT_TIMESTAMP)) { utils.setScriptVar(target, VAR_COMBAT_TIMESTAMP, getGameTime()); } int tally = utils.getIntScriptVar(target, VAR_DAMAGE_TALLY); int newTally = dam + tally; utils.setScriptVar(target, VAR_DAMAGE_TALLY, newTally); int hitCount = utils.getIntScriptVar(target, VAR_DAMAGE_COUNT); hitCount++; utils.setScriptVar(target, VAR_DAMAGE_COUNT, hitCount); if (!isPlayer(attacker) && !pet_lib.isPet(attacker) && !beast_lib.isBeast(attacker) && ai_lib.getDifficultyClass(target) != ai_lib.DIFFICULTY_BOSS) { int npcDamage = utils.getIntScriptVar(target, VAR_NPC_DAMAGE); npcDamage += dam; utils.setScriptVar(target, VAR_NPC_DAMAGE, npcDamage); return; } if (dam > 0) { Vector attackerList = utils.getResizeableObjIdBatchScriptVar(target, VAR_ATTACKER_LIST + ".attackers"); if (attackerList != null && attackerList.size() > 0) { if (utils.getElementPositionInArray(attackerList, attacker) == -1) { attackerList = utils.addElement(attackerList, attacker); utils.setBatchScriptVar(target, VAR_ATTACKER_LIST + ".attackers", attackerList); } } else { attackerList = utils.addElement(attackerList, attacker); utils.setBatchScriptVar(target, VAR_ATTACKER_LIST + ".attackers", attackerList); } String basePath = VAR_ATTACKER_LIST + "." + attacker; String damPath = basePath + ".damage"; int totalDamage = dam + utils.getIntScriptVar(target, damPath); utils.setScriptVar(target, damPath, totalDamage); String xpListBasePath = basePath + ".xp"; String xpListPath = xpListBasePath + ".types"; Vector xpTypes = utils.getResizeableStringBatchScriptVar(target, xpListPath); if (xpTypes != null && xpTypes.size() > 0) { if (utils.getElementPositionInArray(xpTypes, xp_type) == -1) { xpTypes = utils.addElement(xpTypes, xp_type); utils.setBatchScriptVar(target, xpListPath, xpTypes); } } else { xpTypes = utils.addElement(xpTypes, xp_type); utils.setBatchScriptVar(target, xpListPath, xpTypes); } String xpTypePath = xpListBasePath + "." + xp_type; int xpTally = dam + utils.getIntScriptVar(target, xpTypePath); utils.setScriptVar(target, xpTypePath, xpTally); } } public static void removeXpListCombatant(obj_id target, obj_id combatant) throws InterruptedException { if (!isIdValid(target) || !isIdValid(combatant)) { return; } Vector attackerList = utils.getResizeableObjIdBatchScriptVar(target, VAR_ATTACKER_LIST + ".attackers"); if (attackerList == null || attackerList.size() == 0) { return; } int idx = utils.getElementPositionInArray(attackerList, combatant); if (idx == -1) { return; } attackerList = utils.removeElementAt(attackerList, idx); if (attackerList == null || attackerList.size() == 0) { return; } utils.setBatchScriptVar(target, VAR_ATTACKER_LIST + ".attackers", attackerList); utils.removeScriptVarTree(target, VAR_ATTACKER_LIST + "." + combatant); } public static void assessCombatResults(obj_id target) throws InterruptedException { if (!isIdValid(target)) { return; } if (!utils.hasScriptVar(target, VAR_ATTACKER_LIST + ".attackers")) { return; } if (utils.hasScriptVar(target, "storytellerid") || utils.hasObjVar(target, "storytellerid")) { return; } int npcDamage = utils.getIntScriptVar(target, VAR_NPC_DAMAGE); int tally = utils.getIntScriptVar(target, VAR_DAMAGE_TALLY); float npcDamagePercent = npcDamage / (float)tally; if (npcDamagePercent > MAX_NPC_DAMAGE_PERCENT) { return; } obj_id[] attackerList = utils.getObjIdBatchScriptVar(target, VAR_ATTACKER_LIST + ".attackers"); if (attackerList == null || attackerList.length == 0) { return; } attackerList = utils.validateObjIdArray(attackerList); obj_var[] damArray = new obj_var[attackerList.length]; for (int i = 0; i < attackerList.length; i++) { damArray[i] = new obj_var(attackerList[i].toString(), utils.getIntScriptVar(target, VAR_ATTACKER_LIST + "." + attackerList[i] + ".damage")); } if (damArray.length == 0) { return; } obj_var[] killers = list.quickSort(0, attackerList.length - 1, damArray); if ((killers == null) || (killers.length == 0)) { return; } obj_id[] topDamagers = getTopIndividualAttacker(killers); if (topDamagers != null && topDamagers.length > 0) { setObjVar(target, VAR_TOP_DAMAGERS, topDamagers); } dictionary groupDamage = new dictionary(); int topDamage = Integer.MIN_VALUE; int gDam; obj_id attacker; for (obj_var attackerDamageVar : killers) { attacker = utils.stringToObjId(attackerDamageVar.getName()); if (isIdValid(attacker)) { int attackerDamage = attackerDamageVar.getIntData(); gDam = updateGroupDamageDictionary(groupDamage, attacker, attackerDamage, target); if (gDam > topDamage) { topDamage = gDam; } } } Vector primaryKillers = new Vector(); primaryKillers.setSize(0); java.util.Enumeration keys = groupDamage.keys(); String key; obj_id tmpId; while (keys.hasMoreElements()) { key = (String) (keys.nextElement()); int val = groupDamage.getInt(key); if (val >= topDamage) { tmpId = utils.stringToObjId(key); if (isIdValid(tmpId)) { primaryKillers = utils.addElement(primaryKillers, tmpId); if (!group.isGroupObject(tmpId)) { incrementKillMeter(tmpId, 1); } } } } if ((primaryKillers == null) || (primaryKillers.size() == 0)) { return; } int winnerIdx = rand(0, primaryKillers.size() - 1); obj_id winner = ((obj_id)primaryKillers.get(winnerIdx)); if (!group.isGroupObject(winner) && !isPlayer(winner) && isMob(winner)) { obj_id winnerMaster = getMaster(winner); if (!isIdNull(winnerMaster) && isIdValid(winnerMaster)) { winner = winnerMaster; } } if (group.isGroupObject(winner)) { for (obj_var attackerDamageVar : killers) { attacker = utils.stringToObjId(attackerDamageVar.getName()); if (isIdValid(attacker)) { if (getGroupObject(attacker) == winner) { incrementKillMeter(attacker, 1); } } } } setObjVar(target, VAR_TOP_DAMAGE, topDamage); setObjVar(target, VAR_TOP_GROUP, winner); grantQuestKillCredit(winner, target); if (!hasObjVar(target, "combat.zeroXP")) { obj_id[] killerList = new obj_id[primaryKillers.size()]; primaryKillers.toArray(killerList); killers = grantCombatXp(target, killers); obj_id[] playerList = getPlayersFromKillerList(killerList); pet_lib.addToHarvestDroidArray(target, playerList); if (killers == null || killers.length == 0) { setObjVar(target, VAR_TOP_DAMAGE, 0); setObjVar(target, VAR_TOP_GROUP, obj_id.NULL_ID); obj_id[] placeHolder = new obj_id[1]; placeHolder[0] = obj_id.NULL_ID; setObjVar(target, scenario.VAR_PRIMARY_KILLERS, placeHolder); return; } } setObjVar(target, scenario.VAR_PRIMARY_KILLERS, primaryKillers); } public static obj_id[] getPlayersFromKillerList(obj_id[] killerList) throws InterruptedException { Vector players = new Vector(); players.setSize(0); obj_id[] groupMembers; for (obj_id aKillerList : killerList) { if (group.isGroupObject(aKillerList)) { groupMembers = utils.getGroupMemberIds(aKillerList); for (obj_id groupMember : groupMembers) { if (isIdValid(groupMember) && exists(groupMember)) { if (pet_lib.isPet(groupMember)) { utils.addElement(players, getMaster(groupMember)); } else { utils.addElement(players, groupMember); } } } } else { if (pet_lib.isPet(aKillerList)) { utils.addElement(players, getMaster(aKillerList)); } else { utils.addElement(players, aKillerList); } } } killerList = new obj_id[players.size()]; players.toArray(killerList); return killerList; } public static void grantQuestKillCredit(obj_id winner, obj_id target) throws InterruptedException { obj_id[] killList; if (group.isGroupObject(winner)) { killList = getGroupMemberIds(winner); } else { killList = new obj_id[1]; killList[0] = winner; } if (killList.length < 1) { return; } dictionary params = new dictionary(); String creatureName = getCreatureName(target); if (creatureName == null || creatureName.equals("")) { return; } params.put("creatureName", creatureName); params.put("location", getLocation(target)); params.put("socialGroup", ai_lib.getSocialGroup(target)); // only put a value in col_faction if one is found in the datatable. if(dataTableGetString(CREATURES_TABLE, creatureName, "col_faction") != null) params.put("col_faction", dataTableGetString(CREATURES_TABLE, creatureName, "col_faction")); params.put("difficultyClass", dataTableGetInt(CREATURES_TABLE, creatureName, "difficultyClass")); params.put("target", target); if (hasObjVar(target, "quest_spawner.spawned_by")) { params.put("spawnedBy", getObjIdObjVar(target, "quest_spawner.spawned_by")); } obj_id collectionOwner; for (obj_id aKillList : killList) { if (!hasObjVar(target, "soloCollection")) { if (!exists(aKillList) || !isIdValid(aKillList)) { continue; } float distance = getDistance(target, aKillList); if (distance < 128.0f && distance >= 0.0f) { messageTo(aKillList, "receiveCreditForKill", params, 0.0f, false); } } else { collectionOwner = getObjIdObjVar(target, "soloCollection"); if (!exists(collectionOwner) || !isIdValid(collectionOwner)) { continue; } float distance = getDistance(target, collectionOwner); if (distance < 128.0f && distance >= 0.0f) { messageTo(collectionOwner, "receiveCreditForKill", params, 0.0f, false); } } } } public static int updateGroupDamageDictionary(dictionary groupDamage, obj_id attacker, int attackerDamage, obj_id target) throws InterruptedException { if (!isIdValid(attacker) || !isIdValid(target) || attackerDamage < 1) { return attackerDamage; } if (beast_lib.isBeast(attacker)) { obj_id master = getMaster(attacker); if (isIdValid(master) && exists(master)) { attacker = master; } } obj_id attackerGroupId = getGroupObject(attacker); if (!isIdValid(attackerGroupId)) { int currentPersonalDamage = groupDamage.getInt(attacker.toString()); int totalPersonalDamage = currentPersonalDamage + attackerDamage; groupDamage.put(attacker.toString(), totalPersonalDamage); return totalPersonalDamage; } else { int currentGroupDamage = groupDamage.getInt(attackerGroupId.toString()); int totalGroupDamage = currentGroupDamage + attackerDamage; groupDamage.put(attackerGroupId.toString(), totalGroupDamage); return totalGroupDamage; } } public static obj_var[] grantCombatXp(obj_id target, obj_var[] killers) throws InterruptedException { if (!isIdValid(target) || killers == null || killers.length == 0) { return null; } Vector ret = new Vector(); ret.setSize(0); double damageTally = (double)getIntObjVar(target, VAR_TOP_DAMAGE); if (damageTally < 0) { debugServerConsoleMsg(target, "xp::grantCombatXp: damageTally(" + damageTally + ") < 0!! WTF happened in combat?"); return null; } obj_id killCredit = getObjIdObjVar(target, VAR_TOP_GROUP); obj_id[] killList; if (group.isGroupObject(killCredit)) { killList = getGroupMemberIds(killCredit); } else { killList = new obj_id[1]; killList[0] = killCredit; } metrics.doKillMetrics(killCredit, target); String faction = factions.getFaction(target); int levelAmount = getLevel(target) * 10; obj_id[] allKillers = new obj_id[killers.length]; for (int i = 0; i < killers.length; i++) { allKillers[i] = utils.stringToObjId(killers[i].getName()); } obj_var killerVar; obj_id killer; obj_id master; obj_id gcw_gain_object; obj_id beast; dictionary params; obj_id beastBCD; for (int i = 0; i < killers.length; i++) { killerVar = killers[i]; killer = allKillers[i]; master = obj_id.NULL_ID; if (beast_lib.isBeast(killer) && !ai_lib.aiIsDead(killer)) { master = getMaster(killer); if (!master.isLoaded() || master.isBeingDestroyed()) { master = null; } } if (!utils.isObjIdInArray(killList, killer)) { if (isIdValid(master)) { if (!utils.isObjIdInArray(killList, master)) { continue; } } } gcw_gain_object = null; if (isIdValid(master)) { if (!utils.isObjIdInArray(allKillers, master)) { gcw_gain_object = master; } } else { gcw_gain_object = killer; } if (isIdValid(gcw_gain_object) && !hasObjVar(target, gcw.GCW_POINT_OVERRIDE)) { gcw.grantModifiedGcwPoints(target, gcw_gain_object, false, gcw.GCW_POINT_TYPE_GROUND_PVE, getName(target)); } int dam = killerVar.getIntData(); checkAndUpdateHuntingMissions(killer, target); if (isIdValid(killer) && killer.isLoaded() && !killer.isBeingDestroyed() && killer != target) { int xpTotal = getRawCombatXP(killer, target); xpTotal = applyGroupXpModifier(killer, xpTotal); if (isPlayer(killer) && beast_lib.isBeastMaster(killer)) { beast = beast_lib.getBeastOnPlayer(killer); if (beast_lib.isValidBeast(beast) && getDistance(killer, beast) < MAX_DISTANCE && xpTotal > 1) { if (utils.isObjIdInArray(killList, killer) || utils.isObjIdInArray(killList, beast)) { beast_lib.grantBeastExperience(beast); params = new dictionary(); params.put("targetId", target); beastBCD = beast_lib.getBeastBCD(beast); messageTo(beastBCD, "beastKilledSomething", params, 1, false); } } } else { if (beast_lib.isBeast(killer) && beast_lib.isValidPlayer(master) && beast_lib.canBeastGetLevelBasedXP(killer, target)) { if (utils.isObjIdInArray(allKillers, master)) { continue; } else { beast_lib.grantBeastExperience(killer); params = new dictionary(); params.put("targetId", target); beastBCD = beast_lib.getBeastBCD(killer); messageTo(beastBCD, "beastKilledSomething", params, 1, false); } } } if (!isPlayer(killer)) { if ((beast_lib.isBeast(killer) || pet_lib.isPet(killer)) && !ai_lib.aiIsDead(killer) && isIdValid(master)) { xpTotal = getRawCombatXP(master, target); ret = utils.addElement(ret, killerVar); if (!utils.isObjIdInArray(allKillers, master) && utils.isObjIdInArray(allKillers, killer)) { grantCombatStyleXp(master, COMBAT_GENERAL, xpTotal); displayXpFlyText(master, master, xpTotal); displayXpMsg(master, null, xpTotal); double percentDamage = ((double)dam / damageTally) + PERCENT_ADJUSTER; factions.grantCombatFaction(master, target, percentDamage); } } } else if (utils.isObjIdInArray(killList, killer)) { double percentDamage = ((double)dam / damageTally) + PERCENT_ADJUSTER; if (getDistance(killer, target) < MAX_DISTANCE) { grantCombatXpPerAttackType(killer, target, xpTotal); factions.grantCombatFaction(killer, target, percentDamage); if (faction != null) { factions.adjustSocialStanding(killer, faction, -levelAmount); } ret = utils.addElement(ret, killerVar); } } utils.removeScriptVar(killer, "combat.xp.groupBonus"); } } if (ret == null || ret.size() == 0) { return null; } obj_var[] _ret = new obj_var[ret.size()]; ret.toArray(_ret); return _ret; } public static void grantCombatXpPerAttackType(obj_id player, obj_id target, int totalXp) throws InterruptedException { if (!isIdValid(player) || (!isPlayer(player)) || !isIdValid(target) || totalXp < 1) { return; } String basePath = VAR_ATTACKER_LIST + "." + player; String xpListBasePath = basePath + ".xp"; String xpListPath = xpListBasePath + ".types"; if (!utils.hasScriptVar(target, xpListPath)) { return; } String[] xpTypes = utils.getStringBatchScriptVar(target, xpListPath); if (xpTypes == null || xpTypes.length == 0) { return; } if (hasScript(player, "theme_park.new_player.new_player") || hasObjVar(player, "handlePlayerCombatKill")) { dictionary webster = new dictionary(); webster.put("xpTypes", xpTypes); webster.put("target", target); messageTo(player, "handlePlayerCombatKill", webster, 1, false); } String damPath = basePath + ".damage"; int tally = utils.getIntScriptVar(target, damPath); tally -= utils.getIntScriptVar(target, xpListBasePath + "." + PERMISSIONS_ONLY); if (tally < 1) { return; } int raw = 0; int bonusCombatXp = 0; int jediXp = 0; int generalXp = 0; int totalXpGranted = 0; for (String xpType : xpTypes) { int val = utils.getIntScriptVar(target, xpListBasePath + "." + xpType); float xpPercent = ((float) (val) / (float) (tally)); int intNewTotal = totalXp; if (xpType.equals(RAW_COMBAT)) { intNewTotal = (int) (intNewTotal * xpPercent); bonusCombatXp += intNewTotal; } else if (xpType.equals(PARTIAL_COMBAT)) { intNewTotal = (int) (intNewTotal * xpPercent); intNewTotal = (int) (intNewTotal * COMBAT_GENERAL_EXCHANGE_RATE); bonusCombatXp += intNewTotal; } else if (xpType.equals(COMBAT_GENERAL)) { int amt = (int) (intNewTotal * xpPercent); if (amt < 1) { amt = 1; } generalXp += amt; } else if (isCombatXpType(xpType)) { int amt = (int) (intNewTotal * xpPercent); if (amt < 1) { amt = 1; } if (xpType.equals(COMBAT_JEDI_ONEHANDLIGHTSABER) || xpType.equals(COMBAT_JEDI_TWOHANDLIGHTSABER) || xpType.equals(COMBAT_JEDI_POLEARMLIGHTSABER) || xpType.equals(COMBAT_JEDI_FORCE_POWER) || xpType.equals(JEDI_GENERAL)) { if (isJedi(player)) { jediXp += amt; } } else { raw += amt; if (!xpType.equals(COMBAT_THROWN)) { totalXpGranted += grantCombatStyleXp(player, xpType, amt); } } } else if (!xpType.equals(UNKNOWN) && !xpType.equals(PERMISSIONS_ONLY) && !xpType.equals(PET_DAMAGE)) { int amt = (int) (intNewTotal * xpPercent); if (amt < 1) { amt = 1; } totalXpGranted += grantCombatStyleXp(player, xpType, amt); } } if (isJedi(player)) { jediXp *= JEDI_GENERAL_EXCHANGE_RATE; totalXpGranted += grantCombatStyleXp(player, JEDI_GENERAL, jediXp); LOG("jedi", "Granting " + jediXp + " to " + player + " type is " + JEDI_GENERAL); } else { generalXp += (int)(raw * COMBAT_GENERAL_EXCHANGE_RATE); if (generalXp < 0) { generalXp = 0; } if (bonusCombatXp > 0) { generalXp += bonusCombatXp; } if (generalXp > 0) { totalXpGranted += grantCombatStyleXp(player, COMBAT_GENERAL, generalXp); } } if (!isPlayer(target) && factions.getFactionFlag(player) != factions.getFactionFlag(target) && (factions.getFactionFlag(target) == factions.FACTION_FLAG_REBEL || factions.getFactionFlag(target) == factions.FACTION_FLAG_IMPERIAL)) { gcw.gcwInvasionCreditForKill(player); } displayXpFlyText(player, player, totalXpGranted); displayXpMsg(player, null, totalXpGranted); } public static int grantSocialStyleXp(obj_id player, String xpType, int amount) throws InterruptedException { amount = Math.round(amount * ENTERTAINER_XP_MOD); String templateXp = skill_template.getTemplateSkillXpType(player, false); if (templateXp != null) { if (isSocialXpType(templateXp)) { amount = grant(player, templateXp, amount, false); } else { amount = 0; } } else { amount = 0; } return amount; } public static int grantCraftingQuestXp(obj_id player, int amount) throws InterruptedException { String templateXp = skill_template.getTemplateSkillXpType(player, false); if (templateXp != null) { if (isCraftingXpType(templateXp)) { amount = grant(player, templateXp, amount, false); } else { amount = 0; } } else { amount = 0; } return amount; } public static int grantCraftingStyleXp(obj_id player, String xpType, int amount) throws InterruptedException { amount = Math.round(amount * TRADER_XP_MOD); int merchantXP = (int)(amount * CRAFTING_MERCHANT_EXCHANGE_RATE); float xpRatio = skill_template.NON_TEMPLATE_XP_RATIO; if (xpType.equals(QUEST_CRAFTING)) { merchantXP = 0; xpRatio = skill_template.QUEST_XP_RATIO; } String templateXp = skill_template.getTemplateSkillXpType(player, false); if (templateXp != null) { if (isCraftingXpType(templateXp)) { if (!xpType.equals(templateXp)) { amount = (int)(amount * xpRatio); } if (!templateXp.equals(MERCHANT)) { merchantXP = (int)(merchantXP * xpRatio); } amount += merchantXP; amount = grant(player, templateXp, amount, false); } else { amount = 0; } } else { amount = 0; } return amount; } public static int grantCombatStyleXp(obj_id player, String xpType, int amount) throws InterruptedException { float xpRatio = skill_template.NON_TEMPLATE_XP_RATIO; if (xpType.equals(QUEST_COMBAT)) { xpRatio = skill_template.QUEST_XP_RATIO; } String templateXp = skill_template.getTemplateSkillXpType(player, false); if (templateXp != null) { if (isCombatXpType(templateXp)) { if (!xpType.equals(templateXp)) { amount = (int)(amount * xpRatio); } amount = grant(player, templateXp, amount, false); } else { amount = 0; } } else { amount = 0; } return amount; } public static void displayXpMsg(obj_id player, String xpType, int amt) throws InterruptedException { if (xpType == null) { xpType = skill_template.getTemplateSkillXpType(player, true); } if (xpType == null || xpType.equals("")) { return; } if (xpType.equals(skill_template.NO_TEMPLATE_STARTING)) { return; } int currentXp = getExperiencePoints(player, xpType); int xpCap = getExperienceCap(player, xpType); if (currentXp < xpCap) { float grpMod = 1f; if (utils.hasScriptVar(player, "combat.xp.groupBonus")) { grpMod = utils.getFloatScriptVar(player, "combat.xp.groupBonus"); } float inspMod = getInspirationBuffXpModifier(player, xpType); prose_package pp = xp.getXpProsePackage(xpType, amt, grpMod, inspMod); if (pp != null) { if (isSpaceScene()) { sendQuestSystemMessage(player, pp); } } if (currentXp + amt >= xpCap) { prose_package ppAtCap = prose.getPackage(new string_id("base_player", "prose_hit_xp_cap"), new string_id(STF_XP_N, xpType)); if (isSpaceScene()) { sendQuestSystemMessage(player, ppAtCap); } } } } public static void displayXpFlyText(obj_id player, obj_id target, int amount) throws InterruptedException { if (isFreeTrialAccount(player)) { int playerLevel = getLevel(player); if (playerLevel >= TRIAL_LEVEL_CAP) { debugSpeakMsg(player, "I am a greater than or equal to level " + xp.TRIAL_LEVEL_CAP); prose_package pp = new prose_package(); prose.setDI(pp, xp.TRIAL_LEVEL_CAP); prose.setStringId(pp, SID_FREE_TRIAL_LEVEL_CAP); sendSystemMessageProse(player, pp); return; } } if (amount == 0) { return; } if (npe.hasReachedMaxTutorialLevel(player)) { return; } float groupModPct = 1.0f; if (utils.hasScriptVar(player, "combat.xp.groupBonus")) { float groupBonus = utils.getFloatScriptVar(player, "combat.xp.groupBonus"); groupModPct = getGroupXpModifierPercentageOfMax(groupBonus); } float flyScale = getCombatXpFlyScale(groupModPct); color flyColor = getCombatXpFlyColor(groupModPct); showFlyTextPrivate(target, player, prose.getPackage(SID_FLYTEXT_XP, amount), flyScale, flyColor); } public static float getGroupXpModifierPercentageOfMax(float groupMod) throws InterruptedException { float groupModPct; final float maxGroupMod = GROUP_XP_BONUS * MAX_GROUP_BONUS_COUNT; groupModPct = (groupMod - 1) / maxGroupMod; if (groupModPct > 1) { groupModPct = 1; } return groupModPct; } public static float getCombatXpFlyScale(float groupModPct) throws InterruptedException { final float minScale = 1.5f; final float maxScale = 2.5f; final float scaleRange = maxScale - minScale; return minScale + (scaleRange * groupModPct); } public static color getCombatXpFlyColor(float groupModPct) throws InterruptedException { final color minColor = new color(140, 15, 210, 255); final color maxColor = new color(180, 60, 240, 255); final int redRange = maxColor.getR() - minColor.getR(); final int greenRange = maxColor.getG() - minColor.getG(); final int blueRange = maxColor.getB() - minColor.getB(); int red = minColor.getR() + (int)(redRange * groupModPct); int green = minColor.getG() + (int)(greenRange * groupModPct); int blue = minColor.getB() + (int)(blueRange * groupModPct); if (red > maxColor.getR()) { red = maxColor.getR(); } if (green > maxColor.getG()) { green = maxColor.getG(); } if (blue > maxColor.getB()) { blue = maxColor.getB(); } return new color(red, green, blue, 255); } public static boolean isCombatXpType(String xpType) throws InterruptedException { switch (xpType) { case COMBAT_GENERAL: case COMBAT_RANGEDSPECIALIZE_RIFLE: case COMBAT_RANGEDSPECIALIZE_CARBINE: case COMBAT_RANGEDSPECIALIZE_PISTOL: case COMBAT_RANGEDSPECIALIZE_HEAVY: case COMBAT_MELEESPECIALIZE_ONEHAND: case COMBAT_MELEESPECIALIZE_TWOHAND: case COMBAT_MELEESPECIALIZE_UNARMED: case COMBAT_MELEESPECIALIZE_POLEARM: case COMBAT_THROWN: case COMBAT_GRENADE: case JEDI_GENERAL: case COMBAT_JEDI_ONEHANDLIGHTSABER: case COMBAT_JEDI_TWOHANDLIGHTSABER: case COMBAT_JEDI_POLEARMLIGHTSABER: case COMBAT_JEDI_FORCE_POWER: case MEDICAL: case COMBATMEDIC: case CREATUREHANDLER: case QUEST_COMBAT: case QUEST_GENERAL: return true; } return false; } public static boolean isSocialXpType(String xpType) throws InterruptedException { switch (xpType) { case MUSIC: case DANCE: case JUGGLING: case ENTERTAINER: case IMAGEDESIGNER: case QUEST_SOCIAL: case QUEST_COMBAT: case QUEST_GENERAL: return true; } return false; } public static boolean isCraftingXpType(String xpType) throws InterruptedException { switch (xpType) { case HARVEST_INORGANIC: case CRAFTING_GENERAL: case CRAFTING_FOOD_GENERAL: case CRAFTING_MEDICINE_GENERAL: case CRAFTING_CLOTHING_ARMOR: case CRAFTING_CLOTHING_GENERAL: case CRAFTING_WEAPONS_GENERAL: case CRAFTING_WEAPONS_MELEE: case CRAFTING_WEAPONS_RANGED: case CRAFTING_WEAPONS_MUNITION: case CRAFTING_STRUCTURE_GENERAL: case CRAFTING_DROID_GENERAL: case CRAFTING_SHIPWRIGHT: case MERCHANT: case QUEST_CRAFTING: case QUEST_GENERAL: case "crafting": return true; } return false; } public static String[] getXpTypes(obj_id self) throws InterruptedException { Vector xpTypes = new Vector(); xpTypes.setSize(0); if (dataTableOpen(TBL_SKILL)) { String[] colXpType = dataTableGetStringColumnNoDefaults(TBL_SKILL, "XP_TYPE"); if ((colXpType == null) || (colXpType.length == 0)) { return null; } for (String type : colXpType) { if (type != null && !type.equals("") && !type.equals("unobtainable") && !type.equals("jedi")) { if (utils.getElementPositionInArray(xpTypes, type) == -1) { xpTypes = utils.addElement(xpTypes, type); } } } } String[] _xpTypes = new String[0]; if (xpTypes != null) { _xpTypes = new String[xpTypes.size()]; xpTypes.toArray(_xpTypes); } return _xpTypes; } public static void checkAndUpdateHuntingMissions(obj_id objPlayer, obj_id objCreature) throws InterruptedException { if (!isMob(objCreature)) { return; } LOG("missions", "checking for " + objPlayer); obj_id[] objMissions = getMissionObjects(objPlayer); if (objMissions == null) { LOG("missions", "null missions"); return; } String strMissionType; String strCreatureToKill; string_id strName; for (obj_id objMission : objMissions) { strMissionType = getMissionType(objMission); LOG("missions", "type is " + strMissionType); if (strMissionType.equals("hunting")) { strCreatureToKill = getStringObjVar(objMission, "strCreatureToKill"); final String strCreatureType = getCreatureName(objCreature); LOG("missions", "creature to kill is " + strCreatureToKill); LOG("missions", "creature type is " + strCreatureType); if (strCreatureType.equals(strCreatureToKill)) { int intQuantityToKill = getIntObjVar(objMission, "intQuantityToKill"); intQuantityToKill = intQuantityToKill - 1; if (intQuantityToKill <= 0) { messageTo(objMission, "huntingSuccess", null, 0, true); } else { LOG("missions", "Quanitty Ledft is " + intQuantityToKill); setObjVar(objMission, "intQuantityToKill", intQuantityToKill); strName = new string_id("mob/creature_names", strCreatureType); sendSystemMessageProse(objPlayer, prose.getPackage(new string_id("mission/mission_generic", "hunting_kills_remaining"), strName, intQuantityToKill)); return; } } } } } public static obj_id[] getTopIndividualAttacker(obj_var[] killers) throws InterruptedException { Vector tempArray = new Vector(); tempArray.setSize(0); if (killers == null || killers.length <= 0) { return null; } obj_var alpha = killers[0]; obj_id alphaObjId = utils.stringToObjId(alpha.getName()); if (killers.length == 1) { tempArray = utils.addElement(tempArray, alphaObjId); } else { int alphaValue = alpha.getIntData(); obj_var omega = killers[killers.length - 1]; obj_id omegaObjId = utils.stringToObjId(omega.getName()); int omegaValue = omega.getIntData(); if (alphaValue > omegaValue) { tempArray = utils.addElement(tempArray, alphaObjId); obj_var next; for (int a = 1; a < killers.length; a++) { next = killers[a]; int nextValue = next.getIntData(); if (nextValue == alphaValue) { tempArray = utils.addElement(tempArray, utils.stringToObjId(next.getName())); } else { break; } } } else if (alphaValue < omegaValue) { tempArray = utils.addElement(tempArray, omegaObjId); obj_var next; for (int om = (killers.length - 2); om >= 0; om--) { next = killers[om]; int nextValue = next.getIntData(); if (nextValue == omegaValue) { tempArray = utils.addElement(tempArray, utils.stringToObjId(next.getName())); } else { break; } } } } return utils.toStaticObjIdArray(tempArray); } public static boolean displayForceSensitiveXP(obj_id player, String type) throws InterruptedException { if (!isIdValid(player)) { LOG("force_sensitive", "xp.convertForceSensitiveXP -- player is invalid."); return false; } if (type == null) { LOG("force_sensitive", "xp.convertForceSensitiveXP -- type is null."); return false; } int index = dataTableSearchColumnForString(type, "fs_type", "datatables/quest/force_sensitive/xp_conversion.iff"); if (index < 0) { LOG("force_sensitive", "xp.convertForceSensitiveXP -- can't find type " + type + " in xp datatable."); return false; } Vector valid_xp_types = new Vector(); valid_xp_types.setSize(0); for (int i = index; i < dataTableGetNumRows("datatables/quest/force_sensitive/xp_conversion.iff"); i++) { dictionary row = dataTableGetRow("datatables/quest/force_sensitive/xp_conversion.iff", i); String fs_type = row.getString("fs_type"); if (fs_type == null || !fs_type.equals(type)) { break; } String xp_type = row.getString("xp_type"); if (xp_type != null && xp_type.length() > 0) { if (getExperiencePoints(player, xp_type) > 0) { valid_xp_types.add(xp_type); } } } if (valid_xp_types.size() > 0) { String[] dsrc = new String[valid_xp_types.size()]; utils.setScriptVar(player, "force_sensitive.xp_convert", valid_xp_types); utils.setScriptVar(player, "force_sensitive.xp_convert_type", type); for (int i = 0; i < valid_xp_types.size(); i++) { dsrc[i] = "@exp_n:" + valid_xp_types.get(i); } if (!hasScript(player, "quest.force_sensitive.fs_xp_convert")) { attachScript(player, "quest.force_sensitive.fs_xp_convert"); } String type_name = localize(new string_id("exp_n", "fs_" + type)); int pid = sui.listbox(player, player, "Select the experience you wish to convert to " + type_name + ".", sui.OK_CANCEL, "Experience Conversion", dsrc, "msgFSXPConvertSelected"); utils.setScriptVar(player, "force_sensitive.sui_pid", pid); } else { sendSystemMessage(player, new string_id("quest/force_sensitive/utils", "convert_not_enough_for_conversion")); } return true; } public static prose_package getXpProsePackage(String xpType, int xpAmt) throws InterruptedException { return getXpProsePackage(xpType, xpAmt, 1f, 1f); } public static prose_package getXpProsePackage(String xpType, int xpAmt, float grpMod, float inspMod) throws InterruptedException { prose_package pp = new prose_package(); string_id sid_xp = new string_id(STF_XP_N, xpType); prose.setTO(pp, sid_xp); float grpBonus = (grpMod * 100) - 100; float inspBonus = (inspMod * 100) - 100; String grpBonusString = ((new Integer(Math.round(grpBonus)))).toString(); String inspBonusString = ((new Integer(Math.round(inspBonus)))).toString(); prose.setDI(pp, Math.abs(xpAmt)); if (xpAmt >= 0) { if (inspBonus > 0) { if (grpBonus > 0) { prose.setStringId(pp, PROSE_GRANT_GROUP_BUFF_XP); prose.setTT(pp, grpBonusString); prose.setTU(pp, inspBonusString); } else { prose.setStringId(pp, PROSE_GRANT_BUFF_XP); prose.setTT(pp, inspBonusString); } } else { if (grpBonus > 0) { prose.setStringId(pp, PROSE_GRANT_GROUP_XP); prose.setTT(pp, grpBonusString); } else { if (xpAmt == 1) { prose.setStringId(pp, PROSE_GRANT_XP1); } else { prose.setStringId(pp, PROSE_GRANT_XP); } } } } else { if (xpAmt == 1) { prose.setStringId(pp, PROSE_REVOKE_XP1); } else { prose.setStringId(pp, PROSE_REVOKE_XP); } } return pp; } public static int grantXpByTemplate(obj_id player, int amount) throws InterruptedException { String template = getSkillTemplate(player); String xpType; if (!isIdValid(player) || template == null) { return 0; } if (template.startsWith("trader")) { grantCraftingStyleXp(player, xp.QUEST_CRAFTING, amount); xpType = xp.QUEST_CRAFTING; } else if (template.startsWith("entertainer")) { grantSocialStyleXp(player, xp.QUEST_SOCIAL, amount); xpType = xp.QUEST_SOCIAL; } else { grantCombatStyleXp(player, xp.QUEST_COMBAT, amount); xpType = xp.QUEST_COMBAT; } xp.displayXpFlyText(player, player, amount); xp.displayXpMsg(player, xpType, amount); return amount; } public static int grantUnmodifiedXpByTemplate(obj_id player, int amount) throws InterruptedException { String template = getSkillTemplate(player); String xpType; if (!isIdValid(player) || template == null) { return 0; } if (template.startsWith("trader")) { xpType = xp.QUEST_CRAFTING; } else if (template.startsWith("entertainer")) { xpType = xp.QUEST_SOCIAL; } else { xpType = xp.QUEST_COMBAT; } String templateXp = skill_template.getTemplateSkillXpType(player, false); if (templateXp != null && amount > 0) { amount = grant(player, templateXp, amount, false); } xp.displayXpFlyText(player, player, amount); xp.displayXpMsg(player, xpType, amount); return amount; } public static int grantUnmodifiedXPPercentageOfLevel(obj_id player, float percentage) throws InterruptedException { int playerLevel = getLevel(player); if (playerLevel < 90) { int xpForCurrentLevel = dataTableGetInt(xp.TBL_PLAYER_LEVEL_XP, playerLevel - 1, "xp_required"); int xpForNextLevel = dataTableGetInt(xp.TBL_PLAYER_LEVEL_XP, playerLevel, "xp_required"); float xpGrantedFloat = (xpForNextLevel - xpForCurrentLevel) * percentage / 100; int xpGranted = (int)xpGrantedFloat; if (grantUnmodifiedXpByTemplate(player, xpGranted) > 0) { return xpGranted; } } return 0; } public static void applyHealingCredit(obj_id self) throws InterruptedException { deltadictionary scriptVars = self.getScriptVars(); Vector healers = scriptVars.getResizeableObjIdArray("healers"); if (healers != null) { Iterator i = healers.iterator(); dictionary params = new dictionary(); params.put("target", self); while (i.hasNext()) { obj_id healer = (obj_id)i.next(); if (isIdValid(healer)) { messageTo(healer, "receiveCreditForCombatHealing", params, 0.0f, false); } } } } public static void grantMissionXp(obj_id player, int missionLevel) throws InterruptedException { if (isIdValid(player) && missionLevel > 0) { int xpToGrantForRealsies = getMissionXpAmount(player, missionLevel); if (xpToGrantForRealsies > 0) { grantCombatStyleXp(player, COMBAT_GENERAL, xpToGrantForRealsies); displayXpFlyText(player, player, xpToGrantForRealsies); int huySaidToUseTTForTheSecondNumber = ((missions.DAILY_MISSION_XP_REWARD - missions.getPlayerDailyCount(player)) - 1); prose_package pp = new prose_package(); prose.setStringId(pp, missions.DAILY_REWARD_XP); prose.setDI(pp, xpToGrantForRealsies); prose.setTT(pp, "" + huySaidToUseTTForTheSecondNumber); sendSystemMessageProse(player, pp); } } } public static int getMissionXpAmount(obj_id player, int missionLevel) throws InterruptedException { int xpToGrant = 0; int playerLevel = getLevel(player); int xpForCurrentLevel = dataTableGetInt(TBL_PLAYER_LEVEL_XP, playerLevel - 1, "xp_required"); int xpForNextLevel = dataTableGetInt(TBL_PLAYER_LEVEL_XP, playerLevel, "xp_required"); int levelDivisor = 0; int levelDelta = Math.abs(missionLevel - playerLevel); LOG("NewMission", "getMissionXpAmountLevelDelta: " + levelDelta); if (xpForNextLevel <= 0) { return xpToGrant; } int xpForLevel = xpForNextLevel - xpForCurrentLevel; if (levelDelta > 15) { levelDivisor += levelDelta; } if (xpForLevel > 0) { int missionXpDivisor = missions.DAILY_MISSION_XP_LOW; if (playerLevel >= 70) { missionXpDivisor = missions.DAILY_MISSION_XP_MEDIUM; } if (playerLevel >= 80) { missionXpDivisor = missions.DAILY_MISSION_XP_HIGH; } missionXpDivisor += levelDivisor; if (missionXpDivisor > 0) { xpToGrant = xpForLevel / missionXpDivisor; int sanityXpAmount = xpForLevel / missions.DAILY_MISSION_XP_SANITY; if (xpToGrant > sanityXpAmount) { xpToGrant = sanityXpAmount; } } } return xpToGrant; } public static int grantCollectionXP(obj_id player, String collectionName) throws InterruptedException { float xpToGrant; int playerLevel = getLevel(player); if (playerLevel == 90) { return 0; } int xpForCurrentLevel = dataTableGetInt(TBL_PLAYER_LEVEL_XP, playerLevel - 1, "xp_required"); int xpForNextLevel = dataTableGetInt(TBL_PLAYER_LEVEL_XP, playerLevel, "xp_required"); float xpForLevel = xpForNextLevel - xpForCurrentLevel; float xpModifier = dataTableGetFloat(collection.COLLECTION_REWARD_TABLE, collectionName, "xpModifier"); long repeatSlotValue = getCollectionSlotValue(player, collectionName + "_tracker") - 1; if (repeatSlotValue > 0) { float repeatXpModifier = repeatCollectionXpModifier(player, repeatSlotValue); xpToGrant = xpModifier * xpForLevel * repeatXpModifier; return (int)xpToGrant; } xpToGrant = xpModifier * xpForLevel; return (int)xpToGrant; } public static int grantCollectionSpaceXP(obj_id player, String collectionName) throws InterruptedException { if (!isValidId(player)) { return 0; } if (!space_skill.hasSpaceSkills(player)) { return 0; } String profPrefix = space_flags.getProfessionPrefix(player); if (profPrefix == null || profPrefix.equals("")) { return 0; } float xpToGrant; int xpForCurrentLevel; int xpForNextLevel; if (space_flags.hasCompletedTierFour(player)) { String tierFourSkill = profPrefix + space_flags.SKILL_NAMES[space_flags.TIER4_INDEXSTART]; String masterSkill = profPrefix + "_master"; xpForCurrentLevel = dataTableGetInt(TBL_SKILL, tierFourSkill, "XP_COST"); xpForNextLevel = dataTableGetInt(TBL_SKILL, masterSkill, "XP_COST"); } else if (space_flags.hasCompletedTierThree(player)) { String tierThreeSkill = profPrefix + space_flags.SKILL_NAMES[space_flags.TIER3_INDEXSTART]; String tierFourSkill = profPrefix + space_flags.SKILL_NAMES[space_flags.TIER4_INDEXSTART]; xpForCurrentLevel = dataTableGetInt(TBL_SKILL, tierThreeSkill, "XP_COST"); xpForNextLevel = dataTableGetInt(TBL_SKILL, tierFourSkill, "XP_COST"); } else if (space_flags.hasCompletedTierTwo(player)) { String tierTwoSkill = profPrefix + space_flags.SKILL_NAMES[space_flags.TIER2_INDEXSTART]; String tierThreeSkill = profPrefix + space_flags.SKILL_NAMES[space_flags.TIER3_INDEXSTART]; xpForCurrentLevel = dataTableGetInt(TBL_SKILL, tierTwoSkill, "XP_COST"); xpForNextLevel = dataTableGetInt(TBL_SKILL, tierThreeSkill, "XP_COST"); } else if (space_flags.hasCompletedTierOne(player)) { String tierOneSkill = profPrefix + space_flags.SKILL_NAMES[space_flags.TIER1_INDEXSTART]; String tierTwoSkill = profPrefix + space_flags.SKILL_NAMES[space_flags.TIER2_INDEXSTART]; xpForCurrentLevel = dataTableGetInt(TBL_SKILL, tierOneSkill, "XP_COST"); xpForNextLevel = dataTableGetInt(TBL_SKILL, tierTwoSkill, "XP_COST"); } else { String tierOneSkill = profPrefix + space_flags.SKILL_NAMES[space_flags.TIER1_INDEXSTART]; xpForCurrentLevel = 0; xpForNextLevel = dataTableGetInt(TBL_SKILL, tierOneSkill, "XP_COST"); } if (xpForCurrentLevel == -1 || xpForNextLevel == -1) { return 0; } float xpForLevel = xpForNextLevel - xpForCurrentLevel; float xpModifier = dataTableGetFloat(collection.COLLECTION_REWARD_TABLE, collectionName, "xpModifier"); long repeatSlotValue = getCollectionSlotValue(player, collectionName + "_tracker") - 1; if (repeatSlotValue > 0) { float repeatXpModifier = repeatCollectionXpModifier(player, repeatSlotValue); xpToGrant = xpModifier * xpForLevel * repeatXpModifier; return (int)xpToGrant; } xpToGrant = xpModifier * xpForLevel; return (int)xpToGrant; } public static float repeatCollectionXpModifier(obj_id player, long repeatSlotValue) throws InterruptedException { float repeatMultiplier; float adjustedRepeatSlotValue = (float)repeatSlotValue / 10.0f; repeatMultiplier = 1.0f - adjustedRepeatSlotValue; if (repeatMultiplier < 0.1f) { repeatMultiplier = 0.1f; } return repeatMultiplier; } }