1. Соблюдайте Правила форума и проявляйте уважение к другим участникам беседы.

[GHost One solution fix] m_GameOverTime in override

Тема в разделе 'Кодинг/Собственные решения', создана пользователем Synth (LM), 28 авг 2011.

  1. Synth (LM) Пантограф!

    Сообщения:
    2.762
    Спасибы:
    172
    Сборка бота GHost:
    My own version of GhostOne
    Дата начала использования бота:
    15.06.2008
    Skype:
    Мой статус
    Побеседовав с диалсом, мы пришли к выводу, что в коде One ошибка, а именно:
    game.cpp
    ~124 строка
    Код:
    uint32_t endtime = m_GameOverTime;
    	if (endtime == 0)
    		uint32_t endtime = GetTime();
    Заменить на
    Код:
    uint32_t endtime = GetTime();
    Т.к. перменная m_GameOverTime, без прямого наследствия всегда равна 0.
    Это раз, во-вторых:
    команда !override - если вы делали команду которая вновь запускает таймер окончания игры, то таймер запускается с того же момента, на котором был установлен. Кому это не нужно, можно заменить это, указав прямое наследствие класса для переменной m_GameOverTime:
    Заменить все m_GameOverTime в команде !override на CBaseGame::m_GameOverTime
  2. Deals Старожила

    Сообщения:
    784
    Спасибы:
    21
    Сборка бота GHost:
    Ghost One 1.7.266
    Skype:
    Мой статус
    game.h:
    Удаляем
    Код:
            uint32_t m_GameOverTime;                                        // GetTime when the game was over as reported by the stats class
    
    В конструкторе класса в game.cpp:
    Код:
    //
    // CGame
    //
    
    CGame :: CGame( CGHost *nGHost, CMap *nMap, CSaveGame *nSaveGame, uint16_t nHostPort, unsigned char nGameState, string nGameName, string nOwnerName, string nCreatorName, string nCreatorServer ) : CBaseGame( nGHost, nMap, nSaveGame, nHostPort, nGameState, nGameName, nOwnerName, nCreatorName, nCreatorServer )
    {
    	m_DBBanLast = NULL;
    	m_DBGame = new CDBGame( 0, string( ), m_Map->GetMapPath( ), string( ), string( ), string( ), 0 );
    
    	if( m_Map->GetMapType( ) == "w3mmd" )
    		m_Stats = new CStatsW3MMD( this, m_Map->GetMapStatsW3MMDCategory( ) );
    	else if( m_Map->GetMapType( ) == "dota" )
    		m_Stats = new CStatsDOTA( this );
    	else
    		m_Stats = NULL;
    
    	m_CallableGameAdd = NULL;
    
    	m_GameOverTime = 0;
    	m_GameLoadedTime = 0;
    	m_Server = nCreatorServer;
    }
    Удаляем
    Код:
    m_GameOverTime = 0;
    В деструкторе класса в game.cpp:
    Код:
    CGame :: ~CGame( )
    {
    	uint32_t timehasleft;
    	uint32_t endtime = m_GameOverTime;
    	if (endtime == 0)
    		endtime = GetTime();
    	for( vector<CDBGamePlayer *> :: iterator i = m_DBGamePlayers.begin( ); i != m_DBGamePlayers.end( ); i++ ) {
    		if (IsAutoBanned((*i)->GetName())) 
    		{ 
    			timehasleft = (*i)->GetLeavingTime();
    			if (endtime>timehasleft+m_GHost->m_AutoBanGameEndMins*60) 
    			{ 
    				string Reason = CustomReason( timehasleft, string(), (*i)->GetName() );
    				Reason = "Autobanned"+Reason;
    				CONSOLE_Print( "[AUTOBAN: " + m_GameName + "] Autobanning " + (*i)->GetName( ) + " (" + Reason +")" );
    
    				m_GHost->m_Callables.push_back( m_GHost->m_DB->ThreadedBanAdd( (*i)->GetSpoofedRealm(), (*i)->GetName( ), (*i)->GetIP(), m_GameName, "AUTOBAN", Reason, 0, 0 ));
    			}
    		}
    	}
    Заменяем:
    Код:
    	uint32_t endtime = m_GameOverTime;
    	if (endtime == 0)
    		endtime = GetTime();
    на:
    Код:
    uint32_t endtime = GetTime();
    Поясняю. В GHost One обнаружили ошибку:
    Дважды объявлена переменная m_GameOverTime...
    Одна в классе CGame в защищенном методе и одна тоже в защищенном методе класса CBaseGame...
    Т.к. класс CGame унаследован от CBaseGame и одинаковые переменные объявлены в защищенных методах - они доступны в обеих классах. Но переопределения не происходит т.к. объявлены в разных классах. И каждый класс использует соответственно свою переменную...
    В классе CGame комманда оверрайда якобы сбрасывает m_GameOverTime базового класса на 0... но т.к. существует в наследуемом классе переменная m_GameOverTime, то изменяет ее. В итоге фактически комманда работала не правильно.
    Решения пути.
    Либо четко указать что нужно изменять переменную базового класса из производного CBaseGame :: m_GameOverTime = 0; либо переименовать переменную производного класса. Но судя по коду данная переменная утратила силу в свази с комментарием в game.cpp
    Код:
    void CGame :: EventPlayerAction( CGamePlayer *player, CIncomingAction *action )
    {
    	CBaseGame :: EventPlayerAction( player, action );
    
    	// give the stats class a chance to process the action
    
    	if( m_Stats && m_Stats->ProcessAction( action ) && m_GameEndedTime == 0 )
    	{
    //		CONSOLE_Print( "[GAME: " + m_GameName + "] gameover timer started (stats class reported game over)" );
    		SendEndMessage( );
    		m_GameEnded = true;
    		m_GameEndedTime = GetTime( );
    //		m_GameOverTime = GetTime( );
    	}
    }
    Поэтому ее проще удалить. При удалении наследуемый класс начнет использовать переменную из базового.
  3. fake Старожила

    Сообщения:
    1.624
    Спасибы:
    19
    Дата начала использования бота:
    11.11.11
    не пытайся ставить умные слова, которые прочитал в книжке по с++, в случайные места, не зная их значения, спасибо.
  4. Synth (LM) Пантограф!

    Сообщения:
    2.762
    Спасибы:
    172
    Сборка бота GHost:
    My own version of GhostOne
    Дата начала использования бота:
    15.06.2008
    Skype:
    Мой статус
    Хуже того, мне это диалс сказал - грубо говоря, я его процитировал.
  5. Deals Старожила

    Сообщения:
    784
    Спасибы:
    21
    Сборка бота GHost:
    Ghost One 1.7.266
    Skype:
    Мой статус
    :-o я в своем посте правильно написал. Ты что-то перепутал.