Faction Test v1.0.1.0
This commit is contained in:
+17
-14
@@ -147,10 +147,7 @@ namespace Barotrauma
|
||||
ISpatialEntity spawnPoint = SpawnAction.GetSpawnPos(
|
||||
SpawnAction.SpawnLocationType.Outpost, SpawnType.Human | SpawnType.Enemy,
|
||||
moduleFlags, spawnPointTags, element.GetAttributeBool("asfaraspossible", false));
|
||||
if (spawnPoint == null)
|
||||
{
|
||||
spawnPoint = submarine.GetHulls(alsoFromConnectedSubs: false).GetRandomUnsynced();
|
||||
}
|
||||
spawnPoint ??= submarine.GetHulls(alsoFromConnectedSubs: false).GetRandomUnsynced();
|
||||
Vector2 spawnPos = spawnPoint.WorldPosition;
|
||||
if (spawnPoint is WayPoint wp && wp.CurrentHull != null && wp.CurrentHull.Rect.Width > 100)
|
||||
{
|
||||
@@ -189,7 +186,12 @@ namespace Barotrauma
|
||||
|
||||
if (element.Attribute("identifier") != null && element.Attribute("from") != null)
|
||||
{
|
||||
HumanPrefab humanPrefab = GetHumanPrefabFromElement(element);
|
||||
HumanPrefab humanPrefab = GetHumanPrefabFromElement(element);
|
||||
if (humanPrefab == null)
|
||||
{
|
||||
DebugConsole.ThrowError($"Couldn't spawn a human character for abandoned outpost mission: human prefab \"{element.GetAttributeString("identifier", string.Empty)}\" not found");
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
LoadHuman(humanPrefab, element, submarine);
|
||||
@@ -201,7 +203,7 @@ namespace Barotrauma
|
||||
var characterPrefab = CharacterPrefab.FindBySpeciesName(speciesName);
|
||||
if (characterPrefab == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't spawn a character for abandoned outpost mission: character prefab \"" + speciesName + "\" not found");
|
||||
DebugConsole.ThrowError($"Couldn't spawn a character for abandoned outpost mission: character prefab \"{speciesName}\" not found");
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < count; i++)
|
||||
@@ -223,10 +225,7 @@ namespace Barotrauma
|
||||
moduleFlags ?? humanPrefab.GetModuleFlags(),
|
||||
spawnPointTags ?? humanPrefab.GetSpawnPointTags(),
|
||||
element.GetAttributeBool("asfaraspossible", false));
|
||||
if (spawnPos == null)
|
||||
{
|
||||
spawnPos = submarine.GetHulls(alsoFromConnectedSubs: false).GetRandomUnsynced();
|
||||
}
|
||||
spawnPos ??= submarine.GetHulls(alsoFromConnectedSubs: false).GetRandomUnsynced();
|
||||
|
||||
bool requiresRescue = element.GetAttributeBool("requirerescue", false);
|
||||
var teamId = element.GetAttributeEnum("teamid", requiresRescue ? CharacterTeamType.FriendlyNPC : CharacterTeamType.None);
|
||||
@@ -255,6 +254,13 @@ namespace Barotrauma
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (TimesAttempted > 0 && spawnedCharacter.AIController is HumanAIController humanAi)
|
||||
{
|
||||
var order = OrderPrefab.Prefabs["fightintruders"]
|
||||
.CreateInstance(OrderPrefab.OrderTargetType.Entity, orderGiver: spawnedCharacter)
|
||||
.WithManualPriority(CharacterInfo.HighestManualOrderPriority);
|
||||
spawnedCharacter.SetOrder(order, isNewOrder: true, speak: false);
|
||||
}
|
||||
|
||||
if (element.GetAttributeBool("requirekill", false))
|
||||
{
|
||||
@@ -267,10 +273,7 @@ namespace Barotrauma
|
||||
Identifier[] moduleFlags = element.GetAttributeIdentifierArray("moduleflags", null);
|
||||
Identifier[] spawnPointTags = element.GetAttributeIdentifierArray("spawnpointtags", null);
|
||||
ISpatialEntity spawnPos = SpawnAction.GetSpawnPos(SpawnAction.SpawnLocationType.Outpost, SpawnType.Enemy, moduleFlags, spawnPointTags, element.GetAttributeBool("asfaraspossible", false));
|
||||
if (spawnPos == null)
|
||||
{
|
||||
spawnPos = submarine.GetHulls(alsoFromConnectedSubs: false).GetRandomUnsynced();
|
||||
}
|
||||
spawnPos ??= submarine.GetHulls(alsoFromConnectedSubs: false).GetRandomUnsynced();
|
||||
Character spawnedCharacter = Character.Create(monsterPrefab.Identifier, spawnPos.WorldPosition, ToolBox.RandomSeed(8), createNetworkEvent: false);
|
||||
characters.Add(spawnedCharacter);
|
||||
if (element.GetAttributeBool("requirekill", false))
|
||||
|
||||
@@ -203,8 +203,11 @@ namespace Barotrauma
|
||||
projectileTimer -= deltaTime;
|
||||
if (projectileTimer <= 0.0f)
|
||||
{
|
||||
float dist = Vector2.Distance(Submarine.MainSub.WorldPosition, boss.WorldPosition);
|
||||
float distanceFactor = Math.Min(dist / 10000.0f, 1.0f);
|
||||
int projectileAmount = Rand.Range(3, 6);
|
||||
float spread = MathHelper.ToRadians(Rand.Range(20.0f, 180.0f));
|
||||
//more concentrated shots the further the sub is
|
||||
float spread = MathHelper.ToRadians(Rand.Range(20.0f, 180.0f)) * Math.Max(1.0f - distanceFactor, 0.2f);
|
||||
for (int i = 0; i < projectileAmount; i++)
|
||||
{
|
||||
int index = i;
|
||||
@@ -218,13 +221,13 @@ namespace Barotrauma
|
||||
}
|
||||
it.body.SetTransform(it.SimPosition, angle);
|
||||
it.UpdateTransform();
|
||||
projectile.Use();
|
||||
//faster launch velocity the further the sub is
|
||||
projectile.Use(launchImpulseModifier: MathHelper.Lerp(0, 5, distanceFactor));
|
||||
});
|
||||
}
|
||||
|
||||
float dist = Vector2.Distance(Submarine.MainSub.WorldPosition, boss.WorldPosition);
|
||||
//the closer the sub is, more likely it is to shoot frequently
|
||||
float shortIntervalProbability = MathHelper.Lerp(0.9f, 0.05f, dist / 15000.0f);
|
||||
float shortIntervalProbability = MathHelper.Lerp(0.9f, 0.05f, distanceFactor);
|
||||
if (Rand.Range(0.0f, 1.0f) < shortIntervalProbability)
|
||||
{
|
||||
projectileTimer = Rand.Range(3.0f, 5.0f);
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public int TimesAttempted { get; set; }
|
||||
|
||||
protected static bool IsClient => GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
|
||||
|
||||
private readonly CheckDataAction completeCheckDataAction;
|
||||
@@ -49,6 +51,12 @@ namespace Barotrauma
|
||||
public readonly ImmutableArray<LocalizedString> Headers;
|
||||
public readonly ImmutableArray<LocalizedString> Messages;
|
||||
|
||||
/// <summary>
|
||||
/// The reward that was actually given from completing the mission, taking any talent bonuses into account
|
||||
/// (some of which may not be possible to determine in advance)
|
||||
/// </summary>
|
||||
private int? finalReward;
|
||||
|
||||
public virtual LocalizedString Name => Prefab.Name;
|
||||
|
||||
private readonly LocalizedString successMessage;
|
||||
@@ -367,6 +375,8 @@ namespace Barotrauma
|
||||
GiveReward();
|
||||
}
|
||||
|
||||
TimesAttempted++;
|
||||
|
||||
EndMissionSpecific(completed);
|
||||
}
|
||||
|
||||
@@ -374,6 +384,27 @@ namespace Barotrauma
|
||||
|
||||
protected virtual void EndMissionSpecific(bool completed) { }
|
||||
|
||||
/// <summary>
|
||||
/// Get the final reward, taking talent bonuses into account if the mission has concluded and the talents modified the reward accordingly.
|
||||
/// </summary>
|
||||
public int GetFinalReward(Submarine sub)
|
||||
{
|
||||
return finalReward ?? GetReward(sub);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the final reward after talent bonuses have been applied. Note that this triggers talent effects of the type OnGainMissionMoney,
|
||||
/// and should only be called once when the mission is completed!
|
||||
/// </summary>
|
||||
private void CalculateFinalReward(Submarine sub)
|
||||
{
|
||||
int reward = GetReward(sub);
|
||||
IEnumerable<Character> crewCharacters = GameSession.GetSessionCrewCharacters(CharacterType.Both);
|
||||
var missionMoneyGainMultiplier = new AbilityMissionMoneyGainMultiplier(this, 1f);
|
||||
crewCharacters.ForEach(c => c.CheckTalents(AbilityEffectType.OnGainMissionMoney, missionMoneyGainMultiplier));
|
||||
crewCharacters.ForEach(c => missionMoneyGainMultiplier.Value += c.GetStatValue(StatTypes.MissionMoneyGainMultiplier));
|
||||
finalReward = (int)(reward * missionMoneyGainMultiplier.Value);
|
||||
}
|
||||
|
||||
private void GiveReward()
|
||||
{
|
||||
@@ -417,38 +448,35 @@ namespace Barotrauma
|
||||
info?.GiveExperience((int)((experienceGain * experienceGainMultiplier.Value) * experienceGainMultiplierIndividual.Value));
|
||||
}
|
||||
|
||||
// apply money gains afterwards to prevent them from affecting XP gains
|
||||
var missionMoneyGainMultiplier = new AbilityMissionMoneyGainMultiplier(this, 1f);
|
||||
crewCharacters.ForEach(c => c.CheckTalents(AbilityEffectType.OnGainMissionMoney, missionMoneyGainMultiplier));
|
||||
crewCharacters.ForEach(c => missionMoneyGainMultiplier.Value += c.GetStatValue(StatTypes.MissionMoneyGainMultiplier));
|
||||
|
||||
int totalReward = (int)(reward * missionMoneyGainMultiplier.Value);
|
||||
GameAnalyticsManager.AddMoneyGainedEvent(totalReward, GameAnalyticsManager.MoneySource.MissionReward, Prefab.Identifier.Value);
|
||||
|
||||
CalculateFinalReward(Submarine.MainSub);
|
||||
#if SERVER
|
||||
totalReward = DistributeRewardsToCrew(GameSession.GetSessionCrewCharacters(CharacterType.Player), totalReward);
|
||||
finalReward = DistributeRewardsToCrew(GameSession.GetSessionCrewCharacters(CharacterType.Player), finalReward.Value);
|
||||
#endif
|
||||
bool isSingleplayerOrServer = GameMain.IsSingleplayer || GameMain.NetworkMember is { IsServer: true };
|
||||
if (isSingleplayerOrServer && totalReward > 0)
|
||||
if (isSingleplayerOrServer)
|
||||
{
|
||||
campaign.Bank.Give(totalReward);
|
||||
}
|
||||
|
||||
foreach (Character character in crewCharacters)
|
||||
{
|
||||
character.Info.MissionsCompletedSinceDeath++;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Identifier, float> reputationReward in ReputationRewards)
|
||||
{
|
||||
if (reputationReward.Key == "location")
|
||||
if (finalReward > 0)
|
||||
{
|
||||
OriginLocation.Reputation?.AddReputation(reputationReward.Value);
|
||||
campaign.Bank.Give(finalReward.Value);
|
||||
}
|
||||
else
|
||||
|
||||
foreach (Character character in crewCharacters)
|
||||
{
|
||||
Faction faction = campaign.Factions.Find(faction1 => faction1.Prefab.Identifier == reputationReward.Key);
|
||||
if (faction != null) { faction.Reputation.AddReputation(reputationReward.Value); }
|
||||
character.Info.MissionsCompletedSinceDeath++;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Identifier, float> reputationReward in ReputationRewards)
|
||||
{
|
||||
if (reputationReward.Key == "location")
|
||||
{
|
||||
OriginLocation.Reputation?.AddReputation(reputationReward.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Faction faction = campaign.Factions.Find(faction1 => faction1.Prefab.Identifier == reputationReward.Key);
|
||||
float prevValue = faction.Reputation.Value;
|
||||
faction?.Reputation.AddReputation(reputationReward.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,12 +521,9 @@ namespace Barotrauma
|
||||
float rewardWeight = sum > 100 ? rewardDistribution / sum : rewardDistribution / 100f;
|
||||
int rewardPercentage = (int)(rewardWeight * 100);
|
||||
|
||||
return reward switch
|
||||
{
|
||||
Some<int> { Value: var amount } => ((int)(amount * rewardWeight), rewardPercentage, sum),
|
||||
None<int> _ => (0, rewardPercentage, sum),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
int amount = reward.TryUnwrap(out var a) ? a : 0;
|
||||
|
||||
return ((int)(amount * rewardWeight), rewardPercentage, sum);
|
||||
}
|
||||
|
||||
protected void ChangeLocationType(LocationTypeChange change)
|
||||
@@ -518,6 +543,8 @@ namespace Barotrauma
|
||||
if (srcIndex == -1) { return; }
|
||||
var location = Locations[srcIndex];
|
||||
|
||||
if (location.LocationTypeChangesBlocked) { return; }
|
||||
|
||||
if (change.RequiredDurationRange.X > 0)
|
||||
{
|
||||
location.PendingLocationTypeChange = (change, Rand.Range(change.RequiredDurationRange.X, change.RequiredDurationRange.Y), Prefab);
|
||||
|
||||
@@ -99,7 +99,13 @@ namespace Barotrauma
|
||||
|
||||
public readonly bool RequireWreck, RequireRuin;
|
||||
|
||||
/// <summary>
|
||||
/// If enabled, locations this mission takes place in cannot change their type
|
||||
/// </summary>
|
||||
public readonly bool BlockLocationTypeChanges;
|
||||
|
||||
public readonly bool ShowProgressBar;
|
||||
public readonly bool ShowProgressInNumbers;
|
||||
public readonly int MaxProgressState;
|
||||
public readonly LocalizedString ProgressBarLabel;
|
||||
|
||||
@@ -178,6 +184,7 @@ namespace Barotrauma
|
||||
IsSideObjective = element.GetAttributeBool("sideobjective", false);
|
||||
RequireWreck = element.GetAttributeBool("requirewreck", false);
|
||||
RequireRuin = element.GetAttributeBool("requireruin", false);
|
||||
BlockLocationTypeChanges = element.GetAttributeBool(nameof(BlockLocationTypeChanges), false);
|
||||
Commonness = element.GetAttributeInt("commonness", 1);
|
||||
AllowOtherMissionsInLevel = element.GetAttributeBool("allowothermissionsinlevel", true);
|
||||
if (element.GetAttribute("difficulty") != null)
|
||||
@@ -187,6 +194,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
ShowProgressBar = element.GetAttributeBool(nameof(ShowProgressBar), false);
|
||||
ShowProgressInNumbers = element.GetAttributeBool(nameof(ShowProgressInNumbers), false);
|
||||
MaxProgressState = element.GetAttributeInt(nameof(MaxProgressState), 1);
|
||||
string progressBarLabel = element.GetAttributeString(nameof(ProgressBarLabel), "");
|
||||
ProgressBarLabel = TextManager.Get(progressBarLabel).Fallback(progressBarLabel);
|
||||
|
||||
@@ -234,6 +234,12 @@ namespace Barotrauma
|
||||
if (!string.IsNullOrEmpty(target.ExistingItemTag))
|
||||
{
|
||||
var suitableItems = Item.ItemList.Where(it => it.HasTag(target.ExistingItemTag));
|
||||
if (GameMain.GameSession?.Missions != null)
|
||||
{
|
||||
//don't choose an item that was already chosen as the target for another salvage mission
|
||||
suitableItems = suitableItems.Where(it =>
|
||||
GameMain.GameSession.Missions.None(m => m != this && m is SalvageMission salvageMission && salvageMission.targets.Any(t => t.Item == it)));
|
||||
}
|
||||
switch (target.SpawnPositionType)
|
||||
{
|
||||
case Level.PositionType.Cave:
|
||||
|
||||
Reference in New Issue
Block a user