mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-07-31 15:09:21 +07:00
First iteration of attributes revision
This commit is contained in:
43
core/src/com/riiablo/attributes/AggregateAttributes.java
Normal file
43
core/src/com/riiablo/attributes/AggregateAttributes.java
Normal file
@ -0,0 +1,43 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
public class AggregateAttributes extends Attributes {
|
||||
final StatList base = StatList.obtain(1);
|
||||
final StatList agg = StatList.obtain(1);
|
||||
final StatList rem = StatList.obtain(1);
|
||||
|
||||
@Override
|
||||
public StatList base() {
|
||||
return base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatList aggregate() {
|
||||
return agg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatList remaining() {
|
||||
return rem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetToBase() {
|
||||
assert base.numLists() == 1;
|
||||
agg.setAll(base);
|
||||
//mod.clear();
|
||||
rem.clear();
|
||||
super.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}, {@link #base()}, {@link #aggregate()}, and {@link #remaining()}
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
base.clear();
|
||||
agg.clear();
|
||||
//mod.clear();
|
||||
rem.clear();
|
||||
super.clear();
|
||||
}
|
||||
}
|
136
core/src/com/riiablo/attributes/Attributes.java
Normal file
136
core/src/com/riiablo/attributes/Attributes.java
Normal file
@ -0,0 +1,136 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
import android.support.annotation.CallSuper;
|
||||
import java.util.Iterator;
|
||||
import org.apache.commons.collections4.IteratorUtils;
|
||||
|
||||
public abstract class Attributes implements Iterable<StatGetter> {
|
||||
/**
|
||||
* an arithmetic association of StatList
|
||||
*
|
||||
* item property lists will be frozen after creation
|
||||
* base stats should be mutable for players, monsters
|
||||
*
|
||||
* descriptions
|
||||
*/
|
||||
|
||||
public static AggregateAttributes fixedAttributes() {
|
||||
return new AggregateAttributes();
|
||||
}
|
||||
|
||||
public static GemAttributes gemAttributes() {
|
||||
return new GemAttributes();
|
||||
}
|
||||
|
||||
public static StatListWrapper wrappedAttributes(StatList stats) {
|
||||
return new StatListWrapper(stats);
|
||||
}
|
||||
|
||||
private StatList stats;
|
||||
|
||||
Attributes() {
|
||||
this.stats = StatList.obtain();
|
||||
}
|
||||
|
||||
Attributes(StatList stats) {
|
||||
this.stats = stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of properties contained within {@link #aggregate()}.
|
||||
*/
|
||||
public int size() {
|
||||
return aggregate().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the whether or not {@link #aggregate()} contains any properties.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property list containing intrinsic traits of the attributes.
|
||||
*
|
||||
* @see #aggregate()
|
||||
* @see #remaining()
|
||||
* @see #list()
|
||||
*/
|
||||
public StatList base() {
|
||||
return list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property list containing properties from {@link #list() list}
|
||||
* that were applied onto {@link #base() base}.
|
||||
*
|
||||
* @see #base()
|
||||
* @see #remaining()
|
||||
* @see #list()
|
||||
*/
|
||||
public StatList aggregate() {
|
||||
return list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property list containing properties from {@link #list() list}
|
||||
* that were applied onto {@link #base() base}, but could not be
|
||||
* {@link #aggregate() aggregated}.
|
||||
*
|
||||
* @see #base()
|
||||
* @see #aggregate()
|
||||
* @see #list()
|
||||
*/
|
||||
public StatList remaining() {
|
||||
return list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property list associated with this attributes. These
|
||||
* properties will be applied onto {@link #base() base} and the result will
|
||||
* be {@link #aggregate() aggregated}, with any unused properties being
|
||||
* {@link #remaining() remaining}.
|
||||
*
|
||||
* @see #base()
|
||||
* @see #aggregate()
|
||||
* @see #remaining()
|
||||
*/
|
||||
public StatList list() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <i>nth</i> list within {@link #list()}.
|
||||
*/
|
||||
public StatListGetter list(int list) {
|
||||
final StatList stats = list();
|
||||
assert stats.contains(list) : "list(" + list + ") does not exist: numLists(" + stats.numLists() + ")";
|
||||
return stats.get(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears {@link #remaining()} and sets {@link #aggregate()} equal to
|
||||
* {@link #base()}.
|
||||
*/
|
||||
public void resetToBase() {}
|
||||
|
||||
/**
|
||||
* Clears {@link #list()}
|
||||
*/
|
||||
@CallSuper
|
||||
public void clear() {
|
||||
stats.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the {@link #aggregate() aggregate} properties.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<StatGetter> iterator() {
|
||||
final StatList agg = aggregate();
|
||||
final int numLists = agg.numLists();
|
||||
if (numLists < 1) return IteratorUtils.emptyIterator();
|
||||
return agg.statIterator(0);
|
||||
}
|
||||
}
|
19
core/src/com/riiablo/attributes/Fixed.java
Normal file
19
core/src/com/riiablo/attributes/Fixed.java
Normal file
@ -0,0 +1,19 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
public class Fixed {
|
||||
public static int floatToIntBits(float value, int precision) {
|
||||
return (int) (value * (1 << precision));
|
||||
}
|
||||
|
||||
public static float intBitsToFloat(int value, int precision) {
|
||||
final int pow2 = (1 << precision);
|
||||
final int mask = pow2 - 1;
|
||||
return ((value >>> precision) + ((value & mask) / (float) pow2));
|
||||
}
|
||||
|
||||
public static int intBitsToFloatFloor(int value, int precision) {
|
||||
return value >>> precision;
|
||||
}
|
||||
|
||||
private Fixed() {}
|
||||
}
|
16
core/src/com/riiablo/attributes/GemAttributes.java
Normal file
16
core/src/com/riiablo/attributes/GemAttributes.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
import com.riiablo.item.Item;
|
||||
|
||||
public class GemAttributes extends Attributes {
|
||||
private static final int NUM_GEMPROPS = Item.NUM_GEMPROPS; // TODO: move this somewhere else
|
||||
|
||||
GemAttributes() {
|
||||
super(StatList.obtain(NUM_GEMPROPS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetToBase() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
388
core/src/com/riiablo/attributes/Stat.java
Normal file
388
core/src/com/riiablo/attributes/Stat.java
Normal file
@ -0,0 +1,388 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class Stat {
|
||||
public static final short strength = 0;
|
||||
public static final short energy = 1;
|
||||
public static final short dexterity = 2;
|
||||
public static final short vitality = 3;
|
||||
public static final short statpts = 4;
|
||||
public static final short newskills = 5;
|
||||
public static final short hitpoints = 6;
|
||||
public static final short maxhp = 7;
|
||||
public static final short mana = 8;
|
||||
public static final short maxmana = 9;
|
||||
public static final short stamina = 10;
|
||||
public static final short maxstamina = 11;
|
||||
public static final short level = 12;
|
||||
public static final short experience = 13;
|
||||
public static final short gold = 14;
|
||||
public static final short goldbank = 15;
|
||||
public static final short item_armor_percent = 16;
|
||||
public static final short item_maxdamage_percent = 17;
|
||||
public static final short item_mindamage_percent = 18;
|
||||
public static final short tohit = 19;
|
||||
public static final short toblock = 20;
|
||||
public static final short mindamage = 21;
|
||||
public static final short maxdamage = 22;
|
||||
public static final short secondary_mindamage = 23;
|
||||
public static final short secondary_maxdamage = 24;
|
||||
public static final short damagepercent = 25;
|
||||
public static final short manarecovery = 26;
|
||||
public static final short manarecoverybonus = 27;
|
||||
public static final short staminarecoverybonus = 28;
|
||||
public static final short lastexp = 29;
|
||||
public static final short nextexp = 30;
|
||||
public static final short armorclass = 31;
|
||||
public static final short armorclass_vs_missile = 32;
|
||||
public static final short armorclass_vs_hth = 33;
|
||||
public static final short normal_damage_reduction = 34;
|
||||
public static final short magic_damage_reduction = 35;
|
||||
public static final short damageresist = 36;
|
||||
public static final short magicresist = 37;
|
||||
public static final short maxmagicresist = 38;
|
||||
public static final short fireresist = 39;
|
||||
public static final short maxfireresist = 40;
|
||||
public static final short lightresist = 41;
|
||||
public static final short maxlightresist = 42;
|
||||
public static final short coldresist = 43;
|
||||
public static final short maxcoldresist = 44;
|
||||
public static final short poisonresist = 45;
|
||||
public static final short maxpoisonresist = 46;
|
||||
public static final short damageaura = 47;
|
||||
public static final short firemindam = 48;
|
||||
public static final short firemaxdam = 49;
|
||||
public static final short lightmindam = 50;
|
||||
public static final short lightmaxdam = 51;
|
||||
public static final short magicmindam = 52;
|
||||
public static final short magicmaxdam = 53;
|
||||
public static final short coldmindam = 54;
|
||||
public static final short coldmaxdam = 55;
|
||||
public static final short coldlength = 56;
|
||||
public static final short poisonmindam = 57;
|
||||
public static final short poisonmaxdam = 58;
|
||||
public static final short poisonlength = 59;
|
||||
public static final short lifedrainmindam = 60;
|
||||
public static final short lifedrainmaxdam = 61;
|
||||
public static final short manadrainmindam = 62;
|
||||
public static final short manadrainmaxdam = 63;
|
||||
public static final short stamdrainmindam = 64;
|
||||
public static final short stamdrainmaxdam = 65;
|
||||
public static final short stunlength = 66;
|
||||
public static final short velocitypercent = 67;
|
||||
public static final short attackrate = 68;
|
||||
public static final short other_animrate = 69;
|
||||
public static final short quantity = 70;
|
||||
public static final short value = 71;
|
||||
public static final short durability = 72;
|
||||
public static final short maxdurability = 73;
|
||||
public static final short hpregen = 74;
|
||||
public static final short item_maxdurability_percent = 75;
|
||||
public static final short item_maxhp_percent = 76;
|
||||
public static final short item_maxmana_percent = 77;
|
||||
public static final short item_attackertakesdamage = 78;
|
||||
public static final short item_goldbonus = 79;
|
||||
public static final short item_magicbonus = 80;
|
||||
public static final short item_knockback = 81;
|
||||
public static final short item_timeduration = 82;
|
||||
public static final short item_addclassskills = 83;
|
||||
public static final short unsentparam1 = 84;
|
||||
public static final short item_addexperience = 85;
|
||||
public static final short item_healafterkill = 86;
|
||||
public static final short item_reducedprices = 87;
|
||||
public static final short item_doubleherbduration = 88;
|
||||
public static final short item_lightradius = 89;
|
||||
public static final short item_lightcolor = 90;
|
||||
public static final short item_req_percent = 91;
|
||||
public static final short item_levelreq = 92;
|
||||
public static final short item_fasterattackrate = 93;
|
||||
public static final short item_levelreqpct = 94;
|
||||
public static final short lastblockframe = 95;
|
||||
public static final short item_fastermovevelocity = 96;
|
||||
public static final short item_nonclassskill = 97;
|
||||
public static final short state = 98;
|
||||
public static final short item_fastergethitrate = 99;
|
||||
public static final short monster_playercount = 100;
|
||||
public static final short skill_poison_override_length = 101;
|
||||
public static final short item_fasterblockrate = 102;
|
||||
public static final short skill_bypass_undead = 103;
|
||||
public static final short skill_bypass_demons = 104;
|
||||
public static final short item_fastercastrate = 105;
|
||||
public static final short skill_bypass_beasts = 106;
|
||||
public static final short item_singleskill = 107;
|
||||
public static final short item_restinpeace = 108;
|
||||
public static final short curse_resistance = 109;
|
||||
public static final short item_poisonlengthresist = 110;
|
||||
public static final short item_normaldamage = 111;
|
||||
public static final short item_howl = 112;
|
||||
public static final short item_stupidity = 113;
|
||||
public static final short item_damagetomana = 114;
|
||||
public static final short item_ignoretargetac = 115;
|
||||
public static final short item_fractionaltargetac = 116;
|
||||
public static final short item_preventheal = 117;
|
||||
public static final short item_halffreezeduration = 118;
|
||||
public static final short item_tohit_percent = 119;
|
||||
public static final short item_damagetargetac = 120;
|
||||
public static final short item_demondamage_percent = 121;
|
||||
public static final short item_undeaddamage_percent = 122;
|
||||
public static final short item_demon_tohit = 123;
|
||||
public static final short item_undead_tohit = 124;
|
||||
public static final short item_throwable = 125;
|
||||
public static final short item_elemskill = 126;
|
||||
public static final short item_allskills = 127;
|
||||
public static final short item_attackertakeslightdamage = 128;
|
||||
public static final short ironmaiden_level = 129;
|
||||
public static final short lifetap_level = 130;
|
||||
public static final short thorns_percent = 131;
|
||||
public static final short bonearmor = 132;
|
||||
public static final short bonearmormax = 133;
|
||||
public static final short item_freeze = 134;
|
||||
public static final short item_openwounds = 135;
|
||||
public static final short item_crushingblow = 136;
|
||||
public static final short item_kickdamage = 137;
|
||||
public static final short item_manaafterkill = 138;
|
||||
public static final short item_healafterdemonkill = 139;
|
||||
public static final short item_extrablood = 140;
|
||||
public static final short item_deadlystrike = 141;
|
||||
public static final short item_absorbfire_percent = 142;
|
||||
public static final short item_absorbfire = 143;
|
||||
public static final short item_absorblight_percent = 144;
|
||||
public static final short item_absorblight = 145;
|
||||
public static final short item_absorbmagic_percent = 146;
|
||||
public static final short item_absorbmagic = 147;
|
||||
public static final short item_absorbcold_percent = 148;
|
||||
public static final short item_absorbcold = 149;
|
||||
public static final short item_slow = 150;
|
||||
public static final short item_aura = 151;
|
||||
public static final short item_indesctructible = 152;
|
||||
public static final short item_cannotbefrozen = 153;
|
||||
public static final short item_staminadrainpct = 154;
|
||||
public static final short item_reanimate = 155;
|
||||
public static final short item_pierce = 156;
|
||||
public static final short item_magicarrow = 157;
|
||||
public static final short item_explosivearrow = 158;
|
||||
public static final short item_throw_mindamage = 159;
|
||||
public static final short item_throw_maxdamage = 160;
|
||||
public static final short skill_handofathena = 161;
|
||||
public static final short skill_staminapercent = 162;
|
||||
public static final short skill_passive_staminapercent = 163;
|
||||
public static final short skill_concentration = 164;
|
||||
public static final short skill_enchant = 165;
|
||||
public static final short skill_pierce = 166;
|
||||
public static final short skill_conviction = 167;
|
||||
public static final short skill_chillingarmor = 168;
|
||||
public static final short skill_frenzy = 169;
|
||||
public static final short skill_decrepify = 170;
|
||||
public static final short skill_armor_percent = 171;
|
||||
public static final short alignment = 172;
|
||||
public static final short target0 = 173;
|
||||
public static final short target1 = 174;
|
||||
public static final short goldlost = 175;
|
||||
public static final short conversion_level = 176;
|
||||
public static final short conversion_maxhp = 177;
|
||||
public static final short unit_dooverlay = 178;
|
||||
public static final short attack_vs_montype = 179;
|
||||
public static final short damage_vs_montype = 180;
|
||||
public static final short fade = 181;
|
||||
public static final short armor_override_percent = 182;
|
||||
public static final short unused183 = 183;
|
||||
public static final short unused184 = 184;
|
||||
public static final short unused185 = 185;
|
||||
public static final short unused186 = 186;
|
||||
public static final short unused187 = 187;
|
||||
public static final short item_addskill_tab = 188;
|
||||
public static final short unused189 = 189;
|
||||
public static final short unused190 = 190;
|
||||
public static final short unused191 = 191;
|
||||
public static final short unused192 = 192;
|
||||
public static final short unused193 = 193;
|
||||
public static final short item_numsockets = 194;
|
||||
public static final short item_skillonattack = 195;
|
||||
public static final short item_skillonkill = 196;
|
||||
public static final short item_skillondeath = 197;
|
||||
public static final short item_skillonhit = 198;
|
||||
public static final short item_skillonlevelup = 199;
|
||||
public static final short unused200 = 200;
|
||||
public static final short item_skillongethit = 201;
|
||||
public static final short unused202 = 202;
|
||||
public static final short unused203 = 203;
|
||||
public static final short item_charged_skill = 204;
|
||||
public static final short unused204 = 205;
|
||||
public static final short unused205 = 206;
|
||||
public static final short unused206 = 207;
|
||||
public static final short unused207 = 208;
|
||||
public static final short unused208 = 209;
|
||||
public static final short unused209 = 210;
|
||||
public static final short unused210 = 211;
|
||||
public static final short unused211 = 212;
|
||||
public static final short unused212 = 213;
|
||||
public static final short item_armor_perlevel = 214;
|
||||
public static final short item_armorpercent_perlevel = 215;
|
||||
public static final short item_hp_perlevel = 216;
|
||||
public static final short item_mana_perlevel = 217;
|
||||
public static final short item_maxdamage_perlevel = 218;
|
||||
public static final short item_maxdamage_percent_perlevel = 219;
|
||||
public static final short item_strength_perlevel = 220;
|
||||
public static final short item_dexterity_perlevel = 221;
|
||||
public static final short item_energy_perlevel = 222;
|
||||
public static final short item_vitality_perlevel = 223;
|
||||
public static final short item_tohit_perlevel = 224;
|
||||
public static final short item_tohitpercent_perlevel = 225;
|
||||
public static final short item_cold_damagemax_perlevel = 226;
|
||||
public static final short item_fire_damagemax_perlevel = 227;
|
||||
public static final short item_ltng_damagemax_perlevel = 228;
|
||||
public static final short item_pois_damagemax_perlevel = 229;
|
||||
public static final short item_resist_cold_perlevel = 230;
|
||||
public static final short item_resist_fire_perlevel = 231;
|
||||
public static final short item_resist_ltng_perlevel = 232;
|
||||
public static final short item_resist_pois_perlevel = 233;
|
||||
public static final short item_absorb_cold_perlevel = 234;
|
||||
public static final short item_absorb_fire_perlevel = 235;
|
||||
public static final short item_absorb_ltng_perlevel = 236;
|
||||
public static final short item_absorb_pois_perlevel = 237;
|
||||
public static final short item_thorns_perlevel = 238;
|
||||
public static final short item_find_gold_perlevel = 239;
|
||||
public static final short item_find_magic_perlevel = 240;
|
||||
public static final short item_regenstamina_perlevel = 241;
|
||||
public static final short item_stamina_perlevel = 242;
|
||||
public static final short item_damage_demon_perlevel = 243;
|
||||
public static final short item_damage_undead_perlevel = 244;
|
||||
public static final short item_tohit_demon_perlevel = 245;
|
||||
public static final short item_tohit_undead_perlevel = 246;
|
||||
public static final short item_crushingblow_perlevel = 247;
|
||||
public static final short item_openwounds_perlevel = 248;
|
||||
public static final short item_kick_damage_perlevel = 249;
|
||||
public static final short item_deadlystrike_perlevel = 250;
|
||||
public static final short item_find_gems_perlevel = 251;
|
||||
public static final short item_replenish_durability = 252;
|
||||
public static final short item_replenish_quantity = 253;
|
||||
public static final short item_extra_stack = 254;
|
||||
public static final short item_find_item = 255;
|
||||
public static final short item_slash_damage = 256;
|
||||
public static final short item_slash_damage_percent = 257;
|
||||
public static final short item_crush_damage = 258;
|
||||
public static final short item_crush_damage_percent = 259;
|
||||
public static final short item_thrust_damage = 260;
|
||||
public static final short item_thrust_damage_percent = 261;
|
||||
public static final short item_absorb_slash = 262;
|
||||
public static final short item_absorb_crush = 263;
|
||||
public static final short item_absorb_thrust = 264;
|
||||
public static final short item_absorb_slash_percent = 265;
|
||||
public static final short item_absorb_crush_percent = 266;
|
||||
public static final short item_absorb_thrust_percent = 267;
|
||||
public static final short item_armor_bytime = 268;
|
||||
public static final short item_armorpercent_bytime = 269;
|
||||
public static final short item_hp_bytime = 270;
|
||||
public static final short item_mana_bytime = 271;
|
||||
public static final short item_maxdamage_bytime = 272;
|
||||
public static final short item_maxdamage_percent_bytime = 273;
|
||||
public static final short item_strength_bytime = 274;
|
||||
public static final short item_dexterity_bytime = 275;
|
||||
public static final short item_energy_bytime = 276;
|
||||
public static final short item_vitality_bytime = 277;
|
||||
public static final short item_tohit_bytime = 278;
|
||||
public static final short item_tohitpercent_bytime = 279;
|
||||
public static final short item_cold_damagemax_bytime = 280;
|
||||
public static final short item_fire_damagemax_bytime = 281;
|
||||
public static final short item_ltng_damagemax_bytime = 282;
|
||||
public static final short item_pois_damagemax_bytime = 283;
|
||||
public static final short item_resist_cold_bytime = 284;
|
||||
public static final short item_resist_fire_bytime = 285;
|
||||
public static final short item_resist_ltng_bytime = 286;
|
||||
public static final short item_resist_pois_bytime = 287;
|
||||
public static final short item_absorb_cold_bytime = 288;
|
||||
public static final short item_absorb_fire_bytime = 289;
|
||||
public static final short item_absorb_ltng_bytime = 290;
|
||||
public static final short item_absorb_pois_bytime = 291;
|
||||
public static final short item_find_gold_bytime = 292;
|
||||
public static final short item_find_magic_bytime = 293;
|
||||
public static final short item_regenstamina_bytime = 294;
|
||||
public static final short item_stamina_bytime = 295;
|
||||
public static final short item_damage_demon_bytime = 296;
|
||||
public static final short item_damage_undead_bytime = 297;
|
||||
public static final short item_tohit_demon_bytime = 298;
|
||||
public static final short item_tohit_undead_bytime = 299;
|
||||
public static final short item_crushingblow_bytime = 300;
|
||||
public static final short item_openwounds_bytime = 301;
|
||||
public static final short item_kick_damage_bytime = 302;
|
||||
public static final short item_deadlystrike_bytime = 303;
|
||||
public static final short item_find_gems_bytime = 304;
|
||||
public static final short item_pierce_cold = 305;
|
||||
public static final short item_pierce_fire = 306;
|
||||
public static final short item_pierce_ltng = 307;
|
||||
public static final short item_pierce_pois = 308;
|
||||
public static final short item_damage_vs_monster = 309;
|
||||
public static final short item_damage_percent_vs_monster = 310;
|
||||
public static final short item_tohit_vs_monster = 311;
|
||||
public static final short item_tohit_percent_vs_monster = 312;
|
||||
public static final short item_ac_vs_monster = 313;
|
||||
public static final short item_ac_percent_vs_monster = 314;
|
||||
public static final short firelength = 315;
|
||||
public static final short burningmin = 316;
|
||||
public static final short burningmax = 317;
|
||||
public static final short progressive_damage = 318;
|
||||
public static final short progressive_steal = 319;
|
||||
public static final short progressive_other = 320;
|
||||
public static final short progressive_fire = 321;
|
||||
public static final short progressive_cold = 322;
|
||||
public static final short progressive_lightning = 323;
|
||||
public static final short item_extra_charges = 324;
|
||||
public static final short progressive_tohit = 325;
|
||||
public static final short poison_count = 326;
|
||||
public static final short damage_framerate = 327;
|
||||
public static final short pierce_idx = 328;
|
||||
public static final short passive_fire_mastery = 329;
|
||||
public static final short passive_ltng_mastery = 330;
|
||||
public static final short passive_cold_mastery = 331;
|
||||
public static final short passive_pois_mastery = 332;
|
||||
public static final short passive_fire_pierce = 333;
|
||||
public static final short passive_ltng_pierce = 334;
|
||||
public static final short passive_cold_pierce = 335;
|
||||
public static final short passive_pois_pierce = 336;
|
||||
public static final short passive_critical_strike = 337;
|
||||
public static final short passive_dodge = 338;
|
||||
public static final short passive_avoid = 339;
|
||||
public static final short passive_evade = 340;
|
||||
public static final short passive_warmth = 341;
|
||||
public static final short passive_mastery_melee_th = 342;
|
||||
public static final short passive_mastery_melee_dmg = 343;
|
||||
public static final short passive_mastery_melee_crit = 344;
|
||||
public static final short passive_mastery_throw_th = 345;
|
||||
public static final short passive_mastery_throw_dmg = 346;
|
||||
public static final short passive_mastery_throw_crit = 347;
|
||||
public static final short passive_weaponblock = 348;
|
||||
public static final short passive_summon_resist = 349;
|
||||
public static final short modifierlist_skill = 350;
|
||||
public static final short modifierlist_level = 351;
|
||||
public static final short last_sent_hp_pct = 352;
|
||||
public static final short source_unit_type = 353;
|
||||
public static final short source_unit_id = 354;
|
||||
public static final short shortparam1 = 355;
|
||||
public static final short questitemdifficulty = 356;
|
||||
public static final short passive_mag_mastery = 357;
|
||||
public static final short passive_mag_pierce = 358;
|
||||
|
||||
static final int BITS = 9;
|
||||
static final short NONE = (1 << BITS) - 1; // 0x1FF
|
||||
|
||||
private static final byte[] ENCODED_COUNT = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 1, 3, 1, 1, 1, 1, 1, 1, // 32
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 160
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 192
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 224
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 256
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 288
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 320
|
||||
1, 1, 1, 1, 1, 1, 1, // 352
|
||||
};
|
||||
|
||||
static byte getNumEncoded(short stat) {
|
||||
return ENCODED_COUNT[stat];
|
||||
}
|
||||
|
||||
private Stat() {}
|
||||
}
|
109
core/src/com/riiablo/attributes/StatGetter.java
Normal file
109
core/src/com/riiablo/attributes/StatGetter.java
Normal file
@ -0,0 +1,109 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
public final class StatGetter {
|
||||
StatList stats;
|
||||
int index;
|
||||
|
||||
StatGetter() {}
|
||||
|
||||
StatGetter(StatList stats) {
|
||||
this.stats = stats;
|
||||
}
|
||||
|
||||
StatGetter set(StatList stats, int index) {
|
||||
this.stats = stats;
|
||||
this.index = index;
|
||||
return this;
|
||||
}
|
||||
|
||||
StatGetter update(int index) {
|
||||
assert stats != null;
|
||||
this.index = index;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @see StatList#param(int) */
|
||||
int param(short stat) {
|
||||
return stats.param(index);
|
||||
}
|
||||
|
||||
/** @see StatList#value(int) */
|
||||
int value(short stat) {
|
||||
return stats.value(index);
|
||||
}
|
||||
|
||||
/** @see StatList#id(int) */
|
||||
public short id() {
|
||||
return stats.id(index);
|
||||
}
|
||||
|
||||
/** @see StatList#asInt(int) */
|
||||
public int asInt() {
|
||||
return stats.asInt(index);
|
||||
}
|
||||
|
||||
/** @see StatList#asLong(int) */
|
||||
public long asLong() {
|
||||
return stats.asLong(index);
|
||||
}
|
||||
|
||||
/** @see StatList#asFixed(int) */
|
||||
public float asFixed() {
|
||||
return stats.asFixed(index);
|
||||
}
|
||||
|
||||
/** @see StatList#asString(int) */
|
||||
public String asString() {
|
||||
return stats.asString(index);
|
||||
}
|
||||
|
||||
/** @see StatList#indexDebugString(int) */
|
||||
public String debugString() {
|
||||
return stats.indexDebugString(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return asString();
|
||||
}
|
||||
|
||||
/** @see StatList#value1(int) */
|
||||
public int value1() {
|
||||
return stats.value1(index);
|
||||
}
|
||||
|
||||
/** @see StatList#value2(int) */
|
||||
public int value2() {
|
||||
return stats.value2(index);
|
||||
}
|
||||
|
||||
/** @see StatList#value3(int) */
|
||||
public int value3() {
|
||||
return stats.value3(index);
|
||||
}
|
||||
|
||||
/** @see StatList#param1(int) */
|
||||
public int param1() {
|
||||
return stats.param1(index);
|
||||
}
|
||||
|
||||
/** @see StatList#param2(int) */
|
||||
public int param2() {
|
||||
return stats.param2(index);
|
||||
}
|
||||
|
||||
/** @see StatList#add(int, int) */
|
||||
public void add(int value) {
|
||||
stats.add(index, value);
|
||||
}
|
||||
|
||||
/** @see StatList#add(int, long) */
|
||||
public void add(long value) {
|
||||
stats.add(index, value);
|
||||
}
|
||||
|
||||
/** @see StatList#add(int, float) */
|
||||
public void add(float value) {
|
||||
stats.add(index, value);
|
||||
}
|
||||
}
|
665
core/src/com/riiablo/attributes/StatList.java
Normal file
665
core/src/com/riiablo/attributes/StatList.java
Normal file
@ -0,0 +1,665 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
|
||||
import com.riiablo.Riiablo;
|
||||
import com.riiablo.codec.excel.ItemStatCost;
|
||||
import com.riiablo.logger.LogManager;
|
||||
import com.riiablo.logger.Logger;
|
||||
|
||||
public final class StatList {
|
||||
private static final Logger log = LogManager.getLogger(StatList.class);
|
||||
|
||||
public static StatList obtain() {
|
||||
return new StatList();
|
||||
}
|
||||
|
||||
public static StatList obtain(int maxLists) {
|
||||
return new StatList(maxLists);
|
||||
}
|
||||
|
||||
private static final StatList EMPTY_LIST = new StatList().freeze();
|
||||
public static StatList emptyList() {
|
||||
return EMPTY_LIST;
|
||||
}
|
||||
|
||||
private static final int MAX_LISTS = 8;
|
||||
private static final int MAX_STATS = 32;
|
||||
|
||||
/** @see #encodeFlags */
|
||||
private static final int ENCODING_MASK = (1 << 3) - 1;
|
||||
private static final int FLAG_PARAMS = 1 << 3;
|
||||
private static final int FLAG_FIXED = 1 << 4;
|
||||
private static final int FLAG_LONG = 1 << 5;
|
||||
|
||||
private static final long UINT_MAX_VALUE = (1L << Integer.SIZE) - 1;
|
||||
|
||||
private final byte[] offsets;
|
||||
private final short[] ids;
|
||||
private final int[] params;
|
||||
private final int[] values;
|
||||
private final byte[] flags;
|
||||
|
||||
private int maxLists;
|
||||
private int size;
|
||||
private int tail;
|
||||
private int numLists;
|
||||
private boolean immutable;
|
||||
|
||||
private IndexIterator INDEX_ITERATOR;
|
||||
private StatIterator STAT_ITERATOR;
|
||||
|
||||
StatList() {
|
||||
this(MAX_LISTS);
|
||||
}
|
||||
|
||||
StatList(int maxLists) {
|
||||
log.traceEntry("StatList(maxLists: {})", maxLists);
|
||||
assert maxLists > 0 : "maxLists(" + maxLists + ") <= " + 0;
|
||||
this.maxLists = maxLists;
|
||||
offsets = new byte[maxLists << 1];
|
||||
ids = new short[MAX_STATS];
|
||||
params = new int[MAX_STATS];
|
||||
values = new int[MAX_STATS];
|
||||
flags = new byte[MAX_STATS];
|
||||
}
|
||||
|
||||
public StatList freeze() {
|
||||
immutable = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
assertMutable();
|
||||
size = 0;
|
||||
tail = 0;
|
||||
numLists = 0;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public int size(int list) {
|
||||
return endingOffset(list) - startingOffset(list);
|
||||
}
|
||||
|
||||
public boolean isEmpty(int list) {
|
||||
return size(list) == 0;
|
||||
}
|
||||
|
||||
public int numLists() {
|
||||
return numLists;
|
||||
}
|
||||
|
||||
public void clearList(int list) {
|
||||
assertMutable();
|
||||
size -= size(list);
|
||||
final int offset = list << 1;
|
||||
final byte[] offsets = this.offsets;
|
||||
offsets[offset + 1] = offsets[offset];
|
||||
}
|
||||
|
||||
public int newList(int capacity) {
|
||||
assertMutable();
|
||||
if (numLists >= maxLists) { // should never exceed maxLists
|
||||
throw new AssertionError("numLists(" + numLists + ") >= maxLists(" + maxLists + ")");
|
||||
}
|
||||
|
||||
if (tail + capacity >= MAX_STATS) {
|
||||
throw new IllegalArgumentException("capacity(" + capacity + ") would exceed MAX_STATS(" + MAX_STATS + ")");
|
||||
}
|
||||
|
||||
final int list = numLists;
|
||||
final int offset = list << 1;
|
||||
final byte[] offsets = this.offsets;
|
||||
offsets[offset] = offsets[offset + 1] = (byte) tail;
|
||||
numLists++;
|
||||
ensureCapacity(list, capacity);
|
||||
return list;
|
||||
}
|
||||
|
||||
public StatListBuilder buildList() {
|
||||
return buildList(0);
|
||||
}
|
||||
|
||||
public StatListBuilder buildList(int capacity) {
|
||||
assertMutable();
|
||||
return new StatListBuilder(this, newList(capacity));
|
||||
}
|
||||
|
||||
public void ensureCapacity(int list, int capacity) {
|
||||
assertMutable();
|
||||
final int startOffset = startingOffset(list);
|
||||
final int endOffset = endingOffset(list);
|
||||
final int nextStartOffset = (list + 1) < numLists ? startingOffset(list + 1) : MAX_STATS;
|
||||
if (nextStartOffset - startOffset > capacity) {
|
||||
if (tail == endOffset) tail += capacity;
|
||||
return;
|
||||
}
|
||||
|
||||
final int additionalCapacity = capacity - (nextStartOffset - endOffset);
|
||||
if (tail + additionalCapacity >= MAX_STATS) {
|
||||
throw new IllegalArgumentException("capacity(" + capacity + ") would exceed MAX_STATS(" + MAX_STATS + ")");
|
||||
}
|
||||
|
||||
final int dstOffset = nextStartOffset + additionalCapacity;
|
||||
final int length = tail - nextStartOffset;
|
||||
System.arraycopy(ids, nextStartOffset, ids, dstOffset, length);
|
||||
System.arraycopy(params, nextStartOffset, params, dstOffset, length);
|
||||
System.arraycopy(values, nextStartOffset, values, dstOffset, length);
|
||||
System.arraycopy(flags, nextStartOffset, flags, dstOffset, length);
|
||||
tail += additionalCapacity;
|
||||
|
||||
final byte[] offsets = this.offsets;
|
||||
final int listsSize = numLists << 1;
|
||||
for (int i = ((list + 1) << 1); i < listsSize; i++) offsets[i] += additionalCapacity;
|
||||
assert isSorted(offsets, 0, listsSize) : "offsets(" + ByteBufUtil.hexDump(offsets, 0, listsSize) + ") contains property lists that are out of order";
|
||||
}
|
||||
|
||||
public StatList copy(int list, StatList src, int srcList) {
|
||||
assertMutable();
|
||||
final int length = src.size(srcList);
|
||||
ensureCapacity(list, length);
|
||||
|
||||
final int srcListStart = src.startingOffset(srcList);
|
||||
final int dstListStart = this.startingOffset(list);
|
||||
System.arraycopy(src.ids, srcListStart, this.ids, dstListStart, length);
|
||||
System.arraycopy(src.params, srcListStart, this.params, dstListStart, length);
|
||||
System.arraycopy(src.values, srcListStart, this.values, dstListStart, length);
|
||||
System.arraycopy(src.flags, srcListStart, this.flags, dstListStart, length);
|
||||
size += length;
|
||||
|
||||
final byte[] offsets = this.offsets;
|
||||
offsets[(list << 1) + 1] += length;
|
||||
assert isSorted(offsets, 0, numLists << 1) : "offsets(" + ByteBufUtil.hexDump(offsets, 0, numLists << 1) + ") contains property lists that are out of order";
|
||||
return this;
|
||||
}
|
||||
|
||||
public StatList set(int list, StatList src, int srcList) {
|
||||
assertMutable();
|
||||
clearList(list);
|
||||
copy(list, src, srcList);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StatList setAll(StatList src) {
|
||||
assertMutable();
|
||||
clear();
|
||||
final int length = src.tail;
|
||||
System.arraycopy(src.offsets, 0, this.offsets, 0, src.numLists() << 1);
|
||||
System.arraycopy(src.ids, 0, this.ids, 0, length);
|
||||
System.arraycopy(src.params, 0, this.params, 0, length);
|
||||
System.arraycopy(src.values, 0, this.values, 0, length);
|
||||
System.arraycopy(src.flags, 0, this.flags, 0, length);
|
||||
size = src.size;
|
||||
tail = src.tail;
|
||||
numLists = src.numLists;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StatListGetter get(int list) {
|
||||
return new StatListGetter(this, list);
|
||||
}
|
||||
|
||||
public int add(int index, int value) {
|
||||
assertMutable();
|
||||
log.traceEntry("add(index: {}, value: {})", index, value);
|
||||
final short stat = ids[index];
|
||||
assert !hasParams(stat) : "stat(" + stat + ") requires params";
|
||||
assert encoding(stat) <= 2 : "#add() unsupported for encoding(" + encoding(stat) + ")";
|
||||
if (log.debugEnabled()) log.debug(
|
||||
"add(stat: {} ({}), this: {}, src: {})",
|
||||
stat, entry(stat), asString(index), _asString(index, value));
|
||||
return values[index] += value;
|
||||
}
|
||||
|
||||
public int add(int index, long value) {
|
||||
return add(index, _asInt(value));
|
||||
}
|
||||
|
||||
public int add(int index, float value) {
|
||||
return add(index, _asInt(value));
|
||||
}
|
||||
|
||||
public int add(int list, short stat, StatList src, int srcList) {
|
||||
assertMutable();
|
||||
log.traceEntry("add(list: {}, stat: {}, src: {}, srcList: {})", list, stat, src, srcList);
|
||||
assert !hasParams(stat) : "stat(" + stat + ") requires params";
|
||||
assert encoding(stat) <= 2 : "#add() unsupported for encoding(" + encoding(stat) + ")";
|
||||
final int index = indexOf(list, stat, 0);
|
||||
final int otherIndex = src.indexOf(srcList, stat, 0);
|
||||
if (log.debugEnabled()) log.debug(
|
||||
"add(stat: {} ({}), this: {}, src: {})",
|
||||
stat, entry(stat), index >= 0 ? asString(index) : "null", src.asString(otherIndex));
|
||||
if (index >= 0) {
|
||||
values[index] += src.values[otherIndex];
|
||||
return index;
|
||||
} else {
|
||||
/** TODO: possibility to speed this up with {@link #insertAt} */
|
||||
final int putIndex = put(list, stat, src.values[otherIndex]);
|
||||
assert putIndex == ~index : "index(" + putIndex + ") != expected index(" + ~index + ")";
|
||||
return putIndex;
|
||||
}
|
||||
// max
|
||||
}
|
||||
|
||||
public void addAll(int list, StatList src, int srcList) {
|
||||
assertMutable();
|
||||
final int srcStartOffset = src.startingOffset(srcList);
|
||||
final int srcEndOffset = src.endingOffset(srcList);
|
||||
for (int i = srcStartOffset, s = srcEndOffset; i < s; i++) {
|
||||
final short stat = src.id(i);
|
||||
add(list, stat, src, srcList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated undefined behavior -- stat operations should be reversible,
|
||||
* i.e., subtracting a stat to it's default should remove it.
|
||||
* Validate that a value of 0 indicates default for all stats.
|
||||
* Maybe some stats allow 0 value and nonzero param?
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean sub(int list, short stat, StatList src, int srcList) {
|
||||
if (true) throw new UnsupportedOperationException();
|
||||
assertMutable();
|
||||
log.traceEntry("sub(list: {}, stat: {}, src: {}, srcList: {})", list, stat, src, srcList);
|
||||
assert !hasParams(stat) : "stat(" + stat + ") requires params";
|
||||
assert encoding(stat) <= 2 : "#sub() unsupported for encoding(" + encoding(stat) + ")";
|
||||
final int index = indexOf(list, stat, 0);
|
||||
final int otherIndex = src.indexOf(srcList, stat, 0);
|
||||
if (log.debugEnabled()) log.debug(
|
||||
"sub(stat: {} ({}), this: {}, src: {})",
|
||||
stat, entry(stat), index >= 0 ? asString(index) : "null", src.asString(otherIndex));
|
||||
assert index >= 0 : "property list does not contain stat(" + stat + ")";
|
||||
if (index < 0) return false; // indefined behavior
|
||||
values[index] -= src.values[otherIndex];
|
||||
// TODO: if values[index] <= 0, remove it? is <= 0 appropriate
|
||||
return true;
|
||||
// min
|
||||
}
|
||||
|
||||
/** @deprecated see {@link #sub} */
|
||||
@Deprecated
|
||||
public void subAll(int list, StatList src, int srcList) {
|
||||
assertMutable();
|
||||
final int srcStartOffset = src.startingOffset(srcList);
|
||||
final int srcEndOffset = src.endingOffset(srcList);
|
||||
for (int i = srcStartOffset, s = srcEndOffset; i < s; i++) {
|
||||
final short stat = src.id(i);
|
||||
sub(list, stat, src, srcList);
|
||||
}
|
||||
}
|
||||
|
||||
public int put(int list, short stat, int param, int value) {
|
||||
assertMutable();
|
||||
final ItemStatCost.Entry entry = entry(stat);
|
||||
final int encoding = entry.Encode;
|
||||
if (log.traceEnabled()) log.tracefEntry(
|
||||
"put(stat: %d (%s), param: %d (0x%3$x), value: %d (0x%4$x))", stat, entry, param, value);
|
||||
if (log.warnEnabled() && (encoding < 0 || encoding > 4)) log.warn(
|
||||
"stat: {} ({}) has unsupported encoding({})", stat, entry, encoding);
|
||||
|
||||
final int index = indexOf(list, stat, param);
|
||||
if (index >= 0) {
|
||||
set(index, stat, param, value, entry);
|
||||
if (log.debugEnabled()) log.debug(indexDebugString(index));
|
||||
return index;
|
||||
} else {
|
||||
insertAt(list, ~index, stat, param, value, entry);
|
||||
if (log.debugEnabled()) log.debug(indexDebugString(~index));
|
||||
return ~index;
|
||||
}
|
||||
}
|
||||
|
||||
public int put(int list, short stat, int value) {
|
||||
assert !hasParams(stat) : "stat(" + stat + ") requires params";
|
||||
return put(list, stat, 0, value);
|
||||
}
|
||||
|
||||
public int put(int list, short stat, long value) {
|
||||
assert !hasParams(stat) : "stat(" + stat + ") requires params";
|
||||
assert value <= UINT_MAX_VALUE : "value(" + value + ") > " + UINT_MAX_VALUE;
|
||||
return put(list, stat, 0, _asInt(value));
|
||||
}
|
||||
|
||||
public int put(int list, short stat, float value) {
|
||||
assert !hasParams(stat) : "stat(" + stat + ") requires params";
|
||||
assert entry(stat).ValShift == 8 : "entry.ValShift(" + entry(stat).ValShift + ") != " + 8;
|
||||
return put(list, stat, 0, _asInt(value));
|
||||
}
|
||||
|
||||
public boolean contains(int list) {
|
||||
return list >= 0 && list < numLists;
|
||||
}
|
||||
|
||||
public boolean contains(int list, short stat) {
|
||||
return Arrays.binarySearch(ids, startingOffset(list), endingOffset(list), stat) >= 0;
|
||||
}
|
||||
|
||||
public int indexOf(int list, short stat, int param) {
|
||||
final int listStart = startingOffset(list);
|
||||
final int listEnd = endingOffset(list);
|
||||
final int index = Arrays.binarySearch(ids, listStart, listEnd, stat);
|
||||
if (index >= 0) {
|
||||
final int startIndex = firstIndexOf(stat, index, listStart);
|
||||
final int endIndex = lastIndexOf(stat, index, listEnd);
|
||||
return Arrays.binarySearch(params, startIndex, endIndex, param);
|
||||
} else {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
public int indexOf(int list, short stat) {
|
||||
assert !hasParams(stat) : "stat(" + stat + ") requires params";
|
||||
return indexOf(list, stat, 0);
|
||||
}
|
||||
|
||||
private int firstIndexOf(final short stat, final int startIndex, final int listStart) {
|
||||
int i = startIndex - 1;
|
||||
final short[] ids = this.ids;
|
||||
while (i >= listStart && ids[i] == stat) i--;
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
private int lastIndexOf(final short stat, final int startIndex, final int listEnd) {
|
||||
int i = startIndex + 1;
|
||||
final short[] ids = this.ids;
|
||||
for (final int s = listEnd; i < s && ids[i] == stat; i++);
|
||||
return i;
|
||||
}
|
||||
|
||||
int asInt(int index) {
|
||||
return values[index];
|
||||
}
|
||||
|
||||
private static int _asInt(long value) {
|
||||
return (int) value;
|
||||
}
|
||||
|
||||
private static long _asLong(int value) {
|
||||
return value & UINT_MAX_VALUE;
|
||||
}
|
||||
|
||||
long asLong(int index) {
|
||||
assert entry(ids[index]).Send_Bits >= Integer.SIZE : "entry.Send_Bits(" + entry(ids[index]).Send_Bits + ") < " + Integer.SIZE;
|
||||
return _asLong(values[index]);
|
||||
}
|
||||
|
||||
private static int _asInt(float value) {
|
||||
return Fixed.floatToIntBits(value, 8);
|
||||
}
|
||||
|
||||
private static float _asFixed(int value) {
|
||||
return Fixed.intBitsToFloat(value, 8);
|
||||
}
|
||||
|
||||
float asFixed(int index) {
|
||||
assert entry(ids[index]).ValShift == 8 : "entry.ValShift(" + entry(ids[index]).ValShift + ") != " + 8;
|
||||
return _asFixed(values[index]);
|
||||
}
|
||||
|
||||
private String _asString(int index, int value) {
|
||||
final byte flags = this.flags[index];
|
||||
return (flags & FLAG_FIXED) == 0
|
||||
? (flags & FLAG_LONG) == 0
|
||||
? String.valueOf(value)
|
||||
: String.valueOf(_asLong(value))
|
||||
: String.valueOf(_asFixed(value));
|
||||
}
|
||||
|
||||
String asString(int index) {
|
||||
final byte flags = this.flags[index];
|
||||
return (flags & FLAG_FIXED) == 0
|
||||
? (flags & FLAG_LONG) == 0
|
||||
? String.valueOf(asInt(index))
|
||||
: String.valueOf(asLong(index))
|
||||
: String.valueOf(asFixed(index));
|
||||
}
|
||||
|
||||
public short id(int index) {
|
||||
return ids[index];
|
||||
}
|
||||
|
||||
public int encoding(int index) {
|
||||
return flags[index] & ENCODING_MASK;
|
||||
}
|
||||
|
||||
byte flags(int index) {
|
||||
return flags[index];
|
||||
}
|
||||
|
||||
int value(int index) {
|
||||
return values[index];
|
||||
}
|
||||
|
||||
int param(int index) {
|
||||
return params[index];
|
||||
}
|
||||
|
||||
public int value1(int index) {
|
||||
switch (encoding(index)) {
|
||||
default: // fall-through
|
||||
case 0: return values[index];
|
||||
case 1: return values[index];
|
||||
case 2: return values[index];
|
||||
case 3: return values[index] & 0xFF;
|
||||
case 4: return values[index] & 0x3;
|
||||
}
|
||||
}
|
||||
|
||||
public int value2(int index) {
|
||||
switch (encoding(index)) {
|
||||
default: // fall-through
|
||||
case 0: return 0;
|
||||
case 1: return 0;
|
||||
case 2: return 0;
|
||||
case 3: return (values[index] >>> 8) & 0xFF;
|
||||
case 4: return (values[index] >>> 2) & 0x3FF;
|
||||
}
|
||||
}
|
||||
|
||||
public int value3(int index) {
|
||||
switch (encoding(index)) {
|
||||
default: // fall-through
|
||||
case 0: return 0;
|
||||
case 1: return 0;
|
||||
case 2: return 0;
|
||||
case 3: return 0;
|
||||
case 4: return (values[index] >>> 12) & 0x3FF;
|
||||
}
|
||||
}
|
||||
|
||||
public int param1(int index) {
|
||||
switch (encoding(index)) {
|
||||
default: // fall-through
|
||||
case 0: return params[index];
|
||||
case 1: return params[index];
|
||||
case 2: return params[index] & 0x3F;
|
||||
case 3: return params[index] & 0x3F;
|
||||
case 4: return params[index];
|
||||
}
|
||||
}
|
||||
|
||||
public int param2(int index) {
|
||||
switch (encoding(index)) {
|
||||
default: // fall-through
|
||||
case 0: return 0;
|
||||
case 1: return 0;
|
||||
case 2: return (params[index] >>> 6) & 0x3FF;
|
||||
case 3: return (params[index] >>> 6) & 0x3FF;
|
||||
case 4: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int startingOffset(int list) {
|
||||
return offsets[(list << 1)] & 0xFF;
|
||||
}
|
||||
|
||||
private int endingOffset(int list) {
|
||||
return offsets[(list << 1) + 1] & 0xFF;
|
||||
}
|
||||
|
||||
private static boolean isSorted(final byte[] array, final int startIndex, final int endIndex) {
|
||||
if (endIndex - startIndex < 2) return true;
|
||||
byte previous = array[startIndex];
|
||||
for (int i = startIndex + 1; i < endIndex; i++) {
|
||||
final byte current = array[i];
|
||||
if (NumberUtils.compare(previous, current) > 0) {
|
||||
return false;
|
||||
}
|
||||
previous = current;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static byte encodeFlags(ItemStatCost.Entry entry) {
|
||||
byte flags = (byte) (entry.Encode & ENCODING_MASK);
|
||||
if (entry.Save_Param_Bits > 0) flags |= FLAG_PARAMS;
|
||||
if (entry.Send_Bits >= Integer.SIZE) flags |= FLAG_LONG;
|
||||
if (entry.ValShift > 0) flags |= FLAG_FIXED;
|
||||
return flags;
|
||||
}
|
||||
|
||||
private void set(int index, short stat, int param, int value, ItemStatCost.Entry entry) {
|
||||
if (log.traceEnabled()) log.tracefEntry(
|
||||
"set(index: %d, stat: %d (%s), param: %d (0x%4$x), value: %d (0x%5$x))", index, stat, entry, param, value);
|
||||
ids[index] = stat;
|
||||
params[index] = param;
|
||||
values[index] = value;
|
||||
flags[index] = encodeFlags(entry);
|
||||
}
|
||||
|
||||
private void insertAt(int list, int index, short stat, int param, int value, ItemStatCost.Entry entry) {
|
||||
if (log.traceEnabled()) log.tracefEntry(
|
||||
"insertAt(index: %d, stat: %d (%s), param: %d (0x%4$x), value: %d (0x%5$x))", index, stat, entry, param, value);
|
||||
|
||||
if (size >= MAX_STATS) {
|
||||
log.warn("stat(" + stat + ") cannot be inserted, property list is full!");
|
||||
return;
|
||||
}
|
||||
|
||||
ensureCapacity(list, 1);
|
||||
set(index, stat, param, value, entry);
|
||||
size++;
|
||||
|
||||
final byte[] offsets = this.offsets;
|
||||
offsets[(list << 1) + 1]++;
|
||||
final int listsSize = numLists << 1;
|
||||
for (int i = ((list + 1) << 1); i < listsSize; i++) offsets[i]++;
|
||||
assert isSorted(offsets, 0, listsSize) : "offsets(" + Arrays.toString(offsets) + ") contains property lists that are out of order";
|
||||
}
|
||||
|
||||
private void assertMutable() {
|
||||
if (immutable) throw new UnsupportedOperationException("Stat list has been frozen");
|
||||
}
|
||||
|
||||
public String indexDebugString(int index) {
|
||||
final byte flags = this.flags[index];
|
||||
switch (flags & ENCODING_MASK) {
|
||||
default: // fall-through
|
||||
case 0: return entry(ids[index]) + "(" + ids[index] + ")=" + ((flags & FLAG_PARAMS) == 0 ? asString(index) : (asString(index) + ":" + params[index]));
|
||||
case 1: return entry(ids[index]) + "(" + ids[index] + ")=" + param1(index) + ":" + value1(index);
|
||||
case 2: return entry(ids[index]) + "(" + ids[index] + ")=" + param1(index) + ":" + param2(index) + ":" + value1(index);
|
||||
case 3: return entry(ids[index]) + "(" + ids[index] + ")=" + param1(index) + ":" + param2(index) + ":" + value1(index) + ":" + value2(index);
|
||||
case 4: return entry(ids[index]) + "(" + ids[index] + ")=" + value1(index) + ":" + value2(index) + ":" + value3(index);
|
||||
}
|
||||
}
|
||||
|
||||
public String listDebugString(int list) {
|
||||
final int startIndex = startingOffset(list);
|
||||
final int endIndex = endingOffset(list);
|
||||
return new ToStringBuilder(this)
|
||||
.append("immutable", immutable)
|
||||
.append("offsets", '{' + StringUtils.join(offsets, ',', (list << 1), (list << 1) + 2) + '}')
|
||||
.append("ids", '{' + StringUtils.join(ids, ',', startIndex, endIndex) + '}')
|
||||
.append("values", '{' + StringUtils.join(values, ',', startIndex, endIndex) + '}')
|
||||
.append("params", '{' + StringUtils.join(params, ',', startIndex, endIndex) + '}')
|
||||
.append("flags", '{' + StringUtils.join(flags, ',', startIndex, endIndex) + '}')
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("immutable", immutable)
|
||||
.append("offsets", '{' + StringUtils.join(offsets, ',', 0, numLists << 1) + '}')
|
||||
.append("ids", '{' + StringUtils.join(ids, ',', 0, tail) + '}')
|
||||
.append("values", '{' + StringUtils.join(values, ',', 0, tail) + '}')
|
||||
.append("params", '{' + StringUtils.join(params, ',', 0, tail) + '}')
|
||||
.append("flags", '{' + StringUtils.join(flags, ',', 0, tail) + '}')
|
||||
.build();
|
||||
}
|
||||
|
||||
private static ItemStatCost.Entry entry(short stat) {
|
||||
return Riiablo.files.ItemStatCost.get(stat);
|
||||
}
|
||||
|
||||
private static boolean hasParams(short stat) {
|
||||
return false; // TODO: determine if stat requires params
|
||||
}
|
||||
|
||||
public IndexIterator indexIterator(int list) {
|
||||
return INDEX_ITERATOR == null
|
||||
? INDEX_ITERATOR = new IndexIterator().reset(list)
|
||||
: INDEX_ITERATOR.reset(list);
|
||||
}
|
||||
|
||||
public final class IndexIterator {
|
||||
int index;
|
||||
int endIndex;
|
||||
|
||||
IndexIterator reset(int list) {
|
||||
index = startingOffset(list);
|
||||
endIndex = endingOffset(list);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return index < endIndex;
|
||||
}
|
||||
|
||||
public int next() {
|
||||
return index++;
|
||||
}
|
||||
}
|
||||
|
||||
public StatIterator statIterator(int list) {
|
||||
return STAT_ITERATOR == null
|
||||
? STAT_ITERATOR = new StatIterator().reset(list)
|
||||
: STAT_ITERATOR.reset(list);
|
||||
}
|
||||
|
||||
public final class StatIterator implements Iterator<StatGetter> {
|
||||
final StatGetter stat = new StatGetter(StatList.this);
|
||||
int index;
|
||||
int endIndex;
|
||||
|
||||
StatIterator reset(int list) {
|
||||
index = startingOffset(list);
|
||||
endIndex = endingOffset(list);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < endIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatGetter next() {
|
||||
return stat.update(index++);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
47
core/src/com/riiablo/attributes/StatListBuilder.java
Normal file
47
core/src/com/riiablo/attributes/StatListBuilder.java
Normal file
@ -0,0 +1,47 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
public final class StatListBuilder {
|
||||
final StatList stats;
|
||||
final int list;
|
||||
|
||||
StatListBuilder(StatList stats, int list) {
|
||||
this.stats = stats;
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list index.
|
||||
*/
|
||||
public int build() {
|
||||
return list;
|
||||
}
|
||||
|
||||
/** @see StatList#get(int) */
|
||||
public StatListGetter get() {
|
||||
return stats.get(list);
|
||||
}
|
||||
|
||||
/** @see StatList#put(int, short, int, int) */
|
||||
public StatListBuilder put(short stat, int param, int value) {
|
||||
stats.put(list, stat, param, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @see StatList#put(int, short, int) */
|
||||
public StatListBuilder put(short stat, int value) {
|
||||
stats.put(list, stat, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @see StatList#put(int, short, long) */
|
||||
public StatListBuilder put(short stat, long value) {
|
||||
stats.put(list, stat, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @see StatList#put(int, short, float) */
|
||||
public StatListBuilder put(short stat, float value) {
|
||||
stats.put(list, stat, value);
|
||||
return this;
|
||||
}
|
||||
}
|
91
core/src/com/riiablo/attributes/StatListGetter.java
Normal file
91
core/src/com/riiablo/attributes/StatListGetter.java
Normal file
@ -0,0 +1,91 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
public final class StatListGetter {
|
||||
final StatList stats;
|
||||
final int list;
|
||||
final StatGetter tuple = new StatGetter();
|
||||
|
||||
StatListGetter(StatList stats, int list) {
|
||||
this.stats = stats;
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
int param(short stat) {
|
||||
return stats.param(indexOf(stat));
|
||||
}
|
||||
|
||||
int value(short stat) {
|
||||
return stats.value(indexOf(stat));
|
||||
}
|
||||
|
||||
int indexOf(short stat) {
|
||||
return stats.indexOf(list, stat);
|
||||
}
|
||||
|
||||
public boolean contains(short stat) {
|
||||
return stats.contains(list, stat);
|
||||
}
|
||||
|
||||
public StatGetter get(short stat) {
|
||||
final int index = indexOf(stat);
|
||||
if (index < 0) return null;
|
||||
return tuple.set(stats, index);
|
||||
}
|
||||
|
||||
public void addAll(StatListGetter src) {
|
||||
stats.addAll(list, src.stats, src.list);
|
||||
}
|
||||
|
||||
public StatList.IndexIterator indexIterator() {
|
||||
return stats.indexIterator(list);
|
||||
}
|
||||
|
||||
public StatList.StatIterator statIterator() {
|
||||
return stats.statIterator(list);
|
||||
}
|
||||
|
||||
public String debugString() {
|
||||
return stats.listDebugString(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return debugString();
|
||||
}
|
||||
|
||||
// public int asInt(short stat) {
|
||||
// return stats.asInt(indexOf(stat));
|
||||
// }
|
||||
|
||||
// public long asLong(short stat) {
|
||||
// return stats.asLong(indexOf(stat));
|
||||
// }
|
||||
|
||||
// public float asFixed(short stat) {
|
||||
// return stats.asFixed(indexOf(stat));
|
||||
// }
|
||||
|
||||
// public String asString(short stat) {
|
||||
// return stats.asString(indexOf(stat));
|
||||
// }
|
||||
|
||||
// public int value1(short stat) {
|
||||
// return stats.value1(indexOf(stat));
|
||||
// }
|
||||
|
||||
// public int value2(short stat) {
|
||||
// return stats.value2(indexOf(stat));
|
||||
// }
|
||||
|
||||
// public int value3(short stat) {
|
||||
// return stats.value3(indexOf(stat));
|
||||
// }
|
||||
|
||||
// public int param1(short stat) {
|
||||
// return stats.param1(indexOf(stat));
|
||||
// }
|
||||
|
||||
// public int param2(short stat) {
|
||||
// return stats.param2(indexOf(stat));
|
||||
// }
|
||||
}
|
18
core/src/com/riiablo/attributes/StatListWrapper.java
Normal file
18
core/src/com/riiablo/attributes/StatListWrapper.java
Normal file
@ -0,0 +1,18 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
public class StatListWrapper extends Attributes {
|
||||
StatListWrapper(StatList stats) {
|
||||
super(stats);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatListGetter list(int list) {
|
||||
assert list == 0 : "list(" + list + ") != " + 0;
|
||||
return super.list(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetToBase() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
160
core/test/com/riiablo/attributes/StatListTest.java
Normal file
160
core/test/com/riiablo/attributes/StatListTest.java
Normal file
@ -0,0 +1,160 @@
|
||||
package com.riiablo.attributes;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
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 StatListTest {
|
||||
@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);
|
||||
}
|
||||
|
||||
private static StatList newInstance() {
|
||||
return new StatList();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void strength() {
|
||||
StatList stats = newInstance();
|
||||
final int list = stats.newList(0);
|
||||
final int index = stats.put(0, Stat.strength, 15);
|
||||
Assert.assertTrue(stats.contains(list, Stat.strength));
|
||||
Assert.assertEquals(0, stats.param(index));
|
||||
Assert.assertEquals(15, stats.value(index));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void strength_builder() {
|
||||
StatList stats = newInstance();
|
||||
final int list = stats.buildList(0)
|
||||
.put(Stat.strength, 15)
|
||||
.build();
|
||||
final int index = stats.indexOf(list, Stat.strength);
|
||||
Assert.assertEquals(0, stats.param(index));
|
||||
Assert.assertEquals(15, stats.value(index));
|
||||
System.out.println(stats);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hitpoints() {
|
||||
StatList stats = newInstance();
|
||||
final int list = stats.buildList(0)
|
||||
.put(Stat.hitpoints, 1 << 8)
|
||||
.build();
|
||||
final int index = stats.indexOf(list, Stat.hitpoints);
|
||||
Assert.assertEquals(0, stats.param(index));
|
||||
Assert.assertEquals(1 << 8, stats.value(index));
|
||||
Assert.assertEquals(1.0f, stats.asFixed(index), 0f);
|
||||
System.out.println(stats);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hitpoints_float() {
|
||||
StatList stats = newInstance();
|
||||
final int list = stats.buildList(0)
|
||||
.put(Stat.hitpoints, 1.0f)
|
||||
.build();
|
||||
final int index = stats.indexOf(list, Stat.hitpoints);
|
||||
Assert.assertEquals(0, stats.param(index));
|
||||
Assert.assertEquals(1 << 8, stats.value(index));
|
||||
Assert.assertEquals(1.0f, stats.asFixed(index), 0f);
|
||||
System.out.println(stats);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void experience() {
|
||||
StatList stats = newInstance();
|
||||
final int list = stats.buildList(0)
|
||||
.put(Stat.experience, 0xFFFFFFFF)
|
||||
.build();
|
||||
final int index = stats.indexOf(list, Stat.experience);
|
||||
Assert.assertEquals(0, stats.param(index));
|
||||
Assert.assertEquals(0xFFFFFFFF, stats.value(index));
|
||||
Assert.assertEquals(0xFFFFFFFFL, stats.asLong(index));
|
||||
System.out.println(stats);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void experience_long() {
|
||||
StatList stats = newInstance();
|
||||
final int list = stats.buildList(0)
|
||||
.put(Stat.experience, 0xFFFFFFFFL)
|
||||
.build();
|
||||
final int index = stats.indexOf(list, Stat.experience);
|
||||
Assert.assertEquals(0, stats.param(index));
|
||||
Assert.assertEquals(0xFFFFFFFF, stats.value(index));
|
||||
Assert.assertEquals(0xFFFFFFFFL, stats.asLong(index));
|
||||
System.out.println(stats);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void strength_add() {
|
||||
StatList stats = newInstance();
|
||||
final int statsList = stats.buildList(0)
|
||||
.put(Stat.strength, 15)
|
||||
.build();
|
||||
final int statsIndex = stats.indexOf(statsList, Stat.strength);
|
||||
assert stats.asInt(statsIndex) == 15;
|
||||
StatList add = newInstance();
|
||||
final int addList = add.buildList(0)
|
||||
.put(Stat.strength, 5)
|
||||
.build();
|
||||
final int addIndex = stats.indexOf(addList, Stat.strength);
|
||||
assert add.asInt(addIndex) == 5;
|
||||
stats.add(statsList, Stat.strength, add, addList);
|
||||
Assert.assertEquals(0, stats.param(statsIndex));
|
||||
Assert.assertEquals(20, stats.value(statsIndex));
|
||||
Assert.assertEquals(0, add.param(addIndex));
|
||||
Assert.assertEquals(5, add.value(addIndex));
|
||||
System.out.println(stats);
|
||||
System.out.println(add);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void strength_add_internal() {
|
||||
StatList stats = newInstance();
|
||||
final int statsList = stats.buildList(0)
|
||||
.put(Stat.strength, 15)
|
||||
.build();
|
||||
final int statsIndex = stats.indexOf(statsList, Stat.strength);
|
||||
assert stats.asInt(statsIndex) == 15;
|
||||
final int addList = stats.buildList(0)
|
||||
.put(Stat.strength, 5)
|
||||
.build();
|
||||
final int addIndex = stats.indexOf(addList, Stat.strength);
|
||||
assert stats.asInt(addIndex) == 5;
|
||||
stats.add(statsList, Stat.strength, stats, addList);
|
||||
Assert.assertEquals(0, stats.param(statsIndex));
|
||||
Assert.assertEquals(20, stats.value(statsIndex));
|
||||
Assert.assertEquals(0, stats.param(addIndex));
|
||||
Assert.assertEquals(5, stats.value(addIndex));
|
||||
System.out.println(stats);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user