// 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_MAGIC_ACTION_H #define RY_MAGIC_ACTION_H #include "nel/misc/types_nl.h" #include "game_share/brick_families.h" #include "game_share/egs_sheets/egs_sheets.h" #include "game_share/mode_and_behaviour.h" #include "phrase_utilities_functions.h" class CMagicPhrase; extern NLMISC::CRandom RandomGenerator; /// Macro used to declare a Sabrina Magic action ( i.e. : effects represented by active bricks in a spell ) #define BEGIN_MAGIC_ACTION_FACTORY(_class_) \ class _class_##Factory : public IMagicActionFactory \ {\ public:\ _class_##Factory()\ {\ IMagicActionFactory::init(); \ #define ADD_MAGIC_ACTION_TYPE(_type_)\ for (uint i = 0; i < Factories->size(); i++ )\ {\ if ( (*Factories)[i].first == _type_ )\ {\ nlstop;\ }\ }\ Factories->push_back(std::make_pair( std::string(_type_) ,this)); #define END_MAGIC_ACTION_FACTORY(_class_) \ };\ IMagicAction * build( const TDataSetRow & actorRowId, const std::vector< const CStaticBrick* >& bricks, uint & brickIndex, CMagicPhrase * phrase )\ {\ _class_ *inst = new _class_;\ if ( !inst->build( actorRowId, bricks, brickIndex, phrase ) ){delete inst;return NULL;} \ return inst;\ }\ };\ _class_##Factory* _class_##FactoryInstance = new _class_##Factory; /** * Interface for magic actions * \author Nicolas Brigand * \author Nevrax France * \date 2003 */ class IMagicAction { public: /// build the action basic params, the call the addBrick virtual method to retrieve the specific params bool build( const TDataSetRow & actorRowId, const std::vector< const CStaticBrick* >& bricks, uint & index, CMagicPhrase* phrase ) { // get the skill if ( ! bricks.empty() ) { _Skill = bricks[index]->Skill; if ( _Skill == SKILLS::unknown ) { uint idx = index; nlwarning( " invalid skill in brick %s. We will iterate backwards through the brick queue to get a skill",bricks[index]->SheetId.toString().c_str() ); while ( _Skill == SKILLS::unknown && idx > 0 ) _Skill = bricks[idx--]->Skill; if ( _Skill == SKILLS::unknown) { nlwarning( " no valid skill found in brick %s.",bricks[idx]->SheetId.toString().c_str() ); return false; } } } else { nlwarning(" no brick in action..."); return false; } while(1) { if ( index >= bricks.size() ) { nlwarning(" index %u > bricks.size() %u",index, bricks.size()); break; } if ( !bricks[index] ) { nlwarning(" index %u> bricks.size() %u",index, bricks.size()); break; } INFOLOG("IN MAGIC ACTIOND : Parsing brick index %u value %s",index,bricks[index]->SheetId.toString().c_str() ); bool end = false;; if ( !addBrick( *bricks[index], phrase,end ) ) return false; index++; if ( end ) break; } return true; } ///\name virtual action methods //@{ /// validate the action virtual bool validate(CMagicPhrase * phrase) = 0; /// apply the action virtual void apply( CMagicPhrase * phrase, float successFactor,MBEHAV::CBehaviour & behav, bool isMad ) = 0; /// add a brick to build the action virtual bool addBrick( const CStaticBrick & brick, CMagicPhrase * phrase, bool &effectEnd ) = 0; //@} protected: /// the skill used in that action SKILLS::ESkills _Skill; }; /** * class factory for sabrina Magic Effect * \author Nicolas Brigand * \author Nevrax France * \date 2003 */ class IMagicActionFactory { public: /// clear the class factory static void clear(); /** * Build the desired step from a primitive node * \param prim : the primitive node used to build the step * \return a pointer on the built step (NULL if failure) */ inline static IMagicAction * buildAction( const TDataSetRow & actorRowId, const std::vector< const CStaticBrick* >& bricks, uint & brickIndex, CMagicPhrase * phrase ) { // check validity if ( bricks.size()<=brickIndex ) { nlwarning(" brick index %u and size is %u !",brickIndex, bricks.size()); return NULL; } if ( !bricks[brickIndex] ) { nlwarning(" brick index %u is NULL",brickIndex); return NULL; } if ( bricks[brickIndex]->Params.empty() ) { nlwarning("NASTY BUG: no param in brick %u : if we are there there is at least1 param for the effect type",brickIndex); return NULL; } if ( bricks[brickIndex]->Params[0]->id() != TBrickParam::MA ) { nlwarning("NASTY BUG: no param in brick %u : if we are there the first param should be a TBrickParam::MA",brickIndex); return NULL; } INFOLOG("MA: %s",((CSBrickParamMaType *)bricks[brickIndex]->Params[0])->Type.c_str()); const std::string & type = ((CSBrickParamMaType *)bricks[brickIndex]->Params[0])->Type; //get appropriate factory for ( uint i = 0; i < Factories->size(); i++ ) { if ( !NLMISC::nlstricmp( (*Factories)[i].first , type) ) { INFOLOG("MA: %s is managed by the system. Building action...",((CSBrickParamMaType *)bricks[brickIndex]->Params[0])->Type.c_str()); return (*Factories)[i].second->build( actorRowId, bricks, brickIndex, phrase); } } nlwarning( " the type MA:%s has no corresponding magic action class", type.c_str() ); return NULL; } protected: ///\init the factories inline static void init() { if( !Factories ) Factories = new std::vector< std::pair< std::string , IMagicActionFactory* > >; } /** * Create a step from parameters * \param params : a vector of vector of strings describing the step params * \return a pointer on the built step (NULL if failure) */ virtual IMagicAction * build( const TDataSetRow & actorRowId, const std::vector< const CStaticBrick* >& brickIds, uint & index, CMagicPhrase * phrase ) = 0; ///the phrase factories. We use a pointer here because we cant control the order inwhich ctor of static members are called static std::vector< std::pair< std::string , IMagicActionFactory* > >* Factories; }; #endif // RY_MAGIC_ACTION_H /* End of magic_action.h */