home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 February / maximum-cd-2009-02.iso / DiscContents / SMC_1.6_win32.exe / src / enemies / rokko.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2008-09-27  |  12.5 KB  |  552 lines

  1. /***************************************************************************
  2.  * rokko.cpp  -  giant, slow-moving bullet
  3.  *
  4.  * Copyright (C) 2003 - 2008 Florian Richter
  5.  ***************************************************************************/
  6. /*
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 3 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  14. */
  15.  
  16. #include "../enemies/rokko.h"
  17. #include "../core/game_core.h"
  18. #include "../player/player.h"
  19. #include "../video/animation.h"
  20. #include "../gui/hud.h"
  21. #include "../video/gl_surface.h"
  22. #include "../video/renderer.h"
  23. #include "../core/math/utilities.h"
  24. #include "../input/mouse.h"
  25. #include "../core/i18n.h"
  26.  
  27. /* *** *** *** *** *** *** cRokko *** *** *** *** *** *** *** *** *** *** *** */
  28.  
  29. cRokko :: cRokko( float x, float y )
  30. : cEnemy( x, y )
  31. {
  32.     cRokko::Init();
  33. }
  34.  
  35. cRokko :: cRokko( CEGUI::XMLAttributes &attributes )
  36. : cEnemy()
  37. {
  38.     cRokko::Init();
  39.     cRokko::Create_from_Stream( attributes );
  40. }
  41.  
  42. cRokko :: ~cRokko( void )
  43. {
  44.     //
  45. }
  46.  
  47. void cRokko :: Init( void  )
  48. {
  49.     type = TYPE_ROKKO;
  50.     massivetype = MASS_PASSIVE;
  51.     posz = 0.03f;
  52.     editor_posz = 0.09f;
  53.     Set_Visible( 0 );
  54.     can_be_ground = 1;
  55.  
  56.     fire_resistant = 1;
  57.     ice_resistance = 1;
  58.  
  59.     Set_Direction( DIR_LEFT );
  60.     Set_Speed( 8.5f );
  61.     Set_Max_Distance_Front( 1000 );
  62.     Set_Max_Distance_Sides( 400 );
  63.     state = STA_STAY;
  64.  
  65.     player_range = 4000;
  66.     smoke_counter = 0;
  67.  
  68.     kill_sound = "stomp_1.ogg";
  69.     kill_points = 250;
  70. }
  71.  
  72. cRokko *cRokko :: Copy( void )
  73. {
  74.     cRokko *rokko = new cRokko( startposx, startposy );
  75.     rokko->Set_Direction( start_direction );
  76.     rokko->Set_Speed( speed );
  77.  
  78.     return rokko;
  79. }
  80.  
  81. void cRokko :: Create_from_Stream( CEGUI::XMLAttributes &attributes )
  82. {
  83.     // position
  84.     Set_Pos( static_cast<float>(attributes.getValueAsInteger( "posx" )), static_cast<float>(attributes.getValueAsInteger( "posy" )), 1 );
  85.     // direction
  86.     Set_Direction( Get_Direction_Id( attributes.getValueAsString( "direction", Get_Direction_Name( start_direction ) ).c_str() ) );
  87.     // speed
  88.     Set_Speed( attributes.getValueAsFloat( "speed", speed ) );
  89. }
  90.  
  91. void cRokko :: Save_to_Stream( ofstream &file )
  92. {
  93.     // begin enemy
  94.     file << "\t<enemy>" << std::endl;
  95.  
  96.     // name
  97.     file << "\t\t<Property name=\"type\" value=\"rokko\" />" << std::endl;
  98.     // position
  99.     file << "\t\t<Property name=\"posx\" value=\"" << static_cast<int>(startposx) << "\" />" << std::endl;
  100.     file << "\t\t<Property name=\"posy\" value=\"" << static_cast<int>(startposy) << "\" />" << std::endl;
  101.     // direction
  102.     file << "\t\t<Property name=\"direction\" value=\"" << Get_Direction_Name( start_direction ) << "\" />" << std::endl;
  103.     // speed
  104.     file << "\t\t<Property name=\"speed\" value=\"" << speed << "\" />" << std::endl;
  105.  
  106.     // end enemy
  107.     file << "\t</enemy>" << std::endl;
  108. }
  109.  
  110. void cRokko :: Load_from_Savegame( cSave_Level_Object *save_object )
  111. {
  112.     cEnemy::Load_from_Savegame( save_object );
  113.  
  114.     // Don't activate if dead
  115.     if( dead )
  116.     {
  117.         return;
  118.     }
  119.  
  120.     // activate
  121.     if( state == STA_FLY )
  122.     {
  123.         Activate();
  124.     }
  125. }
  126.  
  127. void cRokko :: Set_Direction( ObjectDirection dir )
  128. {
  129.     // already set
  130.     if( direction == dir )
  131.     {
  132.         return;
  133.     }
  134.  
  135.     // clear old images
  136.     Clear_Images();
  137.  
  138.     cEnemy::Set_Direction( dir, 1 );
  139.     name = "Rokko ";
  140.     name += _(Get_Direction_Name( start_direction).c_str());
  141.  
  142.     if( direction == DIR_LEFT )
  143.     {
  144.         images.push_back( pVideo->Get_Surface( "enemy/rokko/l.png" ) );
  145.     }
  146.     else if( direction == DIR_RIGHT )
  147.     {
  148.         images.push_back( pVideo->Get_Surface( "enemy/rokko/r.png" ) );
  149.     }
  150.     else
  151.     {
  152.         printf( "Warning: Unknown Rokko direction %s\n", Get_Direction_Name( dir ).c_str() );
  153.     }
  154.  
  155.     Update_Distance_rect();
  156.     Set_Image( 0, 1 );
  157. }
  158.  
  159. void cRokko :: Set_Speed( float nspeed )
  160. {
  161.     if( nspeed < 2 )
  162.     {
  163.         nspeed = 2;
  164.     }
  165.  
  166.     speed = nspeed;
  167. }
  168.  
  169. void cRokko :: Set_Max_Distance_Front( float distance )
  170. {
  171.     if( distance < 200 )
  172.     {
  173.         distance = 200;
  174.     }
  175.  
  176.     max_distance_front = distance;
  177.  
  178.     Update_Distance_rect();
  179. }
  180.  
  181. void cRokko :: Set_Max_Distance_Sides( float distance )
  182. {
  183.     if( distance < 50 )
  184.     {
  185.         distance = 50;
  186.     }
  187.  
  188.     max_distance_sides = distance;
  189.  
  190.     Update_Distance_rect();
  191. }
  192.  
  193. void cRokko :: Activate( void )
  194. {
  195.     pAudio->Play_Sound( "enemy/rokko/activate.ogg" );
  196.  
  197.     state = STA_FLY;
  198.     walk_count = 1;
  199.     massivetype = MASS_MASSIVE;
  200.     Set_Visible( 1 );
  201.  
  202.     if( direction == DIR_LEFT )
  203.     {
  204.         Set_Velocity( -speed, 0 );
  205.     }
  206.     else
  207.     {
  208.         Set_Velocity( speed, 0 );
  209.     }
  210. }
  211.  
  212. void cRokko :: DownGrade( bool force /* = 0 */ )
  213. {
  214.     Set_Dead( 1 );
  215.     massivetype = MASS_PASSIVE;
  216.     vely = 0;
  217.  
  218.     if( !force )
  219.     {
  220.         // animation
  221.         cParticle_Emitter *anim = new cParticle_Emitter();
  222.         anim->Set_Pos( pPlayer->posx + ( pPlayer->col_rect.w / 2 ), posy + 5 );
  223.         Generate_Hit_Animation( anim );
  224.  
  225.         anim->Set_Quota( 8 );
  226.         anim->Set_Speed( 4, 1 );
  227.         anim->Set_Scale( 0.9f );
  228.         // add animation
  229.         pAnimation_Manager->Add( anim );
  230.     }
  231. }
  232.  
  233. void cRokko :: DieStep( void )
  234. {
  235.     Move( 0, 17 );
  236.  
  237.     if( direction == DIR_LEFT || direction == DIR_RIGHT )
  238.     {
  239.         if( rotz < 90 )
  240.         {
  241.             Add_Rotation_Z( pFramerate->speedfactor );
  242.         }
  243.     }
  244.  
  245.     // generate smoke
  246.     smoke_counter += pFramerate->speedfactor * 10;
  247.     if( smoke_counter >= 1 )
  248.     {
  249.         Generate_Smoke( static_cast<int>(smoke_counter) );
  250.         smoke_counter -= static_cast<int>(smoke_counter);
  251.     }
  252.  
  253.     if( posy > 600 )
  254.     {
  255.         rotz = 0;
  256.         massivetype = MASS_PASSIVE;
  257.         Set_Visible( 0 );
  258.         velx = 0;
  259.     }
  260. }
  261.  
  262. void cRokko :: Update( void )
  263. {
  264.     cEnemy::Update();
  265.  
  266.     if( !valid_update || !is_Player_range() )
  267.     {
  268.         return;
  269.     }
  270.  
  271.     // if not active
  272.     if( state != STA_FLY )
  273.     {
  274.         GL_rect final_distance = Get_Final_Distance_Rect();
  275.  
  276.         // if player is in front then activate
  277.         if( pPlayer->maryo_type != MARYO_GHOST && Col_Box( &pPlayer->col_rect, &final_distance ) )
  278.         {
  279.             Activate();
  280.         }
  281.         else
  282.         {
  283.             return;
  284.         }
  285.     }
  286.  
  287.     // generate smoke
  288.     smoke_counter += pFramerate->speedfactor * 10;
  289.     if( smoke_counter >= 1 )
  290.     {
  291.         Generate_Smoke( static_cast<int>(smoke_counter) );
  292.         smoke_counter -= static_cast<int>(smoke_counter);
  293.     }
  294. }
  295.  
  296. void cRokko :: Draw( cSurfaceRequest *request /* = NULL */ )
  297. {
  298.     if( !valid_draw )
  299.     {
  300.         return;
  301.     }
  302.  
  303.     // draw distance rect
  304.     if( editor_level_enabled )
  305.     {
  306.         GL_rect final_distance = Get_Final_Distance_Rect();
  307.         final_distance.x -= pActive_Camera->x;
  308.         final_distance.y -= pActive_Camera->y;
  309.  
  310.         pVideo->Draw_Rect( &final_distance, posz - 0.000001f, &whitealpha128 );
  311.     }
  312.  
  313.     bool create_request = 0;
  314.  
  315.     if( !request )
  316.     {
  317.         create_request = 1;
  318.         // create request
  319.         request = new cSurfaceRequest();
  320.     }
  321.  
  322.     // Draw
  323.     cEnemy::Draw( request );
  324.  
  325.     // alpha in debug mode
  326.     if( editor_level_enabled )
  327.     {
  328.         request->color.alpha = 64;
  329.     }
  330.  
  331.     if( create_request )
  332.     {
  333.         // add request
  334.         pRenderer->Add( request );
  335.     }
  336. }
  337.  
  338. void cRokko :: Update_Distance_rect( void )
  339. {
  340.     if( start_direction == DIR_UP )
  341.     {
  342.         distance_rect.x = ((col_pos.x + col_rect.w) * 0.5f) - (max_distance_sides * 0.5f);
  343.         distance_rect.y = -max_distance_front;
  344.         distance_rect.w = max_distance_sides;
  345.         distance_rect.h = max_distance_front;
  346.     }
  347.     else if( start_direction == DIR_DOWN )
  348.     {
  349.         distance_rect.x = ((col_pos.x + col_rect.w) * 0.5f) - (max_distance_sides * 0.5f);
  350.         distance_rect.y = 0;
  351.         distance_rect.w = max_distance_sides;
  352.         distance_rect.h = max_distance_front;
  353.     }
  354.     else if( start_direction == DIR_LEFT )
  355.     {
  356.         distance_rect.x = -max_distance_front;
  357.         distance_rect.y = ((col_pos.y + col_rect.h) * 0.5f) - (max_distance_sides * 0.5f);
  358.         distance_rect.w = max_distance_front;
  359.         distance_rect.h = max_distance_sides;
  360.     }
  361.     else if( start_direction == DIR_RIGHT )
  362.     {
  363.         distance_rect.x = 0;
  364.         distance_rect.y = ((col_pos.y + col_rect.h) * 0.5f) - (max_distance_sides * 0.5f);
  365.         distance_rect.w = max_distance_front;
  366.         distance_rect.h = max_distance_sides;
  367.     }
  368. }
  369.  
  370. GL_rect cRokko :: Get_Final_Distance_Rect( void )
  371. {
  372.     GL_rect final_distance = distance_rect;
  373.  
  374.     final_distance.x += rect.x;
  375.     final_distance.y += rect.y;
  376.  
  377.     if( start_direction == DIR_LEFT || start_direction == DIR_RIGHT )
  378.     {
  379.         final_distance.x += rect.w;
  380.         final_distance.w -= rect.w;
  381.     }
  382.     else if( start_direction == DIR_UP || start_direction == DIR_DOWN )
  383.     {
  384.         final_distance.y += rect.h;
  385.         final_distance.h -= rect.h;
  386.     }
  387.  
  388.     return final_distance;
  389. }
  390.  
  391. void cRokko :: Generate_Smoke( unsigned int quota /*= 10 */ )
  392. {
  393.     cParticle_Emitter *anim = NULL;
  394.  
  395.     // moving smoke particle animation
  396.     while( quota > 0 )
  397.     {
  398.         // not dead
  399.         if( !dead )
  400.         {
  401.             if( direction == DIR_LEFT )
  402.             {
  403.                 anim = new cParticle_Emitter();
  404.                 anim->Set_Pos( posx + col_rect.w - Get_Random_Float( 5, 8 ), posy + Get_Random_Float( 0, rect.h - 15 ) );
  405.                 anim->Set_Direction_Range( 320, 100 );
  406.             }
  407.             else
  408.             {
  409.                 anim = new cParticle_Emitter();
  410.                 anim->Set_Pos( posx + Get_Random_Float( 5, 8 ), posy + Get_Random_Float( 0, rect.h - 15 ) );
  411.                 anim->Set_Direction_Range( 140, 100 );
  412.             }
  413.         }
  414.         // dead
  415.         else
  416.         {
  417.             anim = new cParticle_Emitter();
  418.             anim->Set_Pos( posx + Get_Random_Float( 0, col_rect.w ), posy + Get_Random_Float( 0, rect.h ) );
  419.         }
  420.  
  421.         // - 0.000001f caused a weird graphical z pos bug with my ATI card
  422.         anim->Set_Pos_Z( posz - 0.000005f );
  423.         anim->Set_Image( pVideo->Get_Surface( "animation/particles/smoke_black.png" ) );
  424.         anim->Set_Time_to_Live( 0.3f, 1 );
  425.         anim->Set_Speed( 1, 1 );
  426.         anim->Set_Scale( 1.3f );
  427.         anim->Set_Const_Rotation_Z( -1, 2 );
  428.         anim->Set_Color( Color( static_cast<Uint8>(155), 150, 130 ) );
  429.         anim->Set_Fading_Alpha( 1 );
  430.         
  431.         // add animation
  432.         pAnimation_Manager->Add( anim );
  433.  
  434.         if( dead )
  435.         {
  436.             // random sparks
  437.             if( ( rand() % 25 ) == 0 )
  438.             {
  439.                 // animation
  440.                 anim = new cParticle_Emitter();
  441.                 anim->Set_Pos( posx + col_rect.w * 0.2f + Get_Random_Float( 0,  col_rect.w * 0.6f ), posy + rect.h * 0.2f + Get_Random_Float( 0, rect.h * 0.6f ) );
  442.                 anim->Set_Pos_Z( posz + 0.000001f );
  443.                 anim->Set_Quota( 8 );
  444.                 anim->Set_Time_to_Live( 0.3f, 0.1f );
  445.                 anim->Set_Speed( 4, 1.5f );
  446.                 anim->Set_Image( pVideo->Get_Surface( "animation/particles/light.png" ) );
  447.                 anim->Set_Color( Color( static_cast<Uint8>(255), 245, 0 ), Color( static_cast<Uint8>(0), rand() % 10, 0 ) );
  448.                 anim->Set_Scale( 0.5f );
  449.                 anim->Set_Fading_Size( 1 );
  450.                 anim->Set_Fading_Alpha( 0 );
  451.                 // add animation
  452.                 pAnimation_Manager->Add( anim );
  453.             }
  454.         }
  455.  
  456.         quota--;
  457.     }
  458. }
  459.  
  460. bool cRokko :: Is_Update_Valid( void )
  461. {
  462.     if( dead || freeze_counter )
  463.     {
  464.         return 0;
  465.     }
  466.  
  467.     return 1;
  468. }
  469.  
  470. bool cRokko :: Is_Draw_Valid( void )
  471. {
  472.     if( cEnemy::Is_Draw_Valid() == 1 )
  473.     {
  474.         return 1;
  475.     }
  476.  
  477.     // if not editor enabled or not active mouse object
  478.     if( !editor_enabled || pMouseCursor->active_object != this )
  479.     {
  480.         return 0;
  481.     }
  482.  
  483.     return 1;
  484. }
  485.  
  486. unsigned int cRokko :: Validate_Collision( cSprite *obj )
  487. {
  488.     if( obj->type == TYPE_PLAYER )
  489.     {
  490.         return 1;
  491.     }
  492.     if( obj->type == TYPE_BALL )
  493.     {
  494.         return 1;
  495.     }
  496.  
  497.     return 0;
  498. }
  499.  
  500. void cRokko :: Handle_Collision_Player( cObjectCollision *collision )
  501. {
  502.     // if invincible
  503.     if( pPlayer->invincible > 0 || collision->direction == DIR_UNDEFINED )
  504.     {
  505.         return;
  506.     }
  507.  
  508.     if( collision->direction == DIR_TOP && pPlayer->state != STA_FLY )
  509.     {
  510.         pointsdisplay->Add_Points( kill_points, pPlayer->posx + pPlayer->image->w / 3, pPlayer->posy - 5, "", static_cast<Uint8>(255), 1 );
  511.         pAudio->Play_Sound( kill_sound );
  512.         pPlayer->Action_Jump( 1 );
  513.  
  514.         pPlayer->Add_Kill_Multiplier();
  515.         DownGrade();
  516.     }
  517.     else
  518.     {
  519.         pPlayer->DownGrade();
  520.     }
  521. }
  522.  
  523. void cRokko :: Handle_out_of_Level( ObjectDirection dir )
  524. {
  525.     // ignore
  526. }
  527.  
  528. void cRokko :: Editor_Activate( void )
  529. {
  530.     CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
  531.  
  532.     // speed
  533.     CEGUI::Editbox *editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_rokko_speed" ));
  534.     Editor_Add( UTF8_("Speed"), UTF8_("Speed when activated"), editbox, 120 );
  535.  
  536.     editbox->setText( float_to_string( speed ) );
  537.     editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cRokko::Editor_Speed_Key, this ) );
  538.  
  539.     // init
  540.     Editor_Init();
  541. }
  542.  
  543. bool cRokko :: Editor_Speed_Key( const CEGUI::EventArgs &event )
  544. {
  545.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  546.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  547.  
  548.     Set_Speed( string_to_float( str_text ) );
  549.  
  550.     return 1;
  551. }
  552.