private static void AssignMagic(WorldObject wo, TreasureDeath profile, TreasureRoll roll, bool isArmor = false) { int numSpells = 0; if (roll == null) { // previous method if (!AssignMagic_Spells(wo, profile, isArmor, out numSpells)) { return; } } else { // new method if (!AssignMagic_New(wo, profile, roll, out numSpells)) { return; } } wo.UiEffects = UiEffects.Magical; var maxBaseMana = GetMaxBaseMana(wo); wo.ManaRate = CalculateManaRate(maxBaseMana); if (roll == null) { wo.ItemMaxMana = RollItemMaxMana(numSpells, profile.Tier); wo.ItemCurMana = wo.ItemMaxMana; wo.ItemSpellcraft = RollSpellcraft(wo); wo.ItemDifficulty = RollItemDifficulty(wo); } else { var maxSpellMana = maxBaseMana; if (wo.SpellDID != null) { var spell = new Server.Entity.Spell(wo.SpellDID.Value); var castableMana = (int)spell.BaseMana * 5; if (castableMana > maxSpellMana) { maxSpellMana = castableMana; } } wo.ItemMaxMana = RollItemMaxMana_New(wo, roll, maxSpellMana); wo.ItemCurMana = wo.ItemMaxMana; wo.ItemSpellcraft = RollSpellcraft(wo, roll); AddActivationRequirements(wo, roll); } }
private static bool AssignMagic_New(WorldObject wo, TreasureDeath profile, TreasureRoll roll, out int numSpells) { var spells = RollSpells(wo, profile, roll); foreach (var spell in spells) { wo.Biota.GetOrAddKnownSpell((int)spell, wo.BiotaDatabaseLock, out _); } numSpells = spells.Count; return(true); }
private static SpellId RollCantrip(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { if (roll.HasArmorLevel(wo) || roll.IsClothing) { // armor / clothing cantrip // this table also applies to crowns (treasureitemtype.jewelry w/ al) return(ArmorCantrips.Roll()); } if (roll.IsMeleeWeapon) { // melee cantrip var meleeCantrip = MeleeCantrips.Roll(); // adjust for weapon skill if (meleeCantrip == SpellId.CANTRIPLIGHTWEAPONSAPTITUDE1) { meleeCantrip = AdjustForWeaponMastery(wo); } return(meleeCantrip); } else if (roll.IsMissileWeapon) { // missile cantrip return(MissileCantrips.Roll()); } else if (roll.IsCaster) { // caster cantrip var casterCantrip = WandCantrips.Roll(); if (casterCantrip == SpellId.CANTRIPWARMAGICAPTITUDE1) { casterCantrip = AdjustForDamageType(wo, casterCantrip); } return(casterCantrip); } else if (roll.IsJewelry) { // jewelry cantrip return(JewelryCantrips.Roll()); } else { log.Error($"RollCantrip({wo.Name}, {profile.TreasureType}, {roll.ItemType}) - unknown item type"); return(SpellId.Undef); } }
private static string GetMutationScript_ArmorLevel(WorldObject wo, TreasureRoll roll) { switch (roll.ArmorType) { case TreasureArmorType.Covenant: if (wo.IsShield) { return("ArmorLevel.covenant_shield.txt"); } else { return("ArmorLevel.covenant_armor.txt"); } case TreasureArmorType.Olthoi: if (wo.IsShield) { return("ArmorLevel.olthoi_shield.txt"); } else { return("ArmorLevel.olthoi_armor.txt"); } } if (wo.IsShield) { return("ArmorLevel.shield_level.txt"); } var coverage = wo.ClothingPriority ?? 0; if ((coverage & (CoverageMask)CoverageMaskHelper.Extremities) != 0) { return("ArmorLevel.armor_level_extremity.txt"); } else if ((coverage & (CoverageMask)CoverageMaskHelper.Outerwear) != 0) { return("ArmorLevel.armor_level_non_extremity.txt"); } else { return(null); } }
private static WorldObject CreateRandomScroll(TreasureDeath profile, TreasureRoll roll = null) { // level 8 spell components shouldn't be in here, // they should be associated with TreasureItemType.SpellComponent (peas) if (roll == null && profile.Tier >= 7) { // According to wiki, Tier 7 has a chance for level 8 spell components or level 7 spell scrolls (as does Tier 8) // No indication of weighting in either direction, so assuming a 50/50 split var rng = ThreadSafeRandom.Next(0.0f, 1.0f); if (rng < 0.5f) { var wcid = RollLevel8SpellComp(); return(WorldObjectFactory.CreateNewWorldObject((uint)wcid)); } } var spellLevel = ScrollLevelChance.Roll(profile); // todo: switch to SpellLevelProgression var spellId = SpellId.Undef; do { var spellIdx = ThreadSafeRandom.Next(0, ScrollSpells.Table.Length - 1); spellId = ScrollSpells.Table[spellIdx][spellLevel - 1]; }while (spellId == SpellId.Undef); // simple way of handling spells that start at level 3 (blasts, volleys) var weenie = DatabaseManager.World.GetScrollWeenie((uint)spellId); if (weenie == null) { log.DebugFormat("CreateRandomScroll for tier {0} and spellID of {1} returned null from the database.", profile.Tier, spellId); return(null); } return(WorldObjectFactory.CreateNewWorldObject(weenie.WeenieClassId)); }
private static List <SpellId> RollItemSpells(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { List <SpellId> spells = null; //if (roll.IsArmor || roll.IsArmorClothing(wo)) if (roll.HasArmorLevel(wo)) { spells = ArmorSpells.Roll(profile); } else if (roll.IsMeleeWeapon) { spells = MeleeSpells.Roll(profile); } else if (roll.IsMissileWeapon) { spells = MissileSpells.Roll(profile); } else if (roll.IsCaster) { spells = WandSpells.Roll(wo, profile); } else { log.Error($"RollItemSpells({wo.Name}) - item is not clothing / armor / weapon"); return(null); } return(RollSpellLevels(wo, profile, spells)); }
/// <summary> /// An alternate method to using the SpellSelectionCode from PropertyInt.TSysMutationdata /// </summary> private static int GetSpellSelectionCode_Dynamic(WorldObject wo, TreasureRoll roll) { if (wo is Gem) { return(1); } else if (roll.ItemType == TreasureItemType_Orig.Jewelry) { if (!roll.HasArmorLevel(wo)) { return(2); } else { return(3); } } else if (roll.Wcid == Enum.WeenieClassName.orb) { return(4); } else if (roll.IsCaster && wo.W_DamageType != DamageType.Nether) { return(5); } else if (roll.IsMeleeWeapon && wo.WeaponSkill != Skill.TwoHandedCombat) { return(6); } else if ((roll.IsArmor || roll.IsClothing) && !wo.IsShield) { return(GetSpellCode_Dynamic_ClothingArmor(wo, roll)); } else if (wo.IsShield) { return(8); } else if (roll.IsDinnerware) { if (roll.Wcid == Enum.WeenieClassName.flasksimple) { return(0); } else { return(16); } } else if (roll.IsMissileWeapon || wo.WeaponSkill == Skill.TwoHandedCombat) { return(17); } else if (roll.IsCaster && wo.W_DamageType == DamageType.Nether) { return(19); } log.Error($"GetSpellCode_Dynamic({wo.Name}) - couldn't determine spell selection code"); return(0); }
private static List <SpellId> RollSpells(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { var spells = new List <SpellId>(); // crowns, which are classified as TreasureItemType.Jewelry, should also be getting item spells // perhaps replace this with wo.ArmorLevel check? //if (roll.IsArmor || roll.IsArmorClothing(wo) || roll.IsWeapon) if (roll.HasArmorLevel(wo) || roll.IsWeapon) { var itemSpells = RollItemSpells(wo, profile, roll); if (itemSpells != null) { spells.AddRange(itemSpells); } } var enchantments = RollEnchantments(wo, profile, roll); if (enchantments != null) { spells.AddRange(enchantments); roll.ItemDifficulty += RollEnchantmentDifficulty(enchantments); } var cantrips = RollCantrips(wo, profile, roll); if (cantrips != null) { spells.AddRange(cantrips); roll.ItemDifficulty += RollCantripDifficulty(cantrips); } return(spells); }
private static int RollNumEnchantments_Clothing_Jewelry_Dinnerware(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { var chance = 0.1f; var rng = ThreadSafeRandom.NextInterval(profile.LootQualityMod); if (rng >= chance) { return(1); } else if (profile.Tier < 6) { return(2); } // tier 6+ has a chance for 3 enchantments rng = ThreadSafeRandom.NextInterval(profile.LootQualityMod * 0.1f); if (rng >= chance * 0.5f) { return(2); } else { return(3); } }
private static void MutateGem(WorldObject wo, TreasureDeath profile, bool isMagical, TreasureRoll roll = null) { // workmanship wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); // item color MutateColor(wo); if (!isMagical) { // TODO: verify if this is needed wo.ItemUseable = Usable.No; wo.SpellDID = null; wo.ItemManaCost = null; wo.ItemMaxMana = null; wo.ItemCurMana = null; wo.ItemSpellcraft = null; wo.ItemDifficulty = null; wo.ItemSkillLevelLimit = null; wo.ManaRate = null; } else { if (roll == null) { AssignMagic_Gem(wo, profile); } else { AssignMagic_Gem_New(wo, profile, roll); } wo.UiEffects = UiEffects.Magical; wo.ItemUseable = Usable.Contained; wo.LongDesc = GetLongDesc(wo); } // item value, review var gemValue = LootTables.gemValues[(int)wo.MaterialType]; wo.Value = gemValue + ThreadSafeRandom.Next(1, gemValue); }
private static bool AssignMagic_Gem_New(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { // TODO: move to standard AssignMagic() pipeline var spell = SpellSelectionTable.Roll(1); var spellLevel = SpellLevelChance.Roll(profile.Tier); var spellLevels = SpellLevelProgression.GetSpellLevels(spell); if (spellLevels == null || spellLevels.Count != 8) { log.Error($"AssignMagic_Gem_New({wo.Name}, {profile.TreasureType}, {roll.ItemType}) - unknown spell {spell}"); return(false); } var finalSpellId = spellLevels[spellLevel - 1]; wo.SpellDID = (uint)finalSpellId; var _spell = new Server.Entity.Spell(finalSpellId); // retail spellcraft was capped at 370 wo.ItemSpellcraft = Math.Min((int)_spell.Power, 370); var castableMana = (int)_spell.BaseMana * 5; wo.ItemMaxMana = RollItemMaxMana_New(wo, roll, castableMana); wo.ItemCurMana = wo.ItemMaxMana; // verified wo.ItemManaCost = castableMana; return(true); }
private static List <SpellId> RollCantrips(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { // no cantrips on dinnerware? if (roll.ItemType == TreasureItemType_Orig.ArtObject) { return(null); } var numCantrips = CantripChance.RollNumCantrips(profile); if (numCantrips == 0) { return(null); } var numAttempts = numCantrips * 3; var cantrips = new HashSet <SpellId>(); for (var i = 0; i < numAttempts && cantrips.Count < numCantrips; i++) { var cantrip = RollCantrip(wo, profile, roll); if (cantrip != SpellId.Undef) { cantrips.Add(cantrip); } } var finalCantrips = new List <SpellId>(); var hasLegendary = false; foreach (var cantrip in cantrips) { var cantripLevel = CantripChance.RollCantripLevel(profile); var cantripLevels = SpellLevelProgression.GetSpellLevels(cantrip); if (cantripLevels.Count != 4) { log.Error($"RollCantrips({wo.Name}, {profile.TreasureType}, {roll.ItemType}) - {cantrip} has {cantripLevels.Count} cantrip levels, expected 4"); continue; } finalCantrips.Add(cantripLevels[cantripLevel - 1]); if (cantripLevel == 4) { hasLegendary = true; } } // if a legendary cantrip dropped on this item if (hasLegendary) { // and if the item has a level requirement, ensure the level requirement is at least 180 // if the item does not already contain a level requirement, don't add one? if (wo.WieldRequirements == WieldRequirement.Level && wo.WieldDifficulty < 180) { wo.WieldDifficulty = 180; } if (wo.WieldRequirements2 == WieldRequirement.Level && wo.WieldDifficulty2 < 180) { wo.WieldDifficulty2 = 180; } } return(finalCantrips); }
private static void MutateGem(WorldObject wo, TreasureDeath profile, bool isMagical, TreasureRoll roll = null) { // workmanship wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); // item color MutateColor(wo); if (!isMagical) { // TODO: verify if this is needed wo.ItemUseable = Usable.No; wo.SpellDID = null; wo.ItemManaCost = null; wo.ItemMaxMana = null; wo.ItemCurMana = null; wo.ItemSpellcraft = null; wo.ItemDifficulty = null; wo.ItemSkillLevelLimit = null; wo.ManaRate = null; } else { if (roll == null) { AssignMagic_Gem(wo, profile); } else { AssignMagic_Gem_New(wo, profile, roll); } wo.UiEffects = UiEffects.Magical; wo.ItemUseable = Usable.Contained; } // item value if (wo.HasMutateFilter(MutateFilter.Value)) { MutateValue(wo, profile.Tier, roll); } // long desc wo.LongDesc = GetLongDesc(wo); }
private static bool AssignArmorLevel_New(WorldObject wo, TreasureDeath profile, TreasureRoll roll, LootTables.ArmorType armorType) { // retail was only divied up into a few different mutation scripts here // anything with ArmorLevel ran these mutation scripts // anything that covered extremities (head / hand / foot wear) started with a slightly higher base AL, // but otherwise used the same mutation as anything that covered non-extremities // shields also had their own mutation script // only exceptions found: covenant armor, olthoi armor, metal cap if (!roll.HasArmorLevel(wo)) { return(false); } var scriptName = GetMutationScript_ArmorLevel(wo, roll); if (scriptName == null) { log.Error($"AssignArmorLevel_New({wo.Name}, {profile.TreasureType}, {roll.ItemType}) - unknown item type"); return(false); } // persist original values for society armor var wieldRequirements = wo.WieldRequirements; var wieldSkillType = wo.WieldSkillType; var wieldDifficulty = wo.WieldDifficulty; //Console.WriteLine($"Mutating {wo.Name} with {scriptName}"); var mutationFilter = MutationCache.GetMutation(scriptName); var success = mutationFilter.TryMutate(wo, profile.Tier); if (armorType == LootTables.ArmorType.SocietyArmor) { wo.WieldRequirements = wieldRequirements; wo.WieldSkillType = wieldSkillType; wo.WieldDifficulty = wieldDifficulty; } return(success); }
private static List <SpellId> RollEnchantments(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { /*if (wo.SpellSelectionCode == null) * { * log.Warn($"RollEnchantments({wo.Name}) - missing spell selection code / PropertyInt.TsysMutationData"); * return null; * }*/ // test method: determine spell selection code dynamically var spellSelectionCode = GetSpellSelectionCode_Dynamic(wo, roll); if (spellSelectionCode == 0) { return(null); } //Console.WriteLine($"Using spell selection code {spellSelectionCode} for {wo.Name}"); var numEnchantments = RollNumEnchantments(wo, profile, roll); if (numEnchantments <= 0) { return(null); } var numAttempts = numEnchantments * 3; var spells = new HashSet <SpellId>(); for (var i = 0; i < numAttempts && spells.Count < numEnchantments; i++) { var spell = SpellSelectionTable.Roll(spellSelectionCode); if (spell != SpellId.Undef) { spells.Add(spell); } } return(RollSpellLevels(wo, profile, spells)); }
private static int RollNumEnchantments(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { if (roll.IsArmor || roll.IsWeapon) { return(RollNumEnchantments_Armor_Weapon(wo, profile, roll)); } // confirmed: // - crowns (classified as TreasureItemType.Jewelry) used this table // - clothing w/ al also used this table else if (roll.IsClothing || roll.IsJewelry || roll.IsDinnerware) { return(RollNumEnchantments_Clothing_Jewelry_Dinnerware(wo, profile, roll)); } else { log.Warn($"RollNumEnchantments({wo.Name}, {profile.TreasureType}, {roll.ItemType}) - unknown item type"); return(1); // gems? } }
private static void MutateJewelry(WorldObject wo, TreasureDeath profile, bool isMagical, TreasureRoll roll = null) { // material type int materialType = GetMaterialType(wo, profile.Tier); if (materialType > 0) { wo.MaterialType = (MaterialType)materialType; } // item color MutateColor(wo); // gem count / gem material if (wo.GemCode != null) { wo.GemCount = GemCountChance.Roll(wo.GemCode.Value, profile.Tier); } else { wo.GemCount = ThreadSafeRandom.Next(1, 5); } wo.GemType = RollGemType(profile.Tier); // workmanship wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); // wield requirements (verify) if (profile.Tier > 6) { wo.WieldRequirements = WieldRequirement.Level; wo.WieldSkillType = (int)Skill.Axe; // Set by examples from PCAP data var wield = profile.Tier switch { 7 => 150, // In this instance, used for indicating player level, rather than skill level _ => 180, // In this instance, used for indicating player level, rather than skill level }; wo.WieldDifficulty = wield; } // assign magic if (isMagical) { AssignMagic(wo, profile, roll); } else { wo.ItemManaCost = null; wo.ItemMaxMana = null; wo.ItemCurMana = null; wo.ItemSpellcraft = null; wo.ItemDifficulty = null; wo.ManaRate = null; } // gear rating (t8) if (roll != null && profile.Tier == 8) { TryMutateGearRating(wo, profile, roll); } // item value wo.Value = Roll_ItemValue(wo, profile.Tier); wo.LongDesc = GetLongDesc(wo); }
private static int RollNumEnchantments_Armor_Weapon(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { var tierChances = roll.IsCaster ? EnchantmentChances_Caster : EnchantmentChances_Armor_MeleeMissileWeapon; var chance = tierChances[profile.Tier - 1]; var rng = ThreadSafeRandom.NextInterval(profile.LootQualityMod); if (rng < chance) { return(1); } else { return(0); } }
private static bool MutateMeleeWeapon(WorldObject wo, TreasureDeath profile, bool isMagical, TreasureRoll roll = null) { if (!(wo is MeleeWeapon)) { return(false); } if (roll == null) { // previous method var wieldDifficulty = RollWieldDifficulty(profile.Tier, TreasureWeaponType.MeleeWeapon); if (!MutateStats_OldMethod(wo, profile, wieldDifficulty)) { return(false); } } else { // thanks to 4eyebiped for helping with the data analysis of magloot retail logs // that went into reversing these mutation scripts var weaponSkill = wo.WeaponSkill.ToMeleeWeaponSkill(); // mutate Damage / WieldDifficulty / Variance var scriptName = GetDamageScript(weaponSkill, roll.WeaponType); var mutationFilter = MutationCache.GetMutation(scriptName); mutationFilter.TryMutate(wo, profile.Tier); // mutate WeaponOffense / WeaponDefense scriptName = GetOffenseDefenseScript(weaponSkill, roll.WeaponType); mutationFilter = MutationCache.GetMutation(scriptName); mutationFilter.TryMutate(wo, profile.Tier); } // weapon speed if (wo.WeaponTime != null) { var weaponSpeedMod = RollWeaponSpeedMod(profile); wo.WeaponTime = (int)(wo.WeaponTime * weaponSpeedMod); } // material type var materialType = GetMaterialType(wo, profile.Tier); if (materialType > 0) { wo.MaterialType = materialType; } // item color MutateColor(wo); // gem count / gem material if (wo.GemCode != null) { wo.GemCount = GemCountChance.Roll(wo.GemCode.Value, profile.Tier); } else { wo.GemCount = ThreadSafeRandom.Next(1, 5); } wo.GemType = RollGemType(profile.Tier); // workmanship wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); // burden MutateBurden(wo, profile, true); // missile / magic defense wo.WeaponMissileDefense = MissileMagicDefense.Roll(profile.Tier); wo.WeaponMagicDefense = MissileMagicDefense.Roll(profile.Tier); // spells if (!isMagical) { // clear base wo.ItemManaCost = null; wo.ItemMaxMana = null; wo.ItemCurMana = null; wo.ItemSpellcraft = null; wo.ItemDifficulty = null; } else { AssignMagic(wo, profile, roll); } // item value //if (wo.HasMutateFilter(MutateFilter.Value)) // fixme: data MutateValue(wo, profile.Tier, roll); // long description wo.LongDesc = GetLongDesc(wo); return(true); }
private static List <SpellId> RollCantrips(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { // no cantrips on dinnerware? if (roll.ItemType == TreasureItemType_Orig.ArtObject) { return(null); } var numCantrips = CantripChance.RollNumCantrips(profile); if (numCantrips == 0) { return(null); } var numAttempts = numCantrips * 3; var cantrips = new HashSet <SpellId>(); for (var i = 0; i < numAttempts && cantrips.Count < numCantrips; i++) { var cantrip = RollCantrip(wo, profile, roll); if (cantrip != SpellId.Undef) { cantrips.Add(cantrip); } } var finalCantrips = new List <SpellId>(); foreach (var cantrip in cantrips) { var cantripLevel = CantripChance.RollCantripLevel(profile); var cantripLevels = SpellLevelProgression.GetSpellLevels(cantrip); if (cantripLevels.Count != 4) { log.Error($"RollCantrips({wo.Name}, {profile.TreasureType}, {roll.ItemType}) - {cantrip} has {cantripLevels.Count} cantrip levels, expected 4"); continue; } finalCantrips.Add(cantripLevels[cantripLevel - 1]); } return(finalCantrips); }
private static void MutateCaster(WorldObject wo, TreasureDeath profile, bool isMagical, int?wieldDifficulty = null, TreasureRoll roll = null) { if (wieldDifficulty != null) { // previous method var wieldRequirement = WieldRequirement.RawSkill; var wieldSkillType = Skill.None; double elementalDamageMod = 0; if (wieldDifficulty == 0) { if (profile.Tier > 6) { wieldRequirement = WieldRequirement.Level; wieldSkillType = Skill.Axe; // Set by examples from PCAP data wieldDifficulty = profile.Tier switch { 7 => 150, // In this instance, used for indicating player level, rather than skill level _ => 180, // In this instance, used for indicating player level, rather than skill level }; } } else { elementalDamageMod = RollElementalDamageMod(wieldDifficulty.Value); if (wo.W_DamageType == DamageType.Nether) { wieldSkillType = Skill.VoidMagic; } else { wieldSkillType = Skill.WarMagic; } } // ManaConversionMod var manaConversionMod = RollManaConversionMod(profile.Tier); if (manaConversionMod > 0.0f) { wo.ManaConversionMod = manaConversionMod; } // ElementalDamageMod if (elementalDamageMod > 1.0f) { wo.ElementalDamageMod = elementalDamageMod; } // WieldRequirements if (wieldDifficulty > 0 || wieldRequirement == WieldRequirement.Level) { wo.WieldRequirements = wieldRequirement; wo.WieldSkillType = (int)wieldSkillType; wo.WieldDifficulty = wieldDifficulty; } else { wo.WieldRequirements = WieldRequirement.Invalid; wo.WieldSkillType = null; wo.WieldDifficulty = null; } // WeaponDefense wo.WeaponDefense = RollWeaponDefense(wieldDifficulty.Value, profile); } else { // new method - mutation scripts // mutate ManaConversionMod var mutationFilter = MutationCache.GetMutation("Casters.caster.txt"); mutationFilter.TryMutate(wo, profile.Tier); // mutate ElementalDamageMod / WieldRequirements var isElemental = wo.W_DamageType != DamageType.Undef; var scriptName = GetCasterScript(isElemental); mutationFilter = MutationCache.GetMutation(scriptName); mutationFilter.TryMutate(wo, profile.Tier); // this part was not handled by mutation filter if (wo.WieldRequirements == WieldRequirement.RawSkill) { if (wo.W_DamageType == DamageType.Nether) { wo.WieldSkillType = (int)Skill.VoidMagic; } else { wo.WieldSkillType = (int)Skill.WarMagic; } } // mutate WeaponDefense mutationFilter = MutationCache.GetMutation("Casters.weapon_defense.txt"); mutationFilter.TryMutate(wo, profile.Tier); } // material type var materialType = GetMaterialType(wo, profile.Tier); if (materialType > 0) { wo.MaterialType = materialType; } // item color MutateColor(wo); // gem count / gem material if (wo.GemCode != null) { wo.GemCount = GemCountChance.Roll(wo.GemCode.Value, profile.Tier); } else { wo.GemCount = ThreadSafeRandom.Next(1, 5); } wo.GemType = RollGemType(profile.Tier); // workmanship wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); // burden? // missile defense / magic defense wo.WeaponMissileDefense = MissileMagicDefense.Roll(profile.Tier); wo.WeaponMagicDefense = MissileMagicDefense.Roll(profile.Tier); // spells if (!isMagical) { wo.ItemManaCost = null; wo.ItemMaxMana = null; wo.ItemCurMana = null; wo.ItemSpellcraft = null; wo.ItemDifficulty = null; } else { // if a caster was from a MagicItem profile, it always had a SpellDID MutateCaster_SpellDID(wo, profile); AssignMagic(wo, profile, roll); } // item value //if (wo.HasMutateFilter(MutateFilter.Value)) // fixme: data MutateValue(wo, profile.Tier, roll); // long description wo.LongDesc = GetLongDesc(wo); }
private static void MutateJewelry(WorldObject wo, TreasureDeath profile, bool isMagical, TreasureRoll roll = null) { // material type var materialType = GetMaterialType(wo, profile.Tier); if (materialType > 0) { wo.MaterialType = materialType; } // item color MutateColor(wo); // gem count / gem material if (wo.GemCode != null) { wo.GemCount = GemCountChance.Roll(wo.GemCode.Value, profile.Tier); } else { wo.GemCount = ThreadSafeRandom.Next(1, 5); } wo.GemType = RollGemType(profile.Tier); // workmanship wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); // wield level requirement for t7+ if (profile.Tier > 6) { RollWieldLevelReq_T7_T8(wo, profile); } // assign magic if (isMagical) { AssignMagic(wo, profile, roll); } else { wo.ItemManaCost = null; wo.ItemMaxMana = null; wo.ItemCurMana = null; wo.ItemSpellcraft = null; wo.ItemDifficulty = null; wo.ManaRate = null; } // gear rating (t8) if (roll != null && profile.Tier == 8) { TryMutateGearRating(wo, profile, roll); } // item value // if (wo.HasMutateFilter(MutateFilter.Value)) // fixme: data MutateValue(wo, profile.Tier, roll); wo.LongDesc = GetLongDesc(wo); }
private static void MutateArmor(WorldObject wo, TreasureDeath profile, bool isMagical, LootTables.ArmorType armorType, TreasureRoll roll = null) { // material type int materialType = GetMaterialType(wo, profile.Tier); if (materialType > 0) { wo.MaterialType = (MaterialType)materialType; } // item color MutateColor(wo); // gem count / gem material if (wo.GemCode != null) { wo.GemCount = GemCountChance.Roll(wo.GemCode.Value, profile.Tier); } else { wo.GemCount = ThreadSafeRandom.Next(1, 6); } wo.GemType = RollGemType(profile.Tier); // workmanship wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); // try mutate burden, if MutateFilter exists if (wo.HasMutateFilter(MutateFilter.EncumbranceVal)) { MutateBurden(wo, profile, false); } if (profile.Tier > 6 && armorType != LootTables.ArmorType.CovenantArmor && armorType != LootTables.ArmorType.OlthoiArmor) { wo.WieldRequirements = WieldRequirement.Level; wo.WieldSkillType = (int)Skill.Axe; // Set by examples from PCAP data wo.WieldDifficulty = profile.Tier switch { 7 => 150, // In this instance, used for indicating player level, rather than skill level _ => 180, // In this instance, used for indicating player level, rather than skill level }; } if (armorType == LootTables.ArmorType.CovenantArmor || armorType == LootTables.ArmorType.OlthoiArmor) { int chance = ThreadSafeRandom.Next(1, 3); var wieldSkill = chance switch { 1 => Skill.MagicDefense, 2 => Skill.MissileDefense, _ => Skill.MeleeDefense, }; wo.WieldRequirements = WieldRequirement.RawSkill; wo.WieldSkillType = (int)wieldSkill; wo.WieldDifficulty = GetCovenantWieldReq(profile.Tier, wieldSkill); // used by tinkering requirements for copper/silver wo.ItemSkillLimit = wieldSkill; } wo = AssignArmorLevel(wo, profile.Tier, armorType); wo = AssignEquipmentSetId(wo, profile); if (isMagical) { //bool covenantArmor = false || (armorType == LootTables.ArmorType.CovenantArmor || armorType == LootTables.ArmorType.OlthoiArmor); AssignMagic(wo, profile, roll, true); } else { wo.ItemManaCost = null; wo.ItemMaxMana = null; wo.ItemCurMana = null; wo.ItemSpellcraft = null; wo.ItemDifficulty = null; } if (wo.HasMutateFilter(MutateFilter.ArmorModVsType) && wo.ArmorLevel > 0) { // covenant armor and olthoi armor appear to have different mutation methods possibly if (armorType != LootTables.ArmorType.CovenantArmor && armorType != LootTables.ArmorType.OlthoiArmor) { MutateArmorModVsType(wo, profile); } } if (roll != null && profile.Tier == 8) { TryMutateGearRating(wo, profile, roll); } // item value wo.Value = Roll_ItemValue(wo, profile.Tier); wo.LongDesc = GetLongDesc(wo); }
private static int GetSpellCode_Dynamic_ClothingArmor(WorldObject wo, TreasureRoll roll) { // special cases switch (roll.Wcid) { case Enum.WeenieClassName.glovescloth: return(14); case Enum.WeenieClassName.capleather: return(20); } var coverageMask = wo.ClothingPriority ?? 0; var isArmor = roll.IsArmor; if ((coverageMask & upperArmor) != 0 && (coverageMask & CoverageMask.OuterwearLowerLegs) == 0) { return(7); } if (coverageMask == CoverageMask.Hands && isArmor) { return(9); } if (coverageMask == CoverageMask.Head && roll.BaseArmorLevel > 20) { return(10); } // base weenie armorLevel > 20 if ((coverageMask & CoverageMask.Feet) != 0 && roll.BaseArmorLevel > 20) { return(11); } if ((coverageMask & clothing) != 0) { return(12); } // metal cap? if (coverageMask == CoverageMask.Head && !isArmor) { return(13); } if (coverageMask == CoverageMask.Hands && !isArmor) { return(14); } // leggings if ((coverageMask & lowerArmor) != 0) { return(15); } if (coverageMask == CoverageMask.Feet) { return(18); } log.Error($"GetSpellCode_Dynamic_ClothingArmor({wo.Name}) - couldn't determine spell selection code for {coverageMask}, {isArmor}"); return(0); }
private static void MutateSocietyArmor(WorldObject wo, TreasureDeath profile, bool isMagical, TreasureRoll roll = null) { int materialType = GetMaterialType(wo, profile.Tier); if (materialType > 0) { wo.MaterialType = (MaterialType)materialType; } if (wo.GemCode != null) { wo.GemCount = GemCountChance.Roll(wo.GemCode.Value, profile.Tier); } else { wo.GemCount = ThreadSafeRandom.Next(1, 6); } wo.GemType = RollGemType(profile.Tier); wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); wo.Value = Roll_ItemValue(wo, profile.Tier); // wo.WieldSkillType = (int)Skill.Axe; // Set by examples from PCAP data if (isMagical) { // looks like society armor always had impen on it AssignMagic(wo, profile, roll, true); } else { wo.ItemManaCost = null; wo.ItemMaxMana = null; wo.ItemCurMana = null; wo.ItemSpellcraft = null; wo.ItemDifficulty = null; } wo = AssignArmorLevel(wo, profile.Tier, LootTables.ArmorType.SocietyArmor); wo.LongDesc = GetLongDesc(wo); // try mutate burden, if MutateFilter exists if (wo.HasMutateFilter(MutateFilter.EncumbranceVal)) { MutateBurden(wo, profile, false); } }
private static bool AssignArmorLevel_New(WorldObject wo, TreasureDeath profile, TreasureRoll roll) { // retail was only divied up into a few different mutation scripts here // anything with ArmorLevel ran these mutation scripts // anything that covered extremities (head / hand / foot wear) started with a slightly higher base AL, // but otherwise used the same mutation as anything that covered non-extremities // shields also had their own mutation script // only exceptions found: covenant armor, olthoi armor, metal cap if (!roll.HasArmorLevel(wo)) { return(false); } var scriptName = GetMutationScript_ArmorLevel(wo, roll); if (scriptName == null) { log.Error($"AssignArmorLevel_New({wo.Name}, {profile.TreasureType}, {roll.ItemType}) - unknown item type"); return(false); } //Console.WriteLine($"Mutating {wo.Name} with {scriptName}"); var mutationFilter = MutationCache.GetMutation(scriptName); return(mutationFilter.TryMutate(wo, profile.Tier)); }
private static void MutateMissileWeapon(WorldObject wo, TreasureDeath profile, bool isMagical, int?wieldDifficulty = null, TreasureRoll roll = null) { if (roll == null) { // previous method // DamageMod wo.DamageMod = GetMissileDamageMod(wieldDifficulty.Value, wo.W_WeaponType); // ElementalDamageBonus if (wo.W_DamageType != DamageType.Undef) { int elementalBonus = GetElementalDamageBonus(wieldDifficulty.Value); if (elementalBonus > 0) { wo.ElementalDamageBonus = elementalBonus; } } // Wield Requirements if (wieldDifficulty > 0) { wo.WieldDifficulty = wieldDifficulty; wo.WieldRequirements = WieldRequirement.RawSkill; wo.WieldSkillType = (int)Skill.MissileWeapons; } else { wo.WieldDifficulty = null; wo.WieldRequirements = WieldRequirement.Invalid; wo.WieldSkillType = null; } // WeaponDefense var meleeDMod = RollWeaponDefense(wieldDifficulty.Value, profile); if (meleeDMod > 0.0f) { wo.WeaponDefense = meleeDMod; } } else { // new method / mutation scripts var isElemental = wo.W_DamageType != DamageType.Undef; var scriptName = GetMissileScript(roll.WeaponType, isElemental); // mutate DamageMod / ElementalDamageBonus / WieldRequirements var mutationFilter = MutationCache.GetMutation(scriptName); mutationFilter.TryMutate(wo, profile.Tier); // mutate WeaponDefense mutationFilter = MutationCache.GetMutation("MissileWeapons.weapon_defense.txt"); mutationFilter.TryMutate(wo, profile.Tier); } // weapon speed if (wo.WeaponTime != null) { var weaponSpeedMod = RollWeaponSpeedMod(profile); wo.WeaponTime = (int)(wo.WeaponTime * weaponSpeedMod); } // material type var materialType = GetMaterialType(wo, profile.Tier); if (materialType > 0) { wo.MaterialType = materialType; } // item color MutateColor(wo); // gem count / gem material if (wo.GemCode != null) { wo.GemCount = GemCountChance.Roll(wo.GemCode.Value, profile.Tier); } else { wo.GemCount = ThreadSafeRandom.Next(1, 5); } wo.GemType = RollGemType(profile.Tier); // workmanship wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); // burden MutateBurden(wo, profile, true); // missile / magic defense wo.WeaponMissileDefense = MissileMagicDefense.Roll(profile.Tier); wo.WeaponMagicDefense = MissileMagicDefense.Roll(profile.Tier); // spells if (!isMagical) { wo.ItemManaCost = null; wo.ItemMaxMana = null; wo.ItemCurMana = null; wo.ItemSpellcraft = null; wo.ItemDifficulty = null; wo.ManaRate = null; } else { AssignMagic(wo, profile, roll); } // item value //if (wo.HasMutateFilter(MutateFilter.Value)) // fixme: data MutateValue(wo, profile.Tier, roll); // long description wo.LongDesc = GetLongDesc(wo); }
private static void MutateArmor(WorldObject wo, TreasureDeath profile, bool isMagical, LootTables.ArmorType armorType, TreasureRoll roll = null) { // material type var materialType = GetMaterialType(wo, profile.Tier); if (materialType > 0) { wo.MaterialType = materialType; } // item color MutateColor(wo); // gem count / gem material if (wo.GemCode != null) { wo.GemCount = GemCountChance.Roll(wo.GemCode.Value, profile.Tier); } else { wo.GemCount = ThreadSafeRandom.Next(1, 6); } wo.GemType = RollGemType(profile.Tier); // workmanship wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); // burden if (wo.HasMutateFilter(MutateFilter.EncumbranceVal)) // fixme: data { MutateBurden(wo, profile, false); } if (roll == null) { if (armorType == LootTables.ArmorType.CovenantArmor || armorType == LootTables.ArmorType.OlthoiArmor) { int chance = ThreadSafeRandom.Next(1, 3); var wieldSkill = chance switch { 1 => Skill.MagicDefense, 2 => Skill.MissileDefense, _ => Skill.MeleeDefense, }; wo.WieldRequirements = WieldRequirement.RawSkill; wo.WieldSkillType = (int)wieldSkill; wo.WieldDifficulty = GetCovenantWieldReq(profile.Tier, wieldSkill); } else if (profile.Tier > 6) { wo.WieldRequirements = WieldRequirement.Level; wo.WieldSkillType = (int)Skill.Axe; // Set by examples from PCAP data wo.WieldDifficulty = profile.Tier switch { 7 => 150, // In this instance, used for indicating player level, rather than skill level _ => 180, // In this instance, used for indicating player level, rather than skill level }; } } else if (profile.Tier > 6 && !wo.HasArmorLevel()) { // normally this is handled in the mutation script for armor // for clothing, just calling the generic method here RollWieldLevelReq_T7_T8(wo, profile); } if (roll == null) { AssignArmorLevel(wo, profile.Tier, armorType); } else { AssignArmorLevel_New(wo, profile, roll); } if (wo.HasMutateFilter(MutateFilter.ArmorModVsType)) { MutateArmorModVsType(wo, profile); } if (isMagical) { AssignMagic(wo, profile, roll, true); } else { wo.ItemManaCost = null; wo.ItemMaxMana = null; wo.ItemCurMana = null; wo.ItemSpellcraft = null; wo.ItemDifficulty = null; } if (profile.Tier > 6) { TryRollEquipmentSet(wo, profile, roll); } if (roll != null && profile.Tier == 8) { TryMutateGearRating(wo, profile, roll); } // item value //if (wo.HasMutateFilter(MutateFilter.Value)) // fixme: data MutateValue(wo, profile.Tier, roll); wo.LongDesc = GetLongDesc(wo); }
private static void MutateDinnerware(WorldObject wo, TreasureDeath profile, bool isMagical, TreasureRoll roll = null) { // dinnerware did not have its Damage / DamageVariance / WeaponSpeed mutated // material type wo.MaterialType = (MaterialType)GetMaterialType(wo, profile.Tier); // item color MutateColor(wo); // gem count / gem material if (wo.GemCode != null) { wo.GemCount = GemCountChance.Roll(wo.GemCode.Value, profile.Tier); } else { wo.GemCount = ThreadSafeRandom.Next(1, 5); } wo.GemType = RollGemType(profile.Tier); // workmanship wo.ItemWorkmanship = WorkmanshipChance.Roll(profile.Tier); // "Empty Flask" was the only dinnerware that never received spells if (isMagical && wo.WeenieClassId != (uint)WeenieClassName.flasksimple) { AssignMagic(wo, profile, roll); } // item value MutateDinnerware_ItemValue(wo); wo.LongDesc = GetLongDesc(wo); }