Skip to content

Commit

Permalink
2.5.0: Implement spawning of catapult; add console command to spawn m…
Browse files Browse the repository at this point in the history
…ercenaries in with armor; begin preparation for Mac OS X
  • Loading branch information
jpw1991 committed Jun 10, 2024
1 parent 7a0254e commit a5aabf0
Show file tree
Hide file tree
Showing 16 changed files with 268 additions and 97 deletions.
10 changes: 8 additions & 2 deletions ChebsMercenaries/BasePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Security.Cryptography;
using BepInEx;
using BepInEx.Configuration;
using ChebsMercenaries.Commands;
using ChebsMercenaries.Commands.PvP;
using ChebsMercenaries.Items;
using ChebsMercenaries.Minions;
Expand All @@ -25,11 +26,11 @@ public class BasePlugin : BaseUnityPlugin
{
public const string PluginGuid = "com.chebgonaz.chebsmercenaries";
public const string PluginName = "ChebsMercenaries";
public const string PluginVersion = "2.4.0";
public const string PluginVersion = "2.5.0";
private const string ConfigFileName = PluginGuid + ".cfg";
private static readonly string ConfigFileFullPath = Path.Combine(Paths.ConfigPath, ConfigFileName);

public readonly System.Version ChebsValheimLibraryVersion = new("2.6.1");
public readonly System.Version ChebsValheimLibraryVersion = new("2.6.2");

private readonly Harmony harmony = new(PluginGuid);

Expand Down Expand Up @@ -197,6 +198,8 @@ private void Awake()
LoadChebGonazAssetBundle();
harmony.PatchAll();

// PvP commands could've already been added by Cheb's Necromancy or a different mod, therefore we check
// before adding them.
var pvpCommands = new List<ConsoleCommand>()
{ new PvPAddFriend(), new PvPRemoveFriend(), new PvPListFriends() };
foreach (var pvpCommand in pvpCommands)
Expand All @@ -205,6 +208,9 @@ private void Awake()
.ToList().Exists(c => c.Name == pvpCommand.Name))
CommandManager.Instance.AddConsoleCommand(pvpCommand);
}

// No check needed for these because only this mod adds them.
CommandManager.Instance.AddConsoleCommand(new SpawnMerc());

SynchronizationManager.OnConfigurationSynchronized += (obj, attr) =>
{
Expand Down
7 changes: 4 additions & 3 deletions ChebsMercenaries/ChebsMercenaries.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<AssemblyCulture>$(NeutralLanguage)</AssemblyCulture>

<!-- Version Information -->
<Version>2.4.0.0</Version>
<Version>2.5.0.0</Version>
<FileVersion>$(Version)</FileVersion>
<AssemblyVersion>$(Version)</AssemblyVersion>

Expand All @@ -36,8 +36,9 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="ChebsValheimLibrary" Version="2.6.1" />
<PackageReference Include="JotunnLib" Version="2.19.3" />
<PackageReference Include="ChebsValheimLibrary" Version="2.6.2" />
<PackageReference Include="HarmonyX" Version="2.9.0" />
<PackageReference Include="JotunnLib" Version="2.20.1" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
90 changes: 90 additions & 0 deletions ChebsMercenaries/Commands/SpawnMerc.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using ChebsMercenaries.Minions;
using ChebsValheimLibrary.Minions;
using Jotunn.Entities;
using Jotunn.Managers;

namespace ChebsMercenaries.Commands
{
public class SpawnMerc : ConsoleCommand
{
public override string Name => "chebgonaz_spawnmerc";

public override string Help => "Requires admin. Spawn a mercenary. Case insensitive.\n" +
$"Usage: {Name} [TYPE={TypesAsString()}] [ARMOR={ArmorsAsString()}]\n" +
$"eg. {Name} WarriorTier1 Bronze";

private static string TypesAsString()
{
var values = Enum.GetValues(typeof(MercenaryMinion.MercenaryType)).Cast<MercenaryMinion.MercenaryType>();
return string.Join("|", values);
}

private static string ArmorsAsString()
{
var values = Enum.GetValues(typeof(ChebGonazMinion.ArmorType)).Cast<ChebGonazMinion.ArmorType>();
return string.Join("|", values);
}

private static Dictionary<string, MercenaryMinion.MercenaryType> _mercTypeLookup;
private static Dictionary<string, ChebGonazMinion.ArmorType> _armorTypeLookup;

public override void Run(string[] args)
{
if (!SynchronizationManager.Instance.PlayerIsAdmin)
{
Console.instance.Print("Only admins can run this command.");
return;
}

if (args.Length < 1)
{
Console.instance.Print(Help);
return;
}

if (_mercTypeLookup == null)
{
_mercTypeLookup = new Dictionary<string, MercenaryMinion.MercenaryType>();
foreach (MercenaryMinion.MercenaryType mercType in Enum.GetValues(typeof(MercenaryMinion.MercenaryType)))
{
var key = mercType.ToString().ToLower();
_mercTypeLookup.Add(key, mercType);
}
}

if (_armorTypeLookup == null)
{
_armorTypeLookup = new Dictionary<string, ChebGonazMinion.ArmorType>();
foreach (ChebGonazMinion.ArmorType armorType in Enum.GetValues(typeof(ChebGonazMinion.ArmorType)))
{
var key = armorType.ToString().ToLower();
_armorTypeLookup.Add(key, armorType);
}
}

var chosenMerc = MercenaryMinion.MercenaryType.None;
if (!_mercTypeLookup.TryGetValue(args[0].ToLower(), out chosenMerc))
{
Console.instance.Print($"Invalid type: {args[0]}. Valid options: {TypesAsString()}");
return;
}

var chosenArmor = ChebGonazMinion.ArmorType.None;
if (args.Length >= 2)
{
if (!_armorTypeLookup.TryGetValue(args[1].ToLower(), out chosenArmor))
{
Console.instance.Print($"Invalid armor: {args[1]}. Valid options: {ArmorsAsString()}");
return;
}
}

HumanMinion.Spawn(chosenMerc, chosenArmor, Player.m_localPlayer.transform);
}

public override List<string> CommandOptionList()
{
return ZNetScene.instance?.GetPrefabNames();
}
}
}
56 changes: 55 additions & 1 deletion ChebsMercenaries/Minions/CatapultMinion.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
using BepInEx.Configuration;
using ChebsMercenaries.Structure;
using ChebsValheimLibrary.Common;
using Jotunn;
using ChebsValheimLibrary.Minions;
using UnityEngine;
using Logger = Jotunn.Logger;
using Random = System.Random;

namespace ChebsMercenaries.Minions
{
Expand Down Expand Up @@ -46,5 +50,55 @@ protected virtual void ConfigureHealth()
Logger.LogError("Error: Failed to get Humanoid component to set health value.");
}
}

public static void Spawn(Transform spawner)
{
if (ZNetScene.instance == null)
{
Logger.LogWarning("Spawn: ZNetScene.instance is null, trying again later...");
return;
}

var prefab = ZNetScene.instance.GetPrefab(PrefabNames[MercenaryType.Catapult]);
if (!prefab)
{
Logger.LogError($"Spawn: spawning catapult failed - can't find prefab");
return;
}

var spawnedChar = Instantiate(prefab,
spawner.position + spawner.forward * 2f + Vector3.up, Quaternion.identity);

if (spawnedChar == null)
{
Logger.LogError("Spawn: spawnedChar is null");
return;
}

spawnedChar.AddComponent<FreshMinion>();

if (!spawnedChar.TryGetComponent(out ChebGonazMinion minion))
{
Logger.LogError("Spawn: spawnedChar has no ChebGonazMinion component");
return;
}

minion.Roam();

// handle refunding of resources on death
if (DropOnDeath.Value == DropType.Nothing) return;

var characterDrop = spawnedChar.AddComponent<CharacterDrop>();
if (DropOnDeath.Value == DropType.Everything)
{
GenerateDeathDrops(characterDrop, ItemsCost);
}

// the component won't be remembered by the game on logout because
// only what is on the prefab is remembered. Even changes to the prefab
// aren't remembered. So we must write what we're dropping into
// the ZDO as well and then read & restore this on Awake
minion.RecordDrops(characterDrop);
}
}
}
42 changes: 1 addition & 41 deletions ChebsMercenaries/Minions/HumanMinion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,47 +47,7 @@ public class HumanMinion : MercenaryMinion
return cols;
});
}

public enum MercenaryType
{
None,
WarriorTier1,
WarriorTier2,
WarriorTier3,
WarriorTier4,
ArcherTier1,
ArcherTier2,
ArcherTier3,
Miner,
Woodcutter,
}

public static readonly Dictionary<MercenaryType, string> PrefabNames = new()
{
{ MercenaryType.WarriorTier1, "ChebGonaz_HumanWarrior" },
{ MercenaryType.WarriorTier2, "ChebGonaz_HumanWarriorTier2" },
{ MercenaryType.WarriorTier3, "ChebGonaz_HumanWarriorTier3" },
{ MercenaryType.WarriorTier4, "ChebGonaz_HumanWarriorTier4" },
{ MercenaryType.ArcherTier1, "ChebGonaz_HumanArcher" },
{ MercenaryType.ArcherTier2, "ChebGonaz_HumanArcherTier2" },
{ MercenaryType.ArcherTier3, "ChebGonaz_HumanArcherTier3" },
{ MercenaryType.Miner, "ChebGonaz_HumanMiner" },
{ MercenaryType.Woodcutter, "ChebGonaz_HumanWoodcutter" },
};

public static readonly Dictionary<MercenaryType, string> PrefabNamesFemale = new()
{
{ MercenaryType.WarriorTier1, "ChebGonaz_HumanWarriorFemale" },
{ MercenaryType.WarriorTier2, "ChebGonaz_HumanWarriorTier2Female" },
{ MercenaryType.WarriorTier3, "ChebGonaz_HumanWarriorTier3Female" },
{ MercenaryType.WarriorTier4, "ChebGonaz_HumanWarriorTier4Female" },
{ MercenaryType.ArcherTier1, "ChebGonaz_HumanArcherFemale" },
{ MercenaryType.ArcherTier2, "ChebGonaz_HumanArcherTier2Female" },
{ MercenaryType.ArcherTier3, "ChebGonaz_HumanArcherTier3Female" },
{ MercenaryType.Miner, "ChebGonaz_HumanMinerFemale" },
{ MercenaryType.Woodcutter, "ChebGonaz_HumanWoodcutterFemale" },
};


public sealed override void Awake()
{
base.Awake();
Expand Down
44 changes: 44 additions & 0 deletions ChebsMercenaries/Minions/MercenaryMinion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,50 @@ public class MercenaryMinion : ChebGonazMinion
public static ConfigEntry<float> FollowDistance, RunDistance, RoamRange;

public static ConfigEntry<float> Health;

public enum MercenaryType
{
None,
WarriorTier1,
WarriorTier2,
WarriorTier3,
WarriorTier4,
ArcherTier1,
ArcherTier2,
ArcherTier3,
Miner,
Woodcutter,
Catapult,
}

public static readonly Dictionary<MercenaryType, string> PrefabNames = new()
{
{ MercenaryType.WarriorTier1, "ChebGonaz_HumanWarrior" },
{ MercenaryType.WarriorTier2, "ChebGonaz_HumanWarriorTier2" },
{ MercenaryType.WarriorTier3, "ChebGonaz_HumanWarriorTier3" },
{ MercenaryType.WarriorTier4, "ChebGonaz_HumanWarriorTier4" },
{ MercenaryType.ArcherTier1, "ChebGonaz_HumanArcher" },
{ MercenaryType.ArcherTier2, "ChebGonaz_HumanArcherTier2" },
{ MercenaryType.ArcherTier3, "ChebGonaz_HumanArcherTier3" },
{ MercenaryType.Miner, "ChebGonaz_HumanMiner" },
{ MercenaryType.Woodcutter, "ChebGonaz_HumanWoodcutter" },
{ MercenaryType.Catapult, "ChebGonaz_Catapult" },
};

public static readonly Dictionary<MercenaryType, string> PrefabNamesFemale = new()
{
{ MercenaryType.WarriorTier1, "ChebGonaz_HumanWarriorFemale" },
{ MercenaryType.WarriorTier2, "ChebGonaz_HumanWarriorTier2Female" },
{ MercenaryType.WarriorTier3, "ChebGonaz_HumanWarriorTier3Female" },
{ MercenaryType.WarriorTier4, "ChebGonaz_HumanWarriorTier4Female" },
{ MercenaryType.ArcherTier1, "ChebGonaz_HumanArcherFemale" },
{ MercenaryType.ArcherTier2, "ChebGonaz_HumanArcherTier2Female" },
{ MercenaryType.ArcherTier3, "ChebGonaz_HumanArcherTier3Female" },
{ MercenaryType.Miner, "ChebGonaz_HumanMinerFemale" },
{ MercenaryType.Woodcutter, "ChebGonaz_HumanWoodcutterFemale" },
{ MercenaryType.Catapult, "ChebGonaz_Catapult" },
};


public static void CreateConfigs(BasePlugin plugin)
{
Expand Down
2 changes: 1 addition & 1 deletion ChebsMercenaries/Minions/WorkerAI/HumanMinerAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public class HumanMinerAI : MinerAI
{
public override float UpdateDelay => HumanMinerMinion.UpdateDelay.Value;
public override float LookRadius => HumanMinerMinion.LookRadius.Value;
public override float RoamRange => HumanMinion.RoamRange.Value;
public override float RoamRange => MercenaryMinion.RoamRange.Value;
public override string RockInternalIDsList => HumanMinerMinion.RockInternalIDsList.Value;
public override float ToolDamage => HumanMinerMinion.ToolDamage.Value;
public override short ToolTier => HumanMinerMinion.ToolTier.Value;
Expand Down
2 changes: 1 addition & 1 deletion ChebsMercenaries/Minions/WorkerAI/HumanWoodcutterAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public class HumanWoodcutterAI : WoodcutterAI
{
public override float UpdateDelay => HumanWoodcutterMinion.UpdateDelay.Value;
public override float LookRadius => HumanWoodcutterMinion.LookRadius.Value;
public override float RoamRange => HumanMinion.RoamRange.Value;
public override float RoamRange => MercenaryMinion.RoamRange.Value;
public override float ToolDamage => HumanWoodcutterMinion.ToolDamage.Value;
public override short ToolTier => HumanWoodcutterMinion.ToolTier.Value;
public override float ChatInterval => HumanWoodcutterMinion.ChatInterval.Value;
Expand Down
2 changes: 1 addition & 1 deletion ChebsMercenaries/Package/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ChebsMercenaries",
"description": "Cheb's Mercenaries adds mercenaries to Valheim that you can purchase with gold and upgrade with materials to fight (warriors, archers) or perform work (lumberjacks, miners).",
"version_number": "2.4.0",
"version_number": "2.5.0",
"website_url": "https://github.com/jpw1991/chebs-mercenaries",
"dependencies": [
"ValheimModding-Jotunn-2.19.3"
Expand Down
2 changes: 1 addition & 1 deletion ChebsMercenaries/Patches/TameablePatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static bool InteractPrefix(Humanoid user, bool hold, bool alt, Tameable __instan
return false; // deny base method completion
}

if (!HumanMinion.Commandable.Value)
if (!MercenaryMinion.Commandable.Value)
{
return false; // deny base method completion
}
Expand Down
Loading

0 comments on commit a5aabf0

Please sign in to comment.