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