You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ryzom-core/code/ryzom/client/src/npc_icon.h

282 lines
9.1 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/>.
#ifndef CL_NPC_ICON_H
#define CL_NPC_ICON_H
#include "nel/misc/types_nl.h"
#include "game_share/entity_types.h"
#include "game_share/msg_client_server.h"
#include "cdb.h"
#include "entity_cl.h"
#include "interface_v3/view_radar.h"
#include <string>
#include <map>
#include <set>
namespace NLMISC
{
class CBitMemStream;
};
namespace NPC_ICON
{
// This enum maps TNPCMissionGiverState and adds some new values
enum TNPCIconId
{
IconNone = AwaitingFirstData,
IconNotAMissionGiver = NotAMissionGiver,
IconListHasOutOfReachMissions = ListHasOutOfReachMissions,
IconListHasAlreadyTakenMissions = ListHasAlreadyTakenMissions,
IconListHasAvailableMission = ListHasAvailableMission,
IconAutoHasUnavailableMissions = AutoHasUnavailableMissions,
IconAutoHasAvailableMission = AutoHasAvailableMission,
IconStepMission,
NbNPCIcons
};
};
/**
* Description of a mission giver NPC.
* Fed from the server on request by CNPCIconCache.
*/
class CNPCMissionGiverDesc
{
public:
/// Constructor
CNPCMissionGiverDesc() : _MissionGiverState(NPC_ICON::AwaitingFirstData), _IsDescTransient(true), _HasChanged(false)
{}
// Current assignment operator: bitwise copy
/// Return the current state
NPC_ICON::TNPCMissionGiverState getState() const { return _MissionGiverState; }
/// Return the time of last update (only valid if getState() != NPC_ICON::AwaitingFirstData)
NLMISC::TGameCycle getLastUpdateTimestamp() const { return _LastUpdateTimestamp; }
/// Return true if we are awaiting a description update
bool isDescTransient() const { return _IsDescTransient; }
/// Set as transient when about to be updated
void setDescTransient() { _IsDescTransient = true; }
/// Return true if state changed since the previous update
bool hasChanged() const { return _HasChanged; }
/// Set if state changed or not
void setChanged(bool changed) { _HasChanged = changed; }
/// Called on receival of update for this NPC. Return true if something has changed.
bool updateMissionAvailabilityForThisChar(NPC_ICON::TNPCMissionGiverState state);
/// Get debug dump
std::string getDump() const;
private:
NPC_ICON::TNPCMissionGiverState _MissionGiverState;
NLMISC::TGameCycle _LastUpdateTimestamp;
bool _IsDescTransient;
bool _HasChanged;
};
typedef uint32 TNPCIconCacheKey;
/**
* NPC icon management system.
* Tells which icons to display above NPCs, using data from either the server database
* (for mission steps) or requesting and caching data from the server (for mission givers).
*/
class CNPCIconCache
{
public:
/**
* Description of an icon (main texture + optional overlay).
* The spotId tells which small icon, and in which render layer, to display in the radar.
*/
class CNPCIconDesc
{
public:
void init(const std::string& main, const std::string& over, CViewRadar::TRadarSpotId spotId=CViewRadar::Std) { _TextureMain=main; _TextureOver=over; _SpotId=spotId; }
const std::string& getTextureMain() const { return _TextureMain; }
const std::string& getTextureOver() const { return _TextureOver; }
CViewRadar::TRadarSpotId getSpotId() const { return _SpotId; }
private:
std::string _TextureMain;
std::string _TextureOver;
CViewRadar::TRadarSpotId _SpotId;
};
/// Accessor for singleton
static CNPCIconCache& getInstance()
{
if (!_Instance)
_Instance = new CNPCIconCache;
return *_Instance;
}
/// Release singleton
static void release();
/// Return key by entity (or 0 if entity if icon cache is N/A for this entity)
inline static TNPCIconCacheKey entityToKey(const CEntityCL *entity)
{
return entity->npcAlias();
}
/**
* Return the filename of the icon to display for the specified NPC, using the following precedence:
* 1. Icon for the case when the character has a mission step to do with the NPC (Step icon)
* 2. Icon for the case when the character may or may not take a mission with the NPC (Auto or List icon)
* 3. No mission related with this NPC (empty strings returned)
*/
const CNPCIconCache::CNPCIconDesc& getNPCIcon(const CEntityCL *entity, bool bypassEnabled = false);
/// Init the system in either enabled or disabled state
void init(bool enabled) { _Enabled = enabled; }
/// Add DB observers
void addObservers();
/// Remove DB observers
void removeObservers();
/// Request an update about proposed missions of all qualifying npcs in vision, from the server
void onEventForMissionAvailabilityForThisChar();
/// Update routine, to be called from main loop
void update();
/// Enable or disable the system
void setEnabled(bool b);
/// Return the main enabled state
bool enabled() const { return _Enabled; }
/// Get debug dump
std::string getDump() const;
protected:
class CMissionStartStopObserver : public ICDBNode::IPropertyObserver
{
public:
virtual void update(ICDBNode* node);
}
MissionStartStopObserver;
class CMissionNpcAliasObserver : public ICDBNode::IPropertyObserver
{
public:
virtual void update(ICDBNode* node);
}
MissionNpcAliasObserver;
class CMissionPrerequisitEventObserver : public ICDBNode::IPropertyObserver
{
public:
virtual void update(ICDBNode* node);
}
MissionPrerequisitEventObserver;
/// Request an update about proposed missions of the specified npc, from the server.
void queryMissionGiverData(TNPCIconCacheKey npcIconCacheKey);
friend struct commands_queryMissionGiverDataClass;
/** Request an update about proposed missions on all qualifying visible NPCs, from the server.
* If olderThan==0, all qualifying (i.e. that have missions) NPCs are included (and a request
* is sent even for transient descriptions), whereas with a positive delay, only NPCs with
* information old than Now-olderThan are included and transient descriptions are ignored.
*/
void queryAllVisibleMissionGiverData(NLMISC::TGameCycle olderThan);
/** Update visible NPCs related to missions in progress, regarding
* both missions actors (Step icon) and mission givers' proposed missions (Auto/List icon):
* - when a mission is taken (started, new TITLE in database)
* - when a mission is completed or failed (FINISHED changed in database)
*/
void onEventForMissionInProgress();
friend class CMissionStartStopObserver;
/// Update visible NPCs related to missions in progress, regarding missions actors (Step icon)
void onNpcAliasChangedInMissionGoals();
friend class CMissionNpcAliasObserver;
/// Called on receival of update for this NPC. Return true if something has changed.
bool onReceiveMissionAvailabilityForThisChar(TNPCIconCacheKey npcIconCacheKey, NPC_ICON::TNPCMissionGiverState state);
friend void impulseSetNpcIconDesc(NLMISC::CBitMemStream &impulse);
/// Called on receival of new timer delay
void setMissionGiverTimer(NLMISC::TGameCycle delay);
friend void impulseSetNpcIconTimer(NLMISC::CBitMemStream &impulse);
/// Return true if the specified NPC is involved in current mission goals
bool isNPCaCurrentGoal(TNPCIconCacheKey npcIconCacheKey) const;
/// Store keys of current goals when current goals are changed
void storeKeysOfCurrentGoals();
/// Called when data have been modified
void refreshIconsOfScene(bool force = false);
private:
/// Private constructor (singleton)
CNPCIconCache();
typedef std::map<TNPCIconCacheKey, CNPCMissionGiverDesc> CMissionGiverMap;
/// Map of mission giver descriptions
CMissionGiverMap _MissionGivers;
typedef std::vector<TNPCIconCacheKey> CSmallKeyList;
/// List of NPCs involved in current goals (typically, contains 0 to 3 elements)
CSmallKeyList _KeysOfCurrentGoals;
/// List of NPCs for which the description is to be requested at the current update
CSmallKeyList _DescriptionsToRequest;
/// Used by update() to do tick-update tasks
NLMISC::TGameCycle _LastRequestTimestamp;
/// Used by update() to do low frequency tasks
NLMISC::TGameCycle _LastTimerUpdateTimestamp;
/// Descriptions of icons for each case
CNPCIconDesc _Icons[NPC_ICON::NbNPCIcons];
/// Main switch to disable the system
bool _Enabled;
// See in .cpp
static NLMISC::TGameCycle _CacheRefreshTimerDelay;
static NLMISC::TGameCycle _CatchallTimerPeriod;
/// Instance of singleton
static CNPCIconCache *_Instance;
};
#endif // CL_NPC_ICON_H