RuneHive-Tarnish
Neural OSRS Enhancement Framework
Loading...
Searching...
No Matches
FormulaFactory.java
1package com.osroyale.game.world.entity.combat.attack;
2
3import com.osroyale.game.world.entity.combat.CombatType;
4import com.osroyale.game.world.entity.combat.FormulaModifier;
5import com.osroyale.game.world.entity.combat.accuracy.*;
6import com.osroyale.game.world.entity.combat.hit.Hit;
7import com.osroyale.game.world.entity.combat.hit.HitIcon;
8import com.osroyale.game.world.entity.combat.hit.Hitsplat;
9import com.osroyale.game.world.entity.combat.maxhit.MeleeMaxHit;
10import com.osroyale.game.world.entity.combat.maxhit.RangeMaxHit;
11import com.osroyale.game.world.entity.combat.strategy.CombatStrategy;
12import com.osroyale.game.world.entity.mob.Mob;
13import com.osroyale.util.RandomUtils;
14
49
50public final class FormulaFactory {
51
52 public static Hit nextMeleeHit(Mob attacker, Mob defender) {
53 int max = getMaxHit(attacker, defender, CombatType.MELEE);
54 return nextHit(attacker, defender, max, Hitsplat.NORMAL, HitIcon.MELEE, false, CombatType.MELEE);
55 }
56
57 public static Hit nextMeleeHit(Mob attacker, Mob defender, int max) {
58 return nextHit(attacker, defender, max, Hitsplat.NORMAL, HitIcon.MELEE, false, CombatType.MELEE);
59 }
60
61 public static Hit nextMeleeHit(Mob attacker, Mob defender, int max, boolean multipleHitsAllowed) {
62 return nextHit(attacker, defender, max, Hitsplat.NORMAL, HitIcon.MELEE, multipleHitsAllowed, CombatType.MELEE);
63 }
64
65 public static Hit nextRangedHit(Mob attacker, Mob defender, int max) {
66 return nextHit(attacker, defender, max, Hitsplat.NORMAL, HitIcon.RANGED, false, CombatType.RANGED);
67 }
68
69 public static Hit nextMagicHit(Mob attacker, Mob defender, int max) {
70 return nextHit(attacker, defender, max, Hitsplat.NORMAL, HitIcon.MAGIC, false, CombatType.MAGIC);
71 }
72
73 private static Hit nextHit(Mob attacker, Mob defender, int max, Hitsplat hitsplat, HitIcon icon, boolean multipleHitsAllowed, CombatType type) {
74 final CombatStrategy<? super Mob> strategy = attacker.getStrategy();
75 final int totalHits = defender.isNpc() && defender.getNpc().definition.getSize() > 1 ? 3 : 1;
76
77 if (strategy.toString().contains("ScytheOfVitur") && totalHits > 1) {
78 final Hit[] hits = new Hit[totalHits];
79
80 for (int index = 0; index < hits.length; index++) {
81 final Hit hit = hits[index] = new Hit(max < 0 ? -1 : 0, hitsplat, icon,
82 isAccurate(attacker, defender, type, strategy));
83
84 if (max > 0) {
85 max = type.getFormula().modifyDamage(attacker, defender, max);
86 int verdict = RandomUtils.inclusive(0, max);
87
88 switch (index) {
89 case 1:
90 verdict /= 2;
91 break;
92 case 2:
93 verdict /= 3;
94 break;
95 }
96
97 if (verdict > defender.getCurrentHealth()) {
98 verdict = defender.getCurrentHealth();
99 }
100
101 hit.setDamage(verdict);
102 }
103 }
104
105 return new Hit(hits);
106 }
107
108 final Hit hit = new Hit(max < 0 ? -1 : 0, hitsplat, icon,
109 isAccurate(attacker, defender, type, strategy));
110 if (max > 0) {
111 max = type.getFormula().modifyDamage(attacker, defender, max);
112 int verdict = RandomUtils.inclusive(0, max);
113
114 if (verdict > defender.getCurrentHealth()) {
115 verdict = defender.getCurrentHealth();
116 }
117
118 hit.setDamage(verdict);
119 }
120
121 return hit;
122 }
123
124 private static boolean isAccurate(Mob attacker, Mob defender, CombatType type, CombatStrategy<? super Mob> strategy) {
125 if (strategy != null && strategy.isAlwaysAccurate()) {
126 return true;
127 }
128
129 double attackRoll = rollOffensive(attacker, defender, type.getFormula());
130 double defenceRoll = rollDefensive(attacker, defender, type.getFormula());
131 boolean isNpc = attacker.isNpc();
132 switch (type) {
133 case RANGED -> {
134 return isNpc ? RangeAccuracyNpc.successful(attacker, defender, type) : RangeAccuracy.successful(attacker, defender);
135 }
136 case MAGIC -> {
137 return isNpc ? MagicAccuracyNpc.successful(attacker, defender, type) : MagicAccuracy.successful(attacker, defender);
138 }
139 case MELEE -> {
140 return MeleeAccuracy.successful(attacker, defender);
141 }
142 default -> {
143 return RandomUtils.success(attackRoll / (attackRoll + defenceRoll));
144 }
145 }
146 }
147
148 public static int rollOffensive(Mob attacker, Mob defender, FormulaModifier<Mob> formula) {
149 int roll = formula.modifyAccuracy(attacker, defender, 0);
150 int bonus = formula.modifyOffensiveBonus(attacker, defender, 0);
151 return attacker.getCombat().modifyAccuracy(defender, roll * (bonus + 64));
152 }
153
154 public static int rollDefensive(Mob attacker, Mob defender, FormulaModifier<Mob> formula) {
155 int roll = formula.modifyDefensive(attacker, defender, 0);
156 int bonus = formula.modifyDefensiveBonus(attacker, defender, 0);
157 return attacker.getCombat().modifyDefensive(defender, roll * (bonus + 64));
158 }
159
160 public static int getMaxHit(Mob attacker, Mob defender, CombatType type) {
161 FormulaModifier<Mob> formula = type.getFormula();
162 int level = formula.modifyAggressive(attacker, defender, 0);
163 int bonus = formula.modifyAggressiveBonus(attacker, defender, 0);
164 switch (attacker.getStrategy().getCombatType()) {
165 case MELEE -> MeleeMaxHit.maxHit(attacker);
166 }
167 return maxHit(level, bonus);
168 }
169
170 public static int getModifiedMaxHit(Mob attacker, Mob defender, CombatType type) {
171 FormulaModifier<Mob> formula = type.getFormula();
172 int level = formula.modifyAggressive(attacker, defender, 0);
173 int bonus = formula.modifyAggressiveBonus(attacker, defender, 0);
174 switch (attacker.getStrategy().getCombatType()) {
175 case MELEE -> MeleeMaxHit.maxHit(attacker);
176 }
177 if (attacker.getStrategy().getCombatType().equals(CombatType.RANGED)) {
178 return (int) Math.floor(RangeMaxHit.maxHit(attacker));
179 }
180 return formula.modifyDamage(attacker, defender, maxHit(level, bonus));
181 }
182
183 private static int maxHit(int level, int bonus) {
184 return (320 + level * (bonus + 64)) / 640;
185 }
186
187}
abstract< T extends Mob > CombatStrategy<? super T > getStrategy()
abstract Combat<? extends Mob > getCombat()