1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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>
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/>.
27 #include "nel/gui/action_handler.h"
28 #include "../motion/user_controls.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
;
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
93 virtual void execute(CCtrlBase
*pCaller
, const string
&/* Params */)
95 CDBCtrlSheet
*pCSDst
= dynamic_cast<CDBCtrlSheet
*>(pCaller
);
96 if (pCSDst
== NULL
|| !pCSDst
->isSPhraseId())
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
121 virtual void execute(CCtrlBase
*pCaller
, const string
&/* Params */)
123 // Get A free slot to edit (not allocated).
124 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
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();
140 pPM
->CompositionPhraseMemoryLineDest
= 0;
142 pPM
->CompositionPhraseMemorySlotDest
= pCSDst
->getIndexInDB();
144 // else no auto memorize
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
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();
171 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
173 CDBGroupBuildPhrase
*buildGroup
= dynamic_cast<CDBGroupBuildPhrase
*>(parent
->getParent());
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();
185 if(!pPM
->CompositionPhraseId
)
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.
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
;
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
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
242 virtual void execute(CCtrlBase
*pCaller
, const string
&/* Params */)
244 // Test if the OK control is valid.
245 CGroupContainer
*pGC
= dynamic_cast<CGroupContainer
*>(pCaller
);
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
) );
273 CDBGroupBuildPhrase
*buildSentenceTarget
= dynamic_cast<CDBGroupBuildPhrase
*>( CWidgetManager::getInstance()->getElementFromId(PhraseCompositionGroup
) );
275 if(buildSentenceTarget
)
278 window
->setActive(true);
280 // Set the Text of the Window
282 window
->setTitle(CI18N::get("uiPhraseCreate"));
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)
301 // all root are possible => no filter
302 buildSentenceTarget
->setRootBrickTypeFilter(BRICK_TYPE::UNKNOWN
);
309 buildSentenceTarget
->setRootBrickTypeFilter(BRICK_TYPE::UNKNOWN
);
313 CSBrickManager
*pBM
= CSBrickManager::getInstance();
314 const CSBrickSheet
*rootBrick
= pBM
->getBrick(phrase
.Bricks
[0]);
315 // can select only bricks of the same type
317 buildSentenceTarget
->setRootBrickTypeFilter(BRICK_FAMILIES::brickType(rootBrick
->BrickFamily
));
318 // maybe data error: filter nothing
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
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())
351 // get the selected brick
352 const CSBrickSheet
*brick
= pCSSrc
->asSBrickSheet();
356 // and validate the composition
357 // Standard Case: selection for action composition
358 if(BrickType
!= FaberPlan
)
360 nlassert(BuildPhraseGroup
);
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;
370 // Special Case: selection for faber plan
373 extern void validateFaberPlanSelection(CSBrickSheet
*itemPlanBrick
);
374 validateFaberPlanSelection(const_cast<CSBrickSheet
*>(brick
));
377 // And hide the modal
378 CWidgetManager::getInstance()->disableModalWindow();
381 enum TType
{Root
, OtherMain
, Param
, NewOpCredit
, FaberPlan
};
382 static TType BrickType
;
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
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
404 fromString(getParam(Params
, "index"), index
);
405 CHandlerPhraseValidateBrick::Index
= index
;
407 CHandlerPhraseValidateBrick::BrickType
= CHandlerPhraseValidateBrick::Root
;
409 CHandlerPhraseValidateBrick::BrickType
= CHandlerPhraseValidateBrick::OtherMain
;
411 // get our father build sentence
412 CDBGroupBuildPhrase
*buildGroup
= dynamic_cast<CDBGroupBuildPhrase
*>(pCaller
->getParent()->getParent());
415 // setup the validation
416 CHandlerPhraseValidateBrick::BuildPhraseGroup
= buildGroup
;
418 // build the list of possible bricks
420 buildGroup
->fillSelectionRoot();
422 buildGroup
->fillSelectionMain(index
);
425 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal
) );
429 CWidgetManager::getInstance()->enableModalWindow(pCaller
, group
);
433 REGISTER_ACTION_HANDLER( CHandlerPhraseSelectMainBrick
, "phrase_select_main_brick" );
436 // ***************************************************************************
437 class CHandlerPhraseSelectParamBrick
: public IActionHandler
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());
456 // setup the validation
457 CHandlerPhraseValidateBrick::BuildPhraseGroup
= buildGroup
;
459 // build the list of possible bricks
460 buildGroup
->fillSelectionParam(index
, paramIndex
);
463 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal
) );
467 CWidgetManager::getInstance()->enableModalWindow(pCaller
, group
);
471 REGISTER_ACTION_HANDLER( CHandlerPhraseSelectParamBrick
, "phrase_select_param_brick" );
474 // ***************************************************************************
475 class CHandlerPhraseSelectNewBrick
: public IActionHandler
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());
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();
500 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal
) );
504 CWidgetManager::getInstance()->enableModalWindow(pCaller
, group
);
508 REGISTER_ACTION_HANDLER( CHandlerPhraseSelectNewBrick
, "phrase_select_new_brick" );
511 // ***************************************************************************
512 class CHandlerPhraseChangeName
: public IActionHandler
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());
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
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
;
548 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>( CWidgetManager::getInstance()->getElementFromId( CDBGroupBuildPhrase::BrickSelectionModal
) );
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"));
583 buildPhrase
->updateAllDisplay();
586 if(BotChatPageAll
&& BotChatPageAll
->Trade
)
587 BotChatPageAll
->Trade
->updateSPhraseBuyDialog();
590 // **********************************************************************************************************
591 /** Called when the Item in Right Hand change
593 class CHandlerPhraseUpdateFromHand
: public IActionHandler
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
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
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())
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
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());
674 // Get the RootBrick of the Phrase
675 CSBrickSheet
*brick
= pBM
->getBrick(phrase
.Bricks
[0]);
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]);
689 pCSDst
->setCanDrop (true);
692 // check if incoming macro ok
696 const CMacroCmd
*macroCmd
= pMM
->getMacroFromMacroID(pCSSrc
->getMacroId());
698 pCSDst
->setCanDrop(true);
703 REGISTER_ACTION_HANDLER (CHandlerCanMemorizePhraseOrMacro
, "can_memorize_phrase_or_macro");
707 class CHandlerPhraseMemoryCopy
: public IActionHandler
710 static bool haveLastPhraseElement
;
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
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)
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();
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
;
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
);
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
);
813 CInterfaceElement
*pElt
= CWidgetManager::getInstance()->getElementFromId(src
);
814 pCSSrc
= dynamic_cast<CDBCtrlSheet
*>(pElt
);
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;
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());
839 // We may replace a phrase with a macro => must delete the phrase under us
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
850 // if Drag copy => this is a copy!
851 if(pCSSrc
->canDragCopy() && pIM
->testDragCopyKey())
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
);
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
);
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!
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
);
899 memorizePhraseOrMacro(dstMemoryIndex
, srcIsMacro
, srcPhraseId
, srcMacroId
);
901 // forget src (after shorctut change!)
902 CAHManager::getInstance()->runActionHandler("forget_phrase_or_macro", pCSSrc
);
911 void CHandlerMemorizePhraseOrMacro::memorizePhraseOrMacro(uint memoryIndex
, bool isMacro
, sint32 phraseId
, sint32 macroId
)
913 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
915 sint32 memoryLine
= pPM
->getSelectedMemoryLineDB();
921 pPM
->memorizeMacro(memoryLine
, memoryIndex
, macroId
);
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();
941 // this should have been checked in CanDrag
942 if(!pPM
->isPhraseCastable(sheetId
))
944 // build the com phrase
945 CSPhraseCom phraseCom
;
946 pPM
->buildPhraseFromSheet(phraseCom
, sheetId
);
947 if(phraseCom
.empty())
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
);
960 pPM
->setPhrase(newPhraseId
, phraseCom
);
962 // send learn to server
963 pPM
->sendLearnToServer(newPhraseId
);
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
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())
990 // Ok, the user try to forget a phrase slot.
991 sint32 memoryLine
= pPM
->getSelectedMemoryLineDB();
995 // get the memory index
996 uint memoryIndex
= pCSDst
->getIndexInDB();
998 if(pCSDst
->isMacro())
1000 pPM
->forgetMacro(memoryLine
, memoryIndex
);
1005 pPM
->forgetPhrase(memoryLine
, memoryIndex
);
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
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())
1028 // get the memory index
1029 uint memoryIndex
= pCSDst
->getIndexInDB();
1031 bool isMacro
= pCSDst
->isMacro();
1032 sint32 phraseId
= pCSDst
->getSPhraseId();
1034 // build params string
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
);
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
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();
1074 fromString(getParam(Params
, "memoryIndex"), memoryIndex
);
1076 fromString(getParam(Params
, "isMacro"),isMacro
);
1078 fromString(getParam(Params
, "phraseId"),phraseId
);
1082 pPM
->forgetMacro(memoryLine
, memoryIndex
);
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
1102 static sint64 LastHitTime
;
1103 static sint LastIndex
;
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())
1117 // Can cast only if not Latent (ie grayed) !!
1118 if (pCSDst
->getGrayed())
1121 // Ok, the user try to cast a phrase slot.
1123 if (pCSDst
->isShortCut())
1124 memoryLine
= pPM
->getSelectedMemoryLineDB();
1126 memoryLine
= pPM
->getSelectedMemoryAltLineDB();
1130 // get the memory index
1131 uint memoryIndex
= pCSDst
->getIndexInDB();
1133 // Check If the phrase exist
1134 sint phraseId
= pCSDst
->getSPhraseId();
1137 const CSPhraseCom
&phraseCom
= pPM
->getPhrase(phraseId
);
1138 if(phraseCom
.empty())
1140 CSBrickSheet
*rootBrick
= pBM
->getBrick(phraseCom
.Bricks
[0]);
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
1156 // **** Cyclic Cast? (dblclick)
1159 uint dbclickDelay
= CWidgetManager::getInstance()->getUserDblClickDelay();
1160 // if success to "dblclick"
1161 if(LastIndex
==(sint
)memoryIndex
&& T1
<=LastHitTime
+dbclickDelay
)
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
);
1183 // Can't cyclic cast Magic, SpecialPower or Harvest phrases (forage_extraction are auto)
1184 if( rootBrick
->isMagic() || rootBrick
->isHarvest() || rootBrick
->isSpecialPower() )
1187 // auto cyclic for forage extraction
1188 if( rootBrick
->isForageExtraction() )
1191 // even for extraction, if AvoidCyclic in any bricks, no cyclic!
1192 if( pPM
->avoidCyclicForPhrase(phraseCom
) )
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())
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
1224 UserEntity
->moveToExtractionPhrase(target
->slot(), MaxExtractionDistance
, memoryLine
, memoryIndex
, cyclic
);
1226 // start client execution
1227 pPM
->clientExecute(memoryLine
, memoryIndex
, cyclic
);
1231 // inform Server of phrase cast
1232 pPM
->sendExecuteToServer(memoryLine
, memoryIndex
, cyclic
);
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
1264 virtual void execute (CCtrlBase
* /* pCaller */, const string
&Params
)
1267 fromString(Params
, shortcut
);
1268 if (shortcut
>=0 && shortcut
<= 2*RYZOM_MAX_SHORTCUT
)
1270 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1273 CInterfaceElement
*elm
;
1274 if (shortcut
< RYZOM_MAX_SHORTCUT
)
1275 elm
= CWidgetManager::getInstance()->getElementFromId(PhraseMemoryCtrlBase
+ toString(shortcut
) );
1277 elm
= CWidgetManager::getInstance()->getElementFromId(PhraseMemoryAltCtrlBase
+ toString(shortcut
-RYZOM_MAX_SHORTCUT
) );
1278 CDBCtrlSheet
*ctrl
= dynamic_cast<CDBCtrlSheet
*>(elm
);
1281 // run the standard cast case.
1283 CAHManager::getInstance()->runActionHandler("cast_macro", ctrl
);
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
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())
1308 // get the phrase id under it
1309 sint phraseId
= pCSDst
->getSPhraseId();
1310 // if a phrase is on this slot, just cast the phrase
1313 CAHManager::getInstance()->runActionHandler("cast_phrase", pCaller
, Params
);
1315 // else open the RightMenuEmpty, to have "NewAction"
1318 string menu
= pCSDst
->getListMenuRightEmptySlot();
1319 // opens only if no dragged sheet
1320 if( !menu
.empty() && CDBCtrlSheet::getDraggedSheet()==NULL
)
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
1338 virtual void execute (CCtrlBase
*pCaller
, const string
&/* Params */)
1340 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1342 CInterfaceGroup
*parent
= pCaller
->getParent();
1345 // Get the Brother CtrlSheet
1346 CDBCtrlSheet
*ctrl
= dynamic_cast<CDBCtrlSheet
*>(parent
->getCtrl("ctrl_phrase"));
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
1364 virtual void execute(CCtrlBase
* /* pCaller */, const string
&Params
)
1366 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1368 // get the link index
1370 fromString(Params
, index
);
1371 // Get the link counter. Used to verify that the client cancel the correct link according to server
1373 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:EXECUTE_PHRASE:LINK:%d:COUNTER", index
), false);
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
))
1384 out
.serial(counter
);
1389 nlwarning(" unknown message name '%s'", "PHRASE:CANCEL_LINK");
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
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();
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
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
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]);
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
);
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
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())
1509 // Can cast only if not Latent (ie grayed) !!
1510 if (pCSDst
->getGrayed())
1513 // Ok, the user try to cast a phrase slot.
1515 if (pCSDst
->isShortCut())
1516 memoryLine
= pPM
->getSelectedMemoryLineDB();
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
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
1551 fromString(Params
, index
);
1552 if(index
>=0 && index
<SKILLS::NUM_SKILLS
)
1553 pPM
->setBookFilter(BRICK_TYPE::UNKNOWN
, (SKILLS::ESkills
)index
);
1555 pPM
->setBookFilter(BRICK_TYPE::UNKNOWN
, SKILLS::unknown
);
1559 REGISTER_ACTION_HANDLER(CHandlerPhraseBookSkillFilter
, "phrase_book_skill_filter");
1561 // ***************************************************************************
1562 class CHandlerPhraseSelectMemory
: public IActionHandler
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");
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
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");
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
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);
1623 fromString(Params
, val
);
1624 node
->setValue32(val
);
1628 REGISTER_ACTION_HANDLER(CHandlerPhraseSelectShortcutBar
, "select_shortcut_bar");
1630 // ***************************************************************************
1631 class CHandlerPhraseSelectShortcutBar2
: public IActionHandler
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);
1641 fromString(Params
, val
);
1642 node
->setValue32(val
);
1646 REGISTER_ACTION_HANDLER(CHandlerPhraseSelectShortcutBar2
, "select_shortcut_bar_2");
1648 // ***************************************************************************
1649 // ***************************************************************************
1650 // ***************************************************************************
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
)
1668 if(!args
[0].toInteger())
1670 sint sphraseId
= (sint
)args
[0].getInteger();
1671 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
1672 result
.setString(pPM
->getPhrase(sphraseId
).Name
.toUtf8());
1680 REGISTER_INTERFACE_USER_FCT("getSPhraseName", getSPhraseName
)
1683 // ***************************************************************************
1684 // Get the tooltip of a Combat Weapon restriction brick
1685 class CHandlerCombatRestrictTooltip
: public IActionHandler
1688 virtual void execute (CCtrlBase
*pCaller
, const string
&/* Params */)
1690 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1691 CDBCtrlSheet
*ctrlSheet
= dynamic_cast<CDBCtrlSheet
*>(pCaller
);
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"));
1701 strFindReplace(str
, "%comp", CI18N::get("uittPhraseCombatRestrictOK"));
1703 CWidgetManager::getInstance()->setContextHelpText(str
);
1706 REGISTER_ACTION_HANDLER( CHandlerCombatRestrictTooltip
, "phrase_combat_restrict_tooltip");
1709 // ***************************************************************************
1710 // ***************************************************************************
1711 // ***************************************************************************
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
);
1733 nlwarning(" unknown message name '%s'", "PHRASE:BUY_SHEET");
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
));
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
]);
1755 CCDBNodeLeaf
* node
= pBM
->getKnownBrickBitFieldDB(brick
->BrickFamily
);
1758 uint64 flags
= node
->getValue64();
1759 flags
|= uint64(1)<<(brick
->IndexInFamily
-1);
1760 node
->setValue64(flags
);
1766 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
1768 pPM
->receiveBotChatConfirmBuy(phraseId
, true);
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
))
1788 out
.serial(phraseId
);
1792 nlwarning(" unknown message name 'PHRASE:BUY");
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())
1813 const CSPhraseSheet
*sp
= ctrl
->asSPhraseSheet();
1814 if(!sp
|| sp
->Bricks
.empty())
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;
1825 // default: not append to the manager
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())
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
1849 phraseBotChatBuyBySheet(sp
->Id
, phraseId
);
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;
1862 fromString(args
[0], phraseId
);
1865 fromString(args
[1], confirm
);
1867 CSPhraseManager
*pSM
= CSPhraseManager::getInstance();
1868 pSM
->receiveBotChatConfirmBuy(phraseId
, confirm
);
1874 // ***************************************************************************
1875 // ***************************************************************************
1876 // ***************************************************************************
1878 // ***************************************************************************
1879 // ***************************************************************************
1880 // ***************************************************************************
1882 // ***************************************************************************
1883 class CHandlerCastMacro
: public IActionHandler
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())
1895 // Can cast only if not grayed
1896 if (pCSDst
->getGrayed())
1899 // execute the macro id
1900 pMM
->executeID(pCSDst
->getMacroId());
1903 REGISTER_ACTION_HANDLER( CHandlerCastMacro
, "cast_macro");
1906 // ***************************************************************************
1907 // ***************************************************************************
1908 // ***************************************************************************
1910 // ***************************************************************************
1911 // ***************************************************************************
1912 // ***************************************************************************
1914 // ***************************************************************************
1915 class CHandlerPhraseMemoryBeforeMenu
: public IActionHandler
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
)
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
)
1944 if(pPM
->getNextExecutePhraseId()==CHandlerPhraseMemoryBeforeMenu::LastPhraseIdMenu
)
1951 REGISTER_INTERFACE_USER_FCT("isPhraseMenuNotExecuting", isPhraseMenuNotExecuting
)