Rewrote stat format strings

Rewrote stat format strings (should be correct)
Rewrote item details builder
Changed stat impl to use a map for item inherent stats
Added inherent stats header
Added ethereal/socket footer
Added potion right click description
Added placeholders for many item inherent stats
This commit is contained in:
Collin Smith 2019-03-22 23:27:39 -07:00
parent 5af8068452
commit e643ad5cae
3 changed files with 345 additions and 61 deletions

View File

@ -1,10 +1,8 @@
package com.riiablo.codec.excel;
import com.riiablo.codec.excel.Excel;
import com.riiablo.codec.excel.ItemEntry;
public class Misc extends Excel<Misc.Entry> {
public static class Entry extends ItemEntry {
@Column public int spelldesc;
@Column public String spelldescstr;
}
}

View File

@ -1,5 +1,6 @@
package com.riiablo.item;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
@ -12,13 +13,16 @@ import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.IntSet;
import com.badlogic.gdx.utils.ObjectMap;
import com.riiablo.Riiablo;
import com.riiablo.codec.DC6;
import com.riiablo.codec.Index;
import com.riiablo.codec.StringTBL;
import com.riiablo.codec.excel.Inventory;
import com.riiablo.codec.excel.ItemEntry;
import com.riiablo.codec.excel.ItemTypes;
import com.riiablo.codec.excel.MagicAffix;
import com.riiablo.codec.excel.Misc;
import com.riiablo.codec.excel.SetItems;
import com.riiablo.codec.excel.UniqueItems;
import com.riiablo.codec.util.BBox;
@ -32,6 +36,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
import java.util.Arrays;
import java.util.Comparator;
import java.util.EnumMap;
import static com.riiablo.item.Quality.SET;
@ -63,6 +68,33 @@ public class Item extends Actor implements Disposable {
private static final Array<Stat.Instance>[] EMPTY_STAT_ARRAY = (Array<Stat.Instance>[]) new Array[0];
private static final ObjectMap<String, String> WEAPON_DESC = new ObjectMap<>();
static {
WEAPON_DESC.put("mace", "WeaponDescMace");
WEAPON_DESC.put("club", "WeaponDescMace");
WEAPON_DESC.put("hamm", "WeaponDescMace");
WEAPON_DESC.put("scep", "WeaponDescMace");
WEAPON_DESC.put("axe", "WeaponDescAxe");
WEAPON_DESC.put("taxe", "WeaponDescAxe");
WEAPON_DESC.put("swor", "WeaponDescSword");
WEAPON_DESC.put("knif", "WeaponDescDagger");
WEAPON_DESC.put("tkni", "WeaponDescDagger");
WEAPON_DESC.put("tpot", "WeaponDescThrownPotion");
WEAPON_DESC.put("jave", "WeaponDescJavelin");
WEAPON_DESC.put("ajav", "WeaponDescJavelin");
WEAPON_DESC.put("spea", "WeaponDescSpear");
WEAPON_DESC.put("aspe", "WeaponDescSpear");
WEAPON_DESC.put("bow", "WeaponDescBow");
WEAPON_DESC.put("abow", "WeaponDescBow");
WEAPON_DESC.put("staf", "WeaponDescStaff");
WEAPON_DESC.put("pole", "WeaponDescPoleArm");
WEAPON_DESC.put("xbow", "WeaponDescCrossBow");
WEAPON_DESC.put("h2h", "WeaponDescH2H");
WEAPON_DESC.put("h2h2", "WeaponDescH2H");
WEAPON_DESC.put("wand", "WeaponDescOrb");
WEAPON_DESC.put("orb", "WeaponDescOrb");
}
public int flags;
public int version; // 0 = pre-1.08; 1 = 1.08/1.09 normal; 2 = 1.10 normal; 100 = 1.08/1.09 expansion; 101 = 1.10 expansion
public Location location;
@ -86,6 +118,7 @@ public class Item extends Actor implements Disposable {
public int runewordData;
public String inscription;
public EnumMap<Stat, Stat.Instance> props;
public Array<Stat.Instance> stats[];
public ItemEntry base;
@ -147,6 +180,9 @@ public class Item extends Actor implements Disposable {
base = findBase(typeCode);
type = Riiablo.files.ItemTypes.get(base.type);
props = new EnumMap<>(Stat.class);
// TODO: copy base items stats
if ((flags & COMPACT) == COMPACT) {
id = 0;
level = 0;
@ -208,22 +244,20 @@ public class Item extends Actor implements Disposable {
bitStream.skip(1); // TODO: Unknown, this usually is 0, but is 1 on a Tome of Identify. (It's still 0 on a Tome of Townportal.)
stats = (Array<Stat.Instance>[]) new Array[7];
stats[0] = new Array<>(Stat.Instance.class);
if (type.is("armo")) {
stats[0].add(Stat.armorclass.read(bitStream));
props.put(Stat.armorclass, Stat.armorclass.read(bitStream));
}
if (type.is("armo") || type.is("weap")) {
Stat.Instance maxdurability = Stat.maxdurability.read(bitStream);
stats[0].add(maxdurability);
props.put(Stat.maxdurability, maxdurability);
if (maxdurability.value > 0) {
stats[0].add(Stat.durability.read(bitStream));
props.put(Stat.durability, Stat.durability.read(bitStream));
}
}
if ((flags & SOCKETED) == SOCKETED && (type.is("armo") || type.is("weap"))) {
stats[0].add(Stat.item_numsockets.read(bitStream));
props.put(Stat.item_numsockets, Stat.item_numsockets.read(bitStream));
}
if (type.is("book")) {
@ -232,7 +266,7 @@ public class Item extends Actor implements Disposable {
if (base.stackable) {
int quantity = bitStream.readUnsigned15OrLess(9);
stats[0].add(new Stat.Instance(Stat.quantity, quantity, 0));
props.put(Stat.quantity, new Stat.Instance(Stat.quantity, quantity, 0));
}
if (quality == SET) {
@ -244,9 +278,10 @@ public class Item extends Actor implements Disposable {
listsFlags = 0;
}
stats = (Array<Stat.Instance>[]) new Array[7];
for (int i = 0; i < 7; i++) {
if (((listsFlags >> i) & 1) == 1) {
if (i > 0) stats[i] = new Array<>(Stat.Instance.class);
stats[i] = new Array<>(Stat.Instance.class);
Array<Stat.Instance> stats = this.stats[i];
for (;;) {
int prop = bitStream.readUnsigned15OrLess(9);
@ -786,6 +821,13 @@ public class Item extends Actor implements Disposable {
string = Riiablo.string.lookup("RightClicktoOpen");
} else if (base.code.equalsIgnoreCase("bkd")) {
string = Riiablo.string.lookup("RightClicktoRead");
} else if (base instanceof Misc.Entry) {
Misc.Entry misc = (Misc.Entry) base;
if (misc.spelldesc > 0) {
string = Riiablo.string.lookup(misc.spelldescstr);
} else {
string = Riiablo.string.lookup("RightClicktoUse");
}
} else {
string = Riiablo.string.lookup("RightClicktoUse");
}
@ -794,6 +836,33 @@ public class Item extends Actor implements Disposable {
add(usable).center().space(SPACING).row();
}
if ((flags & COMPACT) == 0) {
Stat.Instance stat;
EnumMap<Stat, Stat.Instance> stats = Item.this.props;
if ((stat = stats.get(Stat.armorclass)) != null)
add(new Label(Riiablo.string.lookup("ItemStats1h") + " " + stat.value, font, Riiablo.colors.white)).center().space(SPACING).row();
if ((stat = stats.get(Stat.maxdamage)) != null) // TODO: Conditional 2 handed if barbarian, etc
add(new Label(Riiablo.string.lookup("ItemStats1l") + " " + stat.value, font, Riiablo.colors.white)).center().space(SPACING).row();
if (Item.this.type.is("shie")) {
add(new Label(Riiablo.string.lookup("ItemStats1r") + " " + 0, font, Riiablo.colors.white)).center().space(SPACING).row();
// TODO: if paladin, show smite damage -- ItemStats1o %d to %d
}
if ((stat = stats.get(Stat.durability)) != null)
add(new Label(Riiablo.string.lookup("ItemStats1d") + " " + stat.value + " " + Riiablo.string.lookup("ItemStats1j") + " " + stats.get(Stat.maxdurability).value, font, Riiablo.colors.white)).center().space(SPACING).row();
add(new Label(Riiablo.string.lookup("ItemStats1f") + " " + 0, font, Riiablo.colors.white)).center().space(SPACING).row();
add(new Label(Riiablo.string.lookup("ItemStats1e") + " " + 0, font, Riiablo.colors.white)).center().space(SPACING).row();
add(new Label(Riiablo.string.lookup("ItemStats1p") + " " + 0, font, Riiablo.colors.white)).center().space(SPACING).row();
if (Item.this.type.is("weap")) {
add(new Label(Riiablo.string.lookup(WEAPON_DESC.get(Item.this.base.type)) + " - " + 0, font, Riiablo.colors.white)).center().space(SPACING).row();
}
//for (Stat.Instance stat : stats.values()) {
// add(new Label(stat.stat.toString(), font, Riiablo.colors.white)).center().space(SPACING).row();
//}
}
// TODO: Detect stats with encoded groupings and auto join them into a grouped stat
for (int i = 0; i < stats.length; i++) {
Array<Stat.Instance> stats = Item.this.stats[i];
if (stats == null) continue;
@ -835,7 +904,7 @@ public class Item extends Actor implements Disposable {
stats.sort(new Comparator<Stat.Instance>() {
@Override
public int compare(Stat.Instance o1, Stat.Instance o2) {
return o1.stat.entry().descpriority - o2.stat.entry().descpriority;
return o2.stat.entry().descpriority - o1.stat.entry().descpriority;
}
});
@ -853,11 +922,32 @@ public class Item extends Actor implements Disposable {
}
}
label = new Label(stat.format(group), font);
String text = stat.format(group);
if (text == null) continue;
label = new Label(text, font, Riiablo.colors.blue); // Conditionally, set should be green
add(label).center().space(SPACING).row();
}
}
StringBuilder itemFlags = null;
if ((Item.this.flags & ETHEREAL) == ETHEREAL) {
itemFlags = new StringBuilder(32);
itemFlags.append(Riiablo.string.lookup(StringTBL.EXPANSION_OFFSET + 2745));
}
if ((Item.this.flags & SOCKETED) == SOCKETED) {
if (itemFlags != null) itemFlags.append(',').append(' ');
else itemFlags = new StringBuilder(16);
Stat.Instance stat = props.get(Stat.item_numsockets);
if (stat != null) {
itemFlags.append(Riiablo.string.lookup("Socketable")).append(' ').append('(').append(stat.value).append(')');
} else {
Gdx.app.error(TAG, "Item marked socketed, but missing item_numsockets: " + Item.this.getName());
}
}
if (itemFlags != null) {
add(new Label(itemFlags.toString(), font, Riiablo.colors.blue)).center().space(SPACING).row();
}
// TODO: This can be cleaned up later -- add support for set detection
if (quality == SET) {
add().height(font.getLineHeight()).space(SPACING).row();

View File

@ -386,6 +386,10 @@ public enum Stat {
1, 1, 1, 1, 1, 1, 1, // 352
};
private static final String[] BY_TIME = {
"ModStre9e", "ModStre9g", "ModStre9d", "ModStre9f",
};
private final ItemStatCost.Entry entry;
Stat() {
@ -424,76 +428,268 @@ public enum Stat {
this.param = param;
}
private static final StringBuilder builder = new StringBuilder(32);
private static final CharSequence SPACE = Riiablo.string.lookup("space");
private static final CharSequence DASH = Riiablo.string.lookup("dash");
private static final CharSequence PERCENT = Riiablo.string.lookup("percent");
private static final CharSequence PLUS = Riiablo.string.lookup("plus");
private static final CharSequence TO = Riiablo.string.lookup("ItemStast1k");
public String format(boolean group) {
ItemStatCost.Entry entry = stat.entry;
return group
? format(entry.dgrpfunc, entry.dgrpval, entry.dgrpstrpos, entry.dgrpstrneg, entry.dgrpstr2)
: format(entry.descfunc, entry.descval, entry.descstrpos, entry.descstrneg, entry.descstr2);
}
public String format(int func, int valmode, String strpos, String strneg, String str2) {
int value;
CharStats.Entry entry;
Skills.Entry skill;
SkillDesc.Entry desc;
switch (group ? stat.entry.dgrpfunc : stat.entry.descfunc) {
case 1: return String.format("+%d %s", value, descstr(group));
case 2: return String.format("%d%% %s", value, descstr());
case 3: return String.format("%d %s", value, descstr());
case 4: return String.format("+%d%% %s", value, descstr());
case 5: return String.format("%d%% %s", value * 100 / 128, descstr()); // TODO: item_howl -- verify
case 6: return String.format("+%d %s %s", value, descstr(), descstr2());
case 7: return String.format("%d%% %s %s", value, descstr(), descstr2());
case 8: return String.format("+%d%% %s %s", value, descstr(), descstr2());
case 9: return String.format("%d %s %s", value, descstr(), descstr2());
case 11: return Riiablo.string.format("ModStre9u", 1, value / 100);
case 12: return String.format("+%d %s", value, descstr());
case 13: return String.format("+%d %s", value, Riiablo.string.lookup(CharacterClass.get(param).entry().StrAllSkills));
case 14:
builder.setLength(0);
switch (func) {
case 1: // +%d %s1
value = this.value;
if (valmode == 1) builder.append(PLUS).append(value).append(SPACE);
builder.append(Riiablo.string.lookup(value < 0 ? strneg : strpos));
if (valmode == 2) builder.append(SPACE).append(PLUS).append(value);
return builder.toString();
case 2: // %d%% %s1
value = this.value;
if (valmode == 1) builder.append(value).append(PERCENT).append(SPACE);
builder.append(Riiablo.string.lookup(value < 0 ? strneg : strpos));
if (valmode == 2) builder.append(SPACE).append(value).append(PERCENT);
return builder.toString();
case 3: // %d %s1
value = this.value;
if (valmode == 1) builder.append(value).append(SPACE);
builder.append(Riiablo.string.lookup(value < 0 ? strneg : strpos));
if (valmode == 2) builder.append(SPACE).append(value);
return builder.toString();
case 4: // +%d%% %s1
value = this.value;
if (valmode == 1) builder.append(PLUS).append(value).append(PERCENT).append(SPACE);
builder.append(Riiablo.string.lookup(value < 0 ? strneg : strpos));
if (valmode == 2) builder.append(SPACE).append(PLUS).append(value).append(PERCENT);
return builder.toString();
case 5: // %d%% %s1
value = this.value * 100 / 128;
if (valmode == 1) builder.append(value).append(PERCENT).append(SPACE);
builder.append(Riiablo.string.lookup(value < 0 ? strneg : strpos));
if (valmode == 2) builder.append(SPACE).append(value).append(PERCENT);
return builder.toString();
case 6: // +%d %s1 %s2
value = this.value;
if (valmode == 1) builder.append(PLUS).append(value).append(SPACE);
builder
.append(Riiablo.string.lookup(value < 0 ? strneg : strpos))
.append(SPACE)
.append(Riiablo.string.lookup(str2));
if (valmode == 2) builder.append(SPACE).append(PLUS).append(value);
return builder.toString();
case 7: // %d%% %s1 %s2
value = this.value;
if (valmode == 1) builder.append(value).append(PERCENT).append(SPACE);
builder
.append(Riiablo.string.lookup(value < 0 ? strneg : strpos))
.append(SPACE)
.append(Riiablo.string.lookup(str2));
if (valmode == 2) builder.append(SPACE).append(value).append(PERCENT);
return builder.toString();
case 8: // +%d%% %s1 %s2
value = this.value;
if (valmode == 1) builder.append(PLUS).append(value).append(PERCENT).append(SPACE);
builder
.append(Riiablo.string.lookup(value < 0 ? strneg : strpos))
.append(SPACE)
.append(Riiablo.string.lookup(str2));
if (valmode == 2) builder.append(SPACE).append(PLUS).append(value).append(PERCENT);
return builder.toString();
case 9: // %d %s1 %s2
value = this.value;
if (valmode == 1) builder.append(value).append(SPACE);
builder
.append(Riiablo.string.lookup(value < 0 ? strneg : strpos))
.append(SPACE)
.append(Riiablo.string.lookup(str2));
if (valmode == 2) builder.append(SPACE).append(value);
return builder.toString();
case 10: // %d%% %s1 %s2
value = this.value * 100 / 128;
if (valmode == 1) builder.append(value).append(PERCENT).append(SPACE);
builder
.append(Riiablo.string.lookup(value < 0 ? strneg : strpos))
.append(SPACE)
.append(Riiablo.string.lookup(str2));
if (valmode == 2) builder.append(SPACE).append(value).append(PERCENT);
return builder.toString();
case 11: // Repairs 1 Durability in %d Seconds
value = 100 / this.value;
return Riiablo.string.format("ModStre9u", 1, value);
case 12: // +%d %s1
value = this.value;
if (valmode == 1) builder.append(PLUS).append(value).append(SPACE);
builder.append(Riiablo.string.lookup(value < 0 ? strneg : strpos));
if (valmode == 2) builder.append(SPACE).append(PLUS).append(value);
return builder.toString();
case 13: // +%d %s | +1 to Paladin Skills
value = this.value;
builder
.append(PLUS).append(value)
.append(SPACE)
.append(CharacterClass.get(param).entry().StrAllSkills);
return builder.toString();
case 14: // %s %s | +1 to Fire Skills (Sorceress Only)
value = this.value;
entry = CharacterClass.get((param >>> 3) & 0x3).entry();
return String.format("%s %s", Riiablo.string.format(entry.StrSkillTab[param & 0x7], value), Riiablo.string.lookup(entry.StrClassOnly));
case 15:
int e2p1 = (param >>> 6) & 0x3FF;
int e2p2 = param & 0x3F;
int e2p3 = value;
skill = Riiablo.files.skills.get(e2p1);
builder
.append(Riiablo.string.format(entry.StrSkillTab[param & 0x7], value))
.append(SPACE)
.append(Riiablo.string.lookup(entry.StrClassOnly));
return builder.toString();
case 15: // 15% chance to cast Level 5 Life Tap on Striking
value = this.value;
skill = Riiablo.files.skills.get(param2());
desc = Riiablo.files.skilldesc.get(skill.skilldesc);
return Riiablo.string.format(stat.entry.descstrpos, e2p3, e2p2, Riiablo.string.lookup(desc.str_name));
case 16:
return Riiablo.string.format(strpos, value, param1(), Riiablo.string.lookup(desc.str_name));
case 16: // Level 16 Defiance Aura When Equipped
value = this.value;
skill = Riiablo.files.skills.get(param);
desc = Riiablo.files.skilldesc.get(skill.skilldesc);
return Riiablo.string.format(stat.entry.descstrpos, value, Riiablo.string.lookup(desc.str_name));
case 19: return String.format(descstr(group), value);
case 20: return String.format("%d%% %s", -value, descstr());
case 22: return toString();
case 23: return toString();
return Riiablo.string.format(strpos, value, Riiablo.string.lookup(desc.str_name));
case 17: // +10 to Dexterity (Increases Near Dawn) // TODO: untested
// value needs to update based on time of day
if (valmode == 1) builder.append(PLUS).append(value3()).append(SPACE);
builder.append(Riiablo.string.lookup(strpos));
if (valmode == 2) builder.append(SPACE).append(PLUS).append(value3());
builder.append(SPACE).append(Riiablo.string.lookup(BY_TIME[value1()]));
return builder.toString();
case 18: // 50% Enhanced Defense (Increases Near Dawn) // TODO: untested
// value needs to update based on time of day
if (valmode == 1) builder.append(value3()).append(PERCENT).append(SPACE);
builder.append(Riiablo.string.lookup(strpos));
if (valmode == 2) builder.append(SPACE).append(value3()).append(PERCENT);
builder.append(SPACE).append(Riiablo.string.lookup(BY_TIME[value1()]));
return builder.toString();
case 19: // Formats strpos/strneg with value
value = this.value;
return Riiablo.string.format(value < 0 ? strneg : strpos, value);
case 20: // -%d%% %s1
value = -this.value;
if (valmode == 1) builder.append(value).append(PERCENT).append(SPACE);
builder.append(Riiablo.string.lookup(value < 0 ? strneg : strpos));
if (valmode == 2) builder.append(SPACE).append(value).append(PERCENT);
return builder.toString();
case 21: // -%d %s1
value = -this.value;
if (valmode == 1) builder.append(value).append(SPACE);
builder.append(Riiablo.string.lookup(value < 0 ? strneg : strpos));
if (valmode == 2) builder.append(SPACE).append(value);
return builder.toString();
case 22: // +%d%% %s1 %s | +3% Attack Rating Versus: %s // TODO: unsupported for now
return "ERROR 22";
case 23: // %d%% %s1 %s | 3% ReanimateAs: %s // TODO: unsupported for now
return "ERROR 23";
case 24:
int e3p1 = (param >>> 6) & 0x3FF;
int e3p2 = param & 0x3F;
int e3p3 = (value >>> 8) & 0xFF;
int e3p4 = value & 0xFF;
skill = Riiablo.files.skills.get(e3p1);
skill = Riiablo.files.skills.get(param2());
desc = Riiablo.files.skilldesc.get(skill.skilldesc);
return String.format("%s %d %s %s", Riiablo.string.lookup("ModStre10b"), e3p2, Riiablo.string.lookup(desc.str_name), Riiablo.string.format(stat.entry.descstrpos, e3p3, e3p4));
case 27:
builder
.append(Riiablo.string.lookup("ModStre10b")).append(SPACE)
.append(param1()).append(SPACE)
.append(Riiablo.string.lookup(desc.str_name)).append(SPACE)
.append(Riiablo.string.format(stat.entry.descstrpos, value1(), value2()));
return builder.toString();
case 25: // TODO: unsupported
return "ERROR 25";
case 26: // TODO: unsupported
return "ERROR 26";
case 27: // +1 to Lightning (Sorceress Only)
value = this.value;
skill = Riiablo.files.skills.get(param);
desc = Riiablo.files.skilldesc.get(skill.skilldesc);
entry = Riiablo.files.skills.getClass(skill.charclass).entry();
return String.format("+%d %s %s %s", value, Riiablo.string.lookup("ItemStast1k"), Riiablo.string.lookup(desc.str_name), Riiablo.string.lookup(entry.StrClassOnly));
case 28:
builder
.append(PLUS).append(value).append(SPACE)
.append(TO).append(SPACE)
.append(Riiablo.string.lookup(desc.str_name)).append(SPACE)
.append(Riiablo.string.lookup(entry.StrClassOnly));
return builder.toString();
case 28: // +1 to Teleport
value = this.value;
skill = Riiablo.files.skills.get(param);
desc = Riiablo.files.skilldesc.get(skill.skilldesc);
return String.format("+%d %s %s", value, Riiablo.string.lookup("ItemStast1k"), Riiablo.string.lookup(desc.str_name));
default: return toString();
builder
.append(PLUS).append(value).append(SPACE)
.append(TO).append(SPACE)
.append(Riiablo.string.lookup(desc.str_name));
return builder.toString();
default:
return null;
}
}
private String descstr() {
return Riiablo.string.lookup(value < 0 ? stat.entry.descstrneg : stat.entry.descstrpos);
public int value() {
return value1();
}
private String descstr(boolean group) {
if (group) {
return Riiablo.string.lookup(value < 0 ? stat.entry.dgrpstrneg : stat.entry.dgrpstrpos);
} else {
return Riiablo.string.lookup(value < 0 ? stat.entry.descstrneg : stat.entry.descstrpos);
public int param() {
return param1();
}
public int value1() {
switch (stat.entry.Encode) {
case 0: return value;
case 1: return value;
case 2: return value;
case 3: return value & 0xFF;
case 4: return value & 0x3;
default: return value;
}
}
private String descstr2() {
return Riiablo.string.lookup(stat.entry.descstr2);
public int value2() {
switch (stat.entry.Encode) {
case 0: return 0;
case 1: return 0;
case 2: return 0;
case 3: return (value >>> 8) & 0xFF;
case 4: return (value >>> 2) & 0x3FF;
default: return 0;
}
}
public int value3() {
switch (stat.entry.Encode) {
case 0: return 0;
case 1: return 0;
case 2: return 0;
case 3: return 0;
case 4: return (value >>> 12) & 0x3FF;
default: return 0;
}
}
public int param1() {
switch (stat.entry.Encode) {
case 0: return param;
case 1: return param;
case 2: return param & 0x3F;
case 3: return param & 0x3F;
case 4: return param;
default: return param;
}
}
public int param2() {
switch (stat.entry.Encode) {
case 0: return 0;
case 1: return 0;
case 2: return (param >>> 6) & 0x3FF;
case 3: return (param >>> 6) & 0x3FF;
case 4: return 0;
default: return 0;
}
}
@Override