001package com.fs.starfarer.api.combat; 002 003import java.util.HashMap; 004import java.util.LinkedHashMap; 005 006import com.fs.starfarer.api.combat.MutableStat.StatMod; 007import com.fs.starfarer.api.combat.MutableStat.StatModType; 008 009/** 010 * @author Alex Mosolov 011 * 012 * Copyright 2012 Fractal Softworks, LLC 013 */ 014public class StatBonus { 015 016 @Override 017 public boolean equals(Object obj) { 018 if (this == obj) return true; 019 if (obj == null) return false; 020 if (getClass() != obj.getClass()) return false; 021 022 StatBonus other = (StatBonus) obj; 023 if (Float.floatToIntBits(flatBonus) != Float.floatToIntBits(other.flatBonus)) return false; 024 if (needsRecompute != other.needsRecompute) return false; 025 if (Float.floatToIntBits(percentMod) != Float.floatToIntBits(other.percentMod)) return false; 026 if (Float.floatToIntBits(mult) != Float.floatToIntBits(other.mult)) return false; 027 028 if (flatBonuses == null) { 029 if (other.flatBonuses != null) return false; 030 } else { 031 if (flatBonuses.size() != other.flatBonuses.size()) return false; 032 for (String key : flatBonuses.keySet()) { 033 if (!other.flatBonuses.containsKey(key)) return false; 034 StatMod mod = flatBonuses.get(key); 035 StatMod otherMod = other.flatBonuses.get(key); 036 if (!mod.source.equals(otherMod.source)) return false; 037 if (Float.floatToIntBits(mod.value) != Float.floatToIntBits(otherMod.value)) return false; 038 } 039 } 040 041 if (multBonuses == null) { 042 if (other.multBonuses != null) return false; 043 } else if (!multBonuses.equals(other.multBonuses)) { 044 if (multBonuses.size() != other.multBonuses.size()) return false; 045 for (String key : multBonuses.keySet()) { 046 if (!other.multBonuses.containsKey(key)) return false; 047 StatMod mod = multBonuses.get(key); 048 StatMod otherMod = other.multBonuses.get(key); 049 if (!mod.source.equals(otherMod.source)) return false; 050 if (Float.floatToIntBits(mod.value) != Float.floatToIntBits(otherMod.value)) return false; 051 } 052 } 053 054 if (percentBonuses == null) { 055 if (other.percentBonuses != null) return false; 056 } else if (!percentBonuses.equals(other.percentBonuses)) { 057 if (percentBonuses.size() != other.percentBonuses.size()) return false; 058 for (String key : percentBonuses.keySet()) { 059 if (!other.percentBonuses.containsKey(key)) return false; 060 StatMod mod = percentBonuses.get(key); 061 StatMod otherMod = other.percentBonuses.get(key); 062 if (!mod.source.equals(otherMod.source)) return false; 063 if (Float.floatToIntBits(mod.value) != Float.floatToIntBits(otherMod.value)) return false; 064 } 065 } 066 return true; 067 } 068 069 public StatBonus createCopy() { 070 StatBonus copy = new StatBonus(); 071 copy.applyMods(this); 072 return copy; 073 } 074 075 public float flatBonus = 0f; 076 public float mult = 1f; 077 public float percentMod = 0f; 078 079// private HashMap<String, StatMod> flatBonuses = new HashMap<String, StatMod>(); 080// private HashMap<String, StatMod> percentBonuses = new HashMap<String, StatMod>(); 081// private HashMap<String, StatMod> multBonuses = new HashMap<String, StatMod>(); 082 private LinkedHashMap<String, StatMod> flatBonuses; 083 private LinkedHashMap<String, StatMod> percentBonuses; 084 private LinkedHashMap<String, StatMod> multBonuses; 085 086 private boolean needsRecompute = false; 087 public StatBonus() { 088 } 089 090 Object readResolve() { 091 if (flatBonuses == null) { 092 flatBonuses = new LinkedHashMap<String, StatMod>(); 093 } 094 if (percentBonuses == null) { 095 percentBonuses = new LinkedHashMap<String, StatMod>(); 096 } 097 if (multBonuses == null) { 098 multBonuses = new LinkedHashMap<String, StatMod>(); 099 } 100 return this; 101 } 102 103 public boolean isUnmodified() { 104 return (flatBonuses == null || getFlatBonuses().isEmpty()) && 105 (multBonuses == null || getMultBonuses().isEmpty()) && 106 (percentBonuses == null || getPercentBonuses().isEmpty()); 107 } 108 109 public StatMod getFlatBonus(String source) { 110 return getFlatBonuses().get(source); 111 } 112 113 public StatMod getPercentBonus(String source) { 114 return getPercentBonuses().get(source); 115 } 116 117 public StatMod getMultBonus(String source) { 118 return getMultBonuses().get(source); 119 } 120 121 public void modifyFlat(String source, float value) { 122 modifyFlat(source, value, null); 123 } 124 public void modifyFlat(String source, float value, String desc) { 125 StatMod mod = getFlatBonuses().get(source); 126 if (mod == null && value == 0) return; 127 if (mod != null && mod.value == value) { 128 mod.desc = desc; 129 return; 130 } 131 132 mod = new StatMod(source, StatModType.FLAT, value, desc); 133 getFlatBonuses().put(source, mod); 134 needsRecompute = true; 135 } 136 137 public void modifyPercent(String source, float value) { 138 modifyPercent(source, value, null); 139 } 140 141 public void modifyPercent(String source, float value, String desc) { 142 StatMod mod = getPercentBonuses().get(source); 143 if (mod == null && value == 0) return; 144 if (mod != null && mod.value == value) { 145 mod.desc = desc; 146 return; 147 } 148 149 mod = new StatMod(source, StatModType.PERCENT, value, desc); 150 getPercentBonuses().put(source, mod); 151 needsRecompute = true; 152 } 153 154 public void modifyPercentAlways(String source, float value, String desc) { 155 StatMod mod = new StatMod(source, StatModType.PERCENT, value, desc); 156 getPercentBonuses().put(source, mod); 157 needsRecompute = true; 158 } 159 160 public void modifyMult(String source, float value) { 161 modifyMult(source, value, null); 162 } 163 public void modifyMult(String source, float value, String desc) { 164 StatMod mod = getMultBonuses().get(source); 165 if (mod == null && value == 1) return; 166 if (mod != null && mod.value == value) { 167 mod.desc = desc; 168 return; 169 } 170 171 mod = new StatMod(source, StatModType.MULT, value, desc); 172 getMultBonuses().put(source, mod); 173 needsRecompute = true; 174 } 175 176 public void modifyMultAlways(String source, float value, String desc) { 177 StatMod mod = new StatMod(source, StatModType.MULT, value, desc); 178 getMultBonuses().put(source, mod); 179 needsRecompute = true; 180 } 181 182 public void modifyFlatAlways(String source, float value, String desc) { 183 StatMod mod = new StatMod(source, StatModType.FLAT, value, desc); 184 getFlatBonuses().put(source, mod); 185 needsRecompute = true; 186 } 187 188 public void unmodify() { 189 if (flatBonuses != null) flatBonuses.clear(); 190 if (percentBonuses != null) percentBonuses.clear(); 191 if (multBonuses != null) multBonuses.clear(); 192 needsRecompute = true; 193 } 194 195 public void unmodify(String source) { 196 if (flatBonuses != null) { 197 StatMod mod = flatBonuses.remove(source); 198 if (mod != null && mod.value != 0) needsRecompute = true; 199 } 200 if (percentBonuses != null) { 201 StatMod mod = percentBonuses.remove(source); 202 if (mod != null && mod.value != 0) needsRecompute = true; 203 } 204 205 if (multBonuses != null) { 206 StatMod mod = multBonuses.remove(source); 207 if (mod != null && mod.value != 1) needsRecompute = true; 208 } 209 } 210 211 public void unmodifyFlat(String source) { 212 if (flatBonuses == null) return; 213 StatMod mod = flatBonuses.remove(source); 214 if (mod != null && mod.value != 0) needsRecompute = true; 215 } 216 217 public void unmodifyPercent(String source) { 218 if (percentBonuses == null) return; 219 StatMod mod = percentBonuses.remove(source); 220 if (mod != null && mod.value != 0) needsRecompute = true; 221 } 222 223 public void unmodifyMult(String source) { 224 if (multBonuses == null) return; 225 StatMod mod = multBonuses.remove(source); 226 if (mod != null && mod.value != 1) needsRecompute = true; 227 } 228 229 private void recompute() { 230 float flatMod = 0; 231 float multBonus = 1f; 232 percentMod = 0; 233 if (percentBonuses != null) { 234 for (StatMod mod : percentBonuses.values()) { 235 percentMod += mod.value; 236 } 237 } 238 239 if (flatBonuses != null) { 240 for (StatMod mod : flatBonuses.values()) { 241 flatMod += mod.value; 242 } 243 } 244 245 if (multBonuses != null) { 246 for (StatMod mod : multBonuses.values()) { 247 multBonus *= mod.value; 248 } 249 } 250 251 //mult = 1f + percentMod / 100f; 252 //if (mult < 0) mult = 0; 253 mult = multBonus; 254 flatBonus = flatMod; 255 256 needsRecompute = false; 257 } 258 259 public float computeEffective(float baseValue) { 260 if (needsRecompute) recompute(); 261 //return baseValue * mult + flatBonus; 262 return (baseValue + baseValue * percentMod / 100f + flatBonus) * mult; 263 } 264 265 public float getFlatBonus() { 266 if (needsRecompute) recompute(); 267 return flatBonus; 268 } 269 270 /** 271 * Returns combined percentage and multiplier modifiers. 272 * @return 273 */ 274 public float getBonusMult() { 275 if (needsRecompute) recompute(); 276 return mult * (1f + percentMod / 100f); 277 } 278 279 public float getMult() { 280 if (needsRecompute) recompute(); 281 return mult; 282 } 283 284 public float getPercentMod() { 285 if (needsRecompute) recompute(); 286 return percentMod; 287 } 288 289 public boolean isPositive(float baseValue) { 290 return computeEffective(baseValue) > baseValue; 291 } 292 293 public boolean isNegative(float baseValue) { 294 return computeEffective(baseValue) < baseValue; 295 } 296 297 public HashMap<String, StatMod> getFlatBonuses() { 298 if (flatBonuses == null) { 299 flatBonuses = new LinkedHashMap<String, StatMod>(); 300 } 301 return flatBonuses; 302 } 303 304 public HashMap<String, StatMod> getPercentBonuses() { 305 if (percentBonuses == null) { 306 percentBonuses = new LinkedHashMap<String, StatMod>(); 307 } 308 return percentBonuses; 309 } 310 311 public HashMap<String, StatMod> getMultBonuses() { 312 if (multBonuses == null) { 313 multBonuses = new LinkedHashMap<String, StatMod>(); 314 } 315 return multBonuses; 316 } 317 318 public void applyMods(MutableStat other) { 319 getFlatBonuses().putAll(other.getFlatMods()); 320 getPercentBonuses().putAll(other.getPercentMods()); 321 getMultBonuses().putAll(other.getMultMods()); 322 needsRecompute = true; 323 } 324 325 public void applyMods(StatBonus other) { 326 getFlatBonuses().putAll(other.getFlatBonuses()); 327 getPercentBonuses().putAll(other.getPercentBonuses()); 328 getMultBonuses().putAll(other.getMultBonuses()); 329 needsRecompute = true; 330 } 331} 332 333 334 335 336 337 338 339 340 341 342