Skip to content

Instantly share code, notes, and snippets.

@gwx
Last active December 20, 2015 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gwx/6116836 to your computer and use it in GitHub Desktop.
Save gwx/6116836 to your computer and use it in GitHub Desktop.
Sideview stairs in ZC.
import "std.zh"
////////////////////////////////////////////////////////////////
//// Engine Constants.
// Combo Flag for soft platforms.
const int CF_SOFT = 98;
//// Block Types.
// An empty block.
const int BLOCK_EMPTY = 0;
// A fallthrough block.
const int BLOCK_SOFT = 1;
// A standard block.
const int BLOCK_HARD = 2;
//// Stair combo types.
const int CT_NEG = 142;
const int CT_CROSS = 143;
const int CT_POS = 144;
//// Custom Engine Constants.
// Link's walk speed.
const float LINK_WALK = 1.5;
// Link's gravitic acceleration.
const float LINK_GRAV = 0.16;
// Link's terminal velocity.
const float LINK_TERM = 3.2;
////////////////////////////////////////////////////////////////
//// Global Variables
////////////////
//// Link's State
//// How to handle Link's movement.
// We're letting the ZC engine handle movement.
const int LINK_MODE_ENGINE = 0;
// We're dealing with Link's movement ourselves.
const int LINK_MODE_CUSTOM = 1;
// We're moving link accourding to the stair system.
const int LINK_MODE_STAIR = 2;
// Link's current movement mode.
int LinkMode = LINK_MODE_ENGINE;
// Link's Location. This is so we can have fractional movement.
float LinkX = 0;
float LinkY = 0;
// Link's Vertical Velocity.
float LinkVy = 0;
// What Link is standing on.
int LinkBlock = BLOCK_HARD;
// Link's jump speed.
float LinkJump = -4;
// Link's hop speed.
float LinkHop = -1;
//// Fake input since we're cancelling it.
bool InputJump = false;
bool PressJump = false;
//// Various parts of Link's state from last frame.
// Link's Position.
float OldLinkX = 0;
float OldLinkY = 0;
int OldLinkAction = LA_NONE;
//// Stair State.
// On a down-left up-right stair.
const int STAIR_NEG = -1;
// Not on any stairs.
const int STAIR_NONE = 0;
// On an up-left down-right stair.
const int STAIR_POS = 1;
//// Stair Positioning - where we are on a stair.
// We're in the middle of the stair.
const int STAIR_MIDDLE = 0;
// We're anchored to the side of a stair.
const int STAIR_BOTTOM = 1;
// We're anchored to a stair diagonally.
const int STAIR_TOP = 2;
// The current kind of stair that Link is standing on.
int StairMode = STAIR_NONE;
// If the stairs were mounted this frame.
bool StairMount = false;
// The combo position fo the stair that Link is anchored to.
int StairLoc = -1;
// Where we are on the stair.
int StairPos = STAIR_MIDDLE;
// The x position of the edge of the stairs.
int StairEdgeX = -1;
// The left edge of the stairs that Link is on.
int StairLeft = 0;
// The right edge of the stairs that Link is on.
int StairRight = 0;
// If the anchored stair has another above it.
bool StairAbove = false;
// If the anchored stair has another below it.
bool StairBelow = false;
// The y offset of the current stair.
int StairY = 0;
////////////////
//// Screen Change
//// Screen State on the previous frame.
// DMap from last frame.
int OldDMap = -1;
// DMap Screen from last frame.
int OldDScreen = -1;
// If the dmap has changed from the last frame.
bool DMapChanged = false;
// If the screen has changed from the last frame.
bool ScreenChanged = false;
// Used so that ScreenChanged is only set on the first frame
// of a scrolling screen change.
bool _ScreenChanged_ScrollFlag = false;
// The ScreenChange FFC sets this so that maze screens can be used.
bool _ScreenChanged_ForceFlag = false;
// If the screen change has been handled by custom code.
bool ScreenChangeHandled = true;
// We're pretty sure that the screen change was caused by a warp of
// some sort.
const int SCREEN_CHANGE_WARP = -1;
// Best guess for which direction we changed screens in
// based on Link's current position.
int ScreenChangeDir = SCREEN_CHANGE_WARP;
global script Active {
void run() {
LinkX = Link->X;
LinkY = Link->Y;
while (true) {
OldLink_Update1();
ScreenChange_Update1();
Stair_Update1();
Input_Update1();
//Input_Update2();
// Performs Game Logic.
Waitdraw();
ScreenChange_Update2();
DetermineLinkMode();
// If we're not using custom movement, update Link's positioning
// variables to match whatever the engine says.
if (LinkMode == LINK_MODE_ENGINE) {
LinkX = Link->X;
LinkY = Link->Y;}
// Perform custom movement.
if (LinkMode == LINK_MODE_CUSTOM) {
StairMode = STAIR_NONE;
LinkCustomOnScreenChange();
LinkCustomUpdatePosition();
LinkCustomJump();
LinkCustomMountStair();}
// We could possibly switch to stair movement at this point.
if (LinkMode == LINK_MODE_STAIR) {
Link->Jump = 0;
LinkStairOnScreenChange();
LinkStairFindStair();
LinkStairFallOff();}
// And away from it at this point.
if (LinkMode == LINK_MODE_STAIR) {
LinkStairUpdatePosition();
LinkStairJump();}
LinkAdjust();
// Wait for the screen to draw.
// (You wouldn't think it from the name, right?)
Waitframe();}}}
// If the combo location (in units of tiles) is valid, it is returned.
// otherwise, -1 is returned.
int FindLoc(int tx, int ty) {
if (tx < 0 || tx > 15 || ty < 0 || ty > 10) {
return -1;}
return tx + (ty << 4);}
// Determine whether we'll be relying on the ZC engine for movement
// or on this custom code.
// Place after Waitdraw, and before anything that needs to know Link's mode.
void DetermineLinkMode() {
// Check for various situations in which we want to fallback on
// the built-in ZC engine.
if (// If we're not a sideview screen, we definitely want
// to use the ZC engine.
!IsSideview() ||
// If Link is Frozen, he's probably using the hookshot.
Link->Action == LA_FROZEN ||
// If the screen is scrolling, we can't do anything anyway.
Link->Action == LA_SCROLLING ||
// If he's hurt, we want to rely on the built-in knockback.
Link->Action == LA_GOTHURTLAND ||
Link->Action == LA_GOTHURTWATER) {
// Rely on the engine.
LinkMode = LINK_MODE_ENGINE;}
// There's on reason not to, so use our custom engine or stairs..
else if (StairMode != STAIR_NONE) {
LinkMode = LINK_MODE_STAIR;}
else {
LinkMode = LINK_MODE_CUSTOM;}}
// Return true if the combo at the given position is a stair.
bool IsStair(int x, int y) {
if (x < 0 || x >= 256 || y < 0 || y >= 176) {return false;}
else {return IsStair((y & 240) + (x >> 4));}}
bool IsStair(int loc) {
if (loc == -1) {return false;}
int ct = Screen->ComboT[loc];
return CT_NEG <= ct && ct <= CT_POS;}
bool IsValidStair(int loc) {
if (StairMode == STAIR_NEG) {return IsNegStair(loc);}
else if (StairMode == STAIR_POS) {return IsPosStair(loc);}}
bool IsValidStair(int x, int y) {
if (StairMode == STAIR_NEG) {return IsNegStair(x, y);}
else if (StairMode == STAIR_POS) {return IsPosStair(x, y);}}
bool IsPosStair(int x, int y) {
if (x < 0 || x > 255 || y < 0 || y > 175) {return false;}
else {return IsPosStair((y & 240) + (x >> 4));}}
bool IsPosStair(int loc) {
if (loc == -1) {return false;}
int ct = Screen->ComboT[loc];
return ct == CT_CROSS || ct == CT_POS;}
bool IsNegStair(int x, int y) {
if (x < 0 || x > 255 || y < 0 || y > 175) {return false;}
else {return IsNegStair((y & 240) + (x >> 4));}}
bool IsNegStair(int loc) {
if (loc == -1) {return false;}
int ct = Screen->ComboT[loc];
return ct == CT_CROSS || ct == CT_NEG;}
// Gets the block type at the given position on screen.
int GetBlockType(int x, int y) {
// Outside the screen is always considered open.
if (x < 0 || x >= 256 || y < 0 || y >= 176) {return BLOCK_EMPTY;}
// Non-solid blocks are always empty.
else if (!Screen->isSolid(x, y)) {return BLOCK_EMPTY;}
// Otherwise, if has the soft flag or is a stair,
// it is a soft block.
else if (ComboFI(x, y, CF_SOFT) || IsStair(x, y)) {return BLOCK_SOFT;}
// Otherwise it is hard.
else {return BLOCK_HARD;}}
// Updates Old Link position when the screen changes.
void LinkUpdateOldOnScreenChange() {
// Set old link position to the edge of the screen we came in from.
if (ScreenChangeDir == DIR_UP) {
OldLinkY = 160;}
else if (ScreenChangeDir == DIR_DOWN) {
OldLinkY = 0;}
else if (ScreenChangeDir == DIR_LEFT) {
OldLinkX = 240;}
else if (ScreenChangeDir == DIR_RIGHT) {
OldLinkX = 0;}}
// Various actions to perform if the screen changed on us.
void LinkCustomOnScreenChange() {
if (ScreenChangeHandled) {return;}
// Respect any warps or such.
LinkX = Link->X;
LinkY = Link->Y;
LinkUpdateOldOnScreenChange();
// Mark as being handled.
ScreenChangeHandled = true;}
// Perform the actual movement of Link.
void LinkCustomUpdatePosition() {
// First, move according to player input.
if (// We can only move if we're standing still or walking.
Link->Action == LA_NONE || Link->Action == LA_WALKING ||
// Or we're in the air and attacking.
(Link->Action == LA_ATTACKING && LinkBlock == BLOCK_EMPTY)) {
// Then move left or right, but not both.
if (Link->InputLeft) {LinkX -= LINK_WALK;}
else if (Link->InputRight) {LinkX += LINK_WALK;}}
// Check against running into a wall to the left.
if (// First check that we moved left.
LinkX < OldLinkX &&
(// Then check for hard blocks at Link's top, middle, and bottom.
GetBlockType(LinkX, LinkY) == BLOCK_HARD ||
GetBlockType(LinkX, LinkY + 8) == BLOCK_HARD ||
GetBlockType(LinkX, LinkY + 15) == BLOCK_HARD)) {
// If he hit, move Link right to the next multiple of 8.
LinkX += 8 - (LinkX % 8);}
// Check against running into a wall to the right.
if (// First check that we moved right.
LinkX > OldLinkX &&
(// Then check for hard blocks at Link's top, middle, and bottom.
GetBlockType(LinkX + 15, LinkY) == BLOCK_HARD ||
GetBlockType(LinkX + 15, LinkY + 8) == BLOCK_HARD ||
GetBlockType(LinkX + 15, LinkY + 15) == BLOCK_HARD)) {
// If he hit, move Link left to the previous multiple of 8.
LinkX &= 0x1FFF8;}
// Then move Link according to his vertical velocity.
LinkY += LinkVy;
// Check against running into a hard block above.
if (// First check that we're moving up.
LinkY < OldLinkY &&
(// Then check against Link's middle-left and middle-right.
GetBlockType(LinkX + 5, LinkY) == BLOCK_HARD ||
GetBlockType(LinkX + 11, LinkY) == BLOCK_HARD)) {
// If he hit, move Link down to the next multiple of 8.
LinkY += 8 - (LinkY % 8);
// and get rid of his vertical velocity.
LinkVy = 0;}
// Check against running into a block below, and assign the block type
// below Link to LinkBlock for this round.
// First check to make sure we're moving down.
if (LinkY > OldLinkY) {
// Get the hardest type of platform below Link.
// Check against his middle-left and middle-right.
LinkBlock = Max(GetBlockType(LinkX + 5, LinkY + 16),
GetBlockType(LinkX + 11, LinkY + 16));
// See if we ran into a block.
if (// A hard block always counts.
LinkBlock == BLOCK_HARD ||
// A soft block counts as long as we're not holding the jump
// button down, or we started out past it.
(LinkBlock == BLOCK_SOFT &&
!InputJump &&
!(OldLinkY > (LinkY & 0x1FFF8)))) {
// If he hit, move Link up to the previous multiple of 8.
LinkY &= 0x1FFF8;
// and get rid of his vertical velocity.
LinkVy = 0;}}
// Otherwise, we're in the air.
else {
LinkBlock = BLOCK_EMPTY;}
Link->Jump = 0;
Link->Z = 0;
// Gravity.
LinkVy = Min(LinkVy + LINK_GRAV, LINK_TERM);}
// Perform a sideview jump.
void SideviewJump() {
Game->PlaySound(SFX_JUMP);
// We're holding down, so only hop.
if (Link->InputDown) {LinkVy = LinkHop;}
// Otherwise do the full jump.
else {LinkVy = LinkJump;}}
// Jump according to custom mode rules.
void LinkCustomJump() {
if (// The Jump button is pressed.
PressJump &&
// Can't jump in the air.
LinkBlock != BLOCK_EMPTY &&
// Must have positive y velocity.
LinkVy >= 0 &&
// Can't be doing anything but walking.
(Link->Action == LA_NONE || Link->Action == LA_WALKING)) {
// Jump!
SideviewJump();}}
// Check if we need to get onto stairs from custom mode.
void LinkCustomMountStair() {
// We never get on a stair unless we're standing on something.
if (LinkBlock == BLOCK_EMPTY) {return;}
// We must have a positive or 0 y velocity.
if (LinkVy < 0) {return;}
// We're moving up-left, so check an up-left going stair on the same
// tile as Link.
if (Link->InputLeft && Link->InputUp && IsPosStair(LinkX, LinkY + 15)) {
MountStair(LinkX, LinkY + 15, STAIR_POS);
StairPos = STAIR_BOTTOM;}
// We're moving up-right, so check an up-right going stair on the same
// tile as Link.
else if (Link->InputRight && Link->InputUp &&
IsNegStair(LinkX + 15, LinkY + 15)) {
MountStair(LinkX + 15, LinkY + 15, STAIR_NEG);
StairPos = STAIR_BOTTOM;}
// We're moving down-left, so check a down-left going stair on the
// tile below Link.
if (Link->InputLeft && Link->InputDown && IsNegStair(LinkX + 2, LinkY + 18)) {
MountStair(LinkX + 2, LinkY + 18, STAIR_NEG);
StairPos = STAIR_TOP;}
// We're moving down-right, so check a down-right going stair on the
// tile below Link.
if (Link->InputRight && Link->InputDown &&
IsPosStair(LinkX + 13, LinkY + 18)) {
MountStair(LinkX + 13, LinkY + 18, STAIR_POS);
StairPos = STAIR_TOP;}}
// Causes Link to mount the stair at the given position.
// Returns true if the stair was mounted.
bool MountStair(int x, int y, int mode) {
// First, make sure there's actually a stair there.
int start = (y & 240) + (x >> 4);
if (x < 0 || x >= 256 || y < 0 || y >= 176 || !IsStair(start)) {
LinkMode = LINK_MODE_CUSTOM;
StairMode = STAIR_NONE;
return false;}
// Change to stair movement mode.
LinkMode = LINK_MODE_STAIR;
StairMode = mode;
StairLoc = ComboAt(x, y);
// Mark the stairs being mounted this frame.
StairMount = true;
// Set the Y offset.
x = ComboX(start);
y = ComboY(start);
StairY =
// Start with the y position of the stair combo.
y
// Move to 1 cell above it.
- 16
// Adjust for the x position of the stair combo in the stair direction.
- x * StairMode;
return true;}
void Stair_Update1() {
StairMount = false;}
// Adjust Link's position if the screen changed.
void LinkStairOnScreenChange() {
if (ScreenChangeHandled) {return;}
int stairTX = StairLoc % 16;
int stairTY = StairLoc >> 4;
LinkUpdateOldOnScreenChange();
// If we walked off the top of the screen.
if (ScreenChangeDir == DIR_UP) {
int adjust = (StairLoc >> 4) + 1;
stairTX -= adjust * StairMode;
stairTY = 10;
StairLoc = FindLoc(stairTX, stairTY);
LinkX = (stairTX + StairMode) * 16;
LinkY = 160;}
// We walked off the bottom of the screen.
else if (ScreenChangeDir == DIR_DOWN) {
int adjust = 11 - stairTY;
// First check if there is actually a stair on the top of the new screen.
int loc = FindLoc(stairTX + StairMode * adjust, 0);
if (!IsValidStair(loc)) {
// If there isn't then just set Link's X to where that stair would be.
LinkX = ComboX(loc);
StairLoc = -1;}
// If there is, proceed as normal.
else {
stairTX += 2 * StairMode;
stairTY = 1;
StairLoc = FindLoc(stairTX, stairTY);
LinkX = stairTX * 16;}
LinkY = 0;}
// We walked off the left edge of the screen. Make sure that the
// stairs actually reached all the way to the left as well.
else if (ScreenChangeDir == DIR_LEFT &&
(// If we were on the edge stair, then we know it existed.
stairTX == 0 ||
// Check above or below based on stair direction
Cond(StairMode == STAIR_POS, StairAbove, StairBelow))) {
stairTX = 15;
// How far away the stair we're anchored to is from the wall.
int adjust = (StairLoc % 16) + 1;
stairTY -= adjust * StairMode;
StairLoc = FindLoc(stairTX, stairTY);
LinkX = 240;
LinkY = (stairTY - 1) * 16;
// If there isn't a valid stair there, and we were moving up, then
// move Link down a tile, because he never climbed it while the
// screen was scrolling.
if (StairMode == STAIR_POS && !IsValidStair(StairLoc)) {
LinkY += 16;}}
// We walked off the right edge of the screen. Make sure that the
// stairs actually reached all the way to the right as well.
else if (ScreenChangeDir == DIR_RIGHT &&
(// If we were on the edge stair, then we know it existed.
stairTX == 15 ||
// Check above or below based on stair direction
Cond(StairMode == STAIR_POS, StairBelow, StairAbove))) {
stairTX = 0;
// How far away the stair we're anchored to is from the wall.
int adjust = 16 - (StairLoc % 16);
stairTY += adjust * StairMode;
StairLoc = FindLoc(stairTX, stairTY);
LinkX = 0;
LinkY = (stairTY - 1) * 16;
// If there isn't a valid stair there, and we were moving up, then
// move Link down a tile, because he never climbed it while the
// screen was scrolling.
if (StairMode == STAIR_NEG && !IsValidStair(StairLoc)) {
LinkY += 16;}}
// Otherwise, cancel stairs.
else {
LinkX = Link->X;
LinkY = Link->Y;
StairMode = STAIR_NONE;
LinkMode = LINK_MODE_CUSTOM;}
if (StairMode != STAIR_NONE) {
MountStair(stairTX << 4, stairTY << 4, StairMode);}
ScreenChangeHandled = true;}
// Update Link's position based on the stair he's on.
void LinkStairUpdatePosition() {
// First, move according to player input.
if (// We can only move if we're standing still or walking.
Link->Action == LA_NONE || Link->Action == LA_WALKING) {
// Then move left or right, but not both.
if (Link->InputLeft) {LinkX -= LINK_WALK;}
else if (Link->InputRight) {LinkX += LINK_WALK;}}
// If we're at the top or bottom of the stair, check against running
// into walls.
if (StairPos != STAIR_MIDDLE) {
// Check against running into a wall to the left.
if (// First check that we moved left.
LinkX < OldLinkX &&
// Then check that we're not at the top of a negative stair.
(StairPos != STAIR_TOP || StairMode != STAIR_NEG) &&
(// Then check for hard blocks at Link's top, middle, and bottom.
GetBlockType(LinkX, LinkY) == BLOCK_HARD ||
GetBlockType(LinkX, LinkY + 8) == BLOCK_HARD ||
GetBlockType(LinkX, LinkY + 15) == BLOCK_HARD)) {
// If he hit, move Link right to the next multiple of 8.
LinkX += 8 - (LinkX % 8);}
// Check against running into a wall to the right.
if (// First check that we moved right.
LinkX > OldLinkX &&
// Then check that we're not at the top of a positive stair.
(StairPos != STAIR_TOP || StairMode != STAIR_POS) &&
(// Then check for hard blocks at Link's top, middle, and bottom.
GetBlockType(LinkX + 15, LinkY) == BLOCK_HARD ||
GetBlockType(LinkX + 15, LinkY + 8) == BLOCK_HARD ||
GetBlockType(LinkX + 15, LinkY + 15) == BLOCK_HARD)) {
// If he hit, move Link left to the previous multiple of 8.
LinkX &= 0x1FFF8;}}
//// Then adjust y positioning.
// If we're at the middle of the stair, use the standard formula.
LinkY = LinkX * StairMode + StairY;
// If we're at the bottom, align Link with the anchored stair.
if (StairPos == STAIR_BOTTOM &&
((StairMode == STAIR_NEG && LinkX <= ComboX(StairLoc) - 16) ||
(StairMode == STAIR_POS && LinkX >= ComboX(StairLoc) + 16))) {
LinkY = ComboY(StairLoc);}
// If we're at the top, align Link with the cell above the anchored stair.
else if (StairPos == STAIR_TOP &&
((StairMode == STAIR_NEG && LinkX >= ComboX(StairLoc) - 1) ||
(StairMode == STAIR_POS && LinkX <= ComboX(StairLoc) + 1))) {
LinkY = ComboY(StairLoc) - 16;}}
// Find the stair that Link is currently standing on.
void LinkStairFindStair() {
if (StairLoc == -1) {return;}
//// First, check if we've moved off of the stair we're currently anchored to.
// Get the edge closest to the stair.
int x = LinkX + Cond(StairMode == STAIR_POS, 0, 15);
int stairX = ComboX(StairLoc);
int stairTX = StairLoc % 16;
int stairTY = StairLoc >> 4;
// Direction we've shifted.
int shiftDir = 0;
// We've moved off the left side of the stair, so move the StairLoc
// 1 to the left, plus up or down as appropriate.
if (x < stairX) {
stairTX--;
stairTY -= StairMode;
shiftDir = -1;}
// We've moved off the right side of the stair, so move the StairLoc
// 1 to the right, plus up or down as appropriate.
else if (x >= stairX + 16) {
stairTX++;
stairTY += StairMode;
shiftDir = 1;}
StairLoc = FindLoc(stairTX, stairTY);
StairPos = STAIR_MIDDLE;
// If we found the stairs, but we're on the top edge of a stair (and
// not on the edge of a screen), set to the top edge anyway.
if (IsValidStair(StairLoc) &&
((StairMode == STAIR_POS && stairTX != 0) ||
(StairMode == STAIR_NEG && stairTX != 15))) {
int aboveLoc = FindLoc(stairTX - StairMode, stairTY - 1);
if (!IsValidStair(aboveLoc)) {
StairPos = STAIR_TOP;}}
// Check for a stair to the side.
if (// First, make sure that we didn't already find a stair.
!IsValidStair(StairLoc) &&
// And then also make sure that we didn't shift up the stair,
// because we're shifting up again and a double shift doesn't
// make sense.
shiftDir * StairMode != -1) {
StairLoc = FindLoc(stairTX - StairMode, stairTY - 1);
// If we're on the bottom of the screen, assume there's more
// stairs on the next screen.
if (stairTY - 1 < 10) {
StairPos = STAIR_BOTTOM;}}
// Then check for a stair diagonally downward.
if (!IsValidStair(StairLoc)) {
StairLoc = FindLoc(stairTX + StairMode, stairTY + 1);
StairPos = STAIR_TOP;}
// Check if we failed.
if (!IsValidStair(StairLoc)) {
StairLoc = -1;
return;}
// Set StairLeft and StairRight to the proper values for Link's position.
if (StairPos == STAIR_MIDDLE) {
StairLeft = 0;
StairRight = 255;}
else {
stairTX = StairLoc % 16;
StairLeft = (stairTX - 1) * 16 - 2;
StairRight = (stairTX + 1) * 16 + 2;}
// Find if there's a stair above and below.
StairAbove = IsValidStair(FindLoc(stairTX - StairMode, stairTY - 1));
StairBelow = IsValidStair(FindLoc(stairTX + StairMode, stairTY + 1));}
// See if Link is leaving the stairs.
void LinkStairFallOff() {
if (// Getting hurt knocks you off of stairs.
Link->Action == LA_GOTHURTLAND || Link->Action == LA_GOTHURTWATER ||
// If we couldn't locate a stair earlier, that means we fall off, too.
StairLoc == -1 ||
// Or if we've moved too far off of the top or bottom of a stair.
LinkX < StairLeft || LinkX > StairRight) {
StairMode = STAIR_NONE;
LinkMode = LINK_MODE_CUSTOM;}}
// Jump according to stair mode rules.
void LinkStairJump() {
if (// The Jump button is pressed.
PressJump &&
// Can't be doing anything but walking.
(Link->Action == LA_NONE || Link->Action == LA_WALKING)) {
StairMode = STAIR_NONE;
LinkMode = LINK_MODE_CUSTOM;
// Jump!
SideviewJump();}}
// Assigns all the OldLink variables for the upcoming frame.
// Place before Waitdraw().
void OldLink_Update1() {
OldLinkX = Link->X;
OldLinkY = Link->Y;
OldLinkAction = Link->Action;}
// Record the current dmap and dscreen right before they are changed.
// Place before Waitdraw().
void ScreenChange_Update1() {
OldDMap = Game->GetCurDMap();
OldDScreen = Game->GetCurDMapScreen();}
// Updates information dealing with changing screens.
// Place after Waitdraw(), when the screen changes happen.
void ScreenChange_Update2() {
// Grab current values.
int dMap = Game->GetCurDMap();
int dScreen = Game->GetCurDMapScreen();
// Compare with old values.
DMapChanged = dMap != OldDMap;
ScreenChanged = DMapChanged || dScreen != OldDScreen;
// Check for scrolling change to the same screen.
if (Link->Action == LA_SCROLLING) {
if (!ScreenChanged && !_ScreenChanged_ScrollFlag) {
ScreenChanged = true;
_ScreenChanged_ScrollFlag = true;}}
// We're no longer scrolling, so reset scroll flag.
else {
_ScreenChanged_ScrollFlag = false;}
// Check for a forced screen change flag.
if (_ScreenChanged_ForceFlag) {
ScreenChanged = true;
_ScreenChanged_ForceFlag = false;}
// Find the screen change direction.
if (ScreenChanged) {
// Mark the screen change as needing to be handled.
ScreenChangeHandled = false;
// Try to guess the direction.
if (Link->Y >= 160) {ScreenChangeDir = DIR_UP;}
else if (Link->Y <= 0) {ScreenChangeDir = DIR_DOWN;}
else if (Link->X >= 240) {ScreenChangeDir = DIR_LEFT;}
else if (Link->X <= 0) {ScreenChangeDir = DIR_RIGHT;}
else {ScreenChangeDir = SCREEN_CHANGE_WARP;}}}
// Adjust some of Link's variables after all the mechanical
// manipulation is done.
void LinkAdjust() {
// Don't do anything in engine mode.
if (LinkMode == LINK_MODE_ENGINE) {return;}
// Update Link's actual position.
Link->X = Round(LinkX);
Link->Y = Round(LinkY);
// Force the walking animation if we moved and have no other action.
if (Link->Action == LA_NONE && (LinkX != OldLinkX || LinkY != OldLinkY)) {
Link->Action = LA_WALKING;}
// Set the direction according to input.
if (Link->InputUp) {Link->Dir = DIR_UP;}
else if (Link->InputDown) {Link->Dir = DIR_DOWN;}
else if (Link->InputLeft) {Link->Dir = DIR_LEFT;}
else if (Link->InputRight) {Link->Dir = DIR_RIGHT;}}
// Don't scroll through items on sideview screens with L.
void Input_Update1() {
// Ignore L if this is a sideview screen.
if (IsSideview()) {
InputJump = Link->InputL;
PressJump = Link->PressL;
Link->InputL = false;
Link->PressL = false;}}
// Change the inputs so the engine doesn't set Link facing a weird
// direction or something else we don't want.
void Input_Update2() {
// If we're not in engine mode, up and down take preference for
// direction.
if (LinkMode != LINK_MODE_ENGINE &&
(Link->InputUp || Link->InputDown)) {
Link->InputLeft = false;
Link->InputRight = false;
Link->PressLeft = false;
Link->PressRight = false;}}
ffc script ScreenChange {
void run() {
_ScreenChanged_ForceFlag = true;}}
// Don't carry over velocity or stair state.
global script OnContinue {
void run() {
StairMode = STAIR_NONE;
LinkVy = 0;}}
// Set first argument to Link's full jump speed.
// Set second argument to Link's jump speed while holding down.
item script AdjustLinkJump {
void run (int jumpSpeed, int hopSpeed) {
LinkJump = jumpSpeed;
LinkHop = hopSpeed;}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment