// 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 RY_PHRASE_MANAGER_H #define RY_PHRASE_MANAGER_H // misc #include "nel/misc/types_nl.h" #include "nel/misc/time_nl.h" #include "nel/misc/sheet_id.h" // std #include // game_share #include "game_share/shield_types.h" #include "game_share/brick_types.h" //#include "game_share/slot_equipment.h" //#include "game_share/mirror_equipment.h" #include "game_share/event_report.h" #include "game_share/skills.h" #include "game_share/tick_event_handler.h" #include "game_share/ai_event.h" #include "game_share/sentence_appraisal.h" //#include "game_share/egs_sheets/egs_sheets.h" #include "game_share/egs_sheets/egs_static_brick.h" #include "game_share/game_item_manager/game_item_manager.h" #include "s_phrase.h" #include "combat.h" extern CGameItemManager GameItemManager; typedef std::vector TVectorSheetId; typedef std::list TEventReportList; typedef std::list TAIEventList; typedef std::list TPhraseList; typedef std::map TMapRowidToCombat; struct CEvalReturnInfos { CEvalReturnInfos() :Cost(0),Valid(false), Appraisal(SENTENCE_APPRAISAL::Undefined){} uint32 Cost; //std::string ReturnString; SENTENCE_APPRAISAL::ESentenceAppraisal Appraisal; bool Valid; }; /** * class used for all the sentences and sentence management for an entity */ class CEntityPhrases { public: /// default constructor CEntityPhrases() : CyclicInProgress(false), DefaultAttackUsed(false) { CyclicAction = NULL; } /// destructor ~CEntityPhrases() {} /// get max size of the FIFO inline static uint8 queueMaxSize() { return _QueueMaxSize; } /// set max size of the FIFO inline static void queueMaxSize(uint8 size) { _QueueMaxSize = size; } /// clear : delete the sentences void clear(); /// set the cyclic action void setCyclicAction( CSPhrase *phrase); /// stop the cyclic action void stopCyclicAction(const TDataSetRow &entityRowId); /// create the default attack cyclic sentence if entity in combat without cyclic sentence void createDefaultAttackIfCombat( const TDataSetRow &actingEntityRowId ); /// void cancelAllPhrasesButFirstOne(); /// cancel the top sentence void cancelTopSentence(bool staticOnly = false); /// add a phrase in the FIFO bool addPhraseFifo( CSPhrase *phrase); public: /// the entity current cyclic action (for combat) CSPhrase * CyclicAction; /// set to true if the current sentence is the cyclic one, false otherwise bool CyclicInProgress; /// flag set to true if the current cyclic action is the default_attack bool DefaultAttackUsed; /// the entity sentence fifo TPhraseList Fifo; private: static uint8 _QueueMaxSize; }; /** * * \author David Fleury * \author Nevrax France * \date 2003 */ class CPhraseManager { public: typedef std::map TMapIdToPhraseStruc; typedef std::map TRowRowMap; typedef std::map > TRowSetRowMap; public: /// getInstance static inline CPhraseManager *getInstance() { if (_Instance == NULL) _Instance = new CPhraseManager(); return _Instance; } /// Destructor virtual ~CPhraseManager() {} /// updatePhrases void updatePhrases(); /// add the callbacks to the service callback array void addCallbacks(); /// init method void init(); /** * register a service to the event broadcast * \param serviceName name of the registered service */ inline void registerService( const std::string &serviceName ) { _RegisteredServices.insert( serviceName ); } /** * register a service to the event broadcast for AI * \param serviceName name of the registered service */ inline void registerServiceForAI( const std::string &serviceName ) { _AIRegisteredServices.insert( serviceName ); } /** * get the set of registered servcies for AI event reports */ inline const std::set ®isteredServiceForAI() { return _AIRegisteredServices; } /** * get the set of registered services for event reports */ inline const std::set ®isteredService() { return _RegisteredServices; } /** * unregister a service to the event broadcast * \param serviceName name of the service to remove */ inline void unregisterService( const std::string &serviceName ) { _RegisteredServices.erase( serviceName ); } /** * unregister a service to the event broadcast * \param serviceName name of the service to remove */ inline void unregisterServiceForAI( const std::string &serviceName ) { _AIRegisteredServices.insert( serviceName ); } /** * add an event report for the current tick * \param report the event report to add */ inline void addEventReport( const SEventReport &report) { _EventReports.push_back( report); } /** * add an AI event report for the current tick * \param report the AI event report to add */ inline void addAiEventReport( const CAiEventReport &report ) { _AIEventReports.push_back(report); } /** * add an AI event for the current tick * \param report the event to add */ inline void addAIEvent( IAIEvent *event ) { if (event != NULL) _AIEvents.push_back( event ); } /** * called when an entity dies or a player is disconnected * \param entityRowId rowId of the entity to remove */ void removeEntity( const TDataSetRow &entityRowId); /** * engage entity 1 with entity 2 in melee combat * \param entity1 the entity engaging entity2 * \param entity2 the entity being engaged by entity1 */ void engageMelee( const TDataSetRow &entity1, const TDataSetRow &entity2 ); /** * engage entity 1 with entity 2 in range combat * \param entity1 the entity engaging entity2 * \param entity2 the entity being engaged by entity1 */ void engageRange( const TDataSetRow &entity1, const TDataSetRow &entity2 ); /** * clear engaged entities map for melee combat */ void clearMeleeEngagedEntities(); /** * get the combat object for given entity, return NULL if no combat engaged * \param attackerRowId attacker rowid * \return adress of the Combat object or NULL if not found */ inline CCombat *getCombatInitiatedBy( const TDataSetRow &attackerRowId ) { TMapRowidToCombat::iterator it = _MapEntityToInitiatedCombat.find( attackerRowId ); if (it != _MapEntityToInitiatedCombat.end() ) return &((*it).second); else return NULL; } /** * if the acting entity has engaged another entity in Melee, get the Entity engaged, return TDataSetRow() if no entity engaged * \param entityRowId acting entity row id * \return the entity of default value if no entity engaged */ inline TDataSetRow getEntityEngagedMeleeBy( const TDataSetRow &entityRowId) const { TRowRowMap::const_iterator it = _MapEntityToEngagedEntityInMeleeCombat.find( entityRowId ); if (it != _MapEntityToEngagedEntityInMeleeCombat.end() ) return (*it).second; else return TDataSetRow(); } /** * if the acting entity has engaged another entity in Range combat, get the Entity engaged, return TDataSetRow() if no entity engaged * \param entityRowId acting entity row id * \return the entity of default value if no entity engaged */ inline TDataSetRow getEntityEngagedRangeBy( const TDataSetRow &entityRowId) const { TRowRowMap::const_iterator it = _MapEntityToEngagedEntityInRangeCombat.find( entityRowId ); if (it != _MapEntityToEngagedEntityInRangeCombat.end() ) return (*it).second; else return TDataSetRow(); } /** * get all the melee aggressors for specified entity * \param entityRowId acting entity row id * \return the set of aggressors */ inline const std::set &getMeleeAggressors( const TDataSetRow &entityRowId ) const { static std::set emptySet; const TRowSetRowMap::const_iterator it = _MapEntityToMeleeAggressors.find(entityRowId) ; if (it != _MapEntityToMeleeAggressors.end() ) { return (*it).second; } else return emptySet; } /** * get all the range aggressors for specified entity * \param entityId acting entity CEntityId * \return the set of aggressors */ inline const std::set &getRangeAggressors( const TDataSetRow &entityRowId ) const { static std::set emptySet; const TRowSetRowMap::const_iterator it = _MapEntityToRangeAggressors.find(entityRowId) ; if (it != _MapEntityToRangeAggressors.end() ) { return (*it).second; } else return emptySet; } /* * disengage an entity from combat * \param entityRowId the entity disengaging from combat * \param sendChatMsg true if must send message to the clients * \param cancelCombatSentence true if combat sentence should be canceled, false otherwise * \param */ void disengage( const TDataSetRow &entityRowId, bool sendChatMsg, bool disengageCreature = false, bool cancelCombatSentence = true ); /** * cancel all combat sentences of that player * \param playerId rowId of the entity * \param disengageOnEndOnly if set to true, set the related flag if a combat sentrence if found active, and return true */ bool cancelAllCombatSentences( const TDataSetRow &playerRowId, bool disengageOnEndOnly ); /** * cancel Static action in progress * \param entityRowId row id of the entity */ void cancelStaticActionInProgress( const TDataSetRow &actorRowId ); /** * check the validity (grammar and cost) of given phrase * \param vector of bricks sheet ids * \return true if the phrase is valid */ bool checkPhraseValidity( const std::vector &brickIds ) const; /** * execute a sabrina phrase * \param actorRowId the rowid of the actor * \param targetRowId rowid of the target * \param brickIds ids of the bricks composing the phrase * \param cyclic true if the sentence is cyclic (combat), false otherwise */ void executePhrase( const TDataSetRow &actorRowId, const TDataSetRow &targetRowId, const std::vector &brickIds, bool cyclic = false, uint16 phraseId = 0, uint8 nextCounter = 0 ); /** * create a default harvest phrase * \param actorRowId the rowid of the actor * \param rawMaterialSheet harvested raw material * \param minQuality harvested raw material min quality * \param maxQuality harvested raw material max quality * \param quantity harvested raw material quantity * \param deposit true if the entity harvest a deposit * \return false if the phrase cannot be built */ bool harvestDefault(const TDataSetRow &actorRowId, const NLMISC::CSheetId &rawMaterialSheet, uint16 minQuality, uint16 maxQuality, uint16 quantity, bool deposit = false ); /** * entity1 attacks entity2 using a default attack or any other attacks * \param attackerId id of the attacker * \param targetId id of the attacked entity */ void defaultAttackSabrina( const TDataSetRow &attackerRowId, const TDataSetRow &targetRowId ); inline void defaultAttackSabrina( const NLMISC::CEntityId &attackerId, const NLMISC::CEntityId &targetId ) { defaultAttackSabrina( TheDataset.getDataSetRow(attackerId), TheDataset.getDataSetRow(targetId) ); } /** * build a sabrina phrase from the given set of bricks * \param actorRowId actor row id * \param targetRowId primary target row id * \param brickIds the brick sheet ids * \return pointer on the built phrase, NULL if failed */ CSPhrase *buildSabrinaPhrase( const TDataSetRow &actorRowId, const TDataSetRow &targetRowId, const std::vector &brickIds, uint16 phraseId = 0, uint8 nextCounter = 0); // CSPhrase *buildSabrinaPhrase( const NLMISC::CEntityId &actorId, const NLMISC::CEntityId &targetId, const std::vector &brickIds ) // { // return buildSabrinaPhrase( TheDataset.getDataSetRow(actorId), TheDataset.getDataSetRow(targetId), brickIds ); // } /** * An entity attempts to break a spell being cast * \param attackSkillLevel: value of the skill of the atacker ( = skill /10) * \param attacker: the attacking entity * \param defender : the defender */ void breakCast( sint32 attackSkillLevel, CEntityBase * entity, CEntityBase * defender); private: /// private Constructor CPhraseManager(); /** * send the event reports to the registered services */ void sendEventReports(); /** * flush ai events */ void sendAIEvents(); private: /// unique instance static CPhraseManager* _Instance; /// the map giving the phrase execution FIFO and the current cyclic action for a given entity TMapIdToPhraseStruc _Phrases; /// list of registered services for Event Broadcast std::set _RegisteredServices; /// list of registered services for Event Broadcast for AI std::set _AIRegisteredServices; /// the list of the events to report TEventReportList _EventReports; /// the list of ai events TAIEventList _AIEvents; /// the list of ai event reports std::vector _AIEventReports; /// map entity row id to the related combat object if any TMapRowidToCombat _MapEntityToInitiatedCombat; /// map entity ID with the entity they engaged in combat TRowRowMap _MapEntityToEngagedEntityInMeleeCombat; /// map entities with the set of entities which have engaged them in melee combat TRowSetRowMap _MapEntityToMeleeAggressors; /// map entity ID with the entity they have engaged in range combat TRowRowMap _MapEntityToEngagedEntityInRangeCombat; /// map entities with the set of entities which have engaged them in range combat TRowSetRowMap _MapEntityToRangeAggressors; }; #endif // RY_PHRASE_MANAGER_H /* End of phrase_manager.h */