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) 2012 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
7 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU Affero General Public License as
11 // published by the Free Software Foundation, either version 3 of the
12 // License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Affero General Public License for more details.
19 // You should have received a copy of the GNU Affero General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "action_phrase_faber.h"
26 #include "../client_sheets/sbrick_sheet.h"
27 #include "interface_manager.h"
28 #include "../sheet_manager.h"
29 #include "inventory_manager.h"
30 #include "nel/gui/action_handler.h"
31 #include "../client_cfg.h"
32 #include "nel/gui/ctrl_base_button.h"
33 #include "nel/gui/group_container.h"
34 #include "../string_manager_client.h"
35 #include "../net_manager.h"
36 #include "sbrick_manager.h"
37 #include "sphrase_manager.h"
38 #include "nel/gui/group_editbox.h"
39 #include "nel/gui/dbview_bar.h"
40 #include "skill_manager.h"
41 #include "game_share/bot_chat_types.h"
48 using namespace NLMISC
;
51 // ***************************************************************************
52 const std::string FaberPlanDB
= "UI:PHRASE:FABER:FABER_PLAN:SHEET";
53 const std::string MPFaberDB
= "UI:PHRASE:FABER:MP_BUILD";
54 const std::string MPSelectionDB
= "UI:PHRASE:FABER:MP_SELECT";
55 const std::string MPQuantityDb
= "UI:PHRASE:FABER:MP_QUANTITY";
56 const std::string MPQuantitySelectDb
= "UI:PHRASE:FABER:STACK_SELECT";
57 const std::string ItemResultSheetDB
= "UI:PHRASE:FABER:RESULT_ITEM:SHEET";
58 const std::string ItemResultQuantityDB
= "UI:PHRASE:FABER:RESULT_ITEM:QUANTITY";
59 const std::string ItemResultSheetLevel
= "UI:PHRASE:FABER:RESULT_ITEM:QUALITY";
60 const std::string ItemResultSheetColor
= "UI:PHRASE:FABER:RESULT_ITEM:USER_COLOR";
61 const std::string ItemResultSheetClassType
= "UI:PHRASE:FABER:RESULT_ITEM:RM_CLASS_TYPE";
62 const std::string ItemResultSheetStatType
= "UI:PHRASE:FABER:RESULT_ITEM:RM_FABER_STAT_TYPE";
63 const std::string FaberPhraseWindow
= "ui:interface:phrase_faber_execution";
64 const std::string FaberPhraseItemReqLine
= FaberPhraseWindow
+ ":header_opened:item_reqs:item_req_%d";
65 const std::string FaberPhraseList
= "list";
66 const std::string FaberPhraseText
= "text";
67 const std::string FaberPhraseIcon
= "icon";
68 const std::string FaberPhraseValidButton
= FaberPhraseWindow
+ ":header_opened:ok_cancel:ok";
69 const std::string FaberPhraseFpCtrl
= FaberPhraseWindow
+ ":header_opened:faber_plan";
70 const std::string FaberPhraseFpSuccessText
= FaberPhraseWindow
+ ":header_opened:success_text";
71 const std::string FaberPhraseMpListModal
= "ui:interface:phrase_faber_mp_selection";
72 const std::string FaberPhraseMpQuantityModal
= "ui:interface:phrase_faber_mp_quantity";
73 const std::string FaberPhraseItemResultGroup
= FaberPhraseWindow
+ ":header_opened:item_result";
76 #define MAX_MP_SELECTION_ENTRIES 256
78 // ***************************************************************************
79 CActionPhraseFaber::CActionPhraseFaber()
81 uint size
= MAX_PLAYER_INV_ENTRIES
+ (MAX_ANIMALINV_ENTRIES
* MAX_INVENTORY_ANIMAL
) +
82 MAX_GUILDINV_ENTRIES
+ MAX_ROOMINV_ENTRIES
;
83 _InventoryMirror
.resize(size
);
84 _InventoryObsSetup
= false;
85 _ExecuteFromItemPlanBrick
= NULL
;
89 // ***************************************************************************
90 void CActionPhraseFaber::fillDBWithMP(const std::string
&sheetBase
, const CItem
&item
)
92 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
94 NLGUI::CDBManager::getInstance()->getDbProp(sheetBase
+ ":SHEET")->setValue32(item
.Sheet
.asInt());
95 NLGUI::CDBManager::getInstance()->getDbProp(sheetBase
+ ":QUALITY")->setValue32(item
.Quality
);
96 NLGUI::CDBManager::getInstance()->getDbProp(sheetBase
+ ":QUANTITY")->setValue32(item
.Quantity
);
97 NLGUI::CDBManager::getInstance()->getDbProp(sheetBase
+ ":USER_COLOR")->setValue32(item
.UserColor
);
98 NLGUI::CDBManager::getInstance()->getDbProp(sheetBase
+ ":WEIGHT")->setValue32(item
.Weight
);
102 // ***************************************************************************
103 void CActionPhraseFaber::launchFaberCastWindow(sint32 memoryLine
, uint memoryIndex
, CSBrickSheet
*rootBrick
)
105 // **** Get the ItemSheet for faber plan. NULL => no op.
108 // Copy Execution launch
109 _ExecuteFromMemoryLine
= memoryLine
;
110 _ExecuteFromMemoryIndex
= memoryIndex
;
111 // no item plan setuped for now
112 _ExecuteFromItemPlanBrick
= NULL
;
115 // get the family of item plan (for selection) from the rootBrick. It is stored in the Property0.
116 _FaberPlanBrickFamilies
.clear();
118 if (!rootBrick
->Properties
.empty())
120 string prop
= NLMISC::toUpperAscii(rootBrick
->Properties
[0].Text
);
121 vector
<string
> strList
;
122 splitString(prop
, " ", strList
);
123 // The prop Id should be 'FPLAN:'
124 if(strList
.size()>=2 && strList
[0]=="FPLAN:")
126 for(uint i
=1;i
<strList
.size();i
++)
128 BRICK_FAMILIES::TBrickFamily bfam
= BRICK_FAMILIES::toSBrickFamily(strList
[i
]);
129 if(bfam
!=BRICK_FAMILIES::Unknown
)
130 _FaberPlanBrickFamilies
.push_back(bfam
);
134 // if not found, error, cannot choose the faber plan
135 if(_FaberPlanBrickFamilies
.empty())
137 nlwarning("ERROR: The Craft Root %s does not contain a valid FPLAN: property -> Can't select plan to craft",
138 rootBrick
->Id
.toString().c_str() );
143 // **** Hide all widgets, MP Ctrls, and reset DB, until the Plan is not selected
144 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
145 // Hide the valid button
146 CCtrlBaseButton
*validButton
= dynamic_cast<CCtrlBaseButton
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseValidButton
));
148 validButton
->setFrozen(true);
150 // reset DB, hide the Mps
152 for(itemReqLine
=0;itemReqLine
<MAX_ITEM_REQ_LINE
;itemReqLine
++)
154 // Reset All Mps slots.
155 for(uint mpSlot
=0;mpSlot
<MAX_MP_SLOT
;mpSlot
++)
157 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("%s:%d:%d:SHEET", MPFaberDB
.c_str(), itemReqLine
, mpSlot
), false);
162 // Hide item requirements groups per default
163 CInterfaceGroup
*itemReqLineGroup
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId( toString(FaberPhraseItemReqLine
.c_str(), itemReqLine
) ));
165 itemReqLineGroup
->setActive(false);
168 // Reset the selected plan
169 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(FaberPlanDB
, false);
173 // Reset the result item
174 node
= NLGUI::CDBManager::getInstance()->getDbProp(ItemResultSheetDB
, false);
178 // Hide the ItemResult group
179 CInterfaceGroup
*groupMp
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseItemResultGroup
));
181 groupMp
->setActive(false);
184 // **** Open the window!
185 CGroupContainer
*window
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseWindow
));
188 window
->setActive(true);
190 // Setup the Title with a default text
191 string title
= CI18N::get("uiPhraseFaberExecuteNoPlan");
192 window
->setTitle (title
);
195 // **** setup DB observer!
196 // ensure remove (if setuped before), then add
197 CCDBNodeBranch
*branch
;
198 branch
= NLGUI::CDBManager::getInstance()->getDbBranch("LOCAL:INVENTORY:BAG");
199 if(branch
) NLGUI::CDBManager::getInstance()->removeBranchObserver( "LOCAL:INVENTORY:BAG",&_DBInventoryObs
);
200 if(branch
) NLGUI::CDBManager::getInstance()->addBranchObserver( "LOCAL:INVENTORY:BAG",&_DBInventoryObs
);
202 // and for all pack animals
204 for(i
=0;i
<MAX_INVENTORY_ANIMAL
;i
++)
206 branch
= NLGUI::CDBManager::getInstance()->getDbBranch(toString("LOCAL:INVENTORY:PACK_ANIMAL%d", i
));
207 if(branch
) NLGUI::CDBManager::getInstance()->removeBranchObserver( toString("LOCAL:INVENTORY:PACK_ANIMAL%d", i
).c_str(), &_DBInventoryObs
);
208 if(branch
) NLGUI::CDBManager::getInstance()->addBranchObserver( toString("LOCAL:INVENTORY:PACK_ANIMAL%d", i
).c_str(), &_DBInventoryObs
);
211 // Add observers on animal status, cause inventory may become unavailabe during the process
212 for(i
=0;i
<MAX_INVENTORY_ANIMAL
;i
++)
214 node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:PACK_ANIMAL:BEAST%d:STATUS",i
), false);
217 ICDBNode::CTextId textId
;
218 node
->addObserver(&_DBAnimalObs
, textId
);
222 // Observe skill status change to update success rate
223 CSkillManager
*pSM
= CSkillManager::getInstance();
224 pSM
->appendSkillChangeCallback(&_SkillObserver
);
228 // ***************************************************************************
229 void CActionPhraseFaber::onCloseFaberCastWindow()
231 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
232 CSkillManager
*pSM
= CSkillManager::getInstance();
234 // No more need to listen inventory change
235 CCDBNodeBranch
*branch
;
236 branch
= NLGUI::CDBManager::getInstance()->getDbBranch("LOCAL:INVENTORY:BAG");
237 if(branch
) branch
->removeBranchObserver(&_DBInventoryObs
);
238 // and for all pack animals
239 for(uint i
=0;i
<MAX_INVENTORY_ANIMAL
;i
++)
241 branch
= NLGUI::CDBManager::getInstance()->getDbBranch(toString("LOCAL:INVENTORY:PACK_ANIMAL%d", i
));
242 if(branch
) branch
->removeBranchObserver(&_DBInventoryObs
);
245 // remove observers on animal status, cause inventory may become unavailabe during the process
246 for(uint i
=0;i
<MAX_INVENTORY_ANIMAL
;i
++)
248 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:PACK_ANIMAL:BEAST%d:STATUS",i
), false);
251 ICDBNode::CTextId textId
;
252 node
->removeObserver(&_DBAnimalObs
, textId
);
256 pSM
->removeSkillChangeCallback(&_SkillObserver
);
260 // ***************************************************************************
261 void CActionPhraseFaber::fillFaberPlanSelection(const std::string
&brickDB
, uint maxSelection
)
263 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
264 CSBrickManager
*pBM
= CSBrickManager::getInstance();
266 // fill selection with all bricks of the same family
268 std::vector
<CSheetId
> bricks
;
269 for(i
=0;i
<_FaberPlanBrickFamilies
.size();i
++)
271 const std::vector
<NLMISC::CSheetId
> &famBricks
= pBM
->getFamilyBricks(_FaberPlanBrickFamilies
[i
]);
272 bricks
.insert(bricks
.end(), famBricks
.begin(), famBricks
.end());
275 // get only ones known
276 pBM
->filterKnownBricks(bricks
);
279 uint num
= min(maxSelection
, uint(bricks
.size()));
280 for(i
=0;i
<maxSelection
;i
++)
283 NLGUI::CDBManager::getInstance()->getDbProp(brickDB
+ ":" + toString(i
) + ":SHEET")->setValue32(bricks
[i
].asInt());
285 NLGUI::CDBManager::getInstance()->getDbProp(brickDB
+ ":" + toString(i
) + ":SHEET")->setValue32(0);
289 // ***************************************************************************
290 CItemImage
*CActionPhraseFaber::getInvMirrorItemImage(uint slotIndex
, uint
& invId
, uint
& indexInInv
)
292 if (slotIndex
< MAX_PLAYER_INV_ENTRIES
)
294 invId
= INVENTORIES::bag
;
295 indexInInv
= slotIndex
;
296 return &getInventory().getBagItem(slotIndex
);
298 slotIndex
-= MAX_PLAYER_INV_ENTRIES
;
300 if (slotIndex
< (MAX_ANIMALINV_ENTRIES
* MAX_INVENTORY_ANIMAL
))
302 uint animal
= slotIndex
/ MAX_ANIMALINV_ENTRIES
;
303 uint index
= slotIndex
% MAX_ANIMALINV_ENTRIES
;
304 invId
= INVENTORIES::pet_animal
+ animal
;
306 return &getInventory().getPAItem(animal
, index
);
308 slotIndex
-= (MAX_ANIMALINV_ENTRIES
* MAX_INVENTORY_ANIMAL
);
310 if (slotIndex
< MAX_GUILDINV_ENTRIES
)
312 if (getInventory().isInventoryAvailable(INVENTORIES::guild
))
314 CInterfaceManager
*im
= CInterfaceManager::getInstance();
315 CCDBNodeBranch
*itemBranch
= NLGUI::CDBManager::getInstance()->getDbBranch(SERVER_INVENTORY
":GUILD:" + toString(slotIndex
));
316 static CItemImage image
;
317 image
.build(itemBranch
);
318 invId
= INVENTORIES::guild
;
319 indexInInv
= slotIndex
;
324 slotIndex
-= MAX_GUILDINV_ENTRIES
;
326 if (slotIndex
< MAX_ROOMINV_ENTRIES
)
328 if (getInventory().isInventoryAvailable(INVENTORIES::player_room
))
330 CInterfaceManager
*im
= CInterfaceManager::getInstance();
331 CCDBNodeBranch
*itemBranch
= NLGUI::CDBManager::getInstance()->getDbBranch(SERVER_INVENTORY
":ROOM:" + toString(slotIndex
));
332 static CItemImage image
;
333 image
.build(itemBranch
);
334 invId
= INVENTORIES::player_room
;
335 indexInInv
= slotIndex
;
345 // ***************************************************************************
346 bool CActionPhraseFaber::isMpAvailable(CItemSheet
*mpSheet
, uint invId
, uint slotIndex
) const
348 return mpSheet
&& mpSheet
->Family
==ITEMFAMILY::RAW_MATERIAL
&& getInventory().isInventoryAvailable((INVENTORIES::TInventory
)invId
);
351 // ***************************************************************************
352 void CActionPhraseFaber::validateFaberPlanSelection(CSBrickSheet
*itemPlanBrick
)
354 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
357 // **** Get the ItemSheet for faber plan. NULL => no op.
360 _ExecuteFromItemPlanBrick
= itemPlanBrick
;
364 /*for(uint tam=0;tam<_ExecuteFromItemPlanBrick->FaberPlan.ItemPartMps.size();tam++)
366 _ExecuteFromItemPlanBrick->FaberPlan.ItemPartMps[tam].Quantity= 20;
368 _ExecuteFromItemPlanBrick->FaberPlan.FormulaMps.resize(2);
369 _ExecuteFromItemPlanBrick->FaberPlan.FormulaMps[0].ItemRequired= CSheetId("m0152chdca01.sitem");
370 _ExecuteFromItemPlanBrick->FaberPlan.FormulaMps[0].Quantity= 13;
371 _ExecuteFromItemPlanBrick->FaberPlan.FormulaMps[1].ItemRequired= CSheetId("m0691chdca01.sitem");
372 _ExecuteFromItemPlanBrick->FaberPlan.FormulaMps[1].Quantity= 25;
376 // the num of itempPart/specific items to setup
377 _MPBuildNumItemPartReq
= min((uint
)MAX_ITEM_REQ_LINE
, (uint
)_ExecuteFromItemPlanBrick
->FaberPlan
.ItemPartMps
.size());
378 _MPBuildNumSpecificItemReq
= min(((uint
)MAX_ITEM_REQ_LINE
-_MPBuildNumItemPartReq
), (uint
)_ExecuteFromItemPlanBrick
->FaberPlan
.FormulaMps
.size());
379 _MPBuildNumTotalItemReq
= _MPBuildNumItemPartReq
+ _MPBuildNumSpecificItemReq
;
382 // Setup the selected plan
383 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(FaberPlanDB
, false);
385 node
->setValue32(_ExecuteFromItemPlanBrick
->Id
.asInt());
387 // Setup the result item
388 node
= NLGUI::CDBManager::getInstance()->getDbProp(ItemResultSheetDB
, false);
390 node
->setValue32(itemPlanBrick
->FaberPlan
.ItemBuilt
.asInt());
392 // Setup the result quantity (for stacked items)
393 node
= NLGUI::CDBManager::getInstance()->getDbProp(ItemResultQuantityDB
, false);
395 node
->setValue32(itemPlanBrick
->FaberPlan
.NbItemBuilt
);
397 // Show the ItemResult group
398 CInterfaceGroup
*groupMp
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseItemResultGroup
));
400 groupMp
->setActive(true);
403 // **** reset the mpBuild
404 // For all item required.
406 for(itemReqLine
=0;itemReqLine
<_MPBuildNumTotalItemReq
;itemReqLine
++)
408 CMPBuild
&mpBuild
= _MPBuild
[itemReqLine
];
410 // Type of requirement?
411 // First go the ItemPart reqs
412 if(itemReqLine
<_MPBuildNumItemPartReq
)
414 uint itemPartId
= itemReqLine
;
415 mpBuild
.RequirementType
= CMPBuild::ItemPartReq
;
416 mpBuild
.FaberTypeRequired
= _ExecuteFromItemPlanBrick
->FaberPlan
.ItemPartMps
[itemPartId
].FaberTypeFilter
;
417 mpBuild
.QuantityReq
= _ExecuteFromItemPlanBrick
->FaberPlan
.ItemPartMps
[itemPartId
].Quantity
;
419 // Then go the Specific item reqs
422 uint itemSpecificId
= itemReqLine
- _MPBuildNumItemPartReq
;
423 mpBuild
.RequirementType
= CMPBuild::SpecificItemReq
;
424 mpBuild
.SpecificItemRequired
= _ExecuteFromItemPlanBrick
->FaberPlan
.FormulaMps
[itemSpecificId
].ItemRequired
;
425 mpBuild
.QuantityReq
= _ExecuteFromItemPlanBrick
->FaberPlan
.FormulaMps
[itemSpecificId
].Quantity
;
428 // Reset the quantity setuped for this line
429 mpBuild
.NumMpSlot
= 0;
430 for(uint mpSlot
=0;mpSlot
<MAX_MP_SLOT
;mpSlot
++)
432 mpBuild
.Id
[mpSlot
]= 0; // useless, but for consistency
433 mpBuild
.QuantitySelected
[mpSlot
]= 0;
436 // reset other to 0 also
437 for(;itemReqLine
<MAX_ITEM_REQ_LINE
;itemReqLine
++)
439 _MPBuild
[itemReqLine
].reset();
443 // **** First clear and copy the inventory to local struct
445 for(i
=0;i
<_InventoryMirror
.size();i
++)
447 _InventoryMirror
[i
].reset();
452 // Run all the inventories.
453 for(i
=0;i
<_InventoryMirror
.size();i
++)
455 CItemImage
*itemImage
= getInvMirrorItemImage(i
, invId
, indexInInv
);
456 bool bLockedByOwner
= itemImage
&& itemImage
->getLockedByOwner();
457 // item found and not locked?
461 _InventoryMirror
[i
].InventoryId
= invId
;
462 _InventoryMirror
[i
].IdInInventory
= indexInInv
;
464 // The item must be a mp
465 CSheetId sheetId
= CSheetId(itemImage
->getSheetID());
466 CItemSheet
*mpSheet
= dynamic_cast<CItemSheet
*>(SheetMngr
.get(sheetId
));
467 if( isMpAvailable(mpSheet
, invId
, i
) && !bLockedByOwner
)
469 _InventoryMirror
[i
].Sheet
= sheetId
;
470 _InventoryMirror
[i
].Quality
= itemImage
->getQuality();
471 _InventoryMirror
[i
].Quantity
= itemImage
->getQuantity();
472 _InventoryMirror
[i
].UserColor
= itemImage
->getUserColor();
473 _InventoryMirror
[i
].Weight
= itemImage
->getWeight();
474 // Bkup original quantity from inventory
475 _InventoryMirror
[i
].OriginalQuantity
= _InventoryMirror
[i
].Quantity
;
476 _InventoryMirror
[i
].LockedByOwner
= bLockedByOwner
;
482 // **** show ItemParts according to plan.
483 // Hide the valid button
484 CCtrlBaseButton
*validButton
= dynamic_cast<CCtrlBaseButton
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseValidButton
));
486 validButton
->setFrozen(true);
488 // reset DB, show/hide the Mps
489 for(itemReqLine
=0;itemReqLine
<MAX_ITEM_REQ_LINE
;itemReqLine
++)
491 CMPBuild
&mpBuild
= _MPBuild
[itemReqLine
];
493 // Reset All Mps slots.
494 for(uint mpSlot
=0;mpSlot
<MAX_MP_SLOT
;mpSlot
++)
496 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("%s:%d:%d:SHEET", MPFaberDB
.c_str(), itemReqLine
, mpSlot
), false);
501 // Setup item requirement groups
502 CInterfaceGroup
*itemReqLineGroup
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId( toString(FaberPhraseItemReqLine
.c_str(), itemReqLine
) ));
505 if( itemReqLine
<_MPBuildNumTotalItemReq
)
507 itemReqLineGroup
->setActive(true);
509 // Set as Text the required MP FaberType or Specific item
510 CViewText
*viewText
= dynamic_cast<CViewText
*>(itemReqLineGroup
->getView(FaberPhraseText
));
514 if(mpBuild
.RequirementType
==CMPBuild::ItemPartReq
)
516 text
= CI18N::get("uihelpFaberMpHeader");
517 strFindReplace(text
, "%f", RM_FABER_TYPE::toLocalString(mpBuild
.FaberTypeRequired
) );
519 else if(mpBuild
.RequirementType
==CMPBuild::SpecificItemReq
)
521 text
= STRING_MANAGER::CStringManagerClient::getItemLocalizedName(mpBuild
.SpecificItemRequired
);
527 viewText
->setText(text
);
530 // Set as Icon the required MP FaberType / or Sheet Texture (directly...)
531 CViewBitmap
*viewBmp
= dynamic_cast<CViewBitmap
*>(itemReqLineGroup
->getView(FaberPhraseIcon
));
534 if(mpBuild
.RequirementType
==CMPBuild::ItemPartReq
)
536 // texture name in config.xml
537 viewBmp
->setTexture(CWidgetManager::getInstance()->getParser()->getDefine( RM_FABER_TYPE::toIconDefineString(mpBuild
.FaberTypeRequired
) ));
539 else if(mpBuild
.RequirementType
==CMPBuild::SpecificItemReq
)
541 // NB: the texture is scaled, so it's ok to put the item 40x40 texture
542 const CItemSheet
*itemSheet
= dynamic_cast<const CItemSheet
*>(SheetMngr
.get(mpBuild
.SpecificItemRequired
));
544 viewBmp
->setTexture(itemSheet
->getIconMain());
546 viewBmp
->setTexture(std::string());
554 // update the EmptySlot
555 updateEmptySlot(itemReqLine
, itemReqLineGroup
);
557 // setup item required quantity view
558 updateQuantityView(itemReqLine
);
562 itemReqLineGroup
->setActive(false);
568 // **** Setup the new window title
569 CGroupContainer
*window
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseWindow
));
572 // Setup the Title with the item built
573 string title
= CI18N::get("uiPhraseFaberExecute");
574 strFindReplace(title
, "%item", STRING_MANAGER::CStringManagerClient::getItemLocalizedName(_ExecuteFromItemPlanBrick
->FaberPlan
.ItemBuilt
) );
575 window
->setTitle (title
);
583 // ***************************************************************************
584 void CActionPhraseFaber::resetSelection()
586 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
588 for(uint i
=0;i
<MAX_MP_SELECTION_ENTRIES
;i
++)
590 NLGUI::CDBManager::getInstance()->getDbProp(MPSelectionDB
+ ":" + toString(i
) + ":SHEET")->setValue32(0);
594 // ***************************************************************************
595 void CActionPhraseFaber::fillSelection(const std::vector
<uint
> &mps
)
597 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
599 uint num
= min(uint(MAX_MP_SELECTION_ENTRIES
), uint(mps
.size()));
600 for(uint i
=0;i
<MAX_MP_SELECTION_ENTRIES
;i
++)
602 if(i
<num
&& mps
[i
]<_InventoryMirror
.size())
604 CItem
&item
= _InventoryMirror
[mps
[i
]];
605 fillDBWithMP(MPSelectionDB
+ ":" + toString(i
), item
);
608 NLGUI::CDBManager::getInstance()->getDbProp(MPSelectionDB
+ ":" + toString(i
) + ":SHEET")->setValue32(0);
613 // ***************************************************************************
614 void CActionPhraseFaber::filterSelectionItemPart(std::vector
<uint
> &mps
, RM_FABER_TYPE::TRMFType itemPartFilter
, ITEM_ORIGIN::EItemOrigin originFilter
)
616 // Unknown => no fitler
617 if(itemPartFilter
==RM_FABER_TYPE::Unknown
)
620 std::vector
<uint
> res
;
621 res
.reserve(mps
.size());
623 for(uint i
=0;i
<mps
.size();i
++)
625 // get the item sheet
626 const CItemSheet
*itemSheet
= dynamic_cast<const CItemSheet
*>(SheetMngr
.get(_InventoryMirror
[mps
[i
]].Sheet
));
627 // test itemPartFilter match.
630 if(itemSheet
->canBuildItemPart(itemPartFilter
, originFilter
))
632 res
.push_back(mps
[i
]);
641 // ***************************************************************************
642 void CActionPhraseFaber::filterSelectionItemSpecific(std::vector
<uint
> &mps
, NLMISC::CSheetId specificItemWanted
)
644 std::vector
<uint
> res
;
645 res
.reserve(mps
.size());
647 // if unknown sheetid, no match
648 if(specificItemWanted
==NLMISC::CSheetId::Unknown
)
654 for(uint i
=0;i
<mps
.size();i
++)
656 // get the item sheet
657 const CItemSheet
*itemSheet
= dynamic_cast<const CItemSheet
*>(SheetMngr
.get(_InventoryMirror
[mps
[i
]].Sheet
));
658 // test sheetid match.
661 if(itemSheet
->Id
== specificItemWanted
)
663 res
.push_back(mps
[i
]);
672 // ***************************************************************************
673 void CActionPhraseFaber::startMpSelection(uint itemReqLine
, uint mpSlot
)
675 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
678 CDBCtrlSheet
*ctrlSlot
= NULL
;
679 CInterfaceGroup
*itemReqLineGroup
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId( toString(FaberPhraseItemReqLine
.c_str(), itemReqLine
) ));
682 CDBGroupListSheet
*listSheet
= dynamic_cast<CDBGroupListSheet
*>(itemReqLineGroup
->getGroup(FaberPhraseList
));
684 ctrlSlot
= listSheet
->getSheet(mpSlot
);
689 // get the mpBuild setup
690 nlassert(itemReqLine
<MAX_ITEM_REQ_LINE
);
691 CMPBuild
&mpBuild
= _MPBuild
[itemReqLine
];
693 // If the slot selected is already filled, Launch the MP Quantity selection modal
694 if(mpSlot
<mpBuild
.NumMpSlot
)
696 // fill the sheet info
697 uint invSlot
= mpBuild
.Id
[mpSlot
];
698 CItem item
= _InventoryMirror
[invSlot
];
699 fillDBWithMP(MPQuantitySelectDb
, item
);
701 // compute the maximum quantity possible to fill
702 uint maxQuantity
= getMaxQuantityChange(itemReqLine
, mpSlot
);
704 // set the max quantity as the default quantity to set up.
705 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(MPQuantitySelectDb
+ ":CUR_QUANTITY", false);
706 if(node
) node
->setValue32(maxQuantity
);
707 node
= NLGUI::CDBManager::getInstance()->getDbProp(MPQuantitySelectDb
+ ":MAX_QUANTITY", false);
708 if(node
) node
->setValue32(maxQuantity
);
710 // bkup for validation
711 _MpSelectionItemReqLine
= itemReqLine
;
712 _MpChangeQuantitySlot
= mpSlot
;
714 // Setup the text with value by default
715 CInterfaceGroup
*quantityModal
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseMpQuantityModal
));
718 CGroupEditBox
*eb
= dynamic_cast<CGroupEditBox
*>(quantityModal
->getGroup("eb"));
721 CWidgetManager::getInstance()->setCaptureKeyboard(eb
);
722 eb
->setInputString(toString(maxQuantity
));
723 eb
->setSelectionAll();
728 CWidgetManager::getInstance()->enableModalWindow(ctrlSlot
, quantityModal
);
730 // else select new MP
733 // For All the inventory
734 vector
<uint
> selectMps
;
735 for(uint i
=0;i
<_InventoryMirror
.size();i
++)
737 // If still some MP on this stack, and if not already selected, add to selection
738 if(_InventoryMirror
[i
].Quantity
>0 && (_InventoryMirror
[i
].Selected
&(1<<itemReqLine
))==0 )
740 selectMps
.push_back(i
);
744 // Filter the selection whether it is an itemPart or specificItem reqiurement
745 if(mpBuild
.RequirementType
==CMPBuild::ItemPartReq
)
747 CItemSheet
*itemBuilt
= dynamic_cast<CItemSheet
*>(SheetMngr
.get(_ExecuteFromItemPlanBrick
->FaberPlan
.ItemBuilt
));
748 ITEM_ORIGIN::EItemOrigin itemOrigin
= itemBuilt
? itemBuilt
->ItemOrigin
: ITEM_ORIGIN::UNKNOWN
;
749 filterSelectionItemPart(selectMps
, mpBuild
.FaberTypeRequired
, itemOrigin
);
751 else if(mpBuild
.RequirementType
==CMPBuild::SpecificItemReq
)
753 filterSelectionItemSpecific(selectMps
, mpBuild
.SpecificItemRequired
);
760 // Reset the DB selection
762 fillSelection(selectMps
);
764 // Bkup Selection for Validate later
765 _MpSelectionItemReqLine
= itemReqLine
;
766 _MpCurrentSelection
= selectMps
;
768 // Open the Selection Window.
769 CWidgetManager::getInstance()->enableModalWindow(ctrlSlot
, FaberPhraseMpListModal
);
773 // ***************************************************************************
774 void CActionPhraseFaber::validateMpSelection(uint selectId
)
776 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
778 if(selectId
>=_MpCurrentSelection
.size())
780 CWidgetManager::getInstance()->disableModalWindow();
784 // get which MP of the inventory we have selected
785 uint newInvSlot
= _MpCurrentSelection
[selectId
];
788 uint itemReqLine
= _MpSelectionItemReqLine
;
789 CMPBuild
&mpBuild
= _MPBuild
[itemReqLine
];
791 // Select the quantity to peek from this inventory slot: get max possible
792 sint quantity
= mpBuild
.QuantityReq
- getTotalQuantitySetuped(itemReqLine
);
793 nlassert(quantity
>0);
794 quantity
= min((sint32
)quantity
, _InventoryMirror
[newInvSlot
].Quantity
);
796 // it may be possible (by update DB and error) that selected slot is no more usable => just quit
800 // And Remove (virtually) item stack from this slot
801 _InventoryMirror
[newInvSlot
].Quantity
-= quantity
;
802 // mark as selected for this itemReqLine, so can no more select it
803 _InventoryMirror
[newInvSlot
].Selected
|= 1<<itemReqLine
;
806 nlassert(mpBuild
.NumMpSlot
<MAX_MP_SLOT
);
807 mpBuild
.Id
[mpBuild
.NumMpSlot
]= newInvSlot
;
808 mpBuild
.QuantitySelected
[mpBuild
.NumMpSlot
]= quantity
;
811 // Update The Execution View
812 CItem item
= _InventoryMirror
[newInvSlot
];
813 item
.Quantity
= quantity
;
814 fillDBWithMP(toString("%s:%d:%d", MPFaberDB
.c_str(), itemReqLine
, mpBuild
.NumMpSlot
-1), item
);
816 // update the empty slot
817 updateEmptySlot(itemReqLine
);
819 // update quantity view
820 updateQuantityView(itemReqLine
);
822 // update the validateButton
825 // update the item result
828 // must hide the modal window which had open us. NB: must be done here because next,
829 // we'll open the MP quantity selection
830 CWidgetManager::getInstance()->disableModalWindow();
832 // **** when all is correctly ended, open the quantity selection
833 // NB: just enable this code, if you want this feature
834 //startMpSelection(itemReqLine, mpBuild.NumMpSlot-1);
837 // ***************************************************************************
838 void CActionPhraseFaber::validateMpSelectQuantity()
840 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
842 // get current execution context of the validate
843 uint itemReqLine
= _MpSelectionItemReqLine
;
844 nlassert(itemReqLine
<MAX_ITEM_REQ_LINE
);
845 CMPBuild
&mpBuild
= _MPBuild
[itemReqLine
];
846 uint mpSlot
= _MpChangeQuantitySlot
;
847 nlassert(mpSlot
<mpBuild
.NumMpSlot
);
848 uint invSlot
= mpBuild
.Id
[mpSlot
];
849 nlassert(invSlot
<_InventoryMirror
.size());
850 nlassert(_InventoryMirror
[invSlot
].Selected
& (1<<itemReqLine
));
852 // get the quantity selected
853 uint quantitySelected
= 0;
854 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(MPQuantitySelectDb
+ ":CUR_QUANTITY", false);
855 if(node
) quantitySelected
= node
->getValue32();
857 // maximize (if error)
858 quantitySelected
= min(quantitySelected
, getMaxQuantityChange(itemReqLine
, mpSlot
));
860 // if the new quantity is 0
861 if(quantitySelected
==0)
863 // special: remove the mp slot from list
864 deleteMpSlot(itemReqLine
, mpSlot
);
868 // restore old quantity into inventory
869 _InventoryMirror
[invSlot
].Quantity
+= mpBuild
.QuantitySelected
[mpSlot
];
870 // And then Remove (virtually) new item stack from this slot
871 _InventoryMirror
[invSlot
].Quantity
-= quantitySelected
;
874 mpBuild
.QuantitySelected
[mpSlot
]= quantitySelected
;
876 // Update The Execution View
877 CItem item
= _InventoryMirror
[invSlot
];
878 item
.Quantity
= quantitySelected
;
879 fillDBWithMP(toString("%s:%d:%d", MPFaberDB
.c_str(), itemReqLine
, mpSlot
), item
);
882 // update the empty slot
883 updateEmptySlot(itemReqLine
);
885 // update quantity view
886 updateQuantityView(itemReqLine
);
888 // update the valid button
891 // update the item result
894 // hide the Modal Quantity selection
895 CWidgetManager::getInstance()->disableModalWindow();
898 // ***************************************************************************
899 void CActionPhraseFaber::validateExecution()
901 // the plan has must been selected
902 nlassert(_ExecuteFromItemPlanBrick
);
904 // Build the list of MP in Bag.
905 vector
<CFaberMsgItem
> mpItemPartList
;
906 vector
<CFaberMsgItem
> specificItemList
;
908 // Run all the current Build execution
909 for(uint itemReqLine
=0;itemReqLine
<_MPBuildNumTotalItemReq
;itemReqLine
++)
911 CMPBuild
&mpBuild
= _MPBuild
[itemReqLine
];
912 // For all slot setuped.
913 for(uint mpSlot
=0;mpSlot
<mpBuild
.NumMpSlot
;mpSlot
++)
917 uint invSlot
= mpBuild
.Id
[mpSlot
];
918 nlassert(invSlot
<_InventoryMirror
.size());
919 item
.setInvId(INVENTORIES::TInventory(_InventoryMirror
[invSlot
].InventoryId
));
920 item
.IndexInInv
= _InventoryMirror
[invSlot
].IdInInventory
;
921 item
.Quantity
= mpBuild
.QuantitySelected
[mpSlot
];
923 if(mpBuild
.RequirementType
==CMPBuild::ItemPartReq
)
924 mpItemPartList
.push_back(item
);
925 else if(mpBuild
.RequirementType
==CMPBuild::SpecificItemReq
)
926 specificItemList
.push_back(item
);
934 // display next craft action, and Send message to server
935 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
936 pPM
->executeCraft(_ExecuteFromMemoryLine
, _ExecuteFromMemoryIndex
,
937 _ExecuteFromItemPlanBrick
->Id
.asInt(), mpItemPartList
, specificItemList
);
939 // Open the Interface to get the crafted item
940 CTempInvManager::getInstance()->open(TEMP_INV_MODE::Craft
);
942 // NO more Close the Execution window (allow refaber quick)
943 /*CInterfaceManager *pIM= CInterfaceManager::getInstance();
944 CInterfaceElement *window= CWidgetManager::getInstance()->getElementFromId(FaberPhraseWindow);
946 window->setActive(false);
952 // ***************************************************************************
953 uint
CActionPhraseFaber::getTotalQuantitySetuped(uint itemReqLine
) const
955 nlassert(itemReqLine
<MAX_ITEM_REQ_LINE
);
956 nlassert(_MPBuild
[itemReqLine
].NumMpSlot
<=MAX_MP_SLOT
);
959 for(uint i
=0;i
<_MPBuild
[itemReqLine
].NumMpSlot
;i
++)
961 ret
+= _MPBuild
[itemReqLine
].QuantitySelected
[i
];
968 // ***************************************************************************
969 uint
CActionPhraseFaber::getMaxQuantityChange(uint itemReqLine
, uint mpSlot
) const
971 nlassert(itemReqLine
<MAX_ITEM_REQ_LINE
);
972 nlassert(mpSlot
<_MPBuild
[itemReqLine
].NumMpSlot
);
974 uint invSlot
= _MPBuild
[itemReqLine
].Id
[mpSlot
];
975 nlassert(invSlot
<_InventoryMirror
.size());
976 CItem item
= _InventoryMirror
[invSlot
];
978 // This is the quantity already selected for this itemReqLine, + rest in inventory
979 uint maxQuantity
= _MPBuild
[itemReqLine
].QuantitySelected
[mpSlot
] + item
.Quantity
;
980 // maximize with the rest of quantity with have to setup (remove us btw)
981 maxQuantity
= min(maxQuantity
, _MPBuild
[itemReqLine
].QuantityReq
-
982 (getTotalQuantitySetuped(itemReqLine
) - _MPBuild
[itemReqLine
].QuantitySelected
[mpSlot
]) );
988 // ***************************************************************************
989 void CActionPhraseFaber::updateEmptySlot(uint itemReqLine
, CInterfaceGroup
*itemReqLineGroup
)
991 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
993 if(!itemReqLineGroup
)
994 itemReqLineGroup
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId( toString(FaberPhraseItemReqLine
.c_str(), itemReqLine
) ));
995 if(!itemReqLineGroup
)
998 // get the list sheet and ctrlButton.
999 CDBGroupListSheet
*listSheet
= dynamic_cast<CDBGroupListSheet
*>(itemReqLineGroup
->getGroup(FaberPhraseList
));
1003 // NB: forceValidity calls invalidateCoords() if state change => dont "clear then set".
1006 bool allSetuped
= getTotalQuantitySetuped(itemReqLine
) >= _MPBuild
[itemReqLine
].QuantityReq
;
1008 // button no more needed?
1011 // Reset all ForceValid
1012 for(uint i
=0;i
<MAX_MP_SLOT
;i
++)
1013 listSheet
->forceValidity(i
, false);
1017 // Reset all ForceValid
1018 for(uint i
=0;i
<MAX_MP_SLOT
;i
++)
1020 listSheet
->forceValidity(i
, i
==_MPBuild
[itemReqLine
].NumMpSlot
);
1024 // Special for Specific Item requirement. Setup grayed item for the last empty slot
1025 for(uint i
=0;i
<MAX_MP_SLOT
;i
++)
1027 CMPBuild
&mpBuild
= _MPBuild
[itemReqLine
];
1029 // *** Fill the empty DB.
1030 if(i
>=mpBuild
.NumMpSlot
)
1033 // If Specfific requirement and just the last one, don't leave empty
1034 if(!allSetuped
&& i
==mpBuild
.NumMpSlot
&& mpBuild
.RequirementType
== CMPBuild::SpecificItemReq
)
1036 item
.Sheet
= mpBuild
.SpecificItemRequired
;
1038 fillDBWithMP(toString("%s:%d:%d", MPFaberDB
.c_str(), itemReqLine
, i
), item
);
1041 // *** Grayed,NoQuantity,NoQuality for the last slot of a specific requirement
1042 CDBCtrlSheet
*ctrl
= listSheet
->getSheet(i
);
1045 if(i
==mpBuild
.NumMpSlot
&& mpBuild
.RequirementType
== CMPBuild::SpecificItemReq
)
1047 ctrl
->setUseQuality(false);
1048 ctrl
->setUseQuantity(false);
1049 ctrl
->setGrayed(true);
1053 ctrl
->setUseQuality(true);
1054 ctrl
->setUseQuantity(true);
1055 ctrl
->setGrayed(false);
1062 // ***************************************************************************
1063 void CActionPhraseFaber::updateQuantityView(uint itemReqLine
)
1065 nlassert(itemReqLine
<MAX_ITEM_REQ_LINE
);
1067 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1069 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("%s:%d:SELECTED", MPQuantityDb
.c_str(), itemReqLine
), false);
1071 node
->setValue32(getTotalQuantitySetuped(itemReqLine
));
1072 node
= NLGUI::CDBManager::getInstance()->getDbProp(toString("%s:%d:REQUIRED", MPQuantityDb
.c_str(), itemReqLine
), false);
1074 node
->setValue32(_MPBuild
[itemReqLine
].QuantityReq
);
1078 // ***************************************************************************
1079 void CActionPhraseFaber::updateValidButton()
1081 // Check For All MPSlot: If All Ok, then can validate!
1082 bool canValid
= true;
1084 // can validate only if the Plan has been selected
1085 if(_ExecuteFromItemPlanBrick
)
1087 // Run all the current Build execution
1088 for(uint itemReqLine
=0;itemReqLine
<_MPBuildNumTotalItemReq
;itemReqLine
++)
1090 canValid
= canValid
&& getTotalQuantitySetuped(itemReqLine
)==_MPBuild
[itemReqLine
].QuantityReq
;
1096 // unfreeze if valid
1097 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1098 CCtrlBaseButton
*validButton
= dynamic_cast<CCtrlBaseButton
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseValidButton
));
1099 if(validButton
) validButton
->setFrozen(!canValid
);
1103 // ***************************************************************************
1104 void CActionPhraseFaber::deleteMpSlot(uint itemReqLine
, uint mpSlot
)
1106 nlassert(itemReqLine
<MAX_ITEM_REQ_LINE
);
1107 CMPBuild
&mpBuild
= _MPBuild
[itemReqLine
];
1108 nlassert(mpSlot
<mpBuild
.NumMpSlot
);
1109 uint invSlot
= mpBuild
.Id
[mpSlot
];
1110 nlassert(invSlot
<_InventoryMirror
.size());
1111 nlassert(_InventoryMirror
[invSlot
].Selected
& (1<<itemReqLine
));
1112 // NB: possible that mpBuild.QuantitySelected[mpSlot]==0 (call from removeMpSlotThatUseInvSlot())
1114 // restore quantity into inventory
1115 _InventoryMirror
[invSlot
].Quantity
+= mpBuild
.QuantitySelected
[mpSlot
];
1116 // no more selected for this itemReqLine, so can select it now
1117 _InventoryMirror
[invSlot
].Selected
&= ~(1<<itemReqLine
);
1119 // update the build by shifting in memory
1121 for(i
=mpSlot
;i
<mpBuild
.NumMpSlot
-1;i
++)
1123 mpBuild
.Id
[i
]= mpBuild
.Id
[i
+1];
1124 mpBuild
.QuantitySelected
[i
]= mpBuild
.QuantitySelected
[i
+1];
1126 mpBuild
.NumMpSlot
--;
1128 // update the execution view (just what needed)
1129 for(i
=mpSlot
;i
<mpBuild
.NumMpSlot
;i
++)
1131 CItem item
= _InventoryMirror
[mpBuild
.Id
[i
]];
1132 item
.Quantity
= mpBuild
.QuantitySelected
[i
];
1133 fillDBWithMP(toString("%s:%d:%d", MPFaberDB
.c_str(), itemReqLine
, i
), item
);
1136 // reset the empty slot!
1138 fillDBWithMP(toString("%s:%d:%d", MPFaberDB
.c_str(), itemReqLine
, mpBuild
.NumMpSlot
), item
);
1143 // ***************************************************************************
1144 // ***************************************************************************
1146 // ***************************************************************************
1147 // ***************************************************************************
1150 static CActionPhraseFaber
*ActionPhraseFaber
= NULL
;
1153 // ***************************************************************************
1154 // This expr is used only for define in phrase.xml.
1155 DECLARE_INTERFACE_CONSTANT(getPhraseMPSelectionMax
, MAX_MP_SELECTION_ENTRIES
)
1158 // ***************************************************************************
1159 class CHandlerPhraseFaberSelectMP
: public IActionHandler
1162 virtual void execute (CCtrlBase
*pCaller
, const string
&Params
)
1164 CDBCtrlSheet
*ctrl
= dynamic_cast<CDBCtrlSheet
*>(pCaller
);
1168 // get itemReqLine to Modify
1170 fromString(getParam(Params
, "item_req"), itemReqLine
);
1171 // get mpSlot edited
1172 uint mpSlot
= ctrl
->getIndexInDB();
1174 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1175 ActionPhraseFaber
->startMpSelection(itemReqLine
, mpSlot
);
1178 REGISTER_ACTION_HANDLER( CHandlerPhraseFaberSelectMP
, "phrase_faber_select_mp");
1181 // ***************************************************************************
1182 class CHandlerPhraseFaberValidateMP
: public IActionHandler
1185 virtual void execute (CCtrlBase
*pCaller
, const string
&/* Params */)
1187 CDBCtrlSheet
*ctrl
= dynamic_cast<CDBCtrlSheet
*>(pCaller
);
1190 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1191 CWidgetManager::getInstance()->disableModalWindow();
1195 // get the selected MP.
1196 uint selectMP
= ctrl
->getIndexInDB();
1198 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1199 ActionPhraseFaber
->validateMpSelection(selectMP
);
1202 REGISTER_ACTION_HANDLER( CHandlerPhraseFaberValidateMP
, "phrase_faber_validate_mp");
1205 // ***************************************************************************
1206 class CHandlerPhraseFaberValidate
: public IActionHandler
1209 virtual void execute (CCtrlBase
* /* pCaller */, const string
&/* Params */)
1211 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1212 ActionPhraseFaber
->validateExecution();
1215 REGISTER_ACTION_HANDLER( CHandlerPhraseFaberValidate
, "phrase_faber_validate");
1218 // ***************************************************************************
1219 class CHandlerPhraseFaberValidateOnEnter
: public IActionHandler
1222 virtual void execute (CCtrlBase
* /* pCaller */, const string
&/* Params */)
1225 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1226 CCtrlBaseButton
*button
= dynamic_cast<CCtrlBaseButton
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseValidButton
));
1228 // Ok, button found. test if active.
1229 if( button
&& !button
->getFrozen() )
1231 // Act as if the player click on this button
1232 CAHManager::getInstance()->runActionHandler("phrase_faber_validate", button
);
1236 REGISTER_ACTION_HANDLER( CHandlerPhraseFaberValidateOnEnter
, "phrase_faber_validate_on_enter");
1239 // ***************************************************************************
1240 class CHandlerPhraseFaberSelectMpQuantity
: public IActionHandler
1243 virtual void execute (CCtrlBase
* /* pCaller */, const string
&/* Params */)
1245 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1246 ActionPhraseFaber
->validateMpSelectQuantity();
1249 REGISTER_ACTION_HANDLER( CHandlerPhraseFaberSelectMpQuantity
, "phrase_faber_select_mp_quantity");
1253 // ***************************************************************************
1254 void launchFaberCastWindow(sint32 memoryLine
, uint memoryIndex
, CSBrickSheet
*rootBrick
)
1256 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1257 ActionPhraseFaber
->launchFaberCastWindow(memoryLine
, memoryIndex
, rootBrick
);
1260 // ***************************************************************************
1261 void fillFaberPlanSelection(const std::string
&brickDB
, uint maxSelection
)
1263 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1264 ActionPhraseFaber
->fillFaberPlanSelection(brickDB
, maxSelection
);
1267 // ***************************************************************************
1268 void validateFaberPlanSelection(CSBrickSheet
*itemPlanBrick
)
1270 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1271 ActionPhraseFaber
->validateFaberPlanSelection(itemPlanBrick
);
1274 // ***************************************************************************
1275 void closeFaberCastWindow()
1277 if (ActionPhraseFaber
== NULL
) return;
1278 CGroupContainer
*window
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseWindow
));
1279 if(window
&& window
->getActive())
1280 window
->setActive(false);
1284 // ***************************************************************************
1285 class CHandlerPhraseFaberOnClose
: public IActionHandler
1288 virtual void execute (CCtrlBase
* /* pCaller */, const string
&/* Params */)
1290 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1291 ActionPhraseFaber
->onCloseFaberCastWindow();
1294 REGISTER_ACTION_HANDLER( CHandlerPhraseFaberOnClose
, "phrase_faber_on_close");
1297 // ***************************************************************************
1298 // ***************************************************************************
1299 // Management of Change in Inventory
1300 // ***************************************************************************
1301 // ***************************************************************************
1304 // ***************************************************************************
1305 void CActionPhraseFaber::removeMpSlotThatUseInvSlot(uint invSlot
, uint quantityToRemove
)
1307 if(quantityToRemove
==0)
1310 // remove from all mpSlots
1311 for(uint itemReqLine
=0;itemReqLine
<_MPBuildNumTotalItemReq
;itemReqLine
++)
1313 CMPBuild
&mpBuild
= _MPBuild
[itemReqLine
];
1314 for(uint mpSlot
=0;mpSlot
<mpBuild
.NumMpSlot
;)
1316 // if this mpSlot use the invSlot.
1317 if(mpBuild
.Id
[mpSlot
]==invSlot
)
1319 // then remove stack mp. If slot not enough
1320 uint removeSlotQuantity
;
1321 removeSlotQuantity
= min(quantityToRemove
, mpBuild
.QuantitySelected
[mpSlot
]);
1322 mpBuild
.QuantitySelected
[mpSlot
]-= removeSlotQuantity
;
1323 quantityToRemove
-= removeSlotQuantity
;
1325 // if slot completely removed, then remove it totaly
1326 if(mpBuild
.QuantitySelected
[mpSlot
]==0)
1328 // NB: nothing is restored to inventory since mpBuild.QuantitySelected[mpSlot] is reseted before
1329 deleteMpSlot(itemReqLine
, mpSlot
);
1333 // just change this DB view
1334 CItem item
= _InventoryMirror
[invSlot
];
1335 item
.Quantity
= mpBuild
.QuantitySelected
[mpSlot
];
1336 fillDBWithMP(toString("%s:%d:%d", MPFaberDB
.c_str(), itemReqLine
, mpSlot
), item
);
1342 // if ok, all req quantity removed, quit
1343 if(quantityToRemove
==0)
1353 // ***************************************************************************
1354 void CActionPhraseFaber::onInventoryChange()
1356 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1359 bool displayChange
= false;
1361 // If the Faber Plan has not yet been selected, then must not check _InventoryMirror, since not initialized
1362 if(_ExecuteFromItemPlanBrick
==NULL
)
1367 uint indexInInv
= 0;
1368 for(i
=0;i
<_InventoryMirror
.size();i
++)
1370 CItemImage
*itemImage
= getInvMirrorItemImage(i
, invId
, indexInInv
);
1374 CSheetId sheetId
= CSheetId(itemImage
->getSheetID());
1375 CItemSheet
*mpSheet
= dynamic_cast<CItemSheet
*>(SheetMngr
.get(sheetId
));
1378 bool bLockedByOwner
= itemImage
->getLockedByOwner();
1380 // The item must be a mp, and the item must be available and unlocked
1381 if( isMpAvailable(mpSheet
, invId
, i
) && !bLockedByOwner
)
1383 newInvItem
.Sheet
= sheetId
;
1384 newInvItem
.Quality
= itemImage
->getQuality();
1385 newInvItem
.Quantity
= itemImage
->getQuantity();
1386 newInvItem
.UserColor
= itemImage
->getUserColor();
1387 newInvItem
.Weight
= itemImage
->getWeight();
1388 newInvItem
.OriginalQuantity
= newInvItem
.Quantity
;
1389 newInvItem
.LockedByOwner
= bLockedByOwner
;
1392 /* There is 5 cases:
1393 - no changes => no op.
1394 - new/unlocked Mp on a empty or non Mp slot. Easy, just add.
1395 - old Mp removed (not same sheetId/quality/userColor/locked)
1396 - old Mp with quantity changed to be greater
1397 - old Mp with quantity changed to be smaller
1400 CItem
&curInvItem
= _InventoryMirror
[i
];
1402 // Bkup Id in newInvItem (for ope= correctness)
1403 newInvItem
.InventoryId
= curInvItem
.InventoryId
;
1404 newInvItem
.IdInInventory
= curInvItem
.IdInInventory
;
1406 // If the item was not a mp
1407 if(_InventoryMirror
[i
].Sheet
==CSheetId::Unknown
)
1409 // if now it is, easy, just add if not locked
1410 if(newInvItem
.Sheet
!=CSheetId::Unknown
&& !newInvItem
.LockedByOwner
)
1411 curInvItem
= newInvItem
;
1413 // else must test change or remove
1417 sameMp
= curInvItem
.Sheet
== newInvItem
.Sheet
&&
1418 curInvItem
.Quality
== newInvItem
.Quality
&&
1419 curInvItem
.UserColor
== newInvItem
.UserColor
&&
1420 curInvItem
.LockedByOwner
== newInvItem
.LockedByOwner
;
1422 // if the Mp was deleted from this slot, delete it from all faber execution
1425 // remove all from current execution
1426 removeMpSlotThatUseInvSlot(i
, curInvItem
.OriginalQuantity
);
1428 // replace (with nothing or new different Mp)
1429 curInvItem
= newInvItem
;
1431 // mpSlot may have been deleted
1432 displayChange
= true;
1434 // test change of quantity
1437 // if the quantity is the same, no op!
1438 if(curInvItem
.OriginalQuantity
!=newInvItem
.OriginalQuantity
)
1440 // if the quantity is now greater, its easy
1441 if(newInvItem
.OriginalQuantity
> curInvItem
.OriginalQuantity
)
1443 // just add the difference to the original and current setuped quantity
1444 uint32 diff
= newInvItem
.OriginalQuantity
- curInvItem
.OriginalQuantity
;
1445 curInvItem
.OriginalQuantity
+= diff
;
1446 curInvItem
.Quantity
+= diff
;
1450 // complex, must remove the quantity that has changed
1451 uint32 diff
= curInvItem
.OriginalQuantity
- newInvItem
.OriginalQuantity
;
1452 // try first to remove it from remaining quantity
1453 if(curInvItem
.Quantity
>=(sint32
)diff
)
1455 // no change to current mpSlots!
1456 curInvItem
.Quantity
-= diff
;
1458 // must close the selection modal if opened
1459 displayChange
= true;
1461 // The remaining quantity is not enough, must also remove from mpSlot that use it!
1464 uint32 toRemoveFromSlot
= diff
- curInvItem
.Quantity
;
1465 curInvItem
.Quantity
= 0;
1466 // remove all needed to current mp slot.
1467 removeMpSlotThatUseInvSlot(i
, toRemoveFromSlot
);
1469 // mpSlot may have been deleted
1470 displayChange
= true;
1473 // bkup new original quantity
1474 curInvItem
.OriginalQuantity
= newInvItem
.OriginalQuantity
;
1482 // must update display?
1485 for(uint itemReqLine
= 0;itemReqLine
<_MPBuildNumTotalItemReq
;itemReqLine
++)
1487 updateEmptySlot(itemReqLine
);
1488 updateQuantityView(itemReqLine
);
1490 updateValidButton();
1492 // close selection modals if they are opened
1493 CInterfaceGroup
*quantityModal
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseMpQuantityModal
));
1494 if(quantityModal
&& CWidgetManager::getInstance()->getModalWindow()==quantityModal
)
1495 CWidgetManager::getInstance()->disableModalWindow();
1496 CInterfaceGroup
*listModal
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseMpListModal
));
1497 if(listModal
&& CWidgetManager::getInstance()->getModalWindow()==listModal
)
1498 CWidgetManager::getInstance()->disableModalWindow();
1500 // update item result
1505 // ***************************************************************************
1506 void CActionPhraseFaber::CDBInventoryObs::update(ICDBNode
* /* node */)
1508 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1509 ActionPhraseFaber
->onInventoryChange();
1512 // ***************************************************************************
1513 void CActionPhraseFaber::CDBAnimalObs::update(ICDBNode
* /* node */)
1515 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1516 ActionPhraseFaber
->onInventoryChange();
1521 // ***************************************************************************
1522 void CActionPhraseFaber::updateItemResult()
1524 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1525 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
1526 CSBrickManager
*pBM
= CSBrickManager::getInstance();
1530 // level is the min level of MP
1531 sint32 minLevel
= INT_MAX
;
1532 // Stat is computed like server
1533 float statArray
[RM_FABER_STAT_TYPE::NumRMStatType
];
1534 float statCount
[RM_FABER_STAT_TYPE::NumRMStatType
];
1535 uint64 itemStatBF
= 0;
1536 for(i
=0;i
<RM_FABER_STAT_TYPE::NumRMStatType
;i
++)
1541 // Color stat (for armour)
1542 uint32 bestItemColor
[RM_COLOR::NumColors
];
1543 for(i
=0;i
<RM_COLOR::NumColors
;i
++)
1544 bestItemColor
[i
]= 0;
1545 // Stat energy is computed like server
1546 float statEnergy
= 0;
1549 // **** Parse all Bricks of the phrase executed, to get min level
1550 // take The brick with the lowest CR_RECOMMENDED
1551 uint phraseSlot
= pPM
->getMemorizedPhrase(_ExecuteFromMemoryLine
, _ExecuteFromMemoryIndex
);
1552 const CSPhraseCom
&phrase
= pPM
->getPhrase(phraseSlot
);
1553 uint32 recommendedPropId
= pBM
->getBrickPropId("cr_recommended");
1554 for(i
=0;i
<phrase
.Bricks
.size();i
++)
1556 CSBrickSheet
*brick
= pBM
->getBrick(phrase
.Bricks
[i
]);
1559 for(uint j
=0;j
<brick
->Properties
.size();j
++)
1561 // if a CR_RECOMMENDED propId
1562 if(brick
->Properties
[j
].PropId
== recommendedPropId
)
1564 // minimze the level
1565 minLevel
= min(minLevel
, sint32(brick
->Properties
[j
].Value
));
1572 // **** Parse all MPs setuped, to compute level and stats
1573 uint totalItemPartMPReq
= 0;
1574 uint totalItemPartMPSetuped
= 0;
1575 for(i
=0;i
<_MPBuildNumTotalItemReq
;i
++)
1577 CMPBuild
&mpBuild
= _MPBuild
[i
];
1579 // --- ItemPart requirement?
1580 if(mpBuild
.RequirementType
==CMPBuild::ItemPartReq
)
1582 // For all slots setuped
1583 uint nSlot
= min((uint
)MAX_MP_SLOT
, mpBuild
.NumMpSlot
);
1584 for(uint j
=0;j
<nSlot
;j
++)
1586 // Try to get the MP in this slot
1587 CItemSheet
*mp
= dynamic_cast<CItemSheet
*>(SheetMngr
.get(_InventoryMirror
[mpBuild
.Id
[j
]].Sheet
));
1588 if(mp
&& mp
->canBuildItemPart(mpBuild
.FaberTypeRequired
))
1591 minLevel
= min(_InventoryMirror
[mpBuild
.Id
[j
]].Quality
, minLevel
);
1593 // Increment stat for each of this MP selected
1594 const CItemSheet::CMpItemPart
&mpIP
= mp
->getItemPart(mpBuild
.FaberTypeRequired
);
1596 // append to the stats
1597 uint numMps
= mpBuild
.QuantitySelected
[j
];
1598 for(uint k
=0;k
<RM_FABER_STAT_TYPE::NumRMStatType
;k
++)
1600 if(RM_FABER_STAT_TYPE::isStatRelevant(mpBuild
.FaberTypeRequired
, (RM_FABER_STAT_TYPE::TRMStatType
)k
))
1603 statArray
[k
]+= numMps
* (mpIP
.Stats
[k
]/100.f
);
1607 // Same for total energy
1608 statEnergy
+= numMps
* (mp
->Mp
.StatEnergy
/100.f
);
1610 // Increment color stat
1611 if(mp
->Mp
.MpColor
>=0 && mp
->Mp
.MpColor
<RM_COLOR::NumColors
)
1613 bestItemColor
[mp
->Mp
.MpColor
]+= numMps
;
1617 totalItemPartMPSetuped
+= numMps
;
1621 // get all stat for this item, and count MP req per stat
1622 for(uint k
=0;k
<RM_FABER_STAT_TYPE::NumRMStatType
;k
++)
1624 // if item part 'i' affect stat 'k'
1625 if(RM_FABER_STAT_TYPE::isStatRelevant(mpBuild
.FaberTypeRequired
, (RM_FABER_STAT_TYPE::TRMStatType
)k
))
1627 // StatPerItemPart ored in StatPerItem
1628 itemStatBF
|= uint64(1)<<k
;
1629 // Total Num MP per stat
1630 statCount
[k
]+= mpBuild
.QuantityReq
;
1635 totalItemPartMPReq
+= mpBuild
.QuantityReq
;
1638 // --- Specific Item requirement?
1639 else if(mpBuild
.RequirementType
==CMPBuild::SpecificItemReq
)
1641 // For all slots setuped
1642 uint nSlot
= min((uint
)MAX_MP_SLOT
, mpBuild
.NumMpSlot
);
1643 for(uint j
=0;j
<nSlot
;j
++)
1645 // Try to get the MP in this slot
1646 CItemSheet
*mp
= dynamic_cast<CItemSheet
*>(SheetMngr
.get(_InventoryMirror
[mpBuild
.Id
[j
]].Sheet
));
1647 if(mp
->Id
== mpBuild
.SpecificItemRequired
)
1650 minLevel
= min(_InventoryMirror
[mpBuild
.Id
[j
]].Quality
, minLevel
);
1652 // Formula 's Specific MPs don't impact on stats.
1659 for(i
=0;i
<RM_FABER_STAT_TYPE::NumRMStatType
;i
++)
1662 statArray
[i
]/= statCount
[i
];
1663 clamp(statArray
[i
], 0.f
, 1.f
);
1667 if(totalItemPartMPReq
)
1669 statEnergy
/= totalItemPartMPReq
;
1670 clamp(statEnergy
, 0.f
, 1.f
);
1673 // As in server, stretch the stats.
1674 // Add the special bonus ONLY when all MPs are setuped, for clearness
1675 RM_FABER_STAT_TYPE::stretchItemStats(statArray
, itemStatBF
, totalItemPartMPSetuped
>=totalItemPartMPReq
);
1679 if(minLevel
==INT_MAX
)
1681 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp(ItemResultSheetLevel
, false);
1683 node
->setValue32(minLevel
);
1686 // **** change success rate too
1687 CViewText
*successView
= dynamic_cast<CViewText
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseFpSuccessText
));
1690 string text
= CI18N::get("uiPhraseFaberSuccessRate");
1691 // Get the success rate of the related phrase
1692 uint phraseSlot
= pPM
->getMemorizedPhrase(_ExecuteFromMemoryLine
, _ExecuteFromMemoryIndex
);
1694 sint32 craftSuccessModifier
= 0;
1695 CCDBNodeLeaf
*nodeCSM
= NLGUI::CDBManager::getInstance()->getDbProp("SERVER:CHARACTER_INFO:SUCCESS_MODIFIER:CRAFT", false);
1698 craftSuccessModifier
= nodeCSM
->getValue32();
1700 // With the faber plan skill
1701 sint success
= pPM
->getCraftPhraseSuccessRate(pPM
->getPhrase(phraseSlot
), _ExecuteFromItemPlanBrick
->getSkill(), minLevel
, 0);
1702 sint bonus
= pPM
->getCraftPhraseSuccessRate(pPM
->getPhrase(phraseSlot
), _ExecuteFromItemPlanBrick
->getSkill(), minLevel
, (sint
) craftSuccessModifier
) - success
;
1706 successStr
= toString("@{FFFF}") + toString(success
);
1709 if( bonus
> 0 ) // bonus
1711 successStr
= "@{0F0F}" + toString(success
+ bonus
)
1713 + toString( success
)
1720 successStr
= "@{E42F}" + toString(success
+ bonus
)
1722 + toString( success
)
1724 + toString( abs(bonus
) )
1727 strFindReplace(text
, "%success", successStr
);
1728 successView
->setTextFormatTaged(text
);
1733 // Same than server code (NB: beige==1 per default)
1734 uint maxNumColor
= 0;
1735 uint dominanteColor
= 1;
1736 for(i
= 0; i
< RM_COLOR::NumColors
; ++i
)
1738 if( bestItemColor
[i
] > maxNumColor
)
1740 maxNumColor
= bestItemColor
[i
];
1744 node
= NLGUI::CDBManager::getInstance()->getDbProp(ItemResultSheetColor
, false);
1746 node
->setValue32(dominanteColor
);
1749 // **** Get Stat validity
1750 uint64 itemStatFinalUsageBF
= 0;
1751 // Some stat (magic protection and magic resist) are finaly used in the item only for the best ones
1752 itemStatFinalUsageBF
= RM_FABER_STAT_TYPE::getStatFinalValidity(statArray
, itemStatBF
);
1756 CInterfaceGroup
*groupMp
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(FaberPhraseItemResultGroup
));
1759 // default: hide all
1760 for(i
=0;i
<RM_FABER_STAT_TYPE::NumRMStatType
;i
++)
1762 // get the stat group
1763 CInterfaceGroup
*groupStat
= dynamic_cast<CInterfaceGroup
*>(groupMp
->getElement(groupMp
->getId()+toString(":stat%d",i
) ));
1765 groupStat
->setActive(false);
1767 // enable only one that are relevant for this item
1769 for(i
=0;i
<RM_FABER_STAT_TYPE::NumRMStatType
;i
++)
1771 RM_FABER_STAT_TYPE::TRMStatType statType
= RM_FABER_STAT_TYPE::TRMStatType(i
);
1773 // if this stat is not relevant for the item, don't display it!
1774 if( (itemStatBF
&(uint64(1)<<i
)) == 0)
1777 // Is the stat finaly used? (magic protection for instance may not be)
1778 bool finalyUsed
= (itemStatFinalUsageBF
&(uint64(1)<<i
)) != 0;
1779 CRGBA usageColor
= finalyUsed
?(CRGBA::White
):CRGBA(128,128,128);
1781 // get the next stat group
1782 CInterfaceGroup
*groupStat
= dynamic_cast<CInterfaceGroup
*>(groupMp
->getElement(groupMp
->getId()+toString(":stat%d",groupIndex
) ));
1785 groupStat
->setActive(true);
1786 // fill text and bar according to stat
1787 CViewText
*statTitle
= dynamic_cast<CViewText
*>(groupStat
->getElement(groupStat
->getId()+":text" ));
1788 CDBViewBar
*statValueBar
= dynamic_cast<CDBViewBar
*>(groupStat
->getElement(groupStat
->getId()+":bar" ));
1789 CViewText
*statValueText
= dynamic_cast<CViewText
*>(groupStat
->getElement(groupStat
->getId()+":textstat" ));
1790 CCtrlBase
*statToolTip
= dynamic_cast<CCtrlBase
*>(groupStat
->getElement(groupStat
->getId()+":tt" ));
1791 uint sv
= uint(statArray
[i
]*100);
1794 statTitle
->setText(RM_FABER_STAT_TYPE::toLocalString(statType
));
1795 statTitle
->setColor(usageColor
);
1799 statValueBar
->setValue(sv
);
1800 statValueBar
->setColor(usageColor
);
1804 statValueText
->setText(toString(sv
)+"/100");
1805 statValueText
->setColor(usageColor
);
1811 // display something only for magic/protect stat
1812 if( RM_FABER_STAT_TYPE::isMagicResistStat(RM_FABER_STAT_TYPE::TRMStatType(i
)) ||
1813 RM_FABER_STAT_TYPE::isMagicProtectStat(RM_FABER_STAT_TYPE::TRMStatType(i
)) )
1814 statToolTip
->setDefaultContextHelp(CI18N::get("uiFaberStatActive"));
1816 statToolTip
->setDefaultContextHelp(std::string());
1819 statToolTip
->setDefaultContextHelp(CI18N::get("uiFaberStatGrayed"));
1828 // **** BestStat (for text over)
1829 node
= NLGUI::CDBManager::getInstance()->getDbProp(ItemResultSheetStatType
, false);
1832 float bestStatValue
=-1.0f
;
1833 RM_FABER_STAT_TYPE::TRMStatType bestStat
= RM_FABER_STAT_TYPE::NumRMStatType
;
1834 for( i
= 0; i
< RM_FABER_STAT_TYPE::NumRMStatType
; ++i
)
1836 // if this stat is not relevant for the item, don't use it!
1837 if( (itemStatBF
&(uint64(1)<<i
)) == 0)
1839 float value
= statArray
[i
];
1840 if( value
> bestStatValue
)
1842 bestStatValue
= value
;
1843 bestStat
= (RM_FABER_STAT_TYPE::TRMStatType
)i
;
1847 node
->setValue32(bestStat
);
1851 // **** ClassType (for text over)
1852 node
= NLGUI::CDBManager::getInstance()->getDbProp(ItemResultSheetClassType
, false);
1856 node
->setValue32(RM_CLASS_TYPE::getItemClass((uint32
)(100.0f
* statEnergy
)));
1861 /* Handle change of skill -> recompute success rate */
1862 void CActionPhraseFaber::CSkillObserver::onSkillChange()
1864 if (ActionPhraseFaber
== NULL
) ActionPhraseFaber
= new CActionPhraseFaber
;
1865 // Dont update if the plan has not yet been selected
1866 if(ActionPhraseFaber
->_ExecuteFromItemPlanBrick
==NULL
)
1868 ActionPhraseFaber
->updateItemResult();