ZoriaRPG

Arkanoid (Alpha 11)

Aug 15th, 2018
50
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import "std.zh"
  2. //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
  3. //the ball is still not yet inside that object
  4. //Note: We also need to store the UID of each ball, as HitBy[] works from the UID, not the pointer.
  5.  
  6. //# QUEST ISSUE: Bricks Break playing the wrong sound, despite being set. Might be a 2.54 bug? -Z
  7.  
  8. /* ZC issues: I forgot to expand ->Misc[] in sprite.cpp, which should be fixed int he source for Alpha 32.
  9.     This meant that r/w to ptr->Misc[>15] would use invalid data, or overwrite other data. bad, bad, bad.
  10.    
  11.     Continue script does not run when Init script runs. It NEEDS to do that! Otherwise, settings that affect things such as Link's tile
  12.     don't happen before the opening wipe.
  13.    
  14.     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...
  15.     In fact, the only reason that using HitBy[UID] worked, was because my object 9the ball_ was *both* UID1 and LW1. :D
  16.    
  17. */
  18.  
  19. //Arkanoid script
  20. //v0.11
  21. //15th August, 2018
  22.  
  23. const int FFC_VAUS = 1;
  24. const int CMB_VAUS_EXTENDED = 1528;
  25. const int CMB_VAUS = 1524;
  26. const int CMB_VAUS_DEAD = 1520;
  27.  
  28. const int MID_STAGE_START = 4;
  29. const int NPCM_AWARDED_POINTS = 3; //brick->Misc[], flag to mark if points were awarded to the player.
  30. const int NPC_ATTRIB_POINTS = 0; //brick->Attributes[], value for score.
  31.  
  32. int quit;
  33. int caught;
  34. int frame;
  35. bool newstage = true;
  36. bool revive_vaus = false;
  37.  
  38. int ball_x;
  39. int ball_y;
  40. int ball_dir;
  41. int ball_angle;
  42. int ball_speed;
  43. int ball_vx;
  44. int ball_vy;
  45. int paddle_x;
  46. int paddle_y;
  47. int paddle_width = 16;
  48. int paddle_speed = 2;
  49. int extended;
  50.  
  51. int ball_uid;
  52.  
  53. //animation
  54. int death_frame;
  55.  
  56. int templayer[4];
  57.  
  58. int input_accel; //pressing left and right for multiple frames increases this
  59. int frames_pressed[18];
  60.  
  61. //ffc paddle;
  62.  
  63. int hit_zones[5]; //angle offsets for where the ball strikes the paddle
  64.  
  65. const int WALL_LEFT = 24;
  66. const int WALL_TOP = 8; //Mix Ball Y
  67. const int WALL_RIGHT = 232;
  68.  
  69. const int BALL_MIN_Y = 9; //ceiling +1
  70. const int BALL_MAX_Y = 145; //one pixel under paddle top
  71. const int BALL_MIN_X = 25; //left wall +1
  72. const int BALL_MAX_X = 229; //right wall -1
  73.  
  74.  
  75.  
  76. const int START_PADDLE_X = 62;
  77. const int START_PADDLE_Y = 160;
  78. const int START_PADDLE_WIDTH = 32;
  79. const int START_PADDLE_HEIGHT = 8;
  80. const int BALL_WIDTH = 4;
  81. const int BALL_HEIGHT = 4;
  82. const int START_BALL_X = 98; //(START_PADDLE_X + 36);
  83. const int START_BALL_Y = 156; //START_PADDLE_Y - 4;
  84. const int START_BALL_DIR = 5; //DIR_UPRIGHT;
  85. const int START_BALL_RADS = 220; //angle in radians
  86. const int START_BALL_SPEED = 45;
  87. const int START_BALL_VX = 0;
  88. const int START_BALL_VY = 0;
  89.  
  90. const int PADDLE_MIN_X = 25;
  91. const int PADDLE_MAX_X = 200; //WALL_RIGHT -32; //This one varies as the paddle width may change.
  92. const int PADDLE_MAX_X_EXTENDED = 184; //WALL_RIGHT - 48; //This one varies as the paddle width may change.
  93. const int PADDLE_MIN_X_EXTENDED = 25;
  94.  
  95. const int _MOUSE_X = 0;
  96. const int _MOUSE_Y = 1;
  97. const int _MOUSE_LCLICK = 2;
  98.  
  99. //const float ACCEL_FACTOR = 0.25;
  100.  
  101. const int FRAMES_PER_MOVEMENT = 10;
  102. int USE_ACCEL = 0; //Do we accelerate KB/JP input?
  103. int USE_MOUSE = 0; //Are we using the mouse?
  104.  
  105.  
  106. /*
  107. const int CB_UP     = 0;
  108. const int CB_DOWN   = 1;
  109. const int CB_LEFT   = 2;
  110. const int CB_RIGHT  = 3;
  111. const int CB_A      = 4;
  112. const int CB_B      = 5;
  113. const int CB_L      = 7;
  114. const int CB_R      = 8;
  115. const int CB_START  = 6;
  116. const int CB_MAP    = 9;
  117. const int CB_EX1    = 10;
  118. const int CB_EX2    = 11;
  119. const int CB_EX3    = 12;
  120. const int CB_EX4    = 13;
  121. const int CB_AXIS_UP    = 14;
  122. const int CB_AXIS_DOWN  = 15;
  123. const int CB_AXIS_LEFT  = 16;
  124. const int CB_AXIS_RIGHT = 17;
  125.  
  126. */
  127.  
  128. ffc script paddle
  129. {
  130.     void run(){}
  131.    
  132.     bool move(bool mouse, bool accel, ffc p)
  133.     {
  134.         int dir; int dist;
  135.         if ( mouse )
  136.         {
  137.             //get the mouse movement this frame and apply a relative amount to the paddle
  138.             //set the dir here
  139.             //set the dist here
  140.             //if moving left
  141.             //if ( p->X > PADDLE_MIN_X )
  142.             //{
  143.             //  p->X = Input->Mouse[_MOUSE_X];
  144.                 //apply change -- ZC has no special mouse tracking.
  145.             //}
  146.             //if moving right
  147.             if ( !extended )
  148.             {
  149.                 if ( Input->Mouse[_MOUSE_X] <= PADDLE_MAX_X )
  150.                 {
  151.                     if ( Input->Mouse[_MOUSE_X] >= PADDLE_MIN_X )
  152.                     {
  153.                         //apply change
  154.                         p->X = Input->Mouse[_MOUSE_X];
  155.                     }
  156.                 }
  157.             }
  158.             else
  159.             {
  160.                 if ( Input->Mouse[_MOUSE_X] <= PADDLE_MAX_X_EXTENDED )
  161.                 {
  162.                     if ( Input->Mouse[_MOUSE_X] >= PADDLE_MIN_X_EXTENDED )
  163.                     {
  164.                         //apply change
  165.                         p->X = Input->Mouse[_MOUSE_X];
  166.                     }
  167.                 }
  168.             }
  169.         }
  170.         else //using a KB or joypad
  171.         {
  172.             //check how long the dir button is held
  173.             if ( accel ) //if we allow acceleratiopn, move N pixeld * accel factor * frames held
  174.             {
  175.                
  176.                 if ( !extended )
  177.                 {
  178.                     if (  Input->Button[CB_LEFT] )
  179.                     {
  180.                         for ( int q = frames_pressed[CB_LEFT]; q > 0 ; --q )
  181.                         {
  182.                             if ( p->X > PADDLE_MIN_X )
  183.                             {
  184.                                 --p->X;
  185.                                 --p->X;
  186.                             }
  187.                         }
  188.                     }
  189.                     if (  Input->Button[CB_RIGHT] )
  190.                     {
  191.                         for ( int q = frames_pressed[CB_RIGHT]; q > 0; --q )
  192.                         {
  193.                             if ( p->X < PADDLE_MAX_X )
  194.                             {
  195.                                 ++p->X;
  196.                             }
  197.                         }
  198.                     }
  199.                 }
  200.                
  201.             }
  202.            
  203.             else //no accel offered, move a static number of pixels
  204.             {
  205.                
  206.                 if ( !extended )
  207.                 {
  208.                     if (  Input->Button[CB_LEFT] )
  209.                     {
  210.                         for ( int q = 0; q < paddle_speed; ++q )
  211.                         {
  212.                             if ( p->X > PADDLE_MIN_X )
  213.                             {
  214.                                 --p->X;
  215.                             }
  216.                         }
  217.                     }
  218.                     if (  Input->Button[CB_RIGHT] )
  219.                     {
  220.                         for ( int q = 0; q < paddle_speed; ++q )
  221.                         {
  222.                             if ( p->X < PADDLE_MAX_X )
  223.                             {
  224.                                 ++p->X;
  225.                             }
  226.                         }
  227.                     }
  228.                 }
  229.                 else
  230.                 {
  231.                     if (  Input->Button[CB_LEFT] )
  232.                     {
  233.                         if ( p->X > PADDLE_MIN_X_EXTENDED )
  234.                         {
  235.                             --p->X;
  236.                         }
  237.                     }
  238.                     if (  Input->Button[CB_RIGHT] ) {
  239.                         if ( p->X < PADDLE_MAX_X_EXTENDED )
  240.                         {
  241.                             ++p->X;
  242.                         }
  243.                     }
  244.                    
  245.                 }
  246.             }
  247.         }
  248.        
  249.     }
  250.  
  251.     void check_input()
  252.     {
  253.         if ( Input->Button[CB_LEFT] ) ++frames_pressed[CB_LEFT];
  254.         else frames_pressed[CB_LEFT] = 0;
  255.         if ( Input->Button[CB_RIGHT] ) ++frames_pressed[CB_RIGHT];
  256.         else frames_pressed[CB_RIGHT] = 0;
  257.        
  258.     }
  259.    
  260.     void extend(ffc p)
  261.     {
  262.         if ( extended )
  263.         {
  264.             if ( p->TileWidth < 3 )
  265.             {
  266.                 p->Data = CMB_VAUS_EXTENDED;
  267.                 p->TileWidth = 3;
  268.             }
  269.         }
  270.         else
  271.         {
  272.             if ( p->TileWidth > 2 )
  273.             {
  274.                 p->Data = CMB_VAUS;
  275.                 p->TileWidth = 2;
  276.             }
  277.         }
  278.     }
  279.     void setup(ffc p)
  280.     {
  281.         p->Y = START_PADDLE_Y;
  282.         p->X = START_PADDLE_X;
  283.         p->Data = CMB_VAUS;
  284.         p->TileWidth = 2;
  285.        
  286.     }
  287.     void dead(ffc p)
  288.     {
  289.         p->Data = CMB_VAUS_DEAD;
  290.         p->TileWidth = 2;
  291.         death_frame = frame;
  292.     }
  293.    
  294.  
  295. }
  296.  
  297. const int MISC_BALLID = 0; //Misc index of Vaud->Misc[]
  298. const int MISC_DEAD = 1; //Misc index of Vaud->Misc[]
  299. const int MISC_LAUNCHED = 0; //Misc index of ball->Misc[]
  300.  
  301. const int BALL_MINIMUM_Y = 24; //Invisible line at which point, ball is lost.
  302. global script arkanoid
  303. {
  304.    
  305.     void run()
  306.     {
  307.         quit = -1;
  308.         frame = -1;
  309.         ffc vaus = Screen->LoadFFC(FFC_VAUS);
  310.         lweapon movingball;
  311.         bool ext;
  312.         Link->CollDetection = false;
  313.         Link->DrawYOffset = -32768;
  314.         Trace(quit);
  315.         ball.setup_sprite(SPR_BALL);
  316.         while(true)
  317.         {
  318.             //TraceS("Starting Arkanoid");
  319.             ++frame;
  320.             hold_Link();
  321.             if ( newstage )
  322.             {
  323.                 Game->PlayMIDI(MID_STAGE_START);
  324.                 brick.setup();
  325.                 Waitframes(6);
  326.                
  327.                 brick.clear_combos();
  328.                
  329.                 newstage = false;
  330.                 paddle.setup(vaus);
  331.                 ball.create(vaus);
  332.                 movingball = vaus->Misc[MISC_BALLID];
  333.             }
  334.             if ( revive_vaus ) //when this is called, the ball breaks through all bricks. Something isn't being set.
  335.             {
  336.                 Game->PlayMIDI(MID_STAGE_START);
  337.                 vaus->Misc[MISC_DEAD] = 0;
  338.                 revive_vaus = false;
  339.                 paddle.setup(vaus);
  340.                 ball.create(vaus);
  341.                 movingball = vaus->Misc[MISC_BALLID];
  342.             }
  343.            
  344.             if ( !vaus->Misc[MISC_DEAD] )
  345.             {
  346.                 if ( Input->Key[KEY_P] ) Trace(movingball->UID); //Frick, I'm an idiot. HIT_BY_LWEAPON is the SCREEN INDEX< not the UID!!
  347.                     //2.54 Absolutely needs HitBy_UID!
  348.                 change_setting(); //check for a setting change_setting
  349.                 paddle.extend(vaus);
  350.                 paddle.check_input();
  351.                 paddle.move(USE_MOUSE, USE_ACCEL, vaus);
  352.                
  353.                 ball.launch(movingball);
  354.                 if ( !ball.launched(movingball) )
  355.                 {
  356.                     ball.move_with_vaus(movingball, vaus);
  357.                 }
  358.                
  359.                 ball.check_ceiling(movingball);
  360.                 ball.check_leftwall(movingball);
  361.                 ball.check_rightwall(movingball);
  362.                 ball.check_hitvaus(movingball, vaus);
  363.                 /*
  364.                
  365.                 I moved this to after Waitdraw, because I wanted the post-draw timing for ball bounce, and to ensure that
  366.                 the movingball lweapon stayed alive. -Z (Alpha 0.10)
  367.                 //Bounce ball on bricks.
  368.                 for ( int q = Screen->NumNPCs(); q > 0; --q )
  369.                 {
  370.                     npc b = Screen->LoadNPC(q);
  371.                     if ( b->Type != NPCT_OTHERFLOAT ) continue;
  372.                     TraceNL(); TraceS("movingball->X = "); Trace(movingball->X);
  373.                     TraceNL(); TraceS("movingball->Y = "); Trace(movingball->Y);
  374.                     brick.take_hit(b, movingball);
  375.                 }
  376.                 */
  377.                 movingball->DeadState = WDS_ALIVE; //Force it alive at all times if the vaus is alive.
  378.                     //We'll need another solition once we do the 3-way split ball. Bleah.
  379.             }
  380.            
  381.             //It's probably unwise to run this block twice! Where do I want it, before or after Waitdraw() ? -Z
  382.             else
  383.             {
  384.                 paddle.dead(vaus);
  385.                 while ( (frame - 100) < death_frame )
  386.                 {
  387.                     //we should hide the vaus, and restart the stage here.
  388.                     ++frame;
  389.                     Waitdraw(); //Something is preventing the vaus from changing into the explosion style. S
  390.                     Waitframe();
  391.                 }
  392.                 lweapon deadball = movingball;
  393.                 deadball->DeadState = WDS_DEAD;
  394.                 movingball = vaus->Misc[10];
  395.                 revive_vaus = true;
  396.                
  397.             }
  398.            
  399.             Waitdraw();
  400.            
  401.            
  402.             if ( !vaus->Misc[MISC_DEAD] )
  403.             {
  404.                 movingball->DeadState = WDS_ALIVE;
  405.                
  406.                 //Bounce ball on bricks.
  407.                 for ( int q = Screen->NumNPCs(); q > 0; --q )
  408.                 {
  409.                     npc b = Screen->LoadNPC(q);
  410.                     if ( b->Type != NPCT_OTHERFLOAT ) continue;
  411.                     //TraceNL(); TraceS("movingball->X = "); Trace(movingball->X);
  412.                     //TraceNL(); TraceS("movingball->Y = "); Trace(movingball->Y);
  413.                     movingball->DeadState = WDS_ALIVE;
  414.                     brick.take_hit(b, movingball);
  415.                 }
  416.                
  417.             }
  418.             else
  419.             {
  420.                 paddle.dead(vaus);
  421.                 while ( (frame - 100) < death_frame )
  422.                 {
  423.                     //we should hide the vaus, and restart the stage here.
  424.                     ++frame;
  425.                     Waitdraw();
  426.                     Waitframe();
  427.                 }
  428.                 lweapon deadball = movingball;
  429.                 deadball->DeadState = WDS_DEAD;
  430.                 movingball = vaus->Misc[10]; //Because = NULL() requires alpha 32. :D
  431.                 revive_vaus = true;
  432.                
  433.             }
  434.            
  435.             Waitframe();
  436.         }
  437.     }
  438.     void change_setting()
  439.     {
  440.         if ( Input->Key[KEY_M] ) USE_MOUSE = 1;
  441.         if ( Input->Key[KEY_N] ) USE_MOUSE = 0;
  442.         if ( Input->Key[KEY_F] ) USE_ACCEL = 1;
  443.         if ( Input->Key[KEY_G] ) USE_ACCEL = 0;
  444.         if ( Input->Key[KEY_T] ) --paddle_speed; // paddle_speed = vbound(paddle_speed
  445.         if ( Input->Key[KEY_Y] ) ++paddle_speed; // paddle_speed = vbound(paddle_speed
  446.     }
  447.     void hold_Link()
  448.     {
  449.         Link->X = 60; Link->Y = 60;
  450.     }
  451.    
  452. }
  453.  
  454. const int TILE_BALL = 50512;
  455. const int SPR_BALL = 100;
  456.  
  457.  
  458.  
  459. //preliminary ball
  460. ffc script ball
  461. {
  462.     void run(){}
  463.     void setup_sprite(int sprite_id)
  464.     {
  465.         spritedata sd = Game->LoadSpriteData(sprite_id);
  466.         sd->Tile = TILE_BALL;
  467.     }
  468.     void create(ffc vaus_id) //send the ball lweapon pointer back to the vaus
  469.     {
  470.         lweapon ball = Screen->CreateLWeapon(LW_SCRIPT1);
  471.         TraceNL(); TraceS("Creating ball with Script UID: "); Trace(ball->UID);
  472.         ball->HitWidth = 6; //Not 4, so that the ball bounces when its edges touch a brick.
  473.         ball->HitHeight = 6; //Not 4, so that the ball bounces when its edges touch a brick.
  474.         ball->UseSprite(SPR_BALL);
  475.         ball->X = vaus_id->X+18;
  476.         ball->Y = vaus_id->Y-2;
  477.         ball->Damage = 1;
  478.         ball_uid = ball->UID;
  479.         ball->HitXOffset = -1; //so that the ball bounces when its edges touch a brick.
  480.         ball->HitYOffset = -1; //so that the ball bounces when its edges touch a brick.
  481.         vaus_id->Misc[MISC_BALLID] = ball;
  482.     }
  483.     void launch(lweapon b)
  484.     {
  485.         if ( b->Misc[MISC_LAUNCHED] ) return;
  486.         bool launched;
  487.         for ( int q = CB_A; q < CB_R; ++q )
  488.         {
  489.             if ( Input->Press[q] ) { launched = true; break; }
  490.         }
  491.         if ( launched )
  492.         {
  493.             //b->Angular = true;
  494.             Game->PlaySound(6);
  495.             b->Dir = DIR_RIGHTUP;  
  496.             b->Step = 90;
  497.             b->Misc[MISC_LAUNCHED] = 1;
  498.         }
  499.     }
  500.     bool launched(lweapon b)
  501.     {
  502.         return (b->Misc[MISC_LAUNCHED]);
  503.     }
  504.     void move(lweapon b)
  505.     {
  506.        
  507.     }
  508.     //Not launched yet.
  509.     void move_with_vaus(lweapon b, ffc v)
  510.     {
  511.         b->X = v->X+18;
  512.     }
  513.     void check_ceiling(lweapon b)
  514.     {
  515.         if ( b->Y <= BALL_MIN_Y )          
  516.         {
  517.             Game->PlaySound(7);
  518.             switch(b->Dir)
  519.             {
  520.                 case DIR_RIGHTUP: { b->Dir = DIR_RIGHTDOWN; break; }
  521.                 case DIR_LEFTUP: { b->Dir = DIR_LEFTDOWN; break; }
  522.                 default: { b->Dir = DIR_DOWN; break; }
  523.             }
  524.         }
  525.     }
  526.     void check_leftwall(lweapon b)
  527.     {
  528.         if ( caught ) return; //don't do anything while the vaus is holding the ball
  529.         if ( b->X == BALL_MIN_X )
  530.         {
  531.             Game->PlaySound(7);
  532.             switch(b->Dir)
  533.             {
  534.                 case DIR_LEFTDOWN: { b->Dir = DIR_RIGHTDOWN; break; }
  535.                 case DIR_LEFTUP: { b->Dir = DIR_RIGHTUP; break; }
  536.                 default: { b->Dir = DIR_DOWN; break; }
  537.             }
  538.         }
  539.     }
  540.     void check_rightwall(lweapon b)
  541.     {
  542.         if ( caught ) return; //don't do anything while the vaus is holding the ball
  543.         if ( b->X == BALL_MAX_X )
  544.         {
  545.             Game->PlaySound(7);
  546.             switch(b->Dir)
  547.             {
  548.                 case DIR_RIGHTDOWN: { b->Dir = DIR_LEFTDOWN; break; }
  549.                 case DIR_RIGHTUP: { b->Dir = DIR_LEFTUP; break; }
  550.                 default: { b->Dir = DIR_DOWN; break; }
  551.             }
  552.         }
  553.     }
  554.     void check_hitvaus(lweapon b, ffc v)
  555.     {
  556.         if ( launched(b) )
  557.         {
  558.             if ( b->Dir == DIR_RIGHTUP ) return;
  559.             if ( b->Dir == DIR_LEFTUP ) return;
  560.             //if ( Collision(b,v) ) //We'll refine this, later.
  561.            
  562.             if ( b->Y+4 == v->Y )
  563.                 //Now we need to check here, if the paddle is under the ball:
  564.             {
  565.                 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
  566.                 {
  567.                     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.
  568.                     {
  569.                         Game->PlaySound(6);
  570.                         b->Y = v->Y-1;
  571.                         switch(b->Dir)
  572.                         {
  573.                             case DIR_LEFTDOWN: { b->Dir = DIR_LEFTUP; break; }
  574.                             case DIR_RIGHTDOWN: { b->Dir = DIR_RIGHTUP; break; }
  575.                             default: { b->Dir = DIR_DOWN; break; }
  576.                         }
  577.                     }
  578.                     else
  579.                     {
  580.                         dead(b,v);
  581.                     }
  582.                 }
  583.                 else
  584.                 {
  585.                     dead(b,v);
  586.                 }
  587.             }
  588.            
  589.         }
  590.     }
  591.     void dead(lweapon b, ffc v)
  592.     {
  593.        
  594.         Game->PlayMIDI(5);
  595.         //remove the ball
  596.         b->Y = -32768; b->Step = 0;
  597.         v->Misc[MISC_DEAD] = 1;
  598.         //if there are more balls in play, switch movingball to one of those
  599.         //otherwise,
  600.         //check next life
  601.         //if more lives, reset playfield
  602.         //otherwise game over
  603.        
  604.     }
  605.    
  606.    
  607.    
  608. }
  609.  
  610. ffc script ball_controller
  611. {
  612.     void run()
  613.     {
  614.         lweapon ball;
  615.         lweapon active_ball; //will be used for when we have multiple balls.
  616.         lweapon balls[3]; //for divide
  617.         ball = Screen->CreateLWeapon(LW_SCRIPT1);
  618.         ball->X = START_BALL_X;
  619.         ball->Y = START_BALL_Y;
  620.         this->Vx = START_BALL_VX;
  621.         this->Vy = START_BALL_VY;
  622.         bool alive = true;
  623.         int num_balls = 1;
  624.         while(alive)
  625.         {
  626.             if ( ball->Y <= BALL_MIN_Y )
  627.             {
  628.                 bounce();
  629.             }
  630.             if ( ball->X <= BALL_MIN_X )
  631.             {
  632.                 bounce();
  633.             }
  634.             if ( ball->X >= BALL_MAX_X )
  635.             {
  636.                 bounce();
  637.             }
  638.                
  639.             if ( ball->Y >= BALL_MAX_Y )
  640.             {
  641.                 if ( num_balls < 2 )
  642.                 {
  643.                     alive = false;
  644.                 }
  645.                 else
  646.                 {
  647.                     kill_ball(ball); //removes this ball, and sets another ball to be the active one
  648.                     --num_balls;
  649.                 }
  650.             }
  651.             Waitframe();
  652.         }
  653.     }
  654.     void bounce(){}
  655.     void kill_ball(lweapon b){}
  656.    
  657. }
  658.  
  659. const int BRICK_MAX = 14;
  660.  
  661. //Layer 1
  662. const int CMB_BRICK_RED     = 1488;
  663. const int CMB_BRICK_WHITE   = 1490;
  664. const int CMB_BRICK_BLUE    = 1492;
  665. const int CMB_BRICK_ORANGE  = 1494;
  666. const int CMB_BRICK_TEAL    = 1496;
  667. const int CMB_BRICK_VIOLET  = 1498;
  668. const int CMB_BRICK_GREEN   = 1500;
  669. const int CMB_BRICK_YELLOW  = 1502;
  670. const int CMB_BRICK_SILVER1 = 1504;
  671. const int CMB_BRICK_SILVER2 = 1506;
  672. const int CMB_BRICK_SILVER3 = 1508;
  673. const int CMB_BRICK_SILVER4 = 1510;
  674. const int CMB_BRICK_GOLD    = 1516;
  675.  
  676.  
  677. //layer 2
  678. const int CMB_BRICK_RED_LOW     = 1489;
  679. const int CMB_BRICK_WHITE_LOW   = 1491;
  680. const int CMB_BRICK_BLUE_LOW    = 1493;
  681. const int CMB_BRICK_ORANGE_LOW  = 1495;
  682. const int CMB_BRICK_TEAL_LOW    = 1497;
  683. const int CMB_BRICK_VIOLET_LOW  = 1499;
  684. const int CMB_BRICK_GREEN_LOW   = 1501;
  685. const int CMB_BRICK_YELLOW_LOW  = 1503;
  686. const int CMB_BRICK_SILVER1_LOW = 1505;
  687. const int CMB_BRICK_SILVER2_LOW = 1507;
  688. const int CMB_BRICK_SILVER3_LOW = 1509;
  689. const int CMB_BRICK_SILVER4_LOW = 1511;
  690. const int CMB_BRICK_GOLD_LOW    = 1517;
  691.  
  692. //enemies
  693. const int NPC_BRICK_RED     = 181;
  694. const int NPC_BRICK_WHITE   = 182;
  695. const int NPC_BRICK_BLUE    = 183;
  696. const int NPC_BRICK_ORANGE  = 184;
  697. const int NPC_BRICK_TEAL    = 185;
  698. const int NPC_BRICK_VIOLET  = 186;
  699. const int NPC_BRICK_GREEN   = 187;
  700. const int NPC_BRICK_YELLOW  = 188;
  701. const int NPC_BRICK_SILVER1     = 189;
  702. const int NPC_BRICK_SILVER2     = 190;
  703. const int NPC_BRICK_SILVER3     = 255; //not set up yet;
  704. const int NPC_BRICK_SILVER4     = 255; //not set up yet
  705. const int NPC_BRICK_GOLD    = 191;
  706.  
  707.  
  708. const int HIT_BY_LWEAPON = 2;
  709.  
  710. ffc script brick
  711. {
  712.     void run()
  713.     {
  714.     }
  715.     bool hit(npc a, lweapon v)
  716.     {
  717.         Link->Misc[0] = v; //We'll use this as scratch untyped space for the moment. -Z
  718.        
  719.         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.
  720.             //as UID is not, and NEVER should be!!!
  721.         //TraceNL(); TraceS("v->UID is: "); Trace(v->UID);
  722.         /*
  723.         To determine where a brick was hit, we first scan each brick and look to see which was
  724.         hit at all, by our lweapon.
  725.        
  726.         The, we check if that ball is belove, above, right of, or left of the brick,
  727.         and we read its direction.
  728.        
  729.         Using a logic chain from this data, we determine the direction that the ball should next
  730.         take, when it bounces.
  731.        
  732.         */
  733.         //HitBy[]
  734.        
  735.         //if ( a->HitBy[HIT_BY_LWEAPON] )
  736.         //{
  737.         //  TraceNL(); TraceS("a->HitBy[HIT_BY_LWEAPON] id: "); Trace(a->HitBy[HIT_BY_LWEAPON]);
  738.         //  TraceNL();
  739.         //  TraceS("Our Link->Misc scratch value is: "); Trace((Link->Misc[0]+1));
  740.         //}
  741.        
  742.         //! We'll use this method again when we add UIDs to HitBy[] ! -Z
  743.         //return ( a->HitBy[HIT_BY_LWEAPON] == temp_UID );
  744.         return ( a->HitBy[HIT_BY_LWEAPON] == (Link->Misc[0]+1) );
  745.     }
  746.     bool hit_below(npc a, lweapon v)
  747.     {
  748.         if ( v->Y == (a->Y + 8) ) return true; //we could do bounce here.
  749.     }
  750.     bool hit_above(npc a, lweapon v)
  751.     {
  752.         if ( v->Y == (a->Y - 4) ) return true; //we could do bounce here.
  753.     }
  754.     bool hit_left(npc a, lweapon v)
  755.     {
  756.         if ( v->X == (a->X - 4) ) return true; //we could do bounce here.
  757.     }
  758.     bool hit_right(npc a, lweapon v)
  759.     {
  760.         if ( v->X == (a->X + 16 ) ) return true; //we could do bounce here.
  761.     }
  762.    
  763.     void take_hit(npc a, lweapon v)
  764.     {
  765.         if ( hit(a,v) )
  766.         {
  767.             //TraceNL(); TraceS("Brick hit!");
  768.             v->DeadState = WDS_ALIVE;
  769.             //TraceNL(); TraceS("brick->X = "); Trace(a->X);
  770.             //TraceNL(); TraceS("brick->Y = "); Trace(a->Y);
  771.             //TraceNL(); TraceS("ball->X = "); Trace(v->X);
  772.             //TraceNL(); TraceS("ball->Y = "); Trace(v->Y);
  773.             if ( hit_below(a,v) )
  774.             {
  775.                 switch ( v->Dir )
  776.                 {
  777.                     case DIR_UPRIGHT: { v->Dir = DIR_DOWNRIGHT; break; }
  778.                     case DIR_UPLEFT: { v->Dir = DIR_DOWNLEFT; break; }
  779.                     default: { TraceS("hit_below() found an illegal ball direction"); break; }
  780.                 }
  781.                 if ( a->HP <= 0 )
  782.                 {
  783.                     //TraceS("Brick is dead. "); TraceNL();
  784.                     //TraceS("a->Misc[NPCM_AWARDED_POINTS] is: "); Trace(a->Misc[NPCM_AWARDED_POINTS]); TraceNL();
  785.                     if ( !a->Misc[NPCM_AWARDED_POINTS] )
  786.                     {
  787.                         //TraceS("Can award points!"); TraceNL();
  788.                         a->Misc[18] = 1;
  789.                         //TraceS("The points for this brick are: "); Trace(a->Attributes[NPC_ATTRIB_POINTS]); TraceNL();
  790.                         Game->Counter[CR_SCRIPT1] += a->Attributes[NPC_ATTRIB_POINTS];
  791.                     }
  792.                 }
  793.             }
  794.            
  795.             else if ( hit_above(a,v) )
  796.             {
  797.                 switch ( v->Dir )
  798.                 {
  799.                     case DIR_DOWNLEFT: { v->Dir = DIR_UPLEFT; break; }
  800.                     case DIR_DOWNRIGHT: { v->Dir = DIR_UPRIGHT; break; }
  801.                     default: { TraceS("hit_above() found an illegal ball direction"); break; }
  802.                 }
  803.                 if ( a->HP <= 0 )
  804.                 {
  805.                     if ( !a->Misc[NPCM_AWARDED_POINTS] )
  806.                     {
  807.                         a->Misc[NPCM_AWARDED_POINTS] = 1;
  808.                         Game->Counter[CR_SCRIPT1] += a->Attributes[NPC_ATTRIB_POINTS];
  809.                     }
  810.                 }
  811.             }
  812.            
  813.             else if ( hit_left(a,v) )
  814.             {
  815.                 switch ( v->Dir )
  816.                 {
  817.                     case DIR_UPRIGHT: { v->Dir = DIR_UPLEFT; break; }
  818.                     case DIR_DOWNRIGHT: { v->Dir = DIR_DOWNLEFT; break; }
  819.                     default: { TraceS("hit_left() found an illegal ball direction"); break; }
  820.                 }
  821.                 if ( a->HP <= 0 )
  822.                 {
  823.                     if ( !a->Misc[NPCM_AWARDED_POINTS] )
  824.                     {
  825.                         a->Misc[NPCM_AWARDED_POINTS] = 1;
  826.                         Game->Counter[CR_SCRIPT1] += a->Attributes[NPC_ATTRIB_POINTS];
  827.                     }
  828.                 }
  829.             }
  830.             else if ( hit_right(a,v) )
  831.             {
  832.                 switch ( v->Dir )
  833.                 {
  834.                     case DIR_UPLEFT: { v->Dir = DIR_UPRIGHT; break; }
  835.                     case DIR_DOWNLEFT: { v->Dir = DIR_DOWNRIGHT; break; }
  836.                     default: { TraceS("hit_below() found an illegal ball direction"); break; }
  837.                 }
  838.                 if ( a->HP <= 0 )
  839.                 {
  840.                     if ( !a->Misc[NPCM_AWARDED_POINTS] )
  841.                     {
  842.                         a->Misc[NPCM_AWARDED_POINTS] = 1;
  843.                         Game->Counter[CR_SCRIPT1] += a->Attributes[NPC_ATTRIB_POINTS];
  844.                     }
  845.                 }
  846.             }
  847.            
  848.             else
  849.             {
  850.                 TraceS("brick.hit() returned true, but couldn't determine a valid ball location!");
  851.                 return;
  852.             }
  853.         }
  854.                    
  855.            
  856.     }
  857.     //turns layer objects into npc bricks.
  858.     void setup()
  859.     {
  860.         int tempenem; npc bricks[1024]; int temp;
  861.         for ( int q = 0; q < 176; ++q )
  862.         {
  863.             //bricks on layer 1
  864.             //Trace(GetLayerComboD(1,q));
  865.             //while(!Input->Press[CB_A]) Waitframe();
  866.             tempenem = brick_to_npc(GetLayerComboD(1,q),false);
  867.             //TraceS("tempenem is: "); Trace(tempenem);
  868.             //while(!Input->Press[CB_A]) Waitframe();
  869.             if ( tempenem )
  870.             {
  871.                 bricks[temp] = Screen->CreateNPC(tempenem);
  872.                 //TraceS("Created npc: "); Trace(tempenem);
  873.                 bricks[temp]->X = ComboX(q);
  874.                 bricks[temp]->Y = ComboY(q);
  875.                 TraceS("Brick defence is: "); Trace(bricks[temp]->Defense[20]);
  876.                 tempenem = 0; ++temp;
  877.                
  878.             }
  879.             //bricks on layer 2, Y+8px
  880.             tempenem = brick_to_npc(GetLayerComboD(2,q),true);
  881.             //Trace(tempenem);
  882.             if ( tempenem )
  883.             {
  884.                 bricks[temp] = Screen->CreateNPC(tempenem);
  885.                 //TraceS("Created npc: "); Trace(tempenem);
  886.                 bricks[temp]->X = ComboX(q);
  887.                 bricks[temp]->Y = ComboY(q)+8;
  888.                 TraceS("Brick defence is: "); Trace(bricks[temp]->Defense[20]);
  889.                 tempenem = 0; ++temp;
  890.             }
  891.         }
  892.        
  893.     }
  894.     void clear_combos()
  895.     {
  896.         templayer[0] = Screen->LayerOpacity[0];
  897.         templayer[1] = Screen->LayerOpacity[1];
  898.         templayer[2] = Screen->LayerMap[0];
  899.         templayer[3] = Screen->LayerMap[1];
  900.         Screen->LayerOpacity[0] = 0;
  901.         Screen->LayerOpacity[1] = 0;
  902.         Screen->LayerMap[0] = 0;
  903.         Screen->LayerMap[1] = 0;
  904.     }
  905.    
  906.     int brick_to_npc(int combo_id, bool layer2)
  907.     {
  908.        
  909.         if ( !layer2 )
  910.         {
  911.             int brick_to_enemy[BRICK_MAX*2] =
  912.             {   CMB_BRICK_RED, CMB_BRICK_WHITE, CMB_BRICK_BLUE, CMB_BRICK_ORANGE, CMB_BRICK_TEAL,
  913.                 CMB_BRICK_VIOLET, CMB_BRICK_GREEN, CMB_BRICK_YELLOW, CMB_BRICK_SILVER1, CMB_BRICK_SILVER2,
  914.                 CMB_BRICK_SILVER3, CMB_BRICK_SILVER4, CMB_BRICK_GOLD,
  915.  
  916.                 NPC_BRICK_RED, NPC_BRICK_WHITE, NPC_BRICK_BLUE, NPC_BRICK_ORANGE, NPC_BRICK_TEAL,
  917.                 NPC_BRICK_VIOLET, NPC_BRICK_GREEN, NPC_BRICK_YELLOW, NPC_BRICK_SILVER1, NPC_BRICK_SILVER2,
  918.                 NPC_BRICK_SILVER3, NPC_BRICK_SILVER4, NPC_BRICK_GOLD
  919.             };
  920.             for ( int q = 0; q < BRICK_MAX; ++q )
  921.             {
  922.                 if ( brick_to_enemy[q] == combo_id )
  923.                 {
  924.                     //  TraceS("brick_to_npc : combo input: "); Trace(combo_id);
  925.                     //TraceS("brick_to_npc : enemy output: "); Trace(brick_to_enemy[BRICK_MAX+q]);
  926.                    
  927.                     return ( brick_to_enemy[BRICK_MAX+q-1] );
  928.                 }
  929.             }
  930.         }
  931.         else
  932.         {
  933.             int brick_to_enemy2[BRICK_MAX*2] =
  934.             {   CMB_BRICK_RED_LOW, CMB_BRICK_WHITE_LOW, CMB_BRICK_BLUE_LOW, CMB_BRICK_ORANGE_LOW, CMB_BRICK_TEAL_LOW,
  935.                 CMB_BRICK_VIOLET_LOW, CMB_BRICK_GREEN_LOW, CMB_BRICK_YELLOW_LOW, CMB_BRICK_SILVER1_LOW, CMB_BRICK_SILVER2_LOW,
  936.                 CMB_BRICK_SILVER3_LOW, CMB_BRICK_SILVER4_LOW, CMB_BRICK_GOLD_LOW,
  937.  
  938.                 NPC_BRICK_RED, NPC_BRICK_WHITE, NPC_BRICK_BLUE, NPC_BRICK_ORANGE, NPC_BRICK_TEAL,
  939.                 NPC_BRICK_VIOLET, NPC_BRICK_GREEN, NPC_BRICK_YELLOW, NPC_BRICK_SILVER1, NPC_BRICK_SILVER2,
  940.                 NPC_BRICK_SILVER3, NPC_BRICK_SILVER4, NPC_BRICK_GOLD
  941.             };
  942.             for ( int q = 0; q < BRICK_MAX; ++q )
  943.             {
  944.                 if ( brick_to_enemy2[q] == combo_id )
  945.                 {
  946.                     //TraceS("brick_to_npc : combo input: "); Trace(combo_id);
  947.                     //TraceS("brick_to_npc : enemy output: "); Trace(brick_to_enemy2[BRICK_MAX+q-1]);
  948.                     return ( brick_to_enemy2[BRICK_MAX+q-1] );
  949.                 }
  950.             }
  951.         }
  952.         return 0; //error
  953.     }
  954. }
  955.  
  956. global script onExit
  957. {
  958.     void run()
  959.     {
  960.         Screen->LayerOpacity[0] = templayer[0];
  961.         Screen->LayerOpacity[1] = templayer[1];
  962.         Screen->LayerMap[0] = templayer[2];
  963.         Screen->LayerMap[1] = templayer[3];
  964.         newstage = true;
  965.         //vaus->Misc[MISC_DEAD] = 0;
  966.  
  967.     }
  968. }  
  969.  
  970. global script init
  971. {
  972.     void run()
  973.     {
  974.         Link->CollDetection = false;
  975.         Link->DrawYOffset = -32768;
  976.     }
  977. }
  978.  
  979. global script Init
  980. {
  981.     void run()
  982.     {
  983.         Link->CollDetection = false;
  984.         Link->DrawYOffset = -32768;
  985.     }
  986. }
  987.  
  988. global script onContinue
  989. {
  990.     void run()
  991.     {
  992.         Link->Invisible = true;
  993.         Link->CollDetection = false;
  994.         Link->DrawYOffset = -32768;
  995.     }
  996. }
RAW Paste Data