Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bounty Contracts updates #83

Merged
merged 8 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

<!-- New Contract Details -->
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
<BoxContainer Orientation="Horizontal" Margin="4,4,4,4">
<Label Text="{Loc 'bounty-contracts-ui-create-category'}" MinWidth="80"/>
<OptionButton Name="CategorySelector" HorizontalExpand="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal" Margin="4,4,4,4">
<Label Text="{Loc 'bounty-contracts-ui-create-name'}" MinWidth="80"/>
<OptionButton Name="NameSelector" HorizontalExpand="True"/>
Expand All @@ -13,7 +17,7 @@
<Button Name="CustomNameButton" Text="{Loc 'bounty-contracts-ui-create-custom'}"
ToggleMode="True"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" Margin="4,4,4,4">
<BoxContainer Name="DnaBox" Orientation="Horizontal" Margin="4,4,4,4">
<Label Text="{Loc 'bounty-contracts-ui-create-dna'}" MinWidth="80"/>
<Label Name="DnaLabel" Text="{Loc 'bounty-contracts-ui-create-dna-unknown'}"
HorizontalExpand="True"/>
Expand Down Expand Up @@ -41,7 +45,7 @@
<PanelContainer StyleClasses="LowDivider" />
</BoxContainer>
<RichTextLabel Name="DisclaimerLabel" Margin="4,4,4,4"
HorizontalExpand="True"/>
HorizontalExpand="True" Visible="False"/>
</BoxContainer>

<!-- Footer -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,23 @@ public sealed partial class BountyContractUiFragmentCreate : Control
public BountyContractUiFragmentCreate()
{
RobustXamlLoader.Load(this);
NameSelector.OnItemSelected += (opt) => OnNameSelected(opt.Id);
VeselSelector.OnItemSelected += (opt) => OnVesselSelected(opt.Id);
CategorySelector.OnItemSelected += opt => OnCategorySelected(opt.Id);
NameSelector.OnItemSelected += opt => OnNameSelected(opt.Id);
VeselSelector.OnItemSelected += opt => OnVesselSelected(opt.Id);

CustomNameButton.OnToggled += OnCustomNameToggle;
CustomVeselButton.OnToggled += OnCustomVeselToggle;
CustomNameButton.OnToggled += args => OnCustomNameToggle(args.Pressed);
CustomVeselButton.OnToggled += args => OnCustomVeselToggle(args.Pressed);
NameEdit.OnTextChanged += NameEditOnTextChanged;
RewardEdit.OnTextChanged += OnPriceChanged;

var descPlaceholder = Loc.GetString("bounty-contracts-ui-create-description-placeholder");
DescriptionEdit.Placeholder = new Rope.Leaf(descPlaceholder);
RewardEdit.Text = SharedBountyContractSystem.MinimalReward.ToString();
RewardEdit.Text = SharedBountyContractSystem.DefaultReward.ToString();

CreateButton.OnPressed += _ => OnCreatePressed?.Invoke(GetBountyContract());
CancelButton.OnPressed += _ => OnCancelPressed?.Invoke();

FillCategories();
UpdateDisclaimer();
}

Expand Down Expand Up @@ -84,9 +86,25 @@ public void SetVessels(List<string> vessels)
OnVesselSelected(0);
}

private void FillCategories()
{
foreach (var (id, meta) in SharedBountyContractSystem.CategoriesMeta)
{
var name = Loc.GetString(meta.Name);
CategorySelector.AddItem(name, (byte) id);
}
}

private void UpdateDna(string? dnaStr)
{
DnaLabel.Text = dnaStr ?? Loc.GetString("bounty-contracts-ui-create-dna-unknown");
if (string.IsNullOrEmpty(dnaStr))
{
DnaBox.Visible = false;
return;
}

DnaBox.Visible = true;
DnaLabel.Text = dnaStr;
}

private void OnNameSelected(int itemIndex)
Expand All @@ -112,19 +130,28 @@ private void OnVesselSelected(int itemIndex)
VeselSelector.SelectId(itemIndex);
}

private void OnCustomNameToggle(BaseButton.ButtonToggledEventArgs customToggle)
private void OnCategorySelected(int objId)
{
var cat = (BountyContractCategory) objId;
CustomNameButton.Pressed = cat != BountyContractCategory.Criminal;
OnCustomNameToggle(CustomNameButton.Pressed);

CategorySelector.SelectId(objId);
}

private void OnCustomNameToggle(bool isPressed)
{
NameSelector.Visible = !customToggle.Pressed;
NameEdit.Visible = customToggle.Pressed;
NameSelector.Visible = !isPressed;
NameEdit.Visible = isPressed;

UpdateDna(GetTargetDna());
UpdateDisclaimer();
}

private void OnCustomVeselToggle(BaseButton.ButtonToggledEventArgs customToggle)
private void OnCustomVeselToggle(bool isPressed)
{
VeselSelector.Visible = !customToggle.Pressed;
VeselEdit.Visible = customToggle.Pressed;
VeselSelector.Visible = !isPressed;
VeselEdit.Visible = isPressed;

OnVesselSelected(0);
}
Expand All @@ -133,10 +160,9 @@ private void UpdateDisclaimer()
{
// check if reward is valid
var reward = GetReward();
if (reward < SharedBountyContractSystem.MinimalReward)
if (reward == null || reward < 0)
{
var err = Loc.GetString("bounty-contracts-ui-create-error-too-cheap",
("reward", SharedBountyContractSystem.MinimalReward));
var err = Loc.GetString("bounty-contracts-ui-create-error-invalid-price");
DisclaimerLabel.SetMessage(err);
CreateButton.Disabled = true;
return;
Expand All @@ -157,10 +183,10 @@ private void UpdateDisclaimer()
CreateButton.Disabled = false;
}

public int GetReward()
public int? GetReward()
{
var priceStr = RewardEdit.Text;
return int.TryParse(priceStr, out var price) ? price : 0;
return int.TryParse(priceStr, out var price) ? price : null;
}

public BountyContractTargetInfo? GetTargetInfo()
Expand Down Expand Up @@ -214,15 +240,21 @@ public string GetVessel()
return vessel;
}

public BountyContractCategory GetCategory()
{
return (BountyContractCategory) CategorySelector.SelectedId;
}

public BountyContractRequest GetBountyContract()
{
var info = new BountyContractRequest
{
Category = GetCategory(),
Name = GetTargetName(),
DNA = GetTargetDna(),
Vessel = GetVessel(),
Description = Rope.Collapse(DescriptionEdit.TextRope),
Reward = GetReward()
Reward = GetReward() ?? 0
};
return info;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<Control xmlns="https://spacestation14.io">
<PanelContainer Margin="8,8,8,8" StyleClasses="AngleRect" >
<BoxContainer Orientation="Vertical">
<PanelContainer Name="BountyPanel" Margin="8" StyleClasses="AngleRect" >
<BoxContainer Orientation="Vertical" Margin="4" >
<BoxContainer Orientation="Horizontal">
<Label Name="BountyName" HorizontalExpand="True" />
<Label Name="BountyReward" HorizontalExpand="True"
HorizontalAlignment="Right"/>
</BoxContainer>
<PanelContainer StyleClasses="HighDivider" />
<Label Name="BountyCategory" StyleClasses="WindowFooterText"/>
<BoxContainer HorizontalExpand="True">
<RichTextLabel Name="BountyDescription" StyleClasses="LabelSubText"/>
</BoxContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,14 @@ public BountyContractUiFragmentListEntry(BountyContract contract, bool canRemove
// remove button
RemoveButton.OnPressed += _ => OnRemoveButtonPressed?.Invoke(contract);
RemoveButton.Disabled = !canRemoveContracts;

// color
var meta = SharedBountyContractSystem.CategoriesMeta[contract.Category];
BountyPanel.ModulateSelfOverride = meta.UiColor;

// category
var category = Loc.GetString(meta.Name);
BountyCategory.Text = Loc.GetString("bounty-contracts-ui-list-category",
("category", category));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,8 @@ private void OnTryCreateContract(EntityUid uid, CartridgeLoaderComponent compone
return;

var c = args.Contract;
if (c.Reward < MinimalReward)
return;

var author = GetContractAuthor(args.Entity);
CreateBountyContract(c.Name, c.Reward, c.Description, c.Vessel, c.DNA, author);
CreateBountyContract(c.Category, c.Name, c.Reward, c.Description, c.Vessel, c.DNA, author);

CartridgeOpenListUi(args.Entity);
}
Expand Down
6 changes: 4 additions & 2 deletions Content.Server/_NF/BountyContracts/BountyContractSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ private void OnRoundStarting(RoundStartingEvent ev)
/// <summary>
/// Try to create a new bounty contract and put it in bounties list.
/// </summary>
/// <param name="category">Bounty contract category (bounty head, construction, etc.)</param>
/// <param name="name">IC name for the contract bounty head. Can be players IC name or custom string.</param>
/// <param name="reward">Cash reward for completing bounty. Can be zero.</param>
/// <param name="description">IC description of players crimes, details, etc.</param>
Expand All @@ -67,7 +68,8 @@ private void OnRoundStarting(RoundStartingEvent ev)
/// <param name="author">Optional bounty poster IC name.</param>
/// <param name="postToRadio">Should radio message about contract be posted in general radio channel?</param>
/// <returns>New bounty contract. Null if contract creation failed.</returns>
public BountyContract? CreateBountyContract(string name, int reward,
public BountyContract? CreateBountyContract(BountyContractCategory category,
string name, int reward,
string? description = null, string? vessel = null,
string? dna = null, string? author = null,
bool postToRadio = true)
Expand All @@ -78,7 +80,7 @@ private void OnRoundStarting(RoundStartingEvent ev)

// create a new contract
var contractId = data.LastId++;
var contract = new BountyContract(contractId, name, reward,
var contract = new BountyContract(contractId, category, name, reward,
dna, vessel, description, author);

// try to save it
Expand Down
57 changes: 53 additions & 4 deletions Content.Shared/_NF/BountyContracts/SharedBountyContractSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@

namespace Content.Shared._NF.BountyContracts;

[Serializable, NetSerializable]
public enum BountyContractCategory : byte
{
Criminal,
Vacancy,
Construction,
Service,
Other
}

[Serializable, NetSerializable]
public struct BountyContractCategoryMeta
{
public string Name;
public Color UiColor;
}

[NetSerializable, Serializable]
public struct BountyContractTargetInfo
{
Expand All @@ -27,6 +44,7 @@ public override int GetHashCode()
[NetSerializable, Serializable]
public struct BountyContractRequest
{
public BountyContractCategory Category;
public string Name;
public string? DNA;
public string Vessel;
Expand All @@ -38,17 +56,19 @@ public struct BountyContractRequest
public sealed class BountyContract
{
public readonly uint ContractId;
public readonly BountyContractCategory Category;
public readonly string Name;
public readonly int Reward;
public readonly string? DNA;
public readonly string? Vessel;
public readonly string? Description;
public readonly string? Author;

public BountyContract(uint contractId, string name, int reward,
string? dna, string? vessel, string? description, string? author)
public BountyContract(uint contractId, BountyContractCategory category, string name,
int reward, string? dna, string? vessel, string? description, string? author)
{
ContractId = contractId;
Category = category;
Name = name;
Reward = reward;
DNA = dna;
Expand Down Expand Up @@ -129,6 +149,35 @@ public BountyContractTryCreateMsg(BountyContractRequest contract)

public abstract class SharedBountyContractSystem : EntitySystem
{
// TODO: Cvar?
public const int MinimalReward = 10000;
public const int DefaultReward = 5000;

// TODO: move this to prototypes?
public static readonly Dictionary<BountyContractCategory, BountyContractCategoryMeta> CategoriesMeta = new()
{
[BountyContractCategory.Criminal] = new BountyContractCategoryMeta
{
Name = "bounty-contracts-category-criminal",
UiColor = Color.FromHex("#520c0c")
},
[BountyContractCategory.Vacancy] = new BountyContractCategoryMeta
{
Name = "bounty-contracts-category-vacancy",
UiColor = Color.FromHex("#003866")
},
[BountyContractCategory.Construction] = new BountyContractCategoryMeta
{
Name = "bounty-contracts-category-construction",
UiColor = Color.FromHex("#664a06")
},
[BountyContractCategory.Service] = new BountyContractCategoryMeta
{
Name = "bounty-contracts-category-service",
UiColor = Color.FromHex("#01551e")
},
[BountyContractCategory.Other] = new BountyContractCategoryMeta
{
Name = "bounty-contracts-category-other",
UiColor = Color.FromHex("#474747")
},
};
}
24 changes: 16 additions & 8 deletions Resources/Locale/en-US/_NF/bounty-contracts/bounty-contracts.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,47 @@ bounty-contracts-author = {$name} ({$job})
bounty-contracts-unknown-author-name = Unknown
bounty-contracts-unknown-author-job = Unknown

# Caregories
bounty-contracts-category-criminal = Wanted Criminal
bounty-contracts-category-vacancy = Job Vacancy
bounty-contracts-category-construction = Construction
bounty-contracts-category-service = Service
bounty-contracts-category-other = Other

# Cartridge
bounty-contracts-program-name = Bounty Contracts

## Radio Announcements
bounty-contracts-radio-name = Bounty Contracts Service
bounty-contracts-radio-create = New bounty placed for {$target}. Reward: {$reward}$.
bounty-contracts-radio-create = New bounty placed for "{$target}". Reward: {$reward}$.

## UI - List contracts
bounty-contracts-ui-list-no-contracts = No bounties posted yet...
bounty-contracts-ui-list-no-description = No additional description provided...
bounty-contracts-ui-list-create = New Contract
bounty-contracts-ui-list-create = New Bounty
bounty-contracts-ui-list-refresh = Refresh
bounty-contracts-ui-list-vessel = Last Known Vessel: {$vessel}
bounty-contracts-ui-list-category = Category: {$category}
bounty-contracts-ui-list-vessel = Vessel: {$vessel}
bounty-contracts-ui-list-author = Posted by: {$author}
bounty-contracts-ui-list-remove = Remove

## UI - Create contract
bounty-contracts-ui-create-category = Category:{" "}
bounty-contracts-ui-create-name = Name:{" "}
bounty-contracts-ui-create-custom = Custom
bounty-contracts-ui-create-name-placeholder = Target name...
bounty-contracts-ui-create-name-placeholder = Bounty name...
bounty-contracts-ui-create-dna = DNA:{" "}
bounty-contracts-ui-create-dna-unknown = N/A
bounty-contracts-ui-create-vessel = Vessel:{" "}
bounty-contracts-ui-create-vessel-unknown = Unknown
bounty-contracts-ui-create-vessel-placeholder = Vessel name...
bounty-contracts-ui-create-reward = Reward:{" "}
bounty-contracts-ui-create-reward-currency = $
bounty-contracts-ui-create-description = Description:
bounty-contracts-ui-create-description-placeholder = Crimes, additional details...
bounty-contracts-ui-create-description-placeholder = Additional details...
bounty-contracts-ui-create-button-cancel = Cancel
bounty-contracts-ui-create-button-create = Create
bounty-contracts-ui-create-error-too-cheap = Error: Invalid price! Minimal contract reward is {$reward}$.
bounty-contracts-ui-create-error-no-name = Error: Invalid bounty target name!
bounty-contracts-ui-create-error-invalid-price = Error: Invalid price!
bounty-contracts-ui-create-error-no-name = Error: Invalid bounty name!
bounty-contracts-ui-create-ready = Your contract is ready to be published!


Loading