Advertisement
HylianWhovian

Untitled

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