package alt_advancement // AA tab/group constants based on group # from DB const ( AA_CLASS = 0 // Class-specific advancement trees AA_SUBCLASS = 1 // Subclass-specific advancement trees AA_SHADOW = 2 // Shadows advancement (from Shadows of Luclin) AA_HEROIC = 3 // Heroic advancement (from Destiny of Velious) AA_TRADESKILL = 4 // Tradeskill advancement trees AA_PRESTIGE = 5 // Prestige advancement (from Destiny of Velious) AA_TRADESKILL_PRESTIGE = 6 // Tradeskill prestige advancement AA_DRAGON = 7 // Dragon advancement AA_DRAGONCLASS = 8 // Dragon class-specific advancement AA_FARSEAS = 9 // Far Seas advancement ) // AA tab names for display var AATabNames = map[int8]string{ AA_CLASS: "Class", AA_SUBCLASS: "Subclass", AA_SHADOW: "Shadows", AA_HEROIC: "Heroic", AA_TRADESKILL: "Tradeskill", AA_PRESTIGE: "Prestige", AA_TRADESKILL_PRESTIGE: "Tradeskill Prestige", AA_DRAGON: "Dragon", AA_DRAGONCLASS: "Dragon Class", AA_FARSEAS: "Far Seas", } // Maximum AA values per tab (from C++ packet data) const ( MAX_CLASS_AA = 100 // 0x64 MAX_SUBCLASS_AA = 100 // 0x64 MAX_SHADOWS_AA = 70 // 0x46 MAX_HEROIC_AA = 50 // 0x32 MAX_TRADESKILL_AA = 40 // 0x28 MAX_PRESTIGE_AA = 25 // 0x19 MAX_TRADESKILL_PRESTIGE_AA = 25 // 0x19 MAX_DRAGON_AA = 100 // Estimated MAX_DRAGONCLASS_AA = 100 // Estimated MAX_FARSEAS_AA = 100 // Estimated ) // AA template constants const ( AA_TEMPLATE_PERSONAL_1 = 1 // Personal template 1 AA_TEMPLATE_PERSONAL_2 = 2 // Personal template 2 AA_TEMPLATE_PERSONAL_3 = 3 // Personal template 3 AA_TEMPLATE_SERVER_1 = 4 // Server template 1 AA_TEMPLATE_SERVER_2 = 5 // Server template 2 AA_TEMPLATE_SERVER_3 = 6 // Server template 3 AA_TEMPLATE_CURRENT = 7 // Current template (active in-game) AA_TEMPLATE_BACKUP = 8 // Backup template ) // AA template names for display var AATemplateNames = map[int8]string{ AA_TEMPLATE_PERSONAL_1: "Personal Template 1", AA_TEMPLATE_PERSONAL_2: "Personal Template 2", AA_TEMPLATE_PERSONAL_3: "Personal Template 3", AA_TEMPLATE_SERVER_1: "Server Template 1", AA_TEMPLATE_SERVER_2: "Server Template 2", AA_TEMPLATE_SERVER_3: "Server Template 3", AA_TEMPLATE_CURRENT: "Current", AA_TEMPLATE_BACKUP: "Backup", } // Expansion flag constants const ( EXPANSION_NONE int32 = 0 EXPANSION_RUINS_OF_KUNARK int32 = 1 << 0 // 0x01 EXPANSION_SHADOWS_OF_LUCLIN int32 = 1 << 1 // 0x02 EXPANSION_DESERT_OF_FLAMES int32 = 1 << 2 // 0x04 EXPANSION_KINGDOM_OF_SKY int32 = 1 << 3 // 0x08 EXPANSION_ECHOES_OF_FAYDWER int32 = 1 << 4 // 0x10 EXPANSION_RISE_OF_KUNARK int32 = 1 << 5 // 0x20 EXPANSION_THE_SHADOW_ODYSSEY int32 = 1 << 6 // 0x40 EXPANSION_SENTINEL_FATE int32 = 1 << 7 // 0x80 EXPANSION_DESTINY_OF_VELIOUS int32 = 1 << 8 // 0x100 EXPANSION_AGE_OF_DISCOVERY int32 = 1 << 9 // 0x200 EXPANSION_CHAINS_OF_ETERNITY int32 = 1 << 10 // 0x400 EXPANSION_TEARS_OF_VEESHAN int32 = 1 << 11 // 0x800 EXPANSION_ALTAR_OF_MALICE int32 = 1 << 12 // 0x1000 EXPANSION_TERRORS_OF_THALUMBRA int32 = 1 << 13 // 0x2000 EXPANSION_KUNARK_ASCENDING int32 = 1 << 14 // 0x4000 EXPANSION_PLANES_OF_PROPHECY int32 = 1 << 15 // 0x8000 EXPANSION_CHAOS_DESCENDING int32 = 1 << 16 // 0x10000 EXPANSION_BLOOD_OF_LUCLIN int32 = 1 << 17 // 0x20000 EXPANSION_VISIONS_OF_VETROVIA int32 = 1 << 18 // 0x40000 EXPANSION_RENEWAL_OF_RO int32 = 1 << 19 // 0x80000 ) // AA system configuration defaults const ( DEFAULT_ENABLE_AA_SYSTEM = true DEFAULT_ENABLE_AA_CACHING = true DEFAULT_ENABLE_AA_VALIDATION = true DEFAULT_ENABLE_AA_LOGGING = true DEFAULT_AA_POINTS_PER_LEVEL = 2 DEFAULT_AA_MAX_BANKED_POINTS = 100 AA_CACHE_SIZE = 10000 AA_UPDATE_INTERVAL = 30000 // 30 seconds in milliseconds AA_PROCESSING_BATCH_SIZE = 100 ) // AA purchase and refund constants const ( AA_PURCHASE_SUCCESS = 0 AA_PURCHASE_FAILED = 1 AA_REFUND_SUCCESS = 0 AA_REFUND_FAILED = 1 ) // AA validation error codes const ( AA_ERROR_NONE = 0 AA_ERROR_NOT_FOUND = 1 AA_ERROR_INSUFFICIENT_POINTS = 2 AA_ERROR_LEVEL_TOO_LOW = 3 AA_ERROR_WRONG_CLASS = 4 AA_ERROR_PREREQUISITES_NOT_MET = 5 AA_ERROR_MAX_RANK_REACHED = 6 AA_ERROR_INVALID_RANK = 7 AA_ERROR_TREE_POINTS_REQUIRED = 8 AA_ERROR_EXPANSION_REQUIRED = 9 AA_ERROR_TEMPLATE_LOCKED = 10 AA_ERROR_DATABASE_ERROR = 11 AA_ERROR_SYSTEM_DISABLED = 12 ) // AA error messages var AAErrorMessages = map[int]string{ AA_ERROR_NONE: "Success", AA_ERROR_NOT_FOUND: "AA not found", AA_ERROR_INSUFFICIENT_POINTS: "Insufficient AA points", AA_ERROR_LEVEL_TOO_LOW: "Level requirement not met", AA_ERROR_WRONG_CLASS: "Class requirement not met", AA_ERROR_PREREQUISITES_NOT_MET: "Prerequisites not met", AA_ERROR_MAX_RANK_REACHED: "Maximum rank already reached", AA_ERROR_INVALID_RANK: "Invalid target rank", AA_ERROR_TREE_POINTS_REQUIRED: "Insufficient points spent in tree", AA_ERROR_EXPANSION_REQUIRED: "Expansion requirement not met", AA_ERROR_TEMPLATE_LOCKED: "Template is locked", AA_ERROR_DATABASE_ERROR: "Database error occurred", AA_ERROR_SYSTEM_DISABLED: "AA system is disabled", } // GetMaxAAForTab returns the maximum AA points for a given tab func GetMaxAAForTab(group int8) int32 { switch group { case AA_CLASS: return MAX_CLASS_AA case AA_SUBCLASS: return MAX_SUBCLASS_AA case AA_SHADOW: return MAX_SHADOWS_AA case AA_HEROIC: return MAX_HEROIC_AA case AA_TRADESKILL: return MAX_TRADESKILL_AA case AA_PRESTIGE: return MAX_PRESTIGE_AA case AA_TRADESKILL_PRESTIGE: return MAX_TRADESKILL_PRESTIGE_AA case AA_DRAGON: return MAX_DRAGON_AA case AA_DRAGONCLASS: return MAX_DRAGONCLASS_AA case AA_FARSEAS: return MAX_FARSEAS_AA default: return 100 // Default maximum } } // GetTabName returns the display name for an AA tab func GetTabName(group int8) string { if name, exists := AATabNames[group]; exists { return name } return "Unknown" } // GetTemplateName returns the display name for an AA template func GetTemplateName(templateID int8) string { if name, exists := AATemplateNames[templateID]; exists { return name } return "Unknown" } // IsExpansionRequired checks if a specific expansion is required func IsExpansionRequired(flags int32, expansion int32) bool { return (flags & expansion) != 0 } // GetAAErrorMessage returns the error message for an AA error code func GetAAErrorMessage(errorCode int) string { if message, exists := AAErrorMessages[errorCode]; exists { return message } return "Unknown error" } // ValidateTemplateID checks if a template ID is valid func ValidateTemplateID(templateID int8) bool { return templateID >= AA_TEMPLATE_PERSONAL_1 && templateID <= AA_TEMPLATE_BACKUP } // IsPersonalTemplate checks if a template is a personal template func IsPersonalTemplate(templateID int8) bool { return templateID >= AA_TEMPLATE_PERSONAL_1 && templateID <= AA_TEMPLATE_PERSONAL_3 } // IsServerTemplate checks if a template is a server template func IsServerTemplate(templateID int8) bool { return templateID >= AA_TEMPLATE_SERVER_1 && templateID <= AA_TEMPLATE_SERVER_3 } // IsCurrentTemplate checks if a template is the current active template func IsCurrentTemplate(templateID int8) bool { return templateID == AA_TEMPLATE_CURRENT } // ValidateAAGroup checks if an AA group is valid func ValidateAAGroup(group int8) bool { return group >= AA_CLASS && group <= AA_FARSEAS } // GetExpansionNameByFlag returns the expansion name for a flag func GetExpansionNameByFlag(flag int32) string { switch flag { case EXPANSION_RUINS_OF_KUNARK: return "Ruins of Kunark" case EXPANSION_SHADOWS_OF_LUCLIN: return "Shadows of Luclin" case EXPANSION_DESERT_OF_FLAMES: return "Desert of Flames" case EXPANSION_KINGDOM_OF_SKY: return "Kingdom of Sky" case EXPANSION_ECHOES_OF_FAYDWER: return "Echoes of Faydwer" case EXPANSION_RISE_OF_KUNARK: return "Rise of Kunark" case EXPANSION_THE_SHADOW_ODYSSEY: return "The Shadow Odyssey" case EXPANSION_SENTINEL_FATE: return "Sentinel's Fate" case EXPANSION_DESTINY_OF_VELIOUS: return "Destiny of Velious" case EXPANSION_AGE_OF_DISCOVERY: return "Age of Discovery" case EXPANSION_CHAINS_OF_ETERNITY: return "Chains of Eternity" case EXPANSION_TEARS_OF_VEESHAN: return "Tears of Veeshan" case EXPANSION_ALTAR_OF_MALICE: return "Altar of Malice" case EXPANSION_TERRORS_OF_THALUMBRA: return "Terrors of Thalumbra" case EXPANSION_KUNARK_ASCENDING: return "Kunark Ascending" case EXPANSION_PLANES_OF_PROPHECY: return "Planes of Prophecy" case EXPANSION_CHAOS_DESCENDING: return "Chaos Descending" case EXPANSION_BLOOD_OF_LUCLIN: return "Blood of Luclin" case EXPANSION_VISIONS_OF_VETROVIA: return "Visions of Vetrovia" case EXPANSION_RENEWAL_OF_RO: return "Renewal of Ro" default: return "Unknown Expansion" } }