Advertisement
Guest User

Untitled

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