forked from MagicBane/Server
Effects, their fail conditions and source types come from EffectTemplate. IDs are assigned at boot in file order. The power actions that the server also keys as effects (item enchantment parents and the action tokens sent in effect messages) are built from the ApplyEffect/ApplyEffects/Invis actions with no Effects.cfg block: 776 keys, the 712 old registry rows plus 64 such as BRD-014A, which live also sent. Value changes (cfg wins): BRD-016A/PRS-031A lose the Chant source, RUC-002A..004A lose Buff/Effect, and PRS-031A/RNG-037A no longer break on Attack. Effect modifiers still load from the DB. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
804 lines
29 KiB
Java
804 lines
29 KiB
Java
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
|
// Magicbane Emulator Project © 2013 - 2026
|
|
// https://www.magicbane.com
|
|
|
|
|
|
package engine.powers;
|
|
|
|
import engine.gameManager.DbManager;
|
|
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.PlayerCharacter;
|
|
import engine.parsers.objects.wpak.CurveRamp;
|
|
import engine.parsers.objects.wpak.EffectTemplate;
|
|
import engine.parsers.objects.wpak.PowerActionTemplate;
|
|
import engine.powers.effectmodifiers.AbstractEffectModifier;
|
|
import engine.server.MBServerStatics;
|
|
import engine.util.Hasher;
|
|
import org.pmw.tinylog.Logger;
|
|
|
|
import java.sql.Connection;
|
|
import java.sql.PreparedStatement;
|
|
import java.sql.ResultSet;
|
|
import java.sql.SQLException;
|
|
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() {
|
|
|
|
}
|
|
|
|
/**
|
|
* ResultSet Constructor
|
|
*/
|
|
public EffectsBase(ResultSet rs) throws SQLException {
|
|
|
|
this.UUID = rs.getInt("ID");
|
|
this.IDString = rs.getString("IDString");
|
|
this.name = rs.getString("name");
|
|
this.token = rs.getInt("Token");
|
|
|
|
//override tokens for some effects like Safemode that use the Action Token instead of the effect Token,
|
|
switch (this.IDString) {
|
|
case "INVIS-D":
|
|
this.token = -1661751254;
|
|
break;
|
|
case "SafeMode":
|
|
this.token = -1661750486;
|
|
break;
|
|
|
|
}
|
|
int flags = rs.getInt("flags");
|
|
this.isItemEffect = ((flags & 1) != 0) ? true : false;
|
|
this.isSpireEffect = ((flags & 2) != 0) ? true : false;
|
|
this.ignoreMod = ((flags & 4) != 0) ? true : false;
|
|
this.dontSave = ((flags & 8) != 0) ? true : false;
|
|
|
|
if (this.IDString.startsWith("PRE-"))
|
|
this.isPrefix = true;
|
|
else if (this.IDString.startsWith("SUF-"))
|
|
this.isSuffix = true;
|
|
// getFailConditions();
|
|
}
|
|
|
|
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-");
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
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 void getFailConditions(HashMap<String, EffectsBase> effects) {
|
|
|
|
try (Connection connection = DbManager.getConnection();
|
|
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM static_power_failcondition WHERE powerOrEffect = 'Effect';")) {
|
|
|
|
ResultSet rs = preparedStatement.executeQuery();
|
|
|
|
PowerFailCondition failCondition = null;
|
|
|
|
while (rs.next()) {
|
|
String fail = rs.getString("type");
|
|
|
|
|
|
String IDString = rs.getString("IDString");
|
|
failCondition = PowerFailCondition.valueOf(fail);
|
|
|
|
if (failCondition == null) {
|
|
Logger.error("Couldn't Find FailCondition " + fail + " for " + IDString);
|
|
continue;
|
|
}
|
|
|
|
if (EffectsBase.EffectFailConditions.get(IDString) == null) {
|
|
EffectsBase.EffectFailConditions.put(IDString, new HashSet<>());
|
|
}
|
|
|
|
EffectsBase.EffectFailConditions.get(IDString).add(failCondition);
|
|
EffectsBase eb = effects.get(IDString);
|
|
|
|
switch (failCondition) {
|
|
|
|
case TakeDamage:
|
|
|
|
// dont go any further.
|
|
|
|
if (eb == null)
|
|
break;
|
|
|
|
eb.cancelOnTakeDamage = true;
|
|
|
|
|
|
eb.amount = rs.getFloat("amount");
|
|
eb.amountRamp = rs.getFloat("ramp");
|
|
eb.useRampAdd = rs.getBoolean("UseAddFormula");
|
|
|
|
String damageType1 = rs.getString("damageType1");
|
|
String damageType2 = rs.getString("damageType2");
|
|
String damageType3 = rs.getString("damageType3");
|
|
|
|
if (damageType1.isEmpty() && damageType2.isEmpty() && damageType3.isEmpty())
|
|
break;
|
|
|
|
if (!EffectsBase.EffectDamageTypes.containsKey(eb.getToken()))
|
|
EffectsBase.EffectDamageTypes.put(eb.getToken(), new HashSet<>());
|
|
|
|
mbEnums.DamageType dt = mbEnums.DamageType.getDamageType(damageType1);
|
|
if (dt != null)
|
|
EffectsBase.EffectDamageTypes.get(eb.token).add(dt);
|
|
|
|
dt = mbEnums.DamageType.getDamageType(damageType2);
|
|
if (dt != null)
|
|
EffectsBase.EffectDamageTypes.get(eb.token).add(dt);
|
|
dt = mbEnums.DamageType.getDamageType(damageType3);
|
|
if (dt != null)
|
|
EffectsBase.EffectDamageTypes.get(eb.token).add(dt);
|
|
break;
|
|
case Attack:
|
|
eb.cancelOnAttack = true;
|
|
break;
|
|
case AttackSwing:
|
|
eb.cancelOnAttackSwing = true;
|
|
break;
|
|
case Cast:
|
|
eb.cancelOnCast = true;
|
|
break;
|
|
case CastSpell:
|
|
eb.cancelOnCastSpell = true;
|
|
break;
|
|
case EquipChange:
|
|
eb.cancelOnEquipChange = true;
|
|
break;
|
|
case Logout:
|
|
eb.cancelOnLogout = true;
|
|
break;
|
|
case Move:
|
|
eb.cancelOnMove = true;
|
|
break;
|
|
case NewCharm:
|
|
eb.cancelOnNewCharm = true;
|
|
break;
|
|
case Sit:
|
|
eb.cancelOnSit = true;
|
|
break;
|
|
case TerritoryClaim:
|
|
eb.cancelOnTerritoryClaim = true;
|
|
break;
|
|
case UnEquip:
|
|
eb.cancelOnUnEquip = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
rs.close();
|
|
} catch (Exception e) {
|
|
Logger.error(e);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
}
|