GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
* The ManaPlus Client |
||
3 |
* Copyright (C) 2004-2009 The Mana World Development Team |
||
4 |
* Copyright (C) 2009-2010 The Mana Developers |
||
5 |
* Copyright (C) 2011-2019 The ManaPlus Developers |
||
6 |
* Copyright (C) 2019-2021 Andrei Karas |
||
7 |
* |
||
8 |
* This file is part of The ManaPlus Client. |
||
9 |
* |
||
10 |
* This program is free software; you can redistribute it and/or modify |
||
11 |
* it under the terms of the GNU General Public License as published by |
||
12 |
* the Free Software Foundation; either version 2 of the License, or |
||
13 |
* any later version. |
||
14 |
* |
||
15 |
* This program is distributed in the hope that it will be useful, |
||
16 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
18 |
* GNU General Public License for more details. |
||
19 |
* |
||
20 |
* You should have received a copy of the GNU General Public License |
||
21 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
22 |
*/ |
||
23 |
|||
24 |
#include "gui/windows/npcdialog.h" |
||
25 |
|||
26 |
#include "actormanager.h" |
||
27 |
#include "configuration.h" |
||
28 |
#include "settings.h" |
||
29 |
#include "soundmanager.h" |
||
30 |
|||
31 |
#include "const/sound.h" |
||
32 |
|||
33 |
#include "being/being.h" |
||
34 |
#include "being/playerinfo.h" |
||
35 |
|||
36 |
#include "enums/gui/layouttype.h" |
||
37 |
|||
38 |
#include "gui/gui.h" |
||
39 |
#include "gui/viewport.h" |
||
40 |
|||
41 |
#include "gui/fonts/font.h" |
||
42 |
|||
43 |
#include "gui/popups/popupmenu.h" |
||
44 |
|||
45 |
#include "gui/windows/cutinwindow.h" |
||
46 |
#include "gui/windows/inventorywindow.h" |
||
47 |
|||
48 |
#include "gui/widgets/browserbox.h" |
||
49 |
#include "gui/widgets/button.h" |
||
50 |
#include "gui/widgets/createwidget.h" |
||
51 |
#include "gui/widgets/icon.h" |
||
52 |
#include "gui/widgets/inttextfield.h" |
||
53 |
#include "gui/widgets/itemcontainer.h" |
||
54 |
#include "gui/widgets/itemlinkhandler.h" |
||
55 |
#include "gui/widgets/layout.h" |
||
56 |
#include "gui/widgets/extendedlistbox.h" |
||
57 |
#include "gui/widgets/playerbox.h" |
||
58 |
#include "gui/widgets/scrollarea.h" |
||
59 |
|||
60 |
#include "resources/npcdialoginfo.h" |
||
61 |
|||
62 |
#include "resources/db/avatardb.h" |
||
63 |
#include "resources/db/npcdb.h" |
||
64 |
#include "resources/db/npcdialogdb.h" |
||
65 |
|||
66 |
#include "resources/inventory/complexinventory.h" |
||
67 |
|||
68 |
#include "resources/item/complexitem.h" |
||
69 |
|||
70 |
#include "resources/loaders/imageloader.h" |
||
71 |
|||
72 |
#include "net/npchandler.h" |
||
73 |
#include "net/packetlimiter.h" |
||
74 |
|||
75 |
#include "utils/copynpaste.h" |
||
76 |
#include "utils/delete2.h" |
||
77 |
#include "utils/foreach.h" |
||
78 |
#include "utils/gettext.h" |
||
79 |
|||
80 |
#include <sstream> |
||
81 |
|||
82 |
#include "debug.h" |
||
83 |
|||
84 |
// TRANSLATORS: npc dialog button |
||
85 |
#define CAPTION_WAITING _("Stop waiting") |
||
86 |
// TRANSLATORS: npc dialog button |
||
87 |
#define CAPTION_NEXT _("Next") |
||
88 |
// TRANSLATORS: npc dialog button |
||
89 |
#define CAPTION_CLOSE _("Close") |
||
90 |
// TRANSLATORS: npc dialog button |
||
91 |
#define CAPTION_SUBMIT _("Submit") |
||
92 |
|||
93 |
1 |
NpcDialog::DialogList NpcDialog::instances; |
|
94 |
1 |
NpcDialogs NpcDialog::mNpcDialogs; |
|
95 |
|||
96 |
typedef STD_VECTOR<Image *>::iterator ImageVectorIter; |
||
97 |
|||
98 |
1 |
NpcDialog::NpcDialog(const BeingId npcId) : |
|
99 |
// TRANSLATORS: npc dialog name |
||
100 |
1 |
Window(_("NPC"), Modal_false, nullptr, "npc.xml"), |
|
101 |
ActionListener(), |
||
102 |
mNpcId(npcId), |
||
103 |
mDefaultInt(0), |
||
104 |
mDefaultString(), |
||
105 |
mTextBox(new BrowserBox(this, Opaque_true, |
||
106 |
✓✗✓✗ |
1 |
"browserbox.xml")), |
107 |
1 |
mScrollArea(new ScrollArea(this, mTextBox, |
|
108 |
✓✗✓✗ ✗✓ |
4 |
fromBool(getOptionBool("showtextbackground", false), Opaque), |
109 |
✓✗✓✗ |
2 |
"npc_textbackground.xml")), |
110 |
mText(), |
||
111 |
mNewText(), |
||
112 |
mItems(), |
||
113 |
mImages(), |
||
114 |
✓✗✓✗ ✓✗✓✗ |
4 |
mItemList(CREATEWIDGETR(ExtendedListBox, |
115 |
this, this, "extendedlistbox.xml", 13)), |
||
116 |
1 |
mListScrollArea(new ScrollArea(this, mItemList, |
|
117 |
✓✗✓✗ ✗✓ |
4 |
fromBool(getOptionBool("showlistbackground", false), Opaque), |
118 |
✓✗✓✗ |
2 |
"npc_listbackground.xml")), |
119 |
✓✗✓✗ |
1 |
mSkinContainer(new Container(this)), |
120 |
1 |
mSkinScrollArea(new ScrollArea(this, mSkinContainer, |
|
121 |
✓✗✓✗ ✗✓ |
4 |
fromBool(getOptionBool("showlistbackground", false), Opaque), |
122 |
✓✗✓✗ |
2 |
"npc_listbackground.xml")), |
123 |
✓✗✓✗ |
1 |
mItemLinkHandler(new ItemLinkHandler), |
124 |
2 |
mTextField(new TextField(this, std::string(), LoseFocusOnTab_true, |
|
125 |
✓✗✓✗ |
2 |
nullptr, std::string(), false)), |
126 |
✓✗✓✗ |
1 |
mIntField(new IntTextField(this, 0, 0, 0, Enable_true, 0)), |
127 |
// TRANSLATORS: npc dialog button |
||
128 |
✓✗✓✗ |
2 |
mPlusButton(new Button(this, _("+"), "inc", BUTTON_SKIN, this)), |
129 |
// TRANSLATORS: npc dialog button |
||
130 |
✓✗✓✗ |
2 |
mMinusButton(new Button(this, _("-"), "dec", BUTTON_SKIN, this)), |
131 |
// TRANSLATORS: npc dialog button |
||
132 |
✓✗✓✗ |
2 |
mClearButton(new Button(this, _("Clear"), "clear", BUTTON_SKIN, this)), |
133 |
✓✗✓✗ |
1 |
mButton(new Button(this, "", "ok", BUTTON_SKIN, this)), |
134 |
// TRANSLATORS: npc dialog button |
||
135 |
✓✗✓✗ |
2 |
mButton2(new Button(this, _("Close"), "close", BUTTON_SKIN, this)), |
136 |
// TRANSLATORS: npc dialog button |
||
137 |
✓✗✓✗ |
2 |
mButton3(new Button(this, _("Add"), "add", BUTTON_SKIN, this)), |
138 |
// TRANSLATORS: npc dialog button |
||
139 |
✓✗✓✗ |
2 |
mResetButton(new Button(this, _("Reset"), "reset", BUTTON_SKIN, this)), |
140 |
✓✗✓✗ |
1 |
mInventory(new Inventory(InventoryType::Npc, 1)), |
141 |
✓✗✓✗ |
1 |
mComplexInventory(new ComplexInventory(InventoryType::Craft, 1)), |
142 |
mItemContainer(new ItemContainer(this, mInventory, |
||
143 |
✓✗✓✗ |
1 |
10000, ShowEmptyRows_true, ForceQuantity_false)), |
144 |
1 |
mItemScrollArea(new ScrollArea(this, mItemContainer, |
|
145 |
✓✗✓✗ ✗✓ |
4 |
fromBool(getOptionBool("showitemsbackground", false), Opaque), |
146 |
✓✗✓✗ |
2 |
"npc_listbackground.xml")), |
147 |
mInputState(NpcInputState::NONE), |
||
148 |
mActionState(NpcActionState::WAIT), |
||
149 |
mSkinControls(), |
||
150 |
mSkinName(), |
||
151 |
✓✗✓✗ |
4 |
mPlayerBox(new PlayerBox(nullptr, std::string(), std::string())), |
152 |
mAvatarBeing(nullptr), |
||
153 |
mDialogInfo(nullptr), |
||
154 |
mLastNextTime(0), |
||
155 |
mCameraMode(-1), |
||
156 |
mCameraX(0), |
||
157 |
mCameraY(0), |
||
158 |
mShowAvatar(false), |
||
159 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
107 |
mLogInteraction(config.getBoolValue("logNpcInGui")) |
160 |
{ |
||
161 |
// Basic Window Setup |
||
162 |
✓✗ | 5 |
setWindowName("NpcText"); |
163 |
✓✗ | 1 |
setResizable(true); |
164 |
✓✗ | 1 |
setFocusable(true); |
165 |
✓✗ | 1 |
setStickyButtonLock(true); |
166 |
|||
167 |
✓✗ | 1 |
setMinWidth(200); |
168 |
✓✗ | 1 |
setMinHeight(150); |
169 |
|||
170 |
✓✗ | 1 |
setDefaultSize(300, 578, ImagePosition::LOWER_LEFT, 0, 0); |
171 |
|||
172 |
✓✗ | 1 |
mPlayerBox->setWidth(70); |
173 |
✓✗ | 1 |
mPlayerBox->setHeight(100); |
174 |
|||
175 |
// Setup output text box |
||
176 |
2 |
mTextBox->setOpaque(Opaque_false); |
|
177 |
✓✗✓✗ |
5 |
mTextBox->setMaxRow(config.getIntValue("ChatLogLength")); |
178 |
✓✗ | 1 |
mTextBox->setLinkHandler(mItemLinkHandler); |
179 |
2 |
mTextBox->setProcessVars(true); |
|
180 |
✓✗ | 2 |
mTextBox->setFont(gui->getNpcFont()); |
181 |
2 |
mTextBox->setEnableKeys(true); |
|
182 |
2 |
mTextBox->setEnableTabs(true); |
|
183 |
2 |
mTextBox->setEnableImages(true); |
|
184 |
|||
185 |
✓✗ | 1 |
mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); |
186 |
✓✗ | 1 |
mScrollArea->setVerticalScrollPolicy(ScrollArea::SHOW_ALWAYS); |
187 |
|||
188 |
// Setup listbox |
||
189 |
2 |
mItemList->setWrappingEnabled(true); |
|
190 |
✓✗ | 5 |
mItemList->setActionEventId("ok"); |
191 |
✓✗ | 1 |
mItemList->addActionListener(this); |
192 |
2 |
mItemList->setDistributeMousePressed(false); |
|
193 |
✓✗ | 2 |
mItemList->setFont(gui->getNpcFont()); |
194 |
✓✗✓✗ |
2 |
if (gui->getNpcFont()->getHeight() < 20) |
195 |
1 |
mItemList->setRowHeight(20); |
|
196 |
else |
||
197 |
mItemList->setRowHeight(gui->getNpcFont()->getHeight()); |
||
198 |
|||
199 |
✓✗ | 1 |
setContentSize(260, 175); |
200 |
✓✗ | 1 |
mListScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); |
201 |
✓✗ | 1 |
mItemScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); |
202 |
1 |
mSkinScrollArea->setScrollPolicy(ScrollArea::SHOW_NEVER, |
|
203 |
✓✗ | 1 |
ScrollArea::SHOW_NEVER); |
204 |
✓✗ | 1 |
mItemList->setVisible(Visible_true); |
205 |
✓✗ | 1 |
mTextField->setVisible(Visible_true); |
206 |
✓✗ | 1 |
mIntField->setVisible(Visible_true); |
207 |
|||
208 |
✓✗ | 1 |
const Font *const fnt = mButton->getFont(); |
209 |
✓✗✓✗ |
6 |
int width = std::max(fnt->getWidth(CAPTION_WAITING), |
210 |
✓✗✓✗ |
7 |
fnt->getWidth(CAPTION_NEXT)); |
211 |
✓✗✓✗ |
5 |
width = std::max(width, fnt->getWidth(CAPTION_CLOSE)); |
212 |
✓✗✓✗ |
5 |
width = std::max(width, fnt->getWidth(CAPTION_SUBMIT)); |
213 |
✓✗ | 1 |
mButton->setWidth(8 + width); |
214 |
|||
215 |
// Place widgets |
||
216 |
✓✗ | 1 |
buildLayout(); |
217 |
|||
218 |
✓✗ | 1 |
center(); |
219 |
✓✗ | 1 |
loadWindowState(); |
220 |
|||
221 |
2 |
instances.push_back(this); |
|
222 |
1 |
} |
|
223 |
|||
224 |
1 |
void NpcDialog::postInit() |
|
225 |
{ |
||
226 |
1 |
Window::postInit(); |
|
227 |
1 |
setVisible(Visible_true); |
|
228 |
1 |
requestFocus(); |
|
229 |
2 |
enableVisibleSound(true); |
|
230 |
1 |
soundManager.playGuiSound(SOUND_SHOW_WINDOW); |
|
231 |
|||
232 |
✗✓ | 1 |
if (actorManager != nullptr) |
233 |
{ |
||
234 |
const Being *const being = actorManager->findBeing(mNpcId); |
||
235 |
if (being != nullptr) |
||
236 |
{ |
||
237 |
showAvatar(NPCDB::getAvatarFor(fromInt( |
||
238 |
being->getSubType(), BeingTypeId))); |
||
239 |
setCaption(being->getName()); |
||
240 |
} |
||
241 |
} |
||
242 |
|||
243 |
✓✗ | 4 |
config.addListener("logNpcInGui", this); |
244 |
1 |
} |
|
245 |
|||
246 |
12 |
NpcDialog::~NpcDialog() |
|
247 |
{ |
||
248 |
1 |
config.removeListeners(this); |
|
249 |
CHECKLISTENERS |
||
250 |
1 |
clearLayout(); |
|
251 |
|||
252 |
✓✗ | 1 |
if (mPlayerBox != nullptr) |
253 |
{ |
||
254 |
✗✓ | 2 |
delete mPlayerBox->getBeing(); |
255 |
✓✗ | 1 |
delete mPlayerBox; |
256 |
} |
||
257 |
|||
258 |
1 |
deleteSkinControls(); |
|
259 |
|||
260 |
✓✗ | 1 |
delete2(mTextBox) |
261 |
✓✗ | 1 |
delete2(mClearButton) |
262 |
✓✗ | 1 |
delete2(mButton) |
263 |
✓✗ | 1 |
delete2(mButton2) |
264 |
✓✗ | 1 |
delete2(mButton3) |
265 |
✓✗ | 1 |
delete2(mScrollArea) |
266 |
✓✗ | 1 |
delete2(mItemList) |
267 |
✓✗ | 1 |
delete2(mTextField) |
268 |
✓✗ | 1 |
delete2(mIntField) |
269 |
✓✗ | 1 |
delete2(mResetButton) |
270 |
✓✗ | 1 |
delete2(mPlusButton) |
271 |
✓✗ | 1 |
delete2(mMinusButton) |
272 |
✓✗ | 1 |
delete2(mItemLinkHandler) |
273 |
✓✗ | 1 |
delete2(mItemContainer) |
274 |
✓✗ | 1 |
delete2(mInventory) |
275 |
✓✗ | 1 |
delete2(mComplexInventory) |
276 |
✓✗ | 1 |
delete2(mItemScrollArea) |
277 |
✓✗ | 1 |
delete2(mListScrollArea) |
278 |
✓✗ | 1 |
delete2(mSkinScrollArea) |
279 |
|||
280 |
✗✓ | 4 |
FOR_EACH (ImageVectorIter, it, mImages) |
281 |
{ |
||
282 |
if (*it != nullptr) |
||
283 |
(*it)->decRef(); |
||
284 |
} |
||
285 |
|||
286 |
2 |
mImages.clear(); |
|
287 |
|||
288 |
1 |
instances.remove(this); |
|
289 |
2 |
} |
|
290 |
|||
291 |
void NpcDialog::addText(const std::string &text, const bool save) |
||
292 |
{ |
||
293 |
if (save || mLogInteraction) |
||
294 |
{ |
||
295 |
if (mText.size() > 5000) |
||
296 |
mText.clear(); |
||
297 |
|||
298 |
mNewText.append(text); |
||
299 |
mTextBox->addRow(text, |
||
300 |
false); |
||
301 |
} |
||
302 |
mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll()); |
||
303 |
mActionState = NpcActionState::WAIT; |
||
304 |
buildLayout(); |
||
305 |
} |
||
306 |
|||
307 |
void NpcDialog::showNextButton() |
||
308 |
{ |
||
309 |
mActionState = NpcActionState::NEXT; |
||
310 |
buildLayout(); |
||
311 |
} |
||
312 |
|||
313 |
void NpcDialog::showCloseButton() |
||
314 |
{ |
||
315 |
mActionState = NpcActionState::CLOSE; |
||
316 |
buildLayout(); |
||
317 |
} |
||
318 |
|||
319 |
void NpcDialog::action(const ActionEvent &event) |
||
320 |
{ |
||
321 |
const std::string &eventId = event.getId(); |
||
322 |
if (eventId == "ok") |
||
323 |
{ |
||
324 |
if (mActionState == NpcActionState::NEXT) |
||
325 |
{ |
||
326 |
if (!PacketLimiter::limitPackets(PacketType::PACKET_NPC_NEXT)) |
||
327 |
return; |
||
328 |
|||
329 |
nextDialog(); |
||
330 |
addText(std::string(), false); |
||
331 |
} |
||
332 |
else if (mActionState == NpcActionState::CLOSE |
||
333 |
|| mActionState == NpcActionState::WAIT) |
||
334 |
{ |
||
335 |
if (cutInWindow != nullptr) |
||
336 |
cutInWindow->hide(); |
||
337 |
closeDialog(); |
||
338 |
} |
||
339 |
else if (mActionState == NpcActionState::INPUT) |
||
340 |
{ |
||
341 |
std::string printText; // Text that will get printed |
||
342 |
// in the textbox |
||
343 |
switch (mInputState) |
||
344 |
{ |
||
345 |
case NpcInputState::LIST: |
||
346 |
{ |
||
347 |
if (mDialogInfo != nullptr) |
||
348 |
return; |
||
349 |
if (gui != nullptr) |
||
350 |
gui->resetClickCount(); |
||
351 |
const int selectedIndex = mItemList->getSelected(); |
||
352 |
|||
353 |
if (selectedIndex >= CAST_S32(mItems.size()) |
||
354 |
|| selectedIndex < 0 |
||
355 |
|| !PacketLimiter::limitPackets( |
||
356 |
PacketType::PACKET_NPC_INPUT)) |
||
357 |
{ |
||
358 |
return; |
||
359 |
} |
||
360 |
unsigned char choice = CAST_U8( |
||
361 |
selectedIndex + 1); |
||
362 |
printText = mItems[selectedIndex]; |
||
363 |
|||
364 |
npcHandler->listInput(mNpcId, choice); |
||
365 |
break; |
||
366 |
} |
||
367 |
case NpcInputState::STRING: |
||
368 |
{ |
||
369 |
if (!PacketLimiter::limitPackets( |
||
370 |
PacketType::PACKET_NPC_INPUT)) |
||
371 |
{ |
||
372 |
return; |
||
373 |
} |
||
374 |
printText = mTextField->getText(); |
||
375 |
npcHandler->stringInput(mNpcId, printText); |
||
376 |
break; |
||
377 |
} |
||
378 |
case NpcInputState::INTEGER: |
||
379 |
{ |
||
380 |
if (!PacketLimiter::limitPackets( |
||
381 |
PacketType::PACKET_NPC_INPUT)) |
||
382 |
{ |
||
383 |
return; |
||
384 |
} |
||
385 |
printText = strprintf("%d", mIntField->getValue()); |
||
386 |
npcHandler->integerInput( |
||
387 |
mNpcId, mIntField->getValue()); |
||
388 |
break; |
||
389 |
} |
||
390 |
case NpcInputState::ITEM: |
||
391 |
{ |
||
392 |
restoreVirtuals(); |
||
393 |
if (!PacketLimiter::limitPackets( |
||
394 |
PacketType::PACKET_NPC_INPUT)) |
||
395 |
{ |
||
396 |
return; |
||
397 |
} |
||
398 |
|||
399 |
std::string str; |
||
400 |
const int sz = mInventory->getSize(); |
||
401 |
if (sz == 0) |
||
402 |
{ |
||
403 |
str = "0,0"; |
||
404 |
} |
||
405 |
else |
||
406 |
{ |
||
407 |
const Item *item = mInventory->getItem(0); |
||
408 |
if (item != nullptr) |
||
409 |
{ |
||
410 |
str = strprintf("%d,%d", item->getId(), |
||
411 |
toInt(item->getColor(), int)); |
||
412 |
} |
||
413 |
else |
||
414 |
{ |
||
415 |
str = "0,0"; |
||
416 |
} |
||
417 |
for (int f = 1; f < sz; f ++) |
||
418 |
{ |
||
419 |
str.append(";"); |
||
420 |
item = mInventory->getItem(f); |
||
421 |
if (item != nullptr) |
||
422 |
{ |
||
423 |
str.append(strprintf("%d,%d", item->getId(), |
||
424 |
toInt(item->getColor(), int))); |
||
425 |
} |
||
426 |
else |
||
427 |
{ |
||
428 |
str.append("0,0"); |
||
429 |
} |
||
430 |
} |
||
431 |
} |
||
432 |
|||
433 |
// need send selected item |
||
434 |
npcHandler->stringInput(mNpcId, str); |
||
435 |
mInventory->clear(); |
||
436 |
break; |
||
437 |
} |
||
438 |
case NpcInputState::ITEM_INDEX: |
||
439 |
{ |
||
440 |
restoreVirtuals(); |
||
441 |
if (!PacketLimiter::limitPackets( |
||
442 |
PacketType::PACKET_NPC_INPUT)) |
||
443 |
{ |
||
444 |
return; |
||
445 |
} |
||
446 |
|||
447 |
std::string str; |
||
448 |
const int sz = mInventory->getSize(); |
||
449 |
if (sz == 0) |
||
450 |
{ |
||
451 |
str = "-1"; |
||
452 |
} |
||
453 |
else |
||
454 |
{ |
||
455 |
const Item *item = mInventory->getItem(0); |
||
456 |
if (item != nullptr) |
||
457 |
{ |
||
458 |
str = strprintf("%d", item->getTag()); |
||
459 |
} |
||
460 |
else |
||
461 |
{ |
||
462 |
str = "-1"; |
||
463 |
} |
||
464 |
for (int f = 1; f < sz; f ++) |
||
465 |
{ |
||
466 |
str.append(";"); |
||
467 |
item = mInventory->getItem(f); |
||
468 |
if (item != nullptr) |
||
469 |
str.append(strprintf("%d", item->getTag())); |
||
470 |
else |
||
471 |
str.append("-1"); |
||
472 |
} |
||
473 |
} |
||
474 |
|||
475 |
// need send selected item |
||
476 |
npcHandler->stringInput(mNpcId, str); |
||
477 |
mInventory->clear(); |
||
478 |
break; |
||
479 |
} |
||
480 |
case NpcInputState::ITEM_CRAFT: |
||
481 |
{ |
||
482 |
restoreVirtuals(); |
||
483 |
if (!PacketLimiter::limitPackets( |
||
484 |
PacketType::PACKET_NPC_INPUT)) |
||
485 |
{ |
||
486 |
return; |
||
487 |
} |
||
488 |
|||
489 |
std::string str; |
||
490 |
const int sz = mComplexInventory->getSize(); |
||
491 |
if (sz == 0) |
||
492 |
{ |
||
493 |
str.clear(); |
||
494 |
} |
||
495 |
else |
||
496 |
{ |
||
497 |
const ComplexItem *item = dynamic_cast<ComplexItem*>( |
||
498 |
mComplexInventory->getItem(0)); |
||
499 |
str = complexItemToStr(item); |
||
500 |
for (int f = 1; f < sz; f ++) |
||
501 |
{ |
||
502 |
str.append("|"); |
||
503 |
item = dynamic_cast<ComplexItem*>( |
||
504 |
mComplexInventory->getItem(f)); |
||
505 |
str.append(complexItemToStr(item)); |
||
506 |
} |
||
507 |
} |
||
508 |
|||
509 |
// need send selected item |
||
510 |
npcHandler->stringInput(mNpcId, str); |
||
511 |
mInventory->clear(); |
||
512 |
break; |
||
513 |
} |
||
514 |
|||
515 |
case NpcInputState::NONE: |
||
516 |
default: |
||
517 |
break; |
||
518 |
} |
||
519 |
if (mInputState != NpcInputState::ITEM && |
||
520 |
mInputState != NpcInputState::ITEM_INDEX && |
||
521 |
mInputState != NpcInputState::ITEM_CRAFT) |
||
522 |
{ |
||
523 |
// addText will auto remove the input layout |
||
524 |
addText(strprintf("> \"%s\"", printText.c_str()), false); |
||
525 |
} |
||
526 |
mNewText.clear(); |
||
527 |
} |
||
528 |
|||
529 |
if (!mLogInteraction) |
||
530 |
mTextBox->clearRows(); |
||
531 |
} |
||
532 |
else if (eventId == "reset") |
||
533 |
{ |
||
534 |
switch (mInputState) |
||
535 |
{ |
||
536 |
case NpcInputState::STRING: |
||
537 |
mTextField->setText(mDefaultString); |
||
538 |
break; |
||
539 |
case NpcInputState::INTEGER: |
||
540 |
mIntField->setValue(mDefaultInt); |
||
541 |
break; |
||
542 |
case NpcInputState::ITEM: |
||
543 |
case NpcInputState::ITEM_INDEX: |
||
544 |
mInventory->clear(); |
||
545 |
break; |
||
546 |
case NpcInputState::ITEM_CRAFT: |
||
547 |
mComplexInventory->clear(); |
||
548 |
break; |
||
549 |
case NpcInputState::NONE: |
||
550 |
case NpcInputState::LIST: |
||
551 |
default: |
||
552 |
break; |
||
553 |
} |
||
554 |
} |
||
555 |
else if (eventId == "inc") |
||
556 |
{ |
||
557 |
mIntField->setValue(mIntField->getValue() + 1); |
||
558 |
} |
||
559 |
else if (eventId == "dec") |
||
560 |
{ |
||
561 |
mIntField->setValue(mIntField->getValue() - 1); |
||
562 |
} |
||
563 |
else if (eventId == "clear") |
||
564 |
{ |
||
565 |
switch (mInputState) |
||
566 |
{ |
||
567 |
case NpcInputState::ITEM: |
||
568 |
case NpcInputState::ITEM_INDEX: |
||
569 |
mInventory->clear(); |
||
570 |
break; |
||
571 |
case NpcInputState::ITEM_CRAFT: |
||
572 |
mComplexInventory->clear(); |
||
573 |
break; |
||
574 |
case NpcInputState::STRING: |
||
575 |
case NpcInputState::INTEGER: |
||
576 |
case NpcInputState::LIST: |
||
577 |
case NpcInputState::NONE: |
||
578 |
default: |
||
579 |
clearRows(); |
||
580 |
break; |
||
581 |
} |
||
582 |
} |
||
583 |
else if (eventId == "close") |
||
584 |
{ |
||
585 |
restoreVirtuals(); |
||
586 |
if (mActionState == NpcActionState::INPUT) |
||
587 |
{ |
||
588 |
switch (mInputState) |
||
589 |
{ |
||
590 |
case NpcInputState::ITEM: |
||
591 |
npcHandler->stringInput(mNpcId, "0,0"); |
||
592 |
break; |
||
593 |
case NpcInputState::ITEM_INDEX: |
||
594 |
npcHandler->stringInput(mNpcId, "-1"); |
||
595 |
break; |
||
596 |
case NpcInputState::ITEM_CRAFT: |
||
597 |
npcHandler->stringInput(mNpcId, ""); |
||
598 |
break; |
||
599 |
case NpcInputState::STRING: |
||
600 |
case NpcInputState::INTEGER: |
||
601 |
case NpcInputState::NONE: |
||
602 |
case NpcInputState::LIST: |
||
603 |
default: |
||
604 |
npcHandler->listInput(mNpcId, 255); |
||
605 |
break; |
||
606 |
} |
||
607 |
if (cutInWindow != nullptr) |
||
608 |
cutInWindow->hide(); |
||
609 |
closeDialog(); |
||
610 |
} |
||
611 |
} |
||
612 |
else if (eventId == "add") |
||
613 |
{ |
||
614 |
if (inventoryWindow != nullptr) |
||
615 |
{ |
||
616 |
Item *const item = inventoryWindow->getSelectedItem(); |
||
617 |
Inventory *const inventory = PlayerInfo::getInventory(); |
||
618 |
if (inventory != nullptr) |
||
619 |
{ |
||
620 |
if (mInputState == NpcInputState::ITEM_CRAFT) |
||
621 |
{ |
||
622 |
if (mComplexInventory->addVirtualItem(item, -1, 1)) |
||
623 |
inventory->virtualRemove(item, 1); |
||
624 |
} |
||
625 |
else |
||
626 |
{ |
||
627 |
if (mInventory->addVirtualItem(item, -1, 1)) |
||
628 |
inventory->virtualRemove(item, 1); |
||
629 |
} |
||
630 |
} |
||
631 |
} |
||
632 |
} |
||
633 |
else if (eventId.find("skin_") == 0) |
||
634 |
{ |
||
635 |
const std::string cmd = eventId.substr(5); |
||
636 |
std::string printText; |
||
637 |
int cnt = 0; |
||
638 |
FOR_EACH (StringVectCIter, it, mItems) |
||
639 |
{ |
||
640 |
if (cmd == *it) |
||
641 |
{ |
||
642 |
npcHandler->listInput(mNpcId, CAST_U8(cnt + 1)); |
||
643 |
printText = mItems[cnt]; |
||
644 |
|||
645 |
if (mInputState != NpcInputState::ITEM && |
||
646 |
mInputState != NpcInputState::ITEM_INDEX && |
||
647 |
mInputState != NpcInputState::ITEM_CRAFT) |
||
648 |
{ |
||
649 |
// addText will auto remove the input layout |
||
650 |
addText(strprintf("> \"%s\"", printText.c_str()), false); |
||
651 |
} |
||
652 |
mNewText.clear(); |
||
653 |
break; |
||
654 |
} |
||
655 |
cnt ++; |
||
656 |
} |
||
657 |
} |
||
658 |
} |
||
659 |
|||
660 |
void NpcDialog::nextDialog() |
||
661 |
{ |
||
662 |
npcHandler->nextDialog(mNpcId); |
||
663 |
} |
||
664 |
|||
665 |
void NpcDialog::closeDialog() |
||
666 |
{ |
||
667 |
restoreCamera(); |
||
668 |
npcHandler->closeDialog(mNpcId); |
||
669 |
} |
||
670 |
|||
671 |
1 |
int NpcDialog::getNumberOfElements() |
|
672 |
{ |
||
673 |
2 |
return CAST_S32(mItems.size()); |
|
674 |
} |
||
675 |
|||
676 |
std::string NpcDialog::getElementAt(int i) |
||
677 |
{ |
||
678 |
return mItems[i]; |
||
679 |
} |
||
680 |
|||
681 |
const Image *NpcDialog::getImageAt(int i) |
||
682 |
{ |
||
683 |
return mImages[i]; |
||
684 |
} |
||
685 |
|||
686 |
void NpcDialog::choiceRequest() |
||
687 |
{ |
||
688 |
mItems.clear(); |
||
689 |
FOR_EACH (ImageVectorIter, it, mImages) |
||
690 |
{ |
||
691 |
if (*it != nullptr) |
||
692 |
(*it)->decRef(); |
||
693 |
} |
||
694 |
mImages.clear(); |
||
695 |
mActionState = NpcActionState::INPUT; |
||
696 |
mInputState = NpcInputState::LIST; |
||
697 |
buildLayout(); |
||
698 |
} |
||
699 |
|||
700 |
void NpcDialog::addChoice(const std::string &choice) |
||
701 |
{ |
||
702 |
mItems.push_back(choice); |
||
703 |
mImages.push_back(nullptr); |
||
704 |
} |
||
705 |
|||
706 |
void NpcDialog::parseListItems(const std::string &itemString) |
||
707 |
{ |
||
708 |
std::istringstream iss(itemString); |
||
709 |
std::string tmp; |
||
710 |
const std::string path = paths.getStringValue("guiIcons"); |
||
711 |
while (getline(iss, tmp, ':')) |
||
712 |
{ |
||
713 |
if (tmp.empty()) |
||
714 |
continue; |
||
715 |
const size_t pos = tmp.find('|'); |
||
716 |
if (pos == std::string::npos) |
||
717 |
{ |
||
718 |
mItems.push_back(tmp); |
||
719 |
mImages.push_back(nullptr); |
||
720 |
} |
||
721 |
else |
||
722 |
{ |
||
723 |
mItems.push_back(tmp.substr(pos + 1)); |
||
724 |
Image *const img = Loader::getImage(pathJoin(path, |
||
725 |
std::string(tmp.substr(0, pos)).append(".png"))); |
||
726 |
mImages.push_back(img); |
||
727 |
} |
||
728 |
} |
||
729 |
|||
730 |
if (!mItems.empty()) |
||
731 |
{ |
||
732 |
mItemList->setSelected(0); |
||
733 |
mItemList->requestFocus(); |
||
734 |
} |
||
735 |
else |
||
736 |
{ |
||
737 |
mItemList->setSelected(-1); |
||
738 |
} |
||
739 |
} |
||
740 |
|||
741 |
void NpcDialog::refocus() |
||
742 |
{ |
||
743 |
if (!mItems.empty()) |
||
744 |
mItemList->refocus(); |
||
745 |
} |
||
746 |
|||
747 |
void NpcDialog::textRequest(const std::string &defaultText) |
||
748 |
{ |
||
749 |
mActionState = NpcActionState::INPUT; |
||
750 |
mInputState = NpcInputState::STRING; |
||
751 |
mDefaultString = defaultText; |
||
752 |
mTextField->setText(defaultText); |
||
753 |
|||
754 |
buildLayout(); |
||
755 |
} |
||
756 |
|||
757 |
bool NpcDialog::isTextInputFocused() const |
||
758 |
{ |
||
759 |
return mTextField->isFocused(); |
||
760 |
} |
||
761 |
|||
762 |
bool NpcDialog::isInputFocused() const |
||
763 |
{ |
||
764 |
return mTextField->isFocused() || mIntField->isFocused() |
||
765 |
|| mItemList->isFocused(); |
||
766 |
} |
||
767 |
|||
768 |
bool NpcDialog::isAnyInputFocused() |
||
769 |
{ |
||
770 |
FOR_EACH (DialogList::const_iterator, it, instances) |
||
771 |
{ |
||
772 |
if (((*it) != nullptr) && (*it)->isInputFocused()) |
||
773 |
return true; |
||
774 |
} |
||
775 |
|||
776 |
return false; |
||
777 |
} |
||
778 |
|||
779 |
void NpcDialog::integerRequest(const int defaultValue, |
||
780 |
const int min, |
||
781 |
const int max) |
||
782 |
{ |
||
783 |
mActionState = NpcActionState::INPUT; |
||
784 |
mInputState = NpcInputState::INTEGER; |
||
785 |
mDefaultInt = defaultValue; |
||
786 |
mIntField->setRange(min, max); |
||
787 |
mIntField->setValue(defaultValue); |
||
788 |
buildLayout(); |
||
789 |
} |
||
790 |
|||
791 |
void NpcDialog::itemRequest(const int size) |
||
792 |
{ |
||
793 |
mActionState = NpcActionState::INPUT; |
||
794 |
mInputState = NpcInputState::ITEM; |
||
795 |
mInventory->resize(size); |
||
796 |
buildLayout(); |
||
797 |
} |
||
798 |
|||
799 |
void NpcDialog::itemIndexRequest(const int size) |
||
800 |
{ |
||
801 |
mActionState = NpcActionState::INPUT; |
||
802 |
mInputState = NpcInputState::ITEM_INDEX; |
||
803 |
mInventory->resize(size); |
||
804 |
buildLayout(); |
||
805 |
} |
||
806 |
|||
807 |
void NpcDialog::itemCraftRequest(const int size) |
||
808 |
{ |
||
809 |
mActionState = NpcActionState::INPUT; |
||
810 |
mInputState = NpcInputState::ITEM_CRAFT; |
||
811 |
mComplexInventory->resize(size); |
||
812 |
buildLayout(); |
||
813 |
} |
||
814 |
|||
815 |
void NpcDialog::move(const int amount) |
||
816 |
{ |
||
817 |
if (mActionState != NpcActionState::INPUT) |
||
818 |
return; |
||
819 |
|||
820 |
switch (mInputState) |
||
821 |
{ |
||
822 |
case NpcInputState::INTEGER: |
||
823 |
mIntField->setValue(mIntField->getValue() + amount); |
||
824 |
break; |
||
825 |
case NpcInputState::LIST: |
||
826 |
mItemList->setSelected(mItemList->getSelected() - amount); |
||
827 |
break; |
||
828 |
case NpcInputState::NONE: |
||
829 |
case NpcInputState::STRING: |
||
830 |
case NpcInputState::ITEM: |
||
831 |
case NpcInputState::ITEM_INDEX: |
||
832 |
case NpcInputState::ITEM_CRAFT: |
||
833 |
default: |
||
834 |
break; |
||
835 |
} |
||
836 |
} |
||
837 |
|||
838 |
void NpcDialog::setVisible(Visible visible) |
||
839 |
{ |
||
840 |
1 |
Window::setVisible(visible); |
|
841 |
|||
842 |
if (visible == Visible_false) |
||
843 |
scheduleDelete(); |
||
844 |
} |
||
845 |
|||
846 |
void NpcDialog::optionChanged(const std::string &name) |
||
847 |
{ |
||
848 |
if (name == "logNpcInGui") |
||
849 |
mLogInteraction = config.getBoolValue("logNpcInGui"); |
||
850 |
} |
||
851 |
|||
852 |
NpcDialog *NpcDialog::getActive() |
||
853 |
{ |
||
854 |
if (instances.size() == 1) |
||
855 |
return instances.front(); |
||
856 |
|||
857 |
FOR_EACH (DialogList::const_iterator, it, instances) |
||
858 |
{ |
||
859 |
if (((*it) != nullptr) && (*it)->isFocused()) |
||
860 |
return (*it); |
||
861 |
} |
||
862 |
|||
863 |
return nullptr; |
||
864 |
} |
||
865 |
|||
866 |
void NpcDialog::closeAll() |
||
867 |
{ |
||
868 |
FOR_EACH (DialogList::const_iterator, it, instances) |
||
869 |
{ |
||
870 |
if (*it != nullptr) |
||
871 |
(*it)->close(); |
||
872 |
} |
||
873 |
} |
||
874 |
|||
875 |
1 |
void NpcDialog::placeNormalControls() |
|
876 |
{ |
||
877 |
✗✓ | 1 |
if (mShowAvatar) |
878 |
{ |
||
879 |
place(0, 0, mPlayerBox, 1, 1); |
||
880 |
place(1, 0, mScrollArea, 5, 3); |
||
881 |
place(4, 3, mClearButton, 1, 1); |
||
882 |
place(5, 3, mButton, 1, 1); |
||
883 |
} |
||
884 |
else |
||
885 |
{ |
||
886 |
1 |
place(0, 0, mScrollArea, 5, 3); |
|
887 |
1 |
place(3, 3, mClearButton, 1, 1); |
|
888 |
1 |
place(4, 3, mButton, 1, 1); |
|
889 |
} |
||
890 |
1 |
} |
|
891 |
|||
892 |
void NpcDialog::placeMenuControls() |
||
893 |
{ |
||
894 |
if (mShowAvatar) |
||
895 |
{ |
||
896 |
place(0, 0, mPlayerBox, 1, 1); |
||
897 |
place(1, 0, mScrollArea, 6, 3); |
||
898 |
place(0, 3, mListScrollArea, 7, 3); |
||
899 |
place(1, 6, mButton2, 2, 1); |
||
900 |
place(3, 6, mClearButton, 2, 1); |
||
901 |
place(5, 6, mButton, 2, 1); |
||
902 |
} |
||
903 |
else |
||
904 |
{ |
||
905 |
place(0, 0, mScrollArea, 6, 3); |
||
906 |
place(0, 3, mListScrollArea, 6, 3); |
||
907 |
place(0, 6, mButton2, 2, 1); |
||
908 |
place(2, 6, mClearButton, 2, 1); |
||
909 |
place(4, 6, mButton, 2, 1); |
||
910 |
} |
||
911 |
} |
||
912 |
|||
913 |
void NpcDialog::placeSkinControls() |
||
914 |
{ |
||
915 |
createSkinControls(); |
||
916 |
if ((mDialogInfo != nullptr) && mDialogInfo->hideText) |
||
917 |
{ |
||
918 |
if (mShowAvatar) |
||
919 |
{ |
||
920 |
place(0, 0, mPlayerBox, 1, 1); |
||
921 |
place(1, 0, mSkinScrollArea, 7, 3); |
||
922 |
place(1, 3, mButton2, 2, 1); |
||
923 |
} |
||
924 |
else |
||
925 |
{ |
||
926 |
place(0, 0, mSkinScrollArea, 6, 3); |
||
927 |
place(0, 3, mButton2, 2, 1); |
||
928 |
} |
||
929 |
} |
||
930 |
else |
||
931 |
{ |
||
932 |
if (mShowAvatar) |
||
933 |
{ |
||
934 |
place(0, 0, mPlayerBox, 1, 1); |
||
935 |
place(1, 0, mScrollArea, 6, 3); |
||
936 |
place(0, 3, mSkinScrollArea, 7, 3); |
||
937 |
place(1, 6, mButton2, 2, 1); |
||
938 |
} |
||
939 |
else |
||
940 |
{ |
||
941 |
place(0, 0, mScrollArea, 6, 3); |
||
942 |
place(0, 3, mSkinScrollArea, 6, 3); |
||
943 |
place(0, 6, mButton2, 2, 1); |
||
944 |
} |
||
945 |
} |
||
946 |
} |
||
947 |
|||
948 |
void NpcDialog::placeTextInputControls() |
||
949 |
{ |
||
950 |
if (mShowAvatar) |
||
951 |
{ |
||
952 |
place(0, 0, mPlayerBox, 1, 1); |
||
953 |
place(1, 0, mScrollArea, 6, 3); |
||
954 |
place(1, 3, mTextField, 6, 1); |
||
955 |
place(1, 4, mResetButton, 2, 1); |
||
956 |
place(3, 4, mClearButton, 2, 1); |
||
957 |
place(5, 4, mButton, 2, 1); |
||
958 |
} |
||
959 |
else |
||
960 |
{ |
||
961 |
place(0, 0, mScrollArea, 6, 3); |
||
962 |
place(0, 3, mTextField, 6, 1); |
||
963 |
place(0, 4, mResetButton, 2, 1); |
||
964 |
place(2, 4, mClearButton, 2, 1); |
||
965 |
place(4, 4, mButton, 2, 1); |
||
966 |
} |
||
967 |
} |
||
968 |
|||
969 |
void NpcDialog::placeIntInputControls() |
||
970 |
{ |
||
971 |
if (mShowAvatar) |
||
972 |
{ |
||
973 |
place(0, 0, mPlayerBox, 1, 1); |
||
974 |
place(1, 0, mScrollArea, 6, 3); |
||
975 |
place(1, 3, mMinusButton, 1, 1); |
||
976 |
place(2, 3, mIntField, 4, 1); |
||
977 |
place(6, 3, mPlusButton, 1, 1); |
||
978 |
place(1, 4, mResetButton, 2, 1); |
||
979 |
place(3, 4, mClearButton, 2, 1); |
||
980 |
place(5, 4, mButton, 2, 1); |
||
981 |
} |
||
982 |
else |
||
983 |
{ |
||
984 |
place(0, 0, mScrollArea, 6, 3); |
||
985 |
place(0, 3, mMinusButton, 1, 1); |
||
986 |
place(1, 3, mIntField, 4, 1); |
||
987 |
place(5, 3, mPlusButton, 1, 1); |
||
988 |
place(0, 4, mResetButton, 2, 1); |
||
989 |
place(2, 4, mClearButton, 2, 1); |
||
990 |
place(4, 4, mButton, 2, 1); |
||
991 |
} |
||
992 |
} |
||
993 |
|||
994 |
void NpcDialog::placeItemInputControls() |
||
995 |
{ |
||
996 |
if (mDialogInfo != nullptr) |
||
997 |
{ |
||
998 |
mItemContainer->setCellBackgroundImage(mDialogInfo->inventory.cell); |
||
999 |
mItemContainer->setMaxColumns(mDialogInfo->inventory.columns); |
||
1000 |
} |
||
1001 |
else |
||
1002 |
{ |
||
1003 |
mItemContainer->setCellBackgroundImage("inventory_cell.xml"); |
||
1004 |
mItemContainer->setMaxColumns(10000); |
||
1005 |
} |
||
1006 |
|||
1007 |
if (mInputState == NpcInputState::ITEM_CRAFT) |
||
1008 |
mItemContainer->setInventory(mComplexInventory); |
||
1009 |
else |
||
1010 |
mItemContainer->setInventory(mInventory); |
||
1011 |
|||
1012 |
if ((mDialogInfo != nullptr) && mDialogInfo->hideText) |
||
1013 |
{ |
||
1014 |
if (mShowAvatar) |
||
1015 |
{ |
||
1016 |
place(0, 0, mPlayerBox, 1, 1); |
||
1017 |
place(1, 0, mItemScrollArea, 7, 3); |
||
1018 |
place(1, 3, mButton3, 2, 1); |
||
1019 |
place(3, 3, mClearButton, 2, 1); |
||
1020 |
place(5, 3, mButton, 2, 1); |
||
1021 |
} |
||
1022 |
else |
||
1023 |
{ |
||
1024 |
place(0, 0, mItemScrollArea, 6, 3); |
||
1025 |
place(0, 3, mButton3, 2, 1); |
||
1026 |
place(2, 3, mClearButton, 2, 1); |
||
1027 |
place(4, 3, mButton, 2, 1); |
||
1028 |
} |
||
1029 |
} |
||
1030 |
else |
||
1031 |
{ |
||
1032 |
if (mShowAvatar) |
||
1033 |
{ |
||
1034 |
place(0, 0, mPlayerBox, 1, 1); |
||
1035 |
place(1, 0, mScrollArea, 6, 3); |
||
1036 |
place(0, 3, mItemScrollArea, 7, 3); |
||
1037 |
place(1, 6, mButton3, 2, 1); |
||
1038 |
place(3, 6, mClearButton, 2, 1); |
||
1039 |
place(5, 6, mButton, 2, 1); |
||
1040 |
} |
||
1041 |
else |
||
1042 |
{ |
||
1043 |
place(0, 0, mScrollArea, 6, 3); |
||
1044 |
place(0, 3, mItemScrollArea, 6, 3); |
||
1045 |
place(0, 6, mButton3, 2, 1); |
||
1046 |
place(2, 6, mClearButton, 2, 1); |
||
1047 |
place(4, 6, mButton, 2, 1); |
||
1048 |
} |
||
1049 |
} |
||
1050 |
} |
||
1051 |
|||
1052 |
1 |
void NpcDialog::buildLayout() |
|
1053 |
{ |
||
1054 |
1 |
clearLayout(); |
|
1055 |
|||
1056 |
✓✗ | 1 |
if (mActionState != NpcActionState::INPUT) |
1057 |
{ |
||
1058 |
✓✗ | 1 |
if (mActionState == NpcActionState::WAIT) |
1059 |
5 |
mButton->setCaption(CAPTION_WAITING); |
|
1060 |
else if (mActionState == NpcActionState::NEXT) |
||
1061 |
mButton->setCaption(CAPTION_NEXT); |
||
1062 |
else if (mActionState == NpcActionState::CLOSE) |
||
1063 |
mButton->setCaption(CAPTION_CLOSE); |
||
1064 |
1 |
placeNormalControls(); |
|
1065 |
} |
||
1066 |
else if (mInputState != NpcInputState::NONE) |
||
1067 |
{ |
||
1068 |
mButton->setCaption(CAPTION_SUBMIT); |
||
1069 |
switch (mInputState) |
||
1070 |
{ |
||
1071 |
case NpcInputState::LIST: |
||
1072 |
if (mDialogInfo == nullptr) |
||
1073 |
placeMenuControls(); |
||
1074 |
else |
||
1075 |
placeSkinControls(); |
||
1076 |
mItemList->setSelected(-1); |
||
1077 |
break; |
||
1078 |
|||
1079 |
case NpcInputState::STRING: |
||
1080 |
placeTextInputControls(); |
||
1081 |
break; |
||
1082 |
|||
1083 |
case NpcInputState::INTEGER: |
||
1084 |
placeIntInputControls(); |
||
1085 |
break; |
||
1086 |
|||
1087 |
case NpcInputState::ITEM: |
||
1088 |
case NpcInputState::ITEM_INDEX: |
||
1089 |
case NpcInputState::ITEM_CRAFT: |
||
1090 |
placeItemInputControls(); |
||
1091 |
break; |
||
1092 |
|||
1093 |
case NpcInputState::NONE: |
||
1094 |
default: |
||
1095 |
break; |
||
1096 |
} |
||
1097 |
} |
||
1098 |
|||
1099 |
1 |
Layout &layout = getLayout(); |
|
1100 |
1 |
layout.setRowHeight(1, LayoutType::SET); |
|
1101 |
1 |
redraw(); |
|
1102 |
1 |
mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll()); |
|
1103 |
1 |
} |
|
1104 |
|||
1105 |
void NpcDialog::saveCamera() |
||
1106 |
{ |
||
1107 |
if ((viewport == nullptr) || mCameraMode >= 0) |
||
1108 |
return; |
||
1109 |
|||
1110 |
mCameraMode = CAST_S32(settings.cameraMode); |
||
1111 |
mCameraX = viewport->getCameraRelativeX(); |
||
1112 |
mCameraY = viewport->getCameraRelativeY(); |
||
1113 |
} |
||
1114 |
|||
1115 |
void NpcDialog::restoreCamera() |
||
1116 |
{ |
||
1117 |
if ((viewport == nullptr) || mCameraMode == -1) |
||
1118 |
return; |
||
1119 |
|||
1120 |
if (CAST_S32(settings.cameraMode) != mCameraMode) |
||
1121 |
viewport->toggleCameraMode(); |
||
1122 |
if (mCameraMode != 0) |
||
1123 |
{ |
||
1124 |
viewport->setCameraRelativeX(mCameraX); |
||
1125 |
viewport->setCameraRelativeY(mCameraY); |
||
1126 |
} |
||
1127 |
mCameraMode = -1; |
||
1128 |
} |
||
1129 |
|||
1130 |
void NpcDialog::showAvatar(const BeingTypeId avatarId) |
||
1131 |
{ |
||
1132 |
const bool needShow = (avatarId != BeingTypeId_zero); |
||
1133 |
if (needShow) |
||
1134 |
{ |
||
1135 |
delete mAvatarBeing; |
||
1136 |
mAvatarBeing = Being::createBeing(BeingId_zero, |
||
1137 |
ActorType::Avatar, |
||
1138 |
avatarId, |
||
1139 |
nullptr); |
||
1140 |
mPlayerBox->setPlayer(mAvatarBeing); |
||
1141 |
if (!mAvatarBeing->mSprites.empty()) |
||
1142 |
{ |
||
1143 |
mAvatarBeing->logic(); |
||
1144 |
const BeingInfo *const info = AvatarDB::get(avatarId); |
||
1145 |
const int pad2 = 2 * mPadding; |
||
1146 |
int width = 0; |
||
1147 |
if (info != nullptr) |
||
1148 |
{ |
||
1149 |
width = info->getWidth(); |
||
1150 |
mPlayerBox->setWidth(width + pad2); |
||
1151 |
mPlayerBox->setHeight(info->getHeight() + pad2); |
||
1152 |
} |
||
1153 |
const Sprite *const sprite = mAvatarBeing->mSprites[0]; |
||
1154 |
if ((sprite != nullptr) && (width == 0)) |
||
1155 |
{ |
||
1156 |
mPlayerBox->setWidth(sprite->getWidth() + pad2); |
||
1157 |
mPlayerBox->setHeight(sprite->getHeight() + pad2); |
||
1158 |
} |
||
1159 |
} |
||
1160 |
} |
||
1161 |
else |
||
1162 |
{ |
||
1163 |
delete2(mAvatarBeing) |
||
1164 |
mPlayerBox->setPlayer(nullptr); |
||
1165 |
} |
||
1166 |
if (needShow != mShowAvatar) |
||
1167 |
{ |
||
1168 |
mShowAvatar = needShow; |
||
1169 |
buildLayout(); |
||
1170 |
} |
||
1171 |
else |
||
1172 |
{ |
||
1173 |
mShowAvatar = needShow; |
||
1174 |
} |
||
1175 |
} |
||
1176 |
|||
1177 |
void NpcDialog::setAvatarDirection(const uint8_t direction) |
||
1178 |
{ |
||
1179 |
Being *const being = mPlayerBox->getBeing(); |
||
1180 |
if (being != nullptr) |
||
1181 |
being->setDirection(direction); |
||
1182 |
} |
||
1183 |
|||
1184 |
void NpcDialog::setAvatarAction(const int actionId) |
||
1185 |
{ |
||
1186 |
Being *const being = mPlayerBox->getBeing(); |
||
1187 |
if (being != nullptr) |
||
1188 |
being->setAction(static_cast<BeingActionT>(actionId), 0); |
||
1189 |
} |
||
1190 |
|||
1191 |
void NpcDialog::logic() |
||
1192 |
{ |
||
1193 |
BLOCK_START("NpcDialog::logic") |
||
1194 |
Window::logic(); |
||
1195 |
if (mShowAvatar && (mAvatarBeing != nullptr)) |
||
1196 |
{ |
||
1197 |
mAvatarBeing->logic(); |
||
1198 |
if (mPlayerBox->getWidth() < CAST_S32(3 * getPadding())) |
||
1199 |
{ |
||
1200 |
const Sprite *const sprite = mAvatarBeing->mSprites[0]; |
||
1201 |
if (sprite != nullptr) |
||
1202 |
{ |
||
1203 |
mPlayerBox->setWidth(sprite->getWidth() + 2 * getPadding()); |
||
1204 |
mPlayerBox->setHeight(sprite->getHeight() + 2 * getPadding()); |
||
1205 |
buildLayout(); |
||
1206 |
} |
||
1207 |
} |
||
1208 |
} |
||
1209 |
BLOCK_END("NpcDialog::logic") |
||
1210 |
} |
||
1211 |
|||
1212 |
void NpcDialog::clearRows() |
||
1213 |
{ |
||
1214 |
mTextBox->clearRows(); |
||
1215 |
} |
||
1216 |
|||
1217 |
void NpcDialog::clearDialogs() |
||
1218 |
{ |
||
1219 |
NpcDialogs::iterator it = mNpcDialogs.begin(); |
||
1220 |
const NpcDialogs::iterator it_end = mNpcDialogs.end(); |
||
1221 |
while (it != it_end) |
||
1222 |
{ |
||
1223 |
delete (*it).second; |
||
1224 |
++ it; |
||
1225 |
} |
||
1226 |
mNpcDialogs.clear(); |
||
1227 |
} |
||
1228 |
|||
1229 |
void NpcDialog::mousePressed(MouseEvent &event) |
||
1230 |
{ |
||
1231 |
Window::mousePressed(event); |
||
1232 |
if (event.getButton() == MouseButton::RIGHT |
||
1233 |
&& event.getSource() == mTextBox) |
||
1234 |
{ |
||
1235 |
event.consume(); |
||
1236 |
if (popupMenu != nullptr) |
||
1237 |
{ |
||
1238 |
popupMenu->showNpcDialogPopup(mNpcId, |
||
1239 |
viewport->mMouseX, |
||
1240 |
viewport->mMouseY); |
||
1241 |
} |
||
1242 |
} |
||
1243 |
} |
||
1244 |
|||
1245 |
void NpcDialog::copyToClipboard(const int x, const int y) const |
||
1246 |
{ |
||
1247 |
std::string str = mTextBox->getTextAtPos(x, y); |
||
1248 |
sendBuffer(str); |
||
1249 |
} |
||
1250 |
|||
1251 |
void NpcDialog::setSkin(const std::string &skin) |
||
1252 |
{ |
||
1253 |
if (skin.empty()) |
||
1254 |
{ |
||
1255 |
mSkinName = skin; |
||
1256 |
mDialogInfo = nullptr; |
||
1257 |
return; |
||
1258 |
} |
||
1259 |
const NpcDialogInfo *const dialog = NpcDialogDB::getDialog(skin); |
||
1260 |
if (dialog == nullptr) |
||
1261 |
{ |
||
1262 |
logger->log("Error: creating controls for not existing npc dialog %s", |
||
1263 |
skin.c_str()); |
||
1264 |
return; |
||
1265 |
} |
||
1266 |
mSkinName = skin; |
||
1267 |
mDialogInfo = dialog; |
||
1268 |
} |
||
1269 |
|||
1270 |
void NpcDialog::deleteSkinControls() |
||
1271 |
{ |
||
1272 |
1 |
mSkinContainer->removeControls(); |
|
1273 |
} |
||
1274 |
|||
1275 |
void NpcDialog::createSkinControls() |
||
1276 |
{ |
||
1277 |
deleteSkinControls(); |
||
1278 |
|||
1279 |
if (mDialogInfo == nullptr) |
||
1280 |
return; |
||
1281 |
|||
1282 |
FOR_EACH (STD_VECTOR<NpcImageInfo*>::const_iterator, |
||
1283 |
it, |
||
1284 |
mDialogInfo->menu.images) |
||
1285 |
{ |
||
1286 |
const NpcImageInfo *const info = *it; |
||
1287 |
Image *const image = Theme::getImageFromTheme(info->name); |
||
1288 |
if (image != nullptr) |
||
1289 |
{ |
||
1290 |
Icon *const icon = new Icon(this, image, AutoRelease_true); |
||
1291 |
icon->setPosition(info->x, info->y); |
||
1292 |
mSkinContainer->add(icon); |
||
1293 |
} |
||
1294 |
} |
||
1295 |
FOR_EACH (STD_VECTOR<NpcTextInfo*>::const_iterator, |
||
1296 |
it, |
||
1297 |
mDialogInfo->menu.texts) |
||
1298 |
{ |
||
1299 |
const NpcTextInfo *const info = *it; |
||
1300 |
BrowserBox *box = new BrowserBox(this, |
||
1301 |
Opaque_true, |
||
1302 |
"browserbox.xml"); |
||
1303 |
box->setOpaque(Opaque_false); |
||
1304 |
box->setMaxRow(config.getIntValue("ChatLogLength")); |
||
1305 |
box->setLinkHandler(mItemLinkHandler); |
||
1306 |
box->setProcessVars(true); |
||
1307 |
box->setFont(gui->getNpcFont()); |
||
1308 |
box->setEnableKeys(true); |
||
1309 |
box->setEnableTabs(true); |
||
1310 |
box->setPosition(info->x, info->y); |
||
1311 |
mSkinContainer->add(box); |
||
1312 |
box->setWidth(info->width); |
||
1313 |
box->setHeight(info->height); |
||
1314 |
StringVect parts; |
||
1315 |
splitToStringVector(parts, info->text, '\n'); |
||
1316 |
FOR_EACH (StringVectCIter, it2, parts) |
||
1317 |
{ |
||
1318 |
box->addRow(*it2, |
||
1319 |
false); |
||
1320 |
} |
||
1321 |
} |
||
1322 |
FOR_EACH (STD_VECTOR<NpcButtonInfo*>::const_iterator, |
||
1323 |
it, |
||
1324 |
mDialogInfo->menu.buttons) |
||
1325 |
{ |
||
1326 |
const NpcButtonInfo *const info = *it; |
||
1327 |
Button *const button = new Button(this, |
||
1328 |
BUTTON_SKIN); |
||
1329 |
button->setCaption(info->name); |
||
1330 |
button->setActionEventId("skin_" + info->value); |
||
1331 |
button->addActionListener(this); |
||
1332 |
button->setPosition(info->x, info->y); |
||
1333 |
if (!info->image.empty()) |
||
1334 |
{ |
||
1335 |
button->setImageWidth(info->imageWidth); |
||
1336 |
button->setImageHeight(info->imageHeight); |
||
1337 |
button->loadImageSet(info->image); |
||
1338 |
} |
||
1339 |
mSkinContainer->add(button); |
||
1340 |
button->adjustSize(); |
||
1341 |
} |
||
1342 |
} |
||
1343 |
|||
1344 |
void NpcDialog::restoreVirtuals() |
||
1345 |
{ |
||
1346 |
Inventory *const inventory = PlayerInfo::getInventory(); |
||
1347 |
if (inventory != nullptr) |
||
1348 |
inventory->restoreVirtuals(); |
||
1349 |
} |
||
1350 |
|||
1351 |
std::string NpcDialog::complexItemToStr(const ComplexItem *const item) |
||
1352 |
{ |
||
1353 |
std::string str; |
||
1354 |
if (item != nullptr) |
||
1355 |
{ |
||
1356 |
const STD_VECTOR<Item*> &items = item->getChilds(); |
||
1357 |
const size_t sz = items.size(); |
||
1358 |
if (sz == 0U) |
||
1359 |
return str; |
||
1360 |
|||
1361 |
const Item *item2 = items[0]; |
||
1362 |
|||
1363 |
str = strprintf("%d,%d", |
||
1364 |
item2->getInvIndex(), |
||
1365 |
item2->getQuantity()); |
||
1366 |
for (size_t f = 1; f < sz; f ++) |
||
1367 |
{ |
||
1368 |
str.append(";"); |
||
1369 |
item2 = items[f]; |
||
1370 |
str.append(strprintf("%d,%d", |
||
1371 |
item2->getInvIndex(), |
||
1372 |
item2->getQuantity())); |
||
1373 |
} |
||
1374 |
} |
||
1375 |
else |
||
1376 |
{ |
||
1377 |
str.clear(); |
||
1378 |
} |
||
1379 |
return str; |
||
1380 |
} |
||
1381 |
|||
1382 |
void NpcDialog::addCraftItem(Item *const item, |
||
1383 |
const int amount, |
||
1384 |
const int slot) |
||
1385 |
{ |
||
1386 |
if (mInputState != NpcInputState::ITEM_CRAFT) |
||
1387 |
return; |
||
1388 |
|||
1389 |
Inventory *const inventory = PlayerInfo::getInventory(); |
||
1390 |
|||
1391 |
if (inventory == nullptr) |
||
1392 |
return; |
||
1393 |
|||
1394 |
if (mComplexInventory->addVirtualItem( |
||
1395 |
item, |
||
1396 |
slot, |
||
1397 |
amount)) |
||
1398 |
{ |
||
1399 |
inventory->virtualRemove(item, amount); |
||
1400 |
} |
||
1401 |
✓✗✓✗ |
3 |
} |
Generated by: GCOVR (Version 3.3) |