Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions game-server/src/com/aionemu/gameserver/model/siege/Influence.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,26 +89,23 @@ public Set<Integer> getInfluenceRelevantWorldIds() {
}

/**
* @return float containing dmg modifier for disadvantaged race
* @return int containing dmg modifier for disadvantaged race
*/
public float getPvpRaceBonus(Race attRace) {
switch (attRace) {
case ASMODIANS:
return calculatePvpRaceBonus(getAsmodianInfluenceRate(), getElyosInfluenceRate());
case ELYOS:
return calculatePvpRaceBonus(getElyosInfluenceRate(), getAsmodianInfluenceRate());
default:
return 1f;
}
public int getPvpRaceBonusRatio(Race attRace) {
return switch (attRace) {
case ASMODIANS -> calculatePvpRaceBonusRatio(getAsmodianInfluenceRate(), getElyosInfluenceRate());
case ELYOS -> calculatePvpRaceBonusRatio(getElyosInfluenceRate(), getAsmodianInfluenceRate());
default -> 0;
};
}

private float calculatePvpRaceBonus(float ownInfluence, float enemyInfluence) {
private int calculatePvpRaceBonusRatio(float ownInfluence, float enemyInfluence) {
if (enemyInfluence >= 0.81f && ownInfluence <= 0.10f)
return 1.2f;
return 200;
else if (enemyInfluence >= 0.81f || (enemyInfluence >= 0.71f && ownInfluence <= 0.10f))
return 1.15f;
return 150;
else if (enemyInfluence >= 0.71f)
return 1.1f;
return 1f;
return 100;
return 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import com.aionemu.gameserver.model.gameobjects.Creature;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.stats.container.CombatMode;
import com.aionemu.gameserver.model.stats.container.RatioType;
import com.aionemu.gameserver.model.stats.container.StatEnum;

/**
Expand Down Expand Up @@ -57,6 +59,26 @@ private static void calculate(Stat2 stat2, int lowerCap, int upperCap) {
}
}

public static int limitValueForPvpOrPveStat(CombatMode mode, RatioType type, int value) {
// Note: PvP/PvE ratio caps are symmetric:
// - attack min is fixed, defense max is fixed
// - upper/lower bounds depend on combat mode
Cap cap = switch (mode) {
case PVP -> switch (type) {
case ATTACK -> new Cap(-900, 1000);
case DEFENSE -> new Cap(-1000, 900);
};
case PVE -> switch (type) {
case ATTACK -> new Cap(-900, 5000);
case DEFENSE -> new Cap(-5000, 900);
};
};

return Math.min(cap.max(), Math.max(cap.min(), value));
}

private record Cap(int min, int max) {}

private static class StatLimits {

private final int lowerCap;
Expand Down Expand Up @@ -111,9 +133,6 @@ private static int upperCapFor(StatEnum stat) {
case FLY_SPEED:
value = 16000;
break;
case PVP_DEFEND_RATIO:
value = 900;
break;
case HEAL_BOOST:
value = 1000;
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.aionemu.gameserver.model.stats.container;

public enum CombatMode {
PVP, PVE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.aionemu.gameserver.model.stats.container;

public enum RatioType {
ATTACK, DEFENSE
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.ArrayList;
import java.util.List;

import com.aionemu.gameserver.model.stats.container.*;

import org.apache.commons.lang3.ArrayUtils;

import com.aionemu.commons.utils.Rnd;
Expand All @@ -19,9 +21,6 @@
import com.aionemu.gameserver.model.siege.Influence;
import com.aionemu.gameserver.model.stats.calc.Stat2;
import com.aionemu.gameserver.model.stats.calc.StatCapUtil;
import com.aionemu.gameserver.model.stats.container.CreatureGameStats;
import com.aionemu.gameserver.model.stats.container.PlayerGameStats;
import com.aionemu.gameserver.model.stats.container.StatEnum;
import com.aionemu.gameserver.model.templates.item.WeaponStats;
import com.aionemu.gameserver.model.templates.item.enums.ItemSubType;
import com.aionemu.gameserver.model.templates.npc.NpcRating;
Expand Down Expand Up @@ -445,46 +444,54 @@ public static int getApNpcRating(NpcRating npcRating) {
*/
public static float adjustDamageByPvpOrPveModifiers(Creature attacker, Creature target, float baseDamage, int pvpDamage, boolean useTemplateDmg,
SkillElement element) {
float attackBonus = 1;
float defenseBonus = 1;
int attackBonus = 0;
int defenseBonus = 0;
float damage = baseDamage;
if (attacker.isPvpTarget(target)) {
boolean pvpTarget = attacker.isPvpTarget(target);
if (pvpTarget) {
if (pvpDamage > 0)
damage *= pvpDamage * 0.01f;
damage *= 0.42f; // PVP modifier 42%, last checked on NA (4.9) 19.03.2016
if (!useTemplateDmg) {
attackBonus = attacker.getGameStats().getStat(StatEnum.PVP_ATTACK_RATIO, 0).getCurrent();
defenseBonus = target.getGameStats().getStat(StatEnum.PVP_DEFEND_RATIO, 0).getCurrent();
if (attacker.getRace() != target.getRace() && !attacker.isInInstance())
damage *= Influence.getInstance().getPvpRaceBonus(attacker.getRace());

attackBonus = attacker.getGameStats().getStat(StatEnum.PVP_ATTACK_RATIO, 0).getCurrent() * 0.001f;
defenseBonus = target.getGameStats().getStat(StatEnum.PVP_DEFEND_RATIO, 0).getCurrent() * 0.001f;
attackBonus += Influence.getInstance().getPvpRaceBonusRatio(attacker.getRace());
switch (element) {
case NONE:
attackBonus += attacker.getGameStats().getStat(StatEnum.PVP_ATTACK_RATIO_PHYSICAL, 0).getCurrent() * 0.001f;
defenseBonus += target.getGameStats().getStat(StatEnum.PVP_DEFEND_RATIO_PHYSICAL, 0).getCurrent() * 0.001f;
attackBonus += attacker.getGameStats().getStat(StatEnum.PVP_ATTACK_RATIO_PHYSICAL, 0).getCurrent();
defenseBonus += target.getGameStats().getStat(StatEnum.PVP_DEFEND_RATIO_PHYSICAL, 0).getCurrent();
break;
default:
attackBonus += attacker.getGameStats().getStat(StatEnum.PVP_ATTACK_RATIO_MAGICAL, 0).getCurrent() * 0.001f;
defenseBonus += target.getGameStats().getStat(StatEnum.PVP_DEFEND_RATIO_MAGICAL, 0).getCurrent() * 0.001f;
attackBonus += attacker.getGameStats().getStat(StatEnum.PVP_ATTACK_RATIO_MAGICAL, 0).getCurrent();
defenseBonus += target.getGameStats().getStat(StatEnum.PVP_DEFEND_RATIO_MAGICAL, 0).getCurrent();
}
}
} else if (!useTemplateDmg) {
if (attacker instanceof Player) { // npcs dmg is not reduced because of the level difference GF (4.9) 23.04.2016
damage *= 1f - getNpcLevelDiffMod(target, attacker);
}
attackBonus = attacker.getGameStats().getStat(StatEnum.PVE_ATTACK_RATIO, 0).getCurrent() * 0.001f;
defenseBonus = target.getGameStats().getStat(StatEnum.PVE_DEFEND_RATIO, 0).getCurrent() * 0.001f;
attackBonus = attacker.getGameStats().getStat(StatEnum.PVE_ATTACK_RATIO, 0).getCurrent();
defenseBonus = target.getGameStats().getStat(StatEnum.PVE_DEFEND_RATIO, 0).getCurrent();
switch (element) {
case NONE:
attackBonus += attacker.getGameStats().getStat(StatEnum.PVE_ATTACK_RATIO_PHYSICAL, 0).getCurrent() * 0.001f;
defenseBonus += target.getGameStats().getStat(StatEnum.PVE_DEFEND_RATIO_PHYSICAL, 0).getCurrent() * 0.001f;
attackBonus += attacker.getGameStats().getStat(StatEnum.PVE_ATTACK_RATIO_PHYSICAL, 0).getCurrent();
defenseBonus += target.getGameStats().getStat(StatEnum.PVE_DEFEND_RATIO_PHYSICAL, 0).getCurrent();
break;
default:
attackBonus += attacker.getGameStats().getStat(StatEnum.PVE_ATTACK_RATIO_MAGICAL, 0).getCurrent() * 0.001f;
defenseBonus += target.getGameStats().getStat(StatEnum.PVE_DEFEND_RATIO_MAGICAL, 0).getCurrent() * 0.001f;
attackBonus += attacker.getGameStats().getStat(StatEnum.PVE_ATTACK_RATIO_MAGICAL, 0).getCurrent();
defenseBonus += target.getGameStats().getStat(StatEnum.PVE_DEFEND_RATIO_MAGICAL, 0).getCurrent();
}
}
return damage + (damage * attackBonus) - (damage * defenseBonus);
CombatMode mode = pvpTarget ? CombatMode.PVP : CombatMode.PVE;
// PvP/PvE ratio caps are applied after aggregation (retail behavior)
attackBonus = StatCapUtil.limitValueForPvpOrPveStat(mode, RatioType.ATTACK, attackBonus);
defenseBonus = StatCapUtil.limitValueForPvpOrPveStat(mode, RatioType.DEFENSE, defenseBonus);
float multiplier = 1f + (attackBonus - defenseBonus) / 1000f;
// prevent negative or zero damage
multiplier = Math.max(multiplier, 0.1f);

return damage * multiplier;
}

/**
Expand Down