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

  1. /***************************************************************************
  2.  * thromp.cpp  -  falling stone
  3.  *
  4.  * Copyright (C) 2006 - 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/thromp.h"
  17. #include "../core/game_core.h"
  18. #include "../core/camera.h"
  19. #include "../video/animation.h"
  20. #include "../player/player.h"
  21. #include "../level/level.h"
  22. #include "../gui/hud.h"
  23. #include "../video/gl_surface.h"
  24. #include "../user/savegame.h"
  25. #include "../core/sprite_manager.h"
  26. #include "../core/math/utilities.h"
  27. #include "../input/mouse.h"
  28. #include "../core/i18n.h"
  29.  
  30. /* *** *** *** *** *** *** cThromp *** *** *** *** *** *** *** *** *** *** *** */
  31.  
  32. cThromp :: cThromp( float x, float y )
  33. : cEnemy( x, y )
  34. {
  35.     cThromp::Init();
  36. }
  37.  
  38. cThromp :: cThromp( CEGUI::XMLAttributes &attributes )
  39. : cEnemy()
  40. {
  41.     cThromp::Init();
  42.     cThromp::Create_from_Stream( attributes );
  43. }
  44.  
  45. cThromp :: ~cThromp( void )
  46. {
  47.     //
  48. }
  49.  
  50. void cThromp :: Init( void  )
  51. {
  52.     type = TYPE_THROMP;
  53.     posz = 0.093f;
  54.     player_range = 1000;
  55.     can_be_ground = 1;
  56.  
  57.     fire_resistant = 1;
  58.  
  59.     state = STA_STAY;
  60.     move_back = 0;
  61.     dest_velx = 0;
  62.     dest_vely = 0;
  63.     img_dir = "enemy/thromp/";
  64.     Set_Direction( DIR_DOWN );
  65.     Set_Speed( 7 );
  66.     Set_Max_Distance( 200 );
  67.  
  68.     kill_sound = "enemy/thromp/die.ogg";
  69.     kill_points = 200;
  70. }
  71.  
  72. cThromp *cThromp :: Copy( void )
  73. {
  74.     cThromp *thromp = new cThromp( startposx, startposy );
  75.     thromp->Set_Image_Dir( img_dir );
  76.     thromp->Set_Direction( start_direction );
  77.     thromp->Set_Max_Distance( max_distance );
  78.     thromp->Set_Speed( speed );
  79.  
  80.     return thromp;
  81. }
  82.  
  83. void cThromp :: Create_from_Stream( CEGUI::XMLAttributes &attributes )
  84. {
  85.     // position
  86.     Set_Pos( static_cast<float>(attributes.getValueAsInteger( "posx" )), static_cast<float>(attributes.getValueAsInteger( "posy" )), 1 );
  87.     // image directory
  88.     Set_Image_Dir( attributes.getValueAsString( "image_dir", img_dir ).c_str() );
  89.     // direction
  90.     Set_Direction( Get_Direction_Id( attributes.getValueAsString( "direction", Get_Direction_Name( start_direction ) ).c_str() ) );
  91.     // max distance
  92.     Set_Max_Distance( static_cast<float>(attributes.getValueAsInteger( "max_distance", static_cast<int>(max_distance) )) );
  93.     // speed
  94.     Set_Speed( attributes.getValueAsFloat( "speed", speed ) );
  95. }
  96.  
  97. void cThromp :: Save_to_Stream( ofstream &file )
  98. {
  99.     // begin enemy
  100.     file << "\t<enemy>" << std::endl;
  101.  
  102.     // name
  103.     file << "\t\t<Property name=\"type\" value=\"thromp\" />" << std::endl;
  104.     // position
  105.     file << "\t\t<Property name=\"posx\" value=\"" << static_cast<int>(startposx) << "\" />" << std::endl;
  106.     file << "\t\t<Property name=\"posy\" value=\"" << static_cast<int>(startposy) << "\" />" << std::endl;
  107.     // image directory
  108.     file << "\t\t<Property name=\"image_dir\" value=\"" << img_dir << "\" />" << std::endl;
  109.     // direction
  110.     file << "\t\t<Property name=\"direction\" value=\"" << Get_Direction_Name( start_direction ) << "\" />" << std::endl;
  111.     // max distance
  112.     file << "\t\t<Property name=\"max_distance\" value=\"" << static_cast<int>(max_distance) << "\" />" << std::endl;
  113.     // speed
  114.     file << "\t\t<Property name=\"speed\" value=\"" << speed << "\" />" << std::endl;
  115.  
  116.     // end enemy
  117.     file << "\t</enemy>" << std::endl;
  118. }
  119.  
  120. void cThromp :: Load_from_Savegame( cSave_Level_Object *save_object )
  121. {
  122.     cEnemy::Load_from_Savegame( save_object );
  123.  
  124.     // Don't activate if dead
  125.     if( dead )
  126.     {
  127.         return;
  128.     }
  129.  
  130.     // move_back
  131.     if( save_object->exists( "move_back" ) )
  132.     {
  133.         move_back = string_to_int( save_object->Get_Value( "move_back" ) ) > 0;
  134.     }
  135. }
  136.  
  137. cSave_Level_Object *cThromp :: Save_to_Savegame( void )
  138. {
  139.     cSave_Level_Object *save_object = cEnemy::Save_to_Savegame();
  140.  
  141.     // move_back ( only save if needed )
  142.     if( move_back )
  143.     {
  144.         save_object->properties.push_back( cSave_Level_Object_Property( "move_back", int_to_string( move_back ) ) );
  145.     }
  146.  
  147.     return save_object;
  148. }
  149.  
  150. void cThromp :: Set_Image_Dir( string dir )
  151. {
  152.     if( dir.empty() )
  153.     {
  154.         return;
  155.     }
  156.  
  157.     img_dir = dir;
  158.  
  159.     // remove pixmaps dir
  160.     if( img_dir.find( DATA_DIR "/" GAME_PIXMAPS_DIR "/" ) == 0 )
  161.     {
  162.         img_dir.erase( 0, strlen( DATA_DIR "/" GAME_PIXMAPS_DIR "/" ) );
  163.     }
  164.  
  165.     Update_Images();
  166. }
  167.  
  168. void cThromp :: Set_Direction( ObjectDirection dir )
  169. {
  170.     // already set
  171.     if( start_direction == dir )
  172.     {
  173.         return;
  174.     }
  175.  
  176.     cEnemy::Set_Direction( dir, 1 );
  177.  
  178.     Update_Distance_rect();
  179.     Update_Images();
  180. }
  181.  
  182. void cThromp :: Set_Max_Distance( float nmax_distance )
  183. {
  184.     max_distance = nmax_distance;
  185.  
  186.     if( max_distance < 0 )
  187.     {
  188.         max_distance = 0;
  189.     }
  190.  
  191.     Update_Distance_rect();
  192. }
  193.  
  194. void cThromp :: Set_Speed( float val )
  195. {
  196.     if( speed < 0.1f )
  197.     {
  198.         speed = 0.1f;
  199.     }
  200.  
  201.     speed = val;
  202.  
  203.     Update_dest_vel();
  204. }
  205.  
  206. void cThromp :: Activate( void )
  207. {
  208.     if( state == STA_FLY )
  209.     {
  210.         return;
  211.     }
  212.  
  213.     state = STA_FLY;
  214.  
  215.     velx = dest_velx;
  216.     vely = dest_vely;
  217.     move_back = 0;
  218.  
  219.     // active image
  220.     Set_Image( 1 );
  221. }
  222.  
  223. void cThromp :: Move_Back( void )
  224. {
  225.     if( state == STA_STAY || move_back )
  226.     {
  227.         return;
  228.     }
  229.  
  230.     velx = -dest_velx * 0.01f;
  231.     vely = -dest_vely * 0.01f;
  232.  
  233.     move_back = 1;
  234.  
  235.     // default image
  236.     Set_Image( 0 );
  237. }
  238.  
  239. void cThromp :: DownGrade( bool force /* = 0 */ )
  240. {
  241.     Set_Dead( 1 );
  242.     massivetype = MASS_PASSIVE;
  243.     counter = 0;
  244.     velx = 0;
  245.     vely = 0;
  246.  
  247.     if( !force )
  248.     {
  249.         // animation
  250.         cParticle_Emitter *anim = new cParticle_Emitter();
  251.         anim->Set_Pos( posx + ( col_rect.w / 2 ), posy + ( col_rect.h / 2 ) );
  252.         Generate_Hit_Animation( anim );
  253.  
  254.         anim->Set_Scale( 0.8f );
  255.         anim->Set_Direction_Range( 0, 360 );
  256.         // add animation
  257.         pAnimation_Manager->Add( anim );
  258.     }
  259.     else
  260.     {
  261.         Set_Rotation_Z( 180 );
  262.     }
  263. }
  264.  
  265. void cThromp :: DieStep( void )
  266. {
  267.     counter += pFramerate->speedfactor;
  268.  
  269.     // default death
  270.     if( rotz != 180 )
  271.     {
  272.         Set_Visible( 0 );
  273.     }
  274.     // falling death
  275.     else
  276.     {
  277.         // a little bit upwards first
  278.         if( counter < 5 )
  279.         {
  280.             Move( 0, -5 );
  281.         }
  282.         // if not below the screen fall
  283.         else if( posy < game_res_h + col_rect.h )
  284.         {
  285.             Move( 0, 20 );
  286.         }
  287.         // if below disable
  288.         else
  289.         {
  290.             rotz = 0;
  291.             Set_Visible( 0 );
  292.         }
  293.     }
  294. }
  295.  
  296. void cThromp :: Update( void )
  297. {
  298.     cEnemy::Update();
  299.  
  300.     if( !valid_update || !is_Player_range() )
  301.     {
  302.         return;
  303.     }
  304.  
  305.     // standing ( waiting )
  306.     if( state == STA_STAY )
  307.     {
  308.         GL_rect final_distance = Get_Final_Distance_Rect();
  309.  
  310.         // if player is in front then activate
  311.         if( pPlayer->maryo_type != MARYO_GHOST && Col_Box( &pPlayer->col_rect, &final_distance ) )
  312.         {
  313.             Activate();
  314.         }
  315.     }
  316.     // flying ( moving into the destination direction )
  317.     else
  318.     {
  319.         // distance to final position
  320.         float dist_to_final_pos = 0;
  321.         // multiplier for the minimal velocity
  322.         float vel_mod_min = 1;
  323.  
  324.         /* slow down
  325.          * only if the velocity is not too small for the given distance to the final position
  326.          * final velocity should not get smaller on the last 10% to the final position
  327.         */
  328.         if( direction == DIR_LEFT )
  329.         {
  330.             dist_to_final_pos = max_distance - ( startposx - posx );
  331.  
  332.             // move back
  333.             if( move_back )
  334.             {
  335.                 vel_mod_min = ( dist_to_final_pos + ( max_distance * 0.1f ) ) / max_distance;
  336.                 if( -velx > dest_velx * vel_mod_min )
  337.                 {
  338.                     velx *= 1 + ( 0.2f * pFramerate->speedfactor );
  339.                 }
  340.             }
  341.  
  342.         }
  343.         else if( direction == DIR_RIGHT )
  344.         {
  345.             dist_to_final_pos = max_distance + ( startposx - posx );
  346.  
  347.             // move back
  348.             if( move_back )
  349.             {
  350.                 vel_mod_min = ( dist_to_final_pos + ( max_distance * 0.1f ) ) / max_distance;
  351.                 if( -velx < dest_velx * vel_mod_min )
  352.                 {
  353.                     velx *= 1 + ( 0.2f * pFramerate->speedfactor );
  354.                 }
  355.             }
  356.         }
  357.         else if( direction == DIR_UP )
  358.         {
  359.             dist_to_final_pos = max_distance - ( startposy - posy );
  360.  
  361.             // move back
  362.             if( move_back )
  363.             {
  364.                 vel_mod_min = ( dist_to_final_pos + ( max_distance * 0.1f ) ) / max_distance;
  365.                 if( -vely > dest_vely * vel_mod_min )
  366.                 {
  367.                     vely *= 1 + ( 0.2f * pFramerate->speedfactor );
  368.                 }
  369.             }
  370.         }
  371.         else if( direction == DIR_DOWN )
  372.         {
  373.             dist_to_final_pos = max_distance + ( startposy - posy );
  374.  
  375.             // move back
  376.             if( move_back )
  377.             {
  378.                 vel_mod_min = ( dist_to_final_pos + ( max_distance * 0.1f ) ) / max_distance;
  379.                 if( -vely < dest_vely * vel_mod_min )
  380.                 {
  381.                     vely *= 1 + ( 0.2f * pFramerate->speedfactor );
  382.                 }
  383.             }
  384.         }
  385.  
  386.         // reached final position move back
  387.         if( !move_back && dist_to_final_pos < 0 )
  388.         {
  389.             Move_Back();
  390.         }
  391.         // reached original position
  392.         else if( move_back && dist_to_final_pos > max_distance )
  393.         {
  394.             state = STA_STAY;
  395.             Set_Pos( startposx, startposy );
  396.             // unset velocity
  397.             Set_Velocity( 0, 0 );
  398.  
  399.             move_back = 0;
  400.         }
  401.     }
  402. }
  403.  
  404. void cThromp :: Draw( cSurfaceRequest *request /* = NULL */ )
  405. {
  406.     if( !valid_draw )
  407.     {
  408.         return;
  409.     }
  410.  
  411.     // draw distance rect
  412.     if( editor_level_enabled )
  413.     {
  414.         GL_rect final_distance = Get_Final_Distance_Rect();
  415.         final_distance.x -= pActive_Camera->x;
  416.         final_distance.y -= pActive_Camera->y;
  417.  
  418.         pVideo->Draw_Rect( &final_distance, posz - 0.000001f, &whitealpha128 );
  419.     }
  420.  
  421.     cEnemy::Draw( request );
  422. }
  423.  
  424. void cThromp :: Update_Images( void )
  425. {
  426.     // clear images
  427.     Clear_Images();
  428.     // set images
  429.     images.push_back( pVideo->Get_Surface( img_dir + Get_Direction_Name( start_direction ) + ".png" ) );
  430.     images.push_back( pVideo->Get_Surface( img_dir + Get_Direction_Name( start_direction ) + "_active.png" ) );
  431.     // set start image
  432.     Set_Image( 0, 1 );
  433.  
  434.     // set active image
  435.     if( state == STA_FLY )
  436.     {
  437.         Set_Image( 1 );
  438.     }
  439.  
  440.     Create_Name();
  441. }
  442.  
  443. void cThromp :: Update_dest_vel( void )
  444. {
  445.     if( start_direction == DIR_UP )
  446.     {
  447.         dest_velx = 0;
  448.         dest_vely = -speed;
  449.     }
  450.     else if( start_direction == DIR_DOWN )
  451.     {
  452.         dest_velx = 0;
  453.         dest_vely = speed;
  454.     }
  455.     else if( start_direction == DIR_LEFT )
  456.     {
  457.         dest_velx = -speed;
  458.         dest_vely = 0;
  459.     }
  460.     else if( start_direction == DIR_RIGHT )
  461.     {
  462.         dest_velx = speed;
  463.         dest_vely = 0;
  464.     }
  465.     else
  466.     {
  467.         dest_velx = 0;
  468.         dest_vely = 0;
  469.     }
  470. }
  471.  
  472. void cThromp :: Update_Distance_rect( void )
  473. {
  474.     if( start_direction == DIR_UP )
  475.     {
  476.         distance_rect.x = col_pos.x;
  477.         distance_rect.y = -max_distance;
  478.         distance_rect.w = col_rect.w;
  479.         distance_rect.h = max_distance;
  480.     }
  481.     else if( start_direction == DIR_DOWN )
  482.     {
  483.         distance_rect.x = col_pos.x;
  484.         distance_rect.y = 0;
  485.         distance_rect.w = col_rect.w;
  486.         distance_rect.h = max_distance;
  487.     }
  488.     else if( start_direction == DIR_LEFT )
  489.     {
  490.         distance_rect.x = -max_distance;
  491.         distance_rect.y = col_pos.y;
  492.         distance_rect.w = max_distance;
  493.         distance_rect.h = col_rect.h;
  494.     }
  495.     else if( start_direction == DIR_RIGHT )
  496.     {
  497.         distance_rect.x = 0;
  498.         distance_rect.y = col_pos.y;
  499.         distance_rect.w = max_distance;
  500.         distance_rect.h = col_rect.h;
  501.     }
  502. }
  503.  
  504. GL_rect cThromp :: Get_Final_Distance_Rect( void )
  505. {
  506.     GL_rect final_distance = distance_rect;
  507.  
  508.     final_distance.x += rect.x;
  509.     final_distance.y += rect.y;
  510.  
  511.     if( start_direction == DIR_LEFT || start_direction == DIR_RIGHT )
  512.     {
  513.         final_distance.x += rect.w;
  514.         final_distance.w -= rect.w;
  515.     }
  516.     else if( start_direction == DIR_UP || start_direction == DIR_DOWN )
  517.     {
  518.         final_distance.y += rect.h;
  519.         final_distance.h -= rect.h;
  520.     }
  521.  
  522.     return final_distance;
  523. }
  524.  
  525. bool cThromp :: Is_Update_Valid( void )
  526. {
  527.     if( dead || freeze_counter )
  528.     {
  529.         return 0;
  530.     }
  531.  
  532.     return 1;
  533. }
  534.  
  535. bool cThromp :: Is_Draw_Valid( void )
  536. {
  537.     if( cEnemy::Is_Draw_Valid() == 1 )
  538.     {
  539.         return 1;
  540.     }
  541.  
  542.     // if not editor enabled or not active mouse object
  543.     if( !editor_enabled || pMouseCursor->active_object != this )
  544.     {
  545.         return 0;
  546.     }
  547.  
  548.     return 1;
  549. }
  550.  
  551. void cThromp :: Generate_Smoke( unsigned int power /* = 10 */ )
  552. {
  553.     // smoke on the destination direction
  554.     float smoke_x;
  555.     float smoke_y;
  556.     float smoke_width;
  557.     float smoke_height;
  558.  
  559.     if( direction == DIR_DOWN )
  560.     {
  561.         smoke_x = posx;
  562.         smoke_y = posy + rect.h;
  563.         smoke_width = col_rect.w;
  564.         smoke_height = 1;
  565.     }
  566.     else if( direction == DIR_UP )
  567.     {
  568.         smoke_x = posx;
  569.         smoke_y = posy;
  570.         smoke_width = col_rect.w;
  571.         smoke_height = 1;
  572.     }
  573.     else if( direction == DIR_LEFT )
  574.     {
  575.         smoke_x = posx;
  576.         smoke_y = posy;
  577.         smoke_width = 1;
  578.         smoke_height = col_rect.h;
  579.     }
  580.     else if( direction == DIR_RIGHT )
  581.     {
  582.         smoke_x = posx + rect.w;
  583.         smoke_y = posy;
  584.         smoke_width = 1;
  585.         smoke_height = col_rect.h;
  586.     }
  587.     else
  588.     {
  589.         return;
  590.     }
  591.  
  592.     for( unsigned int i = 0 ; i < power; i++ )
  593.     {
  594.         // animation
  595.         cParticle_Emitter *anim = new cParticle_Emitter();
  596.         anim->Set_Pos( smoke_x + Get_Random_Float( 0, smoke_width ), smoke_y + Get_Random_Float( 0, smoke_height ) );
  597.  
  598.         anim->Set_Image( pVideo->Get_Surface( "animation/particles/smoke.png" ) );
  599.         anim->Set_Pos_Z( posz + 0.000001f );
  600.         anim->Set_Time_to_Live( 1, 1 );
  601.         anim->Set_Direction_Range( 0, 360 );
  602.         anim->Set_Speed( 0.5f, 0.2f );
  603.         anim->Set_Fading_Alpha( 1 );
  604.         anim->Set_Const_Rotation_Z( -2, 4 );
  605.         // add animation
  606.         pAnimation_Manager->Add( anim );
  607.     }
  608. }
  609.  
  610. unsigned int cThromp :: Validate_Collision( cSprite *obj )
  611. {
  612.     // basic validation checking
  613.     int basic_valid = Validate_Collision_Ghost( obj );
  614.  
  615.     // found valid collision
  616.     if( basic_valid > -1 )
  617.     {
  618.         return basic_valid;
  619.     }
  620.  
  621.     if( obj->massivetype == MASS_MASSIVE )
  622.     {
  623.         if( obj->type == TYPE_PLAYER )
  624.         {
  625.             return 1;
  626.         }
  627.         if( obj->type == TYPE_STATIC_ENEMY )
  628.         {
  629.             return 0;
  630.         }
  631.  
  632.         // if moving back collide with nothing
  633.         if( move_back )
  634.         {
  635.             return 0;
  636.         }
  637.         else
  638.         {
  639.             return 2;
  640.         }
  641.     }
  642.     if( obj->massivetype == MASS_HALFMASSIVE )
  643.     {
  644.         // if moving downwards and object is on top
  645.         if( vely >= 0 && Is_on_Top( obj ) )
  646.         {
  647.             // if moving back collide with nothing
  648.             if( !move_back )
  649.             {
  650.                 return 2;
  651.             }
  652.         }
  653.     }
  654.  
  655.     return 0;
  656. }
  657.  
  658. void cThromp :: Handle_Collision_Player( cObjectCollision *collision )
  659. {
  660.     // behind
  661.     if( collision->direction == Get_Opposite_Direction( direction ) )
  662.     {
  663.         if( collision->direction == DIR_LEFT || collision->direction == DIR_RIGHT )
  664.         {
  665.             pPlayer->Col_Move( velx, 0, 1 );
  666.         }
  667.     }
  668.     // front
  669.     else if( collision->direction == direction )
  670.     {
  671.         pPlayer->DownGrade();
  672.  
  673.         if( !move_back )
  674.         {
  675.             pAudio->Play_Sound( "enemy/thromp/hit.ogg" );
  676.             Generate_Smoke();
  677.             Move_Back();
  678.         }
  679.     }
  680.     // else is left/right of front direction which doesn't harm
  681. }
  682.  
  683. void cThromp :: Handle_Collision_Enemy( cObjectCollision *collision )
  684. {
  685.     // only destination direction collisions
  686.     if( collision->direction != direction )
  687.     {
  688.         return;
  689.     }
  690.  
  691.     // if active
  692.     if( state == STA_FLY )
  693.     {
  694.         cEnemy *enemy = static_cast<cEnemy *>(pActive_Sprite_Manager->Get_Pointer( collision->number ));
  695.  
  696.         // kill enemy
  697.         pAudio->Play_Sound( enemy->kill_sound );
  698.         pointsdisplay->Add_Points( enemy->kill_points, posx + image->w / 3, posy - 5, "", static_cast<Uint8>(255), 1 );
  699.         enemy->DownGrade( 1 );
  700.  
  701.         if( !move_back )
  702.         {
  703.             Generate_Smoke();
  704.         }
  705.     }
  706. }
  707.  
  708. void cThromp :: Handle_Collision_Massive( cObjectCollision *collision )
  709. {
  710.     // if not active or already moving back
  711.     if( state != STA_FLY || move_back )
  712.     {
  713.         return;
  714.     }
  715.     
  716.     pAudio->Play_Sound( "enemy/thromp/hit.ogg" );
  717.     Generate_Smoke();
  718.     Move_Back();
  719. }
  720.  
  721. void cThromp :: Editor_Activate( void )
  722. {
  723.     CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
  724.  
  725.     // image dir
  726.     CEGUI::Editbox *editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_thromp_image_dir" ));
  727.     Editor_Add( UTF8_("Image directory"), UTF8_("Directory containing the images"), editbox, 200 );
  728.  
  729.     editbox->setText( img_dir.c_str() );
  730.     editbox->subscribeEvent( CEGUI::Editbox::EventTextChanged, CEGUI::Event::Subscriber( &cThromp::Editor_Image_Dir_Key, this ) );
  731.  
  732.     // max distance
  733.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_thromp_max_distance" ));
  734.     Editor_Add( UTF8_("Distance"), UTF8_("Detection distance into its direction"), editbox, 90 );
  735.  
  736.     editbox->setText( int_to_string( static_cast<int>(max_distance) ) );
  737.     editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cThromp::Editor_Max_Distance_Key, this ) );
  738.  
  739.     // speed
  740.     editbox = static_cast<CEGUI::Editbox *>(wmgr.createWindow( "TaharezLook/Editbox", "editor_thromp_speed" ));
  741.     Editor_Add( UTF8_("Speed"), UTF8_("Speed when activated"), editbox, 120 );
  742.  
  743.     editbox->setText( float_to_string( speed ) );
  744.     editbox->subscribeEvent( CEGUI::Editbox::EventKeyUp, CEGUI::Event::Subscriber( &cThromp::Editor_Speed_Key, this ) );
  745.  
  746.     // init
  747.     Editor_Init();
  748. }
  749.  
  750. bool cThromp :: Editor_Image_Dir_Key( const CEGUI::EventArgs &event )
  751. {
  752.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  753.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  754.  
  755.     Set_Image_Dir( str_text );
  756.  
  757.     return 1;
  758. }
  759.  
  760. bool cThromp :: Editor_Max_Distance_Key( const CEGUI::EventArgs &event )
  761. {
  762.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  763.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  764.  
  765.     Set_Max_Distance( static_cast<float>(string_to_int( str_text )) );
  766.  
  767.     return 1;
  768. }
  769.  
  770. bool cThromp :: Editor_Speed_Key( const CEGUI::EventArgs &event )
  771. {
  772.     const CEGUI::WindowEventArgs &windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>( event );
  773.     string str_text = static_cast<CEGUI::Editbox *>( windowEventArgs.window )->getText().c_str();
  774.  
  775.     Set_Speed( string_to_float( str_text ) );
  776.  
  777.     return 1;
  778. }
  779.  
  780. void cThromp :: Create_Name( void )
  781. {
  782.     name = "Thromp ";
  783.     name += _(Get_Direction_Name( start_direction ).c_str());
  784.  
  785.     if( start_image && !start_image->name.empty() )
  786.     {
  787.         name += " " + start_image->name;
  788.     }
  789. }
  790.