Effects, modifiers, source types, effect fail conditions and item enchant values all come from Effects.cfg (4.6b). Removes dbEffectsBaseHandler, dbPowerHandler, the EffectsBase and effect modifier ResultSet constructors, EffectsBase.getFailConditions and LOAD_ENCHANT_VALUES. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
882 lines
34 KiB
Java
882 lines
34 KiB
Java
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
|
// Magicbane Emulator Project © 2013 - 2026
|
|
// https://www.magicbane.com
|
|
|
|
|
|
package engine.powers;
|
|
|
|
import engine.gameManager.DispatchManager;
|
|
import engine.gameManager.PowersManager;
|
|
import engine.job.JobContainer;
|
|
import engine.jobs.AbstractEffectJob;
|
|
import engine.jobs.DamageOverTimeJob;
|
|
import engine.jobs.FinishSpireEffectJob;
|
|
import engine.jobs.NoTimeJob;
|
|
import engine.mbEnums;
|
|
import engine.mbEnums.EffectSourceType;
|
|
import engine.mbEnums.GameObjectType;
|
|
import engine.mbEnums.PowerFailCondition;
|
|
import engine.net.Dispatch;
|
|
import engine.net.client.ClientConnection;
|
|
import engine.net.client.msg.ApplyEffectMsg;
|
|
import engine.objects.AbstractCharacter;
|
|
import engine.objects.AbstractWorldObject;
|
|
import engine.objects.Effect;
|
|
import engine.objects.Item;
|
|
import engine.objects.PlayerCharacter;
|
|
import engine.parsers.objects.wpak.CurveRamp;
|
|
import engine.parsers.objects.wpak.EffectTemplate;
|
|
import engine.parsers.objects.wpak.PowerActionTemplate;
|
|
import engine.powers.effectmodifiers.*;
|
|
import engine.server.MBServerStatics;
|
|
import engine.util.Hasher;
|
|
import org.pmw.tinylog.Logger;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
public class EffectsBase {
|
|
|
|
public static HashMap<Integer, HashSet<EffectSourceType>> effectSourceTypeMap = new HashMap<>();
|
|
public static HashMap<String, HashSet<AbstractEffectModifier>> modifiersMap = new HashMap<>();
|
|
public static HashMap<String, HashMap<String, ArrayList<String>>> OldEffectsMap = new HashMap<>();
|
|
public static HashMap<String, HashMap<String, ArrayList<String>>> NewEffectsMap = new HashMap<>();
|
|
public static HashMap<String, HashMap<String, ArrayList<String>>> ChangedEffectsMap = new HashMap<>();
|
|
public static HashMap<String, HashSet<PowerFailCondition>> EffectFailConditions = new HashMap<>();
|
|
public static HashMap<Integer, HashSet<mbEnums.DamageType>> EffectDamageTypes = new HashMap<>();
|
|
public static HashSet<AbstractEffectModifier> DefaultModifiers = new HashSet<>();
|
|
private static ConcurrentHashMap<String, String> itemEffectsByName = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
|
private int UUID;
|
|
private String IDString;
|
|
// private String name;
|
|
private int token;
|
|
private float amount;
|
|
private float amountRamp;
|
|
// flags
|
|
private boolean isItemEffect;
|
|
private boolean isSpireEffect;
|
|
private boolean ignoreMod;
|
|
private boolean dontSave;
|
|
private boolean cancelOnAttack = false;
|
|
private boolean cancelOnAttackSwing = false;
|
|
private boolean cancelOnCast = false;
|
|
private boolean cancelOnCastSpell = false;
|
|
private boolean cancelOnEquipChange = false;
|
|
private boolean cancelOnLogout = false;
|
|
private boolean cancelOnMove = false;
|
|
private boolean cancelOnNewCharm = false;
|
|
private boolean cancelOnSit = false;
|
|
private boolean cancelOnTakeDamage = false;
|
|
private boolean cancelOnTerritoryClaim = false;
|
|
private boolean cancelOnUnEquip = false;
|
|
private boolean useRampAdd;
|
|
private boolean isPrefix = false; //used by items
|
|
private boolean isSuffix = false; //used by items
|
|
private String name = "";
|
|
private float value = 0;
|
|
private ConcurrentHashMap<mbEnums.ResourceType, Integer> resourceCosts = new ConcurrentHashMap<>();
|
|
private ConcurrentHashMap<String, Boolean> sourceTypes = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
|
|
|
/**
|
|
* No Table ID Constructor
|
|
*/
|
|
public EffectsBase() {
|
|
|
|
}
|
|
|
|
public EffectsBase(EffectTemplate effectTemplate, int id) {
|
|
|
|
this.UUID = id;
|
|
this.IDString = effectTemplate.effect_id;
|
|
this.name = effectTemplate.effect_name;
|
|
this.token = effectToken(this.IDString);
|
|
this.isItemEffect = effectTemplate.isitemeffect;
|
|
this.isSpireEffect = effectTemplate.isspireeffect;
|
|
this.ignoreMod = effectTemplate.ignorenomod;
|
|
this.dontSave = effectTemplate.dontsave;
|
|
this.isPrefix = this.IDString.startsWith("PRE-");
|
|
this.isSuffix = this.IDString.startsWith("SUF-");
|
|
|
|
loadModifiers(effectTemplate.mods);
|
|
loadFailConditions(effectTemplate.conditions);
|
|
loadSourceTypes(effectTemplate.sources);
|
|
}
|
|
|
|
// A power action with no Effects.cfg block that the server still keys as an effect:
|
|
// item enchantment parents (PRE-/SUF-/ARM-) and the action tokens sent in effect messages.
|
|
public EffectsBase(PowerActionTemplate powerActionTemplate, int id) {
|
|
|
|
this.UUID = id;
|
|
this.IDString = powerActionTemplate.action_id;
|
|
this.token = effectToken(this.IDString);
|
|
this.isPrefix = this.IDString.startsWith("PRE-");
|
|
this.isSuffix = this.IDString.startsWith("SUF-");
|
|
}
|
|
|
|
// INVIS-D and SafeMode show as the SafeModeB/A action tokens on the client
|
|
private static int effectToken(String IDString) {
|
|
|
|
switch (IDString) {
|
|
case "INVIS-D":
|
|
return Hasher.SBStringHash("SafeModeB");
|
|
case "SafeMode":
|
|
return Hasher.SBStringHash("SafeModeA");
|
|
default:
|
|
return Hasher.SBStringHash(IDString);
|
|
}
|
|
}
|
|
|
|
private void loadFailConditions(ArrayList<EffectTemplate.ConditionEntry> conditions) {
|
|
|
|
CurveRamp curveRamp;
|
|
|
|
if (conditions.isEmpty())
|
|
return;
|
|
|
|
if (!EffectsBase.EffectFailConditions.containsKey(this.IDString))
|
|
EffectsBase.EffectFailConditions.put(this.IDString, new HashSet<>());
|
|
|
|
for (EffectTemplate.ConditionEntry condition : conditions) {
|
|
|
|
EffectsBase.EffectFailConditions.get(this.IDString).add(condition.condition);
|
|
|
|
switch (condition.condition) {
|
|
case TakeDamage:
|
|
this.cancelOnTakeDamage = true;
|
|
this.amount = condition.amount;
|
|
|
|
curveRamp = (condition.curve == null) ? null : CurveRamp.fromCurve(condition.curve);
|
|
|
|
if (condition.curve != null && curveRamp == null)
|
|
Logger.warn("Effect " + this.IDString + " TakeDamage curve " + condition.curve + " has no ramp form");
|
|
|
|
this.amountRamp = (curveRamp == null) ? 0 : curveRamp.ramp;
|
|
this.useRampAdd = (curveRamp == null) || curveRamp.useAdd;
|
|
|
|
if (condition.damage_types.isEmpty())
|
|
break;
|
|
|
|
if (!EffectsBase.EffectDamageTypes.containsKey(this.token))
|
|
EffectsBase.EffectDamageTypes.put(this.token, new HashSet<>());
|
|
|
|
EffectsBase.EffectDamageTypes.get(this.token).addAll(condition.damage_types);
|
|
break;
|
|
case Attack:
|
|
this.cancelOnAttack = true;
|
|
break;
|
|
case AttackSwing:
|
|
this.cancelOnAttackSwing = true;
|
|
break;
|
|
case Cast:
|
|
this.cancelOnCast = true;
|
|
break;
|
|
case CastSpell:
|
|
this.cancelOnCastSpell = true;
|
|
break;
|
|
case EquipChange:
|
|
this.cancelOnEquipChange = true;
|
|
break;
|
|
case Logout:
|
|
this.cancelOnLogout = true;
|
|
break;
|
|
case Move:
|
|
this.cancelOnMove = true;
|
|
break;
|
|
case NewCharm:
|
|
this.cancelOnNewCharm = true;
|
|
break;
|
|
case Sit:
|
|
this.cancelOnSit = true;
|
|
break;
|
|
case TerritoryClaim:
|
|
this.cancelOnTerritoryClaim = true;
|
|
break;
|
|
case UnEquip:
|
|
this.cancelOnUnEquip = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// AnimOverride is client-only and has no server modifier
|
|
private void loadModifiers(ArrayList<EffectTemplate.ModEntry> mods) {
|
|
|
|
AbstractEffectModifier modifier;
|
|
|
|
for (EffectTemplate.ModEntry modEntry : mods) {
|
|
|
|
switch (modEntry.mod_type) {
|
|
case AdjustAboveDmgCap:
|
|
modifier = new AdjustAboveDmgCapEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Ambidexterity:
|
|
modifier = new AmbidexterityEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ArmorPiercing:
|
|
modifier = new ArmorPiercingEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case AttackDelay:
|
|
modifier = new AttackDelayEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Attr:
|
|
modifier = new AttributeEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case BlackMantle:
|
|
modifier = new BlackMantleEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case BladeTrails:
|
|
modifier = new BladeTrailsEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Block:
|
|
modifier = new BlockEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case BlockedPowerType:
|
|
modifier = new BlockedPowerTypeEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case CannotAttack:
|
|
modifier = new CannotAttackEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case CannotCast:
|
|
modifier = new CannotCastEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case CannotMove:
|
|
modifier = new CannotMoveEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case CannotTrack:
|
|
modifier = new CannotTrackEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Charmed:
|
|
modifier = new CharmedEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ConstrainedAmbidexterity:
|
|
modifier = new ConstrainedAmbidexterityEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case DamageCap:
|
|
modifier = new DamageCapEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case DamageShield:
|
|
modifier = new DamageShieldEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case DCV:
|
|
modifier = new DCVEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Dodge:
|
|
modifier = new DodgeEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case DR:
|
|
modifier = new DREffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Durability:
|
|
modifier = new DurabilityEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ExclusiveDamageCap:
|
|
modifier = new ExclusiveDamageCapEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Fade:
|
|
modifier = new FadeEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Fly:
|
|
modifier = new FlyEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Health:
|
|
modifier = new HealthEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case HealthFull:
|
|
modifier = new HealthFullEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case HealthRecoverRate:
|
|
modifier = new HealthRecoverRateEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case IgnoreDamageCap:
|
|
modifier = new IgnoreDamageCapEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case IgnorePassiveDefense:
|
|
modifier = new IgnorePassiveDefenseEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ImmuneTo:
|
|
modifier = new ImmuneToEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ImmuneToAttack:
|
|
modifier = new ImmuneToAttackEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ImmuneToPowers:
|
|
modifier = new ImmuneToPowersEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Invisible:
|
|
modifier = new InvisibleEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ItemName:
|
|
modifier = new ItemNameEffectModifier(this.IDString, modEntry);
|
|
if (!((ItemNameEffectModifier) modifier).name.isEmpty())
|
|
this.name = ((ItemNameEffectModifier) modifier).name;
|
|
break;
|
|
case Mana:
|
|
modifier = new ManaEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ManaFull:
|
|
modifier = new ManaFullEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ManaRecoverRate:
|
|
modifier = new ManaRecoverRateEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case MaxDamage:
|
|
modifier = new MaxDamageEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case MeleeDamageModifier:
|
|
modifier = new MeleeDamageEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case MinDamage:
|
|
modifier = new MinDamageEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case NoMod:
|
|
modifier = new NoModEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case OCV:
|
|
modifier = new OCVEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Parry:
|
|
modifier = new ParryEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case PassiveDefense:
|
|
modifier = new PassiveDefenseEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case PowerCost:
|
|
modifier = new PowerCostEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case PowerCostHealth:
|
|
modifier = new PowerCostHealthEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case PowerDamageModifier:
|
|
modifier = new PowerDamageEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ProtectionFrom:
|
|
modifier = new ProtectionFromEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Resistance:
|
|
modifier = new ResistanceEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ScaleHeight:
|
|
modifier = new ScaleHeightEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ScaleWidth:
|
|
modifier = new ScaleWidthEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case ScanRange:
|
|
modifier = new ScanRangeEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case SeeInvisible:
|
|
modifier = new SeeInvisibleEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Silenced:
|
|
modifier = new SilencedEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Skill:
|
|
modifier = new SkillEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Slay:
|
|
modifier = new SlayEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Speed:
|
|
modifier = new SpeedEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case SpireBlock:
|
|
modifier = new SpireBlockEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Stamina:
|
|
modifier = new StaminaEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case StaminaFull:
|
|
modifier = new StaminaFullEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case StaminaRecoverRate:
|
|
modifier = new StaminaRecoverRateEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Stunned:
|
|
modifier = new StunnedEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case Value:
|
|
modifier = new ValueEffectModifier(this.IDString, modEntry);
|
|
this.value = modifier.minMod;
|
|
Item.addEnchantValue(this.IDString, (int) modifier.minMod);
|
|
break;
|
|
case WeaponProc:
|
|
modifier = new WeaponProcEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case WeaponRange:
|
|
modifier = new WeaponRangeEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
case WeaponSpeed:
|
|
modifier = new WeaponSpeedEffectModifier(this.IDString, modEntry);
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
|
|
if (!EffectsBase.modifiersMap.containsKey(this.IDString))
|
|
EffectsBase.modifiersMap.put(this.IDString, new HashSet<>());
|
|
|
|
EffectsBase.modifiersMap.get(this.IDString).add(modifier);
|
|
}
|
|
}
|
|
|
|
private void loadSourceTypes(ArrayList<String> sources) {
|
|
|
|
if (sources.isEmpty())
|
|
return;
|
|
|
|
if (!EffectsBase.effectSourceTypeMap.containsKey(this.token))
|
|
EffectsBase.effectSourceTypeMap.put(this.token, new HashSet<>());
|
|
|
|
for (String source : sources)
|
|
EffectsBase.effectSourceTypeMap.get(this.token).add(EffectSourceType.GetEffectSourceType(source));
|
|
}
|
|
|
|
public static String getItemEffectsByName(String string) {
|
|
if (EffectsBase.itemEffectsByName.containsKey(string))
|
|
return EffectsBase.itemEffectsByName.get(string);
|
|
return "";
|
|
}
|
|
|
|
public static void addItemEffectsByName(String name, String ID) {
|
|
EffectsBase.itemEffectsByName.put(name, ID);
|
|
}
|
|
|
|
public float getDamageAmount(int trains) {
|
|
if (useRampAdd)
|
|
return (amount + (amountRamp * trains));
|
|
else
|
|
return (amount * (1 + (amountRamp * trains)));
|
|
}
|
|
|
|
// public String getName() {
|
|
// return this.name;
|
|
// }
|
|
|
|
public boolean damageTypeSpecific() {
|
|
|
|
return EffectsBase.EffectDamageTypes.containsKey(this.token);
|
|
|
|
}
|
|
|
|
public boolean containsDamageType(mbEnums.DamageType dt) {
|
|
if (!EffectsBase.EffectDamageTypes.containsKey(this.token))
|
|
return false;
|
|
return EffectsBase.EffectDamageTypes.get(this.token).contains(dt);
|
|
}
|
|
|
|
public int getUUID() {
|
|
return this.UUID;
|
|
}
|
|
|
|
public String getIDString() {
|
|
return this.IDString;
|
|
}
|
|
|
|
public int getToken() {
|
|
return this.token;
|
|
}
|
|
|
|
//For Debugging purposes.
|
|
public void setToken(int token) {
|
|
this.token = token;
|
|
}
|
|
|
|
public ConcurrentHashMap<String, Boolean> getSourceTypes() {
|
|
return this.sourceTypes;
|
|
}
|
|
|
|
public HashSet<AbstractEffectModifier> getModifiers() {
|
|
|
|
if (EffectsBase.modifiersMap.containsKey(this.IDString) == false)
|
|
return EffectsBase.DefaultModifiers;
|
|
|
|
return EffectsBase.modifiersMap.get(this.IDString);
|
|
}
|
|
|
|
public boolean isItemEffect() {
|
|
return this.isItemEffect;
|
|
}
|
|
|
|
public boolean isSpireEffect() {
|
|
return this.isSpireEffect;
|
|
}
|
|
|
|
public boolean ignoreMod() {
|
|
return this.ignoreMod;
|
|
}
|
|
|
|
public boolean dontSave() {
|
|
return this.dontSave;
|
|
}
|
|
|
|
public boolean isPrefix() {
|
|
return this.isPrefix;
|
|
}
|
|
|
|
public boolean isSuffix() {
|
|
return this.isSuffix;
|
|
}
|
|
|
|
public void startEffect(AbstractCharacter source, AbstractWorldObject awo, int trains, AbstractEffectJob effect) {
|
|
|
|
|
|
// Add SourceTypes for dispel
|
|
|
|
if (this.token != 0) {
|
|
if (effect == null) {
|
|
Logger.error("AbstractEffectModifier.applyEffectModifier: missing FinishEffectTimeJob");
|
|
return;
|
|
}
|
|
// AbstractWorldObject source = effect.getSource();
|
|
if (source == null) {
|
|
Logger.error("AbstractEffectModifier.applyEffectModifier: missing source");
|
|
return;
|
|
}
|
|
PowersBase pb = effect.getPower();
|
|
if (pb == null) {
|
|
Logger.error("AbstractEffectModifier.applyEffectModifier: missing power");
|
|
return;
|
|
}
|
|
ActionsBase ab = effect.getAction();
|
|
if (ab == null) {
|
|
Logger.error("AbstractEffectModifier.applyEffectModifier: missing action");
|
|
return;
|
|
}
|
|
|
|
//don't send effect if dead, except for death shroud
|
|
if (!awo.isAlive()) {
|
|
if (pb.getToken() != 1672601862)
|
|
return;
|
|
}
|
|
|
|
|
|
if (!effect.skipSendEffect()) {
|
|
// float duration = (pb.isChant()) ? pb.getChantDuration() * 1000 : ab.getDuration(trains);
|
|
float duration = ab.getDurationInSeconds(trains);
|
|
if (pb.getToken() == 1672601862) {
|
|
|
|
Effect eff = awo.getEffects().get("DeathShroud");
|
|
|
|
|
|
if (eff != null) {
|
|
JobContainer jc = eff.getJobContainer();
|
|
|
|
|
|
if (jc != null) {
|
|
duration = jc.timeOfExection() - System.currentTimeMillis();
|
|
duration *= .001f;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (duration > 0f) {
|
|
int removeToken = this.token;
|
|
ApplyEffectMsg pum = new ApplyEffectMsg();
|
|
if (effect.getAction() != null)
|
|
if (effect.getAction().getPowerAction() != null
|
|
&& PowersManager.ActionTokenByIDString.containsKey(effect.getAction().getPowerAction().getIDString()))
|
|
try {
|
|
removeToken = PowersManager.ActionTokenByIDString.get(effect.getAction().getPowerAction().getIDString());
|
|
} catch (Exception e) {
|
|
removeToken = this.token;
|
|
}
|
|
|
|
pum.setEffectID(removeToken);
|
|
pum.setSourceType(source.getObjectType().ordinal());
|
|
pum.setSourceID(source.getObjectUUID());
|
|
pum.setTargetType(awo.getObjectType().ordinal());
|
|
pum.setTargetID(awo.getObjectUUID());
|
|
pum.setNumTrains(trains);
|
|
pum.setDuration((int) duration);
|
|
// pum.setDuration((pb.isChant()) ? (int)pb.getChantDuration() : ab.getDurationInSeconds(trains));
|
|
pum.setPowerUsedID(pb.getToken());
|
|
pum.setPowerUsedName(pb.getName());
|
|
DispatchManager.sendToAllInRange(awo, pum);
|
|
}
|
|
|
|
if (awo.getObjectType().equals(GameObjectType.Item)) {
|
|
if (source.charItemManager != null) {
|
|
source.charItemManager.updateInventory();
|
|
}
|
|
}
|
|
}
|
|
|
|
// call modifiers to do their job
|
|
if (!effect.skipApplyEffect()) {
|
|
for (AbstractEffectModifier em : this.getModifiers())
|
|
em.applyEffectModifier(source, awo, trains, effect);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Send end effect message to client
|
|
public void endEffect(AbstractWorldObject source, AbstractWorldObject awo, int trains, PowersBase pb, AbstractEffectJob effect) {
|
|
if (awo == null) {
|
|
Logger.error("endEffect(): Null AWO object passed in.");
|
|
return;
|
|
}
|
|
if (pb == null) {
|
|
Logger.error("endEffect(): Null PowerBase object passed in.");
|
|
return;
|
|
}
|
|
if (!effect.skipCancelEffect() && !effect.isNoOverwrite()) {
|
|
|
|
int sendToken = this.token;
|
|
|
|
if (effect.getAction() != null)
|
|
if (effect.getAction().getPowerAction() != null
|
|
&& PowersManager.ActionTokenByIDString.containsKey(effect.getAction().getPowerAction().getIDString()))
|
|
try {
|
|
sendToken = PowersManager.ActionTokenByIDString.get(effect.getAction().getPowerAction().getIDString());
|
|
} catch (Exception e) {
|
|
sendToken = this.token;
|
|
}
|
|
ApplyEffectMsg pum = new ApplyEffectMsg();
|
|
pum.setEffectID(sendToken);
|
|
if (source != null) {
|
|
pum.setSourceType(source.getObjectType().ordinal());
|
|
pum.setSourceID(source.getObjectUUID());
|
|
} else {
|
|
pum.setSourceType(0);
|
|
pum.setSourceID(0);
|
|
}
|
|
pum.setTargetType(awo.getObjectType().ordinal());
|
|
pum.setTargetID(awo.getObjectUUID());
|
|
pum.setUnknown02(2);
|
|
pum.setNumTrains(0);
|
|
pum.setDuration(-1);
|
|
pum.setPowerUsedID(pb.getToken());
|
|
pum.setPowerUsedName(pb.getName());
|
|
DispatchManager.sendToAllInRange(awo, pum);
|
|
|
|
}
|
|
}
|
|
|
|
public void endEffectNoPower(int trains, AbstractEffectJob effect) {
|
|
|
|
AbstractWorldObject source = effect.getSource();
|
|
|
|
if (source == null)
|
|
return;
|
|
|
|
if (!effect.skipCancelEffect() && !effect.isNoOverwrite()) {
|
|
ApplyEffectMsg pum = new ApplyEffectMsg();
|
|
pum.setEffectID(this.token);
|
|
|
|
pum.setSourceType(source.getObjectType().ordinal());
|
|
pum.setSourceID(source.getObjectUUID());
|
|
pum.setTargetType(source.getObjectType().ordinal());
|
|
pum.setTargetID(source.getObjectUUID());
|
|
pum.setUnknown02(2);
|
|
pum.setNumTrains(0);
|
|
pum.setDuration(-1);
|
|
pum.setUnknown06((byte) 1);
|
|
pum.setEffectSourceType(effect.getEffectSourceType());
|
|
pum.setEffectSourceID(effect.getEffectSourceID());
|
|
pum.setPowerUsedID(0);
|
|
pum.setPowerUsedName(this.name);
|
|
|
|
if (source.getObjectType() == GameObjectType.PlayerCharacter) {
|
|
Dispatch dispatch = Dispatch.borrow((PlayerCharacter) source, pum);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void sendEffect(AbstractEffectJob effect, int duration, ClientConnection conn) {
|
|
if (effect == null && conn != null)
|
|
return;
|
|
|
|
if (conn == null)
|
|
return;
|
|
AbstractWorldObject source = effect.getSource();
|
|
AbstractWorldObject awo = effect.getTarget();
|
|
int trains = effect.getTrains();
|
|
if (source == null || awo == null)
|
|
return;
|
|
|
|
if (this.token != 0) {
|
|
PowersBase pb = effect.getPower();
|
|
if (pb == null) {
|
|
Logger.error("AbstractEffectModifier.applyEffectModifier: missing power");
|
|
return;
|
|
}
|
|
ActionsBase ab = effect.getAction();
|
|
if (ab == null) {
|
|
Logger.error("AbstractEffectModifier.applyEffectModifier: missing action");
|
|
return;
|
|
}
|
|
|
|
//don't send effect if dead, except for death shroud
|
|
if (!awo.isAlive()) {
|
|
if (pb.getToken() != 1672601862)
|
|
return;
|
|
}
|
|
|
|
//duration for damage over times is (total time - (number of ticks x 5 seconds per tick))
|
|
if (effect instanceof DamageOverTimeJob)
|
|
duration = ((DamageOverTimeJob) effect).getTickLength();
|
|
|
|
// float dur = (pb.isChant()) ? pb.getChantDuration() * 1000 : ab.getDuration(trains);
|
|
float dur = ab.getDuration(trains);
|
|
if (dur > 0f) {
|
|
ApplyEffectMsg pum = new ApplyEffectMsg();
|
|
pum.setEffectID(this.token);
|
|
pum.setSourceType(source.getObjectType().ordinal());
|
|
pum.setSourceID(source.getObjectUUID());
|
|
pum.setTargetType(awo.getObjectType().ordinal());
|
|
pum.setTargetID(awo.getObjectUUID());
|
|
pum.setNumTrains(trains);
|
|
pum.setDuration(duration);
|
|
pum.setPowerUsedID(pb.getToken());
|
|
pum.setPowerUsedName(pb.getName());
|
|
|
|
Dispatch dispatch = Dispatch.borrow(conn.getPlayerCharacter(), pum);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
public void sendEffectNoPower(AbstractEffectJob effect, int duration, ClientConnection conn) {
|
|
|
|
if (effect == null && conn != null)
|
|
return;
|
|
|
|
if (conn == null)
|
|
return;
|
|
|
|
AbstractWorldObject source = effect.getSource();
|
|
AbstractWorldObject awo = effect.getTarget();
|
|
int trains = effect.getTrains();
|
|
|
|
if (source == null || awo == null)
|
|
return;
|
|
|
|
if (this.token != 0) {
|
|
//don't send effect if dead, except for death shroud
|
|
if (!awo.isAlive()) {
|
|
return;
|
|
}
|
|
|
|
//duration for damage over times is (total time - (number of ticks x 5 seconds per tick))
|
|
if (effect instanceof DamageOverTimeJob)
|
|
duration = ((DamageOverTimeJob) effect).getTickLength();
|
|
else if (effect instanceof FinishSpireEffectJob)
|
|
duration = 45;
|
|
else if (effect instanceof NoTimeJob)
|
|
duration = -1;
|
|
|
|
// float dur = (pb.isChant()) ? pb.getChantDuration() * 1000 : ab.getDuration(trains);
|
|
|
|
ApplyEffectMsg pum = new ApplyEffectMsg();
|
|
pum.setEffectID(this.token);
|
|
pum.setSourceType(source.getObjectType().ordinal());
|
|
pum.setSourceID(source.getObjectUUID());
|
|
pum.setTargetType(source.getObjectType().ordinal());
|
|
pum.setTargetID(source.getObjectUUID());
|
|
pum.setUnknown06((byte) 1);
|
|
pum.setEffectSourceType(effect.getEffectSourceType());
|
|
pum.setEffectSourceID(effect.getEffectSourceID());
|
|
pum.setNumTrains(trains);
|
|
pum.setDuration(duration);
|
|
pum.setPowerUsedID(0);
|
|
pum.setPowerUsedName(this.name);
|
|
|
|
Dispatch dispatch = Dispatch.borrow(conn.getPlayerCharacter(), pum);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
|
|
|
|
}
|
|
}
|
|
|
|
public boolean containsSource(EffectSourceType sourceType) {
|
|
if (EffectsBase.effectSourceTypeMap.containsKey(this.token) == false)
|
|
return false;
|
|
return EffectsBase.effectSourceTypeMap.get(this.token).contains(sourceType);
|
|
|
|
}
|
|
|
|
public boolean cancelOnAttack() {
|
|
return this.cancelOnAttack;
|
|
}
|
|
|
|
public boolean cancelOnAttackSwing() {
|
|
return this.cancelOnAttackSwing;
|
|
}
|
|
|
|
public boolean cancelOnCast() {
|
|
return this.cancelOnCast;
|
|
}
|
|
|
|
public boolean cancelOnCastSpell() {
|
|
return this.cancelOnCastSpell;
|
|
}
|
|
|
|
public boolean cancelOnEquipChange() {
|
|
return this.cancelOnEquipChange;
|
|
}
|
|
|
|
public boolean cancelOnLogout() {
|
|
return this.cancelOnLogout;
|
|
}
|
|
|
|
public boolean cancelOnMove() {
|
|
return this.cancelOnMove;
|
|
}
|
|
|
|
public boolean cancelOnNewCharm() {
|
|
return this.cancelOnNewCharm;
|
|
}
|
|
|
|
public boolean cancelOnSit() {
|
|
return this.cancelOnSit;
|
|
}
|
|
|
|
public boolean cancelOnTakeDamage() {
|
|
return this.cancelOnTakeDamage;
|
|
}
|
|
|
|
public boolean cancelOnTerritoryClaim() {
|
|
return this.cancelOnTerritoryClaim;
|
|
}
|
|
|
|
public boolean cancelOnUnEquip() {
|
|
return this.cancelOnUnEquip;
|
|
}
|
|
|
|
public String getDamageTypes() {
|
|
String text = "";
|
|
if (!EffectsBase.EffectDamageTypes.containsKey(this.token))
|
|
return text;
|
|
for (mbEnums.DamageType type : EffectsBase.EffectDamageTypes.get(this.token)) {
|
|
text += type.name() + ' ';
|
|
}
|
|
return text;
|
|
}
|
|
|
|
public String getName() {
|
|
|
|
return name;
|
|
}
|
|
|
|
public void setName(String name) {
|
|
this.name = name;
|
|
}
|
|
|
|
public float getValue() {
|
|
return value;
|
|
}
|
|
|
|
public void setValue(float Value) {
|
|
this.value = Value;
|
|
}
|
|
|
|
}
|