Files
Server/src/engine/gameManager/ItemManager.java
T
MagicBotandClaude Opus 5.5 7abc63ffc3 Read item skill requirements from the cache template
validForSkills, isShield, the guard attack rating and the NPC vendor skill
filter read getItemSkillReq. Offline parity (p15d.py, 7586 rows): 0
differences. No template lists "Cloth" in item_skill_req and none has more
than one entry, so file order vs HashMap order is moot.

Value changes: none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:28:32 -04:00

225 lines
7.8 KiB
Java

package engine.gameManager;
import engine.mbEnums;
import engine.objects.*;
import engine.powers.EffectsBase;
import org.pmw.tinylog.Logger;
import java.util.EnumSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
public enum ItemManager {
ITEMMANAGER;
public static final AtomicInteger lastNegativeID = new AtomicInteger(0);
// restrict true: the set is a blacklist; false: a whitelist. An empty set allows everyone.
public static Boolean ValidRace(Item item, mbEnums.MonsterType race) {
EnumSet<mbEnums.MonsterType> races = item.template.cacheTemplate.getItemRaceReq();
boolean restrict = item.template.cacheTemplate.getItemRaceReqRestrict();
if (races.isEmpty())
return true;
return races.contains(race) != restrict;
}
public static Boolean ValidClass(Item item, mbEnums.ClassType base, mbEnums.ClassType profession) {
EnumSet<mbEnums.ClassType> classes = item.template.cacheTemplate.getItemClassReq();
boolean restrict = item.template.cacheTemplate.getItemClassReqRestrict();
boolean listed;
if (classes.isEmpty())
return true;
listed = classes.contains(base) || classes.contains(profession);
return listed != restrict;
}
public static Boolean ValidDiscipline(Item item, EnumSet<mbEnums.DisciplineType> discs) {
EnumSet<mbEnums.DisciplineType> disciplines = item.template.cacheTemplate.getItemDiscReq();
boolean restrict = item.template.cacheTemplate.getItemDiscReqRestrict();
EnumSet<mbEnums.DisciplineType> workSet;
if (disciplines.isEmpty())
return true;
workSet = EnumSet.copyOf(discs);
workSet.retainAll(disciplines);
return workSet.isEmpty() == restrict;
}
public static Boolean canCharacterEquip(Item item, AbstractCharacter character) {
return ValidRace(item, character.absRace) && ValidClass(item, character.absBaseClass, character.absPromotionClass) && ValidDiscipline(item, character.absDisciplines);
}
public static boolean validForSkills(Item item, ConcurrentHashMap<String, CharacterSkill> skills) {
CharacterSkill characterSkill;
if (item.template.cacheTemplate.getItemSkillReq().isEmpty())
return true;
for (String skillRequired : item.template.cacheTemplate.getItemSkillReq().keySet()) {
int required_value = item.template.cacheTemplate.getItemSkillReq().get(skillRequired);
characterSkill = skills.get(skillRequired);
if (characterSkill == null)
return false;
if (characterSkill.getModifiedAmountBeforeMods() >= required_value)
return true;
}
return false;
}
public static boolean isTwoHanded(Item item) {
if (!item.template.cacheTemplate.getItemType().equals(mbEnums.ItemType.WEAPON))
return false;
return item.template.cacheTemplate.getItemEqSlotsAnd().containsAll(EnumSet.of(mbEnums.EquipSlotType.LHELD, mbEnums.EquipSlotType.RHELD));
}
public static boolean isTwoHanded(ItemTemplate template) {
if (!template.cacheTemplate.getItemType().equals(mbEnums.ItemType.WEAPON))
return false;
return template.cacheTemplate.getItemEqSlotsAnd().containsAll(EnumSet.of(mbEnums.EquipSlotType.LHELD, mbEnums.EquipSlotType.RHELD));
}
public static boolean isShield(Item item) {
if (item.template.cacheTemplate.getItemSkillReq().containsKey("Block"))
return true;
return false;
}
public static boolean isShield(ItemTemplate template) {
if (template.cacheTemplate.getItemSkillReq().containsKey("Block"))
return true;
return false;
}
public static boolean validForSlot(mbEnums.EquipSlotType slot, ConcurrentHashMap<mbEnums.EquipSlotType, Item> equipped, Item item) {
boolean validSlot = false;
if (equipped == null)
return false;
//Item not valid for slot
if (item.template.cacheTemplate.getItemEqSlotsOr().contains(slot) == false)
return false;
// Slot is taken
if (equipped.get(slot) != null && equipped.get(slot).equals(item) == false)
return false;
// Two handed weapons take up two slots
if ((isTwoHanded(item)) &&
((slot == mbEnums.EquipSlotType.LHELD && equipped.get(mbEnums.EquipSlotType.RHELD) != null) ||
(slot == mbEnums.EquipSlotType.RHELD && equipped.get(mbEnums.EquipSlotType.LHELD) != null)))
return false;
if (item.template.cacheTemplate.getItemType().equals(mbEnums.ItemType.WEAPON))
if (equipped.get(slot) != null && equipped.get(slot).equals(item) == false)
return false;
return true;
}
public static boolean canEquip(mbEnums.EquipSlotType slot, CharacterItemManager itemManager, AbstractCharacter abstractCharacter, Item item) {
if (itemManager == null || abstractCharacter == null)
return false;
// Early exit for mobiles and NPCS.
// Perhaps not needed now that mobs have skills.
if (EnumSet.of(mbEnums.GameObjectType.NPC, mbEnums.GameObjectType.Mob).contains(abstractCharacter.getObjectType()))
return false;
if (!validForSlot(slot, itemManager.getEquipped(), item))
return false;
if (!validForSkills(item, abstractCharacter.getSkills()))
return false;
if (!ValidRace(item, abstractCharacter.absRace))
return false;
if (!ValidClass(item, abstractCharacter.absBaseClass, abstractCharacter.absPromotionClass))
return false;
//players can't wear 0 value items.
return item.template.cacheTemplate.getItemValue() != 0 || Kit.IsNoobGear(item.templateID);
}
public static boolean MakeItemForPlayer(int templateID, PlayerCharacter reciever, int amount) {
boolean itemWorked = false;
Item item = new Item(templateID);
item.ownerID = reciever.getObjectUUID();
item.ownerType = mbEnums.OwnerType.PlayerCharacter;
item.containerType = mbEnums.ItemContainerType.INVENTORY;
item.numberOfItems = amount;
try {
item = DbManager.ItemQueries.PERSIST(item);
itemWorked = true;
} catch (Exception e) {
Logger.error(e);
}
if (!itemWorked)
return false;
reciever.charItemManager.addItemToInventory(item);
reciever.charItemManager.updateInventory();
return true;
}
public static void applyItemEffects(Item forgedItem) {
if (forgedItem.prefixToken != 0) {
EffectsBase prefix = PowersManager.getEffectByToken(forgedItem.prefixToken);
forgedItem.addPermanentEnchantment(prefix.getIDString(), 0);
}
if (forgedItem.suffixToken != 0) {
EffectsBase suffix = PowersManager.getEffectByToken(forgedItem.suffixToken);
forgedItem.addPermanentEnchantment(suffix.getIDString(), 0);
}
}
}