Manhunt — Modding Guide
=======================
This explains how to directly modify the gametype without having to hardcode changes
within the .pk3. It covers custom UI, and hook usage.

Manhunt is designed to be flexible: most gameplay behavior can be modified
using exposed hooks, and many features (Tagging, UI, Abilities) can be easily
customized or replaced.

1. Overview
===========
Manhunt exposes two global tables:

MH
  - Holds client-side variables and functions.
  - You may add functions or constants here.

MHN
  - Holds networked variables shared between clients.
  - Do NOT put functions here. Only store synced state.

Additionally, Manhunt includes a modular hook system, allowing you to
modify or override major gameplay events.

2. Adding Custom LMS Graphics
=============================
If your character should display a custom LMS render, include a lump named:
    MH_<SKINNAME>_LMS

Example:
    Skin name: "blaze"
    LMS graphic lump: MH_BLAZE_LMS

This graphic will automatically appear when the player becomes LMS.  
No Lua code is required.
Your lump is recommended to be at 128x128, as that is the same size as all portraits within the mod.
If you do not provide a LMS render, the CSS render will be used by default.


4. Adding Custom LMS UI
========================
Characters or mods may replace the default LMS UI by attaching a UI hook.
This also applies to other UI elements, such as player tracking.

To fully override LMS UI for a character:
  - Copy the default LMS drawing code (from Manhunt HUD files).
  - Paste it inside your hook.
  - Return true to prevent the default UI from drawing.

Only draw for your own character by checking:
    MHN.lastManStandingSkin

You can view an example by scrolling all the way down.

5. Hook System
==============
Manhunt exposes a comprehensive hook list used throughout the gamemode.

Most hooks come in pairs:
  HookName(...)         -- runs BEFORE Manhunt's default behavior  
  PostHookName(..., overridden) -- runs AFTER Manhunt's behavior  
                                   `overridden` is true if the main hook overrode the default.

If a *non-post* hook returns `true`, Manhunt skips its internal logic.
Post-hook return values do nothing — they receive an `overridden` boolean.

Some hooks will run for different types, and it's generally recommended to use types if
supported to prevent lag.

5.1 General Return Rules
-------------------------
Returning TRUE in a normal hook:
  - Cancels default Manhunt logic.
  - PostHookName is called with overridden=true.

Returning any value in a post hook:
  - Ignored (post hooks cannot override logic).

5.2 How To Add A Hook
-------------------------
This is as easy as pie. All you have to do is do it similar to vanilla SRB2!

Example:
	MH:addHook("HookName", function(player)
		...
	end, "hookType")

6. Hook Reference
=================

Below is a complete reference for every hook.
Every hook here has a Post variant.

NewRound()
----------
Arguments: none  
Return:  
  true — override the entire round initialization  
Post: PostNewRound(overridden)

NewMap()
--------
Arguments: none  
Return:  
  true — override map initialization  
Post: PostNewMap(overridden)

EndRound(endReason)
-------------------
Arguments:
  endReason (number) — MH.ER_RUNNERWON / MH.ER_RUNNERDEAD  
Return:
  true — prevent default end-round behavior  
Post: PostEndRound(endReason, overridden)

RunnerCaught(runners, hunters)
------------------------------
Arguments:
  runners (number) — remaining runners  
  hunters (number) — remaining hunters  
Return:
  true — override default “runner caught” logic  
Post: PostRunnerCaught(runners, hunters, overridden)

RunnerTag(hunter, runner, runnersTable, key)
---------------------------------------
Arguments:
  hunter  (player_t)   - player who tagged the runner
  runner  (player_t)   - player who got tagged
  runnersTable (table) - array of players
  key (number)         - to reference the runner in runnersTable
Return:
  true — override tag behavior (you must handle conversion to hunter)  
Post: PostRunnerTag(hunter, runner, runnersTable, key, overridden)

LastManStanding(player, skin, color)
------------------------------------
Arguments:
  player (player_t)
  skin   (string)  
  color  (skincolor)  
Return (special):
  true/player_t       — cancel LMS/override LMS player
  skin (string)       — override skin  
  skincolor (number)  — override color  
  lms (string)        — override music  
Post: PostLastManStanding(player, skin, color, overridden)

AbilityUse(player, role, index)
-------------------------------
Type:
  role ("hunter"|"runner") - the role this hook will run for
Arguments:
  player (player_t)
  role   ("runner"|"hunter")
  index  (number) - the ability number. use it to reference the ability in MH.abilities
Return:
  true — skip default ability use  
Post: PostAbilityUse(player, role, index, overridden)


AbilityThink(player, role, index)
---------------------------------
Type:
  role ("hunter"|"runner") - the role this hook will run for
Arguments:
  player (player_t)
  role   ("runner"|"hunter")
  index  (number) - the ability number. use it to reference the ability in MH.abilities
Return:
  true — skip default ability thinker  
Post: PostAbilityThink(player, role, index, overridden)

StarPostSet(player)
-------------------
Arguments:
  player (runner) - the player who ran into the signpost
Return:
  true — skip default starpost update  
Post: PostStarPostSet(player, overridden)

StarPostTeleport(player)
------------------------
Arguments:
  player (hunter) - the teleporting player
Return:
  true — skip default teleport behavior  
Post: PostStarPostTeleport(player, overridden)

PlayerFinish(player)
--------------------
Arguments:
  player (runner) - the runner that finished
Return:
  true - skip default finish behavior
Post: PostPlayerFinish(player)

UI(v, player, camera, hudtype, ui)
----------------------------------
Warning:
  Not assigning this hook to a type can (and probably will) cause lag.
  This hook is client-side.
Type:
  ui (string) - the name of the ui element
Arguments:
  v       (video)
  player  (player)
  camera  (camera)
  hudtype (string) - the type of hud the hook is running on
  ui      (table)  - the ui element itself
Return:
  true - stop default rendering
Post: PostUI(v, player, camera, hudtype, ui, overridden)
  
-------------------------------------------------------------------------------
Examples
-------------------------------------------------------------------------------

Override tag behavior:
	MH:addHook("RunnerTag", function(hunter, runner)
	    print("Custom tag logic!")
	    return true
	end)

Override hunter ability use:
	MH:addHook("AbilityUse", function(player, _, index)
		if index == 1 then
			print("No speed shoes!")
			return true
		end
	end, "hunter")

Override Last Man Standing UI:
    MH:addHook("UI", function(v)
		if not MHN.lastManStanding then return end
		if MHN.lastManStandingTime < 0 then return end

		if MHN.lastManStandingSkin ~= "skinname" then return end

		-- Render custom LMS, then return true to prevent it from drawing.
		return true
    end, "lastManStanding")

-------------------------------------------------------------------------------
Sendoff
-------------------------------------------------------------------------------

I heavily advise you to look into Manhunt's code to get more of a deep understanding of it.
This API isn't very well documented, nor 