diff --git a/docs/autoGhost.md b/docs/autoGhost.md new file mode 100644 index 0000000..5ab5d14 --- /dev/null +++ b/docs/autoGhost.md @@ -0,0 +1,253 @@ +# AutoGhost setup + +First of all, extract ghost.zh and the ghost_zh folder from the zip file. + +* Windows or Linux: These should go in the same folder as ZC itself. +* Mac: Right-click the ZQuest application and select **Show Package Contents**. + The files should go in **Contents/Resources**. To be sure you're in + the right place, look for **std.zh** and **string.zh**. + +If you want to use ghost.zh in multiple quests with different settings, you can +make copies of the file with a different filename or in a different folder. +You only need to copy the file ghost.zh itself. + +## General setup + +This part only needs done once per quest. + +### Blank tiles and combo + +First, you'll need to set aside a 4x4 block of tiles to leave blank. + +![Example](img/tileExample.png) + +Set up a combo that uses the top-left tile of that block and has its type +and flag both set to **(None)**. Remember the tile and combo numbers for later. + +You should also modify the **MISC: Spawn** sprite in +**Quest > Graphics > Sprites > Weapons/Misc.** It needs to have the animation +speed and number of frames set; 3 frames at a speed of 5 will best match the +built-in enemies. + +![Example](img/spawn.png) + +### Constants + +You'll have to set some constants in ghost.zh. Open it in a text editor. Use +a basic one, like Notepad; more advanced word processors sometimes modify +punctuation marks, which can make scripts unusable. + +The constants look similar to this: + +```cpp +const int CONSTANT_NAME = ###; // And sometimes there's a note here +``` + +The ### part is what you need to change. Be careful to leave the semicolon in place. + +These are the standard settings: + +GH_SHADOW_TILE +GH_SHADOW_CSET +GH_SHADOW_FRAMES +GH_SHADOW_ANIM_SPEED +GH_SHADOW_TRANSLUCENT +GH_SHADOW_FLICKER +: If a shadow needs to be drawn by the script, it will use these settings. + If you want shadows to have multiple frames, they must be consecutive tiles, + and `GH_SHADOW_TILE` should be the number of the first one. For the + translucency and flickering settings, set the number to 1 (yes) or 0 (no). + +GH_LARGE_SHADOW_TILE +GH_LARGE_SHADOW_CSET +GH_LARGE_SHADOW_FRAMES +GH_LARGE_SHADOW_ANIM_SPEED +: Large enemies may have 2x2 tile shadows using these settings. This only + applies when built-in shadows are not used. This is the case only if + `GH_PREFER_GHOST_ZH_SHADOWS` or `GH_FAKE_Z` are used or if a specific enemy + uses fake Z movement. If `GH_LARGE_SHADOW_TILE` is 0, large shadows will never + be used. + +GH_LARGE_SHADOW_MIN_WIDTH +GH_LARGE_SHADOW_MIN_HEIGHT +: An enemy must be at least this large in tiles to have a large shadow. + These are tile sizes; set them between 1 and 4. + +GH_PREFER_GHOST_ZH_SHADOWS +: ghost.zh's shadows will be used instead of built-in ones whenever possible. + Set the number to 1 (yes) or 0 (no). + +AUTOGHOST_MIN_FFC +AUTOGHOST_MAX_FFC +: Every scripted enemy uses at least one FFC. Set these to limit the range of + FFCs they will use automatically. Use these if you want to reserve some FFCs + for other purposes. Both must be between 1 and 32. + + !!! attention + If all FFCs in this range are in use when an enemy appears, the script + won't be able to run, so you shouldn't limit the range more than necessary. + +AUTOGHOST_MIN_ENEMY_ID +AUTOGHOST_MAX_ENEMY_ID +: These allow you to limit the range of enemy IDs that can be set up + automatically by AutoGhost. Any enemy whose ID is below the minimum or + above the maximum will be ignored. This is useful when other scripts use + misc. attributes 11 and 12 for other purposes. + +GH_DRAW_OVER_THRESHOLD +: Some scripts set the FFC's **Draw Over** flag automatically as the enemy moves + up and down. This determines the Z value at which it changes. This is similar + to the setting **Jumping Sprite Layer Threshold** in the quest's initialization data. + +GH_GRAVITY +GH_TERMINAL_VELOCITY +: These should match the numbers set for gravity and terminal velocity in + the initialization data. + +GH_SPAWN_SPRITE +: This is the number of the sprite used by spawningenemies, found in + **Quest > Graphics > Sprites > Weapons/Misc.** Scripted enemies don't use + the normal spawn animations. This sprite is used to fake it. If you use + the default sprite, 22, make sure its animation frames and speed are set. + +GH_FAKE_Z +: If enabled, enemies won't move through the Z axis. Similar to unchecking the + quest rule **Enemies Jump/Fly Through Z-Axis**. Set this to 1 (yes) or 0 (no). + +__GH_FAKE_EWEAPON_Z +: The same, but for weapons. Set this to 1 (yes) or 0 (no). + +GH_ENEMIES_FLICKER +: If enabled, enemies will flicker instead of flashing. Similar to checking + the quest rule **Enemies Flicker When Hit**. Set this to 1 (yes) or 0 (no). + +GH_BLANK_TILE +: Set this to the tile number of the top-left of your 4x4 block of blank tiles. + +GH_INVISIBLE_COMBO +: Set this to the number of the combo that uses the blank tile. + +__GH_ALWAYS_USE_NAME +: If this is set to 0, the enemy's script and combo will be taken from misc. + attributes 11 and 12. If it's set to 1, they'll be read from the name, + freeing up those attributes for other scripts to use. See the section + on setting up the script and combo below for more details. + + +If you're making multiple quests at once that use different settings, you +should use a different copy of ghost.zh for each one. You only need to copy +ghost.zh itself, not the ghost_zh folder. + +### Loading the scripts + +In **ZQuest, go to Quest > Scripts > Compile ZScript... > Edit**. These three lines +need to appear once each. Enter any line that isn't already there. + +``` +import "std.zh" +import "string.zh" +import "ghost.zh" +``` + +This assumes that all these files are in the default location. If you put ghost.zh +in a different folder, you'll have to specify that, for instance: + +``` +import "MyQuest\Scripts\ghost.zh" +``` + +Close the window, save the changes, and click **Compile**. In the **Global** tab, +load `GhostZHActiveScript` into the Active script slot. If you want to use clocks, +in the **Item** tab, load `GhostZHClockScript` into any slot. + +If your quest uses clocks, set the clock's pickup script to `GhostZHClockScript` +and set D0 to the same number as the clock's duration. + + +## Individual enemies + +### Importing the script + +First, the script needs to be imported. In the script buffer, add another line +to import the file. For instance: + +``` +import "GoriyaLttP.z" +``` + +Some scripts might require that you import additional files, but don't include +any file more than once. Compile and load the FFC script into a slot. + +Exactly what needs done varies from one enemy to the next, but a few things are +common. Many scripted enemies need at least one combo set up, but some use the +invisible one. Every enemy needs its type (usually **Other**), HP, damage, tile, +and CSet set. The enemy must also have a script and combo set. There are a few +different ways of doing this, described below. + +![Enemy editor](img/enemy1.png) + +Many enemies require more than one combo. In these cases, assume that all combos +must be consecutive in the list and the enemy's combo set to the first one +unless the instructions say otherwise. Also, some scripts require that multiple +enemies be set up. Unless instructed otherwise, you only need to place the +primary enemy on the screen. + +Some enemies use the invisible combo (`GH_INVISIBLE_COMBO`). In these cases, you +can set the combo to -1. A few enemies also specify -2, another special value. + + +### Setting the script and combo + +If `__GH_ALWAYS_USE_NAME` is 0: + +![Enemy editor](img/enemy2.png) + +Misc. attributes 11 and 12 are used to identify the enemy as scripted and set +up an FFC to run the script. Attribute 11 indicates which combo the enemy +should use, and attribute 12 determines what script it runs. If either of these +is 0, the enemy will not be recognized as scripted and will not function. +If attribute 12 is set to -1, the script name will be read from the enemy's +name as described below. + +If `__GH_ALWAYS_USE_NAME` is 1: + +![Enemy editor](img/enemy3.png) + +Misc. attributes 11 and 12 are not used. The script and combo will be always be +read from the enemy's name. The combo can be omitted, in which case it will +default to `GH_INVISIBLE_COMBO`. + +When reading a script from the enemy's name, whether because misc. attribute 12 +is -1 or `__GH_ALWAYS_USE_NAME` is enabled, the script name must go in the +enemy's name immediately following the character @. The script name must appear +exactly as shown after it is compiled, including capitalization. + +For example, using the Armos_LttP script, these names will work: + +* Armos (LttP) @Armos_LttP +* Armos (L1, @Armos_LttP) + +These names will not work: + +* Armos @armos_lttp + * Incorrect capitalization +* Armos @ Armos_LttP + * Space after @ + +When using `__GH_ALWAYS_USE_NAME`, the combo number is read in the same way. +The order does not matter. Spaces or other characters between the two +are not required, but they're allowed as long as they wouldn't be mistaken +for part of the name or number. + +Using the Goriya_LttP script with combo 5888, these names will work: + +* Goriya (LttP) (@Goriya_LttP, @5888) +* Goriya (LttP) @5888@Goriya_LttP + +These will not work: + +* Goriya (LttP) @Goriya_LttP_@5888 + * _ looks like part of the script name +* Goriya (LttP) @ 5888 @ Goriya_LttP + * Space after @ is not allowed + diff --git a/docs/enemyScript.md b/docs/enemyScript.md new file mode 100644 index 0000000..aa6f1c4 --- /dev/null +++ b/docs/enemyScript.md @@ -0,0 +1,519 @@ +# Enemy variables and functions + +## Global variables + +Many aspects of the enemy are controlled by these global variables. They're set +by a `Ghost_Init` function and kept consistent between frames by the +`Ghost_Waitframe` functions. + +float Ghost_X +float Ghost_Y +float Ghost_Z +: The X, Y and Z position of the enemy. + +float Ghost_Vx +float Ghost_Vy +float Ghost_Jump +: The X, Y, and Z velocity of the enemy. + + `Ghost_Vx` and `Ghost_Vy` are handled by `Ghost_MoveXY()`, so they will respect + solidity, water, pits, and screen edges. + +float Ghost_Ax +float Ghost_Ay +: The X and Y acceleration of the enemy. + +int Ghost_Dir +: The direction the enemy is facing. + +int Ghost_Data +int Ghost_CSet +: The current combo and CSet of the enemy. + + If `Ghost_InitAutoGhost()` is used, `Ghost_CSet` will be set to the enemy's CSet. + All other initializion functions will use the FFC's CSet. + + If the `GHF_4WAY` or `GHF_8WAY` flags are used, `Ghost_Data` should always be set to + the upward-facing combo. + +int Ghost_TileWidth +int Ghost_TileHeight +: The width and height of the enemy in tiles, which must be between 1 and 4. + + !!! caution + If these variables are set, the change will not fully take effect until + the next Waitframe. It's better to use `Ghost_SetSize()` instead and + consider these variables read-only. + +int Ghost_HP +: The enemy's current HP. + +## Initialization + +Call one of the init functions at the start of the script. It will set +the ffc's and npc's properties and initialize the global variables. +Normally, `ghost->OriginalTile` will be set to `GH_BLANK_TILE` to make the enemy +invisible, `ghost->Extend` will be set to 3, and `Ghost_TileWidth` and +`Ghost_TileHeight` will be set to the size of the FFC. These will not happen +if the FFC's combo is `GH_INVISIBLE_COMBO`, or, in the case of AutoGhost +enemies, if that's the combo they're set to use. + +void Ghost_Init(ffc this, npc ghost) +: The basic initialization function. Provide your own npc. + +npc Ghost_InitCreate(ffc this, int enemyID) +: This will create an npc of type `enemyID` and return a pointer to it. + +npc Ghost_InitWait(ffc this, int enemyIndex, bool useEnemyPos) +: This function will select an enemy on the screen as the ghost. + + `enemyIndex` is the number to pass to `Screen->LoadNPC()`, normally the npc's + position in the screen's enemy list. + + If `useEnemyPos` is true, the FFC will be moved to the enemy's position. + Otherwise, the FFC's current position will be used. + + The function will only wait 4 frames for the enemy to appear to minimize + the possibility of incorrectly using an enemy that is spawned later on. If + the expected enemy does not appear in that time, it will call `Quit()`. + +npc Ghost_InitWait2(ffc this, int enemyID, bool useEnemyPos) +: Similar to `Ghost_InitWait()`, except this loads the first enemy of type + `enemyID` that is not already in use by another ghost.zh script. This is + especially helpful if enemies are present other than those placed by + **Screen > Enemies**, since you can't always be certain what index an enemy + will be assigned. + +npc Ghost_InitSpawn(ffc this, int enemyID) +: This will create the ghosted enemy in a random location. + +npc Ghost_InitAutoGhost(ffc this, int enemyID) +: This should only be used with a script that is meant to be set up + automatically by the `AutoGhost()` function. Similar to `Ghost_InitWait2()`, + this will load the first unused enemy of the given type. The enemy must + already be on the screen when the function is called, or it will log + an error and call `Quit()`. + +## Flags + +There are a number of flags you can apply to an enemy to control its behavior +and appearance. This is typically done just after initialization, but flags +can be changed at any time while the enemy is alive. + +Note that these flags cannot be combined with bitwise OR. + +void Ghost_SetFlag(int flag) +void Ghost_UnsetFlag(int flag) +: Set or unset a flag that controls details of the enemy's behavior. + + Valid arguments are: + + GHF_KNOCKBACK + : The enemy can be knocked back when hit. + + GHF_KNOCKBACK_4WAY + : The enemy will be knocked back when hit, even if its direction and + Link's are not suitably aligned. + + !!! note + It is not necessary to use `GHF_KNOCKBACK` along with this flag. + + GHF_REDUCED_KNOCKBACK + : The enemy will be knocked back 2 pixels per frame instead of 4. + + !!! note + It is not necessary to use `GHF_KNOCKBACK` along with this flag. + + GHF_STUN + : Stunning will be handled automatically. `Ghost_Waitframe` functions will not + return while the enemy is stunned. + + GHF_CLOCK + : The enemy will be affected by clocks. `Ghost_Waitframe` functions will not + return while a clock is active. + + GHF_NO_FALL + : `ghost->Jump` will be set to 0 each frame and `Ghost_Jump` will be ignored. + If `GHF_NO_FALL` is not used, `Ghost_CanMove(DIR_UP)` will always be false + on sideview screens. + + GHF_SET_DIRECTION + : The enemy's direction will automatically be set based on which way + it moves. Unless `GHF_8WAY` is set, this will only use up, down, left, + and right. + + GHF_SET_OVERLAY + : Set or unset the **Draw Over** flag each frame based on Z position. The + height at which it changes is determined by `GH_DRAW_OVER_THRESHOLD`. + + GHF_FAKE_Z + : `Ghost_Z` and `Ghost_Jump` will affect the enemy's position on the Y axis + rather than Z. A shadow will be drawn under it according to the + `GH_SHADOW_` settings. + + !!! note + If the global setting `GH_FAKE_Z` is enabled, all Z movement + will behave this way, and this flag will have no effect. + + GHF_4WAY + : Change the FFC's combo based on `Ghost_Dir`. This requires a particular + setup. There must be four consecutive combos in the list, one for each + direction: up, down, left, and right, in order. Set `Ghost_Data` to the + upward-facing combo. + + GHF_8WAY + : Set the FFC's combo based on direction, inclusing diagonals. This will + also cause `GHF_SET_DIRECTION` to use all eight directions. The combo + order is up, down, left, right, up-left, up-right, down-left, down-right. + + GHF_MOVE_OFFSCREEN + : Movement functions will not stop the enemy at the screen edges. + + GHF_NORMAL + : Combines `GHF_KNOCKBACK`, `GHF_STUN`, `GHF_CLOCK`, and `GHF_SET_DIRECTION`. + + GHF_IGNORE_SOLIDITY + : The enemy can move over solid combos, as long as they are not pits or water. + + !!! note + This and the following walkability control flags only affect movement + via the `Ghost_Move` functions and `Ghost_Vx` and `Ghost_Vy`. + If `Ghost_X` and `Ghost_Y` are set directly, the enemy can move anywhere. + + GHF_IGNORE_WATER + : The enemy can move over water, regardless of solidity. + + GHF_IGNORE_PITS + : The enemy can move over direct warps, regardless of solidity. + + GHF_IGNORE_ALL_TERRAIN + : Combines `GHF_IGNORE_SOLIDITY`, `GHF_IGNORE_WATER`, and `GHF_IGNORE_PITS`. + + GHF_WATER_ONLY + : The enemy can only move in water (including shallow water). This overrides + the above terrain flags. + + GHF_DEEP_WATER_ONLY + : The enemy can only move in deep water. This overrides the above + terrain flags. + + GHF_FULL_TILE_MOVEMENT + : The enemy will not walk onto a tile unless the entire tile is walkable. + This is particularly useful for enemies using walking functions along + with other movement. + + GHF_FLYING_ENEMY + : The enemy will be blocked by the **No Flying Enemies** combo type. + If this flag is not set, it will be blocked by **No Ground Enemies** if + `Ghost_Z==0` or **No Jumping Enemies** if `Ghost_Z>0`. + + !!! note + This flag does not imply any others that a flying enemy would likely use, + such as `GHF_IGNORE_PITS` or `GHF_NO_FALL`. Those must be set separately. + + GHF_IGNORE_NO_ENEMY + : The enemy will ignore all enemy blocking flags and combos. + + GHF_STATIC_SHADOW + : The enemy's shadow will not animate. This only applies if Z movement is + faked due to either by `GH_FAKE_Z` or `GHF_FAKE_Z`. + +void Ghost_ClearFlags() +: Unsets all flags. + +bool Ghost_FlagIsSet(int flag) +: Returns true if the given flag is set and false if not. + +## Waitframe + +After the enemy is initialized and until it dies, use the `Ghost_Waitframe` +functions below instead of `Waitframe()` to keep the global variables +consistent and maintain the illusion of a real enemy. Failure to do so may +cause the global variables to become incorrect, completely breaking your script. + +bool Ghost_Waitframe(ffc this, npc ghost, bool clearOnDeath, bool quitOnDeath) +: This is a replacement function for `Waitframe()`. In addition to waiting a frame, + it will handle the necessary routine updates. These include setting the npc's + and ffc's positions and movement and dealing with clocks, stunning, flashing, + knockback, and death. If the enemy is stunned or frozen by a clock, or if + scripts are suspended, `Ghost_Waitframe()` will not return until the enemy dies + or the blocking condition ends. + + If `clearOnDeath` is true, when the npc dies, `this->Data` will be set to 0, + `Ghost_ClearAttachedFFCs()` will be called, and the npc will be moved so that + its death animation and dropped item are centered. + + If `quitOnDeath` is true, `Quit()` will be called when the npc dies. + If it's false, the function will return true if the npc is alive and false otherwise. + +bool Ghost_Waitframe2(ffc this, npc ghost, bool clearOnDeath, bool quitOnDeath) +: Like the above, except this ignores the position and movement variables and + uses the npc's instead. Use this if you want to use built-in enemy movement. + +void Ghost_WaitframeLight(ffc this, npc ghost) +: Minimal waitframe function. Aside from waiting a frame, this only keeps the + global variables consistent, positions attached FFCs, and sets up drawing. + If scripts are suspended, this function will not return until they are resumed. + +bool Ghost_Waitframes(ffc this, npc ghost, bool clearOnDeath, bool quitOnDeath, int numFrames) +bool Ghost_Waitframes2(ffc this, npc ghost, bool clearOnDeath, bool quitOnDeath, int numFrames) +void Ghost_WaitframesLight(ffc this, npc ghost, int numFrames) +: These simply call the corresponding `Ghost_Waitframe` function `numFrames` times. + +void Ghost_Waitframe(ffc this, npc ghost) +void Ghost_Waitframe2(ffc this, npc ghost) +void Ghost_Waitframes(ffc this, npc ghost, int numFrames) +void Ghost_Waitframes2(ffc this, npc ghost, int numFrames) +: Simpler variants of the Waitframe functions. These are equivalent to calling + the regular functions with `clearOnDeath` and `quitOnDeath` both true. The + script will quit if the enemy dies, so there is no return value from these. + +bool Ghost_Waitframe(ffc this, npc ghost, int deathAnimation, bool quitOnDeath) +bool Ghost_Waitframe2(ffc this, npc ghost, int deathAnimation, bool quitOnDeath) +: These will call `Ghost_DeathAnimation()` with the specified animation if the + enemy dies. See `Ghost_DeathAnimation()` for `deathAnimation` arguments. + +## Modification + +void Ghost_SetSize(ffc this, npc ghost, int tileWidth, int tileHeight) +: Sets the tile size of the enemy. The new width and height are given + in tiles and must be between 1 and 4. If -1 is given for either dimension, + it will not be changed. If you called `Ghost_SetHitOffsets()` previously, + it will be undone; the enemy's size and position will be set to match + the FFC's. + +void Ghost_Transform(ffc this, npc ghost, int combo, int cset, int tileWidth, int tileHeight) +: Change the FFC to a new combo and CSet and resize the FFC and npc. The FFC's + and npc's positions will be adjusted so that they're centered on the same + spotas before. For all four numeric arguments, pass in -1 if you don't want to change + the existing value. If you called `Ghost_SetHitOffsets()` previously, it will + be undone. Attached FFCs will not be affected. + +void Ghost_SetHitOffsets(npc ghost, float top, float bottom, float left, float right) +: If you want the enemy's hitbox to be smaller than the FFC, use this function + to adjust it. Each argument will cause the hitbox to shrink away from the + corresponding edge. This applies to both collision detection and movement. + For each argument, if the number is 1 or greater, it will be interpreted as + the difference in pixels; if the number is between 0 and 1, it will be + treated as a fraction of the FFC's full size. So, for instance, a `top` + argument of 0.25 would shrink the hitbox by 1/4 of the FFC's height. + +void Ghost_SwapNPC(npc oldGhost, npc newGhost, bool copyHP) +: Copies size, position, Misc[], and HP (optionally) from the old ghost to the + new one, then moves the old one out of the way. + +void Ghost_ReplaceNPC(npc oldGhost, npc newGhost, bool copyHP) +: Copies data from the old ghost to the new one, then silently kills the old one. + +void Ghost_StoreDefenses(npc ghost, int storedDefense[]) +: Copies `ghost->Defense[]` into `storedDefense`. The array size must be at least 18. + +void Ghost_SetDefenses(npc ghost, int defense[]) +: Copies `defense` into `ghost->Defense[]`. The array size must be at least 18. + +void Ghost_SetAllDefenses(npc ghost, int defType) +: Sets all of the enemy's defenses to `defType`, which should be an NPCDT constant. + +## Movement + +void Ghost_Move(int dir, float step, int imprecision) +void Ghost_MoveXY(float xStep, float yStep, int imprecision) +void Ghost_MoveAtAngle(float angle, float step, int imprecision) +void Ghost_MoveTowardLink(float step, int imprecision) +: Makes the enemy move. `Ghost_CanMove()` will be checked automatically. + If the `GHF_SETDIRECTION` flag is set, the npc's direction will be changed + accordingly unless `Ghost_ForceDir()` was called beforehand. + + `step` is given in pixels. + + `Ghost_MoveAtAngle()`'s `angle` argument is in degrees. + + `imprecision` makes the function ignore a couple of pixels at the + edges of the enemy's hitbox so that it doesn't get stuck on corners. + +bool Ghost_CanMove(int dir, float step, int imprecision) +bool Ghost_CanMove(int dir, float step, int imprecision, bool inAir) +: Determines whether the enemy can move in the given direction and distance. + step is given in pixels. + + On sideview screens, a direction of `DIR_UP` will always return false unless + the `GHF_NO_FALL` flag is set. + + `inAir` determines whether non-flying enemies check for **No Ground Enemies** or + **No Jumping Enemies**. If it is not specified, `inAir` is true if `Ghost_Z>0`. + +bool Ghost_CanMovePixel(int x, int y) +bool Ghost_CanMovePixel(int x, int y, bool inAir) +: Used internally by `Ghost_CanMove()`. Returns true if the enemy can move onto + the given pixel. + +float Ghost_HaltingWalk4(int counter, int step, int rate, int homing, int hunger, int haltRate, int haltTime) +: This function mimics the built-in movement function used by walking enemies. + + `step` corresponds to `npc->Step`. It represents speed in hundredths of a pixel + per frame. + + `rate` corresponds to `npc->Rate` and should be between 0 and 16. + + `homing` corresponds to `npc->Homing` and should be between 0 and 256. + + `hunger` corresponds to `npc->Hunger` and should be between 0 and 4. + + `haltRate` corresponds to `npc->Haltrate` and should be between 0 and 16. + + `haltTime` determines how long the enemy will stand still when it + halts. Zols use `Rand(8)<<4`, Gels use `(Rand(8)<<3)+2`, Goriyas use 1, and all + others use 48. + + `counter` should initially be -1, then set to the function's + return value each frame. While the enemy is halted, the return value will be + the remaining halt time, which you can use to determine when to fire. So: + + :::cpp + int counter = -1; + while(true) + { + counter=Ghost_HaltingWalk4(counter, step, rate, homing, hunger, haltRate, 48); + if(counter==16) // Fire after halted for 32 frames + FireEWeapon(...); + Ghost_Waitframe(...); + } + + This function depends on `Ghost_Dir` and will set it even if `GHF_SET_DIRECTION` + is not used. It will also set `Ghost_Dir` to -1 if the enemy is trapped. + +int Ghost_ConstantWalk4(int counter, int step, int rate, int homing, int hunger) +: This is the movement function used by Dodongos and Lanmolas. The arguments + are the same as above. + + This function depends on `Ghost_Dir` and will set it + even if `GHF_SET_DIRECTION` is not used. It will also set `Ghost_Dir` to -1 if + the enemy is trapped. + +int Ghost_ConstantWalk8(int counter, int step, int rate, int homing, int hunger) +: This is the movement function used by Moldorms. The arguments are the same as above. + + This function depends on `Ghost_Dir` and will set it even if `GHF_SET_DIRECTION` + is not used. It will also set `Ghost_Dir` to -1 if the enemy is trapped. + +int Ghost_VariableWalk8(int counter, int step, int rate, int homing, int hunger, int turnCheckTime) +: This is the movement function used by Digdoggers, Manhandlas, Patras, and + fairies. + + `turnCheckTime` deterines how many frames the enemy moves before checking + whether it should change direction. + + The other arguments are the same as above. + + This function depends on `Ghost_Dir` and will set it even if `GHF_SET_DIRECTION` + is not used. It will also set `Ghost_Dir` to -1 if the enemy is trapped. + +float Ghost_FloaterWalk(float counter, int normalStep, int accelTime, float accelAmount, int accelSteps, int rate, int homing, int hunger, int turnCheckTime, int restTime) +: This is the movement function used by Peahats, Keese, and Ghinis. It works + like `Ghost_VariableWalk8()`, plus the enemy will periodically stop moving. + When the enemy is moving at full speed, there is a 1 in 768 chance each frame + that it will stop. + + When the enemy starts or stops moving, its speed will change in discrete + increments of `accelAmount`. `accelSteps` is the number of times this will + happen, and `accelTime` is the time in frames between each step. + + `restTime` is how long the enemy stays stopped. Peahats use 80, while + Ghinis and Keese use 120. + +## Other + +float Ghost_GetAttribute(npc ghost, int index, float defaultVal) +float Ghost_GetAttribute(npc ghost, int index, float defaultVal, float min, float max) +: Retrieves the value of `ghost->Attribute[index]` bound to the range `min` - `max`. + If the value is 0, `defaultVal` will be returned. `defaultVal` does not need to be + between `min` and `max`. + +void Ghost_SpawnAnimationPuff(ffc this, npc ghost) +: The initialization functions interrupt the normal enemy spawning animation; + this function fakes it. It draws a sprite (lweapon) using sprite number + `GH_SPAWN_SPRITE` at the enemy's position and returns after the animation completes. + +void Ghost_SpawnAnimationFlicker(ffc this, npc ghost) +: Draws the other spawn animation, in which the enemy flickers for 64 frames. + With a visible enemy and invisible FFC, the timing won't be quite right + unless the enemy's spawn type is **Instant**. + +void Ghost_DeathAnimation(ffc this, npc ghost, int anim) +: Displays a death animation based on `anim`, then clears the enemy. This does + not call `Quit()`. + + `anim` should be one of these: + + GHD_EXPLODE + : A series of explosions appear randomly around the enemy. + + GHD_EXPLODE_FLASH + : The same, plus the enemy flashes. + + GHD_SHRINK + : The enemy grows slightly and then shrinks away to nothing. This does not + work with enemies that use additional combos. + + Any other value will simply cause the enemy to disappear. + +void Ghost_AddCombo(int combo, float x, float y) +void Ghost_AddCombo(int combo, float x, float y, int width, int height) +: Add another combo to the enemy. It will move, flash, and flicker along with + the enemy. `x` and `y` are offsets from `Ghost_X` and `Ghost_Y`. Up to four combos + may be added in this way. + +void Ghost_ClearCombos +: Clears all combos added by `Ghost_AddCombo()`. + +bool Ghost_GotHit() +: Returns true if the enemy was hit in the last frame. + +bool Ghost_WasFrozen() +: Returns true if the enemy was stunned or frozen by a clock in the last frame. + This only works if `GHF_STUN` or `GHF_CLOCK` is used. + +void Ghost_ForceDir(int dir) +: Sets `Ghost_Dir` and stops it from being changed automatically until the next frame. + +void Ghost_ForceCSet(int cset) +: Sets `Ghost_CSet` and stops flashing until the next frame. + + This won't work with scripts that use a visible enemy and invisible FFC. + +void Ghost_StartFlashing() +void Ghost_StartFlashing(int time) +: Makes the enemy start flashing or flickering as though it had been hit. + + If `time` is specified, the enemy will flash for that many frames + instead of the standard 32. + + This won't work with scripts that use a visible enemy and invisible FFC. + +void Ghost_StopFlashing() +: Makes the enemy stop flashing or flickering. + + This won't work with scripts that use a visible enemy and invisible FFC. + +void Ghost_StopKnockback() +: Stops the enemy from being knocked back. + +void Ghost_CheckHit(ffc this, npc ghost) +: This will cause the enemy to flash and be knocked back when it is damaged. + + This is used internally by the `Ghost_Waitframe` functions. If you use + one of those, you don't need to use this as well. + +bool Ghost_CheckFreeze(ffc this, npc ghost) +: Checks whether the npc has been stunned or frozen by a clock. If so, the + function does not return until the npc either recovers or dies. `Ghost_CheckHit()` + will be called each frame during that time. The return value is true if the + npc is still alive and false if it's dead. + + This is used internally by the `Ghost_Waitframe` functions. If you use + one of those, you don't need to use this as well. + +void Ghost_SetPosition(ffc this, npc ghost) +: Positions the NPC and FFC according to the position variables and + `ghost->Draw*Offset`. This is done automatically in the `Ghost_Waitframe` + functions, so you generally will never need to use this. diff --git a/docs/eweapon.md b/docs/eweapon.md new file mode 100644 index 0000000..508c3bf --- /dev/null +++ b/docs/eweapon.md @@ -0,0 +1,320 @@ +# Eweapon functions + +eweapon FireEWeapon(int weaponID, int x, int y, float angle, int step, int damage, int sprite, int sound, int flags) +eweapon FireAimedEWeapon(int weaponID, int x, int y, float angle, int step, int damage, int sprite, int sound, int flags) +eweapon FireNonAngularEWeapon(int weaponID, int x, int y, int direction, int step, int damage, int sprite, int sound, int flags) +eweapon FireBigEWeapon(int weaponID, int x, int y, float angle, int step, int damage, int sprite, int sound, int flags, int width, int height) +eweapon FireBigAimedEWeapon(int weaponID, int x, int y, float angle, int step, int damage, int sprite, int sound, int flags, int width, int height) +eweapon FireBigNonAngularEWeapon(int weaponID, int x, int y, int direction, int step, int damage, int sprite, int sound, int flags, int width, int height) +: Create an eweapon with the given properties. + + `angle` is given in radians. If the weapon is aimed, this is an offset from + the base angle. So, for instance, an `angle` of 0.2 will always aim slightly + away from Link. + + `sprite` should be the ID of a sprite from **Quest > Graphics > Sprites > Weapons/Misc.** + If this is -1, the standard sprite for the weapon type will be used. + + `sound` specifies a sound to play. If this is 0, no sound will be played. + If it's -1, a sound will be chosen automatically based on the type of weapon. + + `flags` argument should be one or more `EWF_` constants ORed together, or 0 for none. + + EWF_UNBLOCKABLE + : The weapon is unblockable. + + EWF_ROTATE + : The weapon's sprite will be rotated and flipped according to the weapon's direction. + + EWF_ROTATE_360 + : The weapon will be drawn using Screen->DrawTile(), allowing the sprite + to rotate in whichever direction the weapon is moving. + + !!! tip + The base sprite set in **Quest > Graphics > Sprites > Weapons/Misc.** + should be pointing to the right. + + EWF_SHADOW + : The weapon will cast a shadow if its Z position is greater than 0. + + EWF_FLICKER + : The weapon will be invisible every other frame. + + EWF_NO_COLLISION + : The weapon's collision detection will be disabled. + + EWF_FAKE_Z + : The weapon's hitbox will always be on the ground. + + !!! note + This does not actually keep the weapon on the ground; it only + simulates this by setting the weapon's hit and draw offsets. + +eweapon CreateDummyEWeapon(int weaponID, int step, int damage, int sprite, int sound, int flags) +eweapon CreateBigDummyEWeapon(int weaponID, int step, int damage, int sprite, int sound, int flags, int width, int height) +: These will create a dummy eweapon to be used as a prototype for + `SetEWeaponDeathEffect()`. The dummy weapon will be invisible and will have + collision detection disabled. It can have a movement, lifespan, and death + effect set, but the dummy weapon itself will not make use of them - only + its copies will. + + A dummy weapon will never be removed automatically. If reaching the weapon + limit is a concern, you should destroy the weapon yourself when it's no + longer needed. + +void SetEWeaponMovement(eweapon wpn, int type, float arg, float arg2) +: This sets an eweapon's movement pattern. The type argument should be one of + the `EWM_` constants below. The effect of `arg` and `arg2` vary depending on + the type of movement. + + EWM_SINE_WAVE + : Move in a sine wave. + + `arg`: Amplitude + + `arg2`: Angular frequency in degrees per frame + + EWM_HOMING + : Turn toward Link each frame. + + `arg`: Maximum rotation per frame in radians + + `arg2`: Homing time in frames - after this many frames, the weapon + will die. Use -1 to home indefinitely. + + EWM_HOMING_REAIM + : Move in straight lines, stopping and re-aiming at Link. + + `arg`: Number of re-aims + + `arg2`: Time between re-aims + + EWM_RANDOM + : Turn randomly each frame. + + `arg`: Maximum rotation per frame in radians + + `arg2`: Rotation time in frames - after this many frames, the weapon + will die. Use -1 to keep moving indefinitely. + + EWM_RANDOM_REAIM + : Stop frequently and aim in a random direction + + `arg`: Number of re-aims + + `arg2`: Time between re-aims + + EWM_VEER + : Accelerate in a given direction. + + `arg`: Direction of acceleration + + `arg2`: Rate of acceleration + + EWM_DRIFT + : Drift in the given direction at a constant speed. + + `arg`: Drift direction + + `arg2`: Drift speed + + EWM_DRIFT_WAIT + : Drift in the given direction at a constant speed and wait 16 frames before + beginning normal movement. This mimics the behavior of boss fireballs. + + `arg`: Drift direction + + `arg2`: Drift speed + + EWM_THROW + : Arc through the air as if thrown. The weapon stops moving when it hits + the ground. + + `arg`: Initial upward velocity; use -1 to make the weapon travel the + distance to Link + + `arg2`: OR together these flags, or use 0 for none: + + EWMF_BOUNCE + : The weapon will bounce on impact. + + EWMF_DIE + : The weapon will die on impact rather than simply stopping. + + EWM_FALL + : Fall straight down. The weapon stops moving when it hits the ground. + + `arg`: Initial height + + `arg2`: OR together these flags, or use 0 for none: + + EWMF_BOUNCE + : The weapon will bounce on impact. + + EWMF_DIE + : The weapon will die on impact rather than simply stopping. + +void SetEWeaponLifespan(eweapon wpn, int type, int arg) +: This controls the conditions under which a weapon dies. "Dying" does not mean + the weapon is removed, but that its scripted movement is no longer handled, + and, optionally, a death effect is activated. Use one of the EWL_ constants + for the type argument. The effect of arg depends on the type. + + EWL_TIMER + : Die after a certain amount of time. + + `arg`: Time in frames + + EWL_NEAR_LINK + : Die when within a certain distance of Link. + + `arg`: Distance in pixels + + EWL_SLOW_TO_HALT + : Slow down until stopped, then die. This can behave oddly if movement is set. + + `arg`: Step per frame + +void SetEWeaponDeathEffect(eweapon wpn, int type, int arg) +: This determines what happens when the weapon dies. The type argument should + be one of the `EWD_` constants below. The effect of arg depends on the type. + + EWD_VANISH + : The weapon is removed. + + `arg`: No effect + + EWD_AIM_AT_LINK + : The weapon pauses for a moment, then aims at Link. + + `arg`: Delay + + EWD_EXPLODE + : The weapon explodes. + + `arg`: Explosion damage + + EWD_SBOMB_EXPLODE + : The weapon explodes like a super bomb. + + `arg`: Explosion damage + + EWD_4_FIREBALLS_HV + : Shoots fireballs horizontally and vertically. + + `arg`: Fireball sprite + + EWD_4_FIREBALLS_DIAG + : Shoots fireballs at 45-degree angles. + + `arg`: Fireball sprite + + EWD_4_FIREBALLS_RANDOM + : Randomly shoots fireballs either vertically and horizontally or at + 45-degree angles. + + `arg`: Fireball sprite + + EWD_8_FIREBALLS + : Shoots fireballs horizontally, vertically, and at 45-degree angles + + `arg`: Fireball sprite + + EWD_FIRE + : Leaves a single, immobile fire + + `arg`: Fire sprite + + EWD_4_FIRES_HV + : Shoots fires horizontally and vertically. + + `arg`: Fire sprite + + EWD_4_FIRES_DIAG + : Shoots fires at 45-degree angles. + + `arg`: Fire sprite + + EWD_4_FIRES_RANDOM + : Randomly shoots fires either vertically and horizontally or at + 45-degree angles. + + `arg`: Fire sprite + + EWD_8_FIRES + : Shoots fires horizontally, vertically, and at 45-degree angles + + `arg`: Fire sprite + + EWD_SPAWN_NPC + : Creates an npc at the weapon's location. This is done without regard for + the suitability of the location. + + `arg`: npc to spawn + + EWD_RUN_SCRIPT + : Loads an unused FFC, positions it at the weapons position, and runs a + script. The weapon will not be removed; it should be loaded by the script + with `GetAssociatedEWeapon()`. The number to pass into it will be given to + the script as argument D0. If no FFC is free, the weapon will simply be removed. + + `arg`: Script to run. If this is not a valid script, `EWD_VANISH` will be + set instead + +void SetEWeaponDeathEffect(eweapon wpn, eweapon prototype, int numShots, int spreadType, float angle) +: This will make a weapon spawn copies of a prototype weapon when it dies. + The prototype must be a dummy eweapon. + + `spreadType` is one of the following: + + EWD_EVEN + : Weapons are evenly spaced + + `angle`: First weapon's offset from 0 in radians + + EWD_AIMED + : Weapons are aimed at Link + + `angle`: Angle range of spawned weapons in radians + + EWD_RANDOM + : Weapons are fired at random angles + + `angle`: No effect + +void SetEWeaponDir(eweapon wpn) +: Set the direction of an angled eweapon so that it interacts correctly + with shields. This is normally handled automatically, but you may need + to use it if you script a weapon's movement yourself. + +void SetEWeaponRotation(eweapon wpn) +void SetEWeaponRotation(eweapon wpn, int direction) +: Rotate the weapon's sprite. If `direction` is not given, + this is done according to the weapon's direction. + +void KillEWeapon(eweapon wpn) +: Kill the eweapon, stopping scripted movement and activating any + death effects. + +void DrawEWeaponShadow(eweapon wpn) +: Draws a shadow under the eweapon according to the `GH_SHADOW_` constants. This + is used internally when `EWF_SHADOW` is set. + +int GetDefaultEWeaponSprite(int weaponID) +: Returns the sprite normally used by the given weapon type. + +int GetDefaultEWeaponSound(int weaponID) +: Returns the sound normally used by the given weapon type. + +eweapon GetAssociatedEWeapon(int weaponID) +: Finds an eweapon using an internal ID number. This should be used by scripts + launched by `EWD_RUN_SCRIPT`, and the weaponID argument should be the number + passed to the script as D0. If the requested weapon is not found, an + uninitialized pointer will be returned. + +bool IsGhostZHEWeapon(eweapon wpn) +: Returns true if the weapon is one created or handled by ghost.zh. + +bool IsDummyEWeapon(eweapon wpn) +: Returns true if the eweapon is a dummy. + diff --git a/docs/globalScript.md b/docs/globalScript.md new file mode 100644 index 0000000..ebcfe7c --- /dev/null +++ b/docs/globalScript.md @@ -0,0 +1,67 @@ +# Global script functions + +Many features of ghost.zh require global script support. If you don't want +to use the provided `GhostZHActiveScript`, you just need to add a few functions +into whatever global script you do use. + +## Combined + +The simpler option is to use these three functions. These provide all +functionality and will continue to work if more functions are ever added +in the future. + +void StartGhostZH() +: Call this before the global script's main loop. + +void UpdateGhostZH1() +: Call this in the global script's main loop before `Waitdraw()`. + +void UpdateGhostZH2() +: Call this in the global script's main loop after `Waitdraw()`. + +## Separate + +These are the functions used internally by those listed above. Calling these +individually lets you leave out functionality you don't need, but it's possible +a future ghost.zh update will require updating the script. + +void InitializeGhostZHData() +: Initializes internal counters and data. + + Call before the main loop of the global script. + +void UpdateGhostZHData1() +void UpdateGhostZHData2() +: Updates counters and internal data. + + Call `UpdateGhostZHData1()` in the main loop before `Waitdraw()` and + `UpdateGhostZHData2()` after `Waitdraw()`. + +void UpdateEWeapon(eweapon wpn) +: This must be called on eweapons each frame to enable the special behaviors + provided by ghost.zh. + + Call in the main loop before `Waitdraw()`. + +void UpdateEWeapons() +: Runs `UpdateEWeapon()` on all eweapons onscreen. + + Call in the main loop before `Waitdraw()`. + +void CleanUpGhostFFCs() +: Hides enemy FFCs when Link dies. If `__GH_USE_DRAWCOMBO` is enabled, this function does nothing. + + Call in the main loop before `Waitdraw()` and after anything that would save + Link from dying when `Link->HP<=0`. + +void DrawGhostFFCs() +: Draws enemy combos if `__GH_USE_DRAWCOMBO` is enabled and draws additional + combos regardless. If `__GH_USE_DRAWCOMBO` is disabled and no scripts use + `Ghost_AddCombo()`, this function does nothing. + + Call in the main loop after `Waitdraw()`. + +void AutoGhost() +: Detects AutoGhost enemies and sets up FFCs for them. + + Call in the main loop after `Waitdraw()`. diff --git a/docs/img/enemy1.png b/docs/img/enemy1.png new file mode 100644 index 0000000..246c3aa Binary files /dev/null and b/docs/img/enemy1.png differ diff --git a/docs/img/enemy2.png b/docs/img/enemy2.png new file mode 100644 index 0000000..94847d1 Binary files /dev/null and b/docs/img/enemy2.png differ diff --git a/docs/img/enemy3.png b/docs/img/enemy3.png new file mode 100644 index 0000000..0cc80ff Binary files /dev/null and b/docs/img/enemy3.png differ diff --git a/docs/img/spawn.png b/docs/img/spawn.png new file mode 100644 index 0000000..9763c1e Binary files /dev/null and b/docs/img/spawn.png differ diff --git a/docs/img/tileExample.png b/docs/img/tileExample.png new file mode 100644 index 0000000..a226c24 Binary files /dev/null and b/docs/img/tileExample.png differ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..5a6c113 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,10 @@ +# ghost.zh + +ghost.zh is used to create "ghosted enemy" FFC scripts. These combine an FFC +and a built-in enemy to create what seems to be a scripted enemy. The enemy +handles collision detection, defense. The FFC runs the script and,typically, +is what is actually visible on the screen. + +Most of this documentation is meant for users who want to write scripts. +If you just want to use existing enemy scripts, see [this page](autoGhost.md). + diff --git a/docs/other.md b/docs/other.md new file mode 100644 index 0000000..6c7d196 --- /dev/null +++ b/docs/other.md @@ -0,0 +1,66 @@ +# Miscellaneous functions + +void SetEnemyProperty(npc enemy, int property, float newValue) +float GetEnemyProperty(npc enemy, int property) +: These functions allow some of the properties of ghost.zh scripts to be read + and set from other scripts. property must be one of the following: + + * `ENPROP_X` + * `ENPROP_Y` + * `ENPROP_Z` + * `ENPROP_JUMP` + * `ENPROP_DIR` + * `ENPROP_HP` + * `ENPROP_CSET` + + These work for all enemies, not just scripted ones, so there's no need + to check that beforehand. + +int FindSpawnPoint(bool landOK, bool wallsOK, bool waterOK, bool pitsOK) +: Finds a random combo position meeting the given criteria some distance away + from Link and enemies. This can be useful if you want the enemy to spawn in + a random position that ZC would not select itself. The result is undefined + if no suitable location exists, but that will not happen unless there is + almost no space abailable on the screen. + + `landOK`: Walkable, non-water, non-pit combos are okay + + `wallsOK`: Unwalkable, non-water, non-pit combos are okay + + `waterOK`: All deep water combos are okay + + `pitsOK`: Direct warps are okay + +int FindSpawnPoint(int type, int flag) +: Like the above, but finds a combo with the given combo type or flag, + regardless of solidity. Only layer 0 is checked. Use -1 for either argument + to ignore it. + +npc SpawnNPC(int id) +: Spawns an npc with the given ID in a random location and returns a pointer to it. + +int FindUnusedFFC() +int FindUnusedFFC(int startingFrom) +: Returns the ID number of an FFC that is not currently in use in the range + `AUTOGHOST_MIN_FFC` to `AUTOGHOST_MAX_FFC`. Returns 0 if no FFC is available in + that range. If `startingFrom` is given, the ID returned will be at least + `startingFrom+1`. + +void Ghost_MarkAsInUse(npc ghost) +: Mark an enemy as being in use by a script. This allows you to create + additional enemies without `AutoGhost()` or `Ghost_InitWait2()` trying to use them. + +bool Ghost_IsInUse(npc ghost) +: Returns true if the given enemy is in use by a ghost.zh script. + +bool ClockIsActive() +: Returns true if a clock is currently in effect. + +void SuspendGhostZHScripts() +: Suspends the execution of all ghost.zh scripts. Until scripts are resumed, + `Ghost_Waitframe` functions will not return and `UpdateEWeapon()` will not + do anything. This also stops `AutoGhost()` from running, so any new enemies + will not have scripts launched until `ResumeGhostZHScripts()` is called. + +void ResumeGhostZHScripts() +: Resumes execution of ghost.zh scripts. diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..13a1ef6 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,47 @@ +# General usage + +## Enemy scripts + +A ghost.zh script should begin by calling one of the `Ghost_Init` functions to +find the enemy the FFC should be associated with and set up internal data. +Afterward, `Ghost_Waitframe()` should be used instead of `Waitframe()`. +This is necessary to keep data consistent and to provide standard enemy behavior, +such as reacting to damage. Most of the standard enemy data is manipulated by +using the global variables and functions [here](enemyScript.md), but some things +- particularly defenses and draw offsets - must still be accessed via the npc pointer. + +The enemy used can be of any type and with any settings. Its HP, damage, and +defenses will be used normally. Its regular tiles and animation will be used +if the FFC is set to use `GH_INVISIBLE_COMBO`; otherwise, it will be made +invisible. Other enemy data can be used as you see fit. + +There are also a number of functions used to create and control eweapons. They +can be assigned a number of simple movements and can be made to vanish and +spawn additional eweapons. These behaviors require support from the global script. + +For scripted enemies to be susceptible to clocks, `StartClock()` and `UpdateClock()` +must be called in the global script, and the included item script +`GhostZHClockScript` must be set as any clock items' pickup script, with D0 set +to match the clock's duration. + +To prevent conflicts with ghost.zh, scripts should avoid using +`npc->Misc[__GHI_NPC_DATA]` and `eweapon->Misc[__EWI_FLAGS]`. Both indices +are set to 15 by default. + +Functions, variables, and constants whose names start with `__` are for internal +use and may be changed or removed in future versions without warning. + +## AutoGhost + +With appropriately written scripts, it is possible to place scripted enemies +without any manual FFC setup. The `AutoGhost()` function will scan the screen for +enemies that should be handled by scripts and set up FFCs automatically when +it finds them. `AutoGhost()` should come after `WaitDraw()` in the global script. + +An AutoGhost FFC script's run function should take an enemy ID as argument D0, +which should be passed to the `Ghost_InitAutoGhost` function. `AutoGhost()` will not set +any other arguments, but they can be used if your script runs additional +instances of the same script. + +The corresponding enemy needs to be set up to identify the script and combo +it will use, as described [here](autoGhost.md#setting-the-script-and-combo). diff --git a/images/enemy1.xcf b/images/enemy1.xcf new file mode 100644 index 0000000..e120f30 Binary files /dev/null and b/images/enemy1.xcf differ diff --git a/images/enemy2.xcf b/images/enemy2.xcf new file mode 100644 index 0000000..5b6696e Binary files /dev/null and b/images/enemy2.xcf differ diff --git a/images/enemy3.xcf b/images/enemy3.xcf new file mode 100644 index 0000000..0e731ca Binary files /dev/null and b/images/enemy3.xcf differ diff --git a/images/spawn.xcf b/images/spawn.xcf new file mode 100644 index 0000000..073ab57 Binary files /dev/null and b/images/spawn.xcf differ diff --git a/images/tileExample.xcf b/images/tileExample.xcf new file mode 100644 index 0000000..a7071d2 Binary files /dev/null and b/images/tileExample.xcf differ diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..6cae8dc --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,17 @@ +site_name: ghost.zh 2.8.4 +pages: + - About: index.md + - AutoGhost setup: autoGhost.md + - General usage: usage.md + - Global script: globalScript.md + - Enemy scripts: enemyScript.md + - Eweapons: eweapon.md + - Miscellaneous: other.md +theme: readthedocs +use_directory_urls: false +markdown_extensions: + - admonition + - def_list + - codehilite +extra: + version: 2.8.4