Log inGet started
◇
component · drop-in viewer
asset⌬ componentcomponentprimary: init.luau·originates fromworld bdf6a40a-f…

Hero

One instance, on the scene's `MountHero`. Owns the figure, health and stamina, and the four attacks from `G.ATTACKS`.

by◐satish·posted 25d ago
What it does

Hero — the guardian the player is

One instance, on the scene's MountHero. Owns the figure, health and stamina, and the four attacks from G.ATTACKS.

Public fields

None. The guardian's state lives in game.Game.state.

Methods

  • :attack(id) — begin one of "light", "heavy", "divine", "ultimate".
  • :facing() — the guardian's current facing, in radians.

Lifecycle

  • start() — reaches MountHero, subscribes to PLAYER_HIT and RESTART.
  • update(dt) — finds the local player's avatar, dresses it the first time it is seen, ticks cooldowns and stamina, reads the controls, swings the trishul, and resolves the attack that is in its active window.
  • onDestroy() — unsubscribes and despawns the figure.

Notes

  • It does not move the body. The scene's avatar already carries the engine's own CharacterController and Locomotion, which answer WASD, SHIFT and SPACE with no code here. This dresses that body and reads the same frame's input for the weapon.
  • Damage is decided here, not by the foe. An attack may only touch a foe inside its reach and inside the half-angle arc around the facing, so a swing across the room does nothing. The eight attacks' numbers are in G.ATTACKS.
  • The stock humanoid mesh is hidden once per body, so the guardian's own faceted figure is what the camera sees while the engine still animates the skeleton underneath it.
  • Stamina is the sprint's and the abilities'. Sprinting drains it, standing still refills it, and an attack that costs more than half the bar is refused.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

game.hero.Hero — the guardian the player is. Boots onto `MountHero`. Owns the figure, the camera's subject, movement state, health and stamina, and the four attacks. It does not move the body: the scene's avatar carries the engine's own controller and locomotion, which already answer WASD, SHIFT and SPACE — this reads the same controls for the sword and dresses the body as a guardian. Damage is decided here, not by the foe: an attack may only touch a foe inside its `reach` and inside the half-angle `arc` around the guardian's facing, so a swing across the room does nothing.

Model

mat(name: string, rgb: { number }, emissive: number?, metallic: number?) → void

argtypedescription
namestring
rgb{ number }
emissivenumber?
metallicnumber?

buildFigure(parent: any) → any

A guardian built from faceted primitives: elephant head, crown, trunk, ears, gold at every joint, vermilion dhoti, and a three-pronged trishul. Deliberately the signature silhouette from the character reference, and the last thing a generated mesh replaces.

argtypedescription
parentany

add(name: string, model: any, material: any, pos: { number }, scale: { number }, rot: { number }?) → void

argtypedescription
namestring
modelany
materialany
pos{ number }
scale{ number }
rot{ number }?

wadd(name: string, model: any, material: any, pos: { number }, scale: { number }, rot: { number }?) → void

argtypedescription
namestring
modelany
materialany
pos{ number }
scale{ number }
rot{ number }?

hideStockBody( ) → void

The engine's humanoid mesh is under the avatar; the guardian replaces it.

canAfford(cfg: any) → boolean

argtypedescription
cfgany

beginAttack(id: string) → void

argtypedescription
idstring

resolveHit(cfg: any) → void

argtypedescription
cfgany

tickSwing(dt: number) → void

argtypedescription
dtnumber

onPlayerHit(payload: any) → void

argtypedescription
payloadany

awake( ) → void

start( ) → void

update(dt: ?) → void

argtypedescription
dt?

onDestroy( ) → void

facing( ) → number

The guardian's current facing, in radians.

attack(id: string) → void

Begin one of the four attacks by id. Used by the interface's buttons.

argtypedescription
idstring

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

7items
▣
module · born here
❒asset
# Game The spine of **GANESHA: GUARDIAN OF THE PORTAL**. One shared module every slice requires: the tuning numbers, the eight Rakshasas and their arenas, the eleven quests, the story machine's acts, the mount points, and the event bus. It draws nothing, moves nothing and sounds nothing — it is the contract that lets a slice be written without knowing who else is in the world. `require` returns one shared instance per world, so `G.state` read in the hero slice is the same table the interface slice reads, and `G.on` / `G.emit` is how one slice learns what another did. ## Exports - `G.TITLE`, `G.SUBTITLE` — the title card's own words. - `G.ART_STYLE` — the one art-direction sentence every visual decision answers to. - `G.PALETTE` (hex, for the interface) and `G.RGB` (0-1 triples, for lights/materials). - `G.ACT` / `G.ACT_ORDER` — the story machine's phases. - `G.QUESTS` — the eleven quests, in order: `{ title, objective }`. - `G.PLAYER` — the guardian's 2000 HP, speeds, stamina, jump. - `G.ATTACKS` / `G.ATTACK_ORDER` / `G.ABILITY_BAR` — the four attacks with damage, timing, reach, arc and cooldown. - `G.FOES` — the eight Rakshasas: health, speed, damage, reach, behaviour, tells. - `G.ARENAS` — the eight battlefields: ground colour, sky, sun, fog, props. - `G.BEATS` — timings for the beats between fights. - `G.state` — the shared run state (act, quest, arena, health, foe, banner…). - `G.EV` — event names; `G.on(name, fn)` and `G.emit(name, payload)`. - `G.setAct` / `G.setQuest` / `G.setArena` — the only writers of those fields. - `G.banner` / `G.toast` / `G.kick` / `G.freeze` — the presentation verbs. - `G.MOUNTS` / `G.SLICES` — where each slice is booted. - `G.clamp` / `G.lerp` / `G.damp` / `G.angleDelta` / `G.horizDist` / `G.yawTo`. - `G.arena()` / `G.foeAt(i)` / `G.questForArena(i)` / `G.restart()`. ## Usage ```luau local G = require("game.Game") G.on(G.EV.FOE_DIED, function(foe) G.setQuest(G.questForArena(G.state.arena)) end) if G.state.act == G.ACT.FIGHT then local arena = G.arena() local tuning = G.foeAt(G.state.arena) end ``` ## Notes - **State has one writer per field.** The hero slice owns `health`, `stamina` and `cooldowns`; the foes slice owns `foe` and `bossBar`; the world slice owns `act` transitions from its own beats. Announce changes with `G.emit` so the interface and the sound slice hear them. - **The bus is per world, not per frame.** Subscribe in `start()` and keep the unsubscribe function the subscribe returns; drop it in `onDestroy()` or a reload will leave two listeners running. - **Arenas are 1-indexed and match `G.FOES` by `arena.foe`.**
▲ 0↑ born
backing path · game/hero/Hero.component

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.