SHARE
TWEET

Untitled

a guest Mar 30th, 2020 147 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // This script makes an FFC act as a guard. If Link enters its field of
  2.  
  3. // vision, it will either warp him to another screen or become an enemy.
  4.  
  5.  
  6. // It can also play a sound and display a message when it spots him.
  7.  
  8.  
  9.  
  10. // Setup
  11.  
  12.  
  13. //
  14. // The guard uses eight combos. The first four show it standing still,
  15.  
  16. // facing up, down, left, and right, respectively. The next four show
  17.  
  18. // it walking in the same directions. The combos facing upward must have
  19.  
  20. // numbers divisible by 4; that is, they must be in the left column of
  21.  
  22. // the list. The FFC must start out on one of the standing combos, even
  23.  
  24. // if it will walk constantly. If the combos are set up correctly, it
  25.  
  26. // will automatically figure out which way it's facing.
  27.  
  28.  
  29. //
  30.  
  31. // Set flag 46 on flags that guards should not be able to see through.
  32.  
  33.  
  34. // If the guard will move, set flag 44 and 45 to mark its path. It will
  35.  
  36. // always move straight ahead if it can. When it reaches the point where
  37.  
  38. // it can't go any farther, if it is standing on flag 45, it will stop
  39.  
  40. // and turn around for a moment before moving on. Both placed and inherent
  41.  
  42. // flags will work.
  43.  
  44.  
  45.  
  46. // Arguments
  47.  
  48.  
  49. //
  50. // If an argument has a default value, this will be used if you leave the
  51.  
  52. // value at 0. The script will try to correct invalid values except for D0.
  53.  
  54.  
  55. //
  56.  
  57. // D0: Movement type
  58.  
  59. // Determines how the guard moves.
  60.  
  61. //     0: Walks along flags 44 and 45; at an intersection, the guard will
  62.  
  63. //     turn left if possible
  64.  
  65. //     1: The same as 0, except it will try to turn right instead of left
  66.  
  67. //     2: The guard will not move at all
  68.  
  69. //     3: The guard will stand in place, turning clockwise
  70.  
  71. //     4: The guard will stand in place, turning counterclockwise
  72.  
  73. //     5: The guard stand in place, turning left and right
  74.  
  75.  
  76. // D1: Reaction to Link
  77.  
  78. //     What the guard will do if it sees Link.
  79.  
  80. //     0: Warp Link to another screen
  81.  
  82. //     1: Turn into an enemy
  83.  
  84.  
  85. // D2: Speed
  86.  
  87. //     How fast the guard will move. Affects both walking and turning speed.
  88.  
  89. //     You can set a default below, which will be used if D2 is left at 0.
  90.  
  91.  
  92. // D3: Message
  93.  
  94. //     When the guard sees Link, it will show this message. If this is left
  95.  
  96. //     at 0, no message will be displayed.
  97.  
  98.  
  99. // D4: Destination DMap
  100.  
  101. //     If the guard warps Link when it spots him, this is the DMap it will
  102.  
  103. //     warp him to.
  104.  
  105.  
  106. // D5: Destination screen
  107.  
  108. //     If the guard warps Link when it spots him, this is the screen it will
  109.  
  110. //     warp him to. Remember that this must be converted from the hexadecimal
  111.  
  112. //     numbers used in ZQuest.
  113.  
  114.  
  115. // D6: Enemy ID
  116.  
  117. //     If the guard becomes an enemy when it spots Link, this is the ID number
  118.  
  119. //     of the type of enemy it will become.
  120.  
  121.  
  122. // D7: Screen->D index
  123.  
  124. //     When the guard spots Link, it will set this screen variable. This will
  125.  
  126. //     alert all other guards that use the same number, and potentially other
  127.  
  128. //     scripts. This must be a whole number between 0 and 7. If you have both
  129.  
  130. //     warping and enemy guards on the same screen, they should not use the
  131.  
  132. //     same number. If this is set to a negative number, it will not be used.
  133.  
  134.  
  135.  
  136. // The guard's speed if D2 is left at 0.
  137.  
  138. const int CGUARD_DEFAULT_SPEED=0.75;
  139.  
  140.  
  141.  
  142. // The guard will play this sound when it sees Link. If this is set to 0, no
  143.  
  144. // sound will be played.
  145.  
  146. const int CGUARD_SOUND=88;
  147.  
  148.  
  149.  
  150. // If this is set to anything but 0, the guard will notice Link if he's very
  151.  
  152. // close, even if he's out of sight.
  153.  
  154. const int CGUARD_FIND_LINK_IF_CLOSE=1;
  155.  
  156.  
  157.  
  158. // How close Link must be to be found when out of sight.
  159.  
  160. const int CGUARD_FIND_LINK_DISTANCE=24;
  161.  
  162.  
  163.  
  164. // The angle of the guard's field of vision.
  165.  
  166. const int CGUARD_VISION_ANGLE=75;
  167.  
  168.  
  169.  
  170. // The maximum distance at which the guard can see Link.
  171.  
  172. const int CGUARD_VISION_RANGE=160;
  173.  
  174.  
  175.  
  176. // Movement types
  177.  
  178. const int CGUARD_PATROL_LEFT=0;
  179.  
  180. const int CGUARD_PATROL_RIGHT=1;
  181.  
  182. const int CGUARD_STAND=2;
  183.  
  184. const int CGUARD_ROTATE_CW=3;
  185.  
  186. const int CGUARD_ROTATE_CCW=4;
  187.  
  188. const int CGUARD_LEFT_AND_RIGHT=5;
  189.  
  190.  
  191.  
  192. // Reaction types
  193.  
  194. const int CGUARD_WARP=0;
  195.  
  196. const int CGUARD_BECOME_ENEMY=1;
  197.  
  198.  
  199. const int CGUARD_WALK_FLAG=44;
  200.  
  201. const int CGUARD_TURN_FLAG=45;
  202.  
  203. const int CGUARD_BLOCK_FLAG=46;
  204.  
  205.  
  206.  
  207. ffc script CastleGuard
  208. {
  209.    
  210. void run(int movement, int reaction, float speed, int message,
  211. int destDMap, int destScreen, int enemyID, int screenDIndex){
  212.        
  213.  
  214.  // Infer direction from combo number
  215.        
  216. int direction=this->Data%4;
  217.        
  218.  
  219.        
  220. // First standing and walking combos
  221.        
  222. int baseStandCombo=this->Data-direction;
  223.        
  224. int baseWalkCombo=baseStandCombo+4;
  225.    
  226.    
  227.        
  228. // Initialize the screen variable
  229.        
  230. if(screenDIndex>=0)
  231.            
  232. Screen->D[screenDIndex]=0;
  233.        
  234.        
  235. if(speed==0)
  236.            
  237. speed=CGUARD_DEFAULT_SPEED;
  238.        
  239.        
  240.  
  241. // Stand in place
  242.        
  243. if(movement==CGUARD_STAND)
  244. {
  245.            
  246. while(true)
  247.                
  248. Wait(1, reaction, message, destDMap, destScreen,
  249.  enemyID, screenDIndex, this);
  250.      
  251. }
  252.        
  253.        
  254.  
  255. // Turn clockwise
  256.        
  257. else if(movement==CGUARD_ROTATE_CW){
  258.            
  259. while(true)
  260.             {
  261.                
  262. Wait(120/speed, reaction, message, destDMap, destScreen,
  263.  enemyID, screenDIndex, this);
  264.                
  265. direction=TurnRight(direction);
  266.                
  267. this->Data=baseStandCombo+direction;
  268.            
  269. }
  270.        
  271. }
  272.        
  273.  
  274.        
  275. // Turn clockwise
  276.        
  277. else if(movement==CGUARD_ROTATE_CCW)
  278. {
  279.            
  280. while(true)
  281.             {
  282.                
  283. Wait(120/speed, reaction, message, destDMap, destScreen,
  284.  enemyID, screenDIndex, this);
  285.                
  286. direction=TurnLeft(direction);
  287.                
  288. this->Data=baseStandCombo+direction;
  289.            
  290. }
  291.        
  292. }
  293.        
  294.  
  295.      
  296. // Turn left and right
  297.        
  298. else if(movement==CGUARD_LEFT_AND_RIGHT)
  299.        
  300. {
  301.            
  302. while(true)
  303.            
  304. {
  305.                
  306. Wait(120/speed, reaction, message, destDMap, destScreen, enemyID, screenDIndex, this);
  307.                
  308. direction=TurnLeft(direction);
  309.                
  310. this->Data=baseStandCombo+direction;
  311.                
  312.                
  313. Wait(120/speed, reaction, message, destDMap, destScreen,
  314.  enemyID, screenDIndex, this);
  315.                
  316. direction=TurnRight(direction);
  317.                
  318. this->Data=baseStandCombo+direction;
  319.                
  320.                
  321. Wait(120/speed, reaction, message, destDMap, destScreen,
  322.  enemyID, screenDIndex, this);
  323.                
  324. direction=TurnRight(direction);
  325.                
  326. this->Data=baseStandCombo+direction;
  327.                
  328.                
  329. Wait(120/speed, reaction, message, destDMap, destScreen,
  330.  enemyID, screenDIndex, this);
  331.                
  332. direction=TurnLeft(direction);
  333.                
  334. this->Data=baseStandCombo+direction;
  335.            
  336. }
  337.        
  338. }
  339.        
  340.        
  341.  
  342. // Patrol mode; don't need to compare again
  343.        
  344. this->Data=baseWalkCombo+direction;
  345.        
  346.        
  347. while(true)
  348.        
  349. {
  350.            
  351.  
  352. // Walk forward, if possible
  353.            
  354. if(CanMove(direction, speed, this))
  355.                
  356. Move(direction, speed, this);
  357.            
  358.            
  359.  
  360. // Can't go any farther this direction?
  361.            
  362. else
  363.            
  364. {
  365.                
  366.  
  367. // Align with the tile, first
  368.                
  369. this->X+=8;
  370.                
  371. this->X-=this->X%16;
  372.                
  373. this->Y+=8;
  374.                
  375. this->Y-=this->Y%16;
  376.                
  377.                
  378.  
  379. // See if this was a "stop and turn" tile
  380.                
  381. if(Screen->ComboF[ComboAt(this->X, this->Y)]==CGUARD_TURN_FLAG ||
  382.                    
  383. Screen->ComboI[ComboAt(this->X, this->Y)]==CGUARD_TURN_FLAG)
  384.                
  385. {
  386.                    
  387.  
  388. // If it was, then do so
  389.                    
  390. direction=TurnAround(direction);
  391.                    
  392. this->Data=baseStandCombo+direction;
  393.                    
  394. Wait(60/speed, reaction, message, destDMap, destScreen,
  395.  enemyID, screenDIndex, this);
  396.                    
  397. direction=TurnAround(direction);
  398.                
  399. }
  400.                
  401.                
  402.  
  403. // If this guard tries turning left first...
  404.                
  405. if(movement==CGUARD_PATROL_LEFT)
  406.                
  407. {
  408.                    
  409.  
  410. // Turn left and try moving that way
  411.                    
  412. direction=TurnLeft(direction);
  413.                    
  414. if(!CanMove(direction, speed, this))
  415.                    
  416. {
  417.                        
  418.  
  419. // Maybe right?
  420.                        
  421. direction=TurnAround(direction);
  422.                        
  423. if(!CanMove(direction, speed, this))
  424.                            
  425.  
  426. // Better go back the other way, then
  427.                            
  428. direction=TurnRight(direction);
  429.                    
  430. }
  431.                
  432. }
  433.      
  434.          
  435.                
  436. // Try right first
  437.                
  438. else
  439.                
  440. {
  441.                    
  442. direction=TurnRight(direction);
  443.                    
  444. if(!CanMove(direction, speed, this))
  445.                    
  446. {
  447.                        
  448. direction=TurnAround(direction);
  449.                        
  450. if(!CanMove(direction, speed, this))
  451.                            
  452. direction=TurnLeft(direction);
  453.                    
  454. }
  455.                
  456. }
  457.                
  458.                
  459.  
  460. // Keep going
  461.                
  462. this->Data=baseWalkCombo+direction;
  463.                
  464. Move(direction, speed, this);
  465.            
  466. }
  467.            
  468.            
  469. Wait(1, reaction, message, destDMap, destScreen, enemyID,
  470.  screenDIndex, this);
  471.        
  472. }
  473.    
  474. }
  475.    
  476.    
  477. bool CheckForLink(int direction, ffc this)
  478.    
  479. {
  480.        
  481. float distance;
  482.        
  483. float angle;
  484.        
  485. float adjustedAngle;
  486.        
  487.        
  488.  
  489. // Check the distance first
  490.        
  491. distance=Distance(this->X, this->Y, Link->X, Link->Y);
  492.        
  493.        
  494. if(distance>CGUARD_VISION_RANGE)
  495.            
  496. return false;
  497.        
  498.        
  499. if(CGUARD_FIND_LINK_IF_CLOSE!=0 && distance<=CGUARD_FIND_LINK_DISTANCE)
  500.            
  501. return true;
  502.        
  503.        
  504.  
  505. // See if the angle's good, then
  506.        
  507. angle=ArcTan(Link->X-this->X, Link->Y-this->Y)*180/PI;
  508.        
  509. adjustedAngle=angle;
  510.        
  511.        
  512. if(direction==DIR_UP)
  513.            
  514. adjustedAngle+=90;
  515.        
  516. else if(direction==DIR_DOWN)
  517.            
  518. adjustedAngle-=90;
  519.        
  520. else if(direction==DIR_LEFT)
  521.            
  522. adjustedAngle+=180;
  523.        
  524. if(adjustedAngle>180)
  525.            
  526. adjustedAngle-=360;
  527.        
  528.        
  529. if(Abs(adjustedAngle)>CGUARD_VISION_ANGLE/2)
  530.            
  531. return false;
  532.        
  533.        
  534.  
  535. // Check each tile along the line
  536.        
  537. // This is kind of a crude way of doing it, but it'll work for now
  538.        
  539. int checkX=this->X+8;
  540.        
  541. int checkY=this->Y+8;
  542.        
  543. float xDiff=Cos(angle)/5;
  544.        
  545. float yDiff=Sin(angle)/5;
  546.        
  547. int i;
  548.        
  549.        
  550. for(i=0; i<=distance*5; i++)
  551.        
  552. {
  553.            
  554. if(Screen->ComboF[ComboAt(checkX, checkY)]==CGUARD_BLOCK_FLAG ||
  555.                
  556. Screen->ComboI[ComboAt(checkX, checkY)]==CGUARD_BLOCK_FLAG)
  557.                
  558. return false;
  559.            
  560. checkX+=xDiff;
  561.            
  562. checkY+=yDiff;
  563.        
  564. }
  565.        
  566.        
  567. return true;
  568.    
  569. }
  570.    
  571.    
  572.  
  573. // Called instead of Waitframe(). Handles things that need to be done
  574.    
  575. // every frame.
  576.    
  577. void Wait(int numFrames, int reaction, int message, int destDMap,
  578.              
  579. int destScreen, int enemyID, int screenDIndex, ffc this)
  580.    
  581. {
  582.        
  583.  
  584. // Can't take another argument, so just figure out the direction
  585.        
  586. int direction=this->Data%4;
  587.    
  588.        
  589. for(; numFrames>0; numFrames--)
  590.        
  591. {
  592.            
  593. if(screenDIndex>=0)
  594.            
  595. {
  596.                
  597.  
  598. // First, see if someone else just saw Link; if so...
  599.                
  600. if(Screen->D[screenDIndex]==1)
  601.                
  602. {
  603.                    
  604.  
  605. // A warping guard will let the other guy handle it
  606.                    
  607. if(reaction==CGUARD_WARP)
  608.                        
  609. Quit();
  610.                    
  611.                    
  612.  
  613. // An enemy guard will change
  614.                    
  615. else
  616.                     {
  617.                        
  618. npc enemy=Screen->CreateNPC(enemyID);
  619.                        
  620. enemy->X=this->X;
  621.                        
  622. enemy->Y=this->Y;
  623.                        
  624. enemy->Dir=direction;
  625.                        
  626. this->Data=0;
  627.                        
  628. Quit();
  629.                    
  630. }
  631.                
  632. }
  633.            
  634. }
  635.            
  636.            
  637.  
  638. // See Link?
  639.            
  640. if(CheckForLink(direction, this))
  641.            
  642. {
  643.                
  644.  
  645. // Alert the others, play the sound, and show the message
  646.                
  647. if(screenDIndex>=0)
  648.                    
  649. Screen->D[screenDIndex]=1;
  650.                
  651.                
  652. Game->PlaySound(CGUARD_SOUND);
  653.                
  654.                
  655. if(message>0)
  656.                
  657. {
  658.                    
  659. Screen->Message(message);
  660.                    
  661.                    
  662.  
  663. // If this is a warping guard, don't let Link move
  664.                    
  665. if(reaction==CGUARD_WARP)
  666.                    
  667. {
  668.  
  669. Waitframes(1);                      
  670. //while(!Link->InputA)
  671.                        
  672. //{
  673.                            
  674. //Link->InputB=false;
  675.                            
  676. //Link->InputUp=false;
  677.                            
  678. //Link->InputDown=false;
  679.                            
  680. //Link->InputLeft=false;
  681.                            
  682. //Link->InputRight=false;
  683.                            
  684. //Waitframe();
  685.                        
  686. //}
  687.                    
  688. }
  689.                
  690. }
  691.                
  692. if(reaction==CGUARD_WARP)
  693.                    
  694. Link->Warp(destDMap, destScreen);
  695.                
  696.                
  697. else
  698.  
  699. // Become an enemy
  700.                
  701. {
  702.                    
  703. npc enemy=Screen->CreateNPC(enemyID);
  704.                    
  705. enemy->X=this->X;
  706.                    
  707. enemy->Y=this->Y;
  708.                    
  709. enemy->Dir=direction;
  710.                    
  711. this->Data=0;
  712.                    
  713. Quit();
  714.                
  715. }
  716.            
  717. }
  718.            
  719.            
  720. Waitframe();
  721.        
  722. }
  723.    
  724. }
  725.    
  726.    
  727.  
  728. // Find the guard's new direction if it turns left
  729.     int TurnLeft(int dir)
  730.    
  731. {
  732.        
  733. if((dir&10b)==0)
  734.            
  735. return (dir+10b);
  736.        
  737. else
  738.            
  739. return ((dir^11b)&11b);
  740.    
  741. }
  742.    
  743.    
  744.  
  745. // Find the guard's new direction if it turns right
  746.    
  747. int TurnRight(int dir)
  748.    
  749. {
  750.        
  751. if((dir&10b)==0)
  752.            
  753. return ((dir^11b)&11b);
  754.        
  755. else
  756.            
  757. return (dir-10b);
  758.    
  759. }
  760.    
  761.    
  762.  
  763. // Find the guard's new direction if it turns around
  764.    
  765. int TurnAround(int dir)
  766.    
  767. {
  768.        
  769. return dir^((~dir&10b)|01b);
  770.    
  771. }
  772.    
  773.    
  774.  
  775. // Checks whether the guard can walk on the tile it's trying to move to
  776.    
  777. bool CanMove(int dir, float speed, ffc this)
  778.    
  779. {
  780.        
  781. int xPos;
  782.        
  783. int yPos;
  784.        
  785.        
  786. if(dir==DIR_UP)
  787.        
  788. {
  789.            
  790. xPos=this->X;
  791.            
  792. yPos=Floor(this->Y-speed);
  793.        
  794. }
  795.        
  796. else if(dir==DIR_DOWN)
  797.        
  798. {
  799.            
  800. xPos=this->X;
  801.            
  802. yPos=Ceiling(this->Y+15+speed);
  803.        
  804. }
  805.        
  806. else if(dir==DIR_LEFT)
  807.        
  808. {
  809.            
  810. xPos=Floor(this->X-speed);
  811.            
  812. yPos=this->Y;
  813.        
  814. }
  815.        
  816. else
  817.  
  818. // Right
  819.        
  820. {
  821.            
  822. xPos=Ceiling(this->X+15+speed);
  823.            
  824. yPos=this->Y;
  825.        
  826. }
  827.        
  828.        
  829. return Screen->ComboF[ComboAt(xPos, yPos)]==CGUARD_WALK_FLAG ||
  830.                
  831. Screen->ComboF[ComboAt(xPos, yPos)]==CGUARD_TURN_FLAG ||
  832.                
  833. Screen->ComboI[ComboAt(xPos, yPos)]==CGUARD_WALK_FLAG ||
  834.                
  835. Screen->ComboI[ComboAt(xPos, yPos)]==CGUARD_TURN_FLAG;
  836.    
  837. }
  838.    
  839.    
  840.  
  841. // Walks forward
  842.    
  843. void Move(int dir, float speed, ffc this)
  844.    
  845. {
  846.        
  847. if(dir==DIR_UP)
  848.            
  849. this->Y-=speed;
  850.        
  851. else if(dir==DIR_DOWN)
  852.            
  853. this->Y+=speed;
  854.        
  855. else if(dir==DIR_LEFT)
  856.            
  857. this->X-=speed;
  858.        
  859. else
  860.  
  861. // Right
  862.            
  863. this->X+=speed;
  864.    
  865. }
  866.  
  867. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top