Build 1.1.4.0
This commit is contained in:
@@ -8,19 +8,15 @@ namespace Barotrauma
|
||||
{
|
||||
internal partial class CampaignMetadata
|
||||
{
|
||||
public CampaignMode Campaign { get; }
|
||||
|
||||
private readonly Dictionary<Identifier, object> data = new Dictionary<Identifier, object>();
|
||||
|
||||
public CampaignMetadata(CampaignMode campaign)
|
||||
public CampaignMetadata()
|
||||
{
|
||||
Campaign = campaign;
|
||||
}
|
||||
|
||||
public CampaignMetadata(CampaignMode campaign, XElement element)
|
||||
public void Load(XElement element)
|
||||
{
|
||||
Campaign = campaign;
|
||||
|
||||
data.Clear();
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (string.Equals(subElement.Name.ToString(), "data", StringComparison.InvariantCultureIgnoreCase))
|
||||
@@ -59,10 +55,11 @@ namespace Barotrauma
|
||||
{
|
||||
DebugConsole.Log($"Set the value \"{identifier}\" to {value}");
|
||||
|
||||
SteamAchievementManager.OnCampaignMetadataSet(identifier, value, unlockClients: true);
|
||||
|
||||
if (!data.ContainsKey(identifier))
|
||||
{
|
||||
data.Add(identifier, value);
|
||||
SteamAchievementManager.OnCampaignMetadataSet(identifier, value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#nullable enable
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public enum FactionAffiliation
|
||||
{
|
||||
Affiliated,
|
||||
Neutral
|
||||
Positive,
|
||||
Neutral,
|
||||
Negative
|
||||
}
|
||||
|
||||
class Faction
|
||||
@@ -25,21 +28,25 @@ namespace Barotrauma
|
||||
/// Get what kind of affiliation this faction has towards the player depending on who they chose to side with via talents
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public FactionAffiliation GetPlayerAffiliationStatus()
|
||||
public static FactionAffiliation GetPlayerAffiliationStatus(Faction faction)
|
||||
{
|
||||
float affiliation = 1f;
|
||||
foreach (Character character in GameSession.GetSessionCrewCharacters(CharacterType.Both))
|
||||
{
|
||||
if (character.Info is not { } info) { continue; }
|
||||
if (GameMain.GameSession?.Campaign?.Factions is not { } factions) { return FactionAffiliation.Neutral; }
|
||||
|
||||
affiliation *= 1f + info.GetSavedStatValue(StatTypes.Affiliation, Prefab.Identifier);
|
||||
bool isHighest = true;
|
||||
foreach (Faction otherFaction in factions)
|
||||
{
|
||||
if (otherFaction == faction || otherFaction.Reputation.Value < faction.Reputation.Value) { continue; }
|
||||
|
||||
isHighest = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return affiliation switch
|
||||
{
|
||||
>= 1f => FactionAffiliation.Affiliated,
|
||||
_ => FactionAffiliation.Neutral
|
||||
};
|
||||
return isHighest ? FactionAffiliation.Positive : FactionAffiliation.Negative;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{base.ToString()} ({Prefab?.Identifier.ToString() ?? "null"})";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +59,54 @@ namespace Barotrauma
|
||||
public LocalizedString Description { get; }
|
||||
public LocalizedString ShortDescription { get; }
|
||||
|
||||
public class HireableCharacter
|
||||
{
|
||||
public readonly Identifier NPCSetIdentifier;
|
||||
public readonly Identifier NPCIdentifier;
|
||||
public readonly float MinReputation;
|
||||
|
||||
public HireableCharacter(ContentXElement element)
|
||||
{
|
||||
NPCSetIdentifier = element.GetAttributeIdentifier("from", element.GetAttributeIdentifier("npcsetidentifier", Identifier.Empty));
|
||||
NPCIdentifier = element.GetAttributeIdentifier("identifier", element.GetAttributeIdentifier("npcidentifier", Identifier.Empty));
|
||||
MinReputation = element.GetAttributeFloat("minreputation", 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableArray<HireableCharacter> HireableCharacters;
|
||||
|
||||
public class AutomaticMission
|
||||
{
|
||||
public readonly Identifier MissionTag;
|
||||
public readonly LevelData.LevelType LevelType;
|
||||
public readonly float MinReputation, MaxReputation;
|
||||
public readonly float MinProbability, MaxProbability;
|
||||
public readonly int MaxDistanceFromFactionOutpost;
|
||||
public readonly bool DisallowBetweenOtherFactionOutposts;
|
||||
|
||||
public AutomaticMission(ContentXElement element, string parentDebugName)
|
||||
{
|
||||
MissionTag = element.GetAttributeIdentifier("missiontag", Identifier.Empty);
|
||||
LevelType = element.GetAttributeEnum("leveltype", LevelData.LevelType.LocationConnection);
|
||||
MinReputation = element.GetAttributeFloat("minreputation", 0.0f);
|
||||
MaxReputation = element.GetAttributeFloat("maxreputation", 0.0f);
|
||||
if (MinReputation > MaxReputation)
|
||||
{
|
||||
DebugConsole.ThrowError($"Error in faction prefab \"{parentDebugName}\": MinReputation cannot be larger than MaxReputation.");
|
||||
}
|
||||
float probability = element.GetAttributeFloat("probability", 0.0f);
|
||||
MinProbability = element.GetAttributeFloat("minprobability", probability);
|
||||
MaxProbability = element.GetAttributeFloat("maxprobability", probability);
|
||||
MaxDistanceFromFactionOutpost = element.GetAttributeInt(nameof(MaxDistanceFromFactionOutpost), int.MaxValue);
|
||||
DisallowBetweenOtherFactionOutposts = element.GetAttributeBool(nameof(DisallowBetweenOtherFactionOutposts), false);
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableArray<AutomaticMission> AutomaticMissions;
|
||||
|
||||
public bool StartOutpost { get; }
|
||||
|
||||
|
||||
public int MenuOrder { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -69,38 +124,73 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public int InitialReputation { get; }
|
||||
|
||||
public float ControlledOutpostPercentage { get; }
|
||||
|
||||
public float SecondaryControlledOutpostPercentage { get; }
|
||||
|
||||
#if CLIENT
|
||||
public Sprite? Icon { get; private set; }
|
||||
|
||||
public Sprite? IconSmall { get; private set; }
|
||||
|
||||
public Sprite? BackgroundPortrait { get; private set; }
|
||||
#endif
|
||||
|
||||
public Color IconColor { get; }
|
||||
#endif
|
||||
|
||||
public FactionPrefab(ContentXElement element, FactionsFile file) : base(file, element.GetAttributeIdentifier("identifier", string.Empty))
|
||||
{
|
||||
MenuOrder = element.GetAttributeInt("menuorder", 0);
|
||||
StartOutpost = element.GetAttributeBool("startoutpost", false);
|
||||
MinReputation = element.GetAttributeInt("minreputation", -100);
|
||||
MaxReputation = element.GetAttributeInt("maxreputation", 100);
|
||||
InitialReputation = element.GetAttributeInt("initialreputation", 0);
|
||||
ControlledOutpostPercentage = element.GetAttributeFloat("controlledoutpostpercentage", 0);
|
||||
SecondaryControlledOutpostPercentage = element.GetAttributeFloat("secondarycontrolledoutpostpercentage", 0);
|
||||
Name = element.GetAttributeString("name", null) ?? TextManager.Get($"faction.{Identifier}").Fallback("Unnamed");
|
||||
Description = element.GetAttributeString("description", null) ?? TextManager.Get($"faction.{Identifier}.description").Fallback("");
|
||||
ShortDescription = element.GetAttributeString("shortdescription", null) ?? TextManager.Get($"faction.{Identifier}.shortdescription").Fallback("");
|
||||
#if CLIENT
|
||||
|
||||
List<HireableCharacter> hireableCharacters = new List<HireableCharacter>();
|
||||
List<AutomaticMission> automaticMissions = new List<AutomaticMission>();
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
|
||||
if (subElement.Name.ToString().Equals("icon", StringComparison.OrdinalIgnoreCase))
|
||||
var subElementId = subElement.NameAsIdentifier();
|
||||
if (subElementId == "icon")
|
||||
{
|
||||
IconColor = subElement.GetAttributeColor("color", Color.White);
|
||||
#if CLIENT
|
||||
Icon = new Sprite(subElement);
|
||||
#endif
|
||||
}
|
||||
else if (subElement.Name.ToString().Equals("portrait", StringComparison.OrdinalIgnoreCase))
|
||||
else if (subElementId == "iconsmall")
|
||||
{
|
||||
#if CLIENT
|
||||
IconSmall = new Sprite(subElement);
|
||||
#endif
|
||||
}
|
||||
else if (subElementId == "portrait")
|
||||
{
|
||||
#if CLIENT
|
||||
BackgroundPortrait = new Sprite(subElement);
|
||||
#endif
|
||||
}
|
||||
else if (subElementId == "hireable")
|
||||
{
|
||||
hireableCharacters.Add(new HireableCharacter(subElement));
|
||||
}
|
||||
else if (subElementId == "mission" || subElementId == "automaticmission")
|
||||
{
|
||||
automaticMissions.Add(new AutomaticMission(subElement, Identifier.ToString()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
HireableCharacters = hireableCharacters.ToImmutableArray();
|
||||
AutomaticMissions = automaticMissions.ToImmutableArray();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{base.ToString()} ({Identifier})";
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
|
||||
@@ -1,17 +1,25 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class Reputation
|
||||
{
|
||||
public const float HostileThreshold = 0.2f;
|
||||
public const float ReputationLossPerNPCDamage = 0.1f;
|
||||
public const float ReputationLossPerStolenItemPrice = 0.01f;
|
||||
public const float ReputationLossPerWallDamage = 0.1f;
|
||||
public const float MinReputationLossPerStolenItem = 0.5f;
|
||||
public const float MaxReputationLossPerStolenItem = 10.0f;
|
||||
public const float ReputationLossPerNPCDamage = 0.025f;
|
||||
public const float ReputationLossPerWallDamage = 0.025f;
|
||||
public const float ReputationLossPerStolenItemPrice = 0.0025f;
|
||||
public const float MinReputationLossPerStolenItem = 0.025f;
|
||||
public const float MaxReputationLossPerStolenItem = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum amount of reputation loss you can get from damaging outpost NPCs per round
|
||||
/// </summary>
|
||||
public const float MaxReputationLossFromNPCDamage = 10.0f;
|
||||
/// <summary>
|
||||
/// Maximum amount of reputation loss you can get from damaging outpost walls per round
|
||||
/// </summary>
|
||||
public const float MaxReputationLossFromWallDamage = 10.0f;
|
||||
|
||||
public Identifier Identifier { get; }
|
||||
public int MinReputation { get; }
|
||||
@@ -19,6 +27,8 @@ namespace Barotrauma
|
||||
public int InitialReputation { get; }
|
||||
public CampaignMetadata Metadata { get; }
|
||||
|
||||
public float ReputationAtRoundStart { get; set; }
|
||||
|
||||
private readonly Identifier metaDataIdentifier;
|
||||
|
||||
/// <summary>
|
||||
@@ -59,27 +69,47 @@ namespace Barotrauma
|
||||
Value = newReputation;
|
||||
}
|
||||
|
||||
public void AddReputation(float reputationChange)
|
||||
public float GetReputationChangeMultiplier(float reputationChange)
|
||||
{
|
||||
if (reputationChange > 0f)
|
||||
{
|
||||
float reputationGainMultiplier = 1f;
|
||||
foreach (Character character in GameSession.GetSessionCrewCharacters(CharacterType.Both))
|
||||
{
|
||||
reputationGainMultiplier += character.GetStatValue(StatTypes.ReputationGainMultiplier);
|
||||
reputationGainMultiplier *= 1f + character.GetStatValue(StatTypes.ReputationGainMultiplier, includeSaved: false);
|
||||
reputationGainMultiplier *= 1f + character.Info?.GetSavedStatValue(StatTypes.ReputationGainMultiplier, Identifier) ?? 0;
|
||||
}
|
||||
reputationChange *= reputationGainMultiplier;
|
||||
return reputationGainMultiplier;
|
||||
}
|
||||
else if (reputationChange < 0f)
|
||||
{
|
||||
float reputationLossMultiplier = 1f;
|
||||
foreach (Character character in GameSession.GetSessionCrewCharacters(CharacterType.Both))
|
||||
{
|
||||
reputationLossMultiplier += character.GetStatValue(StatTypes.ReputationLossMultiplier);
|
||||
reputationLossMultiplier *= 1f + character.GetStatValue(StatTypes.ReputationLossMultiplier, includeSaved: false);
|
||||
reputationLossMultiplier *= 1f + character.Info?.GetSavedStatValue(StatTypes.ReputationLossMultiplier, Identifier) ?? 0;
|
||||
}
|
||||
reputationChange *= reputationLossMultiplier;
|
||||
return reputationLossMultiplier;
|
||||
}
|
||||
Value += reputationChange;
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
public void AddReputation(float reputationChange, float maxReputationChangePerRound = float.MaxValue)
|
||||
{
|
||||
float currentValue = Value;
|
||||
float currentReputationChange = currentValue - ReputationAtRoundStart;
|
||||
if (Math.Abs(currentReputationChange) >= maxReputationChangePerRound &&
|
||||
Math.Sign(currentReputationChange) == Math.Sign(reputationChange))
|
||||
{
|
||||
return;
|
||||
}
|
||||
float newValue = Value + reputationChange * GetReputationChangeMultiplier(reputationChange);
|
||||
if (Math.Abs(newValue - ReputationAtRoundStart) > maxReputationChangePerRound &&
|
||||
Math.Sign(newValue - currentValue) == Math.Sign(newValue - ReputationAtRoundStart))
|
||||
{
|
||||
newValue = ReputationAtRoundStart + maxReputationChangePerRound * Math.Sign(reputationChange);
|
||||
}
|
||||
Value = newValue;
|
||||
}
|
||||
|
||||
public readonly NamedEvent<Reputation> OnReputationValueChanged = new NamedEvent<Reputation>();
|
||||
@@ -108,6 +138,7 @@ namespace Barotrauma
|
||||
metaDataIdentifier = $"reputation.{Identifier}".ToIdentifier();
|
||||
MinReputation = minReputation;
|
||||
MaxReputation = maxReputation;
|
||||
ReputationAtRoundStart = initialReputation;
|
||||
InitialReputation = initialReputation;
|
||||
Faction = faction;
|
||||
Location = location;
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace Barotrauma
|
||||
public Option<int> RewardDistributionChanged;
|
||||
public Option<int> BalanceChanged;
|
||||
|
||||
public WalletChangedData MergeInto(WalletChangedData other)
|
||||
public readonly WalletChangedData MergeInto(WalletChangedData other)
|
||||
{
|
||||
other.BalanceChanged = AddOptionalInt(other.BalanceChanged, BalanceChanged);
|
||||
other.RewardDistributionChanged = AddOptionalInt(other.RewardDistributionChanged, RewardDistributionChanged);
|
||||
@@ -80,32 +80,20 @@ namespace Barotrauma
|
||||
|
||||
static Option<int> AddOptionalInt(Option<int> a, Option<int> b)
|
||||
{
|
||||
return a switch
|
||||
{
|
||||
Some<int> some1 => b switch
|
||||
{
|
||||
Some<int> some2 => Option<int>.Some(some1.Value + some2.Value),
|
||||
None<int> _ => Option<int>.Some(some1.Value),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(b))
|
||||
},
|
||||
None<int> _ => b switch
|
||||
{
|
||||
Some<int> some1 => Option<int>.Some(some1.Value),
|
||||
None<int> _ => Option<int>.None(),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(b))
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(a))
|
||||
};
|
||||
bool hasValue1 = a.TryUnwrap(out var value1);
|
||||
bool hasValue2 = b.TryUnwrap(out var value2);
|
||||
return hasValue1
|
||||
? hasValue2
|
||||
? Option.Some(value1 + value2)
|
||||
: Option.Some(value1)
|
||||
: hasValue2
|
||||
? Option.Some(value2)
|
||||
: Option.None;
|
||||
}
|
||||
|
||||
static Option<int> TurnToNoneIfZero(Option<int> option)
|
||||
{
|
||||
return option switch
|
||||
{
|
||||
Some<int> s => s.Value == 0 ? Option<int>.None() : option,
|
||||
None<int> _ => option,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(option))
|
||||
};
|
||||
return option.Bind(i => i == 0 ? Option.None : Option.Some(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,12 +211,8 @@ namespace Barotrauma
|
||||
};
|
||||
}
|
||||
|
||||
public string GetOwnerLogName() => Owner switch
|
||||
{
|
||||
Some<Character> { Value: var character } => character.Name,
|
||||
None<Character> _ => "the bank",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(Owner))
|
||||
};
|
||||
public string GetOwnerLogName()
|
||||
=> Owner.TryUnwrap(out var character) ? character.Name : "the bank";
|
||||
|
||||
partial void SettingsChanged(Option<int> balanceChanged, Option<int> rewardChanged);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user