Advertisement
Guest User

Scripts

a guest
May 25th, 2021
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 77.73 KB | None | 0 0
  1. import "std.zh"
  2.  
  3. import "ffcscript.zh"
  4.  
  5. import "ghost.zh"
  6.  
  7.  
  8. //Global Scripts
  9.  
  10. //%MGSO% DECLARATION ScrollingBackgrounds
  11. //%MGSO% DECLARATION MovingPlatforms
  12. //%MGSO% DECLARATION MooshPit
  13. //%MGSO% DECLARATION Confusion
  14. //%MGSO% DECLARATION SolidFFC
  15. //%MGSO% DECLARATION BombArrow
  16.  
  17. //%MGSO% HEADER_START ScrollingBackgrounds
  18.  
  19. const int SCROLLINGLAYER_LINKSTEP = 1.5; //Link's step speed
  20. const int SCROLLINGLAYER_FASTSCROLLING = 1; //Set to 1 if Very Fast Scrolling is enabled
  21. const int SCROLLINGLAYER_DEBUG = 0; //Set to 1 to show positions of onscreen layers
  22.  
  23. int ScrollingBG[112]; //Size should be at least _SBG_START + 6 * _SBG_BLOCK
  24.  
  25. //Global array indices
  26. const int _SBG_LINKX = 0;
  27. const int _SBG_LINKY = 1;
  28. const int _SBG_SCROLLDIR = 2;
  29. const int _SBG_SCROLLCOUNTER = 3;
  30.  
  31. //Start index of the 2D part of the global array and block size
  32. const int _SBG_START = 16;
  33. const int _SBG_BLOCK = 16;
  34.  
  35. //Indices for scrolling layer properties
  36. const int _SBG_X = 0;
  37. const int _SBG_Y = 1;
  38. const int _SBG_XSTEP = 2;
  39. const int _SBG_YSTEP = 3;
  40. const int _SBG_MAP = 4;
  41. const int _SBG_SCREEN = 5;
  42. const int _SBG_LAYER = 6;
  43. const int _SBG_WIDTH = 7;
  44. const int _SBG_HEIGHT = 8;
  45. const int _SBG_OPACITY = 9;
  46. const int _SBG_FLAGS = 10;
  47. const int _SBG_DMAP = 11;
  48.  
  49. //Flag constants
  50. const int _SBGF_NORESET = 00000001b;
  51. const int _SBGF_NOPOSITION = 00000010b;
  52. const int _SBGF_TRACKX = 00000100b;
  53. const int _SBGF_TRACKY = 00001000b;
  54. const int _SBGF_TRACKXSCROLL = 00010000b;
  55. const int _SBGF_TRACKYSCROLL = 00100000b;
  56. const int _SBGF_FORCEDRAWSCREEN = 01000000b;
  57.  
  58.  
  59. void ScrollingBG_Init(){
  60. int i; int j; int k;
  61. for(i=0; i<6; ++i){
  62. j = _SBG_START+i*_SBG_BLOCK;
  63. //If the layer hasn't been assigned by an FFC this frame, clear it on F6
  64. if(!(ScrollingBG[j+_SBG_FLAGS]&_SBGF_NORESET)){
  65. for(k=0; k<_SBG_BLOCK; ++k){
  66. ScrollingBG[j+k] = 0;
  67. }
  68. }
  69. }
  70.  
  71. ScrollingBG[_SBG_LINKX] = Link->X;
  72. ScrollingBG[_SBG_LINKY] = Link->Y;
  73. ScrollingBG[_SBG_SCROLLDIR] = -1;
  74. ScrollingBG[_SBG_SCROLLCOUNTER] = 0;
  75. }
  76.  
  77. void ScrollingBG_Update(){
  78. int i; int j; int k;
  79.  
  80. int x; int y; int w; int h;
  81. bool trackLinkX; bool trackScrollX;
  82. bool trackLinkY; bool trackScrollY;
  83.  
  84. int dX = (Link->X-ScrollingBG[_SBG_LINKX])/SCROLLINGLAYER_LINKSTEP;
  85. int dY = (Link->Y-ScrollingBG[_SBG_LINKY])/SCROLLINGLAYER_LINKSTEP;
  86. ScrollingBG[_SBG_LINKX] = Link->X;
  87. ScrollingBG[_SBG_LINKY] = Link->Y;
  88.  
  89. if(Link->Action==LA_SCROLLING){
  90. if(ScrollingBG[_SBG_SCROLLDIR]==-1){
  91. if(Link->Y>160)
  92. ScrollingBG[_SBG_SCROLLDIR] = DIR_UP;
  93. else if(Link->Y<0)
  94. ScrollingBG[_SBG_SCROLLDIR] = DIR_DOWN;
  95. else if(Link->X>240)
  96. ScrollingBG[_SBG_SCROLLDIR] = DIR_LEFT;
  97. else
  98. ScrollingBG[_SBG_SCROLLDIR] = DIR_RIGHT;
  99.  
  100. ScrollingBG[_SBG_SCROLLCOUNTER] = 0;
  101. }
  102. else
  103. ++ScrollingBG[_SBG_SCROLLCOUNTER];
  104. }
  105. else
  106. ScrollingBG[_SBG_SCROLLDIR] = -1;
  107.  
  108. for(i=0; i<6; ++i){
  109. j = _SBG_START+i*_SBG_BLOCK;
  110. if(ScrollingBG[j+_SBG_OPACITY]&&ScrollingBG[j+_SBG_DMAP]==Game->GetCurDMap()&&Game->GetCurScreen()<0x7F){
  111. if(ScrollingBG[j+_SBG_FLAGS]&_SBGF_TRACKX)
  112. trackLinkX = true;
  113. if(ScrollingBG[j+_SBG_FLAGS]&_SBGF_TRACKY)
  114. trackLinkY = true;
  115. if(ScrollingBG[j+_SBG_FLAGS]&_SBGF_TRACKXSCROLL)
  116. trackScrollX = true;
  117. if(ScrollingBG[j+_SBG_FLAGS]&_SBGF_TRACKYSCROLL)
  118. trackScrollY = true;
  119.  
  120. w = 256*ScrollingBG[j+_SBG_WIDTH];
  121. h = 176*ScrollingBG[j+_SBG_HEIGHT];
  122.  
  123. //Process scrolling animation
  124. //X-axis
  125. if(ScrollingBG_IsScrolling()){
  126. //During the scroll animation, move the background if set to track scrolling
  127. if(trackScrollX){
  128. if(ScrollingBG[_SBG_SCROLLDIR]==DIR_LEFT)
  129. ScrollingBG[j+_SBG_X] -= ScrollingBG[j+_SBG_XSTEP];
  130. else if(ScrollingBG[_SBG_SCROLLDIR]==DIR_RIGHT)
  131. ScrollingBG[j+_SBG_X] += ScrollingBG[j+_SBG_XSTEP];
  132. }
  133. //Scroll automatically if neither Link nor scrolling are being tracked
  134. else if(!trackLinkX){
  135. ScrollingBG[j+_SBG_X] += ScrollingBG[j+_SBG_XSTEP];
  136. }
  137. }
  138. else{
  139. //Only move when Link does if tracking him
  140. if(trackLinkX){
  141. ScrollingBG[j+_SBG_X] += ScrollingBG[j+_SBG_XSTEP]*dX;
  142. }
  143. else if(!trackScrollX)
  144. ScrollingBG[j+_SBG_X] += ScrollingBG[j+_SBG_XSTEP];
  145. }
  146. //Y-axis
  147. if(ScrollingBG_IsScrolling()){
  148. //During the scroll animation, move the background if set to track scrolling
  149. if(trackScrollY){
  150. if(ScrollingBG[_SBG_SCROLLDIR]==DIR_UP)
  151. ScrollingBG[j+_SBG_Y] -= ScrollingBG[j+_SBG_YSTEP];
  152. else if(ScrollingBG[_SBG_SCROLLDIR]==DIR_DOWN)
  153. ScrollingBG[j+_SBG_Y] += ScrollingBG[j+_SBG_YSTEP];
  154. }
  155. //Scroll automatically if neither Link nor scrolling are being tracked
  156. else if(!trackLinkY){
  157. ScrollingBG[j+_SBG_Y] += ScrollingBG[j+_SBG_YSTEP];
  158. }
  159. }
  160. else{
  161. //Only move when Link does if tracking him
  162. if(trackLinkY){
  163. ScrollingBG[j+_SBG_Y] += ScrollingBG[j+_SBG_YSTEP]*dY;
  164. }
  165. else if(!trackScrollX)
  166. ScrollingBG[j+_SBG_Y] += ScrollingBG[j+_SBG_YSTEP];
  167. }
  168.  
  169. //Keep the X and Y positions of the background wrapped based on size
  170. if(ScrollingBG[j+_SBG_X]<0)
  171. ScrollingBG[j+_SBG_X] += w;
  172. if(ScrollingBG[j+_SBG_X]>=w)
  173. ScrollingBG[j+_SBG_X] -= w;
  174.  
  175. if(ScrollingBG[j+_SBG_Y]<0)
  176. ScrollingBG[j+_SBG_Y] += h;
  177. if(ScrollingBG[j+_SBG_Y]>=h)
  178. ScrollingBG[j+_SBG_Y] -= h;
  179.  
  180. x = Floor(ScrollingBG[j+_SBG_X]);
  181. y = Floor(ScrollingBG[j+_SBG_Y]);
  182.  
  183. ScrollingBG_DrawLayer(ScrollingBG[j+_SBG_LAYER], ScrollingBG[j+_SBG_MAP], ScrollingBG[j+_SBG_SCREEN], x, y, ScrollingBG[j+_SBG_WIDTH], ScrollingBG[j+_SBG_HEIGHT], ScrollingBG[j+_SBG_OPACITY], ScrollingBG[j+_SBG_FLAGS]&_SBGF_FORCEDRAWSCREEN);
  184.  
  185. if(SCROLLINGLAYER_DEBUG){
  186. Screen->DrawInteger(6, 24*i, 0, FONT_Z3SMALL, 0x01, 0x0F, -1, -1, x, 0, 128);
  187. Screen->DrawInteger(6, 24*i, 8, FONT_Z3SMALL, 0x01, 0x0F, -1, -1, y, 0, 128);
  188. }
  189. }
  190.  
  191. //Unmark flags telling the global not to reset it and the FFC not to reposition it
  192. if(ScrollingBG[j+_SBG_FLAGS]&_SBGF_NORESET)
  193. ScrollingBG[j+_SBG_FLAGS] &= ~_SBGF_NORESET;
  194. if(ScrollingBG[j+_SBG_FLAGS]&_SBGF_NOPOSITION)
  195. ScrollingBG[j+_SBG_FLAGS] &= ~_SBGF_NOPOSITION;
  196. }
  197. }
  198.  
  199. bool ScrollingBG_IsScrolling(){
  200. int xFrames = 64;
  201. int yFrames = 44;
  202. if(SCROLLINGLAYER_FASTSCROLLING){
  203. xFrames = 16;
  204. yFrames = 11;
  205. }
  206. if(ScrollingBG[_SBG_SCROLLDIR]>-1&&ScrollingBG[_SBG_SCROLLCOUNTER]>0){
  207. if(ScrollingBG[_SBG_SCROLLDIR]<2&&ScrollingBG[_SBG_SCROLLCOUNTER]<yFrames+1)
  208. return true;
  209. if(ScrollingBG[_SBG_SCROLLDIR]>=2&&ScrollingBG[_SBG_SCROLLCOUNTER]<xFrames+1)
  210. return true;
  211. }
  212. return false;
  213. }
  214.  
  215. void ScrollingBG_DrawLayer(int layer, int srcMap, int srcScreen, int x, int y, int w, int h, int op, bool forceDrawScreen){
  216. int i;
  217. bool useDrawScreen;
  218. if(forceDrawScreen)
  219. useDrawScreen = true;
  220. //While scrolling, avoid using DrawLayer on negative layers. ZC does not like this.
  221. if(op==128&&Link->Action==LA_SCROLLING){
  222. if(layer==2&&ScreenFlag(SF_VIEW, 4))
  223. useDrawScreen = true;
  224. if(layer==3&&ScreenFlag(SF_VIEW, 5))
  225. useDrawScreen = true;
  226. }
  227.  
  228. int tmpScreen;
  229. int scrnX;
  230. int scrnY;
  231.  
  232. for(i=0; i<4; ++i){
  233. scrnX = Floor(x/256)+(i%2);
  234. scrnY = Floor(y/176)+Floor(i/2);
  235.  
  236. if(scrnX<0)
  237. scrnX += w;
  238. if(scrnX>w-1)
  239. scrnX -= w;
  240. if(scrnY<0)
  241. scrnY += h;
  242. if(scrnY>h-1)
  243. scrnY -= h;
  244.  
  245. tmpScreen = srcScreen+scrnX+scrnY*16;
  246. if(useDrawScreen)
  247. Screen->DrawScreen(layer, srcMap, tmpScreen, -(x%256)+256*(i%2), -(y%176)+176*Floor(i/2), 0);
  248. else
  249. Screen->DrawLayer(layer, srcMap, tmpScreen, 0, -(x%256)+256*(i%2), -(y%176)+176*Floor(i/2), 0, op);
  250. }
  251. }
  252.  
  253. //This FFC script is placed on the screen to assign or unassign a scrolling layer for the current DMap
  254. //D0: Which of the simultaneous scrolling layers to assign (0-5)
  255. //D1: Layer to draw to
  256. //D2: Source Map for the layer
  257. //D3: Source Screen for the layer (in decimal)
  258. //D4: X speed for the layer
  259. //D5: Y speed for the layer
  260. //D6: Opacity for the layer (0 to clear, 64 for transparent, 128 for opaque)
  261. //D7: Sum of all of these flags you want to use
  262. // 1 - Track Link when walking on the X axis
  263. // 2 - Track Link when walking on the Y axis
  264. // 4 - Track Link when scrolling on the X axis
  265. // 8 - Track Link when scrolling on the Y axis
  266. // 16 - Use 2x2 screen block
  267. // 32 - Use 3x3 screen block
  268. // 64 - Use 4x4 screen block
  269. // 128 - Always use drawscreen (slow)
  270. ffc script ScrollingLayer_Assign{
  271. void run(int whichScrollingLayer, int drawLayer, int srcMap, int srcScreen, int xStep, int yStep, int opacity, int flags){
  272. whichScrollingLayer = Clamp(whichScrollingLayer, 0, 5);
  273.  
  274. int width = 1;
  275. if(flags&16)
  276. width = 2;
  277. if(flags&32)
  278. width = 3;
  279. if(flags&64)
  280. width = 4;
  281.  
  282. //Get the starting array index for the scrolling layer block
  283. int i = _SBG_START+whichScrollingLayer*_SBG_BLOCK;
  284. int j;
  285.  
  286. //This runs twice because of script order shenanigans. Hooraaaay! Script order!
  287. for(j=0; j<2; ++j){
  288. if(opacity!=0&&(ScrollingBG[i+_SBG_OPACITY]&&ScrollingBG[i+_SBG_DMAP]==Game->GetCurDMap())){
  289. Waitframe();
  290. continue;
  291. }
  292.  
  293. //Assign that stuff
  294. if(!(ScrollingBG[i+_SBG_FLAGS]&_SBGF_NOPOSITION)){
  295. ScrollingBG[i+_SBG_X] = 0;
  296. ScrollingBG[i+_SBG_Y] = 0;
  297. ScrollingBG[i+_SBG_WIDTH] = width;
  298. ScrollingBG[i+_SBG_HEIGHT] = width;
  299. }
  300. ScrollingBG[i+_SBG_XSTEP] = xStep;
  301. ScrollingBG[i+_SBG_YSTEP] = yStep;
  302. ScrollingBG[i+_SBG_MAP] = srcMap;
  303. ScrollingBG[i+_SBG_SCREEN] = srcScreen;
  304. ScrollingBG[i+_SBG_LAYER] = drawLayer;
  305. ScrollingBG[i+_SBG_OPACITY] = opacity;
  306.  
  307. //Assign the flag that tells the global not to reset this index, as well as any others specified
  308. ScrollingBG[i+_SBG_FLAGS] = _SBGF_NORESET;
  309. if(flags&1)
  310. ScrollingBG[i+_SBG_FLAGS] |= _SBGF_TRACKX;
  311. if(flags&2)
  312. ScrollingBG[i+_SBG_FLAGS] |= _SBGF_TRACKY;
  313. if(flags&4)
  314. ScrollingBG[i+_SBG_FLAGS] |= _SBGF_TRACKXSCROLL;
  315. if(flags&8)
  316. ScrollingBG[i+_SBG_FLAGS] |= _SBGF_TRACKYSCROLL;
  317. if(flags&128)
  318. ScrollingBG[i+_SBG_FLAGS] |= _SBGF_FORCEDRAWSCREEN;
  319.  
  320. ScrollingBG[i+_SBG_DMAP] = Game->GetCurDMap();
  321.  
  322. Quit();
  323. }
  324. }
  325. }
  326.  
  327. //This FFC script is placed on the screen to change the position of an assigned layer (because the last script ran out of arguments)
  328. //D0: Which of the simultaneous scrolling layers to assign (0-5)
  329. //D1: X position to set the layer to
  330. //D2: Y position to set the layer to
  331. //D3: Width to set the layer to (overrides flags used by the previous script)
  332. //D4: Height to set the layer to (overrides flags used by the previous script)
  333. ffc script ScrollingLayer_Reposition{
  334. void run(int whichScrollingLayer, int x, int y, int newW, int newH){
  335. whichScrollingLayer = Clamp(whichScrollingLayer, 0, 5);
  336. newW = Clamp(newW, 0, 16);
  337. newH = Clamp(newH, 0, 8);
  338.  
  339. //Get the starting array index for the scrolling layer block
  340. int i = _SBG_START+whichScrollingLayer*_SBG_BLOCK;
  341. int j;
  342.  
  343. int w = ScrollingBG[i+_SBG_WIDTH]*256;
  344. int h = ScrollingBG[i+_SBG_HEIGHT]*176;
  345.  
  346. //This runs twice because of script order shenanigans. Hooraaaay! Script order!
  347. for(j=0; j<2; ++j){
  348. if(!ScrollingBG[i+_SBG_OPACITY]||ScrollingBG[i+_SBG_FLAGS]&_SBGF_NORESET){
  349. if(newW&&newH){
  350. ScrollingBG[i+_SBG_WIDTH] = newW;
  351. ScrollingBG[i+_SBG_HEIGHT] = newH;
  352. w = ScrollingBG[i+_SBG_WIDTH]*256;
  353. h = ScrollingBG[i+_SBG_HEIGHT]*176;
  354. }
  355.  
  356. while(x<0)
  357. x += w;
  358. while(x>=w)
  359. x -= w;
  360. while(y<0)
  361. y += h;
  362. while(y>=h)
  363. y -= h;
  364.  
  365. ScrollingBG[i+_SBG_X] = x;
  366. ScrollingBG[i+_SBG_Y] = y;
  367.  
  368. //Flag that the ScrollingLayer_Assign script shouldn't reset the layer's position, if this one comes first
  369. ScrollingBG[i+_SBG_FLAGS] |= _SBGF_NOPOSITION;
  370. Quit();
  371. }
  372.  
  373. Waitframe();
  374. }
  375. }
  376. }
  377. //%MGSO% HEADER_END ScrollingBackgrounds
  378.  
  379. //%MGSO% HEADER_START MovingPlatforms
  380.  
  381. ///Constants and Variables used by platform script;
  382. const int DIAGONAL_MOVEMENT = 0; //Enable the option and change this to 0 for nes movement.
  383. int onplatform; //Global variable use this to check if Link is on a platform for other scripts.
  384.  
  385.  
  386. void NesMovementFix()
  387. {
  388. if(DIAGONAL_MOVEMENT==0 && (Link->InputUp || Link->InputDown))
  389. {
  390. Link->InputLeft = false;
  391. Link->InputRight = false;
  392. }
  393. }
  394.  
  395. void MovingPlatforms()
  396. {
  397. onplatform = 0;
  398. if(Link->Z == 0)
  399. {
  400. int buffer[] = "movingplatform";
  401. for(int i = 1; i <= 32; i++)
  402. {
  403. ffc f = Screen->LoadFFC(i);
  404. if(f->Script != Game->GetFFCScript(buffer)) continue;
  405. if(Abs(Link->X + 8 - CenterX(f)) >= f->TileWidth*8) continue;
  406. if(Abs(Link->Y + 12 - CenterY(f)) >= f->TileHeight*8) continue;
  407. onplatform = FFCNum(f);
  408. break;
  409. }
  410. }
  411. }
  412.  
  413. ffc script MovingPlatform
  414. {
  415. void run()
  416. {
  417. float oldx = this->X;
  418. float oldy = this->Y;
  419. float linkx;
  420. float linky;
  421. while(true)
  422. {
  423. if(onplatform == FFCNum(this))
  424. {
  425. linkx += this->X - oldx;
  426. linky += this->Y - oldy;
  427. if(linkx << 0 != 0)
  428. {
  429. Link->X += linkx << 0;
  430. linkx -= linkx << 0;
  431. }
  432. if(linky << 0 != 0)
  433. {
  434. Link->Y += linky << 0;
  435. linky -= linky << 0;
  436. }
  437. }
  438. else
  439. {
  440. linkx = 0;
  441. linky = 0;
  442. }
  443. oldx = this->X;
  444. oldy = this->Y;
  445. Waitframe();
  446. }
  447. }
  448. }
  449. //%MGSO% HEADER_END MovingPlatforms
  450.  
  451. //%MGSO% HEADER_START MooshPit
  452.  
  453. int MooshPit[16];
  454. const int _MP_LASTX = 0;
  455. const int _MP_LASTY = 1;
  456. const int _MP_LASTDMAP = 2;
  457. const int _MP_LASTSCREEN = 3;
  458. const int _MP_ENTRYX = 4;
  459. const int _MP_ENTRYY = 5;
  460. const int _MP_ENTRYDMAP = 6;
  461. const int _MP_ENTRYSCREEN = 7;
  462. const int _MP_FALLX = 8;
  463. const int _MP_FALLY = 9;
  464. const int _MP_FALLTIMER = 10;
  465. const int _MP_FALLSTATE = 11;
  466. const int _MP_DAMAGETYPE = 12;
  467. const int _MP_SLIDETIMER = 13;
  468.  
  469. const int MOOSHPIT_NO_GRID_SNAP = 0; //Set to 1 to prevent Link's falling sprite from snapping to the combo grid.
  470. const int MOOSHPIT_ENABLE_SLIDEYPITS = 0; //Set to 1 if Link should slide into pits he's partially on
  471. const int MOOSHPIT_NO_MOVE_WHILE_FALLING = 1; //Set to 1 if you don't want Link able to move while falling
  472. const int MOOSHPIT_NO_REENTER_STAIRS = 1; //Set to 1 to prevent Link reentering stairs when respawning from a pit. This uses an FFC slot to run the script
  473. const int MOOSHPIT_STUN_ENEMIES_WHILE_FALLING = 1; //Set to 1 to stun stunnable enemies while falling in a pit
  474.  
  475. const int CT_HOLELAVA = 128; //Combo type for pits (No Ground Enemies by default)
  476. const int CF_LAVA = 98; //Combo flag marking pits as lava (Script 1 by default)
  477.  
  478. const int SPR_FALLHOLE = 100; //Sprite for Link falling in a hole
  479. const int SPR_FALLLAVA = 89; //Sprite for Link falling in lava
  480.  
  481. const int SFX_FALLHOLE = 38; //Sound for falling in a hole
  482. const int SFX_FALLLAVA = 13; //Sound for falling in lava
  483.  
  484. const int DAMAGE_FALLHOLE = 8; //How much damage pits deal (1/2 heart default)
  485. const int DAMAGE_FALLLAVA = 16; //How much damage lava deals (1 heart default)
  486.  
  487. const int FFC_MOOSHPIT_AUTOWARPA = 32; //FFC that turns into an auto side warp combo when you fall in a pit
  488. const int CMB_MOOSHPIT_AUTOWARPA = 875; //Combo number of an invisible Auto Side Warp A combo
  489. const int SF_MISC_MOOSHPITWARP = 2; //Number of the screen flag under the Misc. section that makes pits warp (Script 1 by default)
  490. //All pit warps use Side Warp A
  491.  
  492. const int MOOSHPIT_MIN_FALL_TIME = 60; //Minimum time for the pit's fall animation, to prevent repeated falling in pits
  493. const int MOOSHPIT_EXTRA_FALL_TIME = 0; //Extra frames at the end of the falling animation before Link respawns
  494.  
  495. //Width and height of Link's hitbox for colliding with pits
  496. const int MOOSHPIT_LINKHITBOXWIDTH = 2;
  497. const int MOOSHPIT_LINKHITBOXHEIGHT = 2;
  498.  
  499. //Width and height of Link's hitbox for colliding with pits/lava in sideview
  500. const int MOOSHPIT_SIDEVIEW_LINKHITBOXWIDTH = 2;
  501. const int MOOSHPIT_SIDEVIEW_LINKHITBOXHEIGHT = 2;
  502.  
  503. const int MOOSHPIT_SLIDEYPIT_FREQ = 3; //Link will be pushed into slideypits every 1/n frames
  504. const int MOOSHPIT_SLIDEYPIT_MAXTIME = 20; //Link will be pushed into slideypits more intensely after n frames
  505. const int MOOSHPIT_SLIDEYPIT_ACCELFREQ = 8; //How often Link accelerates when falling in the pit
  506.  
  507. int MooshPit_OnPit(int LinkX, int LinkY, bool countFFCs){
  508. if(Link->Action==LA_FROZEN||Link->Action==LA_RAFTING||Link->Action==LA_INWIND)
  509. return -1;
  510.  
  511. if(countFFCs){
  512. if(MooshPit_OnFFC(LinkX, LinkY))
  513. return -1;
  514. }
  515.  
  516. bool sideview;
  517. if(Screen->Flags[SF_ROOMTYPE]&100b)
  518. sideview = true;
  519. //wew lad
  520. int width = MOOSHPIT_LINKHITBOXWIDTH;
  521. int height = MOOSHPIT_LINKHITBOXHEIGHT;
  522.  
  523. int total;
  524. int solidTotal;
  525.  
  526. for(int x=0; x<=1; x++){
  527. for(int y=0; y<=1; y++){
  528. int X; int Y;
  529. if(sideview){ //Hitbox functions differently in sideview
  530. width = MOOSHPIT_SIDEVIEW_LINKHITBOXWIDTH;
  531. height = MOOSHPIT_SIDEVIEW_LINKHITBOXHEIGHT;
  532. X = Floor(LinkX+7-width/2+(width-1)*x)+1;
  533. Y = Floor(LinkY+7-height/2+(height-1)*y)+1;
  534. }
  535. else{
  536. X = Floor(LinkX+7-width/2+(width-1)*x)+1;
  537. Y = Floor(LinkY+11-height/2+(height-1)*y)+1;
  538. }
  539.  
  540. //If one corner of Link's hitbox is on a pit, flag that corner as covered
  541. if(Screen->ComboT[ComboAt(X, Y)]==CT_HOLELAVA){
  542. total |= 1<<(1+(x+y*2));
  543. }
  544. //If Link is on a solid combo, count that corner as a pit
  545. if(Screen->isSolid(X, Y)){
  546. solidTotal |= 1<<(x+y*2);
  547. }
  548. }
  549. }
  550. if(total>0) //Assuming Link is on at least one actual pit, add up the solid and nonsolid pits
  551. return (total>>1)|(solidTotal<<4);
  552. return -1;
  553. }
  554.  
  555. bool MooshPit_OnFFC(int LinkX, int LinkY){
  556. for(int i=1; i<=32; i++){ //Cycle through every FFC
  557. ffc f = Screen->LoadFFC(i);
  558. //Check if the FFC is solid
  559. if(f->Data>0&&!f->Flags[FFCF_CHANGER]&&!f->Flags[FFCF_ETHEREAL]){
  560. //Check if Link collides with the FFC
  561. if(RectCollision(LinkX+4, LinkY+9, LinkX+11, LinkY+14, f->X, f->Y, f->X+f->EffectWidth-1, f->Y+f->EffectHeight-1)){
  562. return true;
  563. }
  564. }
  565. }
  566. //If Link doesn't collide with any FFC, return false
  567. return false;
  568. }
  569.  
  570. void MooshPit_StunEnemies(){
  571. for(int i=Screen->NumNPCs(); i>=1; i--){ //Cycle through every enemy
  572. npc n = Screen->LoadNPC(i);
  573. //Make it so the enemy's stun never falls below 1
  574. n->Stun = Max(n->Stun, 1);
  575. }
  576. }
  577.  
  578. void MooshPit_Init(){
  579. MooshPit[_MP_LASTX] = Link->X;
  580. MooshPit[_MP_LASTY] = Link->Y;
  581. MooshPit[_MP_LASTDMAP] = Game->GetCurDMap();
  582. MooshPit[_MP_LASTSCREEN] = Game->GetCurDMapScreen();
  583. MooshPit[_MP_ENTRYX] = Link->X;
  584. MooshPit[_MP_ENTRYY] = Link->Y;
  585. MooshPit[_MP_ENTRYDMAP] = Game->GetCurDMap();
  586. MooshPit[_MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  587. MooshPit[_MP_FALLSTATE] = 0;
  588. MooshPit[_MP_FALLTIMER] = 0;
  589. Link->CollDetection = true;
  590. Link->Invisible = false;
  591. }
  592.  
  593. void MooshPit_Update(){
  594. int i;
  595. bool isWarp;
  596. if(Screen->Flags[SF_MISC]&(1<<SF_MISC_MOOSHPITWARP))
  597. isWarp = true;
  598.  
  599. bool sideview;
  600. if(Screen->Flags[SF_ROOMTYPE]&100b)
  601. sideview = true;
  602.  
  603. if(Link->Action!=LA_SCROLLING){
  604. //Update the entry point whenever the screen changes
  605. if(MooshPit[_MP_ENTRYDMAP]!=Game->GetCurDMap()||MooshPit[_MP_ENTRYSCREEN]!=Game->GetCurDMapScreen()){
  606. MooshPit[_MP_ENTRYX] = Link->X;
  607. MooshPit[_MP_ENTRYY] = Link->Y;
  608. MooshPit[_MP_ENTRYDMAP] = Game->GetCurDMap();
  609. MooshPit[_MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  610. }
  611.  
  612. if(MooshPit[_MP_FALLSTATE]==0){ //Not falling in pit
  613. int onPit = MooshPit_OnPit(Link->X, Link->Y, true);
  614. //Check if slidey pits are enabled and it's not sideview
  615. if(MOOSHPIT_ENABLE_SLIDEYPITS&&!IsSideview()){
  616. if(Link->Z<=0&&onPit>-1){ //If Link is partially on a pit
  617. int slideVx; int slideVy;
  618. int reps = 1;
  619. //Check if it's a frame Link should be moved
  620. if(MooshPit[_MP_SLIDETIMER]%MOOSHPIT_SLIDEYPIT_FREQ==0||MooshPit[_MP_SLIDETIMER]>=MOOSHPIT_SLIDEYPIT_MAXTIME){
  621. if((onPit&0111b)==0111b){ //Going up-left
  622. slideVx = -1;
  623. slideVy = -1;
  624. }
  625. else if((onPit&1011b)==1011b){ //Going up-right
  626. slideVx = 1;
  627. slideVy = -1;
  628. }
  629. else if((onPit&1101b)==1101b){ //Going down-left
  630. slideVx = -1;
  631. slideVy = 1;
  632. }
  633. else if((onPit&1110b)==1110b){ //Going down-right
  634. slideVx = 1;
  635. slideVy = 1;
  636. }
  637. else if((onPit&0011b)==0011b){ //Going up
  638. slideVy = -1;
  639. }
  640. else if((onPit&1100b)==1100b){ //Going down
  641. slideVy = 1;
  642. }
  643. else if((onPit&0101b)==0101b){ //Going left
  644. slideVx = -1;
  645. }
  646. else if((onPit&1010b)==1010b){ //Going right
  647. slideVx = 1;
  648. }
  649. else if((onPit&0001b)==0001b){ //Going up-left
  650. slideVx = -1;
  651. slideVy = -1;
  652. }
  653. else if((onPit&0010b)==0010b){ //Going up-right
  654. slideVx = 1;
  655. slideVy = -1;
  656. }
  657. else if((onPit&0100b)==0100b){ //Going down-left
  658. slideVx = -1;
  659. slideVy = 1;
  660. }
  661. else if((onPit&1000b)==1000b){ //Going down-right
  662. slideVx = 1;
  663. slideVy = 1;
  664. }
  665.  
  666. //DEBUG DRAWS
  667. //VX
  668. // Screen->DrawInteger(6, 0, 0, FONT_Z1, 0x01, 0x0F, -1, -1, slideVx, 0, 128);
  669. //VY
  670. // Screen->DrawInteger(6, 0, 8, FONT_Z1, 0x01, 0x0F, -1, -1, slideVy, 0, 128);
  671. //ONPIT BITS
  672. // Screen->DrawInteger(6, 0, 16, FONT_Z1, 0x01, 0x0F, -1, -1, (onPit&1000b)>>3, 0, 128);
  673. // Screen->DrawInteger(6, 8, 16, FONT_Z1, 0x01, 0x0F, -1, -1, (onPit&0100b)>>2, 0, 128);
  674. // Screen->DrawInteger(6, 16, 16, FONT_Z1, 0x01, 0x0F, -1, -1, (onPit&0010b)>>1, 0, 128);
  675. // Screen->DrawInteger(6, 24, 16, FONT_Z1, 0x01, 0x0F, -1, -1, (onPit&0001b), 0, 128);
  676.  
  677. //If Link is over the max slide time, increase the speed every 4 frames
  678. if(MooshPit[_MP_SLIDETIMER]>=MOOSHPIT_SLIDEYPIT_MAXTIME)
  679. reps += Floor((MooshPit[_MP_SLIDETIMER]-MOOSHPIT_SLIDEYPIT_MAXTIME)/MOOSHPIT_SLIDEYPIT_ACCELFREQ);
  680. }
  681.  
  682. for(i=0; i<reps; i++){
  683. if(slideVx<0&&CanWalk(Link->X, Link->Y, DIR_LEFT, 1, false)){
  684. Link->X--;
  685. }
  686. else if(slideVx>0&&CanWalk(Link->X, Link->Y, DIR_RIGHT, 1, false)){
  687. Link->X++;
  688. }
  689. if(slideVy<0&&CanWalk(Link->X, Link->Y, DIR_UP, 1, false)){
  690. Link->Y--;
  691. }
  692. else if(slideVy>0&&CanWalk(Link->X, Link->Y, DIR_DOWN, 1, false)){
  693. Link->Y++;
  694. }
  695. }
  696. MooshPit[_MP_SLIDETIMER]++;
  697. }
  698. else{
  699. MooshPit[_MP_SLIDETIMER] = 0;
  700. }
  701. }
  702. if(onPit>-1){
  703. //Combine solid combo bits with pit bits
  704. onPit |= (onPit>>4);
  705. //Remove non pit bits
  706. onPit &= 1111b;
  707. }
  708. if(Link->Z<=0&&onPit==15){ //If Link steps on a pit
  709. int underLink;
  710. if(!sideview){
  711. underLink = ComboAt(Link->X+8, Link->Y+12);
  712. if(Screen->ComboT[underLink]!=CT_HOLELAVA){
  713. for(i=0; i<4; i++){
  714. underLink = ComboAt(Link->X+15*(i%2), Link->Y+8+7*Floor(i/2));
  715. if(Screen->ComboT[underLink]==CT_HOLELAVA)
  716. break;
  717. }
  718. }
  719. }
  720. else{
  721. underLink = ComboAt(Link->X+8, Link->Y+8);
  722. if(Screen->ComboT[underLink]!=CT_HOLELAVA){
  723. for(i=0; i<4; i++){
  724. underLink = ComboAt(Link->X+15*(i%2), Link->Y+15*Floor(i/2));
  725. if(Screen->ComboT[underLink]==CT_HOLELAVA)
  726. break;
  727. }
  728. }
  729. }
  730.  
  731. lweapon fall;
  732.  
  733. //Check if the combo is lava
  734. if(ComboFI(underLink, CF_LAVA)){
  735. //Play sound and display animation
  736. Game->PlaySound(SFX_FALLLAVA);
  737. fall = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
  738. if(!MOOSHPIT_NO_GRID_SNAP){
  739. fall->X = ComboX(underLink);
  740. fall->Y = ComboY(underLink);
  741. }
  742. fall->UseSprite(SPR_FALLLAVA);
  743. fall->CollDetection = false;
  744. fall->DeadState = fall->ASpeed*fall->NumFrames;
  745.  
  746. //Mark as lava damage
  747. MooshPit[_MP_DAMAGETYPE] = 1;
  748. }
  749. //Otherwise it's a pit
  750. else{
  751. //Play sound and display animation
  752. Game->PlaySound(SFX_FALLHOLE);
  753. fall = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
  754. if(!MOOSHPIT_NO_GRID_SNAP){
  755. fall->X = ComboX(underLink);
  756. fall->Y = ComboY(underLink);
  757. if(isWarp){
  758. Link->X = ComboX(underLink);
  759. Link->Y = ComboY(underLink);
  760. }
  761. }
  762. fall->UseSprite(SPR_FALLHOLE);
  763. fall->CollDetection = false;
  764. fall->DeadState = fall->ASpeed*fall->NumFrames;
  765.  
  766. //Mark as hole damage
  767. MooshPit[_MP_DAMAGETYPE] = 0;
  768. }
  769.  
  770. MooshPit[_MP_FALLX] = Link->X;
  771. MooshPit[_MP_FALLY] = Link->Y;
  772.  
  773. //Cooldown should last as long as the fall animation
  774. MooshPit[_MP_FALLSTATE] = 1;
  775. MooshPit[_MP_FALLTIMER] = Max(MOOSHPIT_MIN_FALL_TIME, fall->DeadState+MOOSHPIT_EXTRA_FALL_TIME);
  776.  
  777. //Render Link invisible and intangible
  778. Link->Invisible = true;
  779. Link->CollDetection = false;
  780.  
  781. NoAction();
  782. }
  783. else if(MooshPit_OnPit(Link->X, Link->Y, false)==-1&&Link->Action!=LA_FROZEN){ //All other times, while Link is on solid ground, record Link's last position
  784. if(sideview){
  785. //Link has no Z value in sideview, so we check if he's on a platform instead
  786. if(OnSidePlatform(Link->X, Link->Y)){
  787. MooshPit[_MP_LASTDMAP] = Game->GetCurDMap();
  788. MooshPit[_MP_LASTSCREEN] = Game->GetCurDMapScreen();
  789. MooshPit[_MP_LASTX] = Link->X;
  790. MooshPit[_MP_LASTY] = Link->Y;
  791. }
  792. }
  793. else{
  794. if(Link->Z<=0){
  795. MooshPit[_MP_LASTDMAP] = Game->GetCurDMap();
  796. MooshPit[_MP_LASTSCREEN] = Game->GetCurDMapScreen();
  797. MooshPit[_MP_LASTX] = Link->X;
  798. MooshPit[_MP_LASTY] = Link->Y;
  799. }
  800. }
  801. }
  802. }
  803. else if(MooshPit[_MP_FALLSTATE]==1){ //Falling animation
  804. if(MooshPit[_MP_FALLTIMER]>0)
  805. MooshPit[_MP_FALLTIMER]--;
  806.  
  807. if(MOOSHPIT_STUN_ENEMIES_WHILE_FALLING)
  808. MooshPit_StunEnemies();
  809.  
  810. Link->Jump = 0;
  811. Link->Z = 0;
  812.  
  813. //Keep Link invisible just in case
  814. Link->Invisible = true;
  815. Link->CollDetection = false;
  816. NoAction();
  817. if(MooshPit[_MP_FALLTIMER]==0){
  818. MooshPit[_MP_SLIDETIMER] = 0;
  819. if(!isWarp||MooshPit[_MP_DAMAGETYPE]==1){ //If the pit isn't a warp, deal damage and move Link back to the return point
  820. //If the entry would dump Link back in the pit, dump him out at the failsafe position
  821. if(MooshPit_OnPit(MooshPit[_MP_ENTRYX], MooshPit[_MP_ENTRYY], false)==15){
  822. if(MOOSHPIT_NO_REENTER_STAIRS){
  823. //Call a script to place an FFC under Link to prevent reentering stairs
  824. int scriptName[] = "MooshPit_StairsFix";
  825. int ffcNum = RunFFCScript(Game->GetFFCScript(scriptName), 0);
  826. if(ffcNum>0){
  827. ffc f = Screen->LoadFFC(ffcNum);
  828. f->Flags[FFCF_ETHEREAL] = false;
  829. f->X = MooshPit[_MP_LASTX];
  830. f->Y = MooshPit[_MP_LASTY];
  831. }
  832. }
  833.  
  834. Link->X = MooshPit[_MP_LASTX];
  835. Link->Y = MooshPit[_MP_LASTY];
  836.  
  837. //If the failsafe position was on a different screen, warp there
  838. if(Game->GetCurDMap()!=MooshPit[_MP_LASTDMAP]||Game->GetCurDMapScreen()!=MooshPit[_MP_LASTSCREEN]){
  839. Link->PitWarp(MooshPit[_MP_LASTDMAP], MooshPit[_MP_LASTSCREEN]);
  840. }
  841.  
  842. Link->Invisible = false;
  843. Link->CollDetection = true;
  844. }
  845. else{
  846. if(MOOSHPIT_NO_REENTER_STAIRS){
  847. //Call a script to place an FFC under Link to prevent reentering stairs
  848. int scriptName[] = "MooshPit_StairsFix";
  849. int ffcNum = RunFFCScript(Game->GetFFCScript(scriptName), 0);
  850. if(ffcNum>0){
  851. ffc f = Screen->LoadFFC(ffcNum);
  852. f->Flags[FFCF_ETHEREAL] = false;
  853. f->X = MooshPit[_MP_ENTRYX];
  854. f->Y = MooshPit[_MP_ENTRYY];
  855. }
  856. }
  857.  
  858. //Move Link to the entry and make him visible
  859. Link->X = MooshPit[_MP_ENTRYX];
  860. Link->Y = MooshPit[_MP_ENTRYY];
  861.  
  862. Link->Invisible = false;
  863. Link->CollDetection = true;
  864. }
  865.  
  866. //Subtract HP based on damage type
  867. if(MooshPit[_MP_DAMAGETYPE]==1)
  868. Link->HP -= DAMAGE_FALLLAVA;
  869. else
  870. Link->HP -= DAMAGE_FALLHOLE;
  871. //Play hurt sound and animation
  872. Link->Action = LA_GOTHURTLAND;
  873. Link->HitDir = -1;
  874. Game->PlaySound(SFX_OUCH);
  875.  
  876. MooshPit[_MP_FALLSTATE] = 0;
  877. }
  878. else{
  879. MooshPit[_MP_FALLSTATE] = 2;
  880. MooshPit[_MP_FALLTIMER] = 1;
  881. ffc warp = Screen->LoadFFC(FFC_MOOSHPIT_AUTOWARPA);
  882. warp->Data = CMB_MOOSHPIT_AUTOWARPA;
  883. warp->Flags[FFCF_CARRYOVER] = false;
  884. }
  885. }
  886. }
  887. else if(MooshPit[_MP_FALLSTATE]==2){ //Just warped
  888. if(sideview){
  889. Link->X = MooshPit[_MP_FALLX];
  890. Link->Y = 0;
  891. }
  892. else{
  893. Link->X = MooshPit[_MP_FALLX];
  894. Link->Y = MooshPit[_MP_FALLY];
  895. Link->Z = 176;
  896. }
  897. Link->Invisible = false;
  898. Link->CollDetection = true;
  899.  
  900. if(MOOSHPIT_NO_MOVE_WHILE_FALLING){
  901. MooshPit[_MP_FALLSTATE] = 3;
  902. NoAction();
  903. }
  904. else
  905. MooshPit[_MP_FALLSTATE] = 0;
  906. MooshPit[_MP_FALLTIMER] = 0;
  907. }
  908. else if(MooshPit[_MP_FALLSTATE]==3){ //Falling into a new room (no action)
  909. if(MOOSHPIT_STUN_ENEMIES_WHILE_FALLING)
  910. MooshPit_StunEnemies();
  911.  
  912. NoAction();
  913. if(IsSideview()){
  914. if(OnSidePlatform(Link->X, Link->Y))
  915. MooshPit[_MP_FALLSTATE] = 0;
  916. }
  917. else{
  918. if(Link->Z<=0)
  919. MooshPit[_MP_FALLSTATE] = 0;
  920. }
  921. }
  922. }
  923. }
  924.  
  925. void MooshPit_ResetEntry(){
  926. MooshPit[_MP_ENTRYX] = Link->X;
  927. MooshPit[_MP_ENTRYY] = Link->Y;
  928. MooshPit[_MP_ENTRYDMAP] = Game->GetCurDMap();
  929. MooshPit[_MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  930. }
  931.  
  932. ffc script MooshPit_StairsFix{
  933. void run(){
  934. this->Flags[FFCF_ETHEREAL] = false;
  935. while(LinkCollision(this)){
  936. Waitframe();
  937. }
  938. this->X = 0;
  939. this->Y = 0;
  940. this->Data = 0;
  941. }
  942. }
  943.  
  944. //%MGSO% HEADER_END MooshPit
  945.  
  946. //%MGSO% HEADER_START Confusion
  947.  
  948. const int CR_CONFUSION = 7; //The counter to use for confusion. CR_SCRIPT# values are 7-31.
  949.  
  950. global script Init
  951. {
  952. void run()
  953. {
  954. Game->MCounter[CR_CONFUSION]=65535; //Max
  955. }
  956. }
  957.  
  958.  
  959.  
  960. void UpdateConfusion()
  961. {
  962. if(Link->Drunk > 0)
  963. {
  964. Game->Counter[CR_CONFUSION]=Link->Drunk;
  965. Link->Drunk=0;
  966. }
  967. if(Game->Counter[CR_CONFUSION]>0)
  968. {
  969. Game->Counter[CR_CONFUSION]--;
  970. if(Link->InputUp != Link->InputDown)
  971. {
  972. Link->InputUp = !Link->InputUp;
  973. Link->InputDown = !Link->InputDown;
  974. }
  975. if(Link->InputLeft != Link->InputRight)
  976. {
  977. Link->InputLeft = !Link->InputLeft;
  978. Link->InputRight = !Link->InputRight;
  979. }
  980. }
  981. }
  982.  
  983.  
  984. item script RemoveConfusion
  985. {
  986. void run()
  987. {
  988. Game->Counter[CR_CONFUSION]=NULL;
  989. }
  990. }
  991. //%MGSO% HEADER_END Confusion
  992.  
  993. //%MGSO% HEADER_START SolidFFC
  994.  
  995. //Global Constants
  996. const int MISC_SOLIDFFC = 14; //A misc value between 0 and 15 to denote a ffc as solid.
  997. const int MISC_SFFC_X = 0; //This can be used by other ffcs as long as they're not solid.
  998. const int SFFC_SIDEVIEWTHRESHOLD = 12; //Sideview X Overlap: used for hitdetection.
  999. const int CRUSH_DAMAGE = 16; //Damage in 16ths of a heart dealt to link when he is crushed.
  1000. const int SF_SIDEWARP = 2; //The flag to denote that Left/Right sidewarps are used on a screen.
  1001. const int BIG_LINK = 0;
  1002. const int CT_LADDER = 0; //If not using CT_RIGHTSTATUE
  1003.  
  1004. //Don't touch me, don't even think about setting these variables. HEY!
  1005. float SFFC_LinkX;
  1006. float SFFC_LinkY;
  1007.  
  1008. // this utility routine by Saffith checks for walkability of combos
  1009. bool isSolid(int x, int y){
  1010. if(x<0 || x>255 || y<0 || y>175) return false;
  1011. int mask=1111b;
  1012. if(x%16< 8) mask&=0011b;
  1013. else mask&=1100b;
  1014. if(y%16< 8) mask&=0101b;
  1015. else mask&=1010b;
  1016. return (!(Screen->ComboS[ComboAt(x, y)]&mask)==0);
  1017. }
  1018. // this utility is used by the ffcs to check if the platform can move link.
  1019. bool CanMoveLink(int x){
  1020. if(x > 0) x+=Link->X+16;
  1021. else if(x < 0) x+=Link->X-1;
  1022. if(x<0) return (Game->GetCurScreen()%16==0 && ScreenFlag(SF_MISC, SF_SIDEWARP));
  1023. if(x>240) return (Game->GetCurScreen()%16==15 && ScreenFlag(SF_MISC,SF_SIDEWARP));
  1024. int mask;
  1025. if(x < Link->X) mask = 1100b;
  1026. else mask = 11b;
  1027. if(Cond(BIG_LINK || IsSideview(),false,true)){
  1028. if(Link->Y % 16 < 8) mask &= ~101b;
  1029. }
  1030. return (Screen->ComboS[ComboAt(x, Link->Y)]&mask)==0 && !OnLadder();
  1031. }
  1032.  
  1033. // You can customize these functions to suit your needs.
  1034. // this utility is used to check if link is doing something that would interfer with him using an item.
  1035. bool LinkBusy()
  1036. {
  1037. return (Link->Action==LA_ATTACKING||Link->Action == LA_CHARGING||Link->Action==LA_FROZEN);
  1038. }
  1039.  
  1040. // this utility is used to check if link using the feather.
  1041. bool UseFeather()
  1042. {
  1043. return !LinkBusy() && ((GetEquipmentA()==I_ROCSFEATHER && Link->PressA) || (GetEquipmentB()==I_ROCSFEATHER && Link->PressB));
  1044. }
  1045.  
  1046. // this utility is used to check if link is on a sideview ladder.
  1047. bool OnLadder()
  1048. {
  1049. int ct = Screen->ComboT[ComboAt(CenterLinkX(),CenterLinkY())];
  1050. return (ct == Cond(CT_LADDER==0,CT_RIGHTSTATUE,CT_LADDER));
  1051. }
  1052.  
  1053.  
  1054. //Editing anything beneath this point may cause sickness, coma, brain anuerysm, or death.
  1055. //Do so at your own risk and don't hold me responsible. Have a good day! ^_^
  1056.  
  1057. void SolidFFCs(int startx, int starty, int linkxpos, int linkypos, bool dragged)
  1058. {
  1059. int reservedx = Link->X;
  1060. int reservedy = Link->Y;
  1061. bool linkmoved[4]; //Up Down Left Right
  1062. int edge[2];
  1063. bool crushed;
  1064. for(int i = 1; i <= 32 && !crushed; i++)
  1065. {
  1066. ffc f = Screen->LoadFFC(i);
  1067. if(!f->Misc[MISC_SOLIDFFC]) continue;
  1068. if(!SFFC_LinkCollision(f, edge)) continue;
  1069. if(!SFFC_SetDirection(f, linkmoved, edge, linkxpos, linkypos))
  1070. {
  1071. crushed = SFFC_CrushLink(f, linkmoved, edge, startx, starty, dragged);
  1072. continue;
  1073. }
  1074. crushed = SFFC_CrushLink(f, linkmoved, edge, startx, starty, dragged);
  1075. if(!crushed)
  1076. {
  1077. if(edge[0]==DIR_UP || edge[0]==DIR_DOWN)
  1078. {
  1079. if(!IsSideview())
  1080. {
  1081. SFFC_LinkY += edge[1];
  1082. if(Abs(SFFC_LinkY) >= 1) Link->Y += Floor(SFFC_LinkY);
  1083. SFFC_LinkY -= Floor(SFFC_LinkY);
  1084. }
  1085. else if(edge[0]==DIR_UP)
  1086. {
  1087. if(!(OnLadder() && UseFeather()))
  1088. Link->Jump=0; //Negate dat dang gravity
  1089. }
  1090. if(Link->InputLeft || Link->InputRight) Link->X = reservedx;
  1091. }
  1092. else if(edge[0]==DIR_LEFT ||edge[0]==DIR_RIGHT)
  1093. {
  1094. SFFC_LinkX += edge[1];
  1095. if(Abs(SFFC_LinkX) >= 1) Link->X += Floor(SFFC_LinkX);
  1096. SFFC_LinkX -= Floor(SFFC_LinkX);
  1097. if(Link->InputUp || Link->InputDown || IsSideview()) Link->Y=reservedy;
  1098. }
  1099. reservedx=Link->X;
  1100. reservedy=Link->Y;
  1101. }
  1102. }
  1103. }
  1104.  
  1105. //As usual Sideview gravity breaks everything even solid ffcs. XD
  1106. int SFFC_SideviewShenanigans(int linkxpos, int linkypos)
  1107. {
  1108. bool linkmoved[4]; //Up Down Left Right
  1109. int edge[2];
  1110. float dragged;
  1111. for(int i = 1; i <= 32; i++)
  1112. {
  1113. ffc f = Screen->LoadFFC(i);
  1114. if(!f->Misc[MISC_SOLIDFFC]) continue;
  1115. if(!SFFC_LinkCollision(f, edge) || !SFFC_SetDirection(f, linkmoved, edge, linkxpos, linkypos))
  1116. {
  1117. f->Misc[MISC_SFFC_X] = f->X;
  1118. continue;
  1119. }
  1120. if(edge[0]==DIR_UP)
  1121. {
  1122. if(!OnLadder())
  1123. {
  1124. if(UseFeather())
  1125. {
  1126. itemdata feather = Game->LoadItemData(I_ROCSFEATHER);
  1127. Link->Jump = feather->InitD[0];
  1128. Game->PlaySound(feather->UseSound);
  1129. f->Misc[MISC_SFFC_X] = f->X;
  1130. break; //Cause it should only happen once per frame.
  1131. }
  1132. else
  1133. {
  1134. if(Link->Jump<=0) Link->Jump=0;
  1135. Link->Y = f->Y-16;
  1136. }
  1137. linkypos = Link->Y;
  1138. }
  1139. if(CanMoveLink(f->X-f->Misc[MISC_SFFC_X]))
  1140. {
  1141. SFFC_LinkX += f->X-f->Misc[MISC_SFFC_X];
  1142. if(Abs(SFFC_LinkX) >= 1)
  1143. {
  1144. Link->X += Floor(SFFC_LinkX);
  1145. SFFC_LinkX -= Floor(SFFC_LinkX);
  1146. }
  1147. linkxpos = Link->X;
  1148. dragged=0.9999;
  1149. }
  1150. else
  1151. {
  1152. linkxpos = Link->X;
  1153. Link->Jump=0;
  1154. dragged=0;
  1155. }
  1156. }
  1157. else if(edge[0]==DIR_DOWN && Link->Jump>0)
  1158. {
  1159. Link->Jump=0;
  1160. }
  1161. f->Misc[MISC_SFFC_X] = f->X;
  1162. }
  1163. return (linkxpos|(linkypos<<8))+dragged;
  1164. }
  1165.  
  1166. //Link Collision
  1167. bool SFFC_LinkCollision(ffc f, int edge)
  1168. {
  1169. int linktop = Link->Y+Cond(BIG_LINK || IsSideview(), 0, 8)>>0;
  1170. int linkbottom = Link->Y+15>>0;
  1171. int linkleft = Link->X>>0;
  1172. int linkright = Link->X+15>>0;
  1173. int top = HitboxTop(f)>>0;
  1174. int bottom = HitboxBottom(f)>>0;
  1175. int left = HitboxLeft(f)>>0;
  1176. int right = HitboxRight(f)>>0;
  1177. int mod=0;
  1178. if(IsSideview()) mod = SFFC_SIDEVIEWTHRESHOLD;
  1179. // horizontal
  1180. if(linktop < bottom && linkbottom > top)
  1181. {
  1182. if(IsSideview()) mod = 16-mod; //Less math.
  1183. if(CenterLinkX() < CenterX(f)) // Left Side
  1184. {
  1185. edge[0]=DIR_LEFT;
  1186. return (linkright >= left+mod);
  1187. }
  1188. else //Right Side
  1189. {
  1190. edge[0]=DIR_RIGHT;
  1191. return (linkleft <= right-mod);
  1192. }
  1193. }
  1194. // vertical
  1195. else if(linkleft < right && linkright > left)
  1196. {
  1197. if(CenterLinkY() < CenterY(f)) // Top Side
  1198. {
  1199. edge[0]=DIR_UP;
  1200. if(IsSideview()) return linkbottom+1 >= top && (linkleft > left-mod && linkleft < left+mod+(f->TileWidth-1)*16);
  1201. else return (linkbottom >= top);
  1202. }
  1203. else //Bottom Side
  1204. {
  1205. edge[0]=DIR_DOWN;
  1206. return (linktop <= bottom);
  1207. }
  1208. }
  1209. else return false;
  1210. }
  1211.  
  1212. bool SFFC_SetDirection(ffc f, bool linkmoved, int edge, int linkxpos, int linkypos)
  1213. {
  1214. //Move link to his old position.
  1215. int x = Link->X;
  1216. int y = Link->Y;
  1217. Link->X = linkxpos;
  1218. Link->Y = linkypos;
  1219. //Then check for collisions again.
  1220. bool ret = SFFC_LinkCollision(f, edge);
  1221. //If we get here we know he didn't walk on the ffc and we got stuff to do.
  1222. if(edge[0]==DIR_UP) edge[1] = -Abs(HitboxTop(f)-(Link->Y+15));
  1223. else if(edge[0]==DIR_DOWN) edge[1] = Abs(HitboxBottom(f)-(Link->Y+Cond(BIG_LINK || IsSideview(),0,8)));
  1224. else if(edge[0]==DIR_LEFT) edge[1] = -Abs(HitboxLeft(f)-(Link->X+15));
  1225. else if(edge[0]==DIR_RIGHT) edge[1] = Abs(HitboxRight(f)-Link->X);
  1226. linkmoved[edge[0]] = true;
  1227. if(!ret)
  1228. {
  1229. if(Link->X >= HitboxLeft(f)-15 && Link->X <= HitboxRight(f) &&
  1230. (Link->InputLeft||Link->InputRight)) Link->X=x;
  1231. else if(Link->Y >= HitboxTop(f)-15 && Link->Y+Cond(BIG_LINK || IsSideview(),0,8) <= HitboxBottom(f) &&
  1232. (Link->InputUp||Link->InputDown) || IsSideview()) Link->Y=y;
  1233. }
  1234. return ret;
  1235. }
  1236.  
  1237. bool SFFC_CrushLink(ffc f, bool linkmoved, int edge, int linkx, int linky, bool dragged)
  1238. {
  1239. // Solid Combos
  1240. bool crush; //Canwalk sucks, do it yourself guys. :)
  1241. if(!IsSideview()) dragged = false;
  1242. if(edge[0]==DIR_UP)
  1243. {
  1244. crush = isSolid(Floor(CenterLinkX()), Floor(Link->Y+Cond(BIG_LINK || IsSideview(), 0,8)+edge[1])) && !dragged;
  1245. if(IsSideview() && crush) crush = (Floor(Link->Y)+16+edge[1]>=HitboxTop(f)); //Squash Bug Fix.
  1246. }
  1247. else if(edge[0]==DIR_DOWN)
  1248. crush = isSolid(Floor(CenterLinkX()), Floor(Link->Y+15+edge[1]));
  1249. else if(edge[0]==DIR_LEFT)
  1250. crush = isSolid(Floor(Link->X+edge[1]), Floor(Link->Y+Cond(BIG_LINK || IsSideview(), 0,8)));
  1251. else if(edge[0]==DIR_RIGHT)
  1252. crush = isSolid(Floor(Link->X+15+edge[1]), Floor(Link->Y+Cond(BIG_LINK || IsSideview(), 0,8)));
  1253. // Solid FFCs
  1254. if(!crush)
  1255. {
  1256. for(int i; i < 4; i++)
  1257. {
  1258. if(linkmoved[i] && i==OppositeDir(edge[0]))
  1259. {
  1260. crush=true;
  1261. break;
  1262. }
  1263. }
  1264. }
  1265. // Crushing Behavior
  1266. if(crush)
  1267. {
  1268. Link->X = Clamp(linkx,0,240);
  1269. Link->Y = Clamp(linky,0,160);
  1270. Link->HP -= CRUSH_DAMAGE;
  1271. Link->Action = LA_GOTHURTLAND;
  1272. Link->HitDir = -1;
  1273. Game->PlaySound(SFX_OUCH);
  1274. }
  1275. return crush;
  1276. }
  1277.  
  1278. ffc script SolidFFC
  1279. {
  1280. void run()
  1281. {
  1282. this->Misc[MISC_SOLIDFFC] = 1;
  1283. this->Misc[MISC_SFFC_X] = this->X;
  1284. }
  1285. }
  1286. //%MGSO% HEADER_END SolidFFC
  1287.  
  1288. //%MGSO% HEADER_START BombArrow
  1289.  
  1290. //Input constants
  1291. const int ArrowDamage = 2; //Damage for Arrow to deal. Wooden sword deals 2 damage
  1292. const int BombDamage = 8; //Damage for explosion to deal
  1293. const int ArrowSpeed = 300; //Speed arrow moves at, in hundredths of pixels per frame
  1294. const int T_BOMBARROW = 28169; //Arrange tiles in the order 'Up,Down,Left,Right' on the tilesheet. Set up-facing bomb arrow tile here
  1295.  
  1296. //Variables
  1297. int UseBombArrow;
  1298. int ArrowX; int ArrowY;
  1299.  
  1300. //Functions
  1301. //Check inherent and regular flags at the same time
  1302.  
  1303.  
  1304.  
  1305. item script BombArrow{
  1306. void run(){
  1307. if(Game->Counter[CR_SBOMBS] > 0 && UseBombArrow == 0){
  1308. UseBombArrow++;
  1309. Game->Counter[CR_SBOMBS]--;
  1310. }
  1311. }
  1312. }
  1313. //%MGSO% HEADER_END BombArrow
  1314.  
  1315. global script MGSO_Combined
  1316. {
  1317. void run()
  1318. {
  1319. //%MGSO% INIT_START ScrollingBackgrounds
  1320.  
  1321. ScrollingBG_Init();
  1322. //%MGSO% INIT_END ScrollingBackgrounds
  1323.  
  1324. //%MGSO% INIT_START MovingPlatforms
  1325.  
  1326. //%MGSO% INIT_END MovingPlatforms
  1327.  
  1328. //%MGSO% INIT_START MooshPit
  1329.  
  1330. MooshPit_Init();
  1331. //%MGSO% INIT_END MooshPit
  1332.  
  1333. //%MGSO% INIT_START Confusion
  1334.  
  1335. //%MGSO% INIT_END Confusion
  1336.  
  1337. //%MGSO% INIT_START SolidFFC
  1338.  
  1339. int olddmap = Game->GetCurDMap();
  1340. int oldscreen = Game->GetCurScreen();
  1341. int startx = Link->X;
  1342. int starty = Link->Y;
  1343. int linkxpos = startx;
  1344. int linkypos = starty;
  1345. bool dragged;
  1346. //%MGSO% INIT_END SolidFFC
  1347.  
  1348. //%MGSO% INIT_START BombArrow
  1349.  
  1350. //%MGSO% INIT_END BombArrow
  1351.  
  1352. while(true)
  1353. {
  1354. //%MGSO% UPDATE1_START ScrollingBackgrounds
  1355.  
  1356. ScrollingBG_Update();
  1357.  
  1358. //%MGSO% UPDATE1_END ScrollingBackgrounds
  1359.  
  1360. //%MGSO% UPDATE1_START MovingPlatforms
  1361.  
  1362. NesMovementFix();
  1363. //%MGSO% UPDATE1_END MovingPlatforms
  1364.  
  1365. //%MGSO% UPDATE1_START MooshPit
  1366.  
  1367. MooshPit_Update();
  1368. //%MGSO% UPDATE1_END MooshPit
  1369.  
  1370. //%MGSO% UPDATE1_START Confusion
  1371.  
  1372. //Waitdraw();
  1373. UpdateConfusion();
  1374. //%MGSO% UPDATE1_END Confusion
  1375.  
  1376. //%MGSO% UPDATE1_START SolidFFC
  1377.  
  1378. if((Link->Action!=LA_SCROLLING) && (olddmap != Game->GetCurDMap() || oldscreen != Game->GetCurScreen()))
  1379. {
  1380. olddmap = Game->GetCurDMap();
  1381. oldscreen = Game->GetCurScreen();
  1382. startx = Link->X;
  1383. starty = Link->Y;
  1384. }
  1385. if(IsSideview())
  1386. {
  1387. //A fix for something I should of done different D:
  1388. float linkposition = SFFC_SideviewShenanigans(linkxpos, linkypos);
  1389. linkxpos = linkposition&0xFF;
  1390. linkypos = (linkposition>>8)&0xFF;
  1391. if((linkposition%1)*10000) dragged=true;
  1392. else dragged=false;
  1393. }
  1394. //%MGSO% UPDATE1_END SolidFFC
  1395.  
  1396. //%MGSO% UPDATE1_START BombArrow
  1397.  
  1398. //Call bomb arrow functions
  1399. if(UseBombArrow > 0) BombArrow();
  1400.  
  1401. //%MGSO% UPDATE1_END BombArrow
  1402.  
  1403. Waitdraw();
  1404. //%MGSO% UPDATE2_START ScrollingBackgrounds
  1405.  
  1406.  
  1407. //%MGSO% UPDATE2_END ScrollingBackgrounds
  1408.  
  1409. //%MGSO% UPDATE2_START MovingPlatforms
  1410.  
  1411. MovingPlatforms();
  1412. //%MGSO% UPDATE2_END MovingPlatforms
  1413.  
  1414. //%MGSO% UPDATE2_START MooshPit
  1415.  
  1416. //%MGSO% UPDATE2_END MooshPit
  1417.  
  1418. //%MGSO% UPDATE2_START Confusion
  1419.  
  1420. //%MGSO% UPDATE2_END Confusion
  1421.  
  1422. //%MGSO% UPDATE2_START SolidFFC
  1423.  
  1424. SolidFFCs(startx, starty, linkxpos, linkypos, dragged);
  1425. linkxpos = Link->X;
  1426. linkypos = Link->Y;
  1427. //%MGSO% UPDATE2_END SolidFFC
  1428.  
  1429. //%MGSO% UPDATE2_START BombArrow
  1430.  
  1431. //%MGSO% UPDATE2_END BombArrow
  1432.  
  1433. Waitframe();
  1434. }
  1435. //%MGSO% FUNCTIONS_START ScrollingBackgrounds
  1436.  
  1437. //%MGSO% FUNCTIONS_END ScrollingBackgrounds
  1438.  
  1439. //%MGSO% FUNCTIONS_START MovingPlatforms
  1440.  
  1441. //%MGSO% FUNCTIONS_END MovingPlatforms
  1442.  
  1443. //%MGSO% FUNCTIONS_START MooshPit
  1444.  
  1445. //%MGSO% FUNCTIONS_END MooshPit
  1446.  
  1447. //%MGSO% FUNCTIONS_START Confusion
  1448.  
  1449. //%MGSO% FUNCTIONS_END Confusion
  1450.  
  1451. //%MGSO% FUNCTIONS_START SolidFFC
  1452.  
  1453. //%MGSO% FUNCTIONS_END SolidFFC
  1454.  
  1455. //%MGSO% FUNCTIONS_START BombArrow
  1456.  
  1457. //bomb arrow functions
  1458. void BombArrow(){
  1459. if(UseBombArrow == 1){
  1460. lweapon Arrow = Screen->CreateLWeapon(LW_ARROW);
  1461. int x; int y;
  1462. if(Link->Dir > 1) x = (Link->Dir-2)*16-8;
  1463. else y = Link->Dir*16-8;
  1464. Arrow->X = Link->X+x;
  1465. Arrow->Y = Link->Y+y;
  1466. Arrow->Dir = Link->Dir;
  1467. Arrow->Tile = T_BOMBARROW;
  1468. Arrow->Tile += Link->Dir;
  1469.  
  1470. Arrow->Damage = ArrowDamage;
  1471. Arrow->Step = ArrowSpeed;
  1472. Game->PlaySound(SFX_ARROW);
  1473. Link->Action = LA_ATTACKING;
  1474. UseBombArrow++;
  1475. }else{
  1476. lweapon Arrow;
  1477. bool Found;
  1478. for(int i=1;i<=Screen->NumLWeapons();i++){
  1479. Arrow = Screen->LoadLWeapon(i);
  1480. if(Arrow->ID != LW_ARROW) continue;
  1481. Found = true;
  1482. }
  1483. if(Found){
  1484. ArrowX = Arrow->X;
  1485. ArrowY = Arrow->Y;
  1486. }else{
  1487. lweapon Exp = Screen->CreateLWeapon(LW_BOMBBLAST);
  1488. Exp->Damage = BombDamage;
  1489. Exp->X = ArrowX;
  1490. Exp->Y = ArrowY;
  1491. UseBombArrow = 0;
  1492. }
  1493. }
  1494. }
  1495. //%MGSO% FUNCTIONS_END BombArrow
  1496.  
  1497. }
  1498. }
  1499.  
  1500.  
  1501.  
  1502.  
  1503. //Pushable Pillars
  1504.  
  1505. const int PILLAR_SENSITIVITY=8; //Number of frames the block needs to be pushed before it starts moving
  1506.  
  1507. ffc script PushablePillars{
  1508. void run(int orientation, int distance){ //Horizontal/Vertical pushing
  1509. distance=distance*16;
  1510. int undercombo;
  1511. int framecounter=0;
  1512. int pushcounter=0;
  1513. int anicounter=0;
  1514. int anitile=0;
  1515. int originaltile=this->Data;
  1516. int pushspeed=1;
  1517. int width=this->TileWidth;
  1518. int height=this->TileHeight;
  1519.  
  1520. Waitframe();
  1521. undercombo=GetLayerComboD(1,this->Y+(this->X>>4));
  1522. if(orientation==1){ SetSolidCombo(3,this->X,this->Y,width,height,this->Data); } //Horizontally
  1523. if(orientation==2){ SetSolidCombo(1,this->X,this->Y,width,height,this->Data); } //Vertically
  1524.  
  1525. while(true){
  1526. if((Link->X==this->X-16 && (Link->Y<this->Y+4+((height-1)*16) && Link->Y>this->Y-4)
  1527. && Link->InputRight && Link->Dir==DIR_RIGHT && orientation==1) || // Right
  1528.  
  1529. (Link->X==this->X+16 && (Link->Y<this->Y+4+((height-1)*16) && Link->Y>this->Y-4)
  1530. && Link->InputLeft && Link->Dir==DIR_LEFT && orientation==1) || // Left
  1531.  
  1532. (Link->Y==this->Y-16 && (Link->X<this->X+4+((width-1)*16) && Link->X>this->X-4)
  1533. && Link->InputDown && Link->Dir==DIR_DOWN && orientation==2) || // Down
  1534.  
  1535. (Link->Y==this->Y+8 && (Link->X<this->X+4+((width-1)*16) && Link->X>this->X-4) //Change the 8 to 16 if you use big Link
  1536. && Link->InputUp && Link->Dir==DIR_UP && orientation==2)
  1537. ){ // Up
  1538. framecounter++;
  1539. }
  1540. else{ framecounter=0; }
  1541.  
  1542. if(framecounter>=PILLAR_SENSITIVITY){
  1543.  
  1544. if(Link->Dir==DIR_RIGHT){
  1545. while(
  1546. this->X<240 &&
  1547. !ComboFI(this->X+16,this->Y,CF_NOBLOCKS) &&
  1548. NoSolidBlocks(4,this->X,this->Y,width,height)==true &&
  1549. pushcounter<distance
  1550. ){
  1551. if(pushcounter==0){ Game->PlaySound(SFX_PUSHBLOCK); }
  1552. if(pushcounter<distance/2){ NoAction(); }
  1553. if(pushcounter%4==0 && pushcounter!=0){ anitile+=1; }
  1554. if(anitile>3){ anitile=0; }
  1555. SetSolidCombo(4,this->X,this->Y,width,height,undercombo);
  1556. this->Vx=pushspeed;
  1557. this->Data=originaltile+anitile;
  1558. pushcounter+=pushspeed;
  1559. Waitframe();
  1560. if(pushcounter%16==0){ SetUnderCombo(4,this->X-16,this->Y,width,height); }
  1561. }
  1562. this->Vx=0;
  1563. this->Data=originaltile;
  1564. pushcounter=0;
  1565. anitile=0;
  1566. SetSolidCombo(4,this->X,this->Y,width,height,this->Data);
  1567. }
  1568.  
  1569. else if(Link->Dir==DIR_LEFT){
  1570. while(
  1571. this->X>0 &&
  1572. !ComboFI(this->X-1,this->Y,CF_NOBLOCKS) &&
  1573. NoSolidBlocks(3,this->X,this->Y,width,height)==true &&
  1574. pushcounter<distance
  1575. ){
  1576. if(pushcounter==0){ Game->PlaySound(SFX_PUSHBLOCK); }
  1577. if(pushcounter<distance/2){ NoAction(); }
  1578. if(pushcounter%4==0 && pushcounter!=0){ anitile-=1; }
  1579. if(anitile<0){ anitile=3; }
  1580. SetSolidCombo(3,this->X,this->Y,width,height,undercombo);
  1581. this->Vx=-pushspeed;
  1582. this->Data=originaltile+anitile;
  1583. pushcounter+=pushspeed;
  1584. Waitframe();
  1585. if(pushcounter%16==0){ SetUnderCombo(3,this->X+16,this->Y,width,height); }
  1586. }
  1587. this->Vx=0;
  1588. this->Data=originaltile;
  1589. pushcounter=0;
  1590. anitile=0;
  1591. SetSolidCombo(3,this->X,this->Y,width,height,this->Data);
  1592. }
  1593.  
  1594. else if(Link->Dir==DIR_DOWN){
  1595. while(
  1596. this->Y<160 &&
  1597. !ComboFI(this->X, this->Y+16, CF_NOBLOCKS) &&
  1598. NoSolidBlocks(2,this->X,this->Y,width,height)==true &&
  1599. pushcounter<distance
  1600. ){
  1601. if(pushcounter==0){ Game->PlaySound(SFX_PUSHBLOCK); }
  1602. if(pushcounter<distance/2){ NoAction(); }
  1603. if(pushcounter%4==0 && pushcounter!=0){ anitile+=4; }
  1604. if(anitile>12){ anitile=0; }
  1605. SetSolidCombo(2,this->X,this->Y,width,height,undercombo);
  1606. this->Vy=pushspeed;
  1607. this->Data=originaltile+anitile;
  1608. pushcounter+=pushspeed;
  1609. Waitframe();
  1610. if(pushcounter%16==0){ SetUnderCombo(2,this->X,this->Y-16,width,height); }
  1611. }
  1612. this->Vy=0;
  1613. this->Data=originaltile;
  1614. pushcounter=0;
  1615. anitile=0;
  1616. SetSolidCombo(2,this->X,this->Y,width,height,this->Data);
  1617. }
  1618.  
  1619. else if(Link->Dir==DIR_UP){
  1620. while(
  1621. this->Y>0 &&
  1622. !ComboFI(this->X, this->Y-1, CF_NOBLOCKS) &&
  1623. NoSolidBlocks(1,this->X,this->Y,width,height)==true &&
  1624. pushcounter<distance
  1625. ){
  1626. if(pushcounter==0){ Game->PlaySound(SFX_PUSHBLOCK); }
  1627. if(pushcounter<distance/2){ NoAction(); }
  1628. if(pushcounter%4==0 && pushcounter!=0){ anitile-=4; }
  1629. if(anitile<0){ anitile=12; }
  1630. SetSolidCombo(1,this->X,this->Y,width,height,undercombo);
  1631. this->Vy=-pushspeed;
  1632. this->Data=originaltile+anitile;
  1633. pushcounter+=pushspeed;
  1634. Waitframe();
  1635. if(pushcounter%16==0){ SetUnderCombo(1,this->X,this->Y+16,width,height); }
  1636. }
  1637. this->Vy=0;
  1638. this->Data=originaltile;
  1639. pushcounter=0;
  1640. anitile=0;
  1641. SetSolidCombo(1,this->X,this->Y,width,height,this->Data);
  1642. }
  1643.  
  1644. framecounter=0;
  1645. }
  1646.  
  1647. Waitframe();
  1648. }
  1649. }
  1650. }
  1651.  
  1652.  
  1653. bool NoSolidBlocks(int direction, int xpos, int ypos, int width, int height){
  1654. int size=1;
  1655. if(direction==1 || direction==2){ size=width; } //Vertical pushing
  1656. if(direction==3 || direction==4){ size=height; } //Horizontal pushing
  1657.  
  1658. for(int i=size-1; i>=0; i--){
  1659. if(xpos%16==0 && ypos%16==0){
  1660. if(direction==1){ if(Screen->ComboS[ypos-16+((xpos+(i*16))>>4)]!=0000b){ return(false); } }
  1661. if(direction==2){ if(Screen->ComboS[ypos+16+((xpos+(i*16))>>4)]!=0000b){ return(false); } }
  1662. if(direction==3){ if(Screen->ComboS[ypos+(i*16)+((xpos-16)>>4)]!=0000b){ return(false); } }
  1663. if(direction==4){ if(Screen->ComboS[ypos+(i*16)+((xpos+16)>>4)]!=0000b){ return(false); } }
  1664. }
  1665. }
  1666. return(true);
  1667. }
  1668.  
  1669. int SetSolidCombo(int direction, int xpos, int ypos, int width, int height, int data){
  1670. int size=1;
  1671. if(direction==1 || direction==2){ size=width; } //Vertical pushing
  1672. if(direction==3 || direction==4){ size=height; } //Horizontal pushing
  1673.  
  1674. for(int i=size-1; i>=0; i--){
  1675. if(xpos%16==0 && ypos%16==0){
  1676. if(direction==1){ Screen->ComboD[ypos+((xpos+(i*16))>>4)]=data; }
  1677. if(direction==2){ Screen->ComboD[ypos+((xpos+(i*16))>>4)]=data; }
  1678. if(direction==3){ Screen->ComboD[ypos+(i*16)+(xpos>>4)]=data; }
  1679. if(direction==4){ Screen->ComboD[ypos+(i*16)+(xpos>>4)]=data; }
  1680. }
  1681. }
  1682. }
  1683.  
  1684. int SetUnderCombo(int direction, int xpos, int ypos, int width, int height){
  1685. int size=1;
  1686. if(direction==1 || direction==2){ size=width; } //Vertical pushing
  1687. if(direction==3 || direction==4){ size=height; } //Horizontal pushing
  1688.  
  1689. for(int i=size-1; i>=0; i--){
  1690. if(xpos%16==0 && ypos%16==0){
  1691. if(direction==1){ Screen->ComboD[ypos+((xpos+(i*16))>>4)]=GetLayerComboD(1,ComboAt(xpos+(i*16),ypos)); }
  1692. if(direction==2){ Screen->ComboD[ypos+((xpos+(i*16))>>4)]=GetLayerComboD(1,ComboAt(xpos+(i*16),ypos)); }
  1693. if(direction==3){ Screen->ComboD[ypos+(i*16)+(xpos>>4)]=GetLayerComboD(1,ComboAt(xpos,ypos+(i*16))); }
  1694. if(direction==4){ Screen->ComboD[ypos+(i*16)+(xpos>>4)]=GetLayerComboD(1,ComboAt(xpos,ypos+(i*16))); }
  1695. if(direction==1){ Screen->ComboT[ypos+((xpos+(i*16))>>4)]=GetLayerComboT(1,ComboAt(xpos+(i*16),ypos)); }
  1696. if(direction==2){ Screen->ComboT[ypos+((xpos+(i*16))>>4)]=GetLayerComboT(1,ComboAt(xpos+(i*16),ypos)); }
  1697. if(direction==3){ Screen->ComboT[ypos+(i*16)+(xpos>>4)]=GetLayerComboT(1,ComboAt(xpos,ypos+(i*16))); }
  1698. if(direction==4){ Screen->ComboT[ypos+(i*16)+(xpos>>4)]=GetLayerComboT(1,ComboAt(xpos,ypos+(i*16))); }
  1699. }
  1700. }
  1701. }
  1702.  
  1703.  
  1704. //Different Armos
  1705.  
  1706. ffc script differentArmos{
  1707. void run ( int newTile, int cset ){
  1708. while ( true ){
  1709. for ( int i = Screen->NumNPCs(); i > 0; i-- ){
  1710. npc enem = Screen->LoadNPC(i);
  1711. if ( enem->ID == NPC_ARMOS && (enem->Misc[15] & 0xf0000) == 0 ){ //check some flag...
  1712. enem->CSet = cset;
  1713. enem->OriginalTile = newTile;
  1714. enem->Misc[15] |= 0xf0000;
  1715. }
  1716. }
  1717. Waitframe();
  1718. }
  1719. }
  1720. }
  1721.  
  1722. //Perm Push Blocks
  1723.  
  1724. //Instructions:
  1725. //1. Make a new combo with inherent flag 16 (or any secret flag)
  1726. //2. Set this FFC to the above combo
  1727. //3. When secrets are triggered by blocks, this script will make it permanent
  1728. ffc script blockPermSecrets{
  1729. void run(){
  1730. int thisCombo = this->Data;
  1731. while(!Screen->State[ST_SECRET]){
  1732. if(this->Data != thisCombo) Screen->State[ST_SECRET] = true;
  1733. Waitframe();
  1734. }
  1735. }
  1736. }
  1737.  
  1738.  
  1739. //MogShop
  1740.  
  1741. const int MogShop_DefaultFailMessage = 1; // Default message to play when Link can't afford the item
  1742.  
  1743. const int MogShop_PriceTag = 1; // use 0 if you don't want to display price tags, otherwise use 1
  1744. const int MogShop_FontColour = 0x01; // colour of the price tag font (the 2 digits after "0x" is the code for your colour)
  1745. const int MogShop_FontOutline = 0x0F; // colour of the price tag font's outline
  1746. const int MogShop_FontType = 16; // which font to use (0 is the Z1 font, 16 is the LA font. you might have to look up std_constants.zh or just experiment)
  1747. const int MogShop_FontYOffset = -8; // positional offset of the price tag on the Y axis relative to the FFC
  1748.  
  1749. const int MogShop_SoldOutComboID = 1054; // ID of the combo for the FFC to be when the item is sold out (can't use 0)
  1750. const int MogShop_SoldOutComboCSet = 8; // CSet of the combo
  1751.  
  1752. const int MogShop_InteractComboID = 0; // ID of the combo to show above Link's head when he's standing in front of the item. Use 0 if you don't want any.
  1753. const int MogShop_InteractComboCSet = 8; // CSet of the combo
  1754.  
  1755. ffc script MogShop{
  1756. void run(int ShopItem, int InfoMessage, int Price, int Currency, int OnlyOnceID, int FailMessage, int CollisionStyle){
  1757. // Saves the width and height of the FFC for collision checks
  1758. int Width = 16;
  1759. int Height = 16;
  1760. if(this->EffectWidth!=16)
  1761. Width = this->EffectWidth;
  1762. else if(this->TileWidth>1)
  1763. Width = this->TileWidth*16;
  1764. if(this->EffectHeight!=16)
  1765. Height = this->EffectHeight;
  1766. else if(this->TileHeight>1)
  1767. Height = this->TileHeight*16;
  1768. // Determine collision check position
  1769. int HitX = this->X;
  1770. int HitY = this->Y;
  1771. if ( CollisionStyle != 0 )
  1772. HitY = this->Y + 8;
  1773.  
  1774. // Disable the shop if the item is sold out
  1775. int SoldOutComboID = MogShop_SoldOutComboID;
  1776. if ( SoldOutComboID < 0 )
  1777. SoldOutComboID = 1;
  1778. if ( OnlyOnceID >= 0 ) {
  1779. if ( Screen->D[OnlyOnceID] == 1 ) {
  1780. this->Data = SoldOutComboID;
  1781. this->CSet = MogShop_SoldOutComboCSet;
  1782. while(true){
  1783. DrawOverUpdate(this, HitX, HitY, CollisionStyle);
  1784. Waitframe();
  1785. }
  1786. }
  1787. }
  1788.  
  1789. // Determine currency
  1790. int CounterToUse = Currency;
  1791. if ( Currency <= 0 )
  1792. CounterToUse = 1;
  1793.  
  1794. // Create price tag string
  1795. int PriceTag[100];
  1796. itoa(PriceTag, Price);
  1797.  
  1798. // Determine price tag layer
  1799. int PriceTagLayer;
  1800. if ( CollisionStyle != 0 )
  1801. PriceTagLayer = 6;
  1802.  
  1803. while(true){
  1804. // Check collision with the item
  1805. bool CanInteract;
  1806. if ( LinkCanInteract() ) {
  1807. // Facing Up
  1808. if(Link->Dir==DIR_UP&&Link->Y>=HitY&&Link->Y<=HitY+Height-8&&Link->X>=HitX-8&&Link->X<=HitX+Width-8)
  1809. CanInteract = true;
  1810. else if ( CollisionStyle == 0 ) { // Only allow other directions when CollisionStyle is 0
  1811. // Facing Down
  1812. if(Link->Dir==DIR_DOWN&&Link->Y>=HitY-16&&Link->Y<=HitY+Height-16&&Link->X>=HitX-8&&Link->X<=HitX+Width-8)
  1813. CanInteract = true;
  1814. // Facing Left
  1815. else if(Link->Dir==DIR_LEFT&&Link->Y>=HitY-8&&Link->Y<=HitY+Height-9&&Link->X>=HitX&&Link->X<=HitX+Width)
  1816. CanInteract = true;
  1817. // Facing Right
  1818. else if(Link->Dir==DIR_RIGHT&&Link->Y>=HitY-8&&Link->Y<=HitY+Height-9&&Link->X>=HitX-16&&Link->X<=HitX+Width-16)
  1819. CanInteract = true;
  1820. }
  1821. }
  1822.  
  1823. DrawOverUpdate(this, HitX, HitY, CollisionStyle);
  1824.  
  1825. // Draw price tag
  1826. if ( MogShop_PriceTag == 1 ) {
  1827. Screen->DrawString(PriceTagLayer, this->X+8 +1, this->Y+MogShop_FontYOffset, MogShop_FontType, MogShop_FontOutline, -1, TF_CENTERED, PriceTag, OP_OPAQUE);
  1828. Screen->DrawString(PriceTagLayer, this->X+8 -1, this->Y+MogShop_FontYOffset, MogShop_FontType, MogShop_FontOutline, -1, TF_CENTERED, PriceTag, OP_OPAQUE);
  1829. Screen->DrawString(PriceTagLayer, this->X+8, this->Y+MogShop_FontYOffset +1, MogShop_FontType, MogShop_FontOutline, -1, TF_CENTERED, PriceTag, OP_OPAQUE);
  1830. Screen->DrawString(PriceTagLayer, this->X+8, this->Y+MogShop_FontYOffset -1, MogShop_FontType, MogShop_FontOutline, -1, TF_CENTERED, PriceTag, OP_OPAQUE);
  1831. Screen->DrawString(PriceTagLayer, this->X+8, this->Y+MogShop_FontYOffset, MogShop_FontType, MogShop_FontColour, -1, TF_CENTERED, PriceTag, OP_OPAQUE);
  1832. }
  1833.  
  1834. // Handle interaction
  1835. if ( CanInteract ) {
  1836. if ( Link->PressA ) {
  1837. Link->InputA = false;
  1838. Link->PressA = false;
  1839. Screen->Message(InfoMessage);
  1840. }
  1841. else if ( Link->PressR ) {
  1842. Link->InputR = false;
  1843. Link->PressR = false;
  1844.  
  1845. // Check if affordable
  1846. if ( Game->Counter[CounterToUse] >= Price && (CounterToUse != CR_LIFE || Game->Counter[CR_LIFE] - Price > 0) ) {
  1847. Game->DCounter[CounterToUse] -= Price;
  1848. item drop = CreateItemAt(ShopItem, Link->X, Link->Y);
  1849. SetItemPickup(drop, IP_HOLDUP, true);
  1850.  
  1851. if ( OnlyOnceID >= 0 ) { // Check if it can only be bought once
  1852. Screen->D[OnlyOnceID] = 1;
  1853. this->Data = SoldOutComboID;
  1854. this->CSet = MogShop_SoldOutComboCSet;
  1855. while(true){
  1856. DrawOverUpdate(this, HitX, HitY, CollisionStyle);
  1857. Waitframe();
  1858. }
  1859. }
  1860. }
  1861. else { // Can't afford
  1862. if ( FailMessage > 0 )
  1863. Screen->Message(FailMessage);
  1864. else
  1865. Screen->Message(MogShop_DefaultFailMessage);
  1866. }
  1867. }
  1868. else if ( MogShop_InteractComboID > 0 )
  1869. Screen->FastCombo(6, Link->X, Link->Y-16, MogShop_InteractComboID, MogShop_InteractComboCSet, OP_OPAQUE);
  1870. }
  1871. Waitframe();
  1872. }
  1873. }
  1874. bool LinkCanInteract(){
  1875. if ( Link->Action != LA_NONE && Link->Action != LA_WALKING )
  1876. return false;
  1877. if ( Link->Z > 0 )
  1878. return false;
  1879. return true;
  1880. }
  1881. void DrawOverUpdate(ffc this, int HitX, int HitY, int CollisionStyle){
  1882. // Toggle draw-over if CollisionStyle is not 0
  1883. if ( CollisionStyle != 0 ) {
  1884. if ( Link->Y < HitY )
  1885. this->Flags[FFCF_OVERLAY] = true;
  1886. else
  1887. this->Flags[FFCF_OVERLAY] = false;
  1888. }
  1889. }
  1890. }
  1891.  
  1892. //Don't move - Character Direction Script
  1893.  
  1894. //Character Direction Script
  1895.  
  1896. ffc script dontMove{
  1897. void run(int dir){
  1898. while(true){
  1899. Link->Dir = dir;
  1900. WaitNoAction();
  1901. }
  1902. }
  1903. }
  1904.  
  1905. //PlaySound
  1906.  
  1907. //Trigger SFX Script
  1908.  
  1909. ffc script TriggerSFX{
  1910. void run(int sfx){
  1911. int loc = ComboAt(this->X,this->Y);
  1912. int orig = Screen->ComboD[loc];
  1913. while(Screen->ComboD[loc] == orig) Waitframe();
  1914. Game->PlaySound(sfx);
  1915. }
  1916. }
  1917.  
  1918.  
  1919. //SFX On Screen Entry
  1920.  
  1921. // D0 - The SFX ID that you want to play.
  1922. ffc script OnEntrySound{
  1923.  
  1924. void run(int sfx){
  1925.  
  1926. // Play the sound effect.
  1927. Game->PlaySound(sfx);
  1928.  
  1929. // Quit the script.
  1930. Quit();
  1931. }
  1932.  
  1933. }
  1934.  
  1935. //True Push Block Under Combo
  1936.  
  1937. //D0: If D0 >0, set to the map to use as reference for under combos
  1938. //D1: If D0 >0, set to the screen to use as reference for under combos (convert screen numbers from Hex to Decimal)
  1939. ffc script TruePushblockUnderCombo{
  1940. void run(int refMap, int refScreen){
  1941. int i;
  1942. int pos;
  1943. int cd; int cc; int cf; int ci;
  1944. int pushBlockX;
  1945. int pushBlockY;
  1946. bool wasPushBlock; //Keeps track of whether a push block has started moving
  1947.  
  1948. int underCMB[176];
  1949. int underCS[176];
  1950. int underFlag[176];
  1951.  
  1952. //Mark which flags are push blocks
  1953. bool pushFlags[105];
  1954. pushFlags[CF_PUSHUPDOWN] = true;
  1955. pushFlags[CF_PUSH4WAY] = true;
  1956. pushFlags[CF_PUSHLR] = true;
  1957. pushFlags[CF_PUSHUP] = true;
  1958. pushFlags[CF_PUSHDOWN] = true;
  1959. pushFlags[CF_PUSHLEFT] = true;
  1960. pushFlags[CF_PUSHRIGHT] = true;
  1961. pushFlags[CF_PUSHUPDOWNNS] = true;
  1962. pushFlags[CF_PUSHLEFTRIGHTNS] = true;
  1963. pushFlags[CF_PUSH4WAYNS] = true;
  1964. pushFlags[CF_PUSHUPNS] = true;
  1965. pushFlags[CF_PUSHDOWNNS] = true;
  1966. pushFlags[CF_PUSHLEFTNS] = true;
  1967. pushFlags[CF_PUSHRIGHTNS] = true;
  1968. pushFlags[CF_PUSHUPDOWNINS] = true;
  1969. pushFlags[CF_PUSHLEFTRIGHTINS] = true;
  1970. pushFlags[CF_PUSH4WAYINS] = true;
  1971. pushFlags[CF_PUSHUPINS] = true;
  1972. pushFlags[CF_PUSHDOWNINS] = true;
  1973. pushFlags[CF_PUSHLEFTINS] = true;
  1974. pushFlags[CF_PUSHRIGHTINS] = true;
  1975.  
  1976. //Set initial values for all combos on the screen
  1977. for(i=0; i<176; i++){
  1978. cd = Screen->ComboD[i];
  1979. cc = Screen->ComboC[i];
  1980. cf = Screen->ComboF[i];
  1981. ci = Screen->ComboI[i];
  1982. //Set combos underneath a push block
  1983. if(pushFlags[cf] || pushFlags[ci]){
  1984. //If a reference screen is set, draw from that
  1985. if(refMap>0){
  1986. underCMB[i] = Game->GetComboData(refMap, refScreen, i);
  1987. underCS[i] = Game->GetComboCSet(refMap, refScreen, i);
  1988. underFlag[i] = Game->GetComboFlag(refMap, refScreen, i);
  1989. }
  1990. //Otherwise use under combo
  1991. else{
  1992. underCMB[i] = Screen->UnderCombo;
  1993. underCS[i] = Screen->UnderCSet;
  1994. underFlag[i] = 0;
  1995. }
  1996. }
  1997. else{
  1998. underCMB[i] = cd;
  1999. underCS[i] = cc;
  2000. underFlag[i] = cf;
  2001. }
  2002. }
  2003.  
  2004. while(true){
  2005. //If there's a push block on the screen, manage undercombos
  2006. if(Screen->MovingBlockX>-1){
  2007. //If the block just started moving, set the undercombo
  2008. if(!wasPushBlock){
  2009. pos = ComboAt(Screen->MovingBlockX+8, Screen->MovingBlockY+8);
  2010. Screen->ComboD[pos] = underCMB[pos];
  2011. Screen->ComboC[pos] = underCS[pos];
  2012. Screen->ComboF[pos] = underFlag[pos];
  2013. }
  2014. pushBlockX = Screen->MovingBlockX;
  2015. pushBlockY = Screen->MovingBlockY;
  2016. wasPushBlock = true;
  2017. }
  2018. else{
  2019. wasPushBlock = false;
  2020.  
  2021. for(i=0; i<176; i++){
  2022. cd = Screen->ComboD[i];
  2023. cc = Screen->ComboC[i];
  2024. cf = Screen->ComboF[i];
  2025. ci = Screen->ComboI[i];
  2026. //Only update combos in the array if they aren't covered by a push block
  2027. if(!(pushFlags[cf] || pushFlags[ci])){
  2028. underCMB[i] = cd;
  2029. underCS[i] = cc;
  2030. underFlag[i] = cf;
  2031. }
  2032. }
  2033. }
  2034. Waitframe();
  2035. }
  2036. }
  2037. }
  2038.  
  2039. //Item Bundle Script
  2040.  
  2041. // This script is a pickup script that will give some items.
  2042. // This was mostly made to bundle the Bow and Arrows into one item,
  2043. // but it could have other uses.
  2044. // Bundle this with an item that increases a counter to also increase counters.
  2045. // D0-D7: Items to give.
  2046. // D0: If D0 is negative, it will display an item pickup message containing the positive version of the number entered...
  2047. item script itemBundle{
  2048. void run(int item1, int item2, int item3, int item4, int item5, int item6, int item7, int item8)
  2049. {
  2050. if(item1 > 0)
  2051. Link->Item[item1] = true;
  2052. if(item2 > 0)
  2053. Link->Item[item2] = true;
  2054. if(item3 > 0)
  2055. Link->Item[item3] = true;
  2056. if(item4 > 0)
  2057. Link->Item[item4] = true;
  2058. if(item5 > 0)
  2059. Link->Item[item5] = true;
  2060. if(item6 > 0)
  2061. Link->Item[item6] = true;
  2062. if(item7 > 0)
  2063. Link->Item[item7] = true;
  2064. if(item8 > 0)
  2065. Link->Item[item8] = true;
  2066.  
  2067. // Display Item pickup message?
  2068. if(item1 < 0)
  2069. {
  2070. Screen->Message(item1 * -1);
  2071. }
  2072. }//!End void run()
  2073. }//!End item script itemBundle
  2074.  
  2075. //TieredItemPickup
  2076.  
  2077. item script TieredItemPickup{
  2078. void run(int lowTier, int secondTier, int thirdTier, int fourthTier, int fifthTier, int sixthTier, int highTier, int m){
  2079. if (Link->Item[sixthTier]){
  2080. Link->Item[highTier] = true;
  2081. Screen->Message(m);
  2082. }
  2083. else if (Link->Item[fifthTier]){
  2084. Link->Item[sixthTier] = true;
  2085. Screen->Message(m);
  2086. }
  2087. else if (Link->Item[fourthTier]){
  2088. Link->Item[fifthTier] = true;
  2089. Screen->Message(m);
  2090. }
  2091. else if (Link->Item[thirdTier]){
  2092. Link->Item[fourthTier] = true;
  2093. Screen->Message(m);
  2094. }
  2095. else if (Link->Item[secondTier]){
  2096. Link->Item[thirdTier] = true;
  2097. Screen->Message(m);
  2098. }
  2099. else if (Link->Item[lowTier]){
  2100. Link->Item[secondTier] = true;
  2101. Screen->Message(m);
  2102. }
  2103. else {
  2104. Link->Item[lowTier]= true;
  2105. Screen->Message(m);
  2106. }
  2107. }
  2108. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement