// Ryzom - MMORPG Framework // 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 . #ifndef GS_FAME_H #define GS_FAME_H #include "nel/misc/string_mapper.h" #include "mirrored_data_set.h" #include "mirror_prop_value.h" #include "pvp_clan.h" #include "nel/misc/variable.h" /** NB : if you change the MAX_FACTION, you MUST also do the following : * 1 - change the mirror description file data_share/mirror_sheet/fame.dataset to add the additionnal entry (or remove if you reduce the value) * 2 - change the excel worksheet \\server\leveldesign\static_fame.xls : * * resize the sheet (on x and y axis, the sheet must remain square), * * update the macro Module1.ExportFame ligne 6 : Range("A1:CV100").Select : update the range to the new worksheet size */ const uint MAX_FACTION = 100; const sint32 NO_FAME = 0x7FFFFFFF; extern NLMISC::CVariable UseAsymmetricStaticFames; /** Give a simple access to * all the static fame values. * Static fames values include tribe to tribe and tribe to civilisation fames. */ class CStaticFames { public: class CTribeCultThreshold { public: CTribeCultThreshold() { Kami = 0; Karavan = 0; Neutral = 0; } void setKami(sint32 t) { Kami = t; } void setKaravan(sint32 t) { Karavan = t; } void setNeutral(sint32 t) { Neutral = t; } sint32 getKami() const { return Kami; } sint32 getKaravan() const { return Karavan; } sint32 getNeutral() const { return Neutral; } private: sint32 Kami; sint32 Karavan; sint32 Neutral; }; class CTribeCultThresholdPerCiv { public: bool getCultThresholdForCiv( PVP_CLAN::TPVPClan civ, sint32& kami, sint32& karavan, sint32& neutral) const { const CTribeCultThreshold * tc = 0; switch( civ ) { case PVP_CLAN::Matis: tc = &Matis; break; case PVP_CLAN::Fyros: tc = &Fyros; break; case PVP_CLAN::Tryker: tc = &Tryker; break; case PVP_CLAN::Neutral: tc = &Neutral; break; default: return false; } kami = tc->getKami(); karavan = tc->getKaravan(); neutral = tc->getNeutral(); return true; } uint32 FameIndex; CTribeCultThreshold Matis; CTribeCultThreshold Fyros; CTribeCultThreshold Tryker; CTribeCultThreshold Zorai; CTribeCultThreshold Neutral; }; // declare scoped constant value enum { /// Tag value for invalid faction index. INVALID_FACTION_INDEX = 0xffffffff }; static CStaticFames &getInstance() { if (_Instance == NULL) _Instance = new CStaticFames(); return *_Instance; } // release singleton static void releaseInstance(); // destructor ~CStaticFames(); /// Get the list of faction mapped names. const std::vector &getFactionNames() { return _FactionNames; } /// Get the name of a faction. const std::string &getFactionName(uint32 factionIndex); /// Convert the mapped name of a faction into an indexed value (allowing very fast access). uint getFactionIndex(NLMISC::TStringId factionName); /// Same as above but with that name as a string. uint getFactionIndex(const std::string &factionName); /** Get the fame value between two factions. There is no constraint on faction order because * fame values are reciprocal. */ sint32 getStaticFame(NLMISC::TStringId faction1, NLMISC::TStringId faction2); /// Same as above but with string name instead of mapped string. sint32 getStaticFame(const std::string &faction1, const std::string &faction2); /// Same as above but direct index instead of mapped string. sint32 getStaticFameIndexed(uint factionIndex1, uint factionIndex2); /** Get the propagation factor value between two factions. There is no constraint on faction order because * values are reciprocal. */ float getPropagationFactorIndexed(uint factionIndex1, uint factionIndex2) const; /// get the sheet associated with a faction const NLMISC::CSheetId & getFactionSheet(uint32 factionIndex) { if (factionIndex < _FactionSheets.size()) return _FactionSheets[factionIndex]; else return NLMISC::CSheetId::Unknown; } /// get the sheet associated with a faction uint getFactionIndexFromSheet(const NLMISC::CSheetId & sheet) { TFactionNameSheetList::iterator it = _FactionSheetIndex.find( sheet ); if ( it != _FactionSheetIndex.end() ) return (*it).second; else return INVALID_FACTION_INDEX; } // get client database index from fame index uint getDatabaseIndex( uint fameIndex ) { nlassert( _FameIndexToDatabaseIndex.size() > fameIndex ); return _FameIndexToDatabaseIndex[ fameIndex ]; } // get first tribe fame index uint getFirstTribeFameIndex() { return _FirstTribeFameIndex; } // get number of tribe fame index uint getNbTribeFameIndex() { return _FameTableSize - _FirstTribeFameIndex; } // return number of fame in table uint getNbFame() { return _FameTableSize; } // get tribe threshold per civ allegiance const std::vector& getTribeThresholdVector() const { return _TribeCultThresholdPerCiv; } private: /// private ctor CStaticFames(); /// static fame loader void loadStaticFame( const std::string& filename ); /// static fame tribe threshold void loadTribeThreshold( const std::string& filename ); /// singleton instance static CStaticFames *_Instance; /// faction name index table typedef CHashMap TFactionNameIndexList; TFactionNameIndexList _FactionNameIndex; std::vector _FactionNames; // faction databaseIndex <=> fameIndex translation table std::vector< uint > _FameIndexToDatabaseIndex; uint _FirstTribeFameIndex; /// faction sheet - name table typedef CHashMap TFactionNameSheetList; TFactionNameSheetList _FactionSheetIndex; std::vector _FactionSheets; /// cult threshold for tribe depending of civilization allegiance std::vector _TribeCultThresholdPerCiv; /// Size of the fame table (the table is a square) uint _FameTableSize; /// fame table sint32 *_FameTable; /// propagation factor table float *_PropagationFactorTable; }; /** Access and effect on all the fame in the world. * This class can either static fame or dynamic fame. * Static fame are initial fame between civilisation, * fame between civilisation and tribe and beween tribe. * Dynamic fame include civilisation to civilisation, * guild to civilisation, guild to tribe, player to * civilisation and player to tribe. */ class CFameInterface { public: friend class CFameManager; /// Singleton accessor static CFameInterface &getInstance() { if (_Instance == NULL) { _Instance = new CFameInterface; } return *_Instance; } /// Initialise the dataset pointer (call this when mirror is ready). void setFameDataSet(CMirroredDataSet *fameDataSet, bool declareProperty = true); /// get back the fame dataset CMirroredDataSet *getFameDataSet() { return _FameDataSet; } /** Method to call when a fame entry is created in the mirror. * This method is called from the service mirror notification callback. */ void createFameOwner(CMirroredDataSet& dataSet, const TDataSetRow& entityRow) { nlassertex(_FameDataSet, ("You must set the fame dataset pointer before calling this function")); nlassert(_FamesOwners.find(entityRow) == _FamesOwners.end()); TFameOwner *fo = new TFameOwner(dataSet, entityRow); _FamesOwners.insert(std::make_pair(entityRow, fo)); } /** Method to call when a fame entry is deleted from the mirror. * This method is called from the service mirror notification callback. */ void removeFameOwner(CMirroredDataSet& /* dataSet */, const TDataSetRow& entityRow) { nlassertex(_FameDataSet, ("You must set the fame dataset pointer before calling this function")); TFameContainer::iterator it(_FamesOwners.find(entityRow)); nlassert(it != _FamesOwners.end()); delete it->second; _FamesOwners.erase(it); } //@{ //@name Fame querying /** Get the fame of a civilisation, guild or player versus a tribe or civilisation * The name is a mapped name and is the same as in CStaticFame class. */ sint32 getFame(const NLMISC::CEntityId &entityId, NLMISC::TStringId faction, bool modulated = false, bool returnUnknowValue = false); /** Get the fame of a civilisation, guild or player versus a tribe or civilisation * The name is a mapped name and is the same as in CStaticFame class. */ sint32 getFameIndexed(const NLMISC::CEntityId &entityId, uint32 factionIndex, bool modulated = false, bool returnUnknowValue = false); //@} //@{ //@name Fame modification /** Add some fame value for a civilisation, a guild or a player vs a tribe or civilisation. * The value can positive or negative. * Fame modifications are not immediately received because it's the EGS that apply the value. */ void addFame(const NLMISC::CEntityId &entityId, NLMISC::TStringId faction, sint32 deltaFame, bool propagate = false); /** Add some fame value for a civilisation, a guild or a player vs a tribe or civilisation. * The value can positive or negative. * Fame modifications are not immediately received because it's the EGS that apply the value. */ void addFameIndexed(const NLMISC::CEntityId &entityId, uint32 factionIndex, sint32 deltaFame, bool propagate = false); /** Set the value of the fame. */ //void setFame(const NLMISC::CEntityId &entityId, NLMISC::TStringId faction, sint32 fameValue); //@} //@{ //@name Indirect fame feature querying. /// Get the civilisation datasetrow for the given entity. const TDataSetRow &getCivilisationIndex(const NLMISC::CEntityId &entityId); /// Get the guild datasetrow for the given entity. const TDataSetRow &getGuildIndex(const NLMISC::CEntityId &entityId); /// Get the fame memory datasetrow for the given entity. const TDataSetRow &getFameMemoryIndex(const NLMISC::CEntityId &entityId); //@} /** Interface class designed to implemented and registered in the FameInterface by the * EGS services. * This class directly receive fame delta from addFame. * You must not use this feature with more than one service ! (only the EGS actualy). */ class IFameOverload { public: /** Receive fame delta value. * @param entityIndex index inside the fame dataset. * @param factionIndex index of the faction (as defined in CStaticFame). * @param deltaFame The delta fame value. */ virtual void addFameIndexed(const NLMISC::CEntityId &entityId, uint factionIndex, sint32 deltaFame, bool propagate) =0; /** Get the fame of a civilisation, guild or player versus a tribe or civilisation * The name is a mapped name and is the same as in CStaticFame class. */ virtual sint32 getFameIndexed(const NLMISC::CEntityId &entityId, uint32 factionIndex, bool modulated = true, bool returnUnknownValue = false) =0; virtual const TDataSetRow &getCivilisationIndex(const NLMISC::CEntityId &entityId) =0; virtual const TDataSetRow &getGuildIndex(const NLMISC::CEntityId &entityId) =0; virtual const TDataSetRow &getFameMemoryIndex(const NLMISC::CEntityId &entityId) =0; }; /// Register the fame adder interface. void registerFameOverload(IFameOverload *fameOverload) { _FameOverload = fameOverload; } // get faction index from faction name sint32 getFactionIndex(NLMISC::TStringId faction); private: CFameInterface() : _FameDataSet(NULL), _FameOverload(NULL) {} // fame data for civilisation, guild or player entity struct TFameOwner { /// Civilisation index inside the fame dataset (valid for player and guild entity) CMirrorPropValueRO Civilisation; /// Guild index inside the fame dataset (valid for player only) CMirrorPropValueRO Guild; /// Fame memory index inside the fame dataset (valid for player only) CMirrorPropValueRO FameMemory; // declare the 100 fame mirror value CMirrorPropValueRO Fames[MAX_FACTION]; TFameOwner(CMirroredDataSet& dataSet, const TDataSetRow& entityRow) { // WARNING : you must initialise your property in the same order as they are declared in the dataset Civilisation.init(dataSet, entityRow, CivilisationPropIndex); Guild.init(dataSet, entityRow, GuildPropIndex); FameMemory.init(dataSet, entityRow, FameMemoryPropIndex); for (uint i=0; i TFameContainer; /// storage for fame owner TFameContainer _FamesOwners; /// EGS local fame adder. IFameOverload *_FameOverload; /// Singleton instance pointer. static CFameInterface *_Instance; }; #endif // GS_FAME_H