Advertisement
ZoriaRPG

CV Stairs v3 (July 2013)

Oct 28th, 2019
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 25.21 KB | None | 0 0
  1. import "std.zh"
  2.  
  3. ////////////////////////////////////////////////////////////////
  4. //// Engine Constants.
  5.  
  6. // Combo Flag for soft platforms.
  7. const int CF_SOFT = 98;
  8.  
  9. //// Block Types.
  10. // An empty block.
  11. const int BLOCK_EMPTY = 0;
  12. // A fallthrough block.
  13. const int BLOCK_SOFT = 1;
  14. // A standard block.
  15. const int BLOCK_HARD = 2;
  16.  
  17. //// Stair combo types.
  18. const int CT_NEG = 142;
  19. const int CT_CROSS = 143;
  20. const int CT_POS = 144;
  21.  
  22. //// Custom Engine Constants.
  23. // Link's walk speed.
  24. const float LINK_WALK = 1.5;
  25. // Link's gravitic acceleration.
  26. const float LINK_GRAV = 0.16;
  27. // Link's terminal velocity.
  28. const float LINK_TERM = 3.2;
  29.  
  30. ////////////////////////////////////////////////////////////////
  31. //// Global Variables
  32.  
  33. ////////////////
  34. //// Link's State
  35.  
  36. //// How to handle Link's movement.
  37. // We're letting the ZC engine handle movement.
  38. const int LINK_MODE_ENGINE = 0;
  39. // We're dealing with Link's movement ourselves.
  40. const int LINK_MODE_CUSTOM = 1;
  41. // We're moving link accourding to the stair system.
  42. const int LINK_MODE_STAIR = 2;
  43. // Link's current movement mode.
  44. int LinkMode = LINK_MODE_ENGINE;
  45.  
  46. // Link's Location. This is so we can have fractional movement.
  47. float LinkX = 0;
  48. float LinkY = 0;
  49. // Link's Vertical Velocity.
  50. float LinkVy = 0;
  51. // What Link is standing on.
  52. int LinkBlock = BLOCK_HARD;
  53.  
  54. // Link's jump speed.
  55. float LinkJump = -4;
  56. // Link's hop speed.
  57. float LinkHop = -1;
  58.  
  59. //// Fake input since we're cancelling it.
  60. bool InputJump = false;
  61. bool PressJump = false;
  62.  
  63. //// Various parts of Link's state from last frame.
  64. // Link's Position.
  65. float OldLinkX = 0;
  66. float OldLinkY = 0;
  67. int OldLinkAction = LA_NONE;
  68.  
  69. //// Stair State.
  70. // On a down-left up-right stair.
  71. const int STAIR_NEG = -1;
  72. // Not on any stairs.
  73. const int STAIR_NONE = 0;
  74. // On an up-left down-right stair.
  75. const int STAIR_POS = 1;
  76. //// Stair Positioning - where we are on a stair.
  77. // We're in the middle of the stair.
  78. const int STAIR_MIDDLE = 0;
  79. // We're anchored to the side of a stair.
  80. const int STAIR_BOTTOM = 1;
  81. // We're anchored to a stair diagonally.
  82. const int STAIR_TOP = 2;
  83.  
  84. // The current kind of stair that Link is standing on.
  85. int StairMode = STAIR_NONE;
  86. // If the stairs were mounted this frame.
  87. bool StairMount = false;
  88. // The combo position fo the stair that Link is anchored to.
  89. int StairLoc = -1;
  90. // Where we are on the stair.
  91. int StairPos = STAIR_MIDDLE;
  92. // The x position of the edge of the stairs.
  93. int StairEdgeX = -1;
  94. // The left edge of the stairs that Link is on.
  95. int StairLeft = 0;
  96. // The right edge of the stairs that Link is on.
  97. int StairRight = 0;
  98. // If the anchored stair has another above it.
  99. bool StairAbove = false;
  100. // If the anchored stair has another below it.
  101. bool StairBelow = false;
  102. // The y offset of the current stair.
  103. int StairY = 0;
  104.  
  105.  
  106. ////////////////
  107. //// Screen Change
  108.  
  109. //// Screen State on the previous frame.
  110. // DMap from last frame.
  111. int OldDMap = -1;
  112. // DMap Screen from last frame.
  113. int OldDScreen = -1;
  114. // If the dmap has changed from the last frame.
  115. bool DMapChanged = false;
  116. // If the screen has changed from the last frame.
  117. bool ScreenChanged = false;
  118. // Used so that ScreenChanged is only set on the first frame
  119. // of a scrolling screen change.
  120. bool _ScreenChanged_ScrollFlag = false;
  121. // The ScreenChange FFC sets this so that maze screens can be used.
  122. bool _ScreenChanged_ForceFlag = false;
  123. // If the screen change has been handled by custom code.
  124. bool ScreenChangeHandled = true;
  125. // We're pretty sure that the screen change was caused by a warp of
  126. // some sort.
  127. const int SCREEN_CHANGE_WARP = -1;
  128. // Best guess for which direction we changed screens in
  129. // based on Link's current position.
  130. int ScreenChangeDir = SCREEN_CHANGE_WARP;
  131.  
  132. global script Active {
  133. void run() {
  134.  
  135. LinkX = Link->X;
  136. LinkY = Link->Y;
  137.  
  138. while (true) {
  139.  
  140. OldLink_Update1();
  141. ScreenChange_Update1();
  142. Stair_Update1();
  143. Input_Update1();
  144. //Input_Update2();
  145.  
  146. // Performs Game Logic.
  147. Waitdraw();
  148.  
  149. ScreenChange_Update2();
  150. DetermineLinkMode();
  151.  
  152. // If we're not using custom movement, update Link's positioning
  153. // variables to match whatever the engine says.
  154. if (LinkMode == LINK_MODE_ENGINE) {
  155. LinkX = Link->X;
  156. LinkY = Link->Y;}
  157.  
  158. // Perform custom movement.
  159. if (LinkMode == LINK_MODE_CUSTOM) {
  160. StairMode = STAIR_NONE;
  161. LinkCustomOnScreenChange();
  162. LinkCustomUpdatePosition();
  163. LinkCustomJump();
  164. LinkCustomMountStair();}
  165.  
  166. // We could possibly switch to stair movement at this point.
  167. if (LinkMode == LINK_MODE_STAIR) {
  168. Link->Jump = 0;
  169. LinkStairOnScreenChange();
  170. LinkStairFindStair();
  171. LinkStairFallOff();}
  172.  
  173. // And away from it at this point.
  174. if (LinkMode == LINK_MODE_STAIR) {
  175. LinkStairUpdatePosition();
  176. LinkStairJump();}
  177.  
  178. LinkAdjust();
  179.  
  180. // Wait for the screen to draw.
  181. // (You wouldn't think it from the name, right?)
  182. Waitframe();}}}
  183.  
  184. // If the combo location (in units of tiles) is valid, it is returned.
  185. // otherwise, -1 is returned.
  186. int FindLoc(int tx, int ty) {
  187. if (tx < 0 || tx > 15 || ty < 0 || ty > 10) {
  188. return -1;}
  189. return tx + (ty << 4);}
  190.  
  191. // Determine whether we'll be relying on the ZC engine for movement
  192. // or on this custom code.
  193. // Place after Waitdraw, and before anything that needs to know Link's mode.
  194. void DetermineLinkMode() {
  195. // Check for various situations in which we want to fallback on
  196. // the built-in ZC engine.
  197. if (// If we're not a sideview screen, we definitely want
  198. // to use the ZC engine.
  199. !IsSideview() ||
  200. // If Link is Frozen, he's probably using the hookshot.
  201. Link->Action == LA_FROZEN ||
  202. // If the screen is scrolling, we can't do anything anyway.
  203. Link->Action == LA_SCROLLING ||
  204. // If he's hurt, we want to rely on the built-in knockback.
  205. Link->Action == LA_GOTHURTLAND ||
  206. Link->Action == LA_GOTHURTWATER) {
  207. // Rely on the engine.
  208. LinkMode = LINK_MODE_ENGINE;}
  209. // There's on reason not to, so use our custom engine or stairs..
  210. else if (StairMode != STAIR_NONE) {
  211. LinkMode = LINK_MODE_STAIR;}
  212. else {
  213. LinkMode = LINK_MODE_CUSTOM;}}
  214.  
  215. // Return true if the combo at the given position is a stair.
  216. bool IsStair(int x, int y) {
  217. if (x < 0 || x >= 256 || y < 0 || y >= 176) {return false;}
  218. else {return IsStair((y & 240) + (x >> 4));}}
  219.  
  220. bool IsStair(int loc) {
  221. if (loc == -1) {return false;}
  222. int ct = Screen->ComboT[loc];
  223. return CT_NEG <= ct && ct <= CT_POS;}
  224.  
  225. bool IsValidStair(int loc) {
  226. if (StairMode == STAIR_NEG) {return IsNegStair(loc);}
  227. else if (StairMode == STAIR_POS) {return IsPosStair(loc);}}
  228.  
  229. bool IsValidStair(int x, int y) {
  230. if (StairMode == STAIR_NEG) {return IsNegStair(x, y);}
  231. else if (StairMode == STAIR_POS) {return IsPosStair(x, y);}}
  232.  
  233. bool IsPosStair(int x, int y) {
  234. if (x < 0 || x > 255 || y < 0 || y > 175) {return false;}
  235. else {return IsPosStair((y & 240) + (x >> 4));}}
  236.  
  237. bool IsPosStair(int loc) {
  238. if (loc == -1) {return false;}
  239. int ct = Screen->ComboT[loc];
  240. return ct == CT_CROSS || ct == CT_POS;}
  241.  
  242. bool IsNegStair(int x, int y) {
  243. if (x < 0 || x > 255 || y < 0 || y > 175) {return false;}
  244. else {return IsNegStair((y & 240) + (x >> 4));}}
  245.  
  246. bool IsNegStair(int loc) {
  247. if (loc == -1) {return false;}
  248. int ct = Screen->ComboT[loc];
  249. return ct == CT_CROSS || ct == CT_NEG;}
  250.  
  251. // Gets the block type at the given position on screen.
  252. int GetBlockType(int x, int y) {
  253. // Outside the screen is always considered open.
  254. if (x < 0 || x >= 256 || y < 0 || y >= 176) {return BLOCK_EMPTY;}
  255. // Non-solid blocks are always empty.
  256. else if (!Screen->isSolid(x, y)) {return BLOCK_EMPTY;}
  257. // Otherwise, if has the soft flag or is a stair,
  258. // it is a soft block.
  259. else if (ComboFI(x, y, CF_SOFT) || IsStair(x, y)) {return BLOCK_SOFT;}
  260. // Otherwise it is hard.
  261. else {return BLOCK_HARD;}}
  262.  
  263. // Updates Old Link position when the screen changes.
  264. void LinkUpdateOldOnScreenChange() {
  265. // Set old link position to the edge of the screen we came in from.
  266. if (ScreenChangeDir == DIR_UP) {
  267. OldLinkY = 160;}
  268. else if (ScreenChangeDir == DIR_DOWN) {
  269. OldLinkY = 0;}
  270. else if (ScreenChangeDir == DIR_LEFT) {
  271. OldLinkX = 240;}
  272. else if (ScreenChangeDir == DIR_RIGHT) {
  273. OldLinkX = 0;}}
  274.  
  275.  
  276. // Various actions to perform if the screen changed on us.
  277. void LinkCustomOnScreenChange() {
  278. if (ScreenChangeHandled) {return;}
  279.  
  280. // Respect any warps or such.
  281. LinkX = Link->X;
  282. LinkY = Link->Y;
  283.  
  284. LinkUpdateOldOnScreenChange();
  285.  
  286. // Mark as being handled.
  287. ScreenChangeHandled = true;}
  288.  
  289. // Perform the actual movement of Link.
  290. void LinkCustomUpdatePosition() {
  291.  
  292. // First, move according to player input.
  293. if (// We can only move if we're standing still or walking.
  294. Link->Action == LA_NONE || Link->Action == LA_WALKING ||
  295. // Or we're in the air and attacking.
  296. (Link->Action == LA_ATTACKING && LinkBlock == BLOCK_EMPTY)) {
  297. // Then move left or right, but not both.
  298. if (Link->InputLeft) {LinkX -= LINK_WALK;}
  299. else if (Link->InputRight) {LinkX += LINK_WALK;}}
  300.  
  301. // Check against running into a wall to the left.
  302. if (// First check that we moved left.
  303. LinkX < OldLinkX &&
  304. (// Then check for hard blocks at Link's top, middle, and bottom.
  305. GetBlockType(LinkX, LinkY) == BLOCK_HARD ||
  306. GetBlockType(LinkX, LinkY + 8) == BLOCK_HARD ||
  307. GetBlockType(LinkX, LinkY + 15) == BLOCK_HARD)) {
  308. // If he hit, move Link right to the next multiple of 8.
  309. LinkX += 8 - (LinkX % 8);}
  310.  
  311. // Check against running into a wall to the right.
  312. if (// First check that we moved right.
  313. LinkX > OldLinkX &&
  314. (// Then check for hard blocks at Link's top, middle, and bottom.
  315. GetBlockType(LinkX + 15, LinkY) == BLOCK_HARD ||
  316. GetBlockType(LinkX + 15, LinkY + 8) == BLOCK_HARD ||
  317. GetBlockType(LinkX + 15, LinkY + 15) == BLOCK_HARD)) {
  318. // If he hit, move Link left to the previous multiple of 8.
  319. LinkX &= 0x1FFF8;}
  320.  
  321. // Then move Link according to his vertical velocity.
  322. LinkY += LinkVy;
  323.  
  324. // Check against running into a hard block above.
  325. if (// First check that we're moving up.
  326. LinkY < OldLinkY &&
  327. (// Then check against Link's middle-left and middle-right.
  328. GetBlockType(LinkX + 5, LinkY) == BLOCK_HARD ||
  329. GetBlockType(LinkX + 11, LinkY) == BLOCK_HARD)) {
  330. // If he hit, move Link down to the next multiple of 8.
  331. LinkY += 8 - (LinkY % 8);
  332. // and get rid of his vertical velocity.
  333. LinkVy = 0;}
  334.  
  335. // Check against running into a block below, and assign the block type
  336. // below Link to LinkBlock for this round.
  337. // First check to make sure we're moving down.
  338. if (LinkY > OldLinkY) {
  339. // Get the hardest type of platform below Link.
  340. // Check against his middle-left and middle-right.
  341. LinkBlock = Max(GetBlockType(LinkX + 5, LinkY + 16),
  342. GetBlockType(LinkX + 11, LinkY + 16));
  343. // See if we ran into a block.
  344. if (// A hard block always counts.
  345. LinkBlock == BLOCK_HARD ||
  346. // A soft block counts as long as we're not holding the jump
  347. // button down, or we started out past it.
  348. (LinkBlock == BLOCK_SOFT &&
  349. !InputJump &&
  350. !(OldLinkY > (LinkY & 0x1FFF8)))) {
  351. // If he hit, move Link up to the previous multiple of 8.
  352. LinkY &= 0x1FFF8;
  353. // and get rid of his vertical velocity.
  354. LinkVy = 0;}}
  355. // Otherwise, we're in the air.
  356. else {
  357. LinkBlock = BLOCK_EMPTY;}
  358.  
  359. Link->Jump = 0;
  360. Link->Z = 0;
  361.  
  362. // Gravity.
  363. LinkVy = Min(LinkVy + LINK_GRAV, LINK_TERM);}
  364.  
  365. // Perform a sideview jump.
  366. void SideviewJump() {
  367. Game->PlaySound(SFX_JUMP);
  368. // We're holding down, so only hop.
  369. if (Link->InputDown) {LinkVy = LinkHop;}
  370. // Otherwise do the full jump.
  371. else {LinkVy = LinkJump;}}
  372.  
  373. // Jump according to custom mode rules.
  374. void LinkCustomJump() {
  375. if (// The Jump button is pressed.
  376. PressJump &&
  377. // Can't jump in the air.
  378. LinkBlock != BLOCK_EMPTY &&
  379. // Must have positive y velocity.
  380. LinkVy >= 0 &&
  381. // Can't be doing anything but walking.
  382. (Link->Action == LA_NONE || Link->Action == LA_WALKING)) {
  383. // Jump!
  384. SideviewJump();}}
  385.  
  386. // Check if we need to get onto stairs from custom mode.
  387. void LinkCustomMountStair() {
  388. // We never get on a stair unless we're standing on something.
  389. if (LinkBlock == BLOCK_EMPTY) {return;}
  390.  
  391. // We must have a positive or 0 y velocity.
  392. if (LinkVy < 0) {return;}
  393.  
  394. // We're moving up-left, so check an up-left going stair on the same
  395. // tile as Link.
  396. if (Link->InputLeft && Link->InputUp && IsPosStair(LinkX, LinkY + 15)) {
  397. MountStair(LinkX, LinkY + 15, STAIR_POS);
  398. StairPos = STAIR_BOTTOM;}
  399.  
  400. // We're moving up-right, so check an up-right going stair on the same
  401. // tile as Link.
  402. else if (Link->InputRight && Link->InputUp &&
  403. IsNegStair(LinkX + 15, LinkY + 15)) {
  404. MountStair(LinkX + 15, LinkY + 15, STAIR_NEG);
  405. StairPos = STAIR_BOTTOM;}
  406.  
  407. // We're moving down-left, so check a down-left going stair on the
  408. // tile below Link.
  409. if (Link->InputLeft && Link->InputDown && IsNegStair(LinkX + 2, LinkY + 18)) {
  410. MountStair(LinkX + 2, LinkY + 18, STAIR_NEG);
  411. StairPos = STAIR_TOP;}
  412.  
  413. // We're moving down-right, so check a down-right going stair on the
  414. // tile below Link.
  415. if (Link->InputRight && Link->InputDown &&
  416. IsPosStair(LinkX + 13, LinkY + 18)) {
  417. MountStair(LinkX + 13, LinkY + 18, STAIR_POS);
  418. StairPos = STAIR_TOP;}}
  419.  
  420. // Causes Link to mount the stair at the given position.
  421. // Returns true if the stair was mounted.
  422. bool MountStair(int x, int y, int mode) {
  423.  
  424. // First, make sure there's actually a stair there.
  425. int start = (y & 240) + (x >> 4);
  426. if (x < 0 || x >= 256 || y < 0 || y >= 176 || !IsStair(start)) {
  427. LinkMode = LINK_MODE_CUSTOM;
  428. StairMode = STAIR_NONE;
  429. return false;}
  430.  
  431. // Change to stair movement mode.
  432. LinkMode = LINK_MODE_STAIR;
  433. StairMode = mode;
  434. StairLoc = ComboAt(x, y);
  435.  
  436. // Mark the stairs being mounted this frame.
  437. StairMount = true;
  438.  
  439. // Set the Y offset.
  440. x = ComboX(start);
  441. y = ComboY(start);
  442.  
  443. StairY =
  444. // Start with the y position of the stair combo.
  445. y
  446. // Move to 1 cell above it.
  447. - 16
  448. // Adjust for the x position of the stair combo in the stair direction.
  449. - x * StairMode;
  450.  
  451. return true;}
  452.  
  453. void Stair_Update1() {
  454. StairMount = false;}
  455.  
  456. // Adjust Link's position if the screen changed.
  457. void LinkStairOnScreenChange() {
  458. if (ScreenChangeHandled) {return;}
  459.  
  460. int stairTX = StairLoc % 16;
  461. int stairTY = StairLoc >> 4;
  462.  
  463. LinkUpdateOldOnScreenChange();
  464.  
  465. // If we walked off the top of the screen.
  466. if (ScreenChangeDir == DIR_UP) {
  467. int adjust = (StairLoc >> 4) + 1;
  468. stairTX -= adjust * StairMode;
  469. stairTY = 10;
  470. StairLoc = FindLoc(stairTX, stairTY);
  471. LinkX = (stairTX + StairMode) * 16;
  472. LinkY = 160;}
  473.  
  474. // We walked off the bottom of the screen.
  475. else if (ScreenChangeDir == DIR_DOWN) {
  476. int adjust = 11 - stairTY;
  477. // First check if there is actually a stair on the top of the new screen.
  478. int loc = FindLoc(stairTX + StairMode * adjust, 0);
  479. if (!IsValidStair(loc)) {
  480. // If there isn't then just set Link's X to where that stair would be.
  481. LinkX = ComboX(loc);
  482. StairLoc = -1;}
  483. // If there is, proceed as normal.
  484. else {
  485. stairTX += 2 * StairMode;
  486. stairTY = 1;
  487. StairLoc = FindLoc(stairTX, stairTY);
  488. LinkX = stairTX * 16;}
  489. LinkY = 0;}
  490.  
  491. // We walked off the left edge of the screen. Make sure that the
  492. // stairs actually reached all the way to the left as well.
  493. else if (ScreenChangeDir == DIR_LEFT &&
  494. (// If we were on the edge stair, then we know it existed.
  495. stairTX == 0 ||
  496. // Check above or below based on stair direction
  497. Cond(StairMode == STAIR_POS, StairAbove, StairBelow))) {
  498. stairTX = 15;
  499. // How far away the stair we're anchored to is from the wall.
  500. int adjust = (StairLoc % 16) + 1;
  501. stairTY -= adjust * StairMode;
  502. StairLoc = FindLoc(stairTX, stairTY);
  503. LinkX = 240;
  504. LinkY = (stairTY - 1) * 16;
  505. // If there isn't a valid stair there, and we were moving up, then
  506. // move Link down a tile, because he never climbed it while the
  507. // screen was scrolling.
  508. if (StairMode == STAIR_POS && !IsValidStair(StairLoc)) {
  509. LinkY += 16;}}
  510.  
  511. // We walked off the right edge of the screen. Make sure that the
  512. // stairs actually reached all the way to the right as well.
  513. else if (ScreenChangeDir == DIR_RIGHT &&
  514. (// If we were on the edge stair, then we know it existed.
  515. stairTX == 15 ||
  516. // Check above or below based on stair direction
  517. Cond(StairMode == STAIR_POS, StairBelow, StairAbove))) {
  518. stairTX = 0;
  519. // How far away the stair we're anchored to is from the wall.
  520. int adjust = 16 - (StairLoc % 16);
  521. stairTY += adjust * StairMode;
  522. StairLoc = FindLoc(stairTX, stairTY);
  523. LinkX = 0;
  524. LinkY = (stairTY - 1) * 16;
  525. // If there isn't a valid stair there, and we were moving up, then
  526. // move Link down a tile, because he never climbed it while the
  527. // screen was scrolling.
  528. if (StairMode == STAIR_NEG && !IsValidStair(StairLoc)) {
  529. LinkY += 16;}}
  530.  
  531. // Otherwise, cancel stairs.
  532. else {
  533. LinkX = Link->X;
  534. LinkY = Link->Y;
  535. StairMode = STAIR_NONE;
  536. LinkMode = LINK_MODE_CUSTOM;}
  537.  
  538. if (StairMode != STAIR_NONE) {
  539. MountStair(stairTX << 4, stairTY << 4, StairMode);}
  540.  
  541. ScreenChangeHandled = true;}
  542.  
  543. // Update Link's position based on the stair he's on.
  544. void LinkStairUpdatePosition() {
  545. // First, move according to player input.
  546. if (// We can only move if we're standing still or walking.
  547. Link->Action == LA_NONE || Link->Action == LA_WALKING) {
  548. // Then move left or right, but not both.
  549. if (Link->InputLeft) {LinkX -= LINK_WALK;}
  550. else if (Link->InputRight) {LinkX += LINK_WALK;}}
  551.  
  552. // If we're at the top or bottom of the stair, check against running
  553. // into walls.
  554. if (StairPos != STAIR_MIDDLE) {
  555. // Check against running into a wall to the left.
  556. if (// First check that we moved left.
  557. LinkX < OldLinkX &&
  558. // Then check that we're not at the top of a negative stair.
  559. (StairPos != STAIR_TOP || StairMode != STAIR_NEG) &&
  560. (// Then check for hard blocks at Link's top, middle, and bottom.
  561. GetBlockType(LinkX, LinkY) == BLOCK_HARD ||
  562. GetBlockType(LinkX, LinkY + 8) == BLOCK_HARD ||
  563. GetBlockType(LinkX, LinkY + 15) == BLOCK_HARD)) {
  564. // If he hit, move Link right to the next multiple of 8.
  565. LinkX += 8 - (LinkX % 8);}
  566.  
  567. // Check against running into a wall to the right.
  568. if (// First check that we moved right.
  569. LinkX > OldLinkX &&
  570. // Then check that we're not at the top of a positive stair.
  571. (StairPos != STAIR_TOP || StairMode != STAIR_POS) &&
  572. (// Then check for hard blocks at Link's top, middle, and bottom.
  573. GetBlockType(LinkX + 15, LinkY) == BLOCK_HARD ||
  574. GetBlockType(LinkX + 15, LinkY + 8) == BLOCK_HARD ||
  575. GetBlockType(LinkX + 15, LinkY + 15) == BLOCK_HARD)) {
  576. // If he hit, move Link left to the previous multiple of 8.
  577. LinkX &= 0x1FFF8;}}
  578.  
  579. //// Then adjust y positioning.
  580. // If we're at the middle of the stair, use the standard formula.
  581. LinkY = LinkX * StairMode + StairY;
  582.  
  583. // If we're at the bottom, align Link with the anchored stair.
  584. if (StairPos == STAIR_BOTTOM &&
  585. ((StairMode == STAIR_NEG && LinkX <= ComboX(StairLoc) - 16) ||
  586. (StairMode == STAIR_POS && LinkX >= ComboX(StairLoc) + 16))) {
  587. LinkY = ComboY(StairLoc);}
  588. // If we're at the top, align Link with the cell above the anchored stair.
  589. else if (StairPos == STAIR_TOP &&
  590. ((StairMode == STAIR_NEG && LinkX >= ComboX(StairLoc) - 1) ||
  591. (StairMode == STAIR_POS && LinkX <= ComboX(StairLoc) + 1))) {
  592. LinkY = ComboY(StairLoc) - 16;}}
  593.  
  594. // Find the stair that Link is currently standing on.
  595. void LinkStairFindStair() {
  596.  
  597. if (StairLoc == -1) {return;}
  598.  
  599. //// First, check if we've moved off of the stair we're currently anchored to.
  600. // Get the edge closest to the stair.
  601. int x = LinkX + Cond(StairMode == STAIR_POS, 0, 15);
  602. int stairX = ComboX(StairLoc);
  603. int stairTX = StairLoc % 16;
  604. int stairTY = StairLoc >> 4;
  605. // Direction we've shifted.
  606. int shiftDir = 0;
  607. // We've moved off the left side of the stair, so move the StairLoc
  608. // 1 to the left, plus up or down as appropriate.
  609. if (x < stairX) {
  610. stairTX--;
  611. stairTY -= StairMode;
  612. shiftDir = -1;}
  613. // We've moved off the right side of the stair, so move the StairLoc
  614. // 1 to the right, plus up or down as appropriate.
  615. else if (x >= stairX + 16) {
  616. stairTX++;
  617. stairTY += StairMode;
  618. shiftDir = 1;}
  619.  
  620. StairLoc = FindLoc(stairTX, stairTY);
  621. StairPos = STAIR_MIDDLE;
  622.  
  623. // If we found the stairs, but we're on the top edge of a stair (and
  624. // not on the edge of a screen), set to the top edge anyway.
  625. if (IsValidStair(StairLoc) &&
  626. ((StairMode == STAIR_POS && stairTX != 0) ||
  627. (StairMode == STAIR_NEG && stairTX != 15))) {
  628. int aboveLoc = FindLoc(stairTX - StairMode, stairTY - 1);
  629. if (!IsValidStair(aboveLoc)) {
  630. StairPos = STAIR_TOP;}}
  631.  
  632. // Check for a stair to the side.
  633. if (// First, make sure that we didn't already find a stair.
  634. !IsValidStair(StairLoc) &&
  635. // And then also make sure that we didn't shift up the stair,
  636. // because we're shifting up again and a double shift doesn't
  637. // make sense.
  638. shiftDir * StairMode != -1) {
  639. StairLoc = FindLoc(stairTX - StairMode, stairTY - 1);
  640. // If we're on the bottom of the screen, assume there's more
  641. // stairs on the next screen.
  642. if (stairTY - 1 < 10) {
  643. StairPos = STAIR_BOTTOM;}}
  644.  
  645. // Then check for a stair diagonally downward.
  646. if (!IsValidStair(StairLoc)) {
  647. StairLoc = FindLoc(stairTX + StairMode, stairTY + 1);
  648. StairPos = STAIR_TOP;}
  649.  
  650. // Check if we failed.
  651. if (!IsValidStair(StairLoc)) {
  652. StairLoc = -1;
  653. return;}
  654.  
  655. // Set StairLeft and StairRight to the proper values for Link's position.
  656. if (StairPos == STAIR_MIDDLE) {
  657. StairLeft = 0;
  658. StairRight = 255;}
  659. else {
  660. stairTX = StairLoc % 16;
  661. StairLeft = (stairTX - 1) * 16 - 2;
  662. StairRight = (stairTX + 1) * 16 + 2;}
  663.  
  664. // Find if there's a stair above and below.
  665. StairAbove = IsValidStair(FindLoc(stairTX - StairMode, stairTY - 1));
  666. StairBelow = IsValidStair(FindLoc(stairTX + StairMode, stairTY + 1));}
  667.  
  668. // See if Link is leaving the stairs.
  669. void LinkStairFallOff() {
  670. if (// Getting hurt knocks you off of stairs.
  671. Link->Action == LA_GOTHURTLAND || Link->Action == LA_GOTHURTWATER ||
  672. // If we couldn't locate a stair earlier, that means we fall off, too.
  673. StairLoc == -1 ||
  674. // Or if we've moved too far off of the top or bottom of a stair.
  675. LinkX < StairLeft || LinkX > StairRight) {
  676. StairMode = STAIR_NONE;
  677. LinkMode = LINK_MODE_CUSTOM;}}
  678.  
  679. // Jump according to stair mode rules.
  680. void LinkStairJump() {
  681. if (// The Jump button is pressed.
  682. PressJump &&
  683. // Can't be doing anything but walking.
  684. (Link->Action == LA_NONE || Link->Action == LA_WALKING)) {
  685. StairMode = STAIR_NONE;
  686. LinkMode = LINK_MODE_CUSTOM;
  687. // Jump!
  688. SideviewJump();}}
  689.  
  690. // Assigns all the OldLink variables for the upcoming frame.
  691. // Place before Waitdraw().
  692. void OldLink_Update1() {
  693. OldLinkX = Link->X;
  694. OldLinkY = Link->Y;
  695. OldLinkAction = Link->Action;}
  696.  
  697. // Record the current dmap and dscreen right before they are changed.
  698. // Place before Waitdraw().
  699. void ScreenChange_Update1() {
  700. OldDMap = Game->GetCurDMap();
  701. OldDScreen = Game->GetCurDMapScreen();}
  702.  
  703. // Updates information dealing with changing screens.
  704. // Place after Waitdraw(), when the screen changes happen.
  705. void ScreenChange_Update2() {
  706. // Grab current values.
  707. int dMap = Game->GetCurDMap();
  708. int dScreen = Game->GetCurDMapScreen();
  709. // Compare with old values.
  710. DMapChanged = dMap != OldDMap;
  711. ScreenChanged = DMapChanged || dScreen != OldDScreen;
  712.  
  713. // Check for scrolling change to the same screen.
  714. if (Link->Action == LA_SCROLLING) {
  715. if (!ScreenChanged && !_ScreenChanged_ScrollFlag) {
  716. ScreenChanged = true;
  717. _ScreenChanged_ScrollFlag = true;}}
  718. // We're no longer scrolling, so reset scroll flag.
  719. else {
  720. _ScreenChanged_ScrollFlag = false;}
  721.  
  722. // Check for a forced screen change flag.
  723. if (_ScreenChanged_ForceFlag) {
  724. ScreenChanged = true;
  725. _ScreenChanged_ForceFlag = false;}
  726.  
  727. // Find the screen change direction.
  728. if (ScreenChanged) {
  729. // Mark the screen change as needing to be handled.
  730. ScreenChangeHandled = false;
  731. // Try to guess the direction.
  732. if (Link->Y >= 160) {ScreenChangeDir = DIR_UP;}
  733. else if (Link->Y <= 0) {ScreenChangeDir = DIR_DOWN;}
  734. else if (Link->X >= 240) {ScreenChangeDir = DIR_LEFT;}
  735. else if (Link->X <= 0) {ScreenChangeDir = DIR_RIGHT;}
  736. else {ScreenChangeDir = SCREEN_CHANGE_WARP;}}}
  737.  
  738. // Adjust some of Link's variables after all the mechanical
  739. // manipulation is done.
  740. void LinkAdjust() {
  741. // Don't do anything in engine mode.
  742. if (LinkMode == LINK_MODE_ENGINE) {return;}
  743.  
  744. // Update Link's actual position.
  745. Link->X = Round(LinkX);
  746. Link->Y = Round(LinkY);
  747.  
  748. // Force the walking animation if we moved and have no other action.
  749. if (Link->Action == LA_NONE && (LinkX != OldLinkX || LinkY != OldLinkY)) {
  750. Link->Action = LA_WALKING;}
  751.  
  752. // Set the direction according to input.
  753. if (Link->InputUp) {Link->Dir = DIR_UP;}
  754. else if (Link->InputDown) {Link->Dir = DIR_DOWN;}
  755. else if (Link->InputLeft) {Link->Dir = DIR_LEFT;}
  756. else if (Link->InputRight) {Link->Dir = DIR_RIGHT;}}
  757.  
  758. // Don't scroll through items on sideview screens with L.
  759. void Input_Update1() {
  760. // Ignore L if this is a sideview screen.
  761. if (IsSideview()) {
  762. InputJump = Link->InputL;
  763. PressJump = Link->PressL;
  764. Link->InputL = false;
  765. Link->PressL = false;}}
  766.  
  767. // Change the inputs so the engine doesn't set Link facing a weird
  768. // direction or something else we don't want.
  769. void Input_Update2() {
  770.  
  771. // If we're not in engine mode, up and down take preference for
  772. // direction.
  773. if (LinkMode != LINK_MODE_ENGINE &&
  774. (Link->InputUp || Link->InputDown)) {
  775. Link->InputLeft = false;
  776. Link->InputRight = false;
  777. Link->PressLeft = false;
  778. Link->PressRight = false;}}
  779.  
  780. ffc script ScreenChange {
  781. void run() {
  782. _ScreenChanged_ForceFlag = true;}}
  783.  
  784. // Don't carry over velocity or stair state.
  785. global script OnContinue {
  786. void run() {
  787. StairMode = STAIR_NONE;
  788. LinkVy = 0;}}
  789.  
  790. // Set first argument to Link's full jump speed.
  791. // Set second argument to Link's jump speed while holding down.
  792. item script AdjustLinkJump {
  793. void run (int jumpSpeed, int hopSpeed) {
  794. LinkJump = jumpSpeed;
  795. LinkHop = hopSpeed;}}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement