Remove unused scripts and add missing modules to inventory-service
Removed from git (moved to unused/inventoryservice locally): - extract_*.py scripts (one-time enum extraction tools) - init_db.py, debug_ratings.py, test_suitbuilder*.py - Old JSON outputs superseded by comprehensive_enum_database_v2.json Added previously untracked required files: - helpers.py (shared enum state for suitbuilder) - suitbuilder.py (equipment optimization router) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
8cae94d87d
commit
25e5dd32a4
15 changed files with 1865 additions and 58106 deletions
|
|
@ -1,84 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Add dictionaries to the comprehensive enum database."""
|
||||
|
||||
import json
|
||||
|
||||
# AttributeSetInfo dictionary manually extracted (COMPLETE)
|
||||
attribute_set_info = {
|
||||
"2": "Test",
|
||||
"4": "Carraida's Benediction",
|
||||
"5": "Noble Relic Set",
|
||||
"6": "Ancient Relic Set",
|
||||
"7": "Relic Alduressa Set",
|
||||
"8": "Shou-jen Set",
|
||||
"9": "Empyrean Rings Set",
|
||||
"10": "Arm, Mind, Heart Set",
|
||||
"11": "Coat of the Perfect Light Set",
|
||||
"12": "Leggings of Perfect Light Set",
|
||||
"13": "Soldier's Set",
|
||||
"14": "Adept's Set",
|
||||
"15": "Archer's Set",
|
||||
"16": "Defender's Set",
|
||||
"17": "Tinker's Set",
|
||||
"18": "Crafter's Set",
|
||||
"19": "Hearty Set",
|
||||
"20": "Dexterous Set",
|
||||
"21": "Wise Set",
|
||||
"22": "Swift Set",
|
||||
"23": "Hardenend Set",
|
||||
"24": "Reinforced Set",
|
||||
"25": "Interlocking Set",
|
||||
"26": "Flame Proof Set",
|
||||
"27": "Acid Proof Set",
|
||||
"28": "Cold Proof Set",
|
||||
"29": "Lightning Proof Set",
|
||||
"30": "Dedication Set",
|
||||
"31": "Gladiatorial Clothing Set",
|
||||
"32": "Ceremonial Clothing",
|
||||
"33": "Protective Clothing",
|
||||
"34": "Noobie Armor",
|
||||
"35": "Sigil of Defense",
|
||||
"36": "Sigil of Destruction",
|
||||
"37": "Sigil of Fury",
|
||||
"38": "Sigil of Growth",
|
||||
"39": "Sigil of Vigor",
|
||||
"40": "Heroic Protector Set",
|
||||
"41": "Heroic Destroyer Set",
|
||||
"42": "Olthoi Armor D Red",
|
||||
"43": "Olthoi Armor C Rat",
|
||||
"44": "Olthoi Armor C Red",
|
||||
"45": "Olthoi Armor F Red",
|
||||
"46": "Olthoi Armor K Red",
|
||||
"47": "Olthoi Armor M Red",
|
||||
"48": "Olthoi Armor B Red",
|
||||
"49": "Olthoi Armor B Rat",
|
||||
"50": "Olthoi Armor K Rat",
|
||||
"51": "Olthoi Armor M Rat",
|
||||
"52": "Olthoi Armor F Rat",
|
||||
"53": "Olthoi Armor D Rat"
|
||||
}
|
||||
|
||||
# Load existing database
|
||||
with open('comprehensive_enum_database_v2.json', 'r') as f:
|
||||
db = json.load(f)
|
||||
|
||||
# Add dictionaries section
|
||||
if 'dictionaries' not in db:
|
||||
db['dictionaries'] = {}
|
||||
|
||||
db['dictionaries']['AttributeSetInfo'] = {
|
||||
'name': 'AttributeSetInfo',
|
||||
'description': 'Equipment set names',
|
||||
'values': attribute_set_info
|
||||
}
|
||||
|
||||
# Save updated database
|
||||
with open('comprehensive_enum_database_v2.json', 'w') as f:
|
||||
json.dump(db, f, indent=2)
|
||||
|
||||
print("Added AttributeSetInfo dictionary to comprehensive enum database")
|
||||
print(f"Total equipment sets: {len(attribute_set_info)}")
|
||||
print("Example sets:")
|
||||
for set_id in ['13', '14', '16', '21']:
|
||||
if set_id in attribute_set_info:
|
||||
print(f" {set_id} -> {attribute_set_info[set_id]}")
|
||||
|
|
@ -1,294 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Comprehensive enum extraction from Mag-Plugins/Shared/Constants directory.
|
||||
|
||||
This script extracts ALL enum definitions from the Mag-Plugins source code
|
||||
and creates structured JSON mappings for the inventory service.
|
||||
"""
|
||||
|
||||
import re
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Any, Tuple, Optional
|
||||
|
||||
def extract_enum_from_file(file_path: Path) -> Tuple[str, Dict[str, Any]]:
|
||||
"""Extract enum definition from a C# file."""
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Find enum declaration
|
||||
enum_match = re.search(r'public enum (\w+)(?:\s*:\s*(\w+))?\s*{', content)
|
||||
if not enum_match:
|
||||
return None, {}
|
||||
|
||||
enum_name = enum_match.group(1)
|
||||
enum_type = enum_match.group(2) or 'int'
|
||||
|
||||
print(f"Extracting {enum_name} from {file_path.name}")
|
||||
|
||||
# Extract enum entries
|
||||
entries = {}
|
||||
comments = {}
|
||||
attributes = {}
|
||||
|
||||
# Pattern to match enum entries with various formats
|
||||
# Supports: Name = Value, Name, Name = 0x12345, etc.
|
||||
pattern = r'^\s*(?:\[([^\]]+)\])?\s*(?:/// <summary>\s*([^<]*?)\s*/// </summary>\s*)?(?:\[([^\]]+)\])?\s*(\w+)(?:\s*=\s*([^,]+?))?\s*,?\s*(?://\s*(.*))?$'
|
||||
|
||||
lines = content.split('\n')
|
||||
in_enum = False
|
||||
current_value = 0
|
||||
|
||||
for line in lines:
|
||||
# Check if we're entering the enum
|
||||
if f'enum {enum_name}' in line:
|
||||
in_enum = True
|
||||
continue
|
||||
|
||||
# Check if we're exiting the enum
|
||||
if in_enum and '}' in line and not line.strip().startswith('//'):
|
||||
break
|
||||
|
||||
if in_enum:
|
||||
match = re.match(pattern, line)
|
||||
if match:
|
||||
attr1, summary, attr2, name, value, comment = match.groups()
|
||||
|
||||
# Parse value
|
||||
if value:
|
||||
value = value.strip()
|
||||
if value.startswith('0x') and ' ' not in value:
|
||||
# Simple hex value
|
||||
parsed_value = int(value, 16)
|
||||
elif value.isdigit():
|
||||
# Simple integer
|
||||
parsed_value = int(value)
|
||||
elif '|' in value or '<<' in value or '+' in value:
|
||||
# Complex expression - store as string for now
|
||||
parsed_value = f"EXPR:{value}"
|
||||
else:
|
||||
# Try simple conversion
|
||||
try:
|
||||
parsed_value = int(value)
|
||||
except ValueError:
|
||||
parsed_value = f"VALUE:{value}"
|
||||
else:
|
||||
parsed_value = current_value
|
||||
|
||||
entries[parsed_value] = name
|
||||
|
||||
# Update current_value for auto-increment
|
||||
if isinstance(parsed_value, int):
|
||||
current_value = parsed_value + 1
|
||||
else:
|
||||
# For non-numeric values, increment anyway for next entry
|
||||
current_value += 1
|
||||
|
||||
# Store metadata
|
||||
if summary:
|
||||
comments[name] = summary.strip()
|
||||
if comment:
|
||||
comments[name] = comment.strip()
|
||||
if attr1 or attr2:
|
||||
attributes[name] = (attr1 or '') + ' ' + (attr2 or '')
|
||||
|
||||
return enum_name, {
|
||||
'type': enum_type,
|
||||
'values': entries,
|
||||
'comments': comments,
|
||||
'attributes': attributes,
|
||||
'source_file': file_path.name
|
||||
}
|
||||
|
||||
def extract_skill_names():
|
||||
"""Extract skill names with their indices from Skill.cs"""
|
||||
skill_file = Path('/home/erik/MosswartOverlord/Mag-Plugins/Shared/Constants/Skill.cs')
|
||||
|
||||
with open(skill_file, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
skills = {}
|
||||
lines = content.split('\n')
|
||||
in_enum = False
|
||||
index = 0
|
||||
|
||||
for line in lines:
|
||||
if 'enum Skill' in line:
|
||||
in_enum = True
|
||||
continue
|
||||
|
||||
if in_enum and '}' in line:
|
||||
break
|
||||
|
||||
if in_enum:
|
||||
# Match skill entries like "None," or "Axe, /* Retired */"
|
||||
match = re.match(r'^\s*(\w+),?\s*(?:/\*\s*([^*]*)\s*\*/)?', line)
|
||||
if match:
|
||||
skill_name = match.group(1)
|
||||
status = match.group(2) or "Active"
|
||||
skills[index] = {
|
||||
'name': skill_name,
|
||||
'status': status.strip()
|
||||
}
|
||||
index += 1
|
||||
|
||||
return skills
|
||||
|
||||
def categorize_enums():
|
||||
"""Create logical categories for different enum types."""
|
||||
return {
|
||||
'item_properties': {
|
||||
'description': 'Item property value keys for different data types',
|
||||
'enums': ['IntValueKey', 'DoubleValueKey', 'StringValueKey', 'BoolValueKey', 'QuadValueKey']
|
||||
},
|
||||
'item_classification': {
|
||||
'description': 'Item type and material classification',
|
||||
'enums': ['ItemType', 'MaterialType', 'WeenieType']
|
||||
},
|
||||
'game_mechanics': {
|
||||
'description': 'Skills, spells, and game system enums',
|
||||
'enums': ['Skill', 'SpellCategory', 'WieldRequirement']
|
||||
},
|
||||
'technical': {
|
||||
'description': 'Technical flags and masks for game engine',
|
||||
'enums': ['CoverageMask', 'EquipMask']
|
||||
}
|
||||
}
|
||||
|
||||
def create_translation_mappings():
|
||||
"""Create user-friendly translations for important enum values."""
|
||||
|
||||
# Map IntValueKey values to more descriptive names
|
||||
int_value_translations = {
|
||||
5: 'Encumbrance',
|
||||
19: 'Value (Pyreals)',
|
||||
25: 'Level',
|
||||
28: 'Armor Level',
|
||||
44: 'Base Damage',
|
||||
45: 'Damage Type',
|
||||
48: 'Weapon Skill',
|
||||
158: 'Wield Requirements',
|
||||
160: 'Wield Difficulty',
|
||||
218103842: 'Maximum Damage',
|
||||
218103849: 'Icon Overlay',
|
||||
218103850: 'Icon Underlay'
|
||||
}
|
||||
|
||||
# Material type friendly names
|
||||
material_translations = {
|
||||
0: 'Unknown',
|
||||
1: 'Ceramic',
|
||||
20: 'Diamond',
|
||||
21: 'Emerald',
|
||||
31: 'Ruby',
|
||||
32: 'Sapphire'
|
||||
}
|
||||
|
||||
return {
|
||||
'int_values': int_value_translations,
|
||||
'materials': material_translations
|
||||
}
|
||||
|
||||
def main():
|
||||
"""Main extraction process."""
|
||||
|
||||
constants_dir = Path('/home/erik/MosswartOverlord/Mag-Plugins/Shared/Constants')
|
||||
output_dir = Path('/home/erik/MosswartOverlord/inventory-service')
|
||||
|
||||
# Ensure output directory exists
|
||||
output_dir.mkdir(exist_ok=True)
|
||||
|
||||
print("Starting comprehensive enum extraction from Mag-Plugins/Shared/Constants...")
|
||||
|
||||
# Extract all enum files
|
||||
all_enums = {}
|
||||
enum_files = list(constants_dir.glob('*.cs'))
|
||||
|
||||
for enum_file in enum_files:
|
||||
if enum_file.name == 'Dictionaries.cs': # Skip non-enum files
|
||||
continue
|
||||
|
||||
enum_name, enum_data = extract_enum_from_file(enum_file)
|
||||
if enum_name and enum_data:
|
||||
all_enums[enum_name] = enum_data
|
||||
|
||||
# Special handling for Skills (has complex structure)
|
||||
skill_data = extract_skill_names()
|
||||
all_enums['Skill'] = {
|
||||
'type': 'indexed',
|
||||
'values': skill_data,
|
||||
'source_file': 'Skill.cs'
|
||||
}
|
||||
|
||||
# Create categorized structure
|
||||
categories = categorize_enums()
|
||||
translations = create_translation_mappings()
|
||||
|
||||
# Save complete enum database
|
||||
complete_data = {
|
||||
'metadata': {
|
||||
'extracted_at': '2025-06-10',
|
||||
'source': 'Mag-Plugins/Shared/Constants',
|
||||
'total_enums': len(all_enums),
|
||||
'version': '1.0.0'
|
||||
},
|
||||
'categories': categories,
|
||||
'translations': translations,
|
||||
'enums': all_enums
|
||||
}
|
||||
|
||||
# Save main database
|
||||
main_output = output_dir / 'complete_enum_database.json'
|
||||
with open(main_output, 'w') as f:
|
||||
json.dump(complete_data, f, indent=2)
|
||||
|
||||
print(f"Saved complete enum database to {main_output}")
|
||||
|
||||
# Save individual enum files for backward compatibility
|
||||
individual_dir = output_dir / 'enums'
|
||||
individual_dir.mkdir(exist_ok=True)
|
||||
|
||||
for enum_name, enum_data in all_enums.items():
|
||||
enum_file = individual_dir / f'{enum_name}.json'
|
||||
with open(enum_file, 'w') as f:
|
||||
json.dump({enum_name: enum_data}, f, indent=2)
|
||||
|
||||
# Update existing files for backward compatibility
|
||||
if 'IntValueKey' in all_enums:
|
||||
legacy_int_file = output_dir / 'int_value_enums.json'
|
||||
with open(legacy_int_file, 'w') as f:
|
||||
json.dump(all_enums['IntValueKey']['values'], f, indent=2)
|
||||
print(f"Updated legacy file: {legacy_int_file}")
|
||||
|
||||
# Create comprehensive summary
|
||||
print("\n" + "="*60)
|
||||
print("EXTRACTION SUMMARY")
|
||||
print("="*60)
|
||||
|
||||
for enum_name, enum_data in all_enums.items():
|
||||
value_count = len(enum_data.get('values', {}))
|
||||
enum_type = enum_data.get('type', 'unknown')
|
||||
print(f"{enum_name:20} | {value_count:4} values | Type: {enum_type}")
|
||||
|
||||
print(f"\nTotal enums extracted: {len(all_enums)}")
|
||||
print(f"Files created:")
|
||||
print(f" - {main_output}")
|
||||
print(f" - {len(all_enums)} individual enum files in {individual_dir}/")
|
||||
|
||||
# Show sample translations
|
||||
print("\nSample enum translations:")
|
||||
for enum_name in ['IntValueKey', 'MaterialType', 'ItemType', 'Skill']:
|
||||
if enum_name in all_enums:
|
||||
values = all_enums[enum_name]['values']
|
||||
if isinstance(values, dict):
|
||||
sample_keys = list(values.keys())[:3]
|
||||
for key in sample_keys:
|
||||
if isinstance(values[key], dict):
|
||||
print(f" {enum_name}[{key}] = {values[key].get('name', values[key])}")
|
||||
else:
|
||||
print(f" {enum_name}[{key}] = {values[key]}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Comprehensive enum extraction from ALL Mag-Plugins Constants files.
|
||||
This script extracts ALL missing enum values to complete our enum database.
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
def extract_coverage_mask():
|
||||
"""Extract complete CoverageMask enum with ALL values."""
|
||||
file_path = "../unused/Mag-Plugins/Shared/Constants/CoverageMask.cs"
|
||||
|
||||
coverage_values = {}
|
||||
|
||||
with open(file_path, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Extract enum values using regex
|
||||
enum_pattern = r'(\w+)\s*=\s*0x([0-9A-Fa-f]+)'
|
||||
matches = re.findall(enum_pattern, content)
|
||||
|
||||
for name, hex_value in matches:
|
||||
decimal_value = int(hex_value, 16)
|
||||
coverage_values[str(decimal_value)] = name
|
||||
|
||||
return {
|
||||
"name": "CoverageMask",
|
||||
"values": coverage_values,
|
||||
"source_file": "CoverageMask.cs"
|
||||
}
|
||||
|
||||
def extract_bool_value_key():
|
||||
"""Extract BoolValueKey enum (currently missing)."""
|
||||
file_path = "../unused/Mag-Plugins/Shared/Constants/BoolValueKey.cs"
|
||||
|
||||
bool_values = {}
|
||||
|
||||
with open(file_path, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Extract enum values
|
||||
enum_pattern = r'(\w+)\s*=\s*(\d+)'
|
||||
matches = re.findall(enum_pattern, content)
|
||||
|
||||
for name, value in matches:
|
||||
bool_values[value] = name
|
||||
|
||||
return {
|
||||
"name": "BoolValueKey",
|
||||
"values": bool_values,
|
||||
"source_file": "BoolValueKey.cs"
|
||||
}
|
||||
|
||||
def load_current_database():
|
||||
"""Load current enum database."""
|
||||
with open('comprehensive_enum_database_v2.json', 'r') as f:
|
||||
return json.load(f)
|
||||
|
||||
def update_enum_database():
|
||||
"""Update the enum database with ALL missing values."""
|
||||
print("Loading current enum database...")
|
||||
db = load_current_database()
|
||||
|
||||
print("Extracting complete CoverageMask...")
|
||||
complete_coverage = extract_coverage_mask()
|
||||
db['enums']['CoverageMask'] = complete_coverage
|
||||
|
||||
print("Extracting BoolValueKey...")
|
||||
bool_values = extract_bool_value_key()
|
||||
db['enums']['BoolValueKey'] = bool_values
|
||||
|
||||
# Update metadata
|
||||
db['metadata']['last_updated'] = "2025-06-12"
|
||||
db['metadata']['notes'] = "COMPLETE extraction: Added missing CoverageMask values (1,2,4,16,etc) and BoolValueKey enum"
|
||||
|
||||
print("Saving updated database...")
|
||||
with open('comprehensive_enum_database_v2.json', 'w') as f:
|
||||
json.dump(db, f, indent=2)
|
||||
|
||||
print("✅ Enum database updated successfully!")
|
||||
print(f"✅ CoverageMask now has {len(complete_coverage['values'])} values")
|
||||
print(f"✅ BoolValueKey now has {len(bool_values['values'])} values")
|
||||
|
||||
if __name__ == "__main__":
|
||||
update_enum_database()
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Comprehensive enum extraction from Mag-Plugins/Shared directory.
|
||||
Extracts all enums, dictionaries, and data needed for rich tooltip display.
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
import csv
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any
|
||||
|
||||
def extract_csharp_enum(file_path: Path) -> Dict[str, Any]:
|
||||
"""Extract enum definition from C# file."""
|
||||
try:
|
||||
content = file_path.read_text(encoding='utf-8')
|
||||
|
||||
# Find enum declaration
|
||||
enum_match = re.search(r'public enum (\w+)(?:\s*:\s*\w+)?\s*{([^}]+)}', content, re.DOTALL)
|
||||
if not enum_match:
|
||||
return {}
|
||||
|
||||
enum_name = enum_match.group(1)
|
||||
enum_body = enum_match.group(2)
|
||||
|
||||
values = {}
|
||||
for line in enum_body.split('\n'):
|
||||
line = line.strip()
|
||||
if not line or line.startswith('//'):
|
||||
continue
|
||||
|
||||
# Parse enum values (handle various formats)
|
||||
if '=' in line:
|
||||
parts = line.split('=')
|
||||
if len(parts) >= 2:
|
||||
name = parts[0].strip().rstrip(',')
|
||||
value_part = parts[1].strip().rstrip(',')
|
||||
|
||||
# Handle hex values
|
||||
if value_part.startswith('0x'):
|
||||
try:
|
||||
value = int(value_part, 16)
|
||||
values[str(value)] = name
|
||||
except ValueError:
|
||||
pass
|
||||
# Handle decimal values
|
||||
elif value_part.isdigit():
|
||||
values[value_part] = name
|
||||
# Handle expressions (for flags)
|
||||
elif '|' in value_part:
|
||||
values[f"EXPR:{value_part}"] = name
|
||||
else:
|
||||
# Auto-increment enum
|
||||
name = line.rstrip(',').strip()
|
||||
if name and not name.startswith('//'):
|
||||
values[str(len(values))] = name
|
||||
|
||||
return {
|
||||
'name': enum_name,
|
||||
'values': values,
|
||||
'source_file': str(file_path.name)
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Error extracting enum from {file_path}: {e}")
|
||||
return {}
|
||||
|
||||
def extract_dictionaries_cs(file_path: Path) -> Dict[str, Any]:
|
||||
"""Extract dictionary mappings from Dictionaries.cs file."""
|
||||
try:
|
||||
content = file_path.read_text(encoding='utf-8')
|
||||
dictionaries = {}
|
||||
|
||||
# Look for dictionary definitions with various patterns
|
||||
dict_patterns = [
|
||||
r'public static readonly Dictionary<int, string> (\w+) = new Dictionary<int, string>\s*\n\s*{([^}]+)}',
|
||||
r'public static readonly Dictionary<int, string> (\w+) = new Dictionary<int, string>\(\)\s*\n\s*{([^}]+)}'
|
||||
]
|
||||
|
||||
for pattern in dict_patterns:
|
||||
for match in re.finditer(pattern, content, re.DOTALL):
|
||||
dict_name = match.group(1)
|
||||
dict_body = match.group(2)
|
||||
|
||||
values = {}
|
||||
for line in dict_body.split('\n'):
|
||||
line = line.strip()
|
||||
if not line or line.startswith('//'):
|
||||
continue
|
||||
|
||||
# Parse dictionary entries: { 0x1, "value" } or { 1, "value" }
|
||||
entry_patterns = [
|
||||
r'{\s*0x([0-9A-Fa-f]+),\s*"([^"]+)"\s*}', # Hex format
|
||||
r'{\s*(\d+),\s*"([^"]+)"\s*}' # Decimal format
|
||||
]
|
||||
|
||||
for entry_pattern in entry_patterns:
|
||||
entry_match = re.search(entry_pattern, line)
|
||||
if entry_match:
|
||||
key_str = entry_match.group(1)
|
||||
value = entry_match.group(2)
|
||||
|
||||
# Convert hex to decimal if needed
|
||||
if 'x' in entry_pattern:
|
||||
key = str(int(key_str, 16))
|
||||
else:
|
||||
key = key_str
|
||||
|
||||
values[key] = value
|
||||
break
|
||||
|
||||
if values:
|
||||
dictionaries[dict_name] = {
|
||||
'name': dict_name,
|
||||
'values': values,
|
||||
'source_file': 'Dictionaries.cs'
|
||||
}
|
||||
|
||||
return dictionaries
|
||||
except Exception as e:
|
||||
print(f"Error extracting dictionaries: {e}")
|
||||
return {}
|
||||
|
||||
def extract_spells_csv(file_path: Path) -> Dict[str, Any]:
|
||||
"""Extract spell data from Spells.csv."""
|
||||
try:
|
||||
spells = {}
|
||||
# Try different encodings
|
||||
for encoding in ['utf-8', 'latin1', 'cp1252']:
|
||||
try:
|
||||
with open(file_path, 'r', encoding=encoding) as f:
|
||||
reader = csv.DictReader(f)
|
||||
for row in reader:
|
||||
spell_id = row.get('Id', '').strip()
|
||||
if spell_id and spell_id.isdigit():
|
||||
spells[spell_id] = {
|
||||
'id': int(spell_id),
|
||||
'name': row.get('Name', '').strip(),
|
||||
'description': row.get('Description', '').strip(),
|
||||
'school': row.get('School', '').strip(),
|
||||
'difficulty': row.get('Difficulty', '').strip(),
|
||||
'duration': row.get('Duration', '').strip(),
|
||||
'mana': row.get('Mana', '').strip(),
|
||||
'family': row.get('Family', '').strip(),
|
||||
'speed': row.get('Speed', '').strip(),
|
||||
'target_effect': row.get('TargetEffect', '').strip(),
|
||||
'target_mask': row.get('TargetMask', '').strip()
|
||||
}
|
||||
break
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
|
||||
return {
|
||||
'name': 'Spells',
|
||||
'values': spells,
|
||||
'source_file': 'Spells.csv'
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Error extracting spells: {e}")
|
||||
return {}
|
||||
|
||||
def extract_object_class_cs(file_path: Path) -> Dict[str, Any]:
|
||||
"""Extract ObjectClass enum specifically."""
|
||||
try:
|
||||
content = file_path.read_text(encoding='utf-8')
|
||||
|
||||
# Find ObjectClass enum
|
||||
enum_match = re.search(r'public enum ObjectClass\s*{([^}]+)}', content, re.DOTALL)
|
||||
if not enum_match:
|
||||
return {}
|
||||
|
||||
enum_body = enum_match.group(1)
|
||||
values = {}
|
||||
current_value = 0
|
||||
|
||||
for line in enum_body.split('\n'):
|
||||
line = line.strip()
|
||||
if not line or line.startswith('//'):
|
||||
continue
|
||||
|
||||
if '=' in line:
|
||||
parts = line.split('=')
|
||||
if len(parts) >= 2:
|
||||
name = parts[0].strip().rstrip(',')
|
||||
value_str = parts[1].strip().rstrip(',')
|
||||
try:
|
||||
current_value = int(value_str)
|
||||
values[str(current_value)] = name
|
||||
current_value += 1
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
name = line.rstrip(',').strip()
|
||||
if name and not name.startswith('//'):
|
||||
values[str(current_value)] = name
|
||||
current_value += 1
|
||||
|
||||
return {
|
||||
'name': 'ObjectClass',
|
||||
'values': values,
|
||||
'source_file': 'ObjectClass.cs'
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"Error extracting ObjectClass: {e}")
|
||||
return {}
|
||||
|
||||
def main():
|
||||
base_path = Path('/home/erik/MosswartOverlord/Mag-Plugins/Shared')
|
||||
constants_path = base_path / 'Constants'
|
||||
spells_path = base_path / 'Spells'
|
||||
|
||||
comprehensive_database = {
|
||||
'metadata': {
|
||||
'extracted_at': '2025-06-10',
|
||||
'source': 'Mag-Plugins/Shared (comprehensive)',
|
||||
'version': '2.0.0'
|
||||
},
|
||||
'enums': {},
|
||||
'dictionaries': {},
|
||||
'spells': {},
|
||||
'object_classes': {}
|
||||
}
|
||||
|
||||
# Extract all constant enums
|
||||
for cs_file in constants_path.glob('*.cs'):
|
||||
if cs_file.name in ['Dictionaries.cs']:
|
||||
continue # Handle separately
|
||||
|
||||
enum_data = extract_csharp_enum(cs_file)
|
||||
if enum_data:
|
||||
comprehensive_database['enums'][enum_data['name']] = enum_data
|
||||
print(f"✓ Extracted enum: {enum_data['name']} ({len(enum_data['values'])} values)")
|
||||
|
||||
# Extract ObjectClass enum
|
||||
object_class_file = base_path / 'ObjectClass.cs'
|
||||
if object_class_file.exists():
|
||||
object_class_data = extract_object_class_cs(object_class_file)
|
||||
if object_class_data:
|
||||
comprehensive_database['object_classes'] = object_class_data
|
||||
print(f"✓ Extracted ObjectClass: {len(object_class_data['values'])} values")
|
||||
|
||||
# Extract dictionaries
|
||||
dict_file = constants_path / 'Dictionaries.cs'
|
||||
if dict_file.exists():
|
||||
dict_data = extract_dictionaries_cs(dict_file)
|
||||
comprehensive_database['dictionaries'] = dict_data
|
||||
print(f"✓ Extracted dictionaries: {len(dict_data)} dictionaries")
|
||||
|
||||
# Extract spells
|
||||
spells_file = spells_path / 'Spells.csv'
|
||||
if spells_file.exists():
|
||||
spell_data = extract_spells_csv(spells_file)
|
||||
if spell_data:
|
||||
comprehensive_database['spells'] = spell_data
|
||||
print(f"✓ Extracted spells: {len(spell_data['values'])} spells")
|
||||
|
||||
# Save comprehensive database
|
||||
output_file = Path('/home/erik/MosswartOverlord/inventory-service/comprehensive_enum_database_v2.json')
|
||||
with open(output_file, 'w') as f:
|
||||
json.dump(comprehensive_database, f, indent=2)
|
||||
|
||||
print(f"\n✅ Comprehensive enum database saved to: {output_file}")
|
||||
print(f"📊 Total enums: {len(comprehensive_database['enums'])}")
|
||||
print(f"📊 Total dictionaries: {len(comprehensive_database['dictionaries'])}")
|
||||
print(f"📊 Total spells: {len(comprehensive_database['spells'].get('values', {}))}")
|
||||
print(f"📊 Object classes: {len(comprehensive_database['object_classes'].get('values', {}))}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
#\!/usr/bin/env python3
|
||||
"""Extract dictionaries from Mag-Plugins Dictionaries.cs file."""
|
||||
|
||||
import re
|
||||
import json
|
||||
|
||||
def extract_attribute_set_info():
|
||||
"""Extract AttributeSetInfo dictionary from Dictionaries.cs."""
|
||||
with open('/home/erik/MosswartOverlord/unused/Mag-Plugins/Shared/Constants/Dictionaries.cs', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Find the AttributeSetInfo dictionary
|
||||
pattern = r'AttributeSetInfo\s*=\s*new\s+Dictionary<int,\s*string>\s*\{([^}]+)\}'
|
||||
match = re.search(pattern, content, re.DOTALL)
|
||||
|
||||
if not match:
|
||||
print("AttributeSetInfo not found\!")
|
||||
return {}
|
||||
|
||||
dict_content = match.group(1)
|
||||
|
||||
# Extract entries
|
||||
entry_pattern = r'\{\s*(\d+),\s*"([^"]+)"\s*\}'
|
||||
entries = re.findall(entry_pattern, dict_content)
|
||||
|
||||
attribute_sets = {}
|
||||
for set_id, set_name in entries:
|
||||
attribute_sets[set_id] = set_name
|
||||
|
||||
return attribute_sets
|
||||
|
||||
def extract_material_info():
|
||||
"""Extract MaterialInfo dictionary from Dictionaries.cs."""
|
||||
with open('/home/erik/MosswartOverlord/unused/Mag-Plugins/Shared/Constants/Dictionaries.cs', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Find the MaterialInfo dictionary
|
||||
pattern = r'MaterialInfo\s*=\s*new\s+Dictionary<int,\s*string>\s*\{([^}]+)\}'
|
||||
match = re.search(pattern, content, re.DOTALL)
|
||||
|
||||
if not match:
|
||||
print("MaterialInfo not found\!")
|
||||
return {}
|
||||
|
||||
dict_content = match.group(1)
|
||||
|
||||
# Extract entries
|
||||
entry_pattern = r'\{\s*(\d+),\s*"([^"]+)"\s*\}'
|
||||
entries = re.findall(entry_pattern, dict_content)
|
||||
|
||||
materials = {}
|
||||
for mat_id, mat_name in entries:
|
||||
materials[mat_id] = mat_name
|
||||
|
||||
return materials
|
||||
|
||||
def extract_skill_info():
|
||||
"""Extract SkillInfo dictionary from Dictionaries.cs."""
|
||||
with open('/home/erik/MosswartOverlord/unused/Mag-Plugins/Shared/Constants/Dictionaries.cs', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Find the SkillInfo dictionary
|
||||
pattern = r'SkillInfo\s*=\s*new\s+Dictionary<int,\s*string>\s*\{([^}]+)\}'
|
||||
match = re.search(pattern, content, re.DOTALL)
|
||||
|
||||
if not match:
|
||||
print("SkillInfo not found\!")
|
||||
return {}
|
||||
|
||||
dict_content = match.group(1)
|
||||
|
||||
# Extract entries - handle hex values
|
||||
entry_pattern = r'\{\s*(0x[0-9A-Fa-f]+ < /dev/null | \d+),\s*"([^"]+)"\s*\}'
|
||||
entries = re.findall(entry_pattern, dict_content)
|
||||
|
||||
skills = {}
|
||||
for skill_id, skill_name in entries:
|
||||
# Convert hex to decimal if needed
|
||||
if skill_id.startswith('0x'):
|
||||
skill_id = str(int(skill_id, 16))
|
||||
skills[skill_id] = skill_name
|
||||
|
||||
return skills
|
||||
|
||||
def extract_mastery_info():
|
||||
"""Extract MasteryInfo dictionary from Dictionaries.cs."""
|
||||
with open('/home/erik/MosswartOverlord/unused/Mag-Plugins/Shared/Constants/Dictionaries.cs', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Find the MasteryInfo dictionary
|
||||
pattern = r'MasteryInfo\s*=\s*new\s+Dictionary<int,\s*string>\s*\{([^}]+)\}'
|
||||
match = re.search(pattern, content, re.DOTALL)
|
||||
|
||||
if not match:
|
||||
print("MasteryInfo not found\!")
|
||||
return {}
|
||||
|
||||
dict_content = match.group(1)
|
||||
|
||||
# Extract entries
|
||||
entry_pattern = r'\{\s*(\d+),\s*"([^"]+)"\s*\}'
|
||||
entries = re.findall(entry_pattern, dict_content)
|
||||
|
||||
masteries = {}
|
||||
for mastery_id, mastery_name in entries:
|
||||
masteries[mastery_id] = mastery_name
|
||||
|
||||
return masteries
|
||||
|
||||
def main():
|
||||
"""Extract all dictionaries and save to JSON."""
|
||||
dictionaries = {
|
||||
'AttributeSetInfo': extract_attribute_set_info(),
|
||||
'MaterialInfo': extract_material_info(),
|
||||
'SkillInfo': extract_skill_info(),
|
||||
'MasteryInfo': extract_mastery_info()
|
||||
}
|
||||
|
||||
# Print summary
|
||||
for dict_name, dict_data in dictionaries.items():
|
||||
print(f"{dict_name}: {len(dict_data)} entries")
|
||||
if dict_data and dict_name == 'AttributeSetInfo':
|
||||
# Show some equipment set examples
|
||||
for set_id in ['13', '14', '16', '21']:
|
||||
if set_id in dict_data:
|
||||
print(f" {set_id} -> {dict_data[set_id]}")
|
||||
|
||||
# Save to file
|
||||
with open('extracted_dictionaries.json', 'w') as f:
|
||||
json.dump(dictionaries, f, indent=2)
|
||||
|
||||
print("\nDictionaries saved to extracted_dictionaries.json")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
#\!/usr/bin/env python3
|
||||
"""Extract dictionaries from Mag-Plugins Dictionaries.cs file."""
|
||||
|
||||
import re
|
||||
import json
|
||||
|
||||
def extract_dictionary(dict_name):
|
||||
"""Extract a dictionary from Dictionaries.cs by name."""
|
||||
with open('/home/erik/MosswartOverlord/unused/Mag-Plugins/Shared/Constants/Dictionaries.cs', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Find the dictionary - handle multiline definitions
|
||||
pattern = rf'{dict_name}\s*=\s*new\s+Dictionary<int,\s*string>\s*\{{(.*?)^\s*\}};'
|
||||
match = re.search(pattern, content, re.DOTALL < /dev/null | re.MULTILINE)
|
||||
|
||||
if not match:
|
||||
print(f"{dict_name} not found\!")
|
||||
return {}
|
||||
|
||||
dict_content = match.group(1)
|
||||
|
||||
# Extract entries - handle both decimal and hex values
|
||||
entry_pattern = r'\{\s*(0x[0-9A-Fa-f]+|\d+),\s*"([^"]+)"\s*\}'
|
||||
entries = re.findall(entry_pattern, dict_content)
|
||||
|
||||
result = {}
|
||||
for key, value in entries:
|
||||
# Convert hex to decimal if needed
|
||||
if key.startswith('0x'):
|
||||
key = str(int(key, 16))
|
||||
result[key] = value
|
||||
|
||||
return result
|
||||
|
||||
def main():
|
||||
"""Extract all dictionaries and save to JSON."""
|
||||
dictionaries = {
|
||||
'AttributeSetInfo': extract_dictionary('AttributeSetInfo'),
|
||||
'MaterialInfo': extract_dictionary('MaterialInfo'),
|
||||
'SkillInfo': extract_dictionary('SkillInfo'),
|
||||
'MasteryInfo': extract_dictionary('MasteryInfo')
|
||||
}
|
||||
|
||||
# Print summary
|
||||
for dict_name, dict_data in dictionaries.items():
|
||||
print(f"{dict_name}: {len(dict_data)} entries")
|
||||
if dict_data and dict_name == 'AttributeSetInfo':
|
||||
# Show some equipment set examples
|
||||
for set_id in ['13', '14', '16', '21']:
|
||||
if set_id in dict_data:
|
||||
print(f" {set_id} -> {dict_data[set_id]}")
|
||||
|
||||
# Save to file
|
||||
with open('extracted_dictionaries.json', 'w') as f:
|
||||
json.dump(dictionaries, f, indent=2)
|
||||
|
||||
print("\nDictionaries saved to extracted_dictionaries.json")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Extract enum definitions from Mag-Plugins C# files into JSON mappings.
|
||||
|
||||
This script parses the IntValueKey.cs file to create a mapping between
|
||||
numeric enum values and their human-readable names for inventory processing.
|
||||
"""
|
||||
|
||||
import re
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
def extract_int_value_enums(cs_file_path):
|
||||
"""Extract IntValueKey enum definitions from C# file."""
|
||||
|
||||
with open(cs_file_path, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Pattern to match enum entries: EnumName = Value,
|
||||
pattern = r'^\s*(?:\[[^\]]+\])?\s*(\w+)\s*=\s*(\d+),?\s*(?://.*)?$'
|
||||
|
||||
enums = {}
|
||||
in_enum = False
|
||||
|
||||
for line in content.split('\n'):
|
||||
# Check if we're entering the enum
|
||||
if 'enum IntValueKey' in line:
|
||||
in_enum = True
|
||||
continue
|
||||
|
||||
# Check if we're exiting the enum
|
||||
if in_enum and line.strip() == '}':
|
||||
break
|
||||
|
||||
# Parse enum entries
|
||||
if in_enum:
|
||||
match = re.match(pattern, line)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
value = int(match.group(2))
|
||||
enums[value] = name
|
||||
|
||||
return enums
|
||||
|
||||
def create_property_mappings():
|
||||
"""Create organized property mappings for different item aspects."""
|
||||
|
||||
# Based on analysis of the enum values and common item properties
|
||||
property_categories = {
|
||||
'basic': {
|
||||
5: 'encumbrance', # EncumbranceVal
|
||||
19: 'value', # Value
|
||||
25: 'level', # Level
|
||||
28: 'armor_level', # ArmorLevel
|
||||
44: 'damage', # Damage
|
||||
45: 'damage_type', # DamageType
|
||||
},
|
||||
|
||||
'requirements': {
|
||||
158: 'wield_requirement', # Common wield requirement key (from JSON data)
|
||||
160: 'wield_level', # Common wield level key (from JSON data)
|
||||
48: 'weapon_skill', # WeaponSkill
|
||||
},
|
||||
|
||||
'combat': {
|
||||
218103842: 'max_damage', # MaxDamage_Decal
|
||||
36: 'resist_magic', # ResistMagic
|
||||
56: 'shield_value', # ShieldValue
|
||||
},
|
||||
|
||||
'display': {
|
||||
218103809: 'icon', # Icon_Decal_DID
|
||||
218103849: 'icon_overlay', # IconOverlay_Decal_DID
|
||||
218103850: 'icon_underlay', # IconUnderlay_Decal_DID
|
||||
},
|
||||
|
||||
'metadata': {
|
||||
218103808: 'weenie_class_id', # WeenieClassId_Decal
|
||||
218103847: 'physics_data_flags', # PhysicsDataFlags_Decal
|
||||
218103831: 'object_desc_flags', # ObjectDescriptionFlags_Decal
|
||||
}
|
||||
}
|
||||
|
||||
return property_categories
|
||||
|
||||
def main():
|
||||
"""Main extraction process."""
|
||||
|
||||
# Paths
|
||||
mag_plugins_path = Path('/home/erik/MosswartOverlord/Mag-Plugins')
|
||||
int_value_key_path = mag_plugins_path / 'Shared' / 'Constants' / 'IntValueKey.cs'
|
||||
output_dir = Path('/home/erik/MosswartOverlord/inventory-service')
|
||||
|
||||
# Create output directory
|
||||
output_dir.mkdir(exist_ok=True)
|
||||
|
||||
# Extract all enum values
|
||||
print("Extracting IntValueKey enums...")
|
||||
int_enums = extract_int_value_enums(int_value_key_path)
|
||||
print(f"Found {len(int_enums)} enum definitions")
|
||||
|
||||
# Create property categories
|
||||
property_categories = create_property_mappings()
|
||||
|
||||
# Save complete enum mapping
|
||||
enum_output = output_dir / 'int_value_enums.json'
|
||||
with open(enum_output, 'w') as f:
|
||||
json.dump(int_enums, f, indent=2)
|
||||
print(f"Saved complete enum mapping to {enum_output}")
|
||||
|
||||
# Save categorized mappings
|
||||
categories_output = output_dir / 'property_categories.json'
|
||||
with open(categories_output, 'w') as f:
|
||||
json.dump(property_categories, f, indent=2)
|
||||
print(f"Saved property categories to {categories_output}")
|
||||
|
||||
# Print some interesting findings
|
||||
print("\nKey mappings found:")
|
||||
interesting_keys = [5, 19, 28, 44, 158, 160, 218103809, 218103842, 218103847, 218103849]
|
||||
for key in interesting_keys:
|
||||
if key in int_enums:
|
||||
print(f" {key}: {int_enums[key]}")
|
||||
|
||||
print(f"\nFiles created in {output_dir}/")
|
||||
print("- int_value_enums.json: Complete enum mapping")
|
||||
print("- property_categories.json: Organized property categories")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Extract spell names from Mag-Plugins/Shared/Spells/Spells.csv for spell ID translation.
|
||||
"""
|
||||
|
||||
import csv
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
def extract_spell_names():
|
||||
"""Extract spell ID to name mappings from Spells.csv."""
|
||||
|
||||
csv_path = Path('/home/erik/MosswartOverlord/Mag-Plugins/Shared/Spells/Spells.csv')
|
||||
|
||||
if not csv_path.exists():
|
||||
print(f"❌ Spells.csv not found at {csv_path}")
|
||||
return {}
|
||||
|
||||
spell_mappings = {}
|
||||
|
||||
# Try different encodings
|
||||
encodings = ['utf-8', 'latin-1', 'windows-1252', 'utf-8-sig']
|
||||
|
||||
for encoding in encodings:
|
||||
try:
|
||||
with open(csv_path, 'r', encoding=encoding) as f:
|
||||
reader = csv.DictReader(f)
|
||||
print(f"✓ Successfully opened with {encoding} encoding")
|
||||
|
||||
for row in reader:
|
||||
try:
|
||||
spell_id = int(row['Id'])
|
||||
spell_name = row['Name'].strip()
|
||||
spell_description = row.get('Description', '').strip()
|
||||
spell_school = row.get('School', '').strip()
|
||||
spell_family = row.get('Family', '').strip()
|
||||
spell_difficulty = row.get('Difficulty', '').strip()
|
||||
spell_duration = row.get('Duration', '').strip()
|
||||
spell_mana = row.get('Mana', '').strip()
|
||||
|
||||
# Create comprehensive spell data
|
||||
spell_data = {
|
||||
'name': spell_name,
|
||||
'description': spell_description,
|
||||
'school': spell_school,
|
||||
'family': spell_family,
|
||||
'difficulty': spell_difficulty,
|
||||
'duration': spell_duration,
|
||||
'mana': spell_mana
|
||||
}
|
||||
|
||||
spell_mappings[spell_id] = spell_data
|
||||
|
||||
except (ValueError, KeyError) as e:
|
||||
print(f"⚠️ Skipping invalid row: {e}")
|
||||
continue
|
||||
|
||||
# If we get here successfully, we're done
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error with {encoding} encoding: {e}")
|
||||
continue
|
||||
|
||||
if spell_mappings:
|
||||
print(f"✓ Extracted {len(spell_mappings)} spell entries")
|
||||
else:
|
||||
print("❌ Failed to extract spells with any encoding")
|
||||
|
||||
return spell_mappings
|
||||
|
||||
def save_spell_database(spell_mappings):
|
||||
"""Save spell mappings to JSON file."""
|
||||
|
||||
output_path = Path('/home/erik/MosswartOverlord/inventory-service/spell_database.json')
|
||||
|
||||
spell_database = {
|
||||
'metadata': {
|
||||
'version': '1.0.0',
|
||||
'source': 'Mag-Plugins/Shared/Spells/Spells.csv',
|
||||
'total_spells': len(spell_mappings),
|
||||
'description': 'Spell ID to name/data mappings for Asheron\'s Call'
|
||||
},
|
||||
'spells': spell_mappings
|
||||
}
|
||||
|
||||
try:
|
||||
with open(output_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(spell_database, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"✓ Spell database saved to {output_path}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error saving spell database: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Main extraction process."""
|
||||
print("Extracting spell names from Spells.csv...")
|
||||
|
||||
# Extract spell mappings
|
||||
spell_mappings = extract_spell_names()
|
||||
|
||||
if not spell_mappings:
|
||||
print("❌ No spells extracted")
|
||||
return
|
||||
|
||||
# Save to JSON file
|
||||
if save_spell_database(spell_mappings):
|
||||
# Show some sample spells
|
||||
print("\nSample spell entries:")
|
||||
for spell_id, spell_data in list(spell_mappings.items())[:5]:
|
||||
print(f" {spell_id}: {spell_data['name']} ({spell_data['school']})")
|
||||
|
||||
print(f"\n✓ Successfully processed {len(spell_mappings)} spells")
|
||||
else:
|
||||
print("❌ Failed to save spell database")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"AttributeSetInfo": {},
|
||||
"MaterialInfo": {},
|
||||
"SkillInfo": {},
|
||||
"MasteryInfo": {}
|
||||
}
|
||||
17
inventory-service/helpers.py
Normal file
17
inventory-service/helpers.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
"""
|
||||
Shared helper functions for inventory service and suitbuilder.
|
||||
This module contains utility functions that are used by both main.py and suitbuilder.py
|
||||
to avoid circular imports.
|
||||
"""
|
||||
|
||||
# This will be populated by main.py after loading
|
||||
ENUM_MAPPINGS = None
|
||||
|
||||
def set_enum_mappings(mappings):
|
||||
"""Set the enum mappings from main.py after loading."""
|
||||
global ENUM_MAPPINGS
|
||||
ENUM_MAPPINGS = mappings
|
||||
|
||||
def get_enum_mappings():
|
||||
"""Get the loaded enum mappings."""
|
||||
return ENUM_MAPPINGS
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Initialize the inventory service database.
|
||||
Creates all tables and performs initial setup.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
import sqlalchemy as sa
|
||||
from database import Base, DATABASE_URL, create_indexes
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
async def init_database():
|
||||
"""Initialize database tables and indexes."""
|
||||
try:
|
||||
# Create engine
|
||||
engine = sa.create_engine(DATABASE_URL)
|
||||
|
||||
# Create all tables
|
||||
logger.info("Creating database tables...")
|
||||
Base.metadata.create_all(engine)
|
||||
|
||||
# Create indexes
|
||||
logger.info("Creating performance indexes...")
|
||||
create_indexes(engine)
|
||||
|
||||
logger.info("Database initialization completed successfully")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Database initialization failed: {e}")
|
||||
raise
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(init_database())
|
||||
|
|
@ -1,450 +0,0 @@
|
|||
{
|
||||
"0": "Undef",
|
||||
"1": "ItemType",
|
||||
"2": "CreatureType",
|
||||
"3": "PaletteTemplate",
|
||||
"4": "ClothingPriority",
|
||||
"5": "EncumbranceVal",
|
||||
"6": "ItemsCapacity",
|
||||
"7": "ContainersCapacity",
|
||||
"8": "Mass",
|
||||
"9": "ValidLocations",
|
||||
"10": "CurrentWieldedLocation",
|
||||
"11": "MaxStackSize",
|
||||
"12": "StackSize",
|
||||
"13": "StackUnitEncumbrance",
|
||||
"14": "StackUnitMass",
|
||||
"15": "StackUnitValue",
|
||||
"16": "ItemUseable",
|
||||
"17": "RareId",
|
||||
"18": "UiEffects",
|
||||
"19": "Value",
|
||||
"20": "CoinValue",
|
||||
"21": "TotalExperience",
|
||||
"22": "AvailableCharacter",
|
||||
"23": "TotalSkillCredits",
|
||||
"24": "AvailableSkillCredits",
|
||||
"25": "Level",
|
||||
"26": "AccountRequirements",
|
||||
"27": "ArmorType",
|
||||
"28": "ArmorLevel",
|
||||
"29": "AllegianceCpPool",
|
||||
"30": "AllegianceRank",
|
||||
"31": "ChannelsAllowed",
|
||||
"32": "ChannelsActive",
|
||||
"33": "Bonded",
|
||||
"34": "MonarchsRank",
|
||||
"35": "AllegianceFollowers",
|
||||
"36": "ResistMagic",
|
||||
"37": "ResistItemAppraisal",
|
||||
"38": "ResistLockpick",
|
||||
"39": "DeprecatedResistRepair",
|
||||
"40": "CombatMode",
|
||||
"41": "CurrentAttackHeight",
|
||||
"42": "CombatCollisions",
|
||||
"43": "NumDeaths",
|
||||
"44": "Damage",
|
||||
"45": "DamageType",
|
||||
"46": "DefaultCombatStyle",
|
||||
"47": "AttackType",
|
||||
"48": "WeaponSkill",
|
||||
"49": "WeaponTime",
|
||||
"50": "AmmoType",
|
||||
"51": "CombatUse",
|
||||
"52": "ParentLocation",
|
||||
"53": "PlacementPosition",
|
||||
"54": "WeaponEncumbrance",
|
||||
"55": "WeaponMass",
|
||||
"56": "ShieldValue",
|
||||
"57": "ShieldEncumbrance",
|
||||
"58": "MissileInventoryLocation",
|
||||
"59": "FullDamageType",
|
||||
"60": "WeaponRange",
|
||||
"61": "AttackersSkill",
|
||||
"62": "DefendersSkill",
|
||||
"63": "AttackersSkillValue",
|
||||
"64": "AttackersClass",
|
||||
"65": "Placement",
|
||||
"66": "CheckpointStatus",
|
||||
"67": "Tolerance",
|
||||
"68": "TargetingTactic",
|
||||
"69": "CombatTactic",
|
||||
"70": "HomesickTargetingTactic",
|
||||
"71": "NumFollowFailures",
|
||||
"72": "FriendType",
|
||||
"73": "FoeType",
|
||||
"74": "MerchandiseItemTypes",
|
||||
"75": "MerchandiseMinValue",
|
||||
"76": "MerchandiseMaxValue",
|
||||
"77": "NumItemsSold",
|
||||
"78": "NumItemsBought",
|
||||
"79": "MoneyIncome",
|
||||
"80": "MoneyOutflow",
|
||||
"81": "MaxGeneratedObjects",
|
||||
"82": "InitGeneratedObjects",
|
||||
"83": "ActivationResponse",
|
||||
"84": "OriginalValue",
|
||||
"85": "NumMoveFailures",
|
||||
"86": "MinLevel",
|
||||
"87": "MaxLevel",
|
||||
"88": "LockpickMod",
|
||||
"89": "BoosterEnum",
|
||||
"90": "BoostValue",
|
||||
"91": "MaxStructure",
|
||||
"92": "Structure",
|
||||
"93": "PhysicsState",
|
||||
"94": "TargetType",
|
||||
"95": "RadarBlipColor",
|
||||
"96": "EncumbranceCapacity",
|
||||
"97": "LoginTimestamp",
|
||||
"98": "CreationTimestamp",
|
||||
"99": "PkLevelModifier",
|
||||
"100": "GeneratorType",
|
||||
"101": "AiAllowedCombatStyle",
|
||||
"102": "LogoffTimestamp",
|
||||
"103": "GeneratorDestructionType",
|
||||
"104": "ActivationCreateClass",
|
||||
"105": "ItemWorkmanship",
|
||||
"106": "ItemSpellcraft",
|
||||
"107": "ItemCurMana",
|
||||
"108": "ItemMaxMana",
|
||||
"109": "ItemDifficulty",
|
||||
"110": "ItemAllegianceRankLimit",
|
||||
"111": "PortalBitmask",
|
||||
"112": "AdvocateLevel",
|
||||
"113": "Gender",
|
||||
"114": "Attuned",
|
||||
"115": "ItemSkillLevelLimit",
|
||||
"116": "GateLogic",
|
||||
"117": "ItemManaCost",
|
||||
"118": "Logoff",
|
||||
"119": "Active",
|
||||
"120": "AttackHeight",
|
||||
"121": "NumAttackFailures",
|
||||
"122": "AiCpThreshold",
|
||||
"123": "AiAdvancementStrategy",
|
||||
"124": "Version",
|
||||
"125": "Age",
|
||||
"126": "VendorHappyMean",
|
||||
"127": "VendorHappyVariance",
|
||||
"128": "CloakStatus",
|
||||
"129": "VitaeCpPool",
|
||||
"130": "NumServicesSold",
|
||||
"131": "MaterialType",
|
||||
"132": "NumAllegianceBreaks",
|
||||
"133": "ShowableOnRadar",
|
||||
"134": "PlayerKillerStatus",
|
||||
"135": "VendorHappyMaxItems",
|
||||
"136": "ScorePageNum",
|
||||
"137": "ScoreConfigNum",
|
||||
"138": "ScoreNumScores",
|
||||
"139": "DeathLevel",
|
||||
"140": "AiOptions",
|
||||
"141": "OpenToEveryone",
|
||||
"142": "GeneratorTimeType",
|
||||
"143": "GeneratorStartTime",
|
||||
"144": "GeneratorEndTime",
|
||||
"145": "GeneratorEndDestructionType",
|
||||
"146": "XpOverride",
|
||||
"147": "NumCrashAndTurns",
|
||||
"148": "ComponentWarningThreshold",
|
||||
"149": "HouseStatus",
|
||||
"150": "HookPlacement",
|
||||
"151": "HookType",
|
||||
"152": "HookItemType",
|
||||
"153": "AiPpThreshold",
|
||||
"154": "GeneratorVersion",
|
||||
"155": "HouseType",
|
||||
"156": "PickupEmoteOffset",
|
||||
"157": "WeenieIteration",
|
||||
"158": "WieldRequirements",
|
||||
"159": "WieldSkillType",
|
||||
"160": "WieldDifficulty",
|
||||
"161": "HouseMaxHooksUsable",
|
||||
"162": "HouseCurrentHooksUsable",
|
||||
"163": "AllegianceMinLevel",
|
||||
"164": "AllegianceMaxLevel",
|
||||
"165": "HouseRelinkHookCount",
|
||||
"166": "SlayerCreatureType",
|
||||
"167": "ConfirmationInProgress",
|
||||
"168": "ConfirmationTypeInProgress",
|
||||
"169": "TsysMutationData",
|
||||
"170": "NumItemsInMaterial",
|
||||
"171": "NumTimesTinkered",
|
||||
"172": "AppraisalLongDescDecoration",
|
||||
"173": "AppraisalLockpickSuccessPercent",
|
||||
"174": "AppraisalPages",
|
||||
"175": "AppraisalMaxPages",
|
||||
"176": "AppraisalItemSkill",
|
||||
"177": "GemCount",
|
||||
"178": "GemType",
|
||||
"179": "ImbuedEffect",
|
||||
"180": "AttackersRawSkillValue",
|
||||
"181": "ChessRank",
|
||||
"182": "ChessTotalGames",
|
||||
"183": "ChessGamesWon",
|
||||
"184": "ChessGamesLost",
|
||||
"185": "TypeOfAlteration",
|
||||
"186": "SkillToBeAltered",
|
||||
"187": "SkillAlterationCount",
|
||||
"188": "HeritageGroup",
|
||||
"189": "TransferFromAttribute",
|
||||
"190": "TransferToAttribute",
|
||||
"191": "AttributeTransferCount",
|
||||
"192": "FakeFishingSkill",
|
||||
"193": "NumKeys",
|
||||
"194": "DeathTimestamp",
|
||||
"195": "PkTimestamp",
|
||||
"196": "VictimTimestamp",
|
||||
"197": "HookGroup",
|
||||
"198": "AllegianceSwearTimestamp",
|
||||
"199": "HousePurchaseTimestamp",
|
||||
"200": "RedirectableEquippedArmorCount",
|
||||
"201": "MeleeDefenseImbuedEffectTypeCache",
|
||||
"202": "MissileDefenseImbuedEffectTypeCache",
|
||||
"203": "MagicDefenseImbuedEffectTypeCache",
|
||||
"204": "ElementalDamageBonus",
|
||||
"205": "ImbueAttempts",
|
||||
"206": "ImbueSuccesses",
|
||||
"207": "CreatureKills",
|
||||
"208": "PlayerKillsPk",
|
||||
"209": "PlayerKillsPkl",
|
||||
"210": "RaresTierOne",
|
||||
"211": "RaresTierTwo",
|
||||
"212": "RaresTierThree",
|
||||
"213": "RaresTierFour",
|
||||
"214": "RaresTierFive",
|
||||
"215": "AugmentationStat",
|
||||
"216": "AugmentationFamilyStat",
|
||||
"217": "AugmentationInnateFamily",
|
||||
"218": "AugmentationInnateStrength",
|
||||
"219": "AugmentationInnateEndurance",
|
||||
"220": "AugmentationInnateCoordination",
|
||||
"221": "AugmentationInnateQuickness",
|
||||
"222": "AugmentationInnateFocus",
|
||||
"223": "AugmentationInnateSelf",
|
||||
"224": "AugmentationSpecializeSalvaging",
|
||||
"225": "AugmentationSpecializeItemTinkering",
|
||||
"226": "AugmentationSpecializeArmorTinkering",
|
||||
"227": "AugmentationSpecializeMagicItemTinkering",
|
||||
"228": "AugmentationSpecializeWeaponTinkering",
|
||||
"229": "AugmentationExtraPackSlot",
|
||||
"230": "AugmentationIncreasedCarryingCapacity",
|
||||
"231": "AugmentationLessDeathItemLoss",
|
||||
"232": "AugmentationSpellsRemainPastDeath",
|
||||
"233": "AugmentationCriticalDefense",
|
||||
"234": "AugmentationBonusXp",
|
||||
"235": "AugmentationBonusSalvage",
|
||||
"236": "AugmentationBonusImbueChance",
|
||||
"237": "AugmentationFasterRegen",
|
||||
"238": "AugmentationIncreasedSpellDuration",
|
||||
"239": "AugmentationResistanceFamily",
|
||||
"240": "AugmentationResistanceSlash",
|
||||
"241": "AugmentationResistancePierce",
|
||||
"242": "AugmentationResistanceBlunt",
|
||||
"243": "AugmentationResistanceAcid",
|
||||
"244": "AugmentationResistanceFire",
|
||||
"245": "AugmentationResistanceFrost",
|
||||
"246": "AugmentationResistanceLightning",
|
||||
"247": "RaresTierOneLogin",
|
||||
"248": "RaresTierTwoLogin",
|
||||
"249": "RaresTierThreeLogin",
|
||||
"250": "RaresTierFourLogin",
|
||||
"251": "RaresTierFiveLogin",
|
||||
"252": "RaresLoginTimestamp",
|
||||
"253": "RaresTierSix",
|
||||
"254": "RaresTierSeven",
|
||||
"255": "RaresTierSixLogin",
|
||||
"256": "RaresTierSevenLogin",
|
||||
"257": "ItemAttributeLimit",
|
||||
"258": "ItemAttributeLevelLimit",
|
||||
"259": "ItemAttribute2ndLimit",
|
||||
"260": "ItemAttribute2ndLevelLimit",
|
||||
"261": "CharacterTitleId",
|
||||
"262": "NumCharacterTitles",
|
||||
"263": "ResistanceModifierType",
|
||||
"264": "FreeTinkersBitfield",
|
||||
"265": "EquipmentSetId",
|
||||
"266": "PetClass",
|
||||
"267": "Lifespan",
|
||||
"268": "RemainingLifespan",
|
||||
"269": "UseCreateQuantity",
|
||||
"270": "WieldRequirements2",
|
||||
"271": "WieldSkillType2",
|
||||
"272": "WieldDifficulty2",
|
||||
"273": "WieldRequirements3",
|
||||
"274": "WieldSkillType3",
|
||||
"275": "WieldDifficulty3",
|
||||
"276": "WieldRequirements4",
|
||||
"277": "WieldSkillType4",
|
||||
"278": "WieldDifficulty4",
|
||||
"279": "Unique",
|
||||
"280": "SharedCooldown",
|
||||
"281": "Faction1Bits",
|
||||
"282": "Faction2Bits",
|
||||
"283": "Faction3Bits",
|
||||
"284": "Hatred1Bits",
|
||||
"285": "Hatred2Bits",
|
||||
"286": "Hatred3Bits",
|
||||
"287": "SocietyRankCelhan",
|
||||
"288": "SocietyRankEldweb",
|
||||
"289": "SocietyRankRadblo",
|
||||
"290": "HearLocalSignals",
|
||||
"291": "HearLocalSignalsRadius",
|
||||
"292": "Cleaving",
|
||||
"293": "AugmentationSpecializeGearcraft",
|
||||
"294": "AugmentationInfusedCreatureMagic",
|
||||
"295": "AugmentationInfusedItemMagic",
|
||||
"296": "AugmentationInfusedLifeMagic",
|
||||
"297": "AugmentationInfusedWarMagic",
|
||||
"298": "AugmentationCriticalExpertise",
|
||||
"299": "AugmentationCriticalPower",
|
||||
"300": "AugmentationSkilledMelee",
|
||||
"301": "AugmentationSkilledMissile",
|
||||
"302": "AugmentationSkilledMagic",
|
||||
"303": "ImbuedEffect2",
|
||||
"304": "ImbuedEffect3",
|
||||
"305": "ImbuedEffect4",
|
||||
"306": "ImbuedEffect5",
|
||||
"307": "DamageRating",
|
||||
"308": "DamageResistRating",
|
||||
"309": "AugmentationDamageBonus",
|
||||
"310": "AugmentationDamageReduction",
|
||||
"311": "ImbueStackingBits",
|
||||
"312": "HealOverTime",
|
||||
"313": "CritRating",
|
||||
"314": "CritDamageRating",
|
||||
"315": "CritResistRating",
|
||||
"316": "CritDamageResistRating",
|
||||
"317": "HealingResistRating",
|
||||
"318": "DamageOverTime",
|
||||
"319": "ItemMaxLevel",
|
||||
"320": "ItemXpStyle",
|
||||
"321": "EquipmentSetExtra",
|
||||
"322": "AetheriaBitfield",
|
||||
"323": "HealingBoostRating",
|
||||
"324": "HeritageSpecificArmor",
|
||||
"325": "AlternateRacialSkills",
|
||||
"326": "AugmentationJackOfAllTrades",
|
||||
"327": "AugmentationResistanceNether",
|
||||
"328": "AugmentationInfusedVoidMagic",
|
||||
"329": "WeaknessRating",
|
||||
"330": "NetherOverTime",
|
||||
"331": "NetherResistRating",
|
||||
"332": "LuminanceAward",
|
||||
"333": "LumAugDamageRating",
|
||||
"334": "LumAugDamageReductionRating",
|
||||
"335": "LumAugCritDamageRating",
|
||||
"336": "LumAugCritReductionRating",
|
||||
"337": "LumAugSurgeEffectRating",
|
||||
"338": "LumAugSurgeChanceRating",
|
||||
"339": "LumAugItemManaUsage",
|
||||
"340": "LumAugItemManaGain",
|
||||
"341": "LumAugVitality",
|
||||
"342": "LumAugHealingRating",
|
||||
"343": "LumAugSkilledCraft",
|
||||
"344": "LumAugSkilledSpec",
|
||||
"345": "LumAugNoDestroyCraft",
|
||||
"346": "RestrictInteraction",
|
||||
"347": "OlthoiLootTimestamp",
|
||||
"348": "OlthoiLootStep",
|
||||
"349": "UseCreatesContractId",
|
||||
"350": "DotResistRating",
|
||||
"351": "LifeResistRating",
|
||||
"352": "CloakWeaveProc",
|
||||
"353": "WeaponType",
|
||||
"354": "MeleeMastery",
|
||||
"355": "RangedMastery",
|
||||
"356": "SneakAttackRating",
|
||||
"357": "RecklessnessRating",
|
||||
"358": "DeceptionRating",
|
||||
"359": "CombatPetRange",
|
||||
"360": "WeaponAuraDamage",
|
||||
"361": "WeaponAuraSpeed",
|
||||
"362": "SummoningMastery",
|
||||
"363": "HeartbeatLifespan",
|
||||
"364": "UseLevelRequirement",
|
||||
"365": "LumAugAllSkills",
|
||||
"366": "UseRequiresSkill",
|
||||
"367": "UseRequiresSkillLevel",
|
||||
"368": "UseRequiresSkillSpec",
|
||||
"369": "UseRequiresLevel",
|
||||
"370": "GearDamage",
|
||||
"371": "GearDamageResist",
|
||||
"372": "GearCrit",
|
||||
"373": "GearCritResist",
|
||||
"374": "GearCritDamage",
|
||||
"375": "GearCritDamageResist",
|
||||
"376": "GearHealingBoost",
|
||||
"377": "GearNetherResist",
|
||||
"378": "GearLifeResist",
|
||||
"379": "GearMaxHealth",
|
||||
"380": "Unknown380",
|
||||
"381": "PKDamageRating",
|
||||
"382": "PKDamageResistRating",
|
||||
"383": "GearPKDamageRating",
|
||||
"384": "GearPKDamageResistRating",
|
||||
"385": "Unknown385",
|
||||
"386": "Overpower",
|
||||
"387": "OverpowerResist",
|
||||
"388": "GearOverpower",
|
||||
"389": "GearOverpowerResist",
|
||||
"390": "Enlightenment",
|
||||
"8007": "PCAPRecordedAutonomousMovement",
|
||||
"8030": "PCAPRecordedMaxVelocityEstimated",
|
||||
"8041": "PCAPRecordedPlacement",
|
||||
"8042": "PCAPRecordedAppraisalPages",
|
||||
"8043": "PCAPRecordedAppraisalMaxPages",
|
||||
"9008": "CurrentLoyaltyAtLastLogoff",
|
||||
"9009": "CurrentLeadershipAtLastLogoff",
|
||||
"9010": "AllegianceOfficerRank",
|
||||
"9011": "HouseRentTimestamp",
|
||||
"9012": "Hairstyle",
|
||||
"9013": "VisualClothingPriority",
|
||||
"9014": "SquelchGlobal",
|
||||
"9015": "InventoryOrder",
|
||||
"218103808": "WeenieClassId_Decal",
|
||||
"218103809": "Icon_Decal_DID",
|
||||
"218103810": "Container_Decal_IID",
|
||||
"218103811": "Landblock_Decal",
|
||||
"218103812": "ItemSlots_Decal",
|
||||
"218103813": "PackSlots_Decal",
|
||||
"218103814": "StackCount_Decal",
|
||||
"218103815": "StackMax_Decal",
|
||||
"218103816": "Spell_Decal_DID",
|
||||
"218103817": "SlotLegacy_Decal",
|
||||
"218103818": "Wielder_Decal_IID",
|
||||
"218103819": "WieldingSlot_Decal",
|
||||
"218103820": "Monarch_Decal_IID",
|
||||
"218103821": "Coverage_Decal",
|
||||
"218103822": "EquipableSlots_Decal",
|
||||
"218103823": "EquipType_Decal",
|
||||
"218103824": "IconOutline_Decal",
|
||||
"218103825": "MissileType_Decal",
|
||||
"218103826": "UsageMask_Decal",
|
||||
"218103827": "HouseOwner_Decal_IID",
|
||||
"218103828": "HookMask_Decal",
|
||||
"218103829": "HookType_Decal",
|
||||
"218103830": "Setup_Decal_DID",
|
||||
"218103831": "ObjectDescriptionFlags_Decal",
|
||||
"218103832": "CreateFlags1_Decal",
|
||||
"218103833": "CreateFlags2_Decal",
|
||||
"218103834": "Category_Decal",
|
||||
"218103835": "Behavior_Decal",
|
||||
"218103836": "MagicDef_Decal",
|
||||
"218103837": "SpecialProps_Decal",
|
||||
"218103838": "SpellCount_Decal",
|
||||
"218103839": "WeapSpeed_Decal",
|
||||
"218103840": "EquipSkill_Decal",
|
||||
"218103841": "DamageType_Decal",
|
||||
"218103842": "MaxDamage_Decal",
|
||||
"218103843": "Unknown10_Decal",
|
||||
"218103844": "Unknown100000_Decal",
|
||||
"218103845": "Unknown800000_Decal",
|
||||
"218103846": "Unknown8000000_Decal",
|
||||
"218103847": "PhysicsDataFlags_Decal",
|
||||
"218103848": "ActiveSpellCount_Decal",
|
||||
"218103849": "IconOverlay_Decal_DID",
|
||||
"218103850": "IconUnderlay_Decal_DID",
|
||||
"231735296": "Slot_Decal"
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"basic": {
|
||||
"5": "encumbrance",
|
||||
"19": "value",
|
||||
"25": "level",
|
||||
"28": "armor_level",
|
||||
"44": "damage",
|
||||
"45": "damage_type"
|
||||
},
|
||||
"requirements": {
|
||||
"158": "wield_requirement",
|
||||
"160": "wield_level",
|
||||
"48": "weapon_skill"
|
||||
},
|
||||
"combat": {
|
||||
"218103842": "max_damage",
|
||||
"36": "resist_magic",
|
||||
"56": "shield_value"
|
||||
},
|
||||
"display": {
|
||||
"218103809": "icon",
|
||||
"218103849": "icon_overlay",
|
||||
"218103850": "icon_underlay"
|
||||
},
|
||||
"metadata": {
|
||||
"218103808": "weenie_class_id",
|
||||
"218103847": "physics_data_flags",
|
||||
"218103831": "object_desc_flags"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
1848
inventory-service/suitbuilder.py
Normal file
1848
inventory-service/suitbuilder.py
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue