public static void ApplyComponentBonus(NWItem product, ItemProperty sourceIP) { ComponentBonusType bonusType = (ComponentBonusType)_.GetItemPropertySubType(sourceIP); int amount = _.GetItemPropertyCostTableValue(sourceIP); ItemProperty prop = null; string sourceTag = string.Empty; // A note about the sourceTags: // It's not currently possible to create custom item properties on items. To get around this, // we look in an inaccessible container which holds the custom item properties. Then, we get the // item that has the item property we want. From there we take that item property and copy it to // the crafted item. // This is a really roundabout way to do it, but it's the only option for now. Hopefully a feature to // directly add the item properties comes in to NWNX in the future. for (int x = 1; x <= amount; x++) { switch (bonusType) { case ComponentBonusType.ModSocketRed: sourceTag = "rslot_red"; break; case ComponentBonusType.ModSocketBlue: sourceTag = "rslot_blue"; break; case ComponentBonusType.ModSocketGreen: sourceTag = "rslot_green"; break; case ComponentBonusType.ModSocketYellow: sourceTag = "rslot_yellow"; break; case ComponentBonusType.ModSocketPrismatic: sourceTag = "rslot_prismatic"; break; case ComponentBonusType.DurabilityUp: var maxDur = DurabilityService.GetMaxDurability(product) + amount; DurabilityService.SetMaxDurability(product, maxDur); DurabilityService.SetDurability(product, maxDur); break; case ComponentBonusType.ChargesUp: product.Charges += amount; break; case ComponentBonusType.ACUp: product.CustomAC += amount; break; case ComponentBonusType.HarvestingUp: product.HarvestingBonus += amount; break; case ComponentBonusType.CastingSpeedUp: product.CastingSpeed += amount; break; case ComponentBonusType.ArmorsmithUp: product.CraftBonusArmorsmith += amount; break; case ComponentBonusType.WeaponsmithUp: product.CraftBonusWeaponsmith += amount; break; case ComponentBonusType.CookingUp: product.CraftBonusCooking += amount; break; case ComponentBonusType.EngineeringUp: product.CraftBonusEngineering += amount; break; case ComponentBonusType.FabricationUp: product.CraftBonusFabrication += amount; break; case ComponentBonusType.HPUp: product.HPBonus += amount; break; case ComponentBonusType.FPUp: product.FPBonus += amount; break; case ComponentBonusType.EnmityUp: product.EnmityRate += amount; break; case ComponentBonusType.EnmityDown: product.EnmityRate -= amount; break; case ComponentBonusType.DarkPotencyUp: product.DarkPotencyBonus += amount; break; case ComponentBonusType.LightPotencyUp: product.LightPotencyBonus += amount; break; case ComponentBonusType.MindPotencyUp: product.MindPotencyBonus += amount; break; case ComponentBonusType.LuckUp: product.LuckBonus += amount; break; case ComponentBonusType.MeditateUp: product.MeditateBonus += amount; break; case ComponentBonusType.RestUp: product.RestBonus += amount; break; case ComponentBonusType.MedicineUp: product.MedicineBonus += amount; break; case ComponentBonusType.HPRegenUp: product.HPRegenBonus += amount; break; case ComponentBonusType.FPRegenUp: product.FPRegenBonus += amount; break; case ComponentBonusType.BaseAttackBonusUp: product.BaseAttackBonus += amount; break; case ComponentBonusType.SneakAttackUp: product.SneakAttackBonus += amount; break; case ComponentBonusType.DamageUp: product.DamageBonus += amount; break; case ComponentBonusType.DarkPotencyDown: product.DarkPotencyBonus -= amount; break; case ComponentBonusType.LightPotencyDown: product.LightPotencyBonus -= amount; break; case ComponentBonusType.StructureBonusUp: product.StructureBonus += amount; break; case ComponentBonusType.StrengthUp: product.StrengthBonus += amount; break; case ComponentBonusType.DexterityUp: product.DexterityBonus += amount; break; case ComponentBonusType.ConstitutionUp: product.ConstitutionBonus += amount; break; case ComponentBonusType.WisdomUp: product.WisdomBonus += amount; break; case ComponentBonusType.IntelligenceUp: product.IntelligenceBonus += amount; break; case ComponentBonusType.CharismaUp: product.CharismaBonus += amount; break; case ComponentBonusType.AttackBonusUp: prop = _.ItemPropertyAttackBonus(amount); break; case ComponentBonusType.DurationUp: product.DurationBonus += amount; break; case ComponentBonusType.ScanningUp: product.ScanningBonus += amount; break; case ComponentBonusType.ScavengingUp: product.ScavengingBonus += amount; break; case ComponentBonusType.MindPotencyDown: product.MindPotencyBonus -= amount; break; case ComponentBonusType.ElectricalPotencyUp: product.ElectricalPotencyBonus += amount; break; case ComponentBonusType.ElectricalPotencyDown: product.ElectricalPotencyBonus -= amount; break; case ComponentBonusType.ForcePotencyUp: product.ForcePotencyBonus += amount; break; case ComponentBonusType.ForcePotencyDown: product.ForcePotencyBonus -= amount; break; case ComponentBonusType.ForceAccuracyUp: product.ForceAccuracyBonus += amount; break; case ComponentBonusType.ForceAccuracyDown: product.ForceAccuracyBonus -= amount; break; case ComponentBonusType.ForceDefenseUp: product.ForceDefenseBonus += amount; break; case ComponentBonusType.ForceDefenseDown: product.ForceDefenseBonus -= amount; break; case ComponentBonusType.ElectricalDefenseUp: product.ElectricalDefenseBonus += amount; break; case ComponentBonusType.ElectricalDefenseDown: product.ElectricalDefenseBonus -= amount; break; case ComponentBonusType.MindDefenseUp: product.MindDefenseBonus += amount; break; case ComponentBonusType.MindDefenseDown: product.MindDefenseBonus -= amount; break; case ComponentBonusType.LightDefenseUp: product.LightDefenseBonus += amount; break; case ComponentBonusType.LightDefenseDown: product.LightDefenseBonus -= amount; break; case ComponentBonusType.DarkDefenseUp: product.DarkDefenseBonus += amount; break; case ComponentBonusType.DarkDefenseDown: product.DarkDefenseBonus -= amount; break; case ComponentBonusType.PilotingUp: product.PilotingBonus += amount; break; default: throw new ArgumentOutOfRangeException(); } if (!string.IsNullOrWhiteSpace(sourceTag)) { prop = ItemService.GetCustomItemPropertyByItemTag(sourceTag); } if (prop == null) { return; } BiowareXP2.IPSafeAddItemProperty(product, prop, 0.0f, AddItemPropertyPolicy.IgnoreExisting, true, true); } }
private void OnCompleteSmelt(OnCompleteSmelt data) { NWPlayer player = data.Player; string oreResref = data.OreResref; List <ItemProperty> itemProperties = data.ItemProperties; player.IsBusy = false; int rank = SkillService.GetPCSkillRank(player, SkillType.Harvesting); int level = CraftService.GetIngotLevel(oreResref); string ingotResref = CraftService.GetIngotResref(oreResref); if (level < 0 || string.IsNullOrWhiteSpace(ingotResref)) { return; } int delta = rank - level; int count = 2; if (delta > 2) { count = delta; } if (count > 4) { count = 4; } if (RandomService.Random(100) + 1 <= PerkService.GetCreaturePerkLevel(player, PerkType.Lucky)) { count++; } if (RandomService.Random(100) + 1 <= PerkService.GetCreaturePerkLevel(player, PerkType.ProcessingEfficiency) * 10) { count++; } for (int x = 1; x <= count; x++) { var item = (_.CreateItemOnObject(ingotResref, player.Object)); int chance; switch (x) { case 1: case 2: chance = 100; break; case 3: chance = 70; break; case 4: chance = 60; break; case 5: chance = 50; break; default: chance = 30; break; } foreach (var ip in itemProperties) { if (RandomService.D100(1) <= chance) { BiowareXP2.IPSafeAddItemProperty(item, ip, 0.0f, AddItemPropertyPolicy.IgnoreExisting, true, true); } } } var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(player); int harvestingSkill = SkillService.GetPCSkillRank(player, SkillType.Harvesting); int perkBonus = PerkService.GetCreaturePerkLevel(player, PerkType.StronidiumRefining) + 1; int stronidiumAmount = 10 + effectiveStats.Harvesting + harvestingSkill + RandomService.Random(1, 5); stronidiumAmount *= perkBonus; _.CreateItemOnObject("stronidium", player.Object, stronidiumAmount); int xp = (int)SkillService.CalculateRegisteredSkillLevelAdjustedXP(100, level, rank); SkillService.GiveSkillXP(player, SkillType.Harvesting, xp); }
private Tuple <int, float> RunComponentBonusAttempt(NWPlayer player, NWItem component, float equipmentBonus, float chance, List <NWItem> itemSet) { int successAmount = 0; // Note - this line MUST be outside the foreach loop, as inspecting component properties will reset the component.ItemProperties counter. int componentLevel = component.LevelIncrease > 0 ? component.LevelIncrease : component.RecommendedLevel; if (componentLevel < 1) { componentLevel = 1; } foreach (var ip in component.ItemProperties) { int ipType = _.GetItemPropertyType(ip); if (ipType != (int)CustomItemPropertyType.ComponentBonus) { continue; } int bonusTypeID = _.GetItemPropertySubType(ip); int tlkID = Convert.ToInt32(_.Get2DAString("iprp_compbon", "Name", bonusTypeID)); int amount = _.GetItemPropertyCostTableValue(ip); string bonusName = _.GetStringByStrRef(tlkID) + " " + amount; float random = RandomService.RandomFloat() * 100.0f; float modifiedEquipmentBonus = equipmentBonus * 0.25f; if (random <= chance + modifiedEquipmentBonus) { foreach (var item in itemSet) { // If the target item is a component itself, we want to add the component bonuses instead of the // actual item property bonuses. // In other words, we want the custom item property "Component Bonus: AC UP" instead of the "AC Bonus" item property. var componentIP = item.ItemProperties.FirstOrDefault(x => _.GetItemPropertyType(x) == (int)CustomItemPropertyType.ComponentType); if (componentIP == null) { ComponentBonusService.ApplyComponentBonus(item, ip); } else { BiowareXP2.IPSafeAddItemProperty(item, ip, 0.0f, AddItemPropertyPolicy.IgnoreExisting, false, false); } } player.SendMessage(ColorTokenService.Green("Successfully applied component property: " + bonusName)); ComponentBonusType bonusType = (ComponentBonusType)_.GetItemPropertySubType(ip); if (bonusType != ComponentBonusType.DurabilityUp) { // Durability bonuses don't increase the penalty. Higher level components transfer multiple // properties more easily (to balance the fact that you can fit fewer of them on an item). int penalty; switch (componentLevel) { case 1: penalty = RandomService.Random(1, 19); break; case 2: penalty = RandomService.Random(1, 9); break; case 3: penalty = RandomService.Random(1, 6); break; case 4: penalty = RandomService.Random(1, 4); break; default: penalty = RandomService.Random(1, 3); break; } chance -= penalty; if (chance < 1) { chance = 1; } } successAmount++; } else { player.SendMessage(ColorTokenService.Red("Failed to apply component property: " + bonusName)); } } return(new Tuple <int, float>(successAmount, chance)); }
private int ProcessProperty(int amount, int maxBonuses, ComponentBonusType bonus, float levelsPerBonus = 1.0f) { string resref = _componentType.ReassembledResref; int penalty = 0; int luck = PerkService.GetCreaturePerkLevel(_player, PerkType.Lucky) + (_playerItemStats.Luck / 3); int xp = 0; ItemPropertyUnpacked bonusIP = new ItemPropertyUnpacked { Property = (int)ItemPropertyType.ComponentBonus, SubType = (int)bonus, CostTable = 62, CostTableValue = 0, Param1 = 255, Param1Value = 0, UsesPerDay = 255, ChanceToAppear = 100, IsUseable = true, SpellID = -1 }; while (amount > 0) { int chanceToTransfer = CraftService.CalculateReassemblyChance(_player, penalty); // Roll to see if the item can be created. bool success = RandomService.Random(0, 100) <= chanceToTransfer; // Do a lucky roll if we failed the first time. if (!success && luck > 0 && RandomService.Random(0, 100) <= luck) { _player.SendMessage("Lucky reassemble!"); success = true; } if (amount >= maxBonuses) { if (success) { int levelIncrease = (int)(maxBonuses * levelsPerBonus); // Roll succeeded. Create item. bonusIP.CostTableValue = maxBonuses; ItemProperty bonusIPPacked = NWNXItemProperty.PackIP(bonusIP); NWItem item = _.CreateItemOnObject(resref, _player); item.RecommendedLevel = levelIncrease; BiowareXP2.IPSafeAddItemProperty(item, bonusIPPacked, 0.0f, AddItemPropertyPolicy.ReplaceExisting, true, false); xp += (150 * maxBonuses + RandomService.Random(0, 5)); } else { _player.SendMessage(ColorTokenService.Red("You failed to create a component. (+" + maxBonuses + ")")); xp += (50 + RandomService.Random(0, 5)); } // Penalty to chance increases regardless if item was created or not. penalty += (maxBonuses * 5); amount -= maxBonuses; } else { if (success) { int levelIncrease = (int)(amount * levelsPerBonus); bonusIP.CostTableValue = amount; ItemProperty bonusIPPacked = NWNXItemProperty.PackIP(bonusIP); NWItem item = _.CreateItemOnObject(resref, _player); item.RecommendedLevel = levelIncrease; BiowareXP2.IPSafeAddItemProperty(item, bonusIPPacked, 0.0f, AddItemPropertyPolicy.ReplaceExisting, true, false); xp += (150 * amount + RandomService.Random(0, 5)); } else { _player.SendMessage(ColorTokenService.Red("You failed to create a component. (+" + amount + ")")); xp += (50 + RandomService.Random(0, 5)); } break; } } return(xp); }
public void ApplyEffects(NWCreature user, NWItem item, NWObject target, Location targetLocation, CustomData customData) { NWPlayer player = user.Object; ResourceQuality quality = (ResourceQuality)target.GetLocalInt("RESOURCE_QUALITY"); int tier = target.GetLocalInt("RESOURCE_TIER"); int remaining = target.GetLocalInt("RESOURCE_COUNT") - 1; string itemResref = target.GetLocalString("RESOURCE_RESREF"); int ipBonusChance = ResourceService.CalculateChanceForComponentBonus(player, tier, quality); int roll = RandomService.Random(1, 100); int rank = SkillService.GetPCSkillRank(player, SkillType.Harvesting); if (item.RecommendedLevel < rank) { rank = item.RecommendedLevel; } int difficulty = (tier - 1) * 10 + ResourceService.GetDifficultyAdjustment(quality); int delta = difficulty - rank; int baseXP = 0; if (delta >= 6) { baseXP = 400; } else if (delta == 5) { baseXP = 350; } else if (delta == 4) { baseXP = 325; } else if (delta == 3) { baseXP = 300; } else if (delta == 2) { baseXP = 250; } else if (delta == 1) { baseXP = 225; } else if (delta == 0) { baseXP = 200; } else if (delta == -1) { baseXP = 150; } else if (delta == -2) { baseXP = 100; } else if (delta == -3) { baseXP = 50; } else if (delta == -4) { baseXP = 25; } int itemHarvestBonus = item.HarvestingBonus; int scanningBonus = user.GetLocalInt(target.GlobalID.ToString()); ipBonusChance += itemHarvestBonus * 2 + scanningBonus * 2; baseXP = baseXP + scanningBonus * 5; NWItem resource = _.CreateItemOnObject(itemResref, player.Object); if (roll <= ipBonusChance) { var ip = ResourceService.GetRandomComponentBonusIP(quality); BiowareXP2.IPSafeAddItemProperty(resource, ip.Item1, 0.0f, AddItemPropertyPolicy.IgnoreExisting, true, true); switch (ip.Item2) { case 0: resource.Name = ColorTokenService.Green(resource.Name); break; case 1: resource.Name = ColorTokenService.Blue(resource.Name); break; case 2: resource.Name = ColorTokenService.Purple(resource.Name); break; case 3: resource.Name = ColorTokenService.Orange(resource.Name); break; } } float decayMinimum = 0.03f; float decayMaximum = 0.07f; if (delta > 0) { decayMinimum += delta * 0.1f; decayMaximum += delta * 0.1f; } user.SendMessage("You harvest " + resource.Name + "."); DurabilityService.RunItemDecay(player, item, RandomService.RandomFloat(decayMinimum, decayMaximum)); int xp = baseXP; SkillService.GiveSkillXP(player, SkillType.Harvesting, xp); if (remaining <= 0) { NWPlaceable prop = target.GetLocalObject("RESOURCE_PROP_OBJ"); if (prop.IsValid) { prop.Destroy(); } target.Destroy(); user.DeleteLocalInt(target.GlobalID.ToString()); } else { target.SetLocalInt("RESOURCE_COUNT", remaining); } _.ApplyEffectAtLocation(DURATION_TYPE_INSTANT, _.EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_3), target.Location); }
public static void ApplyComponentBonus(NWItem product, ItemProperty sourceIP) { ComponentBonusType bonusType = (ComponentBonusType)_.GetItemPropertySubType(sourceIP); int amount = _.GetItemPropertyCostTableValue(sourceIP); ItemProperty prop = null; string sourceTag = string.Empty; int attackBonus = 0; // A note about the sourceTags: // It's not currently possible to create custom item properties on items. To get around this, // we look in an inaccessible container which holds the custom item properties. Then, we get the // item that has the item property we want. From there we take that item property and copy it to // the crafted item. // This is a really roundabout way to do it, but it's the only option for now. Hopefully a feature to // directly add the item properties comes in to NWNX in the future. // 2019-06-12: Directly modifying item properties is possible now but I'm not going to do a refactor until later. // Anyone interested in working on this let me know and I can point you in the right direction. - Z for (int x = 1; x <= amount; x++) { switch (bonusType) { case ComponentBonusType.ModSocketRed: sourceTag = "rslot_red"; break; case ComponentBonusType.ModSocketBlue: sourceTag = "rslot_blue"; break; case ComponentBonusType.ModSocketGreen: sourceTag = "rslot_green"; break; case ComponentBonusType.ModSocketYellow: sourceTag = "rslot_yellow"; break; case ComponentBonusType.ModSocketPrismatic: sourceTag = "rslot_prismatic"; break; case ComponentBonusType.DurabilityUp: var maxDur = DurabilityService.GetMaxDurability(product) + amount; DurabilityService.SetMaxDurability(product, maxDur); DurabilityService.SetDurability(product, maxDur); break; case ComponentBonusType.ChargesUp: product.Charges += amount; break; case ComponentBonusType.ACUp: product.CustomAC += amount; break; case ComponentBonusType.HarvestingUp: product.HarvestingBonus += amount; break; case ComponentBonusType.CooldownRecoveryUp: product.CooldownRecovery += amount; break; case ComponentBonusType.ArmorsmithUp: product.CraftBonusArmorsmith += amount; break; case ComponentBonusType.WeaponsmithUp: product.CraftBonusWeaponsmith += amount; break; case ComponentBonusType.CookingUp: product.CraftBonusCooking += amount; break; case ComponentBonusType.EngineeringUp: product.CraftBonusEngineering += amount; break; case ComponentBonusType.FabricationUp: product.CraftBonusFabrication += amount; break; case ComponentBonusType.HPUp: product.HPBonus += amount; break; case ComponentBonusType.FPUp: product.FPBonus += amount; break; case ComponentBonusType.EnmityUp: product.EnmityRate += amount; break; case ComponentBonusType.EnmityDown: product.EnmityRate -= amount; break; case ComponentBonusType.LuckUp: product.LuckBonus += amount; break; case ComponentBonusType.MeditateUp: product.MeditateBonus += amount; break; case ComponentBonusType.RestUp: product.RestBonus += amount; break; case ComponentBonusType.MedicineUp: product.MedicineBonus += amount; break; case ComponentBonusType.HPRegenUp: product.HPRegenBonus += amount; break; case ComponentBonusType.FPRegenUp: product.FPRegenBonus += amount; break; case ComponentBonusType.BaseAttackBonusUp: product.BaseAttackBonus += amount; break; case ComponentBonusType.SneakAttackUp: product.SneakAttackBonus += amount; break; case ComponentBonusType.DamageUp: product.DamageBonus += amount; break; case ComponentBonusType.StructureBonusUp: product.StructureBonus += amount; break; case ComponentBonusType.StrengthUp: product.StrengthBonus += amount; break; case ComponentBonusType.DexterityUp: product.DexterityBonus += amount; break; case ComponentBonusType.ConstitutionUp: product.ConstitutionBonus += amount; break; case ComponentBonusType.WisdomUp: product.WisdomBonus += amount; break; case ComponentBonusType.IntelligenceUp: product.IntelligenceBonus += amount; break; case ComponentBonusType.CharismaUp: product.CharismaBonus += amount; break; case ComponentBonusType.AttackBonusUp: attackBonus += amount; break; case ComponentBonusType.DurationUp: product.DurationBonus += amount; break; case ComponentBonusType.ScanningUp: product.ScanningBonus += amount; break; case ComponentBonusType.ScavengingUp: product.ScavengingBonus += amount; break; case ComponentBonusType.PilotingUp: product.PilotingBonus += amount; break; // Legacy and other component bonus types won't do anything. default: return; } if (!string.IsNullOrWhiteSpace(sourceTag)) { prop = ItemService.GetCustomItemPropertyByItemTag(sourceTag); } if (prop == null) { return; } BiowareXP2.IPSafeAddItemProperty(product, prop, 0.0f, AddItemPropertyPolicy.IgnoreExisting, true, true); } // Attack bonus is aggregated into one item property, ensuring that the amount doesn't go over 20. if (attackBonus > 0) { // Look for existing properties, get the value and add it. Then remove that item property. foreach (var ip in product.ItemProperties) { if (_.GetItemPropertyType(ip) == _.ITEM_PROPERTY_ATTACK_BONUS) { amount = _.GetItemPropertyCostTableValue(ip); attackBonus += amount; _.RemoveItemProperty(product, ip); } } // Clamp bonus to 20. if (attackBonus > 20) { attackBonus = 20; } // Time to add the new item property. prop = _.ItemPropertyAttackBonus(attackBonus); BiowareXP2.IPSafeAddItemProperty(product, prop, 0.0f, AddItemPropertyPolicy.ReplaceExisting, false, false); } }