Build kits from StartingKitTable.cfg
Kit is built from StartingKitTemplate._kits and looked up by race name, sex and class name like the client's kit map (0x620250), replacing the hard-coded racebaseclass IDs in GetKitIDByRaceClass. Equip slots come from each item's item_eq_slots_or, filled from the last cfg item so the weapon keeps RHELD. dbKitHandler and the ResultSet ctor stay until the removal commit. Parity (scripts/p42.py, dev static_rune_validkit vs cfg): 68/68 headers, 451/451 item sets, 449/451 kits with identical slots. Value changes: - Irekei female Mage kit 3 (182460/185090/29970) was kitNumber 4 in the DB, so the client's kit 3 was refused at creation; now selectable. - Dwarf male Fighter kits 4 and 5 list two boots; the DB put Black Cuffed Boots (185120) in CHEST. They are a FEET item, so they are now skipped with a warning and Black Riding Boots (185090) stay in FEET. - Old Half-Giant male (2019) now finds the Half-Giant male kits by name instead of a missing map entry. Noob gear item set unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5824f34a79
commit
c1e1ed9148
4 files changed
+100
-345
No files matched your search
+97
-331
@@ -1,3 +1,4 @@
|
||||
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
@@ -11,58 +12,65 @@ package engine.objects;
|
||||
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.mbEnums;
|
||||
import engine.mbEnums.EquipSlotType;
|
||||
import engine.mbEnums.ItemContainerType;
|
||||
import engine.mbEnums.OwnerType;
|
||||
import engine.parsers.objects.ItemTemplate;
|
||||
import engine.parsers.objects.RuneTemplate;
|
||||
import engine.parsers.objects.wpak.StartingKitTemplate;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class Kit extends AbstractGameObject {
|
||||
|
||||
public static HashMap<Integer, Boolean> NoobGearIDS = new HashMap<>();
|
||||
public static HashMap<Integer, ArrayList<Kit>> RaceClassIDMap = new HashMap<>();
|
||||
private final int raceBaseClassID;
|
||||
|
||||
// Keyed like the client's kit map (0x620250): race name, sex and class name, not rune ids
|
||||
private static final HashMap<String, ArrayList<Kit>> _kitsByRaceClass = new HashMap<>();
|
||||
|
||||
private final byte kitNumber;
|
||||
private final int legs;
|
||||
private final int chest;
|
||||
private final int feet;
|
||||
private final int offhand;
|
||||
private final int weapon;
|
||||
private final EnumMap<EquipSlotType, Integer> items = new EnumMap<>(EquipSlotType.class);
|
||||
|
||||
|
||||
/**
|
||||
* No Table ID Constructor
|
||||
*/
|
||||
public Kit(int raceBaseClassID, byte kitNumber, int legs, int chest,
|
||||
int feet, int offhand, int weapon) {
|
||||
public Kit(StartingKitTemplate template) {
|
||||
super();
|
||||
this.raceBaseClassID = raceBaseClassID;
|
||||
this.kitNumber = kitNumber;
|
||||
this.legs = legs;
|
||||
this.chest = chest;
|
||||
this.feet = feet;
|
||||
this.offhand = offhand;
|
||||
this.weapon = weapon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal Constructor
|
||||
*/
|
||||
public Kit(int raceBaseClassID, byte kitNumber, int legs, int chest,
|
||||
int feet, int offhand, int weapon, int newUUID) {
|
||||
super(newUUID);
|
||||
this.raceBaseClassID = raceBaseClassID;
|
||||
this.kitNumber = kitNumber;
|
||||
this.legs = legs;
|
||||
this.chest = chest;
|
||||
this.feet = feet;
|
||||
this.offhand = offhand;
|
||||
this.weapon = weapon;
|
||||
int itemID;
|
||||
ItemTemplate itemTemplate;
|
||||
EquipSlotType slot;
|
||||
|
||||
this.kitNumber = (byte) template.kit_number;
|
||||
|
||||
// The cfg lists the off-hand column before the weapon; fill from the end so the weapon takes RHELD
|
||||
for (int i = template.item_ids.size() - 1; i >= 0; i--) {
|
||||
itemID = template.item_ids.get(i);
|
||||
Kit.NoobGearIDS.put(itemID, true);
|
||||
itemTemplate = ItemTemplate._items.get(itemID);
|
||||
|
||||
if (itemTemplate == null) {
|
||||
Logger.warn("Kit " + kitKey(template.race, template.sex.name(), template.base_class) + " #" + this.kitNumber
|
||||
+ ": no item template " + itemID);
|
||||
continue;
|
||||
}
|
||||
|
||||
slot = freeSlot(itemTemplate);
|
||||
|
||||
if (slot == null) {
|
||||
Logger.warn("Kit " + kitKey(template.race, template.sex.name(), template.base_class) + " #" + this.kitNumber
|
||||
+ ": no free slot for item " + itemID);
|
||||
continue;
|
||||
}
|
||||
|
||||
this.items.put(slot, itemID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,34 +79,54 @@ public class Kit extends AbstractGameObject {
|
||||
public Kit(ResultSet rs) throws SQLException, UnknownHostException {
|
||||
super(rs);
|
||||
|
||||
this.raceBaseClassID = rs.getInt("RaceBaseClassesID");
|
||||
int raceBaseClassID = rs.getInt("RaceBaseClassesID");
|
||||
this.kitNumber = rs.getByte("kitNumber");
|
||||
|
||||
this.legs = rs.getInt("legs");
|
||||
this.chest = rs.getInt("chest");
|
||||
this.feet = rs.getInt("feet");
|
||||
this.offhand = rs.getInt("offhand");
|
||||
this.weapon = rs.getInt("weapon");
|
||||
if (Kit.RaceClassIDMap.containsKey(this.raceBaseClassID)) {
|
||||
Kit.RaceClassIDMap.get(this.raceBaseClassID).add(this);
|
||||
putColumn(EquipSlotType.LEGS, rs.getInt("legs"));
|
||||
putColumn(EquipSlotType.CHEST, rs.getInt("chest"));
|
||||
putColumn(EquipSlotType.FEET, rs.getInt("feet"));
|
||||
putColumn(EquipSlotType.LHELD, rs.getInt("offhand"));
|
||||
putColumn(EquipSlotType.RHELD, rs.getInt("weapon"));
|
||||
|
||||
if (Kit.RaceClassIDMap.containsKey(raceBaseClassID)) {
|
||||
Kit.RaceClassIDMap.get(raceBaseClassID).add(this);
|
||||
} else {
|
||||
ArrayList<Kit> tempList = new ArrayList<>();
|
||||
tempList.add(this);
|
||||
Kit.RaceClassIDMap.put(this.raceBaseClassID, tempList);
|
||||
Kit.RaceClassIDMap.put(raceBaseClassID, tempList);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadAllKits() {
|
||||
|
||||
Kit kit;
|
||||
String key;
|
||||
|
||||
for (StartingKitTemplate template : StartingKitTemplate._kits) {
|
||||
kit = new Kit(template);
|
||||
key = kitKey(template.race, template.sex.name(), template.base_class);
|
||||
_kitsByRaceClass.computeIfAbsent(key, k -> new ArrayList<>()).add(kit);
|
||||
}
|
||||
|
||||
if (this.legs != 0)
|
||||
Kit.NoobGearIDS.put(this.legs, true);
|
||||
if (this.chest != 0)
|
||||
Kit.NoobGearIDS.put(this.chest, true);
|
||||
if (this.feet != 0)
|
||||
Kit.NoobGearIDS.put(this.feet, true);
|
||||
if (this.offhand != 0)
|
||||
Kit.NoobGearIDS.put(this.offhand, true);
|
||||
if (this.weapon != 0)
|
||||
Kit.NoobGearIDS.put(this.weapon, true);
|
||||
Logger.info("Loaded " + StartingKitTemplate._kits.size() + " kits for " + _kitsByRaceClass.size() + " race/sex/class");
|
||||
}
|
||||
|
||||
public static Kit getKit(int raceRuneID, int baseClassRuneID, int kitNumber) {
|
||||
|
||||
RuneTemplate raceRune = RuneTemplate._runes.get(raceRuneID);
|
||||
RuneTemplate classRune = RuneTemplate._runes.get(baseClassRuneID);
|
||||
mbEnums.RaceType raceType = mbEnums.RaceType.getRaceTypebyRuneID(raceRuneID);
|
||||
ArrayList<Kit> kits;
|
||||
|
||||
if (raceRune == null || classRune == null || raceType == null)
|
||||
return null;
|
||||
|
||||
kits = _kitsByRaceClass.get(kitKey(raceRune.obj_name, raceType.getCharacterSex().name(), classRune.obj_name));
|
||||
|
||||
if (kits == null || kitNumber < 0 || kitNumber >= kits.size())
|
||||
return null;
|
||||
|
||||
return kits.get(kitNumber);
|
||||
}
|
||||
|
||||
public static boolean IsNoobGear(int itemID) {
|
||||
@@ -107,9 +135,9 @@ public class Kit extends AbstractGameObject {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
private static String kitKey(String race, String sex, String baseClass) {
|
||||
return race + " " + sex + " " + baseClass;
|
||||
}
|
||||
|
||||
private static boolean kitItemCreator(PlayerCharacter pc, int templateID, mbEnums.EquipSlotType slot) {
|
||||
|
||||
@@ -131,293 +159,31 @@ public class Kit extends AbstractGameObject {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int GetKitIDByRaceClass(final int raceID, final int classID) {
|
||||
switch (raceID) {
|
||||
case 2000:
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 2;
|
||||
case 2501:
|
||||
return 3;
|
||||
case 2502:
|
||||
return 4;
|
||||
case 2503:
|
||||
return 5;
|
||||
}
|
||||
case 2001:
|
||||
private EquipSlotType freeSlot(ItemTemplate itemTemplate) {
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 6;
|
||||
case 2501:
|
||||
return 7;
|
||||
case 2502:
|
||||
return 8;
|
||||
case 2503:
|
||||
return 9;
|
||||
}
|
||||
case 2002:
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 10;
|
||||
case 2501:
|
||||
return 11;
|
||||
case 2502:
|
||||
return 12;
|
||||
for (EquipSlotType slot : itemTemplate.item_eq_slots_or)
|
||||
if (!this.items.containsKey(slot))
|
||||
return slot;
|
||||
|
||||
}
|
||||
case 2003:
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 13;
|
||||
case 2501:
|
||||
return 14;
|
||||
case 2502:
|
||||
return 15;
|
||||
}
|
||||
case 2004:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 16;
|
||||
case 2501:
|
||||
return 17;
|
||||
}
|
||||
case 2005:
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 18;
|
||||
case 2501:
|
||||
return 19;
|
||||
}
|
||||
case 2006:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 20;
|
||||
case 2501:
|
||||
return 21;
|
||||
|
||||
}
|
||||
case 2008:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 22;
|
||||
case 2501:
|
||||
return 23;
|
||||
case 2502:
|
||||
return 24;
|
||||
case 2503:
|
||||
return 25;
|
||||
}
|
||||
|
||||
case 2009:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 26;
|
||||
case 2501:
|
||||
return 27;
|
||||
case 2502:
|
||||
return 28;
|
||||
case 2503:
|
||||
return 29;
|
||||
}
|
||||
case 2010:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 30;
|
||||
}
|
||||
|
||||
case 2011:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 31;
|
||||
case 2501:
|
||||
return 32;
|
||||
case 2502:
|
||||
return 33;
|
||||
case 2503:
|
||||
return 34;
|
||||
}
|
||||
|
||||
case 2012:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 35;
|
||||
case 2501:
|
||||
return 36;
|
||||
case 2502:
|
||||
return 37;
|
||||
case 2503:
|
||||
return 38;
|
||||
}
|
||||
|
||||
case 2013:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 39;
|
||||
case 2501:
|
||||
return 40;
|
||||
case 2502:
|
||||
return 41;
|
||||
case 2503:
|
||||
return 42;
|
||||
}
|
||||
|
||||
case 2014:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 43;
|
||||
case 2501:
|
||||
return 44;
|
||||
case 2502:
|
||||
return 45;
|
||||
case 2503:
|
||||
return 46;
|
||||
}
|
||||
|
||||
case 2015:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 47;
|
||||
case 2502:
|
||||
return 48;
|
||||
case 2503:
|
||||
return 49;
|
||||
|
||||
}
|
||||
|
||||
case 2016:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 50;
|
||||
case 2502:
|
||||
return 51;
|
||||
case 2503:
|
||||
return 52;
|
||||
|
||||
}
|
||||
|
||||
case 2017:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 53;
|
||||
case 2501:
|
||||
return 54;
|
||||
|
||||
}
|
||||
|
||||
case 2025:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 55;
|
||||
case 2501:
|
||||
return 56;
|
||||
case 2502:
|
||||
return 57;
|
||||
case 2503:
|
||||
return 58;
|
||||
}
|
||||
|
||||
case 2026:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 59;
|
||||
case 2501:
|
||||
return 60;
|
||||
case 2502:
|
||||
return 61;
|
||||
case 2503:
|
||||
return 62;
|
||||
}
|
||||
|
||||
case 2027:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 63;
|
||||
}
|
||||
|
||||
case 2028:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 64;
|
||||
|
||||
case 2502:
|
||||
return 65;
|
||||
case 2503:
|
||||
return 66;
|
||||
}
|
||||
|
||||
case 2029:
|
||||
|
||||
switch (classID) {
|
||||
case 2500:
|
||||
return 67;
|
||||
|
||||
case 2502:
|
||||
return 68;
|
||||
case 2503:
|
||||
return 69;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return -1;
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getRaceBaseClassID() {
|
||||
return raceBaseClassID;
|
||||
private void putColumn(EquipSlotType slot, int itemID) {
|
||||
|
||||
if (itemID == 0)
|
||||
return;
|
||||
|
||||
this.items.put(slot, itemID);
|
||||
Kit.NoobGearIDS.put(itemID, true);
|
||||
}
|
||||
|
||||
public byte getKitNumber() {
|
||||
return kitNumber;
|
||||
}
|
||||
|
||||
public int getLegs() {
|
||||
return legs;
|
||||
}
|
||||
|
||||
public int getChest() {
|
||||
return chest;
|
||||
}
|
||||
|
||||
public int getFeet() {
|
||||
return feet;
|
||||
}
|
||||
|
||||
public int getOffhand() {
|
||||
return offhand;
|
||||
}
|
||||
|
||||
public int getWeapon() {
|
||||
return weapon;
|
||||
}
|
||||
|
||||
public void equipPCwithKit(PlayerCharacter pc) {
|
||||
if (weapon != 0)
|
||||
kitItemCreator(pc, weapon, mbEnums.EquipSlotType.RHELD);
|
||||
if (offhand != 0)
|
||||
kitItemCreator(pc, offhand, mbEnums.EquipSlotType.LHELD);
|
||||
if (chest != 0)
|
||||
kitItemCreator(pc, chest, mbEnums.EquipSlotType.CHEST);
|
||||
if (legs != 0)
|
||||
kitItemCreator(pc, legs, mbEnums.EquipSlotType.LEGS);
|
||||
if (feet != 0)
|
||||
kitItemCreator(pc, feet, mbEnums.EquipSlotType.FEET);
|
||||
for (Map.Entry<EquipSlotType, Integer> entry : this.items.entrySet())
|
||||
kitItemCreator(pc, entry.getValue(), entry.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1100,18 +1100,7 @@ public class PlayerCharacter extends AbstractCharacter {
|
||||
|
||||
int kitID = msg.getKit();
|
||||
|
||||
// get the correctKit
|
||||
int raceClassID = Kit.GetKitIDByRaceClass(raceID, baseClassID);
|
||||
ArrayList<Kit> allKits = Kit.RaceClassIDMap.get(raceClassID);
|
||||
|
||||
Kit kit = null;
|
||||
|
||||
for (Kit k : allKits) {
|
||||
if (k.getKitNumber() == kitID) {
|
||||
kit = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Kit kit = Kit.getKit(raceID, baseClassID, kitID);
|
||||
|
||||
if (kit == null) {
|
||||
return refuseCreation(a, clientConnection, "Unable to find matching kitID: " + kitID);
|
||||
|
||||
@@ -390,7 +390,7 @@ public class LoginServer {
|
||||
Blueprint.loadAllBlueprints();
|
||||
|
||||
Logger.info("Loading Kits");
|
||||
DbManager.KitQueries.GET_ALL_KITS();
|
||||
Kit.LoadAllKits();
|
||||
|
||||
Logger.info("Initializing Race data");
|
||||
mbEnums.RaceType.initRaceTypeTables();
|
||||
|
||||
@@ -466,7 +466,7 @@ public class WorldServer {
|
||||
RealmMap.loadRealmImageMap();
|
||||
|
||||
Logger.info("Loading Kits");
|
||||
DbManager.KitQueries.GET_ALL_KITS();
|
||||
Kit.LoadAllKits();
|
||||
|
||||
Logger.info("Loading World Grid");
|
||||
WorldGrid.InitializeGridObjects();
|
||||
|
||||
Reference in new issue
Block a user