Added support for updating stats

Implemented support for updating items, item stats, and applying stats to ItemData attributes field
Added reference to CharStats.Entry to ItemData -- this may be removed when hireling stats are implemented more thoroughly
Added clear method in CharData to support chaining CharData reset methods clear().load(D2S)
Added empty base stats for hireling -- fixes issues with applying hireling stats to their own Attributes
This commit is contained in:
Collin Smith 2020-01-18 15:10:44 -08:00
parent f5552947dc
commit 2d4b2a72a9
3 changed files with 61 additions and 20 deletions

View File

@ -63,7 +63,7 @@ public class CharData implements ItemData.UpdateListener, Pool.Poolable {
final long npcReturnData[] = new long[Riiablo.MAX_DIFFS];
final Attributes statData = new Attributes();
final IntIntMap skillData = new IntIntMap();
final ItemData itemData = new ItemData(statData);
final ItemData itemData = new ItemData(statData, null);
Item golemItemData;
public int diff;
@ -123,6 +123,11 @@ public class CharData implements ItemData.UpdateListener, Pool.Poolable {
CharData() {}
public CharData clear() {
reset();
return this;
}
public CharData load(D2S d2s) {
d2s.copyTo(this);
preprocessItems();
@ -190,6 +195,36 @@ public class CharData implements ItemData.UpdateListener, Pool.Poolable {
base.put(Stat.maxlightresist, 75);
base.put(Stat.maxcoldresist, 75);
base.put(Stat.maxpoisonresist, 75);
// TODO: set base merc stats based on hireling tables and level
base = mercData.statData.base();
base.put(Stat.strength, 0);
base.put(Stat.energy, 0);
base.put(Stat.dexterity, 0);
base.put(Stat.vitality, 0);
base.put(Stat.statpts, 0);
base.put(Stat.newskills, 0);
base.put(Stat.hitpoints, 0);
base.put(Stat.maxhp, 0);
base.put(Stat.mana, 0);
base.put(Stat.maxmana, 0);
base.put(Stat.stamina, 0);
base.put(Stat.maxstamina, 0);
base.put(Stat.level, 0);
base.put(Stat.experience, 0);
base.put(Stat.gold, 0);
base.put(Stat.goldbank, 0);
base.put(Stat.armorclass, 0);
base.put(Stat.damageresist, 0);
base.put(Stat.magicresist, 0);
base.put(Stat.fireresist, diff.ResistPenalty);
base.put(Stat.lightresist, diff.ResistPenalty);
base.put(Stat.coldresist, diff.ResistPenalty);
base.put(Stat.poisonresist, diff.ResistPenalty);
base.put(Stat.maxfireresist, 75);
base.put(Stat.maxlightresist, 75);
base.put(Stat.maxcoldresist, 75);
base.put(Stat.maxpoisonresist, 75);
}
public boolean isManaged() {
@ -424,7 +459,7 @@ public class CharData implements ItemData.UpdateListener, Pool.Poolable {
public int xp;
final Attributes statData = new Attributes();
final ItemData itemData = new ItemData(statData);
final ItemData itemData = new ItemData(statData, null);
public Attributes getStats() {
return statData;

View File

@ -207,12 +207,14 @@ public class D2S {
base.put(Stat.gold, stats.gold);
base.put(Stat.goldbank, stats.goldbank);
for (int spellId = data.classId.firstSpell, s = data.classId.lastSpell, i = 0; spellId < s; spellId++, i++) {
CharacterClass classId = data.classId;
for (int spellId = classId.firstSpell, s = classId.lastSpell, i = 0; spellId < s; spellId++, i++) {
data.skillData.put(spellId, skills.data[i]);
}
data.itemData.clear();
data.itemData.addAll(items.items);
data.itemData.charStats = classId.entry();
data.itemData.alternate = header.alternate;
data.golemItemData = golem.item;
return data;

View File

@ -4,6 +4,7 @@ import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.IntIntMap;
import com.riiablo.Riiablo;
import com.riiablo.codec.excel.CharStats;
import com.riiablo.codec.excel.SetItems;
import com.riiablo.item.Attributes;
import com.riiablo.item.BodyLoc;
@ -19,6 +20,7 @@ public class ItemData {
public static final int INVALID_ITEM = -1;
final Attributes stats;
CharStats.Entry charStats;
final Array<Item> itemData = new Array<>(Item.class);
@ -38,12 +40,14 @@ public class ItemData {
final Array<UpdateListener> updateListeners = new Array<>(false, 16);
ItemData(Attributes stats) {
ItemData(Attributes stats, CharStats.Entry charStats) {
this.stats = stats;
this.charStats = charStats;
}
public void clear() {
cursor = INVALID_ITEM;
charStats = null;
alternate = D2S.PRIMARY;
alternateListeners.clear();
itemData.clear();
@ -59,6 +63,12 @@ public class ItemData {
Item[] items = itemData.items;
for (int i = 0, s = itemData.size; i < s; i++) {
Item item = items[i];
if (item.quality == Quality.SET) {
setItemsOwned.getAndIncrement(item.qualityId, 0, 1);
if (item.location == Location.EQUIPPED && isActive(item)) {
updateSet(item, 1);
}
}
switch (item.location) {
case EQUIPPED:
equipped.put(item.bodyLoc, i);
@ -77,8 +87,9 @@ public class ItemData {
case SOCKET:
default:
}
if (item.quality == Quality.SET) setItemsOwned.getAndIncrement(item.qualityId, 0, 1);
}
updateStats();
}
public Item getItem(int i) {
@ -202,7 +213,7 @@ public class ItemData {
item.bodyLoc = bodyLoc;
int j = equipped.put(bodyLoc, i);
assert j == INVALID_ITEM : "Item " + j + " should have been unequipped by this point.";
update(bodyLoc);
updateStats(); // TODO: add support for appending to existing stats if this is an additional item
updateSet(item, 1);
notifyEquip(bodyLoc, item);
}
@ -210,24 +221,13 @@ public class ItemData {
int unequip(BodyLoc bodyLoc) {
int i = equipped.remove(bodyLoc);
Item item = itemData.get(i);
// update(bodyLoc);
updateStats();
updateSet(item, -1);
notifyUnequip(bodyLoc, item);
return i;
}
void update(BodyLoc bodyLoc) {
int i = equipped.get(bodyLoc);
update(i);
}
void update(int i) {
Item item = itemData.get(i);
// item.update(this);
updateStats();
}
private void updateStats() {
void updateStats() {
Stat stat;
stats.reset();
int[] cache = equipped.values();
@ -236,6 +236,7 @@ public class ItemData {
if (j == ItemData.INVALID_ITEM) continue;
Item item = itemData.get(j);
if (isActive(item)) {
item.update(stats, charStats, equippedSets);
stats.add(item.props.remaining());
if ((stat = item.props.get(Stat.armorclass)) != null) {
stats.aggregate().addCopy(stat);
@ -250,10 +251,13 @@ public class ItemData {
if (j == ItemData.INVALID_ITEM) continue;
Item item = itemData.get(j);
if (item.type.is(Type.CHAR)) {
item.update(stats, charStats, equippedSets);
stats.add(item.props.remaining());
} else if (item.type.is(Type.BOOK)) { // TODO: may not be needed since not stat -- calculate elsewhere?
item.update(stats, charStats, equippedSets);
}
}
// stats.update(this); // TODO: uncomment
stats.update(stats, charStats);
notifyUpdated();
}