Advertisement
HylianWhovian

Untitled

Jan 6th, 2020
292
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 152.92 KB | None | 0 0
  1. import "std.zh"
  2. import "Great.zh"
  3.  
  4. ffc script stepMsg
  5. {
  6. void run(int m, int sens)
  7. {
  8. if ( !sens ) sens = 8;
  9. while(1)
  10. {
  11. if ( DistX(this, sens) )
  12. {
  13. if ( DistY(this, sens) )
  14. {
  15. break;
  16. }
  17. }
  18. Waitframe();
  19. }
  20. Screen->Message(m);
  21. }
  22. }
  23. ffc script EnemyMusic
  24. {
  25. void run(int bmidi, int nmidi)
  26. {
  27. while(true)
  28. {
  29. if (Screen->NumNPCs() != 0)
  30. {
  31. Game->PlayMIDI(bmidi);
  32. }
  33. else
  34. {
  35. Game->PlayMIDI(nmidi);
  36. }
  37. Waitframe();
  38. }
  39. }
  40. }
  41.  
  42. const int EQ_QUAKE_TIME = 90;
  43.  
  44. ffc script Earthquake
  45. {
  46. void run(int wait)
  47. {
  48. Waitframes(wait);
  49. Screen->Quake = EQ_QUAKE_TIME;
  50. Link->SwordJinx = EQ_QUAKE_TIME;
  51. Link->ItemJinx = EQ_QUAKE_TIME;
  52. }
  53. }
  54. item script itemBundle
  55. {
  56. void run(int item1, int item2, int item3, int item4, int item5, int item6, int item7, int item8)
  57. {
  58. if(item1 > 0)
  59. Link->Item[item1] = true;
  60. if(item2 > 0)
  61. Link->Item[item2] = true;
  62. if(item3 > 0)
  63. Link->Item[item3] = true;
  64. if(item4 > 0)
  65. Link->Item[item4] = true;
  66. if(item5 > 0)
  67. Link->Item[item5] = true;
  68. if(item6 > 0)
  69. Link->Item[item6] = true;
  70. if(item7 > 0)
  71. Link->Item[item7] = true;
  72. if(item8 > 0)
  73. Link->Item[item8] = true;
  74.  
  75. // Display Item pickup message?
  76. if(item1 < 0)
  77. {
  78. Screen->Message(item1 * -1);
  79. }
  80. }//!End void run()
  81. }//!End item script itemBundle
  82.  
  83. bool OnPlatform (ffc this){
  84. if(CenterLinkX() < this->X) return false;
  85. else if(CenterLinkX() >= this->X + this->EffectWidth) return false;
  86. else if(CenterLinkY() < this->Y) return false;
  87. else if(CenterLinkY() >= this->Y + this->EffectHeight) return false;
  88. else return true;
  89. }
  90.  
  91.  
  92. ffc script PermanentTieredSecrets
  93. {
  94. void run(int D, int Layer, int NumStates){
  95. //Triggers the number of screen secrets stored in Screen->D when you enter the screen
  96. if(Screen->D[D]>0){
  97. for(int i=0; i<Screen->D[D]; i++){
  98. Screen->TriggerSecrets();
  99. }
  100. }
  101. //Saves the combo position and combo under the FFC
  102. int ComboPos = ComboAt(this->X+8, this->Y+8);
  103. int Combo;
  104. if(Layer>0)
  105. Combo = GetLayerComboD(Layer, ComboPos);
  106. else if(Layer==0)
  107. Combo = Screen->ComboD[ComboPos];
  108. while(true){
  109. //Detects if the combo under the FFC changes and increases Screen->D
  110. if(Layer>0&&GetLayerComboD(Layer, ComboPos)!=Combo){
  111. Combo = GetLayerComboD(Layer, ComboPos);
  112. Screen->D[D]++;
  113. }
  114. else if(Layer==0&&Screen->ComboD[ComboPos]!=Combo){
  115. Combo = Screen->ComboD[ComboPos];
  116. Screen->D[D]++;
  117. }
  118. //Wraps Screen->D if NumStates is set, otherwise caps Screen->D at 100
  119. if(NumStates>0&&Screen->D[D]>=NumStates)
  120. Screen->D[D] -= NumStates;
  121. else if(NumStates==0&&Screen->D[D]>100){
  122. Screen->D[D] = 100;
  123. }
  124. Waitframe();
  125. }
  126. }
  127. }
  128.  
  129. const int CUTSCENETRIGGER_SHOW_HITBOXES = 0; //For debugging problems with the script's hitboxes, set this to 1.
  130. const int C_CUTSCENETRIGGER_HITBOX = 0x01; //Color for the debug hitboxes
  131.  
  132. const int D_CUTSCENETRIGGER = 0; //Screen->D used for cutscene triggers
  133.  
  134. //D0: The DMap to warp to for the cutscene
  135. //D1: The screen to warp to IN DECIMAL. Screens in ZQuest are numbered in hex but FFCs only take arguments
  136. // in decimal, so you'll have to convert.
  137. //D2: Width of the trigger hitbox
  138. //D3: Height of the trigger hitbox
  139. //D4: Set this to a number 1-17 to make the cutscene only play once. By giving FFCs different D4 arguments,
  140. // you can have multiple triggers for different permanent cutscenes on a screen.
  141. //D5: If you want the trigger to check for a flag under Link, set this to the number of the flag.
  142. // If you want it to check for an item, set this to a negative Item ID.
  143. //D6: The X position to try to walk Link to. 0 for no target point.
  144. //D7: The Y position to try to walk Link to. 0 for no target point.
  145. ffc script CutsceneTrigger{
  146. void run(int newDMap, int newScreen, int w, int h, int oneUse, int checkItemorFlag, int targetX, int targetY){
  147. int dbit;
  148. if(oneUse>0){
  149. dbit = 1<<(oneUse-1);
  150. }
  151. //If Link starts standing on the cutscene hitbox, wait for him to step off
  152. while(Link->X+8 >= this->X && Link->X+8 <= this->X+w-1 && Link->Y+12 >= this->Y && Link->Y+12 <= this->Y+h-1 ){
  153. if(CUTSCENETRIGGER_SHOW_HITBOXES){
  154. Screen->Rectangle(6, this->X-1, this->Y-1, this->X+w-1+1, this->Y+h-1+1, C_CUTSCENETRIGGER_HITBOX, 1, 0, 0, 0, false, 64);
  155. Screen->Rectangle(6, this->X, this->Y, this->X+w-1, this->Y+h-1, C_CUTSCENETRIGGER_HITBOX, 1, 0, 0, 0, false, 128);
  156. Screen->Rectangle(6, this->X+1, this->Y+1, this->X+w-1-1, this->Y+h-1-1, C_CUTSCENETRIGGER_HITBOX, 1, 0, 0, 0, true, 64);
  157. }
  158. Waitframe();
  159. }
  160. //Check if the cutscene has already been triggered
  161. if(oneUse&&Screen->D[D_CUTSCENETRIGGER]&dbit){
  162. Quit();
  163. }
  164. while(true){
  165. if(CUTSCENETRIGGER_SHOW_HITBOXES){
  166. Screen->Rectangle(6, this->X-1, this->Y-1, this->X+w-1+1, this->Y+h-1+1, C_CUTSCENETRIGGER_HITBOX, 1, 0, 0, 0, false, 64);
  167. Screen->Rectangle(6, this->X, this->Y, this->X+w-1, this->Y+h-1, C_CUTSCENETRIGGER_HITBOX, 1, 0, 0, 0, false, 128);
  168. Screen->Rectangle(6, this->X+1, this->Y+1, this->X+w-1-1, this->Y+h-1-1, C_CUTSCENETRIGGER_HITBOX, 1, 0, 0, 0, false, 64);
  169. }
  170. //Find if Link has collided with the trigger hitbox
  171. if(Link->X+8 >= this->X && Link->X+8 <= this->X+w-1 && Link->Y+12 >= this->Y && Link->Y+12 <= this->Y+h-1 ){
  172. if(CUTSCENETRIGGER_SHOW_HITBOXES){
  173. Screen->Rectangle(6, this->X+2, this->Y+2, this->X+w-1-2, this->Y+h-1-2, C_CUTSCENETRIGGER_HITBOX, 1, 0, 0, 0, true, 64);
  174. }
  175. //If Link meets one the requirements to trigger the cutscene, break out of the loop
  176. if(checkItemorFlag==0){
  177. break;
  178. }
  179. //If the checkItemorFlag argument is negative, check for an item
  180. else if(checkItemorFlag<0){
  181. if(Link->Item[Abs(checkItemorFlag)])
  182. break;
  183. }
  184. //Else check for a screen flag
  185. else if(ComboFI(Link->X+8, Link->Y+12, checkItemorFlag)){
  186. break;
  187. }
  188. }
  189. Waitframe();
  190. }
  191. if(targetX>0||targetY>0){
  192. //Move Link either until he's in position or 4 seconds have passed
  193. for(int i=0; i<=240&&(Link->X!=targetX||Link->Y!=targetY); i++){
  194. //Prevent moving around while moving Link into position
  195. Link->InputStart = false; Link->PressStart = false;
  196. Link->InputMap = false; Link->PressMap = false;
  197. NoAction();
  198.  
  199. //Apply inputs that should be active
  200. if(Abs(Link->X-targetX)<=2){
  201. Link->X = targetX;
  202. }
  203. else{
  204. if(Link->X<targetX)
  205. Link->InputRight = true;
  206. else if(Link->X>targetX)
  207. Link->InputLeft = true;
  208. }
  209. if(Abs(Link->Y-targetY)<=2){
  210. Link->Y = targetY;
  211. }
  212. else{
  213. if(Link->Y<targetY)
  214. Link->InputDown = true;
  215. else if(Link->Y>targetY)
  216. Link->InputUp = true;
  217. }
  218. Waitframe();
  219. }
  220. }
  221. if(oneUse){
  222. Screen->D[D_CUTSCENETRIGGER] |= dbit;
  223. }
  224. Link->PitWarp(newDMap, newScreen);
  225. }
  226. }
  227.  
  228. int MooshPit[16];
  229. const int _MP_LASTX = 0;
  230. const int _MP_LASTY = 1;
  231. const int _MP_LASTDMAP = 2;
  232. const int _MP_LASTSCREEN = 3;
  233. const int _MP_ENTRYX = 4;
  234. const int _MP_ENTRYY = 5;
  235. const int _MP_ENTRYDMAP = 6;
  236. const int _MP_ENTRYSCREEN = 7;
  237. const int _MP_FALLX = 8;
  238. const int _MP_FALLY = 9;
  239. const int _MP_FALLTIMER = 10;
  240. const int _MP_FALLSTATE = 11;
  241. const int _MP_DAMAGETYPE = 12;
  242. const int _MP_SLIDETIMER = 13;
  243.  
  244. const int MOOSHPIT_NO_GRID_SNAP = 1; //Set to 1 to prevent Link's falling sprite from snapping to the combo grid.
  245. const int MOOSHPIT_ENABLE_SLIDEYPITS = 1; //Set to 1 if Link should slide into pits he's partially on
  246. const int MOOSHPIT_NO_MOVE_WHILE_FALLING = 1; //Set to 1 if you don't want Link able to move while falling
  247. 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
  248. const int MOOSHPIT_STUN_ENEMIES_WHILE_FALLING = 1; //Set to 1 to stun stunnable enemies while falling in a pit
  249.  
  250. const int CT_HOLELAVA = 128;
  251. const int CF_LAVA = 122;
  252.  
  253. const int SPR_FALLHOLE = 126; //Sprite for Link falling in a hole
  254. const int SPR_FALLLAVA = 99; //Sprite for Link falling in lava
  255.  
  256. const int SFX_FALLHOLE = 38; //Sound for falling in a hole
  257. const int SFX_FALLLAVA = 85; //Sound for falling in lava
  258.  
  259. const int DAMAGE_FALLHOLE = 8; //How much damage pits deal (1/2 heart default)
  260. const int DAMAGE_FALLLAVA = 16; //How much damage lava deals (1 heart default)
  261.  
  262. const int FFC_MOOSHPIT_AUTOWARPA = 32;
  263. const int CMB_MOOSHPIT_AUTOWARPA = 2891;
  264. const int SF_MISC_MOOSHPITWARP = 2;
  265.  
  266. const int MOOSHPIT_MIN_FALL_TIME = 60; //Minimum time for the pit's fall animation, to prevent repeated falling in pits
  267. const int MOOSHPIT_EXTRA_FALL_TIME = 0; //Extra frames at the end of the falling animation before Link respawns
  268.  
  269. //Width and height of Link's hitbox for colliding with pits
  270. const int MOOSHPIT_LINKHITBOXWIDTH = 16;
  271. const int MOOSHPIT_LINKHITBOXHEIGHT = 16;
  272.  
  273. //Width and height of Link's hitbox for colliding with pits/lava in sideview
  274. const int MOOSHPIT_SIDEVIEW_LINKHITBOXWIDTH = 2;
  275. const int MOOSHPIT_SIDEVIEW_LINKHITBOXHEIGHT = 2;
  276.  
  277. const int MOOSHPIT_SLIDEYPIT_FREQ = 3; //Link will be pushed into slideypits every 1/n frames
  278. const int MOOSHPIT_SLIDEYPIT_MAXTIME = 20; //Link will be pushed into slideypits more intensely after n frames
  279. const int MOOSHPIT_SLIDEYPIT_ACCELFREQ = 8; //How often Link accelerates when falling in the pit
  280.  
  281. int MooshPit_OnPit(int LinkX, int LinkY, bool countFFCs){
  282. if(Link->Action==LA_FROZEN||Link->Action==LA_RAFTING||Link->Action==LA_INWIND)
  283. return -1;
  284.  
  285. if(countFFCs){
  286. if(MooshPit_OnFFC(LinkX, LinkY))
  287. return -1;
  288. }
  289.  
  290. bool sideview;
  291. if(Screen->Flags[SF_ROOMTYPE]&100b)
  292. sideview = true;
  293. //wew lad
  294. int width = MOOSHPIT_LINKHITBOXWIDTH;
  295. int height = MOOSHPIT_LINKHITBOXHEIGHT;
  296.  
  297. int total;
  298. int solidTotal;
  299.  
  300. for(int x=0; x<=1; x++){
  301. for(int y=0; y<=1; y++){
  302. int X; int Y;
  303. if(sideview){ //Hitbox functions differently in sideview
  304. width = MOOSHPIT_SIDEVIEW_LINKHITBOXWIDTH;
  305. height = MOOSHPIT_SIDEVIEW_LINKHITBOXHEIGHT;
  306. X = Floor(LinkX+7-width/2+(width-1)*x)+1;
  307. Y = Floor(LinkY+7-height/2+(height-1)*y)+1;
  308. }
  309. else{
  310. X = Floor(LinkX+7-width/2+(width-1)*x)+1;
  311. Y = Floor(LinkY+11-height/2+(height-1)*y)+1;
  312. }
  313.  
  314. //If one corner of Link's hitbox is on a pit, flag that corner as covered
  315. if(Screen->ComboT[ComboAt(X, Y)]==CT_HOLELAVA){
  316. total |= 1<<(1+(x+y*2));
  317. }
  318. //If Link is on a solid combo, count that corner as a pit
  319. if(Screen->isSolid(X, Y)){
  320. solidTotal |= 1<<(x+y*2);
  321. }
  322. }
  323. }
  324. if(total>0) //Assuming Link is on at least one actual pit, add up the solid and nonsolid pits
  325. return (total>>1)|(solidTotal<<4);
  326. return -1;
  327. }
  328.  
  329. bool MooshPit_OnFFC(int LinkX, int LinkY){
  330. for(int i=1; i<=32; i++){ //Cycle through every FFC
  331. ffc f = Screen->LoadFFC(i);
  332. //Check if the FFC is solid
  333. if(f->Data>0&&!f->Flags[FFCF_CHANGER]&&!f->Flags[FFCF_ETHEREAL]){
  334. //Check if Link collides with the FFC
  335. if(RectCollision(LinkX+4, LinkY+9, LinkX+11, LinkY+14, f->X, f->Y, f->X+f->EffectWidth-1, f->Y+f->EffectHeight-1)){
  336. return true;
  337. }
  338. }
  339. }
  340. //If Link doesn't collide with any FFC, return false
  341. return false;
  342. }
  343.  
  344. void MooshPit_StunEnemies(){
  345. for(int i=Screen->NumNPCs(); i>=1; i--){ //Cycle through every enemy
  346. npc n = Screen->LoadNPC(i);
  347. //Make it so the enemy's stun never falls below 1
  348. n->Stun = Max(n->Stun, 1);
  349. }
  350. }
  351.  
  352. void MooshPit_Init(){
  353. MooshPit[_MP_LASTX] = Link->X;
  354. MooshPit[_MP_LASTY] = Link->Y;
  355. MooshPit[_MP_LASTDMAP] = Game->GetCurDMap();
  356. MooshPit[_MP_LASTSCREEN] = Game->GetCurDMapScreen();
  357. MooshPit[_MP_ENTRYX] = Link->X;
  358. MooshPit[_MP_ENTRYY] = Link->Y;
  359. MooshPit[_MP_ENTRYDMAP] = Game->GetCurDMap();
  360. MooshPit[_MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  361. MooshPit[_MP_FALLSTATE] = 0;
  362. MooshPit[_MP_FALLTIMER] = 0;
  363. Link->CollDetection = true;
  364. Link->Invisible = false;
  365. }
  366.  
  367. void MooshPit_Update(){
  368. int i;
  369. bool isWarp;
  370. if(Screen->Flags[SF_MISC]&(1<<SF_MISC_MOOSHPITWARP))
  371. isWarp = true;
  372.  
  373. bool sideview;
  374. if(Screen->Flags[SF_ROOMTYPE]&100b)
  375. sideview = true;
  376.  
  377. if(Link->Action!=LA_SCROLLING){
  378. //Update the entry point whenever the screen changes
  379. if(MooshPit[_MP_ENTRYDMAP]!=Game->GetCurDMap()||MooshPit[_MP_ENTRYSCREEN]!=Game->GetCurDMapScreen()){
  380. MooshPit[_MP_ENTRYX] = Link->X;
  381. MooshPit[_MP_ENTRYY] = Link->Y;
  382. MooshPit[_MP_ENTRYDMAP] = Game->GetCurDMap();
  383. MooshPit[_MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  384. }
  385.  
  386. if(MooshPit[_MP_FALLSTATE]==0){ //Not falling in pit
  387. int onPit = MooshPit_OnPit(Link->X, Link->Y, true);
  388. //Check if slidey pits are enabled and it's not sideview
  389. if(MOOSHPIT_ENABLE_SLIDEYPITS&&!IsSideview()){
  390. if(Link->Z<=0&&onPit>-1){ //If Link is partially on a pit
  391. int slideVx; int slideVy;
  392. int reps = 1;
  393. //Check if it's a frame Link should be moved
  394. if(MooshPit[_MP_SLIDETIMER]%MOOSHPIT_SLIDEYPIT_FREQ==0||MooshPit[_MP_SLIDETIMER]>=MOOSHPIT_SLIDEYPIT_MAXTIME){
  395. if((onPit&0111b)==0111b){ //Going up-left
  396. slideVx = -1;
  397. slideVy = -1;
  398. }
  399. else if((onPit&1011b)==1011b){ //Going up-right
  400. slideVx = 1;
  401. slideVy = -1;
  402. }
  403. else if((onPit&1101b)==1101b){ //Going down-left
  404. slideVx = -1;
  405. slideVy = 1;
  406. }
  407. else if((onPit&1110b)==1110b){ //Going down-right
  408. slideVx = 1;
  409. slideVy = 1;
  410. }
  411. else if((onPit&0011b)==0011b){ //Going up
  412. slideVy = -1;
  413. }
  414. else if((onPit&1100b)==1100b){ //Going down
  415. slideVy = 1;
  416. }
  417. else if((onPit&0101b)==0101b){ //Going left
  418. slideVx = -1;
  419. }
  420. else if((onPit&1010b)==1010b){ //Going right
  421. slideVx = 1;
  422. }
  423. else if((onPit&0001b)==0001b){ //Going up-left
  424. slideVx = -1;
  425. slideVy = -1;
  426. }
  427. else if((onPit&0010b)==0010b){ //Going up-right
  428. slideVx = 1;
  429. slideVy = -1;
  430. }
  431. else if((onPit&0100b)==0100b){ //Going down-left
  432. slideVx = -1;
  433. slideVy = 1;
  434. }
  435. else if((onPit&1000b)==1000b){ //Going down-right
  436. slideVx = 1;
  437. slideVy = 1;
  438. }
  439.  
  440. //DEBUG DRAWS
  441. //VX
  442. // Screen->DrawInteger(6, 0, 0, FONT_Z1, 0x01, 0x0F, -1, -1, slideVx, 0, 128);
  443. //VY
  444. // Screen->DrawInteger(6, 0, 8, FONT_Z1, 0x01, 0x0F, -1, -1, slideVy, 0, 128);
  445. //ONPIT BITS
  446. // Screen->DrawInteger(6, 0, 16, FONT_Z1, 0x01, 0x0F, -1, -1, (onPit&1000b)>>3, 0, 128);
  447. // Screen->DrawInteger(6, 8, 16, FONT_Z1, 0x01, 0x0F, -1, -1, (onPit&0100b)>>2, 0, 128);
  448. // Screen->DrawInteger(6, 16, 16, FONT_Z1, 0x01, 0x0F, -1, -1, (onPit&0010b)>>1, 0, 128);
  449. // Screen->DrawInteger(6, 24, 16, FONT_Z1, 0x01, 0x0F, -1, -1, (onPit&0001b), 0, 128);
  450.  
  451. //If Link is over the max slide time, increase the speed every 4 frames
  452. if(MooshPit[_MP_SLIDETIMER]>=MOOSHPIT_SLIDEYPIT_MAXTIME)
  453. reps += Floor((MooshPit[_MP_SLIDETIMER]-MOOSHPIT_SLIDEYPIT_MAXTIME)/MOOSHPIT_SLIDEYPIT_ACCELFREQ);
  454. }
  455.  
  456. for(i=0; i<reps; i++){
  457. if(slideVx<0&&CanWalk(Link->X, Link->Y, DIR_LEFT, 1, false)){
  458. Link->X--;
  459. }
  460. else if(slideVx>0&&CanWalk(Link->X, Link->Y, DIR_RIGHT, 1, false)){
  461. Link->X++;
  462. }
  463. if(slideVy<0&&CanWalk(Link->X, Link->Y, DIR_UP, 1, false)){
  464. Link->Y--;
  465. }
  466. else if(slideVy>0&&CanWalk(Link->X, Link->Y, DIR_DOWN, 1, false)){
  467. Link->Y++;
  468. }
  469. }
  470. MooshPit[_MP_SLIDETIMER]++;
  471. }
  472. else{
  473. MooshPit[_MP_SLIDETIMER] = 0;
  474. }
  475. }
  476. if(onPit>-1){
  477. //Combine solid combo bits with pit bits
  478. onPit |= (onPit>>4);
  479. //Remove non pit bits
  480. onPit &= 1111b;
  481. }
  482. if(Link->Z<=0&&onPit==15){ //If Link steps on a pit
  483. int underLink;
  484. if(!sideview){
  485. underLink = ComboAt(Link->X+8, Link->Y+12);
  486. if(Screen->ComboT[underLink]!=CT_HOLELAVA){
  487. for(i=0; i<4; i++){
  488. underLink = ComboAt(Link->X+15*(i%2), Link->Y+8+7*Floor(i/2));
  489. if(Screen->ComboT[underLink]==CT_HOLELAVA)
  490. break;
  491. }
  492. }
  493. }
  494. else{
  495. underLink = ComboAt(Link->X+8, Link->Y+8);
  496. if(Screen->ComboT[underLink]!=CT_HOLELAVA){
  497. for(i=0; i<4; i++){
  498. underLink = ComboAt(Link->X+15*(i%2), Link->Y+15*Floor(i/2));
  499. if(Screen->ComboT[underLink]==CT_HOLELAVA)
  500. break;
  501. }
  502. }
  503. }
  504.  
  505. lweapon fall;
  506.  
  507. //Check if the combo is lava
  508. if(ComboFI(underLink, CF_LAVA)){
  509. //Play sound and display animation
  510. Game->PlaySound(SFX_FALLLAVA);
  511. fall = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
  512. if(!MOOSHPIT_NO_GRID_SNAP){
  513. fall->X = ComboX(underLink);
  514. fall->Y = ComboY(underLink);
  515. }
  516. fall->UseSprite(SPR_FALLLAVA);
  517. fall->CollDetection = false;
  518. fall->DeadState = fall->ASpeed*fall->NumFrames;
  519.  
  520. //Mark as lava damage
  521. MooshPit[_MP_DAMAGETYPE] = 1;
  522. }
  523. //Otherwise it's a pit
  524. else{
  525. //Play sound and display animation
  526. Game->PlaySound(SFX_FALLHOLE);
  527. fall = CreateLWeaponAt(LW_SCRIPT10, Link->X, Link->Y);
  528. if(!MOOSHPIT_NO_GRID_SNAP){
  529. fall->X = ComboX(underLink);
  530. fall->Y = ComboY(underLink);
  531. if(isWarp){
  532. Link->X = ComboX(underLink);
  533. Link->Y = ComboY(underLink);
  534. }
  535. }
  536. fall->UseSprite(SPR_FALLHOLE);
  537. fall->CollDetection = false;
  538. fall->DeadState = fall->ASpeed*fall->NumFrames;
  539.  
  540. //Mark as hole damage
  541. MooshPit[_MP_DAMAGETYPE] = 0;
  542. }
  543.  
  544. MooshPit[_MP_FALLX] = Link->X;
  545. MooshPit[_MP_FALLY] = Link->Y;
  546.  
  547. //Cooldown should last as long as the fall animation
  548. MooshPit[_MP_FALLSTATE] = 1;
  549. MooshPit[_MP_FALLTIMER] = Max(MOOSHPIT_MIN_FALL_TIME, fall->DeadState+MOOSHPIT_EXTRA_FALL_TIME);
  550.  
  551. //Render Link invisible and intangible
  552. Link->Invisible = true;
  553. Link->CollDetection = false;
  554.  
  555. NoAction();
  556. }
  557. 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
  558. if(sideview){
  559. //Link has no Z value in sideview, so we check if he's on a platform instead
  560. if(OnSidePlatform(Link->X, Link->Y)){
  561. MooshPit[_MP_LASTDMAP] = Game->GetCurDMap();
  562. MooshPit[_MP_LASTSCREEN] = Game->GetCurDMapScreen();
  563. MooshPit[_MP_LASTX] = Link->X;
  564. MooshPit[_MP_LASTY] = Link->Y;
  565. }
  566. }
  567. else{
  568. if(Link->Z<=0){
  569. MooshPit[_MP_LASTDMAP] = Game->GetCurDMap();
  570. MooshPit[_MP_LASTSCREEN] = Game->GetCurDMapScreen();
  571. MooshPit[_MP_LASTX] = Link->X;
  572. MooshPit[_MP_LASTY] = Link->Y;
  573. }
  574. }
  575. }
  576. }
  577. else if(MooshPit[_MP_FALLSTATE]==1){ //Falling animation
  578. if(MooshPit[_MP_FALLTIMER]>0)
  579. MooshPit[_MP_FALLTIMER]--;
  580.  
  581. if(MOOSHPIT_STUN_ENEMIES_WHILE_FALLING)
  582. MooshPit_StunEnemies();
  583.  
  584. Link->Jump = 0;
  585. Link->Z = 0;
  586.  
  587. //Keep Link invisible just in case
  588. Link->Invisible = true;
  589. Link->CollDetection = false;
  590. NoAction();
  591. if(MooshPit[_MP_FALLTIMER]==0){
  592. MooshPit[_MP_SLIDETIMER] = 0;
  593. if(!isWarp||MooshPit[_MP_DAMAGETYPE]==1){ //If the pit isn't a warp, deal damage and move Link back to the return point
  594. //If the entry would dump Link back in the pit, dump him out at the failsafe position
  595. if(MooshPit_OnPit(MooshPit[_MP_ENTRYX], MooshPit[_MP_ENTRYY], false)==15){
  596. if(MOOSHPIT_NO_REENTER_STAIRS){
  597. //Call a script to place an FFC under Link to prevent reentering stairs
  598. int scriptName[] = "MooshPit_StairsFix";
  599. int ffcNum = RunFFCScript(Game->GetFFCScript(scriptName), 0);
  600. if(ffcNum>0){
  601. ffc f = Screen->LoadFFC(ffcNum);
  602. f->Flags[FFCF_ETHEREAL] = false;
  603. f->X = MooshPit[_MP_LASTX];
  604. f->Y = MooshPit[_MP_LASTY];
  605. }
  606. }
  607.  
  608. Link->X = MooshPit[_MP_LASTX];
  609. Link->Y = MooshPit[_MP_LASTY];
  610.  
  611. //If the failsafe position was on a different screen, warp there
  612. if(Game->GetCurDMap()!=MooshPit[_MP_LASTDMAP]||Game->GetCurDMapScreen()!=MooshPit[_MP_LASTSCREEN]){
  613. Link->PitWarp(MooshPit[_MP_LASTDMAP], MooshPit[_MP_LASTSCREEN]);
  614. }
  615.  
  616. Link->Invisible = false;
  617. Link->CollDetection = true;
  618. }
  619. else{
  620. if(MOOSHPIT_NO_REENTER_STAIRS){
  621. //Call a script to place an FFC under Link to prevent reentering stairs
  622. int scriptName[] = "MooshPit_StairsFix";
  623. int ffcNum = RunFFCScript(Game->GetFFCScript(scriptName), 0);
  624. if(ffcNum>0){
  625. ffc f = Screen->LoadFFC(ffcNum);
  626. f->Flags[FFCF_ETHEREAL] = false;
  627. f->X = MooshPit[_MP_ENTRYX];
  628. f->Y = MooshPit[_MP_ENTRYY];
  629. }
  630. }
  631.  
  632. //Move Link to the entry and make him visible
  633. Link->X = MooshPit[_MP_ENTRYX];
  634. Link->Y = MooshPit[_MP_ENTRYY];
  635.  
  636. Link->Invisible = false;
  637. Link->CollDetection = true;
  638. }
  639.  
  640. //Subtract HP based on damage type
  641. if(MooshPit[_MP_DAMAGETYPE]==1)
  642. Link->HP -= DAMAGE_FALLLAVA;
  643. else
  644. Link->HP -= DAMAGE_FALLHOLE;
  645. //Play hurt sound and animation
  646. Link->Action = LA_GOTHURTLAND;
  647. Link->HitDir = -1;
  648. Game->PlaySound(SFX_OUCH);
  649.  
  650. MooshPit[_MP_FALLSTATE] = 0;
  651. }
  652. else{
  653. MooshPit[_MP_FALLSTATE] = 2;
  654. MooshPit[_MP_FALLTIMER] = 1;
  655. ffc warp = Screen->LoadFFC(FFC_MOOSHPIT_AUTOWARPA);
  656. warp->Data = CMB_MOOSHPIT_AUTOWARPA;
  657. warp->Flags[FFCF_CARRYOVER] = false;
  658. }
  659. }
  660. }
  661. else if(MooshPit[_MP_FALLSTATE]==2){ //Just warped
  662. if(sideview){
  663. Link->X = MooshPit[_MP_FALLX];
  664. Link->Y = 0;
  665. }
  666. else{
  667. Link->X = MooshPit[_MP_FALLX];
  668. Link->Y = MooshPit[_MP_FALLY];
  669. Link->Z = 176;
  670. }
  671. Link->Invisible = false;
  672. Link->CollDetection = true;
  673.  
  674. if(MOOSHPIT_NO_MOVE_WHILE_FALLING){
  675. MooshPit[_MP_FALLSTATE] = 3;
  676. NoAction();
  677. }
  678. else
  679. MooshPit[_MP_FALLSTATE] = 0;
  680. MooshPit[_MP_FALLTIMER] = 0;
  681. }
  682. else if(MooshPit[_MP_FALLSTATE]==3){ //Falling into a new room (no action)
  683. if(MOOSHPIT_STUN_ENEMIES_WHILE_FALLING)
  684. MooshPit_StunEnemies();
  685.  
  686. NoAction();
  687. if(IsSideview()){
  688. if(OnSidePlatform(Link->X, Link->Y))
  689. MooshPit[_MP_FALLSTATE] = 0;
  690. }
  691. else{
  692. if(Link->Z<=0)
  693. MooshPit[_MP_FALLSTATE] = 0;
  694. }
  695. }
  696. }
  697. }
  698.  
  699. void MooshPit_ResetEntry(){
  700. MooshPit[_MP_ENTRYX] = Link->X;
  701. MooshPit[_MP_ENTRYY] = Link->Y;
  702. MooshPit[_MP_ENTRYDMAP] = Game->GetCurDMap();
  703. MooshPit[_MP_ENTRYSCREEN] = Game->GetCurDMapScreen();
  704. }
  705.  
  706. const int WATER_CURRENT_FREQ = 5; //# of frames between moving Link (CANNOT BE LOWER THAN 0)
  707. const int WATER_CURRENT_FLAG = 98; //First of 4 flags to use in the order Up, Down, Left, Right
  708.  
  709. void doCurrents (){
  710. if ( Link->Action==LA_SWIMMING || Link->Action==LA_DIVING ){//If Link is swimming...
  711.  
  712. //Move Link based on the current's direction...
  713. //but make sure it isn't solid
  714.  
  715. //Up
  716. if( ComboFI(Link->X,Link->Y+8, WATER_CURRENT_FLAG) //If swimming in the appropriate flag
  717. //And the following combos ahead of Link are not solid
  718. && !Screen->isSolid(Link->X,Link->Y+6) //NW
  719. && !Screen->isSolid(Link->X+7,Link->Y+6) //N
  720. && !Screen->isSolid(Link->X+15,Link->Y+6) //NE
  721.  
  722. //Check if the combo below Link is water to prevent getting pushed out
  723. && waterCheck( ComboAt(Link->X,Link->Y+6))
  724. && waterCheck( ComboAt(Link->X+7,Link->Y+6))
  725. && waterCheck( ComboAt(Link->X+15,Link->Y+6))
  726. )
  727. Link->Y -= 2;
  728. //Down
  729. if( ComboFI(Link->X,Link->Y+8, WATER_CURRENT_FLAG+1 )
  730. && !Screen->isSolid(Link->X,Link->Y+17) //SW
  731. && !Screen->isSolid(Link->X+7,Link->Y+17) //S
  732. && !Screen->isSolid(Link->X+15,Link->Y+17) //SE
  733.  
  734. && waterCheck( ComboAt(Link->X,Link->Y+17))
  735. && waterCheck( ComboAt(Link->X+7,Link->Y+17))
  736. && waterCheck( ComboAt(Link->X+15,Link->Y+17))
  737. )
  738. Link->Y += 2;
  739. //Left
  740. if( ComboFI(Link->X,Link->Y+8, WATER_CURRENT_FLAG+2 )
  741. && !Screen->isSolid(Link->X-2,Link->Y+8) //NW
  742. && !Screen->isSolid(Link->X-2,Link->Y+15) //SW
  743. )
  744. Link->X -= 2;
  745. //Right
  746. if( ComboFI(Link->X,Link->Y+8, WATER_CURRENT_FLAG+3 )
  747. && !Screen->isSolid(Link->X+17,Link->Y+8) //NE
  748. && !Screen->isSolid(Link->X+17,Link->Y+15) //SE
  749.  
  750. && waterCheck( ComboAt(Link->X+17,Link->Y+8) )
  751. && waterCheck( ComboAt(Link->X+17,Link->Y+15) )
  752. )
  753. Link->X += 2;
  754. }
  755. }
  756.  
  757. //Prevents Link from swimming on land
  758. void swimLandCheck(){
  759. if( !waterCheck( ComboAt(Link->X,Link->Y+8) ) //If Link is not in the water...
  760. && ( Link->Action==LA_SWIMMING || Link->Action==LA_DIVING ) ) //and swimming...
  761. Link->Action = LA_NONE; //Make him stop swimming
  762. }
  763.  
  764. //Checks if the designated combo is any water type
  765. bool waterCheck(int cmb){
  766. if( Screen->ComboT[cmb] == CT_WATER
  767. || Screen->ComboT[cmb] == CT_SWIMWARP
  768. || Screen->ComboT[cmb] == CT_SWIMWARPB
  769. || Screen->ComboT[cmb] == CT_SWIMWARPC
  770. || Screen->ComboT[cmb] == CT_SWIMWARPD
  771. || Screen->ComboT[cmb] == CT_DIVEWARP
  772. || Screen->ComboT[cmb] == CT_DIVEWARPB
  773. || Screen->ComboT[cmb] == CT_DIVEWARPC
  774. || Screen->ComboT[cmb] == CT_DIVEWARPD
  775. )
  776. return true; //The combo is water
  777. return false;
  778. }
  779.  
  780. // This enables FFCs to be solid without having to lay a solid combo under it.
  781. //
  782. void GB_SolidifyFFC(ffc this){
  783. int tho=(this->EffectHeight-16);
  784. int two=(this->EffectWidth-16);
  785. int onscreenedge;
  786.  
  787. //This detects if link is on the edge of the screen
  788. if(Link->X<8 || Link->Y<8 || Link->X>232 || Link->Y>152){
  789. onscreenedge=1;
  790. }
  791. else{
  792. onscreenedge=0;
  793. }
  794.  
  795. //This checks if you're above or below the NPC to create an overhead effect
  796. if(Link->Y<this->Y-8+tho && onscreenedge==0){
  797. this->Flags[FFCF_OVERLAY] = true;
  798. }
  799. else{
  800. this->Flags[FFCF_OVERLAY] = false;
  801. }
  802.  
  803. if((Abs(Link->X - this->X-two) < 10) && (Link->Y <= this->Y+tho + 12) && (Link->Y > this->Y+tho+8)){
  804. Link->Y = this->Y+tho+12;
  805. }
  806. if((Abs(Link->Y - this->Y-tho) < 10) && (Link->X >= this->X - 12) && (Link->X < this->X+two-8)){
  807. Link->X = this->X-12;
  808. }
  809. if((Abs(Link->X - this->X-two) < 10) && (Link->Y >= this->Y+tho - 12) && (Link->Y < this->Y+tho-8)){
  810. Link->Y = this->Y+tho-12;
  811. }
  812. if((Abs(Link->Y - this->Y-tho) < 10) && (Link->X <= this->X+two + 12) && (Link->X > this->X+two+8)){
  813. Link->X = this->X+two+12;
  814. }
  815. }
  816.  
  817.  
  818. const int COMBOFX_NOT_TRIGGERED_BY_PUSH = 1; //Set to 1 if you don't want push blocks triggering slash effects (like with a pushable pot)
  819.  
  820. const int NPC_COMBOSFX_DROPSET = 85; //Item dropset enemy (Fire by default)
  821. const int COMBOSFX_CHECKALL = 1; //If set to 1, the script will check all combos on screen every frame. This is generally slower and not advised, but there may be cases you'd want this.
  822.  
  823. void CSA_AutoSlashable_Update(int lastDMapScreen){
  824. if(lastDMapScreen[0]!=Game->GetCurDMap()||lastDMapScreen[1]!=Game->GetCurDMapScreen()){
  825. int i; int j; int k;
  826.  
  827. int autoSlashableID[65280];
  828. int autoSlashableData[2056];
  829. autoSlashableData[0] = 0;
  830.  
  831. //AUTO SLASHABLES HERE
  832. //Add your auto slashables with the provided function here
  833. // COMBO SFX TYPE GFX CS FRAMES ASPEED RAND/DROPSET
  834. //EXAMPLE:
  835. //CSA_AddAutoSlashable(autoSlashableID, autoSlashableData, 7680, 41, 2, 52020, 2, 0, 0, 0); //Bush - Green
  836.  
  837.  
  838.  
  839. //End of auto slashables
  840.  
  841. for(i=0; i<176; i++){
  842. int cd = Screen->ComboD[i];
  843. if(autoSlashableID[cd]){
  844. int scr[] = "ComboSFXAnim";
  845. int args[8];
  846. k = autoSlashableID[cd];
  847. for(j=0; j<8; j++){
  848. args[j] = autoSlashableData[k*8+j];
  849. }
  850.  
  851. RunFFCScript(Game->GetFFCScript(scr), args);
  852.  
  853. autoSlashableID[cd] = 0;
  854. }
  855. }
  856.  
  857. lastDMapScreen[0] = Game->GetCurDMap();
  858. lastDMapScreen[1] = Game->GetCurDMapScreen();
  859. }
  860. }
  861.  
  862. ffc script ComboSFXAnim{
  863. void run(int combo, int sfx, int type, int gfx, int cs, int frames, int aspeed, int rand_or_dropset){
  864. int i; int j; int k;
  865. int comboCount; //Max index of positions[]
  866. int positions[176]; //Keeps track of all combo position (0-175) currently being tracked
  867. int lastCombo[176]; //Last known combo of every position onscreen
  868. bool hadCombo[176]; //Used for when COMBOSFX_CHECKALL is used in combination with negative combo ID
  869.  
  870. //Negative combo ID makes it animate every time the combo changes
  871. bool everyFrame = false;
  872. if(combo<0){
  873. combo = Abs(combo);
  874. everyFrame = true;
  875. }
  876.  
  877. for(i=0; i<176; i++){
  878. positions[i] = -1;
  879. lastCombo[i] = Screen->ComboD[i];
  880. }
  881. //Find all valid combos
  882. for(i=0; i<176; i++){
  883. if(Screen->ComboD[i]==combo||COMBOSFX_CHECKALL){
  884. positions[comboCount] = i;
  885. if(Screen->ComboD[i]==combo)
  886. hadCombo[i] = true;
  887. comboCount++;
  888. }
  889. }
  890.  
  891. int lastMovingBlockX;
  892. int lastMovingBlockY;
  893. int movingBlockPositionIndex = -1; //Array index for the moving block's combo position
  894.  
  895. while(true){
  896. bool blockStartedMoving = false;
  897. bool blockStoppedMoving = false;
  898. //If the push block is active
  899. if(Screen->MovingBlockX>-1&&Screen->MovingBlockY>-1){
  900. //If this is the first frame it was active
  901. if(lastMovingBlockX==-1){
  902. blockStartedMoving = true;
  903. }
  904. }
  905. //If the push block was previously active
  906. if(lastMovingBlockX>-1&&lastMovingBlockY>-1){
  907. //If it isn't active anymore
  908. if(Screen->MovingBlockX==-1){
  909. blockStoppedMoving = true;
  910. }
  911. }
  912.  
  913. //Only check combos that had the right ID on init
  914. for(i=0; i<comboCount; i++){
  915. j = positions[i];
  916. if(j>-1){
  917. //Whenever it changes
  918. if(Screen->ComboD[j]!=lastCombo[j]){
  919. //Keeps track of whether a push block triggered the combo change
  920. bool wasPushBlockTriggered;
  921. if(COMBOFX_NOT_TRIGGERED_BY_PUSH){
  922. if(blockStartedMoving){
  923. //If the push block was triggered by this combo
  924. if(ComboAt(Screen->MovingBlockX+8, Screen->MovingBlockY+8)==j){
  925. wasPushBlockTriggered = true;
  926. }
  927. }
  928. if(blockStoppedMoving){
  929. //If the push block ended up on this combo
  930. if(ComboAt(lastMovingBlockX+8, lastMovingBlockY+8)==j){
  931. wasPushBlockTriggered = true;
  932. }
  933. }
  934. }
  935.  
  936. if(Screen->ComboD[j]==combo)
  937. hadCombo[j] = true;
  938. //Do the animation if other conditions are right
  939. bool doAnim = false;
  940. if(!everyFrame){
  941. if(lastCombo[j]==combo)
  942. doAnim = true;
  943. }
  944. else{
  945. if(hadCombo[j])
  946. doAnim = true;
  947. }
  948.  
  949. if(wasPushBlockTriggered)
  950. doAnim = false;
  951.  
  952. if(doAnim){
  953. Game->PlaySound(sfx);
  954. //Create and kill an enemy if the dropset is set
  955. if(rand_or_dropset<0){
  956. npc n = CreateNPCAt(NPC_COMBOSFX_DROPSET, ComboX(j), ComboY(j));
  957. n->ItemSet = Abs(rand_or_dropset);
  958. n->HP = -1000;
  959. n->DrawYOffset = -1000;
  960. }
  961. if(type>1){ //Particle animations
  962. int scr[] = "CSA_Animations";
  963. int args[8];
  964. args[0] = type-2;
  965. args[1] = gfx;
  966. args[2] = cs;
  967. args[3] = frames;
  968. args[4] = aspeed;
  969. args[5] = rand_or_dropset;
  970. ffc f = Screen->LoadFFC(RunFFCScript(Game->GetFFCScript(scr), args));
  971. f->X = ComboX(j);
  972. f->Y = ComboY(j);
  973. }
  974. else if(type==1){ //Sprite animation
  975. lweapon poof = CreateLWeaponAt(LW_SCRIPT10, ComboX(j), ComboY(j));
  976. poof->UseSprite(gfx);
  977. poof->DrawYOffset = 0;
  978. if(cs>0)
  979. poof->CSet = cs;
  980. poof->DeadState = poof->NumFrames*poof->ASpeed;
  981. if(rand_or_dropset>1){
  982. poof->OriginalTile += Rand(rand_or_dropset)*poof->NumFrames;
  983. poof->Tile = poof->OriginalTile;
  984. }
  985. }
  986. }
  987. lastCombo[j] = Screen->ComboD[j];
  988. }
  989. }
  990. }
  991.  
  992. if(blockStartedMoving){
  993. //Find if the moving block is starting on one of the combo positions in the array
  994. k = ComboAt(Screen->MovingBlockX+8, Screen->MovingBlockY+8);
  995. for(i=0; i<comboCount; i++){
  996. j = positions[i];
  997. if(j==k){
  998. movingBlockPositionIndex = i;
  999. break;
  1000. }
  1001. }
  1002. }
  1003. else if(blockStoppedMoving){
  1004. //If the moving block was in the array, update its position
  1005. if(movingBlockPositionIndex>-1){
  1006. k = ComboAt(lastMovingBlockX+8, lastMovingBlockY+8);
  1007. positions[movingBlockPositionIndex] = k;
  1008. }
  1009. movingBlockPositionIndex = -1;
  1010. }
  1011.  
  1012. lastMovingBlockX = Screen->MovingBlockX;
  1013. lastMovingBlockY = Screen->MovingBlockY;
  1014. Waitframe();
  1015. }
  1016. }
  1017. }
  1018.  
  1019. ffc script CSA_Animations{
  1020. void run(int type, int gfx, int cs, int frames, int aspeed, int rand_or_dropset){
  1021. this->Flags[FFCF_ETHEREAL] = true;
  1022. int i; int j; int k;
  1023. int thisNum;
  1024. for(i=1; i<=32; i++){
  1025. ffc f = Screen->LoadFFC(i);
  1026. if(f->Script==this->Script){
  1027. if(f==this)
  1028. break;
  1029. else
  1030. thisNum++;
  1031. }
  1032. }
  1033.  
  1034.  
  1035. if(type==0){ //Bush leaves
  1036. for(i=0; i<8; i++){
  1037. for(j=0; j<3; j++){
  1038. TileAnim_BushAnim(this->X-8, this->Y, gfx, cs, i, thisNum);
  1039. Waitframe();
  1040. }
  1041. }
  1042. }
  1043. else{
  1044. int particleX[32];
  1045. int particleY[32];
  1046. int particleTile[32];
  1047. int particleA[32];
  1048. int particleS[32];
  1049. int particleT[32];
  1050. int particleMT[32];
  1051. int particleAnim[32];
  1052. int particle[16] = {999, particleX, particleY, particleTile, particleA, particleS, particleT, particleMT, particleAnim};
  1053. if(type==1){ //Random spread
  1054. for(i=0; i<12; i++){
  1055. j = gfx;
  1056. if(rand_or_dropset>1)
  1057. j += Rand(rand_or_dropset)*Max(frames, 1);
  1058. Particle_Add(particle, this->X+Rand(-4, 4), this->Y+Rand(-4, 4), j, Rand(360), Rand(20, 120)/100, Rand(12, 18));
  1059. }
  1060. //Run until all particles are dead
  1061. while(particle[0]>0){
  1062. Particle_Update(particle, frames, aspeed, cs);
  1063. Waitframe();
  1064. }
  1065. }
  1066. else if(type==2){ //Aimed spread
  1067. k = Angle(Link->X, Link->Y, this->X, this->Y);
  1068. for(i=0; i<6; i++){
  1069. j = gfx;
  1070. if(rand_or_dropset>1)
  1071. j += Rand(rand_or_dropset)*Max(frames, 1);
  1072. Particle_Add(particle, this->X+Rand(-4, 4), this->Y+Rand(-4, 4), j, k+Rand(-20, 20), Rand(5, 20)/10, Rand(12, 18));
  1073. }
  1074. //Run until all particles are dead
  1075. while(particle[0]>0){
  1076. Particle_Update(particle, frames, aspeed, cs);
  1077. Waitframe();
  1078. }
  1079. }
  1080. }
  1081. }
  1082. void Particle_Update(int particle, int frames, int aspeed, int cs){
  1083. int particleX = particle[1];
  1084. int particleY = particle[2];
  1085. int particleTile = particle[3];
  1086. int particleA = particle[4];
  1087. int particleS = particle[5];
  1088. int particleT = particle[6];
  1089. int particleMT = particle[7];
  1090. int particleAnim = particle[8];
  1091. particle[0] = 0; //Reset particle counter for the frame
  1092. for(int i=0; i<32; i++){
  1093. if(particleT[i]>0){
  1094. particle[0]++;
  1095.  
  1096. //Movement
  1097. particleX[i] += VectorX(particleS[i], particleA[i]);
  1098. particleY[i] += VectorY(particleS[i], particleA[i]);
  1099.  
  1100. //Animations
  1101. int til = particleTile[i];
  1102. if(frames>0){
  1103. if(aspeed==0){
  1104. int j = Floor((particleMT[i]-particleT[i])/(particleMT[i]/frames));
  1105. til = particleTile[i]+Clamp(j, 0, frames-1);
  1106. }
  1107. else{
  1108. til = particleTile[i] + Floor(particleAnim[i]/aspeed);
  1109. particleAnim[i] = (particleAnim[i]+1)%(frames*aspeed);
  1110. }
  1111. }
  1112.  
  1113. //Drawing
  1114. Screen->FastTile(4, particleX[i], particleY[i], til, cs, 128);
  1115. particleT[i]--;
  1116. }
  1117. }
  1118. }
  1119. int Particle_Add(int particle, int x, int y, int tile, int angle, int step, int time){
  1120. int particleX = particle[1];
  1121. int particleY = particle[2];
  1122. int particleTile = particle[3];
  1123. int particleA = particle[4];
  1124. int particleS = particle[5];
  1125. int particleT = particle[6];
  1126. int particleMT = particle[7];
  1127. int particleAnim = particle[8];
  1128. for(int i=0; i<32; i++){
  1129. //Find unused particle, set the stuff
  1130. if(particleT[i]==0){
  1131. particleX[i] = x;
  1132. particleY[i] = y;
  1133. particleTile[i] = tile;
  1134. particleA[i] = angle;
  1135. particleS[i] = step;
  1136. particleT[i] = time;
  1137. particleMT[i] = time;
  1138. particleAnim[i] = 0;
  1139. return i;
  1140. }
  1141. }
  1142. }
  1143. void TileAnim_BushAnim(int x, int y, int tile, int cset, int frame, int thisNum){
  1144. int posX[32] = {16, 6, 20, 14, //Frame 1
  1145. 16, 9, 17, 14, //Frame 2
  1146. 17, 10, 14, 12, //Frame 3
  1147. 17, 11, 15, 11, //Frame 4
  1148. 19, 8, 18, 10, //Frame 5
  1149. 20, 4, 19, 9, //Frame 6
  1150. 21, 3, 22, 8, //Frame 7
  1151. 14, 1, 16, 7}; //Frame 8
  1152.  
  1153.  
  1154. int posY[32] = {11, 8, 7, 1, //Frame 1
  1155. 14, 9, 8, -1, //Frame 2
  1156. 16, 10, 10, -2, //Frame 3
  1157. 18, 10, 10, -3, //Frame 4
  1158. 20, 10, 14, -4, //Frame 5
  1159. 21, 10, 14, -6, //Frame 6
  1160. 23, 9, 14, -9, //Frame 7
  1161. 24, 7, 21, -11};//Frame 8
  1162.  
  1163. int flip[32] = {0, 0, 1, 0, //Frame 1
  1164. 0, 0, 1, 0, //Frame 2
  1165. 1, 0, 1, 0, //Frame 3
  1166. 0, 1, 0, 3, //Frame 4
  1167. 0, 1, 0, 0, //Frame 5
  1168. 0, 0, 0, 0, //Frame 6
  1169. 0, 0, 1, 0, //Frame 7
  1170. 1, 1, 0, 0}; //Frame 8
  1171.  
  1172. for(int i=0; i<4; i++){
  1173. Screen->DrawTile(4, x+posX[frame*4+i]-4, y+posY[frame*4+i]-4, tile+i, 1, 1, cset, -1, -1, 0, 0, 0, flip[frame*4+i], true, 128);
  1174. }
  1175. }
  1176. }
  1177.  
  1178. void CSA_AddAutoSlashable(int autoSlashableID, int autoSlashableData, int combo, int sfx, int type, int gfx, int cs, int frames, int aspeed, int rand_or_dropset){
  1179. ++autoSlashableData[0];
  1180. int k = autoSlashableData[0];
  1181.  
  1182. autoSlashableID[combo] = k;
  1183.  
  1184. autoSlashableData[k*8+0] = combo;
  1185. autoSlashableData[k*8+1] = sfx;
  1186. autoSlashableData[k*8+2] = type;
  1187. autoSlashableData[k*8+3] = gfx;
  1188. autoSlashableData[k*8+4] = cs;
  1189. autoSlashableData[k*8+5] = frames;
  1190. autoSlashableData[k*8+6] = aspeed;
  1191. autoSlashableData[k*8+7] = rand_or_dropset;
  1192.  
  1193. autoSlashableData[0] = Min(autoSlashableData[0], 256);
  1194. }
  1195.  
  1196.  
  1197. const int dayLength = 5; //Length of a day or night in minutes;
  1198. const int I_NIGHT = 45; //An unused item ID, placed into Link's inventory or removed to change day/night
  1199. const int dayDMAP0 = 0; //Daytime DMap #0
  1200. const int nightDMAP0 = 1; //Night DMap #0
  1201. const int dayDMAP1 = -1; //Daytime DMap #1
  1202. const int nightDMAP1 = -1; //Night DMap #1
  1203.  
  1204. const int dayDMAP24 = 24; //Daytime DMap #2
  1205. const int nightDMAP24 = 25; //Night DMap #2
  1206. const int dayDMAP25 = -25; //Daytime DMap #3
  1207. const int nightDMAP25 = -25; //Night DMap #3
  1208.  
  1209. const int dayDMAP11 = 11; //Daytime DMap #4
  1210. const int nightDMAP11 = 12; //Night DMap #4
  1211. const int dayDMAP12 = -12; //Daytime DMap #5
  1212. const int nightDMAP12 = -12; //Night DMap #5
  1213.  
  1214. const int dayDMAP13 = 13; //Daytime DMap #6
  1215. const int nightDMAP13 = 14; //Night DMap #6
  1216. const int dayDMAP14 = -14; //Daytime DMap #7
  1217. const int nightDMAP14 = -14; //Night DMap #7
  1218.  
  1219. const int dayDMAP26 = 26; //Daytime DMap #6
  1220. const int nightDMAP26 = 27; //Night DMap #6
  1221. const int dayDMAP27 = -27; //Daytime DMap #7
  1222. const int nightDMAP27 = -27; //Night DMap #7
  1223.  
  1224. global script FairyQSTglobal
  1225.  
  1226. {void changeNight(bool cycle)
  1227. {if(cycle){
  1228. if(Link->Item[I_NIGHT])Link->Item[I_NIGHT]=false;
  1229. else{Link->Item[I_NIGHT]=true;}
  1230. }if(Game->GetCurScreen()!=128){
  1231. if(dayDMAP0>=0&&nightDMAP0>=0){
  1232. if(Game->GetCurDMap()==dayDMAP0 && Link->Item[I_NIGHT]){
  1233. Link->PitWarp(nightDMAP0, Game->GetCurScreen());
  1234. } else if(Game->GetCurDMap()==nightDMAP0 && !Link->Item[I_NIGHT]){
  1235. Link->PitWarp(dayDMAP0, Game->GetCurScreen());
  1236. }
  1237. }
  1238. if(dayDMAP1>=0&&nightDMAP1>=0){
  1239. if(Game->GetCurDMap()==dayDMAP1 && Link->Item[I_NIGHT]){
  1240. Link->PitWarp(nightDMAP1, Game->GetCurScreen());
  1241. } else if(Game->GetCurDMap()==nightDMAP1 && !Link->Item[I_NIGHT]){
  1242. Link->PitWarp(dayDMAP1, Game->GetCurScreen());
  1243. }
  1244. }
  1245. if(dayDMAP24>=24&&nightDMAP24>=24){
  1246. if(Game->GetCurDMap()==dayDMAP24 && Link->Item[I_NIGHT]){
  1247. Link->PitWarp(nightDMAP24, Game->GetCurScreen());
  1248. } else if(Game->GetCurDMap()==nightDMAP24 && !Link->Item[I_NIGHT]){
  1249. Link->PitWarp(dayDMAP24, Game->GetCurScreen());
  1250. }
  1251. }
  1252. if(dayDMAP25>=24&&nightDMAP25>=24){
  1253. if(Game->GetCurDMap()==dayDMAP25 && Link->Item[I_NIGHT]){
  1254. Link->PitWarp(nightDMAP25, Game->GetCurScreen());
  1255. } else if(Game->GetCurDMap()==nightDMAP25 && !Link->Item[I_NIGHT]){
  1256. Link->PitWarp(dayDMAP25, Game->GetCurScreen());
  1257. }
  1258. }
  1259. if(dayDMAP11>=11&&nightDMAP11>=11){
  1260. if(Game->GetCurDMap()==dayDMAP11 && Link->Item[I_NIGHT]){
  1261. Link->PitWarp(nightDMAP11, Game->GetCurScreen());
  1262. } else if(Game->GetCurDMap()==nightDMAP11 && !Link->Item[I_NIGHT]){
  1263. Link->PitWarp(dayDMAP11, Game->GetCurScreen());
  1264. }
  1265. }
  1266. if(dayDMAP12>=11&&nightDMAP12>=11){
  1267. if(Game->GetCurDMap()==dayDMAP12 && Link->Item[I_NIGHT]){
  1268. Link->PitWarp(nightDMAP12, Game->GetCurScreen());
  1269. } else if(Game->GetCurDMap()==nightDMAP12 && !Link->Item[I_NIGHT]){
  1270. Link->PitWarp(dayDMAP12, Game->GetCurScreen());
  1271. }
  1272. }
  1273. if(dayDMAP13>=13&&nightDMAP13>=13){
  1274. if(Game->GetCurDMap()==dayDMAP13 && Link->Item[I_NIGHT]){
  1275. Link->PitWarp(nightDMAP13, Game->GetCurScreen());
  1276. } else if(Game->GetCurDMap()==nightDMAP13 && !Link->Item[I_NIGHT]){
  1277. Link->PitWarp(dayDMAP13, Game->GetCurScreen());
  1278. }
  1279. }
  1280. if(dayDMAP14>=13&&nightDMAP14>=13){
  1281. if(Game->GetCurDMap()==dayDMAP14 && Link->Item[I_NIGHT]){
  1282. Link->PitWarp(nightDMAP14, Game->GetCurScreen());
  1283. } else if(Game->GetCurDMap()==nightDMAP14 && !Link->Item[I_NIGHT]){
  1284. Link->PitWarp(dayDMAP14, Game->GetCurScreen());
  1285. }
  1286. }
  1287. if(dayDMAP26>=26&&nightDMAP26>=26){
  1288. if(Game->GetCurDMap()==dayDMAP26 && Link->Item[I_NIGHT]){
  1289. Link->PitWarp(nightDMAP26, Game->GetCurScreen());
  1290. } else if(Game->GetCurDMap()==nightDMAP26 && !Link->Item[I_NIGHT]){
  1291. Link->PitWarp(dayDMAP26, Game->GetCurScreen());
  1292. }
  1293. }
  1294. if(dayDMAP27>=26&&nightDMAP27>=26){
  1295. if(Game->GetCurDMap()==dayDMAP27 && Link->Item[I_NIGHT]){
  1296. Link->PitWarp(nightDMAP27, Game->GetCurScreen());
  1297. } else if(Game->GetCurDMap()==nightDMAP27 && !Link->Item[I_NIGHT]){
  1298. Link->PitWarp(dayDMAP27, Game->GetCurScreen());
  1299. }
  1300. }// You can copy this entire IF statement and change it to, say, dayDMAP10 and nightDMAP11 to create an
  1301. // additional DMap to have a day/night cycle for. This can be done indefinitely.
  1302.  
  1303. }
  1304. }
  1305.  
  1306. void run()
  1307. {
  1308. int frame = 0;
  1309. int min = 0;
  1310. MooshPit_Init();
  1311. int waterCounter = 0;
  1312. int lastDMapScreen[2];
  1313. while(true)
  1314. {
  1315. MooshPit_Update();
  1316. bool cycle = false;
  1317. if(min==dayLength){cycle=true;min=0;}
  1318. changeNight(cycle);
  1319. Waitdraw();
  1320. frame++;
  1321. if(frame==3600)
  1322. {
  1323. frame=0;
  1324. min++;
  1325. if ( waterCounter >= WATER_CURRENT_FREQ )
  1326. {
  1327. doCurrents();
  1328. waterCounter = 0;
  1329. }
  1330. waterCounter++;
  1331. swimLandCheck();
  1332. }
  1333. CSA_AutoSlashable_Update(lastDMapScreen);
  1334. Waitframe();
  1335. }
  1336. }
  1337. }
  1338.  
  1339. ffc script MooshPit_StairsFix{
  1340. void run(){
  1341. this->Flags[FFCF_ETHEREAL] = false;
  1342. while(LinkCollision(this)){
  1343. Waitframe();
  1344. }
  1345. this->X = 0;
  1346. this->Y = 0;
  1347. this->Data = 0;
  1348. }
  1349. }
  1350.  
  1351.  
  1352. ffc script flowingWater{
  1353. void run ( int frequency ){
  1354. if( frequency < 1 )
  1355. frequency = WATER_CURRENT_FREQ;
  1356. while ( true ){
  1357. doCurrents();
  1358. Waitframes(frequency);
  1359. swimLandCheck();
  1360. }
  1361. }
  1362. }
  1363.  
  1364.  
  1365. lweapon script scr9
  1366. {
  1367. void run()
  1368. {
  1369. TraceS("Running Weapon Script scr9"); TraceNL();
  1370. int clk = 200;
  1371. this->X = 50; this->Y = 50;
  1372.  
  1373. while(1)
  1374. {
  1375. //++this->ScriptTile;
  1376. if ( Input->ReadKey[KEY_P] )
  1377. {
  1378. this->DeadState = WDS_DEAD;
  1379. Trace(this->DeadState);
  1380.  
  1381. }
  1382.  
  1383. Waitframe();
  1384. }
  1385. }
  1386. }
  1387.  
  1388. npc script n
  1389. {
  1390. void run()
  1391. {
  1392. while(this->isValid())
  1393. {
  1394. //TraceS("NPC Script N is Running"); TraceNL();
  1395. //TraceS("CanMove returned: "); TraceB(this->CanMove({this->Dir,4,0}));
  1396. bool can = this->CanMove({this->Dir});
  1397. if ( !can ) { TraceS("CanMove returned false."); TraceNL(); }
  1398. if ( Input->ReadKey[KEY_N] ) this->Attack();
  1399. if ( Input->ReadKey[KEY_K] ) this->Remove();
  1400. if ( Input->ReadKey[KEY_L] ) this->Slide();
  1401. Waitframe();
  1402. }
  1403. }
  1404. }
  1405.  
  1406. npc script floater_old
  1407. {
  1408. void run()
  1409. {
  1410. TraceS("Running npc script 'test'"); TraceNL();
  1411. this->Dir = Rand(0,3);
  1412. while(this->isValid())
  1413. {
  1414.  
  1415.  
  1416. this->FloatingWalk({10,200,2});
  1417. Waitframe();
  1418. }
  1419. }
  1420. }
  1421.  
  1422. npc script floater
  1423. {
  1424. void run()
  1425. {
  1426. int attack_clk;
  1427. TraceS("Running npc script 'test'"); TraceNL();
  1428. this->Dir = Rand(0,3);
  1429. switch(this->Dir)
  1430. {
  1431. case DIR_UP: this->ScriptTile = 862; break;
  1432. case DIR_DOWN: this->ScriptTile = 861; break;
  1433. case DIR_LEFT: this->ScriptTile = 882; break;
  1434. case DIR_RIGHT: this->ScriptTile = 881; break;
  1435. default: break;
  1436. }
  1437.  
  1438. this->ScriptTile = this->Tile;
  1439. while(this->isValid())
  1440. {
  1441. switch(this->Dir)
  1442. {
  1443. case DIR_UP: this->ScriptTile = 862; break;
  1444. case DIR_DOWN: this->ScriptTile = 861; break;
  1445. case DIR_LEFT: this->ScriptTile = 882; break;
  1446. case DIR_RIGHT: this->ScriptTile = 881; break;
  1447. default: break;
  1448. }
  1449. //this->ScriptTile;
  1450. //if ( this->CanMove(this->Dir) )
  1451. //{
  1452. this->FloatingWalk({10,200,2});
  1453. //}
  1454. if ( this->LinedUp(200,true) )
  1455. {
  1456. if ( this->LinkInRange(100) )
  1457. {
  1458. if (!attack_clk)
  1459. {
  1460. attack_clk = 100;
  1461. this->Attack();
  1462. }
  1463. }
  1464. }
  1465. if (attack_clk) --attack_clk;
  1466. Waitframe();
  1467. }
  1468. }
  1469. }
  1470.  
  1471. npc script walker
  1472. {
  1473. void run()
  1474. {
  1475. int attack_clk;
  1476. TraceS("Running npc script 'test'"); TraceNL();
  1477. this->Dir = Rand(0,3);
  1478. switch(this->Dir)
  1479. {
  1480. case DIR_UP: this->ScriptTile = 862; break;
  1481. case DIR_DOWN: this->ScriptTile = 861; break;
  1482. case DIR_LEFT: this->ScriptTile = 882; break;
  1483. case DIR_RIGHT: this->ScriptTile = 881; break;
  1484. default: break;
  1485. }
  1486.  
  1487. this->ScriptTile = this->Tile;
  1488. while(this->isValid())
  1489. {
  1490. switch(this->Dir)
  1491. {
  1492. case DIR_UP: this->ScriptTile = 862; break;
  1493. case DIR_DOWN: this->ScriptTile = 861; break;
  1494. case DIR_LEFT: this->ScriptTile = 882; break;
  1495. case DIR_RIGHT: this->ScriptTile = 881; break;
  1496. default: break;
  1497. }
  1498. //this->ScriptTile;
  1499. //if ( this->CanMove(this->Dir) )
  1500. //{
  1501. this->HaltingWalk({10,1,0,50,2});
  1502. //}
  1503. if ( this->LinedUp(200,true) )
  1504. {
  1505. if ( this->LinkInRange(100) )
  1506. {
  1507. if (!attack_clk)
  1508. {
  1509. attack_clk = 100;
  1510. this->Attack();
  1511. }
  1512. }
  1513. }
  1514. if (attack_clk) --attack_clk;
  1515. Waitframe();
  1516. }
  1517. }
  1518. }
  1519.  
  1520.  
  1521. ffc script Only_Move_With_Secrets{
  1522. void run(int initial_x, int initial_y){
  1523. initial_x = this->Vx;
  1524. initial_y = this->Vy;
  1525. this->Vx = 0;
  1526. this->Vy = 0;
  1527. while (!Screen->State[ST_SECRET]) Waitframe();
  1528. this->Vx = initial_x;
  1529. this->Vy = initial_y;
  1530. }
  1531. }
  1532.  
  1533. ffc script CaveItemRoomWarp
  1534. {
  1535. untyped cachedData[NUM_CACHED_DATA] = {-1, -1};
  1536. enum cachedIndex
  1537. {
  1538. CACHED_COMBO,
  1539. CACHED_SPECIALITEM_SCRIPT,
  1540. NUM_CACHED_DATA
  1541. };
  1542. define CARRY_ONLY_SPECIALITEM = NOCARRY_B_SECRET | NOCARRY_B_ITEM | NOCARRY_B_LOCKBLOCK | NOCARRY_B_BOSSLOCKBLOCK | NOCARRY_B_CHEST | NOCARRY_B_LOCKEDCHEST | NOCARRY_B_BOSSCHEST;
  1543. /**
  1544. * SETUP:
  1545. * Set the combo for this FFC to any tile warping combo
  1546. * - example: Stair [A], Cave (Walk Down) [A]
  1547. * - if it is set to anything else, the lowest-numbered valid 'Stairs[A]' combo will be used.
  1548. * Set the tile warp on the screen to the destination you desire.
  1549. * - Also set the warp type, return square, etc; do not use 'Cave/Item Cellar'
  1550. * On the destination screen, both sidewarp A and tilewarp A will be set to return to the origin.
  1551. * -Set these warps for any sides/tiles you want to return you.
  1552. * -They will automatically use the same warp type you warped with as well
  1553. * -The return warps will send you to the same-letter return square that you set for the warp
  1554. *
  1555. * Extra (optional) features:
  1556. * - ITEM: If d0 is an item ID, then it will place that item on the target screen, tied to the SOURCE screen's `ST_SPECIALITEM` state.
  1557. * -To disable this, use a negative number.
  1558. * -You cannot use this and also use screen state carryover on the target screen.
  1559. * -You cannot use this and also use a screen script on the target screen, unless it is the SpawnSpecialItem script.
  1560. * -To position the item placement, set up the SpawnSpecialItem script on the target screen (ignoring it's itemID parameter)
  1561. *
  1562. */
  1563. void run(int itemid)
  1564. {
  1565. combodata cd = Game->LoadComboData(this->Data);
  1566. int tilewarp;
  1567. switch(cd->Type) //start What Tilewarp?
  1568. {
  1569. case CT_CAVE:
  1570. case CT_CAVE2:
  1571. case CT_DIVEWARP:
  1572. case CT_PIT:
  1573. case CT_STAIR:
  1574. case CT_SWIMWARP:
  1575. tilewarp = TILEWARP_A;
  1576. break;
  1577.  
  1578. case CT_CAVEB:
  1579. case CT_CAVE2B:
  1580. case CT_DIVEWARPB:
  1581. case CT_PITB:
  1582. case CT_STAIRB:
  1583. case CT_SWIMWARPB:
  1584. tilewarp = TILEWARP_B;
  1585. break;
  1586.  
  1587. case CT_CAVEC:
  1588. case CT_CAVE2C:
  1589. case CT_DIVEWARPC:
  1590. case CT_PITC:
  1591. case CT_STAIRC:
  1592. case CT_SWIMWARPC:
  1593. tilewarp = TILEWARP_C;
  1594. break;
  1595.  
  1596. case CT_CAVED:
  1597. case CT_CAVE2D:
  1598. case CT_DIVEWARPD:
  1599. case CT_PITD:
  1600. case CT_STAIRD:
  1601. case CT_SWIMWARPD:
  1602. tilewarp = TILEWARP_D;
  1603. break;
  1604.  
  1605. default:
  1606. {
  1607. tilewarp = TILEWARP_A;
  1608. if(cachedData[CACHED_COMBO]>-1)
  1609. {
  1610. this->Data = cachedData[CACHED_COMBO];
  1611. break;
  1612. }
  1613. combodata cd;
  1614. for(int q = 1; q < MAX_COMBOS; ++q)
  1615. {
  1616. cd = Game->LoadComboData(q);
  1617. if(cd->Type == CT_STAIR)
  1618. {
  1619. cachedData[CACHED_COMBO] = q;
  1620. break;
  1621. }
  1622. }
  1623. unless(cachedData[CACHED_COMBO]>-1) //No stairs combos in the ENTIRE COMBOLIST?
  1624. {
  1625. cd->Type = CT_STAIR;
  1626. cachedData[CACHED_COMBO] = cd->ID;
  1627. }
  1628. this->Data = cachedData[CACHED_COMBO];
  1629. }
  1630. } //end
  1631.  
  1632. unless(cachedData[CACHED_SPECIALITEM_SCRIPT]>-1)
  1633. {
  1634. cachedData[CACHED_SPECIALITEM_SCRIPT] = Game->GetScreenScript("SpawnSpecialItem");
  1635. }
  1636.  
  1637. int dmapID = Screen->GetTileWarpDMap(tilewarp);
  1638. dmapdata destDMap = Game->LoadDMapData(dmapID);
  1639. mapdata md = Game->LoadMapData(destDMap->Map, DMapToMap(Screen->GetTileWarpScreen(tilewarp), dmapID));
  1640. int warptype = Screen->GetTileWarpType(tilewarp);
  1641. int curmap = Game->GetCurMap();
  1642. int curdmap = Game->GetCurDMap();
  1643. int curscreen = Game->GetCurScreen();
  1644. int retsquare = Screen->TileWarpReturnSquare[tilewarp];
  1645. bool doItem = itemid>=0;
  1646. while(true)
  1647. {
  1648. if(Distance(this->X, this->Y, Link->X, Link->Y)<24)
  1649. {
  1650. md->TileWarpDMap[TILEWARP_A] = curdmap;
  1651. md->TileWarpScreen[TILEWARP_A] = curscreen;
  1652. md->SideWarpDMap[SIDEWARP_A] = curdmap;
  1653. md->SideWarpScreen[SIDEWARP_A] = curscreen;
  1654. md->TileWarpType[TILEWARP_A] = warptype;
  1655. md->SideWarpType[SIDEWARP_A] = warptype;
  1656. md->TileWarpReturnSquare[TILEWARP_A] = retsquare;
  1657. md->SideWarpReturnSquare[SIDEWARP_A] = retsquare;
  1658. if(doItem)
  1659. {
  1660. md->State[ST_SPECIALITEM] = Screen->State[ST_SPECIALITEM];
  1661. unless(Screen->State[ST_SPECIALITEM])
  1662. {
  1663. md->NextMap = curmap;
  1664. md->NextScreen = curscreen;
  1665. md->NoCarry = CARRY_ONLY_SPECIALITEM;
  1666. md->Script = cachedData[CACHED_SPECIALITEM_SCRIPT];
  1667. md->InitD[0] = itemid;
  1668. }
  1669. }
  1670. while(Distance(this->X, this->Y, Link->X, Link->Y)<24) Waitframe();
  1671. }
  1672. Waitframe();
  1673. }
  1674. }
  1675. }
  1676.  
  1677. screendata script SpawnSpecialItem
  1678. {
  1679. define DEFAULT_X = (256/2)-8;
  1680. define DEFAULT_Y = (176/2)-8;
  1681. /**
  1682. * Setup:
  1683. * d0: Item ID (ignore if using this with CaveItemRoomWarp)
  1684. * d1: Item X position
  1685. * d2: Item Y position
  1686. */
  1687. void run(int spawnItemID, int itemX, int itemY)
  1688. {
  1689. if(this->State[ST_SPECIALITEM]) return;
  1690. unless(itemX) itemX = DEFAULT_X;
  1691. unless(itemY) itemY = DEFAULT_Y;
  1692. item spitem = CreateItemAt(spawnItemID, itemX, itemY);
  1693. spitem->Pickup = IP_ST_SPECIALITEM | IP_HOLDUP;
  1694. }
  1695. }
  1696.  
  1697. npc script FleshyDodongo
  1698. {
  1699. void run()
  1700. {
  1701. //Make the first instance of the enemy invisible
  1702. this->DrawYOffset = -1000;
  1703. this->CollDetection = false;
  1704.  
  1705. //Spawn a second enemy for the body with no script
  1706. npc body = CreateNPCAt(this->ID, this->X, this->Y);
  1707. body->Script = 0;
  1708. body->Extend = 3;
  1709.  
  1710. int vars[16];
  1711. //vars[0] - Animation Clock
  1712.  
  1713. while(true)
  1714. {
  1715. //The controller enemy handles movement
  1716. this->ConstantWalk({this->Rate, this->Homing, this->Hunger});
  1717. //Then update's the body's position and animation
  1718. FD_UpdateBody(this, vars, body);
  1719.  
  1720. //When the body dies, center it and kill the controller too
  1721. if(body->HP<=0)
  1722. {
  1723. int x = CenterX(body);
  1724. int y = CenterY(body);
  1725. body->X = x-8;
  1726. body->Y = y-8;
  1727. body->TileWidth = 1;
  1728. body->TileHeight = 1;
  1729. body->HitWidth = 16;
  1730. body->HitHeight = 16;
  1731. this->HP = -1000;
  1732. this->ItemSet = 0;
  1733. Quit();
  1734. }
  1735.  
  1736. Waitframe();
  1737. }
  1738. }
  1739. void FD_UpdateBody(npc this, int vars, npc body)
  1740. {
  1741. ++vars[0];
  1742. //Get the enemy's current frame based off F.Rate
  1743. int f4 = Floor(vars[0]/(this->ASpeed/4));
  1744. //Keep the frame wrapped from 0-3
  1745. if(f4==4)
  1746. {
  1747. f4 = 0;
  1748. vars[0] = 0;
  1749. }
  1750.  
  1751. //Update tiles, hitboxes, and position based on the controller's
  1752. switch(this->Dir)
  1753. {
  1754. case DIR_DOWN:
  1755. body->X = this->X;
  1756. body->Y = this->Y-16;
  1757. body->TileWidth = 1;
  1758. body->TileHeight = 2;
  1759. body->HitWidth = 16;
  1760. body->HitHeight = 32;
  1761. body->Tile = this->OriginalTile + 4 + f4;
  1762. body->OriginalTile = body->Tile;
  1763.  
  1764. break;
  1765. case DIR_LEFT:
  1766. body->X = this->X;
  1767. body->Y = this->Y;
  1768. body->TileWidth = 2;
  1769. body->TileHeight = 1;
  1770. body->HitWidth = 32;
  1771. body->HitHeight = 16;
  1772. body->Tile = this->OriginalTile + 40 + f4 * 2;
  1773. body->OriginalTile = body->Tile;
  1774.  
  1775. break;
  1776. case DIR_RIGHT:
  1777. body->X = this->X-16;
  1778. body->Y = this->Y;
  1779. body->TileWidth = 2;
  1780. body->TileHeight = 1;
  1781. body->HitWidth = 32;
  1782. body->HitHeight = 16;
  1783. body->Tile = this->OriginalTile + 60 + f4 * 2;
  1784. body->OriginalTile = body->Tile;
  1785.  
  1786. break;
  1787. default:
  1788. body->X = this->X;
  1789. body->Y = this->Y;
  1790. body->TileWidth = 1;
  1791. body->TileHeight = 2;
  1792. body->HitWidth = 16;
  1793. body->HitHeight = 32;
  1794. body->Tile = this->OriginalTile + f4;
  1795. body->OriginalTile = body->Tile;
  1796. }
  1797. }
  1798. }
  1799.  
  1800. npc script wolfie
  1801. {
  1802. void run()
  1803. {
  1804. int clks[1];
  1805. while(1)
  1806. {
  1807. this->ConstantWalk({this->Rate, this->Homing, this->Hunger});
  1808. nmes::transform2x1(this,clks);
  1809. Waitframe();
  1810. }
  1811. }
  1812. }
  1813.  
  1814. namespace nmes
  1815. {
  1816. void transform2x1(npc n, int clk)
  1817. {
  1818. ++clk[0];
  1819. int f4 = Floor(clk[0]/(n->ASpeed/4));
  1820. if( f4 >= 4 ) { f4 = 0; clk[0] = 0;}
  1821. switch(n->Dir)
  1822. {
  1823. case DIR_DOWN:
  1824. n->Tile = (Game->LoadNPCData(n->ID)->Tile) + 4 + f4;
  1825. n->OriginalTile = n->Tile;
  1826. n->HitXOffset = 0;
  1827. n->HitYOffset = -16;
  1828. n->DrawXOffset = 0;
  1829. n->DrawYOffset = -16;
  1830. n->TileWidth = 1;
  1831. n->TileHeight = 2;
  1832. n->HitWidth = 16;
  1833. n->HitHeight = 32;
  1834. break;
  1835. case DIR_RIGHT:
  1836. n->Tile = (Game->LoadNPCData(n->ID)->Tile) + 60 + (f4 * 2);
  1837. n->OriginalTile = n->Tile;
  1838. n->HitXOffset = -16;
  1839. n->HitYOffset = 0;
  1840. n->DrawXOffset = -16;
  1841. n->DrawYOffset = 0;
  1842. n->TileWidth = 2;
  1843. n->TileHeight = 1;
  1844. n->HitWidth = 32;
  1845. n->HitHeight = 16;
  1846. break;
  1847. case DIR_LEFT:
  1848. n->Tile = (Game->LoadNPCData(n->ID)->Tile) + 40 + (f4 *2);
  1849. n->OriginalTile = n->Tile;
  1850. n->TileWidth = 2;
  1851. n->TileHeight = 1;
  1852. n->HitWidth = 32;
  1853. n->HitHeight = 16;
  1854. n->HitXOffset = 0;
  1855. n->HitYOffset = 0;
  1856. n->DrawXOffset = 0;
  1857. n->DrawYOffset = 0;
  1858. break;
  1859. case DIR_UP:
  1860. n->Tile = (Game->LoadNPCData(n->ID)->Tile) + f4;
  1861. n->OriginalTile = n->Tile;
  1862. n->TileWidth = 1;
  1863. n->TileHeight = 2;
  1864. n->HitWidth = 16;
  1865. n->HitHeight = 32;
  1866. n->HitXOffset = 0;
  1867. n->HitYOffset = 0;
  1868. n->DrawXOffset = 0;
  1869. n->DrawYOffset = 0;
  1870. break;
  1871.  
  1872. }
  1873. }
  1874. }
  1875.  
  1876. ffc script chestSound{
  1877. void run(int sfx, int comboID){
  1878. while(true){
  1879. if ( Screen->ComboD[ComboAt(this->X, this->Y)] == comboID && sfx ) {
  1880. Game->PlaySound(sfx);
  1881. this->Data = 0;
  1882. this->Script = 0;
  1883. Quit();
  1884. }
  1885. Waitframe();
  1886. }
  1887. }
  1888. }
  1889.  
  1890. item script SlashScroll
  1891. {
  1892. void run()
  1893. {
  1894. Game->Generic[GEN_CANSLASH] = 1;
  1895. }
  1896. }
  1897.  
  1898.  
  1899.  
  1900. npc script wolfie2
  1901. {
  1902. void run()
  1903. {
  1904. int clks[1];
  1905. lweapon bite = Screen->CreateLWeapon(EW_SCRIPT1);
  1906. bite->X = this->X;
  1907. bite->Y = this->Y;
  1908. bite->HitHeight = 8;
  1909. bite->HitWidth = 16;
  1910. bite->DrawYOffset = -32768;
  1911. bite->Damage = 2;
  1912. while(1)
  1913. {
  1914. this->ConstantWalk({this->Rate, this->Homing, this->Hunger});
  1915. unless(bite->isValid())
  1916. {
  1917. bite = Screen->CreateLWeapon(EW_SCRIPT1);
  1918. bite->DrawYOffset = -32768;
  1919. bite->Damage = 2;
  1920. }
  1921. if(bite->isValid())
  1922. {
  1923. wolfnme::positionbite(this, bite);
  1924. wolfnme::transformbite(this, bite);
  1925.  
  1926. }
  1927. Waitdraw();
  1928. wolfnme::transform2x1(this,clks);
  1929. Waitframe();
  1930. }
  1931. }
  1932. }
  1933.  
  1934. namespace wolfnme
  1935. {
  1936. void positionbite(npc n, lweapon bite)
  1937. {
  1938. switch(n->Dir)
  1939. {
  1940. case DIR_UP:
  1941. bite->X = n->X; bite->Y = n->Y -1; bite->HitYOffset = -2; bite->HitXOffset = 0; break;
  1942. case DIR_DOWN:
  1943. bite->X = n->X; bite->Y = n->Y + 1; bite->HitYOffset = 24; bite->HitXOffset = 0; break;
  1944. case DIR_LEFT:
  1945. bite->X = n->X - 1; bite->Y = ((n->Y > 0) ? n->Y : n->Y + 1); bite->HitYOffset = 0; bite->HitXOffset = -2; break;
  1946. case DIR_RIGHT:
  1947. bite->X = n->X + 1; bite->Y = ((n->Y > 0) ? n->Y : n->Y + 1); bite->HitYOffset = 0; bite->HitXOffset = 25; break;
  1948. }
  1949. }
  1950. void transformbite(npc n, lweapon l)
  1951. {
  1952. switch(n->Dir)
  1953. {
  1954. case DIR_DOWN:
  1955. case DIR_UP:
  1956. {
  1957. l->HitWidth = 16;
  1958. l->HitHeight = 8;
  1959. break;
  1960. }
  1961. case DIR_RIGHT:
  1962. case DIR_LEFT:
  1963. {
  1964. l->HitWidth = 8;
  1965. l->HitHeight = 16;
  1966. break;
  1967. }
  1968. }
  1969. }
  1970.  
  1971. void transform2x1(npc n, int clk)
  1972. {
  1973. ++clk[0];
  1974. int f4 = Floor(clk[0]/(n->ASpeed/4));
  1975. if( f4 >= 4 ) { f4 = 0; clk[0] = 0;}
  1976. switch(n->Dir)
  1977. {
  1978. case DIR_DOWN:
  1979. {
  1980. n->Tile = (Game->LoadNPCData(n->ID)->Tile) + 4 + f4;
  1981. n->OriginalTile = n->Tile;
  1982. n->TileWidth = 1;
  1983. n->TileHeight = 2;
  1984. n->HitWidth = 16;
  1985. n->HitHeight = 32;
  1986. break;
  1987. }
  1988. case DIR_RIGHT:
  1989. {
  1990. n->Tile = (Game->LoadNPCData(n->ID)->Tile) + 60 + (f4 * 2);
  1991. n->OriginalTile = n->Tile;
  1992. n->TileWidth = 2;
  1993. n->TileHeight = 1;
  1994. n->HitWidth = 32;
  1995. n->HitHeight = 16;
  1996. break;
  1997. }
  1998. case DIR_LEFT:
  1999. {
  2000. n->Tile = (Game->LoadNPCData(n->ID)->Tile) + 40 + (f4 *2);
  2001. n->OriginalTile = n->Tile;
  2002. n->TileWidth = 2;
  2003. n->TileHeight = 1;
  2004. n->HitWidth = 32;
  2005. n->HitHeight = 16;
  2006. break;
  2007. }
  2008. case DIR_UP:
  2009. {
  2010. n->Tile = (Game->LoadNPCData(n->ID)->Tile) + f4;
  2011. n->OriginalTile = n->Tile;
  2012. n->TileWidth = 1;
  2013. n->TileHeight = 2;
  2014. n->HitWidth = 16;
  2015. n->HitHeight = 32;
  2016. break;
  2017. }
  2018. }
  2019. }
  2020. }
  2021.  
  2022.  
  2023. ////////////////////////////////
  2024. /// Music.zh ///
  2025. /// v1.3.6 - 26th Mar, 2019 ///
  2026. /// By: ZoriaRPG ///
  2027. ////////////////////////////////////////////////////////////////////////////////////////////////////
  2028. /// A series of FFCs, and utility functions for playing MIDIs, Enhanced Music, and Sound Effects ///
  2029. /// 1.3.3: Optimisation for inclusion with ZC 2.53 Gamma 4 ///
  2030. /// 1.3.4: Fixes to NPC_MIDI and NPC_Music ///
  2031. /// 1.3.5: More Fixes to NPC_MIDI and NPC_Music ///
  2032. /// 1.3.6: Renamed BossMusic to MusicZH_BossMusic to avoid a conflict with Classic.zh. ///
  2033. ////////////////////////////////////////////////////////////////////////////////////////////////////
  2034.  
  2035. //#include "std.zh"
  2036. //#include "string.zh"
  2037.  
  2038. const int MIDI_DEFEATBOSS = 0; //Set to default midi to play for Victory Music.
  2039. //ZC will use this if enhanced Victory music is not available.
  2040.  
  2041. const int DEFAULT_BOSS_MUSIC = 0; //Sets a default boss music file to play.
  2042.  
  2043. ///////////////
  2044. /// SCRIPTS ///
  2045. ///////////////
  2046.  
  2047.  
  2048. /////////////////////
  2049. /// Sound Effects ///
  2050. /////////////////////
  2051.  
  2052. // Ties SFX to an item, that is otherwise normally hardcoded. used for the Sonic Wand in LoE.
  2053.  
  2054. item script playSound
  2055. {
  2056. void run(int sfx)
  2057. {
  2058. Game->PlaySound(sfx);
  2059. }
  2060. }
  2061.  
  2062. /////////////////
  2063. /// MIDI Only ///
  2064. /////////////////
  2065.  
  2066. //Plays MIDI specified at D0. Place on a screen, to change the MIDI for that screen, only.
  2067. //Plays at all times on that screen, and uses no conditions.
  2068.  
  2069. ffc script playMIDI
  2070. {
  2071. void run(int midiNumber)
  2072. {
  2073. Game->PlayMIDI(midiNumber);
  2074. }
  2075. }
  2076.  
  2077. /////////////////////////
  2078. /// Conditional MIDIs ///
  2079. /////////////////////////
  2080.  
  2081.  
  2082.  
  2083. //play a MIDI while an enemy with a specific ID is on-screen
  2084.  
  2085. ffc script NPC_MIDI
  2086. {
  2087. void run(int npc_ID, int midi)
  2088. {
  2089. //int originalMIDi = //share these two
  2090. //int originalMusic[3] = //midi, enh music, track
  2091. //store the normal midi or music
  2092. //check for the npc and while it is on-screen
  2093. //change the midi
  2094. Waitframes(6);
  2095. //LogPrint("NPC_MIDI passed %s \n", "Waitframes(1)");
  2096. //if it dies, change back
  2097. int q[4]; npc n; bool found;
  2098. int enh_music[256] = {0};
  2099. Game->GetDMapMusicFilename(Game->GetCurDMap(), enh_music);
  2100.  
  2101. int enh_trk = Game->GetDMapMusicTrack(Game->GetCurDMap());
  2102. for ( q[0] = 0; q[0] < 256; ++q[0] ) { if ( enh_music[q] == ' ' ) enh_music[q] = 0; } //kill the space.
  2103. bool enhanced = ( enh_music[0] != 0 ); //is the dmap music enhanced?
  2104.  
  2105. int originalmusic = Game->DMapMIDI[Game->GetCurDMap()];
  2106. while(!Screen->NumNPCs())
  2107. {
  2108. //LogPrint("NPC_MIDI is %s \n", "Waiting (!Screen->NumNPCs())");
  2109. Waitframe();
  2110. }
  2111. while(true){
  2112. for ( q[0] = Screen->NumNPCs(); q[0] > 0; --q[0] ) {
  2113. n = Screen->LoadNPC(q);
  2114. if ( n->ID == npc_ID )
  2115. {
  2116. //LogPrint("NPC_MIDI %s \n", "matched the input npc");
  2117. q[1] = 1; break;
  2118. }
  2119. q[1] = 0;
  2120. }
  2121. if ( q[1] ) //found the npc
  2122. {
  2123. //LogPrint("NPC_MIDI %s \n", "if(q[1])");
  2124. if ( !q[2] )
  2125. {
  2126. //LogPrint("NPC_MIDI %s \n", "if(!q[2])");
  2127. Game->PlayMIDI( midi );
  2128. q[2] = 1;
  2129. }
  2130. }
  2131. if ( q[2] ) break;
  2132.  
  2133. Waitframe();
  2134. }
  2135. bool stillalive;
  2136.  
  2137. while(1)
  2138. {
  2139. for ( int w = Screen->NumNPCs(); w > 0; --w )
  2140. {
  2141. npc n = Screen->LoadNPC(w);
  2142. if ( n->ID == npc_ID )
  2143. {
  2144. //LogPrint("npc_ID is: %d \n", npc_ID);
  2145. //LogPrint("NPC_MIDI is at %s \n", "still alive");
  2146. stillalive = true;
  2147. break;
  2148. }
  2149. stillalive = false;
  2150. }
  2151. if ( stillalive ) { Waitframe(); continue; }
  2152. if ( !stillalive )
  2153. {
  2154. //LogPrint("NPC_MIDI is at %s \n", "!still alive");
  2155. break;
  2156. }
  2157. Waitframe();
  2158. }
  2159.  
  2160. //LogPrint("NPC_MIDI is at %s \n", "!NumNPCsOf(npc_id)");
  2161. Waitframes(10);
  2162. //LogPrint("NPC_MIDI %s \n", "PlayEnhancedMusic");
  2163. Game->PlayEnhancedMusic(enh_music, enh_trk);
  2164.  
  2165. if ( !enhanced )
  2166. {
  2167. //LogPrint("NPC_MIDI %s \n", "!enhanced");
  2168. Game->PlayMIDI(originalmusic);
  2169. }
  2170.  
  2171. }
  2172. }
  2173.  
  2174. //play enhanced music while an enemy with a specific ID is on-screen
  2175.  
  2176. ffc script NPC_Music
  2177. {
  2178. void run(int npc_ID, int music_string, int track)
  2179. {
  2180. //int originalMIDi = //share these two
  2181. //int originalMusic[3] = //midi, enh music, track
  2182. //store the normal midi or music
  2183. //check for the npc and while it is on-screen
  2184. //change the midi
  2185. Waitframes(6);
  2186. //if it dies, change back
  2187. int q[4]; npc n; bool found;
  2188. int enh_music[256] = {0};
  2189. Game->GetDMapMusicFilename(Game->GetCurDMap(), enh_music);
  2190.  
  2191. int enh_trk = Game->GetDMapMusicTrack(Game->GetCurDMap());
  2192. for ( q[0] = 0; q[0] < 256; ++q[0] ) { if ( enh_music[q] == ' ' ) enh_music[q] = 0; } //kill the space.
  2193. bool enhanced = ( enh_music[0] != 0 ); //is the dmap music enhanced?
  2194. bool playing;
  2195.  
  2196. int originalmusic = Game->DMapMIDI[Game->GetCurDMap()];
  2197. while(!Screen->NumNPCs()) Waitframe();
  2198.  
  2199. while(true){
  2200. for ( q[0] = Screen->NumNPCs(); q[0] > 0; --q[0] )
  2201. {
  2202. n = Screen->LoadNPC(q);
  2203. if ( n->ID == npc_ID )
  2204. {
  2205. q[1] = 1; break;
  2206. }
  2207. q[1] = 0;
  2208. }
  2209. if ( q[1] )
  2210. {
  2211. if ( !q[2] )
  2212. {
  2213. playing = PlayEnhMusicFile(music_string, track);
  2214. q[2] = 1;
  2215. }
  2216. }
  2217. if ( q[2] ) break;
  2218.  
  2219. Waitframe();
  2220. }
  2221. bool stillalive;
  2222. while(1)
  2223. {
  2224. for ( int w = Screen->NumNPCs(); w > 0; --w )
  2225. {
  2226. npc n = Screen->LoadNPC(w);
  2227. if ( n->ID == npc_ID )
  2228. {
  2229. //LogPrint("npc_ID is: %d \n", npc_ID);
  2230. //LogPrint("NPC_MIDI is at %s \n", "still alive");
  2231. stillalive = true;
  2232. break;
  2233. }
  2234. stillalive = false;
  2235. }
  2236. if ( stillalive ) { Waitframe(); continue; }
  2237. if ( !stillalive )
  2238. {
  2239. //LogPrint("NPC_MIDI is at %s \n", "!still alive");
  2240. break;
  2241. }
  2242. Waitframe();
  2243. }
  2244. //LogPrint("NPC_MIDI is at %s \n", "!NumNPCsOf(npc_id)");
  2245. Waitframes(10);
  2246. //LogPrint("NPC_MIDI %s \n", "PlayEnhancedMusic");
  2247. Game->PlayEnhancedMusic(enh_music, enh_trk);
  2248.  
  2249. if ( enhanced ) Game->PlayEnhancedMusic(enh_music, enh_trk);
  2250.  
  2251. else Game->PlayMIDI(originalmusic);
  2252. }
  2253. }
  2254.  
  2255. // These scripts will play MIDI files based on conditions set in the script args.
  2256.  
  2257. // D0: MIDI file to play while boss is on the screen.
  2258. // D1: The Screen Register (Screen->D[reg]) to use.
  2259. // D2: Victory MIDI to play when boss is defeated. If set to 0, the MIDI set by constant MIDI_DEFEATBOSS plays.
  2260. // D3: The duration of the victory music.
  2261. //
  2262. // If set to 0, the track will not play.
  2263. // If set to greater than 0, the track will play for a specific duration, as follows:
  2264. // To set using minutes, and seconds, set up minutes as the integer portion of the arg, and seconds as the decimal portion:
  2265. // e.g. 00005.0260 is 5 mins, 26 seconds.
  2266. // This works to a fineness of 1/10 second, so 00010.0136 is 10 minutes, 13.6 seconds.
  2267. // If you wish to specify the duration in frames, set the ten-thousands place to '1', and the rest of the value to the number of frames.
  2268. // e.g. 10526.1023 = 5,261,023 frames.
  2269. // e.g. 10001.3591 = 13,591 frames.
  2270. //
  2271. // D4: The enemy ID of the 'boss':
  2272. //
  2273. // A value of zero here, instructs the FFC not to change the Screen->D[reg] value. Leave this at zero, if the enemy does this.
  2274. // Otherwise, set this to -1 (negative one) if you want the Victory music to play when all screen NPCs are dead...or...
  2275. // a positive value matching an enemy ID that is on the screen, if you want to play the Victory music when all enemies with that ID are dead.
  2276.  
  2277.  
  2278. ffc script MusicZH_BossMusic
  2279. {
  2280. void run(int bossMIDI, int reg, int victoryMIDI, int vict_dur, int enem)
  2281. {
  2282. Waitframes(6);
  2283. int curScreen = Game->GetCurScreen();
  2284. int dat = Game->GetScreenD(curScreen,reg);
  2285. if ( dat == 0 ) {
  2286. if ( bossMIDI > 0 )
  2287. {
  2288. Game->PlayMIDI(bossMIDI);
  2289. }
  2290. else
  2291. {
  2292. Game->PlayMIDI(DEFAULT_BOSS_MUSIC);
  2293. }
  2294. }
  2295. int curDMap = Game->GetCurDMap();
  2296. int stdMIDI = Game->DMapMIDI[curDMap];
  2297.  
  2298.  
  2299. int VictoryClockMethod = _Music_zh__GetDigit(vict_dur, 4);
  2300. int dur;
  2301.  
  2302. if ( VictoryClockMethod == 0 )
  2303. {
  2304. dur = MusicFrames(vict_dur); //Convert victory music into frames.
  2305. }
  2306.  
  2307. if ( VictoryClockMethod > 0 )
  2308. {
  2309. dur = _Music_zh__GetPartialArg(vict_dur,3,8); //Use the full value of loopBossMusic as frame in int.
  2310. }
  2311.  
  2312. while(true)
  2313. {
  2314. dat = Game->GetScreenD(curScreen,reg);
  2315.  
  2316. if ( enem == -1 && !Screen->NumNPCs() )
  2317. {
  2318. Game->SetScreenD(curScreen,reg,1);
  2319. }
  2320. if ( enem == 0 )
  2321. {
  2322. //Should we do anything special?
  2323. //A zero value is intended to be used if we don;t want the FFC to set Screen->D to 1.
  2324. //-1 if we do it based on all enemies being dead.
  2325. //A positive value trips it if there are no enemies of that ID on the screen.
  2326. }
  2327.  
  2328. if ( enem > 0 && !NumNPCsOf(enem) )
  2329. {
  2330. Game->SetScreenD(curScreen,reg,1);
  2331. }
  2332.  
  2333. dat = Game->GetScreenD(curScreen,reg);
  2334.  
  2335.  
  2336. if ( dat > 0 )
  2337. {
  2338. if ( dur > 0 )
  2339. {
  2340. if ( victoryMIDI > 0 )
  2341. {
  2342. Game->PlayMIDI(MIDI_DEFEATBOSS);
  2343. }
  2344. else
  2345. {
  2346. Game->PlayMIDI(MIDI_DEFEATBOSS);
  2347. }
  2348. for ( int q = 0; q <= dur; ++q )
  2349. {
  2350. Waitframe();
  2351. }
  2352. }
  2353. Game->PlayMIDI(stdMIDI);
  2354. }
  2355. Waitframe();
  2356. }
  2357. }
  2358. }
  2359.  
  2360. //////////////////////
  2361. /// Enhanced Music ///
  2362. //////////////////////
  2363.  
  2364. /// These scripts will play 'enhanced music', using values set in script args.
  2365. /// If an enhanced music file is not available (e.g. the player does not have it, or elects
  2366. /// not to use it, then they will play a back-up MIDI file, also set by script args.
  2367.  
  2368. // D0: MIDI number to default to for this boss, if no enhanced music is available.
  2369. // Split argument, high and low at decimal point:
  2370. // #####.xxxx -> Backup MIDI file to play if enhanced BOSS music is not available.
  2371. // xxxxx.#### -> Backup MIDI file to play if enhanced VICTORY music is not available.
  2372. // D1: Screen->D reg to set/check.
  2373. // D2: The duration of the victory music.
  2374. // If set to 0, the track will not play.
  2375. // If set to greater than 0, the track will play for a specific duration, as follows:
  2376. // To set using minutes, and seconds, set up minutes as the integer portion of the arg, and seconds as the decimal portion:
  2377. // e.g. 00005.0260 is 5 mins, 26 seconds.
  2378. // This works to a fineness of 1/10 second, so 00010.0136 is 10 minutes, 13.6 seconds.
  2379. // If you wish to specify the duration in frames, set the ten-thousands place to '1', and the rest of the value to the number of frames.
  2380. // e.g. 10526.1023 = 5,261,023 frames.
  2381. // e.g. 10001.3591 = 13,591 frames.
  2382. //
  2383. // D3: The STRING number, and track number, for Boss Music. Split arg, high and low at decimal point:
  2384. // #####.xxxx -> The file number.
  2385. // xxxxx.#### -> The track number to play.
  2386. // Uses string ID from internal strings table.
  2387. // D4: The STRING number, and track number, for Victory Music. Split arg, high and low at decimal point:
  2388. // #####.xxxx -> The file number.
  2389. // xxxxx.#### -> The track number to play.
  2390. // Uses string ID from internal strings table.
  2391. // D5: The point in the track to pause, then loop
  2392. //
  2393. // If set to 0, the track with loop only when it ends.
  2394. // If set to greater than 0, the track will loop befor eit ends, as follows:
  2395. // To loop by setting minutes, and seconds, set up minutes as the integer portion of the arg, and seconds as the decimal portion:
  2396. // e.g. 00005.0260 is 5 mins, 26 seconds.
  2397. // This works to a fineness of 1/10 second, so 00010.0136 is 10 minutes, 13.6 seconds.
  2398. // If you wish to specify the loop in frames, set the ten-thousands place to '1', and the rest of the value to the number of frames.
  2399. // e.g. 10526.1023 = 5,261,023 frames.
  2400. // e.g. 10001.3591 = 13,591 frames.
  2401. //
  2402. // D6: This value instructs the FFC to set Screen->D[reg] = 1 when enemies are dead.
  2403. // A value of zero here, instructs the FFC not to change the Screen->D[reg] value. Leave this at zero, if the enemy does this.
  2404. // Otherwise, set this to -1 (negative one) if you want the Victory music to play when all screen NPCs are dead...or...
  2405. // a positive value matching an enemy ID that is on the screen, if you want to play the Victory music when all enemies with that ID are dead.
  2406. //
  2407. // D7: If set to '1' or above, this will trace informationt o allegro.log for you as debug datum.
  2408.  
  2409.  
  2410. //Version 0.44 - Strings set by String Table (ZQuest String Editor, not hardcoded)
  2411.  
  2412. ffc script BossMusicEnhanced_InternalStrings
  2413. {
  2414. //Credit Moosh for reminding me that reading internal strings in the string table is a thing.
  2415. void run(int midiNumber_victoryMidiNumber, int reg, int vict_dur, float musicBoss_trkBoss, float musicVictory_trkVictory, float loopBossMusic, int enem, int debug)
  2416. {
  2417. int curScreen = Game->GetCurScreen();
  2418. int curDMAP = Game->GetCurDMap();
  2419. int curDmap = Game->GetCurDMap();
  2420. int dat = Game->GetScreenD(curScreen,reg);
  2421. int stdMIDI = Game->DMapMIDI[curDMAP];
  2422.  
  2423. int dmapMusicBuffer[512]=" ";
  2424. Game->GetDMapMusicFilename(curDMAP, dmapMusicBuffer);
  2425.  
  2426. int midiNumber = _Music_zh__GetHighArgument(midiNumber_victoryMidiNumber); //#####.xxxx
  2427. int victoryMIDI = _Music_zh__GetLowArgument(midiNumber_victoryMidiNumber); //xxxxx.####
  2428.  
  2429. int musicBoss = _Music_zh__GetHighArgument(musicBoss_trkBoss); //#####.xxxx
  2430. int trkBoss = _Music_zh__GetLowArgument(musicBoss_trkBoss); //xxxxx.####
  2431.  
  2432. int musicVictory = _Music_zh__GetHighArgument(musicVictory_trkVictory);
  2433. int trkVictory = _Music_zh__GetLowArgument(musicVictory_trkVictory); //xxxxx.####
  2434.  
  2435. int dmapTrack = Game->GetDMapMusicTrack(curDMAP);
  2436. int q;
  2437.  
  2438. int boss_buffer[256]=" "; //two-digit number, plus four-digit extension, plus NULL.
  2439. int victory_buffer[256]=" "; //Buffer for Victory Music Filename.
  2440.  
  2441. Game->GetMessage(musicVictory, victory_buffer);
  2442. Game->GetMessage(musicBoss, boss_buffer);
  2443.  
  2444.  
  2445. //Print filenames to allegro.log.
  2446. if ( debug )
  2447. {
  2448. int loading[]="Attempting to load file: ";
  2449. TraceNL();
  2450. TraceS(loading);
  2451. TraceNL();
  2452. TraceS(boss_buffer);
  2453. TraceNL();
  2454. TraceS(loading);
  2455. TraceNL();
  2456. TraceS(victory_buffer);
  2457. TraceNL();
  2458. }
  2459.  
  2460. int playingBoss[]="Playing Boss Music";
  2461. int playingVictory[]="Playing Victory Music";
  2462. int errLoading[]="Error loading track.";
  2463.  
  2464. int LoopClockMethod = _Music_zh__GetDigit(loopBossMusic, 4);
  2465. //Convert mins and seconds.
  2466.  
  2467. int BossMusicDuration;
  2468. if ( LoopClockMethod == 0 )
  2469. {
  2470. BossMusicDuration = MusicFrames(loopBossMusic); //Convert loopBossMusic into time.
  2471. }
  2472. if ( LoopClockMethod > 0 )
  2473. {
  2474. BossMusicDuration = _Music_zh__GetPartialArg(loopBossMusic,3,8); //Use the full value of loopBossMusic as frame in int.
  2475. }
  2476.  
  2477. int VictoryClockMethod = _Music_zh__GetDigit(vict_dur, 4);
  2478. int dur;
  2479.  
  2480. if ( VictoryClockMethod == 0 )
  2481. {
  2482. dur = MusicFrames(vict_dur); //Convert victory music into frames.
  2483. }
  2484.  
  2485. if ( VictoryClockMethod > 0 )
  2486. {
  2487. dur = _Music_zh__GetPartialArg(vict_dur,3,8); //Use the full value of loopBossMusic as frame in int.
  2488. }
  2489. for ( q = 0; q < 256; q++ ) { if ( boss_buffer[q] == ' ' ) boss_buffer[q] = 0; } //kill the space.
  2490. for ( q = 0; q < 256; q++ ) { if ( victory_buffer[q] == ' ' ) victory_buffer[q] = 0; } //kill the space.
  2491. bool playing = false;
  2492. Waitframes(6); //Wait for enemies to spawn. //Moved up here in 1.3.4
  2493. while(true)
  2494. {
  2495. //Waitframes(5); 1.3.4
  2496. dat = Game->GetScreenD(curScreen,reg);
  2497. //Waitframes(6); //Wait for enemies to spawn. 1.3.4
  2498. //Set Screen->D[reg] = 1 if the enemy is dead.
  2499. if ( enem == -1 && !Screen->NumNPCs() )
  2500. {
  2501. Game->SetScreenD(curScreen,reg,1);
  2502. }
  2503. if ( enem == 0 )
  2504. {
  2505. //Should we do anything special?
  2506. //A zero value is intended to be used if we don't want the FFC to set Screen->D to 1.
  2507. //-1 if we do it based on all enemies being dead.
  2508. //A positive value trips it if there are no enemies of that ID on the screen.
  2509. }
  2510.  
  2511. if ( enem > 0 && !NumNPCsOf(enem) )
  2512. {
  2513. Game->SetScreenD(curScreen,reg,1);
  2514. }
  2515.  
  2516. dat = Game->GetScreenD(curScreen,reg);
  2517.  
  2518. if ( dat == 0 && loopBossMusic == 0 && !playing )
  2519. {
  2520. Game->PlayEnhancedMusic(boss_buffer, trkBoss);
  2521.  
  2522. if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) )
  2523. {
  2524. if ( midiNumber > 0 )
  2525. {
  2526. Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available.
  2527. }
  2528. else
  2529. {
  2530. Game->PlayMIDI(DEFAULT_BOSS_MUSIC); //Play default music if midiNumber is set to '0'.
  2531. }
  2532.  
  2533. }
  2534. playing = true;
  2535. }
  2536.  
  2537. if ( dat == 0 && loopBossMusic > 0 )
  2538. {
  2539.  
  2540. //set up music loop
  2541. for ( int q = BossMusicDuration; q >=0; --q )
  2542. {
  2543. if ( q == BossMusicDuration && dat == 0 )
  2544. {
  2545. Game->PlayEnhancedMusic(boss_buffer, trkBoss);
  2546. if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) )
  2547. {
  2548. Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available.
  2549. }
  2550. }
  2551. if ( enem == -1 && !Screen->NumNPCs() )
  2552. {
  2553. Game->SetScreenD(curScreen,reg,1);
  2554. }
  2555. if ( enem == 0 )
  2556. {
  2557. //Should we do anything special?
  2558. //A zero value is intended to be used if we don;t want the FFC to set Screen->D to 1.
  2559. //-1 if we do it based on all enemies being dead.
  2560. //A positive value trips it if there are no enemies of that ID on the screen.
  2561. }
  2562. if ( enem > 0 && !NumNPCsOf(enem) )
  2563. {
  2564. Game->SetScreenD(curScreen,reg,1);
  2565. }
  2566. dat = Game->GetScreenD(curScreen,reg);
  2567. if ( dat > 0 )
  2568. {
  2569. break;
  2570. }
  2571. Waitframe();
  2572.  
  2573. }
  2574. }
  2575.  
  2576. if ( dat == 0 && loopBossMusic == 0 && !playing )
  2577. {
  2578. Game->PlayEnhancedMusic(boss_buffer, trkBoss);
  2579. if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) )
  2580. {
  2581. if ( midiNumber > 0 )
  2582. {
  2583. Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available.
  2584. }
  2585. else
  2586. {
  2587. Game->PlayMIDI(DEFAULT_BOSS_MUSIC); //Plays default if not specified.
  2588. }
  2589. }
  2590. playing = true;
  2591.  
  2592. }
  2593.  
  2594. dat = Game->GetScreenD(curScreen,reg);
  2595. if ( dat > 0 )
  2596. {
  2597. if ( dur > 0 )
  2598. {
  2599. Game->PlayEnhancedMusic(victory_buffer, trkVictory);
  2600. if ( ! Game->PlayEnhancedMusic(victory_buffer, trkVictory) )
  2601. {
  2602. if ( victoryMIDI > 0 )
  2603. {
  2604. Game->PlayMIDI(victoryMIDI);
  2605. }
  2606. else
  2607. {
  2608. Game->PlayMIDI(MIDI_DEFEATBOSS); //Plays default if Victory MIDI not specified.
  2609. }
  2610.  
  2611. }
  2612. for ( int q = 0; q <= dur; ++q )
  2613. {
  2614. Waitframe(); //Pause for duration of victory music.
  2615. }
  2616. }
  2617. Game->PlayEnhancedMusic(dmapMusicBuffer, dmapTrack);
  2618. if ( ! Game->PlayEnhancedMusic(dmapMusicBuffer, dmapTrack) )
  2619. {
  2620. Game->PlayMIDI(stdMIDI);
  2621. }
  2622. Quit();
  2623. }
  2624. Waitframe();
  2625. }
  2626.  
  2627. }
  2628. }
  2629.  
  2630. // D0: MIDI number to default to for this boss, if no enhanced music is available.
  2631. // Split argument, high and low at decimal point:
  2632. // #####.xxxx -> Backup MIDI file to play if enhanced BOSS music is not available.
  2633. // xxxxx.#### -> Backup MIDI file to play if enhanced VICTORY music is not available.
  2634. // D1: Screen->D reg to set/check.
  2635. // D2: Set to a value of '1' or higher, to use durations.
  2636. // D3: Sets file type for both enhanced music tracks. Split argument, high and low at decimal point:
  2637. // xxx##.xxxx -> Type for Boss Music file
  2638. // xxxxx.xx## -> Type for Victory Music file
  2639. // D4: The file number, and track number, for Boss Music. Split arg, high and low at decimal point:
  2640. // #####.xxxx -> The file number.
  2641. // xxxxx.#### -> The track number to play.
  2642. // D5: The file number, and track number, for Victory Music. Split arg, high and low at decimal point:
  2643. // #####.xxxx -> The file number.
  2644. // xxxxx.#### -> The track number to play.
  2645. // D6: The point in the track to pause, then loop.
  2646. //
  2647. // If set to 0, the track with loop only when it ends.
  2648. // If set to greater than 0, the track will loop befor eit ends, as follows:
  2649. // To loop by setting minutes, and seconds, set up minutes as the integer portion of the arg, and seconds as the decimal portion:
  2650. // e.g. 00005.0260 is 5 mins, 26 seconds.
  2651. // This works to a fineness of 1/10 second, so 00010.0136 is 10 minutes, 13.6 seconds.
  2652. // If you wish to specify the loop in frames, set the ten-thousands place to '1', and the rest of the value to the number of frames.
  2653. // e.g. 10526.1023 = 5,261,023 frames.
  2654. // e.g. 10001.3591 = 13,591 frames.
  2655. //
  2656. // D7: This value instructs the FFC to set Screen->D[reg] = 1 when enemies are dead.
  2657. // #####.xxxx -> A value of zero here, instructs the FFC not to change the Screen->D[reg] value. Leave this at zero, if the enemy does this.
  2658. // Otherwise, set this to -1 (negative one) if you want the Victory music to play when all screen NPCs are dead...or...
  2659. // a positive value matching an enemy ID that is on the screen, if you want to play the Victory music when all enemies with that ID are dead.
  2660. // xxxxx.#### -> Set to '1' or higher to enable debugging reports to allegro.log.
  2661. //
  2662.  
  2663. //Version 0.44 (Numbered Files)
  2664.  
  2665. ffc script BossMusicEnhanced_old
  2666. {
  2667. void run(int midiNumber_victoryMidiNumber, int reg, int victoryDur, float musicType_musicTypeVictory, float musicBoss_trkBoss, float musicVictory_trkVictory, float loopBossMusic, int enem_debug)
  2668. {
  2669. int curScreen = Game->GetCurScreen();
  2670. int curDMAP = Game->GetCurDMap();
  2671. int curDmap = Game->GetCurDMap();
  2672. int dat = Game->GetScreenD(curScreen,reg);
  2673. int stdMIDI = Game->DMapMIDI[curDMAP];
  2674. int enem = _Music_zh__GetHighArgument(enem_debug);
  2675. int debug= _Music_zh__GetLowArgument(enem_debug);
  2676.  
  2677. int dmapMusicBuffer[512]=" ";
  2678. Game->GetDMapMusicFilename(curDMAP, dmapMusicBuffer);
  2679.  
  2680. int midiNumber = _Music_zh__GetHighArgument(midiNumber_victoryMidiNumber); //#####.xxxx
  2681. int victoryMIDI = _Music_zh__GetLowArgument(midiNumber_victoryMidiNumber); //xxxxx.####
  2682.  
  2683. int musicType = _Music_zh__GetHighArgument(musicType_musicTypeVictory); //xxx##.xxxx
  2684. int musicType_Victory = _Music_zh__GetLowArgument(musicType_musicTypeVictory); //xxxxx.xx##
  2685.  
  2686. int musicBoss = _Music_zh__GetHighArgument(musicBoss_trkBoss); //#####.xxxx
  2687. int trkBoss = _Music_zh__GetLowArgument(musicBoss_trkBoss); //xxxxx.####
  2688.  
  2689. int musicVictory = _Music_zh__GetHighArgument(musicVictory_trkVictory); //#####.xxxx
  2690. int trkVictory = _Music_zh__GetLowArgument(musicVictory_trkVictory); //xxxxx.####
  2691.  
  2692. int dmapTrack = Game->GetDMapMusicTrack(curDMAP);
  2693. int mp3[]=".mp3";
  2694. int vgm[]=".vgm";
  2695. int nsf[]=".nsf";
  2696. int ogg[]=".ogg";
  2697. int s3m[]=".s3m";
  2698. int mod[]=".mod";
  2699. int spc[]=".spc";
  2700. int gym[]=".gym";
  2701. int gbs[]=".gbs";
  2702. int it_format[]=".it";
  2703. int xm[]=".xm";
  2704.  
  2705. int boss_buffer[7]=" "; //two-digit number, plus four-digit extension, plus NULL.
  2706. int victory_buffer[7]=" "; //Buffer for Victory Music Filename.
  2707. int strBoss[2]=" "; //The two digit value of musicBoss arg.
  2708. int strVictory[2]=" "; //The two digit value of musicVictory is stored here.
  2709. //int bossMusic[]=" "; //Must read value from enhBoss, append .mp3 to it, and
  2710.  
  2711.  
  2712. ///Set up Boss Music Filename String
  2713. itoa(strBoss, musicBoss); //Copy the value of arg musicBoss into string strBoss.
  2714. strncpy(boss_buffer, strBoss, 2); //Copy filename (two-digit number) to buffer.
  2715. if ( musicType == 0 ) strcat(boss_buffer, mp3); //Append datatype to buffer (MP3)
  2716. else if ( musicType == 1 ) strcat(boss_buffer, vgm); //Append datatype to buffer ( Video Game Music format)
  2717. else if ( musicType == 2 ) strcat(boss_buffer, nsf); //Append datatype to buffer ( NES Sound File )
  2718. else if ( musicType == 3 ) strcat(boss_buffer, ogg); //Append datatype to buffer ( The Xiph.org open music format )
  2719. else if ( musicType == 4 ) strcat(boss_buffer, s3m); //Append datatype to buffer ( ScreamTracker 3 module file )
  2720. else if ( musicType == 5 ) strcat(boss_buffer, mod); //Append datatype to buffer ( Tracker Module file )
  2721. else if ( musicType == 6 ) strcat(boss_buffer, spc); //Append datatype to buffer ( Super NES / SuFami soound file )
  2722. else if ( musicType == 7 ) strcat(boss_buffer, gym); //Append datatype to buffer ( Genesis / Megadrive sound file )
  2723. else if ( musicType == 8 ) strcat(boss_buffer, gbs); //Append datatype to buffer ( Gameboy sound file )
  2724. else if ( musicType == 9 ) strcat(boss_buffer, it_format); //Append datatype to buffer ( Impulse Tracker audio file )
  2725. else if ( musicType == 10 ) strcat(boss_buffer, xm); //Append datatype to buffer ( Triton FastTracker 2 'Extended Module' format }
  2726. ///Other formats.
  2727.  
  2728. //Set up Victory Music Filename String
  2729. itoa(strVictory, musicVictory); //Copy the value of arg musicVictory into string strVictory.
  2730. strncpy(victory_buffer, strVictory, 2); //Copy filename (two-digit number) to buffer.
  2731. if ( musicType_Victory == 0 ) strcat(victory_buffer, mp3); //Append datatype to buffer (MP3)
  2732. else if ( musicType_Victory == 1 ) strcat(victory_buffer, vgm); //Append datatype to buffer ( Video Game Music format)
  2733. else if ( musicType_Victory == 2 ) strcat(victory_buffer, nsf); //Append datatype to buffer ( NES Sound File )
  2734. else if ( musicType_Victory == 3 ) strcat(victory_buffer, ogg); //Append datatype to buffer ( The Xiph.org open music format )
  2735. else if ( musicType_Victory == 4 ) strcat(victory_buffer, s3m); //Append datatype to buffer ( ScreamTracker 3 module file )
  2736. else if ( musicType_Victory == 5 ) strcat(victory_buffer, mod); //Append datatype to buffer ( Tracker Module file )
  2737. else if ( musicType_Victory == 6 ) strcat(victory_buffer, spc); //Append datatype to buffer ( Super NES / SuFami soound file )
  2738. else if ( musicType_Victory == 7 ) strcat(victory_buffer, gym); //Append datatype to buffer ( Genesis / Megadrive sound file )
  2739. else if ( musicType_Victory == 8 ) strcat(victory_buffer, gbs); //Append datatype to buffer ( Gameboy sound file )
  2740. else if ( musicType_Victory == 9 ) strcat(victory_buffer, it_format); //Append datatype to buffer ( Impulse Tracker audio file )
  2741. else if ( musicType_Victory == 10 ) strcat(victory_buffer, xm); //Append datatype to buffer ( Triton FastTracker 2 'Extended Module' format }
  2742. ///Other formats.
  2743.  
  2744.  
  2745. //Print filenames to allegro.log.
  2746. if ( debug )
  2747. {
  2748. int loading[]="Attempting to load file: ";
  2749. TraceNL();
  2750. TraceS(loading);
  2751. TraceNL();
  2752. TraceS(boss_buffer);
  2753. TraceNL();
  2754. TraceS(loading);
  2755. TraceNL();
  2756. TraceS(victory_buffer);
  2757. TraceNL();
  2758. }
  2759.  
  2760. int playingBoss[]="Playing Boss Music";
  2761. int playingVictory[]="Playing Victory Music";
  2762. int errLoading[]="Error loading track.";
  2763.  
  2764. int LoopClockMethod = _Music_zh__GetDigit(loopBossMusic, 4);
  2765. //Convert mins and seconds.
  2766.  
  2767.  
  2768. int BossMusicDuration;
  2769. if ( LoopClockMethod == 0 )
  2770. {
  2771. BossMusicDuration = MusicFrames(loopBossMusic); //Convert loopBossMusic into time.
  2772. }
  2773. if ( LoopClockMethod > 0 )
  2774. {
  2775. BossMusicDuration = _Music_zh__GetPartialArg(loopBossMusic,3,8); //Use the full value of loopBossMusic as frame in int.
  2776. }
  2777.  
  2778. int VictoryDuration;
  2779. int VictoryDurMethod = _Music_zh__GetDigit(victoryDur, 4);
  2780. if ( VictoryDurMethod == 0 )
  2781. {
  2782. VictoryDuration = MusicFrames(victoryDur); //Convert loopBossMusic into time.
  2783. }
  2784. if ( VictoryDurMethod > 0 )
  2785. {
  2786. VictoryDuration = _Music_zh__GetPartialArg(victoryDur,3,8); //Use the full value of loopBossMusic as frame in int.
  2787. }
  2788.  
  2789.  
  2790. bool playing = false;
  2791. Waitframes(6); //Wait for enemies to spawn. //Moved up here in 1.3.4
  2792. while(true)
  2793. {
  2794. dat = Game->GetScreenD(curScreen,reg);
  2795. //Waitframes(6); //Wait for enemies to spawn. 1.3.4
  2796. //Set Screen->D[reg] = 1 if the enemy is dead.
  2797. if ( enem == -1 && !Screen->NumNPCs() )
  2798. {
  2799. Game->SetScreenD(curScreen,reg,1);
  2800. }
  2801. if ( enem == 0 )
  2802. {
  2803. //Should we do anything special?
  2804. //A zero value is intended to be used if we don;t want the FFC to set Screen->D to 1.
  2805. //-1 if we do it based on all enemies being dead.
  2806. //A positive value trips it if there are no enemies of that ID on the screen.
  2807. }
  2808.  
  2809. if ( enem > 0 && !NumNPCsOf(enem) )
  2810. {
  2811. Game->SetScreenD(curScreen,reg,1);
  2812. }
  2813.  
  2814. dat = Game->GetScreenD(curScreen,reg);
  2815.  
  2816. if ( dat == 0 && loopBossMusic == 0 && !playing )
  2817. {
  2818. Game->PlayEnhancedMusic(boss_buffer, trkBoss);
  2819.  
  2820. if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) )
  2821. {
  2822. if ( midiNumber > 0 )
  2823. {
  2824. Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available.
  2825. }
  2826. else
  2827. {
  2828. Game->PlayMIDI(DEFAULT_BOSS_MUSIC); //Play default if not assigned.
  2829. }
  2830.  
  2831. }
  2832.  
  2833. playing = true;
  2834. }
  2835.  
  2836. if ( dat == 0 && loopBossMusic > 0 )
  2837. {
  2838. //set up music loop
  2839. for ( int q = BossMusicDuration; q >=0; q-- ){
  2840. if ( q == BossMusicDuration && dat == 0 )
  2841. {
  2842.  
  2843. Game->PlayEnhancedMusic(boss_buffer, trkBoss);
  2844. if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) )
  2845. {
  2846. if ( midiNumber > 0 )
  2847. {
  2848. Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available.
  2849. }
  2850. else
  2851. {
  2852. Game->PlayMIDI(DEFAULT_BOSS_MUSIC); //Play default if not assigned.
  2853. }
  2854. }
  2855. }
  2856. if ( enem == -1 && !Screen->NumNPCs() )
  2857. {
  2858. Game->SetScreenD(curScreen,reg,1);
  2859. }
  2860. if ( enem == 0 )
  2861. {
  2862. //Should we do anything special?
  2863. //A zero value is intended to be used if we don;t want the FFC to set Screen->D to 1.
  2864. //-1 if we do it based on all enemies being dead.
  2865. //A positive value trips it if there are no enemies of that ID on the screen.
  2866. }
  2867. if ( enem > 0 && !NumNPCsOf(enem) )
  2868. {
  2869. Game->SetScreenD(curScreen,reg,1);
  2870. }
  2871. dat = Game->GetScreenD(curScreen,reg);
  2872. if ( dat > 0 )
  2873. {
  2874. break;
  2875. }
  2876. Waitframe();
  2877.  
  2878. }
  2879. }
  2880.  
  2881. if ( dat == 0 && loopBossMusic == 0 && !playing )
  2882. {
  2883.  
  2884. Game->PlayEnhancedMusic(boss_buffer, trkBoss);
  2885. if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) )
  2886. {
  2887. if ( midiNumber > 0 )
  2888. {
  2889. Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available.
  2890. }
  2891. else
  2892. {
  2893. Game->PlayMIDI(DEFAULT_BOSS_MUSIC); //Play default if not assigned.
  2894. }
  2895. }
  2896. playing = true;
  2897.  
  2898. }
  2899.  
  2900. dat = Game->GetScreenD(curScreen,reg);
  2901. if ( dat > 0 )
  2902. {
  2903. if ( VictoryDuration > 0 )
  2904. {
  2905. Game->PlayEnhancedMusic(victory_buffer, trkVictory);
  2906. if ( ! Game->PlayEnhancedMusic(victory_buffer, trkVictory) )
  2907. {
  2908. if ( victoryMIDI > 0 )
  2909. {
  2910. Game->PlayMIDI(victoryMIDI);
  2911. }
  2912. else
  2913. {
  2914. Game->PlayMIDI(MIDI_DEFEATBOSS);
  2915. }
  2916.  
  2917. }
  2918. for ( int q = 0; q <= VictoryDuration; q++ )
  2919. {
  2920. Waitframe(); //Pause for duration of victory music.
  2921. }
  2922. }
  2923. Game->PlayEnhancedMusic(dmapMusicBuffer, dmapTrack);
  2924. if ( ! Game->PlayEnhancedMusic(dmapMusicBuffer, dmapTrack) )
  2925. {
  2926. Game->PlayMIDI(stdMIDI);
  2927. }
  2928. Quit();
  2929. }
  2930. Waitframe();
  2931. }
  2932.  
  2933. }
  2934. }
  2935.  
  2936. /////////////////
  2937. /// FUNCTIONS ///
  2938. /////////////////
  2939.  
  2940. //Pass a float to either of these, to convert raw float into mins and seconds as:
  2941. // #####.xxxx = # mins x seconds. Example:
  2942. // 00003.0050 = 3 mins, 5 seconds.
  2943. // 00001.0012 = 1 minute, 5.2 seconds.
  2944.  
  2945. //Timers are functional to a total clock of 3579 seconds (59 mins, 39 seconds).
  2946.  
  2947. int MusicSeconds(float seconds)
  2948. {
  2949. int music_seconds = _Music_zh__GetLowArgument(seconds);
  2950. return music_seconds * 6;
  2951. }
  2952.  
  2953. int MusicMinutes(float mins)
  2954. {
  2955. int music_minutes = _Music_zh__GetHighArgument(mins);
  2956. return music_minutes * 360;
  2957. }
  2958.  
  2959. //Returns total time in frames, so that ZC understands it.
  2960.  
  2961. int MusicFrames(float val)
  2962. {
  2963. int mins = MusicMinutes(val);
  2964. int seconds = MusicSeconds(val);
  2965. return mins+seconds;
  2966. }
  2967.  
  2968.  
  2969. int _Music_zh__GetRemainderAsInt(int v)
  2970. {
  2971. int r = (v - (v << 0)) * 10000;
  2972. return r;
  2973. }
  2974.  
  2975. // This function breaks up the value of an argument into individual digits. It is combined with the function GetDigit below.
  2976.  
  2977.  
  2978. int _Music_zh__GetDigit(int n, int place)
  2979. {
  2980. //GetDigit and related functions by Gleeok
  2981. place = Clamp(place, -4, 4);
  2982. if(place < 0){
  2983. n = _Music_zh__GetRemainderAsInt(n);
  2984. place += 4;
  2985. }
  2986.  
  2987. int r = ((n / Pow(10, place)) % 10) << 0;
  2988. return r;
  2989. }
  2990.  
  2991. int _Music_zh__GetHighArgument(int arg)
  2992. {
  2993. return arg >> 0;
  2994. }
  2995.  
  2996. int _Music_zh__GetLowArgument(int arg)
  2997. {
  2998. return (arg - (arg >> 0)) * 10000;
  2999. }
  3000.  
  3001. int _Music_zh__GetPartialArg(int arg, int place, int num)
  3002. {
  3003. place = Clamp(place, -4, 4);
  3004. int r;
  3005. int adj = 1;
  3006. for(int i = num-1; i > -1; i--)
  3007. {
  3008. if(place - i < -4) continue;
  3009. r += _Music_zh__GetDigit(arg, place - i) * adj;
  3010. adj *= 10;
  3011. }
  3012. return r;
  3013. }
  3014.  
  3015.  
  3016. // Plays enhanced music file by reading the string 'str_id' from Quest->Strings, at a specified track 'track_id'.
  3017. // If track_id is positive, it uses this track.
  3018. // If track_id is negative, it uses the message string equal to the inverse value (so -20 is string ID 20)
  3019. // to set the track ID.
  3020. // Returns true if playing, false otherwise.
  3021. bool PlayEnhMusicFile(int str_id, int track_id)
  3022. {
  3023. int musicBuffer[256]=" ";
  3024. int track_buffer[256]=" ";
  3025. int q; int trk;
  3026. Game->GetMessage(str_id, musicBuffer);
  3027. for ( q = 0; q < 256; ++q ) { if ( musicBuffer[q] == ' ' ) musicBuffer[q] = 0; } //Kill GetMessage trailing spaces.
  3028. if ( track_id < 0 )
  3029. {
  3030. Game->GetMessage((track_id * -1), track_buffer);
  3031. for ( q = 0; q < 256; ++q )
  3032. {
  3033. if ( track_buffer[q] == ' ' ) track_buffer[q] = 0;
  3034. } //Kill GetMessage trailing spaces.
  3035. trk = atoi(track_buffer);
  3036. }
  3037. else trk = track_id;
  3038. //Kill GetMessage trailing spaces.
  3039. bool play = Game->PlayEnhancedMusic(musicBuffer, trk);
  3040. return ( play );
  3041. }
  3042.  
  3043. int Legacy_PlayEnhMusicFile(int str_id, int track_id) { if ( PlayEnhMusicFile(str_id, track_id) ) return 1; return 0; }
  3044.  
  3045. ffc script music_zh_spawnnpc
  3046. {
  3047. void run(int nid)
  3048. {
  3049. int pos;
  3050. for ( int q = 0; q < 176; q++ )
  3051. {
  3052. if ( Screen->ComboF[q] == 37 ) pos = q;
  3053. }
  3054. while(1){
  3055. if ( Collision(this) )
  3056. {
  3057. npc n = Screen->CreateNPC(nid);
  3058.  
  3059. n->X = ComboX(pos); n->Y = ComboY(pos);
  3060. Quit();
  3061. }
  3062. Waitframe();
  3063.  
  3064. }
  3065. }
  3066. }
  3067.  
  3068. void WandSound(int sound)
  3069. {
  3070. int itmA = GetEquipmentA();
  3071. int itmB = GetEquipmentB();
  3072. itemdata ida = Game->LoadItemData(itmA);
  3073. itemdata idb = Game->LoadItemData(itmB);
  3074. if ( ( ida->Family == IC_WAND && Link->PressA ) || ( idb->Family == IC_WAND && Link->PressB ) )
  3075. {
  3076. if ( !NumLWeaponsOf(LW_WAND) ) { Game->PlaySound(sound); }
  3077. }
  3078. }
  3079.  
  3080. global script Music_ZH_Global_Active
  3081. {
  3082. void run(){
  3083. while(true){
  3084. WandSound(30);
  3085. Waitdraw();
  3086. Waitframe();
  3087. }
  3088. }
  3089. }
  3090.  
  3091.  
  3092.  
  3093. ffc script fade
  3094. {
  3095. void run(int warptile)
  3096. {
  3097. bool waiting = true;
  3098. while(waiting) { Waitframe(); }
  3099. this->Data = warptile; this->X = Link->X; this->Y = Link->Y;
  3100. }
  3101. }
  3102.  
  3103. ffc script Hoffs_Message_Script
  3104. {
  3105. void run(int string, int delay, int no_return, int string2, int toggle, int screen_var, int item_id)
  3106. {
  3107. //This variable is used to check if you have entered the screen before
  3108. int screen_check = 1;
  3109.  
  3110. //If you have chosen to use a delay(more then 0)
  3111. if (delay > 0)
  3112. {
  3113. //Wait for "delay" amount of frames. 60 frames = 1 second
  3114. Waitframes(delay);
  3115. }
  3116.  
  3117. //If you want to show a string depending on if you have a certain item or not
  3118. if ((item_id > 0))
  3119. {
  3120. //If you do not have a certain item
  3121. if (!Link->Item[item_id])
  3122. {
  3123. //Show the first string on the screen
  3124. Screen->Message(string);
  3125. }
  3126.  
  3127. //If you do have that item
  3128. else if(Link->Item[item_id])
  3129. {
  3130. //Show the second string on the screen
  3131. Screen->Message(string2);
  3132. }
  3133. }
  3134.  
  3135. else
  3136. {
  3137. //This runs the first time you enter the screen
  3138. if (Screen->D[screen_var] != screen_check)
  3139. {
  3140. //Show the first string on the screen
  3141. Screen->Message(string);
  3142.  
  3143. //If you have chosen to use a second string
  3144. if (string2 > 0)
  3145. {
  3146. //Set Screen->D[screen_var] to be equal to screen_check(1)
  3147. Screen->D[screen_var] = screen_check;
  3148. }
  3149. }
  3150.  
  3151. //This runs if you have chosen to use a second string,
  3152. //and you have already visited the screen once before
  3153. else
  3154. {
  3155. //Show the second string on the screen
  3156. Screen->Message(string2);
  3157.  
  3158. //If you want to toggle between string1 and string2 every time you enter the screen
  3159. if (toggle > 0)
  3160. {
  3161. //Now Zelda Classic will think that you have never visited the screen before :)
  3162. //(Seriously, this just changes the Screen->D[screen_var] variable to the default value)
  3163. Screen->D[screen_var] = 0;
  3164. }
  3165. }
  3166.  
  3167. //This only runs if you have set D2(no_return) to 1 or more
  3168. if (no_return > 0)
  3169. {
  3170. //Set Screen->D[screen_var] to be equal to screen_check(1)
  3171. Screen->D[screen_var] = screen_check;
  3172. }
  3173. }
  3174. }
  3175. }
  3176.  
  3177. const int COMPASS_BEEP = 7; //Set this to the SFX id you want to hear when you have the compass,
  3178.  
  3179. //Instructions:
  3180. //1.- Compile and add this to your ZQuest buffer.
  3181. //2.- Add an FFC with this script attached to the screen where you want to hear the compass beep.
  3182. //3.- Let the script do the rest.
  3183.  
  3184. //How does it work:
  3185. //The script checks if ANY of the following has been done:
  3186. //a) Item or Special Item has been picked up.
  3187. //b) Any type of chest has been opened.
  3188. //c) If NOTHING of the above has been done, the script runs. Otherwise, no SFX is heard.
  3189.  
  3190. ffc script CompassBeep{
  3191. void run(){
  3192. if(!Screen->State[ST_ITEM] &&
  3193. !Screen->State[ST_CHEST] &&
  3194. !Screen->State[ST_LOCKEDCHEST] &&
  3195. !Screen->State[ST_BOSSCHEST] &&
  3196. !Screen->State[ST_SPECIALITEM] && (Game->LItems[Game->GetCurLevel()] & LI_COMPASS)){
  3197. Game->PlaySound(COMPASS_BEEP);
  3198. }
  3199. }
  3200. }
  3201.  
  3202. ffc script SpinAttackCheck{
  3203. void run(int sfx){
  3204. if ( Screen->State[ST_SECRET] )
  3205. Quit();
  3206. bool spin;
  3207. while(true){
  3208. if ( Link->Action == LA_SPINNING )
  3209. spin = true;
  3210. if ( !Link->Action == LA_SPINNING && spin ) {
  3211. if ( sfx == 0 )
  3212. Game->PlaySound(27);
  3213. if ( sfx > 0 )
  3214. Game->PlaySound(sfx);
  3215. Screen->TriggerSecrets();
  3216. Screen->State[ST_SECRET] = true;
  3217. Quit();
  3218. }
  3219. Waitframe();
  3220. }
  3221. }
  3222. }
  3223.  
  3224. const int SFX_SWITCH_PRESS = 67; //SFX when a switch is pressed
  3225. const int SFX_SWITCH_RELEASE = 67; //SFX when a switch is released
  3226. const int SFX_SWITCH_ERROR = 68; //SFX when the wrong switch is pressed
  3227.  
  3228. int Switch_Pressed(int x, int y){
  3229. int xOff = 0;
  3230. int yOff = 4;
  3231. int xDist = 8;
  3232. int yDist = 8;
  3233. if(Abs(Link->X+xOff-x)<=xDist&&Abs(Link->Y+yOff-y)<=yDist)
  3234. return 1;
  3235. if(Screen->MovingBlockX>-1){
  3236. if(Abs(Screen->MovingBlockX-x)<=8&&Abs(Screen->MovingBlockY-y)<=8)
  3237. return 1;
  3238. }
  3239. if(Screen->isSolid(x+4, y+4)||
  3240. Screen->isSolid(x+12, y+4)||
  3241. Screen->isSolid(x+4, y+12)||
  3242. Screen->isSolid(x+12, y+12)){
  3243. return 2;
  3244. }
  3245. return 0;
  3246. }
  3247.  
  3248. ffc script Switch_Secret{
  3249. void run(int perm, int id, int sfx){
  3250. int d;
  3251. int db;
  3252. if(id>0){
  3253. d = Floor((id-1)/16);
  3254. db = 1<<((id-1)%16);
  3255. }
  3256. if(perm){
  3257. if(id>0){
  3258. if(Screen->D[d]&db){
  3259. this->Data++;
  3260. Screen->TriggerSecrets();
  3261. Quit();
  3262. }
  3263. }
  3264. else if(Screen->State[ST_SECRET]){
  3265. this->Data++;
  3266. Quit();
  3267. }
  3268. }
  3269. while(!Switch_Pressed(this->X, this->Y)){
  3270. Waitframe();
  3271. }
  3272. this->Data++;
  3273. Screen->TriggerSecrets();
  3274. Game->PlaySound(SFX_SWITCH_PRESS);
  3275. if(sfx==0)
  3276. Game->PlaySound(SFX_SECRET);
  3277. else if(sfx>0)
  3278. Game->PlaySound(sfx);
  3279. if(perm){
  3280. if(id>0)
  3281. Screen->D[d]|=db;
  3282. else
  3283. Screen->State[ST_SECRET] = true;
  3284. }
  3285. }
  3286. }
  3287.  
  3288. ffc script Switch_Remote{
  3289. void run(int pressure, int id, int flag, int sfx){
  3290. int data = this->Data;
  3291. int i; int j; int k;
  3292. int d;
  3293. int db;
  3294. if(id>0){
  3295. d = Floor((id-1)/16);
  3296. db = 1<<((id-1)%16);
  3297. }
  3298. int comboD[176];
  3299. for(i=0; i<176; i++){
  3300. if(Screen->ComboF[i]==flag){
  3301. comboD[i] = Screen->ComboD[i];
  3302. Screen->ComboF[i] = 0;
  3303. }
  3304. }
  3305. if(id>0){
  3306. if(Screen->D[d]&db){
  3307. this->Data = data+1;
  3308. for(i=0; i<176; i++){
  3309. if(comboD[i]>0){
  3310. Screen->ComboD[i] = comboD[i]+1;
  3311. }
  3312. }
  3313. Quit();
  3314. }
  3315. }
  3316. if(pressure){
  3317. while(true){
  3318. while(!Switch_Pressed(this->X, this->Y)){
  3319. Waitframe();
  3320. }
  3321. this->Data = data+1;
  3322. Game->PlaySound(SFX_SWITCH_PRESS);
  3323. for(i=0; i<176; i++){
  3324. if(comboD[i]>0){
  3325. Screen->ComboD[i] = comboD[i]+1;
  3326. }
  3327. }
  3328. while(Switch_Pressed(this->X, this->Y)){
  3329. Waitframe();
  3330. }
  3331. this->Data = data;
  3332. Game->PlaySound(SFX_SWITCH_RELEASE);
  3333. for(i=0; i<176; i++){
  3334. if(comboD[i]>0){
  3335. Screen->ComboD[i] = comboD[i];
  3336. }
  3337. }
  3338. }
  3339. }
  3340. else{
  3341. while(!Switch_Pressed(this->X, this->Y)){
  3342. Waitframe();
  3343. }
  3344. this->Data = data+1;
  3345. Game->PlaySound(SFX_SWITCH_PRESS);
  3346. if(sfx>0)
  3347. Game->PlaySound(sfx);
  3348. else
  3349. Game->PlaySound(SFX_SECRET);
  3350. for(i=0; i<176; i++){
  3351. if(comboD[i]>0){
  3352. Screen->ComboD[i] = comboD[i]+1;
  3353. }
  3354. }
  3355. if(id>0){
  3356. Screen->D[d] |= db;
  3357. }
  3358. }
  3359. }
  3360. }
  3361.  
  3362. ffc script Switch_HitAll{
  3363. void run(int switchCmb, int pressure, int perm, int id, int flag, int sfx, int switchID){
  3364. int i; int j; int k;
  3365. int d;
  3366. int db;
  3367. if(flag==0)
  3368. id = 0;
  3369. int comboD[176];
  3370. if(id>0){
  3371. d = Floor((id-1)/16);
  3372. db = 1<<((id-1)%16);
  3373. for(i=0; i<176; i++){
  3374. if(Screen->ComboF[i]==flag){
  3375. comboD[i] = Screen->ComboD[i];
  3376. Screen->ComboF[i] = 0;
  3377. }
  3378. }
  3379. }
  3380. int switches[34];
  3381. int switchD[34];
  3382. int switchDB[34];
  3383. switchD[0] = switchID;
  3384. bool switchesPressed[34];
  3385. k = SizeOfArray(switches)-2;
  3386. for(i=0; i<176&&switches[0]<k; i++){
  3387. if(Screen->ComboD[i]==switchCmb){
  3388. j = 2+switches[0];
  3389. switches[j] = i;
  3390. if(!pressure&&switchID>0){
  3391. switchD[j] = Floor((switchID+switches[0]-1)/16);
  3392. switchDB[j] = 1<<((switchID+switches[0]-1)%16);
  3393. if(Screen->D[switchD[j]]&switchDB[j]){
  3394. switchesPressed[j] = true;
  3395. Screen->ComboD[i] = switchCmb+1;
  3396. switches[1]++;
  3397. }
  3398. }
  3399. switches[0]++;
  3400. }
  3401. }
  3402. if(perm){
  3403. if(id>0){
  3404. if(Screen->D[d]&db){
  3405. for(i=2; i<switches[0]+2; i++){
  3406. Screen->ComboD[switches[i]] = switchCmb+1;
  3407. switchesPressed[i] = true;
  3408. }
  3409. for(i=0; i<176; i++){
  3410. if(comboD[i]>0){
  3411. Screen->ComboD[i] = comboD[i]+1;
  3412. }
  3413. }
  3414. while(true){
  3415. Switches_Update(switches, switchD, switchDB, switchesPressed, switchCmb, false);
  3416. Waitframe();
  3417. }
  3418. }
  3419. }
  3420. if(Screen->State[ST_SECRET]){
  3421. for(i=2; i<switches[0]+2; i++){
  3422. Screen->ComboD[switches[i]] = switchCmb+1;
  3423. switchesPressed[i] = true;
  3424. }
  3425. while(true){
  3426. Switches_Update(switches, switchD, switchDB, switchesPressed, switchCmb, false);
  3427. Waitframe();
  3428. }
  3429. }
  3430. }
  3431. if(pressure){
  3432. while(switches[1]<switches[0]){
  3433. Switches_Update(switches, switchD, switchDB, switchesPressed, switchCmb, true);
  3434. Waitframe();
  3435. }
  3436. if(id>0){
  3437. if(sfx>0)
  3438. Game->PlaySound(sfx);
  3439. else
  3440. Game->PlaySound(SFX_SECRET);
  3441. for(i=0; i<176; i++){
  3442. if(comboD[i]>0){
  3443. Screen->ComboD[i] = comboD[i]+1;
  3444. }
  3445. }
  3446. }
  3447. else{
  3448. if(sfx>0)
  3449. Game->PlaySound(sfx);
  3450. else
  3451. Game->PlaySound(SFX_SECRET);
  3452. Screen->TriggerSecrets();
  3453. }
  3454. if(perm){
  3455. if(id>0)
  3456. Screen->D[d] |= db;
  3457. else
  3458. Screen->State[ST_SECRET] = true;
  3459. }
  3460. }
  3461. else{
  3462. while(switches[1]<switches[0]){
  3463. Switches_Update(switches, switchD, switchDB, switchesPressed, switchCmb, false);
  3464. Waitframe();
  3465. }
  3466. if(id>0){
  3467. if(sfx>0)
  3468. Game->PlaySound(sfx);
  3469. else
  3470. Game->PlaySound(SFX_SECRET);
  3471. for(i=0; i<176; i++){
  3472. if(comboD[i]>0){
  3473. Screen->ComboD[i] = comboD[i]+1;
  3474. }
  3475. }
  3476. }
  3477. else{
  3478. if(sfx>0)
  3479. Game->PlaySound(sfx);
  3480. else
  3481. Game->PlaySound(SFX_SECRET);
  3482. Screen->TriggerSecrets();
  3483. }
  3484. if(perm){
  3485. if(id>0)
  3486. Screen->D[d] |= db;
  3487. else
  3488. Screen->State[ST_SECRET] = true;
  3489. }
  3490. }
  3491. while(true){
  3492. Switches_Update(switches, switchD, switchDB, switchesPressed, switchCmb, false);
  3493. Waitframe();
  3494. }
  3495. }
  3496. void Switches_Update(int switches, int switchD, int switchDB, bool switchesPressed, int switchCmb, bool pressure){
  3497. if(pressure)
  3498. switches[1] = 0;
  3499. for(int i=0; i<switches[0]; i++){
  3500. int j = i+2;
  3501. int k = switches[j];
  3502. int p = Switch_Pressed(ComboX(k), ComboY(k));
  3503. if(p){
  3504. if(p!=2)
  3505. Screen->ComboD[k] = switchCmb+1;
  3506. if(!switchesPressed[j]){
  3507. Game->PlaySound(SFX_SWITCH_PRESS);
  3508. if(switchD[0]>0){
  3509. Screen->D[switchD[j]] |= switchDB[j];
  3510. }
  3511. switchesPressed[j] = true;
  3512. if(!pressure)
  3513. switches[1]++;
  3514. }
  3515. if(pressure)
  3516. switches[1]++;
  3517. }
  3518. else{
  3519. if(switchesPressed[j]){
  3520. if(pressure){
  3521. Game->PlaySound(SFX_SWITCH_RELEASE);
  3522. Screen->ComboD[k] = switchCmb;
  3523. switchesPressed[j] = false;
  3524. }
  3525. else{
  3526. if(Screen->ComboD[k]!=switchCmb+1)
  3527. Screen->ComboD[k] = switchCmb+1;
  3528. }
  3529. }
  3530. }
  3531. }
  3532. }
  3533. }
  3534.  
  3535. ffc script Switch_Trap{
  3536. void run(int enemyid, int count){
  3537. while(!Switch_Pressed(this->X, this->Y)){
  3538. Waitframe();
  3539. }
  3540. this->Data++;
  3541. Game->PlaySound(SFX_SWITCH_PRESS);
  3542. Game->PlaySound(SFX_SWITCH_ERROR);
  3543. for(int i=0; i<count; i++){
  3544. int pos = Switch_GetSpawnPos();
  3545. npc n = CreateNPCAt(enemyid, ComboX(pos), ComboY(pos));
  3546. Game->PlaySound(SFX_FALL);
  3547. n->Z = 176;
  3548. Waitframes(20);
  3549. }
  3550. }
  3551. int Switch_GetSpawnPos(){
  3552. int pos;
  3553. bool invalid = true;
  3554. int failSafe = 0;
  3555. while(invalid&&failSafe<512){
  3556. pos = Rand(176);
  3557. if(Switch_ValidSpawn(pos))
  3558. return pos;
  3559. }
  3560. for(int i=0; i<176; i++){
  3561. pos = i;
  3562. if(Switch_ValidSpawn(pos))
  3563. return pos;
  3564. }
  3565. }
  3566. bool Switch_ValidSpawn(int pos){
  3567. int x = ComboX(pos);
  3568. int y = ComboY(pos);
  3569. if(Screen->isSolid(x+4, y+4)||
  3570. Screen->isSolid(x+12, y+4)||
  3571. Screen->isSolid(x+4, y+12)||
  3572. Screen->isSolid(x+12, y+12)){
  3573. return false;
  3574.  
  3575. }
  3576. if(ComboFI(pos, CF_NOENEMY)||ComboFI(pos, CF_NOGROUNDENEMY))
  3577. return false;
  3578. int ct = Screen->ComboT[pos];
  3579. if(ct==CT_NOENEMY||ct==CT_NOGROUNDENEMY||ct==CT_NOJUMPZONE)
  3580. return false;
  3581. if(ct==CT_WATER||ct==CT_LADDERONLY||ct==CT_HOOKSHOTONLY||ct==CT_LADDERHOOKSHOT)
  3582. return false;
  3583. if(ct==CT_PIT||ct==CT_PITB||ct==CT_PITC||ct==CT_PITD||ct==CT_PITR)
  3584. return false;
  3585. return true;
  3586. }
  3587. }
  3588.  
  3589. ffc script Switch_Sequential{
  3590. void run(int flag, int perm, int sfx){
  3591. int i; int j; int k;
  3592. int switches[34];
  3593. int switchCmb[34];
  3594. int switchMisc[8];
  3595. bool switchesPressed[34];
  3596. k = SizeOfArray(switches)-2;
  3597. for(i=0; i<176&&switches[0]<k; i++){
  3598. if(Screen->ComboF[i]==flag){
  3599. j = 2+switches[0];
  3600. switches[j] = i;
  3601. switchCmb[j] = Screen->ComboD[i];
  3602. switches[0]++;
  3603. }
  3604. }
  3605. int switchOrder[34];
  3606. Switches_Organize(switches, switchOrder);
  3607. if(perm&&Screen->State[ST_SECRET]){
  3608. for(i=0; i<switches[0]; i++){
  3609. switchesPressed[i+2] = true;
  3610. }
  3611. while(true){
  3612. Switches_Update(switches, switchesPressed, switchOrder, switchCmb, switchMisc, false);
  3613. Waitframe();
  3614. }
  3615. }
  3616. while(switches[1]<switches[0]){
  3617. Switches_Update(switches, switchesPressed, switchOrder, switchCmb, switchMisc, true);
  3618. if(switchMisc[0]==1){
  3619. switchMisc[0] = 0;
  3620. for(i=0; i<30; i++){
  3621. Switches_Update(switches, switchesPressed, switchOrder, switchCmb, switchMisc, false);
  3622. Waitframe();
  3623. }
  3624. while(Switches_LinkOn(switches)){
  3625. Switches_Update(switches, switchesPressed, switchOrder, switchCmb, switchMisc, false);
  3626. Waitframe();
  3627. }
  3628. }
  3629. Waitframe();
  3630. }
  3631. if(sfx>0)
  3632. Game->PlaySound(sfx);
  3633. else
  3634. Game->PlaySound(SFX_SECRET);
  3635. Screen->TriggerSecrets();
  3636. if(perm)
  3637. Screen->State[ST_SECRET] = true;
  3638. for(i=0; i<switches[0]; i++){
  3639. switchesPressed[i+2] = true;
  3640. }
  3641. while(true){
  3642. Switches_Update(switches, switchesPressed, switchOrder, switchCmb, switchMisc, false);
  3643. Waitframe();
  3644. }
  3645.  
  3646. }
  3647. void Switches_Organize(int switches, int switchOrder){
  3648. bool banned[34];
  3649. for(int j=0; j<switches[0]; j++){
  3650. int lowest = -1;
  3651. int lowestIndex = -1;
  3652. for(int i=0; i<switches[0]; i++){
  3653. int c = Screen->ComboD[switches[i+2]];
  3654. if(c!=-1&&!banned[i+2]){
  3655. if(lowest==-1||c<lowest){
  3656. lowest = c;
  3657. lowestIndex = i+2;
  3658. }
  3659. }
  3660. }
  3661. switchOrder[j] = lowestIndex;
  3662. banned[lowestIndex] = true;
  3663. }
  3664. }
  3665. bool Switches_LinkOn(int switches){
  3666. for(int i=0; i<switches[0]; i++){
  3667. int j = i+2;
  3668. int k = switches[j];
  3669. int p = Switch_Pressed(ComboX(k), ComboY(k));
  3670. if(p==1)
  3671. return true;
  3672. }
  3673. return false;
  3674. }
  3675. void Switches_Update(int switches, bool switchesPressed, int switchOrder, int switchCmb, int switchMisc, bool canPress){
  3676. bool reset;
  3677. for(int i=0; i<switches[0]; i++){
  3678. int j = i+2;
  3679. int k = switches[j];
  3680. int p = Switch_Pressed(ComboX(k), ComboY(k));
  3681. if(!switchesPressed[j]){
  3682. if(p!=2)
  3683. Screen->ComboD[k] = switchCmb[j];
  3684. if(p&&canPress){
  3685. if(j==switchOrder[switches[1]]){
  3686. switches[1]++;
  3687. Game->PlaySound(SFX_SWITCH_PRESS);
  3688. switchesPressed[j] = true;
  3689. }
  3690. else{
  3691. switches[1] = 0;
  3692. Game->PlaySound(SFX_SWITCH_ERROR);
  3693. reset = true;
  3694. }
  3695. }
  3696. }
  3697. else{
  3698. if(p!=2)
  3699. Screen->ComboD[k] = switchCmb[j]+1;
  3700. if(p==0&&canPress){
  3701. Game->PlaySound(SFX_SWITCH_RELEASE);
  3702. switchesPressed[j] = false;
  3703. }
  3704. }
  3705. }
  3706. if(reset){
  3707. switchMisc[0] = 1;
  3708. for(int i=0; i<switches[0]; i++){
  3709. int j = i+2;
  3710. int k = switches[j];
  3711. int p = Switch_Pressed(ComboX(k), ComboY(k));
  3712. switchesPressed[j] = false;
  3713. }
  3714. }
  3715. }
  3716. }
  3717.  
  3718. // Edit the following constants according to your tileset.
  3719.  
  3720. // All combos between and including these two values will be considered regular diggable combos.
  3721. // The combo dug by the player will change, and there will be a chance for an item drop.
  3722. const int DigComboStart=3266;
  3723. const int DigComboEnd=3273;
  3724.  
  3725. // The following combos are similarly diggable, but turn into a different kind of combo and
  3726. // do not give item drops. You can use this to have secret stairs, for example.
  3727. // Important: Make sure these combos directly follow the DigComboEnd one.
  3728. const int DigSpecialStart=3274;
  3729. const int DigSpecialEnd=3277;
  3730.  
  3731. // A regular diggable combo will turn into this combo when you use the shovel on it.
  3732. const int DugComboNormal=3278;
  3733.  
  3734. // A special combo will turn into this combo when you use the shovel on it.
  3735. // You can, for example, make it a tile warp, so the player can dig for secret entrances.
  3736. // Set up the warps and the arrival points on your ZQuest screen as usual.
  3737. const int DugComboSpecial=3279;
  3738.  
  3739. // This is the sound to be played when you successfully dig.
  3740. const int ShovelSound=4;
  3741. // The sound to be played when you attempt to dig an undiggable combo.
  3742. const int ShovelFail=51;
  3743. // The secret sound to be played when you dig a special combo.
  3744. const int SecretSound=25;
  3745.  
  3746. item script Shovel{
  3747. void run(){
  3748. int chance;
  3749. int itemdrop;
  3750. int itemlocx;
  3751. int itemlocy;
  3752. Link->Action=LA_ATTACKING;
  3753. if((Link->Dir==0&&(Screen->ComboD[ComboAt(Link->X+8,Link->Y-8)]<DigComboStart||Screen->ComboD[ComboAt(Link->X+8,Link->Y-8)]>DigSpecialEnd))
  3754. ||(Link->Dir==1&&(Screen->ComboD[ComboAt(Link->X+8,Link->Y+24)]<DigComboStart||Screen->ComboD[ComboAt(Link->X+8,Link->Y+24)]>DigSpecialEnd))
  3755. ||(Link->Dir==2&&(Screen->ComboD[ComboAt(Link->X-8,Link->Y+8)]<DigComboStart||Screen->ComboD[ComboAt(Link->X-8,Link->Y+8)]>DigSpecialEnd))
  3756. ||(Link->Dir==3&&(Screen->ComboD[ComboAt(Link->X+24,Link->Y+8)]<DigComboStart||Screen->ComboD[ComboAt(Link->X+24,Link->Y+8)]>DigSpecialEnd))){
  3757. Game->PlaySound(ShovelFail);
  3758. }
  3759. else{
  3760. Game->PlaySound(ShovelSound);
  3761. chance=Rand(100)+1;
  3762. if(Link->Dir==0){
  3763. if(Screen->ComboD[ComboAt(Link->X+8,Link->Y-8)]<DigSpecialStart){
  3764. Screen->ComboD[ComboAt(Link->X+8,Link->Y-8)]=DugComboNormal;
  3765. }
  3766. else{
  3767. Game->PlaySound(SecretSound);
  3768. Screen->ComboD[ComboAt(Link->X+8,Link->Y-8)]=DugComboSpecial;
  3769. chance=101;
  3770. }
  3771. }
  3772. if(Link->Dir==1){
  3773. if(Screen->ComboD[ComboAt(Link->X+8,Link->Y+24)]<DigSpecialStart){
  3774. Screen->ComboD[ComboAt(Link->X+8,Link->Y+24)]=DugComboNormal;
  3775. }
  3776. else{
  3777. Game->PlaySound(SecretSound);
  3778. Screen->ComboD[ComboAt(Link->X+8,Link->Y+24)]=DugComboSpecial;
  3779. chance=101;
  3780. }
  3781. }
  3782. if(Link->Dir==2){
  3783. if(Screen->ComboD[ComboAt(Link->X-8,Link->Y+8)]<DigSpecialStart){
  3784. Screen->ComboD[ComboAt(Link->X-8,Link->Y+8)]=DugComboNormal;
  3785. }
  3786. else{
  3787. Game->PlaySound(SecretSound);
  3788. Screen->ComboD[ComboAt(Link->X-8,Link->Y+8)]=DugComboSpecial;
  3789. chance=101;
  3790. }
  3791. }
  3792. if(Link->Dir==3){
  3793. if(Screen->ComboD[ComboAt(Link->X+24,Link->Y+8)]<DigSpecialStart){
  3794. Screen->ComboD[ComboAt(Link->X+24,Link->Y+8)]=DugComboNormal;
  3795. }
  3796. else{
  3797. Game->PlaySound(SecretSound);
  3798. Screen->ComboD[ComboAt(Link->X+24,Link->Y+8)]=DugComboSpecial;
  3799. chance=101;
  3800. }
  3801. }
  3802. // The item drops are currently set to be the same as the default tall grass combo drops.
  3803. // The variable "chance" is a randomly generated number between 1 and 100.
  3804. // It determines whether you will get an item, and if so, which one.
  3805. // Here, you have a 20% chance to spawn 1 rupee, and a 15% chance to spawn a heart.
  3806. // If you want, edit this or add more lines to spawn more drops.
  3807. // You can use this line as a template: if(chance>=21&&chance<=35)itemdrop=2;
  3808. // The "chance" variable determines the chance you have of obtaining the item, as we've
  3809. // seen before, and the "itemdrop" variable is the number of the item in ZQuest.
  3810. if(chance<=20)itemdrop=0;
  3811. if(chance>=21&&chance<=35)itemdrop=2;
  3812. // NB: If you dug a special combo, the "chance" variable is automatically set to 101 so
  3813. // the script won't spawn drops on top of special combos like stairs.
  3814. if(Link->Dir==0){
  3815. itemlocx=Link->X;
  3816. itemlocy=Link->Y-16;
  3817. }
  3818. if(Link->Dir==1){
  3819. itemlocx=Link->X;
  3820. itemlocy=Link->Y+16;
  3821. }
  3822. if(Link->Dir==2){
  3823. itemlocx=Link->X-16;
  3824. itemlocy=Link->Y;
  3825. }
  3826. if(Link->Dir==3){
  3827. itemlocx=Link->X+16;
  3828. itemlocy=Link->Y;
  3829. }
  3830. // This is the part of the code that spawns the item.
  3831. // If you have edited the default item drops, change "35" and set it according to your drops.
  3832. if(chance<=35){
  3833. item i=Screen->CreateItem(itemdrop);
  3834. i->X=itemlocx;
  3835. i->Y=itemlocy;
  3836. i->Z=10;
  3837. i->Pickup=IP_TIMEOUT;
  3838. }
  3839. }
  3840. }
  3841. }
  3842.  
  3843. //D0: ID of the item
  3844. //D1: Price of the item
  3845. //D2: Message that plays when the item is bought
  3846. //D3: Message that plays when you don't have enough rupees
  3847. //D4: Input type 0=A 1=B 2=L 3=R
  3848.  
  3849. ffc script SimpleShop{
  3850. void run(int itemID, int price, int m, int n, int input){
  3851. int loc = ComboAt(this->X,this->Y);
  3852. while(true){
  3853. while(!AgainstComboBase(loc) || !SelectPressInput(input)) Waitframe();
  3854. SetInput(input,false);
  3855. if(Game->Counter[CR_RUPEES] >= price){
  3856. Game->DCounter[CR_RUPEES] -= price;
  3857. item shpitm = CreateItemAt(itemID, Link->X, Link->Y);
  3858. shpitm->Pickup = IP_HOLDUP;
  3859. Screen->Message(m);
  3860. }
  3861. else{
  3862. Screen->Message(n);
  3863. }
  3864. Waitframe();
  3865. }
  3866. }
  3867. bool AgainstComboBase(int loc){
  3868. return Link->Z == 0 && (Link->Dir == DIR_UP && Link->Y == ComboY(loc)+8 && Abs(Link->X-ComboX(loc)) < 8);
  3869. }
  3870. }
  3871.  
  3872.  
  3873. ffc script Signpost{
  3874. void run(int m,int input){
  3875. int loc = ComboAt(this->X,this->Y);
  3876. while(true){
  3877. while(!AgainstComboBase(loc) || !SelectPressInput(input)) Waitframe();
  3878. SetInput(input,false);
  3879. Screen->Message(m);
  3880. Waitframe();
  3881. }
  3882. }
  3883. bool AgainstComboBase(int loc){
  3884. return Link->Z == 0 && (Link->Dir == DIR_UP && Link->Y == ComboY(loc)+8 && Abs(Link->X-ComboX(loc)) < 8);
  3885. }
  3886. }
  3887.  
  3888. ffc script ButtonDisabler
  3889. {
  3890. void run()
  3891. {
  3892.  
  3893. while(true)
  3894. {
  3895. Game->SkipF6 = true;
  3896. Link->InputStart = false; Link->PressStart = false;
  3897. Link->InputMap = false; Link->PressMap = false;
  3898. NoAction();
  3899. Waitframe();
  3900. }
  3901. }
  3902. }
  3903.  
  3904. //Instructions:
  3905. //1. Make a new combo with inherent flag 16 (or any secret flag)
  3906. //2. Set this FFC to the above combo
  3907. //3. When secrets are triggered by blocks, this script will make it permanent
  3908. ffc script blockPermSecrets{
  3909. void run(){
  3910. int thisCombo = this->Data;
  3911. while(!Screen->State[ST_SECRET]){
  3912. if(this->Data != thisCombo) Screen->State[ST_SECRET] = true;
  3913. Waitframe();
  3914. }
  3915. }
  3916. }
  3917.  
  3918. screendata script ChangeEnemies
  3919. {
  3920. void run(int changeItem, int e1, int e2, int e3, int ne1, int ne2, int ne3)
  3921. {
  3922. unless(Hero->Item[changeItem]) Quit();
  3923. for(int q = 0; q < 10; ++q)
  3924. {
  3925. if(Screen->Enemy[q] == e1)
  3926. Screen->Enemy[q] = ne1;
  3927. else if(Screen->Enemy[q] == e2)
  3928. Screen->Enemy[q] = ne2;
  3929. else if(Screen->Enemy[q] == e3)
  3930. Screen->Enemy[q] = ne3;
  3931. }
  3932. }
  3933. }
  3934.  
  3935. ffc script NewScreenChanger
  3936. {
  3937. void run(int changeItem, int e1, int e2, int e3, int ne1, int ne2, int ne3)
  3938. {
  3939. unless(Hero->Item[changeItem]) Quit();
  3940. for(int q = 0; q < 10; ++q)
  3941. {
  3942. if(Screen->Enemy[q] == e1)
  3943. Screen->Enemy[q] = ne1;
  3944. else if(Screen->Enemy[q] == e2)
  3945. Screen->Enemy[q] = ne2;
  3946. else if(Screen->Enemy[q] == e3)
  3947. Screen->Enemy[q] = ne3;
  3948. }
  3949. }
  3950. }
  3951.  
  3952. const int SAGESSTONE_SOUND = 136; //Set this to the SFX id you want to hear when you have the compass,
  3953.  
  3954. //Instructions:
  3955. //1.- Compile and add this to your ZQuest buffer.
  3956. //2.- Add an FFC with this script attached to the screen where you want to hear the compass beep.
  3957. //3.- Let the script do the rest.
  3958.  
  3959. //How does it work:
  3960. //The script checks if ANY of the following has been done:
  3961. //a) Item or Special Item has been picked up.
  3962. //b) Any type of chest has been opened.
  3963. //c) If NOTHING of the above has been done, the script runs. Otherwise, no SFX is heard.
  3964.  
  3965. ffc script StonesOfSages{
  3966. void run(){
  3967. if(!Screen->State[ST_ITEM] &&
  3968. !Screen->State[ST_CHEST] &&
  3969. !Screen->State[ST_LOCKEDCHEST] &&
  3970. !Screen->State[ST_BOSSCHEST] &&
  3971. !Screen->State[ST_SPECIALITEM] && (Game->LItems[Game->GetCurLevel()] & LI_COMPASS)){
  3972. Game->PlaySound(SAGESSTONE_SOUND);
  3973. }
  3974. }
  3975. }
  3976.  
  3977. screendata script ChangeEnemiesAndMidi
  3978. {
  3979. void run(int changeItem, int e1, int e2, int e3, int ne1, int ne2, int ne3, int midi)
  3980. {
  3981. unless(Hero->Item[changeItem]) Quit();
  3982. for(int q = 0; q < 10; ++q)
  3983. {
  3984. if(Screen->Enemy[q] == e1)
  3985. Screen->Enemy[q] = ne1;
  3986. else if(Screen->Enemy[q] == e2)
  3987. Screen->Enemy[q] = ne2;
  3988. else if(Screen->Enemy[q] == e3)
  3989. Screen->Enemy[q] = ne3;
  3990. }
  3991. unless(midi) return;
  3992. if(midi == -1)
  3993. {
  3994. midi = Game->LoadDMapData(Game->GetCurDMap())->MIDI;
  3995. }
  3996. Audio->PlayMIDI(midi);
  3997. }
  3998. }
  3999.  
  4000. item script FlareSwordItem{
  4001. void run(int nothing, int firesprite){
  4002. int name[] = "FlareSwordFFC";
  4003. int args[8];
  4004. args[0] = firesprite;
  4005. RunFFCScript(Game->GetFFCScript(name), args);
  4006. }
  4007. }
  4008.  
  4009. ffc script FlareSwordFFC
  4010. {void run(int firesprite)
  4011. {
  4012. int SwordX;
  4013. int SwordY;
  4014. int PreviousSwordX;
  4015. int PreviousSwordY;
  4016. int SwordDmg;
  4017. while(true){
  4018. SwordX = -1000;
  4019. SwordY = -1000;
  4020. for (int i = Screen->NumLWeapons(); i > 0; i--) {
  4021. lweapon wpn = Screen->LoadLWeapon(i);
  4022. if ( wpn->ID == LW_SWORD ) {
  4023. SwordX = wpn->X;
  4024. SwordY = wpn->Y;
  4025. SwordDmg = wpn->Damage;
  4026. }
  4027. }
  4028. if ( SwordX == -1000 && SwordY == -1000 )
  4029. Quit();
  4030. if ( Link->Action != LA_CHARGING && Link->Action != LA_GOTHURTLAND && (SwordX != PreviousSwordX || SwordY != PreviousSwordY) ) {
  4031. Game->PlaySound(13);
  4032. lweapon wpn = CreateLWeaponAt(LW_FIRE, SwordX, SwordY);
  4033. wpn->UseSprite(firesprite);
  4034. wpn->Damage = SwordDmg;
  4035. wpn->Step = 0;
  4036. }
  4037. PreviousSwordX = SwordX;
  4038. PreviousSwordY = SwordY;
  4039. Waitframe();
  4040. }
  4041. }
  4042. }
  4043.  
  4044. itemsprite script FlareSwordSprite
  4045. {void run(int firesprite)
  4046. {
  4047. int SwordX;
  4048. int SwordY;
  4049. int PreviousSwordX;
  4050. int PreviousSwordY;
  4051. int SwordDmg;
  4052. while(true){
  4053. SwordX = -1000;
  4054. SwordY = -1000;
  4055. for (int i = Screen->NumLWeapons(); i > 0; i--) {
  4056. lweapon wpn = Screen->LoadLWeapon(i);
  4057. if ( wpn->ID == LW_SWORD ) {
  4058. SwordX = wpn->X;
  4059. SwordY = wpn->Y;
  4060. SwordDmg = wpn->Damage;
  4061. }
  4062. }
  4063. if ( SwordX == -1000 && SwordY == -1000 )
  4064. Quit();
  4065. if ( Link->Action != LA_CHARGING && Link->Action != LA_GOTHURTLAND && (SwordX != PreviousSwordX || SwordY != PreviousSwordY) ) {
  4066. Game->PlaySound(13);
  4067. lweapon wpn = CreateLWeaponAt(LW_FIRE, SwordX, SwordY);
  4068. wpn->UseSprite(firesprite);
  4069. wpn->Damage = SwordDmg;
  4070. wpn->Step = 0;
  4071. }
  4072. PreviousSwordX = SwordX;
  4073. PreviousSwordY = SwordY;
  4074. Waitframe();
  4075. }
  4076. }
  4077. }
  4078.  
  4079. lweapon script FireRod
  4080. {
  4081. void run()
  4082. {
  4083. lweapon flame = Screen->CreateLWeapon(LW_FIRE);
  4084. while(this->isValid())
  4085. {
  4086. flame->X = this->X;
  4087. flame->Y = this->Y;
  4088. flame->Dir = this->Dir;
  4089. Waitframe();
  4090. }
  4091. }
  4092. }
  4093.  
  4094. lweapon script bombarrow
  4095. {
  4096. void run()
  4097. {
  4098.  
  4099. itemdata bomb; bool found; bool super; int x; int y; int pow;
  4100. bomb = Game->LoadItemData(Link->ItemA);
  4101. if ( bomb->Family == IC_BOMB ) found = true;
  4102. if ( bomb->Family == IC_SBOMB ) { found = true; super = true; }
  4103. if ( !found )
  4104. {
  4105. bomb = Game->LoadItemData(Link->ItemB);
  4106. if ( bomb->Family == IC_BOMB ) { found = true; }
  4107. if ( bomb->Family == IC_SBOMB ) { found = true; super = true; }
  4108. }
  4109. if ( !found ) Quit(); //quit if bombs not in a slot
  4110. else
  4111. {
  4112. pow = bomb->Power;
  4113. if ( super )
  4114. {
  4115. if ( !Game->Counter[CR_SBOMBS] ) Quit(); //quit if not enough bombs
  4116. else --Game->Counter[CR_SBOMBS];
  4117. }
  4118. else
  4119. {
  4120. if ( !Game->Counter[CR_BOMBS] ) Quit(); //quit if not enough bombs
  4121. else --Game->Counter[CR_BOMBS];
  4122. }
  4123. }
  4124.  
  4125.  
  4126. while(this->isValid())
  4127. {
  4128. x = this->X; y = this->Y;
  4129.  
  4130. if ( this->DeadState != WDS_ALIVE ) //When the arrow itself dies, make an explosion.
  4131. {
  4132. lweapon boom = Screen->CreateLWeapon( (( super ) ? LW_SBOMBBLAST : LW_BOMBBLAST ));
  4133. boom->Damage = pow;
  4134. boom->X = x;
  4135. boom->Y = y;
  4136. }
  4137.  
  4138. Waitframe();
  4139. }
  4140.  
  4141. }
  4142. }
  4143.  
  4144. eweapon script dairaaxe
  4145. {
  4146. void run()
  4147. {
  4148. this->X = Clamp(this->X, 1, 255);
  4149. this->Y = Clamp(this->Y, 1, 175);
  4150. int timer = 22;
  4151. while(this->isValid())
  4152. {
  4153. this->X = Clamp(this->X, 1, 255);
  4154. this->Y = Clamp(this->Y, 1, 175);
  4155. --timer;
  4156. if ( timer < 1 ) { Remove(this); Quit(); }
  4157. Waitframe();
  4158. }
  4159. }
  4160. }
  4161.  
  4162. const int RESET_NPC_LAYER_ON_ENTRY = 1; //This fix will replace all CMB_NPC_SOLID tiles with CMB_NPC_HIDDEN
  4163. //when entering the screen. This should prevent problems with shared
  4164. //layers. If you don't want this fix, set it to 0.
  4165.  
  4166. const int NPCSCRIPT_ITEMCHECK_ONLY_UPDATES_ON_SCREEN_ENTRY = 1; //Set to 1 if you want itemcheck NPCs to only disappear
  4167. //after you leave the screen.
  4168.  
  4169. const int NPCSCRIPT_WAITS_UNTIL_SCRIPTS_FINISH = 1; //This will make the script wait until a called script
  4170. //finishes before resuming, fixing issues where you talk
  4171. //to the NPC a second time while you should be frozen
  4172.  
  4173. const int LAYER_NPC = 1; //The layer NPCs use for solid combos
  4174. const int CMB_NPC_HIDDEN = 0; //Non-solid combo used for hidden NPCs
  4175. const int CMB_NPC_SOLID = 43; //Solid combo placed under visible NPCs
  4176.  
  4177. const int LAYER_NPC_CANTALK = 4; //The layer used for the speech bubble
  4178. const int CMB_NPC_CANTALK = 9059; //The combo used for the speech bubble
  4179. const int CS_NPC_CANTALK = 8; //The CSet used for the speech bubble
  4180.  
  4181. const int NPCBT_NONE = 0; //Regular NPCs
  4182. const int NPCBT_FACELINK = 1; //NPCs that turn to face Link
  4183. const int NPCBT_GUARDH = 2; //NPCs that move along a horizontal path
  4184. const int NPCBT_GUARDV = 3; //NPCs that move along a vertical path
  4185.  
  4186. ffc script NPCScript_Simple{
  4187. void run(int String, int Script, int D0, int D1, int D2, int D3, int D4, int D5){
  4188. //Saves the width and height of the FFC for collision checks
  4189. int Width = 16;
  4190. int Height = 16;
  4191. if(this->EffectWidth!=16)
  4192. Width = this->EffectWidth;
  4193. else if(this->TileWidth>1)
  4194. Width = this->TileWidth*16;
  4195. if(this->EffectHeight!=16)
  4196. Height = this->EffectHeight;
  4197. else if(this->TileHeight>1)
  4198. Height = this->TileHeight*16;
  4199. while(true){
  4200. //Facing Up
  4201. if(Link->Dir==DIR_UP&&Link->Y>=this->Y&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  4202. if(CMB_NPC_CANTALK>0)
  4203. Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  4204. if(Link->PressA){
  4205. Link->InputA = false;
  4206. Link->PressA = false;
  4207. Screen->Message(String);
  4208. if(Script>0){
  4209. int Args[8] = {D0, D1, D2, D3, D4, D5};
  4210. RunFFCScript(Script, Args);
  4211. }
  4212. }
  4213. }
  4214. //Facing Down
  4215. else if(Link->Dir==DIR_DOWN&&Link->Y>=this->Y-16&&Link->Y<=this->Y+Height-16&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  4216. if(CMB_NPC_CANTALK>0)
  4217. Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  4218. if(Link->PressA){
  4219. Link->InputA = false;
  4220. Link->PressA = false;
  4221. Screen->Message(String);
  4222. if(Script>0){
  4223. int Args[8] = {D0, D1, D2, D3, D4, D5};
  4224. RunFFCScript(Script, Args);
  4225. }
  4226. }
  4227. }
  4228. //Facing Left
  4229. else if(Link->Dir==DIR_LEFT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X&&Link->X<=this->X+Width){
  4230. if(CMB_NPC_CANTALK>0)
  4231. Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  4232. if(Link->PressA){
  4233. Link->InputA = false;
  4234. Link->PressA = false;
  4235. Screen->Message(String);
  4236. if(Script>0){
  4237. int Args[8] = {D0, D1, D2, D3, D4, D5};
  4238. RunFFCScript(Script, Args);
  4239. }
  4240. }
  4241. }
  4242. //Facing Right
  4243. else if(Link->Dir==DIR_RIGHT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-16&&Link->X<=this->X+Width-16){
  4244. if(CMB_NPC_CANTALK>0)
  4245. Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  4246. if(Link->PressA){
  4247. Link->InputA = false;
  4248. Link->PressA = false;
  4249. Screen->Message(String);
  4250. if(Script>0){
  4251. int Args[8] = {D0, D1, D2, D3, D4, D5};
  4252. RunFFCScript(Script, Args);
  4253. }
  4254. }
  4255. }
  4256. Waitframe();
  4257. }
  4258. }
  4259. }
  4260.  
  4261. ffc script playsfx{
  4262. void run(int s, int wait, int r){
  4263. if (r == 0){
  4264. Waitframes(wait);
  4265. Game->PlaySound(s);
  4266. }
  4267. else{
  4268. while(true){
  4269. Waitframes(wait);
  4270. Game->PlaySound(s);
  4271. }
  4272. }
  4273. }
  4274. }
  4275.  
  4276. ffc script NPCScript{
  4277. void run(int String, int ItemCheck, int Type, int Arg1, int Arg2, int NoSolid, int Script, int ScriptArg){
  4278. //Stores the NPC's combo, hides it
  4279. int Combo = this->Data;
  4280. this->Data = CMB_NPC_HIDDEN;
  4281. //Waits until the NPC should appear and shows it
  4282. if(ItemCheck<0){
  4283. while(!Link->Item[Abs(ItemCheck)]){
  4284. Waitframe();
  4285. }
  4286. this->Data = Combo;
  4287. if(Type==NPCBT_FACELINK){
  4288. this->Data = Combo + Arg1;
  4289. }
  4290. }
  4291. else if(ItemCheck>0){
  4292. if(!Link->Item[Abs(ItemCheck)]){
  4293. this->Data = Combo;
  4294. if(Type==NPCBT_FACELINK){
  4295. this->Data = Combo + Arg1;
  4296. }
  4297. }
  4298. }
  4299. else if(ItemCheck==0){
  4300. this->Data = Combo;
  4301. if(Type==NPCBT_FACELINK){
  4302. this->Data = Combo + Arg1;
  4303. }
  4304. }
  4305. //Saves the width and height of the FFC for collision checks
  4306. int Width = 16;
  4307. int Height = 16;
  4308. if(this->EffectWidth!=16)
  4309. Width = this->EffectWidth;
  4310. else if(this->TileWidth>1)
  4311. Width = this->TileWidth*16;
  4312. if(this->EffectHeight!=16)
  4313. Height = this->EffectHeight;
  4314. else if(this->TileHeight>1)
  4315. Height = this->TileHeight*16;
  4316. //Wait until the screen is done scrolling to avoid a weird ZC crashing bug
  4317. Waitframe();
  4318. while(Link->Action==LA_SCROLLING){
  4319. Waitframe();
  4320. }
  4321. //Shared Layer Fix
  4322. if(RESET_NPC_LAYER_ON_ENTRY==1){
  4323. if(Screen->LoadFFC(FindFFCRunning(this->Script))==this){
  4324. for(int i=0; i<176; i++){
  4325. if(GetLayerComboD(LAYER_NPC, i)==CMB_NPC_SOLID){
  4326. SetLayerComboD(LAYER_NPC, i, CMB_NPC_HIDDEN);
  4327. }
  4328. }
  4329. }
  4330. }
  4331. //Sets the space below the NPC or the space a guard NPC occupies to be solid
  4332. if(LAYER_NPC>-1&&NoSolid==0){
  4333. if(Type==NPCBT_GUARDH){
  4334. for(int x=Arg1; x<=Arg2+this->TileWidth-1; x++){
  4335. for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  4336. SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
  4337. }
  4338. }
  4339. }
  4340. else if(Type==NPCBT_GUARDV){
  4341. for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  4342. for(int y=Arg1; y<=Arg2+this->TileHeight-1; y++){
  4343. SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
  4344. }
  4345. }
  4346. }
  4347. else{
  4348. for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  4349. for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  4350. SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_SOLID);
  4351. }
  4352. }
  4353. }
  4354. }
  4355. bool canItemCheck = true;
  4356. while(true){
  4357. //Prevent checking items past the first frame if the rule is checked
  4358. if(!NPCSCRIPT_ITEMCHECK_ONLY_UPDATES_ON_SCREEN_ENTRY)
  4359. canItemCheck = true;
  4360.  
  4361. //Removes NPCs if Link has the required item
  4362. if(ItemCheck>0&&canItemCheck){
  4363. if(Link->Item[ItemCheck]){
  4364. this->Data = CMB_NPC_HIDDEN;
  4365. if(LAYER_NPC>-1&&NoSolid==0){
  4366. if(Type==NPCBT_GUARDH){
  4367. for(int x=Arg1; x<=Arg2+this->TileWidth-1; x++){
  4368. for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  4369. SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
  4370. }
  4371. }
  4372. }
  4373. else if(Type==NPCBT_GUARDV){
  4374. for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  4375. for(int y=Arg1; y<=Arg2+this->TileHeight-1; y++){
  4376. SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
  4377. }
  4378. }
  4379. }
  4380. else{
  4381. for(int x=Floor(this->X/16); x<=Floor(this->X/16)+this->TileWidth-1; x++){
  4382. for(int y=Floor(this->Y/16); y<=Floor(this->Y/16)+this->TileHeight-1; y++){
  4383. SetLayerComboD(LAYER_NPC, y*16+x, CMB_NPC_HIDDEN);
  4384. }
  4385. }
  4386. }
  4387. }
  4388. Quit();
  4389. }
  4390. }
  4391.  
  4392. canItemCheck = false;
  4393.  
  4394. //Handles animation for turning NPCs
  4395. if(Type==NPCBT_FACELINK&&(Link->X>0&&Link->X<240&&Link->Y>0&&Link->Y<160)){
  4396. if(Distance(CenterLinkX(), CenterLinkY(), CenterX(this), CenterY(this))<Arg2)
  4397. this->Data = Combo + AngleDir4(Angle(CenterX(this), CenterY(this), CenterLinkX(), CenterLinkY()));
  4398. else
  4399. this->Data = Combo + Arg1;
  4400. }
  4401.  
  4402. //Handles movement for guard NPCs
  4403. else if(Type==NPCBT_GUARDH){
  4404. if(Link->X>16*Arg1-32&&Link->X<16*Arg2+32&&Link->Y>this->Y-32&&Link->Y<this->Y+32){
  4405. this->X = Clamp(this->X+(-this->X + Link->X)/4, 16*Arg1, 16*Arg2);
  4406. }
  4407. }
  4408. else if(Type==NPCBT_GUARDV){
  4409. if(Link->X>this->X-32&&Link->X<this->X+32&&Link->Y>16*Arg1-32&&Link->Y<16*Arg2+32){
  4410. this->Y = Clamp(this->Y+(-this->Y + Link->Y)/4, 16*Arg1, 16*Arg2);
  4411. }
  4412. }
  4413.  
  4414. int dialogueBox1[] = "DialogueBranch_Simple";
  4415. int dialogueBox2[] = "DialogueBranch_Advanced";
  4416. int scrDB1 = Game->GetFFCScript(dialogueBox1);
  4417. int scrDB2 = Game->GetFFCScript(dialogueBox2);
  4418.  
  4419.  
  4420. bool noTalk;
  4421. if(CountFFCsRunning(scrDB1)>0)
  4422. noTalk = true;
  4423. if(CountFFCsRunning(scrDB2)>0)
  4424. noTalk = true;
  4425.  
  4426. //Facing Up
  4427. if(!noTalk&&Link->Dir==DIR_UP&&Link->Y>=this->Y&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  4428. if(CMB_NPC_CANTALK>0)
  4429. Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  4430. if(Link->PressA){
  4431. Link->InputA = false;
  4432. Link->PressA = false;
  4433. Screen->Message(String);
  4434. if(Script>0){
  4435. int args[8] = {ScriptArg};
  4436. int i = RunFFCScript(Script, args);
  4437. if(NPCSCRIPT_WAITS_UNTIL_SCRIPTS_FINISH){
  4438. ffc f = Screen->LoadFFC(i);
  4439. while(f->Script==Script){
  4440. Waitframe();
  4441. }
  4442. }
  4443. }
  4444. }
  4445. }
  4446. //Facing Down
  4447. else if(!noTalk&&Link->Dir==DIR_DOWN&&Link->Y>=this->Y-16&&Link->Y<=this->Y+Height-16&&Link->X>=this->X-8&&Link->X<=this->X+Width-8){
  4448. if(CMB_NPC_CANTALK>0)
  4449. Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  4450. if(Link->PressA){
  4451. Link->InputA = false;
  4452. Link->PressA = false;
  4453. Screen->Message(String);
  4454. if(Script>0){
  4455. int args[8] = {ScriptArg};
  4456. int i = RunFFCScript(Script, args);
  4457. if(NPCSCRIPT_WAITS_UNTIL_SCRIPTS_FINISH){
  4458. ffc f = Screen->LoadFFC(i);
  4459. while(f->Script==Script){
  4460. Waitframe();
  4461. }
  4462. }
  4463. }
  4464. }
  4465. }
  4466. //Facing Left
  4467. else if(!noTalk&&Link->Dir==DIR_LEFT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X&&Link->X<=this->X+Width){
  4468. if(CMB_NPC_CANTALK>0)
  4469. Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  4470. if(Link->PressA){
  4471. Link->InputA = false;
  4472. Link->PressA = false;
  4473. Screen->Message(String);
  4474. if(Script>0){
  4475. int args[8] = {ScriptArg};
  4476. int i = RunFFCScript(Script, args);
  4477. if(NPCSCRIPT_WAITS_UNTIL_SCRIPTS_FINISH){
  4478. ffc f = Screen->LoadFFC(i);
  4479. while(f->Script==Script){
  4480. Waitframe();
  4481. }
  4482. }
  4483. }
  4484. }
  4485. }
  4486. //Facing Right
  4487. else if(!noTalk&&Link->Dir==DIR_RIGHT&&Link->Y>=this->Y-8&&Link->Y<=this->Y+Height-8&&Link->X>=this->X-16&&Link->X<=this->X+Width-16){
  4488. if(CMB_NPC_CANTALK>0)
  4489. Screen->FastCombo(LAYER_NPC_CANTALK, Link->X, Link->Y-16, CMB_NPC_CANTALK, CS_NPC_CANTALK, 128);
  4490. if(Link->PressA){
  4491. Link->InputA = false;
  4492. Link->PressA = false;
  4493. Screen->Message(String);
  4494. if(Script>0){
  4495. int args[8] = {ScriptArg};
  4496. int i = RunFFCScript(Script, args);
  4497. if(NPCSCRIPT_WAITS_UNTIL_SCRIPTS_FINISH){
  4498. ffc f = Screen->LoadFFC(i);
  4499. while(f->Script==Script){
  4500. Waitframe();
  4501. }
  4502. }
  4503. }
  4504. }
  4505. }
  4506. Waitframe();
  4507. }
  4508. }
  4509. }
  4510.  
  4511. const int D_TRADE = 0; //Screen->D value used for the trade sequence state
  4512.  
  4513. ffc script TradeSequence{
  4514. void run(int CheckItem, int TradeItem, int NoItemString, int HasItemString, int TradedString){
  4515. //Check if the player has already traded
  4516. if(Screen->D[D_TRADE]==0){
  4517. //If player hasn't traded and has the required item, play HasItemString, give the new item, and take the old item
  4518. if(Link->Item[CheckItem]){
  4519. Screen->Message(HasItemString);
  4520. WaitNoAction();
  4521. item itm = CreateItemAt(TradeItem, Link->X, Link->Y);
  4522. itm->Pickup = IP_HOLDUP;
  4523. Link->Item[CheckItem] = false;
  4524. Screen->D[D_TRADE] = 1;
  4525. WaitNoAction();
  4526. }
  4527. //If player hasn't traded and doesn't have the required item, play NoItemString
  4528. else{
  4529. Screen->Message(NoItemString);
  4530. WaitNoAction();
  4531. }
  4532. }
  4533. //If the player has already traded, play TradedString
  4534. else{
  4535. Screen->Message(TradedString);
  4536. WaitNoAction();
  4537. }
  4538. }
  4539. }
  4540.  
  4541. const int CT_CLIFF = 142; //This is the combo type used for the cliffs. Look in std_constants.zh for reference. It's Script 1 (142) by default.
  4542. const int CLIFF_PAUSE = 15; //This is the number of frames (60ths of a second) Link must walk into the cliff before jumping
  4543.  
  4544. ffc script GBCliff{
  4545. bool CheckCliffDirection(int Combo){
  4546. int Dir;
  4547. if(Screen->ComboS[Combo]==0101b)
  4548. Dir = DIR_UP;
  4549. else if(Screen->ComboS[Combo]==1010b)
  4550. Dir = DIR_DOWN;
  4551. else if(Screen->ComboS[Combo]==0011b)
  4552. Dir = DIR_LEFT;
  4553. else if(Screen->ComboS[Combo]==1100b)
  4554. Dir = DIR_RIGHT;
  4555. else
  4556. return false;
  4557. if(Dir==Link->Dir)
  4558. return true;
  4559. return false;
  4560. }
  4561. void run(){
  4562. int PushCounter = 0;
  4563. while(true){
  4564. if(Link->Dir==DIR_UP&&!CanWalk(Link->X, Link->Y, DIR_UP, 1, false)&&Link->InputUp&&Screen->ComboT[ComboAt(Link->X+8, Link->Y+14)]==CT_CLIFF&&CheckCliffDirection(ComboAt(Link->X+8, Link->Y+14))&&(Link->Action==LA_WALKING||Link->Action==LA_NONE)){
  4565. PushCounter++;
  4566. if(PushCounter>=CLIFF_PAUSE){
  4567. Game->PlaySound(SFX_JUMP);
  4568. Link->Jump = 2;
  4569. int Y = Link->Y;
  4570. for(int i=0; i<26; i++){
  4571. Y -= 0.61;
  4572. Link->Y = Y;
  4573. WaitNoAction();
  4574. }
  4575. PushCounter = 0;
  4576. }
  4577. }
  4578. else if(Link->Dir==DIR_DOWN&&!CanWalk(Link->X, Link->Y, DIR_DOWN, 1, false)&&Link->InputDown&&Screen->ComboT[ComboAt(Link->X+8, Link->Y+12)]==CT_CLIFF&&CheckCliffDirection(ComboAt(Link->X+8, Link->Y+12))&&(Link->Action==LA_WALKING||Link->Action==LA_NONE)){
  4579. PushCounter++;
  4580. if(PushCounter>=CLIFF_PAUSE){
  4581. Game->PlaySound(SFX_JUMP);
  4582. Link->Jump = 1;
  4583. int Combo = ComboAt(Link->X+8, Link->Y+12);
  4584. int CliffHeight = 1;
  4585. for(int i=1; i<11; i++){
  4586. if(Screen->isSolid(ComboX(Combo)+8, ComboY(Combo)+8+16*i))
  4587. CliffHeight++;
  4588. else
  4589. break;
  4590. }
  4591. Link->Z = CliffHeight*16;
  4592. Link->Y += CliffHeight*16;
  4593. while(Link->Z>0){
  4594. WaitNoAction();
  4595. }
  4596. PushCounter = 0;
  4597. }
  4598. }
  4599. else if(Link->Dir==DIR_LEFT&&!CanWalk(Link->X, Link->Y, DIR_LEFT, 1, false)&&Link->InputLeft&&Screen->ComboT[ComboAt(Link->X+4, Link->Y+8)]==CT_CLIFF&&CheckCliffDirection(ComboAt(Link->X+4, Link->Y+8))&&(Link->Action==LA_WALKING||Link->Action==LA_NONE)){
  4600. PushCounter++;
  4601. if(PushCounter>=CLIFF_PAUSE){
  4602. Game->PlaySound(SFX_JUMP);
  4603. Link->Jump = 2;
  4604. int X = Link->X;
  4605. for(int i=0; i<26; i++){
  4606. X -= 0.92;
  4607. if(i==13){
  4608. Link->Z += 16;
  4609. Link->Y += 16;
  4610. }
  4611. Link->X = X;
  4612. WaitNoAction();
  4613. }
  4614. while(Link->Z>0){
  4615. WaitNoAction();
  4616. }
  4617. PushCounter = 0;
  4618. }
  4619. }
  4620. else if(Link->Dir==DIR_RIGHT&&!CanWalk(Link->X, Link->Y, DIR_RIGHT, 1, false)&&Link->InputRight&&Screen->ComboT[ComboAt(Link->X+12, Link->Y+8)]==CT_CLIFF&&CheckCliffDirection(ComboAt(Link->X+12, Link->Y+8))&&(Link->Action==LA_WALKING||Link->Action==LA_NONE)){
  4621. PushCounter++;
  4622. if(PushCounter>=CLIFF_PAUSE){
  4623. Game->PlaySound(SFX_JUMP);
  4624. Link->Jump = 2;
  4625. int X = Link->X;
  4626. for(int i=0; i<26; i++){
  4627. X += 0.92;
  4628. if(i==13){
  4629. Link->Z += 16;
  4630. Link->Y += 16;
  4631. }
  4632. Link->X = X;
  4633. WaitNoAction();
  4634. }
  4635. while(Link->Z>0){
  4636. WaitNoAction();
  4637. }
  4638. PushCounter = 0;
  4639. }
  4640. }
  4641. else{
  4642. PushCounter = 0;
  4643. }
  4644. Waitframe();
  4645. }
  4646. }
  4647. }
  4648.  
  4649. ffc script GBDungeonCliff{
  4650. void run(int CliffCombo){
  4651. int PushCounter = 0;
  4652. while(true){
  4653. if(Link->Dir==DIR_UP&&!CanWalk(Link->X, Link->Y, DIR_UP, 1, false)&&Link->InputUp&&Screen->ComboD[ComboAt(Link->X+8, Link->Y+7)]==CliffCombo&&(Link->Action==LA_WALKING||Link->Action==LA_NONE)){
  4654. PushCounter++;
  4655. if(PushCounter>=CLIFF_PAUSE){
  4656. Game->PlaySound(SFX_JUMP);
  4657. Link->Jump = 2;
  4658. int Y = Link->Y;
  4659. for(int i=0; i<26; i++){
  4660. Y -= 0.92;
  4661. Link->Y = Y;
  4662. WaitNoAction();
  4663. }
  4664. PushCounter = 0;
  4665. }
  4666. }
  4667. else if(Link->Dir==DIR_DOWN&&!CanWalk(Link->X, Link->Y, DIR_DOWN, 1, false)&&Link->InputDown&&Screen->ComboD[ComboAt(Link->X+8, Link->Y+16)]==CliffCombo+1&&(Link->Action==LA_WALKING||Link->Action==LA_NONE)){
  4668. PushCounter++;
  4669. if(PushCounter>=CLIFF_PAUSE){
  4670. Game->PlaySound(SFX_JUMP);
  4671. Link->Jump = 1;
  4672. int Combo = ComboAt(Link->X+8, Link->Y+12);
  4673. int CliffHeight = 1;
  4674. for(int i=1; i<11; i++){
  4675. if(Screen->isSolid(ComboX(Combo)+8, ComboY(Combo)+8+16*i))
  4676. CliffHeight++;
  4677. else
  4678. break;
  4679. }
  4680. Link->Z = CliffHeight*16-8;
  4681. Link->Y += CliffHeight*16-8;
  4682. while(Link->Z>0){
  4683. WaitNoAction();
  4684. }
  4685. PushCounter = 0;
  4686. }
  4687. }
  4688. else if(Link->Dir==DIR_LEFT&&!CanWalk(Link->X, Link->Y, DIR_LEFT, 1, false)&&Link->InputLeft&&Screen->ComboD[ComboAt(Link->X-1, Link->Y+8)]==CliffCombo+2&&(Link->Action==LA_WALKING||Link->Action==LA_NONE)){
  4689. PushCounter++;
  4690. if(PushCounter>=CLIFF_PAUSE){
  4691. Game->PlaySound(SFX_JUMP);
  4692. Link->Jump = 2;
  4693. int X = Link->X;
  4694. for(int i=0; i<26; i++){
  4695. X -= 1.23;
  4696. Link->X = X;
  4697. WaitNoAction();
  4698. }
  4699. PushCounter = 0;
  4700. }
  4701. }
  4702. else if(Link->Dir==DIR_RIGHT&&!CanWalk(Link->X, Link->Y, DIR_RIGHT, 1, false)&&Link->InputRight&&Link->InputRight&&Screen->ComboD[ComboAt(Link->X+16, Link->Y+8)]==CliffCombo+3&&(Link->Action==LA_WALKING||Link->Action==LA_NONE)){
  4703. PushCounter++;
  4704. if(PushCounter>=CLIFF_PAUSE){
  4705. Game->PlaySound(SFX_JUMP);
  4706. Link->Jump = 2;
  4707. int X = Link->X;
  4708. for(int i=0; i<26; i++){
  4709. X += 1.23;
  4710. Link->X = X;
  4711. WaitNoAction();
  4712. }
  4713. }
  4714. }
  4715. else{
  4716. PushCounter = 0;
  4717. }
  4718. Waitframe();
  4719. }
  4720. }
  4721. }
  4722.  
  4723. item script Frogforce{
  4724. void run(){
  4725. Game->End();
  4726. }
  4727. }
  4728.  
  4729.  
  4730.  
  4731. npc script stealitems
  4732. {
  4733. void run(int min, int max, int counterA, int counterB, int counterC, int counterD, int sfx)
  4734. {
  4735. min = ( min > -1 ) ? min : 0;
  4736. max = ( max > 0 ) ? max : 1;
  4737. int num = Rand(min,max);
  4738. int counters[4] = { counterA, counterB, counterC, counterD };
  4739. int sel = counters[Rand(4)];
  4740. while(1)
  4741. {
  4742. if ( sel ) //don't affect counter 0 (life)
  4743. {
  4744. if ( Collision(this) && (Hero->HitDir > -1) )
  4745. {
  4746. Audio->PlaySound(sfx);
  4747. //Don't roll over.
  4748. if ( (Game->Counter[sel] - num) >= 0 ) Game->Counter[sel] -= num;
  4749. else
  4750. {
  4751. Game->Counter[sel] = ( num > 0 ) ? 0 : Game->Counter[sel];
  4752. }
  4753. while(Hero->HitDir > -1) { Waitframe(); } //Don't steal again unless Link is hit again.
  4754. }
  4755. }
  4756. num = Rand(min,max);
  4757. sel = counters[Rand(4)];
  4758. Waitframe();
  4759. }
  4760. }
  4761. }
  4762.  
  4763. //! The initial combo used for this ffc (on the screen) should be a rupee icon with a numeric cost.
  4764. //! The next combo in the list, should be blank.
  4765.  
  4766.  
  4767. //Combos
  4768. const int CMB_CHEST_GAME_CLOSED = 2640; //The 'closed' chest combo.
  4769. //! This should be combo type 'none', and solid.
  4770. const int CMB_CHEST_GAME_OPEN = 2641; //The closed chest combo.
  4771. //! This should be the combo immediately after CMB_CHEST_GAME_CLOSED', with a type of 'none'.
  4772.  
  4773.  
  4774. //Strings
  4775. const int MSG_CHEST_GAME_RULES = 367; //Screen->Message string that explains the game rules to the player.
  4776. const int MSG_CHEST_GAME_OVER = 366; //Screen->Message string for the end of a game round.
  4777.  
  4778. //Sounds
  4779. const int SFX_OPEN_CHEST = 20; //The sound that will play when Link opens a chest, and an item is awarded.
  4780. const int SFX_CHEST_GAME_SPECIAL_PRIZE_FANFARE = 27; //The sound to play when the player finds the special item in a chest.
  4781. const int SFX_CHEST_GAME_START = 35; //The sound to play when the player starts the game.
  4782.  
  4783. //Other Settings and Options
  4784. const int CHEST_GAME_SCREEN_D_REGISTER = 5; //The Screen->D[index] used to store if the main prize has been awarded.
  4785. const int CHEST_GAME_HOLDUP_TYPE = 4; // The type of item hold-up tp use. 4 = LA_HOLD1LAND(one hand); 5 = LA_HOLD2LAND(two hands)
  4786. const int CHEST_GAME_ALLOW_REPLAY = 0; //Set to '1' to allow the player to play again without leaving the screen.
  4787. const int TIME_INPUT_UP_OPEN_CHEST = 50; //The number of frames of inputting up will open a closed chest.
  4788. const int OPEN_CHESTS_FROM_SIDES_OR_ABOVE = 1; //Set to '0' to only permit opening them from the bottom.
  4789.  
  4790.  
  4791.  
  4792. // Chest Game FFC
  4793.  
  4794. //~ //D0: Number of chests to allow the player to open, per play.
  4795. //~ //D1: ID of special prize to award.
  4796. //~ //D2: Percentage chance of awarding special prize.
  4797. //~ //D3: Backup prize, if special prize already awarded (e.g. 100 rupees, instead of a heart piece). Set to '0' to not offer a backup prize.
  4798. //~ //D4: Cost per play.
  4799. //~ //D5: String for game rules.
  4800. //~ //D6: String to play at end of game.
  4801. //~ //D7: Set to '1' to allow replaying without leaving the screen.
  4802.  
  4803.  
  4804. ffc script ChestMiniGame{
  4805. void run(int max_chests_Link_can_open, int specialPrize, int percentMainPrize, int backupPrize, int costPerPlay, int msgRules, int msgEnd, int allowReplay){
  4806.  
  4807.  
  4808. //Populate with the IDs of prizes to award. Each index is a 1% chance.
  4809. int chestPrizes[]= { 2, 0, 30, 0, 39, 0, 39, 0, 2, 3,
  4810. 0, 0, 145, 72, 0, 72, 72, 79, 80, 3,
  4811. 40, 2, 39, 38, 71, 40, 0, 40, 0, 38,
  4812. 38, 0, 86, 80, 87, 0, 2, 86, 60, 2,
  4813. 0, 71, 73, 0, 86, 73, 40, 79, 38, 40,
  4814. 145, 80, 59, 86, 0, 0, 38, 40, 2, 0,
  4815. 0, 38, 2, 0, 60, 71, 2, 1, 73, 145,
  4816. 1, 70, 0, 78, 0, 0, 0, 80, 2, 86,
  4817. 79, 0, 70, 0, 70, 0, 0, 0, 86, 0,
  4818. 0, 2, 0, 87, 0, 38, 2, 70, 70, 86 };
  4819.  
  4820. int initialData = this->Data; //Store the initial combo, to revert, if replay is enabled.
  4821. int chestComboSpots[176];
  4822. int check;
  4823. int cmb;
  4824. int mainprize;
  4825. int timer = TIME_INPUT_UP_OPEN_CHEST;
  4826. bool openchest;
  4827. int has_opened_number_of_chests;
  4828. bool award_main_prize;
  4829. bool gameRunning;
  4830. bool gameOver;
  4831. item i;
  4832. bool giveprize;
  4833. bool awardnormalprize;
  4834.  
  4835. if ( msgRules ) Screen->Message(msgRules);
  4836. else Screen->Message(MSG_CHEST_GAME_RULES); //Show the string for the chest game rules.
  4837.  
  4838. while(true) {
  4839. if ( max_chests_Link_can_open == has_opened_number_of_chests ) gameOver = true;
  4840. if ( gameOver && ( !CHEST_GAME_ALLOW_REPLAY && !allowReplay ) || allowReplay < 0 ) break;
  4841.  
  4842. if ( gameOver && ( CHEST_GAME_ALLOW_REPLAY || allowReplay > 0 ) ) {
  4843. gameOver = false;
  4844. gameRunning = false;
  4845. this->Data = initialData;
  4846. for ( int q = 0; q < 176; q++ ) {
  4847. if ( Screen->ComboD[q] == CMB_CHEST_GAME_OPEN ) Screen->ComboD[q] = CMB_CHEST_GAME_CLOSED;
  4848. }
  4849. has_opened_number_of_chests = 0;
  4850. }
  4851.  
  4852. if ( LinkCollision(this) && Game->Counter[CR_RUPEES] > costPerPlay && ____Xor(Link->PressA,Link->PressB) && !gameRunning ) {
  4853. //If Link collides with the ffc, which should show the cost, and presses a button, start the game.
  4854. if ( SFX_CHEST_GAME_START ) Game->PlaySound(SFX_CHEST_GAME_START);
  4855. gameRunning = true;
  4856. Game->DCounter[CR_RUPEES] -= costPerPlay;
  4857. this->Data++; //increase to the next combo, removing the cost icon.
  4858. }
  4859.  
  4860.  
  4861.  
  4862. if ( gameRunning ) {
  4863.  
  4864. //Check to see if the combo above Link is a chest.
  4865.  
  4866.  
  4867. if ( Link->Dir == DIR_UP ){
  4868. cmb = Screen->ComboD[ ___AdjacentCombo(ComboAt(Link->X+8, Link->Y+8),Link->Dir) ];
  4869.  
  4870. if ( cmb == CMB_CHEST_GAME_CLOSED ) {
  4871. if ( timer && Link->InputUp ) timer--;
  4872. if ( timer <= 0 || ____Xor(Link->PressA,Link->PressB)) {
  4873. has_opened_number_of_chests++;
  4874. if ( SFX_OPEN_CHEST ) Game->PlaySound(SFX_OPEN_CHEST);
  4875. Screen->ComboD[ ___AdjacentCombo(ComboAt(Link->X+8, Link->Y+8),Link->Dir) ]++;
  4876.  
  4877. timer = TIME_INPUT_UP_OPEN_CHEST;
  4878. giveprize = true;
  4879. Link->InputUp = false;
  4880. }
  4881. }
  4882. else timer = TIME_INPUT_UP_OPEN_CHEST;
  4883. }
  4884. else if ( Link->Dir == DIR_DOWN && OPEN_CHESTS_FROM_SIDES_OR_ABOVE ){
  4885. cmb = Screen->ComboD[ ___AdjacentCombo(ComboAt(Link->X+8, Link->Y+8),Link->Dir) ];
  4886.  
  4887. if ( cmb == CMB_CHEST_GAME_CLOSED ) {
  4888. if ( timer > 0 && Link->InputDown ) timer--;
  4889. if ( timer <= 0 || ____Xor(Link->PressA,Link->PressB) ) {
  4890. has_opened_number_of_chests++;
  4891. if ( SFX_OPEN_CHEST ) Game->PlaySound(SFX_OPEN_CHEST);
  4892. Screen->ComboD[ ___AdjacentCombo(ComboAt(Link->X+8, Link->Y+8),Link->Dir) ]++;
  4893. timer = TIME_INPUT_UP_OPEN_CHEST;
  4894. giveprize = true;
  4895. Link->InputUp = false;
  4896. }
  4897. }
  4898. else timer = TIME_INPUT_UP_OPEN_CHEST;
  4899. }
  4900. else if ( Link->Dir == DIR_LEFT && OPEN_CHESTS_FROM_SIDES_OR_ABOVE ) {
  4901. cmb = Screen->ComboD[ ___AdjacentCombo(ComboAt(Link->X+8, Link->Y+8),Link->Dir) ];
  4902. if ( cmb == CMB_CHEST_GAME_CLOSED ) {
  4903. if ( timer > 0 && Link->InputLeft ) timer--;
  4904. if ( timer <= 0 || ____Xor(Link->PressA,Link->PressB) ) {
  4905. has_opened_number_of_chests++;
  4906. if ( SFX_OPEN_CHEST ) Game->PlaySound(SFX_OPEN_CHEST);
  4907. Screen->ComboD[ ___AdjacentCombo(ComboAt(Link->X+8, Link->Y+8),Link->Dir) ]++;
  4908. timer = TIME_INPUT_UP_OPEN_CHEST;
  4909. giveprize = true;
  4910. Link->InputUp = false;
  4911. }
  4912. }
  4913. else timer = TIME_INPUT_UP_OPEN_CHEST;
  4914. }
  4915. else if ( Link->Dir == DIR_RIGHT && OPEN_CHESTS_FROM_SIDES_OR_ABOVE ) {
  4916. cmb = Screen->ComboD[ ___AdjacentCombo(ComboAt(Link->X+8, Link->Y+8),Link->Dir)];
  4917. if ( cmb == CMB_CHEST_GAME_CLOSED ) {
  4918. if ( timer > 0 && Link->InputRight ) timer--;
  4919. if ( timer <= 0 || ____Xor(Link->PressA,Link->PressB) ) {
  4920. has_opened_number_of_chests++;
  4921. if ( SFX_OPEN_CHEST ) Game->PlaySound(SFX_OPEN_CHEST);
  4922. Screen->ComboD[ ___AdjacentCombo(ComboAt(Link->X+8, Link->Y+8),Link->Dir) ]++;
  4923. timer = TIME_INPUT_UP_OPEN_CHEST;
  4924. giveprize = true;
  4925. Link->InputUp = false;
  4926. }
  4927. }
  4928. else timer = TIME_INPUT_UP_OPEN_CHEST;
  4929.  
  4930. }
  4931.  
  4932.  
  4933.  
  4934. if ( giveprize ) {
  4935.  
  4936. check = Rand(1,100); //Make a check, to use for determining if the main prize should e awarded.
  4937.  
  4938. if ( check <= percentMainPrize ) award_main_prize = true; //If that check passes, then we will award the main prize.
  4939.  
  4940. if ( check > percentMainPrize ) { awardnormalprize = true; check = Rand(0,SizeOfArray(chestPrizes)); }//Otherwise, reuse that var, and make a new check to determine
  4941. //the prize to award from the table.
  4942. int itm;
  4943.  
  4944. if ( !awardnormalprize && award_main_prize && !Screen->D[CHEST_GAME_SCREEN_D_REGISTER] ) { //The main prize has not been awarded, and has been randomly chosen.
  4945. Game->PlaySound(SFX_CHEST_GAME_SPECIAL_PRIZE_FANFARE); //Play the fanfare...
  4946. i = Screen->CreateItem(specialPrize); //Assign the pointer, and make the item.
  4947. itm = specialPrize; //Set the value of the item ID to a var so that we can use it for holding it up.
  4948. }
  4949. if ( !awardnormalprize && award_main_prize && Screen->D[CHEST_GAME_SCREEN_D_REGISTER] && backupPrize ) { //The main prize has already been awarded, so recheck.
  4950. Game->PlaySound(SFX_CHEST_GAME_SPECIAL_PRIZE_FANFARE); //Play the special award fanfare...
  4951. i = Screen->CreateItem(backupPrize); //Assign the pointer, and make the item.
  4952. itm = backupPrize; //Set the value of the item ID to a var so that we can use it for holding it up.
  4953. }
  4954. if ( awardnormalprize && check ) { //Otherwise, if the check to award a special prize did not pass..
  4955. Game->PlaySound(SFX_OPEN_CHEST); //otherwise, play the default.
  4956. i = Screen->CreateItem(chestPrizes[check]); //Award a normal prize, from the list.
  4957. itm = chestPrizes[check]; //Set the value of the item ID to a var so that we can use it for holding it up.
  4958.  
  4959. }
  4960. if ( check ) { //if we're awarding a prize...
  4961. i -> X = Link->X;
  4962. i -> Y = Link->Y;
  4963. if ( CHEST_GAME_HOLDUP_TYPE ) { //If the setting to hold the item overhead is enabled...
  4964. Link->Action = CHEST_GAME_HOLDUP_TYPE; //Hold the item overhead, using the value of that setting.
  4965. Link->HeldItem = itm;
  4966. }
  4967.  
  4968. if ( award_main_prize ) { Screen->D[CHEST_GAME_SCREEN_D_REGISTER] = 1; award_main_prize = false; } //Set the register so that Link cannot collect the special prize again.
  4969.  
  4970. giveprize = false;
  4971. while( Link->Action == LA_HOLD1LAND ) Waitframe();
  4972. }
  4973. else Remove(i); //if check is zero, remove the item pointer.
  4974. //This allows chances of getting nothing at all.
  4975. }
  4976.  
  4977. if ( has_opened_number_of_chests >= max_chests_Link_can_open ) {
  4978. gameOver = true;
  4979. gameRunning = false;
  4980. if ( msgEnd ) Screen->Message(msgEnd);
  4981. else Screen->Message(MSG_CHEST_GAME_OVER);
  4982.  
  4983. }
  4984.  
  4985. }
  4986.  
  4987. Waitframe();
  4988. }
  4989. //If we reach here, then the chest game is over.
  4990. this->Data = 0;
  4991. this->Script = 0;
  4992. Quit();
  4993. }
  4994.  
  4995. //Constants for AdjacentCombo()
  4996. //This now uses DIR_* constants, so you can do AdjacentCombo(cmb,Link->Dir)
  4997. //Returns the Nth combo index of a combo based on a central point, and a direction.
  4998. //For example, combo 22 + COMBO_UPRIGHT returns '7',
  4999. //as combo 7 is to the upper-right of combo 22.
  5000. int ___AdjacentCombo(int cmb, int dir){
  5001. int combooffsets[13]={-0x10, 0x10, -1, 1, -0x11, -0x0F, 0x0F, 0x11};
  5002. if ( cmb % 16 == 0 ) combooffsets[9] = 1;
  5003. if ( (cmb & 15) == 1 ) combooffsets[10] = 1;
  5004. if ( cmb < 0x10 ) combooffsets[11] = 1; //if it's the top row
  5005. if ( cmb > 0x9F ) combooffsets[12] = 1; //if it's on the bottom row
  5006. if ( combooffsets[9] && ( dir == 7 || dir == 0 || dir == 6 || dir == 0 ) ) return 0; //if the left columb
  5007. if ( combooffsets[10] && ( dir == 3 || dir == 2 || dir == 4 ) ) return 0; //if the right column
  5008. if ( combooffsets[11] && ( dir == 1 || dir == 2 || dir == 0 || dir == 0 ) ) return 0; //if the top row
  5009. if ( combooffsets[12] && ( dir == 5 || dir == 4 || dir == 6 ) ) return 0; //if the bottom row
  5010. else if ( cmb >= 0 && cmb <= 176 ) return cmb + combooffsets[dir];
  5011. else return -1;
  5012. }
  5013. //Xor comparison of two boolean values.
  5014. bool ____Xor(bool valA, bool valB){
  5015. if ( !valA && valB ) return true;
  5016. else if ( valA && !valB ) return true;
  5017. return false;
  5018. }
  5019.  
  5020.  
  5021. }
  5022.  
  5023. const int ComboType_NormalLadder = 143; //combo type for ladders. "script 1" by default. see std_constants.zh for a list of combo types.
  5024. ffc script NormalLadder{
  5025. void run(){
  5026. while(true){
  5027. if ( Screen->ComboT[ComboAt(Link->X+8, Link->Y+8)] == ComboType_NormalLadder ) {
  5028. //disable A and B
  5029. Link->InputA = false; Link->PressA = false;
  5030. Link->InputB = false; Link->PressB = false;
  5031. }
  5032. Waitdraw();
  5033. if ( Screen->ComboT[ComboAt(Link->X+8, Link->Y+8)] == ComboType_NormalLadder ) {
  5034. Link->Dir = DIR_UP; //make link face up
  5035. }
  5036. Waitframe();
  5037. }
  5038. }
  5039. }
  5040.  
  5041.  
  5042. const int ComboType_ClimbWalls = 15; //combo type for ladders. "script 1" by default. see std_constants.zh for a list of combo types.
  5043. ffc script ClimbWalls{
  5044. void run(){
  5045. while(true){
  5046. if ( Screen->ComboT[ComboAt(Link->X+8, Link->Y+8)] == ComboType_ClimbWalls ) {
  5047. //disable A and B
  5048. Link->InputA = false; Link->PressA = false;
  5049. Link->InputB = false; Link->PressB = false;
  5050. }
  5051. Waitdraw();
  5052. if ( Screen->ComboT[ComboAt(Link->X+8, Link->Y+8)] == ComboType_ClimbWalls ) {
  5053. Link->Dir = DIR_UP; //make link face up
  5054. }
  5055. Waitframe();
  5056. }
  5057. }
  5058. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement