khanat-opennel-code/code/ryzom/client/src/interface_v3/bar_manager.cpp
2010-05-07 11:06:20 +02:00

762 lines
25 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "bar_manager.h"
#include "interface_manager.h"
#include "interface_expr.h"
#include "../time_client.h"
using namespace std;
using namespace NLMISC;
// ***************************************************************************
// LOG, for debug
#define ALLOW_BAR_LOG 0
// don't change this (ensure no bug in final version)
#if FINAL_VERSION
#undef ALLOW_BAR_LOG
#define ALLOW_BAR_LOG 0
#endif
#if ALLOW_BAR_LOG
# define barInfoLog nlinfo
#else // NL_RELEASE
# ifdef NL_COMP_VC71
# define barInfoLog __noop
# else
# define barInfoLog 0&&
# endif
#endif // NL_RELEASE
static const char *entryTypeToStr(CBarManager::TEntryType et)
{
switch(et)
{
case CBarManager::EntityType: return "Entity"; break;
case CBarManager::TeamMemberType: return "TeamMember"; break;
case CBarManager::AnimalType: return "Animal"; break;
case CBarManager::TargetType: return "Target"; break;
default: return "Unknown (Error!!)"; break;
}
}
// ***************************************************************************
CBarManager *CBarManager::_Instance= NULL;
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
CBarManager::CBarDataEntry::CBarDataEntry()
{
clear();
resetDB();
}
// ***************************************************************************
void CBarManager::CBarDataEntry::clear()
{
DataSetId= CLFECOMMON::INVALID_CLIENT_DATASET_INDEX;
BarInfo.reset();
}
// ***************************************************************************
void CBarManager::CBarDataEntry::resetDB()
{
UIDIn= NULL;
PresentIn= NULL;
for(uint sc=0;sc<SCORES::NUM_SCORES;sc++)
{
ScoreIn[sc]= NULL;
ScoreOut[sc]= NULL;
}
}
// ***************************************************************************
void CBarManager::CBarDataEntry::connectDB(const std::string &baseDBin, const std::string &baseDBout, const std::string &presentDB,
const std::string &hpDB, const std::string &sapDB, const std::string &staDB, const std::string &focusDB)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
// can only manage 4 scores here
nlctassert(SCORES::NUM_SCORES==4);
// try to connect each input entry (don't create)
if(!baseDBin.empty())
{
UIDIn= pIM->getDbProp(baseDBin+"UID", false);
if(!presentDB.empty())
PresentIn= pIM->getDbProp(baseDBin+presentDB, false);
if(!hpDB.empty())
ScoreIn[SCORES::hit_points]= pIM->getDbProp(baseDBin+hpDB, false);
if(!sapDB.empty())
ScoreIn[SCORES::sap]= pIM->getDbProp(baseDBin+sapDB, false);
if(!staDB.empty())
ScoreIn[SCORES::stamina]= pIM->getDbProp(baseDBin+staDB, false);
if(!focusDB.empty())
ScoreIn[SCORES::focus]= pIM->getDbProp(baseDBin+focusDB, false);
}
// try to connect each output entry (don't create)
if(!baseDBout.empty())
{
if(!hpDB.empty())
ScoreOut[SCORES::hit_points]= pIM->getDbProp(baseDBout+hpDB, false);
if(!sapDB.empty())
ScoreOut[SCORES::sap]= pIM->getDbProp(baseDBout+sapDB, false);
if(!staDB.empty())
ScoreOut[SCORES::stamina]= pIM->getDbProp(baseDBout+staDB, false);
if(!focusDB.empty())
ScoreOut[SCORES::focus]= pIM->getDbProp(baseDBout+focusDB, false);
}
}
// ***************************************************************************
void CBarManager::CBarDataEntry::flushDBOut()
{
for(uint sc=0;sc<SCORES::NUM_SCORES;sc++)
{
if(ScoreOut[sc])
ScoreOut[sc]->setValue8(BarInfo.Score[sc]);
}
}
// ***************************************************************************
void CBarManager::CBarDataEntry::modifyFromDBIn(CBarInfo &barInfo) const
{
for(uint sc=0;sc<SCORES::NUM_SCORES;sc++)
{
if(ScoreIn[sc])
barInfo.Score[sc]= ScoreIn[sc]->getValue8();
}
}
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
CBarManager::CBarManager()
{
// if more than 256 entities, must change MaxEntity
nlctassert(sizeof(CLFECOMMON::TCLEntityId)==1);
// Allocate the array now
nlctassert(MaxEntryType==4);
_EntryBars[EntityType].resize(MaxEntity);
_EntryBars[TeamMemberType].resize(MaxTeamMember);
_EntryBars[AnimalType].resize(MaxAnimal);
_EntryBars[TargetType].resize(MaxTarget);
// no msg still sent
_LastUserBarMsgNumber= 0;
}
// ***************************************************************************
void CBarManager::releaseInstance()
{
if( _Instance )
{
delete _Instance;
_Instance = NULL;
}
}
// ***************************************************************************
void CBarManager::initInGame()
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
//resetShardSpecificData(); // directly called by CFarTP::disconnectFromPreviousShard()
/* *** Verify that MaxTeamMember is correct according to database
change MaxTeamMember if no more the case
*/
uint i=0;
while( pIM->getDbProp(toString("SERVER:GROUP:%d:NAME", i), false) )
i++;
nlassert(i==MaxTeamMember);
// *** create connexion to the Local Output database
for(i=0;i<_EntryBars[TeamMemberType].size();i++)
{
// don't connect FOCUS, since not setuped by SERVER
_EntryBars[TeamMemberType][i].connectDB(
toString("SERVER:GROUP:%d:",i),
toString("UI:VARIABLES:BARS:TEAM:%d:",i),
"PRESENT",
"HP", "SAP", "STA", "");
}
for(i=0;i<_EntryBars[AnimalType].size();i++)
{
// don't connect STA, SAP and FOCUS for animal, since they don't have
_EntryBars[AnimalType][i].connectDB(
toString("SERVER:PACK_ANIMAL:BEAST%d:",i),
toString("UI:VARIABLES:BARS:ANIMAL:%d:",i),
"STATUS",
"HP", "", "", "");
}
nlassert(_EntryBars[TargetType].size()==1);
_EntryBars[TargetType][0].connectDB(
"SERVER:TARGET:BARS:",
"UI:VARIABLES:BARS:TARGET:",
"", // no present flag for target (not so important)
"HP", "SAP", "STA", "FOCUS");
// NB: don't connect the DB for entities, since CEntityCL read it directly from getBarsByEntityId() (simpler and faster)
// *** init _EntryScoreFlags
nlctassert(MaxEntryType==4);
nlctassert(SCORES::NUM_SCORES==4);
// For each entry type, tells what score they can affect (see DB connection above)
_EntryScoreFlags[EntityType]= HpFlag | SapFlag | StaFlag | FocusFlag; // all
_EntryScoreFlags[TeamMemberType]= HpFlag | SapFlag | StaFlag; // anything but focus
_EntryScoreFlags[AnimalType]= HpFlag; // Hp only
_EntryScoreFlags[TargetType]= HpFlag | SapFlag | StaFlag | FocusFlag; // all
// *** create connexion for User Bar mgt
// user now can only manage 4 scores
nlctassert(SCORES::NUM_SCORES==4);
// Input max values
_UserScores[SCORES::hit_points].DBInMax= pIM->getDbProp("SERVER:CHARACTER_INFO:SCORES0:Max", false);
_UserScores[SCORES::sap].DBInMax= pIM->getDbProp("SERVER:CHARACTER_INFO:SCORES2:Max", false);
_UserScores[SCORES::stamina].DBInMax= pIM->getDbProp("SERVER:CHARACTER_INFO:SCORES1:Max", false);
_UserScores[SCORES::focus].DBInMax= pIM->getDbProp("SERVER:CHARACTER_INFO:SCORES3:Max", false);
// Output real values
_UserScores[SCORES::hit_points].DBOutVal= pIM->getDbProp("UI:VARIABLES:USER:HP", false);
_UserScores[SCORES::sap].DBOutVal= pIM->getDbProp("UI:VARIABLES:USER:SAP", false);
_UserScores[SCORES::stamina].DBOutVal= pIM->getDbProp("UI:VARIABLES:USER:STA", false);
_UserScores[SCORES::focus].DBOutVal= pIM->getDbProp("UI:VARIABLES:USER:FOCUS", false);
// Output ratio values
_UserScores[SCORES::hit_points].DBOutRatio= pIM->getDbProp("UI:VARIABLES:USER:HP_RATIO", false);
_UserScores[SCORES::sap].DBOutRatio= pIM->getDbProp("UI:VARIABLES:USER:SAP_RATIO", false);
_UserScores[SCORES::stamina].DBOutRatio= pIM->getDbProp("UI:VARIABLES:USER:STA_RATIO", false);
_UserScores[SCORES::focus].DBOutRatio= pIM->getDbProp("UI:VARIABLES:USER:FOCUS_RATIO", false);
}
// ***************************************************************************
void CBarManager::releaseInGame()
{
// Reset all, and also the DB out
for(uint type=0;type<MaxEntryType;type++)
{
for(uint i=0;i<_EntryBars[type].size();i++)
{
_EntryBars[type][i].clear();
_EntryBars[type][i].resetDB();
}
}
// Reset the map
_UIDBars.clear();
}
// ***************************************************************************
void CBarManager::resetShardSpecificData()
{
// Reset update counter to update properly when reselecting character
_LastUserBarMsgNumber = 0;
}
// ***************************************************************************
void CBarManager::addEntry(TEntryType type, uint entryId, uint dataSetId)
{
std::vector<CBarDataEntry> &entryArray= _EntryBars[type];
nlassert(entryId<entryArray.size());
barInfoLog("BARS: addEntry(%s, eid=%d, dsid=%x)", entryTypeToStr(type), entryId, dataSetId);
// if bad id, quit
if(dataSetId==CLFECOMMON::INVALID_CLIENT_DATASET_INDEX)
return;
// if already registered, quit
if(entryArray[entryId].DataSetId==dataSetId)
return;
// remove the preceding entry, reseting values if necessary
delEntry(type, entryId);
// Add me to list of entries
CBarDataEntry &bde= entryArray[entryId];
bde.DataSetId= dataSetId;
// Add the entry connexion to map by DataSetId
CBarDataUID &barUID= _UIDBars[dataSetId];
barUID.EntryId[type].insert(entryId);
// Special case: if the entry added is the user (slot 0), then force the correct bars info
// This is important because the UserEntity can be created AFTER the receive of USER:BARS message.
if(dataSetId==_EntryBars[EntityType][0].DataSetId)
{
barUID.BarInfo= _UserBarInfo;
}
// Copy the current Bar Info from the map by dataSetId in case it exists before...
// Eg: an entity comes in vision (EntityType entry) while precedingly available in TeamMemberType Entry
bde.BarInfo= barUID.BarInfo;
// then report to DB (if any)
bde.flushDBOut();
}
// ***************************************************************************
void CBarManager::delEntry(TEntryType type, uint entryId)
{
std::vector<CBarDataEntry> &entryArray= _EntryBars[type];
nlassert(entryId<entryArray.size());
barInfoLog("BARS: delEntry(%s, eid=%d)", entryTypeToStr(type), entryId);
// if a DataSetId was registered before
uint dataSetId= entryArray[entryId].DataSetId;
if(dataSetId!=CLFECOMMON::INVALID_CLIENT_DATASET_INDEX)
{
// then unconnect this from the map by UID
_UIDBars[dataSetId].EntryId[type].erase(entryId);
// if no more connexion are made to this UID
if(_UIDBars[dataSetId].noMoreEntry())
{
// erase it
_UIDBars.erase(dataSetId);
}
}
// clear entry
entryArray[entryId].clear();
// flush the clear to the DB if any
entryArray[entryId].flushDBOut();
}
// ***************************************************************************
void CBarManager::addEntity(CLFECOMMON::TCLEntityId entityId, uint dataSetId)
{
addEntry(EntityType, entityId, dataSetId);
}
// ***************************************************************************
void CBarManager::delEntity(CLFECOMMON::TCLEntityId entityId)
{
delEntry(EntityType, entityId);
}
// ***************************************************************************
void CBarManager::addTeamMember(uint teamMemberId, uint dataSetId)
{
addEntry(TeamMemberType, teamMemberId, dataSetId);
}
// ***************************************************************************
void CBarManager::delTeamMember(uint teamMemberId)
{
delEntry(TeamMemberType, teamMemberId);
}
// ***************************************************************************
void CBarManager::addAnimal(uint paId, uint dataSetId)
{
addEntry(AnimalType, paId, dataSetId);
}
// ***************************************************************************
void CBarManager::delAnimal(uint paId)
{
delEntry(AnimalType, paId);
}
// ***************************************************************************
void CBarManager::addTarget(uint dataSetId)
{
addEntry(TargetType, 0, dataSetId);
}
// ***************************************************************************
void CBarManager::delTarget()
{
delEntry(TargetType, 0);
}
// ***************************************************************************
void CBarManager::updateBars(uint dataSetId, CBarInfo barInfo, TGameCycle serverTick, uint scoreFlags)
{
// if dataSetId not registered, quit
TUIDToDatas::iterator it= _UIDBars.find(dataSetId);
if(it==_UIDBars.end())
return;
barInfoLog("BARS: updateBars(dsid=%x, biHP=%d, t=%d, sf=%x", dataSetId, barInfo.Score[SCORES::hit_points], serverTick, scoreFlags);
// special Case: if the info is for the User (slot 0)
if(dataSetId==_EntryBars[EntityType][0].DataSetId)
{
/* Then override the bar info with the one received by USER:BARS message (always take this one)
For instance user bars can be received from VP or from TARGET database (if he targets himself)
But always consider the message USER:BARS as the most accurate one
*/
barInfo= _UserBarInfo;
}
// fill bar info, with relevant values only
CBarDataUID &barUid= it->second;
for(uint sc=0;sc<SCORES::NUM_SCORES;sc++)
{
// if the update affect this score, and if the modification date is more recent (or at least the same)
if( (scoreFlags&(1<<sc)) && serverTick>=barUid.ScoreDate[sc] )
{
// then change this score with the more recent one!
barUid.ScoreDate[sc]= serverTick;
barUid.BarInfo.Score[sc]= barInfo.Score[sc];
}
}
// and report result to all connected entries
for(uint type=0;type<MaxEntryType;type++)
{
// For any connected entries of this type (see EntryId definitio why a set is necessary)
std::set<uint>::iterator itEid= barUid.EntryId[type].begin();
std::set<uint>::iterator itEidEnd= barUid.EntryId[type].end();
for(;itEid!=itEidEnd;itEid++)
{
uint entryId= *itEid;
nlassert(entryId<_EntryBars[type].size());
CBarDataEntry &bde= _EntryBars[type][entryId];
// copy the bar info (with relevant values)
bde.BarInfo= barUid.BarInfo;
// and flush DB (if any)
bde.flushDBOut();
}
}
}
// ***************************************************************************
void CBarManager::updateEntryFromDBNoAddDel(TEntryType type, CBarDataEntry &bde)
{
// get the Bar Info, from the input DB of this entry (only values linked)
CBarInfo barInfo;
bde.modifyFromDBIn(barInfo);
// Get the last DB modification server tick
TGameCycle serverTick= 0;
/* To do this, I test all DB input, and choose the highest changeDate
This works because the branch is atomic (all DB are relevant to the others, and
therefore relevant agst the most recent one)
*/
if(bde.UIDIn && bde.UIDIn->getLastChangeGC() > serverTick )
serverTick= bde.UIDIn->getLastChangeGC();
if(bde.PresentIn && bde.PresentIn->getLastChangeGC() > serverTick )
serverTick= bde.PresentIn->getLastChangeGC();
for(uint sc=0;sc<SCORES::NUM_SCORES;sc++)
{
if( bde.ScoreIn[sc] && bde.ScoreIn[sc]->getLastChangeGC() > serverTick )
serverTick= bde.ScoreIn[sc]->getLastChangeGC();
}
// then update the bars
updateBars(bde.DataSetId, barInfo, serverTick, _EntryScoreFlags[type] );
}
// ***************************************************************************
void CBarManager::updateEntryFromDB(TEntryType type, uint entryId)
{
std::vector<CBarDataEntry> &entryArray= _EntryBars[type];
nlassert(entryId<entryArray.size());
CBarDataEntry &bde= entryArray[entryId];
// if the UID db was not found, can't do nothing... => abort
if(bde.UIDIn==NULL)
return;
// get the new UID from the SERVER DB
uint newDataSetId= bde.UIDIn->getValue32();
// if present flag is linked, and if 0, then force invalid data set id
if(bde.PresentIn && bde.PresentIn->getValue32()==0)
newDataSetId= CLFECOMMON::INVALID_CLIENT_DATASET_INDEX;
// *** if the data set id does not correspond as the cached one
if(newDataSetId!=bde.DataSetId)
{
// if deleted, delete this entry
if(newDataSetId==CLFECOMMON::INVALID_CLIENT_DATASET_INDEX)
delEntry(type, entryId);
// else add
else
addEntry(type, entryId, newDataSetId);
// should be changed
nlassert(bde.DataSetId==newDataSetId);
}
// *** update from DB
if(newDataSetId!=CLFECOMMON::INVALID_CLIENT_DATASET_INDEX)
{
updateEntryFromDBNoAddDel(type, bde);
}
}
// ***************************************************************************
void CBarManager::updateTeamMemberFromDB(uint teamMemberId)
{
updateEntryFromDB(TeamMemberType, teamMemberId);
}
// ***************************************************************************
void CBarManager::updateAnimalFromDB(uint paId)
{
updateEntryFromDB(AnimalType, paId);
}
// ***************************************************************************
void CBarManager::updateTargetFromDB()
{
/* Special case for Target. The DataSetId is not replaced with those in DB (setuped with setLocalTarget())
Instead, we ensure that the 2 match, else ignore DB change
*/
CBarDataEntry &bde= _EntryBars[TargetType][0];
// if the UID db was not found, can't do nothing... => abort
if(bde.UIDIn==NULL)
return;
// get the new UID from the SERVER DB
uint serverDataSetId= bde.UIDIn->getValue32();
barInfoLog("BARS: updateTargetFromDB(dsid=%x)", serverDataSetId);
// *** if the server data set id correspond to the local one (and not invalid), update from DB
if(serverDataSetId==bde.DataSetId && serverDataSetId!=CLFECOMMON::INVALID_CLIENT_DATASET_INDEX)
{
updateEntryFromDBNoAddDel(TargetType, bde);
}
}
// ***************************************************************************
void CBarManager::setLocalTarget(uint dataSetId)
{
CBarDataEntry &bde= _EntryBars[TargetType][0];
barInfoLog("BARS: setLocalTarget(dsid=%x)", dataSetId);
// *** if the data set id does not correspond as the cached one
if(dataSetId!=bde.DataSetId)
{
// if deleted, delete this entry
if(dataSetId==CLFECOMMON::INVALID_CLIENT_DATASET_INDEX)
delEntry(TargetType, 0);
// else add
else
addEntry(TargetType, 0, dataSetId);
// should be changed
nlassert(bde.DataSetId==dataSetId);
}
}
// ***************************************************************************
CBarManager::CBarInfo CBarManager::getBarsByEntityId(CLFECOMMON::TCLEntityId entityId) const
{
const std::vector<CBarDataEntry> &entityBars= _EntryBars[EntityType];
nlassert(entityId<entityBars.size());
return entityBars[entityId].BarInfo;
}
// ***************************************************************************
void CBarManager::setupUserBarInfo(uint8 msgNumber, sint32 hp, sint32 sap, sint32 sta, sint32 focus)
{
/*
Since we are not sure of the message order, use a little counter to discard old messages
suppose that cannot have more than a jump of 127 messages.
eg:
If i Receive: 0..1..4..3..2..5
This will be applied: 0..1..4........5
*/
// compute the difference beetween the msgNumber and the last received
sint32 diff;
if(msgNumber>=_LastUserBarMsgNumber)
diff= (sint32)msgNumber - (sint32)_LastUserBarMsgNumber;
else
diff= (sint32)msgNumber + 256 - (sint32)_LastUserBarMsgNumber;
// if too big difference, suppose a roll (eg last==255, cur=0, real diff==1)
if(diff>127)
diff-=256;
// if diff<0, means that the cur message is actually too old => discard
if(diff<0)
return;
else
{
// bkup last
_LastUserBarMsgNumber= msgNumber;
// user now can only manage 4 scores
nlctassert(SCORES::NUM_SCORES==4);
_UserScores[SCORES::hit_points].Score= hp;
_UserScores[SCORES::sap].Score= sap;
_UserScores[SCORES::stamina].Score= sta;
_UserScores[SCORES::focus].Score= focus;
// update actual database now.
for(uint i=0;i<SCORES::NUM_SCORES;i++)
{
// Clamp To 0, since used only by entries that don't need negative values (for comma mode)
if(_UserScores[i].DBOutVal) _UserScores[i].DBOutVal->setValue32(max((sint32)0,_UserScores[i].Score));
}
// Update the Player Entry
updateUserBars();
}
}
// ***************************************************************************
void CBarManager::updateUserBars()
{
// for all scores
for(uint i=0;i<SCORES::NUM_SCORES;i++)
{
CUserScore &us= _UserScores[i];
// get max value
sint32 maxVal= 1;
if(us.DBInMax)
{
maxVal= us.DBInMax->getValue32();
maxVal= max((sint32)1, maxVal);
}
// setup signed ratio. It is used for the view of Player interface
if(us.DBOutRatio)
{
sint32 v= UserBarMaxRatio*us.Score / maxVal;
clamp(v, (sint32)-UserBarMaxRatio, (sint32)UserBarMaxRatio);
us.DBOutRatio->setValue32(v);
}
// compute signed ratio -127 / 127, for CBarInfo replace
{
sint32 v= 127*us.Score / maxVal;
clamp(v, -127, 127);
_UserBarInfo.Score[i]= (sint8)v;
}
}
// replace the user Entry with the bar info.
// This is used only for the view of bars InScene, and in case the user target himself
uint userDataSetId= _EntryBars[EntityType][0].DataSetId;
if(userDataSetId!=CLFECOMMON::INVALID_CLIENT_DATASET_INDEX)
{
// Do a little cheat: force the update by retrieving the last update time in the BarData
TUIDToDatas::iterator it= _UIDBars.find(userDataSetId);
if(it!=_UIDBars.end())
{
TGameCycle serverTick= 0;
for(uint sc=0;sc<SCORES::NUM_SCORES;sc++)
{
if(it->second.ScoreDate[sc] > serverTick)
serverTick= it->second.ScoreDate[sc];
}
// update (user can only manage 4 scores for now)
nlctassert(SCORES::NUM_SCORES==4);
updateBars(userDataSetId, _UserBarInfo, serverTick, HpFlag | SapFlag | StaFlag | FocusFlag);
}
}
}
// ***************************************************************************
sint32 CBarManager::getUserScore(SCORES::TScores score)
{
nlassert((uint) score < SCORES::NUM_SCORES);
nlassert(_UserScores[score].DBOutVal); // initInGame() not called ?
return _UserScores[score].DBOutVal->getValue32();
}
// ***************************************************************************
// ***************************************************************************
// ACTION HANDLERS
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
DECLARE_INTERFACE_CONSTANT(getMaxAnimal, CBarManager::MaxAnimal);
DECLARE_INTERFACE_CONSTANT(getMaxTeamMember, CBarManager::MaxTeamMember);
// ***************************************************************************
class CAHBarManagerOnTarget : public IActionHandler
{
public:
virtual void execute(CCtrlBase * /* pCaller */, const string &/* Params */)
{
CBarManager::getInstance()->updateTargetFromDB();
}
};
REGISTER_ACTION_HANDLER(CAHBarManagerOnTarget, "bar_manager_on_target");
// ***************************************************************************
class CAHBarManagerOnTeam : public IActionHandler
{
public:
virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
{
uint index;
fromString(Params, index);
if(index<CBarManager::MaxTeamMember)
CBarManager::getInstance()->updateTeamMemberFromDB(index);
}
};
REGISTER_ACTION_HANDLER(CAHBarManagerOnTeam, "bar_manager_on_team");
// ***************************************************************************
class CAHBarManagerOnAnimal : public IActionHandler
{
public:
virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
{
uint index;
fromString(Params, index);
if(index<CBarManager::MaxAnimal)
CBarManager::getInstance()->updateAnimalFromDB(index);
}
};
REGISTER_ACTION_HANDLER(CAHBarManagerOnAnimal, "bar_manager_on_animal");
// ***************************************************************************
class CAHBarManagerOnUserScores : public IActionHandler
{
public:
virtual void execute(CCtrlBase * /* pCaller */, const string &/* Params */)
{
CBarManager::getInstance()->updateUserBars();
}
};
REGISTER_ACTION_HANDLER(CAHBarManagerOnUserScores, "bar_manager_on_user_scores");