Add comprehensive documentation for sprites and systems
- Introduced detailed analysis for the Minecart system, highlighting its state machine, track system, and areas for improvement. - Created an NPCs analysis document, summarizing various NPC sprites and their functionalities. - Added an Objects analysis document, covering interactive elements like collectibles, ice blocks, and minecarts. - Documented the Overlord sprite system, detailing its role in spawning other sprites and managing events. - Compiled a Dungeons & Indoor Areas document, outlining custom room tags, enhanced mechanics, and advanced collision systems. - Developed an Overworld Systems Analysis, focusing on the ZSCustomOverworld architecture and its core features. - Added a Time System document, explaining the in-game clock and day/night cycle management. - Documented the ZScream Custom Overworld, detailing its data-driven approach and key features.
This commit is contained in:
77
Docs/Sprites/Bosses.md
Normal file
77
Docs/Sprites/Bosses.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Bosses Analysis
|
||||
|
||||
This document provides an analysis of the boss sprites found in the `Sprites/Bosses/` directory. These sprites are typically complex, with multiple phases and unique behaviors.
|
||||
|
||||
## File Overview
|
||||
|
||||
| Filename | Sprite ID(s) | Description |
|
||||
|---|---|---|
|
||||
| `arrghus.asm` | (Hooks `$1EB593`) | A custom version of Arrghus that spawns fireballs. |
|
||||
| `dark_link.asm` | `Sprite_DarkLink` (`$C1`) | A multi-phase boss fight against a shadow version of Link. |
|
||||
| `king_dodongo.asm`| (Hooks `$1E811A`) | A custom version of King Dodongo with a new health system. |
|
||||
| `kydreeok.asm` | `Sprite_Kydreeok` | A multi-headed sea monster boss. Parent sprite for `kydreeok_head.asm`. |
|
||||
| `kydreeok_head.asm`| `Sprite_KydreeokHead` | The individual head of the Kydreeok boss, which can be attacked. |
|
||||
| `kydrog.asm` | `Sprite_KydrogNPC` | A cutscene version of Kydrog that appears before the boss fight. |
|
||||
| `kydrog_boss.asm` | `Sprite_KydrogBoss` | The main Kydrog boss fight, a large amphibious creature. |
|
||||
| `lanmola.asm` | (Hooks `$05A377`) | A custom version of the Lanmola boss. |
|
||||
| `lanmola_expanded.asm`| (Expansion) | Contains additional data and drawing logic for the custom Lanmola. |
|
||||
| `manhandla.asm` | `Sprite_Manhandla` | A two-phase boss fight against Manhandla, which later becomes a Big Chuchu. |
|
||||
| `octoboss.asm` | (Hooks `Sprite_A2_Kholdstare`) | A custom boss fight against two octopuses, replacing Kholdstare. |
|
||||
| `twinrova.asm` | `Sprite_Twinrova` (`$CE`) | A custom boss fight replacing Blind the Thief with the twin witches, Koume and Kotake. |
|
||||
| `vampire_bat.asm` | (Subtype of Keese) | A vampire bat mini-boss. |
|
||||
| `wolfos.asm` | `Sprite_Wolfos` | A Wolfos mini-boss that guards the Wolf Mask. |
|
||||
|
||||
## Detailed Boss Analysis
|
||||
|
||||
### `dark_link.asm`
|
||||
- **Sprite ID:** `Sprite_DarkLink` (`$C1`)
|
||||
- **Summary:** A complex, multi-action boss that mimics Link's abilities. The fight has multiple stages, including a Ganon-like form.
|
||||
- **Key Logic:**
|
||||
- The main routine is a large state machine driven by `SprAction, X`.
|
||||
- **Actions:** Includes standard walking, sword slashes, jump attacks, dodging, and using items like bombs and the Magic Cape.
|
||||
- **AI:** The AI in the `Handler` routine decides which action to take based on the distance to the player. It can choose to slash, dodge, or use a special attack.
|
||||
- **Enrage Mechanic:** At a certain health threshold (`SprHealth < $20`), the boss can enter an "enraged" state (`Enraging` action), which refills its health and makes its attacks faster.
|
||||
- **Ganon Subtype:** If `SprSubtype` is 5, it uses Ganon's draw and main logic, acting as a final phase.
|
||||
|
||||
### `kydreeok.asm` / `kydreeok_head.asm`
|
||||
- **Sprite IDs:** `Sprite_Kydreeok` (body), `Sprite_KydreeokHead` (head, ID `$CF`)
|
||||
- **Summary:** A large, stationary sea monster boss with multiple heads that act as its weak points. The main body sprite (`Kydreeok`) is a controller that spawns and manages the head sprites.
|
||||
- **Key Logic:**
|
||||
- **`Kydreeok_Prep`:** Spawns two `KydreeokHead` sprites (`SpawnLeftHead`, `SpawnRightHead`).
|
||||
- **`Kydreeok_Main`:** The body moves around the arena, and the heads follow its position, controlled via shared RAM addresses (`LeftNeck1_X`, etc.).
|
||||
- **`KydreeokHead_Main`:** The heads have their own AI. They move in a rotational pattern and randomly shoot fireballs at the player.
|
||||
- **Damage:** Only the head sprites can be damaged. When both heads are defeated, the main body sprite is killed.
|
||||
|
||||
### `manhandla.asm`
|
||||
- **Sprite ID:** `Sprite_Manhandla` (`$88`)
|
||||
- **Summary:** A two-phase boss. The first phase is a plant-like creature with three heads. The second phase is a large Big Chuchu.
|
||||
- **Key Logic:**
|
||||
- **Phase 1 (Manhandla):** The main body (`Manhandla_Body`) moves around the room, and three head sprites are spawned as offspring. The boss is only vulnerable when the heads are defeated.
|
||||
- **Phase Transition:** When all three heads are killed, `Sprite_Manhandla_CheckForNextPhaseOrDeath` sets `SprMiscD` to 1, refills the boss's health, and transitions to the `BigChuchu_Emerge` action.
|
||||
- **Phase 2 (Big Chuchu):** The sprite changes its appearance and behavior to that of a large slime. It moves around, spawns smaller slime projectiles (`Chuchu_SpawnBlast`), and has a central flower weak point.
|
||||
|
||||
### `octoboss.asm`
|
||||
- **Sprite ID:** (Replaces `Sprite_A2_Kholdstare`)
|
||||
- **Summary:** A custom boss fight featuring two octopus brothers who replace the vanilla Kholdstare boss.
|
||||
- **Key Logic:**
|
||||
- The fight begins when the player approaches, triggering the `Emerge` sequence.
|
||||
- The first octopus spawns its brother (`SpawnAndAwakeHisBrother`), and they both don hats (`SpawnPirateHats`).
|
||||
- The two sprites then move independently, attacking the player. Their total health is tracked via `ReturnTotalHealth`.
|
||||
- When their combined health is low enough, they surrender (`WaitMessageBeforeSurrender`), remove their hats, and one submerges to give the player the Quake Medallion.
|
||||
|
||||
### `twinrova.asm`
|
||||
- **Sprite ID:** `Sprite_Twinrova` (`$CE`, replaces Blind the Thief)
|
||||
- **Summary:** A custom, multi-phase boss fight against the twin witches Koume (fire) and Kotake (ice). This sprite completely replaces the vanilla Blind the Thief boss, including the cutscene leading up to it.
|
||||
- **Key Logic:**
|
||||
- **Trigger:** The fight begins when the Blind Maiden follower is brought into the boss room. `Follower_CheckBlindTrigger` detects this, and `Blind_SpawnFromMaiden` despawns the maiden and spawns the Twinrova sprite.
|
||||
- **Phase 1:** The combined Twinrova form moves around the room, alternating between fire (`Twinrova_FireAttack`) and ice (`Twinrova_IceAttack`) attacks.
|
||||
- **Phase 2:** When health is low, the boss splits. The `Twinrova_MoveState` action will randomly choose between `KoumeMode` (fire) and `KotakeMode` (ice). In these modes, the boss has different attack patterns, including spawning Keese and changing the floor tiles.
|
||||
|
||||
### `wolfos.asm`
|
||||
- **Sprite ID:** `Sprite_Wolfos`
|
||||
- **Summary:** A mini-boss that guards the Wolf Mask. It is designed to be subdued rather than killed.
|
||||
- **Key Logic:**
|
||||
- The Wolfos attacks Link with lunges and swipes.
|
||||
- When its health is depleted, `Sprite_Wolfos_CheckIfDefeated` transitions it to the `Wolfos_Subdued` action instead of killing it.
|
||||
- In the subdued state, it waits for the player to play the Song of Healing (`SongFlag`).
|
||||
- Once the song is played, it grants the Wolf Mask (`ITEMGET` ID `$10F`) and then despawns.
|
||||
78
Docs/Sprites/IceBlock.md
Normal file
78
Docs/Sprites/IceBlock.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Ice Block System (`Sprites/Objects/ice_block.asm`)
|
||||
|
||||
## Overview
|
||||
|
||||
This file contains the logic for the pushable ice block sprite. It's a statue-like object that, when pushed by Link, slides in one direction until it collides with a wall, another object, or a switch.
|
||||
|
||||
## Key Functionality
|
||||
|
||||
- **Pushing Mechanics:** When Link makes contact, the block's `SprMiscA` register stores Link's facing direction. A timer (`SprTimerA`) is used to confirm the push, after which the block is set in motion.
|
||||
- **Sliding:** Once pushed, the block moves at a constant velocity until a collision is detected.
|
||||
- **Collision:** The block stops moving when it collides with a wall (detected via `SprCollision`) or another sprite (handled in `Statue_BlockSprites`). It also stops when it hits a specific switch tile.
|
||||
- **State Management:** The sprite uses `SprMisc` registers to track its state, such as whether it's currently being pushed (`SprMiscC`) or is in motion (`SprMiscB`).
|
||||
|
||||
## Analysis & Areas for Improvement
|
||||
|
||||
The ice block is a classic Zelda puzzle element, but its current implementation suffers from over-sensitivity and unpredictable behavior, leading to frustration for beta testers. The goal is to achieve a "Pokémon-style" grid-based sliding puzzle feel, requiring intentional pushes and predictable movement.
|
||||
|
||||
### Current Problems:
|
||||
- **Over-sensitivity:** The block initiates movement on simple hitbox overlap with Link, leading to accidental pushes.
|
||||
- **Unpredictable Direction:** Link's slight movements or diagonal contact can result in the block sliding in unintended directions.
|
||||
- **Non-grid-aligned movement:** The block does not snap to a grid, making its stopping positions feel imprecise.
|
||||
|
||||
### Proposed Improvements:
|
||||
|
||||
#### 1. Intent-Based Push Mechanics (Addressing Sensitivity & Direction)
|
||||
The current `JSL Sprite_CheckDamageToPlayerSameLayer` is too broad. It will be replaced with a more robust system:
|
||||
|
||||
- **Directional Alignment Check:** A new subroutine (`IceBlock_CheckLinkPushAlignment`) will be implemented. This routine will verify that Link is:
|
||||
- Directly adjacent to the ice block.
|
||||
- Facing the ice block (e.g., if Link is facing right, the block must be to his right).
|
||||
- Aligned within a small pixel tolerance (e.g., +/- 4 pixels) on the non-pushing axis (e.g., for a horizontal push, Link's Y-coordinate must be close to the block's Y-coordinate).
|
||||
- **Push Confirmation Timer:** Instead of an immediate push, a short timer (e.g., 10-15 frames) will be introduced. Link must maintain the correct directional alignment and contact for this duration to confirm an intentional push. If contact or alignment is broken, the timer resets.
|
||||
- **Locked Direction:** Once a push is confirmed, the block's movement direction will be locked to a single cardinal direction (horizontal or vertical) until it collides with an obstacle.
|
||||
|
||||
#### 2. Predictable Movement & Stopping (Grid Alignment)
|
||||
- **Grid Snapping on Push:** When a push is confirmed, the ice block's coordinates (`SprX, SprY`) will be snapped to the nearest 8-pixel grid boundary before movement begins. This ensures that all slides start and end cleanly on the game's tile grid.
|
||||
|
||||
#### 3. Code Refactoring & Readability (General Improvements)
|
||||
While implementing the above, the following existing suggestions from the previous analysis will also be applied:
|
||||
|
||||
- **Use `subroutine` for All Code Blocks:** Convert all major logical blocks within `Sprites/Objects/ice_block.asm` into proper `subroutine`s for better scope management and readability.
|
||||
- **Replace Magic Numbers with Constants:** Define named constants for all hardcoded values (speeds, timers, tile IDs, alignment tolerances) to improve code clarity and maintainability.
|
||||
- **Refactor `Sprite_ApplyPush`:** Convert the `Sprite_ApplyPush` routine to use a lookup table for setting `SprXSpeed` and `SprYSpeed` based on the determined push direction. This will make the code more compact and easier to modify.
|
||||
- **Clarify `Statue_BlockSprites`:** Rename this routine to `IceBlock_HandleSpriteToSpriteCollision` and add detailed comments to explain its logic, especially concerning sprite-to-sprite collision and recoil calculations.
|
||||
|
||||
## Deeper Analysis: Sprite Solidity and Link's Collision
|
||||
|
||||
To understand why the ice block is not solid, we need to look at both the sprite's properties and Link's collision detection code.
|
||||
|
||||
### Sprite Property Analysis
|
||||
|
||||
Several flags in the sprite's RAM data structure control its physical properties. These are the most relevant for solidity:
|
||||
|
||||
* **`!Statue = 01` Property:** In the sprite's header, `!Statue = 01` is set. This is a high-level property that should be translated into one or more of the low-level RAM flags by the `%Set_Sprite_Properties` macro when the sprite is initialized.
|
||||
|
||||
* **`SprDefl` (`$0CAA`):** This is the "Sprite Deflection" register and appears to be critical.
|
||||
* **Bit 2 (`$04`):** The `Core/symbols.asm` file labels this the "pushable interaction flag". Although the comment says it's "Never queried," this is highly suspect and is the most likely candidate for enabling pushable-statue physics.
|
||||
* **Our Bug:** Our previous attempts to modify `Sprite_IceBlock_Prep` either cleared this register entirely (`STZ.w SprDefl, X`) or left it alone, both of which resulted in Link walking through the block. This indicates that this register's value is crucial and must be set correctly, likely by the engine's default property loading routines. Our code was interfering with this.
|
||||
|
||||
* **`SprHitbox` (`$0F60`):** This register contains the `I` (Ignore Collisions) bit.
|
||||
* **Bit 7 (`$80`):** If this bit is set, the sprite will ignore all collisions with Link. We must ensure our code does not accidentally set this bit.
|
||||
|
||||
### Link's Collision Logic (Hypothesis)
|
||||
|
||||
The core of Link's interaction with the world is handled in `bank_07.asm`.
|
||||
|
||||
* **`Link_HandleCardinalCollision` (`JSR` at `#_0782C2`):** This is the key function that processes Link's movement against solid objects. A full analysis is pending a complete reading of `bank_07.asm`, but we can hypothesize its behavior.
|
||||
* **Hypothesis:** This routine likely loops through all active sprites on screen. For each sprite, it checks a combination of flags (e.g., `SprDefl`, `SprHitbox`) to determine if the sprite is solid. If it is, it performs a bounding box check. If Link's next position would overlap with a solid sprite, his movement is halted. The fact that Link walks through the ice block proves that the block is not being flagged as solid correctly.
|
||||
|
||||
### Revised Troubleshooting Plan
|
||||
|
||||
Based on this deeper analysis, the plan is to work *with* the game engine's properties, not against them.
|
||||
|
||||
1. **Analyze `Link_HandleCardinalCollision`:** The top priority is to find and fully analyze this function in `bank_07.asm` to understand exactly which sprite flags it checks to identify a solid, pushable object.
|
||||
2. **Analyze `SpritePrep_LoadProperties`:** Understand how the `%Set_Sprite_Properties` macro and the subsequent `JSL SpritePrep_LoadProperties` function translate the `!Statue = 01` property into RAM flags. This will reveal the correct default values for a statue.
|
||||
3. **Correct `Sprite_IceBlock_Prep`:** With the knowledge from the steps above, write a definitive `Sprite_IceBlock_Prep` routine that correctly initializes all necessary flags (`SprDefl`, etc.) for a pushable statue, without overriding engine defaults.
|
||||
4. **Verify Solidity:** Build and test to confirm Link collides with the block.
|
||||
5. **Re-evaluate Push Logic:** Once the block is solid, re-evaluate the push initiation logic, which uses `JSL Sprite_CheckDamageToPlayerSameLayer`. If it still fails, we will have a solid object to debug against, which is a much better state.
|
||||
72
Docs/Sprites/Minecart.md
Normal file
72
Docs/Sprites/Minecart.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Minecart System (`Sprites/Objects/minecart.asm`)
|
||||
|
||||
## Overview
|
||||
|
||||
The minecart is a highly complex and stateful sprite. It functions as a vehicle for the player, following predefined tracks, handling intersections, and persisting its location across rooms. This system is one of the most intricate custom sprites in the project.
|
||||
|
||||
## Key Functionality
|
||||
|
||||
- **State Machine:** The sprite operates on a state machine (`Minecart_WaitHoriz`, `Minecart_WaitVert`, `Minecart_Move...`) to handle waiting, player interaction, and movement.
|
||||
- **Track System:** A custom system using a large block of SRAM (starting at `!MinecartTrackRoom = $0728`) allows up to 32 unique minecart "tracks" to exist in the world. The sprite saves its position and room index to this table, allowing it to reappear where the player left it.
|
||||
- **Custom Collision:** The minecart does not use standard sprite collision. Instead, it reads the tile ID at its center to determine its behavior, following a complex set of rules for straight tracks, corners, intersections, and stops.
|
||||
- **Player Interaction:** The player can start, stop, and change the direction of the cart at specific junctions.
|
||||
|
||||
## Analysis & Areas for Improvement
|
||||
|
||||
This is a very impressive piece of engineering for an SNES game. The code is dense and showcases advanced techniques. The main areas for improvement are in readability, data organization, and reducing code duplication.
|
||||
|
||||
### 1. Use a `struct` for the Track System
|
||||
|
||||
- **Observation:** The minecart tracking system is managed by a series of parallel arrays in SRAM (`!MinecartTrackRoom`, `!MinecartTrackX`, `!MinecartTrackY`). This is functional but can be confusing to read and maintain.
|
||||
- **Suggestion:** This is a perfect use case for asar's `struct` directive. Define a structure for a single track and then create a table of those structures.
|
||||
|
||||
*Example:*
|
||||
```asm
|
||||
struct MinecartTrack
|
||||
Room dw
|
||||
XPos dw
|
||||
YPos dw
|
||||
endstruct
|
||||
|
||||
; In your RAM definitions
|
||||
MinecartTracks table[32] of MinecartTrack
|
||||
```
|
||||
- **Benefit:** This makes the data structure explicit and far more readable. Accessing data becomes `MinecartTracks.Room[track_index]` instead of calculating offsets into a generic block of RAM.
|
||||
|
||||
### 2. Refactor Movement and Direction-Setting Code
|
||||
|
||||
- **Observation:**
|
||||
- The routines `Minecart_MoveNorth`, `Minecart_MoveEast`, `Minecart_MoveSouth`, and `Minecart_MoveWest` contain very similar logic, differing only in the speed value and axis.
|
||||
- The direction-setting routines (`Minecart_SetDirectionNorth`, etc.) also contain significant duplication.
|
||||
- **Suggestion:**
|
||||
- Create a single `Minecart_Move` subroutine that takes a direction as an argument. It could use a lookup table to fetch the correct speed and axis.
|
||||
- Create a single `Minecart_SetDirection` subroutine that takes a direction argument and sets the `SprMiscB`, `!MinecartDirection`, and animation state from lookup tables.
|
||||
- **Benefit:** Massively reduces code duplication, making the logic easier to debug and modify. A change to movement logic would only need to be made in one place.
|
||||
|
||||
### 3. Use `subroutine` for All Code Blocks
|
||||
|
||||
- **Observation:** The file uses a mix of labels and macros (`%GotoAction`) for its state machine. The main logic is a large jump table.
|
||||
- **Suggestion:** Convert all logical blocks (`Minecart_WaitHoriz`, `HandleTileDirections`, `CheckForCornerTiles`, etc.) into proper `subroutine`s.
|
||||
- **Benefit:** Enforces local scoping for labels, improves readability, and makes the code's structure much clearer.
|
||||
|
||||
### 4. Replace Magic Numbers with Constants
|
||||
|
||||
- **Observation:** The code is full of hardcoded values for directions, speeds, tile IDs, and sprite states.
|
||||
- **Suggestion:** Define constants for all of these.
|
||||
|
||||
*Example:*
|
||||
```asm
|
||||
!CART_SPEED = 20
|
||||
!TILE_TRACK_CORNER_TL = $B2
|
||||
|
||||
!DIR_NORTH = 0
|
||||
!DIR_EAST = 1
|
||||
; etc.
|
||||
```
|
||||
- **Benefit:** This is crucial for a system this complex. It makes the code self-documenting and dramatically reduces the chance of introducing bugs from typos in numerical values.
|
||||
|
||||
### 5. Add High-Level Comments
|
||||
|
||||
- **Observation:** The code has some comments, but they mostly describe *what* a single line is doing.
|
||||
- **Suggestion:** Add block comments at the top of major subroutines (especially `Sprite_Minecart_Prep` and `HandleTileDirections`) explaining the overall *purpose* and *logic* of the code block. Explain the caching/tracking system in detail.
|
||||
- **Benefit:** This is essential for future maintainability, especially for a system this intricate. It will make it possible for you or others to understand the code after being away from it for a while.
|
||||
90
Docs/Sprites/NPCs.md
Normal file
90
Docs/Sprites/NPCs.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# NPCs Analysis
|
||||
|
||||
This document provides an analysis of the Non-Player Character (NPC) sprites found in the `Sprites/NPCs/` directory.
|
||||
|
||||
## File Overview
|
||||
|
||||
| Filename | Sprite ID(s) | Description |
|
||||
|---|---|---|
|
||||
| `bean_vendor.asm` | `Sprite_BeanVendor` | Handles the logic for the bean vendor who sells Magic Beans to the player. |
|
||||
| `bottle_vendor.asm` | (Vanilla Hook) | Modifies the vanilla bottle vendor to handle selling milk. |
|
||||
| `bug_net_kid.asm` | (Vanilla Hook) | Modifies the Sick Kid to grant the Pegasus Boots after playing the Song of Healing. |
|
||||
| `deku_scrub.asm` | `Sprite_DekuScrubNPCs` | Manages various Deku Scrub NPCs, including one who gives the Deku Mask. |
|
||||
| `eon_owl.asm` | `Sprite_EonOwl` | The owl that guides Link. Includes logic for both the Eon Owl and Kaepora Gaebora. |
|
||||
| `eon_zora.asm` | (Part of `zora.asm`) | A friendly Zora NPC found in the Eon Abyss. |
|
||||
| `eon_zora_elder.asm`| (Part of `zora.asm`) | The elder Zora in the Eon Abyss. |
|
||||
| `farore.asm` | `Sprite_Farore` | The Oracle Farore, who appears in cutscenes and guides the player. |
|
||||
| `followers.asm` | (Vanilla Hooks) | Contains logic for various follower characters like the Zora Baby and the Old Man. |
|
||||
| `fortune_teller.asm`| (Vanilla Hook) | Modifies the fortune teller's dialogue to provide hints relevant to the hack's progression. |
|
||||
| `goron.asm` | `Sprite_Goron` | Handles both the Kalyxo Goron who opens the mines and the Eon Gorons. |
|
||||
| `hyrule_dream.asm` | (Part of `farore.asm`) | Logic for NPCs appearing in Link's dream sequences (Zelda, King, Soldier). |
|
||||
| `impa.asm` | (Vanilla Hook) | Modifies Impa's behavior, particularly in setting spawn points. |
|
||||
| `korok.asm` | `Sprite_Korok` | A friendly Korok NPC. |
|
||||
| `maku_tree.asm` | `Sprite_MakuTree` | The Maku Tree, a key story NPC who provides a Heart Container. |
|
||||
| `maple.asm` | (Part of `mermaid.asm`)| Maple the witch, who can send Link to dream worlds. |
|
||||
| `mask_salesman.asm` | `Sprite_MaskSalesman` | The Happy Mask Salesman, who sells the Bunny Hood and Stone Mask. |
|
||||
| `mermaid.asm` | `Sprite_Mermaid` | A friendly mermaid NPC. Also contains logic for Maple and the Librarian. |
|
||||
| `piratian.asm` | `$0E` | A friendly pirate-like NPC that becomes aggressive if attacked. |
|
||||
| `ranch_girl.asm` | (Vanilla Hook) | Modifies the chicken lady at the ranch to give the Ocarina. |
|
||||
| `tingle.asm` | `$22` | Tingle, who sells dungeon maps to the player. |
|
||||
| `vasu.asm` | `Sprite_Vasu` | Vasu, the jeweler who appraises magic rings. Also includes logic for Error. |
|
||||
| `village_dog.asm` | `Sprite_VillageDog` | A friendly dog that interacts with the player. Includes logic for the Eon Dog. |
|
||||
| `village_elder.asm` | (Part of `bean_vendor.asm`)| The village elder NPC. |
|
||||
| `zora_princess.asm` | `Sprite_ZoraPrincess` | The Zora Princess, who grants the Zora Mask. |
|
||||
| `zora.asm` | `Sprite_Zora` | A friendly Zora NPC. Also contains logic for the Zora Princess and Eon Zoras. |
|
||||
|
||||
## Detailed NPC Analysis
|
||||
|
||||
### `bean_vendor.asm` / `village_elder.asm`
|
||||
- **Sprite ID:** `Sprite_BeanVendor`
|
||||
- **Summary:** This file contains the logic for two NPCs. The primary is the Bean Vendor, who sells Magic Beans for 100 rupees. The second is the Village Elder.
|
||||
- **Key Logic:**
|
||||
- **BeanVendor:** Initiates a dialogue on contact. If the player agrees to buy, it checks for sufficient rupees, deducts the cost, and spawns a collectible Magic Bean sprite.
|
||||
- **VillageElder:** Engages in dialogue and sets a progress flag (`OOSPROG`) after the first interaction.
|
||||
|
||||
### `bug_net_kid.asm`
|
||||
- **Sprite ID:** (Hooks `SpritePrep_SickKid`)
|
||||
- **Summary:** This modifies the vanilla "Sick Kid" NPC. Instead of giving the Bug Net, he gives the player the Pegasus Boots.
|
||||
- **Key Logic:** The `SickKid_CheckForSongOfHealing` routine checks if the `SongFlag` is set. If it is, the `BugNetKid_GrantBugNet` routine is called, which uses `Link_ReceiveItem` to give the boots (`ITEMGET` ID `$4B`).
|
||||
|
||||
### `deku_scrub.asm`
|
||||
- **Sprite ID:** `Sprite_DekuScrubNPCs`
|
||||
- **Summary:** Manages several Deku Scrub NPCs, including the Deku Butler and Deku Princess. A key interaction involves a withered Deku Scrub who, after being healed with the Song of Healing, gives the player the Deku Mask.
|
||||
- **Key Logic:**
|
||||
- The main state machine checks for the `SongFlag`.
|
||||
- If the song is played, it transitions through a dialogue sequence (`QuiereCuracion`, `DarMascara`).
|
||||
- Finally, in the `Regalo` state, it calls `Link_ReceiveItem` with item ID `$11` (Deku Mask) and sets a progress flag (`$7EF301`).
|
||||
|
||||
### `eon_owl.asm`
|
||||
- **Sprite ID:** `Sprite_EonOwl`
|
||||
- **Summary:** This is the guide owl, appearing in both the overworld (as Eon Owl) and the Hall of Secrets (as Kaepora Gaebora).
|
||||
- **Key Logic:**
|
||||
- **Eon Owl:** In the overworld, it triggers introductory dialogue when the player gets close and then flies away.
|
||||
- **Kaepora Gaebora:** In the Hall of Secrets, it appears only after all 7 crystals are collected and before the player has the Song of Soaring. It offers to teach the player the song.
|
||||
|
||||
### `farore.asm` / `hyrule_dream.asm`
|
||||
- **Sprite ID:** `Sprite_Farore`
|
||||
- **Summary:** Handles the Oracle Farore and NPCs that appear in dream sequences.
|
||||
- **Key Logic:**
|
||||
- **Farore:** Manages the introductory cutscene where she follows Link, sets the main story state (`$B6`), and changes the game state to post-pendants (`$7EF3C5 = 2`).
|
||||
- **Dream NPCs:** Contains simple display logic for Zelda, the King, and a soldier during the `MakuTree_HasMetLink` dream sequence.
|
||||
|
||||
### `followers.asm`
|
||||
- **Sprite ID:** (Hooks vanilla follower system)
|
||||
- **Summary:** Contains significant custom logic for follower characters, most notably the Zora Baby (Locksmith) and the Old Man.
|
||||
- **Key Logic:**
|
||||
- **Zora Baby:**
|
||||
- Replaces the Locksmith sprite (`$39`).
|
||||
- Can be picked up and carried by Link.
|
||||
- When placed on a water gate switch, it triggers the switch.
|
||||
- Transitions from a follower to a standard sprite when on a star tile in a dungeon.
|
||||
- **Old Man:** Logic is modified to grant the Goldstar (Hookshot Lv2 upgrade) instead of the Magic Mirror.
|
||||
|
||||
### `vasu.asm`
|
||||
- **Sprite ID:** `Sprite_Vasu`
|
||||
- **Summary:** This is the ring jeweler, Vasu. He can appraise rings the player has found. The file also contains logic for the "I am Error" NPC.
|
||||
- **Key Logic:**
|
||||
- Vasu's main loop presents a choice: "Appraise" or "Explain".
|
||||
- If "Appraise" is chosen, it checks if the player has any unappraised rings (`FOUNDRINGS`).
|
||||
- It charges 20 rupees (the first one is free) and transfers the bits from `FOUNDRINGS` to `MAGICRINGS`, making them usable.
|
||||
- The Error NPC appears as a subtype and gives the player a random ring when spoken to.
|
||||
56
Docs/Sprites/Objects.md
Normal file
56
Docs/Sprites/Objects.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Objects Analysis
|
||||
|
||||
This document provides an analysis of the object sprites found in the `Sprites/Objects/` directory. These sprites are typically interactive elements of the environment rather than enemies.
|
||||
|
||||
## File Overview
|
||||
|
||||
| Filename | Sprite ID(s) | Description |
|
||||
|---|---|---|
|
||||
| `collectible.asm` | `$52` | A generic collectible sprite that can represent a Pineapple, Seashell, Sword/Shield, or Rock Sirloin. |
|
||||
| `deku_leaf.asm` | `Sprite_DekuLeaf` | A Deku Leaf platform that Link can stand on. Also used for whirlpools. |
|
||||
| `ice_block.asm` | `$D5` | A pushable ice block used in puzzles. |
|
||||
| `minecart.asm` | `Sprite_Minecart` (`$A3`) | A rideable minecart used for transportation puzzles in dungeons. |
|
||||
| `mineswitch.asm` | `Sprite_Mineswitch` | A lever switch that can be hit to change the state of other objects, like minecart tracks. |
|
||||
| `pedestal.asm` | (Hooks `$1EE05F`) | Logic for the magic pedestals where Link can read text with the Book of Mudora. |
|
||||
| `portal_sprite.asm` | `Sprite_Portal` | The blue and orange portals created by the Portal Rod. |
|
||||
| `switch_track.asm` | `Sprite_SwitchTrack` (`$B0`) | The visual component of a switchable minecart track, which rotates when a lever is hit. |
|
||||
|
||||
## Detailed Object Analysis
|
||||
|
||||
### `collectible.asm`
|
||||
- **Sprite ID:** `$52`
|
||||
- **Summary:** This is a versatile sprite that acts as a world collectible. Its behavior and appearance are determined by its `SprAction` state, which is set during prep.
|
||||
- **Key Logic:**
|
||||
- **`Sprite_Collectible_Prep`:** Checks the current map (`$8A`) to determine what the sprite should be. For example, on map `$58` (intro), it becomes the sword and shield.
|
||||
- **`Sprite_Collectible_Main`:** The main state machine. On contact with the player (`Sprite_CheckDamageToPlayer`), it increments the corresponding counter in SRAM (e.g., `Pineapples`, `Seashells`) or grants an item (`Link_ReceiveItem`) and then despawns itself.
|
||||
|
||||
### `ice_block.asm`
|
||||
- **Sprite ID:** `$D5`
|
||||
- **Summary:** A block that slides on icy floors when pushed by Link. It is used for puzzles.
|
||||
- **Key Logic:**
|
||||
- **Pushing:** When Link is in contact (`Sprite_CheckDamageToPlayerSameLayer`), the `Sprite_ApplyPush` routine gives the block velocity based on the direction Link is facing.
|
||||
- **Sliding:** The block continues to move in that direction (`Sprite_Move`) until it hits a wall (`Sprite_CheckTileCollision`) or another object.
|
||||
- **Switch Interaction:** `Sprite_IceBlock_CheckForSwitch` checks if the block is on top of a floor switch tile. If so, it sets a flag (`$0642`) to activate the switch and stops moving.
|
||||
|
||||
### `minecart.asm` / `switch_track.asm` / `mineswitch.asm`
|
||||
- **Sprite IDs:** `Sprite_Minecart` (`$A3`), `Sprite_SwitchTrack` (`$B0`), `Sprite_Mineswitch`
|
||||
- **Summary:** This is a complex system of three interconnected sprites that create minecart puzzles.
|
||||
- **Key Logic:**
|
||||
- **`Sprite_Minecart`:**
|
||||
- The player can press B to enter the cart (`Minecart_WaitHoriz`/`Vert`). This sets the `!LinkInCart` flag and attaches the player.
|
||||
- The cart moves along a path defined by custom tile types (`$B0`-`$BE`).
|
||||
- At intersections (`$B6`, etc.), it reads player input (`$F0`) to determine which way to turn (`CheckForPlayerInput`).
|
||||
- At corners (`$B2`-`$B5`), it automatically turns (`CheckForCornerTiles`).
|
||||
- At dynamic switch tracks (`$D0`-`$D3`), it checks the state of the corresponding `Sprite_Mineswitch` to determine its path (`HandleDynamicSwitchTileDirections`).
|
||||
- At dungeon transitions, it converts into a follower sprite (`MinecartFollower_TransitionToSprite`) to persist between rooms.
|
||||
- **`Sprite_SwitchTrack`:** This is a purely visual sprite. Its frame is set based on the on/off state of its corresponding `Mineswitch`, which is stored in `SwitchRam`.
|
||||
- **`Sprite_Mineswitch`:** This is a lever. When hit by the player, it toggles its state in the `SwitchRam` array, which is then read by the `SwitchTrack` and `Minecart` sprites.
|
||||
|
||||
### `portal_sprite.asm`
|
||||
- **Sprite ID:** `Sprite_Portal`
|
||||
- **Summary:** This sprite handles the logic for the portals created by the Portal Rod.
|
||||
- **Key Logic:**
|
||||
- **Spawning:** Two portals can exist at once: one blue and one orange. The `StateHandler` determines which type to create based on the `$7E0FA6` flag.
|
||||
- **Warping:** When Link overlaps with a portal (`CheckIfHitBoxesOverlap`), it triggers a warp. The destination is the location of the *other* portal, whose coordinates are stored in RAM (`BluePortal_X/Y`, `OrangePortal_X/Y`).
|
||||
- **Dismissal:** The `CheckForDismissPortal` routine despawns the oldest portal when a third one is created.
|
||||
- **Invalid Placement:** `RejectOnTileCollision` prevents portals from being placed on invalid surfaces like walls and despawns the sprite if they are.
|
||||
28
Docs/Sprites/Overlord.md
Normal file
28
Docs/Sprites/Overlord.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Overlord Sprite Analysis
|
||||
|
||||
This document provides an analysis of the "Overlord" sprite system, which is a special type of sprite that acts as a controller for spawning other sprites or triggering events within a room. The main logic is found in `Sprites/overlord.asm`.
|
||||
|
||||
## Overview
|
||||
|
||||
Overlord sprites are invisible, non-interactive sprites that are placed in a room via a level editor. Their purpose is to run logic in the background, often tied to room-specific events or conditions. They are distinct from standard sprites and are processed by a separate loop.
|
||||
|
||||
In this project, the primary use of the Overlord system is to dynamically spawn soldiers in Hyrule Castle after the player acquires the Master Sword.
|
||||
|
||||
## `overlord.asm` Analysis
|
||||
|
||||
- **File:** `Sprites/overlord.asm`
|
||||
- **Summary:** This file contains the logic for `Overlord04`, which is hooked into the game at `$09B7AE`. This specific overlord is responsible for continuously spawning soldiers in Hyrule Castle to create a sense of alarm and danger.
|
||||
|
||||
### Key Logic
|
||||
|
||||
- **`Overlord_KalyxoCastleGuards`:** This is the main entry point for the overlord's logic. It is a simple routine that calls `SummonGuards`.
|
||||
|
||||
- **`SummonGuards`:**
|
||||
- **Trigger Condition:** This routine first checks if Link has the Master Sword (`LDA.l Sword : CMP.b #$02`). It will only proceed if the sword level is 2 or greater.
|
||||
- **Spawning Logic:** If the condition is met, it calls `Overlord_SpawnSoldierPath`.
|
||||
|
||||
- **`Overlord_SpawnSoldierPath`:**
|
||||
- **Spawn Timer:** This routine uses `OverlordTimerB` as a countdown timer to manage the rate of spawning. It will not spawn a new soldier until the timer reaches zero.
|
||||
- **Sprite Limit:** It checks the number of active soldiers (`Sprite Type $41`) on screen. If there are already 5 or more, it will not spawn a new one.
|
||||
- **Spawning:** If the conditions are met, it calls `Sprite_SpawnDynamically_slot_limited` to create a new Blue Soldier (`$41`).
|
||||
- **Positioning:** The new soldier's position and initial direction are determined by data tables within the routine (`soldier_position_x`, `soldier_position_y`, `soldier_direction`), allowing for multiple spawn points.
|
||||
Reference in New Issue
Block a user