private void LoadMainPage() { NWPlayer player = GetPC(); NWPlaceable terminal = NWGameObject.OBJECT_SELF; DateTime now = DateTime.UtcNow; Guid boardID = new Guid(terminal.GetLocalString("MESSAGE_BOARD_ID")); bool isDM = player.IsDM; var messages = DataService.Message .GetAllByBoardID(boardID) .Where(x => x.DateExpires > now && x.DateRemoved == null) .OrderByDescending(o => o.DatePosted); ClearPageResponses("MainPage"); AddResponseToPage("MainPage", ColorTokenService.Green("Create New Post"), !isDM); foreach (var message in messages) { string title = message.Title; if (message.PlayerID == player.GlobalID) { title = ColorTokenService.Cyan(title); } AddResponseToPage("MainPage", title, true, message.ID); } }
private void LoadConfirmPage() { var model = GetDialogCustomData <Model>(); var pcPerk = DataService.Single <PCPerk>(x => x.ID == model.PCPerkID); var perk = DataService.Get <Data.Entity.Perk>(pcPerk.PerkID); var minimumLevel = 1; if (IsGrantedByBackground((PerkType)perk.ID)) { minimumLevel = 2; } int refundAmount = DataService.Where <PerkLevel>(x => x.PerkID == perk.ID && x.Level <= pcPerk.PerkLevel && x.Level >= minimumLevel).Sum(x => x.Price); string header = ColorTokenService.Green("Perk: ") + perk.Name + "\n"; header += ColorTokenService.Green("Level: ") + pcPerk.PerkLevel + "\n\n"; header += "You will receive " + ColorTokenService.Green(refundAmount.ToString()) + " SP if you refund this perk. Are you sure you want to refund it?"; SetPageHeader("ConfirmPage", header); SetResponseText("ConfirmPage", 1, model.IsConfirming ? "CONFIRM REFUND" : "Confirm Refund"); }
private void LoadItemDetailsPage() { var player = GetPC(); var model = MarketService.GetPlayerMarketData(player); var listing = DataService.PCMarketListing.GetByID(model.BrowseListingID); string sellerNote = listing.Note; if (string.IsNullOrWhiteSpace(listing.Note)) { sellerNote = "[UNSPECIFIED]"; } string header = ColorTokenService.Green("Galactic Trade Network") + "\n\n"; header += ColorTokenService.Green("Name: ") + listing.ItemStackSize + "x " + listing.ItemName + "\n"; if (listing.ItemRecommendedLevel > 0) { header += ColorTokenService.Green("Recommended Level: ") + listing.ItemRecommendedLevel + "\n"; } header += ColorTokenService.Green("Price: ") + listing.Price + " credits\n"; header += ColorTokenService.Green("Seller Note: ") + sellerNote + "\n"; SetPageHeader("ItemDetailsPage", header); // Show or hide the "Buy Item" option depending on whether the player has enough gold. if (player.Gold < listing.Price) { SetResponseVisible("ItemDetailsPage", 2, false); } else { SetResponseVisible("ItemDetailsPage", 2, true); } }
public override PlayerDialog SetUp(NWPlayer player) { PlayerDialog dialog = new PlayerDialog("MainPage"); DialogPage mainPage = new DialogPage( ColorTokenService.Green("Persistent Storage Menu") + "\n\nPlease select an option.", "Open Storage", "Change Container Name" ); DialogPage changeNamePage = new DialogPage( ColorTokenService.Green("Change Container Name") + "\n\nPlease type a name for the container into your chat bar and then press enter. After that's done click the 'Next' button on this conversation window.", "Next" ); DialogPage confirmChangeName = new DialogPage( "<SET LATER>", "Confirm Name Change" ); dialog.AddPage("MainPage", mainPage); dialog.AddPage("ChangeNamePage", changeNamePage); dialog.AddPage("ConfirmChangeNamePage", confirmChangeName); return(dialog); }
private void LoadDistributeRPXPPage() { NWPlayer player = GetPC(); Player dbPlayer = DataService.Get <Player>(player.GlobalID); Model vm = GetDialogCustomData <Model>(); Skill skill = SkillService.GetSkill(vm.SelectedSkillID); string header = ColorTokenService.Green("Roleplay XP Distribution") + "\n\n"; header += ColorTokenService.Green("Skill: ") + skill.Name + "\n"; header += ColorTokenService.Green("Available RP XP: ") + dbPlayer.RoleplayXP + "\n"; header += ColorTokenService.Green("Currently Distributing: ") + vm.RPXPDistributing + " RP XP\n"; if (vm.IsConfirming) { SetResponseText("DistributeRPXPPage", 10, "CONFIRM DISTRIBUTE ROLEPLAY XP (" + vm.RPXPDistributing + ")"); } else { SetResponseText("DistributeRPXPPage", 10, "Distribute Roleplay XP (" + vm.RPXPDistributing + ")"); } SetPageHeader("DistributeRPXPPage", header); }
private void BuildPlayerListPage() { var speakingPC = GetPC(); List <Guid> playerIdList = new List <Guid>(); ClearPageResponses("PlayerListPage"); // Online players foreach (var player in NWModule.Get().Players) { if (player == speakingPC || !player.IsPlayer) { continue; } playerIdList.Add(player.GlobalID); AddResponseToPage("PlayerListPage", player.Name + ColorTokenService.Green(" online"), true, DataService.Player.GetByID(player.GlobalID)); } // Offline players with existing permissions var data = BaseService.GetPlayerTempData(GetPC()); var permissions = DataService.PCBasePermission.GetAllPermissionsByPCBaseID(data.PCBaseID); foreach (PCBasePermission permission in permissions) { Player player = DataService.Player.GetByID(permission.PlayerID); // don't allow deletion of the self! if (player.ID == speakingPC.GlobalID || playerIdList.Contains(player.ID)) { continue; } playerIdList.Add(player.ID); AddResponseToPage("PlayerListPage", player.CharacterName + ColorTokenService.Red(" offline"), true, player); } }
private void LoadTaskDetailsPage() { var player = GetPC(); var model = GetDialogCustomData <Model>(); var task = DataService.GuildTask.GetByID(model.TaskID); var quest = QuestService.GetQuestByID(task.QuestID); var status = DataService.PCQuestStatus.GetByPlayerAndQuestIDOrDefault(player.GlobalID, task.QuestID); bool showQuestAccept = status == null || status.CompletionDate != null; // Never accepted, or has already been completed once. bool showGiveReport = status != null && status.CompletionDate == null; // Accepted, but not completed. var gpRewards = quest.GetRewards().Where(x => x.GetType() == typeof(QuestGPReward)).Cast <QuestGPReward>(); var goldRewards = quest.GetRewards().Where(x => x.GetType() == typeof(QuestGoldReward)).Cast <QuestGoldReward>(); int gpAmount = 0; int goldAmount = 0; foreach (var gpReward in gpRewards) { gpAmount += GuildService.CalculateGPReward(player, gpReward.Guild, gpReward.Amount); } foreach (var goldReward in goldRewards) { goldAmount += goldReward.Amount; } string header = ColorTokenService.Green("Task: ") + quest.Name + "\n\n"; header += "Rewards:\n\n"; header += ColorTokenService.Green("Credits: ") + goldAmount + "\n"; header += ColorTokenService.Green("Guild Points: ") + gpAmount; SetPageHeader("TaskDetailsPage", header); SetResponseVisible("TaskDetailsPage", 1, showQuestAccept); SetResponseVisible("TaskDetailsPage", 2, showGiveReport); }
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 gemChance = 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()); gemChance += itemHarvestBonus * 2 + scanningBonus * 2; baseXP = baseXP + scanningBonus * 5; // Spawn the normal resource. NWItem resource = CreateItemOnObject(itemResref, player); user.SendMessage("You harvest " + resource.Name + "."); // If player meets the chance to acquire a gem, create one and modify its properties. if (quality > ResourceQuality.Low && roll <= gemChance) { // Gemstone quality is determined by the quality of the vein. switch (quality) { case ResourceQuality.Normal: resource = CreateItemOnObject("flawed_gemstone", player); break; case ResourceQuality.High: resource = CreateItemOnObject("gemstone", player); break; case ResourceQuality.VeryHigh: resource = CreateItemOnObject("perfect_gemstone", player); break; } 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; case 4: resource.Name = ColorTokenService.LightPurple(resource.Name); break; case 5: resource.Name = ColorTokenService.Yellow(resource.Name); break; case 6: resource.Name = ColorTokenService.Red(resource.Name); break; case 7: resource.Name = ColorTokenService.Cyan(resource.Name); break; } user.SendMessage("You harvest " + resource.Name + "."); } float decayMinimum = 0.03f; float decayMaximum = 0.07f; if (delta > 0) { decayMinimum += delta * 0.1f; decayMaximum += delta * 0.1f; } 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(DurationType.Instant, EffectVisualEffect(VisualEffect.Vfx_Fnf_Summon_Monster_3), target.Location); }
public static void SubscribeEvents() { MessageHub.Instance.Subscribe <OnModuleLoad>(x => { var classes = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(s => s.GetTypes()) .Where(p => typeof(IChatCommand).IsAssignableFrom(p) && p.IsClass) .OrderBy(o => o.Name) .ToArray(); foreach (var @class in classes) { var attribute = @class.GetCustomAttribute <CommandDetailsAttribute>(); if (attribute == null) { continue; } if (attribute.Permissions.HasFlag(CommandPermissionType.Player)) { _helpTextPlayer += ColorTokenService.Green("/" + @class.Name.ToLower()) + ColorTokenService.White(": " + attribute.Description) + "\n"; } if (attribute.Permissions.HasFlag(CommandPermissionType.DM)) { _helpTextDM += ColorTokenService.Green("/" + @class.Name.ToLower()) + ColorTokenService.White(": " + attribute.Description) + "\n"; } } }); }
public override PlayerDialog SetUp(NWPlayer player) { PlayerDialog dialog = new PlayerDialog("MainPage"); // Entry point into conversation for selecting Buy or Sell DialogPage mainPage = new DialogPage( ColorTokenService.Green("Galactic Trade Network"), "Buy", "Sell", "Manage Market Listings"); // Page for selecting browse method - either by category or by seller DialogPage buyPage = new DialogPage( ColorTokenService.Green("Galactic Trade Network - Buy"), "Browse by Category", "Browse by Seller"); // Page for selecting which item category to browse DialogPage browseByCategoryPage = new DialogPage(); // Dynamically built // Page for selecting which seller's items to browse DialogPage browseBySellerPage = new DialogPage(); // Dynamically built // Page for selecting an item to buy. // Populated based on option selected in the "Browse by Category" and "Browse by Seller" pages. DialogPage itemListPage = new DialogPage(); // Dynamically built // Page for viewing item details and buying the item. DialogPage itemDetailsPage = new DialogPage( "<SET LATER>", "Examine Item", "Buy Item"); // Page for selling an item. DialogPage sellItemPage = new DialogPage( ColorTokenService.Green("Galactic Trade Network - Sell Item"), ColorTokenService.Green("Refresh"), "Pick an Item", "Change Price", "Change Seller Note", "Remove Seller Note", "Change Listing Length", ColorTokenService.Green("List the Item")); // Page for setting a price on an item. DialogPage changePricePage = new DialogPage( "<SET LATER>", "Increase by 100,000 credits", "Increase by 10,000 credits", "Increase by 1,000 credits", "Increase by 100 credits", "Increase by 10 credits", "Increase by 1 credit", "Decrease by 100,000 credits", "Decrease by 10,000 credits", "Decrease by 1,000 credits", "Decrease by 100 credits", "Decrease by 10 credits", "Decrease by 1 credit"); // Page for changing the listing length on an item sale. DialogPage changeListingLengthPage = new DialogPage("<SET LATER>", "Set to Max (30 days, 3% fee)", "Set to Default (7 days, 0.7% fee)", "Increase by 7 days (+0.7% fee)", "Increase by 1 day (+0.1% fee)", "Decrease by 7 days (-0.7% fee)", "Decrease by 1 day (-0.1% fee)"); // Page for viewing items currently being sold by the player. DialogPage marketListingsPage = new DialogPage( ColorTokenService.Green("Galactic Trade Market - Manage Market Listings")); // Page for viewing detailed information about a market listing. DialogPage marketListingDetailsPage = new DialogPage( "<SET LATER>", ColorTokenService.Green("Refresh"), ColorTokenService.Red("Remove Listing")); dialog.AddPage("MainPage", mainPage); dialog.AddPage("BuyPage", buyPage); dialog.AddPage("BrowseByCategoryPage", browseByCategoryPage); dialog.AddPage("BrowseBySellerPage", browseBySellerPage); dialog.AddPage("ItemListPage", itemListPage); dialog.AddPage("ItemDetailsPage", itemDetailsPage); dialog.AddPage("SellItemPage", sellItemPage); dialog.AddPage("ChangePricePage", changePricePage); dialog.AddPage("ChangeListingLengthPage", changeListingLengthPage); dialog.AddPage("MarketListingsPage", marketListingsPage); dialog.AddPage("MarketListingDetailsPage", marketListingDetailsPage); return(dialog); }
public void Main() { NWPlayer oPC = (_.GetLastDisturbed()); NWItem item = (_.GetInventoryDisturbItem()); NWPlaceable container = (NWGameObject.OBJECT_SELF); int disturbType = _.GetInventoryDisturbType(); var structureID = new Guid(container.GetLocalString("PC_BASE_STRUCTURE_ID")); var structure = DataService.PCBaseStructure.GetByID(structureID); var baseStructure = DataService.BaseStructure.GetByID(structure.BaseStructureID); int itemLimit = baseStructure.Storage + structure.StructureBonus; int itemCount = container.InventoryItems.Count(); string itemResref = item.Resref; if (disturbType == _.INVENTORY_DISTURB_TYPE_ADDED) { if (_.GetHasInventory(item) == _.TRUE) { item.SetLocalInt("RETURNING_ITEM", _.TRUE); ItemService.ReturnItem(oPC, item); oPC.SendMessage(ColorTokenService.Red("Containers cannot currently be stored inside banks.")); return; } if (itemCount > itemLimit) { ItemService.ReturnItem(oPC, item); oPC.SendMessage(ColorTokenService.Red("No more items can be placed inside.")); } else if (item.BaseItemType == _.BASE_ITEM_GOLD) { ItemService.ReturnItem(oPC, item); oPC.SendMessage(ColorTokenService.Red("Credits cannot be placed inside.")); } else { PCBaseStructureItem itemEntity = new PCBaseStructureItem { ItemName = item.Name, ItemResref = itemResref, ItemTag = item.Tag, PCBaseStructureID = structureID, ItemGlobalID = item.GlobalID.ToString(), ItemObject = SerializationService.Serialize(item) }; DataService.SubmitDataChange(itemEntity, DatabaseActionType.Insert); MessageHub.Instance.Publish(new OnStoreStructureItem(oPC, itemEntity)); } } else if (disturbType == _.INVENTORY_DISTURB_TYPE_REMOVED) { if (item.GetLocalInt("RETURNING_ITEM") == _.TRUE) { item.DeleteLocalInt("RETURNING_ITEM"); } else { var dbItem = DataService.PCBaseStructureItem.GetByItemGlobalID(item.GlobalID.ToString()); DataService.SubmitDataChange(dbItem, DatabaseActionType.Delete); MessageHub.Instance.Publish(new OnRemoveStructureItem(oPC, dbItem)); } } oPC.SendMessage(ColorTokenService.White("Item Limit: " + itemCount + " / ") + ColorTokenService.Red(itemLimit.ToString())); }
private void BuildPlayerDetailsPage(NWPlayer player) { ClearPageResponses("PlayerDetailsPage"); var data = BaseService.GetPlayerTempData(GetPC()); var permission = DataService.SingleOrDefault <PCBaseStructurePermission>(x => x.PlayerID == player.GlobalID && x.PCBaseStructureID == data.StructureID && !x.IsPublicPermission); // Intentionally excluded permissions: CanAdjustPermissions, CanCancelLease bool canPlaceEditStructures = permission?.CanPlaceEditStructures ?? false; bool canAccessStructureInventory = permission?.CanAccessStructureInventory ?? false; bool canEnterBuilding = permission?.CanEnterBuilding ?? false; bool canAdjustPermissions = permission?.CanAdjustPermissions ?? false; bool canRetrieveStructures = permission?.CanRetrieveStructures ?? false; bool canRenameStructures = permission?.CanRenameStructures ?? false; bool canEditPrimaryResidence = permission?.CanEditPrimaryResidence ?? false; bool canRemovePrimaryResidence = permission?.CanRemovePrimaryResidence ?? false; bool canChangeStructureMode = permission?.CanChangeStructureMode ?? false; bool canAdjustPublicPermissions = permission?.CanAdjustPublicPermissions ?? false; bool canFlyStarship = permission?.CanFlyStarship ?? false; bool isStarship = GetPC().Area.GetLocalInt("BUILDING_TYPE") == (int)Enumeration.BuildingType.Starship; string header = ColorTokenService.Green("Name: ") + player.Name + "\n\n"; header += ColorTokenService.Green("Permissions:\n\n"); header += "Can Place/Edit Structures: " + (canPlaceEditStructures ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Access Structure Inventory: " + (canAccessStructureInventory ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Enter Building: " + (canEnterBuilding ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Adjust Permissions: " + (canAdjustPermissions ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Retrieve Structures: " + (canRetrieveStructures ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Rename Structures: " + (canRenameStructures ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Edit Primary Residence: " + (canEditPrimaryResidence ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Remove Primary Residence: " + (canRemovePrimaryResidence ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Change Structure Mode: " + (canChangeStructureMode ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Adjust PUBLIC Permissions: " + (canAdjustPublicPermissions ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; if (isStarship) { header += "Can Fly Starship: " + (canFlyStarship ? ColorTokenService.Green("YES") :ColorTokenService.Red("NO")) + "\n"; } SetPageHeader("PlayerDetailsPage", header); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Place/Edit Structures", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Access Structure Inventory", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Enter Building", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Adjust Permissions", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Retrieve Structures", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Rename Structures", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Edit Primary Residence", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Remove Primary Residence", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Change Structure Mode", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Adjust PUBLIC Permissions", true, player); // Add new non-conditional responses here to avoid confusing the response handling logic. if (isStarship) { AddResponseToPage("PlayerDetailsPage", "Toggle: Can Fly Starship", true, player); } }
private string CreateSkillDetailsHeader(PCSkill pcSkill, int req) { Player player = DataService.Player.GetByID(pcSkill.PlayerID); Skill skill = SkillService.GetSkill(pcSkill.SkillID); string title; if (pcSkill.Rank <= 3) { title = "Untrained"; } else if (pcSkill.Rank <= 7) { title = "Neophyte"; } else if (pcSkill.Rank <= 13) { title = "Novice"; } else if (pcSkill.Rank <= 20) { title = "Apprentice"; } else if (pcSkill.Rank <= 35) { title = "Journeyman"; } else if (pcSkill.Rank <= 50) { title = "Expert"; } else if (pcSkill.Rank <= 65) { title = "Adept"; } else if (pcSkill.Rank <= 80) { title = "Master"; } else if (pcSkill.Rank <= 100) { title = "Grandmaster"; } else { title = "Unknown"; } title += " (" + pcSkill.Rank + ")"; string decayLock = ColorTokenService.Green("Decay Lock: ") + ColorTokenService.White("Unlocked"); if (pcSkill.IsLocked) { decayLock = ColorTokenService.Green("Decay Lock: ") + ColorTokenService.Red("Locked"); } // Skills which don't contribute to the cap cannot be locked (there's no reason for it.) // Display a message explaining this to the player instead. string noContributeMessage = string.Empty; if (!skill.ContributesToSkillCap) { decayLock = string.Empty; noContributeMessage = ColorTokenService.Green("This skill does not contribute to your cumulative skill cap.") + "\n\n"; } string rpXP = ColorTokenService.Green("Roleplay XP: ") + player.RoleplayXP + "\n"; Attribute primaryAttribute = DataService.Attribute.GetByID(skill.Primary); Attribute secondaryAttribute = DataService.Attribute.GetByID(skill.Secondary); Attribute tertiaryAttribute = DataService.Attribute.GetByID(skill.Tertiary); string primary = ColorTokenService.Green("Primary (+" + PlayerStatService.PrimaryIncrease + "): ") + primaryAttribute.Name + "\n"; string secondary = ColorTokenService.Green("Secondary (+" + PlayerStatService.SecondaryIncrease + "): ") + secondaryAttribute.Name + "\n"; string tertiary = ColorTokenService.Green("Tertiary (+" + PlayerStatService.TertiaryIncrease + "): ") + tertiaryAttribute.Name + "\n"; return (ColorTokenService.Green("Skill: ") + skill.Name + "\n" + ColorTokenService.Green("Rank: ") + title + "\n" + ColorTokenService.Green("Exp: ") + MenuService.BuildBar(pcSkill.XP, req, 100, ColorTokenService.TokenStart(255, 127, 0)) + "\n" + rpXP + primary + secondary + tertiary + noContributeMessage + decayLock + "\n\n" + ColorTokenService.Green("Description: ") + skill.Description + "\n"); }
public bool Run(params object[] args) { using (new Profiler(nameof(FinishAbilityUse))) { // These arguments are sent from the AbilityService's ActivateAbility method. NWCreature activator = (NWCreature)args[0]; string spellUUID = Convert.ToString(args[1]); int perkID = (int)args[2]; NWObject target = (NWObject)args[3]; int pcPerkLevel = (int)args[4]; int spellTier = (int)args[5]; float armorPenalty = (float)args[6]; // Get the relevant perk information from the database. Data.Entity.Perk dbPerk = DataService.Single <Data.Entity.Perk>(x => x.ID == perkID); // The execution type determines how the perk behaves and the rules surrounding it. PerkExecutionType executionType = dbPerk.ExecutionTypeID; // Get the class which handles this perk's behaviour. IPerkHandler perk = PerkService.GetPerkHandler(perkID); // Pull back cooldown information. int?cooldownID = perk.CooldownCategoryID(activator, dbPerk.CooldownCategoryID, spellTier); CooldownCategory cooldown = cooldownID == null ? null : DataService.SingleOrDefault <CooldownCategory>(x => x.ID == cooldownID); // If the activator interrupted the spell or died, we can bail out early. if (activator.GetLocalInt(spellUUID) == (int)SpellStatusType.Interrupted || // Moved during casting activator.CurrentHP < 0 || activator.IsDead) // Or is dead/dying { activator.DeleteLocalInt(spellUUID); return(false); } // Remove the temporary UUID which is tracking this spell cast. activator.DeleteLocalInt(spellUUID); // Force Abilities, Combat Abilities, Stances, and Concentration Abilities if (executionType == PerkExecutionType.ForceAbility || executionType == PerkExecutionType.CombatAbility || executionType == PerkExecutionType.Stance || executionType == PerkExecutionType.ConcentrationAbility) { // Run the impact script. perk.OnImpact(activator, target, pcPerkLevel, spellTier); // If an animation is specified for this perk, play it now. if (dbPerk.CastAnimationID != null && dbPerk.CastAnimationID > 0) { activator.AssignCommand(() => { _.ActionPlayAnimation((int)dbPerk.CastAnimationID, 1f, 1f); }); } // If the target is an NPC, assign enmity towards this creature for that NPC. if (target.IsNPC) { AbilityService.ApplyEnmity(activator, target.Object, dbPerk); } } // Adjust creature's current FP, if necessary. // Adjust FP only if spell cost > 0 PerkFeat perkFeat = DataService.Single <PerkFeat>(x => x.PerkID == perkID && x.PerkLevelUnlocked == spellTier); int fpCost = perk.FPCost(activator, perkFeat.BaseFPCost, spellTier); if (fpCost > 0) { int currentFP = AbilityService.GetCurrentFP(activator); int maxFP = AbilityService.GetMaxFP(activator); currentFP -= fpCost; AbilityService.SetCurrentFP(activator, currentFP); activator.SendMessage(ColorTokenService.Custom("FP: " + currentFP + " / " + maxFP, 32, 223, 219)); } // Notify activator of concentration ability change and also update it in the DB. if (executionType == PerkExecutionType.ConcentrationAbility) { AbilityService.StartConcentrationEffect(activator, perkID, spellTier); activator.SendMessage("Concentration ability activated: " + dbPerk.Name); // The Skill Increase effect icon and name has been overwritten. Apply the effect to the player now. // This doesn't do anything - it simply gives a visual cue that the player has an active concentration effect. _.ApplyEffectToObject(_.DURATION_TYPE_PERMANENT, _.EffectSkillIncrease(_.SKILL_USE_MAGIC_DEVICE, 1), activator); } // Handle applying cooldowns, if necessary. if (cooldown != null) { AbilityService.ApplyCooldown(activator, cooldown, perk, spellTier, armorPenalty); } // Mark the creature as no longer busy. activator.IsBusy = false; // Mark the spell cast as complete. activator.SetLocalInt(spellUUID, (int)SpellStatusType.Completed); return(true); } }
public bool Run(params object[] args) { NWPlaceable point = (Object.OBJECT_SELF); NWPlayer oPC = (_.GetLastOpenedBy()); if (!oPC.IsPlayer) { return(false); } var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(oPC); const int baseChanceToFullyHarvest = 50; bool alwaysDestroys = point.GetLocalInt("SCAVENGE_POINT_ALWAYS_DESTROYS") == 1; bool hasBeenSearched = point.GetLocalInt("SCAVENGE_POINT_FULLY_HARVESTED") == 1; if (hasBeenSearched) { oPC.SendMessage("There's nothing left to harvest here..."); return(true); } // Not fully harvested but the timer hasn't counted down yet. int refillTick = point.GetLocalInt("SCAVENGE_POINT_REFILL_TICKS"); if (refillTick > 0) { oPC.SendMessage("You couldn't find anything new here. Check back later..."); return(true); } if (!oPC.IsPlayer && !oPC.IsDM) { return(false); } int rank = SkillService.GetPCSkillRank(oPC, SkillType.Scavenging); int lootTableID = point.GetLocalInt("SCAVENGE_POINT_LOOT_TABLE_ID"); int level = point.GetLocalInt("SCAVENGE_POINT_LEVEL"); int delta = level - rank; if (delta > 8) { oPC.SendMessage("You aren't skilled enough to scavenge through this. (Required Level: " + (level - 8) + ")"); oPC.AssignCommand(() => _.ActionInteractObject(point.Object)); return(true); } int dc = 6 + delta; if (dc <= 4) { dc = 4; } int searchAttempts = 1 + CalculateSearchAttempts(oPC); int luck = PerkService.GetPCPerkLevel(oPC, PerkType.Lucky) + effectiveStats.Luck; if (RandomService.Random(100) + 1 <= luck / 2) { dc--; } oPC.AssignCommand(() => _.ActionPlayAnimation(_.ANIMATION_LOOPING_GET_LOW, 1.0f, 2.0f)); for (int attempt = 1; attempt <= searchAttempts; attempt++) { int roll = RandomService.Random(20) + 1; if (roll >= dc) { oPC.FloatingText(ColorTokenService.SkillCheck("Search: *success*: (" + roll + " vs. DC: " + dc + ")")); ItemVO spawnItem = LootService.PickRandomItemFromLootTable(lootTableID); if (spawnItem == null) { return(false); } if (!string.IsNullOrWhiteSpace(spawnItem.Resref) && spawnItem.Quantity > 0) { NWItem resource = _.CreateItemOnObject(spawnItem.Resref, point.Object, spawnItem.Quantity); var componentIP = resource.ItemProperties.FirstOrDefault(x => _.GetItemPropertyType(x) == (int)CustomItemPropertyType.ComponentType); if (componentIP != null) { // Add properties to the item based on Scavenging skill. Similar logic to the resource harvester. var chance = RandomService.Random(1, 100) + PerkService.GetPCPerkLevel(oPC, PerkType.Lucky) + effectiveStats.Luck; ResourceQuality quality; if (chance < 50) { quality = ResourceQuality.Low; } else if (chance < 75) { quality = ResourceQuality.Normal; } else if (chance < 95) { quality = ResourceQuality.High; } else { quality = ResourceQuality.VeryHigh; } int ipBonusChance = ResourceService.CalculateChanceForComponentBonus(oPC, (level / 10 + 1), quality, true); if (RandomService.Random(1, 100) <= ipBonusChance) { var ip = ResourceService.GetRandomComponentBonusIP(ResourceQuality.Normal); 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 xp = SkillService.CalculateRegisteredSkillLevelAdjustedXP(200, level, rank); SkillService.GiveSkillXP(oPC, SkillType.Scavenging, (int)xp); } else { oPC.FloatingText(ColorTokenService.SkillCheck("Search: *failure*: (" + roll + " vs. DC: " + dc + ")")); float xp = SkillService.CalculateRegisteredSkillLevelAdjustedXP(50, level, rank); SkillService.GiveSkillXP(oPC, SkillType.Scavenging, (int)xp); } dc += RandomService.Random(3) + 1; } // Chance to destroy the scavenge point. int chanceToFullyHarvest = baseChanceToFullyHarvest - (PerkService.GetPCPerkLevel(oPC, PerkType.CarefulScavenger) * 5); string growingPlantID = point.GetLocalString("GROWING_PLANT_ID"); if (!string.IsNullOrWhiteSpace(growingPlantID)) { Data.Entity.GrowingPlant growingPlant = FarmingService.GetGrowingPlantByID(new Guid(growingPlantID)); chanceToFullyHarvest = chanceToFullyHarvest - (growingPlant.LongevityBonus); } if (chanceToFullyHarvest <= 5) { chanceToFullyHarvest = 5; } if (alwaysDestroys || RandomService.Random(100) + 1 <= chanceToFullyHarvest) { point.SetLocalInt("SCAVENGE_POINT_FULLY_HARVESTED", 1); oPC.SendMessage("This resource has been fully harvested..."); } // Otherwise the scavenge point will be refilled in 10-20 minutes. else { point.SetLocalInt("SCAVENGE_POINT_REFILL_TICKS", 100 + RandomService.Random(100)); } point.SetLocalInt("SCAVENGE_POINT_DESPAWN_TICKS", 30); return(true); }
private void HandleSaveOutfit(int responseID) { NWPlayer oPC = GetPC(); NWItem oClothes = (_.GetItemInSlot(INVENTORY_SLOT_CHEST, oPC.Object)); if (!CanModifyClothes()) { oPC.FloatingText("You cannot save your currently equipped clothes."); return; } PCOutfit entity = GetPlayerOutfits(oPC); var action = DatabaseActionType.Update; if (entity == null) { entity = new PCOutfit { PlayerID = oPC.GlobalID }; action = DatabaseActionType.Insert; } if (!oClothes.IsValid) { oPC.FloatingText(ColorTokenService.Red("You do not have clothes equipped")); return; } string clothesData = SerializationService.Serialize(oClothes); if (responseID == 1) { entity.Outfit1 = clothesData; } else if (responseID == 2) { entity.Outfit2 = clothesData; } else if (responseID == 3) { entity.Outfit3 = clothesData; } else if (responseID == 4) { entity.Outfit4 = clothesData; } else if (responseID == 5) { entity.Outfit5 = clothesData; } else if (responseID == 6) { entity.Outfit6 = clothesData; } else if (responseID == 7) { entity.Outfit7 = clothesData; } else if (responseID == 8) { entity.Outfit8 = clothesData; } else if (responseID == 9) { entity.Outfit9 = clothesData; } else if (responseID == 10) { entity.Outfit10 = clothesData; } DataService.SubmitDataChange(entity, action); ShowSaveOutfitOptions(); }
private void ShowSaveOutfitOptions() { PCOutfit entity = GetPlayerOutfits(GetPC()) ?? new PCOutfit(); ClearPageResponses("SaveOutfitPage"); string responseText = entity.Outfit1 == null?ColorTokenService.Red("Save in Slot 1") : ColorTokenService.Green("Save in Slot 1"); AddResponseToPage("SaveOutfitPage", responseText); responseText = entity.Outfit2 == null?ColorTokenService.Red("Save in Slot 2") : ColorTokenService.Green("Save in Slot 2"); AddResponseToPage("SaveOutfitPage", responseText); responseText = entity.Outfit3 == null?ColorTokenService.Red("Save in Slot 3") : ColorTokenService.Green("Save in Slot 3"); AddResponseToPage("SaveOutfitPage", responseText); responseText = entity.Outfit4 == null?ColorTokenService.Red("Save in Slot 4") : ColorTokenService.Green("Save in Slot 4"); AddResponseToPage("SaveOutfitPage", responseText); responseText = entity.Outfit5 == null?ColorTokenService.Red("Save in Slot 5") : ColorTokenService.Green("Save in Slot 5"); AddResponseToPage("SaveOutfitPage", responseText); responseText = entity.Outfit6 == null?ColorTokenService.Red("Save in Slot 6") : ColorTokenService.Green("Save in Slot 6"); AddResponseToPage("SaveOutfitPage", responseText); responseText = entity.Outfit7 == null?ColorTokenService.Red("Save in Slot 7") : ColorTokenService.Green("Save in Slot 7"); AddResponseToPage("SaveOutfitPage", responseText); responseText = entity.Outfit8 == null?ColorTokenService.Red("Save in Slot 8") : ColorTokenService.Green("Save in Slot 8"); AddResponseToPage("SaveOutfitPage", responseText); responseText = entity.Outfit9 == null?ColorTokenService.Red("Save in Slot 9") : ColorTokenService.Green("Save in Slot 9"); AddResponseToPage("SaveOutfitPage", responseText); responseText = entity.Outfit10 == null?ColorTokenService.Red("Save in Slot 10") : ColorTokenService.Green("Save in Slot 10"); AddResponseToPage("SaveOutfitPage", responseText); }
private void BuildPlayerDetailsPage(NWPlayer player) { ClearPageResponses("PlayerDetailsPage"); var data = BaseService.GetPlayerTempData(GetPC()); var permission = DataService.SingleOrDefault <PCBasePermission>(x => x.PlayerID == player.GlobalID && x.PCBaseID == data.PCBaseID && !x.IsPublicPermission); // Intentionally excluded permissions: CanAdjustPermissions, CanCancelLease bool canPlaceEditStructures = permission?.CanPlaceEditStructures ?? false; bool canAccessStructureInventory = permission?.CanAccessStructureInventory ?? false; bool canManageBaseFuel = permission?.CanManageBaseFuel ?? false; bool canExtendLease = permission?.CanExtendLease ?? false; bool canEnterBuildings = permission?.CanEnterBuildings ?? false; bool canRetrieveStructures = permission?.CanRetrieveStructures ?? false; bool canRenameStructures = permission?.CanRenameStructures ?? false; bool canEditPrimaryResidence = permission?.CanEditPrimaryResidence ?? false; bool canRemovePrimaryResidence = permission?.CanRemovePrimaryResidence ?? false; bool canChangeStructureMode = permission?.CanChangeStructureMode ?? false; bool canDockShip = permission?.CanDockStarship ?? false; bool canAdjustPublicPermissions = permission?.CanAdjustPublicPermissions ?? false; string header = ColorTokenService.Green("Name: ") + player.Name + "\n\n"; header += ColorTokenService.Green("Permissions:\n\n"); header += "Can Place/Edit Structures: " + (canPlaceEditStructures ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Access Structure Inventory: " + (canAccessStructureInventory ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Manage Base Fuel: " + (canManageBaseFuel ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Extend Lease: " + (canExtendLease ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Enter Buildings: " + (canEnterBuildings ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Retrieve Structures: " + (canRetrieveStructures ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Rename Structures: " + (canRenameStructures ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Edit Primary Residence: " + (canEditPrimaryResidence ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Remove Primary Residence: " + (canRemovePrimaryResidence ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Change Structure Mode: " + (canChangeStructureMode ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Dock Starships: " + (canDockShip ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; header += "Can Adjust PUBLIC Permissions: " + (canAdjustPublicPermissions ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; SetPageHeader("PlayerDetailsPage", header); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Place/Edit Structures", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Access Structure Inventory", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Manage Base Fuel", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Extend Lease", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Enter Buildings", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Retrieve Structures", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Rename Structures", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Edit Primary Residence", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Change Structure Mode", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Dock Starships", true, player); AddResponseToPage("PlayerDetailsPage", "Toggle: Can Adjust PUBLIC Permissions", true, player); }
private void LoadTaskListPage() { var player = GetPC(); var model = GetDialogCustomData <Model>(); string header = "These are our currently available tasks. Please check back periodically because our needs are always changing."; SetPageHeader("TaskListPage", header); ClearPageResponses("TaskListPage"); var lastUpdate = DataService.ServerConfiguration.Get().LastGuildTaskUpdate; var pcGP = DataService.PCGuildPoint.GetByPlayerIDAndGuildID(player.GlobalID, (int)model.Guild); // It's possible for players to have tasks which are no longer offered. // In this case, we still display them on the menu. Once they complete them, they'll disappear from the list. var questIDs = DataService.PCQuestStatus .GetAllByPlayerID(player.GlobalID) .Where(x => x.CompletionDate == null) .Select(s => s.QuestID); var expiredTasks = DataService.GuildTask .GetAll() .Where(x => !x.IsCurrentlyOffered && questIDs.Contains(x.QuestID) && x.GuildID == (int)model.Guild) .OrderByDescending(o => o.RequiredRank); foreach (var task in expiredTasks) { var quest = DataService.Quest.GetByID(task.QuestID); string status = ColorTokenService.Green("{ACCEPTED}"); AddResponseToPage("TaskListPage", quest.Name + " [Rank " + (task.RequiredRank + 1) + "] " + status + ColorTokenService.Red(" [EXPIRED]"), true, task.ID); } // Pull back all currently available tasks. This list rotates after 24 hours and a reboot occurs. var tasks = DataService.GuildTask .GetAllByCurrentlyOffered() .Where(x => x.GuildID == (int)model.Guild && x.RequiredRank <= pcGP.Rank) .OrderByDescending(o => o.RequiredRank); foreach (var task in tasks) { var quest = DataService.Quest.GetByID(task.QuestID); var questStatus = DataService.PCQuestStatus.GetByPlayerAndQuestIDOrDefault(player.GlobalID, task.QuestID); // If the player has completed the task during this task cycle, it will be excluded from this list. // The reason for this is to prevent players from repeating the same tasks over and over without impunity. if (questStatus != null && questStatus.CompletionDate >= lastUpdate) { continue; } string status = ColorTokenService.Green("{ACCEPTED}"); // Player has never accepted the quest, or they've already completed it at least once and can accept it again. if (questStatus == null || questStatus.CompletionDate != null) { status = ColorTokenService.Yellow("{Available}"); } AddResponseToPage("TaskListPage", quest.Name + " [Rank " + (task.RequiredRank + 1) + "] " + status, true, task.ID); } }
public void Main() { NWPlaceable container = NWGameObject.OBJECT_SELF; NWObject owner = container.GetLocalObject("QUEST_OWNER"); NWPlayer player = _.GetLastDisturbed(); NWItem item = _.GetInventoryDisturbItem(); int disturbType = _.GetInventoryDisturbType(); string crafterPlayerID = item.GetLocalString("CRAFTER_PLAYER_ID"); Guid? crafterPlayerGUID = null; if (!string.IsNullOrWhiteSpace(crafterPlayerID)) { crafterPlayerGUID = new Guid(crafterPlayerID); } if (disturbType == _.INVENTORY_DISTURB_TYPE_ADDED) { int questID = container.GetLocalInt("QUEST_ID"); PCQuestStatus status = DataService.PCQuestStatus.GetByPlayerAndQuestID(player.GlobalID, questID); PCQuestItemProgress progress = DataService.PCQuestItemProgress.GetByPCQuestStatusIDAndResrefOrDefault(status.ID, item.Resref); DatabaseActionType action = DatabaseActionType.Update; if (progress == null) { _.CopyItem(item, player, _.TRUE); player.SendMessage(ColorTokenService.Red("That item is not required for this quest.")); } else if (progress.MustBeCraftedByPlayer && crafterPlayerGUID != player.GlobalID) { _.CopyItem(item, player, _.TRUE); player.SendMessage(ColorTokenService.Red("You may only submit items which you have personally created for this quest.")); } else { progress.Remaining--; if (progress.Remaining <= 0) { var progressCopy = progress; progress = DataService.PCQuestItemProgress.GetByID(progressCopy.ID); action = DatabaseActionType.Delete; } DataService.SubmitDataChange(progress, action); // Recalc the remaining items needed. int remainingCount = DataService.PCQuestItemProgress.GetCountByPCQuestStatusID(status.ID); if (remainingCount <= 0) { QuestService.AdvanceQuestState(player, owner, questID); } player.SendMessage("You need " + progress.Remaining + "x " + item.Name + " for this quest."); } item.Destroy(); var questItemProgresses = DataService.PCQuestItemProgress.GetAllByPCQuestStatusID(status.ID); if (!questItemProgresses.Any()) { string conversation = _.GetLocalString(owner, "CONVERSATION"); // Either start a SWLOR conversation if (!string.IsNullOrWhiteSpace(conversation)) { DialogService.StartConversation(player, owner, conversation); } // Or a regular NWN conversation. else { player.AssignCommand(() => { _.ActionStartConversation(owner, "", _.TRUE, _.FALSE); }); } } } }
private void BuildPublicPermissionsPage() { ClearPageResponses("PublicPermissionsPage"); var data = BaseService.GetPlayerTempData(GetPC()); var permission = DataService.SingleOrDefault <PCBaseStructurePermission>(x => x.PCBaseStructureID == data.StructureID && x.IsPublicPermission); // Intentionally excluded permissions: // CanAdjustPermissions, CanCancelLease, CanPlaceEditStructures, CanAccessStructureInventory, CanAdjustPermissions, // CanRetrieveStructures, CanRenameStructures, CanEditPrimaryResidence, CanRemovePrimaryResidence, CanChangeStructureMode, // CanAdjustPublicPermissions bool canEnterBuilding = permission?.CanEnterBuilding ?? false; string header = ColorTokenService.Green("Public Permissions: ") + "\n\n"; header += "Can Enter Building: " + (canEnterBuilding ? ColorTokenService.Green("YES") : ColorTokenService.Red("NO")) + "\n"; SetPageHeader("PublicPermissionsPage", header); AddResponseToPage("PublicPermissionsPage", "Toggle: Can Enter Building"); }
private void LoadSalvagePage() { var player = GetPC(); var model = CraftService.GetPlayerCraftingData(player); NWPlaceable tempStorage = _.GetObjectByTag("TEMP_ITEM_STORAGE"); var item = SerializationService.DeserializeItem(model.SerializedSalvageItem, tempStorage); var componentType = DataService.Get <ComponentType>(model.SalvageComponentTypeID); string header = ColorTokenService.Green("Item: ") + item.Name + "\n\n"; header += "Reassembling this item will create the following " + ColorTokenService.Green(componentType.Name) + " component(s). Chance to create depends on your perks, skills, and harvesting bonus on items.\n\n"; // Always create one item with zero bonuses. header += componentType.Name + " (No Bonuses) [RL: 0] " + GetChanceColor(100) + "\n"; // Start by checking attack bonus since we're not storing this value as a local variable on the item. foreach (var prop in item.ItemProperties) { int propTypeID = _.GetItemPropertyType(prop); if (propTypeID == ITEM_PROPERTY_ATTACK_BONUS) { // Get the amount of Attack Bonus int amount = _.GetItemPropertyCostTableValue(prop); header += ProcessPropertyDetails(amount, componentType.Name, "Attack Bonus", 3); } } // Now check specific custom properties which are stored as local variables on the item. header += ProcessPropertyDetails(item.HarvestingBonus, componentType.Name, "Harvesting Bonus", 3); header += ProcessPropertyDetails(item.PilotingBonus, componentType.Name, "Piloting Bonus", 3); header += ProcessPropertyDetails(item.ScanningBonus, componentType.Name, "Scanning Bonus", 3); header += ProcessPropertyDetails(item.ScavengingBonus, componentType.Name, "Scavenging Bonus", 3); header += ProcessPropertyDetails(item.CooldownRecovery, componentType.Name, "Cooldown Recovery", 3); header += ProcessPropertyDetails(item.CraftBonusArmorsmith, componentType.Name, "Armorsmith", 3); header += ProcessPropertyDetails(item.CraftBonusWeaponsmith, componentType.Name, "Weaponsmith", 3); header += ProcessPropertyDetails(item.CraftBonusCooking, componentType.Name, "Cooking", 3); header += ProcessPropertyDetails(item.CraftBonusEngineering, componentType.Name, "Engineering", 3); header += ProcessPropertyDetails(item.CraftBonusFabrication, componentType.Name, "Fabrication", 3); header += ProcessPropertyDetails(item.HPBonus, componentType.Name, "HP", 5, 0.5f); header += ProcessPropertyDetails(item.FPBonus, componentType.Name, "FP", 5, 0.5f); header += ProcessPropertyDetails(item.EnmityRate, componentType.Name, "Enmity", 3); header += ProcessPropertyDetails(item.LuckBonus, componentType.Name, "Luck", 3); header += ProcessPropertyDetails(item.MeditateBonus, componentType.Name, "Meditate", 3); header += ProcessPropertyDetails(item.RestBonus, componentType.Name, "Rest", 3); header += ProcessPropertyDetails(item.MedicineBonus, componentType.Name, "Medicine", 3); header += ProcessPropertyDetails(item.HPRegenBonus, componentType.Name, "HP Regen", 3); header += ProcessPropertyDetails(item.FPRegenBonus, componentType.Name, "FP Regen", 3); header += ProcessPropertyDetails(item.StructureBonus, componentType.Name, "Structure Bonus", 3); header += ProcessPropertyDetails(item.SneakAttackBonus, componentType.Name, "Sneak Attack", 3); header += ProcessPropertyDetails(item.DamageBonus, componentType.Name, "Damage", 3); header += ProcessPropertyDetails(item.StrengthBonus, componentType.Name, "STR", 3); header += ProcessPropertyDetails(item.DexterityBonus, componentType.Name, "DEX", 3); header += ProcessPropertyDetails(item.ConstitutionBonus, componentType.Name, "CON", 3); header += ProcessPropertyDetails(item.WisdomBonus, componentType.Name, "WIS", 3); header += ProcessPropertyDetails(item.IntelligenceBonus, componentType.Name, "INT", 3); header += ProcessPropertyDetails(item.CharismaBonus, componentType.Name, "CHA", 3); header += ProcessPropertyDetails(item.DurationBonus, componentType.Name, "Duration", 3); SetPageHeader("SalvagePage", header); // Remove the temporary copy from the game world. item.Destroy(); }
public void ColorTokenService_NullText_ShouldThrowArgumentException() { ColorTokenService service = new ColorTokenService(); Assert.Throws(typeof(ArgumentException), () => { service.Black(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Blue(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Gray(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Green(null); }); Assert.Throws(typeof(ArgumentException), () => { service.LightPurple(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Orange(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Pink(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Purple(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Red(null); }); Assert.Throws(typeof(ArgumentException), () => { service.White(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Yellow(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Cyan(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Combat(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Dialog(null); }); Assert.Throws(typeof(ArgumentException), () => { service.DialogAction(null); }); Assert.Throws(typeof(ArgumentException), () => { service.DialogCheck(null); }); Assert.Throws(typeof(ArgumentException), () => { service.DialogHighlight(null); }); Assert.Throws(typeof(ArgumentException), () => { service.DialogReply(null); }); Assert.Throws(typeof(ArgumentException), () => { service.DM(null); }); Assert.Throws(typeof(ArgumentException), () => { service.GameEngine(null); }); Assert.Throws(typeof(ArgumentException), () => { service.SavingThrow(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Script(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Server(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Shout(null); }); Assert.Throws(typeof(ArgumentException), () => { service.SkillCheck(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Talk(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Tell(null); }); Assert.Throws(typeof(ArgumentException), () => { service.Whisper(null); }); }
public void ApplyEffects(NWCreature user, NWItem modItem, NWObject target, Location targetLocation, CustomData customData) { NWPlayer player = (user.Object); NWItem targetItem = (target.Object); ModSlots slots = ModService.GetModSlots(targetItem); CustomItemPropertyType modType = ModService.GetModType(modItem); int modID = modItem.GetLocalInt("RUNE_ID"); string[] modArgs = modItem.GetLocalString("RUNE_VALUE").Split(','); int modLevel = modItem.RecommendedLevel; int levelIncrease = modItem.LevelIncrease; var mod = ModService.GetModHandler(modID); mod.Apply(player, targetItem, modArgs); string description = mod.Description(player, targetItem, modArgs); bool usePrismatic = false; switch (modType) { case CustomItemPropertyType.RedMod: if (slots.FilledRedSlots < slots.RedSlots) { targetItem.SetLocalInt("MOD_SLOT_RED_" + (slots.FilledRedSlots + 1), modID); targetItem.SetLocalString("MOD_SLOT_RED_DESC_" + (slots.FilledRedSlots + 1), description); player.SendMessage("Mod installed into " + ColorTokenService.Red("red") + " slot #" + (slots.FilledRedSlots + 1)); } else { usePrismatic = true; } break; case CustomItemPropertyType.BlueMod: if (slots.FilledBlueSlots < slots.BlueSlots) { targetItem.SetLocalInt("MOD_SLOT_BLUE_" + (slots.FilledBlueSlots + 1), modID); targetItem.SetLocalString("MOD_SLOT_BLUE_DESC_" + (slots.FilledBlueSlots + 1), description); player.SendMessage("Mod installed into " + ColorTokenService.Blue("blue") + " slot #" + (slots.FilledBlueSlots + 1)); } else { usePrismatic = true; } break; case CustomItemPropertyType.GreenMod: if (slots.FilledBlueSlots < slots.GreenSlots) { targetItem.SetLocalInt("MOD_SLOT_GREEN_" + (slots.FilledGreenSlots + 1), modID); targetItem.SetLocalString("MOD_SLOT_GREEN_DESC_" + (slots.FilledGreenSlots + 1), description); player.SendMessage("Mod installed into " + ColorTokenService.Green("green") + " slot #" + (slots.FilledGreenSlots + 1)); } else { usePrismatic = true; } break; case CustomItemPropertyType.YellowMod: if (slots.FilledBlueSlots < slots.YellowSlots) { targetItem.SetLocalInt("MOD_SLOT_YELLOW_" + (slots.FilledYellowSlots + 1), modID); targetItem.SetLocalString("MOD_SLOT_YELLOW_DESC_" + (slots.FilledYellowSlots + 1), description); player.SendMessage("Mod installed into " + ColorTokenService.Yellow("yellow") + " slot #" + (slots.FilledYellowSlots + 1)); } else { usePrismatic = true; } break; } if (usePrismatic) { string prismaticText = ModService.PrismaticString(); targetItem.SetLocalInt("MOD_SLOT_PRISMATIC_" + (slots.FilledPrismaticSlots + 1), modID); targetItem.SetLocalString("MOD_SLOT_PRISMATIC_DESC_" + (slots.FilledPrismaticSlots + 1), description); player.SendMessage("Mod installed into " + prismaticText + " slot #" + (slots.FilledPrismaticSlots + 1)); } targetItem.RecommendedLevel += levelIncrease; modItem.Destroy(); SkillType skillType; if (ArmorBaseItemTypes.Contains(targetItem.BaseItemType)) { skillType = SkillType.Armorsmith; } else if (WeaponsmithBaseItemTypes.Contains(targetItem.BaseItemType)) { skillType = SkillType.Weaponsmith; } else if (EngineeringBaseItemTypes.Contains(targetItem.BaseItemType)) { skillType = SkillType.Engineering; } else { return; } int rank = SkillService.GetPCSkillRank(player, skillType); int xp = (int)SkillService.CalculateRegisteredSkillLevelAdjustedXP(400, modLevel, rank); SkillService.GiveSkillXP(player, skillType, xp); }
private void LoadSellItemPage() { var player = GetPC(); var model = MarketService.GetPlayerMarketData(player); string header; // A null or empty item object signifies that an item hasn't been selected for selling yet. // Hide all options except for "Pick Item" if (string.IsNullOrWhiteSpace(model.ItemObject)) { int numberItemsSelling = DataService .PCMarketListing .GetAllBySellerPlayerID(player.GlobalID) .Count(x => x.DateRemoved == null && x.DateSold == null); bool canSellAnotherItem = numberItemsSelling < MarketService.NumberOfItemsAllowedToBeSoldAtATime; header = ColorTokenService.Green("Galactic Trade Network - Sell Item") + "\n\n"; header += ColorTokenService.Green("Items Selling: ") + numberItemsSelling + " / " + MarketService.NumberOfItemsAllowedToBeSoldAtATime + "\n\n"; if (canSellAnotherItem) { header += "Please select an item to sell."; } else { header += "You cannot sell any more items at this time."; } SetResponseVisible("SellItemPage", 1, false); // Refresh SetResponseVisible("SellItemPage", 2, canSellAnotherItem); // Pick Item SetResponseVisible("SellItemPage", 3, false); // Change Price SetResponseVisible("SellItemPage", 4, false); // Change Seller Note SetResponseVisible("SellItemPage", 5, false); // Remove Seller Note SetResponseVisible("SellItemPage", 6, false); // Change Listing Length SetResponseVisible("SellItemPage", 7, false); // List the Item } // Otherwise an item has already been picked. else { MarketCategory category = DataService.MarketCategory.GetByID(model.ItemMarketCategoryID); float feeRate = MarketService.CalculateFeePercentage(model.LengthDays); int fees = (int)(model.SellPrice * feeRate); if (fees < 1) { fees = 1; } bool canListItem = model.SellPrice > 0; string sellerNote = model.SellerNote; if (string.IsNullOrWhiteSpace(sellerNote)) { sellerNote = "[NOT SPECIFIED]"; } header = ColorTokenService.Green("Galactic Trade Network - Sell Item") + "\n\n"; header += ColorTokenService.Green("Item: ") + model.ItemStackSize + "x " + model.ItemName + "\n"; header += ColorTokenService.Green("Category: ") + category.Name + "\n"; if (model.ItemRecommendedLevel > 0) { header += ColorTokenService.Green("Recommended Level: ") + model.ItemRecommendedLevel + "\n"; } header += ColorTokenService.Green("Sell Price: ") + model.SellPrice + " credits\n"; header += ColorTokenService.Green("Fees: ") + fees + " credits\n"; header += ColorTokenService.Green("Listing Length: ") + model.LengthDays + " days\n"; header += ColorTokenService.Green("Seller Note: ") + sellerNote + "\n\n"; if (canListItem) { header += ColorTokenService.Green("This item can be listed now."); } else { header += ColorTokenService.Red("This item cannot be listed yet. Please confirm all details - such as pricing - have been set."); } SetResponseVisible("SellItemPage", 1, true); // Refresh SetResponseVisible("SellItemPage", 2, false); // Pick Item SetResponseVisible("SellItemPage", 3, true); // Change Price SetResponseVisible("SellItemPage", 4, true); // Change Seller Note SetResponseVisible("SellItemPage", 5, true); // Remove Seller Note SetResponseVisible("SellItemPage", 6, true); // Change Listing Length SetResponseVisible("SellItemPage", 7, canListItem); // List the Item } SetPageHeader("SellItemPage", header); }
public void Main() { NWPlaceable terminal = OBJECT_SELF; int bankID = terminal.GetLocalInt("BANK_ID"); if (bankID <= 0) { return; } NWPlayer player = GetLastDisturbed(); NWItem item = GetInventoryDisturbItem(); var disturbType = GetInventoryDisturbType(); int itemCount = terminal.InventoryItems.Count(); int itemLimit = terminal.GetLocalInt("BANK_LIMIT"); if (itemLimit <= 0) { itemLimit = 20; } if (disturbType == DisturbType.Added) { if (GetHasInventory(item) == true) { SetLocalBool(item, "RETURNING_ITEM", true); ItemService.ReturnItem(player, item); player.SendMessage(ColorTokenService.Red("Containers cannot currently be stored inside banks.")); return; } if (itemCount > itemLimit) { ItemService.ReturnItem(player, item); player.SendMessage(ColorTokenService.Red("No more items can be placed inside.")); } else { BankItem itemEntity = new BankItem { ItemName = item.Name, ItemTag = item.Tag, ItemResref = item.Resref, ItemID = item.GlobalID.ToString(), ItemObject = SerializationService.Serialize(item), BankID = bankID, PlayerID = player.GlobalID, DateStored = DateTime.UtcNow }; DataService.SubmitDataChange(itemEntity, DatabaseActionType.Insert); MessageHub.Instance.Publish(new OnStoreBankItem(player, itemEntity)); } } else if (disturbType == DisturbType.Removed) { if (GetLocalBool(item, "RETURNING_ITEM") == true) { item.DeleteLocalInt("RETURNING_ITEM"); } else { var record = DataService.BankItem.GetByItemID(item.GlobalID.ToString()); DataService.SubmitDataChange(record, DatabaseActionType.Delete); MessageHub.Instance.Publish(new OnRemoveBankItem(player, record)); } } player.SendMessage(ColorTokenService.White("Item Limit: " + (itemCount > itemLimit ? itemLimit : itemCount) + " / ") + ColorTokenService.Red("" + itemLimit)); }
private void LoadMainPage() { var data = BaseService.GetPlayerTempData(GetPC()); BaseStructure structure = DataService.BaseStructure.GetByID(data.BaseStructureID); var tower = BaseService.GetBaseControlTower(data.PCBaseID); var towerBaseStructure = tower == null ? null : DataService.BaseStructure.GetByID(tower.BaseStructureID); bool canPlaceStructure = true; bool isPlacingTower = structure.BaseStructureTypeID == (int)BaseStructureType.ControlTower; bool isPlacingBuilding = structure.BaseStructureTypeID == (int)BaseStructureType.Building; bool canChangeBuildingStyles = isPlacingBuilding && data.StructureItem.GetLocalInt("STRUCTURE_BUILDING_INITIALIZED") == FALSE; double powerInUse = BaseService.GetPowerInUse(data.PCBaseID); double cpuInUse = BaseService.GetCPUInUse(data.PCBaseID); double towerPower = tower != null ? towerBaseStructure.Power + (tower.StructureBonus * 3) : 0.0f; double towerCPU = tower != null ? towerBaseStructure.CPU + (tower.StructureBonus * 2) : 0.0f; double newPower = powerInUse + structure.Power; double newCPU = cpuInUse + structure.CPU; string insufficientPower = newPower > towerPower && !isPlacingTower?ColorTokenService.Red(" (INSUFFICIENT POWER)") : string.Empty; string insufficientCPU = newCPU > towerCPU && !isPlacingTower?ColorTokenService.Red(" (INSUFFICIENT CPU)") : string.Empty; string header = ColorTokenService.Green("Structure: ") + structure.Name + "\n"; if (data.BuildingType == BuildingType.Interior) { var buildingStructure = DataService.PCBaseStructure.GetByID((Guid)data.ParentStructureID); var baseStructure = DataService.BaseStructure.GetByID(buildingStructure.BaseStructureID); var childStructures = DataService.PCBaseStructure.GetAllByParentPCBaseStructureID(buildingStructure.ID).ToList(); header += ColorTokenService.Green("Structure Limit: ") + childStructures.Count + " / " + (baseStructure.Storage + buildingStructure.StructureBonus) + "\n"; var structures = DataService.PCBaseStructure .GetAllByParentPCBaseStructureID(buildingStructure.ID).Where(x => { var childStructure = DataService.BaseStructure.GetByID(x.BaseStructureID); return(childStructure.HasAtmosphere); }); // Add up the total atmosphere rating, being careful not to go over the cap. int bonus = structures.Sum(x => 1 + x.StructureBonus) * 2; if (bonus > 150) { bonus = 150; } header += ColorTokenService.Green("Atmosphere Bonus: ") + bonus + "% / " + "150%"; header += "\n"; } else if (data.BuildingType == BuildingType.Starship) { var buildingStructure = DataService.PCBaseStructure.GetByID((Guid)data.ParentStructureID); var buildingStyle = DataService.BuildingStyle.GetByID(Convert.ToInt32(buildingStructure.InteriorStyleID)); var childStructures = DataService.PCBaseStructure.GetAllByParentPCBaseStructureID(buildingStructure.ID).ToList(); header += ColorTokenService.Green("Structure Limit: ") + childStructures.Count + " / " + (buildingStyle.FurnitureLimit + buildingStructure.StructureBonus) + "\n"; var structures = DataService.PCBaseStructure .GetAllByParentPCBaseStructureID(buildingStructure.ID).Where(x => { var childStructure = DataService.BaseStructure.GetByID(x.BaseStructureID); return(childStructure.HasAtmosphere); }); // Add up the total atmosphere rating, being careful not to go over the cap. int bonus = structures.Sum(x => 1 + x.StructureBonus) * 2; if (bonus > 150) { bonus = 150; } header += ColorTokenService.Green("Atmosphere Bonus: ") + bonus + "% / " + "150%"; header += "\n"; } else if (data.BuildingType == BuildingType.Apartment) { var pcBase = DataService.PCBase.GetByID(data.PCBaseID); var buildingStyle = DataService.BuildingStyle.GetByID(Convert.ToInt32(pcBase.BuildingStyleID)); var structures = DataService.PCBaseStructure.GetAllByPCBaseID(pcBase.ID).ToList(); header += ColorTokenService.Green("Structure Limit: ") + structures.Count + " / " + buildingStyle.FurnitureLimit + "\n"; int bonus = structures.Sum(x => 1 + x.StructureBonus) * 2; if (bonus > 150) { bonus = 150; } header += ColorTokenService.Green("Atmosphere Bonus: ") + bonus + "% / " + "150%"; header += "\n"; } else if (data.BuildingType == BuildingType.Exterior) { if (isPlacingTower) { header += ColorTokenService.Green("Available Power: ") + (structure.Power + data.StructureItem.StructureBonus * 3) + "\n"; header += ColorTokenService.Green("Available CPU: ") + (structure.CPU + data.StructureItem.StructureBonus * 2) + "\n"; } else { header += ColorTokenService.Green("Base Power: ") + powerInUse + " / " + towerPower + "\n"; header += ColorTokenService.Green("Base CPU: ") + cpuInUse + " / " + towerCPU + "\n"; header += ColorTokenService.Green("Required Power: ") + structure.Power + insufficientPower + "\n"; header += ColorTokenService.Green("Required CPU: ") + structure.CPU + insufficientCPU + "\n"; } } if (isPlacingBuilding) { int exteriorStyle = data.StructureItem.GetLocalInt("STRUCTURE_BUILDING_EXTERIOR_ID"); int interiorStyle = data.StructureItem.GetLocalInt("STRUCTURE_BUILDING_INTERIOR_ID"); var exterior = DataService.BuildingStyle.GetByID(exteriorStyle); var interior = DataService.BuildingStyle.GetByID(interiorStyle); header += ColorTokenService.Green("Exterior Style: ") + exterior.Name + "\n"; header += ColorTokenService.Green("Interior Style: ") + interior.Name + "\n"; } if (!isPlacingTower && (newPower > towerPower || newCPU > towerCPU)) { canPlaceStructure = false; header += "\nOne or more requirements not met. Cannot place structure."; } SetPageHeader("MainPage", header); SetResponseVisible("MainPage", 1, canPlaceStructure); SetResponseVisible("MainPage", 2, canPlaceStructure); SetResponseVisible("MainPage", 3, canPlaceStructure); SetResponseVisible("MainPage", 4, canPlaceStructure && canChangeBuildingStyles); SetResponseVisible("MainPage", 5, canPlaceStructure && canChangeBuildingStyles); }
private string BuildMainPageHeader(NWPlayer player) { Player playerEntity = DataService.Single <Player>(x => x.ID == player.GlobalID); var association = DataService.Get <Association>(playerEntity.AssociationID); int totalSkillCount = DataService.Where <PCSkill>(x => { var skill = DataService.Get <Skill>(x.SkillID); return(x.PlayerID == player.GlobalID && skill.ContributesToSkillCap); }).Sum(s => s.Rank); string header = ColorTokenService.Green("Name: ") + player.Name + "\n"; header += ColorTokenService.Green("Association: ") + association.Name + "\n\n"; header += ColorTokenService.Green("Skill Points: ") + totalSkillCount + " / " + SkillService.SkillCap + "\n"; header += ColorTokenService.Green("Unallocated SP: ") + playerEntity.UnallocatedSP + "\n"; header += ColorTokenService.Green("Roleplay XP: ") + playerEntity.RoleplayXP + "\n"; header += ColorTokenService.Green("FP: ") + (playerEntity.MaxFP > 0 ? MenuService.BuildBar(playerEntity.CurrentFP, playerEntity.MaxFP, 100, ColorTokenService.TokenStart(32, 223, 219)) : "N/A") + "\n"; return(header); }
private int ProcessProperty(int amount, int maxBonuses, ComponentBonusType bonus, float levelsPerBonus = 1.0f) { string resref = _componentType.ReassembledResref; int penalty = 0; int luck = PerkService.GetPCPerkLevel(_player, PerkType.Lucky) + (_playerItemStats.Luck / 3); int xp = 0; ItemPropertyUnpacked bonusIP = new ItemPropertyUnpacked { Property = (int)CustomItemPropertyType.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 Main() { NWPlaceable point = (_.OBJECT_SELF); NWPlayer oPC = (_.GetLastOpenedBy()); if (!oPC.IsPlayer) { return; } var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(oPC); const int baseChanceToFullyHarvest = 50; bool hasBeenSearched = point.GetLocalInt("SCAVENGE_POINT_FULLY_HARVESTED") == 1; if (hasBeenSearched) { oPC.SendMessage("There's nothing left to harvest here..."); return; } if (!oPC.IsPlayer && !oPC.IsDM) { return; } int rank = SkillService.GetPCSkillRank(oPC, SkillType.Scavenging); int lootTableID = point.GetLocalInt("SCAVENGE_POINT_LOOT_TABLE_ID"); int level = point.GetLocalInt("SCAVENGE_POINT_LEVEL"); int delta = level - rank; if (delta > 8) { oPC.SendMessage("You aren't skilled enough to scavenge through this. (Required Level: " + (level - 8) + ")"); oPC.AssignCommand(() => _.ActionInteractObject(point.Object)); return; } int dc = 6 + delta; if (dc <= 4) { dc = 4; } int searchAttempts = 1 + CalculateSearchAttempts(oPC); int luck = PerkService.GetCreaturePerkLevel(oPC, PerkType.Lucky) + effectiveStats.Luck; if (RandomService.Random(100) + 1 <= luck / 2) { dc--; } oPC.AssignCommand(() => _.ActionPlayAnimation(Animation.LoopingGetLow, 1.0f, 2.0f)); for (int attempt = 1; attempt <= searchAttempts; attempt++) { int roll = RandomService.Random(20) + 1; if (roll >= dc) { oPC.FloatingText(ColorTokenService.SkillCheck("Search: *success*: (" + roll + " vs. DC: " + dc + ")")); ItemVO spawnItem = LootService.PickRandomItemFromLootTable(lootTableID); if (spawnItem == null) { return; } if (!string.IsNullOrWhiteSpace(spawnItem.Resref) && spawnItem.Quantity > 0) { _.CreateItemOnObject(spawnItem.Resref, point.Object, spawnItem.Quantity); } float xp = SkillService.CalculateRegisteredSkillLevelAdjustedXP(200, level, rank); SkillService.GiveSkillXP(oPC, SkillType.Scavenging, (int)xp); } else { oPC.FloatingText(ColorTokenService.SkillCheck("Search: *failure*: (" + roll + " vs. DC: " + dc + ")")); float xp = SkillService.CalculateRegisteredSkillLevelAdjustedXP(50, level, rank); SkillService.GiveSkillXP(oPC, SkillType.Scavenging, (int)xp); } dc += RandomService.Random(3) + 1; } // Chance to destroy the scavenge point. int chanceToFullyHarvest = baseChanceToFullyHarvest - (PerkService.GetCreaturePerkLevel(oPC, PerkType.CarefulScavenger) * 5); if (chanceToFullyHarvest <= 5) { chanceToFullyHarvest = 5; } point.SetLocalInt("SCAVENGE_POINT_FULLY_HARVESTED", 1); oPC.SendMessage("This resource has been fully harvested..."); point.SetLocalInt("SCAVENGE_POINT_DESPAWN_TICKS", 30); }