// 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 .
#include "stdpch.h"
#include "action_handler.h"
#include "../motion/user_controls.h"
#include "../view.h"
#include "../misc.h"
#include "../input.h"
#include "../client_cfg.h"
#include "../actions_client.h"
#include "../sheet_manager.h"
#include "interface_manager.h"
#include "dbctrl_sheet.h"
#include "dbgroup_build_phrase.h"
#include "group_container.h"
#include "sphrase_manager.h"
#include "sbrick_manager.h"
#include "ctrl_button.h"
#include "../user_entity.h"
#include "skill_manager.h"
#include "inventory_manager.h"
#include "game_share/memorization_set_types.h"
#include "action_handler_help.h"
#include "bot_chat_page_all.h"
#include "bot_chat_page_trade.h"
#include "../net_manager.h"
#include "../entities.h"
#include "macrocmd_manager.h"
#include "group_menu.h"
#include "group_tree.h"
extern CSheetManager SheetMngr;
using namespace std;
using namespace NLMISC;
// ***************************************************************************
void launchPhraseComposition(bool creation);
const std::string PhraseComposition="ui:interface:phrase_composition";
const std::string PhraseCompositionGroup="ui:interface:phrase_composition:header_opened";
const std::string PhraseMemoryCtrlBase= "ui:interface:gestionsets:shortcuts:s";
const std::string PhraseMemoryAltCtrlBase= "ui:interface:gestionsets2:header_closed:shortcuts:s";
// **********************************************************************************************************
// debug update the action bar
void debugUpdateActionBar()
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:ACT_TSTART")->setValue64(NetMngr.getCurrentServerTick());
NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:ACT_TEND")->setValue64(NetMngr.getCurrentServerTick()+30);
}
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// PHRASE BOOK EDITION
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
class CHandlerPhraseEdit : public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
{
CDBCtrlSheet *pCSDst = dynamic_cast(pCaller);
if (pCSDst == NULL || !pCSDst->isSPhraseId())
return;
// get the phrase id.
sint32 id= pCSDst->getSPhraseId();
// Nb: Yoyo: this slot can come from eiter the Action Book, or the Memorized sentence
// set the phrase to edit
CSPhraseManager *pPM= CSPhraseManager::getInstance();
pPM->CompositionPhraseId= id;
pPM->CompositionPhraseMemoryLineDest= -1;
pPM->CompositionPhraseMemorySlotDest= -1;
// Launch the composition window
launchPhraseComposition(false);
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseEdit, "phrase_edit" );
// ***************************************************************************
class CHandlerPhraseNew : public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
{
// Get A free slot to edit (not allocated).
CSPhraseManager *pPM= CSPhraseManager::getInstance();
// if possible
if(pPM->hasFreeSlot())
{
// Set the phrase to edit to 0, to indicate a new phrase. CANNOT "ALLOCATE" THE ID NOW, else may
// crash if buy a botchatphrase, while editing a new phrase!!!!
pPM->CompositionPhraseId= 0;
// If the caller is ctrl sheet (may be a standard button else), and if comes from memory
CDBCtrlSheet *pCSDst= dynamic_cast(pCaller);
if(pCSDst && pCSDst->isSPhraseId() && pCSDst->isSPhraseIdMemory())
{
// then will auto-memorize it in this slot
if (pCSDst->isShortCut())
pPM->CompositionPhraseMemoryLineDest= pPM->getSelectedMemoryLineDB();
else
pPM->CompositionPhraseMemoryLineDest= 0;
pPM->CompositionPhraseMemorySlotDest= pCSDst->getIndexInDB();
}
// else no auto memorize
else
{
pPM->CompositionPhraseMemoryLineDest= -1;
pPM->CompositionPhraseMemorySlotDest= -1;
}
// Launch the composition window
launchPhraseComposition(true);
}
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseNew, "phrase_new" );
// ***************************************************************************
class CHandlerPhraseValidate : public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
{
// NB: The user can validate only if the server was OK.
// get our father build sentence
CInterfaceGroup *parent = pCaller->getParent();
if (parent)
{
CSPhraseManager *pPM= CSPhraseManager::getInstance();
CDBGroupBuildPhrase *buildGroup= dynamic_cast(parent->getParent());
if(!buildGroup)
return;
// is this an action creation or action edition?
bool actionCreation= pPM->CompositionPhraseId==0;
// For a new created phrase, the CompositionPhraseId is 0, allocate it now
if(!pPM->CompositionPhraseId)
{
pPM->CompositionPhraseId= pPM->allocatePhraseSlot();
// fail?
if(!pPM->CompositionPhraseId)
return;
}
// build the edited phrase
CSPhraseCom newPhrase;
buildGroup->buildCurrentPhrase(newPhrase);
// the new slot of the phrase
uint32 slotId= pPM->CompositionPhraseId;
// Action Creation case.
if(actionCreation)
{
// Append in the Phrase Manager.
pPM->setPhrase(slotId, newPhrase);
// inform the server of our book change, with the edited name
pPM->sendLearnToServer(slotId);
// if this action creation requires an auto "memorize in slot"
sint32 memoryLine= pPM->CompositionPhraseMemoryLineDest;
sint32 memorySlot= pPM->CompositionPhraseMemorySlotDest;
if( memoryLine>=0 &&
memorySlot>=0 &&
memorySlotmemorizePhrase(memoryLine, memorySlot, slotId);
pPM->sendMemorizeToServer(memoryLine, memorySlot, slotId);
}
}
// Action edition case
else
{
// Replace in the Phrase Manager.
pPM->setPhrase(slotId, newPhrase);
// inform the server of our book change, with the edited name
pPM->sendLearnToServer(slotId);
// Then, auto-re_memorize all after, changing Ctrl Gray States if needed, and sending msg to server
pPM->rememorizeAllThatUsePhrase(slotId);
}
// Close the Composition Window
pCaller->getRootWindow()->setActive(false);
}
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseValidate, "phrase_validate" );
// ***************************************************************************
class CHandlerPhraseValidateOnEnter : public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
{
// Test if the OK control is valid.
CGroupContainer *pGC= dynamic_cast(pCaller);
if(!pGC) return;
if(!pGC->getHeaderOpened()) return;
CDBGroupBuildPhrase *buildPhrase= dynamic_cast(pGC->getHeaderOpened());
if(!buildPhrase) return;
CCtrlBaseButton *button= buildPhrase->getValidateButton();
// Ok, button found. test if active and not frozen.
if( button && button->getActive() && !button->getFrozen() )
{
// Act as if the player click on this button
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CAHManager::getInstance()->runActionHandler(button->getActionOnLeftClick(), button, button->getParamsOnLeftClick() );
}
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseValidateOnEnter, "phrase_validate_on_enter");
// ***************************************************************************
void launchPhraseComposition(bool creation)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
// Launch the composition window
CGroupContainer *window= dynamic_cast( CWidgetManager::getInstance()->getElementFromId(PhraseComposition) );
if(window)
{
CDBGroupBuildPhrase *buildSentenceTarget= dynamic_cast( CWidgetManager::getInstance()->getElementFromId(PhraseCompositionGroup) );
// if found
if(buildSentenceTarget)
{
// enable the window
window->setActive(true);
// Set the Text of the Window
if(creation)
window->setUCTitle(CI18N::get("uiPhraseCreate"));
else
window->setUCTitle(CI18N::get("uiPhraseEdit"));
// clear the sentence for a New Phrase creation.
buildSentenceTarget->clearBuildingPhrase();
// copy phrase to edit
CSPhraseManager *pPM= CSPhraseManager::getInstance();
// get the edited (or empty if new) phrase.
const CSPhraseCom &phrase= pPM->getPhrase(pPM->CompositionPhraseId);
// Start the composition
buildSentenceTarget->startComposition(phrase);
/** if edition, avoid changing the root type, it behaves better
*/
// Default, no filter (important for creation)
if(creation)
{
// all root are possible => no filter
buildSentenceTarget->setRootBrickTypeFilter(BRICK_TYPE::UNKNOWN);
}
// if edition
else
{
if(phrase.empty())
{
buildSentenceTarget->setRootBrickTypeFilter(BRICK_TYPE::UNKNOWN);
}
else
{
CSBrickManager *pBM= CSBrickManager::getInstance();
const CSBrickSheet *rootBrick= pBM->getBrick(phrase.Bricks[0]);
// can select only bricks of the same type
if(rootBrick)
buildSentenceTarget->setRootBrickTypeFilter(BRICK_FAMILIES::brickType(rootBrick->BrickFamily));
// maybe data error: filter nothing
else
buildSentenceTarget->setRootBrickTypeFilter(BRICK_TYPE::UNKNOWN);
}
}
}
}
}
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// PHRASE COMPOSITION
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// **********************************************************************************************************
/** Called when the user select a brick from the list of possible bricks
*/
class CHandlerPhraseValidateBrick : public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CDBCtrlSheet *pCSSrc = dynamic_cast(pCaller);
if(!pCSSrc || !pCSSrc->isSBrick())
return;
// get the selected brick
const CSBrickSheet *brick= pCSSrc->asSBrickSheet();
if(brick==NULL)
return;
// and validate the composition
// Standard Case: selection for action composition
if(BrickType != FaberPlan)
{
nlassert(BuildPhraseGroup);
switch(BrickType)
{
case Root: BuildPhraseGroup->validateRoot(brick); break;
case OtherMain: BuildPhraseGroup->validateMain(Index, brick); break;
case Param: BuildPhraseGroup->validateParam(Index, ParamIndex, brick); break;
case NewOpCredit: BuildPhraseGroup->validateNewOpCredit(brick); break;
default: break;
}
}
// Special Case: selection for faber plan
else
{
extern void validateFaberPlanSelection(CSBrickSheet *itemPlanBrick);
validateFaberPlanSelection(const_cast(brick));
}
// And hide the modal
CWidgetManager::getInstance()->disableModalWindow();
}
public:
enum TType {Root, OtherMain, Param, NewOpCredit, FaberPlan};
static TType BrickType;
static uint Index;
static uint ParamIndex;
static CDBGroupBuildPhrase *BuildPhraseGroup;
};
REGISTER_ACTION_HANDLER( CHandlerPhraseValidateBrick, "phrase_validate_brick" );
CHandlerPhraseValidateBrick::TType CHandlerPhraseValidateBrick::BrickType;
uint CHandlerPhraseValidateBrick::Index;
uint CHandlerPhraseValidateBrick::ParamIndex;
CDBGroupBuildPhrase *CHandlerPhraseValidateBrick::BuildPhraseGroup= NULL;
// ***************************************************************************
class CHandlerPhraseSelectMainBrick : public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &Params)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
// get the type and index in the current build sentence
uint index;
fromString(getParam(Params, "index"), index);
CHandlerPhraseValidateBrick::Index= index;
if(index==0)
CHandlerPhraseValidateBrick::BrickType= CHandlerPhraseValidateBrick::Root;
else
CHandlerPhraseValidateBrick::BrickType= CHandlerPhraseValidateBrick::OtherMain;
// get our father build sentence
CDBGroupBuildPhrase *buildGroup= dynamic_cast(pCaller->getParent()->getParent());
if(!buildGroup)
return;
// setup the validation
CHandlerPhraseValidateBrick::BuildPhraseGroup= buildGroup;
// build the list of possible bricks
if(index==0)
buildGroup->fillSelectionRoot();
else
buildGroup->fillSelectionMain(index);
// launch the modal
CInterfaceGroup *group= dynamic_cast( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal ) );
if(group)
{
// enable the modal
CWidgetManager::getInstance()->enableModalWindow(pCaller, group);
}
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseSelectMainBrick, "phrase_select_main_brick" );
// ***************************************************************************
class CHandlerPhraseSelectParamBrick : public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &Params)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
// get the type and index in the current build sentence
CHandlerPhraseValidateBrick::BrickType= CHandlerPhraseValidateBrick::Param;
uint index, paramIndex;
fromString(getParam(Params, "index"), index);
CHandlerPhraseValidateBrick::Index= index;
fromString(getParam(Params, "param_index"), paramIndex);
CHandlerPhraseValidateBrick::ParamIndex= paramIndex;
// get our father build sentence
CDBGroupBuildPhrase *buildGroup= dynamic_cast(pCaller->getParent()->getParent());
if(!buildGroup)
return;
// setup the validation
CHandlerPhraseValidateBrick::BuildPhraseGroup= buildGroup;
// build the list of possible bricks
buildGroup->fillSelectionParam(index, paramIndex);
// launch the modal
CInterfaceGroup *group= dynamic_cast( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal ) );
if(group)
{
// enable the modal
CWidgetManager::getInstance()->enableModalWindow(pCaller, group);
}
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseSelectParamBrick, "phrase_select_param_brick" );
// ***************************************************************************
class CHandlerPhraseSelectNewBrick : public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &Params)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
// get the type and index in the current build sentence
CHandlerPhraseValidateBrick::BrickType= CHandlerPhraseValidateBrick::NewOpCredit;
string typeStr= getParam(Params, "type");
// get our father build sentence
CDBGroupBuildPhrase *buildGroup= dynamic_cast(pCaller->getParent()->getParent());
if(!buildGroup)
return;
// setup the validation
CHandlerPhraseValidateBrick::BuildPhraseGroup= buildGroup;
// build the list of possible bricks
if(typeStr=="optional")
buildGroup->fillSelectionNewOp();
else if(typeStr=="credit")
buildGroup->fillSelectionNewCredit();
// launch the modal
CInterfaceGroup *group= dynamic_cast( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal ) );
if(group)
{
// enable the modal
CWidgetManager::getInstance()->enableModalWindow(pCaller, group);
}
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseSelectNewBrick, "phrase_select_new_brick" );
// ***************************************************************************
class CHandlerPhraseChangeName : public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
{
// The BuildPhrase should be the grandParent
CDBGroupBuildPhrase *buildPhrase= dynamic_cast(pCaller->getParent()->getParent());
if(!buildPhrase)
return;
// update the edited icon
buildPhrase->updateSpellView();
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseChangeName, "phrase_change_name");
// ***************************************************************************
/*
* Special For Faber Plan selection
*/
class CHandlerPhraseFaberSelectPlan : public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
// Launch the modal to select the faber plan
extern void fillFaberPlanSelection(const std::string &brickDB, uint maxSelection);
fillFaberPlanSelection(CDBGroupBuildPhrase::BrickSelectionDB, CDBGroupBuildPhrase::MaxSelection);
// setup the validation
CHandlerPhraseValidateBrick::BuildPhraseGroup= NULL;
CHandlerPhraseValidateBrick::BrickType= CHandlerPhraseValidateBrick::FaberPlan;
// launch the modal
CInterfaceGroup *group= dynamic_cast( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal ) );
if(group)
{
// enable the modal
CWidgetManager::getInstance()->enableModalWindow(pCaller, group);
}
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseFaberSelectPlan, "phrase_faber_select_plan" );
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// PHRASE MEMORISATION / EXECUTION / MISC
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
static void updateAllSPhraseInfo()
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
// update all info windows
CInterfaceHelp::updateWindowSPhraseTexts();
// If the composition is opened, refresh
CInterfaceGroup *pIG= dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:phrase_composition"));
if(pIG && pIG->getActive())
{
CDBGroupBuildPhrase *buildPhrase= dynamic_cast(pIG->getGroup("header_opened"));
if(buildPhrase)
buildPhrase->updateAllDisplay();
}
// update bot chat
if(BotChatPageAll && BotChatPageAll->Trade)
BotChatPageAll->Trade->updateSPhraseBuyDialog();
}
// **********************************************************************************************************
/** Called when the Item in Right Hand change
*/
class CHandlerPhraseUpdateFromHand : public IActionHandler
{
public:
virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
{
CSPhraseManager *pPM = CSPhraseManager::getInstance();
// **** Update the grayed state of all memory ctrls
pPM->updateAllMemoryCtrlState();
// **** Update misc Action Infos related to items weared
updateAllSPhraseInfo();
}
};
REGISTER_ACTION_HANDLER (CHandlerPhraseUpdateFromHand, "phrase_update_from_hand");
// **********************************************************************************************************
/** Called when the Item in equip change (Action Malus due to armor)
*/
class CHandlerPhraseUpdateFromActionMalus : public IActionHandler
{
public:
virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
{
// **** Update misc Action Infos related to items weared
updateAllSPhraseInfo();
}
};
REGISTER_ACTION_HANDLER(CHandlerPhraseUpdateFromActionMalus, "phrase_update_from_action_malus");
// **********************************************************************************************************
/** drag'n'drop: cannot drag PhraseSheet that are not castable
*/
class CHandlerCanDragPhrase : public IActionHandler
{
public:
virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
{
CSPhraseManager *pPM= CSPhraseManager::getInstance();
CDBCtrlSheet *pCSSrc = dynamic_cast(pCaller);
if(!pCSSrc || !pCSSrc->isSPhrase())
return;
// can drag only if memorizable
pCSSrc->setTempCanDrag(pPM->isPhraseCastable(pCSSrc->getSheetId()));
}
};
REGISTER_ACTION_HANDLER (CHandlerCanDragPhrase, "phrase_can_drag_castable");
// **********************************************************************************************************
/** drag'n'drop: true if the src ctrlSheet is a Phrase and the dest is in memory. Or if both are in memory
*/
class CHandlerCanMemorizePhraseOrMacro : public IActionHandler
{
public:
virtual void execute (CCtrlBase *pCaller, const string &Params)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CSPhraseManager *pPM = CSPhraseManager::getInstance();
CSBrickManager *pBM = CSBrickManager::getInstance();
CMacroCmdManager *pMM = CMacroCmdManager::getInstance();
string src = getParam(Params, "src");
CInterfaceElement *pElt = CWidgetManager::getInstance()->getElementFromId(src);
CDBCtrlSheet *pCSSrc = dynamic_cast(pElt);
CDBCtrlSheet *pCSDst = dynamic_cast(pCaller);
// can be a phrase id (comes from memory), a phraseSheet (comes from progression), or a macro,
if (pCSSrc->isSPhraseId() || pCSSrc->isMacro() || pCSSrc->isSPhrase())
if (pCSDst->isSPhraseId() || pCSDst->isMacro())
{
// check if incoming phrase ok
if(pCSSrc->isSPhraseId())
{
// get the src phrase.
const CSPhraseCom &phrase= pPM->getPhrase(pCSSrc->getSPhraseId());
if(!phrase.empty())
{
// Get the RootBrick of the Phrase
CSBrickSheet *brick= pBM->getBrick(phrase.Bricks[0]);
if(brick)
pCSDst->setCanDrop (true);
}
}
// can be a phrase sheet
else if(pCSSrc->isSPhrase())
{
CSPhraseSheet *phrase= dynamic_cast(SheetMngr.get(NLMISC::CSheetId(pCSSrc->getSheetId())));
if(phrase && !phrase->Bricks.empty())
{
// Get the RootBrick of the Phrase
CSBrickSheet *brick= pBM->getBrick(phrase->Bricks[0]);
if(brick)
pCSDst->setCanDrop (true);
}
}
// check if incoming macro ok
else
{
// get the macro
const CMacroCmd *macroCmd= pMM->getMacroFromMacroID(pCSSrc->getMacroId());
if(macroCmd)
pCSDst->setCanDrop(true);
}
}
}
};
REGISTER_ACTION_HANDLER (CHandlerCanMemorizePhraseOrMacro, "can_memorize_phrase_or_macro");
class CHandlerPhraseMemoryCopy : public IActionHandler
{
public:
static bool haveLastPhraseElement;
static bool isMacro;
static sint32 sPhraseId;
static sint32 macroId;
virtual void execute(CCtrlBase *pCaller, const string &Params)
{
CDBCtrlSheet *ctrl= dynamic_cast(pCaller);
if(ctrl && ctrl->isSPhraseIdMemory())
{
haveLastPhraseElement = true;
isMacro = ctrl->isMacro();
sPhraseId = ctrl->getSPhraseId();
macroId = ctrl->getMacroId();
string mode = getParam(Params, "mode"); //default mode is copy
if (mode == "cut") //need delete src
{
CAHManager::getInstance()->runActionHandler("forget_phrase_or_macro", ctrl);
}
}
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseMemoryCopy, "phrase_memory_copy");
bool CHandlerPhraseMemoryCopy::haveLastPhraseElement = false;
bool CHandlerPhraseMemoryCopy::isMacro = false;
sint32 CHandlerPhraseMemoryCopy::sPhraseId = 0;
sint32 CHandlerPhraseMemoryCopy::macroId = 0;
// **********************************************************************************************************
// debug update the action bar
extern void debugUpdateActionBar();
// **********************************************************************************************************
/** Memorize a combat Brick into a Memory slot.
* Called when the user drop a combat brick on a spell slot.
*/
class CHandlerMemorizePhraseOrMacro : public IActionHandler
{
public:
virtual void execute (CCtrlBase *pCaller, const string &Params);
void memorizePhraseOrMacro(uint dstMemoryIndex, bool isMacro, sint32 phraseId, sint32 macroId);
void memorizePhraseSheet(uint dstMemoryIndex, uint32 sheetId);
};
REGISTER_ACTION_HANDLER( CHandlerMemorizePhraseOrMacro, "memorize_phrase_or_macro");
void CHandlerMemorizePhraseOrMacro::execute (CCtrlBase *pCaller, const string &Params)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CSPhraseManager *pPM = CSPhraseManager::getInstance();
string src = getParam(Params, "src");
CDBCtrlSheet *pCSSrc;
CDBCtrlSheet *pCSDst = dynamic_cast(pCaller);
// NB: THIS IS UGLY BUT WORKS BECAUSE Memory ctrls are first initialized as SPhrase (branchname init)
// type check
if (pCSDst == NULL) return;
// The dest must be a memory or a macro memory
if (!pCSDst->isSPhraseIdMemory() && !pCSDst->isMacroMemory()) return;
// get the memory line and memory index
sint32 dstMemoryLine= pPM->getSelectedMemoryLineDB();
uint dstMemoryIndex= pCSDst->getIndexInDB();
bool srcIsMacro;
sint32 srcPhraseId;
sint32 srcMacroId;
bool dstIsMacro= pCSDst->isMacro();
sint32 dstPhraseId= pCSDst->getSPhraseId();
sint32 dstMacroId= pCSDst->getMacroId();
if ((src == "") && (CHandlerPhraseMemoryCopy::haveLastPhraseElement))
{
// get the slot ids from save
srcIsMacro= CHandlerPhraseMemoryCopy::isMacro;
srcPhraseId= CHandlerPhraseMemoryCopy::sPhraseId;
srcMacroId= CHandlerPhraseMemoryCopy::macroId;
// if a phrase
if(!srcIsMacro)
{
// \toto yoyo: There is a Network BUG which prevents us from simply doing {Forget(),Delete()} Old phrase,
// then {Learn(),Memorize()} new one (Messages are shuffled).
// Instead, replace the old phrase if needed
uint16 newPhraseId= (uint16)pPM->getMemorizedPhraseIfLastOrNewSlot(dstMemoryLine, dstMemoryIndex);
if(!newPhraseId)
return;
// set it, copy from srcPhraseId
pPM->setPhrase(newPhraseId, pPM->getPhrase(srcPhraseId));
// send learn to server
pPM->sendLearnToServer(newPhraseId);
// memorize the new phrase
memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, newPhraseId, srcMacroId);
}
}
else
{
CInterfaceElement *pElt = CWidgetManager::getInstance()->getElementFromId(src);
pCSSrc = dynamic_cast(pElt);
// type check
if (pCSSrc == NULL) return;
// The src must be a phraseid, a phrasesheet, or a macro droped
if (!pCSSrc->isSPhraseId() && !pCSSrc->isSPhrase() && !pCSSrc->isMacro()) return;
// get the slot ids.
srcIsMacro= pCSSrc->isMacro();
srcPhraseId= pCSSrc->getSPhraseId();
srcMacroId= pCSSrc->getMacroId();
// If the src comes not from a memory
if(!pCSSrc->isSPhraseIdMemory() && !pCSSrc->isMacroMemory())
{
// if the src is a phrase sheet
if(pCSSrc->isSPhrase())
{
// learn and memorize this phrase
memorizePhraseSheet(dstMemoryIndex, pCSSrc->getSheetId());
}
else
{
// We may replace a phrase with a macro => must delete the phrase under us
if(srcIsMacro)
pPM->fullDeletePhraseIfLast(dstMemoryLine, dstMemoryIndex);
// memorize the phrase or macro
memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId);
}
}
// Else the src is a memory too
else
{
// if Drag copy => this is a copy!
if(pCSSrc->canDragCopy() && pIM->testDragCopyKey())
{
// if a phrase
if(!srcIsMacro)
{
// \toto yoyo: There is a Network BUG which prevents us from simply doing {Forget(),Delete()} Old phrase,
// then {Learn(),Memorize()} new one (Messages are shuffled).
// Instead, replace the old phrase if needed
uint16 newPhraseId= (uint16)pPM->getMemorizedPhraseIfLastOrNewSlot(dstMemoryLine, dstMemoryIndex);
if(!newPhraseId)
return;
// set it, copy from srcPhraseId
pPM->setPhrase(newPhraseId, pPM->getPhrase(srcPhraseId));
// send learn to server
pPM->sendLearnToServer(newPhraseId);
// memorize the new phrase
memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, newPhraseId, srcMacroId);
}
else
{
// We may replace a phrase with a macro => must delete the phrase under us
pPM->fullDeletePhraseIfLast(dstMemoryLine, dstMemoryIndex);
// memorize the macro (still a reference)
memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId);
}
}
// else this is a swap!
else
{
// if the dest exist, swap
if(dstPhraseId || dstIsMacro)
{
// get the memory index for src
uint srcMemoryIndex= pCSSrc->getIndexInDB();
// memorize dst into src
memorizePhraseOrMacro(srcMemoryIndex, dstIsMacro, dstPhraseId, dstMacroId);
// memorize src into dst
memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId);
}
// else, it's a move
else
{
// copy
memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId);
// forget src (after shorctut change!)
CAHManager::getInstance()->runActionHandler("forget_phrase_or_macro", pCSSrc);
}
}
}
}
}
// memorize a spell
void CHandlerMemorizePhraseOrMacro::memorizePhraseOrMacro(uint memoryIndex, bool isMacro, sint32 phraseId, sint32 macroId)
{
CSPhraseManager *pPM= CSPhraseManager::getInstance();
sint32 memoryLine= pPM->getSelectedMemoryLineDB();
if(memoryLine<0)
return;
if(isMacro)
{
pPM->memorizeMacro(memoryLine, memoryIndex, macroId);
}
else
{
// memorize in local
pPM->memorizePhrase(memoryLine, memoryIndex, phraseId);
// Send the Server msg
pPM->sendMemorizeToServer(memoryLine, memoryIndex, phraseId);
}
}
// memorize a default spell
void CHandlerMemorizePhraseOrMacro::memorizePhraseSheet(uint memoryIndex, uint32 sheetId)
{
CSPhraseManager *pPM= CSPhraseManager::getInstance();
sint32 memoryLine= pPM->getSelectedMemoryLineDB();
if(memoryLine<0)
return;
// this should have been checked in CanDrag
if(!pPM->isPhraseCastable(sheetId))
return;
// build the com phrase
CSPhraseCom phraseCom;
pPM->buildPhraseFromSheet(phraseCom, sheetId);
if(phraseCom.empty())
return;
// **** first learn this phrase
// \toto yoyo: There is a Network BUG which prevents us from simply doing {Forget(),Delete()} Old phrase,
// then {Learn(),Memorize()} new one (Messages are shuffled).
// Instead, replace the old phrase if needed
uint16 newPhraseId= (uint16)pPM->getMemorizedPhraseIfLastOrNewSlot(memoryLine, memoryIndex);
if(!newPhraseId)
return;
// set it
pPM->setPhrase(newPhraseId, phraseCom);
// send learn to server
pPM->sendLearnToServer(newPhraseId);
// **** memorize
// memorize in local
pPM->memorizePhrase(memoryLine, memoryIndex, newPhraseId);
// Send the Server msg
pPM->sendMemorizeToServer(memoryLine, memoryIndex, newPhraseId);
}
// **********************************************************************************************************
/** Forget a Phrase from a Memory slot
* Called when the user choose to free a spell memory slot
*/
class CHandlerForgetPhraseOrMacro : public IActionHandler
{
public:
virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
{
CSPhraseManager *pPM = CSPhraseManager::getInstance();
CDBCtrlSheet *pCSDst = dynamic_cast(pCaller);
if (pCSDst == NULL) return;
if (!pCSDst->isSPhraseIdMemory() && !pCSDst->isMacroMemory())
return;
// Ok, the user try to forget a phrase slot.
sint32 memoryLine= pPM->getSelectedMemoryLineDB();
if(memoryLine<0)
return;
// get the memory index
uint memoryIndex= pCSDst->getIndexInDB();
if(pCSDst->isMacro())
{
pPM->forgetMacro(memoryLine, memoryIndex);
}
else
{
// forget in local.
pPM->forgetPhrase(memoryLine, memoryIndex);
// Server com.
pPM->sendForgetToServer(memoryLine, memoryIndex);
}
}
};
REGISTER_ACTION_HANDLER( CHandlerForgetPhraseOrMacro, "forget_phrase_or_macro");
// **********************************************************************************************************
/** Forget a Phrase from a Memory slot
* Called when the user choose to free a spell memory slot
*/
class CHandlerDeletePhraseOrForgetMacro : public IActionHandler
{
public:
virtual void execute (CCtrlBase *pCaller, const string & Params)
{
CDBCtrlSheet *pCSDst = dynamic_cast(pCaller);
if (pCSDst == NULL) return;
if (!pCSDst->isSPhraseIdMemory() && !pCSDst->isMacroMemory())
return;
// get the memory index
uint memoryIndex = pCSDst->getIndexInDB();
bool isMacro = pCSDst->isMacro();
sint32 phraseId = pCSDst->getSPhraseId();
// build params string
string sParams;
sParams.append("memoryIndex=");
sParams.append(toString(memoryIndex));
sParams.append("|isMacro=");
sParams.append(toString(isMacro));
sParams.append("|phraseId=");
sParams.append(toString(phraseId));
if (!Params.empty())
{
sParams.append("|");
sParams.append(Params);
}
// Ask if ok before
CInterfaceManager *pIM = CInterfaceManager::getInstance();
pIM->validMessageBox(CInterfaceManager::QuestionIconMsg, CI18N::get("uiQDeleteAction"), "do_delete_phrase_or_forget_macro", sParams);
}
};
REGISTER_ACTION_HANDLER( CHandlerDeletePhraseOrForgetMacro, "delete_phrase_or_forget_macro");
// **********************************************************************************************************
/** Forget a Phrase from a Memory slot
* Called when the user confirmed that he want to free a spell memory slot
*/
class CHandlerDoDeletePhraseOrForgetMacro : public IActionHandler
{
public:
virtual void execute (CCtrlBase *pCaller, const string &Params)
{
// Ok, the user try to forget a phrase slot
CSPhraseManager *pPM = CSPhraseManager::getInstance();
sint32 memoryLine = pPM->getSelectedMemoryLineDB();
if (memoryLine<0)
return;
// get params
uint memoryIndex;
fromString(getParam(Params, "memoryIndex"), memoryIndex);
bool isMacro;
fromString(getParam(Params, "isMacro"),isMacro);
sint32 phraseId;
fromString(getParam(Params, "phraseId"),phraseId);
if (isMacro)
{
pPM->forgetMacro(memoryLine, memoryIndex);
}
else
{
// do all the thing to delete properly this phrase
pPM->fullDelete(phraseId);
}
}
};
REGISTER_ACTION_HANDLER( CHandlerDoDeletePhraseOrForgetMacro, "do_delete_phrase_or_forget_macro");
// **********************************************************************************************************
/** Cast a spell from a memory slot (combat or magic)
* Called when the user click on a memory slot. Can be called also from CAHRunShortcut, or from
* MoveToAction system (in CSPhraseManager)
*/
class CHandlerCastPhrase : public IActionHandler
{
public:
static sint64 LastHitTime;
static sint LastIndex;
public:
virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CSPhraseManager *pPM = CSPhraseManager::getInstance();
CSBrickManager *pBM= CSBrickManager::getInstance();
CDBCtrlSheet *pCSDst = dynamic_cast(pCaller);
if (pCSDst == NULL) return;
if (!pCSDst->isSPhraseIdMemory())
return;
// Can cast only if not Latent (ie grayed) !!
if (pCSDst->getGrayed())
return;
// Ok, the user try to cast a phrase slot.
sint32 memoryLine;
if (pCSDst->isShortCut())
memoryLine = pPM->getSelectedMemoryLineDB();
else
memoryLine = 0;
if(memoryLine<0)
return;
// get the memory index
uint memoryIndex= pCSDst->getIndexInDB();
// Check If the phrase exist
sint phraseId= pCSDst->getSPhraseId();
if(!phraseId)
return;
const CSPhraseCom &phraseCom= pPM->getPhrase(phraseId);
if(phraseCom.empty())
return;
CSBrickSheet *rootBrick= pBM->getBrick(phraseCom.Bricks[0]);
if(!rootBrick)
return;
// **** Check If the phrase is a Craft Phrase.
if( rootBrick->isFaber() )
{
extern void launchFaberCastWindow(sint32 , uint , CSBrickSheet *);
launchFaberCastWindow(memoryLine, memoryIndex, rootBrick);
// Cancel any moveTo, because don't want to continue reaching the prec entity
UserEntity->resetAnyMoveTo();
}
// **** Else standart cast
else
{
// **** Cyclic Cast? (dblclick)
bool cyclic;
// Manage "DblHit"
uint dbclickDelay = pIM->getUserDblClickDelay();
// if success to "dblclick"
if(LastIndex==(sint)memoryIndex && T1<=LastHitTime+dbclickDelay )
cyclic= true;
else
cyclic= false;
// for next hit
LastHitTime= T1;
LastIndex= memoryIndex;
// can't cast magic phrase while moving
if( rootBrick->isMagic() )
{
if( UserControls.isMoving() || (UserEntity && UserEntity->follow() && UserEntity->speed()!=0.0) )
{
// display "you can't cast while moving"
CInterfaceManager *pIM= CInterfaceManager::getInstance();
ucstring msg = CI18N::get("msgNoCastWhileMoving");
string cat = getStringCategory(msg, msg);
pIM->displaySystemInfo(msg, cat);
return;
}
}
// Can't cyclic cast Magic, SpecialPower or Harvest phrases (forage_extraction are auto)
if( rootBrick->isMagic() || rootBrick->isHarvest() || rootBrick->isSpecialPower() )
cyclic= false;
// auto cyclic for forage extraction
if( rootBrick->isForageExtraction() )
cyclic= true;
// even for extraction, if AvoidCyclic in any bricks, no cyclic!
if( pPM->avoidCyclicForPhrase(phraseCom) )
cyclic= false;
// **** Launch the cast
// Cast only if their is a target, or if it is not a combat action
CEntityCL *target = EntitiesMngr.entity(UserEntity->targetSlot());
if(target || !rootBrick->isCombat())
{
// combat (may moveTo before) ?
if(rootBrick->isCombat())
{
if( !UserEntity->canEngageCombat() )
return;
UserEntity->executeCombatWithPhrase(target, memoryLine, memoryIndex, cyclic);
}
// else can cast soon!
else if ( rootBrick->isForageExtraction() && (! UserEntity->isRiding()) ) // if mounted, send directly to server (without moving) to receive the error message
{
// Yoyo: TEMP if a target selected, must be a forage source
if(!target || target->isForageSource())
{
// Cancel any follow
UserEntity->disableFollow();
// reset any moveTo also (if target==NULL, moveToExtractionPhrase() and therefore resetAnyMoveTo() not called)
// VERY important if previous MoveTo was a SPhrase MoveTo (because cancelClientExecute() must be called)
UserEntity->resetAnyMoveTo();
// Move to targetted source
if ( target )
UserEntity->moveToExtractionPhrase( target->slot(), MaxExtractionDistance, memoryLine, memoryIndex, cyclic );
// start client execution
pPM->clientExecute(memoryLine, memoryIndex, cyclic);
if ( ! target )
{
// inform Server of phrase cast
pPM->sendExecuteToServer(memoryLine, memoryIndex, cyclic);
}
}
}
else
{
// Cancel any moveTo(), because don't want to continue reaching the prec entity
// VERY important if previous MoveTo was a SPhrase MoveTo (because cancelClientExecute() must be called)
UserEntity->resetAnyMoveTo();
// start client execution: NB: start client execution even if it
pPM->clientExecute(memoryLine, memoryIndex, cyclic);
// inform Server of phrase cast
pPM->sendExecuteToServer(memoryLine, memoryIndex, cyclic);
}
}
}
}
};
REGISTER_ACTION_HANDLER( CHandlerCastPhrase, "cast_phrase");
sint64 CHandlerCastPhrase::LastHitTime= 0;
sint CHandlerCastPhrase::LastIndex= -1;
// ***************************************************************************
/** Called when user hit the 1.2.3.4.5..... key
*/
class CAHRunShortcut : public IActionHandler
{
public:
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
{
sint shortcut;
fromString(Params, shortcut);
if (shortcut>=0 && shortcut <= 2*RYZOM_MAX_SHORTCUT)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
// get the control
CInterfaceElement *elm;
if (shortcut < RYZOM_MAX_SHORTCUT)
elm = CWidgetManager::getInstance()->getElementFromId(PhraseMemoryCtrlBase + toString(shortcut) );
else
elm = CWidgetManager::getInstance()->getElementFromId(PhraseMemoryAltCtrlBase + toString(shortcut-RYZOM_MAX_SHORTCUT) );
CDBCtrlSheet *ctrl= dynamic_cast(elm);
if(ctrl)
{
// run the standard cast case.
if(ctrl->isMacro())
CAHManager::getInstance()->runActionHandler("cast_macro", ctrl);
else
CAHManager::getInstance()->runActionHandler("cast_phrase", ctrl);
}
}
}
};
REGISTER_ACTION_HANDLER (CAHRunShortcut, "run_shortcut");
// ***************************************************************************
/** Called when the user click on a memory slot. Different AH called if the slot is empty or full
*/
class CHandlerCastPhraseOrCreateNew : public IActionHandler
{
public:
virtual void execute (CCtrlBase *pCaller, const string &Params)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CDBCtrlSheet *pCSDst = dynamic_cast(pCaller);
if (pCSDst == NULL) return;
if (!pCSDst->isSPhraseIdMemory())
return;
// get the phrase id under it
sint phraseId= pCSDst->getSPhraseId();
// if a phrase is on this slot, just cast the phrase
if(phraseId)
{
CAHManager::getInstance()->runActionHandler("cast_phrase", pCaller, Params);
}
// else open the RightMenuEmpty, to have "NewAction"
else
{
string menu= pCSDst->getListMenuRightEmptySlot();
// opens only if no dragged sheet
if( !menu.empty() && CDBCtrlSheet::getDraggedSheet()==NULL )
{
// opens the menu
CDBCtrlSheet::setCurrSelSheet(pCSDst);
CWidgetManager::getInstance()->enableModalWindow (pCSDst, menu);
}
}
}
};
REGISTER_ACTION_HANDLER (CHandlerCastPhraseOrCreateNew, "cast_phrase_or_create_new");
// ***************************************************************************
/** Called to get info on Phrase Link
*/
class CHandlerPhraseLinkCtrlRClick : public IActionHandler
{
public:
virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
CInterfaceGroup *parent= pCaller->getParent();
if(parent)
{
// Get the Brother CtrlSheet
CDBCtrlSheet *ctrl= dynamic_cast(parent->getCtrl("ctrl_phrase"));
if(ctrl)
{
CAHManager::getInstance()->runActionHandler(ctrl->getActionOnRightClick(), ctrl, ctrl->getParamsOnRightClick());
}
}
}
};
REGISTER_ACTION_HANDLER (CHandlerPhraseLinkCtrlRClick, "phrase_link_ctrl_rclick");
// ***************************************************************************
/** Called to cancel a Phrase link
*/
class CHandlerPhraseLinkStop : public IActionHandler
{
public:
virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
// get the link index
uint8 index;
fromString(Params, index);
// Get the link counter. Used to verify that the client cancel the correct link according to server
uint8 counter= 0;
CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:EXECUTE_PHRASE:LINK:%d:COUNTER", index), false);
if(node)
counter= node->getValue8();
// Send msg to server
if (!ClientCfg.Local)
{
NLMISC::CBitMemStream out;
if(GenericMsgHeaderMngr.pushNameToStream("PHRASE:CANCEL_LINK", out))
{
out.serial(index);
out.serial(counter);
NetMngr.push(out);
}
else
{
nlwarning(" unknown message name '%s'", "PHRASE:CANCEL_LINK");
}
}
else
{
// debug:
pIM->displaySystemInfo( toString("PHRASE:CANCEL_LINK %d, %d", index, counter) );
}
}
};
REGISTER_ACTION_HANDLER(CHandlerPhraseLinkStop, "phrase_link_stop");
// ***************************************************************************
/** Called to cancel a Phrase link
*/
class CHandlerPhraseCancelCast: public IActionHandler
{
public:
virtual void execute(CCtrlBase * /* pCaller */, const string &/* Params */)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
// Send msg to server
if (!ClientCfg.Local)
{
UserEntity->cancelAllPhrases();
}
else
{
// debug:
pIM->displaySystemInfo( ucstring("PHRASE:CANCEL_ALL") );
}
}
};
REGISTER_ACTION_HANDLER(CHandlerPhraseCancelCast, "phrase_cancel_cast");
// ***************************************************************************
/// Called when one of the BRICK_TICK_RANGE has changed
class CHandlerPhraseUpdateAllMemoryRegenTickRange : public IActionHandler
{
public:
virtual void execute(CCtrlBase *, const string &)
{
CSPhraseManager *pPM= CSPhraseManager::getInstance();
pPM->updateAllMemoryCtrlState();
pPM->touchRegenTickRangeFlag();
}
};
REGISTER_ACTION_HANDLER(CHandlerPhraseUpdateAllMemoryRegenTickRange, "phrase_update_all_memory_ctrl_regen_tick_range");
// ***************************************************************************
/// Called when we right click on a brick in the memories
class CHandlerPhraseCheckCanCristalize: public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
{
const string sCristalizePath = "ui:interface:cm_memory_phrase:cri";
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CSPhraseManager *pPM = CSPhraseManager::getInstance();
CSBrickManager *pBM = CSBrickManager::getInstance();
CInterfaceElement *pCristalizeMenuOption = CWidgetManager::getInstance()->getElementFromId(sCristalizePath);
if (pCristalizeMenuOption == NULL) return;
// The default is to not display the cristalize menu option
pCristalizeMenuOption->setActive(false);
if (pCaller == NULL) return;
// Get the interface control sheet
CDBCtrlSheet *pCS = dynamic_cast(CWidgetManager::getInstance()->getCtrlLaunchingModal());
if (pCS == NULL) return;
if (!pCS->isSPhraseIdMemory()) return;
// If its a phrase id in memory then get the phrase
const CSPhraseCom &phrase = pPM->getPhrase(pCS->getSheetId());
if (phrase.empty()) return;
// If the phrase is not empty get the root to known if its a magic phrase or not
// And if its a magic phrase display the cristalize menu option
CSBrickSheet *pBrick = pBM->getBrick(phrase.Bricks[0]);
if (pBrick != NULL)
{
if (pBrick->isMagic())
{
pCristalizeMenuOption->setActive(true);
// Disable the cristalize item if the player has a forage in progress
CViewTextMenu* vtm = dynamic_cast(pCristalizeMenuOption);
if ( vtm )
{
CTempInvManager *tim = CTempInvManager::getInstance();
bool isForageInProgress = tim && tim->isOpened() && (tim->getMode() == TEMP_INV_MODE::Forage);
vtm->setGrayed( isForageInProgress );
}
}
}
}
};
REGISTER_ACTION_HANDLER(CHandlerPhraseCheckCanCristalize, "phrase_check_can_cristalize");
// ***************************************************************************
/// Called after the cm_memory_phrase menu has been opened on a magic phrase
class CHandlerPhraseCristalize: public IActionHandler
{
public:
virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
{
CSPhraseManager *pPM = CSPhraseManager::getInstance();
CDBCtrlSheet *pCSDst = dynamic_cast(pCaller);
if (pCSDst == NULL) return;
if (!pCSDst->isSPhraseIdMemory())
return;
// Can cast only if not Latent (ie grayed) !!
if (pCSDst->getGrayed())
return;
// Ok, the user try to cast a phrase slot.
sint32 memoryLine;
if (pCSDst->isShortCut())
memoryLine = pPM->getSelectedMemoryLineDB();
else
memoryLine = 0;
if(memoryLine<0)
return;
// get the memory index
uint memoryIndex= pCSDst->getIndexInDB();
// execute both client and server
pPM->executeCristalize(memoryLine, memoryIndex);
}
};
REGISTER_ACTION_HANDLER(CHandlerPhraseCristalize, "phrase_cristalize");
// ***************************************************************************
class CHandlerPhraseBookSkillFilter : public IActionHandler
{
public:
virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
{
CSPhraseManager *pPM= CSPhraseManager::getInstance();
// If the param is a BrickType Filter...
string btFilter= getParam(Params, "bt");
if(!btFilter.empty())
{
BRICK_TYPE::EBrickType bt= BRICK_TYPE::toBrickType(btFilter);
if(bt!=BRICK_TYPE::UNKNOWN)
pPM->setBookFilter(bt, SKILLS::unknown);
}
// else it is a skill filter
else
{
sint index;
fromString(Params, index);
if(index>=0 && indexsetBookFilter(BRICK_TYPE::UNKNOWN, (SKILLS::ESkills)index);
else
pPM->setBookFilter(BRICK_TYPE::UNKNOWN, SKILLS::unknown);
}
}
};
REGISTER_ACTION_HANDLER(CHandlerPhraseBookSkillFilter, "phrase_book_skill_filter");
// ***************************************************************************
class CHandlerPhraseSelectMemory : public IActionHandler
{
public:
virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
{
string expr = getParam (Params, "value");
CInterfaceExprValue value;
if (CInterfaceExpr::eval(expr, value, NULL))
{
if (!value.toInteger())
{
nlwarning(" expression doesn't evaluate to a numerical value");
}
else
{
CSPhraseManager *pPM= CSPhraseManager::getInstance();
sint val= (sint32)value.getInteger();
clamp(val, 0, MEM_SET_TYPES::NumMemories-1);
pPM->selectMemoryLineDB(val);
}
}
}
};
REGISTER_ACTION_HANDLER(CHandlerPhraseSelectMemory, "phrase_select_memory");
// ***************************************************************************
class CHandlerPhraseSelectShortcutBar : public IActionHandler
{
public:
virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("UI:PHRASE:SELECT_MEMORY", false);
if(node)
{
sint32 val;
fromString(Params, val);
node->setValue32(val);
}
}
};
REGISTER_ACTION_HANDLER(CHandlerPhraseSelectShortcutBar, "select_shortcut_bar");
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// HELP / LINKS
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// This expr is used only for define in phrase.xml.
DECLARE_INTERFACE_CONSTANT(getPhraseBrickSelectionMax, CDBGroupBuildPhrase::MaxSelection)
// ***************************************************************************
// Get the UC name of a phraseId
static DECLARE_INTERFACE_USER_FCT(getSPhraseName)
{
if (args.size() > 0)
{
if(!args[0].toInteger())
return false;
sint sphraseId= (sint)args[0].getInteger();
CSPhraseManager *pPM= CSPhraseManager::getInstance();
result.setUCString(pPM->getPhrase(sphraseId).Name);
return true;
}
else
{
return false;
}
}
REGISTER_INTERFACE_USER_FCT("getSPhraseName", getSPhraseName)
// ***************************************************************************
// Get the tooltip of a Combat Weapon restriction brick
class CHandlerCombatRestrictTooltip : public IActionHandler
{
public:
virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
{
CInterfaceManager *pIM= CInterfaceManager::getInstance();
CDBCtrlSheet *ctrlSheet= dynamic_cast(pCaller);
if(!ctrlSheet)
return;
ucstring str(STRING_MANAGER::CStringManagerClient::getSBrickLocalizedName(CSheetId(ctrlSheet->getSheetId())));
// According to locked state
if(ctrlSheet->getGrayed())
strFindReplace(str, "%comp", CI18N::get("uittPhraseCombatRestrictKO"));
else
strFindReplace(str, "%comp", CI18N::get("uittPhraseCombatRestrictOK"));
pIM->setContextHelpText(str);
}
};
REGISTER_ACTION_HANDLER( CHandlerCombatRestrictTooltip, "phrase_combat_restrict_tooltip");
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// BOT CHAT
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
void phraseBotChatBuyBySheet(NLMISC::CSheetId sheetId, uint16 phraseId)
{
uint32 sheetNum= sheetId.asInt();
if (!ClientCfg.Local)
{
NLMISC::CBitMemStream out;
if(GenericMsgHeaderMngr.pushNameToStream("PHRASE:BUY_SHEET", out))
{
out.serial(sheetNum);
out.serial(phraseId);
NetMngr.push(out);
}
else
{
nlwarning(" unknown message name '%s'", "PHRASE:BUY_SHEET");
}
}
else
{
// debug:
CInterfaceManager *pIM= CInterfaceManager::getInstance();
pIM->displaySystemInfo( toString("PHRASE:BUY_SHEET => ") + toString(phraseId) );
// **** Server emulation
// learn all bricks of this phrase
CSPhraseSheet *phrase= dynamic_cast(SheetMngr.get(sheetId));
if(phrase)
{
CSBrickManager *pBM= CSBrickManager::getInstance();
// For all bricks of this phrase
for(uint i=0;iBricks.size();i++)
{
CSBrickSheet *brick= pBM->getBrick(phrase->Bricks[i]);
if(brick)
{
// force learn it.
CCDBNodeLeaf * node= pBM->getKnownBrickBitFieldDB(brick->BrickFamily);
if(node)
{
uint64 flags= node->getValue64();
flags|= uint64(1)<<(brick->IndexInFamily-1);
node->setValue64(flags);
}
}
}
}
// ack phrase learn
CSPhraseManager *pPM= CSPhraseManager::getInstance();
if(phraseId)
pPM->receiveBotChatConfirmBuy(phraseId, true);
// synchronize
uint counter= pIM->getLocalSyncActionCounter();
NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:COUNTER")->setValue32(counter);
NLGUI::CDBManager::getInstance()->getDbProp("SERVER:EXCHANGE:COUNTER")->setValue32(counter);
NLGUI::CDBManager::getInstance()->getDbProp("SERVER:TARGET:CONTEXT_MENU:COUNTER")->setValue32(counter);
NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:COUNTER")->setValue32(counter);
}
}
// ***************************************************************************
void phraseBotChatBuyActionByIndex(uint8 index, uint16 phraseId)
{
if (!ClientCfg.Local)
{
// send the selection to the server
NLMISC::CBitMemStream out;
if(GenericMsgHeaderMngr.pushNameToStream("PHRASE:BUY", out))
{
out.serial(index);
out.serial(phraseId);
NetMngr.push(out);
}
else
nlwarning(" unknown message name 'PHRASE:BUY");
}
else
{
// debug:
CInterfaceManager *pIM= CInterfaceManager::getInstance();
pIM->displaySystemInfo("PHRASE:BUY => " + toString(phraseId) );
}
}
// ***************************************************************************
/* Called from CConfirmBuyItem action handler
*/
void phraseBuyBotChat(CDBCtrlSheet *ctrl, uint8 index, bool useBuySheetMsg)
{
CSBrickManager *pBM= CSBrickManager::getInstance();
CSPhraseManager *pSM= CSPhraseManager::getInstance();
if(!ctrl->isSPhrase())
return;
// Get the SPhrase
const CSPhraseSheet *sp= ctrl->asSPhraseSheet();
if(!sp || sp->Bricks.empty())
return;
// Verify that the phrase is not a special "CHARACTERISTIC BUYING" phrase
bool isCharacBuying= false;
CSBrickSheet *brickSheet= pBM->getBrick(CSheetId(sp->Bricks[0]));
if(brickSheet && BRICK_FAMILIES::isCharacBuyFamily(brickSheet->BrickFamily) )
isCharacBuying= true;
// confirm the buy
{
// default: not append to the manager
uint16 phraseId= 0;
// Append the phrase to the manager. ONLY if this phrase is castable
if(sp->Castable && !isCharacBuying)
{
CSPhraseCom phraseCom;
pSM->buildPhraseFromSheet(phraseCom, ctrl->getSheetId());
if(phraseCom.empty())
return;
// get the new phraseId
phraseId= (uint16)pSM->allocatePhraseSlot();
// Since we are not sure this slot work, lock it!
pSM->setPhrase(phraseId, phraseCom, true);
}
// Special for LOCAL:USER:SKILL_POINTS_ update
CInterfaceManager *pIM= CInterfaceManager::getInstance();
pIM->incLocalSyncActionCounter();
// Send msg to server
if(useBuySheetMsg)
phraseBotChatBuyBySheet(sp->Id, phraseId);
else
phraseBotChatBuyActionByIndex(index, phraseId);
}
}
// ***************************************************************************
// Command for Debug BotChat ACK.
NLMISC_COMMAND(phraseComfirmBuy, "Debug: confirm a phrase BotChat buy", "")
{
if(args.size() != 2) return false;
uint phraseId;
fromString(args[0], phraseId);
bool confirm;
fromString(args[1], confirm);
CSPhraseManager *pSM= CSPhraseManager::getInstance();
pSM->receiveBotChatConfirmBuy(phraseId, confirm);
return true;
}
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// MACRO
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
class CHandlerCastMacro : public IActionHandler
{
public:
virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
{
CMacroCmdManager *pMM = CMacroCmdManager::getInstance();
CDBCtrlSheet *pCSDst = dynamic_cast(pCaller);
if (pCSDst == NULL) return;
if (!pCSDst->isMacroMemory())
return;
// Can cast only if not grayed
if (pCSDst->getGrayed())
return;
// execute the macro id
pMM->executeID(pCSDst->getMacroId());
}
};
REGISTER_ACTION_HANDLER( CHandlerCastMacro, "cast_macro");
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// MISC
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
class CHandlerPhraseMemoryBeforeMenu : public IActionHandler
{
public:
static uint32 LastPhraseIdMenu;
virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
{
CDBCtrlSheet *ctrl= dynamic_cast(pCaller);
if(ctrl && ctrl->isSPhraseIdMemory())
{
LastPhraseIdMenu= ctrl->getSPhraseId();
}
}
};
REGISTER_ACTION_HANDLER( CHandlerPhraseMemoryBeforeMenu, "phrase_memory_before_menu");
uint32 CHandlerPhraseMemoryBeforeMenu::LastPhraseIdMenu= 0;
// ***************************************************************************
static DECLARE_INTERFACE_USER_FCT(isPhraseMenuNotExecuting)
{
bool ok= true;
// if the PhraseId for this menu is equal to either cyclic action, or next action, fails
CSPhraseManager *pPM= CSPhraseManager::getInstance();
if(CHandlerPhraseMemoryBeforeMenu::LastPhraseIdMenu!=0)
{
if(pPM->getCycleExecutePhraseId()==CHandlerPhraseMemoryBeforeMenu::LastPhraseIdMenu)
ok= false;
if(pPM->getNextExecutePhraseId()==CHandlerPhraseMemoryBeforeMenu::LastPhraseIdMenu)
ok= false;
}
result.setBool(ok);
return true;
}
REGISTER_INTERFACE_USER_FCT("isPhraseMenuNotExecuting", isPhraseMenuNotExecuting)