ePlayer Class Reference

#include <ePlayer.h>

Inheritance diagram for ePlayer:

Inheritance graph
[legend]
Collaboration diagram for ePlayer:

Collaboration graph
[legend]

List of all members.

Public Member Functions

 tCHECKED_PTR (eCamera) cam
 tCONTROLLED_PTR (ePlayerNetID) netPlayer
 ePlayer ()
virtual ~ePlayer ()
virtual const char * Name () const
virtual const char * Teamname () const
virtual bool Act (uAction *act, REAL x)
int ID () const
void Render ()

Static Public Member Functions

static ePlayerPlayerConfig (int p)
static bool PlayerIsInGame (int p)
static rViewportPlayerViewport (int p)
static void LogIn ()
 sends authentication login messages for all local players
static void SendAuthNames ()
 sends authentication names and authentication wishes for all local players
static void Init ()
static void Exit ()

Public Attributes

tString name
tString globalID
tString teamname
bool centerIncamOnTurn
bool wobbleIncam
bool autoSwitchIncam
bool spectate
bool stealth
bool autoLogin
bool nameTeamAfterMe
int favoriteNumberOfPlayersPerTeam
eCamMode startCamera
bool allowCam [CAMERA_COUNT]
int startFOV
bool smartCustomGlance
 flag making the smart camera use the custom settings for glancing
tJUST_CONTROLLED_PTR
< eCockpitPrototype
cockpit
int rgb [3]
tString instantChatString [MAX_INSTANT_CHAT]

Static Public Attributes

static uActionPlayerse_instantChatAction [MAX_INSTANT_CHAT]

Private Member Functions

void StoreConfitem (tConfItemBase *c)
void DeleteConfitems ()

Private Attributes

tConfItemBaseconfiguration [PLAYER_CONFITEMS]
int CurrentConfitem

Static Private Attributes

static uActionPlayer s_chat

Friends

class eMenuItemChat


Detailed Description

Definition at line 62 of file ePlayer.h.


Constructor & Destructor Documentation

ePlayer::ePlayer (  ) 

Definition at line 1040 of file ePlayer.cpp.

References allowCam, autoLogin, autoSwitchIncam, CAMERA_COUNT, CAMERA_SMART, centerIncamOnTurn, tString::Clear(), CurrentConfitem, default_instant_chat, favoriteNumberOfPlayersPerTeam, G, tRandomizer::Get(), tRandomizer::GetInstance(), globalID, instantChatString, tString::Len(), MAX_INSTANT_CHAT, MAX_PLAYERS, nameTeamAfterMe, NULL, PasswordCallback(), REAL, rgb, se_UserName(), nAuthentication::SetLoginResultCallback(), nAuthentication::SetUserPasswordCallback(), smartCustomGlance, spectate, startCamera, startFOV, stealth, StoreConfitem(), teamname, tNEW, and wobbleIncam.

01040                 :cockpit(0){
01041     nAuthentication::SetUserPasswordCallback(&PasswordCallback);
01042 #ifdef KRAWALL_SERVER
01043     nAuthentication::SetLoginResultCallback (&ResultCallback);
01044 #endif
01045 
01046     nameTeamAfterMe = false;
01047     favoriteNumberOfPlayersPerTeam = 3;
01048 
01049     CurrentConfitem = 0;
01050 
01051     bool getUserName = false;
01052     if ( id == 0 )
01053     {
01054         name = se_UserName();
01055         getUserName = ( name.Len() > 1 );
01056     }
01057     if ( !getUserName )
01058         name << "Player " << id+1;
01059 
01060 #ifndef DEDICATED
01061     tString confname;
01062 
01063     confname << "PLAYER_"<< id+1;
01064     StoreConfitem(tNEW(tConfItemLine) (confname,
01065                                        "$player_name_confitem_help",
01066                                        name));
01067 
01068     confname.Clear();
01069 
01070     confname << "TEAMNAME_"<< id+1;
01071     StoreConfitem(tNEW(tConfItemLine) (confname,
01072                                        "$team_name_confitem_help",
01073                                        teamname));
01074 
01075     confname.Clear();
01076 
01077     confname << "USER_"<< id+1;
01078     StoreConfitem(tNEW(tConfItemLine) (confname,
01079                                        "$player_user_confitem_help",
01080                                        globalID));
01081     
01082     confname.Clear();
01083     confname << "AUTO_LOGIN_"<< id+1;
01084     StoreConfitem(tNEW(tConfItem<bool>)(confname,
01085                                         "$auto_login_help",
01086                                         autoLogin));
01087     autoLogin = false;
01088 
01089     confname.Clear();
01090 
01091     confname << "CAMCENTER_"<< id+1;
01092     centerIncamOnTurn=true;
01093     StoreConfitem(tNEW(tConfItem<bool>)
01094                   (confname,
01095                    "$camcenter_help",
01096                    centerIncamOnTurn) );
01097 
01098     confname.Clear();
01099     startCamera=CAMERA_SMART;
01100     confname << "START_CAM_"<< id+1;
01101     StoreConfitem(tNEW(tConfItem<eCamMode>) (confname,
01102                   "$start_cam_help",
01103                   startCamera));
01104 
01105     confname.Clear();
01106     confname << "START_FOV_"<< id+1;
01107     startFOV=90;
01108     StoreConfitem(tNEW(tConfItem<int>) (confname,
01109                                         "$start_fov_help",
01110                                         startFOV));
01111     confname.Clear();
01112 
01113     confname.Clear();
01114     confname << "SMART_GLANCE_CUSTOM_"<< id+1;
01115     smartCustomGlance=true;
01116     StoreConfitem(tNEW(tConfItem<bool>) (confname,
01117                                          "$camera_smart_glance_custom_help",
01118                                          smartCustomGlance));
01119     confname.Clear();
01120 
01121     int i;
01122     for(i=CAMERA_COUNT-1;i>=0;i--){
01123         confname << "ALLOW_CAM_"<< id+1 << "_" << i;
01124         StoreConfitem(tNEW(tConfItem<bool>) (confname,
01125                                              "$allow_cam_help",
01126                                              allowCam[i]));
01127         allowCam[i]=true;
01128         confname.Clear();
01129     }
01130 
01131     for(i=MAX_INSTANT_CHAT-1;i>=0;i--){
01132         confname << "INSTANT_CHAT_STRING_" << id+1 << '_' <<  i+1;
01133         StoreConfitem(tNEW(tConfItemLine) (confname,
01134                                            "$instant_chat_string_help",
01135                                            instantChatString[i]));
01136         confname.Clear();
01137     }
01138 
01139     for(i=0; i < MAX_INSTANT_CHAT;i++){
01140         if (!default_instant_chat[i])
01141             break;
01142 
01143         instantChatString[i]=default_instant_chat[i];
01144     }
01145 
01146     confname << "SPECTATOR_MODE_"<< id+1;
01147     StoreConfitem(tNEW(tConfItem<bool>)(confname,
01148                                         "$spectator_mode_help",
01149                                         spectate));
01150     spectate=false;
01151     confname.Clear();
01152 
01153     confname << "HIDE_IDENTITY_"<< id+1;
01154     StoreConfitem(tNEW(tConfItem<bool>)(confname,
01155                                         "$hide_identity_help",
01156                                         stealth));
01157     stealth=false;
01158     confname.Clear();
01159 
01160     confname << "NAME_TEAM_AFTER_PLAYER_"<< id+1;
01161     StoreConfitem(tNEW(tConfItem<bool>)(confname,
01162                                         "$name_team_after_player_help",
01163                                         nameTeamAfterMe));
01164     nameTeamAfterMe=false;
01165     confname.Clear();
01166 
01167     confname << "FAV_NUM_PER_TEAM_PLAYER_"<< id+1;
01168     StoreConfitem(tNEW(tConfItem<int>)(confname,
01169                                        "$fav_num_per_team_player_help",
01170                                        favoriteNumberOfPlayersPerTeam ));
01171     favoriteNumberOfPlayersPerTeam = 3;
01172     confname.Clear();
01173 
01174 
01175     confname << "AUTO_INCAM_"<< id+1;
01176     autoSwitchIncam=false;
01177     StoreConfitem(tNEW(tConfItem<bool>) (confname,
01178                                          "$auto_incam_help",
01179                                          autoSwitchIncam));
01180     confname.Clear();
01181 
01182     confname << "CAMWOBBLE_"<< id+1;
01183     wobbleIncam=false;
01184     StoreConfitem(tNEW(tConfItem<bool>) (confname,
01185                                          "$camwobble_help",
01186                                          wobbleIncam));
01187 
01188     confname.Clear();
01189     confname << "COLOR_B_"<< id+1;
01190     StoreConfitem(tNEW(tConfItem<int>) (confname,
01191                                         "$color_b_help",
01192                                         rgb[2]));
01193 
01194     confname.Clear();
01195     confname << "COLOR_G_"<< id+1;
01196     StoreConfitem(tNEW(tConfItem<int>) (confname,
01197                                         "$color_g_help",
01198                                         rgb[1]));
01199 
01200     confname.Clear();
01201     confname << "COLOR_R_"<< id+1;
01202     StoreConfitem(tNEW(tConfItem<int>) (confname,
01203                                         "$color_r_help",
01204                                         rgb[0]));
01205     confname.Clear();
01206 #endif
01207 
01208     tRandomizer & randomizer = tRandomizer::GetInstance();
01209     //static int r = rand() / ( RAND_MAX >> 2 ) + se_UserName().Len();
01210     static int r = randomizer.Get(4) + se_UserName().Len();
01211     int cid = ( r + id ) % 4;
01212 
01213     static REAL R[MAX_PLAYERS]={1,.2,.2,1};
01214     static REAL G[MAX_PLAYERS]={.2,1,.2,1};
01215     static REAL B[MAX_PLAYERS]={.2,.2,1,.2};
01216 
01217     rgb[0]=int(R[cid]*15);
01218     rgb[1]=int(G[cid]*15);
01219     rgb[2]=int(B[cid]*15);
01220 
01221     cam=NULL;
01222 }

Here is the call graph for this function:

ePlayer::~ePlayer (  )  [virtual]

Definition at line 1224 of file ePlayer.cpp.

References DeleteConfitems(), and tCHECK_DEST.

01224                  {
01225     tCHECK_DEST;
01226     DeleteConfitems();
01227 }

Here is the call graph for this function:


Member Function Documentation

void ePlayer::StoreConfitem ( tConfItemBase c  )  [private]

Definition at line 995 of file ePlayer.cpp.

References configuration, CurrentConfitem, PLAYER_CONFITEMS, and tASSERT.

Referenced by ePlayer().

00995                                              {
00996     tASSERT(CurrentConfitem < PLAYER_CONFITEMS);
00997     configuration[CurrentConfitem++] = c;
00998 }

Here is the caller graph for this function:

void ePlayer::DeleteConfitems (  )  [private]

Definition at line 1000 of file ePlayer.cpp.

References configuration, CurrentConfitem, and tDESTROY.

Referenced by ~ePlayer().

01000                                {
01001     while (CurrentConfitem>0){
01002         CurrentConfitem--;
01003         tDESTROY(configuration[CurrentConfitem]);
01004     }
01005 }

Here is the caller graph for this function:

ePlayer::tCHECKED_PTR ( eCamera   ) 

ePlayer::tCONTROLLED_PTR ( ePlayerNetID   ) 

virtual const char* ePlayer::Name (  )  const [inline, virtual]

Implements uPlayerPrototype.

Definition at line 105 of file ePlayer.h.

References name.

Referenced by operator<<(), ArmageTronPlayer_to_viewport_menuitem::RenderBackground(), and gTeam::TeamMenu().

00105 {return name;}

Here is the caller graph for this function:

virtual const char* ePlayer::Teamname (  )  const [inline, virtual]

Definition at line 106 of file ePlayer.h.

References teamname.

Referenced by ePlayerNetID::Update().

00106 {return teamname;}

Here is the caller graph for this function:

bool ePlayer::Act ( uAction act,
REAL  x 
) [virtual]

Implements uPlayerPrototype.

Definition at line 3529 of file ePlayer.cpp.

03531                                     {
03532     eGameObject *object=NULL;
03533 
03534     if ( act == &se_toggleSpectator && x > 0 )
03535     {
03536         spectate = !spectate;
03537         con << tOutput(spectate ? "$player_toggle_spectator_on" : "$player_toggle_spectator_off", name );
03538         if ( !spectate )
03539         {
03540             ePlayerNetID::Update();
03541         }
03542         return true;
03543     }
03544     else if (!se_chatter && s_chat==*reinterpret_cast<uActionPlayer *>(act)){
03545         if(x>0) {
03546             chat( this );
03547         }
03548         return true;
03549     }
03550     else{
03551         if ( x > 0 )
03552         {
03553             int i;
03554             uActionPlayer* pact = reinterpret_cast<uActionPlayer *>(act);
03555             for(i=MAX_INSTANT_CHAT-1;i>=0;i--){
03556                 uActionPlayer* pcompare = se_instantChatAction[i];
03557                 if (pact == pcompare && x>=0){
03558                     for(int j=se_PlayerNetIDs.Len()-1;j>=0;j--)
03559                         if (se_PlayerNetIDs(j)->pID==ID())
03560                         {
03561                             tString say = instantChatString[i];
03562                             bool sendImmediately = true;
03563                             if ( say.Len() > 2 && say[say.Len()-2] == '\\' )
03564                             {
03565                                 // cut away trailing slash and note for later
03566                                 // that the message should not be sent immediately.
03567                                 say = say.SubStr( 0, say.Len()-2 );
03568                                 sendImmediately = false;
03569                             }
03570 
03571                             if ( se_chatter == this )
03572                             {
03573                                 // a chat is already active, insert the chat string
03574                                 throw eChatInsertionCommand( say );
03575                             }
03576                             else
03577                             {
03578                                 if ( sendImmediately )
03579                                 {
03580                                     // fire out chat string immediately
03581                                     se_PlayerNetIDs(j)->Chat(say);
03582                                 }
03583                                 else
03584                                 {
03585                                     // chat with instant chat string as template
03586                                     chat( this, say );
03587                                 }
03588                             }
03589                             return true;
03590                         }
03591                 }
03592             }
03593         }
03594 
03595         // no other command should get through during chat
03596         if ( se_chatter && !se_allowControlDuringChat )
03597             return false;
03598 
03599         int i;
03600         for(i=se_PlayerNetIDs.Len()-1;i>=0;i--)
03601             if (se_PlayerNetIDs[i]->pID==id && se_PlayerNetIDs[i]->object)
03602                 object=se_PlayerNetIDs[i]->object;
03603 
03604         bool objectAct = false; // set to true if an action of the object was triggered
03605         bool ret = ((cam    && cam->Act(reinterpret_cast<uActionCamera *>(act),x)) ||
03606                     ( objectAct = (object && se_GameTime()>=0 && object->Act(reinterpret_cast<uActionPlayer *>(act),x))));
03607 
03608         if (bool(netPlayer) && (objectAct || !se_chatter))
03609             netPlayer->Activity();
03610 
03611         return ret;
03612     }

int ePlayer::ID (  )  const [inline]

Definition at line 110 of file ePlayer.h.

References uPlayerPrototype::id.

Referenced by se_GetWatchedPlayer().

00110 {return id;};

Here is the caller graph for this function:

void ePlayer::Render (  ) 

Definition at line 1230 of file ePlayer.cpp.

Referenced by RenderAllViewports().

01230                     {
01231     if (cam) cam->Render();
01232 }

Here is the caller graph for this function:

ePlayer * ePlayer::PlayerConfig ( int  p  )  [static]

Reimplemented from uPlayerPrototype.

Definition at line 989 of file ePlayer.cpp.

References uPlayerPrototype::PlayerConfig().

Referenced by display_cockpit_lucifer(), gMenuItemPlayer::Enter(), exit_game_objects(), gGame::GameLoop(), init_game_camera(), LogIn(), gGame::NetSync(), ArmageTronPlayer_to_viewport_menuitem::Render(), RenderAllViewports(), ArmageTronPlayer_to_viewport_menuitem::RenderBackground(), se_DisplayChatLocallyClient(), se_rubyEval(), SendAuthNames(), sg_PlayerMenu(), ePlayerNetID::SpectateAll(), gTeam::TeamMenu(), and ePlayerNetID::Update().

00989                                     {
00990     uPlayerPrototype *P = uPlayerPrototype::PlayerConfig(p);
00991     return dynamic_cast<ePlayer*>(P);
00992     //  return (ePlayer*)P;
00993 }

Here is the call graph for this function:

Here is the caller graph for this function:

bool ePlayer::PlayerIsInGame ( int  p  )  [static]

Definition at line 3624 of file ePlayer.cpp.

Referenced by gMenuItemPlayer::Enter(), init_game_camera(), gTeam::TeamMenu(), and ePlayerNetID::Update().

03626                                  {

Here is the caller graph for this function:

rViewport * ePlayer::PlayerViewport ( int  p  )  [static]

Definition at line 3614 of file ePlayer.cpp.

Referenced by init_game_camera().

03616                                         {
03617     if (!PlayerConfig(p)) return NULL;
03618 
03619     for (int i=rViewportConfiguration::CurrentViewportConfiguration()->num_viewports-1;i>=0;i--)
03620         if (sr_viewportBelongsToPlayer[i] == p)
03621             return rViewportConfiguration::CurrentViewport(i);
03622 

Here is the caller graph for this function:

void ePlayer::LogIn (  )  [static]

sends authentication login messages for all local players

Definition at line 1398 of file ePlayer.cpp.

References MAX_PLAYERS, nCLIENT, PlayerConfig(), se_WantLogin(), and sn_GetNetState().

Referenced by PlayerLogIn().

01399 {
01400     // only meaningful on client
01401     if( sn_GetNetState() != nCLIENT )
01402     {
01403         return;
01404     }
01405 
01406     // mark all players as wanting to log in
01407     for(int i=MAX_PLAYERS-1;i>=0;i--)
01408     {
01409         ePlayer * lp = ePlayer::PlayerConfig(i); 
01410         if ( lp && lp->netPlayer )
01411         {
01412             lp->netPlayer->loginWanted = true;
01413             se_WantLogin( lp );
01414         }
01415     }
01416 }

Here is the call graph for this function:

Here is the caller graph for this function:

void ePlayer::SendAuthNames (  )  [static]

sends authentication names and authentication wishes for all local players

Definition at line 1355 of file ePlayer.cpp.

References MAX_PLAYERS, nCLIENT, PlayerConfig(), se_WantLogin(), and sn_GetNetState().

Referenced by gGame::GameLoop(), and sg_PlayerMenu().

01356 {
01357     // only meaningful on client
01358     if( sn_GetNetState() != nCLIENT )
01359     {
01360         return;
01361     }
01362     for(int i=MAX_PLAYERS-1;i>=0;i--)
01363     {
01364         se_WantLogin( ePlayer::PlayerConfig(i) );
01365     }
01366 }

Here is the call graph for this function:

Here is the caller graph for this function:

void ePlayer::Init (  )  [static]

Definition at line 3630 of file ePlayer.cpp.

References uPlayerPrototype::id, MAX_INSTANT_CHAT, MAX_PLAYERS, MAX_VIEWPORTS, s_newViewportBelongsToPlayer, se_instantChatAction, tOutput::SetTemplateParameter(), tNEW, and vpbtp.

Referenced by main().

03632                   {
03633     se_Players = tNEW( ePlayer[MAX_PLAYERS] );
03634 
03635     int i;
03636     for(i=MAX_INSTANT_CHAT-1;i>=0;i--){
03637         tString id;
03638         id << "INSTANT_CHAT_";
03639         id << i+1;
03640         tOutput desc;
03641         desc.SetTemplateParameter(1, i+1);
03642         desc << "$input_instant_chat_text";
03643 
03644         tOutput help;
03645         help.SetTemplateParameter(1, i+1);
03646         help << "$input_instant_chat_help";
03647         ePlayer::se_instantChatAction[i]=tNEW(uActionPlayer) (id, desc, help);
03648         //,desc,       "Issues a special instant chat macro.");
03649     }
03650 
03651 
03652     for(i=MAX_VIEWPORTS-1;i>=0;i--){
03653         tString id;
03654         id << "VIEWPORT_TO_PLAYER_";
03655         id << i+1;
03656         vpbtp[i] = tNEW(tConfItem<int>(id,"$viewport_belongs_help",
03657                                        s_newViewportBelongsToPlayer[i]));
03658         s_newViewportBelongsToPlayer[i]=i;

Here is the call graph for this function:

Here is the caller graph for this function:

void ePlayer::Exit (  )  [static]

Definition at line 3660 of file ePlayer.cpp.

Referenced by main().

03662                   {
03663     int i;
03664     for(i=MAX_INSTANT_CHAT-1;i>=0;i--)
03665         tDESTROY(ePlayer::se_instantChatAction[i]);
03666 
03667     for(i=MAX_VIEWPORTS-1;i>=0;i--)
03668         tDESTROY(vpbtp[i]);
03669 
03670     delete[] se_Players;

Here is the caller graph for this function:


Friends And Related Function Documentation

friend class eMenuItemChat [friend]

Definition at line 63 of file ePlayer.h.


Member Data Documentation

uActionPlayer ePlayer::s_chat [static, private]

Definition at line 64 of file ePlayer.h.

tConfItemBase* ePlayer::configuration[PLAYER_CONFITEMS] [private]

Definition at line 66 of file ePlayer.h.

Referenced by DeleteConfitems(), and StoreConfitem().

int ePlayer::CurrentConfitem [private]

Definition at line 67 of file ePlayer.h.

Referenced by DeleteConfitems(), ePlayer(), and StoreConfitem().

tString ePlayer::name

Definition at line 71 of file ePlayer.h.

Referenced by gMenuItemPlayer::Enter(), Name(), and sg_PlayerMenu().

tString ePlayer::globalID

Definition at line 72 of file ePlayer.h.

Referenced by ePlayer(), PasswordCallback(), se_WantLogin(), and sg_PlayerMenu().

tString ePlayer::teamname

Definition at line 74 of file ePlayer.h.

Referenced by ePlayer(), sg_PlayerMenu(), and Teamname().

bool ePlayer::centerIncamOnTurn

Definition at line 75 of file ePlayer.h.

Referenced by ePlayer(), and sg_PlayerMenu().

bool ePlayer::wobbleIncam

Definition at line 76 of file ePlayer.h.

Referenced by ePlayer(), and sg_PlayerMenu().

bool ePlayer::autoSwitchIncam

Definition at line 77 of file ePlayer.h.

Referenced by ePlayer(), and sg_PlayerMenu().

bool ePlayer::spectate

Definition at line 79 of file ePlayer.h.

Referenced by gMenuItemPlayer::Enter(), ePlayer(), sg_PlayerMenu(), ePlayerNetID::SpectateAll(), and ePlayerNetID::Update().

bool ePlayer::stealth

Definition at line 80 of file ePlayer.h.

Referenced by ePlayer(), sg_PlayerMenu(), and ePlayerNetID::Update().

bool ePlayer::autoLogin

Definition at line 81 of file ePlayer.h.

Referenced by ePlayer(), and sg_PlayerMenu().

bool ePlayer::nameTeamAfterMe

Definition at line 83 of file ePlayer.h.

Referenced by ePlayer(), sg_PlayerMenu(), and ePlayerNetID::Update().

int ePlayer::favoriteNumberOfPlayersPerTeam

Definition at line 84 of file ePlayer.h.

Referenced by ePlayer(), sg_PlayerMenu(), and ePlayerNetID::Update().

eCamMode ePlayer::startCamera

Definition at line 86 of file ePlayer.h.

Referenced by ePlayer(), and sg_PlayerMenu().

bool ePlayer::allowCam[CAMERA_COUNT]

Definition at line 87 of file ePlayer.h.

Referenced by ePlayer(), and sg_PlayerMenu().

int ePlayer::startFOV

Definition at line 88 of file ePlayer.h.

Referenced by ePlayer(), and sg_PlayerMenu().

bool ePlayer::smartCustomGlance

flag making the smart camera use the custom settings for glancing

Definition at line 89 of file ePlayer.h.

Referenced by ePlayer(), and sg_PlayerMenu().

tJUST_CONTROLLED_PTR<eCockpitPrototype> ePlayer::cockpit

Definition at line 93 of file ePlayer.h.

Referenced by display_cockpit_lucifer().

int ePlayer::rgb[3]

Definition at line 95 of file ePlayer.h.

Referenced by ePlayer(), operator<<(), sg_PlayerMenu(), and ePlayerNetID::Update().

tString ePlayer::instantChatString[MAX_INSTANT_CHAT]

Definition at line 97 of file ePlayer.h.

Referenced by ePlayer(), and sg_PlayerMenu().

uActionPlayer * ePlayer::se_instantChatAction [static]

Definition at line 100 of file ePlayer.h.

Referenced by Init().


The documentation for this class was generated from the following files:
Generated on Sat Mar 15 23:27:01 2008 for Armagetron Advanced by  doxygen 1.5.4