Files
TekaohandGitHub 5c2e112349 Java 11.0.2 migration (#32)
* Code compiles - execution NOT tested

* updating gitignore

* Removed intellij settings files

* Removed more intellij files

* Added exclusion for JDK classes.

* Fixed purchasing script for vendors that have listed coin types.

* Updated script to not kick off until the entire preload is complete.

* adds static name entry for Solo movie poster and tcg9 vendor entry

* clean up empty and orphaned object templates

* adds placeholder black market (static) spawns

* corrects entries for the video game table to correctly set it in tcg series 2 and remove series 1 console errors

* Updated gitignore and removed intellij project files

* Fixed appearance reference for thranta payroll and kashyyyk door, added skipLosCheck objvar due to cannit see issue. Requires updated src

* Fixed appearance and template for terminal (#2)

* Fixed appearance and template for terminal (#3)

* Fixed appearance and template for terminal (#4)

* Deleted another faulty/orphaned object template

* Fixed gcw ranks option on frog. Only issue is that it doesn't award the officer commands or badges.

* Fixed some unneeded java 11 changes
2019-04-18 18:31:52 -05:00

4069 lines
182 KiB
Java
Executable File

package script.systems.combat;
import script.*;
import script.combat_engine.*;
import script.library.*;
import java.util.Arrays;
import java.util.Vector;
public class combat_base extends script.base_script
{
public combat_base()
{
}
public static final float MAX_THROWING_DISTANCE = 30;
public static final float PVP_DAMAGE_REDUCTION_VALUE = 0.75f;
public static final float UNIVERSAL_ACTION_COST_MULTIPLIER = 1.0f;
public static final String JEDI_COMBAT_DATATABLE = "datatables/jedi/jedi_combat_data.iff";
public static final int MAX_TARGET_ARRAY_SIZE = 10;
public static final int ALLOWED_LOS_FAILURES = 10;
public static final int TARGET_COMMAND = -2;
public static final int PRECHECK_SUCCESS = -1;
public static final int PRECHECK_OVERRIDE = 0;
public static final int PRECHECK_CONTINUE = 1;
public static final int HIT_RESULT_MISS = 0;
public static final int HIT_RESULT_DODGE = 1;
public static final int HIT_RESULT_PARRY = 2;
public static final int HIT_RESULT_GLANCING = 3;
public static final int HIT_RESULT_BLOCK = 4;
public static final int HIT_RESULT_CRITICAL = 5;
public static final int HIT_RESULT_PUNISHING = 6;
public static final int HIT_RESULT_HIT = 7;
public static final int HIT_RESULT_EVADE = 8;
public static final int HIT_RESULT_STRIKETHROUGH = 9;
public static final String PROGRESSIVE_DAMAGE_COUNTER = "hitData.progressive.counter";
public static final string_id SID_NONE = new string_id();
public boolean combatStandardAction(String actionName, obj_id self, obj_id target, String params, String successHandler, String failHandler) throws InterruptedException
{
return combatStandardAction(actionName, self, target, getCurrentWeapon(self), params, null, false, false, 0);
}
public boolean combatStandardAction(String actionName, obj_id self, obj_id target, String params, String successHandler, String failHandler, int overloadDamage) throws InterruptedException
{
return combatStandardAction(actionName, self, target, getCurrentWeapon(self), params, null, false, false, overloadDamage);
}
public boolean combatStandardAction(String actionName, obj_id self, obj_id target, String params, String successHandler, String failHandler, boolean testPetBar) throws InterruptedException
{
return combatStandardAction(actionName, self, target, getCurrentWeapon(self), params, null, false, testPetBar, 0);
}
public boolean combatStandardAction(String actionName, obj_id self, obj_id target, String params) throws InterruptedException
{
return combatStandardAction(actionName, self, target, getCurrentWeapon(self), params, null, false, false, 0);
}
public void sendPerformSpam(obj_id actor, obj_id target, string_id message, String actionName, int spam_type) throws InterruptedException
{
string_id actionStringId = new string_id("cmd_n", actionName);
prose_package pp = new prose_package();
pp = prose.setStringId(pp, message);
pp = prose.setTU(pp, actor);
pp = prose.setTT(pp, target);
pp = prose.setTO(pp, actionStringId);
sendCombatSpamMessageProse(actor, target, pp, true, true, true, spam_type);
}
public boolean combatStandardAction(String actionName, obj_id self, obj_id target, obj_id objWeapon, String params, combat_data actionData, boolean isTangibleAttacking) throws InterruptedException
{
return combatStandardAction(actionName, self, target, objWeapon, params, actionData, isTangibleAttacking, false, 0);
}
public boolean combatStandardAction(String actionName, obj_id self, obj_id target, obj_id objWeapon, String params, combat_data actionData, boolean isTangibleAttacking, boolean testPetBar, int overloadDamage) throws InterruptedException
{
if (combat.isStunned(self))
{
return false;
}
boolean triggerPetBar = false;
obj_id player = self;
if (testPetBar && isPlayer(self))
{
obj_id beast = beast_lib.getBeastOnPlayer(self);
if (!isIdValid(beast) || !exists(beast) || !beast_lib.canPerformCommand(self, beast, actionName))
{
return false;
}
target = isIdValid(getTarget(beast)) ? getTarget(beast) : getIntendedTarget(self);
self = beast;
objWeapon = getCurrentWeapon(self);
triggerPetBar = true;
}
if (weapons.checkForIllegalStorytellerWeapon(self, objWeapon))
{
weapons.handleIllegalStorytellerWeapon(self, objWeapon, "combatStandardAction");
utils.setScriptVar(objWeapon, "illegalStorytellerWeapon", true);
}
if (!storyteller.storytellerCombatCheck(self, target))
{
target = obj_id.NULL_ID;
}
boolean verbose = false;
boolean isEggWeapon = utils.hasScriptVar(objWeapon, "objOwner");
if (actionData == null)
{
actionData = combat_engine.getCombatData(actionName);
}
actionData = attackOverrideByBuff(self, actionData);
if (actionData == null)
{
combat.combatLog(self, target, "combatStandardAction", "Attack Aborted - Not a valid combat action - " + actionName);
return false;
}
if (isEggWeapon && actionName.equals("forceThrow"))
{
self = utils.getObjIdScriptVar(objWeapon, "objOwner");
objWeapon = getCurrentWeapon(self);
}
combat.combatLog(self, target, "combatStandardAction", "who=" + getName(self) + ", actionName=" + actionName + ", target = " + target + ", params.length=" + params.length() + ", params=" + params + ", weapon=" + getName(objWeapon));
boolean isGroundTarget = getWeaponType(objWeapon) == WEAPON_TYPE_GROUND_TARGETTING;
boolean isDirectionTarget = getWeaponType(objWeapon) == WEAPON_TYPE_DIRECTIONAL;
boolean isLocationTargetOk = actionData.delayAttackEggPosition == 3;
float xTarget = -1;
float yTarget = -1;
float zTarget = -1;
obj_id cellTarget = null;
location targetLoc = null;
boolean isAutoAiming = false;
if (params != null && !params.equals(""))
{
actionData.params = params;
java.util.StringTokenizer st = new java.util.StringTokenizer(params);
int paramCount = st.countTokens();
long cellId = 0;
if (paramCount >= 7)
{
xTarget = Float.parseFloat(st.nextToken());
yTarget = Float.parseFloat(st.nextToken());
zTarget = Float.parseFloat(st.nextToken());
cellId = Long.parseLong(st.nextToken());
if (cellId != 0)
{
cellTarget = obj_id.getObjId(cellId);
xTarget = Float.parseFloat(st.nextToken());
yTarget = Float.parseFloat(st.nextToken());
zTarget = Float.parseFloat(st.nextToken());
}
targetLoc = new location(xTarget, yTarget, zTarget, getCurrentSceneName(), cellTarget);
}
String lastArg = "";
while (st.hasMoreTokens())
{
lastArg = st.nextToken();
}
if (lastArg.equals("a"))
{
isAutoAiming = true;
}
}
if (params.equals("") && isLocationTargetOk)
{
targetLoc = getLocation(objWeapon);
}
if (utils.hasScriptVar(objWeapon, "isAutoAimed"))
{
isAutoAiming = utils.getBooleanScriptVar(objWeapon, "isAutoAimed");
}
boolean isSpecialAttack = actionData.commandType == combat.RIGHT_CLICK_SPECIAL;
int hitType = actionData.hitType;
boolean isDelayedAttack = false;
if (!isTangibleAttacking)
{
isDelayedAttack = (hitType == combat.DELAY_ATTACK);
}
weapon_data weaponData = getOverloadedWeaponData(self, objWeapon, actionData);
if (weaponData == null)
{
String logString = "getOverloadedWeaponData failed to return data for self: " + self + " " + " actionData: " + actionData;
if (isIdValid(self))
{
logString += (isPlayer(self) ? " a player object" : " a non-player object");
}
if (isIdValid(objWeapon))
{
logString += " objWeapon: " + objWeapon + " getName(objWeapon): " + getName(objWeapon);
if (!utils.hasScriptVar(objWeapon, "dctWeaponStats"))
{
logString += " dctWeaponStats: null";
}
else
{
logString += " dctWeaponStats: exists";
}
}
else
{
logString += " objWeapon: null dctWeaponStats: null";
}
CustomerServiceLog("combat_errors: ", logString);
return false;
}
if (!isTangibleAttacking)
{
if (!combat.canUseWeaponWithAbility(self, weaponData, actionData, verbose))
{
combat.combatLog(self, null, "combatStandardAction", "Aborting Attack - Not able to use this action (" + actionName + ") with the current weapon");
return false;
}
}
obj_id combatTarget = target;
if (isTangibleAttacking)
{
actionData.validTarget = actionData.validEggTarget;
}
if (isSpecialAttack && !isTangibleAttacking)
{
combatTarget = getCorrectCombatTarget(self, target, actionData, verbose);
if (!isIdValid(combatTarget))
{
combat.combatLog(self, target, "combatStandardAction", "Attack Failed - No valid combat target");
return false;
}
}
else if (!isTangibleAttacking && !isGroundTarget && !isDirectionTarget)
{
combatTarget = getCorrectCombatTarget(self, target, actionData, verbose);
if (!isIdValid(combatTarget))
{
combat.combatLog(self, target, "combatStandardAction", "Attack Failed - No valid combat target");
return false;
}
}
attacker_data attackerData = new attacker_data();
defender_data[] defenderData = null;
if (isGroundTarget || isDirectionTarget)
{
actionData.targetLoc = targetLoc;
}
if (isLocationTargetOk && targetLoc != null)
{
actionData.targetLoc = targetLoc;
}
if (!isTangibleAttacking)
{
actionData = modifyActionDataByExpertise(self, actionData);
}
stealth.clearPreviousInvis(self);
stealth.testInvisCombatAction(self, target, actionData);
if (!isDelayedAttack)
{
obj_id[] defenders = getCombatDefenders(self, combatTarget, weaponData, actionData, isSpecialAttack);
if (defenders == null || defenders.length == 0)
{
combat.combatLog(self, target, "combatStandardAction", "Attack Failed - No valid targets");
if (weaponData.weaponType == WEAPON_TYPE_DIRECTIONAL && !isEggWeapon)
{
attacker_results atkRslt = new attacker_results();
defender_results[] dfndRslt = new defender_results[0];
atkRslt.id = self;
atkRslt.weapon = weaponData.id;
atkRslt.actionName = getStringCrc(toLower(actionName));
atkRslt.useLocation = true;
if(targetLoc != null && isValidLocation(targetLoc)) {
atkRslt.targetLocation = new vector(targetLoc.x, targetLoc.y, targetLoc.z);
atkRslt.targetCell = targetLoc.cell;
}
else {
location tl = getLocation(target);
if(!isValidLocation(tl)){
LOG("combat","Could not identify the target's (" + target + ":" + getPlayerFullName(target) + ") location (" + targetLoc + ") to attack it.");
}
atkRslt.targetLocation = new vector(tl.x, tl.y, tl.z);
atkRslt.targetCell = tl.cell;
}
atkRslt.endPosture = (combat.isMeleeWeapon(weaponData.id) || combat.isLightsaberWeapon(weaponData.id)) ? POSTURE_UPRIGHT : getPosture(self);
String anim = actionData.animDefault;
stealth.testInvisCombatAction(self, target, actionData);
doCombatResults(anim, atkRslt, dfndRslt);
return true;
}
stealth.reinstateInvisFromCombat(self);
return false;
}
weapon_data junkData = new weapon_data();
defenderData = new defender_data[defenders.length];
if (!getCombatData(self, defenders, attackerData, defenderData, junkData))
{
String msg = "ERROR::combatStandardAction:" + actionData.actionName + ") call to getCombatData returned false";
CustomerServiceLog("combat_errors", msg);
stealth.reinstateInvisFromCombat(self);
return false;
}
}
else
{
attackerData.id = self;
defender_data dat = new defender_data();
dat.id = target;
defenderData = new defender_data[]
{
dat
};
}
int[] actionCost = null;
if (!isTangibleAttacking)
{
actionCost = combat.getActionCost(self, weaponData, actionData);
if (!combat.canDrainCombatActionAttributes(self, actionCost))
{
showFlyTextPrivate(self, self, new string_id("combat_effects", "action_too_tired"), 1.5f, colors.GOLDENROD);
if (verbose)
{
combat.sendCombatSpamMessage(self, new string_id("cbt_spam", "pool_drain_fail"));
}
combat.combatLog(self, self, "combatStandardAction", "Aborting Attack - Insufficient ability points for action");
stealth.reinstateInvisFromCombat(self);
return false;
}
int killMeterCost = (int)actionData.vigorCost;
if (killMeterCost > 0)
{
if (!beast_lib.isBeast(attackerData.id) && isPlayer(attackerData.id))
{
if (!combat.canDrainKillMeter(attackerData.id, killMeterCost))
{
showFlyTextPrivate(self, self, new string_id("combat_effects", "need_more_kills"), 1.5f, colors.FIREBRICK);
stealth.reinstateInvisFromCombat(self);
return false;
}
combat.drainKillMeter(attackerData.id, killMeterCost);
}
}
}
boolean isHeal = hitType == combat.HEAL;
boolean isRevive = hitType == combat.REVIVE;
if (isHeal || isRevive)
{
combat.combatLog(self, combatTarget, "combatStandardAction", "Heal Action - Branching off to healing functionality");
if (!doHealingPreCheck(actionData, attackerData, defenderData, verbose))
{
combat.combatLog(self, combatTarget, "combatStandardAction", "Attack Failed - Healing precheck failed");
stealth.reinstateInvisFromCombat(self);
return false;
}
if (!combat.canDrainCombatActionAttributes(self, actionCost))
{
stealth.reinstateInvisFromCombat(self);
return false;
}
if (actionData.performanceSpamStrId.isValid() && !isTangibleAttacking)
{
sendPerformSpam(self, combatTarget, actionData.performanceSpamStrId, actionName, COMBAT_RESULT_GENERIC);
}
boolean success = false;
if (isHeal)
{
success = healing.performHealDamage(attackerData, defenderData, actionData);
}
if (isRevive)
{
success = healing.performRevivePlayer(attackerData, defenderData, actionData, actionData.addedDamage > 0);
}
if (success)
{
stealth.testInvisNonCombatAction(self, target, actionData);
}
if (success)
{
LOG("combat_base", "combatStandardAction 7 success " + actionName);
if (!combat.drainCombatActionAttributes(self, actionCost))
{
combat.combatLog(self, combatTarget, "combatStandardAction", "ERROR:Insufficient action not caught in canDrainCombatActionAttributes()");
stealth.reinstateInvisFromCombat(self);
return false;
}
String anim = actionData.animDefault;
attacker_results cbtAttackerResults = new attacker_results();
obj_id defender = self;
if (isIdValid(target) && target != self && !isDead(target))
{
defender = target;
}
defender_results[] cbtDefenderResults = new defender_results[1];
cbtDefenderResults[0] = new defender_results();
cbtDefenderResults[0].id = defender;
cbtDefenderResults[0].endPosture = getPosture(defender);
cbtDefenderResults[0].result = COMBAT_RESULT_HIT;
cbtAttackerResults.id = self;
cbtAttackerResults.weapon = null;
cbtAttackerResults.actionName = getStringCrc(toLower(actionName));
cbtAttackerResults.endPosture = getPosture(self);
doCombatResults(anim, cbtAttackerResults, cbtDefenderResults);
}
return success;
}
else if (!isTangibleAttacking)
{
if (!doCombatPreCheck(actionData, attackerData, weaponData, defenderData, verbose))
{
combat.combatLog(self, combatTarget, "combatStandardAction", "Attack Failed - Combat precheck failed");
stealth.reinstateInvisFromCombat(self);
return false;
}
boolean isSingleTargetAttack = actionData.hitType == -1 && actionData.attackType == combat.SINGLE_TARGET;
if (!isSingleTargetAttack && !combat.drainCombatActionAttributes(self, actionCost))
{
showFlyTextPrivate(self, self, new string_id("combat_effects", "action_too_tired"), 1.5f, colors.GOLDENROD);
combat.combatLog(self, combatTarget, "combatStandardAction", "ERROR:Insufficient action not caught in canDrainCombatActionAttributes()");
stealth.reinstateInvisFromCombat(self);
return false;
}
if (actionData.performanceSpamStrId.isValid())
{
sendPerformSpam(self, combatTarget, actionData.performanceSpamStrId, actionName, COMBAT_RESULT_GENERIC);
}
}
attacker_results attackerResults = new attacker_results();
defender_results[] defenderResults = new defender_results[defenderData.length];
if (!isDelayedAttack)
{
hit_result[] hitData = null;
hitData = runHitEngine(attackerData, weaponData, defenderData, attackerResults, defenderResults, actionData, isTangibleAttacking, isAutoAiming, overloadDamage);
if (hitData == null)
{
String msg = " Attack Failed - No hit data returned";
CustomerServiceLog("combat_errors", "ERROR::combatStandardAction:" + actionData.actionName + " " + msg);
combat.combatLog(self, combatTarget, "combatStandardAction", msg);
stealth.reinstateInvisFromCombat(self);
return false;
}
}
else if (isGroundTarget && !isSpecialAttack)
{
attacker_results atkRslt = new attacker_results();
defender_results[] dfndRslt = new defender_results[0];
atkRslt.id = self;
atkRslt.weapon = weaponData.id;
atkRslt.actionName = getStringCrc(toLower(actionName));
atkRslt.useLocation = true;
atkRslt.targetLocation = new vector(targetLoc.x, targetLoc.y, targetLoc.z);
atkRslt.targetCell = targetLoc.cell;
atkRslt.endPosture = (combat.isMeleeWeapon(weaponData.id) || combat.isLightsaberWeapon(weaponData.id)) ? POSTURE_UPRIGHT : getPosture(self);
String anim = actionData.animDefault;
doCombatResults(anim, atkRslt, dfndRslt);
}
if ((isDelayedAttack) && (!isTangibleAttacking))
{
if (utils.hasScriptVar(self, combat.DIED_RECENTLY))
{
utils.removeScriptVar(self, combat.DIED_RECENTLY);
}
LOG("combat_base", "startDelayedAttack");
startDelayedAttack(self, combatTarget, objWeapon, actionName, actionData, isGroundTarget, isAutoAiming);
}
if (beast_lib.isChargeAttack(actionName))
{
setLocation(self, getLocation(target));
}
if (!isPlayer(self) && !beast_lib.isBeast(self))
{
setCommandTimerValue(self, TIMER_COOLDOWN, 0.0f);
}
if (triggerPetBar)
{
combat_data cd = combat_engine.getCombatData(actionName);
String cooldownGroup = cd.cooldownGroup;
int groupCrc = getStringCrc(cooldownGroup);
sendCooldownGroupTimingOnly(player, groupCrc, cd.cooldownTime);
}
return true;
}
public void startDelayedAttack(obj_id attacker, obj_id target, obj_id objWeapon, String attackName, combat_data actionData, boolean instantHit, boolean isAutoAimed) throws InterruptedException
{
int eggPosition = actionData.delayAttackEggPosition;
location where = getLocation(attacker);
if (eggPosition == 2)
{
where = getLocation(target);
}
else if (eggPosition == 3)
{
where = (location)actionData.targetLoc.clone();
}
obj_id egg = combat.makeTrackerEgg(attacker, where, actionData);
if (!isIdValid(egg) || !exists(egg))
{
return;
}
dictionary dctWeaponStats = utils.getDictionaryScriptVar(objWeapon, "dctWeaponStats");
if(dctWeaponStats != null)
utils.setScriptVar(egg, "dctWeaponStats", dctWeaponStats);
utils.setScriptVar(egg, "isAutoAimed", isAutoAimed);
doStandardDelayedAction(egg, target, attackName, actionData, instantHit);
}
public void doStandardDelayedAction(obj_id objEgg, obj_id target, String attackName, combat_data actionData, boolean instantHit) throws InterruptedException
{
float delay = actionData.delayAttackInterval;
String strEffect = actionData.delayAttackParticle;
int intLoops = actionData.delayAttackLoops;
boolean boolDestroy = true;
if (intLoops > 1)
{
if (!utils.hasScriptVar(objEgg, "intLoopsLeft"))
{
utils.setScriptVar(objEgg, "intLoopsLeft", intLoops);
boolDestroy = false;
}
else
{
intLoops = utils.getIntScriptVar(objEgg, "intLoopsLeft");
if (intLoops > 1)
{
boolDestroy = false;
}
}
}
if (instantHit)
{
float initDelay = actionData.initialDelayAttackInterval;
if (initDelay >= 0)
{
delay = initDelay;
}
}
obj_id objOwner = utils.getObjIdScriptVar(objEgg, "objOwner");
if (isIdValid(objOwner))
{
delay += (int)getSkillStatisticModifier(objOwner, "expertise_delay_line_" + actionData.specialLine);
delay -= (int)getSkillStatisticModifier(objOwner, "expertise_delay_reduce_line_" + actionData.specialLine);
}
if (delay < 0)
{
delay = 0;
}
doDelayedParticle(objEgg, strEffect, delay, false);
doDelayedAttack(objEgg, attackName, target, delay, "", boolDestroy);
return;
}
public void doDelayedParticle(obj_id objEgg, String strEffect, float fltDelay, boolean boolCleanup) throws InterruptedException
{
dictionary dctParams = new dictionary();
dctParams.put("strEffect", strEffect);
dctParams.put("boolCleanup", boolCleanup);
utils.setScriptVar(objEgg, "handleDelayedParticle", dctParams);
messageTo(objEgg, "handleDelayedParticle", dctParams, fltDelay, false);
return;
}
public void doDelayedAttack(obj_id objEgg, String strAttack, obj_id objTarget, float fltDelay, String strEffect, boolean boolCleanup) throws InterruptedException
{
dictionary dctParams = new dictionary();
dctParams.put("strCommand", strAttack);
dctParams.put("objTarget", objTarget);
dctParams.put("boolCleanup", boolCleanup);
dctParams.put("strEffect", strEffect);
utils.setScriptVar(objEgg, "handleDelayedAttack", dctParams);
messageTo(objEgg, "handleDelayedAttack", dctParams, fltDelay, false);
}
public obj_id getCorrectCombatTarget(obj_id self, obj_id curTarget, boolean verbose) throws InterruptedException
{
return getCorrectCombatTarget(self, curTarget, "", new combat_data(), verbose);
}
public obj_id getCorrectCombatTarget(obj_id self, obj_id curTarget, combat_data actionData, boolean verbose) throws InterruptedException
{
return getCorrectCombatTarget(self, curTarget, "", actionData, verbose);
}
public obj_id getCorrectCombatTarget(obj_id self, obj_id curTarget, String params, combat_data actionData, boolean verbose) throws InterruptedException
{
obj_id newTarget = curTarget;
int validTargetType = actionData.validTarget;
boolean isOffensive = (validTargetType != combat.VALID_TARGET_FRIEND && validTargetType != combat.VALID_TARGET_DEAD);
if (actionData.actionName.equals("me_stasis_1") || actionData.actionName.startsWith("bm_mend_pet") || actionData.actionName.equals("bm_soothing_comfort_1") || actionData.actionName.startsWith("bm_revive"))
{
return newTarget;
}
if (validTargetType == -1)
{
return self;
}
if (newTarget == self)
{
int intHitType = actionData.hitType;
if (isOffensive)
{
if (verbose)
{
combat.sendCombatSpamMessage(self, new string_id("cbt_spam", "shoot_self"));
}
combat.combatLog(self, curTarget, "getCorrectCombatTarget", "Cannot attack self - returning null target");
return null;
}
}
if (isOffensive && isDead(newTarget))
{
if (verbose)
{
combat.sendCombatSpamMessage(self, new string_id("cbt_spam", "invalid_target"));
}
combat.combatLog(self, newTarget, "getCorrectCombatTarget", "Invalid Target - Target is Dead");
return null;
}
if (isOffensive && isIncapacitated(newTarget))
{
if (verbose)
{
combat.sendCombatSpamMessage(self, new string_id("cbt_spam", "invalid_target"));
}
combat.combatLog(self, newTarget, "getCorrectCombatTarget", "Invalid Target - Target is Incapped");
return null;
}
if (!isOffensive && (newTarget != self) && (!isIdValid(newTarget) || pvpCanAttack(self, newTarget) || !pvpCanHelp(self, newTarget)))
{
newTarget = self;
}
if (!combat.validateTarget(newTarget, actionData.validTarget))
{
if (verbose)
{
combat.sendCombatSpamMessage(self, new string_id("cbt_spam", "invalid_target"));
}
combat.combatLog(self, curTarget, "getCorrectCombatTarget", "Invalid target as defined in datatable - returning null target");
return null;
}
obj_id container = getContainedBy(newTarget);
if (isPlayer(container))
{
String msg = "Cannot attack item contained by player - returning null target";
CustomerServiceLog("combat_errors", "ERROR::getCorrectCombatTarget:" + msg);
return null;
}
if ((!isOffensive && !pvpCanHelp(self, newTarget)) || (isOffensive && !pvpCanAttack(self, newTarget)))
{
if (verbose)
{
combat.sendCombatSpamMessage(self, new string_id("cbt_spam", "invalid_pvp_target"));
}
combat.combatLog(self, curTarget, "getCorrectCombatTarget", "Not a valid PvP target - returning null target");
return null;
}
if (isOffensive && stealth.hasInvisibleBuff(newTarget))
{
int range = getPassiveRevealRange(newTarget, self);
if (range >= 0)
{
stealth.checkForAndMakeVisible(newTarget);
}
else
{
if (verbose)
{
combat.sendCombatSpamMessage(self, new string_id("cbt_spam", "invalid_target"));
}
return null;
}
}
return newTarget;
}
public boolean isInAttackRange(obj_id attacker, obj_id target, String actionName, boolean verbose) throws InterruptedException
{
if (!isIdValid(attacker) || !exists(attacker) || !isIdValid(target) || !exists(target))
{
return false;
}
combat_data actionData = combat_engine.getCombatData(actionName);
if (actionData == null)
{
return false;
}
obj_id weapon = getCurrentWeapon(attacker);
if (!isIdValid(weapon) || !exists(weapon))
{
return false;
}
weapon_data weaponData = getOverloadedWeaponData(attacker, weapon, actionData);
if (weaponData == null)
{
return false;
}
return isInAttackRange(attacker, target, actionData, weaponData, verbose);
}
public boolean isInAttackRange(obj_id attacker, obj_id target, combat_data actionData, weapon_data weaponData, boolean verbose) throws InterruptedException
{
float dist = getDistance(attacker, target);
float adjustMin = 0.0f;
float adjustMax = 0.0f;
if (dist > combat_engine.getMaxCombatRange() && actionData.ignore_distance == 0)
{
if (verbose)
{
showFlyTextPrivate(attacker, attacker, new string_id("combat_effects", "range_too_far"), 1.5f, colors.MEDIUMTURQUOISE);
combat.sendCombatSpamMessage(attacker, new string_id("cbt_spam", "out_of_range_far"), COMBAT_RESULT_OUT_OF_RANGE);
}
combat.combatLog(attacker, target, "doCombatPreCheck", "Aborting Attack - Target is further than max combat range");
return false;
}
if (actionData.overloadWeaponType == WEAPON_TYPE_THROWN)
{
weaponData.maxRange = cybernetic.getThrowRangeMod(attacker, weaponData.maxRange);
}
else
{
int intWeaponCategory = combat.getWeaponCategory(weaponData.weaponType);
if (intWeaponCategory == combat.RANGED_WEAPON)
{
weaponData.maxRange = cybernetic.getRangedRangeMod(attacker, weaponData.maxRange);
}
else
{
adjustMax = 6.0f;
}
}
float rangeMod = getSkillStatisticModifier(attacker, "expertise_range_bonus_" + weaponData.weaponType);
weaponData.maxRange += rangeMod;
float actionMaxRange = actionData.maxRange;
if (actionMaxRange > 0)
{
weaponData.maxRange = actionMaxRange;
}
rangeMod = getSkillStatisticModifier(attacker, "expertise_range_line_" + actionData.specialLine);
if (rangeMod != 0)
{
weaponData.maxRange += rangeMod;
}
if (dist > (weaponData.maxRange + adjustMax) && actionData.ignore_distance == 0)
{
if (verbose)
{
showFlyTextPrivate(attacker, attacker, new string_id("combat_effects", "range_too_far"), 1.5f, colors.MEDIUMTURQUOISE);
combat.sendCombatSpamMessage(attacker, new string_id("cbt_spam", "out_of_range_far"), COMBAT_RESULT_OUT_OF_RANGE);
}
combat.combatLog(attacker, target, "doCombatPreCheck", "Aborting Attak - Target is further than max range modified");
return false;
}
return true;
}
public boolean doCombatPreCheck(combat_data actionData, attacker_data attackerData, weapon_data weaponData, defender_data[] defenderData, boolean verbose) throws InterruptedException
{
verbose = false;
if ((isPlayer(attackerData.id) && isPlayer(defenderData[0].id)) && (attackerData.id != defenderData[0].id))
{
String setting = getConfigSetting("GameServer", "disablePvP");
if (setting != null && (setting.equals("1") || setting.equals("true")))
{
if (verbose)
{
return false;
}
}
}
if (isDead(attackerData.id))
{
if (verbose)
{
showFlyTextPrivate(attackerData.id, attackerData.id, new string_id("combat_effects", "cant_attack_fly"), 1.5f, colors.WHITE);
combat.sendCombatSpamMessage(attackerData.id, new string_id("cbt_spam", "attack_fail_dead"));
}
combat.combatLog(attackerData.id, defenderData[0].id, "doCombatPreCheck", "Aborting Attack - Attacker is dead");
return false;
}
if (isIncapacitated(attackerData.id))
{
if (verbose)
{
showFlyTextPrivate(attackerData.id, attackerData.id, new string_id("combat_effects", "cant_attack_fly"), 1.5f, colors.WHITE);
combat.sendCombatSpamMessage(attackerData.id, new string_id("cbt_spam", "attack_fail_incap"));
}
combat.combatLog(attackerData.id, defenderData[0].id, "doCombatPreCheck", "Aborting Attack - Attacker is incapped");
return false;
}
if (!isInAttackRange(attackerData.id, defenderData[0].id, actionData, weaponData, verbose))
{
return false;
}
boolean cansee = false;
if (actionData.specialLine.equals("ignore_los") || actionData.specialLine.equals("co_remote_detonator"))
{
cansee = true;
}
else if (weaponData.weaponType == WEAPON_TYPE_GROUND_TARGETTING)
{
int isSpecialAttack = actionData.commandType;
if (actionData.specialLine.equals("no_proc"))
{
cansee = true;
}
else if (isSpecialAttack == combat.RIGHT_CLICK_SPECIAL && combat.isHeavyWeapon(weaponData))
{
cansee = true;
}
else
{
location where = (location)actionData.targetLoc.clone();
where.y += 0.5f;
cansee = canSee(attackerData.id, where);
}
}
else if (weaponData.weaponType == WEAPON_TYPE_DIRECTIONAL)
{
cansee = true;
}
else
{
cansee = canSee(attackerData.id, defenderData[0].id);
}
if (!cansee)
{
if (verbose)
{
showFlyTextPrivate(attackerData.id, attackerData.id, new string_id("combat_effects", "cant_see"), 1.5f, colors.MEDIUMTURQUOISE);
combat.sendCombatSpamMessage(attackerData.id, new string_id("cbt_spam", "out_of_range_close"), COMBAT_RESULT_OUT_OF_RANGE);
}
return false;
}
setState(attackerData.id, STATE_PEACE, false);
return true;
}
public obj_id getNextHatedTarget(obj_id self, obj_id[] tempDefenders, obj_id currentTarget) throws InterruptedException
{
if (tempDefenders == null || tempDefenders.length == 0)
{
return null;
}
for (obj_id tempDefender : tempDefenders) {
if (tempDefender != currentTarget && isOnHateList(self, tempDefender)) {
return tempDefender;
}
}
return null;
}
public obj_id[] getCombatDefenders(obj_id self, obj_id target, weapon_data weaponData, combat_data actionData, boolean isSpecialAttack) throws InterruptedException
{
int validTargetType = actionData.validTarget;
int attackType = actionData.attackType;
int hitType = actionData.hitType;
boolean isOffensive = true;
int pvpOnly = actionData.pvp_only;
if (validTargetType == combat.VALID_TARGET_FRIEND || validTargetType == combat.VALID_TARGET_DEAD || hitType == combat.HEAL || hitType == combat.REVIVE)
{
isOffensive = false;
}
boolean fromTrap = hitType == combat.DELAY_ATTACK;
obj_id source = self;
obj_id[] defenders = null;
if (actionData.actionName.equals("me_stasis_1") || actionData.actionName.startsWith("bm_mend_pet") || actionData.actionName.equals("bm_soothing_comfort_1") || actionData.actionName.startsWith("bm_revive"))
{
isOffensive = false;
}
if ((!isOffensive || hitType == combat.NON_ATTACK) && validTargetType == combat.VALID_TARGET_NONE)
{
target = self;
}
if (validTargetType == -1 && attackType == combat.SINGLE_TARGET)
{
defenders = new obj_id[1];
defenders[0] = target;
return defenders;
}
if (attackType == combat.SINGLE_TARGET)
{
if (defenders == null || defenders.length == 0)
{
int rolls = actionData.attack_rolls == 1 ? 1 : actionData.attack_rolls - 1;
defenders = new obj_id[rolls];
for (int q = 0; q < defenders.length; q++)
{
defenders[q] = target;
}
}
}
else if (attackType == combat.CONE)
{
float length = actionData.coneLength;
float width = actionData.coneWidth;
String actionName = actionData.actionName;
String specialLine = actionData.specialLine;
float expertiseConeLengthBonus = 0.0f;
float expertiseConeWidthBonus = 0.0f;
if (actionName != null && !actionName.equals(""))
{
expertiseConeLengthBonus = getSkillStatisticModifier(self, "expertise_cone_length_single_" + actionName);
}
if (specialLine != null && !specialLine.equals(""))
{
expertiseConeLengthBonus += getSkillStatisticModifier(self, "expertise_cone_length_line_" + specialLine);
}
if (specialLine != null && !actionName.equals(""))
{
expertiseConeWidthBonus += getSkillStatisticModifier(self, "expertise_cone_width_line_" + specialLine);
}
length += expertiseConeLengthBonus;
width += (expertiseConeWidthBonus / 2.0f);
if (actionData.maxRange == 0)
{
length = weaponData.maxRange;
}
if (!isOffensive)
{
defenders = getObjectsInCone(fromTrap ? weaponData.id : self, target, length, width);
}
else
{
if (weaponData.weaponType == WEAPON_TYPE_DIRECTIONAL)
{
if(actionData != null && isValidLocation(actionData.targetLoc)) {
defenders = pvpGetTargetsInCone(self, self, actionData.targetLoc, length, width);
}
else{
defenders = pvpGetTargetsInCone(self, self, target, length, width);
}
}
else
{
defenders = pvpGetTargetsInCone(self, fromTrap ? weaponData.id : self, target, length, width);
}
}
if (defenders == null || defenders.length < 1)
{
defenders = new obj_id[1];
defenders[0] = target;
}
combat.combatLog(self, target, "getCombatDefenders", "CONE TARGET: Defender count = " + defenders.length);
}
else if (attackType == combat.AREA || attackType == combat.TARGET_AREA)
{
float area = actionData.coneLength;
String actionName = actionData.actionName;
String specialLine = actionData.specialLine;
float expertiseConeLengthBonus = 0.0f;
if (actionName != null && !actionName.equals(""))
{
expertiseConeLengthBonus = getSkillStatisticModifier(self, "expertise_area_size_single_" + actionName);
}
if (specialLine != null && !specialLine.equals(""))
{
expertiseConeLengthBonus += getSkillStatisticModifier(self, "expertise_area_size_line_" + specialLine);
}
area += expertiseConeLengthBonus;
if (area <= 0)
{
area = weaponData.maxRange;
}
if (attackType == combat.AREA)
{
combat.combatLog(self, target, "getCombatDefenders", "Attack Type = combat.AREA");
combat.combatLog(self, target, "getCombatDefenders", "Area Effect = " + area);
if (!isOffensive)
{
defenders = getCreaturesInRange(fromTrap ? weaponData.id : self, area);
}
else
{
defenders = pvpGetTargetsInRange(self, fromTrap ? weaponData.id : self, area);
}
combat.combatLog(self, target, "getCombatDefenders", "AREA SELF: self = " + self);
}
else
{
combat.combatLog(self, target, "getCombatDefenders", "Attack Type = combat.TARGET_AREA");
combat.combatLog(self, target, "getCombatDefenders", "Area Effect = " + area);
if (!isOffensive)
{
defenders = getCreaturesInRange(target, area);
}
else
{
defenders = pvpGetTargetsInRange(self, fromTrap ? weaponData.id : target, area);
}
source = target;
}
if (defenders == null || defenders.length < 1 && actionData.commandType == combat.LEFT_CLICK_DEFAULT)
{
defenders = new obj_id[1];
defenders[0] = target;
}
combat.combatLog(self, target, "getCombatDefenders", "AREA EFFECT: Defender count = " + defenders.length);
}
else if (attackType == combat.RAMPAGE)
{
float area = actionData.coneLength;
obj_id[] areaTargets = pvpGetTargetsInRange(self, self, area);
float maxHate = 0;
obj_id rampageTarget = null;
for (obj_id areaTarget : areaTargets) {
if (areaTarget == target) {
continue;
}
if (isOnHateList(self, areaTarget)) {
float targetHate = getHate(self, areaTarget);
if (targetHate > maxHate && combat.cachedCanSee(self, areaTarget)) {
rampageTarget = areaTarget;
maxHate = targetHate;
}
}
}
if (isIdValid(rampageTarget))
{
defenders = new obj_id[1];
target = rampageTarget;
defenders[0] = rampageTarget;
}
else
{
defenders = new obj_id[1];
defenders[0] = target;
}
combat.combatLog(self, target, "getCombatDefenders", "RAMPAGE: Defender count = " + defenders.length);
}
else if (attackType == combat.RANDOM_HATE_TARGET)
{
obj_id[] potentialTargets = getHateList(self);
float max_range = 64.0f;
Vector validTargets = new Vector();
validTargets.setSize(0);
for (obj_id potentialTarget : potentialTargets) {
if (potentialTarget != target && combat.cachedCanSee(self, potentialTarget) && !isDead(potentialTarget)) {
if (getDistance(self, potentialTarget) < max_range) {
utils.addElement(validTargets, potentialTarget);
}
}
}
if (validTargets == null || validTargets.size() == 0)
{
defenders = new obj_id[1];
defenders[0] = target;
}
else
{
target = ((obj_id)validTargets.get(rand(0, validTargets.size() - 1)));
defenders = new obj_id[1];
defenders[0] = target;
}
}
else if (attackType == combat.RANDOM_HATE_TARGET_CONE)
{
float length = actionData.coneLength;
float width = actionData.coneWidth;
float max_range = length;
obj_id[] potentialTargets = getHateList(self);
Vector validTargets = new Vector();
validTargets.setSize(0);
for (obj_id potentialTarget : potentialTargets) {
if (potentialTarget != target && combat.cachedCanSee(self, potentialTarget) && !isDead(potentialTarget)) {
if (getDistance(self, potentialTarget) < max_range) {
utils.addElement(validTargets, potentialTarget);
}
}
}
if (validTargets == null || validTargets.size() == 0)
{
defenders = pvpGetTargetsInCone(self, self, target, length, width);
}
else
{
target = ((obj_id)validTargets.get(rand(0, validTargets.size() - 1)));
defenders = pvpGetTargetsInCone(self, self, target, length, width);
}
}
else if (attackType == combat.RANDOM_HATE_TARGET_CONE_TERMINUS)
{
float width = actionData.coneWidth;
float max_range = 64.0f;
obj_id[] potentialTargets = getHateList(self);
Vector validTargets = new Vector();
validTargets.setSize(0);
for (obj_id potentialTarget : potentialTargets) {
if (potentialTarget != target && combat.cachedCanSee(self, potentialTarget)) {
if (getDistance(self, potentialTarget) < max_range) {
utils.addElement(validTargets, potentialTarget);
}
}
}
if (validTargets == null || validTargets.size() == 0)
{
defenders = pvpGetTargetsInCone(self, self, target, getDistance(self, target) + 5.0f, width);
}
else
{
target = ((obj_id)validTargets.get(rand(0, validTargets.size() - 1)));
max_range = getDistance(self, target) + 5.0f;
defenders = pvpGetTargetsInCone(self, self, target, max_range, width);
}
}
else if (attackType == combat.HATE_LIST)
{
obj_id[] hateTargets = getHateList(self);
Vector validTargets = new Vector();
validTargets.setSize(0);
int max_range = 90;
for (obj_id hateTarget : hateTargets) {
if (hateTarget != target && canSee(self, hateTarget)) {
if (getDistance(self, hateTarget) < max_range) {
utils.addElement(validTargets, hateTarget);
}
}
}
if (validTargets != null)
{
defenders = new obj_id[validTargets.size()];
validTargets.toArray(defenders);
}
}
else if (attackType == combat.RANDOM_HATE_MULTI)
{
obj_id[] hateTargets = getHateList(self);
int max_targets = (int)actionData.coneLength;
if (hateTargets.length == 1)
{
defenders = new obj_id[1];
defenders[0] = target;
}
else
{
obj_id[] randomTargets = new obj_id[max_targets];
Vector targetList = new Vector(Arrays.asList((obj_id[])hateTargets.clone()));
targetList = utils.shuffleArray(targetList);
if (max_targets > hateTargets.length)
{
max_targets = hateTargets.length;
}
for (int i = 0; i < max_targets; i++)
{
randomTargets[i] = ((obj_id)targetList.get(i));
}
defenders = randomTargets;
}
}
else if (attackType == combat.AREA_PROGRESSIVE)
{
float area = actionData.coneLength;
if (area <= 0)
{
area = weaponData.maxRange;
}
defenders = pvpGetTargetsInRange(self, self, area);
}
else if (attackType == combat.SPLIT_DAMAGE_TARGET_AREA)
{
float area = actionData.coneLength;
float targets = actionData.coneWidth;
obj_id[] targetsInArea = pvpGetTargetsInRange(self, fromTrap ? weaponData.id : target, area);
defenders = new obj_id[2];
defenders[0] = target;
for (obj_id obj_id : targetsInArea) {
if (obj_id != target) {
defenders[1] = obj_id;
break;
}
}
}
else if (attackType == combat.DISTANCE_FARTHEST)
{
obj_id[] hateList = getHateList(self);
obj_id farthest = getHateTarget(self);
float farDist = 0.0f;
for (obj_id obj_id : hateList) {
if (getDistance(self, obj_id) >= farDist) {
farthest = obj_id;
farDist = getDistance(self, obj_id);
}
}
defenders = new obj_id[1];
defenders[0] = farthest;
target = farthest;
}
else
{
defenders = new obj_id[1];
defenders[0] = target;
combat.combatLog(self, target, "getCombatDefenders", "DEFAULT: Defender count = " + defenders.length);
}
defenders = validateDefenders(self, target, defenders, source, MAX_TARGET_ARRAY_SIZE, validTargetType, isOffensive, fromTrap ? weaponData.id : null, combat.isHeavyWeapon(weaponData), isSpecialAttack, actionData.specialLine.equals("ignore_los") ? true : false, pvpOnly, actionData);
utils.setScriptVar(self, combat.CHARGE_TARGET, target);
return defenders;
}
public hit_result[] runHitEngine(attacker_data attackerData, weapon_data weaponData, defender_data[] defenderData, attacker_results attackerResults, defender_results[] defenderResults, combat_data actionData, boolean isTangibleAttacking) throws InterruptedException
{
return runHitEngine(attackerData, weaponData, defenderData, attackerResults, defenderResults, actionData, isTangibleAttacking, true, 0);
}
public hit_result[] runHitEngine(attacker_data attackerData, weapon_data weaponData, defender_data[] defenderData, attacker_results attackerResults, defender_results[] defenderResults, combat_data actionData, boolean isTangibleAttacking, boolean isAutoAiming, int overloadDamage) throws InterruptedException
{
hit_result[] hitData = new hit_result[defenderData.length];
obj_id[] defenders = new obj_id[defenderData.length];
int[] results = new int[hitData.length];
String[] playbackNames = new String[defenderData.length];
String strAttack = actionData.actionName;
attackerResults.id = attackerData.id;
attackerResults.weapon = weaponData.id;
attackerResults.endPosture = (!isTangibleAttacking && (combat.isMeleeWeapon(weaponData.id) || combat.isLightsaberWeapon(weaponData.id))) ? POSTURE_UPRIGHT : getPosture(attackerData.id);
combat.applyAttackerCombatBuffs(attackerData.id, actionData);
int hitType = actionData.hitType;
if (hitType == combat.NON_ATTACK)
{
combat.combatLog(attackerData.id, defenderData[0].id, "runHitEngine", "Non-Combat action - Skipping hitEngine");
attackerResults.endPosture = getPosture(attackerData.id);
for (int i = 0; i < defenderData.length; i++)
{
hitData[i] = new hit_result();
if (i == 0)
{
hitData[i].success = true;
}
else
{
hitData[i].success = false;
}
if (actionData.validTarget == combat.VALID_TARGET_FRIEND && pvpCanHelp(attackerData.id, defenderData[i].id))
{
pvpHelpPerformed(attackerData.id, defenderData[i].id);
combat.applyDefenderCombatBuffs(attackerData.id, defenderData[i].id, weaponData, actionData);
}
defenderResults[i] = new defender_results();
defenderResults[i].id = defenderData[i].id;
defenderResults[i].endPosture = getPosture(defenderData[i].id);
}
return hitData;
}
boolean isHeavyWeapon = combat.isHeavyWeapon(weaponData);
int attackerLevel = getLevel(attackerData.id);
boolean criticalHit = false;
boolean seriesStrikethrough = false;
attackerData = combat.fillAttackerCombatAttributes(attackerData);
if (utils.hasScriptVar(attackerData.id, "nextCritHit") && actionData.commandType != combat.LEFT_CLICK_DEFAULT)
{
actionData.increaseCritical += 100.0f;
actionData.reduceParry += 100;
actionData.reduceDodge += 100;
actionData.reduceBlock += 100;
actionData.reduceGlancing += 100;
actionData.increaseStrikethrough -= 100;
}
utils.removeScriptVar(attackerData.id, PROGRESSIVE_DAMAGE_COUNTER);
if (combat.isCommandoBonus(attackerData.id, weaponData, actionData.commandType))
{
float devastationBonus = combat.getDevastationChance(attackerData.id);
if (rand(0.0f, 99.0f) < devastationBonus)
{
weaponData.minDamage = weaponData.maxDamage;
weaponData.maxDamage *= 1.5f;
showFlyTextPrivate(attackerData.id, attackerData.id, new string_id("combat_effects", "devastation"), 1.5f, colors.VIOLETRED);
}
if (actionData.buffNameTarget.length() == 0 || actionData.buffNameTarget.equals(""))
{
int passiveDotBonus = 10;
passiveDotBonus += getEnhancedSkillStatisticModifierUncapped(attackerData.id, "commando_passive_dot");
if (rand(0, 99) < passiveDotBonus)
{
String commandoDotName = heavyweapons.getHeavyWeaponDotName(attackerData.id, weaponData, true);
if (commandoDotName != null && !commandoDotName.equals(""))
{
actionData.buffNameTarget = commandoDotName;
}
}
}
}
boolean isPlayerAttacker = isPlayer(attackerData.id);
int intWeaponAttackType = getWeaponAttackType(weaponData.id);
boolean isRanged = (intWeaponAttackType == ATTACK_TYPE_RANGED);
boolean specialAttack = actionData.commandType == combat.RIGHT_CLICK_SPECIAL;
int critDamageIncrease = getEnhancedSkillStatisticModifierUncapped(attackerData.id, "expertise_critical_damage_increase");
for (int i = 0; i < defenderData.length; i++)
{
float minDamage = weaponData.minDamage;
float maxDamage = weaponData.maxDamage;
hitData[i] = new hit_result();
float distance = 0;
boolean isPlayerDefender = isPlayer(defenderData[i].id);
obj_id oldDefender = defenderData[i].id;
if (hitType != combat.NON_DAMAGE_ATTACK)
{
obj_id newDefender = combat.directDamageToDifferentTarget(attackerData.id, defenderData[i].id);
if (oldDefender != newDefender)
{
defenderData[i].id = newDefender;
}
}
defenderData[i] = combat.fillDefenderCombatAttributes(defenderData[i]);
int defenderLevel = getLevel(defenderData[i].id);
if (hitType == combat.NON_DAMAGE_ATTACK)
{
hitData[i].success = true;
}
else
{
int defResult = getDefenderResult(attackerData, defenderData[i], actionData, isAutoAiming);
int atkResult = getAttackerResult(attackerData, defenderData[i], actionData, isAutoAiming);
switch (defResult)
{
case HIT_RESULT_DODGE:
hitData[i].success = false;
hitData[i].dodge = true;
break;
case HIT_RESULT_PARRY:
hitData[i].success = false;
hitData[i].parry = true;
break;
case HIT_RESULT_GLANCING:
hitData[i].success = true;
hitData[i].glancing = true;
break;
case HIT_RESULT_BLOCK:
hitData[i].success = true;
hitData[i].blockResult = true;
break;
case HIT_RESULT_EVADE:
hitData[i].success = true;
hitData[i].evadeResult = true;
break;
case HIT_RESULT_HIT:
hitData[i].success = true;
break;
default:
hitData[i].success = true;
break;
}
if (hitData[i].success == true)
{
switch (atkResult)
{
case HIT_RESULT_MISS:
hitData[i].success = false;
hitData[i].miss = true;
break;
case HIT_RESULT_CRITICAL:
hitData[i].success = true;
hitData[i].critical = true;
hitData[i].glancing = false;
break;
case HIT_RESULT_PUNISHING:
hitData[i].success = true;
hitData[i].crushing = true;
break;
case HIT_RESULT_STRIKETHROUGH:
hitData[i].success = true;
hitData[i].strikethrough = true;
hitData[i].glancing = false;
break;
}
}
}
int[] actionCost = combat.getSuccessBasedSingleTargetActionCost(hitData[i], actionData, attackerData.id, weaponData);
combat.drainCombatActionAttributes(attackerData.id, actionCost);
int validTargetType = actionData.validTarget;
if (validTargetType == combat.VALID_TARGET_FRIEND && pvpCanHelp(attackerData.id, defenderData[i].id))
{
pvpHelpPerformed(attackerData.id, defenderData[i].id);
}
else if (pvpCanAttack(attackerData.id, defenderData[i].id))
{
pvpAttackPerformed(attackerData.id, defenderData[i].id);
}
defenderResults[i] = new defender_results();
defenderResults[i].id = defenderData[i].id;
defenderResults[i].endPosture = getPosture(defenderData[i].id);
if (validTargetType != combat.VALID_TARGET_FRIEND && defenderData[i].id != attackerData.id && hitData[i].success)
{
startCombat(defenderData[i].id, attackerData.id);
if (oldDefender != defenderData[i].id)
{
startCombat(oldDefender, attackerData.id);
}
}
if (combat.isDamageImmune(attackerData.id, defenderData[i].id, actionData))
{
if (defenderData.length == 1)
{
actionData.hitSpam = combat.NO_HIT_SPAM;
}
continue;
}
if (combat.hasPrescience(attackerData.id, defenderData[i].id, actionData))
{
if (defenderData.length == 1)
{
actionData.hitSpam = combat.NO_HIT_SPAM;
}
continue;
}
if (!hitData[i].success)
{
target_dummy.sendTargetDummyCombatData(attackerData.id, defenderData[i].id, actionData, hitData[i]);
}
if (hitData[i].success)
{
defenderResults[i].result = COMBAT_RESULT_HIT;
if (beast_lib.isBeast(attackerData.id))
{
addHate(defenderData[i].id, getMaster(attackerData.id), 0);
}
if (hitData[i].strikethrough)
{
hitData[i].strikethroughAmmount = combat.getStrikethroughValue(attackerData.id, defenderData[i].id);
seriesStrikethrough |= true;
}
if (hitData[i].evadeResult)
{
hitData[i].evadeAmmount = combat.getEvasionRoll(defenderData[i].id);
}
if (hitData[i].blockResult)
{
hitData[i].block = combat.getBlockAmmount(defenderData[i].id);
}
if (hitData[i].crushing)
{
minDamage = maxDamage * 1.5f;
maxDamage = (maxDamage * 1.5f) + 1.0f;
}
dictionary rawDict = getRawDamage(attackerData.id, weaponData, actionData, hitData[i], minDamage, maxDamage, defenderData.length);
minDamage = rawDict.getFloat("minDamage");
maxDamage = rawDict.getFloat("maxDamage");
if (hitData[i].glancing)
{
minDamage *= 0.35f;
maxDamage *= 0.35f;
weaponData.elementalValue *= 0.35f;
hitData[i].critDamage = 1;
string_id critSpam = new string_id("combat_effects", "glancing_blow");
prose_package ppc = new prose_package();
ppc = prose.setStringId(ppc, critSpam);
showFlyTextPrivateProseWithFlags(defenderData[i].id, defenderData[i].id, ppc, 1.5f, colors.LIMEGREEN, FLY_TEXT_FLAG_IS_GLANCING_BLOW);
hasSkill(defenderData[i].id, "expertise_fs_general_alacrity_1");
playClientEffectObj(defenderData[i].id, "appearance/pt_jedi_alacrity.prt", defenderData[i].id, "");
}
if (hitData[i].critical)
{
float damageMod = combat.doCriticalHitEffect(attackerData, defenderData[i], weaponData, hitData[i], actionData);
float critBonus = 1.0f + (critDamageIncrease / 100.0f);
damageMod += critDamageIncrease / 100.0f;
minDamage = maxDamage * critBonus;
maxDamage = maxDamage * damageMod;
criticalHit = true;
}
hitData[i].damage = rand((int)minDamage, (int)maxDamage);
if (hitType != combat.NON_DAMAGE_ATTACK)
{
hitData[i] = applyDamage(attackerData.id, defenderData[i].id, weaponData, hitData[i], actionData, (i == 0), overloadDamage);
}
else
{
hitData[i].damage = 0;
}
effect_data defenderEffect = new effect_data();
combat.applyDefenderCombatBuffs(attackerData.id, defenderData[i].id, weaponData, actionData);
beast_lib.checkForSkillAcquisition(attackerData.id, defenderData[i].id, actionData.actionName);
if (!actionData.specialLine.equals("no_proc"))
{
proc.executeProcEffects(attackerData.id, defenderData[i].id, actionData);
}
else
{
hitData[i].proc = true;
}
if (actionData.effectOnTarget != null && actionData.effectOnTarget != "")
{
playClientEffectObj(defenderData[i].id, actionData.effectOnTarget, defenderData[i].id, "");
}
int luckyBreakChance = getSkillStatisticModifier(attackerData.id, "expertise_lucky_break_chance");
if (luckyBreakChance > 0 && buff.hasBuff(attackerData.id, "sm_feeling_lucky") && !buff.hasBuff(attackerData.id, "sm_lucky_break") && !buff.hasBuff(attackerData.id, "sm_lucky_break_recourse") && rand(0, 99) < luckyBreakChance)
{
buff.applyBuff(attackerData.id, "sm_lucky_break");
string_id luckySID = new string_id("cbt_spam", "sm_lucky_break_proc");
sendCombatSpamMessage(attackerData.id, defenderData[i].id, luckySID, true, true, true, COMBAT_RESULT_BUFF);
}
if (buff.hasBuff(attackerData.id, "sm_lucky_break"))
{
int doubleHitChance = (int)getSkillStatisticModifier(attackerData.id, "expertise_double_hit_chance");
if (doubleHitChance > 0 && !buff.hasBuff(attackerData.id, "sm_double_hit") && !buff.hasBuff(attackerData.id, "sm_double_hit_recourse") && rand(0, 99) < doubleHitChance)
{
buff.applyBuff(attackerData.id, "sm_double_hit");
string_id doubleHitSID = new string_id("cbt_spam", "sm_double_hit_proc");
sendCombatSpamMessage(attackerData.id, defenderData[i].id, doubleHitSID, true, true, true, COMBAT_RESULT_BUFF);
}
}
}
else if (hitData[i].dodge)
{
if (!hasScript(defenderData[i].id, "player.player_countdown") && !movement.hasMovementModifier(defenderData[i].id))
{
defenderResults[i].result = COMBAT_RESULT_EVADE;
}
else
{
defenderResults[i].result = COMBAT_RESULT_MISS;
}
}
else if (hitData[i].parry)
{
defenderResults[i].result = COMBAT_RESULT_BLOCK;
weapon_data attackerWeapon = getWeaponData(getCurrentWeapon(attackerData.id));
weapon_data defenderWeapon = getWeaponData(getCurrentWeapon(defenderData[i].id));
boolean isRangedAttacker = false;
boolean isLightSaber = false;
if (attackerWeapon != null)
{
isRangedAttacker = combat.isRangedWeapon(attackerWeapon.weaponType);
}
if (defenderWeapon != null)
{
isLightSaber = jedi.isLightsaber(defenderWeapon.id);
}
if (isRangedAttacker && isLightSaber)
{
defenderResults[i].result = COMBAT_RESULT_LIGHTSABER_BLOCK;
}
if (!actionData.specialLine.equals("no_proc"))
{
proc.executeProcEffects(attackerData.id, defenderData[i].id, actionData);
}
else
{
hitData[i].proc = true;
}
if (isLightSaber && buff.hasBuff(defenderData[i].id, "fs_saber_reflect") && !strAttack.equals("fs_saber_reflect"))
{
queueCommand(defenderData[i].id, (1345072218), attackerData.id, "", COMMAND_PRIORITY_DEFAULT);
}
int addDefenderDamageToAction = getSkillStatisticModifier(defenderData[i].id, "expertise_damage_add_to_action");
if (addDefenderDamageToAction > 0)
{
float halfOfMod = addDefenderDamageToAction / 2.0f;
int actionToAdd = Math.round((halfOfMod / 100.0f) * getMaxAction(defenderData[i].id));
combat.gainCombatActionAttribute(defenderData[i].id, actionToAdd);
}
}
else
{
defenderResults[i].result = COMBAT_RESULT_MISS;
}
if (defenderResults[i].result != COMBAT_RESULT_TETHERED)
{
combat.addHateProcess(attackerData.id, defenderData[i].id, hitData[i], actionData);
}
playbackNames[i] = combat.getActionAnimation(actionData, combat.getWeaponStringType(weaponData.weaponType));
if (hitType == combat.NON_DAMAGE_ATTACK && hasScript(defenderData[i].id, "player.player_logout"))
{
defenders[i] = null;
}
else
{
defenders[i] = defenderData[i].id;
}
results[i] = defenderResults[i].result;
}
if (criticalHit && utils.hasScriptVar(attackerData.id, "critRemoveBuffNames") && actionData.commandType != combat.LEFT_CLICK_DEFAULT)
{
utils.removeScriptVar(attackerData.id, "nextCritHit");
Vector buffNames = utils.getResizeableStringArrayScriptVar(attackerData.id, "critRemoveBuffNames");
buff.removeBuffs(attackerData.id, buffNames);
}
if (seriesStrikethrough)
{
int stproc = getEnhancedSkillStatisticModifierUncapped(attackerData.id, "expertise_onstrikethrough_proc_sp_resonance");
if (stproc > 0)
{
buff.partyBuff(attackerData.id, "sp_critbuff_resonance");
}
}
if (criticalHit)
{
int critproc = getEnhancedSkillStatisticModifierUncapped(attackerData.id, "expertise_oncrit_proc_sp_savagery");
if (critproc > 0)
{
buff.partyBuff(attackerData.id, "sp_critbuff_savagery");
}
}
if (utils.hasScriptVar(attackerData.id, buff.ON_ATTACK_REMOVE) && actionData.commandType != combat.LEFT_CLICK_DEFAULT)
{
Vector buffList = utils.getResizeableStringArrayScriptVar(attackerData.id, buff.ON_ATTACK_REMOVE);
for (Object o : buffList) {
if (buff.hasBuff(attackerData.id, ((String) o))) {
buff.removeBuff(attackerData.id, ((String) o));
}
}
}
if (actionData.hitSpam != combat.NO_HIT_SPAM)
{
obj_id currentWeapon = null;
if (actionData.hitSpam == combat.ACTION_NAME)
{
string_id attackId = new string_id("cmd_n", actionData.actionName);
combat.doBasicCombatSpam(attackId, SID_NONE, currentWeapon, attackerResults, defenderResults, hitData);
}
else if (actionData.hitSpam == combat.WEAPON_NAME)
{
if (weaponData.weaponName != null)
{
combat.doBasicCombatSpam(SID_NONE, weaponData.weaponName, currentWeapon, attackerResults, defenderResults, hitData);
}
else if (isValidId(weaponData.id))
{
combat.doBasicCombatSpam(SID_NONE, weaponData.weaponName, weaponData.id, attackerResults, defenderResults, hitData);
}
else if (isValidId(attackerResults.weapon))
{
combat.doBasicCombatSpam(SID_NONE, weaponData.weaponName, attackerResults.weapon, attackerResults, defenderResults, hitData);
}
else if (isValidId(getCurrentWeapon(attackerResults.id)))
{
combat.doBasicCombatSpam(SID_NONE, weaponData.weaponName, getCurrentWeapon(attackerResults.id), attackerResults, defenderResults, hitData);
}
else
{
combat.doBasicCombatSpam(SID_NONE, SID_NONE, currentWeapon, attackerResults, defenderResults, hitData);
}
}
else
{
combat.doBasicCombatSpam(SID_NONE, SID_NONE, currentWeapon, attackerResults, defenderResults, hitData);
}
}
if (actionData.hitType != 6 || actionData.delayAttackLoopsDone == 0)
{
doMultiDefenderCombatResults(playbackNames, attackerResults, defenderResults, weaponData, actionData, hitData);
}
int rampageAttacks = getEnhancedSkillStatisticModifierUncapped(attackerData.id, "expertise_co_killing_spree_target");
if (actionData.commandType == combat.LEFT_CLICK_DEFAULT && buff.hasBuff(attackerData.id, "co_killing_spree") && rampageAttacks > 0)
{
obj_id[] hateList = getHateList(attackerData.id);
for (int q = 0; q < rampageAttacks; q++)
{
if (hateList != null && hateList.length > 0)
{
queueCommand(attackerData.id, (-410474913), hateList[rand(0, hateList.length - 1)], "", COMMAND_PRIORITY_IMMEDIATE);
}
}
}
callDefenderCombatAction(defenders, results, attackerData.id, weaponData.id);
return hitData;
}
public int getDefenderResult(attacker_data attackerData, defender_data defenderData, combat_data actionData, boolean autoAim) throws InterruptedException
{
if (combat.isAreaAttack(actionData.attackType))
{
return getAreaDefenderResult(attackerData, defenderData, actionData, autoAim);
}
else
{
return getSingleTargetDefenderResult(attackerData, defenderData, actionData, autoAim);
}
}
public int getAttackerResult(attacker_data attackerData, defender_data defenderData, combat_data actionData, boolean autoAim) throws InterruptedException
{
if (combat.isAreaAttack(actionData.attackType))
{
return getAreaAttackResult(attackerData, defenderData, actionData, autoAim);
}
else
{
return getSingleTargetAttackResult(attackerData, defenderData, actionData, autoAim);
}
}
public int getAreaDefenderResult(attacker_data attackerData, defender_data defenderData, combat_data actionData, boolean autoAim) throws InterruptedException
{
obj_id attacker = attackerData.id;
obj_id defender = defenderData.id;
if (movement.hasStunEffect(defenderData.id))
{
return HIT_RESULT_HIT;
}
int glancingBlow = Math.round(10.0f * combat.getGlancingBlowChance(attackerData, defenderData, actionData));
int evasionChance = Math.round(10.0f * combat.getEvasionChance(attackerData, defenderData));
int blockChance = Math.round(10.0f * combat.getBlockChance(attackerData, defenderData, actionData));
int loaded_dice = getEnhancedSkillStatisticModifierUncapped(defenderData.id, "hit_table_add_defender_position");
int impossible_odds = getEnhancedSkillStatisticModifierUncapped(defenderData.id, "hit_table_defender_add_hit");
glancingBlow = glancingBlow < 0 ? 0 : glancingBlow;
evasionChance = evasionChance < 0 ? 0 : evasionChance;
blockChance = blockChance < 0 ? 0 : blockChance;
loaded_dice = loaded_dice < 0 ? 0 : loaded_dice;
impossible_odds = impossible_odds < 0 ? 0 : impossible_odds;
evasionChance = evasionChance >= 1000 ? 1000 : evasionChance;
blockChance = blockChance + evasionChance < 1000 ? blockChance + evasionChance : 1000;
glancingBlow = glancingBlow + blockChance < 1000 ? glancingBlow + blockChance : 1000;
impossible_odds = blockChance + impossible_odds < 1000 + impossible_odds ? blockChance + impossible_odds : 1000 + impossible_odds;
int defRollResult = rand(1, 1000) + loaded_dice;
if (defRollResult <= evasionChance)
{
return HIT_RESULT_EVADE;
}
if (defRollResult <= blockChance)
{
return HIT_RESULT_BLOCK;
}
if (defRollResult <= glancingBlow)
{
return HIT_RESULT_GLANCING;
}
if (defRollResult <= impossible_odds)
{
return HIT_RESULT_HIT;
}
return HIT_RESULT_HIT;
}
public int getAreaAttackResult(attacker_data attackerData, defender_data defenderData, combat_data actionData, boolean autoAim) throws InterruptedException
{
obj_id attacker = attackerData.id;
obj_id defender = defenderData.id;
boolean attackCanPunish = actionData.canBePunishing == 1;
boolean mobCanPunish = utils.getIntScriptVar(attackerData.id, "combat.immune.no_punish") == 0 ? true : false;
int punishingBlow = 0;
if (attackCanPunish && mobCanPunish)
{
punishingBlow = Math.round(10.0f * combat.getPunishingBlowChance(attackerData, defenderData));
}
punishingBlow = punishingBlow < 0 ? 0 : punishingBlow;
int criticalChance = Math.round(10.0f * combat.getCriticalHitChance(attackerData, defenderData, actionData, autoAim));
criticalChance = criticalChance < 0 ? 0 : criticalChance;
int length = 1000 - punishingBlow < 0 ? 0 : 1000 - punishingBlow;
criticalChance = criticalChance >= length ? length : criticalChance;
punishingBlow += criticalChance;
int attackRollResult = rand(1, 1000);
if (attackRollResult <= criticalChance)
{
return HIT_RESULT_CRITICAL;
}
if (attackRollResult <= punishingBlow)
{
return HIT_RESULT_PUNISHING;
}
return HIT_RESULT_HIT;
}
public int getSingleTargetDefenderResult(attacker_data attackerData, defender_data defenderData, combat_data actionData, boolean autoAim) throws InterruptedException
{
obj_id attacker = attackerData.id;
obj_id defender = defenderData.id;
int loaded_dice = getEnhancedSkillStatisticModifierUncapped(defenderData.id, "hit_table_add_defender_position");
int impossible_odds = getEnhancedSkillStatisticModifierUncapped(defenderData.id, "hit_table_defender_add_hit");
int hit_always = getEnhancedSkillStatisticModifierUncapped(attacker, "hit_always");
if (hit_always > 0)
{
return HIT_RESULT_HIT;
}
if (movement.hasStunEffect(defenderData.id))
{
return HIT_RESULT_HIT;
}
weapon_data attackerWeapon = getWeaponData(getCurrentWeapon(attacker));
weapon_data defenderWeapon = getWeaponData(getCurrentWeapon(defender));
boolean isRangedAttacker = false;
boolean isRangedDefender = false;
boolean isLightSaber = false;
if (attackerWeapon != null)
{
isRangedAttacker = combat.isRangedWeapon(attackerWeapon.weaponType);
}
if (defenderWeapon != null)
{
isRangedDefender = combat.isRangedWeapon(defenderWeapon.weaponType);
isLightSaber = jedi.isLightsaber(defenderWeapon.id);
}
int glancingBlow = Math.round(10.0f * combat.getGlancingBlowChance(attackerData, defenderData, actionData));
glancingBlow = glancingBlow < 0 ? 0 : glancingBlow;
int dodgeChance = Math.round(10.0f * combat.getDodgeChance(attackerData, defenderData, actionData));
dodgeChance = dodgeChance < 0 ? 0 : dodgeChance;
int parryChance = Math.round(10.0f * combat.getParryChance(attackerData, defenderData, actionData));
parryChance = parryChance < 0 ? 0 : parryChance;
int blockChance = Math.round(10.0f * combat.getBlockChance(attackerData, defenderData, actionData));
blockChance = blockChance < 0 ? 0 : blockChance;
if (isRangedDefender || (isRangedAttacker && !isLightSaber))
{
parryChance = 0;
}
dodgeChance = dodgeChance >= 1000 ? 1000 : dodgeChance;
parryChance = dodgeChance + parryChance < 1000 ? dodgeChance + parryChance : 1000;
blockChance = blockChance + parryChance < 1000 ? blockChance + parryChance : 1000;
glancingBlow = glancingBlow + blockChance < 1000 ? glancingBlow + blockChance : 1000;
impossible_odds = blockChance + impossible_odds < 1000 + impossible_odds ? blockChance + impossible_odds : 1000 + impossible_odds;
int defRollResult = rand(1, 1000) + loaded_dice;
if (defRollResult <= dodgeChance)
{
return HIT_RESULT_DODGE;
}
if (defRollResult <= parryChance)
{
return HIT_RESULT_PARRY;
}
if (defRollResult <= blockChance)
{
return HIT_RESULT_BLOCK;
}
if (defRollResult <= glancingBlow)
{
return HIT_RESULT_GLANCING;
}
if (defRollResult <= impossible_odds)
{
return HIT_RESULT_HIT;
}
return HIT_RESULT_HIT;
}
public int getSingleTargetAttackResult(attacker_data attackerData, defender_data defenderData, combat_data actionData, boolean autoAim) throws InterruptedException
{
obj_id attacker = attackerData.id;
obj_id defender = defenderData.id;
int crit_always = getEnhancedSkillStatisticModifierUncapped(attacker, "crit_always");
if (crit_always > 0)
{
return HIT_RESULT_CRITICAL;
}
weapon_data attackerWeapon = getWeaponData(getCurrentWeapon(attacker));
weapon_data defenderWeapon = getWeaponData(getCurrentWeapon(defender));
boolean isRangedAttacker = false;
boolean isRangedDefender = false;
boolean isLightSaber = false;
if (attackerWeapon != null)
{
isRangedAttacker = combat.isRangedWeapon(attackerWeapon.weaponType);
}
if (defenderWeapon != null)
{
isRangedDefender = combat.isRangedWeapon(defenderWeapon.weaponType);
isLightSaber = jedi.isLightsaber(defenderWeapon.id);
}
int missChance = Math.round(10.0f * combat.getMissChance(attackerData, defenderData, actionData, autoAim));
missChance = missChance < 0 ? 0 : missChance;
int punishingBlow = Math.round(10.0f * combat.getPunishingBlowChance(attackerData, defenderData));
punishingBlow = punishingBlow < 0 ? 0 : punishingBlow;
int criticalChance = Math.round(10.0f * combat.getCriticalHitChance(attackerData, defenderData, actionData, autoAim));
criticalChance = criticalChance < 0 ? 0 : criticalChance;
int strikethroughChance = Math.round(10.0f * combat.getStrikethroughChance(attackerData, defenderData, actionData));
strikethroughChance = strikethroughChance < 0 ? 0 : strikethroughChance;
int length = 1000 - punishingBlow < 0 ? 0 : 1000 - punishingBlow;
missChance = missChance > length ? length : missChance;
strikethroughChance = strikethroughChance + missChance < length ? strikethroughChance + missChance : length;
criticalChance = criticalChance + strikethroughChance < length ? criticalChance + strikethroughChance : length;
punishingBlow += criticalChance;
int attackRollResult = rand(1, 1000);
int stvalue = strikethroughChance - missChance;
int critvalue = criticalChance - strikethroughChance;
if (attackRollResult <= missChance)
{
return HIT_RESULT_MISS;
}
if (attackRollResult <= strikethroughChance)
{
return HIT_RESULT_STRIKETHROUGH;
}
if (attackRollResult <= criticalChance)
{
return HIT_RESULT_CRITICAL;
}
if (attackRollResult <= punishingBlow)
{
return HIT_RESULT_PUNISHING;
}
return HIT_RESULT_HIT;
}
public void displayHitTable(obj_id attacker, obj_id defender, int[] defTable, int[] atkTable, int defResult, int atkResult) throws InterruptedException
{
if (!isGod(attacker) && !isGod(defender))
{
return;
}
int miss = 0;
int dodge = 0;
int parry = 0;
int glancing = 0;
int block = 0;
int critical = 0;
int punishing = 0;
int hit = 0;
int evade = 0;
int strikethrough = 0;
for (int i2 : defTable) {
switch (i2) {
case HIT_RESULT_MISS:
miss++;
break;
case HIT_RESULT_DODGE:
dodge++;
break;
case HIT_RESULT_PARRY:
parry++;
break;
case HIT_RESULT_GLANCING:
glancing++;
break;
case HIT_RESULT_BLOCK:
block++;
break;
case HIT_RESULT_CRITICAL:
critical++;
break;
case HIT_RESULT_PUNISHING:
punishing++;
break;
case HIT_RESULT_HIT:
hit++;
break;
case HIT_RESULT_EVADE:
evade++;
break;
case HIT_RESULT_STRIKETHROUGH:
strikethrough++;
break;
}
}
for (int i1 : atkTable) {
switch (i1) {
case HIT_RESULT_MISS:
miss++;
break;
case HIT_RESULT_DODGE:
dodge++;
break;
case HIT_RESULT_PARRY:
parry++;
break;
case HIT_RESULT_GLANCING:
glancing++;
break;
case HIT_RESULT_BLOCK:
block++;
break;
case HIT_RESULT_CRITICAL:
critical++;
break;
case HIT_RESULT_PUNISHING:
punishing++;
break;
case HIT_RESULT_HIT:
hit++;
break;
case HIT_RESULT_EVADE:
evade++;
break;
case HIT_RESULT_STRIKETHROUGH:
strikethrough++;
break;
}
}
if (isPlayer(attacker))
{
LOG("atkHitTable", "Forming Hit Table");
LOG("atkHitTable", getName(attacker) + " Vs. " + getName(defender));
LOG("atkHitTable", "Miss " + miss);
LOG("atkHitTable", "Dodge " + dodge);
LOG("atkHitTable", "Parry " + parry);
LOG("atkHitTable", "Glancing " + glancing);
LOG("atkHitTable", "Block " + block);
LOG("atkHitTable", "Critical " + critical);
LOG("atkHitTable", "Punishing " + punishing);
LOG("atkHitTable", "Hit " + hit);
LOG("atkHitTable", "Evade " + evade);
LOG("atkHitTable", "Strikethrough " + strikethrough);
LOG("atkHitTable", "Defender Result was " + getHitResultByName(defResult));
LOG("atkHitTable", "Attacker Results was " + getHitResultByName(atkResult));
LOG("atkHitTable", "xx");
}
if (!isPlayer(attacker))
{
LOG("defHitTabel", "Forming Hit Table");
LOG("defHitTable", getName(attacker) + " Vs. " + getName(defender));
LOG("defHitTable", "Miss " + miss);
LOG("defHitTable", "Dodge " + dodge);
LOG("defHitTable", "Parry " + parry);
LOG("defHitTable", "Glancing " + glancing);
LOG("defHitTable", "Block " + block);
LOG("defHitTable", "Critical " + critical);
LOG("defHitTable", "Punishing " + punishing);
LOG("defHitTable", "Hit " + hit);
LOG("defHitTable", "Evade " + evade);
LOG("defHitTable", "Strikethrough " + strikethrough);
LOG("defHitTable", "Defender Result was " + getHitResultByName(defResult));
LOG("defHitTable", "Attacker Results was " + getHitResultByName(atkResult));
LOG("defHitTable", "xx");
}
if (hasObjVar(attacker, "viewHitTable"))
{
sendSystemMessageTestingOnly(attacker, "Forming Hit Table");
sendSystemMessageTestingOnly(attacker, getName(attacker) + " Attacking. " + getName(defender));
sendSystemMessageTestingOnly(attacker, "Miss " + miss);
sendSystemMessageTestingOnly(attacker, "Dodge " + dodge);
sendSystemMessageTestingOnly(attacker, "Parry " + parry);
sendSystemMessageTestingOnly(attacker, "Glancing " + glancing);
sendSystemMessageTestingOnly(attacker, "Block " + block);
sendSystemMessageTestingOnly(attacker, "Critical " + critical);
sendSystemMessageTestingOnly(attacker, "Punishing " + punishing);
sendSystemMessageTestingOnly(attacker, "Hit " + hit);
sendSystemMessageTestingOnly(attacker, "Evade " + evade);
sendSystemMessageTestingOnly(attacker, "Strikethrough " + strikethrough);
sendSystemMessageTestingOnly(attacker, "" + getHitResultByName(defResult));
sendSystemMessageTestingOnly(attacker, "" + getHitResultByName(atkResult));
sendSystemMessageTestingOnly(attacker, "xx");
}
if (hasObjVar(defender, "viewHitTable"))
{
sendSystemMessageTestingOnly(defender, "Forming Hit Table");
sendSystemMessageTestingOnly(defender, getName(attacker) + " Attacking. " + getName(defender));
sendSystemMessageTestingOnly(defender, "Miss " + miss);
sendSystemMessageTestingOnly(defender, "Dodge " + dodge);
sendSystemMessageTestingOnly(defender, "Parry " + parry);
sendSystemMessageTestingOnly(defender, "Glancing " + glancing);
sendSystemMessageTestingOnly(defender, "Block " + block);
sendSystemMessageTestingOnly(defender, "Critical " + critical);
sendSystemMessageTestingOnly(defender, "Punishing " + punishing);
sendSystemMessageTestingOnly(defender, "Hit " + hit);
sendSystemMessageTestingOnly(defender, "Evade " + evade);
sendSystemMessageTestingOnly(defender, "Strikethrough " + strikethrough);
sendSystemMessageTestingOnly(defender, "" + getHitResultByName(defResult));
sendSystemMessageTestingOnly(defender, "" + getHitResultByName(atkResult));
sendSystemMessageTestingOnly(defender, "xx");
}
}
public String getHitResultByName(int hitResult) throws InterruptedException
{
String hitType = "None";
switch (hitResult)
{
case HIT_RESULT_MISS:
hitType = "Miss";
break;
case HIT_RESULT_DODGE:
hitType = "Dodge";
break;
case HIT_RESULT_PARRY:
hitType = "Parry";
break;
case HIT_RESULT_GLANCING:
hitType = "Glancing";
break;
case HIT_RESULT_BLOCK:
hitType = "Block";
break;
case HIT_RESULT_CRITICAL:
hitType = "Critical";
break;
case HIT_RESULT_PUNISHING:
hitType = "Punishing";
break;
case HIT_RESULT_HIT:
hitType = "Hit";
break;
case HIT_RESULT_EVADE:
hitType = "Evade";
break;
case HIT_RESULT_STRIKETHROUGH:
hitType = "Strikethrough";
break;
}
return hitType;
}
public hit_result applyDamage(obj_id attacker, obj_id defender, weapon_data weaponData, hit_result hitData, combat_data actionData, boolean primaryTarget) throws InterruptedException
{
return applyDamage(attacker, defender, weaponData, hitData, actionData, primaryTarget, 0);
}
public hit_result applyDamage(obj_id attacker, obj_id defender, weapon_data weaponData, hit_result hitData, combat_data actionData, boolean primaryTarget, int overloadDamage) throws InterruptedException
{
doWrappedDamage(attacker, defender, weaponData, hitData, actionData, overloadDamage);
return hitData;
}
public weapon_data getOverloadedWeaponData(obj_id self, obj_id objWeapon, combat_data actionData) throws InterruptedException
{
if (!isIdValid(self))
{
return null;
}
if (!isIdValid(objWeapon))
{
return getWeaponData(getCurrentWeapon(self));
}
if (actionData.overloadWeapon > 0)
{
return weapons.fillWeaponData(objWeapon, actionData);
}
weapon_data weaponData = weapons.getNewWeaponData(objWeapon);
if (weaponData == null)
{
CustomerServiceLog("combat_errors: ", "getOverloadedWeaponData weaponData: null for objWeapon: " + objWeapon + " getName(objWeapon): " + getName(objWeapon));
weaponData = getWeaponData(getCurrentWeapon(self));
}
else
{
weaponData.elementalValue = isPlayer(self) ? weaponData.elementalValue * 2 : weaponData.elementalValue;
}
return weaponData;
}
public dictionary getRawDamage(obj_id attacker, weapon_data weaponData, combat_data actionData, hit_result hitData, float minDamage, float maxDamage, int numTargets) throws InterruptedException
{
int addedDamage = actionData.addedDamage;
if (actionData.attackType == combat.AREA_PROGRESSIVE)
{
addedDamage += utils.getIntScriptVar(attacker, PROGRESSIVE_DAMAGE_COUNTER);
utils.setScriptVar(attacker, PROGRESSIVE_DAMAGE_COUNTER, addedDamage);
}
if (actionData.attackType == combat.SPLIT_DAMAGE_TARGET_AREA)
{
addedDamage = Math.round((float)addedDamage / numTargets);
}
float percentAddFromWeapon = actionData.percentAddFromWeapon;
if (!combat.checkWeaponCerts(attacker, weaponData, false))
{
combat.combatLog(attacker, null, "getRawDamage", "Weapon Certification Failed. Modifying damage to 5 min, 10 max.");
minDamage = 5.0f;
maxDamage = 10.0f;
}
if (beast_lib.isBeastMaster(attacker) || beast_lib.isBeast(attacker))
{
minDamage = minDamage + (minDamage * (beast_lib.getBeastModDamageBonus(attacker) / 100.0f));
maxDamage = maxDamage + (maxDamage * (beast_lib.getBeastModDamageBonus(attacker) / 100.0f));
}
combat.combatLog(attacker, null, "getRawDamage", "RAW DAMAGE Damage = " + minDamage + "-" + maxDamage);
float speed = weaponData.attackSpeed;
if (speed == 0 || (isMob(attacker) && beast_lib.isBeast(attacker)))
{
speed = 1.0f;
}
minDamage *= percentAddFromWeapon;
maxDamage *= percentAddFromWeapon;
if (addedDamage > 0)
{
float dps = ((minDamage + maxDamage) / 2.0f) / speed;
float totalAddedDamage = dps + addedDamage;
float normalizedSpecialDmg = totalAddedDamage - ((minDamage + maxDamage) / 2);
minDamage += normalizedSpecialDmg;
maxDamage += normalizedSpecialDmg;
}
float damageAddFromLevel = getEnhancedSkillStatisticModifierUncapped(attacker, "level_add_to_damage");
if (damageAddFromLevel > 0.0f)
{
float levelDamageMod = getLevel(attacker) * (damageAddFromLevel / 100.0f);
minDamage += levelDamageMod * speed;
maxDamage += levelDamageMod * speed;
}
if (getWeaponType(weaponData.id) >= 0)
{
if (combat.isMeleeWeapon(weaponData.id) || combat.isLightsaberWeapon(weaponData.id))
{
int strengthBonus = 0;
strengthBonus += Math.round(getEnhancedSkillStatisticModifierUncapped(attacker, "strength_modified") / 3.0f);
strengthBonus += Math.round(getSkillStatisticModifier(attacker, "strength") / 3.0f);
minDamage += strengthBonus;
maxDamage += strengthBonus;
}
}
float enragedMod = utils.getFloatScriptVar(attacker, "damageDealtMod.value");
if (enragedMod > 0)
{
minDamage *= enragedMod;
maxDamage *= enragedMod;
}
combat.combatLog(attacker, null, "getRawDamage", "Final Modified Damage = " + minDamage + "-" + maxDamage);
if (minDamage > maxDamage - 1)
{
minDamage = maxDamage - 1;
}
if (minDamage < 1)
{
minDamage = 1;
}
if (percentAddFromWeapon == 0.0)
{
weaponData.elementalValue = 0;
}
if (utils.hasScriptVar(attacker, "private_damage_bonus"))
{
minDamage = minDamage * (1 + utils.getFloatScriptVar(attacker, "private_damage_bonus"));
maxDamage = maxDamage * (1 + utils.getFloatScriptVar(attacker, "private_damage_bonus"));
}
dictionary dict = new dictionary();
dict.put("minDamage", minDamage);
dict.put("maxDamage", maxDamage);
return dict;
}
public int expertiseDamageModify(obj_id attacker, obj_id defender, hit_result hitData, combat_data actionData) throws InterruptedException
{
int newDamage = hitData.damage;
int damageDecrease = getSkillStatisticModifier(attacker, "expertise_damage_decrease_chance");
if (damageDecrease > 0)
{
float spotASuckerDecreaseChance = rand(0, damageDecrease) * 0.01f;
if (spotASuckerDecreaseChance > 1.0f)
{
spotASuckerDecreaseChance = 1.0f;
}
newDamage *= 1.0f - spotASuckerDecreaseChance;
}
float smugglerRankBonus = getSkillStatisticModifier(attacker, "expertise_sm_rank_damage_bonus");
if (smugglerRankBonus > 0)
{
smugglerRankBonus *= 0.01f;
newDamage += newDamage * smugglerRankBonus;
}
int jediAnticipateAggression = getSkillStatisticModifier(defender, "expertise_damage_reduce_anticipate_aggression");
if (jediAnticipateAggression > 0)
{
float conversionPercentage = jediAnticipateAggression / 100.0f;
int oldDamage = hitData.damage;
newDamage -= (int)(oldDamage * conversionPercentage);
if (rand(0, 9) < 1)
{
playClientEffectObj(defender, "appearance/pt_jedi_anticipate_aggression.prt", defender, "root");
}
}
damageDecrease = getSkillStatisticModifier(defender, "damage_decrease_percentage");
if (damageDecrease > 0)
{
newDamage -= (int)(hitData.damage * (float)(damageDecrease / 100.0f));
}
int areaDamageDecrease = getSkillStatisticModifier(defender, "area_damage_decrease_percentage");
if (areaDamageDecrease > 0 && combat.isAreaAttack(actionData.attackType))
{
newDamage -= (int)(hitData.damage * (float)(areaDamageDecrease / 100.0f));
}
int areaDamageResist = getSkillStatisticModifier(defender, "area_damage_resist_full_percentage");
if (areaDamageResist > 0 && combat.isAreaAttack(actionData.attackType) && rand(0, 99) < areaDamageResist)
{
newDamage = 0;
}
if (hitData.critDamage > 0)
{
if (utils.hasScriptVar(attacker, "critDoubleDamage") && actionData.commandType != combat.LEFT_CLICK_DEFAULT)
{
newDamage *= 2;
playClientEffectObj(defender, "appearance/pt_smuggler_end_line.prt", defender, "");
}
if (utils.hasScriptVar(attacker, "critRoot") && actionData.commandType != combat.LEFT_CLICK_DEFAULT)
{
buff.applyBuff(defender, attacker, "sm_nerf_herder_root");
}
}
newDamage = ai_lib.triggerSharedHealthLink(defender, newDamage);
return newDamage;
}
public void doWrappedDamage(obj_id attacker, obj_id defender, weapon_data weaponData, hit_result hitData, combat_data actionData) throws InterruptedException
{
doWrappedDamage(attacker, defender, weaponData, hitData, actionData, 0);
}
public void clog(String message) throws InterruptedException
{
debugSpeakMsg(getSelf(), message);
}
public void doWrappedDamage(obj_id attacker, obj_id defender, weapon_data weaponData, hit_result hitData, combat_data actionData, int overloadDamage) throws InterruptedException
{
boolean dmgSpecial = false;
boolean evade = hitData.evadeResult;
boolean block = hitData.blockResult;
float armorBypass = actionData.bypassArmor;
float siphonLife = actionData.convertDamageToHealth;
hitData.rawDamage = hitData.damage;
int maxDamage = hitData.rawDamage + weaponData.elementalValue;
String dotType = actionData.dotType;
if (utils.hasScriptVar(defender, "elemental_vulnerability.type_heat"))
{
float value = utils.getFloatScriptVar(defender, "elemental_vulnerability.type_heat.value");
boolean exclusive = utils.getBooleanScriptVar(defender, "elemental_vulnerability.type_heat.exclusive");
if (exclusive)
{
hitData.rawDamage = 0;
maxDamage = 0;
}
if (weaponData.elementalType == DAMAGE_ELEMENTAL_HEAT)
{
weaponData.elementalValue *= value;
}
else if (exclusive)
{
weaponData.elementalValue *= 0.0f;
}
}
if (utils.hasScriptVar(defender, "elemental_vulnerability.type_electrical"))
{
float value = utils.getFloatScriptVar(defender, "elemental_vulnerability.type_electrical.value");
boolean exclusive = utils.getBooleanScriptVar(defender, "elemental_vulnerability.type_electrical.exclusive");
if (exclusive)
{
hitData.rawDamage = 0;
maxDamage = 0;
}
if (weaponData.elementalType == DAMAGE_ELEMENTAL_ELECTRICAL)
{
weaponData.elementalValue *= value;
}
else if (exclusive)
{
weaponData.elementalValue *= 0.0f;
}
}
if (utils.hasScriptVar(defender, "elemental_vulnerability.type_cold"))
{
float value = utils.getFloatScriptVar(defender, "elemental_vulnerability.type_cold.value");
boolean exclusive = utils.getBooleanScriptVar(defender, "elemental_vulnerability.type_cold.exclusive");
if (exclusive)
{
hitData.rawDamage = 0;
maxDamage = 0;
}
if (weaponData.elementalType == DAMAGE_ELEMENTAL_COLD)
{
weaponData.elementalValue *= value;
}
else if (exclusive)
{
weaponData.elementalValue *= 0.0f;
}
}
if (utils.hasScriptVar(defender, "elemental_vulnerability.type_acid"))
{
float value = utils.getFloatScriptVar(defender, "elemental_vulnerability.type_acid.value");
boolean exclusive = utils.getBooleanScriptVar(defender, "elemental_vulnerability.type_acid.exclusive");
if (exclusive)
{
hitData.rawDamage = 0;
maxDamage = 0;
}
if (weaponData.elementalType == DAMAGE_ELEMENTAL_ACID)
{
weaponData.elementalValue *= value;
}
else if (exclusive)
{
weaponData.elementalValue *= 0.0f;
}
}
if (beast_lib.isBeastMaster(defender) || beast_lib.isBeast(defender))
{
hitData.rawDamage = hitData.rawDamage - (int)(hitData.rawDamage * (beast_lib.getBeastModDamageReduction(defender) / 100.0f));
}
int evadeReduction = 0;
if (hitData.evadeResult)
{
float evadeValue = hitData.evadeAmmount;
if (evadeValue == -1)
{
hitData.rawDamage = 0;
weaponData.elementalValue = 0;
hitData.evadeAmmount = 100.0f;
dotType = null;
}
else
{
float percentReduction = rand(evadeValue / 2.0f, evadeValue);
evadeReduction = (int)(hitData.rawDamage * (percentReduction / 100.0f));
weaponData.elementalValue = (int)(weaponData.elementalValue * (percentReduction / 100.0f));
hitData.rawDamage -= evadeReduction;
hitData.evadeAmmount = percentReduction;
}
}
if (dotType != null && dotType.length() > 0)
{
int dotIntensity = actionData.dotIntensity;
int dotDuration = actionData.dotDuration;
if (dotIntensity == 0)
{
dotIntensity = (int)(hitData.rawDamage * actionData.percentAddFromWeapon);
}
String specialName = actionData.actionName;
String specialLine = actionData.specialLine;
int expertiseDotDurationBonus = 0;
float expertiseDotDamageBonus = getEnhancedSkillStatisticModifierUncapped(attacker, "expertise_damage_all");
if (isMob(defender) && !isPlayer(defender) && !isIdValid(getMaster(defender)))
{
expertiseDotDamageBonus += getEnhancedSkillStatisticModifierUncapped(attacker, "expertise_damage_npc");
}
if (specialLine != null && specialLine.length() > 0)
{
expertiseDotDurationBonus = getEnhancedSkillStatisticModifierUncapped(attacker, "expertise_dot_duration_line_" + specialLine);
expertiseDotDurationBonus += getEnhancedSkillStatisticModifierUncapped(attacker, "expertise_dot_duration_single_" + specialName);
expertiseDotDamageBonus += getEnhancedSkillStatisticModifierUncapped(attacker, "expertise_dot_damage_line_" + specialLine);
}
float dotIntensityFloat = dotIntensity * (1.0f + (expertiseDotDamageBonus / 100.0f));
dotIntensity = (int)dotIntensityFloat;
dotDuration += expertiseDotDurationBonus;
int targetAttrib = dotType.equals("disease") ? ACTION : HEALTH;
boolean rslt = dot.applyDotEffect(defender, attacker, dotType, dotType + "" + attacker, targetAttrib, 100, dotIntensity, dotDuration);
}
hitData.damage = (hitData.rawDamage);
hitData.damageType = weaponData.damageType;
if (actionData.overloadWeapon > 0)
{
hitData.damageType = actionData.overloadWeaponDamageType;
}
hitData.damage = expertiseDamageModify(attacker, defender, hitData, actionData);
float expertiseDamageBonus = 0;
obj_id expert = attacker;
if (!isPlayer(attacker) && utils.hasScriptVar(attacker, "objOwner"))
{
expert = utils.getObjIdObjVar(attacker, "objOwner");
}
int killMeter = getKillMeter(expert);
if (actionData.percentAddFromWeapon > 0.0f)
{
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(expert, "expertise_damage_weapon_all");
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(expert, "expertise_damage_weapon_" + combat.getCorrectedWeaponType(weaponData.weaponType));
expertiseDamageBonus += killMeter * getSkillStatisticModifier(expert, "kill_meter_damage_weapon_all");
}
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(expert, "expertise_damage_all");
if (isMob(defender) && !isPlayer(defender) && !isIdValid(getMaster(defender)))
{
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(attacker, "expertise_damage_npc");
}
if (getWeaponType(weaponData.id) >= 0)
{
if ((combat.isMeleeWeapon(weaponData.id)) || (combat.isLightsaberWeapon(weaponData.id)))
{
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(expert, "expertise_damage_melee");
}
if (combat.isRangedWeapon(weaponData.id))
{
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(expert, "expertise_damage_ranged");
}
}
String specialLine = actionData.specialLine;
String actionName = actionData.actionName;
if (specialLine != null && !specialLine.equals(""))
{
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(defender, "expertise_damage_line_vulnerability_" + specialLine);
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(expert, "expertise_damage_line_" + specialLine);
expertiseDamageBonus += killMeter * getSkillStatisticModifier(expert, "kill_meter_damage_line_" + specialLine);
}
if (actionName != null && !actionName.equals(""))
{
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(expert, "expertise_damage_single_" + actionName);
}
if (actionName != null && !actionName.equals(""))
{
if (combat.isAreaAttack(actionData.attackType))
{
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(expert, "expertise_damage_area_effect");
}
}
if (hasObjVar(attacker, "specialNicheType"))
{
String subType = getStringObjVar(attacker, "specialNicheType");
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(defender, "increase_damage_taken_from_" + subType);
expertiseDamageBonus -= getEnhancedSkillStatisticModifierUncapped(defender, "reduce_damage_taken_from_" + subType);
}
if (hasObjVar(defender, "specialNicheType"))
{
String subType = getStringObjVar(defender, "specialNicheType");
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(attacker, "increase_damage_dealt_to_" + subType);
expertiseDamageBonus -= getEnhancedSkillStatisticModifierUncapped(attacker, "reduce_damage_dealt_to_" + subType);
}
if (overloadDamage > 0)
{
hitData.damage = overloadDamage;
armorBypass = 100.0f;
}
if (actionData.scaleByDefenderWeaponSpeed > 0)
{
obj_id defenderWeapon = getCurrentWeapon(defender);
if (isIdValid(defenderWeapon))
{
float defenderWeaponSpeed = getWeaponAttackSpeed(getCurrentWeapon(defender));
hitData.damage *= actionData.scaleByDefenderWeaponSpeed * defenderWeaponSpeed;
}
}
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(expert, "combat_multiply_damage_dealt");
expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(defender, "combat_multiply_damage_taken");
float tempDamageFloat = hitData.damage;
tempDamageFloat = tempDamageFloat * (1.0f + ((float)expertiseDamageBonus / 100.0f));
int expertiseDamageReduction = 0;
expertiseDamageReduction += getEnhancedSkillStatisticModifierUncapped(expert, "combat_divide_damage_dealt");
expertiseDamageReduction += getEnhancedSkillStatisticModifierUncapped(defender, "combat_divide_damage_taken");
expertiseDamageReduction = expertiseDamageReduction > 100 ? 100 : expertiseDamageReduction;
tempDamageFloat = tempDamageFloat * (1.0f - (expertiseDamageReduction / 100.0f));
hitData.damage = (int)tempDamageFloat;
hitData.damage += getEnhancedSkillStatisticModifierUncapped(expert, "combat_add_damage_dealt");
hitData.damage -= getEnhancedSkillStatisticModifierUncapped(expert, "combat_subtract_damage_dealt");
hitData.damage += getEnhancedSkillStatisticModifierUncapped(defender, "combat_add_damage_taken");
hitData.damage -= getEnhancedSkillStatisticModifierUncapped(defender, "combat_subtract_damage_taken");
if (isPlayer(attacker))
{
session.logActivity(attacker, isPlayer(defender) ? session.ACTIVITY_PVP : session.ACTIVITY_PVE);
}
hitData.blockedDamage += combat.applyArmorProtection(attacker, defender, weaponData, hitData, armorBypass, expertiseDamageBonus);
if (hitData.damage < 0)
{
hitData.damage = 0;
}
healing.applyLifeSiphonHeal(attacker, defender, hitData.damage, siphonLife, actionData.actionName);
int addDefenderDamageToAction = getSkillStatisticModifier(defender, "expertise_damage_add_to_action");
if (addDefenderDamageToAction > 0)
{
int actionToAdd = (int)(hitData.damage * (float)(addDefenderDamageToAction / 100.0f));
combat.gainCombatActionAttribute(defender, actionToAdd);
if (rand(0, 9) < 1)
{
playClientEffectObj(defender, "appearance/pt_jedi_reactive_response.prt", defender, "root");
}
}
int addAttackerDamageToAction = getSkillStatisticModifier(attacker, "expertise_attacker_action_gain");
if (addAttackerDamageToAction > 0)
{
int actionToAdd = (int)(hitData.damage * (float)(addAttackerDamageToAction / 100.0f));
combat.gainCombatActionAttribute(attacker, actionToAdd);
if (rand(0, 9) < 1)
{
playClientEffectObj(attacker, "appearance/pt_jedi_tempt_hatred.prt", attacker, "");
}
}
target_dummy.sendTargetDummyCombatData(attacker, defender, actionData, hitData);
doDamage(attacker, defender, hitData);
int expertiseActionDamage = 0;
if (specialLine != null && specialLine.length() > 0)
{
expertiseActionDamage = getSkillStatisticModifier(attacker, "expertise_action_damage_line_" + specialLine);
}
int flatActionDamage = getAction(defender) < actionData.flatActionDamage + expertiseActionDamage ? getAction(defender) : actionData.flatActionDamage + expertiseActionDamage;
if (flatActionDamage > 0)
{
drainAttributes(defender, flatActionDamage, 0);
}
doKillMeterUpdate(attacker, defender, hitData.damage);
if (isPlayer(attacker))
{
string_id strSpam = new string_id("combat_effects", "damage_fly");
prose_package pp = new prose_package();
pp = prose.setStringId(pp, strSpam);
pp = prose.setDI(pp, -(hitData.damage + hitData.elementalDamage));
String strName = actionData.actionName;
float textSize = 1.5f;
color combatColor = colors.RED;
if ((strName.equals("meleeHit")) || (strName.equals("rangedShot")) || (strName.equals("saberHit")))
{
if (hitData.critDamage > 0 && hitData.critDamage < 7)
{
string_id critSpam = new string_id("combat_effects", "critical_hit_" + hitData.critDamage);
prose_package ppc = new prose_package();
ppc = prose.setStringId(ppc, critSpam);
ppc = prose.setDI(ppc, -(hitData.damage + hitData.elementalDamage));
showFlyTextPrivateProseWithFlags(defender, attacker, ppc, 1.5f, combat.getCriticalColor(hitData.critDamage), FLY_TEXT_FLAG_IS_DAMAGE_FROM_PLAYER);
}
else
{
showFlyTextPrivateProseWithFlags(defender, attacker, pp, textSize, combatColor, FLY_TEXT_FLAG_IS_DAMAGE_FROM_PLAYER);
}
}
else
{
if (hitData.critDamage > 0 && hitData.critDamage < 7)
{
string_id critSpam = new string_id("combat_effects", "critical_hit_" + hitData.critDamage);
prose_package ppc = new prose_package();
ppc = prose.setStringId(ppc, critSpam);
ppc = prose.setDI(ppc, -(hitData.damage + hitData.elementalDamage));
showFlyTextPrivateProseWithFlags(defender, attacker, ppc, 1.5f, combat.getCriticalColor(hitData.critDamage), FLY_TEXT_FLAG_IS_DAMAGE_FROM_PLAYER);
}
else
{
showFlyTextPrivateProseWithFlags(defender, attacker, pp, 1.5f, colors.DARKORANGE, FLY_TEXT_FLAG_IS_DAMAGE_FROM_PLAYER);
}
}
}
if (beast_lib.isBeast(defender) || pet_lib.isPet(defender))
{
obj_id master = getMaster(defender);
if (isIdValid(master) && exists(master))
{
string_id strSpam = null;
color combatHue = colors.YELLOW;
if (hitData.critDamage > 0 && hitData.critDamage < 7)
{
strSpam = new string_id("combat_effects", "critical_hit_" + hitData.critDamage);
combatHue = combat.getCriticalColor(hitData.critDamage);
}
else
{
strSpam = new string_id("combat_effects", "damage_fly");
}
prose_package pp = new prose_package();
pp = prose.setStringId(pp, strSpam);
pp = prose.setDI(pp, -(hitData.damage + hitData.elementalDamage));
showFlyTextPrivate(defender, master, pp, 1.5f, combatHue);
}
}
if (beast_lib.isBeast(attacker) || pet_lib.isPet(attacker))
{
obj_id master = getMaster(attacker);
if (isIdValid(master) && exists(master))
{
string_id strSpam = null;
color combatHue = colors.RED;
if (hitData.critDamage > 0 && hitData.critDamage < 7)
{
strSpam = new string_id("combat_effects", "critical_hit_" + hitData.critDamage);
combatHue = combat.getCriticalColor(hitData.critDamage);
}
else
{
strSpam = new string_id("combat_effects", "damage_fly");
}
prose_package pp = new prose_package();
pp = prose.setStringId(pp, strSpam);
pp = prose.setDI(pp, -(hitData.damage + hitData.elementalDamage));
showFlyTextPrivate(defender, master, pp, 1.5f, combatHue);
}
}
combat.assignDamageCredit(attacker, defender, weaponData, hitData.damage);
}
public obj_id[] truncateTargetArray(obj_id[] array, obj_id target, int size) throws InterruptedException
{
if (array.length <= size + 1)
{
return array;
}
obj_id[] truncArray = new obj_id[size];
truncArray[0] = target;
int source = 0;
int dest = 1;
while (source < size)
{
if (array[source] != target)
{
truncArray[dest] = array[source];
dest++;
}
source++;
}
return truncArray;
}
public void sortDefendersByPlayer(obj_id[] defenders) throws InterruptedException
{
Vector playerList = new Vector();
playerList.setSize(0);
Vector objectList = new Vector();
objectList.setSize(0);
for (obj_id defender : defenders) {
if (isPlayer(defender)) {
utils.addElement(playerList, defender);
} else {
utils.addElement(objectList, defender);
}
}
if ((playerList.size() + objectList.size()) == defenders.length)
{
obj_id[] tempPlayerList = new obj_id[0];
if (playerList != null)
{
tempPlayerList = new obj_id[playerList.size()];
playerList.toArray(tempPlayerList);
}
obj_id[] tempObjectList = new obj_id[0];
if (objectList != null)
{
tempObjectList = new obj_id[objectList.size()];
objectList.toArray(tempObjectList);
}
defenders = utils.concatArrays(tempPlayerList, tempObjectList);
}
}
public obj_id[] validateDefenders(obj_id attacker, obj_id target, obj_id[] defenders, obj_id source, int maxDefenders, int validTargetType, boolean isOffensiveAction, obj_id losSourceObj, boolean isHeavyWeapon, boolean isSpecialAttack, boolean ignoreLOS, int pvpOnly, combat_data actionData) throws InterruptedException
{
Vector validDefenders = new Vector();
validDefenders.setSize(0);
if (defenders == null || defenders.length == 0)
{
obj_id[] _validDefenders = new obj_id[0];
if (validDefenders != null)
{
_validDefenders = new obj_id[validDefenders.size()];
validDefenders.toArray(_validDefenders);
}
return _validDefenders;
}
combat.combatLog(attacker, target, "validateDefenders", "Attempting to put target at start of list");
if (isIdValid(target) && (!isOffensiveAction || attacker != target))
{
if (!factions.ignorePlayer(attacker, target))
{
obj_id pvpAttacker = attacker;
obj_id pvpTarget = target;
if (isMob(attacker) && !isPlayer(attacker) && isIdValid(getMaster(attacker)))
{
pvpAttacker = getMaster(attacker);
}
if (isMob(target) && !isPlayer(target) && isIdValid(getMaster(target)))
{
pvpTarget = getMaster(target);
}
if (!isOffensiveAction || pvpCanAttack(pvpAttacker, pvpTarget))
{
validDefenders = utils.addElement(validDefenders, target);
}
}
else
{
combat.combatLog(attacker, target, "validateDefenders", "Invalid Target - Attacker or Target is flagged as playerIgnore");
}
}
if (!isOffensiveAction)
{
sortDefendersByPlayer(defenders);
}
losSourceObj = losSourceObj != null ? losSourceObj : attacker;
if (isIdValid(target) && target != attacker && (!combat.cachedCanSee(losSourceObj, target) && !ignoreLOS))
{
showFlyTextPrivate(attacker, attacker, new string_id("combat_effects", "cant_see"), 1.5f, colors.MEDIUMTURQUOISE);
combat.combatLog(attacker, target, "validateDefenders", "Invalid Target - Fail LOS check");
return null;
}
String attackerSocialGroup = null;
if (!isPlayer(attacker) && !pet_lib.isPet(attacker))
{
attackerSocialGroup = ai_lib.getSocialGroup(attacker);
}
for (obj_id defender : defenders) {
if (isInvulnerable(defender)) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Defender is invulnerable");
continue;
}
if (defender == target && actionData.attack_rolls == 1) {
combat.combatLog(attacker, defender, "validateDefenders", "Skipping target");
continue;
}
if (pvpOnly == 1 && !isPlayer(defender)) {
combat.combatLog(attacker, defender, "validateDefenders", "Skipping target - is not a Player");
continue;
}
if (!isIdValid(defender)) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Invalid ObjId");
continue;
}
if (isGameObjectTypeOf(defender, GOT_building)) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Is a building");
continue;
}
if (!isOffensiveAction && !isMob(defender)) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Not a mobile object");
continue;
}
if (!isOffensiveAction && vehicle.isVehicle(defender)) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Is a vehicle");
continue;
}
if (isOffensiveAction && isDead(defender) || getState(defender, STATE_FEIGN_DEATH) > 0) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Target is Dead");
continue;
}
if (isOffensiveAction && isIncapacitated(defender)) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Target is Incapped");
continue;
}
if (isOffensiveAction) {
obj_id pvpAttacker = attacker;
obj_id pvpTarget = defender;
if (isMob(attacker) && !isPlayer(attacker) && isIdValid(getMaster(attacker))) {
pvpAttacker = getMaster(attacker);
}
if (isMob(defender) && !isPlayer(defender) && isIdValid(getMaster(defender))) {
pvpTarget = getMaster(defender);
}
if (!pvpCanAttack(pvpAttacker, pvpTarget)) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Failed PvP check");
continue;
}
}
if (!isOffensiveAction && (!pvpCanHelp(attacker, defender) || pvpCanAttack(attacker, defender))) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Failed PvP check");
continue;
}
if (isOffensiveAction && attackerSocialGroup != null && attackerSocialGroup.equals(ai_lib.getSocialGroup(defender))) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Same AI social group");
continue;
}
if (!combat.cachedCanSee(losSourceObj, defender) && !ignoreLOS) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Fail LOS check");
continue;
}
if (isOffensiveAction && factions.ignorePlayer(attacker, defender)) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - Attacker or Defender is flagged as playerIgnore");
continue;
}
if (!combat.validateTarget(defender, validTargetType)) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - failed valid target check");
continue;
}
if (pet_lib.getPetType(defender) == pet_lib.PET_TYPE_FAMILIAR) {
combat.combatLog(attacker, defender, "validateDefenders", "Invalid Target - familiar");
continue;
}
combat.combatLog(attacker, defender, "validateDefenders", "Valid Target - Adding Defender: " + defender);
validDefenders = utils.addElement(validDefenders, defender);
if (validDefenders.size() == maxDefenders) {
break;
}
}
combat.combatLog(attacker, defenders[0], "validateDefenders", "Valid defender count = " + validDefenders.size());
obj_id[] _validDefenders = new obj_id[0];
if (validDefenders != null)
{
_validDefenders = new obj_id[validDefenders.size()];
validDefenders.toArray(_validDefenders);
}
return _validDefenders;
}
public obj_id[] validateDefenders(obj_id attacker, obj_id target, obj_id[] defenders, obj_id source, int maxDefenders, int validTargetType, boolean isOffensiveAction, obj_id losSourceObj, boolean isHeavyWeapon, boolean isSpecialAttack) throws InterruptedException
{
return validateDefenders(attacker, target, defenders, source, maxDefenders, validTargetType, isOffensiveAction, null, false, false, false, 0, null);
}
public obj_id[] validateDefenders(obj_id attacker, obj_id target, obj_id[] defenders, obj_id source, int maxDefenders, int validTargetType, boolean isOffensiveAction) throws InterruptedException
{
return validateDefenders(attacker, target, defenders, source, maxDefenders, validTargetType, isOffensiveAction, null, false, false);
}
public defender_results[] createDefenderResultsArray(int size) throws InterruptedException
{
defender_results[] defenderResults = new defender_results[size];
for (int i = 0; i < size; i++)
{
defenderResults[i] = new defender_results();
}
return defenderResults;
}
public hit_result[] createHitResultsArray(int size) throws InterruptedException
{
hit_result[] hitData = new hit_result[size];
for (int i = 0; i < size; i++)
{
hitData[i] = new hit_result();
}
return hitData;
}
public attacker_results[] createAttackerResultsArray(int size) throws InterruptedException
{
attacker_results[] attackerResults = new attacker_results[size];
for (int i = 0; i < size; i++)
{
attackerResults[i] = new attacker_results();
}
return attackerResults;
}
public boolean shouldPlayAnimation(obj_id objAttacker, combat_data actionData) throws InterruptedException
{
return true;
}
public void doMultiDefenderCombatResults(String[] playbackNames, attacker_results attackerResults, defender_results[] defenderResults, weapon_data weaponData, combat_data actionData, hit_result[] cbtHitData) throws InterruptedException
{
int weaponTrail = actionData.intWeapon;
int leftHandTrail = actionData.intLeftHand;
int rightHandTrail = actionData.intRightHand;
int leftFootTrail = actionData.intLeftFoot;
int rightFootTrail = actionData.intRightFoot;
if (playbackNames == null || playbackNames.length == 0 || attackerResults == null || defenderResults == null || defenderResults.length == 0 || weaponData == null || actionData == null || cbtHitData == null || cbtHitData.length == 0)
{
boolean pbnull = playbackNames == null;
boolean pbzero = playbackNames.length == 0;
boolean atkres = attackerResults == null;
boolean defres = defenderResults == null;
boolean deflen = defenderResults.length == 0;
boolean weadat = weaponData == null;
boolean actdat = actionData == null;
boolean cbtdat = cbtHitData == null;
CustomerServiceLog("COMBAT_exception", "Error in doMultiDefenderCombatResult: playbackNames == null : " + pbnull + ", playbackNames.length == 0: " + pbzero + ", attackerResults == null: " + atkres + ", defenderResults == null : " + defres + ", defenderResults.length == 0 : " + deflen + ", weaponData == null : " + weadat + ", actionData == null : " + actdat + ", cbtHitData = null : " + cbtdat);
return;
}
boolean addDamageAmount = (cbtHitData.length == defenderResults.length);
boolean boolPlayAnim = shouldPlayAnimation(attackerResults.id, actionData);
if (weaponData.weaponType == WEAPON_TYPE_UNARMED)
{
if (leftHandTrail > 0)
{
attackerResults.setTrail(attacker_results.TRAIL_LHAND, true);
}
if (rightHandTrail > 0)
{
attackerResults.setTrail(attacker_results.TRAIL_RHAND, true);
}
if (leftFootTrail > 0)
{
attackerResults.setTrail(attacker_results.TRAIL_LFOOT, true);
}
if (rightFootTrail > 0)
{
attackerResults.setTrail(attacker_results.TRAIL_RFOOT, true);
}
}
else
{
if (weaponTrail > 0 || combat.isLightsaberWeapon(weaponData.weaponType))
{
attackerResults.setTrail(attacker_results.TRAIL_WEAPON, true);
}
}
if (actionData.actionName == "" || actionData.actionName == null)
{
return;
}
attackerResults.actionName = getStringCrc(actionData.actionName.toLowerCase());
if (defenderResults.length > 1)
{
if (defenderResults[0] == null || cbtHitData[0] == null)
{
return;
}
defender_results[] defenderResult = new defender_results[1];
defenderResult[0] = defenderResults[0];
if (addDamageAmount)
{
defenderResult[0].damageAmount = cbtHitData[0].damage;
}
if (boolPlayAnim)
{
if (playbackNames[0] != null && !playbackNames[0].equals(""))
{
doCombatResults(playbackNames[0], attackerResults, defenderResult);
}
}
attacker_results animationResults = new attacker_results();
for (int i = 1; i < defenderResults.length; i++)
{
if (playbackNames[i] == null || playbackNames[i].equals("") || defenderResults[i] == null)
{
continue;
}
defenderResult[0].endPosture = defenderResults[i].endPosture;
defenderResult[0].id = defenderResults[i].id;
if (defenderResults[i].result == COMBAT_RESULT_HIT)
{
doCombatResults(playbackNames[i], null, defenderResult);
}
else if (defenderResults[i].result == COMBAT_RESULT_EVADE)
{
doCombatResults(playbackNames[i], null, defenderResult);
}
else if (defenderResults[i].result == COMBAT_RESULT_BLOCK)
{
doCombatResults(playbackNames[i], null, defenderResult);
}
else if (defenderResults[i].result == COMBAT_RESULT_MISS)
{
doCombatResults(playbackNames[i], null, defenderResult);
}
else if (defenderResults[i].result == COMBAT_RESULT_TETHERED)
{
defenderResults[i].result = COMBAT_RESULT_MISS;
doCombatResults(playbackNames[i], null, defenderResult);
defenderResults[i].result = COMBAT_RESULT_TETHERED;
}
}
}
else
{
if (playbackNames[0] != null && !playbackNames[0].equals("") && defenderResults[0] != null)
{
if (addDamageAmount)
{
defenderResults[0].damageAmount = cbtHitData[0].damage + cbtHitData[0].elementalDamage;
}
if (defenderResults[0].result == COMBAT_RESULT_TETHERED)
{
defenderResults[0].result = COMBAT_RESULT_MISS;
if (boolPlayAnim)
{
doCombatResults(playbackNames[0], attackerResults, defenderResults);
}
defenderResults[0].result = COMBAT_RESULT_TETHERED;
}
if (boolPlayAnim)
{
doCombatResults(playbackNames[0], attackerResults, defenderResults);
}
}
}
}
public void doBasicGrenadeCombatResults(String[] playbackNames, attacker_results attackerResults, defender_results[] defenderResults, weapon_data weaponData, combat_data actionData, hit_result[] hitData) throws InterruptedException
{
String attackAnim = "throw_grenade";
String distance = "_near";
float range = getDistance(attackerResults.id, defenderResults[0].id);
String hitStrength = "_light";
int avgDamage = (weaponData.minDamage + weaponData.maxDamage) / 2;
String grenadeName = getGrenadeType(weaponData.id);
attackAnim += distance + "_" + grenadeName;
attackerResults.weapon = null;
boolean addDamageAmount = (hitData.length == defenderResults.length);
if (defenderResults.length > 1)
{
defender_results[] defenderResult = new defender_results[1];
defenderResult[0] = defenderResults[0];
if (addDamageAmount)
{
defenderResult[0].damageAmount = hitData[0].damage;
}
if (!playbackNames[0].equals(""))
{
doCombatResults(attackAnim, attackerResults, defenderResult);
}
attacker_results animationResults = new attacker_results();
for (int i = 1; i < defenderResults.length; i++)
{
animationResults.endPosture = defenderResults[i].endPosture;
animationResults.id = defenderResults[i].id;
if (defenderResults[i].result == COMBAT_RESULT_HIT)
{
if (hitData[i].damage > avgDamage)
{
hitStrength = "_medium";
}
else
{
hitStrength = "_light";
}
doCombatResults("get_hit_grenade" + distance + hitStrength, animationResults, null);
}
}
}
else
{
if (addDamageAmount)
{
defenderResults[0].damageAmount = hitData[0].damage;
}
doCombatResults(attackAnim, attackerResults, defenderResults);
}
return;
}
public boolean checkPosture(obj_id objAttacker, obj_id objDefender) throws InterruptedException
{
if (isDead(objDefender))
{
return false;
}
if (isIncapacitated(objDefender))
{
return false;
}
return true;
}
public boolean didHit(hit_result[] cbtHitData) throws InterruptedException
{
int intI = 0;
while (intI < cbtHitData.length)
{
if (cbtHitData[intI].success == true)
{
return true;
}
intI = intI + 1;
}
return false;
}
public void finalizeMineDamage(obj_id objAttacker, weapon_data cbtWeaponData, defender_data[] cbtDefenderData, hit_result[] cbtHitData, defender_results[] cbtDefenderResults) throws InterruptedException
{
obj_id[] objDefenders = new obj_id[cbtDefenderData.length];
int[] intResults = new int[cbtHitData.length];
int intI = 0;
while (intI < cbtDefenderData.length)
{
if (cbtHitData[intI].success)
{
if (damage(cbtDefenderData[intI].id, cbtWeaponData.damageType, cbtHitData[intI].hitLocation, cbtHitData[intI].damage))
{
}
else
{
}
}
else
{
}
objDefenders[intI] = cbtDefenderData[intI].id;
intResults[intI] = cbtDefenderResults[intI].result;
intI = intI + 1;
}
}
public color getHitColor(int intHitLocation) throws InterruptedException
{
switch (intHitLocation)
{
case HIT_LOCATION_BODY:
return colors.RED;
case HIT_LOCATION_HEAD:
return colors.BLUE;
case HIT_LOCATION_R_ARM:
return colors.RED;
case HIT_LOCATION_L_ARM:
return colors.RED;
case HIT_LOCATION_R_LEG:
return colors.GREEN;
case HIT_LOCATION_L_LEG:
return colors.GREEN;
}
return colors.WHITE;
}
public void doCombatFlyText(defender_data[] defenderData, obj_id attacker, hit_result[] hitData, defender_results[] defenderResults) throws InterruptedException
{
float textSize = 1.5f;
for (int i = 0; i < hitData.length; i++)
{
string_id strSpam = null;
color textColor = colors.WHITE;
if (defenderResults[i].result == COMBAT_RESULT_BLOCK || defenderResults[i].result == COMBAT_RESULT_LIGHTSABER_BLOCK)
{
strSpam = new string_id("combat_effects", "block");
}
else if (defenderResults[i].result == COMBAT_RESULT_EVADE)
{
strSpam = new string_id("combat_effects", "dodge");
}
else if (defenderResults[i].result == COMBAT_RESULT_COUNTER)
{
strSpam = new string_id("combat_effects", "counterattack");
}
else if (defenderResults[i].result == COMBAT_RESULT_MISS)
{
strSpam = new string_id("combat_effects", "miss");
}
else if (defenderResults[i].result == COMBAT_RESULT_TETHERED)
{
strSpam = new string_id("combat_effects", "tethered");
textSize = 5.0f;
}
if (strSpam != null)
{
if (isPlayer(attacker) && isMob(defenderData[i].id) && (!vehicle.isDriveableVehicle(defenderData[i].id)))
{
showCombatTextPrivate(defenderData[i].id, attacker, attacker, strSpam, textSize, textColor);
}
if (isPlayer(defenderData[i].id) && isMob(defenderData[i].id) && (!vehicle.isDriveableVehicle(defenderData[i].id)))
{
showCombatTextPrivate(defenderData[i].id, attacker, defenderData[i].id, strSpam, textSize, textColor);
}
}
}
}
public String getHitSpam(hit_result cbtHitData) throws InterruptedException
{
int intHitLocation = cbtHitData.hitLocation;
String strId = "";
switch (intHitLocation)
{
case HIT_LOCATION_BODY:
return "body";
case HIT_LOCATION_HEAD:
return "head";
case HIT_LOCATION_R_ARM:
return "rarm";
case HIT_LOCATION_L_ARM:
return "larm";
case HIT_LOCATION_R_LEG:
return "rleg";
case HIT_LOCATION_L_LEG:
return "lleg";
}
return strId;
}
public boolean checkForFumbles(hit_result[] hitData) throws InterruptedException
{
return false;
}
public void doFumble(attacker_data cbtAttackerData, weapon_data cbtWeaponData, int intAttackerPosture, String strAnimationAction) throws InterruptedException
{
string_id strSpam = new string_id("cbt_spam", "fumble");
int intFumbleDamage = rand(cbtWeaponData.minDamage, cbtWeaponData.maxDamage);
return;
}
public boolean isImmuneToStateChange(obj_id target) throws InterruptedException
{
if (vehicle.isDriveableVehicle(target))
{
return true;
}
if (ai_lib.aiGetNiche(target) == NICHE_DROID)
{
return true;
}
if (ai_lib.aiGetNiche(target) == NICHE_VEHICLE)
{
return true;
}
if (ai_lib.isAndroid(target))
{
return true;
}
if (ai_lib.isTurret(target))
{
return true;
}
return false;
}
public void doWarcryCombatResults(String strAnimationAction, attacker_results cbtAttackerResults, defender_results[] cbtDefenderResults) throws InterruptedException
{
if (cbtDefenderResults.length > 1)
{
attacker_results cbtAnimationResults = new attacker_results();
defender_results[] cbtDefenderResult = new defender_results[1];
cbtDefenderResult[0] = cbtDefenderResults[0];
doCombatResults(strAnimationAction, cbtAttackerResults, cbtDefenderResult);
for (defender_results cbtDefenderResult1 : cbtDefenderResults) {
cbtAnimationResults.endPosture = cbtDefenderResult1.endPosture;
cbtAnimationResults.id = cbtDefenderResult1.id;
if (cbtDefenderResult1.result == COMBAT_RESULT_HIT) {
doCombatResults("get_hit_light", cbtAnimationResults, null);
}
}
}
else
{
doCombatResults(strAnimationAction, cbtAttackerResults, cbtDefenderResults);
}
}
public void doSuppressionFireResults(String strPlaybackName, attacker_results cbtAttackerResults, defender_results[] cbtDefenderResults, combat_data dctCombatInfo) throws InterruptedException
{
int intLeftFoot = dctCombatInfo.intLeftFoot;
int intRightFoot = dctCombatInfo.intRightFoot;
int intWeapon = dctCombatInfo.intWeapon;
int intRightHand = dctCombatInfo.intRightHand;
int intLeftHand = dctCombatInfo.intLeftHand;
if (jedi.isLightsaber(cbtAttackerResults.weapon))
{
intWeapon = 1;
}
if (intLeftFoot > 0)
{
cbtAttackerResults.setTrail(attacker_results.TRAIL_LFOOT, true);
}
if (intRightFoot > 0)
{
cbtAttackerResults.setTrail(attacker_results.TRAIL_RFOOT, true);
}
if (intLeftHand > 0)
{
cbtAttackerResults.setTrail(attacker_results.TRAIL_LHAND, true);
}
if (intRightHand > 0)
{
cbtAttackerResults.setTrail(attacker_results.TRAIL_RHAND, true);
}
if (intWeapon > 0)
{
cbtAttackerResults.setTrail(attacker_results.TRAIL_WEAPON, true);
}
if (cbtDefenderResults.length > 1)
{
int intI = 1;
attacker_results cbtAnimationResults = new attacker_results();
defender_results[] cbtDefenderResult = new defender_results[1];
cbtDefenderResult[0] = cbtDefenderResults[0];
doCombatResults(strPlaybackName, cbtAttackerResults, cbtDefenderResult);
while (intI < cbtDefenderResults.length)
{
cbtAnimationResults.endPosture = cbtDefenderResults[intI].endPosture;
cbtAnimationResults.id = cbtDefenderResults[intI].id;
if (cbtDefenderResults[intI].result == COMBAT_RESULT_HIT)
{
doCombatResults("posture_scramble", cbtAnimationResults, null);
}
else if (cbtDefenderResults[intI].result == COMBAT_RESULT_EVADE)
{
doCombatResults("dodge", cbtAnimationResults, null);
}
else if (cbtDefenderResults[intI].result == COMBAT_RESULT_BLOCK)
{
doCombatResults("dodge", cbtAnimationResults, null);
}
else if (cbtDefenderResults[intI].result == COMBAT_RESULT_MISS)
{
doCombatResults("dodge", cbtAnimationResults, null);
}
else
{
}
intI = intI + 1;
}
}
else
{
doCombatResults(strPlaybackName, cbtAttackerResults, cbtDefenderResults);
}
}
public void doChargeResults(String strPlaybackName, attacker_results cbtAttackerResults, defender_results[] cbtDefenderResults) throws InterruptedException
{
if (cbtDefenderResults.length > 1)
{
int intI = 1;
attacker_results cbtAnimationResults = new attacker_results();
defender_results[] cbtDefenderResult = new defender_results[1];
cbtDefenderResult[0] = cbtDefenderResults[0];
doCombatResults(strPlaybackName, cbtAttackerResults, cbtDefenderResult);
while (intI < cbtDefenderResults.length)
{
cbtAnimationResults.endPosture = cbtDefenderResults[intI].endPosture;
cbtAnimationResults.id = cbtDefenderResults[intI].id;
if (cbtDefenderResults[intI].result == COMBAT_RESULT_HIT)
{
doCombatResults("change_posture", cbtAnimationResults, null);
}
else if (cbtDefenderResults[intI].result == COMBAT_RESULT_EVADE)
{
doCombatResults("dodge", cbtAnimationResults, null);
}
else if (cbtDefenderResults[intI].result == COMBAT_RESULT_BLOCK)
{
doCombatResults("dodge", cbtAnimationResults, null);
}
else if (cbtDefenderResults[intI].result == COMBAT_RESULT_MISS)
{
doCombatResults("dodge", cbtAnimationResults, null);
}
intI = intI + 1;
}
}
else
{
doCombatResults(strPlaybackName, cbtAttackerResults, cbtDefenderResults);
}
}
public String getPlaybackIntensity(String strPlaybackName, hit_result[] cbtHitData, weapon_data cbtWeaponData) throws InterruptedException
{
String strNewAction = new String();
strNewAction = strPlaybackName;
int intMidDamage = (cbtWeaponData.minDamage + cbtWeaponData.maxDamage) / 2;
if (cbtHitData[0].damage > intMidDamage)
{
strNewAction = strNewAction + "_medium";
}
else
{
strNewAction = strNewAction + "_light";
}
return strNewAction;
}
public String getThrownWeaponStringType(obj_id objWeapon) throws InterruptedException
{
String strType = "";
String strTemplate = getGrenadeType(objWeapon);
if (strTemplate == null)
{
strType = "";
}
strType = strType + strTemplate;
return strType;
}
public String getHeavyWeaponStringType(obj_id objWeapon) throws InterruptedException
{
String strType = "heavy_";
String strTemplate = getHeavyWeaponType(objWeapon);
if (strTemplate == null)
{
strType = "";
}
strType = strType + strTemplate;
return strTemplate;
}
public String[] makeStringArray(int intLength) throws InterruptedException
{
int intI = 0;
String[] strArray = new String[intLength];
while (intI < intLength)
{
strArray[intI] = "";
intI = intI + 1;
}
return strArray;
}
public boolean checkWeaponData(obj_id objPlayer, obj_id objTarget, int intAttackCategory, weapon_data cbtWeaponData, String strCommand, String strWeaponType) throws InterruptedException
{
float fltDistance = getDistance(objPlayer, objTarget);
if (fltDistance > cbtWeaponData.maxRange)
{
combat.sendCombatSpamMessage(objPlayer, new string_id("cbt_spam", "out_of_range"), COMBAT_RESULT_OUT_OF_RANGE);
sendSystemMessage(objPlayer, new string_id("cbt_spam", "out_of_range_single"));
return false;
}
if (intAttackCategory != combat.ALL_WEAPONS)
{
if ((intAttackCategory == combat.RANGED_WEAPON) || (intAttackCategory == combat.MELEE_WEAPON))
{
int intWeaponCategory = combat.getWeaponCategory(cbtWeaponData.weaponType);
if (intWeaponCategory != intAttackCategory)
{
string_id strSpam = new string_id("cbt_spam", "no_attack_wrong_weapon");
sendSystemMessage(objPlayer, strSpam);
return false;
}
}
else if (intAttackCategory == combat.ALL_LIGHTSABERS)
{
if (!jedi.isLightsaber(cbtWeaponData.weaponType))
{
string_id strSpam = new string_id("cbt_spam", "no_attack_wrong_weapon");
sendSystemMessage(objPlayer, strSpam);
return false;
}
}
else if (intAttackCategory == combat.FORCE_POWER)
{
if (!jedi.isLightsaber(cbtWeaponData.weaponType))
{
if (cbtWeaponData.weaponType != WEAPON_TYPE_UNARMED)
{
}
}
}
else if (intAttackCategory != cbtWeaponData.weaponType)
{
string_id strSpam = new string_id("cbt_spam", "no_attack_wrong_weapon");
sendSystemMessage(objPlayer, strSpam);
return false;
}
}
if (!strCommand.equals(""))
{
String strAbility = strWeaponType + strCommand;
if (!hasCommand(objPlayer, strAbility))
{
string_id strSpam = new string_id("cbt_spam", "no_ability");
sendSystemMessage(objPlayer, strSpam);
return false;
}
}
return true;
}
public boolean checkCommands(obj_id objPlayer, String strCommand, String strWeaponType) throws InterruptedException
{
if (!strCommand.equals(""))
{
String strAbility = strWeaponType + strCommand;
if (!hasCommand(objPlayer, strAbility))
{
string_id strSpam = new string_id("cbt_spam", "no_ability");
sendSystemMessage(objPlayer, strSpam);
return false;
}
}
return true;
}
public boolean checkForCombatActions(obj_id objPlayer) throws InterruptedException
{
if (queueHasCommandFromGroup(objPlayer, (-1170591580)))
{
return true;
}
if (queueHasCommandFromGroup(objPlayer, (391413347)))
{
return true;
}
if (queueHasCommandFromGroup(objPlayer, (-506878646)))
{
return true;
}
return false;
}
public String getGrenadeType(obj_id objGrenade) throws InterruptedException
{
String strTemplate = getTemplateName(objGrenade);
if (strTemplate.equals("object/weapon/ranged/grenade/grenade_cryoban.iff"))
{
return "cryoban";
}
if (strTemplate.equals("object/weapon/ranged/grenade/grenade_fragmentation_light.iff"))
{
return "fragmentation";
}
if (strTemplate.equals("object/weapon/ranged/grenade/grenade_fragmentation.iff"))
{
return "fragmentation";
}
if (strTemplate.equals("object/weapon/ranged/grenade/grenade_glop.iff"))
{
return "glop";
}
if (strTemplate.equals("object/weapon/ranged/grenade/grenade_imperial_detonator.iff"))
{
return "imperial_detonator";
}
if (strTemplate.equals("object/weapon/ranged/grenade/grenade_proton.iff"))
{
return "proton";
}
if (strTemplate.equals("object/weapon/ranged/grenade/grenade_thermal_detonator.iff"))
{
return "thermal_detonator";
}
if (strTemplate.equals("object/weapon/ranged/grenade/grenade_bug_bomb.iff"))
{
return "bug_bomb";
}
return "fragmentation";
}
public String getHeavyWeaponType(obj_id objHeavyWeapon) throws InterruptedException
{
String strTemplate = getTemplateName(objHeavyWeapon);
String hw = "heavyweapon";
if (strTemplate.equals("object/weapon/ranged/heavy/heavy_rocket_laucher.iff"))
{
return hw;
}
if (strTemplate.equals("object/weapon/ranged/heavy/heavy_lightning_beam.iff"))
{
return hw;
}
if (strTemplate.equals("object/weapon/ranged/heavy/heavy_particle_beam.iff"))
{
return hw;
}
if (strTemplate.equals("object/weapon/ranged/heavy/heavy_acid_beam.iff"))
{
return hw;
}
if (strTemplate.equals("object/weapon/ranged/rifle/rifle_flame_thrower.iff"))
{
return "rifle";
}
if (strTemplate.equals("object/weapon/ranged/rifle/rifle_beam.iff"))
{
return "rifle_beam";
}
if (strTemplate.equals("object/weapon/ranged/rifle/rifle_acid_beam.iff"))
{
return "rifle";
}
if (strTemplate.equals("object/weapon/ranged/rifle/rifle_lightning.iff"))
{
return "carbine";
}
return hw;
}
public void clearQueue(obj_id objPlayer) throws InterruptedException
{
queueClearCommandsFromGroup(objPlayer, (-506878646));
queueClearCommandsFromGroup(objPlayer, (-1170591580));
queueClearCommandsFromGroup(objPlayer, (391413347));
}
public boolean callSupplyDrop(obj_id self, int supplyId) throws InterruptedException
{
location loc = getLocation(self);
if (isIdValid(loc.cell))
{
sendSystemMessage(self, new string_id("combat_effects", "not_indoors"));
return false;
}
obj_id shuttle = createObject("object/creature/npc/theme_park/lambda_shuttle.iff", loc);
if (!isIdValid(shuttle))
{
return false;
}
dictionary d = new dictionary();
d.put("owner", self);
d.put("supplyId", supplyId);
attachScript(shuttle, "systems.combat.combat_supply_drop_controller");
messageTo(shuttle, "startLandingSequence", d, 5.0f, false);
if (supplyId < 13)
{
prose_package pp = new prose_package();
prose.setStringId(pp, new string_id("combat_effects", "supply_drop_comm"));
commPlayers(self, "object/mobile/npe/npe_hutt_minion.iff", "sound/sys_comm_other.snd", 5.0f, self, pp);
}
else
{
prose_package pp = new prose_package();
prose.setStringId(pp, new string_id("spam", "officer_reinforcement_com"));
commPlayers(self, "object/mobile/npe/npe_hutt_minion.iff", "sound/sys_comm_other.snd", 5.0f, self, pp);
}
return true;
}
public boolean canCallSupplyDrop(obj_id self) throws InterruptedException
{
location loc = getLocation(self);
if (isIdValid(loc.cell))
{
sendSystemMessage(self, new string_id("combat_effects", "not_indoors"));
return false;
}
return true;
}
public boolean callFavor(obj_id self, int which) throws InterruptedException
{
location loc = getLocation(self);
String buddyObj = "summon_smuggler_buddy_";
String buddyScript = "ai.smuggler_buddy";
String buddyName = "smuggler_buddy_name";
if (which == 1)
{
buddyObj = "summon_smuggler_medic_";
buddyScript = "ai.smuggler_medic";
buddyName = "smuggler_medic_name";
}
if (!isIdValid(loc.cell))
{
int x = rand(-3, 3);
int z = rand(-3, 3);
loc.x += x;
loc.z += z;
}
int playerLevel = getLevel(self);
int summonLevel = playerLevel / 10;
if (summonLevel < 1)
{
summonLevel = 1;
}
else
{
if (summonLevel > 9)
{
summonLevel = 9;
}
}
buddyObj += summonLevel;
obj_id target = getHateTarget(self);
if (!isIdValid(target))
{
sendSystemMessage(self, new string_id("combat_effects", "no_target_for_buddy"));
return false;
}
obj_id buddy = create.object(buddyObj, loc, getLevel(self));
if (!isIdValid(buddy))
{
return false;
}
setName(buddy, new string_id("combat_effects", buddyName));
attachScript(buddy, buddyScript);
if (!isIdValid(loc.cell))
{
loc.x += 30;
setHomeLocation(buddy, loc);
}
setMaster(buddy, self);
startCombat(buddy, target);
return true;
}
public boolean doHealingPreCheck(combat_data actionData, attacker_data attackerData, defender_data[] defenderData, boolean verbose) throws InterruptedException
{
if (vehicle.isRidingVehicle(attackerData.id))
{
if (verbose)
{
sendSystemMessage(attackerData.id, new string_id("cbt_spam", "attack_fail_vehicle_single"));
}
combat.combatLog(attackerData.id, defenderData[0].id, "doHealingPreCheck", "Aborting Action - Riding vehicle");
return false;
}
obj_id mount = getMountId(attackerData.id);
if (isIdValid(mount))
{
if (pet_lib.isGalloping(mount))
{
if (verbose)
{
sendSystemMessage(attackerData.id, new string_id("cbt_spam", "attack_fail_gallop_single"));
}
combat.combatLog(attackerData.id, defenderData[0].id, "doHealingPreCheck", "Aborting Action - Riding galloping mount");
return false;
}
}
if (attackerData.posture == POSTURE_KNOCKED_DOWN)
{
if (verbose)
{
sendSystemMessage(attackerData.id, new string_id("cbt_spam", "attack_fail_knockdown_single"));
}
combat.combatLog(attackerData.id, defenderData[0].id, "doHealingPreCheck", "Aborting Action - Attacker id knocked down");
return false;
}
float actionMaxRange = actionData.maxRange;
float dist = getDistance(attackerData.id, defenderData[0].id);
if (dist > actionMaxRange)
{
if (verbose)
{
sendSystemMessage(attackerData.id, new string_id("cbt_spam", "out_of_range_far_single"));
showFlyTextPrivate(attackerData.id, attackerData.id, new string_id("combat_effects", "range_too_far"), 1.0f, colors.MEDIUMTURQUOISE);
}
combat.combatLog(attackerData.id, defenderData[0].id, "doHealingPreCheck", "Aborting Action - Target is further than max range");
return false;
}
if ((ai_lib.isDroid(defenderData[0].id) && !ai_lib.isDroid(attackerData.id)) || (ai_lib.isAndroid(defenderData[0].id) && !ai_lib.isAndroid(attackerData.id)))
{
if (verbose)
{
sendSystemMessage(attackerData.id, new string_id("cbt_spam", "cannot_heal_droid"));
showFlyTextPrivate(attackerData.id, attackerData.id, new string_id("cbt_spam", "cannot_heal_droid"), 1.0f, colors.MEDIUMTURQUOISE);
}
return false;
}
return true;
}
public boolean hasFullActionPool(obj_id target) throws InterruptedException
{
int currentAction = getAction(target);
int maxAction = getMaxAction(target);
if (currentAction == maxAction)
{
return true;
}
return false;
}
public boolean healthToActionConversion(obj_id target, int healthCost, int actionGain) throws InterruptedException
{
int currentHealth = getHealth(target);
int modifiedHealth = currentHealth - healthCost;
attrib_mod[] healthMods = getHealthModifiers(target);
int healthModsValue = 0;
for (attrib_mod healthMod : healthMods) {
healthModsValue += healthMod.getValue();
}
if (healthModsValue < 0)
{
sendSystemMessage(target, new string_id("spam", "not_well_enough"));
return false;
}
if (modifiedHealth < 1)
{
showFlyTextPrivate(target, target, new string_id("spam", "low_health"), 1.0f, colors.RED);
return false;
}
int currentAction = getAction(target);
int maxAction = getMaxAction(target);
int modifiedAction = currentAction + actionGain;
int trueActionGained = 0;
if (modifiedAction > maxAction)
{
setAction(target, maxAction);
trueActionGained = maxAction - currentAction;
}
else
{
setAction(target, modifiedAction);
trueActionGained = actionGain;
}
setHealth(target, modifiedHealth);
string_id actionStringId = new string_id("spam", "plus_action");
prose_package pp = new prose_package();
pp = prose.setStringId(pp, actionStringId);
pp = prose.setDI(pp, trueActionGained);
showFlyTextPrivate(target, target, pp, 1.1f, colors.YELLOW);
playClientEffectObj(target, "clienteffect/medic_reckless_stimulation.cef", target, "root");
return true;
}
public void doMedicEvasion(obj_id medic) throws InterruptedException
{
obj_id[] thoseWhoHateMe = getHateList(medic);
int medicLevel = getLevel(medic);
String evasionScriptVarName = "me_evasion." + medic;
if (thoseWhoHateMe.length != 0 && thoseWhoHateMe != null)
{
for (obj_id obj_id : thoseWhoHateMe) {
int haterLevel = getLevel(obj_id);
int levelSpread = medicLevel - haterLevel;
int baseChance = 93;
int difficultyClass = getIntObjVar(obj_id, "difficultyClass");
if (difficultyClass > 1) {
baseChance = -45;
}
if (levelSpread < -24) {
levelSpread = -24;
}
int roll = rand(1, 100);
if (roll + baseChance + (levelSpread * 3) > 100) {
removeHateTarget(medic, obj_id);
removeHateTarget(obj_id, medic);
utils.setScriptVar(obj_id, evasionScriptVarName, 1);
} else {
float hate = getHate(medic, obj_id);
float oldHate = hate;
hate /= 2;
setHate(medic, obj_id, hate);
utils.removeScriptVar(obj_id, evasionScriptVarName);
}
}
}
return;
}
public combat_data modifyActionDataByExpertise(obj_id self, combat_data actionData) throws InterruptedException
{
if (stealth.hasInvisibleBuff(self) || buff.hasBuff(self, "sp_smoke_mirrors"))
{
float expertise_defense_overpower = getEnhancedSkillStatisticModifierUncapped(self, "expertise_avoidance_overpower");
actionData.reduceParry += expertise_defense_overpower;
actionData.reduceDodge += expertise_defense_overpower;
actionData.reduceBlock += expertise_defense_overpower;
actionData.reduceGlancing += expertise_defense_overpower;
}
float armorBypass = getEnhancedSkillStatisticModifierUncapped(self, "expertise_armor_bypass_" + actionData.specialLine);
if (armorBypass > 0.0f)
{
armorBypass = armorBypass / 100.0f;
armorBypass += actionData.bypassArmor;
armorBypass = armorBypass > 1.0f ? 1.0f : armorBypass;
actionData.increaseStrikethrough = -1000.0f;
actionData.bypassArmor = armorBypass;
}
float damToHeal = getEnhancedSkillStatisticModifierUncapped(self, "expertise_damage_to_healing_" + actionData.specialLine);
if (damToHeal > 0.0f && actionData.convertDamageToHealth > 0.0f)
{
damToHeal = damToHeal / 100.0f;
actionData.convertDamageToHealth += damToHeal;
}
float flawlessBead = getEnhancedSkillStatisticModifierUncapped(self, "flawless_bead");
if (flawlessBead > 0 && actionData.commandType != combat.LEFT_CLICK_DEFAULT)
{
actionData.reduceParry += flawlessBead;
actionData.reduceDodge += flawlessBead;
actionData.reduceBlock += flawlessBead;
actionData.reduceGlancing += flawlessBead;
}
return actionData;
}
public void runHitSimulator(obj_id self, int[] atkTable, int[] defTable) throws InterruptedException
{
if (!isGod(self) && !utils.hasObjVar(self, "runHitSimulator"))
{
return;
}
int hitLoops = 0;
if (hasObjVar(self, "runHitSimulator"))
{
hitLoops = getIntObjVar(self, "runHitSimulator");
}
if (hitLoops < 1)
{
utils.removeObjVar(self, "runHitSimulator");
return;
}
hitLoops--;
utils.setObjVar(self, "runHitSimulator", hitLoops);
if (utils.hasScriptVar(self, "hitpid"))
{
int bellpid = utils.getIntScriptVar(self, "hitpid");
sui.forceCloseSUIPage(bellpid);
}
int hitNumber = 1000;
int miss = 0;
int dodge = 0;
int parry = 0;
int glancing = 0;
int block = 0;
int critical = 0;
int punishing = 0;
int dhit = 0;
int ahit = 0;
int hit = 0;
int evade = 0;
int strikethrough = 0;
for (int i2 : defTable) {
switch (i2) {
case HIT_RESULT_MISS:
miss++;
break;
case HIT_RESULT_DODGE:
dodge++;
break;
case HIT_RESULT_PARRY:
parry++;
break;
case HIT_RESULT_GLANCING:
glancing++;
break;
case HIT_RESULT_BLOCK:
block++;
break;
case HIT_RESULT_CRITICAL:
critical++;
break;
case HIT_RESULT_PUNISHING:
punishing++;
break;
case HIT_RESULT_EVADE:
evade++;
break;
case HIT_RESULT_STRIKETHROUGH:
strikethrough++;
break;
}
}
for (int i = 0; i < atkTable.length; i++)
{
switch (atkTable[i])
{
case HIT_RESULT_MISS:
miss++;
break;
case HIT_RESULT_DODGE:
dodge++;
break;
case HIT_RESULT_PARRY:
parry++;
break;
case HIT_RESULT_GLANCING:
glancing++;
break;
case HIT_RESULT_BLOCK:
block++;
break;
case HIT_RESULT_CRITICAL:
critical++;
break;
case HIT_RESULT_PUNISHING:
punishing++;
break;
case HIT_RESULT_HIT:
if (defTable[i] == HIT_RESULT_HIT)
{
hit++;
}
break;
case HIT_RESULT_EVADE:
evade++;
break;
case HIT_RESULT_STRIKETHROUGH:
strikethrough++;
break;
}
}
int test_miss = 0;
int test_dodge = 0;
int test_parry = 0;
int test_glancing = 0;
int test_block = 0;
int test_critical = 0;
int test_punishing = 0;
int test_hit = 0;
int test_evade = 0;
int test_strikethrough = 0;
int[] atkResult = new int[hitNumber];
int[] defResult = new int[hitNumber];
for (int i = 0; i < hitNumber; i++)
{
defResult[i] = defTable[rand(0, defTable.length - 1)];
atkResult[i] = atkTable[rand(0, atkTable.length - 1)];
}
for (int i1 : defResult) {
switch (i1) {
case HIT_RESULT_MISS:
test_miss++;
break;
case HIT_RESULT_DODGE:
test_dodge++;
break;
case HIT_RESULT_PARRY:
test_parry++;
break;
case HIT_RESULT_GLANCING:
test_glancing++;
break;
case HIT_RESULT_BLOCK:
test_block++;
break;
case HIT_RESULT_CRITICAL:
test_critical++;
break;
case HIT_RESULT_PUNISHING:
test_punishing++;
break;
case HIT_RESULT_EVADE:
test_evade++;
break;
case HIT_RESULT_STRIKETHROUGH:
test_strikethrough++;
break;
}
}
for (int i = 0; i < atkResult.length; i++)
{
switch (atkResult[i])
{
case HIT_RESULT_MISS:
test_miss++;
break;
case HIT_RESULT_DODGE:
test_dodge++;
break;
case HIT_RESULT_PARRY:
test_parry++;
break;
case HIT_RESULT_GLANCING:
test_glancing++;
break;
case HIT_RESULT_BLOCK:
test_block++;
break;
case HIT_RESULT_CRITICAL:
test_critical++;
break;
case HIT_RESULT_PUNISHING:
test_punishing++;
break;
case HIT_RESULT_HIT:
if (defResult[i] == HIT_RESULT_HIT)
{
test_hit++;
}
break;
case HIT_RESULT_EVADE:
test_evade++;
break;
case HIT_RESULT_STRIKETHROUGH:
test_strikethrough++;
break;
}
}
int pid = createSUIPage(sui.SUI_MSGBOX, self, self, "noHandler");
setSUIProperty(pid, "", "Size", "650,375");
setSUIProperty(pid, sui.LISTBOX_TITLE, sui.PROP_TEXT, "Hit Result Analysis");
sui.listboxButtonSetup(pid, sui.OK_ONLY);
setSUIProperty(pid, sui.LISTBOX_BTN_OK, sui.PROP_TEXT, "@cancel");
int passedTotal = miss + dodge + parry + glancing + block + critical + punishing + evade + strikethrough;
hit = 1000 - passedTotal > -1 ? 1000 - passedTotal : 0;
int simTotal = test_miss + test_dodge + test_parry + test_glancing + test_block + test_critical + test_punishing + test_evade + test_strikethrough;
test_hit = 1000 - simTotal > -1 ? 1000 - simTotal : 0;
String resultString = "Defender and Attacker Hit Table Values \n ";
resultString += "Passed hit_table Values \n ";
resultString += "Defender Dodge: " + dodge / 10.0f + " \n ";
resultString += "Defender Parry: " + parry / 10.0f + " \n ";
resultString += "Defender Evade: " + evade / 10.0f + " \n ";
resultString += "Defender Block: " + block / 10.0f + " \n ";
resultString += "Defender Glance: " + glancing / 10.0f + " \n\n ";
resultString += "Attacker Miss: " + miss / 10.0f + " \n ";
resultString += "Attacker Strikethrough: " + strikethrough / 10.0f + " \n ";
resultString += "Attacker Critical: " + critical / 10.0f + " \n ";
resultString += "Attacker Punishing: " + punishing / 10.0f + " \n ";
resultString += "Attacker Hit: " + hit / 10.0f + " \n\n\n";
resultString += "Simulated hit_table rolls (" + hitNumber + ") itterations \n ";
resultString += "Defender Dodge: " + test_dodge / 10.0f + " \n ";
resultString += "Defender Parry: " + test_parry / 10.0f + " \n ";
resultString += "Defender Evade: " + test_evade / 10.0f + " \n ";
resultString += "Defender Block: " + test_block / 10.0f + " \n ";
resultString += "Defender Glance: " + test_glancing / 10.0f + " \n\n ";
resultString += "Attacker Miss: " + test_miss / 10.0f + " \n ";
resultString += "Attacker Strikethrough: " + test_strikethrough / 10.0f + " \n ";
resultString += "Attacker Critical: " + test_critical / 10.0f + " \n ";
resultString += "Attacker Punishing: " + test_punishing / 10.0f + " \n ";
resultString += "Attacker Hit: " + test_hit / 10.0f + " \n ";
setSUIProperty(pid, sui.MSGBOX_PROMPT, sui.PROP_TEXT, resultString);
showSUIPage(pid);
flushSUIPage(pid);
utils.setScriptVar(self, "hitpid", pid);
}
public combat_data attackOverrideByBuff(obj_id self, combat_data actionData) throws InterruptedException
{
int hasAO = getEnhancedSkillStatisticModifierUncapped(self, "attack_override_by_buff");
if (hasAO < 1)
{
return actionData;
}
int[] allBuffs = buff.getAllBuffs(self);
if (allBuffs == null || allBuffs.length == 0)
{
return actionData;
}
for (int allBuff : allBuffs) {
String buffName = buff.getBuffNameFromCrc(allBuff);
if (buffName.length() != 0 && !buffName.equals("") && buffName.startsWith("attack_override_" + actionData.actionName)) {
String[] parse = split(buffName, '|');
String newAttack = parse[1];
return combat_engine.getCombatData(newAttack);
}
}
return actionData;
}
public void doKillMeterUpdate(obj_id attacker, obj_id defender, int damage) throws InterruptedException
{
if (!utils.isProfession(attacker, utils.COMMANDO) && !utils.isProfession(defender, utils.COMMANDO) || damage < 1)
{
return;
}
if (utils.isProfession(attacker, utils.COMMANDO))
{
int damageInterval = utils.getIntScriptVar(attacker, "km.damage_done");
damageInterval += damage;
if (damageInterval >= getLevel(attacker) * (15 - Math.round(getKillMeter(attacker) / 5.0f)))
{
utils.setScriptVar(attacker, "km.damage_done", 0);
combat.modifyKillMeter(attacker, 1);
}
else
{
utils.setScriptVar(attacker, "km.damage_done", damageInterval);
}
}
if (utils.isProfession(defender, utils.COMMANDO))
{
int damageInterval = utils.getIntScriptVar(defender, "km.damage_taken");
damageInterval += damage;
if (damageInterval >= getLevel(defender) * (25 - Math.round(getKillMeter(attacker) / 5.0f)))
{
utils.setScriptVar(defender, "km.damage_taken", 0);
combat.modifyKillMeter(defender, 1);
}
else
{
utils.setScriptVar(defender, "km.damage_taken", damageInterval);
}
}
}
}