Skip to content

Commit

Permalink
Support advanced graphic classes, 4 new mods, reworked outcome utility.
Browse files Browse the repository at this point in the history
  • Loading branch information
Epicguru committed Apr 10, 2023
1 parent d00b737 commit aa95aed
Show file tree
Hide file tree
Showing 116 changed files with 1,571 additions and 106 deletions.
1 change: 1 addition & 0 deletions Defs/Hediffs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<HediffDef>
<defName>AM_KnockedOut</defName>
<label>knocked out</label>
<labelNoun>being knocked out</labelNoun>
<description>The result of being knocked out during melee combat.
Recovery will happen automatically over time, or it can be cured by another pawn, even without medicine.</description>
<hediffClass>HediffWithComps</hediffClass>
Expand Down
4 changes: 3 additions & 1 deletion Languages/English/Keyed/Keys.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

<AM.Error.Exec.FloatMenu>Cannot execute: {0}</AM.Error.Exec.FloatMenu>
<AM.Exec.FloatMenu>Execute {0}</AM.Exec.FloatMenu>
<AM.Exec.FloatMenu.Tip>Perform an execution animation on {1}.\nWill attempt to use an lasso if available to pull {1} into melee range.\nPlease note, 'execution' animations are not always lethal - please read the workshop page and mod settings for more info.</AM.Exec.FloatMenu.Tip>
<AM.Exec.FloatMenu.Tip>Perform an execution animation on {1}.\nPlease note, 'execution' animations are not always lethal - please read the workshop page and mod settings for more info.</AM.Exec.FloatMenu.Tip>
<AM.Exec.FloatMenu.Walk> (walk to target)</AM.Exec.FloatMenu.Walk>
<AM.Exec.FloatMenu.Lasso> (lasso)</AM.Exec.FloatMenu.Lasso>

<AM.Error.Grapple.Internal>Int.Error: {Error}</AM.Error.Grapple.Internal>
<AM.Error.Exec.Internal>Int.Error: {Error}</AM.Error.Exec.Internal>
Expand Down
13 changes: 0 additions & 13 deletions Patch_FacialAnimation/1.3/Patches/FacialAnimationPatch.xml

This file was deleted.

53 changes: 46 additions & 7 deletions Source/AMRetextureSupport/RetextureUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,27 @@ public static class RetextureUtility

private static readonly Dictionary<ThingDef, ActiveTextureReport> reportCache = new Dictionary<ThingDef, ActiveTextureReport>(128);
private static readonly Dictionary<ThingDef, bool> reportCacheIsFull = new Dictionary<ThingDef, bool>(128);
private static readonly Dictionary<string, Func<string, int, (bool isCollection, string newPath)>> graphicClassCustomHandlers = new Dictionary<string, Func<string, int, (bool isCollection, string newPath)>>()
{
// AdvancedGraphics Single Randomized, is a collection despite being marked as Graphic_Single.
{"AdvancedGraphics.Graphic_SingleRandomized", (path, pass) => pass switch
{
0 => (true, path),
_ => (false, null)
}
},

// AdvancedGraphics SingleQuality. The tex name has a _Quality suffix.
// If the _Normal graphic cannot be found, the fallback is the raw xml path.
{"AdvancedGraphics.Graphic_SingleQuality", (path, pass) => pass switch
{
0 => (false, path + "_Normal"),
1 => (false, path),
_ => (false, null)
}
},

};
private static HashSet<ModContentPack> OfficialMods;
private static ModContentPack CoreMCP;

Expand All @@ -30,7 +51,7 @@ public static TimeSpan PreCacheAllTextureReports(Action<ActiveTextureReport> onR
var sw = Stopwatch.StartNew();
foreach (var weapon in DefDatabase<ThingDef>.AllDefsListForReading.Where(d => d.IsMeleeWeapon))
{
onReport(GetTextureReport(weapon, full));
onReport(GetTextureReport(weapon, 0, full));
}
sw.Stop();
return sw.Elapsed;
Expand All @@ -39,7 +60,7 @@ public static TimeSpan PreCacheAllTextureReports(Action<ActiveTextureReport> onR
/// <summary>
/// Generates information about a weapon's textures, such as what mod(s) are supplying textures.
/// </summary>
public static ActiveTextureReport GetTextureReport(ThingDef weapon, bool full = true, bool loadFromCache = true, bool saveToCache = true)
public static ActiveTextureReport GetTextureReport(ThingDef weapon, int pass = 0, bool full = true, bool loadFromCache = true, bool saveToCache = true)
{
if (weapon == null)
return default;
Expand All @@ -48,9 +69,9 @@ public static ActiveTextureReport GetTextureReport(ThingDef weapon, bool full =
return found;

// 0. Get active texture.
string texPath = ResolveTexturePath(weapon);
string texPath = ResolveTexturePath(weapon, pass, out bool canDoAnotherPass);
if (string.IsNullOrWhiteSpace(texPath))
return new ActiveTextureReport($"Failed to find texture path i.e. graphicData.texPath '{weapon.graphicData.texPath}' ({weapon.graphicData.graphicClass.FullName})");
return new ActiveTextureReport($"Failed to find texture path i.e. graphicData.texPath '{weapon.graphicData.texPath}' ({weapon.graphicData.graphicClass.FullName}) pass {pass}");

// Make basic report. Data still missing.
var report = new ActiveTextureReport
Expand Down Expand Up @@ -141,7 +162,13 @@ public static ActiveTextureReport GetTextureReport(ThingDef weapon, bool full =
}

if (report.AllRetextures.Count == 0)
report.ErrorMessage = $"No textures found for path '{report.TexturePath}'";
{
report.ErrorMessage = $"No textures found for path '{report.TexturePath}' ({weapon.graphicData.graphicClass.FullName})";
if (canDoAnotherPass)
{
return GetTextureReport(weapon, pass + 1, full, loadFromCache, saveToCache);
}
}

if (!saveToCache)
return report;
Expand Down Expand Up @@ -230,14 +257,26 @@ private static void LogAllTextureReports()
DebugTables.MakeTablesDialog(meleeWeapons, table);
}

private static string ResolveTexturePath(ThingDef weapon)
private static string ResolveTexturePath(ThingDef weapon, int pass, out bool canDoAnotherPass)
{
canDoAnotherPass = false;
string xmlPath = weapon.graphicData?.texPath.Replace('\\', '/');
if (string.IsNullOrWhiteSpace(xmlPath))
return null;

var gc = weapon.graphicData.graphicClass;
bool isCollection = gc.IsSubclassOf(typeof(Graphic_Collection));

// Attempt to get custom handler for this graphic class (required for some modded classes)
// and override the xmlpath and/or collection status.
if (graphicClassCustomHandlers.TryGetValue(gc.FullName, out var func))
{
(isCollection, xmlPath) = func(xmlPath, pass);
canDoAnotherPass = xmlPath != null;
}

// Collections load from sub-folders, normal graphic types don't:
if (!weapon.graphicData.graphicClass.IsSubclassOf(typeof(Graphic_Collection)))
if (!isCollection)
return xmlPath;

// Other graphic classes will pull images from a sub-folder.
Expand Down
25 changes: 15 additions & 10 deletions Source/ThingGenerator/AMSettings/Settings.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using System;
using Meta.Numerics.Statistics.Distributions;
using System;
using System.Collections.Generic;
using System.Linq;
using AM.Idle;
using Meta.Numerics.Statistics.Distributions;
using UnityEngine;
using Verse;

Expand Down Expand Up @@ -111,6 +110,10 @@ public class Settings : SimpleSettingsBase
"This only changes the <b>default</b> setting. It can also be configured on a per-pawn basis.")]
public bool AutoExecute = true;

[Label("Enemies Can Perform Executions")]
[Description("Can enemies perform execution animations?")]
public bool EnemiesCanExecute = true;

[Label("Automatic Execution Average Interval (Friendly)")]
[Description("This is the average time, in seconds, at which friendly pawns will attempt to start an execution animation on the enemy they are currently fighting.\n" +
"For example, if this is set to 5 and your pawn is fighting in melee, an execution animation will be triggered on average after 5 seconds.\n" +
Expand All @@ -119,11 +122,6 @@ public class Settings : SimpleSettingsBase
[Step(1f)]
public float ExecuteAttemptMTBSeconds = 10;

[Label("Enemies Can Perform Executions")]
[Description("Can enemies perform execution animations?")]
public bool EnemiesCanExecute = true;


[Label("Automatic Execution Average Interval (Enemy)")]
[Description("This is the average time, in seconds, at which enemy pawns will attempt to start an execution animation on the target they are currently fighting.\n" +
"For example, if this is set to 5 and an enemy is fighting in melee, an execution animation will be triggered on average after 5 seconds.\n" +
Expand All @@ -141,10 +139,16 @@ public class Settings : SimpleSettingsBase
[Description("A general modifier on the lethality of execution animations. Higher values make executions more lethal. Affects all pawns.")]
public float ExecutionLethalityModifier = 1f;

[Label("Execution Are Non Lethal On Friendlies")]
[Description("If enabled, execution animations on friendly pawns are always non-lethal regardless of other settings.\nPrisoners are considered friendly.\n\nUseful when trying to stop a mental break or prisoner uprising without causing a bloodbath.")]
[Label("Executions Are Non Lethal On Friendlies")]
[Description("If enabled, execution animations on friendly pawns are always non-lethal regardless of other settings.\nPrisoners and slaves are considered friendly.\n\nUseful when trying to stop a mental break or prisoner uprising without causing a bloodbath.")]
public bool ExecutionsOnFriendliesAreNotLethal = true;

[Label("Execution Armor Strength")]
[Description("A multiplier on the effectiveness of armor when calculating execution animation outcome.\nLower values decrease the effect of armor on the outcome, higher values increase the effect of armor.\nSet to 0% to make armor be ignored.")]
[Percentage]
[Range(0, 3)]
public float ExecutionArmorCoefficient = 1f;

[Description("If true, executions can destroy specific vital body parts, such as the heart or head.\n" +
"If false, the pawn is simply killed by 'magic' (no specific part takes damage)\n" +
"Note: if disabled, combat log generation does not work properly for the execution, and will give a default message: \"<i>name was killed.</i>\"")]
Expand Down Expand Up @@ -268,6 +272,7 @@ public class Settings : SimpleSettingsBase
[Label("Friendly Pawn Lethality Bonus")]
[Description("Positive values act as a lethality bonus for friendly pawns (including slaves) in execution & duel outcomes, meaning that they will be lethal more often.")]
[Percentage]
[Range(-1, 1)]
public float FriendlyPawnLethalityBonus = 0f;

[Label("Friendly Pawn Duel Ability Bonus")]
Expand Down
2 changes: 1 addition & 1 deletion Source/ThingGenerator/Events/Workers/KillPawnWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ private void Injure(AnimEventInput i, Pawn pawn, Pawn killer, KillPawnEvent @eve
DamageDef = @event.DamageDef.AsDefOfType(DamageDefOf.Cut),
LogGenDef = @event.BattleLogDef.AsDefOfType(AM_DefOf.AM_Execution_Generic),
Weapon = killer.GetFirstMeleeWeapon(),
TargetDamageAmount = 20 // TODO pull from animation data, optional args or something along those lines.
TargetDamageAmount = 30 // TODO pull from animation data, optional args or something along those lines.
};

OutcomeUtility.PerformOutcome(ExecutionOutcome.Damage, killer, pawn, args);
Expand Down
11 changes: 5 additions & 6 deletions Source/ThingGenerator/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using AM.Events;
using AM.Events;
using AM.Events.Workers;
using AM.Idle;
using AM.PawnData;
using AM.Reqs;
using AM.Tweaks;
using RimWorld;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using UnityEngine;
using Verse;
using Verse.AI;
Expand Down
Loading

0 comments on commit aa95aed

Please sign in to comment.