RuneHive-Game
Loading...
Searching...
No Matches
FormulaFactory.java
Go to the documentation of this file.
1package com.runehive.game.world.entity.combat.attack;
2
3import com.runehive.game.world.entity.combat.CombatType;
4import com.runehive.game.world.entity.combat.FormulaModifier;
5import com.runehive.game.world.entity.combat.accuracy.*;
6import com.runehive.game.world.entity.combat.hit.Hit;
7import com.runehive.game.world.entity.combat.hit.HitIcon;
8import com.runehive.game.world.entity.combat.hit.Hitsplat;
9import com.runehive.game.world.entity.combat.maxhit.MeleeMaxHit;
10import com.runehive.game.world.entity.combat.maxhit.RangeMaxHit;
11import com.runehive.game.world.entity.combat.strategy.CombatStrategy;
12import com.runehive.game.world.entity.mob.Mob;
13import com.runehive.util.RandomUtils;
14
15/**
16 * Supplies factory methods useful for combat.
17 *
18 * @author Michael | Chex
19 */
20public final class FormulaFactory {
21
22 public static Hit nextMeleeHit(Mob attacker, Mob defender) {
23 int max = getMaxHit(attacker, defender, CombatType.MELEE);
24 return nextHit(attacker, defender, max, Hitsplat.NORMAL, HitIcon.MELEE, false, CombatType.MELEE);
25 }
26
27 public static Hit nextMeleeHit(Mob attacker, Mob defender, int max) {
28 return nextHit(attacker, defender, max, Hitsplat.NORMAL, HitIcon.MELEE, false, CombatType.MELEE);
29 }
30
31 public static Hit nextMeleeHit(Mob attacker, Mob defender, int max, boolean multipleHitsAllowed) {
32 return nextHit(attacker, defender, max, Hitsplat.NORMAL, HitIcon.MELEE, multipleHitsAllowed, CombatType.MELEE);
33 }
34
35 public static Hit nextRangedHit(Mob attacker, Mob defender, int max) {
36 return nextHit(attacker, defender, max, Hitsplat.NORMAL, HitIcon.RANGED, false, CombatType.RANGED);
37 }
38
39 public static Hit nextMagicHit(Mob attacker, Mob defender, int max) {
40 return nextHit(attacker, defender, max, Hitsplat.NORMAL, HitIcon.MAGIC, false, CombatType.MAGIC);
41 }
42
43 private static Hit nextHit(Mob attacker, Mob defender, int max, Hitsplat hitsplat, HitIcon icon, boolean multipleHitsAllowed, CombatType type) {
45 final int totalHits = defender.isNpc() && defender.getNpc().definition.getSize() > 1 ? 3 : 1;
46
47 if (strategy.toString().contains("ScytheOfVitur") && totalHits > 1) {
48 final Hit[] hits = new Hit[totalHits];
49
50 for (int index = 0; index < hits.length; index++) {
51 final Hit hit = hits[index] = new Hit(max < 0 ? -1 : 0, hitsplat, icon,
52 isAccurate(attacker, defender, type, strategy));
53
54 if (max > 0) {
55 max = type.getFormula().modifyDamage(attacker, defender, max);
56 int verdict = RandomUtils.inclusive(0, max);
57
58 switch (index) {
59 case 1:
60 verdict /= 2;
61 break;
62 case 2:
63 verdict /= 3;
64 break;
65 }
66
67 if (verdict > defender.getCurrentHealth()) {
68 verdict = defender.getCurrentHealth();
69 }
70
71 hit.setDamage(verdict);
72 }
73 }
74
75 return new Hit(hits);
76 }
77
78 final Hit hit = new Hit(max < 0 ? -1 : 0, hitsplat, icon,
79 isAccurate(attacker, defender, type, strategy));
80 if (max > 0) {
81 max = type.getFormula().modifyDamage(attacker, defender, max);
82 int verdict = RandomUtils.inclusive(0, max);
83
84 if (verdict > defender.getCurrentHealth()) {
85 verdict = defender.getCurrentHealth();
86 }
87
88 hit.setDamage(verdict);
89 }
90
91 return hit;
92 }
93
94 private static boolean isAccurate(Mob attacker, Mob defender, CombatType type, CombatStrategy<? super Mob> strategy) {
95 if (strategy != null && strategy.isAlwaysAccurate()) {
96 return true;
97 }
98
99 double attackRoll = rollOffensive(attacker, defender, type.getFormula());
100 double defenceRoll = rollDefensive(attacker, defender, type.getFormula());
101 boolean isNpc = attacker.isNpc();
102 switch (type) {
103 case RANGED -> {
104 return isNpc ? RangeAccuracyNpc.successful(attacker, defender, type) : RangeAccuracy.successful(attacker, defender);
105 }
106 case MAGIC -> {
107 return isNpc ? MagicAccuracyNpc.successful(attacker, defender, type) : MagicAccuracy.successful(attacker, defender);
108 }
109 case MELEE -> {
110 return MeleeAccuracy.successful(attacker, defender);
111 }
112 default -> {
113 return RandomUtils.success(attackRoll / (attackRoll + defenceRoll));
114 }
115 }
116 }
117
118 public static int rollOffensive(Mob attacker, Mob defender, FormulaModifier<Mob> formula) {
119 int roll = formula.modifyAccuracy(attacker, defender, 0);
120 int bonus = formula.modifyOffensiveBonus(attacker, defender, 0);
121 return attacker.getCombat().modifyAccuracy(defender, roll * (bonus + 64));
122 }
123
124 public static int rollDefensive(Mob attacker, Mob defender, FormulaModifier<Mob> formula) {
125 int roll = formula.modifyDefensive(attacker, defender, 0);
126 int bonus = formula.modifyDefensiveBonus(attacker, defender, 0);
127 return attacker.getCombat().modifyDefensive(defender, roll * (bonus + 64));
128 }
129
130 public static int getMaxHit(Mob attacker, Mob defender, CombatType type) {
132 int level = formula.modifyAggressive(attacker, defender, 0);
133 int bonus = formula.modifyAggressiveBonus(attacker, defender, 0);
134 switch (attacker.getStrategy().getCombatType()) {
135 case MELEE -> MeleeMaxHit.maxHit(attacker);
136 }
137 return maxHit(level, bonus);
138 }
139
140 public static int getModifiedMaxHit(Mob attacker, Mob defender, CombatType type) {
142 int level = formula.modifyAggressive(attacker, defender, 0);
143 int bonus = formula.modifyAggressiveBonus(attacker, defender, 0);
144 switch (attacker.getStrategy().getCombatType()) {
145 case MELEE -> MeleeMaxHit.maxHit(attacker);
146 }
147 if (attacker.getStrategy().getCombatType().equals(CombatType.RANGED)) {
148 return (int) Math.floor(RangeMaxHit.maxHit(attacker));
149 }
150 return formula.modifyDamage(attacker, defender, maxHit(level, bonus));
151 }
152
153 private static int maxHit(int level, int bonus) {
154 return (320 + level * (bonus + 64)) / 640;
155 }
156
157}
static boolean successful(Mob attacker, Mob defender)
static boolean successful(Mob attacker, Mob defender, CombatType style)
static boolean successful(Mob attacker, Mob defender)
static boolean successful(Mob attacker, Mob defender)
static boolean successful(Mob attacker, Mob defender, CombatType style)
Supplies factory methods useful for combat.
static Hit nextRangedHit(Mob attacker, Mob defender, int max)
static Hit nextMeleeHit(Mob attacker, Mob defender, int max)
static int getModifiedMaxHit(Mob attacker, Mob defender, CombatType type)
static Hit nextMagicHit(Mob attacker, Mob defender, int max)
static boolean isAccurate(Mob attacker, Mob defender, CombatType type, CombatStrategy<? super Mob > strategy)
static Hit nextHit(Mob attacker, Mob defender, int max, Hitsplat hitsplat, HitIcon icon, boolean multipleHitsAllowed, CombatType type)
static Hit nextMeleeHit(Mob attacker, Mob defender, int max, boolean multipleHitsAllowed)
static int rollOffensive(Mob attacker, Mob defender, FormulaModifier< Mob > formula)
static int rollDefensive(Mob attacker, Mob defender, FormulaModifier< Mob > formula)
static int getMaxHit(Mob attacker, Mob defender, CombatType type)
A Hit object holds the damage amount and hitsplat data.
Definition Hit.java:10
Handles the mob class.
Definition Mob.java:66
abstract< T extends Mob > CombatStrategy<? super T > getStrategy()
The combat strategy of the mob.
abstract Combat<? extends Mob > getCombat()
The combat of the mob.
final boolean isNpc()
Check if an entity is an npc.
Definition Mob.java:550
A static-util class that provides additional functionality for generating pseudo-random numbers.
static int inclusive(int min, int max)
Returns a pseudo-random int value between inclusive min and inclusive max.
static boolean success(double value)
Determines if a pseudorandomly generated double rounded to two decimal places is below or equal to va...
The enumerated type whose elements represent the hit icon of a Hit.
Definition HitIcon.java:8
MELEE
Represents the melee sword hit icon.
Definition HitIcon.java:14
RANGED
Represents the ranged bow hit icon.
Definition HitIcon.java:17
MAGIC
Represents the magic hat hit icon.
Definition HitIcon.java:20
default int modifyDamage(T attacker, Mob defender, int damage)