Debug and inventory
This commit is contained in:
parent
1febf6e918
commit
80a0a16bab
15 changed files with 2764 additions and 341 deletions
|
|
@ -254,6 +254,18 @@ def translate_item_type(item_type_id: int) -> str:
|
|||
item_types = ENUM_MAPPINGS.get('item_types', {})
|
||||
return item_types.get(item_type_id, f"Unknown_ItemType_{item_type_id}")
|
||||
|
||||
def derive_item_type_from_object_class(object_class: int, item_data: dict = None) -> str:
|
||||
"""Derive ItemType from ObjectClass using the object_classes enum."""
|
||||
# Use the object_classes enum directly for accurate classifications
|
||||
object_classes = ENUM_MAPPINGS.get('object_classes', {})
|
||||
item_type = object_classes.get(object_class)
|
||||
|
||||
if item_type:
|
||||
return item_type
|
||||
else:
|
||||
# Fallback to "Misc" if ObjectClass not found in enum
|
||||
return "Misc"
|
||||
|
||||
def translate_object_class(object_class_id: int, item_data: dict = None) -> str:
|
||||
"""Translate object class ID to human-readable name with context-aware detection."""
|
||||
# Use the extracted ObjectClass enum first
|
||||
|
|
@ -573,6 +585,17 @@ def translate_equipment_slot(wielded_location: int) -> str:
|
|||
}
|
||||
return name_mapping.get(slot_name, slot_name)
|
||||
|
||||
# Handle common equipment slots that may be missing from enum database
|
||||
common_slots = {
|
||||
30: "Shirt", # ChestWear + AbdomenWear + UpperArmWear + LowerArmWear for shirts
|
||||
786432: "Left Ring, Right Ring", # 262144 + 524288 for rings that can go in either slot
|
||||
262144: "Left Ring",
|
||||
524288: "Right Ring"
|
||||
}
|
||||
|
||||
if wielded_location in common_slots:
|
||||
return common_slots[wielded_location]
|
||||
|
||||
# If no exact match, decode bit flags
|
||||
slot_parts = []
|
||||
for mask_value, slot_name in equip_mask_map.items():
|
||||
|
|
@ -627,7 +650,7 @@ def translate_equipment_slot(wielded_location: int) -> str:
|
|||
else:
|
||||
return f"Special Slot ({wielded_location})"
|
||||
|
||||
return f"Unknown Slot ({wielded_location})"
|
||||
return "-"
|
||||
|
||||
def translate_workmanship(workmanship_value: int) -> str:
|
||||
"""Translate workmanship value to descriptive text."""
|
||||
|
|
@ -845,10 +868,21 @@ def get_comprehensive_translations(item_data: Dict[str, Any]) -> Dict[str, Any]:
|
|||
translations['material_name'] = translate_material_type(material_id)
|
||||
translations['material_id'] = material_id
|
||||
|
||||
# Translate item type if present
|
||||
# Translate item type if present (check ItemType field or IntValues[1])
|
||||
item_type_id = item_data.get('ItemType')
|
||||
if item_type_id is None:
|
||||
# Check IntValues for ItemType (key 1)
|
||||
int_values = item_data.get('IntValues', {})
|
||||
if isinstance(int_values, dict):
|
||||
item_type_id = int_values.get('1', int_values.get(1))
|
||||
|
||||
if item_type_id is not None:
|
||||
translations['item_type_name'] = translate_item_type(item_type_id)
|
||||
else:
|
||||
# Fallback: derive ItemType from ObjectClass
|
||||
object_class = item_data.get('ObjectClass')
|
||||
if object_class is not None:
|
||||
translations['item_type_name'] = derive_item_type_from_object_class(object_class, item_data)
|
||||
|
||||
# Translate object class using WeenieType enum
|
||||
object_class = item_data.get('ObjectClass')
|
||||
|
|
@ -880,7 +914,7 @@ def extract_item_properties(item_data: Dict[str, Any]) -> Dict[str, Any]:
|
|||
# Item state
|
||||
'bonded': int_values.get('33', int_values.get(33, 0)),
|
||||
'attuned': int_values.get('114', int_values.get(114, 0)),
|
||||
'unique': int_values.get('279', int_values.get(279, 0)) != 0,
|
||||
'unique': bool(int_values.get('279', int_values.get(279, 0))),
|
||||
|
||||
# Stack/Container properties
|
||||
'stack_size': int_values.get('12', int_values.get(12, 1)),
|
||||
|
|
@ -941,11 +975,11 @@ def extract_item_properties(item_data: Dict[str, Any]) -> Dict[str, Any]:
|
|||
'equip_skill': item_data.get('EquipSkill'),
|
||||
},
|
||||
'enhancements': {
|
||||
'material': item_data.get('Material'),
|
||||
'material': None, # Will be set below with proper logic
|
||||
'imbue': item_data.get('Imbue'),
|
||||
'tinks': item_data.get('Tinks', -1),
|
||||
'workmanship': item_data.get('Workmanship', -1.0),
|
||||
'item_set': int_values.get('265', int_values.get(265)) if int_values.get('265', int_values.get(265)) else None,
|
||||
'item_set': None, # Will be set below with translation
|
||||
|
||||
# Advanced tinkering
|
||||
'num_times_tinkered': int_values.get('171', int_values.get(171, -1)),
|
||||
|
|
@ -997,6 +1031,32 @@ def extract_item_properties(item_data: Dict[str, Any]) -> Dict[str, Any]:
|
|||
}
|
||||
}
|
||||
|
||||
# Handle material field properly - check if already translated or needs translation
|
||||
material_field = item_data.get('Material')
|
||||
if material_field and isinstance(material_field, str):
|
||||
# Material is already a translated string (like "Gold", "Iron", "Brass")
|
||||
properties['enhancements']['material'] = material_field
|
||||
else:
|
||||
# Material needs translation from IntValues[131]
|
||||
material_id = int_values.get('131', int_values.get(131))
|
||||
if material_id:
|
||||
material_name = translate_material_type(material_id)
|
||||
# Only store if translation succeeded (not "Unknown_Material_*")
|
||||
if not material_name.startswith('Unknown_Material_'):
|
||||
properties['enhancements']['material'] = material_name
|
||||
|
||||
# Translate item_set ID to name for database storage
|
||||
item_set_id = int_values.get('265', int_values.get(265))
|
||||
if item_set_id:
|
||||
dictionaries = ENUM_MAPPINGS.get('dictionaries', {})
|
||||
attribute_set_info = dictionaries.get('AttributeSetInfo', {}).get('values', {})
|
||||
set_name = attribute_set_info.get(str(item_set_id))
|
||||
if set_name:
|
||||
properties['enhancements']['item_set'] = set_name
|
||||
else:
|
||||
# Fallback to just store the ID as string
|
||||
properties['enhancements']['item_set'] = str(item_set_id)
|
||||
|
||||
# Get comprehensive translations
|
||||
translations = get_comprehensive_translations(item_data)
|
||||
if translations:
|
||||
|
|
@ -1113,6 +1173,14 @@ async def process_inventory(inventory: InventoryItem):
|
|||
|
||||
# Simple INSERT since we cleared the table first
|
||||
basic = properties['basic']
|
||||
|
||||
# Debug logging for problematic items
|
||||
if item_id in [-2133380247, -2144880287, -2136150336]:
|
||||
logger.info(f"Debug item {item_id}: basic={basic}")
|
||||
logger.info(f"Debug item {item_id}: name='{basic['name']}' type={type(basic['name'])}")
|
||||
logger.info(f"Debug item {item_id}: current_wielded_location={basic['current_wielded_location']} type={type(basic['current_wielded_location'])}")
|
||||
logger.info(f"Debug item {item_id}: enhancements={properties['enhancements']}")
|
||||
|
||||
item_stmt = sa.insert(Item).values(
|
||||
character_name=inventory.character_name,
|
||||
item_id=item_id,
|
||||
|
|
@ -1316,9 +1384,12 @@ async def get_character_inventory(
|
|||
# Add translated properties to the item
|
||||
processed_item['translated_properties'] = properties
|
||||
|
||||
# Add material translation
|
||||
# Add material name - use material directly if it's already a string
|
||||
if processed_item.get('material'):
|
||||
processed_item['material_name'] = translate_material_type(processed_item['material'])
|
||||
if isinstance(processed_item['material'], str):
|
||||
processed_item['material_name'] = processed_item['material']
|
||||
else:
|
||||
processed_item['material_name'] = translate_material_type(processed_item['material'])
|
||||
|
||||
# Add object class translation
|
||||
if processed_item.get('object_class'):
|
||||
|
|
@ -1430,6 +1501,8 @@ async def get_character_inventory(
|
|||
processed_item['material_name'] = trans['material_name']
|
||||
if trans.get('material_id'):
|
||||
processed_item['material_id'] = trans['material_id']
|
||||
if trans.get('item_type_name'):
|
||||
processed_item['item_type_name'] = trans['item_type_name']
|
||||
|
||||
# Continue with other enhancements
|
||||
if 'enhancements' in translated_props:
|
||||
|
|
@ -2092,11 +2165,15 @@ async def search_items(
|
|||
if item.get('material') or properties.get('translations', {}).get('material_name'):
|
||||
material_name = None
|
||||
if item.get('material'):
|
||||
material_name = translate_material_type(item['material'])
|
||||
# Check if material is already a string or needs translation
|
||||
if isinstance(item['material'], str):
|
||||
material_name = item['material']
|
||||
else:
|
||||
material_name = translate_material_type(item['material'])
|
||||
elif properties.get('translations', {}).get('material_name'):
|
||||
material_name = properties['translations']['material_name']
|
||||
|
||||
if material_name:
|
||||
if material_name and not material_name.startswith('Unknown_Material_'):
|
||||
item['material_name'] = material_name
|
||||
# Apply material prefix to item name
|
||||
original_name = item['name']
|
||||
|
|
@ -2108,6 +2185,13 @@ async def search_items(
|
|||
if item.get('object_class'):
|
||||
item['object_class_name'] = translate_object_class(item['object_class'], original_json)
|
||||
|
||||
# Add item type translation
|
||||
if properties.get('translations', {}).get('item_type_name'):
|
||||
item['item_type_name'] = properties['translations']['item_type_name']
|
||||
elif item.get('object_class'):
|
||||
# Fallback: derive ItemType from object_class when translation is missing
|
||||
item['item_type_name'] = derive_item_type_from_object_class(item['object_class'], {'Name': item.get('name', '')})
|
||||
|
||||
# Add spell information
|
||||
if 'spells' in properties:
|
||||
spell_info = properties['spells']
|
||||
|
|
@ -2168,11 +2252,15 @@ async def search_items(
|
|||
if slot_name and slot_name not in slot_names:
|
||||
slot_names.append(slot_name)
|
||||
|
||||
item['slot_name'] = ', '.join(slot_names) if slot_names else f"Slot_{equippable_slots}"
|
||||
# Debug logging for slot issues
|
||||
if not slot_names and equippable_slots in [30, 786432]:
|
||||
logger.warning(f"No slot names found for item '{item['name']}' with equippable_slots={equippable_slots}, slot_options={slot_options}")
|
||||
|
||||
item['slot_name'] = ', '.join(slot_names) if slot_names else "-"
|
||||
else:
|
||||
item['slot_name'] = "Unknown"
|
||||
item['slot_name'] = "-"
|
||||
else:
|
||||
item['slot_name'] = "Unknown"
|
||||
item['slot_name'] = "-"
|
||||
|
||||
# Use gear totals as display ratings when individual ratings don't exist
|
||||
# For armor/clothing, ratings are often stored as gear totals (370, 372, 374)
|
||||
|
|
@ -3487,33 +3575,6 @@ def decode_coverage_to_slots(coverage_mask, object_class=None, item_name=''):
|
|||
return list(set(slots)) # Remove duplicates
|
||||
|
||||
|
||||
def translate_equipment_slot(slot_option):
|
||||
"""
|
||||
Translate equipment slot option to human-readable slot name.
|
||||
This handles the slot options returned by get_sophisticated_slot_options.
|
||||
"""
|
||||
# Equipment slot mappings based on EquipMask values
|
||||
slot_mappings = {
|
||||
1: "Head",
|
||||
2: "Chest",
|
||||
4: "Abdomen",
|
||||
8: "Upper Arms",
|
||||
16: "Lower Arms",
|
||||
32: "Hands",
|
||||
64: "Upper Legs",
|
||||
128: "Lower Legs",
|
||||
256: "Feet",
|
||||
512: "Shield",
|
||||
1024: "Neck",
|
||||
2048: "Left Wrist",
|
||||
4096: "Right Wrist",
|
||||
8192: "Left Ring",
|
||||
16384: "Right Ring",
|
||||
32768: "Trinket"
|
||||
}
|
||||
|
||||
return slot_mappings.get(slot_option, f"Slot_{slot_option}")
|
||||
|
||||
|
||||
def categorize_items_by_set(items):
|
||||
"""Categorize items by equipment set for efficient set-based optimization."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue