ModernUO/Projects/UOContent/Engines/Bounties/BountyBoard.cs

178 lines
6.5 KiB
C#

using System;
using ModernUO.Serialization;
using Server.Engines.Bounties;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Network;
namespace Server.Items;
[SerializationGenerator(0, false)]
[Flippable(0x1E5E, 0x1E5F)]
public partial class DungeonBountyBoard : Item
{
[Constructible]
public DungeonBountyBoard() : base(0x1E5E)
{
Name = "Dungeon Bounty Board";
Movable = false;
}
public override void OnDoubleClick(Mobile from)
{
if (from is PlayerMobile pm)
{
if (from.InRange(Location, 3))
pm.SendGump(new BountyBoardGump(pm));
else
from.SendLocalizedMessage(500446);
}
}
}
public class BountyBoardGump : Gump
{
private readonly PlayerMobile _player;
public BountyBoardGump(PlayerMobile player) : base(50, 50)
{
_player = player;
BountyProfile profile = BountySystem.GetProfile(player);
AddPage(0);
AddBackground(0, 0, 550, 480, 9270);
AddAlphaRegion(10, 10, 530, 460);
AddLabel(180, 15, 1152, "DUNGEON BOUNTY BOARD");
// --- ACTIVE BOUNTY SECTION ---
AddLabel(20, 50, 0x3F, "--- Your Active Bounty ---");
if (profile.HasActiveBounty && BountyRegistry.AllBounties.TryGetValue(profile.ActiveBountyID, out var activeBounty))
{
AddLabel(20, 75, 1152, activeBounty.Title);
AddLabel(350, 75, 2100, $"{profile.CurrentKills} / {activeBounty.RequiredKills} Slain");
if (profile.CurrentKills >= activeBounty.RequiredKills)
{
AddButton(20, 100, 4005, 4007, 1000, GumpButtonType.Reply, 0);
AddLabel(55, 100, 0x44, "CLAIM REWARD");
}
else
{
int penaltyCost = activeBounty.RewardGold; // Cancellation costs the reward amount
AddButton(20, 100, 4017, 4019, 1001, GumpButtonType.Reply, 0);
AddLabel(55, 100, 33, $"Refuse Bounty (Cost: {penaltyCost} Gold)");
}
}
else
{
AddLabel(20, 75, 1152, "You have no active bounties.");
}
// --- AVAILABLE BOUNTIES SECTION ---
AddLabel(20, 150, 0x3F, "--- Available Bounties ---");
if (profile.IsOnCooldown)
{
TimeSpan wait = profile.NextAvailableTime - DateTime.UtcNow;
AddLabel(20, 180, 33, $"The board is empty. Next bounties arrive in {(int)wait.TotalMinutes} minutes.");
}
else
{
AddLabel(20, 170, 2100, $"Your Current Fame: {player.Fame}");
int y = 200;
for (int tier = 1; tier <= 5; tier++)
{
// Grab an example from the tier to check fame requirements and rewards
var example = BountyRegistry.GetRandomBounty(tier);
if (example == null) continue;
if (player.Fame >= example.RequiredFame)
{
if (!profile.HasActiveBounty)
{
// Assigning Button IDs 101 to 105 for Tiers 1-5
AddButton(20, y, 4005, 4007, 100 + tier, GumpButtonType.Reply, 0);
}
AddLabel(55, y, 1152, $"Request Tier {tier} Bounty");
AddLabel(320, y, 0x3F, $"Earn {example.RewardTokens} Tokens");
}
else
{
AddLabel(55, y, 33, $"Tier {tier} Bounty (Requires {example.RequiredFame} Fame)");
}
y += 35;
}
}
AddButton(20, 440, 4017, 4019, 0, GumpButtonType.Reply, 0);
AddLabel(55, 440, 1152, "Close Board");
}
public override void OnResponse(NetState sender, in RelayInfo info)
{
if (info.ButtonID == 0) return;
BountyProfile profile = BountySystem.GetProfile(_player);
if (info.ButtonID == 1000) // CLAIM REWARD
{
if (profile.HasActiveBounty && BountyRegistry.AllBounties.TryGetValue(profile.ActiveBountyID, out var activeBounty))
{
if (profile.CurrentKills >= activeBounty.RequiredKills)
{
_player.AddToBackpack(new BountyToken(activeBounty.RewardTokens));
_player.AddToBackpack(new Gold(activeBounty.RewardGold));
_player.SendMessage(0x44, $"Complete! Received {activeBounty.RewardTokens} Tokens and {activeBounty.RewardGold} Gold.");
_player.PlaySound(0x2E6);
// Reset Profile and trigger the 60 minute cooldown
profile.ActiveBountyID = -1;
profile.CurrentKills = 0;
profile.NextAvailableTime = DateTime.UtcNow + TimeSpan.FromMinutes(ValidSettings.BountyBoardDelay());
}
}
}
else if (info.ButtonID == 1001) // CANCEL BOUNTY (Refusal Fee)
{
if (BountyRegistry.AllBounties.TryGetValue(profile.ActiveBountyID, out var activeBounty))
{
int cost = activeBounty.RewardGold;
// Attempt to consume gold from their backpack
if (_player.Backpack != null && _player.Backpack.ConsumeTotal(typeof(Gold), cost))
{
profile.ActiveBountyID = -1;
profile.CurrentKills = 0;
profile.NextAvailableTime = DateTime.UtcNow + TimeSpan.FromMinutes(ValidSettings.BountyBoardDelay());
_player.SendMessage(33, $"You paid the {cost} gold refusal fee and abandoned the bounty.");
}
else
{
_player.SendMessage(33, $"You need {cost} gold in your backpack to refuse this bounty!");
}
}
}
else if (info.ButtonID > 100 && info.ButtonID <= 105) // ACCEPT RANDOM BOUNTY BY TIER
{
int selectedTier = info.ButtonID - 100;
if (!profile.HasActiveBounty && !profile.IsOnCooldown)
{
var newBounty = BountyRegistry.GetRandomBounty(selectedTier);
if (newBounty != null && _player.Fame >= newBounty.RequiredFame)
{
profile.ActiveBountyID = newBounty.ID;
profile.CurrentKills = 0;
_player.SendMessage(0x3F, $"You have been assigned: {newBounty.Title}");
_player.PlaySound(0x04A);
}
}
}
_player.SendGump(new BountyBoardGump(_player));
}
}