mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-01-17 00:05:07 -05:00
2035 lines
84 KiB
Java
Executable File
2035 lines
84 KiB
Java
Executable File
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 != null && 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));
|
|
// only put a value in socialGroup if one can be derived from the target.
|
|
if(ai_lib.getSocialGroup(target) != null)
|
|
params.put("socialGroup", ai_lib.getSocialGroup(target));
|
|
else
|
|
LOG("DESIGNER_FATAL", "WARNING: target (" + target + ":" + creatureName + ") with tempate (" + getTemplateName(target) + ") does not have a social group!!");
|
|
// 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.getDailyMissionXpLimit() - 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;
|
|
}
|
|
}
|