Fix css style order when using external css files
[ryzomcore.git] / ryzom / client / src / interface_v3 / action_handler_phrase.cpp
blob489dcbc35c6a9a4c593aa2e436c82991f9f0d43c
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "stdpch.h"
27 #include "nel/gui/action_handler.h"
28 #include "../motion/user_controls.h"
29 #include "../view.h"
30 #include "../misc.h"
31 #include "../input.h"
32 #include "../client_cfg.h"
33 #include "../actions_client.h"
34 #include "../sheet_manager.h"
35 #include "interface_manager.h"
36 #include "dbctrl_sheet.h"
37 #include "dbgroup_build_phrase.h"
38 #include "nel/gui/group_container.h"
39 #include "sphrase_manager.h"
40 #include "sbrick_manager.h"
41 #include "nel/gui/ctrl_button.h"
42 #include "../user_entity.h"
43 #include "skill_manager.h"
44 #include "inventory_manager.h"
45 #include "game_share/memorization_set_types.h"
46 #include "action_handler_help.h"
47 #include "bot_chat_page_all.h"
48 #include "bot_chat_page_trade.h"
49 #include "../net_manager.h"
50 #include "../entities.h"
51 #include "macrocmd_manager.h"
52 #include "nel/gui/group_menu.h"
53 #include "nel/gui/group_tree.h"
55 extern CSheetManager SheetMngr;
57 using namespace std;
58 using namespace NLMISC;
62 // ***************************************************************************
63 void launchPhraseComposition(bool creation);
64 const std::string PhraseComposition="ui:interface:phrase_composition";
65 const std::string PhraseCompositionGroup="ui:interface:phrase_composition:header_opened";
66 const std::string PhraseMemoryCtrlBase= "ui:interface:gestionsets:shortcuts:s";
67 const std::string PhraseMemoryAltCtrlBase= "ui:interface:gestionsets2:header_closed:shortcuts:s";
70 // **********************************************************************************************************
71 // debug update the action bar
72 void debugUpdateActionBar()
74 CInterfaceManager *pIM= CInterfaceManager::getInstance();
75 NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:ACT_TSTART")->setValue64(NetMngr.getCurrentServerTick());
76 NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:ACT_TEND")->setValue64(NetMngr.getCurrentServerTick()+30);
80 // ***************************************************************************
81 // ***************************************************************************
82 // ***************************************************************************
83 // PHRASE BOOK EDITION
84 // ***************************************************************************
85 // ***************************************************************************
86 // ***************************************************************************
89 // ***************************************************************************
90 class CHandlerPhraseEdit : public IActionHandler
92 public:
93 virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
95 CDBCtrlSheet *pCSDst = dynamic_cast<CDBCtrlSheet*>(pCaller);
96 if (pCSDst == NULL || !pCSDst->isSPhraseId())
97 return;
99 // get the phrase id.
100 sint32 id= pCSDst->getSPhraseId();
102 // Nb: Yoyo: this slot can come from eiter the Action Book, or the Memorized sentence
104 // set the phrase to edit
105 CSPhraseManager *pPM= CSPhraseManager::getInstance();
106 pPM->CompositionPhraseId= id;
107 pPM->CompositionPhraseMemoryLineDest= -1;
108 pPM->CompositionPhraseMemorySlotDest= -1;
110 // Launch the composition window
111 launchPhraseComposition(false);
114 REGISTER_ACTION_HANDLER( CHandlerPhraseEdit, "phrase_edit" );
117 // ***************************************************************************
118 class CHandlerPhraseNew : public IActionHandler
120 public:
121 virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
123 // Get A free slot to edit (not allocated).
124 CSPhraseManager *pPM= CSPhraseManager::getInstance();
125 // if possible
126 if(pPM->hasFreeSlot())
128 // Set the phrase to edit to 0, to indicate a new phrase. CANNOT "ALLOCATE" THE ID NOW, else may
129 // crash if buy a botchatphrase, while editing a new phrase!!!!
130 pPM->CompositionPhraseId= 0;
132 // If the caller is ctrl sheet (may be a standard button else), and if comes from memory
133 CDBCtrlSheet *pCSDst= dynamic_cast<CDBCtrlSheet*>(pCaller);
134 if(pCSDst && pCSDst->isSPhraseId() && pCSDst->isSPhraseIdMemory())
136 // then will auto-memorize it in this slot
137 if (pCSDst->isShortCut())
138 pPM->CompositionPhraseMemoryLineDest= pPM->getSelectedMemoryLineDB();
139 else
140 pPM->CompositionPhraseMemoryLineDest= 0;
142 pPM->CompositionPhraseMemorySlotDest= pCSDst->getIndexInDB();
144 // else no auto memorize
145 else
147 pPM->CompositionPhraseMemoryLineDest= -1;
148 pPM->CompositionPhraseMemorySlotDest= -1;
151 // Launch the composition window
152 launchPhraseComposition(true);
156 REGISTER_ACTION_HANDLER( CHandlerPhraseNew, "phrase_new" );
159 // ***************************************************************************
160 class CHandlerPhraseValidate : public IActionHandler
162 public:
163 virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
165 // NB: The user can validate only if the server was OK.
167 // get our father build sentence
168 CInterfaceGroup *parent = pCaller->getParent();
169 if (parent)
171 CSPhraseManager *pPM= CSPhraseManager::getInstance();
173 CDBGroupBuildPhrase *buildGroup= dynamic_cast<CDBGroupBuildPhrase*>(parent->getParent());
174 if(!buildGroup)
175 return;
177 // is this an action creation or action edition?
178 bool actionCreation= pPM->CompositionPhraseId==0;
180 // For a new created phrase, the CompositionPhraseId is 0, allocate it now
181 if(!pPM->CompositionPhraseId)
183 pPM->CompositionPhraseId= pPM->allocatePhraseSlot();
184 // fail?
185 if(!pPM->CompositionPhraseId)
186 return;
189 // build the edited phrase
190 CSPhraseCom newPhrase;
191 buildGroup->buildCurrentPhrase(newPhrase);
193 // the new slot of the phrase
194 uint32 slotId= pPM->CompositionPhraseId;
196 // Action Creation case.
197 if(actionCreation)
199 // Append in the Phrase Manager.
200 pPM->setPhrase(slotId, newPhrase);
202 // inform the server of our book change, with the edited name
203 pPM->sendLearnToServer(slotId);
205 // if this action creation requires an auto "memorize in slot"
206 sint32 memoryLine= pPM->CompositionPhraseMemoryLineDest;
207 sint32 memorySlot= pPM->CompositionPhraseMemorySlotDest;
208 if( memoryLine>=0 &&
209 memorySlot>=0 &&
210 memorySlot<PHRASE_MAX_MEMORY_SLOT)
212 // then memorize auto, client and server
213 pPM->memorizePhrase(memoryLine, memorySlot, slotId);
214 pPM->sendMemorizeToServer(memoryLine, memorySlot, slotId);
217 // Action edition case
218 else
220 // Replace in the Phrase Manager.
221 pPM->setPhrase(slotId, newPhrase);
223 // inform the server of our book change, with the edited name
224 pPM->sendLearnToServer(slotId);
226 // Then, auto-re_memorize all after, changing Ctrl Gray States if needed, and sending msg to server
227 pPM->rememorizeAllThatUsePhrase(slotId);
230 // Close the Composition Window
231 pCaller->getRootWindow()->setActive(false);
235 REGISTER_ACTION_HANDLER( CHandlerPhraseValidate, "phrase_validate" );
238 // ***************************************************************************
239 class CHandlerPhraseValidateOnEnter : public IActionHandler
241 public:
242 virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
244 // Test if the OK control is valid.
245 CGroupContainer *pGC= dynamic_cast<CGroupContainer*>(pCaller);
246 if(!pGC) return;
247 if(!pGC->getHeaderOpened()) return;
248 CDBGroupBuildPhrase *buildPhrase= dynamic_cast<CDBGroupBuildPhrase*>(pGC->getHeaderOpened());
249 if(!buildPhrase) return;
250 CCtrlBaseButton *button= buildPhrase->getValidateButton();
252 // Ok, button found. test if active and not frozen.
253 if( button && button->getActive() && !button->getFrozen() )
255 // Act as if the player click on this button
256 CInterfaceManager *pIM = CInterfaceManager::getInstance();
257 CAHManager::getInstance()->runActionHandler(button->getActionOnLeftClick(), button, button->getParamsOnLeftClick() );
261 REGISTER_ACTION_HANDLER( CHandlerPhraseValidateOnEnter, "phrase_validate_on_enter");
264 // ***************************************************************************
265 void launchPhraseComposition(bool creation)
267 CInterfaceManager *pIM= CInterfaceManager::getInstance();
269 // Launch the composition window
270 CGroupContainer *window= dynamic_cast<CGroupContainer*>( CWidgetManager::getInstance()->getElementFromId(PhraseComposition) );
271 if(window)
273 CDBGroupBuildPhrase *buildSentenceTarget= dynamic_cast<CDBGroupBuildPhrase*>( CWidgetManager::getInstance()->getElementFromId(PhraseCompositionGroup) );
274 // if found
275 if(buildSentenceTarget)
277 // enable the window
278 window->setActive(true);
280 // Set the Text of the Window
281 if(creation)
282 window->setTitle(CI18N::get("uiPhraseCreate"));
283 else
284 window->setTitle(CI18N::get("uiPhraseEdit"));
286 // clear the sentence for a New Phrase creation.
287 buildSentenceTarget->clearBuildingPhrase();
289 // copy phrase to edit
290 CSPhraseManager *pPM= CSPhraseManager::getInstance();
291 // get the edited (or empty if new) phrase.
292 const CSPhraseCom &phrase= pPM->getPhrase(pPM->CompositionPhraseId);
293 // Start the composition
294 buildSentenceTarget->startComposition(phrase);
296 /** if edition, avoid changing the root type, it behaves better
298 // Default, no filter (important for creation)
299 if(creation)
301 // all root are possible => no filter
302 buildSentenceTarget->setRootBrickTypeFilter(BRICK_TYPE::UNKNOWN);
304 // if edition
305 else
307 if(phrase.empty())
309 buildSentenceTarget->setRootBrickTypeFilter(BRICK_TYPE::UNKNOWN);
311 else
313 CSBrickManager *pBM= CSBrickManager::getInstance();
314 const CSBrickSheet *rootBrick= pBM->getBrick(phrase.Bricks[0]);
315 // can select only bricks of the same type
316 if(rootBrick)
317 buildSentenceTarget->setRootBrickTypeFilter(BRICK_FAMILIES::brickType(rootBrick->BrickFamily));
318 // maybe data error: filter nothing
319 else
320 buildSentenceTarget->setRootBrickTypeFilter(BRICK_TYPE::UNKNOWN);
328 // ***************************************************************************
329 // ***************************************************************************
330 // ***************************************************************************
331 // PHRASE COMPOSITION
332 // ***************************************************************************
333 // ***************************************************************************
334 // ***************************************************************************
337 // **********************************************************************************************************
338 /** Called when the user select a brick from the list of possible bricks
340 class CHandlerPhraseValidateBrick : public IActionHandler
342 public:
343 virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
345 CInterfaceManager *pIM = CInterfaceManager::getInstance();
347 CDBCtrlSheet *pCSSrc = dynamic_cast<CDBCtrlSheet*>(pCaller);
348 if(!pCSSrc || !pCSSrc->isSBrick())
349 return;
351 // get the selected brick
352 const CSBrickSheet *brick= pCSSrc->asSBrickSheet();
353 if(brick==NULL)
354 return;
356 // and validate the composition
357 // Standard Case: selection for action composition
358 if(BrickType != FaberPlan)
360 nlassert(BuildPhraseGroup);
361 switch(BrickType)
363 case Root: BuildPhraseGroup->validateRoot(brick); break;
364 case OtherMain: BuildPhraseGroup->validateMain(Index, brick); break;
365 case Param: BuildPhraseGroup->validateParam(Index, ParamIndex, brick); break;
366 case NewOpCredit: BuildPhraseGroup->validateNewOpCredit(brick); break;
367 default: break;
370 // Special Case: selection for faber plan
371 else
373 extern void validateFaberPlanSelection(CSBrickSheet *itemPlanBrick);
374 validateFaberPlanSelection(const_cast<CSBrickSheet*>(brick));
377 // And hide the modal
378 CWidgetManager::getInstance()->disableModalWindow();
380 public:
381 enum TType {Root, OtherMain, Param, NewOpCredit, FaberPlan};
382 static TType BrickType;
383 static uint Index;
384 static uint ParamIndex;
385 static CDBGroupBuildPhrase *BuildPhraseGroup;
387 REGISTER_ACTION_HANDLER( CHandlerPhraseValidateBrick, "phrase_validate_brick" );
388 CHandlerPhraseValidateBrick::TType CHandlerPhraseValidateBrick::BrickType;
389 uint CHandlerPhraseValidateBrick::Index;
390 uint CHandlerPhraseValidateBrick::ParamIndex;
391 CDBGroupBuildPhrase *CHandlerPhraseValidateBrick::BuildPhraseGroup= NULL;
394 // ***************************************************************************
395 class CHandlerPhraseSelectMainBrick : public IActionHandler
397 public:
398 virtual void execute(CCtrlBase *pCaller, const string &Params)
400 CInterfaceManager *pIM= CInterfaceManager::getInstance();
402 // get the type and index in the current build sentence
403 uint index;
404 fromString(getParam(Params, "index"), index);
405 CHandlerPhraseValidateBrick::Index= index;
406 if(index==0)
407 CHandlerPhraseValidateBrick::BrickType= CHandlerPhraseValidateBrick::Root;
408 else
409 CHandlerPhraseValidateBrick::BrickType= CHandlerPhraseValidateBrick::OtherMain;
411 // get our father build sentence
412 CDBGroupBuildPhrase *buildGroup= dynamic_cast<CDBGroupBuildPhrase*>(pCaller->getParent()->getParent());
413 if(!buildGroup)
414 return;
415 // setup the validation
416 CHandlerPhraseValidateBrick::BuildPhraseGroup= buildGroup;
418 // build the list of possible bricks
419 if(index==0)
420 buildGroup->fillSelectionRoot();
421 else
422 buildGroup->fillSelectionMain(index);
424 // launch the modal
425 CInterfaceGroup *group= dynamic_cast<CInterfaceGroup*>( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal ) );
426 if(group)
428 // enable the modal
429 CWidgetManager::getInstance()->enableModalWindow(pCaller, group);
433 REGISTER_ACTION_HANDLER( CHandlerPhraseSelectMainBrick, "phrase_select_main_brick" );
436 // ***************************************************************************
437 class CHandlerPhraseSelectParamBrick : public IActionHandler
439 public:
440 virtual void execute(CCtrlBase *pCaller, const string &Params)
442 CInterfaceManager *pIM= CInterfaceManager::getInstance();
444 // get the type and index in the current build sentence
445 CHandlerPhraseValidateBrick::BrickType= CHandlerPhraseValidateBrick::Param;
446 uint index, paramIndex;
447 fromString(getParam(Params, "index"), index);
448 CHandlerPhraseValidateBrick::Index= index;
449 fromString(getParam(Params, "param_index"), paramIndex);
450 CHandlerPhraseValidateBrick::ParamIndex= paramIndex;
452 // get our father build sentence
453 CDBGroupBuildPhrase *buildGroup= dynamic_cast<CDBGroupBuildPhrase*>(pCaller->getParent()->getParent());
454 if(!buildGroup)
455 return;
456 // setup the validation
457 CHandlerPhraseValidateBrick::BuildPhraseGroup= buildGroup;
459 // build the list of possible bricks
460 buildGroup->fillSelectionParam(index, paramIndex);
462 // launch the modal
463 CInterfaceGroup *group= dynamic_cast<CInterfaceGroup*>( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal ) );
464 if(group)
466 // enable the modal
467 CWidgetManager::getInstance()->enableModalWindow(pCaller, group);
471 REGISTER_ACTION_HANDLER( CHandlerPhraseSelectParamBrick, "phrase_select_param_brick" );
474 // ***************************************************************************
475 class CHandlerPhraseSelectNewBrick : public IActionHandler
477 public:
478 virtual void execute(CCtrlBase *pCaller, const string &Params)
480 CInterfaceManager *pIM= CInterfaceManager::getInstance();
482 // get the type and index in the current build sentence
483 CHandlerPhraseValidateBrick::BrickType= CHandlerPhraseValidateBrick::NewOpCredit;
484 string typeStr= getParam(Params, "type");
486 // get our father build sentence
487 CDBGroupBuildPhrase *buildGroup= dynamic_cast<CDBGroupBuildPhrase*>(pCaller->getParent()->getParent());
488 if(!buildGroup)
489 return;
490 // setup the validation
491 CHandlerPhraseValidateBrick::BuildPhraseGroup= buildGroup;
493 // build the list of possible bricks
494 if(typeStr=="optional")
495 buildGroup->fillSelectionNewOp();
496 else if(typeStr=="credit")
497 buildGroup->fillSelectionNewCredit();
499 // launch the modal
500 CInterfaceGroup *group= dynamic_cast<CInterfaceGroup*>( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal ) );
501 if(group)
503 // enable the modal
504 CWidgetManager::getInstance()->enableModalWindow(pCaller, group);
508 REGISTER_ACTION_HANDLER( CHandlerPhraseSelectNewBrick, "phrase_select_new_brick" );
511 // ***************************************************************************
512 class CHandlerPhraseChangeName : public IActionHandler
514 public:
515 virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
517 // The BuildPhrase should be the grandParent
518 CDBGroupBuildPhrase *buildPhrase= dynamic_cast<CDBGroupBuildPhrase*>(pCaller->getParent()->getParent());
519 if(!buildPhrase)
520 return;
521 // update the edited icon
522 buildPhrase->updateSpellView();
525 REGISTER_ACTION_HANDLER( CHandlerPhraseChangeName, "phrase_change_name");
528 // ***************************************************************************
530 * Special For Faber Plan selection
532 class CHandlerPhraseFaberSelectPlan : public IActionHandler
534 public:
535 virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
537 CInterfaceManager *pIM= CInterfaceManager::getInstance();
539 // Launch the modal to select the faber plan
540 extern void fillFaberPlanSelection(const std::string &brickDB, uint maxSelection);
541 fillFaberPlanSelection(CDBGroupBuildPhrase::BrickSelectionDB, CDBGroupBuildPhrase::MaxSelection);
543 // setup the validation
544 CHandlerPhraseValidateBrick::BuildPhraseGroup= NULL;
545 CHandlerPhraseValidateBrick::BrickType= CHandlerPhraseValidateBrick::FaberPlan;
547 // launch the modal
548 CInterfaceGroup *group= dynamic_cast<CInterfaceGroup*>( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal ) );
549 if(group)
551 // enable the modal
552 CWidgetManager::getInstance()->enableModalWindow(pCaller, group);
556 REGISTER_ACTION_HANDLER( CHandlerPhraseFaberSelectPlan, "phrase_faber_select_plan" );
561 // ***************************************************************************
562 // ***************************************************************************
563 // ***************************************************************************
564 // PHRASE MEMORISATION / EXECUTION / MISC
565 // ***************************************************************************
566 // ***************************************************************************
567 // ***************************************************************************
570 // ***************************************************************************
571 static void updateAllSPhraseInfo()
573 CInterfaceManager *pIM= CInterfaceManager::getInstance();
575 // update all info windows
576 CInterfaceHelp::updateWindowSPhraseTexts();
577 // If the composition is opened, refresh
578 CInterfaceGroup *pIG= dynamic_cast<CInterfaceGroup*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:phrase_composition"));
579 if(pIG && pIG->getActive())
581 CDBGroupBuildPhrase *buildPhrase= dynamic_cast<CDBGroupBuildPhrase*>(pIG->getGroup("header_opened"));
582 if(buildPhrase)
583 buildPhrase->updateAllDisplay();
585 // update bot chat
586 if(BotChatPageAll && BotChatPageAll->Trade)
587 BotChatPageAll->Trade->updateSPhraseBuyDialog();
590 // **********************************************************************************************************
591 /** Called when the Item in Right Hand change
593 class CHandlerPhraseUpdateFromHand : public IActionHandler
595 public:
596 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
598 CSPhraseManager *pPM = CSPhraseManager::getInstance();
600 // **** Update the grayed state of all memory ctrls
601 pPM->updateAllMemoryCtrlState();
603 // **** Update misc Action Infos related to items weared
604 updateAllSPhraseInfo();
607 REGISTER_ACTION_HANDLER (CHandlerPhraseUpdateFromHand, "phrase_update_from_hand");
610 // **********************************************************************************************************
611 /** Called when the Item in equip change (Action Malus due to armor)
613 class CHandlerPhraseUpdateFromActionMalus : public IActionHandler
615 public:
616 virtual void execute (CCtrlBase * /* pCaller */, const string &/* Params */)
618 // **** Update misc Action Infos related to items weared
619 updateAllSPhraseInfo();
622 REGISTER_ACTION_HANDLER(CHandlerPhraseUpdateFromActionMalus, "phrase_update_from_action_malus");
625 // **********************************************************************************************************
626 /** drag'n'drop: cannot drag PhraseSheet that are not castable
628 class CHandlerCanDragPhrase : public IActionHandler
630 public:
631 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
633 CSPhraseManager *pPM= CSPhraseManager::getInstance();
635 CDBCtrlSheet *pCSSrc = dynamic_cast<CDBCtrlSheet*>(pCaller);
636 if(!pCSSrc || !pCSSrc->isSPhrase())
637 return;
639 // can drag only if memorizable
640 pCSSrc->setTempCanDrag(pPM->isPhraseCastable(pCSSrc->getSheetId()));
643 REGISTER_ACTION_HANDLER (CHandlerCanDragPhrase, "phrase_can_drag_castable");
646 // **********************************************************************************************************
647 /** drag'n'drop: true if the src ctrlSheet is a Phrase and the dest is in memory. Or if both are in memory
649 class CHandlerCanMemorizePhraseOrMacro : public IActionHandler
651 public:
652 virtual void execute (CCtrlBase *pCaller, const string &Params)
654 CInterfaceManager *pIM = CInterfaceManager::getInstance();
655 CSPhraseManager *pPM = CSPhraseManager::getInstance();
656 CSBrickManager *pBM = CSBrickManager::getInstance();
657 CMacroCmdManager *pMM = CMacroCmdManager::getInstance();
659 string src = getParam(Params, "src");
660 CInterfaceElement *pElt = CWidgetManager::getInstance()->getElementFromId(src);
661 CDBCtrlSheet *pCSSrc = dynamic_cast<CDBCtrlSheet*>(pElt);
662 CDBCtrlSheet *pCSDst = dynamic_cast<CDBCtrlSheet*>(pCaller);
663 // can be a phrase id (comes from memory), a phraseSheet (comes from progression), or a macro,
664 if (pCSSrc->isSPhraseId() || pCSSrc->isMacro() || pCSSrc->isSPhrase())
665 if (pCSDst->isSPhraseId() || pCSDst->isMacro())
667 // check if incoming phrase ok
668 if(pCSSrc->isSPhraseId())
670 // get the src phrase.
671 const CSPhraseCom &phrase= pPM->getPhrase(pCSSrc->getSPhraseId());
672 if(!phrase.empty())
674 // Get the RootBrick of the Phrase
675 CSBrickSheet *brick= pBM->getBrick(phrase.Bricks[0]);
676 if(brick)
677 pCSDst->setCanDrop (true);
680 // can be a phrase sheet
681 else if(pCSSrc->isSPhrase())
683 CSPhraseSheet *phrase= dynamic_cast<CSPhraseSheet*>(SheetMngr.get(NLMISC::CSheetId(pCSSrc->getSheetId())));
684 if(phrase && !phrase->Bricks.empty())
686 // Get the RootBrick of the Phrase
687 CSBrickSheet *brick= pBM->getBrick(phrase->Bricks[0]);
688 if(brick)
689 pCSDst->setCanDrop (true);
692 // check if incoming macro ok
693 else
695 // get the macro
696 const CMacroCmd *macroCmd= pMM->getMacroFromMacroID(pCSSrc->getMacroId());
697 if(macroCmd)
698 pCSDst->setCanDrop(true);
703 REGISTER_ACTION_HANDLER (CHandlerCanMemorizePhraseOrMacro, "can_memorize_phrase_or_macro");
707 class CHandlerPhraseMemoryCopy : public IActionHandler
709 public:
710 static bool haveLastPhraseElement;
711 static bool isMacro;
712 static sint32 sPhraseId;
713 static sint32 macroId;
715 virtual void execute(CCtrlBase *pCaller, const string &Params)
717 CDBCtrlSheet *ctrl= dynamic_cast<CDBCtrlSheet*>(pCaller);
718 if(ctrl && ctrl->isSPhraseIdMemory())
720 haveLastPhraseElement = true;
721 isMacro = ctrl->isMacro();
722 sPhraseId = ctrl->getSPhraseId();
723 macroId = ctrl->getMacroId();
725 string mode = getParam(Params, "mode"); //default mode is copy
726 if (mode == "cut") //need delete src
728 CAHManager::getInstance()->runActionHandler("forget_phrase_or_macro", ctrl);
733 REGISTER_ACTION_HANDLER( CHandlerPhraseMemoryCopy, "phrase_memory_copy");
734 bool CHandlerPhraseMemoryCopy::haveLastPhraseElement = false;
735 bool CHandlerPhraseMemoryCopy::isMacro = false;
736 sint32 CHandlerPhraseMemoryCopy::sPhraseId = 0;
737 sint32 CHandlerPhraseMemoryCopy::macroId = 0;
740 // **********************************************************************************************************
741 // debug update the action bar
742 extern void debugUpdateActionBar();
744 // **********************************************************************************************************
745 /** Memorize a combat Brick into a Memory slot.
746 * Called when the user drop a combat brick on a spell slot.
748 class CHandlerMemorizePhraseOrMacro : public IActionHandler
750 public:
751 virtual void execute (CCtrlBase *pCaller, const string &Params);
752 void memorizePhraseOrMacro(uint dstMemoryIndex, bool isMacro, sint32 phraseId, sint32 macroId);
753 void memorizePhraseSheet(uint dstMemoryIndex, uint32 sheetId);
755 REGISTER_ACTION_HANDLER( CHandlerMemorizePhraseOrMacro, "memorize_phrase_or_macro");
757 void CHandlerMemorizePhraseOrMacro::execute (CCtrlBase *pCaller, const string &Params)
759 CInterfaceManager *pIM = CInterfaceManager::getInstance();
760 CSPhraseManager *pPM = CSPhraseManager::getInstance();
762 string src = getParam(Params, "src");
763 CDBCtrlSheet *pCSSrc;
764 CDBCtrlSheet *pCSDst = dynamic_cast<CDBCtrlSheet*>(pCaller);
766 // NB: THIS IS UGLY BUT WORKS BECAUSE Memory ctrls are first initialized as SPhrase (branchname init)
768 // type check
769 if (pCSDst == NULL) return;
770 // The dest must be a memory or a macro memory
771 if (!pCSDst->isSPhraseIdMemory() && !pCSDst->isMacroMemory()) return;
772 // get the memory line and memory index
773 sint32 dstMemoryLine= pPM->getSelectedMemoryLineDB();
774 uint dstMemoryIndex= pCSDst->getIndexInDB();
776 bool srcIsMacro;
777 sint32 srcPhraseId;
778 sint32 srcMacroId;
780 bool dstIsMacro= pCSDst->isMacro();
781 sint32 dstPhraseId= pCSDst->getSPhraseId();
782 sint32 dstMacroId= pCSDst->getMacroId();
784 if (src.empty() && (CHandlerPhraseMemoryCopy::haveLastPhraseElement))
786 // get the slot ids from save
787 srcIsMacro= CHandlerPhraseMemoryCopy::isMacro;
788 srcPhraseId= CHandlerPhraseMemoryCopy::sPhraseId;
789 srcMacroId= CHandlerPhraseMemoryCopy::macroId;
791 // if a phrase
792 if(!srcIsMacro)
794 // \toto yoyo: There is a Network BUG which prevents us from simply doing {Forget(),Delete()} Old phrase,
795 // then {Learn(),Memorize()} new one (Messages are shuffled).
796 // Instead, replace the old phrase if needed
797 uint16 newPhraseId= (uint16)pPM->getMemorizedPhraseIfLastOrNewSlot(dstMemoryLine, dstMemoryIndex);
798 if(!newPhraseId)
799 return;
801 // set it, copy from srcPhraseId
802 pPM->setPhrase(newPhraseId, pPM->getPhrase(srcPhraseId));
804 // send learn to server
805 pPM->sendLearnToServer(newPhraseId);
807 // memorize the new phrase
808 memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, newPhraseId, srcMacroId);
811 else
813 CInterfaceElement *pElt = CWidgetManager::getInstance()->getElementFromId(src);
814 pCSSrc = dynamic_cast<CDBCtrlSheet*>(pElt);
816 // type check
817 if (pCSSrc == NULL) return;
818 // The src must be a phraseid, a phrasesheet, or a macro droped
819 if (!pCSSrc->isSPhraseId() && !pCSSrc->isSPhrase() && !pCSSrc->isMacro()) return;
821 // get the slot ids.
822 srcIsMacro= pCSSrc->isMacro();
823 srcPhraseId= pCSSrc->getSPhraseId();
824 srcMacroId= pCSSrc->getMacroId();
827 // If the src comes not from a memory
828 if(!pCSSrc->isSPhraseIdMemory() && !pCSSrc->isMacroMemory())
831 // if the src is a phrase sheet
832 if(pCSSrc->isSPhrase())
834 // learn and memorize this phrase
835 memorizePhraseSheet(dstMemoryIndex, pCSSrc->getSheetId());
837 else
839 // We may replace a phrase with a macro => must delete the phrase under us
840 if(srcIsMacro)
841 pPM->fullDeletePhraseIfLast(dstMemoryLine, dstMemoryIndex);
843 // memorize the phrase or macro
844 memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId);
847 // Else the src is a memory too
848 else
850 // if Drag copy => this is a copy!
851 if(pCSSrc->canDragCopy() && pIM->testDragCopyKey())
853 // if a phrase
854 if(!srcIsMacro)
856 // \toto yoyo: There is a Network BUG which prevents us from simply doing {Forget(),Delete()} Old phrase,
857 // then {Learn(),Memorize()} new one (Messages are shuffled).
858 // Instead, replace the old phrase if needed
859 uint16 newPhraseId= (uint16)pPM->getMemorizedPhraseIfLastOrNewSlot(dstMemoryLine, dstMemoryIndex);
860 if(!newPhraseId)
861 return;
863 // set it, copy from srcPhraseId
864 pPM->setPhrase(newPhraseId, pPM->getPhrase(srcPhraseId));
866 // send learn to server
867 pPM->sendLearnToServer(newPhraseId);
869 // memorize the new phrase
870 memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, newPhraseId, srcMacroId);
872 else
874 // We may replace a phrase with a macro => must delete the phrase under us
875 pPM->fullDeletePhraseIfLast(dstMemoryLine, dstMemoryIndex);
877 // memorize the macro (still a reference)
878 memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId);
881 // else this is a swap!
882 else
884 // if the dest exist, swap
885 if(dstPhraseId || dstIsMacro)
887 // get the memory index for src
888 uint srcMemoryIndex= pCSSrc->getIndexInDB();
890 // memorize dst into src
891 memorizePhraseOrMacro(srcMemoryIndex, dstIsMacro, dstPhraseId, dstMacroId);
892 // memorize src into dst
893 memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId);
895 // else, it's a move
896 else
898 // copy
899 memorizePhraseOrMacro(dstMemoryIndex, srcIsMacro, srcPhraseId, srcMacroId);
901 // forget src (after shorctut change!)
902 CAHManager::getInstance()->runActionHandler("forget_phrase_or_macro", pCSSrc);
910 // memorize a spell
911 void CHandlerMemorizePhraseOrMacro::memorizePhraseOrMacro(uint memoryIndex, bool isMacro, sint32 phraseId, sint32 macroId)
913 CSPhraseManager *pPM= CSPhraseManager::getInstance();
915 sint32 memoryLine= pPM->getSelectedMemoryLineDB();
916 if(memoryLine<0)
917 return;
919 if(isMacro)
921 pPM->memorizeMacro(memoryLine, memoryIndex, macroId);
923 else
925 // memorize in local
926 pPM->memorizePhrase(memoryLine, memoryIndex, phraseId);
927 // Send the Server msg
928 pPM->sendMemorizeToServer(memoryLine, memoryIndex, phraseId);
932 // memorize a default spell
933 void CHandlerMemorizePhraseOrMacro::memorizePhraseSheet(uint memoryIndex, uint32 sheetId)
935 CSPhraseManager *pPM= CSPhraseManager::getInstance();
937 sint32 memoryLine= pPM->getSelectedMemoryLineDB();
938 if(memoryLine<0)
939 return;
941 // this should have been checked in CanDrag
942 if(!pPM->isPhraseCastable(sheetId))
943 return;
944 // build the com phrase
945 CSPhraseCom phraseCom;
946 pPM->buildPhraseFromSheet(phraseCom, sheetId);
947 if(phraseCom.empty())
948 return;
951 // **** first learn this phrase
952 // \toto yoyo: There is a Network BUG which prevents us from simply doing {Forget(),Delete()} Old phrase,
953 // then {Learn(),Memorize()} new one (Messages are shuffled).
954 // Instead, replace the old phrase if needed
955 uint16 newPhraseId= (uint16)pPM->getMemorizedPhraseIfLastOrNewSlot(memoryLine, memoryIndex);
956 if(!newPhraseId)
957 return;
959 // set it
960 pPM->setPhrase(newPhraseId, phraseCom);
962 // send learn to server
963 pPM->sendLearnToServer(newPhraseId);
966 // **** memorize
967 // memorize in local
968 pPM->memorizePhrase(memoryLine, memoryIndex, newPhraseId);
969 // Send the Server msg
970 pPM->sendMemorizeToServer(memoryLine, memoryIndex, newPhraseId);
974 // **********************************************************************************************************
975 /** Forget a Phrase from a Memory slot
976 * Called when the user choose to free a spell memory slot
978 class CHandlerForgetPhraseOrMacro : public IActionHandler
980 public:
981 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
983 CSPhraseManager *pPM = CSPhraseManager::getInstance();
985 CDBCtrlSheet *pCSDst = dynamic_cast<CDBCtrlSheet*>(pCaller);
986 if (pCSDst == NULL) return;
987 if (!pCSDst->isSPhraseIdMemory() && !pCSDst->isMacroMemory())
988 return;
990 // Ok, the user try to forget a phrase slot.
991 sint32 memoryLine= pPM->getSelectedMemoryLineDB();
992 if(memoryLine<0)
993 return;
995 // get the memory index
996 uint memoryIndex= pCSDst->getIndexInDB();
998 if(pCSDst->isMacro())
1000 pPM->forgetMacro(memoryLine, memoryIndex);
1002 else
1004 // forget in local.
1005 pPM->forgetPhrase(memoryLine, memoryIndex);
1006 // Server com.
1007 pPM->sendForgetToServer(memoryLine, memoryIndex);
1011 REGISTER_ACTION_HANDLER( CHandlerForgetPhraseOrMacro, "forget_phrase_or_macro");
1014 // **********************************************************************************************************
1015 /** Forget a Phrase from a Memory slot
1016 * Called when the user choose to free a spell memory slot
1018 class CHandlerDeletePhraseOrForgetMacro : public IActionHandler
1020 public:
1021 virtual void execute (CCtrlBase *pCaller, const string & Params)
1023 CDBCtrlSheet *pCSDst = dynamic_cast<CDBCtrlSheet*>(pCaller);
1024 if (pCSDst == NULL) return;
1025 if (!pCSDst->isSPhraseIdMemory() && !pCSDst->isMacroMemory())
1026 return;
1028 // get the memory index
1029 uint memoryIndex = pCSDst->getIndexInDB();
1031 bool isMacro = pCSDst->isMacro();
1032 sint32 phraseId = pCSDst->getSPhraseId();
1034 // build params string
1035 string sParams;
1036 sParams.append("memoryIndex=");
1037 sParams.append(toString(memoryIndex));
1038 sParams.append("|isMacro=");
1039 sParams.append(toString(isMacro));
1040 sParams.append("|phraseId=");
1041 sParams.append(toString(phraseId));
1042 if (!Params.empty())
1044 sParams.append("|");
1045 sParams.append(Params);
1048 // Ask if ok before
1049 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1050 pIM->validMessageBox(CInterfaceManager::QuestionIconMsg, CI18N::get("uiQDeleteAction"), "do_delete_phrase_or_forget_macro", sParams);
1053 REGISTER_ACTION_HANDLER( CHandlerDeletePhraseOrForgetMacro, "delete_phrase_or_forget_macro");
1056 // **********************************************************************************************************
1057 /** Forget a Phrase from a Memory slot
1058 * Called when the user confirmed that he want to free a spell memory slot
1060 class CHandlerDoDeletePhraseOrForgetMacro : public IActionHandler
1062 public:
1063 virtual void execute (CCtrlBase *pCaller, const string &Params)
1065 // Ok, the user try to forget a phrase slot
1066 CSPhraseManager *pPM = CSPhraseManager::getInstance();
1068 sint32 memoryLine = pPM->getSelectedMemoryLineDB();
1069 if (memoryLine<0)
1070 return;
1072 // get params
1073 uint memoryIndex;
1074 fromString(getParam(Params, "memoryIndex"), memoryIndex);
1075 bool isMacro;
1076 fromString(getParam(Params, "isMacro"),isMacro);
1077 sint32 phraseId;
1078 fromString(getParam(Params, "phraseId"),phraseId);
1080 if (isMacro)
1082 pPM->forgetMacro(memoryLine, memoryIndex);
1084 else
1086 // do all the thing to delete properly this phrase
1087 pPM->fullDelete(phraseId);
1091 REGISTER_ACTION_HANDLER( CHandlerDoDeletePhraseOrForgetMacro, "do_delete_phrase_or_forget_macro");
1094 // **********************************************************************************************************
1095 /** Cast a spell from a memory slot (combat or magic)
1096 * Called when the user click on a memory slot. Can be called also from CAHRunShortcut, or from
1097 * MoveToAction system (in CSPhraseManager)
1099 class CHandlerCastPhrase : public IActionHandler
1101 public:
1102 static sint64 LastHitTime;
1103 static sint LastIndex;
1105 public:
1106 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
1108 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1109 CSPhraseManager *pPM = CSPhraseManager::getInstance();
1110 CSBrickManager *pBM= CSBrickManager::getInstance();
1112 CDBCtrlSheet *pCSDst = dynamic_cast<CDBCtrlSheet*>(pCaller);
1113 if (pCSDst == NULL) return;
1114 if (!pCSDst->isSPhraseIdMemory())
1115 return;
1117 // Can cast only if not Latent (ie grayed) !!
1118 if (pCSDst->getGrayed())
1119 return;
1121 // Ok, the user try to cast a phrase slot.
1122 sint32 memoryLine;
1123 if (pCSDst->isShortCut())
1124 memoryLine = pPM->getSelectedMemoryLineDB();
1125 else
1126 memoryLine = pPM->getSelectedMemoryAltLineDB();
1127 if(memoryLine<0)
1128 return;
1130 // get the memory index
1131 uint memoryIndex= pCSDst->getIndexInDB();
1133 // Check If the phrase exist
1134 sint phraseId= pCSDst->getSPhraseId();
1135 if(!phraseId)
1136 return;
1137 const CSPhraseCom &phraseCom= pPM->getPhrase(phraseId);
1138 if(phraseCom.empty())
1139 return;
1140 CSBrickSheet *rootBrick= pBM->getBrick(phraseCom.Bricks[0]);
1141 if(!rootBrick)
1142 return;
1144 // **** Check If the phrase is a Craft Phrase.
1145 if( rootBrick->isFaber() )
1147 extern void launchFaberCastWindow(sint32 , uint , CSBrickSheet *);
1148 launchFaberCastWindow(memoryLine, memoryIndex, rootBrick);
1150 // Cancel any moveTo, because don't want to continue reaching the prec entity
1151 UserEntity->resetAnyMoveTo();
1153 // **** Else standart cast
1154 else
1156 // **** Cyclic Cast? (dblclick)
1157 bool cyclic;
1158 // Manage "DblHit"
1159 uint dbclickDelay = CWidgetManager::getInstance()->getUserDblClickDelay();
1160 // if success to "dblclick"
1161 if(LastIndex==(sint)memoryIndex && T1<=LastHitTime+dbclickDelay )
1162 cyclic= true;
1163 else
1164 cyclic= false;
1165 // for next hit
1166 LastHitTime= T1;
1167 LastIndex= memoryIndex;
1169 // can't cast magic phrase while moving
1170 if( rootBrick->isMagic() )
1172 if( UserControls.isMoving() || (UserEntity && UserEntity->follow() && UserEntity->speed()!=0.0) )
1174 // display "you can't cast while moving"
1175 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1176 string msg = CI18N::get("msgNoCastWhileMoving");
1177 string cat = getStringCategory(msg, msg);
1178 pIM->displaySystemInfo(msg, cat);
1179 return;
1183 // Can't cyclic cast Magic, SpecialPower or Harvest phrases (forage_extraction are auto)
1184 if( rootBrick->isMagic() || rootBrick->isHarvest() || rootBrick->isSpecialPower() )
1185 cyclic= false;
1187 // auto cyclic for forage extraction
1188 if( rootBrick->isForageExtraction() )
1189 cyclic= true;
1191 // even for extraction, if AvoidCyclic in any bricks, no cyclic!
1192 if( pPM->avoidCyclicForPhrase(phraseCom) )
1193 cyclic= false;
1195 if (UserEntity)
1197 // **** Launch the cast
1198 // Cast only if their is a target, or if it is not a combat action
1199 CEntityCL *target = EntitiesMngr.entity(UserEntity->targetSlot());
1200 if (target || !rootBrick->isCombat())
1202 // combat (may moveTo before) ?
1203 if (rootBrick->isCombat())
1205 if (!UserEntity->canEngageCombat())
1206 return;
1208 UserEntity->executeCombatWithPhrase(target, memoryLine, memoryIndex, cyclic);
1210 // else can cast soon!
1211 else if (rootBrick->isForageExtraction() && (!UserEntity->isRiding())) // if mounted, send directly to server (without moving) to receive the error message
1213 // Yoyo: TEMP if a target selected, must be a forage source
1214 if (!target || target->isForageSource())
1216 // Cancel any follow
1217 UserEntity->disableFollow();
1218 // reset any moveTo also (if target==NULL, moveToExtractionPhrase() and therefore resetAnyMoveTo() not called)
1219 // VERY important if previous MoveTo was a SPhrase MoveTo (because cancelClientExecute() must be called)
1220 UserEntity->resetAnyMoveTo();
1222 // Move to targetted source
1223 if (target)
1224 UserEntity->moveToExtractionPhrase(target->slot(), MaxExtractionDistance, memoryLine, memoryIndex, cyclic);
1226 // start client execution
1227 pPM->clientExecute(memoryLine, memoryIndex, cyclic);
1229 if (!target)
1231 // inform Server of phrase cast
1232 pPM->sendExecuteToServer(memoryLine, memoryIndex, cyclic);
1236 else
1238 // Cancel any moveTo(), because don't want to continue reaching the prec entity
1239 // VERY important if previous MoveTo was a SPhrase MoveTo (because cancelClientExecute() must be called)
1240 UserEntity->resetAnyMoveTo();
1242 // start client execution: NB: start client execution even if it
1243 pPM->clientExecute(memoryLine, memoryIndex, cyclic);
1245 // inform Server of phrase cast
1246 pPM->sendExecuteToServer(memoryLine, memoryIndex, cyclic);
1253 REGISTER_ACTION_HANDLER( CHandlerCastPhrase, "cast_phrase");
1254 sint64 CHandlerCastPhrase::LastHitTime= 0;
1255 sint CHandlerCastPhrase::LastIndex= -1;
1258 // ***************************************************************************
1259 /** Called when user hit the 1.2.3.4.5..... key
1261 class CAHRunShortcut : public IActionHandler
1263 public:
1264 virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
1266 sint shortcut;
1267 fromString(Params, shortcut);
1268 if (shortcut>=0 && shortcut <= 2*RYZOM_MAX_SHORTCUT)
1270 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1272 // get the control
1273 CInterfaceElement *elm;
1274 if (shortcut < RYZOM_MAX_SHORTCUT)
1275 elm = CWidgetManager::getInstance()->getElementFromId(PhraseMemoryCtrlBase + toString(shortcut) );
1276 else
1277 elm = CWidgetManager::getInstance()->getElementFromId(PhraseMemoryAltCtrlBase + toString(shortcut-RYZOM_MAX_SHORTCUT) );
1278 CDBCtrlSheet *ctrl= dynamic_cast<CDBCtrlSheet*>(elm);
1279 if(ctrl)
1281 // run the standard cast case.
1282 if(ctrl->isMacro())
1283 CAHManager::getInstance()->runActionHandler("cast_macro", ctrl);
1284 else
1285 CAHManager::getInstance()->runActionHandler("cast_phrase", ctrl);
1290 REGISTER_ACTION_HANDLER (CAHRunShortcut, "run_shortcut");
1293 // ***************************************************************************
1294 /** Called when the user click on a memory slot. Different AH called if the slot is empty or full
1296 class CHandlerCastPhraseOrCreateNew : public IActionHandler
1298 public:
1299 virtual void execute (CCtrlBase *pCaller, const string &Params)
1301 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1303 CDBCtrlSheet *pCSDst = dynamic_cast<CDBCtrlSheet*>(pCaller);
1304 if (pCSDst == NULL) return;
1305 if (!pCSDst->isSPhraseIdMemory())
1306 return;
1308 // get the phrase id under it
1309 sint phraseId= pCSDst->getSPhraseId();
1310 // if a phrase is on this slot, just cast the phrase
1311 if(phraseId)
1313 CAHManager::getInstance()->runActionHandler("cast_phrase", pCaller, Params);
1315 // else open the RightMenuEmpty, to have "NewAction"
1316 else
1318 string menu= pCSDst->getListMenuRightEmptySlot();
1319 // opens only if no dragged sheet
1320 if( !menu.empty() && CDBCtrlSheet::getDraggedSheet()==NULL )
1322 // opens the menu
1323 CDBCtrlSheet::setCurrSelSheet(pCSDst);
1324 CWidgetManager::getInstance()->enableModalWindow (pCSDst, menu);
1329 REGISTER_ACTION_HANDLER (CHandlerCastPhraseOrCreateNew, "cast_phrase_or_create_new");
1332 // ***************************************************************************
1333 /** Called to get info on Phrase Link
1335 class CHandlerPhraseLinkCtrlRClick : public IActionHandler
1337 public:
1338 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
1340 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1342 CInterfaceGroup *parent= pCaller->getParent();
1343 if(parent)
1345 // Get the Brother CtrlSheet
1346 CDBCtrlSheet *ctrl= dynamic_cast<CDBCtrlSheet*>(parent->getCtrl("ctrl_phrase"));
1347 if(ctrl)
1349 CAHManager::getInstance()->runActionHandler(ctrl->getActionOnRightClick(), ctrl, ctrl->getParamsOnRightClick());
1355 REGISTER_ACTION_HANDLER (CHandlerPhraseLinkCtrlRClick, "phrase_link_ctrl_rclick");
1358 // ***************************************************************************
1359 /** Called to cancel a Phrase link
1361 class CHandlerPhraseLinkStop : public IActionHandler
1363 public:
1364 virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
1366 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1368 // get the link index
1369 uint8 index;
1370 fromString(Params, index);
1371 // Get the link counter. Used to verify that the client cancel the correct link according to server
1372 uint8 counter= 0;
1373 CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:EXECUTE_PHRASE:LINK:%d:COUNTER", index), false);
1374 if(node)
1375 counter= node->getValue8();
1377 // Send msg to server
1378 if (!ClientCfg.Local)
1380 NLMISC::CBitMemStream out;
1381 if(GenericMsgHeaderMngr.pushNameToStream("PHRASE:CANCEL_LINK", out))
1383 out.serial(index);
1384 out.serial(counter);
1385 NetMngr.push(out);
1387 else
1389 nlwarning(" unknown message name '%s'", "PHRASE:CANCEL_LINK");
1392 else
1394 // debug:
1395 pIM->displaySystemInfo( toString("PHRASE:CANCEL_LINK %d, %d", index, counter) );
1399 REGISTER_ACTION_HANDLER(CHandlerPhraseLinkStop, "phrase_link_stop");
1402 // ***************************************************************************
1403 /** Called to cancel a Phrase link
1405 class CHandlerPhraseCancelCast: public IActionHandler
1407 public:
1408 virtual void execute(CCtrlBase * /* pCaller */, const string &/* Params */)
1410 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1412 // Send msg to server
1413 if (!ClientCfg.Local)
1415 UserEntity->cancelAllPhrases();
1417 else
1419 // debug:
1420 pIM->displaySystemInfo("PHRASE:CANCEL_ALL");
1424 REGISTER_ACTION_HANDLER(CHandlerPhraseCancelCast, "phrase_cancel_cast");
1427 // ***************************************************************************
1428 /// Called when one of the BRICK_TICK_RANGE has changed
1429 class CHandlerPhraseUpdateAllMemoryRegenTickRange : public IActionHandler
1431 public:
1432 virtual void execute(CCtrlBase *, const string &)
1434 CSPhraseManager *pPM= CSPhraseManager::getInstance();
1435 pPM->updateAllMemoryCtrlState();
1436 pPM->touchRegenTickRangeFlag();
1439 REGISTER_ACTION_HANDLER(CHandlerPhraseUpdateAllMemoryRegenTickRange, "phrase_update_all_memory_ctrl_regen_tick_range");
1442 // ***************************************************************************
1443 /// Called when we right click on a brick in the memories
1444 class CHandlerPhraseCheckCanCristalize: public IActionHandler
1446 public:
1447 virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
1449 const string sCristalizePath = "ui:interface:cm_memory_phrase:cri";
1450 CInterfaceManager *pIM = CInterfaceManager::getInstance();
1451 CSPhraseManager *pPM = CSPhraseManager::getInstance();
1452 CSBrickManager *pBM = CSBrickManager::getInstance();
1453 CInterfaceElement *pCristalizeMenuOption = CWidgetManager::getInstance()->getElementFromId(sCristalizePath);
1455 if (pCristalizeMenuOption == NULL) return;
1456 // The default is to not display the cristalize menu option
1457 pCristalizeMenuOption->setActive(false);
1458 if (pCaller == NULL) return;
1460 // Get the interface control sheet
1462 CDBCtrlSheet *pCS = dynamic_cast<CDBCtrlSheet*>(CWidgetManager::getInstance()->getCtrlLaunchingModal());
1463 if (pCS == NULL) return;
1464 if (!pCS->isSPhraseIdMemory()) return;
1466 // If its a phrase id in memory then get the phrase
1468 const CSPhraseCom &phrase = pPM->getPhrase(pCS->getSheetId());
1469 if (phrase.empty()) return;
1471 // If the phrase is not empty get the root to known if its a magic phrase or not
1472 // And if its a magic phrase display the cristalize menu option
1474 CSBrickSheet *pBrick = pBM->getBrick(phrase.Bricks[0]);
1475 if (pBrick != NULL)
1477 if (pBrick->isMagic())
1479 pCristalizeMenuOption->setActive(true);
1481 // Disable the cristalize item if the player has a forage in progress
1482 CViewTextMenu* vtm = dynamic_cast<CViewTextMenu*>(pCristalizeMenuOption);
1483 if ( vtm )
1485 CTempInvManager *tim = CTempInvManager::getInstance();
1486 bool isForageInProgress = tim && tim->isOpened() && (tim->getMode() == TEMP_INV_MODE::Forage);
1487 vtm->setGrayed( isForageInProgress );
1493 REGISTER_ACTION_HANDLER(CHandlerPhraseCheckCanCristalize, "phrase_check_can_cristalize");
1495 // ***************************************************************************
1496 /// Called after the cm_memory_phrase menu has been opened on a magic phrase
1497 class CHandlerPhraseCristalize: public IActionHandler
1499 public:
1500 virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
1502 CSPhraseManager *pPM = CSPhraseManager::getInstance();
1504 CDBCtrlSheet *pCSDst = dynamic_cast<CDBCtrlSheet*>(pCaller);
1505 if (pCSDst == NULL) return;
1506 if (!pCSDst->isSPhraseIdMemory())
1507 return;
1509 // Can cast only if not Latent (ie grayed) !!
1510 if (pCSDst->getGrayed())
1511 return;
1513 // Ok, the user try to cast a phrase slot.
1514 sint32 memoryLine;
1515 if (pCSDst->isShortCut())
1516 memoryLine = pPM->getSelectedMemoryLineDB();
1517 else
1518 memoryLine = 0;
1519 if(memoryLine<0)
1520 return;
1522 // get the memory index
1523 uint memoryIndex= pCSDst->getIndexInDB();
1525 // execute both client and server
1526 pPM->executeCristalize(memoryLine, memoryIndex);
1529 REGISTER_ACTION_HANDLER(CHandlerPhraseCristalize, "phrase_cristalize");
1531 // ***************************************************************************
1532 class CHandlerPhraseBookSkillFilter : public IActionHandler
1534 public:
1535 virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
1537 CSPhraseManager *pPM= CSPhraseManager::getInstance();
1539 // If the param is a BrickType Filter...
1540 string btFilter= getParam(Params, "bt");
1541 if(!btFilter.empty())
1543 BRICK_TYPE::EBrickType bt= BRICK_TYPE::toBrickType(btFilter);
1544 if(bt!=BRICK_TYPE::UNKNOWN)
1545 pPM->setBookFilter(bt, SKILLS::unknown);
1547 // else it is a skill filter
1548 else
1550 sint index;
1551 fromString(Params, index);
1552 if(index>=0 && index<SKILLS::NUM_SKILLS)
1553 pPM->setBookFilter(BRICK_TYPE::UNKNOWN, (SKILLS::ESkills)index);
1554 else
1555 pPM->setBookFilter(BRICK_TYPE::UNKNOWN, SKILLS::unknown);
1559 REGISTER_ACTION_HANDLER(CHandlerPhraseBookSkillFilter, "phrase_book_skill_filter");
1561 // ***************************************************************************
1562 class CHandlerPhraseSelectMemory : public IActionHandler
1564 public:
1565 virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
1567 string expr = getParam (Params, "value");
1568 CInterfaceExprValue value;
1569 if (CInterfaceExpr::eval(expr, value, NULL))
1571 if (!value.toInteger())
1573 nlwarning("<CHandlerPhraseSelectMemory:execute> expression doesn't evaluate to a numerical value");
1575 else
1577 CSPhraseManager *pPM= CSPhraseManager::getInstance();
1578 sint val= (sint32)value.getInteger();
1579 clamp(val, 0, MEM_SET_TYPES::NumMemories-1);
1580 pPM->selectMemoryLineDB(val);
1585 REGISTER_ACTION_HANDLER(CHandlerPhraseSelectMemory, "phrase_select_memory");
1587 class CHandlerPhraseSelectMemory2 : public IActionHandler
1589 public:
1590 virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
1592 string expr = getParam (Params, "value");
1593 CInterfaceExprValue value;
1594 if (CInterfaceExpr::eval(expr, value, NULL))
1596 if (!value.toInteger())
1598 nlwarning("<CHandlerPhraseSelectMemory:execute> expression doesn't evaluate to a numerical value");
1600 else
1602 CSPhraseManager *pPM= CSPhraseManager::getInstance();
1603 sint val= (sint32)value.getInteger();
1604 clamp(val, 0, MEM_SET_TYPES::NumMemories-1);
1605 pPM->selectMemoryLineDBalt(val);
1610 REGISTER_ACTION_HANDLER(CHandlerPhraseSelectMemory2, "phrase_select_memory_2");
1612 // ***************************************************************************
1613 class CHandlerPhraseSelectShortcutBar : public IActionHandler
1615 public:
1616 virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
1618 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1619 CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("UI:PHRASE:SELECT_MEMORY", false);
1620 if(node)
1622 sint32 val;
1623 fromString(Params, val);
1624 node->setValue32(val);
1628 REGISTER_ACTION_HANDLER(CHandlerPhraseSelectShortcutBar, "select_shortcut_bar");
1630 // ***************************************************************************
1631 class CHandlerPhraseSelectShortcutBar2 : public IActionHandler
1633 public:
1634 virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
1636 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1637 CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("UI:PHRASE:SELECT_MEMORY_2", false);
1638 if(node)
1640 sint32 val;
1641 fromString(Params, val);
1642 node->setValue32(val);
1646 REGISTER_ACTION_HANDLER(CHandlerPhraseSelectShortcutBar2, "select_shortcut_bar_2");
1648 // ***************************************************************************
1649 // ***************************************************************************
1650 // ***************************************************************************
1651 // HELP / LINKS
1652 // ***************************************************************************
1653 // ***************************************************************************
1654 // ***************************************************************************
1657 // ***************************************************************************
1658 // This expr is used only for define in phrase.xml.
1659 DECLARE_INTERFACE_CONSTANT(getPhraseBrickSelectionMax, CDBGroupBuildPhrase::MaxSelection)
1662 // ***************************************************************************
1663 // Get the UC name of a phraseId
1664 static DECLARE_INTERFACE_USER_FCT(getSPhraseName)
1666 if (!args.empty())
1668 if(!args[0].toInteger())
1669 return false;
1670 sint sphraseId= (sint)args[0].getInteger();
1671 CSPhraseManager *pPM= CSPhraseManager::getInstance();
1672 result.setString(pPM->getPhrase(sphraseId).Name.toUtf8());
1673 return true;
1675 else
1677 return false;
1680 REGISTER_INTERFACE_USER_FCT("getSPhraseName", getSPhraseName)
1683 // ***************************************************************************
1684 // Get the tooltip of a Combat Weapon restriction brick
1685 class CHandlerCombatRestrictTooltip : public IActionHandler
1687 public:
1688 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
1690 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1691 CDBCtrlSheet *ctrlSheet= dynamic_cast<CDBCtrlSheet*>(pCaller);
1692 if(!ctrlSheet)
1693 return;
1695 string str(STRING_MANAGER::CStringManagerClient::getSBrickLocalizedName(CSheetId(ctrlSheet->getSheetId())));
1697 // According to locked state
1698 if(ctrlSheet->getGrayed())
1699 strFindReplace(str, "%comp", CI18N::get("uittPhraseCombatRestrictKO"));
1700 else
1701 strFindReplace(str, "%comp", CI18N::get("uittPhraseCombatRestrictOK"));
1703 CWidgetManager::getInstance()->setContextHelpText(str);
1706 REGISTER_ACTION_HANDLER( CHandlerCombatRestrictTooltip, "phrase_combat_restrict_tooltip");
1709 // ***************************************************************************
1710 // ***************************************************************************
1711 // ***************************************************************************
1712 // BOT CHAT
1713 // ***************************************************************************
1714 // ***************************************************************************
1715 // ***************************************************************************
1718 // ***************************************************************************
1719 void phraseBotChatBuyBySheet(NLMISC::CSheetId sheetId, uint16 phraseId)
1721 uint32 sheetNum= sheetId.asInt();
1722 if (!ClientCfg.Local)
1724 NLMISC::CBitMemStream out;
1725 if(GenericMsgHeaderMngr.pushNameToStream("PHRASE:BUY_SHEET", out))
1727 out.serial(sheetNum);
1728 out.serial(phraseId);
1729 NetMngr.push(out);
1731 else
1733 nlwarning(" unknown message name '%s'", "PHRASE:BUY_SHEET");
1736 else
1738 // debug:
1739 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1740 pIM->displaySystemInfo( toString("PHRASE:BUY_SHEET => ") + toString(phraseId) );
1742 // **** Server emulation
1743 // learn all bricks of this phrase
1744 CSPhraseSheet *phrase= dynamic_cast<CSPhraseSheet*>(SheetMngr.get(sheetId));
1745 if(phrase)
1747 CSBrickManager *pBM= CSBrickManager::getInstance();
1748 // For all bricks of this phrase
1749 for(uint i=0;i<phrase->Bricks.size();i++)
1751 CSBrickSheet *brick= pBM->getBrick(phrase->Bricks[i]);
1752 if(brick)
1754 // force learn it.
1755 CCDBNodeLeaf * node= pBM->getKnownBrickBitFieldDB(brick->BrickFamily);
1756 if(node)
1758 uint64 flags= node->getValue64();
1759 flags|= uint64(1)<<(brick->IndexInFamily-1);
1760 node->setValue64(flags);
1765 // ack phrase learn
1766 CSPhraseManager *pPM= CSPhraseManager::getInstance();
1767 if(phraseId)
1768 pPM->receiveBotChatConfirmBuy(phraseId, true);
1769 // synchronize
1770 uint counter= pIM->getLocalSyncActionCounter();
1771 NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:COUNTER")->setValue32(counter);
1772 NLGUI::CDBManager::getInstance()->getDbProp("SERVER:EXCHANGE:COUNTER")->setValue32(counter);
1773 NLGUI::CDBManager::getInstance()->getDbProp("SERVER:TARGET:CONTEXT_MENU:COUNTER")->setValue32(counter);
1774 NLGUI::CDBManager::getInstance()->getDbProp("SERVER:USER:COUNTER")->setValue32(counter);
1778 // ***************************************************************************
1779 void phraseBotChatBuyActionByIndex(uint8 index, uint16 phraseId)
1781 if (!ClientCfg.Local)
1783 // send the selection to the server
1784 NLMISC::CBitMemStream out;
1785 if(GenericMsgHeaderMngr.pushNameToStream("PHRASE:BUY", out))
1787 out.serial(index);
1788 out.serial(phraseId);
1789 NetMngr.push(out);
1791 else
1792 nlwarning(" unknown message name 'PHRASE:BUY");
1794 else
1796 // debug:
1797 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1798 pIM->displaySystemInfo("PHRASE:BUY => " + toString(phraseId) );
1802 // ***************************************************************************
1803 /* Called from CConfirmBuyItem action handler
1805 void phraseBuyBotChat(CDBCtrlSheet *ctrl, uint8 index, bool useBuySheetMsg)
1807 CSBrickManager *pBM= CSBrickManager::getInstance();
1808 CSPhraseManager *pSM= CSPhraseManager::getInstance();
1810 if(!ctrl->isSPhrase())
1811 return;
1812 // Get the SPhrase
1813 const CSPhraseSheet *sp= ctrl->asSPhraseSheet();
1814 if(!sp || sp->Bricks.empty())
1815 return;
1817 // Verify that the phrase is not a special "CHARACTERISTIC BUYING" phrase
1818 bool isCharacBuying= false;
1819 CSBrickSheet *brickSheet= pBM->getBrick(CSheetId(sp->Bricks[0]));
1820 if(brickSheet && BRICK_FAMILIES::isCharacBuyFamily(brickSheet->BrickFamily) )
1821 isCharacBuying= true;
1823 // confirm the buy
1825 // default: not append to the manager
1826 uint16 phraseId= 0;
1828 // Append the phrase to the manager. ONLY if this phrase is castable
1829 if(sp->Castable && !isCharacBuying)
1831 CSPhraseCom phraseCom;
1832 pSM->buildPhraseFromSheet(phraseCom, ctrl->getSheetId());
1833 if(phraseCom.empty())
1834 return;
1836 // get the new phraseId
1837 phraseId= (uint16)pSM->allocatePhraseSlot();
1839 // Since we are not sure this slot work, lock it!
1840 pSM->setPhrase(phraseId, phraseCom, true);
1843 // Special for LOCAL:USER:SKILL_POINTS_ update
1844 CInterfaceManager *pIM= CInterfaceManager::getInstance();
1845 pIM->incLocalSyncActionCounter();
1847 // Send msg to server
1848 if(useBuySheetMsg)
1849 phraseBotChatBuyBySheet(sp->Id, phraseId);
1850 else
1851 phraseBotChatBuyActionByIndex(index, phraseId);
1855 // ***************************************************************************
1856 // Command for Debug BotChat ACK.
1857 NLMISC_COMMAND(phraseComfirmBuy, "Debug: confirm a phrase BotChat buy", "")
1859 if(args.size() != 2) return false;
1861 uint phraseId;
1862 fromString(args[0], phraseId);
1864 bool confirm;
1865 fromString(args[1], confirm);
1867 CSPhraseManager *pSM= CSPhraseManager::getInstance();
1868 pSM->receiveBotChatConfirmBuy(phraseId, confirm);
1870 return true;
1874 // ***************************************************************************
1875 // ***************************************************************************
1876 // ***************************************************************************
1877 // MACRO
1878 // ***************************************************************************
1879 // ***************************************************************************
1880 // ***************************************************************************
1882 // ***************************************************************************
1883 class CHandlerCastMacro : public IActionHandler
1885 public:
1886 virtual void execute (CCtrlBase *pCaller, const string &/* Params */)
1888 CMacroCmdManager *pMM = CMacroCmdManager::getInstance();
1890 CDBCtrlSheet *pCSDst = dynamic_cast<CDBCtrlSheet*>(pCaller);
1891 if (pCSDst == NULL) return;
1892 if (!pCSDst->isMacroMemory())
1893 return;
1895 // Can cast only if not grayed
1896 if (pCSDst->getGrayed())
1897 return;
1899 // execute the macro id
1900 pMM->executeID(pCSDst->getMacroId());
1903 REGISTER_ACTION_HANDLER( CHandlerCastMacro, "cast_macro");
1906 // ***************************************************************************
1907 // ***************************************************************************
1908 // ***************************************************************************
1909 // MISC
1910 // ***************************************************************************
1911 // ***************************************************************************
1912 // ***************************************************************************
1914 // ***************************************************************************
1915 class CHandlerPhraseMemoryBeforeMenu : public IActionHandler
1917 public:
1918 static uint32 LastPhraseIdMenu;
1920 virtual void execute(CCtrlBase *pCaller, const string &/* Params */)
1922 CDBCtrlSheet *ctrl= dynamic_cast<CDBCtrlSheet*>(pCaller);
1923 if(ctrl && ctrl->isSPhraseIdMemory())
1925 LastPhraseIdMenu= ctrl->getSPhraseId();
1929 REGISTER_ACTION_HANDLER( CHandlerPhraseMemoryBeforeMenu, "phrase_memory_before_menu");
1930 uint32 CHandlerPhraseMemoryBeforeMenu::LastPhraseIdMenu= 0;
1933 // ***************************************************************************
1934 static DECLARE_INTERFACE_USER_FCT(isPhraseMenuNotExecuting)
1936 bool ok= true;
1938 // if the PhraseId for this menu is equal to either cyclic action, or next action, fails
1939 CSPhraseManager *pPM= CSPhraseManager::getInstance();
1940 if(CHandlerPhraseMemoryBeforeMenu::LastPhraseIdMenu!=0)
1942 if(pPM->getCycleExecutePhraseId()==CHandlerPhraseMemoryBeforeMenu::LastPhraseIdMenu)
1943 ok= false;
1944 if(pPM->getNextExecutePhraseId()==CHandlerPhraseMemoryBeforeMenu::LastPhraseIdMenu)
1945 ok= false;
1948 result.setBool(ok);
1949 return true;
1951 REGISTER_INTERFACE_USER_FCT("isPhraseMenuNotExecuting", isPhraseMenuNotExecuting)