GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/popups/popupmenu.cpp Lines: 21 1624 1.3 %
Date: 2019-08-19 Branches: 16 2129 0.8 %

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
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
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 General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "gui/popups/popupmenu.h"
24
25
#include "actormanager.h"
26
#include "configuration.h"
27
#include "party.h"
28
#include "settings.h"
29
30
#include "being/flooritem.h"
31
#include "being/localplayer.h"
32
#include "being/playerinfo.h"
33
#include "being/playerrelation.h"
34
#include "being/playerrelations.h"
35
36
#include "const/spells.h"
37
38
#include "enums/resources/map/mapitemtype.h"
39
40
#include "input/inputmanager.h"
41
42
#include "gui/buttontext.h"
43
#include "gui/gui.h"
44
#include "gui/popupmanager.h"
45
#include "gui/viewport.h"
46
#include "gui/windowmenu.h"
47
48
#include "gui/windows/chatwindow.h"
49
#include "gui/windows/inventorywindow.h"
50
#include "gui/windows/minimap.h"
51
#include "gui/windows/ministatuswindow.h"
52
#include "gui/windows/npcdialog.h"
53
#include "gui/windows/outfitwindow.h"
54
#include "gui/windows/socialwindow.h"
55
#include "gui/windows/textcommandeditor.h"
56
#include "gui/windows/textdialog.h"
57
#include "gui/windows/tradewindow.h"
58
59
#include "gui/widgets/button.h"
60
#include "gui/widgets/createwidget.h"
61
#include "gui/widgets/progressbar.h"
62
#include "gui/widgets/scrollarea.h"
63
#include "gui/widgets/staticbrowserbox.h"
64
#include "gui/widgets/textfield.h"
65
66
#include "gui/widgets/tabs/chat/whispertab.h"
67
68
#include "net/adminhandler.h"
69
#include "net/chathandler.h"
70
#include "net/guildhandler.h"
71
#include "net/npchandler.h"
72
#include "net/net.h"
73
74
#ifdef TMWA_SUPPORT
75
#include "net/tmwa/guildmanager.h"
76
#endif  // TMWA_SUPPORT
77
78
#include "resources/chatobject.h"
79
#include "resources/groupinfo.h"
80
#include "resources/iteminfo.h"
81
#include "resources/itemmenuitem.h"
82
83
#include "resources/db/groupdb.h"
84
#include "resources/db/npcdb.h"
85
86
#include "resources/item/item.h"
87
88
#include "resources/map/map.h"
89
#include "resources/map/mapitem.h"
90
#include "resources/map/speciallayer.h"
91
92
#include "resources/skill/skillinfo.h"
93
94
#include "utils/checkutils.h"
95
#include "utils/foreach.h"
96
#include "utils/gettext.h"
97
98
#include "debug.h"
99
100
1
std::string tradePartnerName;
101
102
PopupMenu *popupMenu = nullptr;
103
104
2
PopupMenu::PopupMenu() :
105
    Popup("PopupMenu", "popupmenu.xml"),
106
    mBrowserBox(new StaticBrowserBox(this, Opaque_true,
107

2
        "popupbrowserbox.xml")),
108
    mScrollArea(nullptr),
109
    mBeingId(BeingId_zero),
110
    mFloorItemId(BeingId_zero),
111
    mItemId(0),
112
    mItemIndex(-1),
113
    mItemColor(ItemColor_one),
114
    mMapItem(nullptr),
115
    mTab(nullptr),
116
    mSpell(nullptr),
117
    mCallerWindow(nullptr),
118
    mRenameListener(),
119
    mPlayerListener(),
120
    mDialog(nullptr),
121
    mButton(nullptr),
122
    mGroup(nullptr),
123
    mName(),
124
    mExtName(),
125
    mTextField(nullptr),
126
    mType(ActorType::Unknown),
127
    mSubType(BeingTypeId_zero),
128
    mX(0),
129
    mY(0),
130


28
    mAllowCleanMenu(true)
131
{
132
4
    mBrowserBox->setOpaque(Opaque_false);
133
2
    mBrowserBox->setLinkHandler(this);
134
2
    mRenameListener.setMapItem(nullptr);
135
4
    mRenameListener.setDialog(nullptr);
136
10
    mPlayerListener.setNick("");
137
4
    mPlayerListener.setDialog(nullptr);
138
4
    mPlayerListener.setType(ActorType::Unknown);
139
2
    mScrollArea = new ScrollArea(this,
140

4
        mBrowserBox, Opaque_false, std::string());
141
2
    mScrollArea->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO);
142
2
    addMouseListener(this);
143
2
}
144
145
2
void PopupMenu::postInit()
146
{
147
4
    Popup::postInit();
148
2
    add(mScrollArea);
149
2
}
150
151
void PopupMenu::initPopup()
152
{
153
    if (localPlayer == nullptr)
154
        return;
155
    const int groupId = localPlayer->getGroupId();
156
    mGroup = GroupDb::getGroup(groupId);
157
}
158
159
bool PopupMenu::isAllowCommand(const ServerCommandTypeT command)
160
{
161
    if (mGroup == nullptr)
162
        return false;
163
#ifdef TMWA_SUPPORT
164
    // allow any commands for legacy if group > 0
165
    if (Net::getNetworkType() == ServerType::TMWATHENA &&
166
        localPlayer != nullptr &&
167
        localPlayer->isGM())
168
    {
169
        return true;
170
    }
171
#endif
172
    if (mGroup->mPermissions[CAST_SIZE(ServerPermissionType::all_commands)] ==
173
        Enable_true)
174
    {
175
        return true;
176
    }
177
    const ServerCommandEnable::Type enabled =
178
        mGroup->mCommands[CAST_SIZE(command)];
179
    return (enabled & ServerCommandEnable::Self) != 0;
180
}
181
182
bool PopupMenu::isAllowOtherCommand(const ServerCommandTypeT command)
183
{
184
    if (mGroup == nullptr ||
185
        localPlayer == nullptr)
186
        return false;
187
#ifdef TMWA_SUPPORT
188
    // allow any commands for legacy if group > 0
189
    if (Net::getNetworkType() == ServerType::TMWATHENA &&
190
        localPlayer->isGM())
191
    {
192
        return true;
193
    }
194
#endif
195
    const ServerCommandEnable::Type enabled =
196
        mGroup->mCommands[CAST_SIZE(command)];
197
    if (mName == localPlayer->getName())
198
        return (enabled & ServerCommandEnable::Self) != 0;
199
    return (enabled & ServerCommandEnable::Other) != 0;
200
}
201
202
void PopupMenu::showPopup(const int x, const int y, const Being *const being)
203
{
204
    if (being == nullptr ||
205
        localPlayer == nullptr ||
206
        actorManager == nullptr)
207
    {
208
        return;
209
    }
210
211
    initPopup();
212
    mBeingId = being->getId();
213
    mName = being->getName();
214
    mExtName = being->getExtName();
215
    mType = being->getType();
216
    mSubType = being->getSubType();
217
    mBrowserBox->clearRows();
218
    mX = x;
219
    mY = y;
220
221
    const std::string &name = mName;
222
    if (being->getType() != ActorType::SkillUnit)
223
    {
224
        mBrowserBox->addRow(name + being->getGenderSignWithSpace(),
225
            false);
226
    }
227
228
    switch (being->getType())
229
    {
230
        case ActorType::Player:
231
        {
232
            // TRANSLATORS: popup menu item
233
            // TRANSLATORS: trade with player
234
            mBrowserBox->addRow("/trade 'NAME'", _("Trade"));
235
            // TRANSLATORS: popup menu item
236
            // TRANSLATORS: trade attack player
237
            mBrowserBox->addRow("/attack 'NAME'", _("Attack"));
238
            // TRANSLATORS: popup menu item
239
            // TRANSLATORS: send whisper to player
240
            mBrowserBox->addRow("/whispertext 'NAME'", _("Whisper"));
241
            addMailCommands();
242
            addGmCommands();
243
            mBrowserBox->addSeparator("##3---");
244
245
#ifdef TMWA_SUPPORT
246
            if (Net::getNetworkType() == ServerType::TMWATHENA)
247
            {
248
                // TRANSLATORS: popup menu item
249
                // TRANSLATORS: heal player
250
                mBrowserBox->addRow("/heal :'BEINGID'", _("Heal"));
251
                mBrowserBox->addSeparator("##3---");
252
            }
253
#endif  // TMWA_SUPPORT
254
255
            addPlayerRelation(name);
256
            mBrowserBox->addSeparator("##3---");
257
258
            addFollow();
259
            addPartyName(being->getPartyName());
260
261
            const Guild *const guild1 = being->getGuild();
262
            const Guild *const guild2 = localPlayer->getGuild();
263
            if (guild2 != nullptr)
264
            {
265
                if (guild1 != nullptr)
266
                {
267
                    if (guild1->getId() == guild2->getId())
268
                    {
269
                        mBrowserBox->addRow("/kickguild 'NAME'",
270
                            // TRANSLATORS: popup menu item
271
                            // TRANSLATORS: kick player from guild
272
                            _("Kick from guild"));
273
                        if (guild2->getServerGuild())
274
                        {
275
                            mBrowserBox->addRow(strprintf(
276
                                "@@guild-pos|%s >@@",
277
                                // TRANSLATORS: popup menu item
278
                                // TRANSLATORS: change player position in guild
279
                                _("Change pos in guild")),
280
                                false);
281
                        }
282
                    }
283
                }
284
                else if (guild2->getMember(mName) != nullptr)
285
                {
286
                    mBrowserBox->addRow("/kickguild 'NAME'",
287
                        // TRANSLATORS: popup menu item
288
                        // TRANSLATORS: kick player from guild
289
                        _("Kick from guild"));
290
                    if (guild2->getServerGuild())
291
                    {
292
                        mBrowserBox->addRow(strprintf(
293
                            "@@guild-pos|%s >@@",
294
                            // TRANSLATORS: popup menu item
295
                            // TRANSLATORS: change player position in guild
296
                            _("Change pos in guild")),
297
                            false);
298
                    }
299
                }
300
                else
301
                {
302
#ifdef TMWA_SUPPORT
303
                    if (guild2->getServerGuild() ||
304
                        (guildManager != nullptr && guildManager->havePower()))
305
#endif  // TMWA_SUPPORT
306
                    {
307
                        mBrowserBox->addRow("/guild 'NAME'",
308
                            // TRANSLATORS: popup menu item
309
                            // TRANSLATORS: invite player to guild
310
                            _("Invite to guild"));
311
                    }
312
                }
313
            }
314
315
            // TRANSLATORS: popup menu item
316
            // TRANSLATORS: set player invisible for self by id
317
            mBrowserBox->addRow("/nuke 'NAME'", _("Nuke"));
318
            // TRANSLATORS: popup menu item
319
            // TRANSLATORS: move to player location
320
            mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
321
            addPlayerMisc();
322
            addBuySell(being);
323
            addChat(being);
324
            break;
325
        }
326
327
        case ActorType::Npc:
328
            if (!addBeingMenu())
329
            {
330
                // TRANSLATORS: popup menu item
331
                // TRANSLATORS: talk with npc
332
                mBrowserBox->addRow("/talk :'BEINGID'", _("Talk"));
333
#ifdef TMWA_SUPPORT
334
                if (Net::getNetworkType() != ServerType::TMWATHENA)
335
#endif
336
                {
337
                    mBrowserBox->addRow("/whispertext NPC:'NAME'",
338
                        // TRANSLATORS: popup menu item
339
                        // TRANSLATORS: whisper to npc
340
                        _("Whisper"));
341
                }
342
                // TRANSLATORS: popup menu item
343
                // TRANSLATORS: buy from npc
344
                mBrowserBox->addRow("/buy 'NAME'", _("Buy"));
345
                // TRANSLATORS: popup menu item
346
                // TRANSLATORS: sell to npc
347
                mBrowserBox->addRow("/sell 'NAME'", _("Sell"));
348
            }
349
350
            addGmCommands();
351
            mBrowserBox->addSeparator("##3---");
352
            // TRANSLATORS: popup menu item
353
            // TRANSLATORS: move to npc location
354
            mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
355
            // TRANSLATORS: popup menu item
356
            // TRANSLATORS: add comment to npc
357
            mBrowserBox->addRow("addcomment", _("Add comment"));
358
            addChat(being);
359
            break;
360
361
        case ActorType::Monster:
362
        {
363
            // Monsters can be attacked
364
            // TRANSLATORS: popup menu item
365
            // TRANSLATORS: attack monster
366
            mBrowserBox->addRow("/attack :'BEINGID'", _("Attack"));
367
            addCatchPetCommands();
368
            addGmCommands();
369
            mBrowserBox->addSeparator("##3---");
370
371
            if (config.getBoolValue("enableAttackFilter"))
372
            {
373
                mBrowserBox->addSeparator("##3---");
374
                if (actorManager->isInAttackList(name)
375
                    || actorManager->isInIgnoreAttackList(name)
376
                    || actorManager->isInPriorityAttackList(name))
377
                {
378
                    mBrowserBox->addRow("/removeattack 'NAME'",
379
                        // TRANSLATORS: remove monster from attack list
380
                        // TRANSLATORS: popup menu item
381
                        _("Remove from attack list"));
382
                }
383
                else
384
                {
385
                    mBrowserBox->addRow("/addpriorityattack 'NAME'",
386
                        // TRANSLATORS: popup menu item
387
                        // TRANSLATORS: add monster to priotiry attack list
388
                        _("Add to priority attack list"));
389
                    mBrowserBox->addRow("/addattack 'NAME'",
390
                        // TRANSLATORS: popup menu item
391
                        // TRANSLATORS: add monster to attack list
392
                        _("Add to attack list"));
393
                    mBrowserBox->addRow("/addignoreattack 'NAME'",
394
                        // TRANSLATORS: popup menu item
395
                        // TRANSLATORS: add monster to ignore list
396
                        _("Add to ignore list"));
397
                }
398
            }
399
            break;
400
        }
401
402
        case ActorType::Mercenary:
403
            // TRANSLATORS: popup menu item
404
            // TRANSLATORS: Mercenary move to master
405
            mBrowserBox->addRow("/mercenarytomaster", _("Move to master"));
406
            addGmCommands();
407
            mBrowserBox->addSeparator("##3---");
408
            // TRANSLATORS: popup menu item
409
            // TRANSLATORS: fire mercenary
410
            mBrowserBox->addRow("/firemercenary", _("Fire"));
411
            mBrowserBox->addSeparator("##3---");
412
            break;
413
414
        case ActorType::Homunculus:
415
        {
416
            const HomunculusInfo *const info = PlayerInfo::getHomunculus();
417
            if (info != nullptr)
418
            {
419
                mBrowserBox->addRow("/homunculustomaster",
420
                    // TRANSLATORS: popup menu item
421
                    // TRANSLATORS: homunculus move to master
422
                    _("Move to master"));
423
                // TRANSLATORS: popup menu item
424
                // TRANSLATORS: feed homunculus
425
                mBrowserBox->addRow("/homunculusfeed", _("Feed"));
426
                mBrowserBox->addSeparator("##3---");
427
                // TRANSLATORS: popup menu item
428
                // TRANSLATORS: pet rename item
429
                mBrowserBox->addRow("/sethomunname", _("Rename"));
430
                mBrowserBox->addSeparator("##3---");
431
                // TRANSLATORS: popup menu item
432
                // TRANSLATORS: delete homunculus
433
                mBrowserBox->addRow("/homunculusfire", _("Kill"));
434
                mBrowserBox->addSeparator("##3---");
435
            }
436
            addGmCommands();
437
            break;
438
        }
439
        case ActorType::Pet:
440
            if (being->getOwner() == localPlayer)
441
            {
442
                // TRANSLATORS: popup menu item
443
                // TRANSLATORS: feed pet
444
                mBrowserBox->addRow("/petfeed", _("Feed"));
445
                // TRANSLATORS: popup menu item
446
                // TRANSLATORS: pet drop loot
447
                mBrowserBox->addRow("/petdroploot", _("Drop loot"));
448
                // TRANSLATORS: popup menu item
449
                // TRANSLATORS: pet unequip item
450
                mBrowserBox->addRow("/petunequip", _("Unequip"));
451
                addGmCommands();
452
                mBrowserBox->addSeparator("##3---");
453
                // TRANSLATORS: popup menu item
454
                // TRANSLATORS: pet rename item
455
                mBrowserBox->addRow("/setpetname", _("Rename"));
456
                mBrowserBox->addSeparator("##3---");
457
                const BeingInfo *const info = being->getInfo();
458
                std::string msg;
459
                if (info != nullptr)
460
                    msg = info->getString(0);
461
                if (!msg.empty())
462
                {
463
                    mBrowserBox->addRow("/petreturnegg", msg.c_str());
464
                }
465
                else
466
                {
467
                    mBrowserBox->addRow("/petreturnegg",
468
                        // TRANSLATORS: popup menu item
469
                        // TRANSLATORS: pet return to egg
470
                        _("Return to egg"));
471
                }
472
                mBrowserBox->addSeparator("##3---");
473
            }
474
            else
475
            {
476
                addCatchPetCommands();
477
            }
478
            break;
479
        case ActorType::SkillUnit:
480
        {
481
            const BeingId id = being->getCreatorId();
482
            std::string creatorName;
483
            Being *const creator = actorManager->findBeing(id);
484
            if (creator != nullptr)
485
                creatorName = creator->getName();
486
            else
487
                creatorName = actorManager->getSeenPlayerById(id);
488
489
            if (creatorName.empty())
490
                creatorName = strprintf("?%d", CAST_S32(id));
491
492
            mBrowserBox->addRow(strprintf("%s, %d (%s)",
493
                name.c_str(),
494
                CAST_S32(being->getSubType()),
495
                creatorName.c_str()),
496
                false);
497
            break;
498
        }
499
        case ActorType::Avatar:
500
        case ActorType::Unknown:
501
        case ActorType::FloorItem:
502
        case ActorType::Portal:
503
        case ActorType::Elemental:
504
        default:
505
            break;
506
    }
507
    // TRANSLATORS: popup menu item
508
    // TRANSLATORS: add being name to chat
509
    mBrowserBox->addRow("/addtext 'NAME'", _("Add name to chat"));
510
    mBrowserBox->addSeparator("##3---");
511
512
    // TRANSLATORS: popup menu item
513
    // TRANSLATORS: close menu
514
    mBrowserBox->addRow("cancel", _("Cancel"));
515
516
    showPopup(x, y);
517
}
518
519
bool PopupMenu::addBeingMenu()
520
{
521
    Being *being = actorManager->findBeing(mBeingId);
522
    if (being == nullptr)
523
        return false;
524
525
    BeingInfo *const info = NPCDB::get(fromInt(
526
        being->getSubType(), BeingTypeId));
527
    if (info == nullptr)
528
        return false;
529
530
    const STD_VECTOR<BeingMenuItem> &menu = info->getMenu();
531
    FOR_EACH (STD_VECTOR<BeingMenuItem>::const_iterator, it, menu)
532
    {
533
        const BeingMenuItem &item = *it;
534
        mBrowserBox->addRow("/" + item.command, item.name.c_str());
535
    }
536
    return true;
537
}
538
539
void PopupMenu::setMousePos()
540
{
541
    if (viewport != nullptr)
542
    {
543
        mX = viewport->mMouseX;
544
        mY = viewport->mMouseY;
545
    }
546
    else
547
    {
548
        Gui::getMouseState(mX, mY);
549
    }
550
}
551
552
void PopupMenu::setMousePos2()
553
{
554
    if (mX == 0 && mY == 0)
555
    {
556
        if (viewport != nullptr)
557
        {
558
            mX = viewport->mMouseX;
559
            mY = viewport->mMouseY;
560
        }
561
        else
562
        {
563
            Gui::getMouseState(mX, mY);
564
        }
565
    }
566
}
567
568
void PopupMenu::showPopup(const int x, const int y,
569
                          const STD_VECTOR<ActorSprite*> &beings)
570
{
571
    initPopup();
572
    mX = x;
573
    mY = y;
574
    mBrowserBox->clearRows();
575
    // TRANSLATORS: popup menu header
576
    mBrowserBox->addRow(_("Players"), false);
577
    FOR_EACH (STD_VECTOR<ActorSprite*>::const_iterator, it, beings)
578
    {
579
        const Being *const being = dynamic_cast<const Being*>(*it);
580
        const ActorSprite *const actor = *it;
581
        if ((being != nullptr) && !being->getName().empty())
582
        {
583
            mBrowserBox->addRow(strprintf("@@player_%u|%s >@@",
584
                CAST_U32(being->getId()), (being->getName()
585
                + being->getGenderSignWithSpace()).c_str()),
586
                false);
587
        }
588
        else if (actor->getType() == ActorType::FloorItem)
589
        {
590
            const FloorItem *const floorItem
591
                = static_cast<const FloorItem*>(actor);
592
            mBrowserBox->addRow(strprintf("@@flooritem_%u|%s >@@",
593
                CAST_U32(actor->getId()),
594
                floorItem->getName().c_str()),
595
                false);
596
        }
597
    }
598
    mBrowserBox->addSeparator("##3---");
599
    // TRANSLATORS: popup menu item
600
    // TRANSLATORS: close menu
601
    mBrowserBox->addRow("cancel", _("Cancel"));
602
    showPopup(x, y);
603
}
604
605
void PopupMenu::showPlayerPopup(const std::string &nick)
606
{
607
    if (nick.empty() || (localPlayer == nullptr))
608
        return;
609
610
    initPopup();
611
    setMousePos();
612
    mName = nick;
613
    mExtName = nick;
614
    mBeingId = BeingId_zero;
615
    mType = ActorType::Player;
616
    mSubType = BeingTypeId_zero;
617
    mBrowserBox->clearRows();
618
619
    const std::string &name = mName;
620
621
    mBrowserBox->addRow(name, false);
622
623
    // TRANSLATORS: popup menu item
624
    // TRANSLATORS: send whisper to player
625
    mBrowserBox->addRow("/whispertext 'NAME'", _("Whisper"));
626
    addMailCommands();
627
    addGmCommands();
628
    mBrowserBox->addSeparator("##3---");
629
630
    addPlayerRelation(name);
631
    mBrowserBox->addSeparator("##3---");
632
633
    addFollow();
634
    // TRANSLATORS: popup menu item
635
    // TRANSLATORS: add comment to player
636
    mBrowserBox->addRow("addcomment", _("Add comment"));
637
638
    if (localPlayer->isInParty())
639
    {
640
        const Party *const party = localPlayer->getParty();
641
        if (party != nullptr)
642
        {
643
            const PartyMember *const member = party->getMember(mName);
644
            if (member != nullptr)
645
            {
646
                // TRANSLATORS: popup menu item
647
                // TRANSLATORS: kick player from party
648
                mBrowserBox->addRow("/kickparty 'NAME'", _("Kick from party"));
649
                mBrowserBox->addSeparator("##3---");
650
                const PartyMember *const o = party->getMember(
651
                    localPlayer->getName());
652
                showAdoptCommands();
653
                if ((o != nullptr) && member->getMap() == o->getMap())
654
                {
655
                    // TRANSLATORS: popup menu item
656
                    // TRANSLATORS: move to player position
657
                    mBrowserBox->addRow("/navigate 'X' 'Y'", _("Move"));
658
                }
659
            }
660
        }
661
    }
662
663
    const Guild *const guild2 = localPlayer->getGuild();
664
    if (guild2 != nullptr)
665
    {
666
        if (guild2->getMember(mName) != nullptr)
667
        {
668
#ifdef TMWA_SUPPORT
669
            if (guild2->getServerGuild() || (guildManager != nullptr
670
                && guildManager->havePower()))
671
#endif  // TMWA_SUPPORT
672
            {
673
                mBrowserBox->addRow("/kickguild 'NAME'",
674
                    // TRANSLATORS: popup menu item
675
                    // TRANSLATORS: kick player from guild
676
                    _("Kick from guild"));
677
            }
678
            if (guild2->getServerGuild())
679
            {
680
                mBrowserBox->addRow(strprintf(
681
                    // TRANSLATORS: popup menu item
682
                    // TRANSLATORS: change player position in guild
683
                    "@@guild-pos|%s >@@", _("Change pos in guild")),
684
                    false);
685
            }
686
        }
687
        else
688
        {
689
#ifdef TMWA_SUPPORT
690
            if (guild2->getServerGuild() || (guildManager != nullptr
691
                && guildManager->havePower()))
692
#endif  // TMWA_SUPPORT
693
            {
694
                // TRANSLATORS: popup menu item
695
                // TRANSLATORS: invite player to guild
696
                mBrowserBox->addRow("/guild 'NAME'", _("Invite to guild"));
697
            }
698
        }
699
    }
700
701
    addBuySellDefault();
702
    // TRANSLATORS: popup menu item
703
    // TRANSLATORS: add player name to chat
704
    mBrowserBox->addRow("/addtext 'NAME'", _("Add name to chat"));
705
    mBrowserBox->addSeparator("##3---");
706
    // TRANSLATORS: popup menu item
707
    // TRANSLATORS: close menu
708
    mBrowserBox->addRow("cancel", _("Cancel"));
709
710
    showPopup(mX, mY);
711
}
712
713
void PopupMenu::showPopup(const int x, const int y,
714
                          const FloorItem *const floorItem)
715
{
716
    if (floorItem == nullptr)
717
        return;
718
719
    initPopup();
720
    mX = x;
721
    mY = y;
722
    mFloorItemId = floorItem->getId();
723
    mItemId = floorItem->getItemId();
724
    mType = ActorType::FloorItem;
725
    mSubType = BeingTypeId_zero;
726
    for (int f = 0; f < maxCards; f ++)
727
        mItemCards[f] = floorItem->getCard(f);
728
    mBrowserBox->clearRows();
729
    const std::string name = floorItem->getName();
730
    mName = name;
731
    mExtName = name;
732
733
    mBrowserBox->addRow(name, false);
734
735
    if (config.getBoolValue("enablePickupFilter"))
736
    {
737
        if (actorManager->isInPickupList(name)
738
            || (actorManager->isInPickupList("")
739
            && !actorManager->isInIgnorePickupList(name)))
740
        {
741
            // TRANSLATORS: popup menu item
742
            // TRANSLATORS: pickup item from ground
743
            mBrowserBox->addRow("/pickup 'FLOORID'", _("Pick up"));
744
            mBrowserBox->addSeparator("##3---");
745
        }
746
        addPickupFilter(name);
747
    }
748
    else
749
    {
750
        // TRANSLATORS: popup menu item
751
        // TRANSLATORS: pickup item from ground
752
        mBrowserBox->addRow("/pickup 'FLOORID'", _("Pick up"));
753
    }
754
    addProtection();
755
    // TRANSLATORS: popup menu item
756
    // TRANSLATORS: add item name to chat
757
    mBrowserBox->addRow("/addchat 'FLOORID''CARDS'", _("Add to chat"));
758
    mBrowserBox->addSeparator("##3---");
759
    addGmCommands();
760
761
    // TRANSLATORS: popup menu item
762
    // TRANSLATORS: close menu
763
    mBrowserBox->addRow("cancel", _("Cancel"));
764
765
    showPopup(mX, mY);
766
}
767
768
void PopupMenu::showPopup(const int x, const int y, MapItem *const mapItem)
769
{
770
    if (mapItem == nullptr)
771
        return;
772
773
    initPopup();
774
    mMapItem = mapItem;
775
    mX = x;
776
    mY = y;
777
778
    mBrowserBox->clearRows();
779
780
    // TRANSLATORS: popup menu header
781
    mBrowserBox->addRow(_("Map Item"), false);
782
    // TRANSLATORS: popup menu item
783
    // TRANSLATORS: rename map item
784
    mBrowserBox->addRow("rename map", _("Rename"));
785
    // TRANSLATORS: popup menu item
786
    // TRANSLATORS: remove map item
787
    mBrowserBox->addRow("remove map", _("Remove"));
788
789
    if (isAllowCommand(ServerCommandType::slide))
790
    {
791
        mBrowserBox->addSeparator("##3---");
792
        // TRANSLATORS: popup menu item
793
        // TRANSLATORS: warp to map item
794
        mBrowserBox->addRow("/slide 'MAPX' 'MAPY'", _("Warp"));
795
    }
796
    mBrowserBox->addSeparator("##3---");
797
    // TRANSLATORS: popup menu item
798
    // TRANSLATORS: close menu
799
    mBrowserBox->addRow("cancel", _("Cancel"));
800
801
    showPopup(x, y);
802
}
803
804
void PopupMenu::showMapPopup(const int x, const int y,
805
                             const int x2, const int y2,
806
                             const bool isMinimap)
807
{
808
    initPopup();
809
    mX = x2;
810
    mY = y2;
811
812
    if (isMinimap)
813
        mCallerWindow = minimap;
814
815
    mBrowserBox->clearRows();
816
817
    // TRANSLATORS: popup menu header
818
    mBrowserBox->addRow(_("Map Item"), false);
819
820
    if (isAllowCommand(ServerCommandType::slide))
821
    {
822
        // TRANSLATORS: popup menu item
823
        // TRANSLATORS: warp to map item
824
        mBrowserBox->addRow("/slide 'MAPX' 'MAPY'", _("Warp"));
825
    }
826
    // TRANSLATORS: popup menu item
827
    // TRANSLATORS: move to map item
828
    mBrowserBox->addRow("/navigate 'X' 'Y'", _("Move"));
829
    // TRANSLATORS: popup menu item
830
    // TRANSLATORS: move camera to map item
831
    mBrowserBox->addRow("/movecamera 'X' 'Y'", _("Move camera"));
832
    if (settings.cameraMode != 0)
833
    {
834
        // TRANSLATORS: popup menu item
835
        // TRANSLATORS: restore camera to default view
836
        mBrowserBox->addRow("/restorecamera", _("Restore camera"));
837
    }
838
    mBrowserBox->addSeparator("##3---");
839
    if (isMinimap)
840
    {
841
        // TRANSLATORS: popup menu item
842
        mBrowserBox->addRow("window close", _("Close"));
843
    }
844
    mBrowserBox->addSeparator("##3---");
845
    // TRANSLATORS: popup menu item
846
    // TRANSLATORS: close menu
847
    mBrowserBox->addRow("cancel", _("Cancel"));
848
849
    showPopup(x, y);
850
}
851
852
void PopupMenu::showOutfitsWindowPopup(const int x, const int y)
853
{
854
    initPopup();
855
    mX = x;
856
    mY = y;
857
    mCallerWindow = outfitWindow;
858
859
    mBrowserBox->clearRows();
860
861
    // TRANSLATORS: popup menu header
862
    mBrowserBox->addRow(_("Outfits"), false);
863
    // TRANSLATORS: popup menu item
864
    // TRANSLATORS: copy selected outfit to chat input
865
    mBrowserBox->addRow("/outfittochat", _("Add to chat"));
866
    mBrowserBox->addSeparator("##3---");
867
    // TRANSLATORS: popup menu item
868
    // TRANSLATORS: copy equipment from player to outfit
869
    mBrowserBox->addRow("/itemstooutfit", _("Copy from player"));
870
    mBrowserBox->addSeparator("##3---");
871
    // TRANSLATORS: popup menu item
872
    // TRANSLATORS: clear selected outfit
873
    mBrowserBox->addRow("/clearoutfit", _("Clear outfit"));
874
    mBrowserBox->addSeparator("##3---");
875
876
    addWindowMenu(outfitWindow);
877
    mBrowserBox->addSeparator("##3---");
878
879
    // TRANSLATORS: popup menu item
880
    // TRANSLATORS: close menu
881
    mBrowserBox->addRow("cancel", _("Cancel"));
882
883
    showPopup(x, y);
884
}
885
886
void PopupMenu::showSpellPopup(const int x, const int y,
887
                               TextCommand *const cmd)
888
{
889
    if (cmd == nullptr)
890
        return;
891
892
    initPopup();
893
    mBrowserBox->clearRows();
894
895
    mSpell = cmd;
896
    mX = x;
897
    mY = y;
898
899
    // TRANSLATORS: popup menu header
900
    mBrowserBox->addRow(_("Spells"), false);
901
    // TRANSLATORS: popup menu item
902
    // TRANSLATORS: edit selected spell
903
    mBrowserBox->addRow("edit spell", _("Edit spell"));
904
    mBrowserBox->addSeparator("##3---");
905
    // TRANSLATORS: popup menu item
906
    // TRANSLATORS: close menu
907
    mBrowserBox->addRow("cancel", _("Cancel"));
908
909
    showPopup(x, y);
910
}
911
912
void PopupMenu::showChatPopup(const int x, const int y, ChatTab *const tab)
913
{
914
    if (tab == nullptr ||
915
        actorManager == nullptr ||
916
        localPlayer == nullptr)
917
    {
918
        return;
919
    }
920
921
    initPopup();
922
    mTab = tab;
923
    mX = x;
924
    mY = y;
925
    mCallerWindow = chatWindow;
926
927
    mBrowserBox->clearRows();
928
929
    const ChatTabTypeT &type = tab->getType();
930
    if (type == ChatTabType::WHISPER || type == ChatTabType::CHANNEL)
931
    {
932
        // TRANSLATORS: popup menu item
933
        // TRANSLATORS: close chat tab
934
        mBrowserBox->addRow("/close", _("Close"));
935
    }
936
937
    // TRANSLATORS: popup menu item
938
    // TRANSLATORS: remove all text from chat tab
939
    mBrowserBox->addRow("/chatclear", _("Clear"));
940
    mBrowserBox->addSeparator("##3---");
941
942
    if (tab->getAllowHighlight())
943
    {
944
        // TRANSLATORS: popup menu item
945
        // TRANSLATORS: disable chat tab highlight
946
        mBrowserBox->addRow("/disablehighlight", _("Disable highlight"));
947
    }
948
    else
949
    {
950
        // TRANSLATORS: popup menu item
951
        // TRANSLATORS: enable chat tab highlight
952
        mBrowserBox->addRow("/enablehighlight", _("Enable highlight"));
953
    }
954
    if (tab->getRemoveNames())
955
    {
956
        // TRANSLATORS: popup menu item
957
        // TRANSLATORS: do not remove player names from chat tab
958
        mBrowserBox->addRow("/dontremovename", _("Don't remove name"));
959
    }
960
    else
961
    {
962
        // TRANSLATORS: popup menu item
963
        // TRANSLATORS: remove player names from chat tab
964
        mBrowserBox->addRow("/removename", _("Remove name"));
965
    }
966
    if (tab->getNoAway())
967
    {
968
        // TRANSLATORS: popup menu item
969
        // TRANSLATORS: enable away messages in chat tab
970
        mBrowserBox->addRow("/enableaway", _("Enable away"));
971
    }
972
    else
973
    {
974
        // TRANSLATORS: popup menu item
975
        // TRANSLATORS: disable away messages in chat tab
976
        mBrowserBox->addRow("/disableaway", _("Disable away"));
977
    }
978
    mBrowserBox->addSeparator("##3---");
979
    if (type == ChatTabType::PARTY)
980
    {
981
        // TRANSLATORS: popup menu item
982
        // TRANSLATORS: enable away messages in chat tab
983
        mBrowserBox->addRow("/leaveparty", _("Leave"));
984
        mBrowserBox->addSeparator("##3---");
985
    }
986
    // TRANSLATORS: popup menu item
987
    // TRANSLATORS: copy selected text to clipboard
988
    mBrowserBox->addRow("/chatclipboard 'X' 'Y'", _("Copy to clipboard"));
989
    mBrowserBox->addSeparator("##3---");
990
991
    if (type == ChatTabType::WHISPER)
992
    {
993
        const WhisperTab *const wTab = static_cast<WhisperTab*>(tab);
994
        const std::string &name = wTab->getNick();
995
996
        const Being* const being  = actorManager->findBeingByName(
997
            name, ActorType::Player);
998
999
        addGmCommands();
1000
        if (being != nullptr)
1001
        {
1002
            mBeingId = being->getId();
1003
            mName = being->getName();
1004
            mExtName = being->getExtName();
1005
            mType = being->getType();
1006
            mSubType = being->getSubType();
1007
1008
            // TRANSLATORS: popup menu item
1009
            // TRANSLATORS: trade with player
1010
            mBrowserBox->addRow("/trade 'NAME'", _("Trade"));
1011
            // TRANSLATORS: popup menu item
1012
            // TRANSLATORS: attack player
1013
            mBrowserBox->addRow("/attack 'NAME'", _("Attack"));
1014
            addMailCommands();
1015
            mBrowserBox->addSeparator("##3---");
1016
            // TRANSLATORS: popup menu item
1017
            // TRANSLATORS: heal player
1018
            mBrowserBox->addRow("/heal :'BEINGID'", _("Heal"));
1019
            mBrowserBox->addSeparator("##3---");
1020
            addPlayerRelation(name);
1021
            mBrowserBox->addSeparator("##3---");
1022
            addFollow();
1023
            // TRANSLATORS: popup menu item
1024
            // TRANSLATORS: move to player position
1025
            mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
1026
            addPlayerMisc();
1027
            addBuySell(being);
1028
            mBrowserBox->addSeparator("##3---");
1029
            addParty(wTab->getNick());
1030
            const Guild *const guild1 = being->getGuild();
1031
            const Guild *const guild2 = localPlayer->getGuild();
1032
            if (guild2 != nullptr)
1033
            {
1034
                if (guild1 != nullptr)
1035
                {
1036
                    if (guild1->getId() == guild2->getId())
1037
                    {
1038
#ifdef TMWA_SUPPORT
1039
                        if (guild2->getServerGuild() ||
1040
                            (guildManager != nullptr &&
1041
                            guildManager->havePower()))
1042
#endif  // TMWA_SUPPORT
1043
                        {
1044
                            mBrowserBox->addRow("/kickguild 'NAME'",
1045
                                // TRANSLATORS: popup menu item
1046
                                // TRANSLATORS: kick player from guild
1047
                                _("Kick from guild"));
1048
                        }
1049
                        if (guild2->getServerGuild())
1050
                        {
1051
                            mBrowserBox->addRow(strprintf("@@guild-pos|%s >@@",
1052
                                // TRANSLATORS: popup menu item
1053
                                // TRANSLATORS: change player position in guild
1054
                                 _("Change pos in guild")),
1055
                                false);
1056
                        }
1057
                    }
1058
                }
1059
                else
1060
                {
1061
#ifdef TMWA_SUPPORT
1062
                    if (guild2->getServerGuild() || (guildManager != nullptr
1063
                        && guildManager->havePower()))
1064
#endif  // TMWA_SUPPORT
1065
                    {
1066
                        mBrowserBox->addRow("/guild 'NAME'",
1067
                            // TRANSLATORS: popup menu item
1068
                            // TRANSLATORS: invite player to guild
1069
                            _("Invite to guild"));
1070
                    }
1071
                }
1072
            }
1073
        }
1074
        else
1075
        {
1076
            mBeingId = BeingId_zero;
1077
            mName = name;
1078
            mExtName = name;
1079
            mType = ActorType::Player;
1080
            mSubType = BeingTypeId_zero;
1081
            addPlayerRelation(name);
1082
            mBrowserBox->addSeparator("##3---");
1083
            addMailCommands();
1084
            addFollow();
1085
1086
            if (localPlayer->isInParty())
1087
            {
1088
                const Party *const party = localPlayer->getParty();
1089
                if (party != nullptr)
1090
                {
1091
                    const PartyMember *const m = party->getMember(mName);
1092
                    if (m != nullptr)
1093
                    {
1094
                        // TRANSLATORS: popup menu item
1095
                        // TRANSLATORS: move to player location
1096
                        mBrowserBox->addRow("/navigateto 'NAME'", _("Move"));
1097
                    }
1098
                }
1099
            }
1100
            addPlayerMisc();
1101
            addBuySellDefault();
1102
            if (Net::getNetworkType() != ServerType::TMWATHENA)
1103
                addParty(wTab->getNick());
1104
            mBrowserBox->addSeparator("##3---");
1105
        }
1106
    }
1107
1108
    addWindowMenu(chatWindow);
1109
    // TRANSLATORS: popup menu item
1110
    // TRANSLATORS: close menu
1111
    mBrowserBox->addRow("cancel", _("Cancel"));
1112
1113
    showPopup(x, y);
1114
}
1115
1116
void PopupMenu::showChangePos(const int x, const int y)
1117
{
1118
    initPopup();
1119
    mBrowserBox->clearRows();
1120
    // TRANSLATORS: popup menu header
1121
    mBrowserBox->addRow(_("Change guild position"), false);
1122
1123
    if (localPlayer == nullptr)
1124
        return;
1125
1126
    mX = x;
1127
    mY = y;
1128
    const Guild *const guild = localPlayer->getGuild();
1129
    if (guild != nullptr)
1130
    {
1131
        const PositionsMap &map = guild->getPositions();
1132
        FOR_EACH (PositionsMap::const_iterator, itr, map)
1133
        {
1134
            mBrowserBox->addRow(strprintf("@@guild-pos-%u|%[email protected]@",
1135
                itr->first, itr->second.c_str()),
1136
                false);
1137
        }
1138
        // TRANSLATORS: popup menu item
1139
        // TRANSLATORS: close menu
1140
        mBrowserBox->addRow("cancel", _("Cancel"));
1141
1142
        showPopup(x, y);
1143
    }
1144
    else
1145
    {
1146
        mBeingId = BeingId_zero;
1147
        mFloorItemId = BeingId_zero;
1148
        mItemIndex = -1;
1149
        mItemId = 0;
1150
        for (int f = 0; f < maxCards; f ++)
1151
            mItemCards[f] = 0;
1152
        mMapItem = nullptr;
1153
        mName.clear();
1154
        mExtName.clear();
1155
        mType = ActorType::Unknown;
1156
        mSubType = BeingTypeId_zero;
1157
        mX = 0;
1158
        mY = 0;
1159
        setVisible(Visible_false);
1160
    }
1161
}
1162
1163
void PopupMenu::showWindowPopup(Window *const window)
1164
{
1165
    if (window == nullptr)
1166
        return;
1167
1168
    initPopup();
1169
    setMousePos();
1170
    mCallerWindow = window;
1171
    mBrowserBox->clearRows();
1172
    // TRANSLATORS: popup menu header
1173
    mBrowserBox->addRow(_("window"), false);
1174
1175
    addWindowMenu(window);
1176
1177
    // TRANSLATORS: popup menu item
1178
    // TRANSLATORS: close menu
1179
    mBrowserBox->addRow("cancel", _("Cancel"));
1180
1181
    showPopup(mX, mY);
1182
}
1183
1184
void PopupMenu::addWindowMenu(const Window *const window)
1185
{
1186
    if (window == nullptr)
1187
        return;
1188
1189
    initPopup();
1190
    if (window->getAlowClose())
1191
    {
1192
        // TRANSLATORS: popup menu item
1193
        // TRANSLATORS: close window
1194
        mBrowserBox->addRow("window close", _("Close"));
1195
    }
1196
1197
    if (window->isStickyButtonLock())
1198
    {
1199
        if (window->isSticky())
1200
        {
1201
            // TRANSLATORS: popup menu item
1202
            // TRANSLATORS: unlock window
1203
            mBrowserBox->addRow("window unlock", _("Unlock"));
1204
        }
1205
        else
1206
        {
1207
            // TRANSLATORS: popup menu item
1208
            // TRANSLATORS: lock window
1209
            mBrowserBox->addRow("window lock", _("Lock"));
1210
        }
1211
    }
1212
}
1213
1214
void PopupMenu::showEmoteType()
1215
{
1216
    initPopup();
1217
    setMousePos();
1218
1219
    mBrowserBox->clearRows();
1220
    // TRANSLATORS: popup menu header
1221
    mBrowserBox->addRow(_("Show emotes for:"), false);
1222
1223
    // TRANSLATORS: popup menu item
1224
    // TRANSLATORS: show emotes for player
1225
    mBrowserBox->addRow("/setemotetype player", _("Player"));
1226
1227
    // TRANSLATORS: popup menu item
1228
    // TRANSLATORS: show emotes for pet
1229
    mBrowserBox->addRow("/setemotetype pet", _("Pet"));
1230
1231
    if (Net::getNetworkType() == ServerType::EVOL2)
1232
    {
1233
        // TRANSLATORS: popup menu item
1234
        // TRANSLATORS: show emotes for homuncules
1235
        mBrowserBox->addRow("/setemotetype homun", _("Homunculus"));
1236
1237
        // TRANSLATORS: popup menu item
1238
        // TRANSLATORS: show emotes for mercenary
1239
        mBrowserBox->addRow("/setemotetype merc", _("Mercenary"));
1240
    }
1241
    mBrowserBox->addSeparator("##3---");
1242
1243
    // TRANSLATORS: popup menu item
1244
    // TRANSLATORS: close menu
1245
    mBrowserBox->addRow("cancel", _("Cancel"));
1246
1247
    showPopup(mX, mY);
1248
}
1249
1250
void PopupMenu::handleLink(const std::string &link,
1251
                           MouseEvent *event A_UNUSED)
1252
{
1253
    Being *being = nullptr;
1254
    if (actorManager != nullptr)
1255
        being = actorManager->findBeing(mBeingId);
1256
1257
    mAllowCleanMenu = true;
1258
1259
    if (link == "remove map" && (mMapItem != nullptr))
1260
    {
1261
        if (viewport != nullptr)
1262
        {
1263
            const Map *const map = viewport->getMap();
1264
            if (map != nullptr)
1265
            {
1266
                SpecialLayer *const specialLayer = map->getSpecialLayer();
1267
                if (specialLayer != nullptr)
1268
                {
1269
                    const bool isHome = (mMapItem->getType()
1270
                        == CAST_S32(MapItemType::HOME));
1271
                    const int x = static_cast<int>(mMapItem->getX());
1272
                    const int y = static_cast<int>(mMapItem->getY());
1273
                    specialLayer->setTile(x, y,
1274
                        CAST_S32(MapItemType::EMPTY));
1275
                    specialLayer->updateCache();
1276
                    if (socialWindow != nullptr)
1277
                        socialWindow->removePortal(x, y);
1278
                    if (isHome && (localPlayer != nullptr))
1279
                    {
1280
                        localPlayer->removeHome();
1281
                        localPlayer->saveHomes();
1282
                    }
1283
                }
1284
            }
1285
        }
1286
    }
1287
    else if (link == "rename map" && (mMapItem != nullptr))
1288
    {
1289
        mRenameListener.setMapItem(mMapItem);
1290
        CREATEWIDGETV(mDialog, TextDialog,
1291
            // TRANSLATORS: dialog caption
1292
            // TRANSLATORS: number of chars in string should be near original
1293
            _("Rename map sign          "),
1294
            // TRANSLATORS: label
1295
            // TRANSLATORS: number of chars in string should be near original
1296
            _("Name:                    "),
1297
            nullptr,
1298
            false);
1299
        mRenameListener.setDialog(mDialog);
1300
        mDialog->setText(mMapItem->getComment());
1301
        mDialog->setActionEventId("ok");
1302
        mDialog->addActionListener(&mRenameListener);
1303
    }
1304
    else if (link == "edit spell" && (mSpell != nullptr))
1305
    {
1306
        CREATEWIDGET(TextCommandEditor, mSpell);
1307
    }
1308
    else if (link == "addcomment" && !mName.empty())
1309
    {
1310
        TextDialog *const dialog = CREATEWIDGETR(TextDialog,
1311
            // TRANSLATORS: dialog caption
1312
            // TRANSLATORS: number of chars in string should be near original
1313
            _("Player comment            "),
1314
            // TRANSLATORS: label
1315
            // TRANSLATORS: number of chars in string should be near original
1316
            _("Comment:                      "),
1317
            nullptr,
1318
            false);
1319
        mPlayerListener.setDialog(dialog);
1320
        mPlayerListener.setNick(mName);
1321
        mPlayerListener.setType(mType);
1322
1323
        if (being != nullptr)
1324
        {
1325
            being->updateComment();
1326
            dialog->setText(being->getComment());
1327
        }
1328
        else
1329
        {
1330
            dialog->setText(Being::loadComment(mName,
1331
                static_cast<ActorTypeT>(mType)));
1332
        }
1333
        dialog->setActionEventId("ok");
1334
        dialog->addActionListener(&mPlayerListener);
1335
    }
1336
    else if (link == "guild-pos" && !mName.empty())
1337
    {
1338
        showChangePos(getX(), getY());
1339
        return;
1340
    }
1341
    else if (link == "clipboard copy")
1342
    {
1343
        if (mTextField != nullptr)
1344
            mTextField->handleCopy();
1345
    }
1346
    else if (link == "clipboard paste")
1347
    {
1348
        if (mTextField != nullptr)
1349
            mTextField->handlePaste();
1350
    }
1351
    else if (link == "gm" && !mName.empty())
1352
    {
1353
        showGMPopup(mName);
1354
        return;
1355
    }
1356
    else if (link == "mute" && !mName.empty())
1357
    {
1358
        showMuteCommands();
1359
        return;
1360
    }
1361
    else if (link == "show" && !mName.empty())
1362
    {
1363
        showPlayerMenu();
1364
        return;
1365
    }
1366
    else if (link == "window close" && (mCallerWindow != nullptr))
1367
    {
1368
        if (Widget::widgetExists(mCallerWindow))
1369
            mCallerWindow->close();
1370
    }
1371
    else if (link == "window unlock" && (mCallerWindow != nullptr))
1372
    {
1373
        if (Widget::widgetExists(mCallerWindow))
1374
            mCallerWindow->setSticky(false);
1375
    }
1376
    else if (link == "window lock" && (mCallerWindow != nullptr))
1377
    {
1378
        if (Widget::widgetExists(mCallerWindow))
1379
            mCallerWindow->setSticky(true);
1380
    }
1381
    else if (link == "join chat" && (being != nullptr))
1382
    {
1383
        const ChatObject *const chat = being->getChat();
1384
        if (chat != nullptr)
1385
            chatHandler->joinChat(chat, "");
1386
    }
1387
    else if (link == "craftmenu")
1388
    {
1389
        showCraftPopup();
1390
        return;
1391
    }
1392
    else if (link.compare(0, 10, "guild-pos-") == 0)
1393
    {
1394
        if (localPlayer != nullptr)
1395
        {
1396
            const int num = atoi(link.substr(10).c_str());
1397
            const Guild *const guild = localPlayer->getGuild();
1398
            if (guild != nullptr)
1399
            {
1400
                guildHandler->changeMemberPostion(
1401
                    guild->getMember(mName), num);
1402
            }
1403
        }
1404
    }
1405
    else if (link.compare(0, 7, "player_") == 0)
1406
    {
1407
        if (actorManager != nullptr)
1408
        {
1409
            mBeingId = fromInt(atoi(link.substr(7).c_str()), BeingId);
1410
            being = actorManager->findBeing(mBeingId);
1411
            if (being != nullptr)
1412
            {
1413
                showPopup(getX(), getY(), being);
1414
                return;
1415
            }
1416
        }
1417
    }
1418
    else if (link.compare(0, 10, "flooritem_") == 0)
1419
    {
1420
        if (actorManager != nullptr)
1421
        {
1422
            const BeingId id = fromInt(atoi(
1423
                link.substr(10).c_str()), BeingId);
1424
            if (id != BeingId_zero)
1425
            {
1426
                const FloorItem *const item = actorManager->findItem(id);
1427
                if (item != nullptr)
1428
                {
1429
                    mFloorItemId = item->getId();
1430
                    mItemId = item->getItemId();
1431
                    for (int f = 0; f < maxCards; f ++)
1432
                        mItemCards[f] = item->getCard(f);
1433
                    showPopup(getX(), getY(), item);
1434
                    return;
1435
                }
1436
            }
1437
        }
1438
    }
1439
    else if (link.compare(0, 12, "hide button_") == 0)
1440
    {
1441
        if (windowMenu != nullptr)
1442
            windowMenu->showButton(link.substr(12), Visible_false);
1443
    }
1444
    else if (link.compare(0, 12, "show button_") == 0)
1445
    {
1446
        if (windowMenu != nullptr)
1447
            windowMenu->showButton(link.substr(12), Visible_true);
1448
    }
1449
    else if (link.compare(0, 9, "hide bar_") == 0)
1450
    {
1451
        if (miniStatusWindow != nullptr)
1452
            miniStatusWindow->showBar(link.substr(9), Visible_false);
1453
    }
1454
    else if (link.compare(0, 9, "show bar_") == 0)
1455
    {
1456
        if (miniStatusWindow != nullptr)
1457
            miniStatusWindow->showBar(link.substr(9), Visible_true);
1458
    }
1459
    else if (link.compare(0, 12, "show window_") == 0)
1460
    {
1461
        const int id = atoi(link.substr(12).c_str());
1462
        if (id >= 0)
1463
            inputManager.executeAction(static_cast<InputActionT>(id));
1464
    }
1465
    else if (link.compare(0, 6, "mute_+") == 0)
1466
    {
1467
        if (being != nullptr)
1468
        {
1469
            const int time = atoi(link.substr(6).c_str());
1470
            adminHandler->mute(being, 1, time);
1471
        }
1472
    }
1473
    else if (link.compare(0, 6, "mute_-") == 0)
1474
    {
1475
        if (being != nullptr)
1476
        {
1477
            const int time = atoi(link.substr(6).c_str());
1478
            adminHandler->mute(being, 0, time);
1479
        }
1480
    }
1481
    else if (!link.empty() && link[0] == '/')
1482
    {
1483
        std::string cmd = link.substr(1);
1484
        replaceAll(cmd, "'NAME'", mName);
1485
        replaceAll(cmd, "'ENAME'", escapeString(mName));
1486
        replaceAll(cmd, "'EXTNAME'", mExtName);
1487
        replaceAll(cmd, "'EEXTNAME'", escapeString(mExtName));
1488
        replaceAll(cmd, "'X'", toString(mX));
1489
        replaceAll(cmd, "'Y'", toString(mY));
1490
        replaceAll(cmd, "'BEINGID'", toString(toInt(mBeingId, int)));
1491
        replaceAll(cmd, "'FLOORID'", toString(toInt(mFloorItemId, int)));
1492
        replaceAll(cmd, "'ITEMID'", toString(mItemId));
1493
        replaceAll(cmd, "'ITEMCOLOR'", toString(toInt(mItemColor, int)));
1494
        replaceAll(cmd, "'BEINGTYPEID'", toString(CAST_S32(mType)));
1495
        replaceAll(cmd, "'BEINGSUBTYPEID'", toString(CAST_S32(mSubType)));
1496
        replaceAll(cmd, "'PLAYER'", localPlayer->getName());
1497
        replaceAll(cmd, "'EPLAYER'", escapeString(localPlayer->getName()));
1498
        replaceAll(cmd, "'PLAYERX'", toString(localPlayer->getTileX()));
1499
        replaceAll(cmd, "'PLAYERY'", toString(localPlayer->getTileY()));
1500
        if (mItemIndex >= 0)
1501
            replaceAll(cmd, "'INVINDEX'", toString(mItemIndex));
1502
        else
1503
            replaceAll(cmd, "'INVINDEX'", "0");
1504
        if (mMapItem != nullptr)
1505
        {
1506
            replaceAll(cmd, "'MAPX'", toString(mMapItem->getX()));
1507
            replaceAll(cmd, "'MAPY'", toString(mMapItem->getY()));
1508
        }
1509
        else
1510
        {
1511
            replaceAll(cmd, "'MAPX'", toString(mX));
1512
            replaceAll(cmd, "'MAPY'", toString(mY));
1513
        }
1514
1515
        std::string cards;
1516
        for (int f = 0; f < maxCards; f ++)
1517
        {
1518
            const int id = mItemCards[f];
1519
            if (id != 0)
1520
            {
1521
                cards.append(",");
1522
                cards.append(toString(id));
1523
            }
1524
        }
1525
        replaceAll(cmd, "'CARDS'", cards);
1526
        replaceAll(cmd, "'ECARDS'", escapeString(cards));
1527
        if (actorManager != nullptr)
1528
        {
1529
            if (being == nullptr)
1530
            {
1531
                being = actorManager->findBeingByName(mName,
1532
                    ActorType::Player);
1533
            }
1534
        }
1535
        if (being != nullptr)
1536
            replaceAll(cmd, "'PARTY'", being->getPartyName());
1537
        else
1538
            replaceAll(cmd, "'PARTY'", "");
1539
1540
        const size_t pos = cmd.find(' ');
1541
        const std::string type(cmd, 0, pos);
1542
        std::string args(cmd, pos == std::string::npos ? cmd.size() : pos + 1);
1543
        args = trim(args);
1544
        inputManager.executeChatCommand(type, args, mTab);
1545
    }
1546
    // Unknown actions
1547
    else if (link != "cancel")
1548
    {
1549
        reportAlways("PopupMenu: Warning, unknown action '%s'", link.c_str())
1550
    }
1551
1552
    if (!mAllowCleanMenu)
1553
        return;
1554
1555
    setVisible(Visible_false);
1556
1557
    mBeingId = BeingId_zero;
1558
    mFloorItemId = BeingId_zero;
1559
    mItemId = 0;
1560
    mItemIndex = -1;
1561
    for (int f = 0; f < maxCards; f ++)
1562
        mItemCards[f] = 0;
1563
    mItemColor = ItemColor_one;
1564
    mMapItem = nullptr;
1565
    mTab = nullptr;
1566
    mSpell = nullptr;
1567
    mCallerWindow = nullptr;
1568
    mDialog = nullptr;
1569
    mButton = nullptr;
1570
    mName.clear();
1571
    mExtName.clear();
1572
    mTextField = nullptr;
1573
    mType = ActorType::Unknown;
1574
    mSubType = BeingTypeId_zero;
1575
    mX = 0;
1576
    mY = 0;
1577
}
1578
1579
void PopupMenu::showPopup(Window *const parent,
1580
                          const int x, const int y,
1581
                          const Item *const item,
1582
                          const InventoryTypeT type)
1583
{
1584
    if (item == nullptr)
1585
        return;
1586
1587
    initPopup();
1588
    mItemId = item->getId();
1589
    mItemIndex = item->getInvIndex();
1590
    for (int f = 0; f < maxCards; f ++)
1591
        mItemCards[f] = item->getCard(f);
1592
    mItemColor = item->getColor();
1593
    mCallerWindow = parent;
1594
    mX = x;
1595
    mY = y;
1596
    mName.clear();
1597
    mExtName.clear();
1598
    mBrowserBox->clearRows();
1599
1600
    const int cnt = item->getQuantity();
1601
    const bool isProtected = PlayerInfo::isItemProtected(mItemId);
1602
1603
    switch (type)
1604
    {
1605
        case InventoryType::Inventory:
1606
            if (tradeWindow != nullptr &&
1607
                tradeWindow->isWindowVisible() &&
1608
                !isProtected)
1609
            {
1610
                // TRANSLATORS: popup menu item
1611
                // TRANSLATORS: add item to trade
1612
                mBrowserBox->addRow("/addtrade 'INVINDEX'", _("Add to trade"));
1613
                if (cnt > 1)
1614
                {
1615
                    if (cnt > 10)
1616
                    {
1617
                        mBrowserBox->addRow("/addtrade 'INVINDEX' 10",
1618
                            // TRANSLATORS: popup menu item
1619
                            // TRANSLATORS: add 10 item amount to trade
1620
                            _("Add to trade 10"));
1621
                    }
1622
                    mBrowserBox->addRow("/addtrade 'INVINDEX' /",
1623
                        // TRANSLATORS: popup menu item
1624
                        // TRANSLATORS: add half item amount to trade
1625
                        _("Add to trade half"));
1626
                    mBrowserBox->addRow("/addtrade 'INVINDEX' -1",
1627
                        // TRANSLATORS: popup menu item
1628
                        // TRANSLATORS: add all amount except one item to trade
1629
                        _("Add to trade all-1"));
1630
                    mBrowserBox->addRow("/addtrade 'INVINDEX' all",
1631
                        // TRANSLATORS: popup menu item
1632
                        // TRANSLATORS: add all amount item to trade
1633
                        _("Add to trade all"));
1634
                }
1635
                mBrowserBox->addSeparator("##3---");
1636
            }
1637
            if (InventoryWindow::isStorageActive())
1638
            {
1639
                // TRANSLATORS: popup menu item
1640
                // TRANSLATORS: add item to storage
1641
                mBrowserBox->addRow("/invtostorage 'INVINDEX'", _("Store"));
1642
                if (cnt > 1)
1643
                {
1644
                    if (cnt > 10)
1645
                    {
1646
                        mBrowserBox->addRow("/invtostorage 'INVINDEX' 10",
1647
                            // TRANSLATORS: popup menu item
1648
                            // TRANSLATORS: add 10 item amount to storage
1649
                            _("Store 10"));
1650
                    }
1651
                    mBrowserBox->addRow("/invtostorage 'INVINDEX' /",
1652
                        // TRANSLATORS: popup menu item
1653
                        // TRANSLATORS: add half item amount to storage
1654
                        _("Store half"));
1655
                    mBrowserBox->addRow("/invtostorage 'INVINDEX' -1",
1656
                        // TRANSLATORS: popup menu item
1657
                        // TRANSLATORS: add all except one item to storage
1658
                        _("Store all-1"));
1659
                    mBrowserBox->addRow("/invtostorage 'INVINDEX' all",
1660
                        // TRANSLATORS: popup menu item
1661
                        // TRANSLATORS: add all item amount to storage
1662
                        _("Store all"));
1663
                }
1664
                mBrowserBox->addSeparator("##3---");
1665
            }
1666
            if (npcHandler != nullptr)
1667
            {
1668
                NpcDialog *const dialog = npcHandler->getCurrentNpcDialog();
1669
                if ((dialog != nullptr) &&
1670
                    dialog->getInputState() == NpcInputState::ITEM_CRAFT)
1671
                {
1672
                    mBrowserBox->addRow("craftmenu",
1673
                        // TRANSLATORS: popup menu item
1674
                        // TRANSLATORS: sub menu for craft
1675
                        _("Move to craft..."));
1676
                }
1677
            }
1678
            addItemMenu(item, InventoryType::Inventory);
1679
            addDrop(item, isProtected);
1680
            break;
1681
1682
        case InventoryType::Storage:
1683
            // TRANSLATORS: popup menu item
1684
            // TRANSLATORS: get item from storage
1685
            mBrowserBox->addRow("/storagetoinv 'INVINDEX'", _("Retrieve"));
1686
            if (cnt > 1)
1687
            {
1688
                if (cnt > 10)
1689
                {
1690
                    mBrowserBox->addRow("/storagetoinv 'INVINDEX' 10",
1691
                        // TRANSLATORS: popup menu item
1692
                        // TRANSLATORS: get 10 item amount from storage
1693
                        _("Retrieve 10"));
1694
                }
1695
                mBrowserBox->addRow("/storagetoinv 'INVINDEX' /",
1696
                    // TRANSLATORS: popup menu item
1697
                    // TRANSLATORS: get half item amount from storage
1698
                    _("Retrieve half"));
1699
                mBrowserBox->addRow("/storagetoinv 'INVINDEX' -1",
1700
                    // TRANSLATORS: popup menu item
1701
                    // TRANSLATORS: get all except one item amount from storage
1702
                    _("Retrieve all-1"));
1703
                mBrowserBox->addRow("/storagetoinv 'INVINDEX' all",
1704
                    // TRANSLATORS: popup menu item
1705
                    // TRANSLATORS: get all item amount from storage
1706
                    _("Retrieve all"));
1707
                mBrowserBox->addSeparator("##3---");
1708
            }
1709
            addItemMenu(item, InventoryType::Storage);
1710
            break;
1711
        case InventoryType::Cart:
1712
            addItemMenu(item, InventoryType::Cart);
1713
            break;
1714
1715
        case InventoryType::Trade:
1716
        case InventoryType::Npc:
1717
        case InventoryType::Vending:
1718
        case InventoryType::MailEdit:
1719
        case InventoryType::MailView:
1720
        case InventoryType::Craft:
1721
        case InventoryType::TypeEnd:
1722
        default:
1723
            break;
1724
    }
1725
1726
1727
    addProtection();
1728
    if (config.getBoolValue("enablePickupFilter"))
1729
    {
1730
        mName = item->getName();
1731
        mExtName = mName;
1732
        mBrowserBox->addSeparator("##3---");
1733
        addPickupFilter(mName);
1734
    }
1735
    addGmCommands();
1736
    // TRANSLATORS: popup menu item
1737
    // TRANSLATORS: add item name to chat
1738
    mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
1739
    mBrowserBox->addSeparator("##3---");
1740
    // TRANSLATORS: popup menu item
1741
    // TRANSLATORS: close menu
1742
    mBrowserBox->addRow("cancel", _("Cancel"));
1743
1744
    showPopup(x, y);
1745
}
1746
1747
void PopupMenu::showItemPopup(const int x, const int y,
1748
                              const int itemId,
1749
                              const ItemColor color)
1750
{
1751
    const Inventory *const inv = PlayerInfo::getInventory();
1752
    if (inv == nullptr)
1753
        return;
1754
1755
    Item *const item = inv->findItem(itemId, color);
1756
    if (item != nullptr)
1757
    {
1758
        showItemPopup(x, y, item);
1759
    }
1760
    else
1761
    {
1762
        initPopup();
1763
        mItemId = itemId;
1764
        mItemIndex = -1;
1765
        mItemColor = color;
1766
        for (int f = 0; f < maxCards; f ++)
1767
            mItemCards[f] = 0;
1768
        mX = x;
1769
        mY = y;
1770
        mBrowserBox->clearRows();
1771
1772
        if (!PlayerInfo::isItemProtected(mItemId))
1773
        {
1774
            // TRANSLATORS: popup menu item
1775
            // TRANSLATORS: use item
1776
            mBrowserBox->addRow("/use 'ITEMID'", _("Use"));
1777
        }
1778
        addProtection();
1779
        addGmCommands();
1780
        mBrowserBox->addSeparator("##3---");
1781
        // TRANSLATORS: popup menu item
1782
        // TRANSLATORS: close menu
1783
        mBrowserBox->addRow("cancel", _("Cancel"));
1784
1785
        showPopup(x, y);
1786
    }
1787
}
1788
1789
void PopupMenu::showItemPopup(const int x, const int y,
1790
                              const Item *const item)
1791
{
1792
    initPopup();
1793
    mX = x;
1794
    mY = y;
1795
    if (item != nullptr)
1796
    {
1797
        mItemId = item->getId();
1798
        mItemColor = item->getColor();
1799
        mItemIndex = item->getInvIndex();
1800
        for (int f = 0; f < maxCards; f ++)
1801
            mItemCards[f] = item->getCard(f);
1802
    }
1803
    else
1804
    {
1805
        mItemId = 0;
1806
        mItemColor = ItemColor_one;
1807
        mItemIndex = -1;
1808
        for (int f = 0; f < maxCards; f ++)
1809
            mItemCards[f] = 0;
1810
    }
1811
    mName.clear();
1812
    mExtName.clear();
1813
    mBrowserBox->clearRows();
1814
1815
    if (item != nullptr)
1816
    {
1817
        const bool isProtected = PlayerInfo::isItemProtected(mItemId);
1818
        addUse(item);
1819
        addDrop(item, isProtected);
1820
        if (InventoryWindow::isStorageActive())
1821
        {
1822
            // TRANSLATORS: popup menu item
1823
            // TRANSLATORS: add item to storage
1824
            mBrowserBox->addRow("/invtostorage 'INVINDEX'", _("Store"));
1825
        }
1826
        // TRANSLATORS: popup menu item
1827
        // TRANSLATORS: add item name to chat
1828
        mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
1829
1830
        if (config.getBoolValue("enablePickupFilter"))
1831
        {
1832
            mName = item->getName();
1833
            mExtName = mName;
1834
            mBrowserBox->addSeparator("##3---");
1835
            addPickupFilter(mName);
1836
        }
1837
    }
1838
    addProtection();
1839
    addGmCommands();
1840
    mBrowserBox->addSeparator("##3---");
1841
    // TRANSLATORS: popup menu item
1842
    // TRANSLATORS: close menu
1843
    mBrowserBox->addRow("cancel", _("Cancel"));
1844
1845
    showPopup(x, y);
1846
}
1847
1848
void PopupMenu::showDropPopup(const int x,
1849
                              const int y,
1850
                              const Item *const item)
1851
{
1852
    initPopup();
1853
    mX = x;
1854
    mY = y;
1855
    mName.clear();
1856
    mExtName.clear();
1857
    mBrowserBox->clearRows();
1858
1859
    if (item != nullptr)
1860
    {
1861
        mItemId = item->getId();
1862
        mItemColor = item->getColor();
1863
        mItemIndex = item->getInvIndex();
1864
        for (int f = 0; f < maxCards; f ++)
1865
            mItemCards[f] = item->getCard(f);
1866
        const bool isProtected = PlayerInfo::isItemProtected(mItemId);
1867
        addUse(item);
1868
        addDrop(item, isProtected);
1869
        if (InventoryWindow::isStorageActive())
1870
        {
1871
            // TRANSLATORS: popup menu item
1872
            // TRANSLATORS: add item to storage
1873
            mBrowserBox->addRow("/invtostorage 'INVINDEX'", _("Store"));
1874
        }
1875
        addProtection();
1876
        // TRANSLATORS: popup menu item
1877
        // TRANSLATORS: add item name to chat
1878
        mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
1879
        if (config.getBoolValue("enablePickupFilter"))
1880
        {
1881
            mName = item->getName();
1882
            mExtName = mName;
1883
            mBrowserBox->addSeparator("##3---");
1884
            addPickupFilter(mName);
1885
        }
1886
    }
1887
    addGmCommands();
1888
    mBrowserBox->addSeparator("##3---");
1889
    // TRANSLATORS: popup menu item
1890
    mBrowserBox->addRow("/cleardrops", _("Clear drop window"));
1891
    mBrowserBox->addSeparator("##3---");
1892
    // TRANSLATORS: popup menu item
1893
    // TRANSLATORS: close menu
1894
    mBrowserBox->addRow("cancel", _("Cancel"));
1895
1896
    showPopup(x, y);
1897
}
1898
1899
void PopupMenu::showPopup(const int x, const int y, Button *const button)
1900
{
1901
    if ((button == nullptr) || (windowMenu == nullptr))
1902
        return;
1903
1904
    initPopup();
1905
    mButton = button;
1906
    mX = x;
1907
    mY = y;
1908
1909
    mBrowserBox->clearRows();
1910
    STD_VECTOR<Button *> names = windowMenu->getButtons();
1911
    for (STD_VECTOR<Button *>::const_iterator it = names.begin(),
1912
         it_end = names.end(); it != it_end; ++ it)
1913
    {
1914
        const Button *const btn = *it;
1915
        if ((btn == nullptr) || btn->getActionEventId() == "SET")
1916
            continue;
1917
1918
        if (btn->mVisible == Visible_true)
1919
        {
1920
            mBrowserBox->addRow(strprintf("@@hide button_%s|%s %s (%s)@@",
1921
                // TRANSLATORS: popup menu item
1922
                btn->getActionEventId().c_str(), _("Hide"),
1923
                btn->getDescription().c_str(), btn->getCaption().c_str()),
1924
                false);
1925
        }
1926
        else
1927
        {
1928
            mBrowserBox->addRow(strprintf("@@show button_%s|%s %s (%s)@@",
1929
                // TRANSLATORS: popup menu item
1930
                btn->getActionEventId().c_str(), _("Show"),
1931
                btn->getDescription().c_str(), btn->getCaption().c_str()),
1932
                false);
1933
        }
1934
    }
1935
    mBrowserBox->addSeparator("##3---");
1936
    // TRANSLATORS: popup menu item
1937
    // TRANSLATORS: close menu
1938
    mBrowserBox->addRow("cancel", _("Cancel"));
1939
1940
    showPopup(x, y);
1941
}
1942
1943
void PopupMenu::showPopup(const int x, const int y, const ProgressBar *const b)
1944
{
1945
    if ((b == nullptr) || (miniStatusWindow == nullptr))
1946
        return;
1947
1948
    initPopup();
1949
    mName = b->text();
1950
    mExtName = mName;
1951
    mX = x;
1952
    mY = y;
1953
1954
    mBrowserBox->clearRows();
1955
    STD_VECTOR <ProgressBar*> bars = miniStatusWindow->getBars();
1956
    ProgressBar *onlyBar = nullptr;
1957
    int cnt = 0;
1958
1959
    // search for alone visible bar
1960
    for (STD_VECTOR <ProgressBar*>::const_iterator it = bars.begin(),
1961
         it_end = bars.end(); it != it_end; ++it)
1962
    {
1963
        ProgressBar *const bar = *it;
1964
        if (bar == nullptr)
1965
            continue;
1966
1967
        if (bar->mVisible == Visible_true)
1968
        {
1969
            cnt ++;
1970
            onlyBar = bar;
1971
        }
1972
    }
1973
    if (cnt > 1)
1974
        onlyBar = nullptr;
1975
1976
    for (STD_VECTOR <ProgressBar*>::const_iterator it = bars.begin(),
1977
         it_end = bars.end(); it != it_end; ++it)
1978
    {
1979
        ProgressBar *const bar = *it;
1980
        if ((bar == nullptr) || bar == onlyBar)
1981
            continue;
1982
1983
        if (bar->mVisible == Visible_true)
1984
        {
1985
            mBrowserBox->addRow(strprintf("@@hide bar_%s|%s %[email protected]@",
1986
                // TRANSLATORS: popup menu item
1987
                bar->getActionEventId().c_str(), _("Hide"),
1988
                bar->getId().c_str()),
1989
                false);
1990
        }
1991
        else
1992
        {
1993
            mBrowserBox->addRow(strprintf("@@show bar_%s|%s %[email protected]@",
1994
                // TRANSLATORS: popup menu item
1995
                bar->getActionEventId().c_str(), _("Show"),
1996
                bar->getId().c_str()),
1997
                false);
1998
        }
1999
    }
2000
2001
    mBrowserBox->addSeparator("##3---");
2002
    // TRANSLATORS: popup menu item
2003
    mBrowserBox->addRow("/yellowbar", _("Open yellow bar settings"));
2004
    // TRANSLATORS: popup menu item
2005
    mBrowserBox->addRow("/resetmodifiers", _("Reset yellow bar"));
2006
    mBrowserBox->addSeparator("##3---");
2007
    // TRANSLATORS: popup menu item
2008
    // TRANSLATORS: copy status to chat
2009
    mBrowserBox->addRow("/bartochat 'NAME'", _("Copy to chat"));
2010
    // TRANSLATORS: popup menu item
2011
    // TRANSLATORS: close menu
2012
    mBrowserBox->addRow("cancel", _("Cancel"));
2013
2014
    showPopup(x, y);
2015
}
2016
2017
void PopupMenu::showAttackMonsterPopup(const int x, const int y,
2018
                                       const std::string &name,
2019
                                       const int type)
2020
{
2021
    if ((localPlayer == nullptr) || (actorManager == nullptr))
2022
        return;
2023
2024
    initPopup();
2025
    mName = name;
2026
    mExtName = name;
2027
    mType = ActorType::Monster;
2028
    mSubType = BeingTypeId_zero;
2029
    mX = x;
2030
    mY = y;
2031
2032
    mBrowserBox->clearRows();
2033
2034
    if (name.empty())
2035
    {
2036
        // TRANSLATORS: popup menu header
2037
        mBrowserBox->addRow(_("(default)"), false);
2038
    }
2039
    else
2040
    {
2041
        mBrowserBox->addRow(name, false);
2042
    }
2043
    switch (type)
2044
    {
2045
        case MapItemType::ATTACK:
2046
        {
2047
            const int idx = actorManager->getAttackMobIndex(name);
2048
            const int size = actorManager->getAttackMobsSize();
2049
            if (idx > 0)
2050
            {
2051
                // TRANSLATORS: popup menu item
2052
                // TRANSLATORS: move attack target up
2053
                mBrowserBox->addRow("/moveattackup 'NAME'", _("Move up"));
2054
            }
2055
            if (idx + 1 < size)
2056
            {
2057
                // TRANSLATORS: popup menu item
2058
                // TRANSLATORS: move attack target down
2059
                mBrowserBox->addRow("/moveattackdown 'NAME'", _("Move down"));
2060
            }
2061
            break;
2062
        }
2063
        case MapItemType::PRIORITY:
2064
        {
2065
            const int idx = actorManager->
2066
                getPriorityAttackMobIndex(name);
2067
            const int size = actorManager->getPriorityAttackMobsSize();
2068
            if (idx > 0)
2069
            {
2070
                mBrowserBox->addRow("/movepriorityattackup 'NAME'",
2071
                    // TRANSLATORS: popup menu item
2072
                    // TRANSLATORS: move attack target up
2073
                    _("Move up"));
2074
            }
2075
            if (idx + 1 < size)
2076
            {
2077
                mBrowserBox->addRow("/movepriorityattackdown 'NAME'",
2078
                    // TRANSLATORS: popup menu item
2079
                    // TRANSLATORS: move attack target down
2080
                    _("Move down"));
2081
            }
2082
            break;
2083
        }
2084
        case MapItemType::IGNORE_:
2085
        default:
2086
            break;
2087
    }
2088
2089
    // TRANSLATORS: popup menu item
2090
    // TRANSLATORS: remove attack target
2091
    mBrowserBox->addRow("/removeattack 'NAME'", _("Remove"));
2092
    mBrowserBox->addSeparator("##3---");
2093
    // TRANSLATORS: popup menu item
2094
    // TRANSLATORS: close menu
2095
    mBrowserBox->addRow("cancel", _("Cancel"));
2096
2097
    showPopup(x, y);
2098
}
2099
2100
void PopupMenu::showPickupItemPopup(const int x, const int y,
2101
                                    const std::string &name)
2102
{
2103
    if ((localPlayer == nullptr) || (actorManager == nullptr))
2104
        return;
2105
2106
    initPopup();
2107
    mName = name;
2108
    mExtName = name;
2109
    mType = ActorType::FloorItem;
2110
    mSubType = BeingTypeId_zero;
2111
    mX = x;
2112
    mY = y;
2113
2114
    mBrowserBox->clearRows();
2115
2116
    if (name.empty())
2117
    {
2118
        // TRANSLATORS: popup menu header
2119
        mBrowserBox->addRow(_("(default)"), false);
2120
    }
2121
    else
2122
    {
2123
        mBrowserBox->addRow(name, false);
2124
    }
2125
2126
    // TRANSLATORS: popup menu item
2127
    // TRANSLATORS: remove item from pickup filter
2128
    mBrowserBox->addRow("/removepickup 'NAME'", _("Remove"));
2129
    mBrowserBox->addSeparator("##3---");
2130
    // TRANSLATORS: popup menu item
2131
    // TRANSLATORS: close menu
2132
    mBrowserBox->addRow("cancel", _("Cancel"));
2133
2134
    showPopup(x, y);
2135
}
2136
2137
void PopupMenu::showUndressPopup(const int x, const int y,
2138
                                 const Being *const being,
2139
                                 const Item *const item)
2140
{
2141
    if ((being == nullptr) || (item == nullptr))
2142
        return;
2143
2144
    initPopup();
2145
    mBeingId = being->getId();
2146
    mItemId = item->getId();
2147
    mItemColor = item->getColor();
2148
    mItemIndex = item->getInvIndex();
2149
    for (int f = 0; f < maxCards; f ++)
2150
        mItemCards[f] = item->getCard(f);
2151
    mX = x;
2152
    mY = y;
2153
2154
    mBrowserBox->clearRows();
2155
2156
    // TRANSLATORS: popup menu item
2157
    // TRANSLATORS: undress item from player
2158
    mBrowserBox->addRow("/undress :'BEINGID' 'ITEMID'", _("Undress"));
2159
    // TRANSLATORS: popup menu item
2160
    // TRANSLATORS: add item name to chat
2161
    mBrowserBox->addRow("/addchat 'ITEMID''CARDS'", _("Add to chat"));
2162
    addGmCommands();
2163
    mBrowserBox->addSeparator("##3---");
2164
    // TRANSLATORS: popup menu item
2165
    // TRANSLATORS: close menu
2166
    mBrowserBox->addRow("cancel", _("Cancel"));
2167
2168
    showPopup(x, y);
2169
}
2170
2171
void PopupMenu::showTextFieldPopup(TextField *const input)
2172
{
2173
    initPopup();
2174
    setMousePos();
2175
    mTextField = input;
2176
2177
    mBrowserBox->clearRows();
2178
2179
    // TRANSLATORS: popup menu item
2180
    // TRANSLATORS: copy text to clipboard
2181
    mBrowserBox->addRow("clipboard copy", _("Copy"));
2182
    // TRANSLATORS: popup menu item
2183
    // TRANSLATORS: paste text from clipboard
2184
    mBrowserBox->addRow("clipboard paste", _("Paste"));
2185
    mBrowserBox->addSeparator("##3---");
2186
    // TRANSLATORS: popup menu item
2187
    // TRANSLATORS: close menu
2188
    mBrowserBox->addRow("cancel", _("Cancel"));
2189
2190
    showPopup(mX, mY);
2191
}
2192
2193
void PopupMenu::showLinkPopup(const std::string &link)
2194
{
2195
    initPopup();
2196
    setMousePos();
2197
    mName = link;
2198
    mExtName = link;
2199
2200
    mBrowserBox->clearRows();
2201
2202
    // TRANSLATORS: popup menu item
2203
    // TRANSLATORS: open link in browser
2204
    mBrowserBox->addRow("/open 'NAME'", _("Open link"));
2205
    // TRANSLATORS: popup menu item
2206
    // TRANSLATORS: copy link to clipboard
2207
    mBrowserBox->addRow("/clipboardcopy 'NAME'", _("Copy to clipboard"));
2208
    mBrowserBox->addSeparator("##3---");
2209
    // TRANSLATORS: popup menu item
2210
    // TRANSLATORS: close menu
2211
    mBrowserBox->addRow("cancel", _("Cancel"));
2212
2213
    showPopup(mX, mY);
2214
}
2215
2216
void PopupMenu::showWindowsPopup()
2217
{
2218
    initPopup();
2219
    setMousePos();
2220
    mBrowserBox->clearRows();
2221
    const STD_VECTOR<ButtonText*> &names = windowMenu->getButtonTexts();
2222
    // TRANSLATORS: popup menu header
2223
    mBrowserBox->addRow(_("Show window"), false);
2224
2225
    FOR_EACH (STD_VECTOR<ButtonText*>::const_iterator, it, names)
2226
    {
2227
        const ButtonText *const btn = *it;
2228
        if (btn == nullptr)
2229
            continue;
2230
2231
        mBrowserBox->addRow(strprintf("show window_%d",
2232
            CAST_S32(btn->key)),
2233
            btn->text.c_str());
2234
    }
2235
    mBrowserBox->addSeparator("##3---");
2236
    // TRANSLATORS: popup menu item
2237
    // TRANSLATORS: close menu
2238
    mBrowserBox->addRow("cancel", _("Cancel"));
2239
2240
    showPopup(mX, mY);
2241
}
2242
2243
void PopupMenu::showNpcDialogPopup(const BeingId npcId,
2244
                                   const int x, const int y)
2245
{
2246
    initPopup();
2247
    mBeingId = npcId;
2248
    mX = x;
2249
    mY = y;
2250
    mBrowserBox->clearRows();
2251
    // TRANSLATORS: popup menu item
2252
    // TRANSLATORS: copy npc text to clipboard
2253
    mBrowserBox->addRow("/npcclipboard 'X' 'Y'", _("Copy to clipboard"));
2254
    mBrowserBox->addSeparator("##3---");
2255
    // TRANSLATORS: popup menu item
2256
    // TRANSLATORS: close menu
2257
    mBrowserBox->addRow("cancel", _("Cancel"));
2258
2259
    showPopup(x, y);
2260
}
2261
2262
void PopupMenu::showSkillPopup(const SkillInfo *const info)
2263
{
2264
    if (info == nullptr)
2265
        return;
2266
2267
    initPopup();
2268
    setMousePos();
2269
2270
    // using mItemId as skill id
2271
    mItemId = info->id;
2272
    // using mItemIndex as skill level
2273
    mItemIndex = info->level;
2274
    mBrowserBox->clearRows();
2275
2276
    // TRANSLATORS: popup menu header
2277
    mBrowserBox->addRow(_("Skill"), false);
2278
    mBrowserBox->addRow("/addskillshortcut 'ITEMID'",
2279
        // TRANSLATORS: popup menu item
2280
        // TRANSLATORS: add skill to shortcurs tab
2281
        _("Add skill shortcut"));
2282
    mBrowserBox->addSeparator("##3---");
2283
    mBrowserBox->addRow("/showskilllevels 'ITEMID'",
2284
        // TRANSLATORS: popup menu item
2285
        // TRANSLATORS: set skill level
2286
        _("Skill level..."));
2287
    mBrowserBox->addRow("/showskilltypes 'ITEMID'",
2288
        // TRANSLATORS: popup menu item
2289
        // TRANSLATORS: set skill cast type
2290
        _("Skill cast type..."));
2291
    mBrowserBox->addRow("/showskilloffsetx 'ITEMID'",
2292
        // TRANSLATORS: popup menu item
2293
        // TRANSLATORS: set skill cast offset by x
2294
        _("Skill offset by x..."));
2295
    mBrowserBox->addRow("/showskilloffsety 'ITEMID'",
2296
        // TRANSLATORS: popup menu item
2297
        // TRANSLATORS: set skill cast offset by y
2298
        _("Skill offset by y..."));
2299
    // TRANSLATORS: popup menu item
2300
    // TRANSLATORS: close menu
2301
    mBrowserBox->addRow("cancel", _("Cancel"));
2302
2303
    showPopup(mX, mY);
2304
}
2305
2306
void PopupMenu::showSkillOffsetPopup(const SkillInfo *const info,
2307
                                     const bool isOffsetX)
2308
{
2309
    if (info == nullptr)
2310
        return;
2311
2312
    initPopup();
2313
    setMousePos2();
2314
2315
    // using mItemId as skill id
2316
    mItemId = info->id;
2317
    // using mItemIndex as skill level
2318
    mItemIndex = info->level;
2319
    mBrowserBox->clearRows();
2320
    char letter = ' ';
2321
2322
    if (isOffsetX)
2323
    {
2324
        // TRANSLATORS: popup menu header
2325
        mBrowserBox->addRow(_("Skill cast offset by x"), false);
2326
        letter = 'x';
2327
    }
2328
    else
2329
    {
2330
        // TRANSLATORS: popup menu header
2331
        mBrowserBox->addRow(_("Skill cast offset by y"), false);
2332
        letter = 'y';
2333
    }
2334
    for (int f = -9; f <= 9; f ++)
2335
    {
2336
        const std::string command = strprintf(
2337
            "/setskilloffset%c 'ITEMID' %d", letter, f);
2338
        if (f == 0)
2339
        {
2340
            mBrowserBox->addRow(command,
2341
                strprintf("%d", f).c_str());
2342
        }
2343
        else
2344
        {
2345
            mBrowserBox->addRow(command,
2346
                strprintf("%+d", f).c_str());
2347
        }
2348
    }
2349
    // TRANSLATORS: popup menu item
2350
    // TRANSLATORS: close menu
2351
    mBrowserBox->addRow("cancel", _("Cancel"));
2352
    showPopup(mX, mY);
2353
}
2354
2355
void PopupMenu::showSkillLevelPopup(const SkillInfo *const info)
2356
{
2357
    if (info == nullptr)
2358
        return;
2359
2360
    initPopup();
2361
    setMousePos2();
2362
2363
    // using mItemId as skill id
2364
    mItemId = info->id;
2365
    // using mItemIndex as skill level
2366
    mItemIndex = info->level;
2367
2368
    for (int f = 0; f < maxCards; f ++)
2369
        mItemCards[f] = 0;
2370
    mBrowserBox->clearRows();
2371
    // TRANSLATORS: popup menu item
2372
    // TRANSLATORS: skill level header
2373
    mBrowserBox->addRow(_("Select skill level"), false);
2374
    for (int f = 1; f <= mItemIndex; f ++)
2375
    {
2376
        mBrowserBox->addRow(strprintf("/selectskilllevel %d %d", mItemId, f),
2377
            // TRANSLATORS: popup menu item
2378
            // TRANSLATORS: skill level
2379
            strprintf(_("Level: %d"), f).c_str());
2380
    }
2381
    mBrowserBox->addRow(strprintf("/selectskilllevel %d 0", mItemId),
2382
        // TRANSLATORS: popup menu item
2383
        // TRANSLATORS: skill level
2384
        _("Max level"));
2385
    mBrowserBox->addSeparator("##3---");
2386
    // TRANSLATORS: popup menu item
2387
    // TRANSLATORS: close menu
2388
    mBrowserBox->addRow("cancel", _("Cancel"));
2389
2390
    showPopup(mX, mY);
2391
}
2392
2393
void PopupMenu::showSkillTypePopup(const SkillInfo *const info)
2394
{
2395
    if (info == nullptr)
2396
        return;
2397
2398
    initPopup();
2399
    setMousePos2();
2400
2401
    // using mItemId as skill id
2402
    mItemId = info->id;
2403
    // using mItemIndex as skill level
2404
    mItemIndex = info->level;
2405
2406
    for (int f = 0; f < maxCards; f ++)
2407
        mItemCards[f] = 0;
2408
    mBrowserBox->clearRows();
2409
2410
    // TRANSLATORS: popup menu item
2411
    // TRANSLATORS: skill cast type header
2412
    mBrowserBox->addRow(_("Select skill cast type"), false);
2413
    mBrowserBox->addRow(strprintf("/selectskilltype %d 0", mItemId),
2414
        // TRANSLATORS: popup menu item
2415
        // TRANSLATORS: skill cast type
2416
        _("Default"));
2417
    mBrowserBox->addRow(strprintf("/selectskilltype %d 1", mItemId),
2418
        // TRANSLATORS: popup menu item
2419
        // TRANSLATORS: skill cast type
2420
        _("Target"));
2421
    mBrowserBox->addRow(strprintf("/selectskilltype %d 2", mItemId),
2422
        // TRANSLATORS: popup menu item
2423
        // TRANSLATORS: skill cast type
2424
        _("Mouse position"));
2425
    mBrowserBox->addRow(strprintf("/selectskilltype %d 3", mItemId),
2426
        // TRANSLATORS: popup menu item
2427
        // TRANSLATORS: skill cast type
2428
        _("Self"));
2429
    mBrowserBox->addSeparator("##3---");
2430
    // TRANSLATORS: popup menu item
2431
    // TRANSLATORS: close menu
2432
    mBrowserBox->addRow("cancel", _("Cancel"));
2433
2434
    showPopup(mX, mY);
2435
}
2436
2437
void PopupMenu::showPopup(int x, int y)
2438
{
2439
    PopupManager::hideItemPopup();
2440
    const int pad2 = 2 * mPadding;
2441
    mBrowserBox->setPosition(mPadding, mPadding);
2442
    mScrollArea->setPosition(mPadding, mPadding);
2443
    mBrowserBox->updateHeight();
2444
    // add padding to initial size before draw browserbox
2445
    int height = mBrowserBox->getHeight();
2446
    if (height + pad2 >= mainGraphics->getHeight())
2447
    {
2448
        height = mainGraphics->getHeight() - pad2;
2449
        mBrowserBox->setWidth(mBrowserBox->getWidth() + 5);
2450
        mScrollArea->setWidth(mBrowserBox->getWidth() + pad2 + 10);
2451
        setContentSize(mBrowserBox->getWidth() + pad2 + 20,
2452
            height + pad2);
2453
    }
2454
    else
2455
    {
2456
        mBrowserBox->setWidth(mBrowserBox->getWidth());
2457
        mScrollArea->setWidth(mBrowserBox->getWidth() + pad2);
2458
        setContentSize(mBrowserBox->getWidth() + pad2,
2459
            height + pad2);
2460
    }
2461
    if (mainGraphics->mWidth < (x + getWidth() + 5))
2462
        x = mainGraphics->mWidth - getWidth();
2463
    if (mainGraphics->mHeight < (y + getHeight() + 5))
2464
        y = mainGraphics->mHeight - getHeight();
2465
    mScrollArea->setHeight(height);
2466
    setPosition(x, y);
2467
    setVisible(Visible_true);
2468
    requestMoveToTop();
2469
    mAllowCleanMenu = false;
2470
}
2471
2472
void PopupMenu::addNormalRelations()
2473
{
2474
    // TRANSLATORS: popup menu item
2475
    // TRANSLATORS: add player to disregarded list
2476
    mBrowserBox->addRow("/disregard 'NAME'", _("Disregard"));
2477
    // TRANSLATORS: popup menu item
2478
    // TRANSLATORS: add player to ignore list
2479
    mBrowserBox->addRow("/ignore 'NAME'", _("Ignore"));
2480
    // TRANSLATORS: popup menu item
2481
    // TRANSLATORS: add player to black list
2482
    mBrowserBox->addRow("/blacklist 'NAME'", _("Black list"));
2483
    // TRANSLATORS: popup menu item
2484
    // TRANSLATORS: add player to enemy list
2485
    mBrowserBox->addRow("/enemy 'NAME'", _("Set as enemy"));
2486
    // TRANSLATORS: popup menu item
2487
    // TRANSLATORS: add player to erased list
2488
    mBrowserBox->addRow("/erase 'NAME'", _("Erase"));
2489
}
2490
2491
void PopupMenu::addPlayerRelation(const std::string &name)
2492
{
2493
    switch (playerRelations.getRelation(name))
2494
    {
2495
        case Relation::NEUTRAL:
2496
            // TRANSLATORS: popup menu item
2497
            // TRANSLATORS: add player to friends list
2498
            mBrowserBox->addRow("/friend 'NAME'", _("Be friend"));
2499
            addNormalRelations();
2500
            break;
2501
2502
        case Relation::FRIEND:
2503
            addNormalRelations();
2504
            break;
2505
2506
        case Relation::BLACKLISTED:
2507
            // TRANSLATORS: popup menu item
2508
            // TRANSLATORS: remove player from ignore list
2509
            mBrowserBox->addRow("/unignore 'NAME'", _("Unignore"));
2510
            // TRANSLATORS: popup menu item
2511
            // TRANSLATORS: add player to disregarded list
2512
            mBrowserBox->addRow("/disregard 'NAME'", _("Disregard"));
2513
            // TRANSLATORS: popup menu item
2514
            // TRANSLATORS: add player to ignore list
2515
            mBrowserBox->addRow("/ignore 'NAME'", _("Ignore"));
2516
            // TRANSLATORS: popup menu item
2517
            // TRANSLATORS: add player to enemy list
2518
            mBrowserBox->addRow("/enemy 'NAME'", _("Set as enemy"));
2519
            // TRANSLATORS: popup menu item
2520
            // TRANSLATORS: add player to erased list
2521
            mBrowserBox->addRow("/erase 'NAME'", _("Erase"));
2522
            break;
2523
2524
        case Relation::DISREGARDED:
2525
            // TRANSLATORS: popup menu item
2526
            // TRANSLATORS: remove player from ignore list
2527
            mBrowserBox->addRow("/unignore 'NAME'", _("Unignore"));
2528
            // TRANSLATORS: popup menu item
2529
            // TRANSLATORS: add player to completle ignore list
2530
            mBrowserBox->addRow("/ignore 'NAME'", _("Completely ignore"));
2531
            // TRANSLATORS: popup menu item
2532
            // TRANSLATORS: add player to erased list
2533
            mBrowserBox->addRow("/erase 'NAME'", _("Erase"));
2534
            break;
2535
2536
        case Relation::IGNORED:
2537
            // TRANSLATORS: popup menu item
2538
            // TRANSLATORS: remove player from ignore list
2539
            mBrowserBox->addRow("/unignore 'NAME'", _("Unignore"));
2540
            // TRANSLATORS: popup menu item
2541
            // TRANSLATORS: add player to erased list
2542
            mBrowserBox->addRow("/erase 'NAME'", _("Erase"));
2543
            break;
2544
2545
        case Relation::ENEMY2:
2546
            // TRANSLATORS: popup menu item
2547
            // TRANSLATORS: remove player from ignore list
2548
            mBrowserBox->addRow("/unignore 'NAME'", _("Unignore"));
2549
            // TRANSLATORS: popup menu item
2550
            // TRANSLATORS: add player to disregarded list
2551
            mBrowserBox->addRow("/disregard 'NAME'", _("Disregard"));
2552
            // TRANSLATORS: popup menu item
2553
            // TRANSLATORS: add player to ignore list
2554
            mBrowserBox->addRow("/ignore 'NAME'", _("Ignore"));
2555
            // TRANSLATORS: popup menu item
2556
            // TRANSLATORS: add player to black list
2557
            mBrowserBox->addRow("/blacklist 'NAME'", _("Black list"));
2558
            // TRANSLATORS: popup menu item
2559
            // TRANSLATORS: add player to erased list
2560
            mBrowserBox->addRow("/erase 'NAME'", _("Erase"));
2561
            break;
2562
2563
        case Relation::ERASED:
2564
            // TRANSLATORS: popup menu item
2565
            // TRANSLATORS: remove player from ignore list
2566
            mBrowserBox->addRow("/unignore 'NAME'", _("Unignore"));
2567
            // TRANSLATORS: popup menu item
2568
            // TRANSLATORS: add player to disregarded list
2569
            mBrowserBox->addRow("/disregard 'NAME'", _("Disregard"));
2570
            // TRANSLATORS: popup menu item
2571
            // TRANSLATORS: add player to ignore list
2572
            mBrowserBox->addRow("/ignore 'NAME'", _("Completely ignore"));
2573
            break;
2574
2575
        default:
2576
            break;
2577
    }
2578
}
2579
2580
void PopupMenu::addFollow()
2581
{
2582
    if (features.getBoolValue("allowFollow"))
2583
    {
2584
        // TRANSLATORS: popup menu item
2585
        mBrowserBox->addRow("/follow 'NAME'", _("Follow"));
2586
    }
2587
    // TRANSLATORS: popup menu item
2588
    // TRANSLATORS: imitate player
2589
    mBrowserBox->addRow("/imitation 'NAME'", _("Imitate"));
2590
}
2591
2592
void PopupMenu::addBuySell(const Being *const being)
2593
{
2594
    if ((playerRelations.getDefault() & PlayerRelation::TRADE) != 0U)
2595
    {
2596
        mBrowserBox->addSeparator("##3---");
2597
        const bool haveVending =
2598
            (Net::getNetworkType() != ServerType::TMWATHENA);
2599
        if (being->isSellShopEnabled())
2600
        {
2601
            // TRANSLATORS: popup menu item
2602
            // TRANSLATORS: buy item
2603
            mBrowserBox->addRow("/buy 'NAME'", _("Buy"));
2604
        }
2605
        else if (!haveVending)
2606
        {
2607
            // TRANSLATORS: popup menu item
2608
            // TRANSLATORS: buy item
2609
            mBrowserBox->addRow("/buy 'NAME'", _("Buy (?)"));
2610
        }
2611
        if (being->isBuyShopEnabled())
2612
        {
2613
            // TRANSLATORS: popup menu item
2614
            // TRANSLATORS: sell item
2615
            mBrowserBox->addRow("/sell 'NAME'", _("Sell"));
2616
        }
2617
        else if (!haveVending)
2618
        {
2619
            // TRANSLATORS: popup menu item
2620
            // TRANSLATORS: sell item
2621
            mBrowserBox->addRow("/sell 'NAME'", _("Sell (?)"));
2622
        }
2623
    }
2624
}
2625
2626
void PopupMenu::addBuySellDefault()
2627
{
2628
    if ((playerRelations.getDefault() & PlayerRelation::TRADE) != 0U)
2629
    {
2630
        mBrowserBox->addSeparator("##3---");
2631
        // TRANSLATORS: popup menu item
2632
        // TRANSLATORS: buy item
2633
        mBrowserBox->addRow("/buy 'NAME'", _("Buy (?)"));
2634
        // TRANSLATORS: popup menu item
2635
        // TRANSLATORS: sell item
2636
        mBrowserBox->addRow("/sell 'NAME'", _("Sell (?)"));
2637
    }
2638
}
2639
2640
void PopupMenu::addPartyName(const std::string &partyName)
2641
{
2642
    if (localPlayer->isInParty())
2643
    {
2644
        if (localPlayer->getParty() != nullptr)
2645
        {
2646
            if (localPlayer->getParty()->getName() != partyName)
2647
            {
2648
                // TRANSLATORS: popup menu item
2649
                // TRANSLATORS: invite player to party
2650
                mBrowserBox->addRow("/party 'NAME'", _("Invite to party"));
2651
            }
2652
            else
2653
            {
2654
                // TRANSLATORS: popup menu item
2655
                // TRANSLATORS: kick player from party
2656
                mBrowserBox->addRow("/kickparty 'NAME'", _("Kick from party"));
2657
                showAdoptCommands();
2658
            }
2659
            mBrowserBox->addSeparator("##3---");
2660
        }
2661
    }
2662
}
2663
2664
void PopupMenu::addParty(const std::string &nick)
2665
{
2666
    if (localPlayer->isInParty())
2667
    {
2668
        const Party *const party = localPlayer->getParty();
2669
        if (party != nullptr)
2670
        {
2671
            if (!party->isMember(nick))
2672
            {
2673
                // TRANSLATORS: popup menu item
2674
                // TRANSLATORS: invite player to party
2675
                mBrowserBox->addRow("/party 'NAME'", _("Invite to party"));
2676
            }
2677
            else
2678
            {
2679
                // TRANSLATORS: popup menu item
2680
                // TRANSLATORS: kick player from party
2681
                mBrowserBox->addRow("/kickparty 'NAME'", _("Kick from party"));
2682
                showAdoptCommands();
2683
            }
2684
            mBrowserBox->addSeparator("##3---");
2685
        }
2686
    }
2687
}
2688
2689
void PopupMenu::addChat(const Being *const being)
2690
{
2691
    if (being == nullptr)
2692
        return;
2693
    const ChatObject *const chat = being->getChat();
2694
    if (chat != nullptr)
2695
    {
2696
        mBrowserBox->addRow("join chat",
2697
            // TRANSLATORS: popup menu item
2698
            // TRANSLATORS: invite player to party
2699
            strprintf(_("Join chat %s"), chat->title.c_str()).c_str());
2700
        mBrowserBox->addSeparator("##3---");
2701
    }
2702
}
2703
2704
void PopupMenu::addPlayerMisc()
2705
{
2706
    // TRANSLATORS: popup menu item
2707
    mBrowserBox->addRow("/showitems :'BEINGID'", _("Show Items"));
2708
    // TRANSLATORS: popup menu item
2709
    // TRANSLATORS: undress player
2710
    mBrowserBox->addRow("/undress :'BEINGID'", _("Undress"));
2711
    // TRANSLATORS: popup menu item
2712
    // TRANSLATORS: add comment to player
2713
    mBrowserBox->addRow("addcomment", _("Add comment"));
2714
}
2715
2716
void PopupMenu::addPickupFilter(const std::string &name)
2717
{
2718
    if (actorManager->isInPickupList(name)
2719
        || actorManager->isInIgnorePickupList(name))
2720
    {
2721
        mBrowserBox->addRow("/removepickup 'NAME'",
2722
            // TRANSLATORS: popup menu item
2723
            // TRANSLATORS: remove item from pickup list
2724
            _("Remove from pickup list"));
2725
    }
2726
    else
2727
    {
2728
        mBrowserBox->addRow("/addpickup 'NAME'",
2729
            // TRANSLATORS: popup menu item
2730
            // TRANSLATORS: popup menu item
2731
            _("Add to pickup list"));
2732
        mBrowserBox->addRow("/ignorepickup 'NAME'",
2733
            // TRANSLATORS: popup menu item
2734
            // TRANSLATORS: add item to pickup list
2735
            _("Add to ignore list"));
2736
    }
2737
}
2738
2739
void PopupMenu::showPopup(const int x, const int y,
2740
                          ListModel *const model)
2741
{
2742
    if (model == nullptr)
2743
        return;
2744
2745
    mBrowserBox->clearRows();
2746
    for (int f = 0, sz = model->getNumberOfElements(); f < sz; f ++)
2747
    {
2748
        mBrowserBox->addRow(strprintf("dropdown_%d", f),
2749
            model->getElementAt(f).c_str());
2750
    }
2751
    // TRANSLATORS: popup menu item
2752
    // TRANSLATORS: close menu
2753
    mBrowserBox->addRow("cancel", _("Cancel"));
2754
    showPopup(x, y);
2755
}
2756
2757
void PopupMenu::clear()
2758
{
2759
    if (mDialog != nullptr)
2760
    {
2761
        mDialog->close();
2762
        mDialog = nullptr;
2763
    }
2764
    mItemIndex = -1;
2765
    mItemId = 0;
2766
    for (int f = 0; f < maxCards; f ++)
2767
        mItemCards[f] = 0;
2768
    mMapItem = nullptr;
2769
    mTab = nullptr;
2770
    mSpell = nullptr;
2771
    mCallerWindow = nullptr;
2772
    mButton = nullptr;
2773
    mTextField = nullptr;
2774
}
2775
2776
void PopupMenu::addProtection()
2777
{
2778
    if (PlayerInfo::isItemProtected(mItemId))
2779
    {
2780
        mBrowserBox->addSeparator("##3---");
2781
        // TRANSLATORS: popup menu item
2782
        // TRANSLATORS: remove protection from item
2783
        mBrowserBox->addRow("/unprotectitem 'ITEMID'", _("Unprotect item"));
2784
    }
2785
    else
2786
    {
2787
        if (mItemId < SPELL_MIN_ID)
2788
        {
2789
            mBrowserBox->addSeparator("##3---");
2790
            // TRANSLATORS: popup menu item
2791
            // TRANSLATORS: add protection to item
2792
            mBrowserBox->addRow("/protectitem 'ITEMID'", _("Protect item"));
2793
        }
2794
    }
2795
}
2796
2797
void PopupMenu::addUse(const Item *const item)
2798
{
2799
    const ItemInfo &info = item->getInfo();
2800
    const std::string &str = (item->isEquipment() == Equipm_true
2801
        && item->isEquipped() == Equipped_true)
2802
        ? info.getUseButton2() : info.getUseButton();
2803
2804
    if (str.empty())
2805
    {
2806
        // TRANSLATORS: popup menu item
2807
        mBrowserBox->addRow("/useinv 'INVINDEX'", _("Use"));
2808
    }
2809
    else
2810
    {
2811
        // TRANSLATORS: popup menu item
2812
        mBrowserBox->addRow("/useinv 'INVINDEX'", str.c_str());
2813
    }
2814
}
2815
2816
void PopupMenu::addItemMenu(const Item *const item,
2817
                            const InventoryTypeT type)
2818
{
2819
    const ItemInfo &info = item->getInfo();
2820
    const STD_VECTOR<ItemMenuItem> *menu = nullptr;
2821
    switch (type)
2822
    {
2823
        case InventoryType::Inventory:
2824
            menu = &info.getInventoryMenuConst();
2825
            break;
2826
        case InventoryType::Storage:
2827
            menu = &info.getStorageMenuConst();
2828
            break;
2829
        case InventoryType::Cart:
2830
            menu = &info.getCartMenuConst();
2831
            break;
2832
        case InventoryType::Trade:
2833
        case InventoryType::Npc:
2834
        case InventoryType::Vending:
2835
        case InventoryType::MailEdit:
2836
        case InventoryType::MailView:
2837
        case InventoryType::Craft:
2838
        case InventoryType::TypeEnd:
2839
        default:
2840
            return;
2841
    }
2842
2843
    const bool firstMode = (item->isEquipment() == Equipm_true ?
2844
        (item->isEquipped() != Equipped_true) : (item->getQuantity() == 1));
2845
2846
    FOR_EACHP (STD_VECTOR<ItemMenuItem>::const_iterator, it, menu)
2847
    {
2848
        const ItemMenuItem &menuItem = *it;
2849
        const std::string &name = firstMode ?
2850
            menuItem.name1 : menuItem.name2;
2851
        const std::string &command = firstMode ?
2852
            menuItem.command1 : menuItem.command2;
2853
        if (command.empty() ||
2854
            name.empty())
2855
        {
2856
            continue;
2857
        }
2858
        mBrowserBox->addRow("/" + command, name.c_str());
2859
    }
2860
    mBrowserBox->addSeparator("##3---");
2861
}
2862
2863
void PopupMenu::addDrop(const Item *const item,
2864
                        const bool isProtected)
2865
{
2866
    if (!isProtected)
2867
    {
2868
        mBrowserBox->addSeparator("##3---");
2869
        if (item->getQuantity() > 1)
2870
        {
2871
            // TRANSLATORS: popup menu item
2872
            // TRANSLATORS: drop item
2873
            mBrowserBox->addRow("/dropinv 'INVINDEX'", _("Drop..."));
2874
            // TRANSLATORS: popup menu item
2875
            // TRANSLATORS: drop all item amount
2876
            mBrowserBox->addRow("/dropinvall 'INVINDEX'", _("Drop all"));
2877
        }
2878
        else
2879
        {
2880
            // TRANSLATORS: popup menu item
2881
            // TRANSLATORS: drop item
2882
            mBrowserBox->addRow("/dropinv 'INVINDEX'", _("Drop"));
2883
        }
2884
    }
2885
}
2886
2887
void PopupMenu::addGmCommands()
2888
{
2889
    if (localPlayer->isGM())
2890
    {
2891
        // TRANSLATORS: popup menu item
2892
        // TRANSLATORS: gm commands
2893
        mBrowserBox->addRow("gm", _("GM..."));
2894
    }
2895
}
2896
2897
void PopupMenu::showPlayerMenu()
2898
{
2899
    mBrowserBox->clearRows();
2900
    // TRANSLATORS: popup menu header
2901
    mBrowserBox->addRow(strprintf(_("Show %s"),
2902
        mName.c_str()),
2903
        false);
2904
    if (isAllowCommand(ServerCommandType::accinfo))
2905
    {
2906
        // TRANSLATORS: popup menu item
2907
        // TRANSLATORS: show player account info
2908
        mBrowserBox->addRow("/showaccountinfo 'NAME'", _("Account info"));
2909
    }
2910
    if (isAllowOtherCommand(ServerCommandType::exp))
2911
    {
2912
        // TRANSLATORS: popup menu item
2913
        // TRANSLATORS: show player level
2914
        mBrowserBox->addRow("/showlevel 'NAME'", _("Level"));
2915
    }
2916
    if (isAllowOtherCommand(ServerCommandType::stats))
2917
    {
2918
        // TRANSLATORS: popup menu item
2919
        // TRANSLATORS: show player stats
2920
        mBrowserBox->addRow("/showstats 'NAME'", _("Stats"));
2921
    }
2922
    if (isAllowOtherCommand(ServerCommandType::itemlist))
2923
    {
2924
        // TRANSLATORS: popup menu item
2925
        // TRANSLATORS: show player inventory list
2926
        mBrowserBox->addRow("/showinventory 'NAME'", _("Inventory"));
2927
    }
2928
    if (isAllowOtherCommand(ServerCommandType::storagelist))
2929
    {
2930
        // TRANSLATORS: popup menu item
2931
        // TRANSLATORS: show player storage list
2932
        mBrowserBox->addRow("/showstorage 'NAME'", _("Storage"));
2933
    }
2934
    if (isAllowOtherCommand(ServerCommandType::cartlist))
2935
    {
2936
        // TRANSLATORS: popup menu item
2937
        // TRANSLATORS: show player cart list
2938
        mBrowserBox->addRow("/showcart 'NAME'", _("Cart"));
2939
    }
2940
    if (isAllowOtherCommand(ServerCommandType::commands))
2941
    {
2942
        // TRANSLATORS: popup menu item
2943
        // TRANSLATORS: gm commands
2944
        mBrowserBox->addRow("/gmcommands 'NAME'", _("Commands"));
2945
    }
2946
    if (isAllowOtherCommand(ServerCommandType::charcommands))
2947
    {
2948
        // TRANSLATORS: popup menu item
2949
        // TRANSLATORS: gm char commands
2950
        mBrowserBox->addRow("/gmcharcommands 'NAME'", _("Char commands"));
2951
    }
2952
    // TRANSLATORS: popup menu item
2953
    // TRANSLATORS: back to gm menu
2954
    mBrowserBox->addRow("gm", _("Back"));
2955
    // TRANSLATORS: popup menu item
2956
    // TRANSLATORS: close menu
2957
    mBrowserBox->addRow("cancel", _("Cancel"));
2958
    showPopup(getX(), getY());
2959
}
2960
2961
void PopupMenu::showPlayerGMCommands(const std::string &name)
2962
{
2963
    if (localPlayer == nullptr)
2964
        return;
2965
    const bool legacy = Net::getNetworkType() == ServerType::TMWATHENA;
2966
    if (!legacy && isAllowCommand(ServerCommandType::where))
2967
    {
2968
        // TRANSLATORS: popup menu item
2969
        // TRANSLATORS: find player position
2970
        mBrowserBox->addRow("/locateplayer 'NAME'", _("Locate"));
2971
    }
2972
    if (legacy)
2973
    {
2974
        // TRANSLATORS: popup menu item
2975
        // TRANSLATORS: check player ip
2976
        mBrowserBox->addRow("/ipcheck 'NAME'", _("Check ip"));
2977
    }
2978
    if (isAllowCommand(ServerCommandType::jumpto))
2979
    {
2980
        // TRANSLATORS: popup menu item
2981
        // TRANSLATORS: go to player position
2982
        mBrowserBox->addRow("/gotopc 'NAME'", _("Goto"));
2983
    }
2984
    if (isAllowCommand(ServerCommandType::recall))
2985
    {
2986
        // TRANSLATORS: popup menu item
2987
        // TRANSLATORS: recall player to current position
2988
        mBrowserBox->addRow("/recallpc 'NAME'", _("Recall"));
2989
    }
2990
    if (isAllowOtherCommand(ServerCommandType::alive))
2991
    {
2992
        // TRANSLATORS: popup menu item
2993
        // TRANSLATORS: revive player
2994
        mBrowserBox->addRow("/alive 'NAME'", _("Revive"));
2995
    }
2996
    if (!legacy)
2997
    {
2998
        Being *const being = actorManager->findBeingByName(name,
2999
            ActorType::Player);
3000
        if (being != nullptr && being == localPlayer)
3001
        {
3002
            if (!being->getPartyName().empty() &&
3003
                isAllowCommand(ServerCommandType::partyrecall))
3004
            {
3005
                mBrowserBox->addRow("/partyrecall 'PARTY'",
3006
                    // TRANSLATORS: popup menu item
3007
                    // TRANSLATORS: recall all party members to player location
3008
                    _("Recall party"));
3009
            }
3010
            if (!being->getGuildName().empty() &&
3011
                isAllowCommand(ServerCommandType::guildrecall))
3012
            {
3013
                mBrowserBox->addRow("/guildrecall 'PARTY'",
3014
                    // TRANSLATORS: popup menu item
3015
                    // TRANSLATORS: recall all guild members to player location
3016
                    _("Recall guild"));
3017
            }
3018
        }
3019
        if (localPlayer->isInParty())
3020
        {
3021
            const Party *const party = localPlayer->getParty();
3022
            if (party != nullptr &&
3023
                party->isMember(name) &&
3024
                isAllowCommand(ServerCommandType::changeleader))
3025
            {
3026
                mBrowserBox->addRow("/gmpartyleader 'NAME'",
3027
                    // TRANSLATORS: popup menu item
3028
                    // TRANSLATORS: give party leader status
3029
                    _("Give party leader"));
3030
            }
3031
        }
3032
3033
        if (isAllowCommand(ServerCommandType::nuke))
3034
        {
3035
            // TRANSLATORS: popup menu item
3036
            // TRANSLATORS: nuke player
3037
            mBrowserBox->addRow("/gmnuke 'NAME'", _("Nuke"));
3038
        }
3039
        if (isAllowOtherCommand(ServerCommandType::kill))
3040
        {
3041
            // TRANSLATORS: popup menu item
3042
            // TRANSLATORS: kill player
3043
            mBrowserBox->addRow("/kill 'NAME'", _("Kill"));
3044
        }
3045
        if (mBeingId != BeingId_zero)
3046
        {
3047
            mBrowserBox->addSeparator("##3---");
3048
            // TRANSLATORS: popup menu item
3049
            // TRANSLATORS: show menu
3050
            mBrowserBox->addRow("show", _("Show..."));
3051
            // TRANSLATORS: popup menu item
3052
            // TRANSLATORS: mute menu
3053
            mBrowserBox->addRow("mute", _("Mute..."));
3054
        }
3055
    }
3056
    if (legacy)
3057
    {
3058
        if (localPlayer->getName() == mName)
3059
        {
3060
            // TRANSLATORS: popup menu item
3061
            // TRANSLATORS: hide player
3062
            mBrowserBox->addRow("/hide", _("Hide"));
3063
            mBrowserBox->addSeparator("##3---");
3064
        }
3065
    }
3066
    else
3067
    {
3068
        if (isAllowOtherCommand(ServerCommandType::heal))
3069
        {
3070
            // TRANSLATORS: popup menu item
3071
            // TRANSLATORS: heal player
3072
            mBrowserBox->addRow("/gmheal 'NAME'", _("Heal"));
3073
        }
3074
        if (isAllowOtherCommand(ServerCommandType::monsterignore))
3075
        {
3076
            // TRANSLATORS: popup menu item
3077
            // TRANSLATORS: enable immortal mode for player
3078
            mBrowserBox->addRow("/immortal 'NAME'", _("Immortal"));
3079
        }
3080
        if (isAllowCommand(ServerCommandType::jail))
3081
        {
3082
            // TRANSLATORS: popup menu item
3083
            // TRANSLATORS: send player to jail
3084
            mBrowserBox->addRow("/jail 'NAME'", _("Jail"));
3085
        }
3086
        if (isAllowCommand(ServerCommandType::unjail))
3087
        {
3088
            // TRANSLATORS: popup menu item
3089
            // TRANSLATORS: restore player from jail
3090
            mBrowserBox->addRow("/unjail 'NAME'", _("Unjail"));
3091
        }
3092
        if (name == localPlayer->getName() &&
3093
            isAllowCommand(ServerCommandType::hide))
3094
        {
3095
            // TRANSLATORS: popup menu item
3096
            // TRANSLATORS: hide player
3097
            mBrowserBox->addRow("/hide 'NAME'", _("Hide"));
3098
        }
3099
        mBrowserBox->addSeparator("##3---");
3100
        if (isAllowOtherCommand(ServerCommandType::killer))
3101
        {
3102
            // TRANSLATORS: popup menu item
3103
            // TRANSLATORS: set player as killer
3104
            mBrowserBox->addRow("/killer 'NAME'", _("Killer"));
3105
        }
3106
        if (isAllowOtherCommand(ServerCommandType::killable))
3107
        {
3108
            // TRANSLATORS: popup menu item
3109
            // TRANSLATORS: set player as killable
3110
            mBrowserBox->addRow("/killable 'NAME'", _("Killable"));
3111
        }
3112
        if (isAllowOtherCommand(ServerCommandType::save))
3113
        {
3114
            // TRANSLATORS: popup menu item
3115
            // TRANSLATORS: set player save position
3116
            mBrowserBox->addRow("/savepos 'NAME'", _("Set save"));
3117
        }
3118
        if (isAllowOtherCommand(ServerCommandType::load))
3119
        {
3120
            // TRANSLATORS: popup menu item
3121
            // TRANSLATORS: warp player to save position
3122
            mBrowserBox->addRow("/loadpos 'NAME'", _("Warp to save"));
3123
        }
3124
        if (isAllowOtherCommand(ServerCommandType::jump))
3125
        {
3126
            // TRANSLATORS: popup menu item
3127
            // TRANSLATORS: warp player to random position on same map
3128
            mBrowserBox->addRow("/randomwarp 'NAME'", _("Warp to random"));
3129
        }
3130
        mBrowserBox->addSeparator("##3---");
3131
        if (isAllowCommand(ServerCommandType::clone))
3132
        {
3133
            // TRANSLATORS: popup menu item
3134
            // TRANSLATORS: spawn player clone
3135
            mBrowserBox->addRow("/spawnclone 'NAME'", _("Spawn clone"));
3136
        }
3137
        if (isAllowCommand(ServerCommandType::slaveclone))
3138
        {
3139
            mBrowserBox->addRow("/spawnslaveclone 'NAME'",
3140
                // TRANSLATORS: popup menu item
3141
                // TRANSLATORS: spawn slave player clone
3142
                _("Spawn slave clone"));
3143
        }
3144
        if (isAllowCommand(ServerCommandType::evilclone))
3145
        {
3146
            mBrowserBox->addRow("/spawnevilclone 'NAME'",
3147
                // TRANSLATORS: popup menu item
3148
                // TRANSLATORS: spawn evil player clone
3149
                _("Spawn evil clone"));
3150
        }
3151
        mBrowserBox->addSeparator("##3---");
3152
        if (isAllowOtherCommand(ServerCommandType::breakguild))
3153
        {
3154
            // TRANSLATORS: popup menu item
3155
            // TRANSLATORS: break guild
3156
            mBrowserBox->addRow("/gmbreakguild 'NAME'", _("Break guild"));
3157
        }
3158
    }
3159
    if (mBeingId != BeingId_zero &&
3160
        isAllowCommand(ServerCommandType::kick))
3161
    {
3162
        mBrowserBox->addSeparator("##3---");
3163
        // TRANSLATORS: popup menu item
3164
        // TRANSLATORS: kick player
3165
        mBrowserBox->addRow("/kick :'BEINGID'", _("Kick"));
3166
    }
3167
}
3168
3169
void PopupMenu::showMuteCommands()
3170
{
3171
    mBrowserBox->clearRows();
3172
    // TRANSLATORS: popup menu header
3173
    mBrowserBox->addRow(strprintf(_("Mute %s"),
3174
        mName.c_str()),
3175
        false);
3176
    if (mBeingId != BeingId_zero &&
3177
        Net::getNetworkType() != ServerType::TMWATHENA &&
3178
        isAllowCommand(ServerCommandType::mute))
3179
    {
3180
        mBrowserBox->addRow("mute_+1",
3181
            // TRANSLATORS: popup menu item
3182
            // TRANSLATORS: mute player
3183
            strprintf(_("Mute %d"), 1).c_str());
3184
        mBrowserBox->addRow("mute_+5",
3185
            // TRANSLATORS: popup menu item
3186
            // TRANSLATORS: mute player
3187
            strprintf(_("Mute %d"), 5).c_str());
3188
        mBrowserBox->addRow("mute_+10",
3189
            // TRANSLATORS: popup menu item
3190
            // TRANSLATORS: mute player
3191
            strprintf(_("Mute %d"), 10).c_str());
3192
        mBrowserBox->addRow("mute_+15",
3193
            // TRANSLATORS: popup menu item
3194
            // TRANSLATORS: mute player
3195
            strprintf(_("Mute %d"), 15).c_str());
3196
        mBrowserBox->addRow("mute_+30",
3197
            // TRANSLATORS: popup menu item
3198
            // TRANSLATORS: mute player
3199
            strprintf(_("Mute %d"), 30).c_str());
3200
3201
        mBrowserBox->addRow("mute_-1",
3202
            // TRANSLATORS: popup menu item
3203
            // TRANSLATORS: mute player
3204
            strprintf(_("Unmute %d"), 1).c_str());
3205
        mBrowserBox->addRow("mute_-5",
3206
            // TRANSLATORS: popup menu item
3207
            // TRANSLATORS: mute player
3208
            strprintf(_("Unmute %d"), 5).c_str());
3209
        mBrowserBox->addRow("mute_-10",
3210
            // TRANSLATORS: popup menu item
3211
            // TRANSLATORS: mute player
3212
            strprintf(_("Unmute %d"), 10).c_str());
3213
        mBrowserBox->addRow("mute_-15",
3214
            // TRANSLATORS: popup menu item
3215
            // TRANSLATORS: mute player
3216
            strprintf(_("Unmute %d"), 15).c_str());
3217
        mBrowserBox->addRow("mute_-30",
3218
            // TRANSLATORS: popup menu item
3219
            // TRANSLATORS: mute player
3220
            strprintf(_("Unmute %d"), 30).c_str());
3221
        mBrowserBox->addSeparator("##3---");
3222
    }
3223
    // TRANSLATORS: popup menu item
3224
    // TRANSLATORS: back to gm menu
3225
    mBrowserBox->addRow("gm", _("Back"));
3226
    // TRANSLATORS: popup menu item
3227
    // TRANSLATORS: close menu
3228
    mBrowserBox->addRow("cancel", _("Cancel"));
3229
    showPopup(getX(), getY());
3230
}
3231
3232
void PopupMenu::showNpcGMCommands()
3233
{
3234
    if (mBeingId != BeingId_zero)
3235
    {
3236
        if (isAllowCommand(ServerCommandType::kick))
3237
        {
3238
            // TRANSLATORS: popup menu item
3239
            // TRANSLATORS: kick player
3240
            mBrowserBox->addRow("/kick :'BEINGID'", _("Kick"));
3241
        }
3242
        const bool legacy = Net::getNetworkType() == ServerType::TMWATHENA;
3243
        if (!legacy)
3244
        {
3245
            if (isAllowCommand(ServerCommandType::hidenpc))
3246
            {
3247
                // TRANSLATORS: popup menu item
3248
                // TRANSLATORS: hide npc
3249
                mBrowserBox->addRow("/hidenpc 'EXTNAME'", _("Hide"));
3250
            }
3251
            mBrowserBox->addSeparator("##3---");
3252
            if (isAllowCommand(ServerCommandType::npcmove))
3253
            {
3254
                mBrowserBox->addRow("/npcmove 'EEXTNAME' 'PLAYERX' 'PLAYERY'",
3255
                    // TRANSLATORS: popup menu item
3256
                    // TRANSLATORS: warp npc to player location
3257
                    _("Recall"));
3258
            }
3259
            if (isAllowCommand(ServerCommandType::disguise))
3260
            {
3261
                mBrowserBox->addRow("/disguise 'BEINGSUBTYPEID'",
3262
                    // TRANSLATORS: popup menu item
3263
                    // TRANSLATORS: disguise to npc
3264
                    _("Disguise"));
3265
            }
3266
            if (isAllowCommand(ServerCommandType::tonpc))
3267
            {
3268
                // TRANSLATORS: popup menu item
3269
                // TRANSLATORS: warp to npc
3270
                mBrowserBox->addRow("/gotonpc 'EXTNAME'", _("Goto"));
3271
            }
3272
        }
3273
    }
3274
}
3275
3276
void PopupMenu::showMonsterGMCommands()
3277
{
3278
    if (mBeingId != BeingId_zero)
3279
    {
3280
        const bool legacy = Net::getNetworkType() == ServerType::TMWATHENA;
3281
        if (isAllowCommand(ServerCommandType::kick))
3282
        {
3283
            // TRANSLATORS: popup menu item
3284
            // TRANSLATORS: kick monster
3285
            mBrowserBox->addRow("/kick :'BEINGID'", _("Kick"));
3286
        }
3287
        if (isAllowCommand(ServerCommandType::monster))
3288
        {
3289
            // TRANSLATORS: popup menu item
3290
            // TRANSLATORS: spawn monster
3291
            mBrowserBox->addRow("/spawn 'BEINGSUBTYPEID'", _("Spawn same"));
3292
        }
3293
        if (!legacy)
3294
        {
3295
            if (isAllowCommand(ServerCommandType::summon))
3296
            {
3297
                mBrowserBox->addRow("/spawnslave 'BEINGSUBTYPEID'",
3298
                    // TRANSLATORS: popup menu item
3299
                    // TRANSLATORS: spawn slave monster
3300
                    _("Spawn slave"));
3301
            }
3302
            if (isAllowCommand(ServerCommandType::disguise))
3303
            {
3304
                mBrowserBox->addRow("/disguise 'BEINGSUBTYPEID'",
3305
                    // TRANSLATORS: popup menu item
3306
                    // TRANSLATORS: disguise to monster
3307
                    _("Disguise"));
3308
            }
3309
            mBrowserBox->addSeparator("##3---");
3310
            if (isAllowCommand(ServerCommandType::mobinfo))
3311
            {
3312
                mBrowserBox->addRow("/monsterinfo 'BEINGSUBTYPEID'",
3313
                    // TRANSLATORS: popup menu item
3314
                    // TRANSLATORS: show monster information
3315
                    _("Info"));
3316
            }
3317
            if (isAllowCommand(ServerCommandType::mobsearch))
3318
            {
3319
                mBrowserBox->addRow("/mobsearch 'BEINGSUBTYPEID'",
3320
                    // TRANSLATORS: popup menu item
3321
                    // TRANSLATORS: show selected monster in current map
3322
                    _("Search"));
3323
            }
3324
            if (isAllowCommand(ServerCommandType::whereis))
3325
            {
3326
                mBrowserBox->addRow("/mobspawnsearch 'BEINGSUBTYPEID'",
3327
                    // TRANSLATORS: popup menu item
3328
                    // TRANSLATORS: show selected monster spawns in all maps
3329
                    _("Search spawns"));
3330
            }
3331
        }
3332
    }
3333
}
3334
3335
void PopupMenu::showFloorItemGMCommands()
3336
{
3337
    const bool legacy = Net::getNetworkType() == ServerType::TMWATHENA;
3338
    if (legacy)
3339
        return;
3340
    if (isAllowCommand(ServerCommandType::iteminfo))
3341
    {
3342
        // TRANSLATORS: popup menu item
3343
        // TRANSLATORS: show item information
3344
        mBrowserBox->addRow("/iteminfo 'ITEMID'", _("Info"));
3345
    }
3346
    if (isAllowCommand(ServerCommandType::whodrops))
3347
    {
3348
        // TRANSLATORS: popup menu item
3349
        // TRANSLATORS: show who drops item
3350
        mBrowserBox->addRow("/whodrops 'ITEMID'", _("Who drops"));
3351
    }
3352
}
3353
3354
void PopupMenu::showItemGMCommands()
3355
{
3356
    const bool legacy = Net::getNetworkType() == ServerType::TMWATHENA;
3357
    if (legacy)
3358
        return;
3359
    if (isAllowCommand(ServerCommandType::iteminfo))
3360
    {
3361
        // TRANSLATORS: popup menu item
3362
        // TRANSLATORS: show item information
3363
        mBrowserBox->addRow("/iteminfo 'ITEMID'", _("Info"));
3364
    }
3365
    if (isAllowCommand(ServerCommandType::whodrops))
3366
    {
3367
        // TRANSLATORS: popup menu item
3368
        // TRANSLATORS: show who drops item
3369
        mBrowserBox->addRow("/whodrops 'ITEMID'", _("Who drops"));
3370
    }
3371
    mBrowserBox->addSeparator("##3---");
3372
    if (isAllowCommand(ServerCommandType::item))
3373
    {
3374
        // TRANSLATORS: popup menu item
3375
        // TRANSLATORS: gm create item
3376
        mBrowserBox->addRow("/createitem 'ITEMID' 1", _("Add 1"));
3377
        // TRANSLATORS: popup menu item
3378
        // TRANSLATORS: gm create item
3379
        mBrowserBox->addRow("/createitem 'ITEMID' 5", _("Add 5"));
3380
        // TRANSLATORS: popup menu item
3381
        // TRANSLATORS: gm create item
3382
        mBrowserBox->addRow("/createitem 'ITEMID' 10", _("Add 10"));
3383
        // TRANSLATORS: popup menu item
3384
        // TRANSLATORS: gm create item
3385
        mBrowserBox->addRow("/createitem 'ITEMID' 100", _("Add 100"));
3386
        // TRANSLATORS: popup menu item
3387
        // TRANSLATORS: gm create item
3388
        mBrowserBox->addRow("/createitem 'ITEMID' 1000", _("Add 1000"));
3389
        // TRANSLATORS: popup menu item
3390
        // TRANSLATORS: gm create item
3391
        mBrowserBox->addRow("/createitem 'ITEMID' 10000", _("Add 10000"));
3392
    }
3393
}
3394
3395
void PopupMenu::showGMPopup(const std::string &name)
3396
{
3397
    mBrowserBox->clearRows();
3398
    // TRANSLATORS: popup menu header
3399
    mBrowserBox->addRow(_("GM commands"), false);
3400
    if (localPlayer->isGM())
3401
    {
3402
        switch (mType)
3403
        {
3404
            case ActorType::Player:
3405
                showPlayerGMCommands(name);
3406
                break;
3407
            case ActorType::Npc:
3408
                showNpcGMCommands();
3409
                break;
3410
            case ActorType::Monster:
3411
                showMonsterGMCommands();
3412
                break;
3413
            case ActorType::FloorItem:
3414
                showFloorItemGMCommands();
3415
                break;
3416
            case ActorType::Homunculus:
3417
                showHomunGMCommands();
3418
                break;
3419
            case ActorType::Pet:
3420
                showPetGMCommands();
3421
                break;
3422
            case ActorType::Mercenary:
3423
                showMercenaryGMCommands();
3424
                break;
3425
            case ActorType::SkillUnit:
3426
                break;
3427
            default:
3428
            case ActorType::Unknown:
3429
                if (mItemId != 0)
3430
                    showItemGMCommands();
3431
                break;
3432
            case ActorType::Portal:
3433
            case ActorType::Avatar:
3434
            case ActorType::Elemental:
3435
                break;
3436
        }
3437
    }
3438
3439
    mBrowserBox->addSeparator("##3---");
3440
    // TRANSLATORS: popup menu item
3441
    // TRANSLATORS: close menu
3442
    mBrowserBox->addRow("cancel", _("Cancel"));
3443
3444
    showPopup(getX(), getY());
3445
}
3446
3447
void PopupMenu::showHomunGMCommands()
3448
{
3449
}
3450
3451
void PopupMenu::showPetGMCommands()
3452
{
3453
}
3454
3455
void PopupMenu::showMercenaryGMCommands()
3456
{
3457
}
3458
3459
void PopupMenu::showCraftPopup()
3460
{
3461
    mBrowserBox->clearRows();
3462
3463
    for (int f = 0; f < 9; f ++)
3464
    {
3465
        const std::string cmd = strprintf("/craft %d", f);
3466
        mBrowserBox->addRow(cmd,
3467
            // TRANSLATORS: popup menu item
3468
            // TRANSLATORS: move current item to craft slot
3469
            strprintf(_("Move to craft %d"), f + 1).c_str());
3470
    }
3471
3472
    // TRANSLATORS: popup menu item
3473
    // TRANSLATORS: close menu
3474
    mBrowserBox->addRow("cancel", _("Cancel"));
3475
3476
    showPopup(mX, mY);
3477
}
3478
3479
void PopupMenu::addMailCommands()
3480
{
3481
    if (Net::getNetworkType() == ServerType::TMWATHENA)
3482
        return;
3483
3484
    // TRANSLATORS: popup menu item
3485
    // TRANSLATORS: open mail dialog
3486
    mBrowserBox->addRow("/mailto 'NAME'", _("Mail to..."));
3487
}
3488
3489
void PopupMenu::addCatchPetCommands()
3490
{
3491
    if (Net::getNetworkType() == ServerType::TMWATHENA)
3492
        return;
3493
    // TRANSLATORS: popup menu item
3494
    // TRANSLATORS: catch pet command
3495
    mBrowserBox->addRow("/catchpet :'BEINGID'", _("Taming pet"));
3496
}
3497
3498
void PopupMenu::showAdoptCommands()
3499
{
3500
    if (Net::getNetworkType() == ServerType::TMWATHENA)
3501
        return;
3502
    // TRANSLATORS: popup menu item
3503
    // TRANSLATORS: adopt child command
3504
    mBrowserBox->addRow("/adoptchild 'NAME'", _("Adopt child"));
3505
}
3506
3507
void PopupMenu::addSocialMenu()
3508
{
3509
    initPopup();
3510
    mBrowserBox->clearRows();
3511
    setMousePos();
3512
    const Party *const party = localPlayer->getParty();
3513
    if (party != nullptr)
3514
    {
3515
        // TRANSLATORS: popup menu item
3516
        // TRANSLATORS: leave party
3517
        mBrowserBox->addRow("/leaveparty", _("Leave party"));
3518
    }
3519
    else
3520
    {
3521
        // TRANSLATORS: popup menu item
3522
        // TRANSLATORS: create party
3523
        mBrowserBox->addRow("/createparty", _("Create party"));
3524
    }
3525
3526
    if (Net::getNetworkType() != ServerType::TMWATHENA)
3527
    {
3528
        const Guild *const guild = localPlayer->getGuild();
3529
        if (guild != nullptr)
3530
        {
3531
            // TRANSLATORS: popup menu item
3532
            // TRANSLATORS: leave guild
3533
            mBrowserBox->addRow("/leaveguild", _("Leave guild"));
3534
        }
3535
        else
3536
        {
3537
            // TRANSLATORS: popup menu item
3538
            // TRANSLATORS: create guild
3539
            mBrowserBox->addRow("/createguild", _("Create guild"));
3540
        }
3541
    }
3542
    mBrowserBox->addSeparator("##3---");
3543
}
3544
3545
void PopupMenu::showPartyPopup()
3546
{
3547
    addSocialMenu();
3548
3549
    // TRANSLATORS: popup menu item
3550
    // TRANSLATORS: close menu
3551
    mBrowserBox->addRow("cancel", _("Cancel"));
3552
    showPopup(mX, mY);
3553
}
3554
3555
void PopupMenu::showGuildPopup()
3556
{
3557
    addSocialMenu();
3558
3559
    // TRANSLATORS: popup menu item
3560
    // TRANSLATORS: change guild notice message
3561
    mBrowserBox->addRow("/guildnotice", _("Change notice"));
3562
3563
    // TRANSLATORS: popup menu item
3564
    // TRANSLATORS: close menu
3565
    mBrowserBox->addRow("cancel", _("Cancel"));
3566
    showPopup(mX, mY);
3567
}
3568
3569
void PopupMenu::showAttackPopup()
3570
{
3571
    addSocialMenu();
3572
3573
    // TRANSLATORS: popup menu item
3574
    // TRANSLATORS: close menu
3575
    mBrowserBox->addRow("cancel", _("Cancel"));
3576
    showPopup(mX, mY);
3577
}
3578
3579
void PopupMenu::showNavigationPopup()
3580
{
3581
    addSocialMenu();
3582
3583
    // TRANSLATORS: popup menu item
3584
    // TRANSLATORS: close menu
3585
    mBrowserBox->addRow("cancel", _("Cancel"));
3586
    showPopup(mX, mY);
3587
}
3588
3589
void PopupMenu::showPickupPopup()
3590
{
3591
    addSocialMenu();
3592
3593
    // TRANSLATORS: popup menu item
3594
    // TRANSLATORS: close menu
3595
    mBrowserBox->addRow("cancel", _("Cancel"));
3596
    showPopup(mX, mY);
3597
}
3598
3599
void PopupMenu::showPlayersPopup()
3600
{
3601
    addSocialMenu();
3602
3603
    // TRANSLATORS: popup menu item
3604
    // TRANSLATORS: close menu
3605
    mBrowserBox->addRow("cancel", _("Cancel"));
3606
    showPopup(mX, mY);
3607
}
3608
3609
void PopupMenu::showFriendsPopup()
3610
{
3611
    addSocialMenu();
3612
3613
    // TRANSLATORS: popup menu item
3614
    // TRANSLATORS: close menu
3615
    mBrowserBox->addRow("cancel", _("Cancel"));
3616
    showPopup(mX, mY);
3617
}
3618
3619
void PopupMenu::moveUp()
3620
{
3621
    mBrowserBox->moveSelectionUp();
3622
}
3623
3624
void PopupMenu::moveDown()
3625
{
3626
    mBrowserBox->moveSelectionDown();
3627
}
3628
3629
void PopupMenu::select()
3630
{
3631
    mBrowserBox->selectSelection();
3632

3
}