You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
491 lines
17 KiB
491 lines
17 KiB
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . |
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· |
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ |
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ |
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ |
|
// Magicbane Emulator Project © 2013 - 2022 |
|
// www.magicbane.com |
|
|
|
|
|
package engine.objects; |
|
|
|
import engine.gameManager.ChatManager; |
|
import engine.gameManager.ConfigManager; |
|
import engine.gameManager.PowersManager; |
|
import engine.mbEnums; |
|
import engine.mbEnums.ModType; |
|
import engine.mbEnums.SourceType; |
|
import engine.powers.DamageShield; |
|
import engine.powers.EffectsBase; |
|
import engine.powers.effectmodifiers.AbstractEffectModifier; |
|
|
|
import java.util.HashMap; |
|
import java.util.HashSet; |
|
import java.util.concurrent.ConcurrentHashMap; |
|
|
|
|
|
public class PlayerBonuses { |
|
|
|
//First bonus set |
|
ConcurrentHashMap<AbstractEffectModifier, Float> bonusFloats = new ConcurrentHashMap<>(); |
|
private ConcurrentHashMap<AbstractEffectModifier, DamageShield> bonusDamageShields = new ConcurrentHashMap<>(); |
|
private ConcurrentHashMap<AbstractEffectModifier, String> bonusStrings = new ConcurrentHashMap<>(); |
|
private ConcurrentHashMap<ModType, HashSet<SourceType>> bonusLists = new ConcurrentHashMap<>(); |
|
private ConcurrentHashMap<ModType, HashMap<SourceType, Boolean>> bonusBools = new ConcurrentHashMap<>(); |
|
private ConcurrentHashMap<SourceType, Float> skillBonuses = new ConcurrentHashMap<>(); |
|
private ConcurrentHashMap<ModType, Float> regens = new ConcurrentHashMap<>(); |
|
|
|
//If active == 0 then all gets come from the A list and all puts go to the B list |
|
//If active == 1 then all gets come from the B list and all puts go to the A list |
|
//They alternate each time bonuses are calculated so the one being updated isn't read from. |
|
|
|
|
|
/** |
|
* Generic Constructor |
|
*/ |
|
public PlayerBonuses(PlayerCharacter pc) { |
|
} |
|
|
|
public PlayerBonuses(Mob mob) { |
|
clearRuneBaseEffects(); |
|
} |
|
|
|
public static void InitializeBonuses(PlayerCharacter player) { |
|
if (player.bonuses == null) |
|
return; |
|
if (ConfigManager.serverType.equals(mbEnums.ServerType.LOGINSERVER)) |
|
return; |
|
|
|
player.bonuses.calculateRuneBaseEffects(player); |
|
} |
|
|
|
public static PlayerBonuses grantBonuses(AbstractCharacter ac) { |
|
|
|
if (ac.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) |
|
return new PlayerBonuses((PlayerCharacter) ac); |
|
else if (ac.getObjectType().equals(mbEnums.GameObjectType.Mob)) |
|
return new PlayerBonuses((Mob) ac); |
|
else |
|
return null; |
|
} |
|
|
|
public void clearRuneBaseEffects() { |
|
|
|
this.bonusBools.clear(); |
|
this.bonusFloats.clear(); |
|
this.bonusStrings.clear(); |
|
this.bonusDamageShields.clear(); |
|
this.bonusLists.clear(); |
|
this.skillBonuses.clear(); |
|
this.regens.put(ModType.HealthRecoverRate, (float) 1); |
|
this.regens.put(ModType.ManaRecoverRate, (float) 1); |
|
this.regens.put(ModType.StaminaRecoverRate, (float) 1); |
|
} |
|
|
|
|
|
public void calculateRuneBaseEffects(PlayerCharacter pc) { |
|
//Clear everything |
|
clearRuneBaseEffects(); |
|
|
|
//recalculate race |
|
|
|
|
|
if (pc.race != null) { |
|
|
|
|
|
if (pc.race.getEffectsList() != null) |
|
for (MobBaseEffects raceEffect : pc.race.getEffectsList()) { |
|
EffectsBase eb = PowersManager.getEffectByToken(raceEffect.getToken()); |
|
|
|
if (eb == null) |
|
continue; |
|
if (pc.getLevel() < raceEffect.getReqLvl()) |
|
continue; |
|
for (AbstractEffectModifier modifier : eb.getModifiers()) { |
|
modifier.applyBonus(pc, raceEffect.getRank()); |
|
} |
|
|
|
} |
|
|
|
if (SkillsBase.runeSkillsCache.containsKey(pc.getRaceID())) { |
|
for (int skillToken : SkillsBase.runeSkillsCache.get(pc.getRaceID()).keySet()) { |
|
float amount = SkillsBase.runeSkillsCache.get(pc.getRaceID()).get(skillToken); |
|
|
|
SkillsBase sb = SkillsBase.tokenCache.get(skillToken); |
|
|
|
if (sb == null) |
|
continue; |
|
if (this.skillBonuses.containsKey(sb.sourceType) == false) |
|
this.skillBonuses.put(sb.sourceType, amount); |
|
else |
|
this.skillBonuses.put(sb.sourceType, this.skillBonuses.get(sb.sourceType) + amount); |
|
|
|
} |
|
} |
|
} |
|
|
|
//calculate baseclass effects |
|
if (pc.baseClass != null) { |
|
|
|
if (pc.baseClass.getEffectsList() != null) |
|
for (MobBaseEffects classEffect : pc.baseClass.getEffectsList()) { |
|
EffectsBase eb = PowersManager.getEffectByToken(classEffect.getToken()); |
|
|
|
if (eb == null) |
|
continue; |
|
if (pc.getLevel() < classEffect.getReqLvl()) |
|
continue; |
|
for (AbstractEffectModifier modifier : eb.getModifiers()) { |
|
modifier.applyBonus(pc, classEffect.getRank()); |
|
} |
|
|
|
} |
|
|
|
if (SkillsBase.runeSkillsCache.containsKey(pc.getBaseClassID())) { |
|
for (int skillToken : SkillsBase.runeSkillsCache.get(pc.getBaseClassID()).keySet()) { |
|
float amount = SkillsBase.runeSkillsCache.get(pc.getBaseClassID()).get(skillToken); |
|
|
|
SkillsBase sb = SkillsBase.tokenCache.get(skillToken); |
|
|
|
if (sb == null) |
|
continue; |
|
if (this.skillBonuses.containsKey(sb.sourceType) == false) |
|
this.skillBonuses.put(sb.sourceType, amount); |
|
else |
|
this.skillBonuses.put(sb.sourceType, this.skillBonuses.get(sb.sourceType) + amount); |
|
} |
|
} |
|
|
|
} |
|
|
|
//calculate promotionClass Effects |
|
if (pc.getPromotionClass() != null) { |
|
if (pc.getPromotionClass().getEffectsList() != null) |
|
for (MobBaseEffects promoEffect : pc.getPromotionClass().getEffectsList()) { |
|
EffectsBase eb = PowersManager.getEffectByToken(promoEffect.getToken()); |
|
|
|
if (eb == null) |
|
continue; |
|
if (pc.getLevel() < promoEffect.getReqLvl()) |
|
continue; |
|
for (AbstractEffectModifier modifier : eb.getModifiers()) { |
|
modifier.applyBonus(pc, promoEffect.getRank()); |
|
} |
|
|
|
} |
|
|
|
if (SkillsBase.runeSkillsCache.containsKey(pc.getPromotionClassID())) { |
|
for (int skillToken : SkillsBase.runeSkillsCache.get(pc.getPromotionClassID()).keySet()) { |
|
float amount = SkillsBase.runeSkillsCache.get(pc.getPromotionClassID()).get(skillToken); |
|
|
|
SkillsBase sb = SkillsBase.tokenCache.get(skillToken); |
|
|
|
if (sb == null) |
|
continue; |
|
if (this.skillBonuses.containsKey(sb.sourceType) == false) |
|
this.skillBonuses.put(sb.sourceType, amount); |
|
else |
|
this.skillBonuses.put(sb.sourceType, this.skillBonuses.get(sb.sourceType) + amount); |
|
|
|
} |
|
} |
|
|
|
} |
|
|
|
for (CharacterRune runes : pc.getRunes()) { |
|
RuneBase characterRune = RuneBase.getRuneBase(runes.getRuneBaseID()); |
|
|
|
if (characterRune.getEffectsList() != null) |
|
for (MobBaseEffects runeEffect : characterRune.getEffectsList()) { |
|
EffectsBase eb = PowersManager.getEffectByToken(runeEffect.getToken()); |
|
|
|
if (eb == null) |
|
continue; |
|
if (pc.getLevel() < runeEffect.getReqLvl()) |
|
continue; |
|
for (AbstractEffectModifier modifier : eb.getModifiers()) { |
|
modifier.applyBonus(pc, runeEffect.getRank()); |
|
} |
|
|
|
} |
|
|
|
if (SkillsBase.runeSkillsCache.containsKey(runes.getRuneBaseID())) { |
|
for (int skillToken : SkillsBase.runeSkillsCache.get(runes.getRuneBaseID()).keySet()) { |
|
float amount = SkillsBase.runeSkillsCache.get(runes.getRuneBaseID()).get(skillToken); |
|
|
|
SkillsBase sb = SkillsBase.tokenCache.get(skillToken); |
|
|
|
if (sb == null) |
|
continue; |
|
if (this.skillBonuses.containsKey(sb.sourceType) == false) |
|
this.skillBonuses.put(sb.sourceType, amount); |
|
else |
|
this.skillBonuses.put(sb.sourceType, this.skillBonuses.get(sb.sourceType) + amount); |
|
|
|
} |
|
} |
|
|
|
} |
|
|
|
//Update seeInvis if needed |
|
|
|
float seeInvis = this.getFloat(ModType.SeeInvisible, SourceType.None); |
|
if (pc.getSeeInvis() < seeInvis) |
|
pc.setSeeInvis((short) seeInvis); |
|
|
|
} |
|
|
|
|
|
public void grantEffect(RuneBaseEffect rbe) { |
|
} |
|
|
|
|
|
public void setFloat(AbstractEffectModifier mod, float val) { |
|
if (val != 0) |
|
this.bonusFloats.put(mod, val); |
|
else |
|
this.bonusFloats.remove(mod); |
|
} |
|
|
|
public void setString(AbstractEffectModifier mod, String val) { |
|
if (!val.isEmpty()) |
|
this.bonusStrings.put(mod, val); |
|
else |
|
this.bonusStrings.remove(mod); |
|
} |
|
|
|
public void setList(ModType mod, HashSet<SourceType> val) { |
|
if (!val.equals(null)) |
|
this.bonusLists.put(mod, val); |
|
else |
|
this.bonusLists.remove(mod); |
|
} |
|
|
|
|
|
public void addFloat(AbstractEffectModifier mod, Float val) { |
|
if (this.bonusFloats.containsKey(mod) == false) |
|
this.bonusFloats.put(mod, val); |
|
else |
|
this.bonusFloats.put(mod, this.bonusFloats.get(mod) + val); |
|
} |
|
|
|
public void multFloat(AbstractEffectModifier mod, Float val) { |
|
if (this.bonusFloats.containsKey(mod) == false) |
|
this.bonusFloats.put(mod, val); |
|
else |
|
this.bonusFloats.put(mod, this.bonusFloats.get(mod) + (val * (this.bonusFloats.get(mod) + val))); |
|
} |
|
|
|
public void multRegen(ModType mod, Float val) { |
|
this.regens.put(mod, this.regens.get(mod) + (this.regens.get(mod) * val)); |
|
} |
|
|
|
|
|
public boolean getBool(ModType modType, SourceType sourceType) { |
|
|
|
if (this.bonusBools.containsKey(modType) == false) |
|
return false; |
|
|
|
if (this.bonusBools.get(modType).containsKey(sourceType) == false) |
|
return false; |
|
|
|
return this.bonusBools.get(modType).get(sourceType); |
|
|
|
} |
|
|
|
public float getSkillBonus(SourceType sourceType) { |
|
|
|
if (this.skillBonuses.containsKey(sourceType) == false) |
|
return 0; |
|
return this.skillBonuses.get(sourceType); |
|
} |
|
|
|
|
|
public float getFloat(ModType modType, SourceType sourceType) { |
|
float amount = 0; |
|
for (AbstractEffectModifier mod : this.bonusFloats.keySet()) { |
|
if (mod.getPercentMod() != 0) |
|
continue; |
|
if (mod.modType.equals(modType) == false || mod.sourceType.equals(sourceType) == false) |
|
continue; |
|
|
|
if (this.bonusFloats.get(mod) == null) |
|
continue; |
|
|
|
amount += this.bonusFloats.get(mod); |
|
} |
|
return amount; |
|
} |
|
|
|
public float getFloatPercentPositive(ModType modType, SourceType sourceType) { |
|
float amount = 0; |
|
for (AbstractEffectModifier mod : this.bonusFloats.keySet()) { |
|
|
|
if (mod.getPercentMod() == 0 && !modType.equals(ModType.AdjustAboveDmgCap)) |
|
continue; |
|
|
|
|
|
if (mod.modType.equals(modType) == false || mod.sourceType.equals(sourceType) == false) |
|
continue; |
|
|
|
|
|
if (this.bonusFloats.get(mod) == null) |
|
continue; |
|
|
|
if (this.bonusFloats.get(mod) < 0) |
|
continue; |
|
amount += this.bonusFloats.get(mod); |
|
} |
|
|
|
return amount; |
|
} |
|
|
|
public float getFloatPercentAll(ModType modType, SourceType sourceType) { |
|
float amount = 0; |
|
for (AbstractEffectModifier mod : this.bonusFloats.keySet()) { |
|
|
|
if (mod.getPercentMod() == 0 && !modType.equals(ModType.AdjustAboveDmgCap)) |
|
continue; |
|
|
|
|
|
if (mod.modType.equals(modType) == false || mod.sourceType.equals(sourceType) == false) |
|
continue; |
|
|
|
if (this.bonusFloats.get(mod) == null) |
|
continue; |
|
|
|
amount += this.bonusFloats.get(mod); |
|
} |
|
|
|
return amount; |
|
} |
|
|
|
public float getRegen(ModType modType) { |
|
return this.regens.get(modType); |
|
} |
|
|
|
|
|
public float getFloatPercentNullZero(ModType modType, SourceType sourceType) { |
|
float amount = 0; |
|
for (AbstractEffectModifier mod : this.bonusFloats.keySet()) { |
|
|
|
if (mod.getPercentMod() == 0) |
|
continue; |
|
if (mod.modType.equals(modType) == false || mod.sourceType.equals(sourceType) == false) |
|
continue; |
|
|
|
if (this.bonusFloats.get(mod) == null) |
|
continue; |
|
|
|
amount += this.bonusFloats.get(mod); |
|
} |
|
return amount; |
|
} |
|
|
|
public float getFloatPercentNegative(ModType modType, SourceType sourceType) { |
|
float amount = 0; |
|
for (AbstractEffectModifier mod : this.bonusFloats.keySet()) { |
|
|
|
if (mod.getPercentMod() == 0) |
|
continue; |
|
if (mod.modType.equals(modType) == false || mod.sourceType.equals(sourceType) == false) |
|
continue; |
|
|
|
if (this.bonusFloats.get(mod) == null) |
|
continue; |
|
|
|
if (this.bonusFloats.get(mod) > 0) |
|
continue; |
|
|
|
|
|
amount += this.bonusFloats.get(mod); |
|
} |
|
return amount; |
|
} |
|
|
|
|
|
public HashSet<SourceType> getList(ModType modType) { |
|
if (this.bonusLists.containsKey(modType)) |
|
return this.bonusLists.get(modType); |
|
else |
|
return null; |
|
} |
|
|
|
public ConcurrentHashMap<AbstractEffectModifier, DamageShield> getDamageShields() { |
|
return this.bonusDamageShields; |
|
} |
|
|
|
public void addDamageShield(AbstractEffectModifier mod, DamageShield ds) { |
|
this.bonusDamageShields.put(mod, ds); |
|
} |
|
|
|
|
|
public void updateIfHigher(AbstractEffectModifier mod, Float val) { |
|
|
|
if (this.bonusFloats.containsKey(mod) == false) { |
|
this.bonusFloats.put(mod, val); |
|
return; |
|
} |
|
float oldVal = this.getFloat(mod.modType, mod.sourceType); |
|
|
|
if (oldVal > val) |
|
return; |
|
|
|
this.bonusFloats.put(mod, val); |
|
|
|
} |
|
|
|
|
|
//Read maps |
|
|
|
public void printBonusesToClient(PlayerCharacter pc) { |
|
|
|
|
|
for (ModType modType : this.bonusBools.keySet()) { |
|
for (SourceType sourceType : this.bonusBools.get(modType).keySet()) { |
|
ChatManager.chatSystemInfo(pc, modType.name() + "-" + sourceType.name() + " = " + this.bonusBools.get(modType).get(sourceType)); |
|
} |
|
} |
|
|
|
for (ModType modType : ModType.values()) { |
|
|
|
if (modType.equals(ModType.StaminaRecoverRate) || modType.equals(ModType.HealthRecoverRate) || modType.equals(ModType.ManaRecoverRate)) |
|
ChatManager.chatSystemInfo(pc, modType.name() + " = " + this.getRegen(modType)); |
|
else |
|
for (SourceType sourceType : SourceType.values()) { |
|
float amount = this.getFloat(modType, sourceType); |
|
float percentAmount = this.getFloatPercentPositive(modType, sourceType); |
|
float percentAmountNegative = this.getFloatPercentNegative(modType, sourceType); |
|
|
|
if (amount != 0) |
|
ChatManager.chatSystemInfo(pc, modType.name() + "-" + (sourceType.equals(SourceType.None) == false ? sourceType.name() : "") + " = " + amount); |
|
|
|
if (percentAmount != 0) |
|
ChatManager.chatSystemInfo(pc, "Percent : " + modType.name() + "-" + (sourceType.equals(SourceType.None) == false ? sourceType.name() : "") + " = " + percentAmount); |
|
|
|
if (percentAmountNegative != 0) |
|
ChatManager.chatSystemInfo(pc, "Negative Percent : " + modType.name() + "-" + (sourceType.equals(SourceType.None) == false ? sourceType.name() : "") + " = " + percentAmountNegative); |
|
|
|
} |
|
} |
|
|
|
} |
|
|
|
|
|
public void setBool(ModType modType, SourceType sourceType, boolean val) { |
|
if (val == true) { |
|
|
|
if (this.bonusBools.get(modType) == null) { |
|
HashMap<SourceType, Boolean> sourceMap = new HashMap<>(); |
|
this.bonusBools.put(modType, sourceMap); |
|
} |
|
|
|
this.bonusBools.get(modType).put(sourceType, val); |
|
return; |
|
} |
|
|
|
if (this.bonusBools.containsKey(modType)) |
|
this.bonusBools.get(modType).remove(sourceType); |
|
} |
|
|
|
}
|
|
|