using System; using System.Collections.Generic; using System.Linq; using ACE.Database.Models.World; namespace ACE.Adapter.GDLE { public static class GDLEConverter { /// /// Converts ACE -> GDLE quest /// public static bool TryConvert(Quest input, out Models.Quest result) { result = new Models.Quest(); result.key = input.Name; var quest = new Models.QuestValue(); quest.fullname = input.Message; quest.mindelta = (int)input.MinDelta; quest.maxsolves = input.MaxSolves; result.value = quest; return true; } public static Dictionary WeenieNames; public static Dictionary WeenieClassNames; /// /// Converts ACE landblock instances -> GDLE landblock instances /// public static bool TryConvert(List input, out Models.Landblock result) { var instanceWcids = new Dictionary(); foreach (var instance in input) instanceWcids.Add(instance.Guid, instance.WeenieClassId); result = new Models.Landblock(); if (input.Count == 0) return true; result.key = (uint)input[0].Landblock << 16; result.value = new Models.LandblockValue(); result.desc = $"{result.key}({input[0].Landblock:X4})"; foreach (var lbi in input) { if (result.value.weenies == null) result.value.weenies = new List(); var weenie = new Models.LandblockWeenie(); weenie.id = lbi.Guid; weenie.wcid = lbi.WeenieClassId; if (WeenieNames != null && WeenieClassNames != null) { WeenieNames.TryGetValue(lbi.WeenieClassId, out var weenieName); WeenieClassNames.TryGetValue(lbi.WeenieClassId, out var weenieClassName); weenie.desc = $"{weenieName}({weenieClassName})"; } // fix this ***, write it properly. var pos = new Models.Position(); pos.LandCellId = lbi.ObjCellId; var frame = new Models.Frame(); frame.Position = new Models.XYZ(); frame.Position.X = lbi.OriginX; frame.Position.Y = lbi.OriginY; frame.Position.Z = lbi.OriginZ; frame.Rotations = new Models.Quaternion(); frame.Rotations.W = lbi.AnglesW; frame.Rotations.X = lbi.AnglesX; frame.Rotations.Y = lbi.AnglesY; frame.Rotations.Z = lbi.AnglesZ; pos.Frame = frame; weenie.pos = pos; result.value.weenies.Add(weenie); if (lbi.LandblockInstanceLink != null) { foreach (var link in lbi.LandblockInstanceLink) { if (result.value.links == null) result.value.links = new List(); var _link = new Models.LandblockLink(); _link.target = link.ParentGuid; _link.source = link.ChildGuid; if (WeenieNames != null && WeenieClassNames != null) { WeenieNames.TryGetValue(lbi.WeenieClassId, out var targetName); WeenieClassNames.TryGetValue(lbi.WeenieClassId, out var targetClassName); if (instanceWcids.TryGetValue(link.ChildGuid, out var sourceWcid)) { WeenieNames.TryGetValue(sourceWcid, out var sourceName); WeenieClassNames.TryGetValue(sourceWcid, out var sourceClassName); _link.desc = $"{sourceName}({sourceClassName})(wcid: {sourceWcid}) -> {targetClassName}(wcid: {lbi.WeenieClassId})"; } } result.value.links.Add(_link); } } } return true; } /// /// Converts GDLE spawn map -> ACE landblock instances /// /// This will not alter the Guid. To sanitize the Guid for ACE usage, you should use GDLELoader.TryLoadWorldSpawnsConverted() instead. /// public static bool TryConvert(Models.Landblock input, out List results, out List links) { try { results = new List(); links = new List(); foreach (var value in input.value.weenies) { var result = new LandblockInstance(); result.Guid = value.id; // Collisions and other errors can be caused by invalid input. Data should be sanitized by the running ACE server. //result.Landblock = input.key; ACE uses a virtual column here of (result.ObjCellId >> 16) result.WeenieClassId = value.wcid; result.ObjCellId = value.pos.LandCellId; result.OriginX = value.pos.Frame.Position.X; result.OriginY = value.pos.Frame.Position.Y; result.OriginZ = value.pos.Frame.Position.Z; result.AnglesW = value.pos.Frame.Rotations.W; result.AnglesX = value.pos.Frame.Rotations.X; result.AnglesY = value.pos.Frame.Rotations.Y; result.AnglesZ = value.pos.Frame.Rotations.Z; results.Add(result); } if (input.value.links != null) { foreach (var value in input.value.links) { var result = new LandblockInstanceLink(); result.ParentGuid = value.target; result.ChildGuid = value.source; links.Add(result); } } // reguid if needed var landblockId = (ushort)(input.key >> 16); ReGuidAndConvertLandblocks(results, links, landblockId); return true; } catch { results = null; links = null; return false; } } private static void ReGuidAndConvertLandblocks(List instances, List links, ushort landblockId) { var firstGuid = 0x70000000 | ((uint)landblockId << 12); var lastGuid = firstGuid | 0xFFF; var nextGuid = firstGuid; var reguid = new Dictionary(); foreach (var instance in instances) { if (instance.Guid < firstGuid || instance.Guid > lastGuid) { reguid.Add(instance.Guid, nextGuid); instance.Guid = nextGuid++; } } foreach (var link in links) { if (reguid.TryGetValue(link.ParentGuid, out var newParentGuid)) link.ParentGuid = newParentGuid; if (reguid.TryGetValue(link.ChildGuid, out var newChildGuid)) link.ChildGuid = newChildGuid; } } public static bool TryConvert(Models.Event input, out Event result) { try { result = new Event(); //result.Id // This is an Auto Increment field in the ACE schema result.Name = input.Key; result.StartTime = input.Value.StartTime; result.EndTime = input.Value.EndTime; result.State = input.Value.EventState; return true; } catch { result = null; return false; } } /// /// Converts GDLE -> ACE quest /// public static bool TryConvert(Models.Quest input, out Quest result) { try { result = new Quest(); //result.Id // This is an Auto Increment field in the ACE schema result.Name = input.key; // FIXME: db schema should be int result.MinDelta = (uint)input.value.mindelta; result.MaxSolves = input.value.maxsolves; result.Message = input.value.fullname; return true; } catch { result = null; return false; } } public static bool TryConvert(uint id, Models.SpellValue input, out Spell result) { try { result = new Spell(); result.Id = id; result.Name = input.Name; if (input.MetaSpell.Spell.StatMod != null) { result.StatModType = input.MetaSpell.Spell.StatMod.Type; result.StatModKey = input.MetaSpell.Spell.StatMod.Key; result.StatModVal = (float)input.MetaSpell.Spell.StatMod.Val; } // Projectile, LifeProjectile result.EType = input.MetaSpell.Spell.EType; result.BaseIntensity = input.MetaSpell.Spell.BaseIntensity; result.Variance = input.MetaSpell.Spell.Variance; result.Wcid = input.MetaSpell.Spell.Wcid; result.NumProjectiles = input.MetaSpell.Spell.NumProjectiles; result.NumProjectilesVariance = (int?)input.MetaSpell.Spell.NumProjectilesVariance; result.SpreadAngle = input.MetaSpell.Spell.SpreadAngle; result.VerticalAngle = input.MetaSpell.Spell.VerticalAngle; result.DefaultLaunchAngle = input.MetaSpell.Spell.DefaultLaunchAngle; result.NonTracking = input.MetaSpell.Spell.NonTracking; if (input.MetaSpell.Spell.CreateOffset != null) { result.CreateOffsetOriginX = (float)input.MetaSpell.Spell.CreateOffset.X; result.CreateOffsetOriginY = (float)input.MetaSpell.Spell.CreateOffset.Y; result.CreateOffsetOriginZ = (float)input.MetaSpell.Spell.CreateOffset.Z; } if (input.MetaSpell.Spell.Padding != null) { result.PaddingOriginX = (float)input.MetaSpell.Spell.Padding.X; result.PaddingOriginY = (float)input.MetaSpell.Spell.Padding.Y; result.PaddingOriginZ = (float)input.MetaSpell.Spell.Padding.Z; } if (input.MetaSpell.Spell.Dims != null) { result.DimsOriginX = (float)input.MetaSpell.Spell.Dims.X; result.DimsOriginY = (float)input.MetaSpell.Spell.Dims.Y; result.DimsOriginZ = (float)input.MetaSpell.Spell.Dims.Z; } if (input.MetaSpell.Spell.Peturbation != null) { result.PeturbationOriginX = (float)input.MetaSpell.Spell.Peturbation.X; result.PeturbationOriginY = (float)input.MetaSpell.Spell.Peturbation.Y; result.PeturbationOriginZ = (float)input.MetaSpell.Spell.Peturbation.Z; } result.ImbuedEffect = input.MetaSpell.Spell.ImbuedEffect; result.SlayerCreatureType = input.MetaSpell.Spell.SlayerCreatureType; result.SlayerDamageBonus = input.MetaSpell.Spell.SlayerDamageBonus; result.CritFreq = input.MetaSpell.Spell.CritFreq; result.CritMultiplier = input.MetaSpell.Spell.CritMultiplier; result.IgnoreMagicResist = input.MetaSpell.Spell.IgnoreMagicResist; result.ElementalModifier = input.MetaSpell.Spell.ElementalModifier; // LifeProjectile result.DrainPercentage = (float?)input.MetaSpell.Spell.DrainPercentage; result.DamageRatio = (float?)input.MetaSpell.Spell.DamageRatio; // Boost, FellowBoost result.DamageType = input.MetaSpell.Spell.DamageType; result.Boost = input.MetaSpell.Spell.Boost; result.BoostVariance = input.MetaSpell.Spell.BoostVariance; // Transfer result.Source = input.MetaSpell.Spell.Source; result.Destination = input.MetaSpell.Spell.Dest; result.Proportion = (float?)input.MetaSpell.Spell.Proportion; result.LossPercent = (float?)input.MetaSpell.Spell.LossPercent; result.SourceLoss = input.MetaSpell.Spell.SourceLoss; result.TransferCap = input.MetaSpell.Spell.TransferCap; result.MaxBoostAllowed = input.MetaSpell.Spell.MaxBoostAllowed; result.TransferBitfield = input.MetaSpell.Spell.Bitfield; // PortalLink result.Index = input.MetaSpell.Spell.Index; // PortalSummon result.Link = input.MetaSpell.Spell.Link; // PortalSending, FellowPortalSending if (input.MetaSpell.Spell.Position != null) { result.PositionObjCellId = input.MetaSpell.Spell.Position.LandCellId; result.PositionOriginX = input.MetaSpell.Spell.Position.Frame.Position.X; result.PositionOriginY = input.MetaSpell.Spell.Position.Frame.Position.Y; result.PositionOriginZ = input.MetaSpell.Spell.Position.Frame.Position.Z; result.PositionAnglesW = input.MetaSpell.Spell.Position.Frame.Rotations.W; result.PositionAnglesX = input.MetaSpell.Spell.Position.Frame.Rotations.X; result.PositionAnglesY = input.MetaSpell.Spell.Position.Frame.Rotations.Y; result.PositionAnglesZ = input.MetaSpell.Spell.Position.Frame.Rotations.Z; } // Dispel, FellowDispel result.MinPower = input.MetaSpell.Spell.MinPower; result.MaxPower = input.MetaSpell.Spell.MaxPower; result.PowerVariance = input.MetaSpell.Spell.PowerVariance; //result.DispelSchool = input.DispelSchool; // TODO!!! result.Align = input.MetaSpell.Spell.Align; result.Number = input.MetaSpell.Spell.Number; result.NumberVariance = (float?)input.MetaSpell.Spell.NumberVariance; return true; } catch { result = null; return false; } } public static int GetIndex(RecipeMod mod) { if (mod.RecipeModsBool != null && mod.RecipeModsBool.Count > 0) return mod.RecipeModsBool.First().Index; if (mod.RecipeModsDID != null && mod.RecipeModsDID.Count > 0) return mod.RecipeModsDID.First().Index; if (mod.RecipeModsFloat != null && mod.RecipeModsFloat.Count > 0) return mod.RecipeModsFloat.First().Index; if (mod.RecipeModsIID != null && mod.RecipeModsIID.Count > 0) return mod.RecipeModsIID.First().Index; if (mod.RecipeModsInt != null && mod.RecipeModsInt.Count > 0) return mod.RecipeModsInt.First().Index; if (mod.RecipeModsString != null && mod.RecipeModsString.Count > 0) return mod.RecipeModsString.First().Index; return -1; } /// /// Converts ACE recipe + cookbooks to GDLE recipe + precursors /// public static bool TryConvert(List cookbooks, out Models.RecipeCombined result) { if (cookbooks == null || cookbooks.Count == 0 || cookbooks[0].Recipe == null) { result = null; return false; } var recipe = cookbooks[0].Recipe; result = new Models.RecipeCombined(); result.key = recipe.Id; result.desc = cookbooks[0].SourceWCID.ToString(); // TODO: get weenie name if (!TryConvert(recipe, out var newRecipe)) return false; newRecipe.RecipeId = 0; result.recipe = newRecipe; result.precursors = new List(); foreach (var cookbook in cookbooks) { if (TryConvert(cookbook, out var precursor)) { precursor.RecipeId = null; result.precursors.Add(precursor); } } return true; } /// /// Converts an ACE recipe to GDLE recipe /// public static bool TryConvert(Recipe input, out Models.Recipe result) { try { result = new Models.Recipe(); result.RecipeId = input.Id; result.Unknown = (int)input.Unknown1; result.Skill = input.Skill; result.Difficulty = input.Difficulty; result.SkillCheckFormulaType = (int)input.SalvageType; result.SuccessWcid = input.SuccessWCID; result.SuccessAmount = input.SuccessAmount; result.SuccessMessage = input.SuccessMessage; result.FailWcid = input.FailWCID; result.FailAmount = input.FailAmount; result.FailMessage = input.FailMessage; result.SuccessConsumeTargetChance = input.SuccessDestroyTargetChance; result.SuccessConsumeTargetAmount = input.SuccessDestroyTargetAmount; result.SuccessConsumeTargetMessage = input.SuccessDestroyTargetMessage; result.SuccessConsumeToolChance = input.SuccessDestroySourceChance; result.SuccessConsumeToolAmount = input.SuccessDestroySourceAmount; result.SuccessConsumeToolMessage = input.SuccessDestroySourceMessage; result.FailureConsumeTargetChance = input.FailDestroyTargetChance; result.FailureConsumeTargetAmount = input.FailDestroyTargetAmount; result.FailureConsumeTargetMessage = input.FailDestroyTargetMessage; result.FailureConsumeToolChance = input.FailDestroySourceChance; result.FailureConsumeToolAmount = input.FailDestroySourceAmount; result.FailureConsumeToolMessage = input.FailDestroySourceMessage; result.DataId = input.DataId; // requirements result.Requirements = new List(); for (var idx = 0; idx < 3; idx++) result.Requirements.Add(null); foreach (var intReq in input.RecipeRequirementsInt) { var requirements = result.Requirements[intReq.Index]; if (requirements == null) { requirements = new Models.RecipeRequirements(); result.Requirements[intReq.Index] = requirements; } requirements.IntRequirements.Add(new Models.IntRequirement { Stat = intReq.Stat, Value = intReq.Value, OperationType = intReq.Enum, Message = intReq.Message }); } foreach (var didReq in input.RecipeRequirementsDID) { var requirements = result.Requirements[didReq.Index]; if (requirements == null) { requirements = new Models.RecipeRequirements(); result.Requirements[didReq.Index] = requirements; } requirements.DIDRequirements.Add(new Models.DIDRequirement { Stat = didReq.Stat, Value = didReq.Value, OperationType = didReq.Enum, Message = didReq.Message }); } foreach (var iidReq in input.RecipeRequirementsIID) { var requirements = result.Requirements[iidReq.Index]; if (requirements == null) { requirements = new Models.RecipeRequirements(); result.Requirements[iidReq.Index] = requirements; } requirements.IIDRequirements.Add(new Models.IIDRequirement { Stat = iidReq.Stat, Value = iidReq.Value, OperationType = iidReq.Enum, Message = iidReq.Message }); } foreach (var floatReq in input.RecipeRequirementsFloat) { var requirements = result.Requirements[floatReq.Index]; if (requirements == null) { requirements = new Models.RecipeRequirements(); result.Requirements[floatReq.Index] = requirements; } requirements.FloatRequirements.Add(new Models.FloatRequirement { Stat = floatReq.Stat, Value = floatReq.Value, OperationType = floatReq.Enum, Message = floatReq.Message }); } foreach (var stringReq in input.RecipeRequirementsString) { var requirements = result.Requirements[stringReq.Index]; if (requirements == null) { requirements = new Models.RecipeRequirements(); result.Requirements[stringReq.Index] = requirements; } requirements.StringRequirements.Add(new Models.StringRequirement { Stat = stringReq.Stat, Value = stringReq.Value, OperationType = stringReq.Enum, }); } foreach (var boolReq in input.RecipeRequirementsBool) { var requirements = result.Requirements[boolReq.Index]; if (requirements == null) { requirements = new Models.RecipeRequirements(); result.Requirements[boolReq.Index] = requirements; } requirements.BoolRequirements.Add(new Models.BoolRequirement { Stat = boolReq.Stat, Value = boolReq.Value, OperationType = boolReq.Enum, }); } // modifications result.Mods = new List(); for (var idx = 0; idx < 8; idx++) result.Mods.Add(null); foreach (var recipeMod in input.RecipeMod) { // should index be on RecipeMod, or RecipeModType? var idx = GetIndex(recipeMod); if (idx == -1) { Console.WriteLine($"Couldn't find recipe mod idx"); continue; } var mod = result.Mods[idx]; if (mod == null) { mod = new Models.Mod(); result.Mods[idx] = mod; } // base stats mod.ModifyHealth = recipeMod.Health; mod.ModifyStamina = recipeMod.Stamina; mod.ModifyMana = recipeMod.Mana; // TODO!!! we're missing the following RequiresHealth, RequiresStamina, RequiresMana mod.Unknown7 = recipeMod.Unknown7; mod.ModificationScriptId = recipeMod.DataId; mod.Unknown9 = recipeMod.Unknown9; mod.Unknown10 = recipeMod.InstanceId; // type mods foreach (var intMod in recipeMod.RecipeModsInt) { mod.IntRequirements.Add(new Models.IntRequirement { Stat = intMod.Stat, Value = intMod.Value, OperationType = intMod.Enum, Unknown = intMod.Source }); } foreach (var didMod in recipeMod.RecipeModsDID) { mod.DIDRequirements.Add(new Models.DIDRequirement { Stat = didMod.Stat, Value = didMod.Value, OperationType = didMod.Enum, Unknown = didMod.Source }); } foreach (var iidMod in recipeMod.RecipeModsIID) { mod.IIDRequirements.Add(new Models.IIDRequirement { Stat = iidMod.Stat, Value = iidMod.Value, OperationType = iidMod.Enum, Unknown = iidMod.Source }); } foreach (var floatMod in recipeMod.RecipeModsFloat) { mod.FloatRequirements.Add(new Models.FloatRequirement { Stat = floatMod.Stat, Value = floatMod.Value, OperationType = floatMod.Enum, Unknown = floatMod.Source }); } foreach (var stringMod in recipeMod.RecipeModsString) { mod.StringRequirements.Add(new Models.StringRequirement { Stat = stringMod.Stat, Value = stringMod.Value, OperationType = stringMod.Enum, Unknown = stringMod.Source }); } foreach (var boolMod in recipeMod.RecipeModsBool) { mod.BoolRequirements.Add(new Models.BoolRequirement { Stat = boolMod.Stat, Value = boolMod.Value, OperationType = boolMod.Enum, Unknown = boolMod.Source }); } } return true; } catch { result = null; return false; } } /// /// Converts GDLE recipe + precursors to ACE recipe + cookbooks /// public static bool TryConvert(Models.RecipeCombined input, out List cookbooks, out Recipe recipe) { if (!TryConvert(input.recipe, out recipe)) { cookbooks = null; return false; } recipe.Id = input.key; cookbooks = new List(); foreach (var precursor in input.precursors) { if (!TryConvert(precursor, out var cookbook)) return false; cookbook.RecipeId = input.key; cookbooks.Add(cookbook); } return true; } /// /// Converts a GDLE recipe to an ACE recipe /// public static bool TryConvert(Models.Recipe input, out Recipe result) { try { result = new Recipe(); result.Id = input.RecipeId; result.Unknown1 = (uint)input.Unknown; result.Skill = input.Skill; result.Difficulty = input.Difficulty; result.SalvageType = (uint)input.SkillCheckFormulaType; result.SuccessWCID = input.SuccessWcid; result.SuccessAmount = input.SuccessAmount; result.SuccessMessage = input.SuccessMessage; result.FailWCID = input.FailWcid; result.FailAmount = input.FailAmount; result.FailMessage = input.FailMessage; result.SuccessDestroyTargetChance = input.SuccessConsumeTargetChance; result.SuccessDestroyTargetAmount = input.SuccessConsumeTargetAmount; result.SuccessDestroyTargetMessage = input.SuccessConsumeTargetMessage; result.SuccessDestroySourceChance = input.SuccessConsumeToolChance; result.SuccessDestroySourceAmount = input.SuccessConsumeToolAmount; result.SuccessDestroySourceMessage = input.SuccessConsumeToolMessage; result.FailDestroyTargetChance = input.FailureConsumeTargetChance; result.FailDestroyTargetAmount = input.FailureConsumeTargetAmount; result.FailDestroyTargetMessage = input.FailureConsumeTargetMessage; result.FailDestroySourceChance = input.FailureConsumeToolChance; result.FailDestroySourceAmount = input.FailureConsumeToolAmount; result.FailDestroySourceMessage = input.FailureConsumeToolMessage; result.DataId = input.DataId; sbyte index = -1; foreach (var value in input.Requirements) { index++; if (value == null) continue; if (value.IntRequirements != null) { foreach (var requirement in value.IntRequirements) { result.RecipeRequirementsInt.Add(new RecipeRequirementsInt { Index = index, Stat = requirement.Stat, Value = requirement.Value, Enum = requirement.OperationType, Message = requirement.Message }); } } if (value.DIDRequirements != null) { foreach (var requirement in value.DIDRequirements) { result.RecipeRequirementsDID.Add(new RecipeRequirementsDID { Index = index, Stat = requirement.Stat, Value = requirement.Value, Enum = requirement.OperationType, Message = requirement.Message }); } } if (value.IIDRequirements != null) { foreach (var requirement in value.IIDRequirements) { result.RecipeRequirementsIID.Add(new RecipeRequirementsIID { Index = index, Stat = requirement.Stat, Value = requirement.Value, Enum = requirement.OperationType, Message = requirement.Message }); } } if (value.FloatRequirements != null) { foreach (var requirement in value.FloatRequirements) { result.RecipeRequirementsFloat.Add(new RecipeRequirementsFloat { Index = index, Stat = requirement.Stat, Value = requirement.Value, Enum = requirement.OperationType, Message = requirement.Message }); } } if (value.StringRequirements != null) { foreach (var requirement in value.StringRequirements) { result.RecipeRequirementsString.Add(new RecipeRequirementsString { Index = index, Stat = requirement.Stat, Value = requirement.Value, Enum = requirement.OperationType, }); } } if (value.BoolRequirements != null) { foreach (var requirement in value.BoolRequirements) { result.RecipeRequirementsBool.Add(new RecipeRequirementsBool { Index = index, Stat = requirement.Stat, Value = requirement.Value, Enum = requirement.OperationType, Message = requirement.Message }); } } } for (int i = 0; i < 8; i++) // Must be 8 { var recipeMod = new RecipeMod(); var value = input.Mods[i]; if (value == null) continue; if (value.IntRequirements != null) { foreach (var mod in value.IntRequirements) { recipeMod.RecipeModsInt.Add(new RecipeModsInt { Index = (sbyte)i, Stat = mod.Stat, Value = mod.Value, Enum = mod.OperationType, Source = mod.Unknown ?? 0 }); } } if (value.DIDRequirements != null) { foreach (var mod in value.DIDRequirements) { recipeMod.RecipeModsDID.Add(new RecipeModsDID { Index = (sbyte)i, Stat = mod.Stat, Value = mod.Value, Enum = mod.OperationType, Source = mod.Unknown ?? 0 }); } } if (value.IIDRequirements != null) { foreach (var mod in value.IIDRequirements) { recipeMod.RecipeModsIID.Add(new RecipeModsIID { Index = (sbyte)i, Stat = mod.Stat, Value = mod.Value, Enum = mod.OperationType, Source = mod.Unknown ?? 0 }); ; } } if (value.FloatRequirements != null) { foreach (var mod in value.FloatRequirements) { recipeMod.RecipeModsFloat.Add(new RecipeModsFloat { Index = (sbyte)i, Stat = mod.Stat, Value = mod.Value, Enum = mod.OperationType, Source = mod.Unknown ?? 0 }); } } if (value.StringRequirements != null) { foreach (var mod in value.StringRequirements) { recipeMod.RecipeModsString.Add(new RecipeModsString { Index = (sbyte)i, Stat = mod.Stat, Value = mod.Value, Enum = mod.OperationType, Source = mod.Unknown }); } } if (value.BoolRequirements != null) { foreach (var mod in value.BoolRequirements) { recipeMod.RecipeModsBool.Add(new RecipeModsBool { Index = (sbyte)i, Stat = mod.Stat, Value = mod.Value, Enum = mod.OperationType, Source = mod.Unknown ?? 0 }); } } recipeMod.RecipeId = result.Id; recipeMod.ExecutesOnSuccess = (i <= 3); // The first 4 are "act on success", the second 4 are "act on failure" recipeMod.Health = value.ModifyHealth; recipeMod.Stamina = value.ModifyStamina; recipeMod.Mana = value.ModifyMana; // TODO: ACE is missing RequiresHealth, RequiresStamina, RequiresMana recipeMod.Unknown7 = value.Unknown7; recipeMod.DataId = value.ModificationScriptId; recipeMod.Unknown9 = value.Unknown9; recipeMod.InstanceId = value.Unknown10; bool add = (recipeMod.Health > 0 || recipeMod.Stamina > 0 || recipeMod.Mana > 0); add = (add || recipeMod.Unknown7 || recipeMod.DataId > 0 || recipeMod.Unknown9 > 0 || recipeMod.InstanceId > 0); add = (add || recipeMod.RecipeModsBool.Count > 0 || recipeMod.RecipeModsDID.Count > 0 || recipeMod.RecipeModsFloat.Count > 0 || recipeMod.RecipeModsIID.Count > 0 || recipeMod.RecipeModsInt.Count > 0 || recipeMod.RecipeModsString.Count > 0); if (add) result.RecipeMod.Add(recipeMod); } return true; } catch { result = null; return false; } } /// /// Converts ACE cookbook to GDLE precursor /// public static bool TryConvert(CookBook input, out Models.RecipePrecursor result) { try { result = new Models.RecipePrecursor(); result.RecipeId = input.RecipeId; result.Tool = input.SourceWCID; result.Target = input.TargetWCID; return true; } catch { result = null; return false; } } /// /// Converts a GDLE precursor to ACE cookbook /// public static bool TryConvert(Models.RecipePrecursor input, out CookBook result) { try { result = new CookBook(); result.RecipeId = input.RecipeId ?? 0; result.SourceWCID = input.Tool; result.TargetWCID = input.Target; return true; } catch { result = null; return false; } } /// /// Converts GDLE -> ACE wielded treasure table /// public static bool TryConvert(Models.WieldedTreasureTable input, out List results) { try { results = new List(); foreach (var entry in input.Value) { var result = new TreasureWielded(); result.TreasureType = input.Key; result.ContinuesPreviousSet = entry.ContinuesPreviousSet; result.HasSubSet = entry.HasSubSet; result.PaletteId = entry.PaletteId; result.Probability = entry.Probability; result.SetStart = entry.SetStart; result.Shade = entry.Shade; result.StackSize = entry.StackSize; result.StackSizeVariance = entry.StackSizeVariance; result.Unknown1 = entry.Unknown1; result.Unknown10 = entry.Unknown10; result.Unknown11 = entry.Unknown11; result.Unknown12 = entry.Unknown12; result.Unknown3 = entry.Unknown3; result.Unknown4 = entry.Unknown4; result.Unknown5 = entry.Unknown5; result.Unknown9 = entry.Unknown9; result.WeenieClassId = entry.WeenieClassId; results.Add(result); } return true; } catch { results = null; return false; } } } }