Advertisement
Guest User

Untitled

a guest
Mar 30th, 2020
190
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.01 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement