ZoriaRPG

Arkanoid Alpha 15

Aug 17th, 2018
103
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //This was the script for Alpha 15.Over the course of various changes and attempted fixes, it became less and less stable.
  2. //I decided to revert and start fresh with some of these things.
  3. //The major bug is that the ball was ploughing through blocks and not having its direction set properly.
  4.  
  5. import "std.zh"
  6.  
  7. //I think, that to avoid multiple block collisions per frame, we need a 1x1px hitbox for the ball, and we need to move
  8. //the x/y of the hitbox based ont he direction that the ball is moving.
  9. //for the normal 4 directions, it'd be in the corner of the sprite, one pixel away from the ball.
  10. //  thus, if dir-right-up, we'd put it at x-offset = 4, y offset = -1.
  11. //for additional directions, it'd move to a specific pixel of the sprite based on the angle.
  12. //Every frame, we'd repositionreposition this one-pixel hitbox based on ball dir or angle.
  13.  
  14.  
  15.  
  16. const int ALLOW_16_ANGLES = 0;
  17.  
  18. const float DIR16_DEG_UP        = 270;
  19. const float DIR16_DEG_UPUPLEFT = 247.5;
  20.  
  21. const float DIR16_DEG_UPLEFT    = 225;
  22. const float DIR16_DEG_LEFTLEFTUP = 202.5;
  23. const float DIR16_DEG_LEFT      = 180;
  24. const float DIR16_DEG_LEFTLEFTDOWN = 157.5;
  25. const float DIR16_DEG_LEFTDOWN  = 135;
  26. const float DIR16_DEG_DOWNDOWNLEFT = 112.5;
  27. const float DIR16_DEG_DOWN      = 90;
  28. const float DIR16_DEG_DOWNDOWNRIGHT = 67.5;
  29. const float DIR16_DEG_RIGHTDOWN     = 45;
  30. const float DIR16_DEG_RIGHTRIGHTDOWN = 22.5;
  31. const float DIR16_DEG_RIGHT     = 0;
  32. const float DIR16_DEG_RIGHTRIGHTUP  = 292.5;
  33. const float DIR16_DEG_DIR_RIGHTUP   = 315;
  34.  
  35. const float DIR_16_RADS_INCREMENT = 0.3927; //Number of radians per 1/16 rotation
  36.  
  37. const float DIR16_RADS_UP       = 4.7214;
  38. const float DIR16_RADS_UPUPLEFT = 4.3197;
  39. const float DIR16_RADS_UPLEFT   = 3.927;
  40. const float DIR16_RADS_LEFTLEFTUP = 3.5343;
  41. const float DIR16_RADS_LEFT     = 3.1416; //3.1519; //Pi
  42. const float DIR16_RADS_LEFTLEFTDOWN = 2.7489;
  43. const float DIR16_RADS_LEFTDOWN     = 2.3562;
  44. const float DIR16_RADS_DOWNDOWNLEFT = 1.9635;
  45. const float DIR16_RADS_DOWN     = 1.5708;
  46. const float DIR16_RADS_DOWNDOWNRIGHT = 1.1781;
  47. const float DIR16_RADS_RIGHTDOWN    = 0.7854;
  48. const float DIR16_RADS_RIGHTRIGHTDOWN = 0.3927;
  49. const float DIR16_RADS_RIGHT    = 0;
  50. const float DIR16_RADS_RIGHTRIGHTUP = 5.1051;
  51. const float DIR16_RADS_RIGHTUP  = 5.4978;
  52. const float DIR16_RADS_RIGHTUPUP    = 5.1141;
  53.  
  54. //Ball Dir Compares
  55. const int BALL_MISC_DIR = 3; //Misc index to hold ball direction.
  56. const int BALL_DIR_LLU = 0;
  57. const int BALL_DIR_LU = 1;
  58. const int BALL_DIR_UUL = 2;
  59. const int BALL_DIR_UUR = 3;
  60. const int BALL_DIR_RU = 4;
  61. const int BALL_DIR_RRU = 5;
  62.  
  63. //There's a step speed at which the ball phases *through* the vaus! //FIXED with ball.clamp().
  64.                     //Perhaps we should make the vaus an enemy, too? An invisible enemy to act as a failsafe?
  65.                     //if the ball hits the vaus, it bounces.
  66.                    
  67.             //Or just scrap the vaus ffc, and use an npc for it in general?
  68.  
  69. //BALL NEEDS TO HAVE A 6PX BY 6PX HITBOX, AND THUS A HIT OFFSET OF -1,-1, so that ->HitBy[] returns when the ball hits a block, and
  70. //the ball is still not yet inside that object
  71. //Note: We also need to store the UID of each ball, as HitBy[] works from the UID, not the pointer.
  72.  
  73. //# QUEST ISSUE: Bricks Break playing the wrong sound, despite being set. Might be a 2.54 bug? -Z
  74.  
  75. /* ZC issues: I forgot to expand ->Misc[] in sprite.cpp, which should be fixed int he source for Alpha 32.
  76.     This meant that r/w to ptr->Misc[>15] would use invalid data, or overwrite other data. bad, bad, bad.
  77.    
  78.     Continue script does not run when Init script runs. It NEEDS to do that! Otherwise, settings that affect things such as Link's tile
  79.     don't happen before the opening wipe.
  80.    
  81.     HitBy[] Doesn't yet use UIDs. :/ I forgot that it uses the screen index. This is a case for adding HitBy[UID] to 2.54...
  82.     In fact, the only reason that using HitBy[UID] worked, was because my object 9the ball_ was *both* UID1 and LW1. :D
  83.    
  84. */
  85.  
  86. // We need to either re-arrange the living/dead/death logic, or add another animation phase.
  87. //May as well set up the Vaus explosion and add it with a SPARKLE LWeapon.
  88.  
  89. //Arkanoid script
  90. //v0.15
  91. //17th August, 2018
  92.  
  93. //Radians for special directions.
  94. const float DIR_UUL = 4.3197;
  95. const float DIR_LUU = 4.3197;
  96. const float DIR_LLU = 3.5343;
  97. const float DIR_ULL = 3.5343;
  98. const float DIR_LLD = 2.7489;
  99. const float DIR_DLL = 2.7489;
  100. const float DIR_DDL = 1.9635;
  101. const float DIR_LDD = 1.9635;
  102. const float DIR_DDR = 1.1781;
  103. const float DIR_RDD = 1.1781;
  104. const float DIR_RRD = 0.3927;
  105. const float DIR_DRR = 0.3927;
  106. const float DIR_RRU = 5.1051;
  107. const float DIR_URR = 5.1051;
  108. const float DIR_RUU = 5.1141;
  109. const float DIR_UUR = 5.1141;
  110.  
  111.  
  112.        
  113.  
  114. const float ARKANOID_VERSION = 0.15;
  115.  
  116. int GAME[256];
  117. const int GAME_MISC_FLAGS = 0;
  118. const int GMFS_PLAYED_GAME_OVER_MUSIC = 0x01;
  119.  
  120. const int FFC_VAUS = 1;
  121. const int CMB_VAUS_EXTENDED = 1528;
  122. const int CMB_VAUS = 1524;
  123. const int CMB_VAUS_DEAD = 1520;
  124.  
  125. const int MID_STAGE_START = 4;
  126. const int NPCM_AWARDED_POINTS = 3; //brick->Misc[], flag to mark if points were awarded to the player.
  127. const int NPC_ATTRIB_POINTS = 0; //brick->Attributes[], value for score.
  128.  
  129. //Counters
  130. const int CR_SCORE = 7; //script 1
  131. const int CR_LIVES = 8;
  132.  
  133. int quit;
  134.  
  135. const int QUIT_TITLE = -1;
  136. const int QUIT_GAME_RUNNING = 0; //i.e., !quit
  137. const int QUIT_GAMEOVER = 1;
  138.  
  139. const int MAX_BALL_SPEED = 600;
  140.  
  141. int caught;
  142. int frame;
  143. bool newstage = true;
  144. bool revive_vaus = false;
  145. bool must_repos_hitbox;
  146.  
  147. int ball_x;
  148. int ball_y;
  149. int ball_dir;
  150. int ball_angle;
  151. int ball_speed;
  152. int ball_vx;
  153. int ball_vy;
  154. int paddle_x;
  155. int paddle_y;
  156. int paddle_width = 16;
  157. int paddle_speed = 2;
  158. int extended;
  159.  
  160. int ball_uid;
  161.  
  162. int ball_cooldown = -1;
  163. const int COOLDOWN_FRAMES = 0;
  164.  
  165. //animation
  166. int death_frame;
  167.  
  168. int death_anim[DEATH_ANIM_MAX];
  169. const int DEATH_ANIM_TIMER = 0;
  170. const int DEATH_ANIM_1 = 1; //1-7 Unused
  171. const int DEATH_ANIM_2 = 2;
  172. const int DEATH_ANIM_3 = 3;
  173. const int DEATH_ANIM_4 = 4;
  174. const int DEATH_ANIM_5 = 5;
  175. const int DEATH_ANIM_6 = 6;
  176. const int DEATH_ANIM_COUNTDOWN_TO_QUIT = 7;
  177.  
  178. const int DEATH_ANIM_MAX = 8;
  179.  
  180. const int COUNTDOWN_TO_QUIT_FRAMES = 289; //36*8+1;
  181.  
  182. int templayer[4];
  183.  
  184. int input_accel; //pressing left and right for multiple frames increases this
  185. int frames_pressed[18];
  186.  
  187. //ffc paddle;
  188.  
  189. int hit_zones[5]; //angle offsets for where the ball strikes the paddle
  190.  
  191. const int WALL_LEFT = 24;
  192. const int WALL_TOP = 8; //Mix Ball Y
  193. const int WALL_RIGHT = 232;
  194.  
  195. const int BALL_MIN_Y = 9; //ceiling +1
  196. const int BALL_MAX_Y = 145; //one pixel under paddle top
  197. const int BALL_MIN_X = 25; //left wall +1
  198. const int BALL_MAX_X = 229; //right wall -1
  199.  
  200.  
  201.  
  202. const int START_PADDLE_X = 62;
  203. const int START_PADDLE_Y = 160;
  204. const int START_PADDLE_WIDTH = 32;
  205. const int START_PADDLE_HEIGHT = 8;
  206. const int BALL_WIDTH = 4;
  207. const int BALL_HEIGHT = 4;
  208. const int START_BALL_X = 98; //(START_PADDLE_X + 36);
  209. const int START_BALL_Y = 156; //START_PADDLE_Y - 4;
  210. const int START_BALL_DIR = 5; //DIR_UPRIGHT;
  211. const int START_BALL_RADS = 220; //angle in radians
  212. const int START_BALL_SPEED = 45;
  213. const int START_BALL_VX = 0;
  214. const int START_BALL_VY = 0;
  215.  
  216. const int PADDLE_MIN_X = 25;
  217. const int PADDLE_MAX_X = 200; //WALL_RIGHT -32; //This one varies as the paddle width may change.
  218. const int PADDLE_MAX_X_EXTENDED = 184; //WALL_RIGHT - 48; //This one varies as the paddle width may change.
  219. const int PADDLE_MIN_X_EXTENDED = 25;
  220.  
  221. const int _MOUSE_X = 0;
  222. const int _MOUSE_Y = 1;
  223. const int _MOUSE_LCLICK = 2;
  224.  
  225. //const float ACCEL_FACTOR = 0.25;
  226.  
  227. const int FRAMES_PER_MOVEMENT = 10;
  228. int USE_ACCEL = 0; //Do we accelerate KB/JP input?
  229. int USE_MOUSE = 0; //Are we using the mouse?
  230.  
  231.  
  232. /*
  233. const int CB_UP     = 0;
  234. const int CB_DOWN   = 1;
  235. const int CB_LEFT   = 2;
  236. const int CB_RIGHT  = 3;
  237. const int CB_A      = 4;
  238. const int CB_B      = 5;
  239. const int CB_L      = 7;
  240. const int CB_R      = 8;
  241. const int CB_START  = 6;
  242. const int CB_MAP    = 9;
  243. const int CB_EX1    = 10;
  244. const int CB_EX2    = 11;
  245. const int CB_EX3    = 12;
  246. const int CB_EX4    = 13;
  247. const int CB_AXIS_UP    = 14;
  248. const int CB_AXIS_DOWN  = 15;
  249. const int CB_AXIS_LEFT  = 16;
  250. const int CB_AXIS_RIGHT = 17;
  251.  
  252. */
  253.  
  254. ffc script paddle
  255. {
  256.     void run(){}
  257.    
  258.     bool move(bool mouse, bool accel, ffc p)
  259.     {
  260.         int dir; int dist;
  261.         if ( mouse )
  262.         {
  263.             //get the mouse movement this frame and apply a relative amount to the paddle
  264.             //set the dir here
  265.             //set the dist here
  266.             //if moving left
  267.             //if ( p->X > PADDLE_MIN_X )
  268.             //{
  269.             //  p->X = Input->Mouse[_MOUSE_X];
  270.                 //apply change -- ZC has no special mouse tracking.
  271.             //}
  272.             //if moving right
  273.             if ( !extended )
  274.             {
  275.                 if ( Input->Mouse[_MOUSE_X] <= PADDLE_MAX_X )
  276.                 {
  277.                     if ( Input->Mouse[_MOUSE_X] >= PADDLE_MIN_X )
  278.                     {
  279.                         //apply change
  280.                         p->X = Input->Mouse[_MOUSE_X];
  281.                     }
  282.                 }
  283.             }
  284.             else
  285.             {
  286.                 if ( Input->Mouse[_MOUSE_X] <= PADDLE_MAX_X_EXTENDED )
  287.                 {
  288.                     if ( Input->Mouse[_MOUSE_X] >= PADDLE_MIN_X_EXTENDED )
  289.                     {
  290.                         //apply change
  291.                         p->X = Input->Mouse[_MOUSE_X];
  292.                     }
  293.                 }
  294.             }
  295.         }
  296.         else //using a KB or joypad
  297.         {
  298.             //check how long the dir button is held
  299.             if ( accel ) //if we allow acceleratiopn, move N pixeld * accel factor * frames held
  300.             {
  301.                
  302.                 if ( !extended )
  303.                 {
  304.                     if (  Input->Button[CB_LEFT] )
  305.                     {
  306.                         for ( int q = frames_pressed[CB_LEFT]; q > 0 ; --q )
  307.                         {
  308.                             if ( p->X > PADDLE_MIN_X )
  309.                             {
  310.                                 --p->X;
  311.                                 --p->X;
  312.                             }
  313.                         }
  314.                     }
  315.                     if (  Input->Button[CB_RIGHT] )
  316.                     {
  317.                         for ( int q = frames_pressed[CB_RIGHT]; q > 0; --q )
  318.                         {
  319.                             if ( p->X < PADDLE_MAX_X )
  320.                             {
  321.                                 ++p->X;
  322.                             }
  323.                         }
  324.                     }
  325.                 }
  326.                
  327.             }
  328.            
  329.             else //no accel offered, move a static number of pixels
  330.             {
  331.                
  332.                 if ( !extended )
  333.                 {
  334.                     if (  Input->Button[CB_LEFT] )
  335.                     {
  336.                         for ( int q = 0; q < paddle_speed; ++q )
  337.                         {
  338.                             if ( p->X > PADDLE_MIN_X )
  339.                             {
  340.                                 --p->X;
  341.                             }
  342.                         }
  343.                     }
  344.                     if (  Input->Button[CB_RIGHT] )
  345.                     {
  346.                         for ( int q = 0; q < paddle_speed; ++q )
  347.                         {
  348.                             if ( p->X < PADDLE_MAX_X )
  349.                             {
  350.                                 ++p->X;
  351.                             }
  352.                         }
  353.                     }
  354.                 }
  355.                 else
  356.                 {
  357.                     if (  Input->Button[CB_LEFT] )
  358.                     {
  359.                         if ( p->X > PADDLE_MIN_X_EXTENDED )
  360.                         {
  361.                             --p->X;
  362.                         }
  363.                     }
  364.                     if (  Input->Button[CB_RIGHT] ) {
  365.                         if ( p->X < PADDLE_MAX_X_EXTENDED )
  366.                         {
  367.                             ++p->X;
  368.                         }
  369.                     }
  370.                    
  371.                 }
  372.             }
  373.         }
  374.        
  375.     }
  376.  
  377.     void check_input()
  378.     {
  379.         if ( Input->Button[CB_LEFT] ) ++frames_pressed[CB_LEFT];
  380.         else frames_pressed[CB_LEFT] = 0;
  381.         if ( Input->Button[CB_RIGHT] ) ++frames_pressed[CB_RIGHT];
  382.         else frames_pressed[CB_RIGHT] = 0;
  383.        
  384.     }
  385.    
  386.     void extend(ffc p)
  387.     {
  388.         if ( extended )
  389.         {
  390.             if ( p->TileWidth < 3 )
  391.             {
  392.                 p->Data = CMB_VAUS_EXTENDED;
  393.                 p->TileWidth = 3;
  394.             }
  395.         }
  396.         else
  397.         {
  398.             if ( p->TileWidth > 2 )
  399.             {
  400.                 p->Data = CMB_VAUS;
  401.                 p->TileWidth = 2;
  402.             }
  403.         }
  404.     }
  405.     void setup(ffc p)
  406.     {
  407.         p->Y = START_PADDLE_Y;
  408.         p->X = START_PADDLE_X;
  409.         p->Data = CMB_VAUS;
  410.         p->TileWidth = 2;
  411.        
  412.     }
  413.     void dead(ffc p)
  414.     {
  415.         p->Data = CMB_VAUS_DEAD;
  416.         p->TileWidth = 2;
  417.         death_frame = frame;
  418.     }
  419.    
  420.  
  421. }
  422.  
  423. const int MISC_BALLID = 0; //Misc index of Vaud->Misc[]
  424. const int MISC_DEAD = 1; //Misc index of Vaud->Misc[]
  425. const int MISC_LAUNCHED = 0; //Misc index of ball->Misc[]
  426.  
  427. const int BALL_MINIMUM_Y = 24; //Invisible line at which point, ball is lost.
  428.  
  429. ffc script holdlink
  430. {
  431.     void run()
  432.     {
  433.         while(1)
  434.         {
  435.             Link->Y = START_PADDLE_Y - 4;
  436.             Waitframe();
  437.         }
  438.     }
  439. }
  440.        
  441.  
  442. global script arkanoid
  443. {
  444.    
  445.     void run()
  446.     {
  447.         TraceNL(); TraceS("Starting Arkanoid"); TraceNL(); TraceS("Game 'quit' state: "); Trace(quit);
  448.         TraceNL(); TraceS("Game version, Alpha "); Trace(ARKANOID_VERSION);
  449.        
  450.         //frame = -1;
  451.         ffc vaus = Screen->LoadFFC(FFC_VAUS);
  452.         lweapon movingball;
  453.         npc vaus_guard;
  454.         bool ext;
  455.         Link->CollDetection = false;
  456.         Link->DrawYOffset = -32768;
  457.        
  458.         ball.setup_sprite(SPR_BALL);
  459.         while(true)
  460.         {
  461.             while(!quit)
  462.             {
  463.                 ++frame;
  464.                 if ( Input->Key[KEY_L] ) ++Game->Counter[CR_LIVES];
  465.                 hold_Link_y(); //Don't allow Link to leave the screen, bt
  466.                     //keep his X and Y matched to the Vaus!
  467.                 hold_Link_x(vaus); //Link is used to cause floating enemies to home in on the vaus.
  468.                 if ( newstage )
  469.                 {
  470.                     //vaus_guard = Screen->CreateNPC(NPC_VAUSGUARD);
  471.                     Game->PlayMIDI(MID_STAGE_START);
  472.                     brick.setup();
  473.                     Waitframes(6);
  474.                    
  475.                     brick.clear_combos();
  476.                    
  477.                     newstage = false;
  478.                     paddle.setup(vaus);
  479.                     ball.create(vaus);
  480.                     movingball = vaus->Misc[MISC_BALLID];
  481.                 }
  482.                 if ( revive_vaus ) //when this is called, the ball breaks through all bricks. Something isn't being set.
  483.                 {
  484.                     Game->PlayMIDI(MID_STAGE_START);
  485.                     vaus->Misc[MISC_DEAD] = 0;
  486.                     revive_vaus = false;
  487.                    
  488.                     paddle.setup(vaus);
  489.                     ball.create(vaus);
  490.                     movingball = vaus->Misc[MISC_BALLID];
  491.                 }
  492.                
  493.                 if ( !vaus->Misc[MISC_DEAD] )
  494.                 {
  495.                     //if ( Input->Key[KEY_P] ) Trace(movingball->UID); //Frick, I'm an idiot. HIT_BY_LWEAPON is the SCREEN INDEX< not the UID!!
  496.                         //2.54 Absolutely needs HitBy_UID!
  497.                     if ( Input->Key[KEY_1] ) Trace(frame);
  498.                     //if ( frame%60 == 0 ) { Trace(movingball->Step); }
  499.                     //Trace(movingball->Step);
  500.                     change_setting(); //check for a setting change_setting
  501.                     paddle.extend(vaus);
  502.                     paddle.check_input();
  503.                     paddle.move(USE_MOUSE, USE_ACCEL, vaus);
  504.                    
  505.                     ball.launch(movingball);
  506.                     if ( !ball.launched(movingball) )
  507.                     {
  508.                         ball.move_with_vaus(movingball, vaus);
  509.                     }
  510.                    
  511.                     if ( must_repos_hitbox )
  512.                     {
  513.                         must_repos_hitbox = false;
  514.                         ball.reposition_hitbox(movingball);
  515.                     }
  516.                     //if ( movingball->Step % 50 == 0 )
  517.                     //{
  518.                     //  TraceNL(); TraceS("Step is now: "); Trace(movingball->Step);
  519.                     //}
  520.                    
  521.                     //clamp within bounds - MANDATORY because very fast Step speeds can cause the ball
  522.                     //to *phase* through pseudo-solid objects, such as walls and the Vaus.
  523.                     ball.clamp_rightwall(movingball);
  524.                     ball.clamp_ceiling(movingball);
  525.                     ball.clamp_leftwall(movingball);
  526.                     ball.clamp_bottom(movingball, vaus);
  527.                    
  528.                    
  529.                     //ball wall bounce checks
  530.                     ball.check_ceiling(movingball);
  531.                     ball.check_leftwall(movingball);
  532.                     ball.check_rightwall(movingball);
  533.                     ball.check_hitvaus(movingball, vaus);
  534.                    
  535.                     /*
  536.                     if ( ball_cooldown > 0 )
  537.                     {
  538.                         movingball->CollDetection = false;
  539.                         --ball_cooldown;
  540.                     }
  541.                     if ( ball_cooldown == 0 )
  542.                     {
  543.                         movingball->CollDetection = true;
  544.                         ball_cooldown = -1;
  545.                     }
  546.                     */
  547.                     //ball.increase_speed(movingball);
  548.                     /*
  549.                    
  550.                     I moved this to after Waitdraw, because I wanted the post-draw timing for ball bounce, and to ensure that
  551.                     the movingball lweapon stayed alive. -Z (Alpha 0.10)
  552.                     //Bounce ball on bricks.
  553.                     for ( int q = Screen->NumNPCs(); q > 0; --q )
  554.                     {
  555.                         npc b = Screen->LoadNPC(q);
  556.                         if ( b->Type != NPCT_OTHERFLOAT ) continue;
  557.                         TraceNL(); TraceS("movingball->X = "); Trace(movingball->X);
  558.                         TraceNL(); TraceS("movingball->Y = "); Trace(movingball->Y);
  559.                         brick.take_hit(b, movingball);
  560.                     }
  561.                     */
  562.                     movingball->DeadState = WDS_ALIVE; //Force it alive at all times if the vaus is alive.
  563.                         //We'll need another solition once we do the 3-way split ball. Bleah.
  564.                 }
  565.                
  566.                 //It's probably unwise to run this block twice! Where do I want it, before or after Waitdraw() ? -Z
  567.                 else
  568.                 {
  569.                     paddle.dead(vaus); //Set the death animation here.
  570.                    
  571.                     /*
  572.                     while ( (frame - 100) < death_frame )
  573.                     {
  574.                         //we should hide the vaus, and restart the stage here.
  575.                         ++frame;
  576.                         Waitdraw(); //Something is preventing the vaus from changing into the explosion style. S
  577.                         Waitframe();
  578.                     }
  579.                     lweapon deadball = movingball;
  580.                     deadball->DeadState = WDS_DEAD;
  581.                     movingball = vaus->Misc[10];
  582.                     if ( Game->Counter[CR_LIVES] )
  583.                     {
  584.                         --Game->Counter[CR_LIVES];
  585.                         revive_vaus = true;
  586.                     }
  587.                     */
  588.                    
  589.                 }
  590.                
  591.                
  592.                 Waitdraw();
  593.                
  594.                 hold_Link_y();
  595.                
  596.                 if ( !vaus->Misc[MISC_DEAD] )
  597.                 {
  598.                     movingball->DeadState = WDS_ALIVE;
  599.                    
  600.                     //ball.reposition_hitbox(movingball);
  601.                    
  602.                     //Bounce ball on bricks.
  603.                     for ( int q = Screen->NumNPCs(); q > 0; --q )
  604.                     {
  605.                         npc b = Screen->LoadNPC(q);
  606.                         if ( b->Type != NPCT_OTHERFLOAT ) continue;
  607.                         //TraceNL(); TraceS("movingball->X = "); Trace(movingball->X);
  608.                         //TraceNL(); TraceS("movingball->Y = "); Trace(movingball->Y);
  609.                         movingball->DeadState = WDS_ALIVE;
  610.                         //TraceNL(); TraceS("movingball ptr: "); Trace(movingball);
  611.                         if ( brick.take_hit(b, movingball) )
  612.                         {
  613.                             continue;
  614.                             //break;
  615.                         }
  616.                         //ball.reposition_hitbox(movingball);
  617.                        
  618.                     }
  619.                    
  620.                 }
  621.                 else
  622.                 {
  623.                     paddle.dead(vaus);
  624.                     while ( (frame - 100) < death_frame )
  625.                     {
  626.                         //we should hide the vaus, and restart the stage here.
  627.                         ++frame;
  628.                         Waitdraw();
  629.                         Waitframe();
  630.                     }
  631.                     lweapon deadball = movingball;
  632.                     deadball->DeadState = WDS_DEAD;
  633.                     movingball = vaus->Misc[10]; //Because = NULL() requires alpha 32. :D
  634.                     if ( Game->Counter[CR_LIVES] )
  635.                     {
  636.                         --Game->Counter[CR_LIVES];
  637.                         revive_vaus = true;
  638.                     }
  639.                     else //Ugh, this is a mess. I might want to rewrite the gane over portion, as it feels as if it'll be a biugger kludge than just calling break.
  640.                     {
  641.                         if ( !death_anim[DEATH_ANIM_COUNTDOWN_TO_QUIT] )
  642.                         {
  643.                             death_anim[DEATH_ANIM_COUNTDOWN_TO_QUIT] = COUNTDOWN_TO_QUIT_FRAMES;
  644.                             continue;
  645.                         }
  646.                         else
  647.                         {
  648.                             --death_anim[DEATH_ANIM_COUNTDOWN_TO_QUIT];
  649.                             if ( death_anim[DEATH_ANIM_COUNTDOWN_TO_QUIT] == 1 )
  650.                             {
  651.                                 quit = QUIT_GAMEOVER; //Game over state.
  652.                                 TraceNL(); TraceS("Game 'quit' state is now: "); Trace(quit);
  653.                             }
  654.                         }
  655.                     }
  656.                        
  657.                 }
  658.                
  659.                 Waitframe();
  660.             }
  661.            
  662.             while (quit == QUIT_GAMEOVER) //Game Over
  663.             {
  664.                 if ( !(GAME[GAME_MISC_FLAGS]&GMFS_PLAYED_GAME_OVER_MUSIC) )
  665.                 {
  666.                     GAME[GAME_MISC_FLAGS]|=GMFS_PLAYED_GAME_OVER_MUSIC;
  667.                     //Play Game over MIDI
  668.                     Game->PlayMIDI(1);
  669.                 }
  670.                    
  671.                 Screen->DrawString(6, 96, 80, 1, 0x51, 0x00, 0, "GAME OVER", 128);
  672.                
  673.                 Waitdraw();
  674.                 Waitframe();
  675.             }
  676.             //We should never reach here.
  677.             Waitframe();
  678.         }
  679.     }
  680.     void change_setting()
  681.     {
  682.         if ( Input->Key[KEY_M] ) USE_MOUSE = 1;
  683.         if ( Input->Key[KEY_N] ) USE_MOUSE = 0;
  684.         if ( Input->Key[KEY_F] ) USE_ACCEL = 1;
  685.         if ( Input->Key[KEY_G] ) USE_ACCEL = 0;
  686.         if ( Input->Key[KEY_T] ) --paddle_speed; // paddle_speed = vbound(paddle_speed
  687.         if ( Input->Key[KEY_Y] ) ++paddle_speed; // paddle_speed = vbound(paddle_speed
  688.     }
  689.     void hold_Link_x(ffc v)
  690.     {
  691.         Link->X = v->X+(v->TileWidth*8);
  692.     }
  693.     void hold_Link_y()
  694.     {
  695.         Link->Y = START_PADDLE_Y - 4;
  696.     }
  697.     bool quit() { return ( quit ); }
  698.    
  699. }
  700.  
  701. const int TILE_BALL = 50512;
  702. const int SPR_BALL = 100;
  703.  
  704.  
  705.  
  706. //preliminary ball
  707. ffc script ball
  708. {
  709.     void run(){}
  710.     void setup_sprite(int sprite_id)
  711.     {
  712.         spritedata sd = Game->LoadSpriteData(sprite_id);
  713.         sd->Tile = TILE_BALL;
  714.     }
  715.     void set_speed(lweapon b, int speed)
  716.     {
  717.         //Trace(bounces);
  718.         b->Step = speed; // bound(bounces,0,MAX_BOUNCES);
  719.         //Trace(b->Step);
  720.     }
  721.     void increase_speed(lweapon b, int amt_base)
  722. {
  723.     int prevStep = b->Step;
  724.     int inc = amt_base;
  725.     while ( b->Step == prevStep )
  726.     {
  727.         b->Step += inc;
  728.         ++inc;
  729.     }
  730. }
  731.     void reposition_hitbox(lweapon b)
  732.     {
  733.         if ( !b->Angular )
  734.         {
  735.             switch(b->Dir)
  736.             {
  737.                 case DIR_RIGHTUP:
  738.                 {
  739.                     //TraceNL(); TraceS("Ball Hitbox is now UR corner");
  740.                     b->HitYOffset = -1;
  741.                     b->HitXOffset = 2;
  742.                     break;
  743.                 }
  744.                 case DIR_LEFTUP:
  745.                 {
  746.                     //TraceNL(); TraceS("Ball Hitbox is now UL corner");
  747.                     b->HitYOffset = -1;
  748.                     b->HitXOffset = 1;
  749.                     break;
  750.                 }
  751.                 case DIR_LEFTDOWN:
  752.                 {
  753.                     //TraceNL(); TraceS("Ball Hitbox is now LL corner");
  754.                     b->HitYOffset = 4;
  755.                     b->HitXOffset = 1;
  756.                     break;
  757.                 }
  758.                 case DIR_RIGHTDOWN:
  759.                 {
  760.                     //TraceNL(); TraceS("Ball Hitbox is now LR corner");
  761.                     b->HitYOffset = 4;
  762.                     b->HitXOffset = 2;
  763.                     break;
  764.                 }
  765.             }
  766.         }
  767.         else //angular
  768.         {
  769.            
  770.            
  771.         }
  772.     }
  773.            
  774.            
  775.     void create(ffc vaus_id) //send the ball lweapon pointer back to the vaus
  776.     {
  777.         lweapon ball = Screen->CreateLWeapon(LW_SCRIPT1);
  778.         TraceNL(); TraceS("Creating ball with Script UID: "); Trace(ball->UID);
  779.         ball->HitWidth = 1; //6; //Not 4, so that the ball bounces when its edges touch a brick.
  780.         ball->HitHeight = 1; //6; //Not 4, so that the ball bounces when its edges touch a brick.
  781.         ball->UseSprite(SPR_BALL);
  782.         ball->X = vaus_id->X+18;
  783.         ball->Y = vaus_id->Y-2;
  784.         ball->Damage = 1;
  785.         ball_uid = ball->UID;
  786.         ball->HitXOffset = 4; //so that the ball bounces when its edges touch a brick.
  787.         ball->HitYOffset = -1; //so that the ball bounces when its edges touch a brick.
  788.         vaus_id->Misc[MISC_BALLID] = ball;
  789.     }
  790.     void launch(lweapon b)
  791.     {
  792.         if ( b->Misc[MISC_LAUNCHED] ) return;
  793.         bool launched;
  794.         for ( int q = CB_A; q < CB_R; ++q )
  795.         {
  796.             if ( Input->Press[q] ) { launched = true; break; }
  797.         }
  798.         if ( launched )
  799.         {
  800.             //b->Angular = true;
  801.             Game->PlaySound(6);
  802.             b->Dir = DIR_RIGHTUP;  
  803.             b->Step = 90;
  804.             b->Misc[MISC_LAUNCHED] = 1;
  805.         }
  806.     }
  807.     bool launched(lweapon b)
  808.     {
  809.         return (b->Misc[MISC_LAUNCHED]);
  810.     }
  811.     void move(lweapon b)
  812.     {
  813.        
  814.     }
  815.     float bound(int val, int min, int max)
  816.     {
  817.         if ( val < min ) return min;
  818.         if ( val > max ) return max;
  819.         return val;
  820.     }
  821.     //Not launched yet.
  822.     void move_with_vaus(lweapon b, ffc v)
  823.     {
  824.         b->X = v->X+18;
  825.     }
  826.     //ball.clamp*() are needed for when the step speed is so great that the ball skips past the equality checks.
  827.     void clamp_ceiling(lweapon b)
  828.     {
  829.         if ( b->Y < BALL_MIN_Y )           
  830.         {
  831.             b->Y = BALL_MIN_Y;
  832.         }
  833.     }
  834.     void clamp_leftwall(lweapon b)
  835.     {
  836.         if ( caught ) return; //don't do anything while the vaus is holding the ball
  837.         if ( b->X < BALL_MIN_X ) b ->X = BALL_MIN_X;
  838.     }
  839.     void clamp_rightwall(lweapon b)
  840.     {
  841.         if ( caught ) return; //don't do anything while the vaus is holding the ball
  842.         if ( b->X > BALL_MAX_X ) b->X = BALL_MAX_X;
  843.     }
  844.     /*
  845.     void clamp_bottom(lweapon b, ffc v)
  846.     {
  847.         if ( caught ) return; //don't do anything while the vaus is holding the ball
  848.         if ( b->Y+4 > v->Y+8 ) dead(b,v);
  849.     }
  850.     */
  851.     //A function to check of the bounding will prevent the ball from falling out of field.
  852.     void clamp_bottom(lweapon b, ffc v)
  853.     {
  854.         if ( caught ) return; //don't do anything while the vaus is holding the ball
  855.         if ( b->Y+4 > v->Y ) b->Y = v->Y-4;
  856.     }
  857.     void check_ceiling(lweapon b)
  858.     {
  859.         if ( b->Y == BALL_MIN_Y )          
  860.         {
  861.             Game->PlaySound(7);
  862.             if ( b->Angular && ALLOW_16_ANGLES )
  863.             {
  864.                 switch ( b->Misc[BALL_MISC_DIR] )
  865.                 //switch ( b->Angle )
  866.                 {
  867.                     //flip up and down
  868.                     //left
  869.                     case DIR_LLU:
  870.                     {
  871.                         //++v->X; //not sure if we'll need this bit.
  872.                         b->Angle = DIR_LLD;
  873.                         b->Misc[BALL_MISC_DIR] = DIR_LLD;
  874.                         increase_speed(b,2);
  875.                         //ball_cooldown = COOLDOWN_FRAMES;
  876.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  877.                         break;
  878.                     }
  879.                     case DIR_UUL:
  880.                     {
  881.                         //++v->X; //not sure if we'll need this bit.
  882.                         b->Angle = DIR_DDL;
  883.                         b->Misc[BALL_MISC_DIR] = DIR_DDL;
  884.                         increase_speed(b,2);
  885.                         //ball_cooldown = COOLDOWN_FRAMES;
  886.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  887.                         break;
  888.                     }
  889.                     //right
  890.                     case DIR_RRU:
  891.                     {
  892.                         //++v->X; //not sure if we'll need this bit.
  893.                         b->Angle = DIR_RRD;
  894.                         b->Misc[BALL_MISC_DIR] = DIR_RRD;
  895.                         increase_speed(b,2);
  896.                         //ball_cooldown = COOLDOWN_FRAMES;
  897.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  898.                         break;
  899.                     }
  900.                     case DIR_RUU:
  901.                     {
  902.                         //++v->X; //not sure if we'll need this bit.
  903.                         b->Angle = DIR_DDR;
  904.                         b->Misc[BALL_MISC_DIR] = DIR_DDR;
  905.                         increase_speed(b,2);
  906.                         //ball_cooldown = COOLDOWN_FRAMES;
  907.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  908.                         break;
  909.                     }
  910.                     default: { TraceNL(); TraceS("check_ceiling() could not determine the angle of an ANgular ball!"); break;}
  911.                 }
  912.             }
  913.             else
  914.             {
  915.                 switch(b->Dir)
  916.                 {
  917.                     case DIR_RIGHTUP: { b->Dir = DIR_RIGHTDOWN;
  918.                         //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  919.                         increase_speed(b,2);
  920.                         //ball_cooldown = COOLDOWN_FRAMES;
  921.                         b->Misc[BALL_MISC_DIR] = DIR_RIGHTDOWN; break; }
  922.                     case DIR_LEFTUP: { b->Dir = DIR_LEFTDOWN;
  923.                         //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  924.                         increase_speed(b,2);
  925.                         //ball_cooldown = COOLDOWN_FRAMES;
  926.                         b->Misc[BALL_MISC_DIR] = DIR_LEFTDOWN; break; }
  927.                     default: { b->Dir = DIR_DOWN; b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED); break; }
  928.                 }
  929.             }
  930.             reposition_hitbox(b);
  931.         }
  932.     }
  933.     void check_leftwall(lweapon b)
  934.     {
  935.         if ( caught ) return; //don't do anything while the vaus is holding the ball
  936.         if ( b->X == BALL_MIN_X )
  937.         {
  938.             Game->PlaySound(7);
  939.             if ( b->Angular && ALLOW_16_ANGLES )
  940.             {
  941.                 switch ( b->Misc[BALL_MISC_DIR] )
  942.                 //switch ( b->Angle )
  943.                 {
  944.                     //flip left and right
  945.                     //left
  946.                     case DIR_LLU:
  947.                     {
  948.                         //++v->X; //not sure if we'll need this bit.
  949.                         b->Angle = DIR_RRU;
  950.                         b->Misc[BALL_MISC_DIR] = DIR_RRU;
  951.                         increase_speed(b,2);
  952.                         //ball_cooldown = COOLDOWN_FRAMES;
  953.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  954.                         break;
  955.                     }
  956.                     case DIR_UUL:
  957.                     {
  958.                         //++v->X; //not sure if we'll need this bit.
  959.                         b->Angle = DIR_UUR;
  960.                         b->Misc[BALL_MISC_DIR] = DIR_UUR;
  961.                         increase_speed(b,2);
  962.                         //ball_cooldown = COOLDOWN_FRAMES;
  963.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  964.                         break;
  965.                     }
  966.                     //right
  967.                     case DIR_LLD:
  968.                     {
  969.                         //++v->X; //not sure if we'll need this bit.
  970.                         b->Angle = DIR_RRD;
  971.                         b->Misc[BALL_MISC_DIR] = DIR_RRD;
  972.                         increase_speed(b,2);
  973.                         //ball_cooldown = COOLDOWN_FRAMES;
  974.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  975.                         break;
  976.                        
  977.                     }
  978.                     case DIR_LDD:
  979.                     {
  980.                         //++v->X; //not sure if we'll need this bit.
  981.                         b->Angle = DIR_DDR;
  982.                         b->Misc[BALL_MISC_DIR] = DIR_DDR;
  983.                         increase_speed(b,2);
  984.                         //ball_cooldown = COOLDOWN_FRAMES;
  985.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  986.                         break;
  987.                     }
  988.                     default: { TraceNL(); TraceS("check_leftwall() could not determine the angle of an ANgular ball!"); break;}
  989.                 }
  990.             }
  991.             else
  992.             {
  993.                 switch(b->Dir)
  994.                 {
  995.                     case DIR_LEFTDOWN: { b->Dir = DIR_RIGHTDOWN;
  996.                         //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  997.                         increase_speed(b,2);
  998.                         //ball_cooldown = COOLDOWN_FRAMES;
  999.                         b->Misc[BALL_MISC_DIR] = DIR_RIGHTDOWN; break; }
  1000.                     case DIR_LEFTUP: { b->Dir = DIR_RIGHTUP;
  1001.                         //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1002.                         increase_speed(b,2);
  1003.                         //ball_cooldown = COOLDOWN_FRAMES;
  1004.                         b->Misc[BALL_MISC_DIR] = DIR_RIGHTUP; break; }
  1005.                     default: { b->Dir = DIR_DOWN; b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED); break; }
  1006.                 }
  1007.             }
  1008.             reposition_hitbox(b);
  1009.         }
  1010.     }
  1011.     void check_rightwall(lweapon b)
  1012.     {
  1013.         if ( caught ) return; //don't do anything while the vaus is holding the ball
  1014.         if ( b->X == BALL_MAX_X )
  1015.         {
  1016.             Game->PlaySound(7);
  1017.             if ( b->Angular && ALLOW_16_ANGLES )
  1018.             {
  1019.                 switch ( b->Misc[BALL_MISC_DIR] )
  1020.                 //switch ( b->Angle )
  1021.                 {
  1022.                     //flip left and right
  1023.                     //left
  1024.                     case DIR_RRU:
  1025.                     {
  1026.                         //++v->X; //not sure if we'll need this bit.
  1027.                         b->Angle = DIR_LLU;
  1028.                         b->Misc[BALL_MISC_DIR] = DIR_LLU;
  1029.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  1030.                         increase_speed(b,2);
  1031.                         //ball_cooldown = COOLDOWN_FRAMES;
  1032.                         break;
  1033.                     }
  1034.                     case DIR_UUR:
  1035.                     {
  1036.                         //++v->X; //not sure if we'll need this bit.
  1037.                         b->Angle = DIR_UUL;
  1038.                         b->Misc[BALL_MISC_DIR] = DIR_UUL;
  1039.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  1040.                         increase_speed(b,2);
  1041.                         //ball_cooldown = COOLDOWN_FRAMES;
  1042.                         break;
  1043.                     }
  1044.                     //right
  1045.                     case DIR_RRD:
  1046.                     {
  1047.                         //++v->X; //not sure if we'll need this bit.
  1048.                         b->Angle = DIR_LLD;
  1049.                         b->Misc[BALL_MISC_DIR] = DIR_LLD;
  1050.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  1051.                         increase_speed(b,2);
  1052.                         //ball_cooldown = COOLDOWN_FRAMES;
  1053.                         break;
  1054.                     }
  1055.                     case DIR_RDD:
  1056.                     {
  1057.                         //++v->X; //not sure if we'll need this bit.
  1058.                         b->Angle = DIR_DDL;
  1059.                         b->Misc[BALL_MISC_DIR] = DIR_DDL;
  1060.                         //b->Step = bound(b->Step+2, 0, MAX_BALL_SPEED);
  1061.                         increase_speed(b,2);
  1062.                         //ball_cooldown = COOLDOWN_FRAMES;
  1063.                         break;
  1064.                     }
  1065.                     default: { TraceNL(); TraceS("check_rightwall() could not determine the angle of an ANgular ball!"); break;}
  1066.                 }
  1067.             }
  1068.             else
  1069.             {
  1070.                 switch(b->Dir)
  1071.                 {
  1072.                     case DIR_RIGHTDOWN: { b->Dir = DIR_LEFTDOWN;
  1073.                         //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1074.                         increase_speed(b,2);
  1075.                         //ball_cooldown = COOLDOWN_FRAMES;
  1076.                         b->Misc[BALL_MISC_DIR] = DIR_LEFTDOWN; break; }
  1077.                     case DIR_RIGHTUP: { b->Dir = DIR_LEFTUP;
  1078.                         //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1079.                         increase_speed(b,2);
  1080.                         //ball_cooldown = COOLDOWN_FRAMES;
  1081.                         b->Misc[BALL_MISC_DIR] = DIR_LEFTUP; break; }
  1082.                     default: { b->Dir = DIR_DOWN; b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED); break; }
  1083.                 }
  1084.             }
  1085.             reposition_hitbox(b);
  1086.         }
  1087.     }
  1088.     void check_hitvaus(lweapon b, ffc v)
  1089.     {
  1090.         int hit_position; int vaus_midpoint =  v->X+(((v->TileWidth*16)/2)-1);
  1091.         int midpoint_segment = v->X+(((v->TileWidth*16)/6));
  1092.         int ball_midpoint = b->X+3;
  1093.         if ( launched(b) )
  1094.         {
  1095.             if ( b->Dir == DIR_RIGHTUP ) return;
  1096.             if ( b->Dir == DIR_LEFTUP ) return;
  1097.             //if ( Collision(b,v) ) //We'll refine this, later.
  1098.            
  1099.             if ( b->Y+4 == v->Y )
  1100.                 //Now we need to check here, if the paddle is under the ball:
  1101.             {
  1102.                 if ( b->X >= v->X-3 ) //-3, because the ball is 4px wide, so we cover the last pixel of the ball against the furst pixel of the Vaus
  1103.                 {
  1104.                     if ( b->X <= v->X+(v->TileWidth*16) ) //no +3 here, because it's the actual X, so the first pixel of the ball is covered by the last pixel of the vaus.
  1105.                     {
  1106.                         Game->PlaySound(6);
  1107.  
  1108.                         if ( ALLOW_16_ANGLES )
  1109.                         {
  1110.                             if ( ball_midpoint <= vaus_midpoint ) //hit left side of vaus
  1111.                             {
  1112.                                 TraceNL(); TraceS("Hit vaus left of midpoint.");
  1113.                                 //divide midpoint into three sections
  1114.                                 if ( ball_midpoint <= (v->X+2) )
  1115.                                 //if ( ball_midpoint <= (v->X+midpoint_segment) )
  1116.                                 {
  1117.                                     //hit the leftmost third, use LLU
  1118.                                     //set angular, then Angle == LLU
  1119.                                     TraceNL(); TraceS("Setting ball dir to ANGULAR Left-Left-Up");
  1120.                                     --b->Y;
  1121.                                     b->Angular = true;
  1122.                                     b->Angle = DIR_LLU;
  1123.                                     b->Misc[BALL_MISC_DIR] = DIR_LLU;
  1124.                                     //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1125.                                     increase_speed(b,2);
  1126.                                     //ball_cooldown = COOLDOWN_FRAMES;
  1127.                                     return;
  1128.                                    
  1129.                                 }
  1130.                                 else if ( ball_midpoint <= (v->X +13) )
  1131.                                 //else if ( ball_midpoint <= (v->X + (midpoint_segment*2)) )
  1132.                                 {
  1133.                                     //hit the centre midpoint
  1134.                                     //set angular = false
  1135.                                     //set DIR_UL
  1136.                                     TraceNL(); TraceS("Setting ball dir to DIGITAL Left-Up");
  1137.                                     --b->Y;
  1138.                                     b->Angular = false;
  1139.                                     b->Dir = DIR_UPLEFT;
  1140.                                     b->Misc[BALL_MISC_DIR] = DIR_LEFTUP;
  1141.                                     //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1142.                                     increase_speed(b,2);
  1143.                                     //ball_cooldown = COOLDOWN_FRAMES;
  1144.                                     return;
  1145.                                 }
  1146.                                 else //hit close to centre
  1147.                                 {
  1148.                                     //set angular true
  1149.                                     //set dir to UUL
  1150.                                     TraceNL(); TraceS("Setting ball dir to ANGULAR Left-Up-Up");
  1151.                                     --b->Y;
  1152.                                     b->Angular = true;
  1153.                                     b->Angle = DIR_LUU;
  1154.                                     b->Misc[BALL_MISC_DIR] = DIR_LUU;
  1155.                                     //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1156.                                     increase_speed(b,2);
  1157.                                     //ball_cooldown = COOLDOWN_FRAMES;
  1158.                                     return;
  1159.                                 }
  1160.                             }
  1161.                             else //if ( ball_midpoint > vaus_midpoint ) //hit right side of vaus
  1162.                             {
  1163.                                 TraceNL(); TraceS("Hit vaus left of midpoint.");
  1164.                                 //divide midpoint into three sections
  1165.                                 if ( ball_midpoint <= (vaus_midpoint+2) )
  1166.                                 //if ( ball_midpoint <= (vaus_midpoint+(midpoint_segment)) )
  1167.                                 {
  1168.                                     //hit close to centre
  1169.                                     //set angular true
  1170.                                     //set dir to UUR
  1171.                                     TraceNL(); TraceS("Setting ball dir to ANGULAR Right-Up-Up");
  1172.                                     --b->Y;
  1173.                                     b->Angular = true;
  1174.                                     b->Angle = DIR_RUU;
  1175.                                     b->Misc[BALL_MISC_DIR] = DIR_RUU;
  1176.                                     //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1177.                                     increase_speed(b,2);
  1178.                                     //ball_cooldown = COOLDOWN_FRAMES;
  1179.                                     return;
  1180.                                    
  1181.                                 }
  1182.                                 else if ( ball_midpoint <= (vaus_midpoint+13) )
  1183.                                 //else if ( ball_midpoint <= (vaus_midpoint+(midpoint_segment*2)) )
  1184.                                 {
  1185.                                     //hit the centre midpoint
  1186.                                     //set angular = false
  1187.                                     //set DIR_UR
  1188.                                     TraceNL(); TraceS("Setting ball dir to DIGITAL Right-Up");
  1189.                                     --b->Y;
  1190.                                     b->Angular = false;
  1191.                                     b->Dir = DIR_UPRIGHT;
  1192.                                     b->Misc[BALL_MISC_DIR] = DIR_UPRIGHT;
  1193.                                     //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1194.                                     increase_speed(b,2);
  1195.                                     //ball_cooldown = COOLDOWN_FRAMES;
  1196.                                     return;
  1197.                                 }
  1198.                                 else //hit close to rightmost edge
  1199.                                 {
  1200.                                     //set angular true
  1201.                                     //set dir to URR
  1202.                                     TraceNL(); TraceS("Setting ball dir to ANGULAR Right-Right--Up");
  1203.                                     --b->Y;
  1204.                                     b->Angular = true;
  1205.                                     b->Angle = DIR_RRU;
  1206.                                     b->Misc[BALL_MISC_DIR] = DIR_RRU;
  1207.                                     //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1208.                                     increase_speed(b,2);
  1209.                                     //ball_cooldown = COOLDOWN_FRAMES;
  1210.                                     return;
  1211.                                 }
  1212.                                
  1213.                             }
  1214.                         }
  1215.                         else
  1216.                         {
  1217.                             if ( ball_midpoint <= vaus_midpoint ) //hit left side of vaus
  1218.                             {
  1219.                                
  1220.                                     //hit the centre midpoint
  1221.                                     //set angular = false
  1222.                                     //set DIR_UL
  1223.                                     TraceNL(); TraceS("Setting ball dir to DIGITAL Left-Up");
  1224.                                     b->Y = v->Y-1;
  1225.                                     b->Angular = false;
  1226.                                     b->Dir = DIR_UPLEFT;
  1227.                                     b->Misc[BALL_MISC_DIR] = DIR_UPLEFT;
  1228.                                     //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1229.                                     increase_speed(b,2);
  1230.                                     //ball_cooldown = COOLDOWN_FRAMES;
  1231.                                     return;
  1232.                                
  1233.                             }
  1234.                             else if ( ball_midpoint > vaus_midpoint ) //hit right side of vaus
  1235.                             {
  1236.                                
  1237.                                     //hit the centre midpoint
  1238.                                     //set angular = false
  1239.                                     //set DIR_UR
  1240.                                     TraceNL(); TraceS("Setting ball dir to DIGITAL Right-Up");
  1241.                                     b->Y = v->Y-6;
  1242.                                     b->Angular = false;
  1243.                                     b->Dir = DIR_UPRIGHT;
  1244.                                     b->Misc[BALL_MISC_DIR] = DIR_UPRIGHT;
  1245.                                     //b->Dir = DIR_UPRIGHT;
  1246.                                     //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1247.                                     increase_speed(b,2);
  1248.                                     //ball_cooldown = COOLDOWN_FRAMES;
  1249.                                     return;
  1250.                                
  1251.                                
  1252.                             }
  1253.                        
  1254.                             else
  1255.                             {
  1256.                                 //failsafe
  1257.                                 switch(b->Dir)
  1258.                                 {
  1259.                                     case DIR_LEFTDOWN: { b->Dir = DIR_LEFTUP;
  1260.                                         //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1261.                                         increase_speed(b,2);
  1262.                                         //ball_cooldown = COOLDOWN_FRAMES;
  1263.                                         b->Misc[BALL_MISC_DIR] = DIR_LEFTDOWN; break; }
  1264.                                     case DIR_RIGHTDOWN: { b->Dir = DIR_RIGHTUP;
  1265.                                         //b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED);
  1266.                                         increase_speed(b,2);
  1267.                                         //ball_cooldown = COOLDOWN_FRAMES;
  1268.                                         b->Misc[BALL_MISC_DIR] = DIR_RIGHTDOWN; break; }
  1269.                                     default: { b->Dir = DIR_DOWN; b->Step = bound(b->Step+1, 0, MAX_BALL_SPEED); break; }
  1270.                                 }
  1271.                             }
  1272.                         }
  1273.                        
  1274.                         reposition_hitbox(b);
  1275.                        
  1276.                        
  1277.                        
  1278.                     }
  1279.                    
  1280.                     else
  1281.                     {
  1282.                         dead(b,v);
  1283.                     }
  1284.                 }
  1285.                 else
  1286.                 {
  1287.                     dead(b,v);
  1288.                 }
  1289.             }
  1290.            
  1291.         }
  1292.     }
  1293.     void dead(lweapon b, ffc v)
  1294.     {
  1295.        
  1296.         Game->PlayMIDI(5);
  1297.         //remove the ball
  1298.         b->Y = -32768; b->Step = 0;
  1299.         v->Misc[MISC_DEAD] = 1;
  1300.         //if there are more balls in play, switch movingball to one of those
  1301.         //otherwise,
  1302.         //check next life
  1303.         //if more lives, reset playfield
  1304.         //otherwise game over
  1305.        
  1306.     }
  1307.    
  1308.    
  1309.    
  1310. }
  1311.  
  1312. ffc script ball_controller
  1313. {
  1314.     void run()
  1315.     {
  1316.         lweapon ball;
  1317.         lweapon active_ball; //will be used for when we have multiple balls.
  1318.         lweapon balls[3]; //for divide
  1319.         ball = Screen->CreateLWeapon(LW_SCRIPT1);
  1320.         ball->X = START_BALL_X;
  1321.         ball->Y = START_BALL_Y;
  1322.         this->Vx = START_BALL_VX;
  1323.         this->Vy = START_BALL_VY;
  1324.         bool alive = true;
  1325.         int num_balls = 1;
  1326.         while(alive)
  1327.         {
  1328.             if ( ball->Y <= BALL_MIN_Y )
  1329.             {
  1330.                 bounce();
  1331.             }
  1332.             if ( ball->X <= BALL_MIN_X )
  1333.             {
  1334.                 bounce();
  1335.             }
  1336.             if ( ball->X >= BALL_MAX_X )
  1337.             {
  1338.                 bounce();
  1339.             }
  1340.                
  1341.             if ( ball->Y >= BALL_MAX_Y )
  1342.             {
  1343.                 if ( num_balls < 2 )
  1344.                 {
  1345.                     alive = false;
  1346.                 }
  1347.                 else
  1348.                 {
  1349.                     kill_ball(ball); //removes this ball, and sets another ball to be the active one
  1350.                     --num_balls;
  1351.                 }
  1352.             }
  1353.             Waitframe();
  1354.         }
  1355.     }
  1356.     void bounce(){}
  1357.     void kill_ball(lweapon b){}
  1358.    
  1359. }
  1360.  
  1361. const int BRICK_MAX = 14;
  1362.  
  1363. //Layer 1
  1364. const int CMB_BRICK_RED     = 1488;
  1365. const int CMB_BRICK_WHITE   = 1490;
  1366. const int CMB_BRICK_BLUE    = 1492;
  1367. const int CMB_BRICK_ORANGE  = 1494;
  1368. const int CMB_BRICK_TEAL    = 1496;
  1369. const int CMB_BRICK_VIOLET  = 1498;
  1370. const int CMB_BRICK_GREEN   = 1500;
  1371. const int CMB_BRICK_YELLOW  = 1502;
  1372. const int CMB_BRICK_SILVER1 = 1504;
  1373. const int CMB_BRICK_SILVER2 = 1506;
  1374. const int CMB_BRICK_SILVER3 = 1508;
  1375. const int CMB_BRICK_SILVER4 = 1510;
  1376. const int CMB_BRICK_GOLD    = 1516;
  1377.  
  1378.  
  1379. //layer 2
  1380. const int CMB_BRICK_RED_LOW     = 1489;
  1381. const int CMB_BRICK_WHITE_LOW   = 1491;
  1382. const int CMB_BRICK_BLUE_LOW    = 1493;
  1383. const int CMB_BRICK_ORANGE_LOW  = 1495;
  1384. const int CMB_BRICK_TEAL_LOW    = 1497;
  1385. const int CMB_BRICK_VIOLET_LOW  = 1499;
  1386. const int CMB_BRICK_GREEN_LOW   = 1501;
  1387. const int CMB_BRICK_YELLOW_LOW  = 1503;
  1388. const int CMB_BRICK_SILVER1_LOW = 1505;
  1389. const int CMB_BRICK_SILVER2_LOW = 1507;
  1390. const int CMB_BRICK_SILVER3_LOW = 1509;
  1391. const int CMB_BRICK_SILVER4_LOW = 1511;
  1392. const int CMB_BRICK_GOLD_LOW    = 1517;
  1393.  
  1394. //enemies
  1395. const int NPC_BRICK_RED     = 181;
  1396. const int NPC_BRICK_WHITE   = 182;
  1397. const int NPC_BRICK_BLUE    = 183;
  1398. const int NPC_BRICK_ORANGE  = 184;
  1399. const int NPC_BRICK_TEAL    = 185;
  1400. const int NPC_BRICK_VIOLET  = 186;
  1401. const int NPC_BRICK_GREEN   = 187;
  1402. const int NPC_BRICK_YELLOW  = 188;
  1403. const int NPC_BRICK_SILVER1     = 189;
  1404. const int NPC_BRICK_SILVER2     = 190;
  1405. const int NPC_BRICK_SILVER3     = 255; //not set up yet;
  1406. const int NPC_BRICK_SILVER4     = 255; //not set up yet
  1407. const int NPC_BRICK_GOLD    = 191;
  1408.  
  1409.  
  1410. const int HIT_BY_LWEAPON = 2;
  1411.  
  1412. ffc script brick
  1413. {
  1414.     void run()
  1415.     {
  1416.     }
  1417.     float bound(int val, int min, int max)
  1418.     {
  1419.         if ( val < min ) return min;
  1420.         if ( val > max ) return max;
  1421.         return val;
  1422.     }
  1423.     bool hit(npc a, lweapon v)
  1424.     {
  1425.         if ( a->HitBy[HIT_BY_LWEAPON] < 1 ) return false;
  1426.         a->Misc[12] = Screen->LoadLWeapon(a->HitBy[HIT_BY_LWEAPON]);
  1427.         lweapon hitwpn = a->Misc[12];
  1428.         return ( hitwpn->UID == v->UID );
  1429.        
  1430.         //int indx; //Until we have UIDs working for HitBy[], we need to do it this way.
  1431.         //for ( int q = Screen->NumLWeapons(); q > 0; --q )
  1432.         //{
  1433.         //  lweapon temp = Screen->LoadLWeapon(q);
  1434.         //  if ( temp->UID == v->UID )
  1435.         //  {
  1436.         //      indx = q; break;
  1437.         //  }
  1438.         //}
  1439.         //Link->Misc[0] = v; //We'll use this as scratch untyped space for the moment. -Z
  1440.         //TraceS("brick.hit() Link->Misc[] is: "); Trace(Link->Misc[0]);
  1441.         //TraceS("brick.hit() v is: "); Trace(v);
  1442.         //int temp_UID = v->UID * 10000; //this is a bug in HITBY[]. The HitBy value being stored is being multiplied by 10000, and it should not be.
  1443.             //as UID is not, and NEVER should be!!!
  1444.         //TraceNL(); TraceS("v->UID is: "); Trace(v->UID);
  1445.         /*
  1446.         To determine where a brick was hit, we first scan each brick and look to see which was
  1447.         hit at all, by our lweapon.
  1448.        
  1449.         The, we check if that ball is belove, above, right of, or left of the brick,
  1450.         and we read its direction.
  1451.        
  1452.         Using a logic chain from this data, we determine the direction that the ball should next
  1453.         take, when it bounces.
  1454.        
  1455.         */
  1456.         //HitBy[]
  1457.        
  1458.         //if ( a->HitBy[HIT_BY_LWEAPON] )
  1459.         //{
  1460.         //  TraceNL(); TraceS("a->HitBy[HIT_BY_LWEAPON] id: "); Trace(a->HitBy[HIT_BY_LWEAPON]);
  1461.         //  TraceNL();
  1462.         //  TraceS("Our Link->Misc scratch value `is: "); Trace((Link->Misc[0]+1));
  1463.         //}
  1464.        
  1465.         //! We'll use this method again when we add UIDs to HitBy[] ! -Z
  1466.         //return ( a->HitBy[HIT_BY_LWEAPON] == temp_UID );
  1467.         //return ( a->HitBy[HIT_BY_LWEAPON] == indx ); //(Link->Misc[0]+1) );
  1468.        
  1469.     }
  1470.     bool hit_below(npc a, lweapon v)
  1471.     {
  1472.         if ( v->Y == (a->Y + 8) ) return true; //we could do bounce here.
  1473.     }
  1474.     bool hit_above(npc a, lweapon v)
  1475.     {
  1476.         if ( v->Y == (a->Y - 4) ) return true; //we could do bounce here.
  1477.     }
  1478.     bool hit_left(npc a, lweapon v)
  1479.     {
  1480.         if ( v->X == (a->X - 4) ) return true; //we could do bounce here.
  1481.     }
  1482.     bool hit_right(npc a, lweapon v)
  1483.     {
  1484.         if ( v->X == (a->X + 16 ) ) return true; //we could do bounce here.
  1485.     }
  1486.    
  1487.     bool take_hit(npc a, lweapon v)
  1488.     {
  1489.         if ( hit(a,v) )
  1490.         {
  1491.             //TraceNL(); TraceS("Brick hit!");
  1492.             v->DeadState = WDS_ALIVE;
  1493.             //TraceNL(); TraceS("brick->X = "); Trace(a->X);
  1494.             //TraceNL(); TraceS("brick->Y = "); Trace(a->Y);
  1495.             //TraceNL(); TraceS("ball->X = "); Trace(v->X);
  1496.             //TraceNL(); TraceS("ball->Y = "); Trace(v->Y);
  1497.             if ( hit_below(a,v) )
  1498.             {
  1499.                 if ( v->Angular )
  1500.                 {
  1501.                     switch ( v->Misc[BALL_MISC_DIR] )
  1502.                     //switch ( v->Angle )
  1503.                     {
  1504.                         //left
  1505.                         case DIR_LLU:
  1506.                         {
  1507.                             //++v->X; //not sure if we'll need this bit.
  1508.                             v->Angle = DIR_LLD;
  1509.                             v->Misc[BALL_MISC_DIR] = DIR_LLD;
  1510.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1511.                             ball.increase_speed(v,2);
  1512.                             ball_cooldown = COOLDOWN_FRAMES;
  1513.                             break;
  1514.                         }
  1515.                         case DIR_UUL:
  1516.                         {
  1517.                             //++v->X; //not sure if we'll need this bit.
  1518.                             v->Angle = DIR_DDL;
  1519.                             v->Misc[BALL_MISC_DIR] = DIR_DDL;
  1520.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1521.                             ball.increase_speed(v,2);
  1522.                             ball_cooldown = COOLDOWN_FRAMES;
  1523.                             break;
  1524.                         }
  1525.                         //right
  1526.                         case DIR_RRU:
  1527.                         {
  1528.                             //++v->X; //not sure if we'll need this bit.
  1529.                             v->Angle = DIR_RRD;
  1530.                             v->Misc[BALL_MISC_DIR] = DIR_RRD;
  1531.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1532.                             ball.increase_speed(v,2);
  1533.                             ball_cooldown = COOLDOWN_FRAMES;
  1534.                             break;
  1535.                         }
  1536.                         case DIR_RUU:
  1537.                         {
  1538.                             //++v->X; //not sure if we'll need this bit.
  1539.                             v->Angle = DIR_DDR;
  1540.                             v->Misc[BALL_MISC_DIR] = DIR_DDR;
  1541.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1542.                             ball.increase_speed(v,2);
  1543.                             ball_cooldown = COOLDOWN_FRAMES;
  1544.                             break;
  1545.                         }
  1546.                         default: { TraceNL(); TraceS("hit_below() could not determine the angle of an ANgular ball!"); break;}
  1547.                     }
  1548.                 }
  1549.                    
  1550.                 else
  1551.                 {
  1552.                     switch(v->Dir)
  1553.                     {
  1554.                         case DIR_UPRIGHT: { v->Dir = DIR_DOWNRIGHT;
  1555.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1556.                             ball.increase_speed(v,2);
  1557.                             ball_cooldown = COOLDOWN_FRAMES;
  1558.                             v->Misc[BALL_MISC_DIR] = DIR_UPRIGHT; break; }
  1559.                         case DIR_UPLEFT: { v->Dir = DIR_DOWNLEFT;
  1560.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1561.                             ball.increase_speed(v,2);
  1562.                             ball_cooldown = COOLDOWN_FRAMES;
  1563.                             v->Misc[BALL_MISC_DIR] = DIR_UPLEFT; break; }
  1564.                         default: { TraceS("hit_below() found an illegal ball direction"); break; }
  1565.                     }
  1566.                 }
  1567.                
  1568.                 if ( a->HP <= 0 )
  1569.                 {
  1570.                     //TraceS("Brick is dead. "); TraceNL();
  1571.                     //TraceS("a->Misc[NPCM_AWARDED_POINTS] is: "); Trace(a->Misc[NPCM_AWARDED_POINTS]); TraceNL();
  1572.                     if ( !a->Misc[NPCM_AWARDED_POINTS] )
  1573.                     {
  1574.                         //TraceS("Can award points!"); TraceNL();
  1575.                         a->Misc[18] = 1;
  1576.                         //TraceS("The points for this brick are: "); Trace(a->Attributes[NPC_ATTRIB_POINTS]); TraceNL();
  1577.                         Game->Counter[CR_SCRIPT1] += a->Attributes[NPC_ATTRIB_POINTS];
  1578.                     }
  1579.                 }
  1580.             }
  1581.            
  1582.             else if ( hit_above(a,v) )
  1583.             {
  1584.                 if ( v->Angular )
  1585.                 {
  1586.                     switch ( v->Misc[BALL_MISC_DIR] )
  1587.                     //switch ( v->Angle )
  1588.                     {
  1589.                         //left
  1590.                         case DIR_LLD:
  1591.                         {
  1592.                             //++v->X; //not sure if we'll need this bit.
  1593.                             v->Angle = DIR_LLU;
  1594.                             v->Misc[BALL_MISC_DIR] = DIR_LLU;
  1595.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1596.                             ball.increase_speed(v,2);
  1597.                             ball_cooldown = COOLDOWN_FRAMES;
  1598.                             break;
  1599.                         }
  1600.                         case DIR_DDL:
  1601.                         {
  1602.                             //++v->X; //not sure if we'll need this bit.
  1603.                             v->Angle = DIR_UUL;
  1604.                             v->Misc[BALL_MISC_DIR] = DIR_UUL;
  1605.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1606.                             ball.increase_speed(v,2);
  1607.                             ball_cooldown = COOLDOWN_FRAMES;
  1608.                             break;
  1609.                         }
  1610.                         //right
  1611.                         case DIR_RRD:
  1612.                         {
  1613.                             //++v->X; //not sure if we'll need this bit.
  1614.                             v->Angle = DIR_RRU;
  1615.                             v->Misc[BALL_MISC_DIR] = DIR_RRU;
  1616.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1617.                             ball.increase_speed(v,2);
  1618.                             ball_cooldown = COOLDOWN_FRAMES;
  1619.                             break;
  1620.                         }
  1621.                         case DIR_RDD:
  1622.                         {
  1623.                             //++v->X; //not sure if we'll need this bit.
  1624.                             v->Angle = DIR_UUR;
  1625.                             v->Misc[BALL_MISC_DIR] = DIR_UUR;
  1626.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1627.                             ball.increase_speed(v,2);
  1628.                             ball_cooldown = COOLDOWN_FRAMES;
  1629.                             break;
  1630.                         }
  1631.                         default: { TraceNL(); TraceS("hit_above() could not determine the angle of an ANgular ball!"); break;}
  1632.                     }
  1633.                 }
  1634.                 else
  1635.                 {
  1636.                     switch ( v->Dir )
  1637.                     {
  1638.                         case DIR_DOWNLEFT: { v->Dir = DIR_UPLEFT;
  1639.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1640.                             ball.increase_speed(v,2);
  1641.                             ball_cooldown = COOLDOWN_FRAMES;
  1642.                             v->Misc[BALL_MISC_DIR] = DIR_DOWNLEFT; break; }
  1643.                         case DIR_DOWNRIGHT: { v->Dir = DIR_UPRIGHT;
  1644.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1645.                             ball.increase_speed(v,2);
  1646.                             ball_cooldown = COOLDOWN_FRAMES;
  1647.                             v->Misc[BALL_MISC_DIR] = DIR_DOWNRIGHT; break; }
  1648.                         default: { TraceS("hit_above() found an illegal ball direction"); break; }
  1649.                     }
  1650.                 }
  1651.                 if ( a->HP <= 0 )
  1652.                 {
  1653.                     if ( !a->Misc[NPCM_AWARDED_POINTS] )
  1654.                     {
  1655.                         a->Misc[NPCM_AWARDED_POINTS] = 1;
  1656.                         Game->Counter[CR_SCRIPT1] += a->Attributes[NPC_ATTRIB_POINTS];
  1657.                     }
  1658.                 }
  1659.             }
  1660.            
  1661.             else if ( hit_left(a,v) )
  1662.             {
  1663.                 if ( v->Angular )
  1664.                 {
  1665.                     //switch ( v->Angle )
  1666.                     switch ( v->Misc[BALL_MISC_DIR] )
  1667.                     {
  1668.                         //flip left-right
  1669.                         //left
  1670.                         case DIR_RRD:
  1671.                         {
  1672.                             //++v->X; //not sure if we'll need this bit.
  1673.                             v->Angle = DIR_LLD;
  1674.                             v->Misc[BALL_MISC_DIR] = DIR_LLD;
  1675.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1676.                             ball.increase_speed(v,2);
  1677.                             ball_cooldown = COOLDOWN_FRAMES;
  1678.                             break;
  1679.                         }
  1680.                         case DIR_DDR:
  1681.                         {
  1682.                             //++v->X; //not sure if we'll need this bit.
  1683.                             v->Angle = DIR_DDL;
  1684.                             v->Misc[BALL_MISC_DIR] = DIR_DDL;
  1685.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1686.                             ball.increase_speed(v,2);
  1687.                             ball_cooldown = COOLDOWN_FRAMES;
  1688.                             break;
  1689.                         }
  1690.                         //right
  1691.                         case DIR_RRU:
  1692.                         {
  1693.                             //++v->X; //not sure if we'll need this bit.
  1694.                             v->Angle = DIR_LLU;
  1695.                             v->Misc[BALL_MISC_DIR] = DIR_LLU;
  1696.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1697.                             ball.increase_speed(v,2);
  1698.                             ball_cooldown = COOLDOWN_FRAMES;
  1699.                             break;
  1700.                         }
  1701.                         case DIR_UUR:
  1702.                         {
  1703.                             //++v->X; //not sure if we'll need this bit.
  1704.                             v->Angle = DIR_UUL;
  1705.                             v->Misc[BALL_MISC_DIR] = DIR_UUL;
  1706.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1707.                             ball.increase_speed(v,2);
  1708.                             ball_cooldown = COOLDOWN_FRAMES;
  1709.                             break;
  1710.                         }
  1711.                         default: { TraceNL(); TraceS("hit_above() could not determine the angle of an ANgular ball!"); break;}
  1712.                     }
  1713.                 }
  1714.                 else
  1715.                 {
  1716.                     switch ( v->Dir )
  1717.                     {
  1718.                         case DIR_UPRIGHT: { v->Dir = DIR_UPLEFT;
  1719.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1720.                             ball.increase_speed(v,2);
  1721.                             ball_cooldown = COOLDOWN_FRAMES;
  1722.                             v->Misc[BALL_MISC_DIR] = DIR_UPRIGHT; break; }
  1723.                         case DIR_DOWNRIGHT: { v->Dir = DIR_DOWNLEFT;
  1724.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1725.                             ball.increase_speed(v,2);
  1726.                             ball_cooldown = COOLDOWN_FRAMES;
  1727.                             v->Misc[BALL_MISC_DIR] = DIR_DOWNRIGHT; break; }
  1728.                         default: { TraceS("hit_left() found an illegal ball direction"); break; }
  1729.                     }
  1730.                 }
  1731.                 if ( a->HP <= 0 )
  1732.                 {
  1733.                     if ( !a->Misc[NPCM_AWARDED_POINTS] )
  1734.                     {
  1735.                         a->Misc[NPCM_AWARDED_POINTS] = 1;
  1736.                         Game->Counter[CR_SCRIPT1] += a->Attributes[NPC_ATTRIB_POINTS];
  1737.                     }
  1738.                 }
  1739.             }
  1740.             else if ( hit_right(a,v) )
  1741.             {
  1742.                 if ( v->Angular )
  1743.                 {
  1744.                     switch ( v->Misc[BALL_MISC_DIR] )
  1745.                     //switch ( v->Angle )
  1746.                     {
  1747.                         //flip left-right
  1748.                         //left
  1749.                         case DIR_LLD:
  1750.                         {
  1751.                             //++v->X; //not sure if we'll need this bit.
  1752.                             v->Angle = DIR_RRD;
  1753.                             v->Misc[BALL_MISC_DIR] = DIR_RRD;
  1754.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1755.                             ball.increase_speed(v,2);
  1756.                             ball_cooldown = COOLDOWN_FRAMES;
  1757.                             break;
  1758.                         }
  1759.                         case DIR_DDL:
  1760.                         {
  1761.                             //++v->X; //not sure if we'll need this bit.
  1762.                             v->Angle = DIR_DDR;
  1763.                             v->Misc[BALL_MISC_DIR] = DIR_DDR;
  1764.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1765.                             ball.increase_speed(v,2);
  1766.                             ball_cooldown = COOLDOWN_FRAMES;
  1767.                             break;
  1768.                         }
  1769.                         //right
  1770.                         case DIR_LLU:
  1771.                         {
  1772.                             //++v->X; //not sure if we'll need this bit.
  1773.                             v->Angle = DIR_RRU;
  1774.                             v->Misc[BALL_MISC_DIR] = DIR_RRU;
  1775.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1776.                             ball.increase_speed(v,2);
  1777.                             ball_cooldown = COOLDOWN_FRAMES;
  1778.                             break;
  1779.                         }
  1780.                         case DIR_UUL:
  1781.                         {
  1782.                             //++v->X; //not sure if we'll need this bit.
  1783.                             v->Angle = DIR_UUR;
  1784.                             v->Misc[BALL_MISC_DIR] = DIR_UUR;
  1785.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1786.                             ball.increase_speed(v,2);
  1787.                             ball_cooldown = COOLDOWN_FRAMES;
  1788.                             break;
  1789.                         }
  1790.                         default: { TraceNL(); TraceS("hit_above() could not determine the angle of an ANgular ball!"); break;}
  1791.                     }
  1792.                 }
  1793.                 else
  1794.                 {
  1795.                     switch ( v->Dir )
  1796.                     {
  1797.                         case DIR_UPLEFT: { v->Dir = DIR_UPRIGHT;
  1798.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1799.                             ball.increase_speed(v,2);
  1800.                             ball_cooldown = COOLDOWN_FRAMES;
  1801.                             v->Misc[BALL_MISC_DIR] = DIR_UPLEFT; break; }
  1802.                         case DIR_DOWNLEFT: { v->Dir = DIR_DOWNRIGHT;
  1803.                             //v->Step = bound(v->Step+2, 0, MAX_BALL_SPEED);
  1804.                             ball.increase_speed(v,2);
  1805.                             ball_cooldown = COOLDOWN_FRAMES;
  1806.                             v->Misc[BALL_MISC_DIR] = DIR_DOWNLEFT; break; }
  1807.                         default: { TraceS("hit_below() found an illegal ball direction"); break; }
  1808.                     }
  1809.                 }
  1810.                 if ( a->HP <= 0 )
  1811.                 {
  1812.                     if ( !a->Misc[NPCM_AWARDED_POINTS] )
  1813.                     {
  1814.                         a->Misc[NPCM_AWARDED_POINTS] = 1;
  1815.                         Game->Counter[CR_SCRIPT1] += a->Attributes[NPC_ATTRIB_POINTS];
  1816.                     }
  1817.                 }
  1818.             }
  1819.            
  1820.             else
  1821.             {
  1822.                 TraceS("brick.hit() returned true, but couldn't determine a valid ball location!");
  1823.                 return false;
  1824.             }
  1825.             //must_repos_hitbox = true;
  1826.             ball.reposition_hitbox(v);
  1827.             return true;
  1828.         }
  1829.         return false;
  1830.                    
  1831.            
  1832.     }
  1833.     //turns layer objects into npc bricks.
  1834.     void setup()
  1835.     {
  1836.         int tempenem; npc bricks[1024]; int temp;
  1837.         for ( int q = 0; q < 176; ++q )
  1838.         {
  1839.             //bricks on layer 1
  1840.             //Trace(GetLayerComboD(1,q));
  1841.             //while(!Input->Press[CB_A]) Waitframe();
  1842.             tempenem = brick_to_npc(GetLayerComboD(1,q),false);
  1843.             //TraceS("tempenem is: "); Trace(tempenem);
  1844.             //while(!Input->Press[CB_A]) Waitframe();
  1845.             if ( tempenem )
  1846.             {
  1847.                 bricks[temp] = Screen->CreateNPC(tempenem);
  1848.                 //TraceS("Created npc: "); Trace(tempenem);
  1849.                 bricks[temp]->X = ComboX(q);
  1850.                 bricks[temp]->Y = ComboY(q);
  1851.                 TraceS("Brick defence is: "); Trace(bricks[temp]->Defense[20]);
  1852.                 tempenem = 0; ++temp;
  1853.                
  1854.             }
  1855.             //bricks on layer 2, Y+8px
  1856.             tempenem = brick_to_npc(GetLayerComboD(2,q),true);
  1857.             //Trace(tempenem);
  1858.             if ( tempenem )
  1859.             {
  1860.                 bricks[temp] = Screen->CreateNPC(tempenem);
  1861.                 //TraceS("Created npc: "); Trace(tempenem);
  1862.                 bricks[temp]->X = ComboX(q);
  1863.                 bricks[temp]->Y = ComboY(q)+8;
  1864.                 TraceS("Brick defence is: "); Trace(bricks[temp]->Defense[20]);
  1865.                 tempenem = 0; ++temp;
  1866.             }
  1867.         }
  1868.        
  1869.     }
  1870.     void clear_combos()
  1871.     {
  1872.         templayer[0] = Screen->LayerOpacity[0];
  1873.         templayer[1] = Screen->LayerOpacity[1];
  1874.         templayer[2] = Screen->LayerMap[0];
  1875.         templayer[3] = Screen->LayerMap[1];
  1876.         Screen->LayerOpacity[0] = 0;
  1877.         Screen->LayerOpacity[1] = 0;
  1878.         Screen->LayerMap[0] = 0;
  1879.         Screen->LayerMap[1] = 0;
  1880.     }
  1881.    
  1882.     int brick_to_npc(int combo_id, bool layer2)
  1883.     {
  1884.        
  1885.         if ( !layer2 )
  1886.         {
  1887.             int brick_to_enemy[BRICK_MAX*2] =
  1888.             {   CMB_BRICK_RED, CMB_BRICK_WHITE, CMB_BRICK_BLUE, CMB_BRICK_ORANGE, CMB_BRICK_TEAL,
  1889.                 CMB_BRICK_VIOLET, CMB_BRICK_GREEN, CMB_BRICK_YELLOW, CMB_BRICK_SILVER1, CMB_BRICK_SILVER2,
  1890.                 CMB_BRICK_SILVER3, CMB_BRICK_SILVER4, CMB_BRICK_GOLD,
  1891.  
  1892.                 NPC_BRICK_RED, NPC_BRICK_WHITE, NPC_BRICK_BLUE, NPC_BRICK_ORANGE, NPC_BRICK_TEAL,
  1893.                 NPC_BRICK_VIOLET, NPC_BRICK_GREEN, NPC_BRICK_YELLOW, NPC_BRICK_SILVER1, NPC_BRICK_SILVER2,
  1894.                 NPC_BRICK_SILVER3, NPC_BRICK_SILVER4, NPC_BRICK_GOLD
  1895.             };
  1896.             for ( int q = 0; q < BRICK_MAX; ++q )
  1897.             {
  1898.                 if ( brick_to_enemy[q] == combo_id )
  1899.                 {
  1900.                     //  TraceS("brick_to_npc : combo input: "); Trace(combo_id);
  1901.                     //TraceS("brick_to_npc : enemy output: "); Trace(brick_to_enemy[BRICK_MAX+q]);
  1902.                    
  1903.                     return ( brick_to_enemy[BRICK_MAX+q-1] );
  1904.                 }
  1905.             }
  1906.         }
  1907.         else
  1908.         {
  1909.             int brick_to_enemy2[BRICK_MAX*2] =
  1910.             {   CMB_BRICK_RED_LOW, CMB_BRICK_WHITE_LOW, CMB_BRICK_BLUE_LOW, CMB_BRICK_ORANGE_LOW, CMB_BRICK_TEAL_LOW,
  1911.                 CMB_BRICK_VIOLET_LOW, CMB_BRICK_GREEN_LOW, CMB_BRICK_YELLOW_LOW, CMB_BRICK_SILVER1_LOW, CMB_BRICK_SILVER2_LOW,
  1912.                 CMB_BRICK_SILVER3_LOW, CMB_BRICK_SILVER4_LOW, CMB_BRICK_GOLD_LOW,
  1913.  
  1914.                 NPC_BRICK_RED, NPC_BRICK_WHITE, NPC_BRICK_BLUE, NPC_BRICK_ORANGE, NPC_BRICK_TEAL,
  1915.                 NPC_BRICK_VIOLET, NPC_BRICK_GREEN, NPC_BRICK_YELLOW, NPC_BRICK_SILVER1, NPC_BRICK_SILVER2,
  1916.                 NPC_BRICK_SILVER3, NPC_BRICK_SILVER4, NPC_BRICK_GOLD
  1917.             };
  1918.             for ( int q = 0; q < BRICK_MAX; ++q )
  1919.             {
  1920.                 if ( brick_to_enemy2[q] == combo_id )
  1921.                 {
  1922.                     //TraceS("brick_to_npc : combo input: "); Trace(combo_id);
  1923.                     //TraceS("brick_to_npc : enemy output: "); Trace(brick_to_enemy2[BRICK_MAX+q-1]);
  1924.                     return ( brick_to_enemy2[BRICK_MAX+q-1] );
  1925.                 }
  1926.             }
  1927.         }
  1928.         return 0; //error
  1929.     }
  1930. }
  1931.  
  1932. global script onExit
  1933. {
  1934.     void run()
  1935.     {
  1936.         Screen->LayerOpacity[0] = templayer[0];
  1937.         Screen->LayerOpacity[1] = templayer[1];
  1938.         Screen->LayerMap[0] = templayer[2];
  1939.         Screen->LayerMap[1] = templayer[3];
  1940.         newstage = true;
  1941.         //vaus->Misc[MISC_DEAD] = 0;
  1942.  
  1943.     }
  1944. }  
  1945.  
  1946. global script init
  1947. {
  1948.     void run()
  1949.     {
  1950.         quit = 0;
  1951.         frame = -1;
  1952.         ball_cooldown = -1;
  1953.         Game->Counter[CR_LIVES] = 5;
  1954.         Link->CollDetection = false;
  1955.         Link->DrawYOffset = -32768;
  1956.     }
  1957. }
  1958.  
  1959. global script Init
  1960. {
  1961.     void run()
  1962.     {
  1963.         quit = 0;
  1964.         frame = -1;
  1965.         ball_cooldown = -1;
  1966.         Game->Counter[CR_LIVES] = 5;
  1967.         Link->CollDetection = false;
  1968.         Link->DrawYOffset = -32768;
  1969.     }
  1970. }
  1971.  
  1972. global script onContinue
  1973. {
  1974.     void run()
  1975.     {
  1976.         quit = 0;
  1977.         frame = -1;
  1978.         ball_cooldown = -1;
  1979.         Game->Counter[CR_LIVES] = 5;
  1980.         Link->Invisible = true;
  1981.         Link->CollDetection = false;
  1982.         Link->DrawYOffset = -32768;
  1983.     }
  1984. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×