Decompiled source of HaldorBounties v0.0.1

HaldorBounties.dll

Decompiled 10 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HaldorOverhaul;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HaldorBounties
{
	public class BountyEntry
	{
		public string Id = "";

		public string Title = "";

		public string Description = "";

		public string Type = "Kill";

		public string Target = "";

		public int Amount = 1;

		public int Reward = 50;

		public string RequiredBoss = "";

		public int SpawnLevel;

		public string Tier = "Easy";

		public int Gender;
	}
	internal class ConfigWrapper
	{
		public int Version;

		public List<BountyEntry> Bounties;
	}
	public static class BountyConfig
	{
		private struct KillDef
		{
			public string Id;

			public string Title;

			public string Desc;

			public string Target;

			public int Amount;

			public int Reward;
		}

		private struct MinibossDef
		{
			public string Id;

			public string Title;

			public string Desc;

			public int Reward;

			public int Gender;
		}

		private struct RaidDef
		{
			public string Id;

			public string Title;

			public string Desc;

			public int Amount;

			public int Reward;
		}

		private const int CurrentConfigVersion = 2;

		private static string _configPath;

		public static List<BountyEntry> Bounties { get; private set; } = new List<BountyEntry>();


		public static void Initialize(string configPath)
		{
			_configPath = configPath;
			if (File.Exists(_configPath))
			{
				try
				{
					ConfigWrapper configWrapper = JsonConvert.DeserializeObject<ConfigWrapper>(File.ReadAllText(_configPath));
					if (configWrapper != null && configWrapper.Version >= 2 && configWrapper.Bounties != null && configWrapper.Bounties.Count > 0)
					{
						Bounties = configWrapper.Bounties;
						ValidateEntries();
						HaldorBounties.Log.LogInfo((object)$"[BountyConfig] Loaded {Bounties.Count} bounties (v{configWrapper.Version}).");
						return;
					}
					int num = configWrapper?.Version ?? 0;
					HaldorBounties.Log.LogInfo((object)$"[BountyConfig] Config version {num} < {2}, regenerating.");
				}
				catch (Exception ex)
				{
					HaldorBounties.Log.LogWarning((object)("[BountyConfig] Failed to load config: " + ex.Message + ". Using defaults."));
				}
			}
			Bounties = BuildDefaultBounties();
			ValidateEntries();
			SaveToFile();
			HaldorBounties.Log.LogInfo((object)$"[BountyConfig] Generated {Bounties.Count} default bounties (v{2}).");
		}

		private static void ValidateEntries()
		{
			foreach (BountyEntry bounty in Bounties)
			{
				if ((bounty.Tier == "Miniboss" || bounty.Tier == "Raid") && bounty.SpawnLevel < 1)
				{
					HaldorBounties.Log.LogWarning((object)$"[BountyConfig] Entry '{bounty.Id}' is {bounty.Tier} but SpawnLevel={bounty.SpawnLevel}, fixing to 1.");
					bounty.SpawnLevel = 1;
				}
			}
		}

		private static void SaveToFile()
		{
			try
			{
				string contents = JsonConvert.SerializeObject((object)new ConfigWrapper
				{
					Version = 2,
					Bounties = Bounties
				}, (Formatting)1);
				string directoryName = Path.GetDirectoryName(_configPath);
				if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				File.WriteAllText(_configPath, contents);
			}
			catch (Exception ex)
			{
				HaldorBounties.Log.LogWarning((object)("[BountyConfig] Failed to save config: " + ex.Message));
			}
		}

		private static List<BountyEntry> BuildDefaultBounties()
		{
			List<BountyEntry> list = new List<BountyEntry>();
			AddKillBounties(list, "", "Easy", K("m_greyling_1", "Skogvættr's Brood", "The grey ones crawl from the earth like maggots from a wound. Haldor's caravans cannot pass.", "Greyling", 5, 25), K("m_greyling_2", "Scourge of the Glade", "Greylings swarm the meadow in numbers unseen. The roads must be cleared by steel.", "Greyling", 12, 50), K("m_neck_1", "Serpents of the Shallows", "Necks snap at wading travelers along every shore. Make the riverbanks safe again.", "Neck", 5, 30), K("m_neck_2", "Fang-Water", "Every stream and pond teems with Necks grown bold on easy prey.", "Neck", 12, 60), K("m_boar_1", "Tusks of the Wildwood", "Feral boars gore anyone who strays from the paths. Cull them before they breed further.", "Boar", 8, 40), K("m_boar_2", "Razorback Rampage", "The boars have gone berserk — tusks bloody, eyes wild. Something in the meadow drives them mad.", "Boar", 15, 75), K("m_deer_1", "Eikthyr's Offering", "Haldor craves fresh venison for his stores. Track the swiftest deer and bring them down.", "Deer", 5, 30), K("m_deer_2", "The Great Hunt", "A proper hunt worthy of song — enough deer to feast a warband.", "Deer", 12, 60), K("m_greyling_3", "Grey Tide Rising", "An enormous colony festers beneath the meadow roots. Burn them out.", "Greyling", 20, 80), K("m_neck_3", "Jaws of the Runoff", "The Neck swarms have grown beyond all reckoning. The waterways belong to them now — take them back.", "Neck", 20, 90));
			AddMinibossBounties(list, "", "HB_BountyNpc_T1", MB("mb_m_m1", "The Oath-Breaker", "A disgraced warrior haunts the crossroads, challenging travelers to holmgang they cannot refuse.", 200, 1), MB("mb_m_f1", "Grelka the Scavenger", "A scarred deserter raids supply caches by moonlight, leaving only bones and ash.", 220, 2), MB("mb_m_m2", "Bjolf Stone-Fist", "A hulking brute blocks the meadow crossing, demanding tribute in blood.", 210, 1), MB("mb_m_f2", "Runa Thorn-Heart", "An exile who fights like the wild creatures she lives among — without mercy.", 230, 2), MB("mb_m_m3", "The Nithing", "An outlaw branded with the mark of shame. He has nothing left to lose.", 200, 1), MB("mb_m_f3", "Ylva Grass-Viper", "She strikes from the tall grass and vanishes before the blood dries.", 240, 2), MB("mb_m_m4", "Vagn the Wanderer", "A drifting sellsword who cuts down anyone foolish enough to draw steel.", 210, 1), MB("mb_m_f4", "Sigrid Dawn-Stalker", "She hunts at first light when travelers are bleary-eyed and careless.", 250, 2), MB("mb_m_m5", "Keld Flint-Fang", "Armed with crude but wicked weapons shaped from the meadow's stones.", 200, 1), MB("mb_m_f5", "Inga Way-Finder", "A former merchant who knows every road — and the best places to ambush them.", 230, 2));
			AddRaidBounties(list, "", "HB_BountyNpc_T1", RD("rd_m_1", "Oath-Breakers' Warband", "A pack of disgraced warriors roam the meadow seeking plunder and redemption through blood.", 3, 350), RD("rd_m_2", "Outlaws of the Glade", "Desperate exiles have sworn a blood-oath and banded together. They answer to no jarl.", 4, 500), RD("rd_m_3", "Road-Wolves", "Bandits who prey on lone travelers, picking the roads clean like carrion birds.", 3, 400), RD("rd_m_4", "Camp-Burners", "Firebrands who torch camps and steal every scrap. Smoke marks their passing.", 4, 550), RD("rd_m_5", "Meadow Reavers", "A gang of marauders terrorizes the open fields, emboldened by their easy prey.", 3, 380), RD("rd_m_6", "The Landless", "Exiled warriors stripped of name and land, fighting with the fury of those who have nothing.", 4, 480), RD("rd_m_7", "Grey-Herders", "Outlaws who drive Greylings before them as scouts and distractions.", 3, 420), RD("rd_m_8", "Crossroad Kinsmen", "They control every crossroad in the meadows, demanding toll in steel.", 4, 520), RD("rd_m_9", "Dusk-Prowlers", "They strike at twilight when the shadows grow long and eyes grow dim.", 3, 400), RD("rd_m_10", "The Hunger-Sworn", "Starving raiders who have sworn to take what they need or die fighting.", 4, 500));
			AddKillBounties(list, "defeated_eikthyr", "Easy", K("bf_greydwarf_1", "Eyes in the Undergrowth", "Greydwarf scouts watch every road through the forest with hollow, hateful eyes.", "Greydwarf", 8, 50), K("bf_greydwarf_2", "Root and Ruin", "A Greydwarf horde gathers beneath the ancient roots. If left unchecked, the forest will be lost.", "Greydwarf", 20, 120), K("bf_brute_1", "The Trunk-Breakers", "Greydwarf Brutes have blockaded the crossings, smashing carts and travelers alike.", "Greydwarf_Elite", 3, 90), K("bf_brute_2", "Timber Crushers", "Packs of Brutes lumber through the forest, toppling trees and crushing all who flee.", "Greydwarf_Elite", 6, 160), K("bf_shaman_1", "Menders of the Dark", "Shamans knit wounds with foul sap-magic, making the hordes near-unkillable.", "Greydwarf_Shaman", 3, 80), K("bf_shaman_2", "Curse-Weavers", "Their poison magic sustains entire warbands. Cut down the shamans and the rest will follow.", "Greydwarf_Shaman", 6, 140), K("bf_skeleton_1", "The Restless Dead", "Skeletons wander far beyond their burial mounds, rattling through the darkened woods.", "Skeleton", 8, 60), K("bf_skeleton_2", "Crypt-Purge", "The burial chambers overflow with the risen dead. Someone must seal them back in.", "Skeleton", 15, 110), K("bf_troll_1", "Bridge-Breaker", "A Troll has claimed a vital forest bridge. Travelers detour for half a day to avoid it.", "Troll", 1, 90), K("bf_ghost_1", "The Barrow-Haunts", "Spirits of the ancient dead drift through the old burial sites, hungering for warmth.", "Ghost", 5, 120));
			AddMinibossBounties(list, "defeated_eikthyr", "HB_BountyNpc_T2", MB("mb_bf_m1", "Grimjaw the Brigand", "A cunning forest brigand who preys on miners hauling ore from the deep woods.", 500, 1), MB("mb_bf_f1", "Hild Iron-Maiden", "A shieldmaiden turned bandit queen. She takes what she wants and burns the rest.", 550, 2), MB("mb_bf_m2", "Torolf Deepwood-Warden", "He demands blood-tribute from anyone who sets foot in his claimed territory.", 580, 1), MB("mb_bf_f2", "Bodil Root-Witch", "Clad in living root-armor, she fights with a ferocity that is not entirely human.", 600, 2), MB("mb_bf_m3", "Ketill Copper-King", "A miner who found it easier to kill for ore than to dig for it.", 520, 1), MB("mb_bf_f3", "Alva Shadow-Fern", "She vanishes into the undergrowth after every kill. No tracker has found her camp.", 560, 2), MB("mb_bf_m4", "Ulf Troll-Tamer", "He fights alongside trained Greydwarves and knows every hollow in the forest.", 620, 1), MB("mb_bf_f4", "Svala Dark-Bark", "Covered in bark and moss, she has become one with the black forest.", 640, 2), MB("mb_bf_m5", "Hreidar Stone-Breaker", "A massive warrior who shatters shields with a single blow of his bronze mace.", 580, 1), MB("mb_bf_f5", "Jorunn Night-Shade", "She tips her blades in poison brewed from forest fungi. Death comes slowly.", 650, 2));
			AddRaidBounties(list, "defeated_eikthyr", "HB_BountyNpc_T2", RD("rd_bf_1", "The Iron Ambush", "Brigands with iron weapons lie in wait along the forest road, hungry for blood and bronze.", 3, 750), RD("rd_bf_2", "Root-Clad War Party", "A war party in root armor has fortified a ruin in the heart of the forest.", 4, 1000), RD("rd_bf_3", "Troll-Hide Gang", "Outlaws clad in troll leather who strike without warning and vanish into the trees.", 3, 850), RD("rd_bf_4", "Crypt-Plunderers", "Grave-robbers who kill any witness. They've grown rich — and dangerous.", 4, 950), RD("rd_bf_5", "Forest Kinslayers", "Reavers who know every path through the black wood and use them to deadly effect.", 3, 780), RD("rd_bf_6", "The Bronze Brotherhood", "Deserters bound by oath and bronze, they answer challenges with axe and shield.", 4, 900), RD("rd_bf_7", "Timber-Wolves", "They ambush loggers and steal their haul. The forest roads are theirs.", 3, 800), RD("rd_bf_8", "Flame-Sworn Cult", "Outlaws who worship the Surtling flame and carry cores as holy relics.", 4, 1050), RD("rd_bf_9", "The Undergrowth", "They hide in the brush and strike from below. You'll never see the blade that kills you.", 3, 820), RD("rd_bf_10", "Darkwood Huskarls", "A warband of hardened killers who take no prisoners and leave no survivors.", 4, 1100));
			AddKillBounties(list, "defeated_gdking", "Medium", K("sw_draugr_1", "The Walking Dead", "Draugr shuffle near the borders, testing the living with dead hands and rusty steel.", "Draugr", 8, 120), K("sw_draugr_2", "Dead Tide", "The swamp crawls with Draugr rising in numbers not seen since the old wars.", "Draugr", 18, 250), K("sw_elite_1", "Grave-Knights", "Draugr Elites clad in ancient iron lead raiding parties out of the sunken crypts.", "Draugr_Elite", 3, 180), K("sw_elite_2", "Wight Purge", "Draugr Elites have risen in alarming numbers. The dead outnumber the living.", "Draugr_Elite", 6, 320), K("sw_blob_1", "Bile-Cleansing", "Poisonous Blobs ooze through the bog, leaving trails of rot that kill the very earth.", "Blob", 8, 120), K("sw_wraith_1", "Fog-Wraiths", "Wraiths materialize from the mire-fog, their wailing a death-knell for the unwary.", "Wraith", 3, 220), K("sw_leech_1", "Blood-Drinkers", "Giant Leeches infest every body of stagnant water. Wading is a death sentence.", "Leech", 10, 130), K("sw_surtling_1", "Geyser-Flames", "Surtlings blaze near the fire geysers, scorching anyone who seeks their cores.", "Surtling", 8, 130), K("sw_abom_1", "Root-Horror", "An Abomination has torn itself free of the muck. The ground shakes with its fury.", "Abomination", 1, 180), K("sw_abom_2", "The Great Uprooting", "Multiple Abominations tear through the swamp. The land itself has turned hostile.", "Abomination", 3, 420));
			AddMinibossBounties(list, "defeated_gdking", "HB_BountyNpc_T3", MB("mb_sw_m1", "Halvard Bog-Stalker", "Born in the mire, he fights with ruthless cunning. The Draugr fear his iron.", 1000, 1), MB("mb_sw_f1", "Groa the Drowned Queen", "Even the walking dead give this one a wide berth. She rules the sunken places.", 1100, 2), MB("mb_sw_m2", "Vidar Crypt-Breaker", "His silver blade drips with undead ichor — he has slain many, and will slay you next.", 1200, 1), MB("mb_sw_f2", "Thora Mire-Witch", "She commands the swamp-fog itself as a weapon, blinding her prey before the kill.", 1150, 2), MB("mb_sw_m3", "Eindride Rot-Walker", "He wades through poison without flinching, armored in leather cured with grave-wax.", 1050, 1), MB("mb_sw_f3", "Hervor Iron-Widow", "She lost every shield-brother to the swamp. Now she seeks vengeance on all who live.", 1250, 2), MB("mb_sw_m4", "Gorm the Undertaker", "He buries his victims in the mud where they rise again to serve him.", 1100, 1), MB("mb_sw_f4", "Solveig Mire-Singer", "Her voice carries through the fog, luring travelers into the drowning-deeps.", 1300, 2), MB("mb_sw_m5", "Bjarke Leech-Lord", "The bloodsuckers seem to obey his whispered commands. He is more swamp than man.", 1150, 1), MB("mb_sw_f5", "Vigdis Guck-Weaver", "She crafts traps from swamp-filth that would make a Draugr recoil.", 1200, 2));
			AddRaidBounties(list, "defeated_gdking", "HB_BountyNpc_T3", RD("rd_sw_1", "Silver Marauders", "Silver-clad raiders stalk the mist-shrouded bogs, hunting for worthy prey.", 3, 1500), RD("rd_sw_2", "The Drowned Company", "Battle-hardened and half-mad from the swamp. They fight as if already dead.", 4, 2000), RD("rd_sw_3", "Mire-Reavers", "They use the fog like a war-cloak, striking from the murk and melting away.", 3, 1800), RD("rd_sw_4", "Crypt-Raiders", "Tomb raiders armed with grave-plunder. They kill any witness to their sacrilege.", 4, 1900), RD("rd_sw_5", "The Rotting Hand", "Warriors who have embraced the swamp's decay and wear it like battle-paint.", 3, 1600), RD("rd_sw_6", "Bog-Runners", "Fast and lethal, they vault across the muck while their prey sinks and drowns.", 4, 2100), RD("rd_sw_7", "The Iron Tide", "An iron-clad warband pushing through the swamp, crushing all in their path.", 3, 1700), RD("rd_sw_8", "The Sunken Ones", "They emerge from black water where no man should survive. No one knows how.", 4, 2200), RD("rd_sw_9", "Wraith-Pact Warriors", "Warriors who have sworn oaths to the swamp spirits. They do not die easily.", 3, 1650), RD("rd_sw_10", "Mire-Wolves", "A wolfpack of fighters who hunt in formation through the sucking bog.", 4, 2300));
			AddKillBounties(list, "defeated_bonemass", "Medium", K("mt_wolf_1", "Fenrir's Get", "A wolf pack descends on climbers with fangs bared and frost on their breath.", "Wolf", 5, 150), K("mt_wolf_2", "Blood on the Snow", "The mountain is overrun — wolves howl from every ridge and ravine.", "Wolf", 15, 350), K("mt_drake_1", "Ice-Wyrm Hunters", "Frost Drakes rain shards of ice on anyone below. The skies are not safe.", "Hatchling", 5, 190), K("mt_drake_2", "Storm of Wings", "The skies are thick with Drakes. They must be thinned before passage is possible.", "Hatchling", 10, 340), K("mt_golem_1", "Stone-Breaker", "A Stone Golem blocks the mountain pass, grinding boulders in its fists.", "StoneGolem", 1, 200), K("mt_golem_2", "Walking Avalanche", "Multiple Golems descend the slopes, crushing everything in their grinding path.", "StoneGolem", 3, 420), K("mt_fenring_1", "Moon-Hunters", "Fenrings emerge under the cold stars, their howls echoing off the peaks.", "Fenring", 3, 340), K("mt_ulv_1", "Ghost-Wolves", "Ulvs haunt the mountain caves, spectral and savage in equal measure.", "Ulv", 5, 280), K("mt_bat_1", "The Shrieking Dark", "Swarms of bats pour from mountain caves, blotting out the light.", "Bat", 10, 150), K("mt_wolf_3", "Howling Peaks", "Wolf packs grow dangerously large on the heights. The mountain belongs to them.", "Wolf", 10, 260));
			AddMinibossBounties(list, "defeated_bonemass", "HB_BountyNpc_T4", MB("mb_mt_m1", "Skallagrim Frost-Bitten", "His silver weapons have claimed lives beyond counting. The cold has made him merciless.", 2000, 1), MB("mb_mt_f1", "Astrid Summit-Huntress", "She commands the wolves of the peaks and hunts alongside them.", 2200, 2), MB("mb_mt_m2", "Thorvald Blizzard-Born", "He walks through storms that would bury other men, blade in hand.", 2100, 1), MB("mb_mt_f2", "Brynhild the Avalanche", "She has crushed more challengers than any golem on the mountain.", 2400, 2), MB("mb_mt_m3", "Egil Frost-Warden", "Self-proclaimed guardian of the high passes. He lets no one through alive.", 2050, 1), MB("mb_mt_f3", "Eira Ice-Whisper", "She moves silently through the snow. Her victims never hear the killing blow.", 2300, 2), MB("mb_mt_m4", "Hallbjorn Peak-Breaker", "He breaks through shield-walls with the force of a mountain gale.", 2500, 1), MB("mb_mt_f4", "Dagny Crystal-Edge", "Her crystal-tipped weapons cut through armor as if it were cloth.", 2600, 2), MB("mb_mt_m5", "Arne the Cold One", "He feels nothing — not frost, not pain, not mercy.", 2150, 1), MB("mb_mt_f5", "Sif Storm-Caller", "She fights hardest when the blizzard howls, as if the storm answers her will.", 2350, 2));
			AddRaidBounties(list, "defeated_bonemass", "HB_BountyNpc_T4", RD("rd_mt_1", "Frost-Reavers", "Black metal glints in the cold air. These warriors have slain dragons for their steel.", 3, 3000), RD("rd_mt_2", "Summit Warhost", "They hold the highest peaks and challenge any fool who dares ascend.", 4, 4200), RD("rd_mt_3", "Blizzard Fangs", "They attack only during storms, invisible until the killing blow.", 3, 3500), RD("rd_mt_4", "The Summit-Guard", "Elite warriors sworn to hold the peaks against all comers. They have never broken.", 4, 4000), RD("rd_mt_5", "Silver Brotherhood", "Bound by silver and blood-oaths, they fight as one terrible weapon.", 3, 3200), RD("rd_mt_6", "Ulfhednar", "Berserkers who don wolf-skins and fight with the frenzy of Fenrir's children.", 4, 4500), RD("rd_mt_7", "The Frozen Ones", "Warriors who endure any cold, any wound. They do not stop.", 3, 3300), RD("rd_mt_8", "Crystal-Guard", "Armed with obsidian-edged weapons that sing in the frozen air.", 4, 4100), RD("rd_mt_9", "Hrimthursar's Kin", "Frost-touched warriors as unyielding as the mountain itself.", 3, 3400), RD("rd_mt_10", "The High King's Hird", "The finest warriors of the peaks, forged in ice and sworn to death.", 4, 4800));
			AddKillBounties(list, "defeated_dragon", "Hard", K("pl_fuling_1", "Goblin Outriders", "Fuling scouts probe the plains' edges, their crude spears gleaming with malice.", "Goblin", 8, 250), K("pl_fuling_2", "The Great Horde", "A Fuling invasion force marches across the golden fields. The earth trembles.", "Goblin", 25, 600), K("pl_brute_1", "Skull-Crushers", "Fuling Berserkers crush armor like parchment and bone like kindling.", "GoblinBrute", 2, 380), K("pl_brute_2", "The Wrecking Tide", "Multiple Berserkers on a rampage — nothing stands before them.", "GoblinBrute", 4, 650), K("pl_shaman_1", "Flame-Snuffers", "Fuling Shamans channel dark fire-magic that chars flesh and warps iron.", "GoblinShaman", 3, 300), K("pl_squito_1", "Needle-Storm", "Deathsquitos punch through armor with barbed stingers. Death by a thousand needles.", "Deathsquito", 10, 270), K("pl_squito_2", "Plague of Needles", "An overwhelming swarm descends. The buzzing alone drives warriors to madness.", "Deathsquito", 20, 500), K("pl_lox_1", "Beast-Feller", "Lox trample everything beneath their thundering hooves. Even the Fulings flee.", "Lox", 2, 320), K("pl_lox_2", "Thunder Hooves", "A herd of enraged Lox stampedes across the plains, crushing all in their wake.", "Lox", 5, 620), K("pl_tar_1", "Tar-Blight", "Tar Growths spread black corruption from bubbling pits. The land itself sickens.", "BlobTar", 5, 320));
			AddMinibossBounties(list, "defeated_dragon", "HB_BountyNpc_T5", MB("mb_pl_m1", "Ragnar Golden-Bane", "Carapace armor gleams on his shoulders. Even Fuling war-chiefs flee at his approach.", 3200, 1), MB("mb_pl_f1", "Freydis the Conqueress", "Her blade has carved a path through villages and war-camps alike.", 3600, 2), MB("mb_pl_m2", "Styrbjorn Dusk-Reaper", "He strikes at twilight when the golden light blinds. None have seen his face and lived.", 3800, 1), MB("mb_pl_f2", "Gudrun Shield-Maiden", "She fights as if Odin himself watches — because she believes he does.", 4000, 2), MB("mb_pl_m3", "Hakon Sand-Viper", "He strikes from the tall barley like a serpent, silent and lethal.", 3400, 1), MB("mb_pl_f3", "Alfhild Barley-Queen", "She controls the farmlands through fear and fire. The harvest is hers.", 3700, 2), MB("mb_pl_m4", "Bjorn Lox-Breaker", "He charges on foot but hits like a rampaging beast.", 4200, 1), MB("mb_pl_f4", "Ranveig Needle-Dancer", "She weaves through combat like a Deathsquito — impossible to pin down.", 3900, 2), MB("mb_pl_m5", "Jarl Skuli the Bloody", "A self-proclaimed jarl of terrible reputation. His saga is written in blood.", 4500, 1), MB("mb_pl_f5", "Sigrun Golden-Fury", "Fury incarnate on the golden fields. She fights until the plains run red.", 4100, 2));
			AddRaidBounties(list, "defeated_dragon", "HB_BountyNpc_T5", RD("rd_pl_1", "Carapace Raiders", "Clad in chitin-plate with exotic weapons and deadly coordination.", 4, 6000), RD("rd_pl_2", "The Conqueror's Hird", "The deadliest warband in the realm. Songs are sung of those brave enough to face them.", 5, 8500), RD("rd_pl_3", "Dusk-Riders", "They sweep the plains at sunset, silhouettes against the dying light.", 4, 7000), RD("rd_pl_4", "The Golden Host", "An army ablaze on the golden fields. Odin watches this battle.", 5, 9000), RD("rd_pl_5", "Fuling-Slayers", "They hunt Fulings for sport and wear their trophies as war-paint.", 4, 6500), RD("rd_pl_6", "Vanguard of the Fallen", "First into the shield-wall, last to retreat. They know no fear.", 5, 8000), RD("rd_pl_7", "Plains-Wolves", "Fast and lethal across open ground, they run down prey like a wolf pack.", 4, 7500), RD("rd_pl_8", "The Iron Harvest", "They reap what others have sown, and their scythes are sharpened steel.", 5, 9500), RD("rd_pl_9", "Blood-Drenched Veterans", "Survivors of a hundred battles. They fight without hesitation or mercy.", 4, 7200), RD("rd_pl_10", "Sand-Storm Berserkers", "They charge like wind across the plains, howling war-cries to Tyr.", 5, 10000));
			AddKillBounties(list, "defeated_goblinking", "Hard", K("ml_seeker_1", "Hive-Purge", "Seekers strike from the eternal twilight, their mandibles slick with venom.", "Seeker", 8, 420), K("ml_seeker_2", "The Infestation", "Seeker hives spread through every ruin and hollow. The mist breeds them endlessly.", "Seeker", 15, 680), K("ml_brute_1", "Chitin-Cracker", "Seeker Brutes guard the deepest hives, armored in plates that turn steel.", "SeekerBrute", 2, 500), K("ml_brute_2", "Chitin Siege", "Seeker Brutes blockade all passage through the mist. Exploration has ceased.", "SeekerBrute", 4, 880), K("ml_tick_1", "Bloodtick Purge", "Ticks drop from the canopy without warning, draining the life from armored warriors.", "Tick", 10, 360), K("ml_tick_2", "Canopy Scourge", "A plague of Ticks overwhelms even the strongest. The treetops writhe with them.", "Tick", 20, 620), K("ml_gjall_1", "Sky-Terror", "A Gjall rains explosive bile from above, cratering the earth below.", "Gjall", 1, 460), K("ml_gjall_2", "Bombardment", "Multiple Gjall turn the landscape into a cratered wasteland of fire and chitin.", "Gjall", 3, 920), K("ml_dvergr_1", "Rogue Dvergr", "Some Dvergr have turned hostile, wielding arcane weapons of terrible power.", "Dverger", 5, 540), K("ml_seeker_3", "The Deep Hive", "The largest hive pulses beneath the mist. It must be destroyed before it hatches.", "Seeker", 20, 800));
			AddMinibossBounties(list, "defeated_goblinking", "HB_BountyNpc_T6", MB("mb_ml_m1", "Arnbjorn Mist-Phantom", "Even the Seekers recoil from his approach. He is more wraith than warrior.", 5000, 1), MB("mb_ml_f1", "Aslaug the Ash-Born", "The most dangerous bounty ever nailed to Haldor's board. Approach with caution.", 5500, 2), MB("mb_ml_m2", "Fenrir Eitr-Walker", "His weapons hum with raw eitr. One cut festers into something worse than death.", 5800, 1), MB("mb_ml_f2", "Gunnhild Void-Walker", "She wears armor no living smith has ever forged. It moves with her like skin.", 6200, 2), MB("mb_ml_m3", "Snorri Mist-Reaver", "He strikes from the fog and vanishes, leaving only corpses and silence.", 5200, 1), MB("mb_ml_f3", "Torhild Seeker-Queen", "She moves like a Seeker but thinks like a war-chief. The worst of both worlds.", 6000, 2), MB("mb_ml_m4", "Floki the Dvergr-Touched", "Trained by the Dvergr in arts no human should know. His weapons defy nature.", 5600, 1), MB("mb_ml_f4", "Hallveig Chitin-Empress", "Carapace armor fused with eitr-magic. She is the mist made flesh.", 6500, 2), MB("mb_ml_m5", "Hrolf Shadow-Blade", "His blade drinks the light itself. You will not see the edge that ends you.", 5400, 1), MB("mb_ml_f5", "Sigrid Mist-Walker", "She has walked deeper into the mist than any living soul — and returned changed.", 6800, 2));
			AddRaidBounties(list, "defeated_goblinking", "HB_BountyNpc_T6", RD("rd_ml_1", "Flametal Brotherhood", "Their weapons blaze with flametal fire. Their coordinated assaults are devastating.", 4, 8500), RD("rd_ml_2", "Ashlands Vanguard", "An army unto themselves, forged in realms beyond the mist.", 5, 12000), RD("rd_ml_3", "The Void-Pact", "They fight in eerie silence, communicating without words. Unnerving and lethal.", 4, 9500), RD("rd_ml_4", "The Last Legion", "Flametal from helm to heel. The final obstacle between you and legend.", 5, 14000), RD("rd_ml_5", "Mist-Walkers", "They emerge from the fog as one, a wall of steel and eitr-glow.", 4, 9000), RD("rd_ml_6", "Eitr-Guard", "Their weapons crackle with eitr energy that burns through any defense.", 5, 13000), RD("rd_ml_7", "Chitin-Sworn", "Warriors bound in Seeker chitin who have surrendered their humanity.", 4, 10000), RD("rd_ml_8", "The Forgotten", "No saga remembers their names. Few who face them survive to sing one.", 5, 15000), RD("rd_ml_9", "Deep Patrol", "They patrol the deepest, darkest reaches of the mist where no light penetrates.", 4, 9800), RD("rd_ml_10", "Ragnarok's Herald", "The final challenge for any Viking who would earn a seat in Valhalla.", 5, 16000));
			return list;
		}

		private static KillDef K(string id, string title, string desc, string target, int amount, int reward)
		{
			KillDef result = default(KillDef);
			result.Id = id;
			result.Title = title;
			result.Desc = desc;
			result.Target = target;
			result.Amount = amount;
			result.Reward = reward;
			return result;
		}

		private static MinibossDef MB(string id, string title, string desc, int reward, int gender)
		{
			MinibossDef result = default(MinibossDef);
			result.Id = id;
			result.Title = title;
			result.Desc = desc;
			result.Reward = reward;
			result.Gender = gender;
			return result;
		}

		private static RaidDef RD(string id, string title, string desc, int amount, int reward)
		{
			RaidDef result = default(RaidDef);
			result.Id = id;
			result.Title = title;
			result.Desc = desc;
			result.Amount = amount;
			result.Reward = reward;
			return result;
		}

		private static void AddKillBounties(List<BountyEntry> list, string boss, string tier, params KillDef[] defs)
		{
			for (int i = 0; i < defs.Length; i++)
			{
				KillDef killDef = defs[i];
				list.Add(new BountyEntry
				{
					Id = killDef.Id,
					Title = killDef.Title,
					Description = killDef.Desc,
					Type = "Kill",
					Target = killDef.Target,
					Amount = killDef.Amount,
					Reward = killDef.Reward,
					RequiredBoss = boss,
					Tier = tier
				});
			}
		}

		private static void AddMinibossBounties(List<BountyEntry> list, string boss, string target, params MinibossDef[] defs)
		{
			for (int i = 0; i < defs.Length; i++)
			{
				MinibossDef minibossDef = defs[i];
				list.Add(new BountyEntry
				{
					Id = minibossDef.Id,
					Title = minibossDef.Title,
					Description = minibossDef.Desc,
					Type = "Kill",
					Target = target,
					Amount = 1,
					Reward = minibossDef.Reward,
					RequiredBoss = boss,
					SpawnLevel = 1,
					Tier = "Miniboss",
					Gender = minibossDef.Gender
				});
			}
		}

		private static void AddRaidBounties(List<BountyEntry> list, string boss, string target, params RaidDef[] defs)
		{
			for (int i = 0; i < defs.Length; i++)
			{
				RaidDef raidDef = defs[i];
				list.Add(new BountyEntry
				{
					Id = raidDef.Id,
					Title = raidDef.Title,
					Description = raidDef.Desc,
					Type = "Kill",
					Target = target,
					Amount = raidDef.Amount,
					Reward = raidDef.Reward,
					RequiredBoss = boss,
					SpawnLevel = 1,
					Tier = "Raid"
				});
			}
		}
	}
	[BepInPlugin("com.haldor.bounties", "Haldor Bounties", "0.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class HaldorBounties : BaseUnityPlugin
	{
		public const string PluginGUID = "com.haldor.bounties";

		public const string PluginName = "Haldor Bounties";

		public const string PluginVersion = "0.0.1";

		private static Harmony _harmony;

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"Haldor Bounties v0.0.1 loading...");
			BountyConfig.Initialize(Path.Combine(Paths.ConfigPath, "HaldorBounties.bounties.json"));
			BountyManager.Initialize();
			_harmony = new Harmony("com.haldor.bounties");
			try
			{
				_harmony.PatchAll(Assembly.GetExecutingAssembly());
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"[HaldorBounties] Harmony PatchAll failed: {arg}");
			}
			int num = 0;
			foreach (MethodBase patchedMethod in _harmony.GetPatchedMethods())
			{
				_ = patchedMethod;
				num++;
			}
			Log.LogInfo((object)string.Format("{0} loaded successfully! ({1} methods patched)", "Haldor Bounties", num));
		}

		private void Update()
		{
			BountyManager.Instance?.UpdateBountyPins();
			BountyManager.Instance?.UpdateBossHudRange();
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"Haldor Bounties unloaded.");
			}
		}
	}
	public enum BountyState
	{
		Available,
		Active,
		Ready,
		Claimed
	}
	public class BountyManager
	{
		private const string StateKeyPrefix = "HaldorBounty_State_";

		private const string ProgressKeyPrefix = "HaldorBounty_Progress_";

		private const string BossNameKeyPrefix = "HaldorBounty_BossName_";

		private const string SpawnPosKeyPrefix = "HaldorBounty_SpawnPos_";

		private const string BankDataKey = "TraderSharedBank_Balance";

		private const string BankLegacyHaldor = "HaldorBank_Balance";

		private const string BankLegacyHildir = "HildirBank_Balance";

		private const string BankLegacyBogWitch = "BogWitchBank_Balance";

		private const string LastDayKey = "HaldorBounty_LastDay";

		private MethodInfo _reloadBankBalance;

		private MethodInfo _getTraderUI;

		private int _lastDay = -1;

		private readonly Dictionary<string, PinData> _bountyPins = new Dictionary<string, PinData>();

		private readonly Dictionary<string, Character> _bountyCreatures = new Dictionary<string, Character>();

		private readonly HashSet<string> _activeBountyIds = new HashSet<string>();

		private bool _activeBountyIdsLoaded;

		private readonly Dictionary<string, BountyEntry> _bountyLookup;

		private static readonly string[] MaleNames = new string[45]
		{
			"Ragnar", "Sigurd", "Gunnar", "Halvard", "Agnar", "Torstein", "Ottar", "Ivar", "Bjarke", "Torbjorn",
			"Thorvald", "Styrbjorn", "Ketil", "Hakon", "Erling", "Folkvar", "Geir", "Vidar", "Grimolf", "Thorgrim",
			"Rolf", "Orm", "Asmund", "Einar", "Hjalmar", "Dag", "Bodvar", "Ulf", "Bjorn", "Erik",
			"Leif", "Skallagrim", "Hrothgar", "Bragi", "Kolbein", "Trygve", "Arnbjorn", "Gudmund", "Fenrir", "Alfgeir",
			"Skuli", "Hrolf", "Guthorm", "Snorri", "Floki"
		};

		private static readonly string[] FemaleNames = new string[30]
		{
			"Valdis", "Freya", "Brynhild", "Solveig", "Ingrid", "Ragnhild", "Hervor", "Svanhild", "Jorunn", "Alva",
			"Astrid", "Sigrid", "Thyra", "Helga", "Sif", "Gudrun", "Ylva", "Thora", "Hilde", "Embla",
			"Vigdis", "Eira", "Gunnhild", "Dagny", "Aslaug", "Alfhild", "Ranveig", "Sigrun", "Torhild", "Hallveig"
		};

		private static Sprite _bountyIcon;

		public static BountyManager Instance { get; private set; }

		private BountyManager()
		{
			_bountyLookup = new Dictionary<string, BountyEntry>(BountyConfig.Bounties.Count);
			foreach (BountyEntry bounty in BountyConfig.Bounties)
			{
				_bountyLookup[bounty.Id] = bounty;
			}
		}

		public static void Initialize()
		{
			Instance = new BountyManager();
			Instance.CacheReflection();
		}

		public bool TryGetEntry(string bountyId, out BountyEntry entry)
		{
			return _bountyLookup.TryGetValue(bountyId, out entry);
		}

		private void CacheReflection()
		{
			try
			{
				Type type = Type.GetType("HaldorOverhaul.TraderUI, HaldorOverhaul");
				if (type != null)
				{
					_reloadBankBalance = type.GetMethod("ReloadBankBalance", BindingFlags.Instance | BindingFlags.Public);
				}
				Type type2 = Type.GetType("HaldorOverhaul.ControlPatches, HaldorOverhaul");
				if (type2 != null)
				{
					_getTraderUI = type2.GetMethod("GetTraderUI", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				}
				if (_getTraderUI == null)
				{
					HaldorBounties.Log.LogWarning((object)"[BountyManager] GetTraderUI not found — bank balance will not refresh on coin reward.");
				}
				if (_reloadBankBalance == null)
				{
					HaldorBounties.Log.LogWarning((object)"[BountyManager] ReloadBankBalance not found — bank balance will not refresh on coin reward.");
				}
			}
			catch (Exception ex)
			{
				HaldorBounties.Log.LogWarning((object)("[BountyManager] Reflection cache failed: " + ex.Message));
			}
		}

		private void EnsureActiveBountyIdsLoaded()
		{
			if (_activeBountyIdsLoaded)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			_activeBountyIds.Clear();
			foreach (KeyValuePair<string, string> customDatum in localPlayer.m_customData)
			{
				if (customDatum.Key.StartsWith("HaldorBounty_State_") && customDatum.Value == "active")
				{
					_activeBountyIds.Add(customDatum.Key.Substring("HaldorBounty_State_".Length));
				}
			}
			_activeBountyIdsLoaded = true;
		}

		public int GetCurrentDay()
		{
			if ((Object)(object)EnvMan.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null)
			{
				return 0;
			}
			return EnvMan.instance.GetDay(ZNet.instance.GetTimeSeconds());
		}

		public void CheckDayReset()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			int currentDay = GetCurrentDay();
			if (currentDay <= 0)
			{
				return;
			}
			if (_lastDay < 0)
			{
				if (localPlayer.m_customData.TryGetValue("HaldorBounty_LastDay", out var value) && int.TryParse(value, out var result))
				{
					_lastDay = result;
				}
				else
				{
					_lastDay = currentDay;
				}
			}
			if (currentDay == _lastDay)
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, string> customDatum in localPlayer.m_customData)
			{
				if (customDatum.Key.StartsWith("HaldorBounty_State_") && customDatum.Value == "claimed")
				{
					list.Add(customDatum.Key);
				}
			}
			foreach (string item in list)
			{
				localPlayer.m_customData.Remove(item);
			}
			foreach (string item2 in list)
			{
				string text = item2.Substring("HaldorBounty_State_".Length);
				localPlayer.m_customData.Remove("HaldorBounty_Progress_" + text);
				localPlayer.m_customData.Remove("HaldorBounty_BossName_" + text);
				localPlayer.m_customData.Remove("HaldorBounty_SpawnPos_" + text);
			}
			_lastDay = currentDay;
			localPlayer.m_customData["HaldorBounty_LastDay"] = currentDay.ToString();
			_activeBountyIdsLoaded = false;
			EnsureActiveBountyIdsLoaded();
			HaldorBounties.Log.LogInfo((object)$"[BountyManager] New day {currentDay} — reset {list.Count} claimed bounties.");
		}

		public List<BountyEntry> GetDailyBounties()
		{
			Random rng = new Random((int)((long)GetCurrentDay() * 31337L % int.MaxValue));
			List<BountyEntry> source = BountyConfig.Bounties.Where((BountyEntry b) => IsBossGateUnlocked(b)).ToList();
			List<BountyEntry> pool = source.Where((BountyEntry b) => b.Type == "Kill" && !IsMiniboss(b) && !IsRaid(b)).ToList();
			List<BountyEntry> pool2 = source.Where((BountyEntry b) => IsMiniboss(b)).ToList();
			List<BountyEntry> pool3 = source.Where((BountyEntry b) => IsRaid(b)).ToList();
			List<BountyEntry> list = new List<BountyEntry>();
			list.AddRange(PickRandom(pool, 2, rng));
			list.AddRange(PickRandom(pool2, 1, rng));
			list.AddRange(PickRandom(pool3, 1, rng));
			return list;
		}

		private static List<BountyEntry> PickRandom(List<BountyEntry> pool, int count, Random rng)
		{
			if (pool.Count <= count)
			{
				return new List<BountyEntry>(pool);
			}
			return pool.OrderBy((BountyEntry _) => rng.Next()).Take(count).ToList();
		}

		private static bool IsMiniboss(BountyEntry entry)
		{
			if (!(entry.Tier == "Miniboss"))
			{
				return entry.Tier == "Special";
			}
			return true;
		}

		private static bool IsRaid(BountyEntry entry)
		{
			return entry.Tier == "Raid";
		}

		private static bool IsBossGateUnlocked(BountyEntry entry)
		{
			if (string.IsNullOrEmpty(entry.RequiredBoss))
			{
				return true;
			}
			if ((Object)(object)ZoneSystem.instance == (Object)null)
			{
				return false;
			}
			return ZoneSystem.instance.GetGlobalKey(entry.RequiredBoss);
		}

		public BountyState GetState(string bountyId)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return BountyState.Available;
			}
			if (!localPlayer.m_customData.TryGetValue("HaldorBounty_State_" + bountyId, out var value))
			{
				return BountyState.Available;
			}
			if (value == "claimed")
			{
				return BountyState.Claimed;
			}
			if (value == "active")
			{
				if (_bountyLookup.TryGetValue(bountyId, out var value2) && GetProgress(bountyId) >= value2.Amount)
				{
					return BountyState.Ready;
				}
				return BountyState.Active;
			}
			return BountyState.Available;
		}

		public int GetProgress(string bountyId)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return 0;
			}
			int result = 0;
			if (localPlayer.m_customData.TryGetValue("HaldorBounty_Progress_" + bountyId, out var value))
			{
				int.TryParse(value, out result);
			}
			return result;
		}

		public bool IsAvailable(string bountyId)
		{
			if (!_bountyLookup.TryGetValue(bountyId, out var value))
			{
				return false;
			}
			if (GetState(bountyId) != 0)
			{
				return false;
			}
			return IsBossGateUnlocked(value);
		}

		public List<BountyEntry> GetVisibleBounties()
		{
			CheckDayReset();
			List<BountyEntry> list = new List<BountyEntry>();
			HashSet<string> hashSet = new HashSet<string>();
			foreach (BountyEntry dailyBounty in GetDailyBounties())
			{
				if (GetState(dailyBounty.Id) != 0 || IsAvailable(dailyBounty.Id))
				{
					list.Add(dailyBounty);
					hashSet.Add(dailyBounty.Id);
				}
			}
			foreach (BountyEntry bounty in BountyConfig.Bounties)
			{
				if (!hashSet.Contains(bounty.Id))
				{
					BountyState state = GetState(bounty.Id);
					if (state == BountyState.Active || state == BountyState.Ready)
					{
						list.Add(bounty);
						hashSet.Add(bounty.Id);
					}
				}
			}
			return list;
		}

		public static string GetBossName(string bountyId)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && localPlayer.m_customData.TryGetValue("HaldorBounty_BossName_" + bountyId, out var value) && !string.IsNullOrEmpty(value))
			{
				return value;
			}
			int gender = 0;
			if (Instance != null && Instance._bountyLookup.TryGetValue(bountyId, out var value2))
			{
				gender = value2.Gender;
			}
			return GenerateBossName(bountyId, gender);
		}

		private static string GenerateBossName(string bountyId, int gender = 0)
		{
			int num = StableHash(bountyId);
			int num2 = 0;
			if ((Object)(object)EnvMan.instance != (Object)null && (Object)(object)ZNet.instance != (Object)null)
			{
				num2 = EnvMan.instance.GetDay(ZNet.instance.GetTimeSeconds());
			}
			string[] array = gender switch
			{
				1 => MaleNames, 
				2 => FemaleNames, 
				_ => MaleNames, 
			};
			if (gender == 0)
			{
				int num3 = ((num + num2 * 7) & 0x7FFFFFFF) % (MaleNames.Length + FemaleNames.Length);
				array = ((num3 < MaleNames.Length) ? MaleNames : FemaleNames);
				int num4 = ((num3 < MaleNames.Length) ? num3 : (num3 - MaleNames.Length));
				return array[num4];
			}
			int num5 = ((num + num2 * 7) & 0x7FFFFFFF) % array.Length;
			return array[num5];
		}

		private static int StableHash(string s)
		{
			int num = 5381;
			foreach (char c in s)
			{
				num = (num << 5) + num + c;
			}
			return num & 0x7FFFFFFF;
		}

		public bool AcceptBounty(string bountyId)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			if (!IsAvailable(bountyId))
			{
				return false;
			}
			localPlayer.m_customData["HaldorBounty_State_" + bountyId] = "active";
			localPlayer.m_customData["HaldorBounty_Progress_" + bountyId] = "0";
			_activeBountyIds.Add(bountyId);
			_activeBountyIdsLoaded = true;
			string text = null;
			_bountyLookup.TryGetValue(bountyId, out var value);
			if (value != null && value.SpawnLevel > 0)
			{
				text = GenerateBossName(bountyId, value.Gender);
				localPlayer.m_customData["HaldorBounty_BossName_" + bountyId] = text;
			}
			PlaySkillLevelupEffect(localPlayer);
			if (value != null && value.SpawnLevel > 0)
			{
				try
				{
					SpawnBountyCreature(localPlayer, value, text);
				}
				catch (Exception arg)
				{
					HaldorBounties.Log.LogError((object)$"[BountyManager] SpawnBountyCreature failed for {bountyId}: {arg}");
				}
			}
			if (value != null)
			{
				AddBountyStatusEffect(localPlayer, value);
			}
			HaldorBounties.Log.LogInfo((object)("[BountyManager] Accepted bounty: " + bountyId));
			return true;
		}

		public bool AbandonBounty(string bountyId)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			if (GetState(bountyId) != BountyState.Active)
			{
				return false;
			}
			localPlayer.m_customData.Remove("HaldorBounty_State_" + bountyId);
			localPlayer.m_customData.Remove("HaldorBounty_Progress_" + bountyId);
			localPlayer.m_customData.Remove("HaldorBounty_BossName_" + bountyId);
			localPlayer.m_customData.Remove("HaldorBounty_SpawnPos_" + bountyId);
			_activeBountyIds.Remove(bountyId);
			RemoveBountyStatusEffect(localPlayer, bountyId);
			DespawnBountyCreature(bountyId);
			RemoveBountyPin(bountyId);
			HaldorBounties.Log.LogInfo((object)("[BountyManager] Abandoned bounty: " + bountyId));
			return true;
		}

		private void SpawnBountyCreature(Player player, BountyEntry entry, string bossName)
		{
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = ZNetScene.instance.GetPrefab(entry.Target);
			if ((Object)(object)prefab == (Object)null)
			{
				HaldorBounties.Log.LogWarning((object)("[BountyManager] Prefab not found: " + entry.Target));
				return;
			}
			if (string.IsNullOrEmpty(bossName))
			{
				bossName = GetBossName(entry.Id);
			}
			bool flag = IsRaid(entry);
			int num = ((!flag) ? 1 : entry.Amount);
			Vector3 position = ((Component)player).transform.position;
			Vector3 val = position;
			Character val2 = null;
			int num2 = 0;
			RemoveBountyPin(entry.Id);
			CleanupStaleCreatures(entry.Id);
			for (int i = 0; i < num; i++)
			{
				try
				{
					Vector3 val3 = ((!flag || i <= 0) ? FindSpawnPosition(position, 700f) : FindSpawnPosition(val, 10f));
					if (i == 0)
					{
						val = val3;
					}
					Quaternion val4 = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);
					GameObject obj = Object.Instantiate<GameObject>(prefab, val3, val4);
					Character component = obj.GetComponent<Character>();
					ZNetView component2 = obj.GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && ((component2 != null) ? component2.GetZDO() : null) != null)
					{
						ZDO zDO = component2.GetZDO();
						zDO.Set(StringExtensionMethods.GetStableHashCode("HB_NpcGender"), entry.Gender, false);
						component.SetLevel(entry.SpawnLevel);
						component.SetHealth(component.GetMaxHealth());
						if (flag)
						{
							component.m_name = "Valheim Raider";
						}
						else
						{
							component.m_name = bossName;
							component.m_boss = true;
							component.m_dontHideBossHud = false;
						}
						zDO.Set("HaldorBountyMiniboss", true);
						zDO.Set("HaldorBountyBossName", bossName);
						zDO.Set("HaldorBountyId", entry.Id);
						zDO.Persistent = true;
					}
					if (i == 0 && (Object)(object)component != (Object)null)
					{
						val2 = component;
					}
					num2++;
				}
				catch (Exception ex)
				{
					HaldorBounties.Log.LogWarning((object)$"[BountyManager] Failed to spawn creature {i + 1}/{num}: {ex.Message}");
				}
			}
			if ((Object)(object)val2 != (Object)null)
			{
				_bountyCreatures[entry.Id] = val2;
			}
			player.m_customData["HaldorBounty_SpawnPos_" + entry.Id] = string.Format(CultureInfo.InvariantCulture, "{0:F1},{1:F1},{2:F1}", val.x, val.y, val.z);
			if ((Object)(object)Minimap.instance != (Object)null)
			{
				try
				{
					PinData val5 = Minimap.instance.AddPin(val, (PinType)13, bossName, false, false, 0L, default(PlatformUserID));
					val5.m_worldSize = 80f;
					val5.m_animate = true;
					_bountyPins[entry.Id] = val5;
				}
				catch
				{
					try
					{
						PinData value = Minimap.instance.AddPin(val, (PinType)9, bossName, true, false, 0L, default(PlatformUserID));
						_bountyPins[entry.Id] = value;
					}
					catch
					{
					}
				}
			}
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)2, bossName + " the " + entry.Title + " has appeared in the wild!", 0, (Sprite)null, false);
			}
			HaldorBounties.Log.LogInfo((object)$"[BountyManager] Spawned {num2}/{num}x {entry.Target} \"{bossName}\" level {entry.SpawnLevel}");
		}

		public void RegisterBountyCreature(string bountyId, Character creature)
		{
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(bountyId) || (Object)(object)creature == (Object)null)
			{
				return;
			}
			BountyState state = GetState(bountyId);
			if (state != BountyState.Active && state != BountyState.Ready)
			{
				return;
			}
			bool flag = false;
			if (_bountyLookup.TryGetValue(bountyId, out var value))
			{
				flag = IsRaid(value);
			}
			string text = GetBossName(bountyId);
			if (flag)
			{
				creature.m_name = "Valheim Raider";
			}
			else
			{
				if (!string.IsNullOrEmpty(text))
				{
					creature.m_name = text;
				}
				else
				{
					text = creature.m_name;
				}
				creature.m_boss = true;
				creature.m_dontHideBossHud = false;
			}
			_bountyCreatures[bountyId] = creature;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				Vector3 position = ((Component)creature).transform.position;
				localPlayer.m_customData["HaldorBounty_SpawnPos_" + bountyId] = string.Format(CultureInfo.InvariantCulture, "{0:F1},{1:F1},{2:F1}", position.x, position.y, position.z);
			}
			if (_bountyPins.ContainsKey(bountyId) || !((Object)(object)Minimap.instance != (Object)null))
			{
				return;
			}
			string text2 = (flag ? "Valheim Raiders" : text);
			try
			{
				PinData val = Minimap.instance.AddPin(((Component)creature).transform.position, (PinType)13, text2, false, false, 0L, default(PlatformUserID));
				val.m_worldSize = 80f;
				val.m_animate = true;
				_bountyPins[bountyId] = val;
			}
			catch
			{
				try
				{
					PinData value2 = Minimap.instance.AddPin(((Component)creature).transform.position, (PinType)9, text2, true, false, 0L, default(PlatformUserID));
					_bountyPins[bountyId] = value2;
				}
				catch
				{
				}
			}
			HaldorBounties.Log.LogInfo((object)("[BountyManager] Re-registered bounty creature: " + text2 + " (bounty=" + bountyId + ")"));
		}

		public double GetSecondsUntilReset()
		{
			if ((Object)(object)EnvMan.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null)
			{
				return 0.0;
			}
			double timeSeconds = ZNet.instance.GetTimeSeconds();
			long dayLengthSec = EnvMan.instance.m_dayLengthSec;
			double num = (double)((int)(timeSeconds / (double)dayLengthSec) + 1) * (double)dayLengthSec;
			return Math.Max(0.0, num - timeSeconds);
		}

		public int ResetAll(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 0;
			}
			List<string> list = new List<string>();
			foreach (string key in player.m_customData.Keys)
			{
				if (key.StartsWith("HaldorBounty_State_") || key.StartsWith("HaldorBounty_Progress_") || key.StartsWith("HaldorBounty_BossName_") || key.StartsWith("HaldorBounty_SpawnPos_") || key == "HaldorBounty_LastDay")
				{
					list.Add(key);
				}
			}
			foreach (string item in list)
			{
				player.m_customData.Remove(item);
			}
			foreach (KeyValuePair<string, Character> bountyCreature in _bountyCreatures)
			{
				if ((Object)(object)bountyCreature.Value != (Object)null && !bountyCreature.Value.IsDead())
				{
					ZNetView component = ((Component)bountyCreature.Value).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid())
					{
						component.Destroy();
					}
					else
					{
						Object.Destroy((Object)(object)((Component)bountyCreature.Value).gameObject);
					}
				}
			}
			_bountyCreatures.Clear();
			foreach (KeyValuePair<string, PinData> bountyPin in _bountyPins)
			{
				if ((Object)(object)Minimap.instance != (Object)null && bountyPin.Value != null)
				{
					Minimap.instance.RemovePin(bountyPin.Value);
				}
			}
			_bountyPins.Clear();
			foreach (string item2 in new List<string>(_activeBountyIds))
			{
				RemoveBountyStatusEffect(player, item2);
			}
			_activeBountyIds.Clear();
			_activeBountyIdsLoaded = false;
			_lastDay = -1;
			HaldorBounties.Log.LogInfo((object)$"[BountyManager] Reset all bounties. Removed {list.Count} keys.");
			return list.Count;
		}

		public void UpdateBossHudRange()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			float num = (((Object)(object)Minimap.instance != (Object)null) ? Minimap.instance.m_exploreRadius : 100f);
			Vector3 position = ((Component)localPlayer).transform.position;
			foreach (KeyValuePair<string, Character> bountyCreature in _bountyCreatures)
			{
				Character value = bountyCreature.Value;
				if (!((Object)(object)value == (Object)null) && !value.IsDead() && (!_bountyLookup.TryGetValue(bountyCreature.Key, out var value2) || !IsRaid(value2)))
				{
					bool flag = Vector3.Distance(((Component)value).transform.position, position) <= num;
					if (value.m_boss != flag)
					{
						value.m_boss = flag;
						value.m_dontHideBossHud = false;
					}
				}
			}
		}

		public void UpdateBountyPins()
		{
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Minimap.instance == (Object)null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			EnsureActiveBountyIdsLoaded();
			List<KeyValuePair<string, bool>> list = new List<KeyValuePair<string, bool>>();
			foreach (KeyValuePair<string, Character> bountyCreature in _bountyCreatures)
			{
				PinData value2;
				if ((Object)(object)bountyCreature.Value == (Object)null)
				{
					BountyState state = GetState(bountyCreature.Key);
					bool value = state == BountyState.Ready || state == BountyState.Claimed;
					list.Add(new KeyValuePair<string, bool>(bountyCreature.Key, value));
				}
				else if (bountyCreature.Value.IsDead())
				{
					list.Add(new KeyValuePair<string, bool>(bountyCreature.Key, value: true));
				}
				else if (_bountyPins.TryGetValue(bountyCreature.Key, out value2) && value2 != null)
				{
					value2.m_pos = ((Component)bountyCreature.Value).transform.position;
				}
			}
			foreach (KeyValuePair<string, bool> item in list)
			{
				string key = item.Key;
				bool value3 = item.Value;
				_bountyCreatures.Remove(key);
				if (value3 && _bountyPins.TryGetValue(key, out var value4))
				{
					if (value4 != null)
					{
						Minimap.instance.RemovePin(value4);
					}
					_bountyPins.Remove(key);
				}
			}
			foreach (string activeBountyId in _activeBountyIds)
			{
				if (_bountyPins.ContainsKey(activeBountyId) || GetState(activeBountyId) != BountyState.Active || !_bountyLookup.TryGetValue(activeBountyId, out var value5) || value5.SpawnLevel <= 0 || !localPlayer.m_customData.TryGetValue("HaldorBounty_SpawnPos_" + activeBountyId, out var value6) || !TryParsePosition(value6, out var result))
				{
					continue;
				}
				string bossName = GetBossName(activeBountyId);
				string text = (IsRaid(value5) ? "Valheim Raiders" : bossName);
				try
				{
					PinData val = Minimap.instance.AddPin(result, (PinType)13, text, false, false, 0L, default(PlatformUserID));
					val.m_worldSize = 80f;
					val.m_animate = true;
					_bountyPins[activeBountyId] = val;
				}
				catch
				{
					try
					{
						PinData value7 = Minimap.instance.AddPin(result, (PinType)9, text, true, false, 0L, default(PlatformUserID));
						_bountyPins[activeBountyId] = value7;
					}
					catch
					{
					}
				}
			}
		}

		private static bool TryParsePosition(string posStr, out Vector3 result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			result = Vector3.zero;
			if (string.IsNullOrEmpty(posStr))
			{
				return false;
			}
			string[] array = posStr.Split(new char[1] { ',' });
			if (array.Length != 3)
			{
				return false;
			}
			if (!float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
			{
				return false;
			}
			if (!float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
			{
				return false;
			}
			if (!float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4))
			{
				return false;
			}
			result = new Vector3(result2, result3, result4);
			return true;
		}

		private static void CleanupStaleCreatures(string bountyId)
		{
			try
			{
				int num = 0;
				List<Character> allCharacters = Character.GetAllCharacters();
				for (int num2 = allCharacters.Count - 1; num2 >= 0; num2--)
				{
					Character val = allCharacters[num2];
					if ((Object)(object)val == (Object)null || val.IsPlayer())
					{
						continue;
					}
					ZNetView component = ((Component)val).GetComponent<ZNetView>();
					ZDO val2 = ((component != null) ? component.GetZDO() : null);
					if (val2 == null || val2.GetString("HaldorBountyId", "") != bountyId)
					{
						continue;
					}
					if (component.IsValid() && component.IsOwner())
					{
						component.Destroy();
					}
					else
					{
						if (!component.IsOwner())
						{
							continue;
						}
						Object.Destroy((Object)(object)((Component)val).gameObject);
					}
					num++;
				}
				if (num > 0)
				{
					HaldorBounties.Log.LogInfo((object)$"[BountyManager] Cleaned up {num} stale creatures for bounty: {bountyId}");
				}
			}
			catch (Exception ex)
			{
				HaldorBounties.Log.LogWarning((object)("[BountyManager] Stale creature cleanup failed: " + ex.Message));
			}
		}

		private void DespawnBountyCreature(string bountyId)
		{
			if (!_bountyCreatures.TryGetValue(bountyId, out var value))
			{
				return;
			}
			if ((Object)(object)value != (Object)null && !value.IsDead())
			{
				ZNetView component = ((Component)value).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid())
				{
					component.Destroy();
				}
				else
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
				HaldorBounties.Log.LogInfo((object)("[BountyManager] Despawned creature for bounty: " + bountyId));
			}
			_bountyCreatures.Remove(bountyId);
		}

		private void RemoveBountyPin(string bountyId)
		{
			if (_bountyPins.TryGetValue(bountyId, out var value))
			{
				if ((Object)(object)Minimap.instance != (Object)null && value != null)
				{
					Minimap.instance.RemovePin(value);
				}
				_bountyPins.Remove(bountyId);
			}
			_bountyCreatures.Remove(bountyId);
		}

		private static Vector3 FindSpawnPosition(Vector3 center, float distance)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(10f, distance * 0.07f);
			bool flag = distance > 128f && WorldGenerator.instance != null;
			float num4 = default(float);
			for (int i = 0; i < 30; i++)
			{
				float num2 = Random.Range(0f, 360f);
				float num3 = distance + Random.Range(0f - num, num);
				Vector3 val = center + Quaternion.Euler(0f, num2, 0f) * Vector3.forward * num3;
				if (flag)
				{
					float height = WorldGenerator.instance.GetHeight(val.x, val.z);
					if (height > 30f)
					{
						val.y = height + 0.5f;
						return val;
					}
				}
				else if (ZoneSystem.instance.GetGroundHeight(val, ref num4) && num4 > 30f)
				{
					val.y = num4 + 0.5f;
					return val;
				}
			}
			float num9 = default(float);
			for (int j = 1; j <= 5; j++)
			{
				float num5 = distance * (1f - (float)j * 0.15f);
				float num6 = Mathf.Max(10f, num5 * 0.1f);
				for (int k = 0; k < 20; k++)
				{
					float num7 = Random.Range(0f, 360f);
					float num8 = num5 + Random.Range(0f - num6, num6);
					Vector3 val2 = center + Quaternion.Euler(0f, num7, 0f) * Vector3.forward * num8;
					if (flag)
					{
						float height2 = WorldGenerator.instance.GetHeight(val2.x, val2.z);
						if (height2 > 30f)
						{
							val2.y = height2 + 0.5f;
							return val2;
						}
					}
					else if (ZoneSystem.instance.GetGroundHeight(val2, ref num9) && num9 > 30f)
					{
						val2.y = num9 + 0.5f;
						return val2;
					}
				}
			}
			Vector3 result = center;
			float num10 = default(float);
			if (flag)
			{
				float height3 = WorldGenerator.instance.GetHeight(center.x, center.z);
				result.y = Mathf.Max(height3, 30f) + 0.5f;
			}
			else if (ZoneSystem.instance.GetGroundHeight(center, ref num10))
			{
				result.y = Mathf.Max(num10, 30f) + 0.5f;
			}
			else
			{
				result.y = Mathf.Max(center.y, 31f);
			}
			HaldorBounties.Log.LogWarning((object)"[BountyManager] FindSpawnPosition: all attempts hit ocean — spawning near player as last resort");
			return result;
		}

		public void IncrementKill(string prefabName, int level)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			EnsureActiveBountyIdsLoaded();
			if (_activeBountyIds.Count == 0)
			{
				return;
			}
			HaldorBounties.Log.LogInfo((object)$"[BountyManager] Kill detected: {prefabName} (level {level})");
			foreach (string activeBountyId in _activeBountyIds)
			{
				if (!_bountyLookup.TryGetValue(activeBountyId, out var value) || value.Type != "Kill" || !string.Equals(value.Target, prefabName, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				if (value.SpawnLevel > 0 && level != value.SpawnLevel)
				{
					HaldorBounties.Log.LogInfo((object)$"[BountyManager] Level mismatch for {activeBountyId}: need {value.SpawnLevel}, got {level}");
					continue;
				}
				int progress = GetProgress(activeBountyId);
				if (progress >= value.Amount)
				{
					continue;
				}
				int num = progress + 1;
				localPlayer.m_customData["HaldorBounty_Progress_" + activeBountyId] = num.ToString();
				HaldorBounties.Log.LogInfo((object)$"[BountyManager] Bounty progress: {activeBountyId} ({num}/{value.Amount})");
				if (num >= value.Amount)
				{
					HaldorBounties.Log.LogInfo((object)("[BountyManager] Bounty ready: " + activeBountyId));
					MessageHud instance = MessageHud.instance;
					if (instance != null)
					{
						instance.ShowMessage((MessageType)2, "Bounty Complete: " + value.Title + "!", 0, (Sprite)null, false);
					}
					RemoveBountyPin(activeBountyId);
				}
			}
		}

		public bool ClaimReward(string bountyId)
		{
			return ClaimRewardChoice(bountyId, RewardCategory.Coins);
		}

		public bool ClaimRewardChoice(string bountyId, RewardCategory category)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			if (!_bountyLookup.TryGetValue(bountyId, out var value))
			{
				return false;
			}
			if (GetState(bountyId) != BountyState.Ready)
			{
				return false;
			}
			RewardResolver.ResolvedReward resolvedReward = RewardResolver.ResolveRewards(value).Find((RewardResolver.ResolvedReward r) => r.Category == category);
			if (resolvedReward == null)
			{
				return false;
			}
			if (category == RewardCategory.Coins)
			{
				int value2 = ReadBankBalance(localPlayer) + resolvedReward.CoinAmount;
				WriteBankBalance(localPlayer, value2);
				RefreshBankUI();
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)2, $"Deposited {resolvedReward.CoinAmount:N0} coins into your bank!", 0, (Sprite)null, false);
				}
			}
			else if (!RewardResolver.DeliverReward(resolvedReward, localPlayer))
			{
				HaldorBounties.Log.LogWarning((object)$"[BountyManager] Failed to deliver {category} reward for {bountyId}");
				return false;
			}
			localPlayer.m_customData["HaldorBounty_State_" + bountyId] = "claimed";
			localPlayer.m_customData.Remove("HaldorBounty_BossName_" + bountyId);
			localPlayer.m_customData.Remove("HaldorBounty_SpawnPos_" + bountyId);
			RemoveBountyStatusEffect(localPlayer, bountyId);
			RemoveBountyPin(bountyId);
			_activeBountyIds.Remove(bountyId);
			PlaySkillLevelupEffect(localPlayer);
			HaldorBounties.Log.LogInfo((object)$"[BountyManager] Claimed bounty: {bountyId}, reward: {category} ({resolvedReward.DisplayText})");
			return true;
		}

		private static void PlaySkillLevelupEffect(Player player)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			try
			{
				if (player.m_skillLevelupEffects != null && player.m_skillLevelupEffects.m_effectPrefabs != null && player.m_skillLevelupEffects.m_effectPrefabs.Length != 0)
				{
					player.m_skillLevelupEffects.Create(((Component)player).transform.position, ((Component)player).transform.rotation, ((Component)player).transform, 1f, -1);
					return;
				}
				ZNetScene instance = ZNetScene.instance;
				if ((Object)(object)instance != (Object)null)
				{
					GameObject prefab = instance.GetPrefab("vfx_RaiseSkill");
					if ((Object)(object)prefab != (Object)null)
					{
						Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, ((Component)player).transform.rotation);
						return;
					}
				}
				HaldorBounties.Log.LogWarning((object)"[BountyManager] Could not play skill levelup effect — no source found");
			}
			catch (Exception ex)
			{
				HaldorBounties.Log.LogWarning((object)("[BountyManager] PlaySkillLevelupEffect error: " + ex.Message));
			}
		}

		private static Sprite GetOrLoadBountyIcon()
		{
			if ((Object)(object)_bountyIcon != (Object)null)
			{
				return _bountyIcon;
			}
			try
			{
				ObjectDB instance = ObjectDB.instance;
				GameObject obj = ((instance != null) ? instance.GetItemPrefab("Coins") : null);
				Sprite[] array = ((obj == null) ? null : obj.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_icons);
				if (array != null && array.Length != 0)
				{
					_bountyIcon = array[0];
				}
			}
			catch
			{
			}
			return _bountyIcon;
		}

		private static void AddBountyStatusEffect(Player player, BountyEntry entry)
		{
			if ((Object)(object)player == (Object)null || entry == null)
			{
				return;
			}
			try
			{
				SEMan sEMan = ((Character)player).GetSEMan();
				if (sEMan != null)
				{
					int stableHashCode = StringExtensionMethods.GetStableHashCode("HaldorBounty_" + entry.Id);
					if (!((Object)(object)sEMan.GetStatusEffect(stableHashCode) != (Object)null))
					{
						BountyStatusEffect bountyStatusEffect = ScriptableObject.CreateInstance<BountyStatusEffect>();
						bountyStatusEffect.Setup(entry.Id, entry.Title, entry.Amount, GetOrLoadBountyIcon());
						sEMan.AddStatusEffect((StatusEffect)(object)bountyStatusEffect, false, 0, 0f);
					}
				}
			}
			catch (Exception ex)
			{
				HaldorBounties.Log.LogWarning((object)("[BountyManager] Failed to add status effect for " + entry.Id + ": " + ex.Message));
			}
		}

		private static void RemoveBountyStatusEffect(Player player, string bountyId)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			try
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode("HaldorBounty_" + bountyId);
				SEMan sEMan = ((Character)player).GetSEMan();
				if (sEMan != null)
				{
					sEMan.RemoveStatusEffect(stableHashCode, false);
				}
			}
			catch (Exception ex)
			{
				HaldorBounties.Log.LogWarning((object)("[BountyManager] Failed to remove status effect for " + bountyId + ": " + ex.Message));
			}
		}

		public void RefreshStatusEffects(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			EnsureActiveBountyIdsLoaded();
			foreach (string activeBountyId in _activeBountyIds)
			{
				if (_bountyLookup.TryGetValue(activeBountyId, out var value))
				{
					AddBountyStatusEffect(player, value);
				}
			}
		}

		public void RestoreBountyPins(Player player)
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)Minimap.instance == (Object)null)
			{
				return;
			}
			EnsureActiveBountyIdsLoaded();
			foreach (string activeBountyId in _activeBountyIds)
			{
				if (_bountyPins.ContainsKey(activeBountyId) || !_bountyLookup.TryGetValue(activeBountyId, out var value) || value.SpawnLevel <= 0 || !player.m_customData.TryGetValue("HaldorBounty_SpawnPos_" + activeBountyId, out var value2) || !TryParsePosition(value2, out var result))
				{
					continue;
				}
				string text = (IsRaid(value) ? "Valheim Raiders" : GetBossName(activeBountyId));
				try
				{
					PinData val = Minimap.instance.AddPin(result, (PinType)13, text, false, false, 0L, default(PlatformUserID));
					val.m_worldSize = 80f;
					val.m_animate = true;
					_bountyPins[activeBountyId] = val;
				}
				catch
				{
					try
					{
						PinData value3 = Minimap.instance.AddPin(result, (PinType)9, text, true, false, 0L, default(PlatformUserID));
						_bountyPins[activeBountyId] = value3;
					}
					catch
					{
					}
				}
				HaldorBounties.Log.LogInfo((object)$"[BountyManager] Restored pin for bounty: {activeBountyId} at {result}");
			}
		}

		private static int ReadBankBalance(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 0;
			}
			if (player.m_customData.TryGetValue("TraderSharedBank_Balance", out var value) && int.TryParse(value, out var result))
			{
				return result;
			}
			if (player.m_customData.TryGetValue("HaldorBank_Balance", out value) && int.TryParse(value, out result))
			{
				return result;
			}
			return 0;
		}

		private static void WriteBankBalance(Player player, int value)
		{
			if (!((Object)(object)player == (Object)null))
			{
				value = Mathf.Max(0, value);
				string value2 = value.ToString();
				player.m_customData["TraderSharedBank_Balance"] = value2;
				player.m_customData["HaldorBank_Balance"] = value2;
				player.m_customData["HildirBank_Balance"] = value2;
				player.m_customData["BogWitchBank_Balance"] = value2;
			}
		}

		private void RefreshBankUI()
		{
			try
			{
				if (!(_reloadBankBalance == null))
				{
					object obj = TraderUIPatches.TraderUIInstance;
					if (obj == null && _getTraderUI != null)
					{
						obj = _getTraderUI.Invoke(null, null);
					}
					if (obj != null)
					{
						_reloadBankBalance.Invoke(obj, null);
					}
				}
			}
			catch (Exception ex)
			{
				HaldorBounties.Log.LogWarning((object)("[BountyManager] Failed to refresh bank UI: " + ex.Message));
			}
		}
	}
	public class BountyStatusEffect : StatusEffect
	{
		public string BountyId;

		private int _target;

		public void Setup(string bountyId, string title, int target, Sprite icon)
		{
			BountyId = bountyId;
			_target = target;
			base.m_name = title;
			base.m_ttl = 0f;
			base.m_icon = icon;
			((Object)this).name = "HaldorBounty_" + bountyId;
		}

		public override string GetIconText()
		{
			if (BountyManager.Instance == null || string.IsNullOrEmpty(BountyId))
			{
				return "";
			}
			int num = Mathf.Min(BountyManager.Instance.GetProgress(BountyId), _target);
			return $"{num}/{_target}";
		}

		public override string GetTooltipString()
		{
			if (BountyManager.Instance == null || string.IsNullOrEmpty(BountyId))
			{
				return base.m_name;
			}
			int progress = BountyManager.Instance.GetProgress(BountyId);
			if (BountyManager.Instance.GetState(BountyId) == BountyState.Ready)
			{
				return base.m_name + "\nCompleted! Return to Haldor to choose your reward.";
			}
			return $"{base.m_name}\nProgress: {Mathf.Min(progress, _target)} / {_target}";
		}

		public override void UpdateStatusEffect(float dt)
		{
		}

		public override bool IsDone()
		{
			return false;
		}
	}
	public enum RewardCategory
	{
		Coins,
		Ingots,
		Resources,
		Consumables
	}
	public enum BiomeTier
	{
		Meadows,
		BlackForest,
		Swamp,
		Mountain,
		Plains,
		Mistlands,
		Ashlands
	}
	public class RewardItem
	{
		public string PrefabName;

		public int MinStack;

		public int MaxStack;

		public int Quality;

		public RewardItem(string prefab, int min, int max, int quality = 1)
		{
			PrefabName = prefab;
			MinStack = min;
			MaxStack = max;
			Quality = quality;
		}
	}
	public static class RewardPool
	{
		public static readonly Dictionary<BiomeTier, RewardItem[]> IngotPool = new Dictionary<BiomeTier, RewardItem[]>
		{
			{
				BiomeTier.Meadows,
				new RewardItem[3]
				{
					new RewardItem("CopperOre", 5, 10),
					new RewardItem("TinOre", 5, 10),
					new RewardItem("Flint", 8, 14)
				}
			},
			{
				BiomeTier.BlackForest,
				new RewardItem[4]
				{
					new RewardItem("Bronze", 4, 8),
					new RewardItem("Copper", 5, 8),
					new RewardItem("Tin", 5, 8),
					new RewardItem("Coal", 8, 14)
				}
			},
			{
				BiomeTier.Swamp,
				new RewardItem[3]
				{
					new RewardItem("Iron", 4, 8),
					new RewardItem("IronScrap", 6, 12),
					new RewardItem("Chain", 1, 3)
				}
			},
			{
				BiomeTier.Mountain,
				new RewardItem[3]
				{
					new RewardItem("Silver", 4, 8),
					new RewardItem("SilverOre", 6, 10),
					new RewardItem("Crystal", 3, 6)
				}
			},
			{
				BiomeTier.Plains,
				new RewardItem[3]
				{
					new RewardItem("BlackMetal", 4, 8),
					new RewardItem("BlackMetalScrap", 6, 12),
					new RewardItem("LinenThread", 4, 8)
				}
			},
			{
				BiomeTier.Mistlands,
				new RewardItem[4]
				{
					new RewardItem("BlackCore", 1, 2),
					new RewardItem("Eitr", 3, 6),
					new RewardItem("Carapace", 5, 10),
					new RewardItem("Sap", 4, 8)
				}
			},
			{
				BiomeTier.Ashlands,
				new RewardItem[5]
				{
					new RewardItem("FlametalNew", 4, 8),
					new RewardItem("GemstoneRed", 1, 3),
					new RewardItem("GemstoneBlue", 1, 3),
					new RewardItem("GemstoneGreen", 1, 3),
					new RewardItem("CelestialFeather", 1, 2)
				}
			}
		};

		public static readonly Dictionary<BiomeTier, RewardItem[]> ResourcePool = new Dictionary<BiomeTier, RewardItem[]>
		{
			{
				BiomeTier.Meadows,
				new RewardItem[6]
				{
					new RewardItem("Wood", 15, 30),
					new RewardItem("Stone", 12, 25),
					new RewardItem("LeatherScraps", 6, 12),
					new RewardItem("DeerHide", 4, 8),
					new RewardItem("Resin", 8, 16),
					new RewardItem("BoneFragments", 6, 12)
				}
			},
			{
				BiomeTier.BlackForest,
				new RewardItem[6]
				{
					new RewardItem("FineWood", 10, 20),
					new RewardItem("SurtlingCore", 2, 4),
					new RewardItem("BoneFragments", 8, 14),
					new RewardItem("TrollHide", 3, 6),
					new RewardItem("Thistle", 5, 10),
					new RewardItem("GreydwarfEye", 6, 12)
				}
			},
			{
				BiomeTier.Swamp,
				new RewardItem[6]
				{
					new RewardItem("ElderBark", 8, 15),
					new RewardItem("Guck", 4, 8),
					new RewardItem("Bloodbag", 4, 8),
					new RewardItem("Entrails", 5, 10),
					new RewardItem("WitheredBone", 2, 4),
					new RewardItem("Thistle", 6, 12)
				}
			},
			{
				BiomeTier.Mountain,
				new RewardItem[5]
				{
					new RewardItem("WolfPelt", 3, 6),
					new RewardItem("FreezeGland", 4, 8),
					new RewardItem("Obsidian", 6, 12),
					new RewardItem("DragonTear", 1, 1),
					new RewardItem("JuteRed", 2, 4)
				}
			},
			{
				BiomeTier.Plains,
				new RewardItem[5]
				{
					new RewardItem("Needle", 6, 12),
					new RewardItem("Flax", 6, 10),
					new RewardItem("Barley", 8, 14),
					new RewardItem("LoxPelt", 2, 5),
					new RewardItem("Tar", 5, 10)
				}
			},
			{
				BiomeTier.Mistlands,
				new RewardItem[5]
				{
					new RewardItem("Softtissue", 5, 10),
					new RewardItem("RoyalJelly", 3, 6),
					new RewardItem("ScaleHide", 4, 8),
					new RewardItem("YggdrasilWood", 8, 14),
					new RewardItem("DvergrNeedle", 2, 4)
				}
			},
			{
				BiomeTier.Ashlands,
				new RewardItem[5]
				{
					new RewardItem("Grausten", 8, 14),
					new RewardItem("CharredBone", 5, 10),
					new RewardItem("AskHide", 3, 6),
					new RewardItem("MorgenSinew", 1, 3),
					new RewardItem("BellFragment", 1, 2)
				}
			}
		};

		public static readonly Dictionary<BiomeTier, RewardItem[]> ConsumablePool = new Dictionary<BiomeTier, RewardItem[]>
		{
			{
				BiomeTier.Meadows,
				new RewardItem[6]
				{
					new RewardItem("CookedMeat", 3, 6),
					new RewardItem("CookedDeerMeat", 3, 5),
					new RewardItem("QueensJam", 3, 5),
					new RewardItem("Honey", 3, 6),
					new RewardItem("MeadHealthMinor", 3, 5),
					new RewardItem("MeadStaminaMinor", 3, 5)
				}
			},
			{
				BiomeTier.BlackForest,
				new RewardItem[5]
				{
					new RewardItem("CarrotSoup", 3, 5),
					new RewardItem("MeadPoisonResist", 3, 5),
					new RewardItem("MeadHealthMedium", 3, 5),
					new RewardItem("Sausages", 3, 6),
					new RewardItem("DeerStew", 3, 5)
				}
			},
			{
				BiomeTier.Swamp,
				new RewardItem[6]
				{
					new RewardItem("MeadPoisonResist", 4, 6),
					new RewardItem("MeadStaminaMedium", 3, 5),
					new RewardItem("TurnipStew", 3, 5),
					new RewardItem("Sausages", 4, 6),
					new RewardItem("BlackSoup", 3, 5),
					new RewardItem("MeadHealthMedium", 3, 6)
				}
			},
			{
				BiomeTier.Mountain,
				new RewardItem[6]
				{
					new RewardItem("WolfSkewer", 3, 5),
					new RewardItem("EyeScream", 3, 5),
					new RewardItem("MeadFrostResist", 3, 5),
					new RewardItem("MeadStaminaMedium", 4, 6),
					new RewardItem("OnionSoup", 3, 5),
					new RewardItem("MeadHealthMajor", 2, 4)
				}
			},
			{
				BiomeTier.Plains,
				new RewardItem[6]
				{
					new RewardItem("LoxPie", 2, 4),
					new RewardItem("BloodPudding", 2, 4),
					new RewardItem("FishAndBread", 2, 4),
					new RewardItem("MeadHealthMajor", 3, 5),
					new RewardItem("MeadStaminaLingering", 3, 5),
					new RewardItem("Bread", 3, 6)
				}
			},
			{
				BiomeTier.Mistlands,
				new RewardItem[6]
				{
					new RewardItem("YggdrasilPorridge", 2, 4),
					new RewardItem("SeekerAspic", 2, 4),
					new RewardItem("MagicallyStuffedShroom", 2, 4),
					new RewardItem("MeadEitrMinor", 3, 5),
					new RewardItem("MushroomOmelette", 2, 4),
					new RewardItem("MisthareSupreme", 2, 4)
				}
			},
			{
				BiomeTier.Ashlands,
				new RewardItem[6]
				{
					new RewardItem("MeatPlatter", 2, 4),
					new RewardItem("ScorchingMedley", 2, 4),
					new RewardItem("FierySvinstew", 2, 3),
					new RewardItem("MeadEitrLingering", 2, 4),
					new RewardItem("PiquantPie", 2, 3),
					new RewardItem("SparklingShroomshake", 2, 3)
				}
			}
		};

		public static BiomeTier GetBiomeTier(BountyEntry entry)
		{
			return (entry.RequiredBoss ?? "") switch
			{
				"" => BiomeTier.Meadows, 
				"defeated_eikthyr" => BiomeTier.BlackForest, 
				"defeated_gdking" => BiomeTier.Swamp, 
				"defeated_bonemass" => BiomeTier.Mountain, 
				"defeated_dragon" => BiomeTier.Plains, 
				"defeated_goblinking" => BiomeTier.Mistlands, 
				"defeated_queen" => BiomeTier.Ashlands, 
				_ => BiomeTier.Meadows, 
			};
		}
	}
	public static class RewardResolver
	{
		public class ResolvedReward
		{
			public RewardCategory Category;

			public string DisplayText;

			public string PrefabName;

			public int Stack;

			public int Quality;

			public int CoinAmount;

			public Sprite Icon;
		}

		public static List<ResolvedReward> ResolveRewards(BountyEntry entry)
		{
			List<ResolvedReward> list = new List<ResolvedReward>();
			Random rng = new Random(StableHash(entry.Id));
			BiomeTier biomeTier = RewardPool.GetBiomeTier(entry);
			bool num = entry.Tier == "Miniboss" || entry.Tier == "Special";
			bool flag = entry.Tier == "Raid";
			float num2 = (num ? 1.5f : (flag ? 1.25f : 1f));
			float stackMult = (num ? 1.5f : (flag ? 1.25f : 1f));
			int num3 = (int)((float)entry.Reward * num2);
			list.Add(new ResolvedReward
			{
				Category = RewardCategory.Coins,
				CoinAmount = num3,
				PrefabName = "Coins",
				DisplayText = $"{num3}c",
				Stack = num3,
				Quality = 1
			});
			list.Add(ResolveFromPool(RewardPool.IngotPool, biomeTier, rng, stackMult, RewardCategory.Ingots));
			list.Add(ResolveFromPool(RewardPool.ResourcePool, biomeTier, rng, stackMult, RewardCategory.Resources));
			list.Add(ResolveFromPool(RewardPool.ConsumablePool, biomeTier, rng, stackMult, RewardCategory.Consumables));
			return list;
		}

		private static ResolvedReward ResolveFromPool(Dictionary<BiomeTier, RewardItem[]> pool, BiomeTier biome, Random rng, float stackMult, RewardCategory category)
		{
			if ((!pool.TryGetValue(biome, out var value) || value.Length == 0) && (!pool.TryGetValue(BiomeTier.Meadows, out value) || value == null || value.Length == 0))
			{
				return new ResolvedReward
				{
					Category = category,
					DisplayText = "???",
					PrefabName = "",
					Stack = 1,
					Quality = 1
				};
			}
			int num = rng.Next(value.Length);
			RewardItem rewardItem = value[num];
			int num2 = rng.Next(rewardItem.MinStack, rewardItem.MaxStack + 1);
			if (stackMult > 1f)
			{
				num2 = Mathf.Max(1, (int)((float)num2 * stackMult));
			}
			string displayName = GetDisplayName(rewardItem.PrefabName);
			string displayText = ((num2 > 1) ? $"{num2}x {displayName}" : displayName);
			return new ResolvedReward
			{
				Category = category,
				PrefabName = rewardItem.PrefabName,
				Stack = Mathf.Max(1, num2),
				Quality = rewardItem.Quality,
				DisplayText = displayText
			};
		}

		public static bool DeliverReward(ResolvedReward reward, Player player)
		{
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || reward == null)
			{
				return false;
			}
			if (reward.Category == RewardCategory.Coins)
			{
				return true;
			}
			try
			{
				ObjectDB instance = ObjectDB.instance;
				GameObject val = ((instance != null) ? instance.GetItemPrefab(reward.PrefabName) : null);
				if ((Object)(object)val == (Object)null)
				{
					HaldorBounties.Log.LogWarning((object)("[RewardResolver] Prefab not found: " + reward.PrefabName));
					return false;
				}
				ItemDrop component = val.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null)
				{
					return false;
				}
				ItemData val2 = component.m_itemData.Clone();
				val2.m_dropPrefab = val;
				val2.m_worldLevel = (byte)Game.m_worldLevel;
				val2.m_stack = reward.Stack;
				val2.m_quality = reward.Quality;
				val2.m_durability = val2.GetMaxDurability();
				Inventory inventory = ((Humanoid)player).GetInventory();
				if (inventory.CanAddItem(val2, -1))
				{
					inventory.AddItem(val2);
					HaldorBounties.Log.LogInfo((object)$"[RewardResolver] Added to inventory: {reward.PrefabName} x{reward.Stack}");
					return true;
				}
				Vector3 val3 = ((Component)player).transform.position + ((Component)player).transform.forward * 1.5f + Vector3.up;
				ItemDrop.DropItem(val2, reward.Stack, val3, ((Component)player).transform.rotation);
				MessageHud instance2 = MessageHud.instance;
				if (instance2 != null)
				{
					instance2.ShowMessage((MessageType)1, "Inventory full — reward dropped nearby", 0, (Sprite)null, false);
				}
				HaldorBounties.Log.LogInfo((object)$"[RewardResolver] Dropped at player: {reward.PrefabName} x{reward.Stack}");
				return true;
			}
			catch (Exception ex)
			{
				HaldorBounties.Log.LogWarning((object)("[RewardResolver] Delivery failed: " + ex.Message));
				return false;
			}
		}

		public static string GetDisplayName(string prefabName)
		{
			try
			{
				ObjectDB instance = ObjectDB.instance;
				GameObject obj = ((instance != null) ? instance.GetItemPrefab(prefabName) : null);
				ItemDrop val = ((obj != null) ? obj.GetComponent<ItemDrop>() : null);
				if (val?.m_itemData?.m_shared != null)
				{
					Localization instance2 = Localization.instance;
					string text = ((instance2 != null) ? instance2.Localize(val.m_itemData.m_shared.m_name) : null);
					if (!string.IsNullOrEmpty(text))
					{
						return text;
					}
				}
			}
			catch
			{
			}
			return prefabName;
		}

		public static Sprite GetRewardIcon(ResolvedReward reward)
		{
			if ((Object)(object)reward.Icon != (Object)null)
			{
				return reward.Icon;
			}
			try
			{
				ObjectDB instance = ObjectDB.instance;
				GameObject val = ((instance != null) ? instance.GetItemPrefab(reward.PrefabName) : null);
				object icon;
				if (val == null)
				{
					icon = null;
				}
				else
				{
					ItemDrop component = val.GetComponent<ItemDrop>();
					if (component == null)
					{
						icon = null;
					}
					else
					{
						ItemData itemData = component.m_itemData;
						icon = ((itemData != null) ? itemData.GetIcon() : null);
					}
				}
				reward.Icon = (Sprite)icon;
			}
			catch
			{
			}
			return reward.Icon;
		}

		private static int StableHash(string s)
		{
			int num = 5381;
			foreach (char c in s)
			{
				num = (num << 5) + num + c;
			}
			return num & 0x7FFFFFFF;
		}
	}
	[HarmonyPatch(typeof(Terminal), "InitTerminal")]
	public static class ConsoleCommands
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__0_0;

			internal void <Postfix>b__0_0(ConsoleEventArgs args)
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					args.Context.AddString("No player found.");
					return;
				}
				int num = BountyManager.Instance?.ResetAll(localPlayer) ?? 0;
				args.Context.AddString($"Bounty reset complete. Cleared {num} bounty entries.");
				((Character)localPlayer).Message((MessageType)2, "All bounties have been reset!", 0, (Sprite)null);
			}
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer == (Object)null)
					{
						args.Context.AddString("No player found.");
					}
					else
					{
						int num = BountyManager.Instance?.ResetAll(localPlayer) ?? 0;
						args.Context.AddString($"Bounty reset complete. Cleared {num} bounty entries.");
						((Character)localPlayer).Message((MessageType)2, "All bounties have been reset!", 0, (Sprite)null);
					}
				};
				<>c.<>9__0_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("BountyReset", "Reset all bounty progress, active bounties, and claimed states.", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}
	[HarmonyPatch(typeof(Character), "OnDeath")]
	public static class KillTracker
	{
		[ThreadStatic]
		private static Stack<(string Prefab, int Level)?> _killStack;

		private static FieldInfo _hasHitField;

		private static FieldInfo _lastHitField;

		private static bool _fieldsCached;

		private static bool IsActiveTaggedBounty(Character character)
		{
			ZNetView component = ((Component)character).GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			if (val == null || !val.GetBool("HaldorBountyMiniboss", false))
			{
				return false;
			}
			string @string = val.GetString("HaldorBountyId", "");
			if (string.IsNullOrEmpty(@string))
			{
				return false;
			}
			BountyState bountyState = BountyManager.Instance?.GetState(@string) ?? BountyState.Available;
			if (bountyState != BountyState.Active)
			{
				return bountyState == BountyState.Ready;
			}
			return true;
		}

		[HarmonyPrefix]
		private static void Prefix(Character __instance)
		{
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			if (_killStack == null)
			{
				_killStack = new Stack<(string, int)?>();
			}
			try
			{
				if ((Object)(object)__instance == (Object)null || __instance.IsPlayer())
				{
					_killStack.Push(null);
					return;
				}
				if (!_fieldsCached)
				{
					_hasHitField = AccessTools.Field(typeof(Character), "m_localPlayerHasHit");
					_lastHitField = AccessTools.Field(typeof(Character), "m_lastHit");
					_fieldsCached = true;
				}
				bool flag = false;
				bool flag2 = false;
				bool flag3 = IsActiveTaggedBounty(__instance);
				try
				{
					if (_hasHitField != null)
					{
						flag = (bool)_hasHitField.GetValue(__instance);
					}
					object? obj = _lastHitField?.GetValue(__instance);
					HitData val = (HitData)((obj is HitData) ? obj : null);
					if (val != null)
					{
						flag2 = (Object)(object)val.GetAttacker() == (Object)(object)Player.m_localPlayer;
					}
				}
				catch (Exception ex)
				{
					HaldorBounties.Log.LogWarning((object)("[KillTracker] Failed to read kill fields: " + ex.Message));
				}
				bool flag4 = flag || flag2 || flag3;
				if (!flag4 && (Object)(object)Player.m_localPlayer != (Object)null && Vector3.Distance(((Component)__instance).transform.position, ((Component)Player.m_localPlayer).transform.position) < 40f)
				{
					flag4 = true;
				}
				if (!flag4)
				{
					_killStack.Push(null);
					return;
				}
				string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject);
				int level = __instance.GetLevel();
				_killStack.Push((prefabName, level));
			}
			catch (Exception ex2)
			{
				HaldorBounties.Log.LogWarning((object)("[KillTracker] Prefix error: " + ex2.Message));
				_killStack?.Push(null);
			}
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			if (_killStack == null || _killStack.Count == 0)
			{
				return;
			}
			(string, int)? tuple = _killStack.Pop();
			try
			{
				if (tuple.HasValue && !string.IsNullOrEmpty(tuple.Value.Item1))
				{
					BountyManager.Instance?.IncrementKill(tuple.Value.Item1, tuple.Value.Item2);
				}
			}
			catch (Exception ex)
			{
				HaldorBounties.Log.LogWarning((object)("[KillTracker] Postfix error: " + ex.Message));
			}
		}
	}
	public static class MinibossHud
	{
		[HarmonyPatch(typeof(Character), "Start")]
		public static class CharacterStartPatch
		{
			[HarmonyPostfix]
			private static void Postfix(Character __instance)
			{
				try
				{
					if (TryApplyMinibossFlags(__instance, out var bountyId))
					{
						if (!string.IsNullOrEmpty(bountyId))
						{
							BountyManager.Instance?.RegisterBountyCreature(bountyId, __instance);
						}
						HaldorBounties.Log.LogInfo((object)("[MinibossHud] Restored bounty creature: " + __instance.m_name + " (bounty=" + bountyId + ")"));
					}
				}
				catch (Exception ex)
				{
					HaldorBounties.Log.LogWarning((object)("[MinibossHud] CharacterStart error: " + ex.Message));
				}
			}
		}

		[HarmonyPatch(typeof(EnemyHud), "ShowHud")]
		public static class ShowHudPatch
		{
			[HarmonyPrefix]
			private static void Prefix(EnemyHud __instance, Character c, bool isMount)
			{
				try
				{
					if (isMount || (Object)(object)c == (Object)null)
					{
						return;
					}
					bool flag = c.IsBoss();
					if (!TryApplyMinibossFlags(c, out var bountyId))
					{
						return;
					}
					if (!string.IsNullOrEmpty(bountyId))
					{
						BountyManager.Instance?.RegisterBountyCreature(bountyId, c);
					}
					if (!flag && !(_hudsField == null) && _hudsField.GetValue(__instance) is IDictionary dictionary && dictionary.Contains(c))
					{
						object obj = dictionary[c];
						if (_guiField == null)
						{
							_guiField = AccessTools.Field(obj.GetType(), "m_gui");
						}
						object? obj2 = _guiField?.GetValue(obj);
						GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null);
						if (val != null)
						{
							Object.Destroy((Object)(object)val);
						}
						dictionary.Remove(c);
					}
				}
				catch (Exception ex)
				{
					HaldorBounties.Log.LogWarning((object)("[MinibossHud] ShowHud prefix error: " + ex.Message));
				}
			}

			[HarmonyPostfix]
			private static void Postfix(EnemyHud __instance, Character c, bool isMount)
			{
				//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (isMount || !TryApplyMinibossFlags(c, out var _) || _hudsField == null || !(_hudsField.GetValue(__instance) is IDictionary dictionary) || !dictionary.Contains(c))
					{
						return;
					}
					object obj = dictionary[c];
					if (_guiField == null)
					{
						_guiField = AccessTools.Field(obj.GetType(), "m_gui");
					}
					if (!(_guiField == null))
					{
						object? value = _guiField.GetValue(obj);
						GameObject val = (GameObject)((value is GameObject) ? value : null);
						if (!((Object)(object)val == (Object)null))
						{
							val.transform.localScale = new Vector3(0.75f, 0.75f, 1f);
						}
					}
				}
				catch (Exception ex)
				{
					HaldorBounties.Log.LogWarning((object)("[MinibossHud] ShowHud error: " + ex.Message));
				}
			}
		}

		private static readonly FieldInfo _hudsField = AccessTools.Field(typeof(EnemyHud), "m_huds");

		private static FieldInfo _guiField;

		private static bool TryApplyMinibossFlags(Character character, out string bountyId)
		{
			bountyId = "";
			if ((Object)(object)character == (Object)null || character.IsPlayer())
			{
				return false;
			}
			ZNetView component = ((Component)character).GetComponent<ZNetVie