mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-07-09 23:38:15 +07:00
Created AttributesUpdater and tests to fold attributes into each other
This commit is contained in:
126
core/src/com/riiablo/attributes/AttributesUpdater.java
Normal file
126
core/src/com/riiablo/attributes/AttributesUpdater.java
Normal file
@ -0,0 +1,126 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
import com.riiablo.codec.excel.CharStats;
|
||||
import com.riiablo.codec.excel.ItemStatCost;
|
||||
import com.riiablo.logger.LogManager;
|
||||
import com.riiablo.logger.Logger;
|
||||
import com.riiablo.logger.MDC;
|
||||
|
||||
public class AttributesUpdater {
|
||||
private static final Logger log = LogManager.getLogger(AttributesUpdater.class);
|
||||
|
||||
public Attributes update(Attributes attrs, Attributes opAttrs) {
|
||||
log.traceEntry("update(attrs: {}, opAttrs: {})", attrs, opAttrs);
|
||||
return update(attrs, opAttrs, null);
|
||||
}
|
||||
|
||||
public Attributes update(Attributes attrs, Attributes opAttrs, CharStats.Entry charStats) {
|
||||
log.traceEntry("update(attrs: {}, opAttrs: {}, charStats: {})", attrs, opAttrs, charStats);
|
||||
final StatList list = attrs.list();
|
||||
if (list.isEmpty()) return attrs;
|
||||
final StatListGetter base = attrs.base();
|
||||
final StatListBuilder agg = attrs.aggregate().builder();
|
||||
final StatListBuilder rem = attrs.remaining().builder();
|
||||
for (StatListGetter stats : list.listIterator()) {
|
||||
update(opAttrs, charStats, stats, base, agg, rem);
|
||||
}
|
||||
|
||||
return attrs;
|
||||
}
|
||||
|
||||
private static void update(
|
||||
final Attributes opAttrs,
|
||||
final CharStats.Entry charStats,
|
||||
final StatListGetter stats,
|
||||
final StatListGetter base,
|
||||
final StatListBuilder agg,
|
||||
final StatListBuilder rem) {
|
||||
for (StatGetter stat : stats) {
|
||||
final ItemStatCost.Entry entry = stat.entry();
|
||||
try {
|
||||
MDC.put("updateStat", stat.id());
|
||||
if (entry.op > 0) {
|
||||
final int ops = op(opAttrs, charStats, agg, stat);
|
||||
if (ops == 0) {
|
||||
log.trace("Propagating stat({})", stat.debugString());
|
||||
rem.add(stat);
|
||||
}
|
||||
} else if (!base.contains(stat)) {
|
||||
log.trace("Propagating stat({})", stat.debugString());
|
||||
rem.add(stat);
|
||||
} else {
|
||||
log.trace("Aggregating stat({})", stat.debugString());
|
||||
agg.add(stat);
|
||||
}
|
||||
} finally {
|
||||
MDC.remove("updateStat");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int op(
|
||||
final Attributes opAttrs,
|
||||
final CharStats.Entry charStats,
|
||||
final StatListBuilder agg,
|
||||
final StatGetter stat) {
|
||||
final ItemStatCost.Entry entry = stat.entry();
|
||||
final int op = entry.op;
|
||||
final int op_param = entry.op_param;
|
||||
final int op_base = op_param > 0
|
||||
? opAttrs.aggregate().get(Stat.index(entry.op_base)).value()
|
||||
: 1;
|
||||
int ops = 0;
|
||||
for (String op_stat : entry.op_stat) {
|
||||
if (op_stat.isEmpty()) break;
|
||||
final short statId = Stat.index(op_stat);
|
||||
final StatGetter opStat = agg.get(statId);
|
||||
if (opStat != null) {
|
||||
final int opValue = op(charStats, agg, stat, opStat, op, op_base, op_param);
|
||||
opStat.add(opValue);
|
||||
ops++;
|
||||
}
|
||||
}
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
||||
/** @see StatFormatter#op(StatGetter, Attributes) */
|
||||
private static int op(
|
||||
final CharStats.Entry charStats,
|
||||
final StatListBuilder agg,
|
||||
final StatGetter stat,
|
||||
final StatGetter opStat,
|
||||
final int op,
|
||||
final int op_base,
|
||||
final int op_param) {
|
||||
switch (op) {
|
||||
case 1: return (stat.value() * opStat.value()) / 100;
|
||||
case 2: return Fixed.intBitsToFloatFloor(stat.value() * op_base, op_param);
|
||||
case 3: return Fixed.intBitsToFloatFloor(stat.value() * op_base, op_param) * opStat.value() / 100;
|
||||
case 4: return Fixed.intBitsToFloatFloor(stat.value() * op_base, op_param);
|
||||
case 5: return Fixed.intBitsToFloatFloor(stat.value() * op_base, op_param) * opStat.value() / 100;
|
||||
case 6: return 0; // by-time
|
||||
case 7: return 0; // by-time percent
|
||||
case 8:
|
||||
if (charStats == null) return 0;
|
||||
agg.add(stat);
|
||||
//mod.set(stat.id);
|
||||
return stat.value() * charStats.ManaPerMagic; // max mana
|
||||
case 9:
|
||||
if (charStats == null) return 0;
|
||||
if (opStat.id() == Stat.maxhp) { // only increment vit on maxhp op
|
||||
agg.add(stat);
|
||||
//mod.set(stat.id);
|
||||
}
|
||||
return stat.value() // max hitpoints or stamina
|
||||
* (opStat.id() == Stat.maxhp
|
||||
? charStats.LifePerVitality
|
||||
: charStats.StaminaPerVitality);
|
||||
case 10: return 0; // no-op
|
||||
case 11: return (stat.value() * opStat.value()) / 100; // TODO: modify field value? used with item_maxhp_percent and item_maxmana_percent
|
||||
case 12: return 0; // no-op
|
||||
case 13: return (stat.value() * opStat.value()) / 100;
|
||||
default: throw new AssertionError("Unsupported op: " + op + " for " + stat);
|
||||
}
|
||||
}
|
||||
}
|
48
core/test/com/riiablo/attributes/AttributesTest.java
Normal file
48
core/test/com/riiablo/attributes/AttributesTest.java
Normal file
@ -0,0 +1,48 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.badlogic.gdx.ApplicationAdapter;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.backends.headless.HeadlessApplication;
|
||||
|
||||
import com.riiablo.Files;
|
||||
import com.riiablo.Riiablo;
|
||||
import com.riiablo.codec.StringTBLs;
|
||||
import com.riiablo.logger.Level;
|
||||
import com.riiablo.logger.LogManager;
|
||||
import com.riiablo.mpq.MPQFileHandleResolver;
|
||||
|
||||
public class AttributesTest {
|
||||
@BeforeClass
|
||||
public static void setup() {
|
||||
Gdx.app = new HeadlessApplication(new ApplicationAdapter() {});
|
||||
Riiablo.home = Gdx.files.absolute("C:\\Program Files (x86)\\Steam\\steamapps\\common\\Diablo II");
|
||||
Riiablo.mpqs = new MPQFileHandleResolver();
|
||||
Riiablo.string = new StringTBLs(Riiablo.mpqs);
|
||||
Riiablo.files = new Files();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardown() {
|
||||
Gdx.app.exit();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void before() {
|
||||
LogManager.setLevel("com.riiablo.attributes", Level.TRACE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reset_does_not_reset_base() {
|
||||
AggregateAttributes attrs = Attributes.aggregateAttributes();
|
||||
attrs.base().builder().put(Stat.strength, 5).put(Stat.vitality, 15);
|
||||
attrs.reset();
|
||||
|
||||
for (StatGetter stat : attrs) {
|
||||
System.out.println(stat.debugString());
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user