GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/progs/manaplus/actions/commands.cpp Lines: 1 942 0.1 %
Date: 2021-03-17 Branches: 0 1019 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2012-2019  The ManaPlus Developers
4
 *  Copyright (C) 2019-2021  Andrei Karas
5
 *
6
 *  This file is part of The ManaPlus Client.
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License as published by
10
 *  the Free Software Foundation; either version 2 of the License, or
11
 *  any later version.
12
 *
13
 *  This program is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *  GNU General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU General Public License
19
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
#include "actions/commands.h"
23
24
#include "actormanager.h"
25
#include "configuration.h"
26
#include "game.h"
27
#include "party.h"
28
29
#include "actions/actiondef.h"
30
31
#include "being/flooritem.h"
32
#include "being/localplayer.h"
33
#include "being/playerrelations.h"
34
#include "being/homunculusinfo.h"
35
#include "being/playerinfo.h"
36
37
#include "const/resources/skill.h"
38
39
#include "gui/viewport.h"
40
41
#include "gui/popups/popupmenu.h"
42
43
#include "gui/shortcut/emoteshortcut.h"
44
#include "gui/shortcut/itemshortcut.h"
45
46
#include "gui/windows/mailwindow.h"
47
48
#include "gui/windows/chatwindow.h"
49
#include "gui/windows/inventorywindow.h"
50
#include "gui/windows/npcdialog.h"
51
#include "gui/windows/outfitwindow.h"
52
#include "gui/windows/shortcutwindow.h"
53
#include "gui/windows/skilldialog.h"
54
#include "gui/windows/socialwindow.h"
55
56
#include "gui/widgets/tabs/chat/whispertab.h"
57
58
#include "input/inputactionoperators.h"
59
60
#include "listeners/inputactionreplaylistener.h"
61
62
#include "net/adminhandler.h"
63
#include "net/chathandler.h"
64
#include "net/guildhandler.h"
65
#include "net/familyhandler.h"
66
#include "net/homunculushandler.h"
67
#include "net/mail2handler.h"
68
#include "net/mailhandler.h"
69
#include "net/net.h"
70
#include "net/npchandler.h"
71
#include "net/partyhandler.h"
72
#include "net/serverfeatures.h"
73
74
#include "resources/chatobject.h"
75
76
#include "resources/db/itemdb.h"
77
78
#include "resources/map/map.h"
79
80
#include "resources/skill/skillinfo.h"
81
82
#include "utils/booleanoptions.h"
83
#include "utils/chatutils.h"
84
#include "utils/copynpaste.h"
85
#include "utils/gmfunctions.h"
86
#include "utils/parameters.h"
87
#include "utils/process.h"
88
89
#ifdef HAVE_MALLOC_TRIM
90
#include <malloc.h>
91
#endif
92
93
#include "debug.h"
94
95
namespace Actions
96
{
97
98
static std::string getNick(const InputEvent &event)
99
{
100
    std::string args = event.args;
101
    if (args.empty())
102
    {
103
        if (event.tab == nullptr ||
104
            event.tab->getType() != ChatTabType::WHISPER)
105
        {
106
            return std::string();
107
        }
108
109
        WhisperTab *const whisper = static_cast<WhisperTab *>(event.tab);
110
        if (whisper->getNick().empty())
111
        {
112
            // TRANSLATORS: change relation
113
            event.tab->chatLog(_("Please specify a name."),
114
                ChatMsgType::BY_SERVER,
115
                IgnoreRecord_false,
116
                TryRemoveColors_true);
117
            return std::string();
118
        }
119
        args = whisper->getNick();
120
    }
121
    return args;
122
}
123
124
static void reportRelation(const InputEvent &event,
125
                           const RelationT &rel,
126
                           const std::string &str1,
127
                           const std::string &str2)
128
{
129
    if (event.tab != nullptr)
130
    {
131
        if (playerRelations.getRelation(event.args) == rel)
132
        {
133
            // TRANSLATORS: unignore command
134
            event.tab->chatLog(str1,
135
                ChatMsgType::BY_SERVER,
136
                IgnoreRecord_false,
137
                TryRemoveColors_true);
138
        }
139
        else
140
        {
141
            // TRANSLATORS: unignore command
142
            event.tab->chatLog(str2,
143
                ChatMsgType::BY_SERVER,
144
                IgnoreRecord_false,
145
                TryRemoveColors_true);
146
        }
147
    }
148
}
149
150
static void changeRelation(const InputEvent &event,
151
                           const RelationT relation,
152
                           const std::string &relationText)
153
{
154
    std::string args = getNick(event);
155
    if (args.empty())
156
        return;
157
158
    if (playerRelations.getRelation(args) == relation)
159
    {
160
        if (event.tab != nullptr)
161
        {
162
            // TRANSLATORS: change relation
163
            event.tab->chatLog(strprintf(_("Player already %s!"),
164
                relationText.c_str()),
165
                ChatMsgType::BY_SERVER,
166
                IgnoreRecord_false,
167
                TryRemoveColors_true);
168
            return;
169
        }
170
    }
171
    else
172
    {
173
        playerRelations.setRelation(args, relation);
174
    }
175
176
    reportRelation(event,
177
        relation,
178
        // TRANSLATORS: change relation
179
        strprintf(_("Player successfully %s!"), relationText.c_str()),
180
        // TRANSLATORS: change relation
181
        strprintf(_("Player could not be %s!"), relationText.c_str()));
182
}
183
184
impHandler(chatAnnounce)
185
{
186
    if (adminHandler != nullptr)
187
    {
188
        adminHandler->announce(event.args);
189
        return true;
190
    }
191
    return false;
192
}
193
194
impHandler(chatIgnore)
195
{
196
    changeRelation(event, Relation::IGNORED, "ignored");
197
    return true;
198
}
199
200
impHandler(chatUnignore)
201
{
202
    std::string args = getNick(event);
203
    if (args.empty())
204
        return false;
205
206
    const RelationT rel = playerRelations.getRelation(args);
207
    if (rel != Relation::NEUTRAL && rel != Relation::FRIEND)
208
    {
209
        playerRelations.setRelation(args, Relation::NEUTRAL);
210
    }
211
    else
212
    {
213
        if (event.tab != nullptr)
214
        {
215
            // TRANSLATORS: unignore command
216
            event.tab->chatLog(_("Player wasn't ignored!"),
217
                ChatMsgType::BY_SERVER,
218
                IgnoreRecord_false,
219
                TryRemoveColors_true);
220
        }
221
        return true;
222
    }
223
224
    reportRelation(event,
225
        Relation::NEUTRAL,
226
        // TRANSLATORS: unignore command
227
        _("Player no longer ignored!"),
228
        // TRANSLATORS: unignore command
229
        _("Player could not be unignored!"));
230
    return true;
231
}
232
233
impHandler(chatErase)
234
{
235
    std::string args = getNick(event);
236
    if (args.empty())
237
        return false;
238
239
    if (playerRelations.getRelation(args) == Relation::ERASED)
240
    {
241
        if (event.tab != nullptr)
242
        {
243
            // TRANSLATORS: erase command
244
            event.tab->chatLog(_("Player already erased!"),
245
                ChatMsgType::BY_SERVER,
246
                IgnoreRecord_false,
247
                TryRemoveColors_true);
248
        }
249
        return true;
250
    }
251
    playerRelations.setRelation(args, Relation::ERASED);
252
253
    reportRelation(event,
254
        Relation::ERASED,
255
        // TRANSLATORS: erase command
256
        _("Player no longer erased!"),
257
        // TRANSLATORS: erase command
258
        _("Player could not be erased!"));
259
    return true;
260
}
261
262
impHandler(chatFriend)
263
{
264
    // TRANSLATORS: adding friend command
265
    changeRelation(event, Relation::FRIEND, _("friend"));
266
    return true;
267
}
268
269
impHandler(chatDisregard)
270
{
271
    // TRANSLATORS: disregard command
272
    changeRelation(event, Relation::DISREGARDED, _("disregarded"));
273
    return true;
274
}
275
276
impHandler(chatNeutral)
277
{
278
    // TRANSLATORS: neutral command
279
    changeRelation(event, Relation::NEUTRAL, _("neutral"));
280
    return true;
281
}
282
283
impHandler(chatBlackList)
284
{
285
    // TRANSLATORS: blacklist command
286
    changeRelation(event, Relation::BLACKLISTED, _("blacklisted"));
287
    return true;
288
}
289
290
impHandler(chatEnemy)
291
{
292
    // TRANSLATORS: enemy command
293
    changeRelation(event, Relation::ENEMY2, _("enemy"));
294
    return true;
295
}
296
297
impHandler(chatNuke)
298
{
299
    if (actorManager == nullptr)
300
        return false;
301
302
    const std::string nick = getNick(event);
303
    Being *const being = actorManager->findBeingByName(
304
        nick, ActorType::Player);
305
    if (being == nullptr)
306
        return true;
307
308
    actorManager->addBlock(being->getId());
309
    actorManager->destroy(being);
310
    return true;
311
}
312
313
impHandler(chatAdd)
314
{
315
    if (chatWindow == nullptr)
316
        return false;
317
318
    if (event.args.empty())
319
        return true;
320
321
    STD_VECTOR<int> str;
322
    splitToIntVector(str, event.args, ',');
323
    if (str.empty())
324
        return true;
325
326
    int id = str[0];
327
    if (id == 0)
328
        return true;
329
330
    if (ItemDB::exists(id))
331
    {
332
        const std::string names = ItemDB::getNamesStr(str);
333
        if (!names.empty())
334
            chatWindow->addItemText(names);
335
        return true;
336
    }
337
338
    const FloorItem *const floorItem = actorManager->findItem(
339
        fromInt(id, BeingId));
340
341
    if (floorItem != nullptr)
342
    {
343
        str[0] =  floorItem->getItemId();
344
        const std::string names = ItemDB::getNamesStr(str);
345
        chatWindow->addItemText(names);
346
    }
347
    return true;
348
}
349
350
impHandler0(present)
351
{
352
    if (chatWindow != nullptr)
353
    {
354
        chatWindow->doPresent();
355
        return true;
356
    }
357
    return false;
358
}
359
360
impHandler0(printAll)
361
{
362
    if (actorManager != nullptr)
363
    {
364
        actorManager->printAllToChat();
365
        return true;
366
    }
367
    return false;
368
}
369
370
impHandler(move)
371
{
372
    int x = 0;
373
    int y = 0;
374
375
    if ((localPlayer != nullptr) && parse2Int(event.args, x, y))
376
    {
377
        localPlayer->setDestination(x, y);
378
        return true;
379
    }
380
    return false;
381
}
382
383
impHandler(setTarget)
384
{
385
    if ((actorManager == nullptr) || (localPlayer == nullptr))
386
        return false;
387
388
    Being *const target = actorManager->findNearestByName(event.args,
389
        ActorType::Unknown);
390
    if (target != nullptr)
391
        localPlayer->setTarget(target);
392
    return true;
393
}
394
395
impHandler(commandOutfit)
396
{
397
    if (outfitWindow != nullptr)
398
    {
399
        if (!event.args.empty())
400
        {
401
            const std::string op = event.args.substr(0, 1);
402
            if (op == "n")
403
            {
404
                outfitWindow->wearNextOutfit(true);
405
            }
406
            else if (op == "p")
407
            {
408
                outfitWindow->wearPreviousOutfit(true);
409
            }
410
            else
411
            {
412
                outfitWindow->wearOutfit(atoi(event.args.c_str()) - 1,
413
                    false, true);
414
            }
415
        }
416
        else
417
        {
418
            outfitWindow->wearOutfit(atoi(event.args.c_str()) - 1,
419
                false, true);
420
        }
421
        return true;
422
    }
423
    return false;
424
}
425
426
impHandler(commandEmote)
427
{
428
    LocalPlayer::emote(CAST_U8(atoi(event.args.c_str())));
429
    return true;
430
}
431
432
impHandler(awayMessage)
433
{
434
    if (localPlayer != nullptr)
435
    {
436
        localPlayer->setAway(event.args);
437
        return true;
438
    }
439
    return false;
440
}
441
442
impHandler(pseudoAway)
443
{
444
    if (localPlayer != nullptr)
445
    {
446
        LocalPlayer::setPseudoAway(event.args);
447
        localPlayer->updateStatus();
448
        return true;
449
    }
450
    return false;
451
}
452
453
impHandler(follow)
454
{
455
    if (localPlayer == nullptr)
456
        return false;
457
458
    if (!features.getBoolValue("allowFollow"))
459
        return false;
460
461
    if (!event.args.empty())
462
    {
463
        localPlayer->setFollow(event.args);
464
    }
465
    else if (event.tab != nullptr &&
466
             event.tab->getType() == ChatTabType::WHISPER)
467
    {
468
        localPlayer->setFollow(static_cast<WhisperTab*>(event.tab)->getNick());
469
    }
470
    else
471
    {
472
        const Being *const being = localPlayer->getTarget();
473
        if (being != nullptr)
474
            localPlayer->setFollow(being->getName());
475
    }
476
    return true;
477
}
478
479
impHandler(navigate)
480
{
481
    if ((localPlayer == nullptr) ||
482
        !localPlayer->canMove())
483
    {
484
        return false;
485
    }
486
487
    int x = 0;
488
    int y = 0;
489
490
    if (parse2Int(event.args, x, y))
491
        localPlayer->navigateTo(x, y);
492
    else
493
        localPlayer->navigateClean();
494
    return true;
495
}
496
497
impHandler(navigateTo)
498
{
499
    if ((localPlayer == nullptr) ||
500
        !localPlayer->canMove())
501
    {
502
        return false;
503
    }
504
505
    const std::string args = event.args;
506
    if (args.empty())
507
        return true;
508
509
    Being *const being = actorManager->findBeingByName(args,
510
        ActorType::Unknown);
511
    if (being != nullptr)
512
    {
513
        localPlayer->navigateTo(being->getTileX(), being->getTileY());
514
    }
515
    else if (localPlayer->isInParty())
516
    {
517
        const Party *const party = localPlayer->getParty();
518
        if (party != nullptr)
519
        {
520
            const PartyMember *const m = party->getMember(args);
521
            const PartyMember *const o = party->getMember(
522
                localPlayer->getName());
523
            if (m != nullptr &&
524
                o != nullptr &&
525
                m->getMap() == o->getMap())
526
            {
527
                localPlayer->navigateTo(m->getX(), m->getY());
528
            }
529
        }
530
    }
531
    return true;
532
}
533
534
impHandler(moveCamera)
535
{
536
    int x = 0;
537
    int y = 0;
538
539
    if (viewport == nullptr)
540
        return false;
541
542
    if (parse2Int(event.args, x, y))
543
        viewport->moveCameraToPosition(x * mapTileSize, y * mapTileSize);
544
    return true;
545
}
546
547
impHandler0(restoreCamera)
548
{
549
    if (viewport == nullptr)
550
        return false;
551
552
    viewport->returnCamera();
553
    return true;
554
}
555
556
impHandler(imitation)
557
{
558
    if (localPlayer == nullptr)
559
        return false;
560
561
    if (!event.args.empty())
562
    {
563
        localPlayer->setImitate(event.args);
564
    }
565
    else if (event.tab != nullptr &&
566
             event.tab->getType() == ChatTabType::WHISPER)
567
    {
568
        localPlayer->setImitate(static_cast<WhisperTab*>(
569
            event.tab)->getNick());
570
    }
571
    else
572
    {
573
        localPlayer->setImitate("");
574
    }
575
    return true;
576
}
577
578
impHandler(sendMail)
579
{
580
#ifdef TMWA_SUPPORT
581
    const ServerTypeT type = Net::getNetworkType();
582
    if (type == ServerType::EATHENA || type == ServerType::EVOL2)
583
#endif  // TMWA_SUPPORT
584
    {
585
        std::string name;
586
        std::string text;
587
588
        if (parse2Str(event.args, name, text))
589
        {
590
            if (settings.enableNewMailSystem)
591
            {
592
                mail2Handler->queueCheckName(MailQueueType::SendMail,
593
                    name,
594
                    // TRANSLATORS: quick mail message caption
595
                    _("Quick message"),
596
                    text,
597
                    0);
598
            }
599
            else
600
            {
601
                // TRANSLATORS: quick mail message caption
602
                mailHandler->send(name, _("Quick message"), text);
603
            }
604
        }
605
    }
606
#ifdef TMWA_SUPPORT
607
    else if (serverConfig.getBoolValue("enableManaMarketBot"))
608
    {
609
        chatHandler->privateMessage("ManaMarket", "!mail " + event.args);
610
        return true;
611
    }
612
#endif  // TMWA_SUPPORT
613
614
    return false;
615
}
616
617
impHandler(info)
618
{
619
    if (event.tab == nullptr ||
620
        localPlayer == nullptr ||
621
        Net::getNetworkType() == ServerType::TMWATHENA)
622
    {
623
        return false;
624
    }
625
626
    if (guildHandler != nullptr &&
627
        event.tab->getType() == ChatTabType::GUILD)
628
    {
629
        const Guild *const guild = localPlayer->getGuild();
630
        if (guild != nullptr)
631
            guildHandler->info();
632
    }
633
    return true;
634
}
635
636
impHandler(wait)
637
{
638
    if (localPlayer != nullptr)
639
    {
640
        localPlayer->waitFor(event.args);
641
        return true;
642
    }
643
    return false;
644
}
645
646
impHandler(addPriorityAttack)
647
{
648
    if ((actorManager == nullptr) ||
649
        actorManager->isInPriorityAttackList(event.args))
650
    {
651
        return false;
652
    }
653
654
    actorManager->removeAttackMob(event.args);
655
    actorManager->addPriorityAttackMob(event.args);
656
657
    if (socialWindow != nullptr)
658
        socialWindow->updateAttackFilter();
659
    return true;
660
}
661
662
impHandler(addAttack)
663
{
664
    if (actorManager == nullptr)
665
        return false;
666
667
    actorManager->removeAttackMob(event.args);
668
    actorManager->addAttackMob(event.args);
669
670
    if (socialWindow != nullptr)
671
        socialWindow->updateAttackFilter();
672
    return true;
673
}
674
675
impHandler(removeAttack)
676
{
677
    if (actorManager == nullptr)
678
        return false;
679
680
    if (event.args.empty())
681
    {
682
        if (actorManager->isInAttackList(event.args))
683
        {
684
            actorManager->removeAttackMob(event.args);
685
            actorManager->addIgnoreAttackMob(event.args);
686
        }
687
        else
688
        {
689
            actorManager->removeAttackMob(event.args);
690
            actorManager->addAttackMob(event.args);
691
        }
692
    }
693
    else
694
    {
695
        actorManager->removeAttackMob(event.args);
696
    }
697
698
699
    if (socialWindow != nullptr)
700
        socialWindow->updateAttackFilter();
701
    return true;
702
}
703
704
impHandler(addIgnoreAttack)
705
{
706
    if (actorManager == nullptr)
707
        return false;
708
709
    actorManager->removeAttackMob(event.args);
710
    actorManager->addIgnoreAttackMob(event.args);
711
712
    if (socialWindow != nullptr)
713
        socialWindow->updateAttackFilter();
714
    return true;
715
}
716
717
impHandler(setDrop)
718
{
719
    GameModifiers::setQuickDropCounter(atoi(event.args.c_str()));
720
    return true;
721
}
722
723
impHandler(url)
724
{
725
    if (event.tab != nullptr)
726
    {
727
        std::string url1 = event.args;
728
        if (!strStartWith(url1, "http") && !strStartWith(url1, "?"))
729
            url1 = "http://" + url1;
730
        std::string str(strprintf("[@@%s |%[email protected]@]",
731
            url1.c_str(), event.args.c_str()));
732
        outStringNormal(event.tab, str, str);
733
        return true;
734
    }
735
    return false;
736
}
737
738
impHandler(openUrl)
739
{
740
    std::string url = event.args;
741
    if (!strStartWith(url, "http"))
742
        url = "http://" + url;
743
    openBrowser(url);
744
    return true;
745
}
746
747
impHandler(execute)
748
{
749
    const size_t idx = event.args.find(' ');
750
    std::string name;
751
    std::string params;
752
    if (idx == std::string::npos)
753
    {
754
        name = event.args;
755
    }
756
    else
757
    {
758
        name = event.args.substr(0, idx);
759
        params = event.args.substr(idx + 1);
760
    }
761
    execFile(name, name, params, "");
762
    return true;
763
}
764
765
impHandler(enableHighlight)
766
{
767
    if (event.tab != nullptr)
768
    {
769
        event.tab->setAllowHighlight(true);
770
        if (chatWindow != nullptr)
771
        {
772
            chatWindow->saveState();
773
            return true;
774
        }
775
    }
776
    return false;
777
}
778
779
impHandler(disableHighlight)
780
{
781
    if (event.tab != nullptr)
782
    {
783
        event.tab->setAllowHighlight(false);
784
        if (chatWindow != nullptr)
785
        {
786
            chatWindow->saveState();
787
            return true;
788
        }
789
    }
790
    return false;
791
}
792
793
impHandler(dontRemoveName)
794
{
795
    if (event.tab != nullptr)
796
    {
797
        event.tab->setRemoveNames(false);
798
        if (chatWindow != nullptr)
799
        {
800
            chatWindow->saveState();
801
            return true;
802
        }
803
    }
804
    return false;
805
}
806
807
impHandler(removeName)
808
{
809
    if (event.tab != nullptr)
810
    {
811
        event.tab->setRemoveNames(true);
812
        if (chatWindow != nullptr)
813
        {
814
            chatWindow->saveState();
815
            return true;
816
        }
817
    }
818
    return false;
819
}
820
821
impHandler(disableAway)
822
{
823
    if (event.tab != nullptr)
824
    {
825
        event.tab->setNoAway(true);
826
        if (chatWindow != nullptr)
827
        {
828
            chatWindow->saveState();
829
            return true;
830
        }
831
    }
832
    return false;
833
}
834
835
impHandler(enableAway)
836
{
837
    if (event.tab != nullptr)
838
    {
839
        event.tab->setNoAway(false);
840
        if (chatWindow != nullptr)
841
        {
842
            chatWindow->saveState();
843
            return true;
844
        }
845
    }
846
    return false;
847
}
848
849
impHandler(testParticle)
850
{
851
    if (localPlayer != nullptr)
852
    {
853
        localPlayer->setTestParticle(event.args, true);
854
        return true;
855
    }
856
    return false;
857
}
858
859
impHandler(talkRaw)
860
{
861
    if (chatHandler != nullptr)
862
    {
863
        chatHandler->talkRaw(event.args);
864
        return true;
865
    }
866
    return false;
867
}
868
869
impHandler(gm)
870
{
871
    if (chatHandler != nullptr)
872
    {
873
        Gm::runCommand("wgm", event.args);
874
        return true;
875
    }
876
    return false;
877
}
878
879
impHandler(hack)
880
{
881
    if (chatHandler != nullptr)
882
    {
883
        chatHandler->sendRaw(event.args);
884
        return true;
885
    }
886
    return false;
887
}
888
889
impHandler(debugSpawn)
890
{
891
    if (localPlayer == nullptr)
892
        return false;
893
    int cnt = atoi(event.args.c_str());
894
    if (cnt < 1)
895
        cnt = 1;
896
    const int half = cnt / 2;
897
    const Map *const map = localPlayer->getMap();
898
    int x1 = -half;
899
    if (x1 < 0)
900
        x1 = 0;
901
    int y1 = x1;
902
    int x2 = cnt - half;
903
    if (x2 > map->getWidth())
904
        x2 = map->getWidth();
905
    int y2 = x2;
906
907
    for (int x = x1; x < x2; x ++)
908
    {
909
        for (int y = y1; y < y2; y ++)
910
            ActorManager::cloneBeing(localPlayer, x, y, cnt);
911
    }
912
    return true;
913
}
914
915
impHandler(serverIgnoreWhisper)
916
{
917
    std::string args = getNick(event);
918
    if (args.empty())
919
        return false;
920
921
    if (chatHandler != nullptr)
922
    {
923
        chatHandler->ignore(args);
924
        return true;
925
    }
926
    return false;
927
}
928
929
impHandler(serverUnIgnoreWhisper)
930
{
931
    std::string args = getNick(event);
932
    if (args.empty())
933
        return false;
934
935
    if (chatHandler != nullptr)
936
    {
937
        chatHandler->unIgnore(args);
938
        return true;
939
    }
940
    return false;
941
}
942
943
impHandler(setHomunculusName)
944
{
945
    const std::string args = event.args;
946
    if (args.empty())
947
    {
948
        const HomunculusInfo *const info = PlayerInfo::getHomunculus();
949
        if (info != nullptr)
950
        {
951
            // TRANSLATORS: dialog header
952
            inputActionReplayListener.openDialog(_("Rename your homun"),
953
                info->name,
954
                InputAction::HOMUNCULUS_SET_NAME);
955
        }
956
        return false;
957
    }
958
959
    if (homunculusHandler != nullptr)
960
    {
961
        homunculusHandler->setName(args);
962
        return true;
963
    }
964
    return false;
965
}
966
967
impHandler0(fireHomunculus)
968
{
969
    if (homunculusHandler != nullptr)
970
    {
971
        homunculusHandler->fire();
972
        return true;
973
    }
974
    return false;
975
}
976
977
impHandler0(leaveParty)
978
{
979
    if (partyHandler != nullptr)
980
    {
981
        partyHandler->leave();
982
        return true;
983
    }
984
    return false;
985
}
986
987
impHandler0(leaveGuild)
988
{
989
    if ((guildHandler != nullptr) && (localPlayer != nullptr))
990
    {
991
        const Guild *const guild = localPlayer->getGuild();
992
        if (guild != nullptr)
993
            guildHandler->leave(guild->getId());
994
        return true;
995
    }
996
    return false;
997
}
998
999
impHandler(warp)
1000
{
1001
    int x = 0;
1002
    int y = 0;
1003
1004
    if ((adminHandler != nullptr) &&
1005
        (Game::instance() != nullptr) &&
1006
        parse2Int(event.args, x, y))
1007
    {
1008
        adminHandler->warp(Game::instance()->getCurrentMapName(),
1009
            x, y);
1010
        return true;
1011
    }
1012
    return false;
1013
}
1014
1015
impHandler(homunTalk)
1016
{
1017
    if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet())
1018
        return false;
1019
1020
    std::string args = event.args;
1021
    if (findCutFirst(args, "/me "))
1022
        args = textToMe(args);
1023
    if (homunculusHandler != nullptr)
1024
    {
1025
        homunculusHandler->talk(args);
1026
        return true;
1027
    }
1028
    return false;
1029
}
1030
1031
impHandler(homunEmote)
1032
{
1033
    if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet())
1034
        return false;
1035
1036
    if ((homunculusHandler != nullptr) &&
1037
        event.action >= InputAction::HOMUN_EMOTE_1 &&
1038
        event.action <= InputAction::HOMUN_EMOTE_48)
1039
    {
1040
        if (emoteShortcut != nullptr)
1041
        {
1042
            const int emotion = event.action - InputAction::HOMUN_EMOTE_1;
1043
            homunculusHandler->emote(emoteShortcut->getEmote(emotion));
1044
        }
1045
        if (Game::instance() != nullptr)
1046
            Game::instance()->setValidSpeed();
1047
        return true;
1048
    }
1049
1050
    return false;
1051
}
1052
1053
impHandler(commandHomunEmote)
1054
{
1055
    if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet())
1056
        return false;
1057
1058
    if (homunculusHandler != nullptr)
1059
    {
1060
        homunculusHandler->emote(CAST_U8(
1061
            atoi(event.args.c_str())));
1062
        return true;
1063
    }
1064
    return false;
1065
}
1066
1067
impHandler(createPublicChatRoom)
1068
{
1069
    if ((chatHandler == nullptr) || event.args.empty())
1070
        return false;
1071
    chatHandler->createChatRoom(event.args, "", 100, true);
1072
    return true;
1073
}
1074
1075
impHandler(joinChatRoom)
1076
{
1077
    if (chatHandler == nullptr)
1078
        return false;
1079
    const std::string args = event.args;
1080
    if (args.empty())
1081
        return false;
1082
    ChatObject *const chat = ChatObject::findByName(args);
1083
    if (chat == nullptr)
1084
        return false;
1085
    chatHandler->joinChat(chat, "");
1086
    return true;
1087
}
1088
1089
impHandler0(leaveChatRoom)
1090
{
1091
    if (chatHandler != nullptr)
1092
    {
1093
        chatHandler->leaveChatRoom();
1094
        return true;
1095
    }
1096
    return false;
1097
}
1098
1099
impHandler(confSet)
1100
{
1101
    std::string name;
1102
    std::string val;
1103
1104
    if (parse2Str(event.args, name, val))
1105
    {
1106
        config.setValue(name, val);
1107
        return true;
1108
    }
1109
    return false;
1110
}
1111
1112
impHandler(serverConfSet)
1113
{
1114
    std::string name;
1115
    std::string val;
1116
1117
    if (parse2Str(event.args, name, val))
1118
    {
1119
        serverConfig.setValue(name, val);
1120
        return true;
1121
    }
1122
    return false;
1123
}
1124
1125
impHandler(confGet)
1126
{
1127
    const std::string args = event.args;
1128
    if (args.empty())
1129
        return false;
1130
1131
    // TRANSLATORS: result from command /confget
1132
    const std::string str = strprintf(_("Config value: %s"),
1133
        config.getStringValue(args).c_str());
1134
    outStringNormal(event.tab, str, str);
1135
    return true;
1136
}
1137
1138
impHandler(serverConfGet)
1139
{
1140
    const std::string args = event.args;
1141
    if (args.empty())
1142
        return false;
1143
1144
    // TRANSLATORS: result from command /serverconfget
1145
    const std::string str = strprintf(_("Server config value: %s"),
1146
        serverConfig.getStringValue(args).c_str());
1147
    outStringNormal(event.tab, str, str);
1148
    return true;
1149
}
1150
1151
impHandler(slide)
1152
{
1153
    int x = 0;
1154
    int y = 0;
1155
1156
    if ((adminHandler != nullptr) && parse2Int(event.args, x, y))
1157
    {
1158
        adminHandler->slide(x, y);
1159
        return true;
1160
    }
1161
    return false;
1162
}
1163
1164
impHandler(selectSkillLevel)
1165
{
1166
    int skill = 0;
1167
    int level = 0;
1168
1169
    if ((skillDialog != nullptr) && parse2Int(event.args, skill, level))
1170
    {
1171
        skillDialog->selectSkillLevel(skill, level);
1172
        return true;
1173
    }
1174
    return false;
1175
}
1176
1177
impHandler(skill)
1178
{
1179
    StringVect vect;
1180
    splitToStringVector(vect, event.args, ' ');
1181
    const int sz = CAST_S32(vect.size());
1182
    if (sz < 1)
1183
        return true;
1184
    const int skillId = atoi(vect[0].c_str());
1185
    int level = 0;
1186
    std::string text;
1187
    if (sz > 1)
1188
    {
1189
        level = atoi(vect[1].c_str());
1190
        if (sz > 2)
1191
            text = vect[2];
1192
    }
1193
    // +++ add here also cast type and offsets
1194
    if (text.empty())
1195
    {
1196
        SkillDialog::useSkill(skillId,
1197
            AutoTarget_true,
1198
            level,
1199
            false,
1200
            "",
1201
            CastType::Default,
1202
            0,
1203
            0);
1204
    }
1205
    else
1206
    {
1207
        SkillDialog::useSkill(skillId,
1208
            AutoTarget_true,
1209
            level,
1210
            true,
1211
            text,
1212
            CastType::Default,
1213
            0,
1214
            0);
1215
    }
1216
    return true;
1217
}
1218
1219
impHandler(craft)
1220
{
1221
    const std::string args = event.args;
1222
    if (args.empty() || (inventoryWindow == nullptr))
1223
        return false;
1224
1225
    inventoryWindow->moveItemToCraft(atoi(args.c_str()));
1226
    return true;
1227
}
1228
1229
impHandler(npcClipboard)
1230
{
1231
    if (npcHandler != nullptr)
1232
    {
1233
        int x = 0;
1234
        int y = 0;
1235
1236
        NpcDialog *const dialog = npcHandler->getCurrentNpcDialog();
1237
1238
        if ((dialog != nullptr) && parse2Int(event.args, x, y))
1239
        {
1240
            dialog->copyToClipboard(x, y);
1241
            return true;
1242
        }
1243
    }
1244
    return false;
1245
}
1246
1247
impHandler(clipboardCopy)
1248
{
1249
    const std::string args = event.args;
1250
    if (args.empty())
1251
        return false;
1252
    sendBuffer(args);
1253
    return true;
1254
}
1255
1256
impHandler(addPickup)
1257
{
1258
    if (actorManager != nullptr)
1259
    {
1260
        actorManager->removePickupItem(event.args);
1261
        actorManager->addPickupItem(event.args);
1262
        if (socialWindow != nullptr)
1263
            socialWindow->updatePickupFilter();
1264
        return true;
1265
    }
1266
    return false;
1267
}
1268
1269
impHandler(removePickup)
1270
{
1271
    if (actorManager != nullptr)
1272
    {
1273
        if (event.args.empty())
1274
        {   // default pickup manipulation
1275
            if (actorManager->checkDefaultPickup())
1276
            {
1277
                actorManager->removePickupItem(event.args);
1278
                actorManager->addIgnorePickupItem(event.args);
1279
            }
1280
            else
1281
            {
1282
                actorManager->removePickupItem(event.args);
1283
                actorManager->addPickupItem(event.args);
1284
            }
1285
        }
1286
        else
1287
        {   // any other pickups
1288
            actorManager->removePickupItem(event.args);
1289
        }
1290
        if (socialWindow != nullptr)
1291
            socialWindow->updatePickupFilter();
1292
        return true;
1293
    }
1294
    return false;
1295
}
1296
1297
impHandler(ignorePickup)
1298
{
1299
    if (actorManager != nullptr)
1300
    {
1301
        actorManager->removePickupItem(event.args);
1302
        actorManager->addIgnorePickupItem(event.args);
1303
        if (socialWindow != nullptr)
1304
            socialWindow->updatePickupFilter();
1305
        return true;
1306
    }
1307
    return false;
1308
}
1309
1310
impHandler(monsterInfo)
1311
{
1312
    const std::string args = event.args;
1313
    if (args.empty())
1314
        return false;
1315
    adminHandler->monsterInfo(args);
1316
    return true;
1317
}
1318
1319
impHandler(itemInfo)
1320
{
1321
    const std::string args = event.args;
1322
    if (args.empty())
1323
        return false;
1324
    adminHandler->itemInfo(args);
1325
    return true;
1326
}
1327
1328
impHandler(whoDrops)
1329
{
1330
    const std::string args = event.args;
1331
    if (args.empty())
1332
        return false;
1333
    adminHandler->whoDrops(args);
1334
    return true;
1335
}
1336
1337
impHandler(mobSearch)
1338
{
1339
    const std::string args = event.args;
1340
    if (args.empty())
1341
        return false;
1342
    adminHandler->mobSearch(args);
1343
    return true;
1344
}
1345
1346
impHandler(mobSpawnSearch)
1347
{
1348
    const std::string args = event.args;
1349
    if (args.empty())
1350
        return false;
1351
    adminHandler->mobSpawnSearch(args);
1352
    return true;
1353
}
1354
1355
impHandler(playerGmCommands)
1356
{
1357
    adminHandler->playerGmCommands(event.args);
1358
    return true;
1359
}
1360
1361
impHandler(playerCharGmCommands)
1362
{
1363
    adminHandler->playerCharGmCommands(event.args);
1364
    return true;
1365
}
1366
1367
impHandler(commandShowLevel)
1368
{
1369
    adminHandler->showLevel(event.args);
1370
    return true;
1371
}
1372
1373
impHandler(commandShowStats)
1374
{
1375
    adminHandler->showStats(event.args);
1376
    return true;
1377
}
1378
1379
impHandler(commandShowStorage)
1380
{
1381
    adminHandler->showStorageList(event.args);
1382
    return true;
1383
}
1384
1385
impHandler(commandShowCart)
1386
{
1387
    adminHandler->showCartList(event.args);
1388
    return true;
1389
}
1390
1391
impHandler(commandShowInventory)
1392
{
1393
    adminHandler->showInventoryList(event.args);
1394
    return true;
1395
}
1396
1397
impHandler(locatePlayer)
1398
{
1399
    const std::string args = event.args;
1400
    if (args.empty())
1401
        return false;
1402
    adminHandler->locatePlayer(args);
1403
    return true;
1404
}
1405
1406
impHandler(commandShowAccountInfo)
1407
{
1408
    const std::string args = event.args;
1409
    if (args.empty())
1410
        return false;
1411
    adminHandler->showAccountInfo(args);
1412
    return true;
1413
}
1414
1415
impHandler(commandSpawn)
1416
{
1417
    const std::string args = event.args;
1418
    if (args.empty())
1419
        return false;
1420
    adminHandler->spawn(args);
1421
    return true;
1422
}
1423
1424
impHandler(commandSpawnSlave)
1425
{
1426
    const std::string args = event.args;
1427
    if (args.empty())
1428
        return false;
1429
    adminHandler->spawnSlave(args);
1430
    return true;
1431
}
1432
1433
impHandler(commandSpawnClone)
1434
{
1435
    const std::string args = event.args;
1436
    if (args.empty())
1437
        return false;
1438
    adminHandler->spawnClone(args);
1439
    return true;
1440
}
1441
1442
impHandler(commandSpawnSlaveClone)
1443
{
1444
    const std::string args = event.args;
1445
    if (args.empty())
1446
        return false;
1447
    adminHandler->spawnSlaveClone(args);
1448
    return true;
1449
}
1450
1451
impHandler(commandSpawnEvilClone)
1452
{
1453
    const std::string args = event.args;
1454
    if (args.empty())
1455
        return false;
1456
    adminHandler->spawnEvilClone(args);
1457
    return true;
1458
}
1459
1460
impHandler(commandSavePosition)
1461
{
1462
    adminHandler->savePosition(event.args);
1463
    return true;
1464
}
1465
1466
impHandler(commandLoadPosition)
1467
{
1468
    adminHandler->loadPosition(event.args);
1469
    return true;
1470
}
1471
1472
impHandler(commandRandomWarp)
1473
{
1474
    adminHandler->randomWarp(event.args);
1475
    return true;
1476
}
1477
1478
impHandler(commandGotoNpc)
1479
{
1480
    const std::string args = event.args;
1481
    if (args.empty())
1482
        return false;
1483
    adminHandler->gotoNpc(args);
1484
    return true;
1485
}
1486
1487
impHandler(commandGotoPc)
1488
{
1489
    const std::string args = event.args;
1490
    if (args.empty())
1491
        return false;
1492
    adminHandler->gotoName(args);
1493
    return true;
1494
}
1495
1496
impHandler(commandRecallPc)
1497
{
1498
    const std::string args = event.args;
1499
    if (args.empty())
1500
        return false;
1501
    adminHandler->recallName(args);
1502
    return true;
1503
}
1504
1505
impHandler(commandIpCheck)
1506
{
1507
    const std::string args = event.args;
1508
    if (args.empty())
1509
        return false;
1510
    adminHandler->ipcheckName(args);
1511
    return true;
1512
}
1513
1514
impHandler(commandKiller)
1515
{
1516
    adminHandler->killer(event.args);
1517
    return true;
1518
}
1519
1520
impHandler(commandKillable)
1521
{
1522
    adminHandler->killable(event.args);
1523
    return true;
1524
}
1525
1526
impHandler(commandHeal)
1527
{
1528
    adminHandler->heal(event.args);
1529
    return true;
1530
}
1531
1532
impHandler(commandAlive)
1533
{
1534
    adminHandler->alive(event.args);
1535
    return true;
1536
}
1537
1538
impHandler(commandDisguise)
1539
{
1540
    const std::string args = event.args;
1541
    if (args.empty())
1542
        return false;
1543
    adminHandler->disguise(args);
1544
    return true;
1545
}
1546
1547
impHandler(commandImmortal)
1548
{
1549
    adminHandler->immortal(event.args);
1550
    return true;
1551
}
1552
1553
impHandler(commandHide)
1554
{
1555
    adminHandler->hide(event.args);
1556
    return true;
1557
}
1558
1559
impHandler(commandNuke)
1560
{
1561
    const std::string args = event.args;
1562
    if (args.empty())
1563
        return false;
1564
    adminHandler->nuke(args);
1565
    return true;
1566
}
1567
1568
impHandler(commandKill)
1569
{
1570
    adminHandler->kill(event.args);
1571
    return true;
1572
}
1573
1574
impHandler(commandJail)
1575
{
1576
    const std::string args = event.args;
1577
    if (args.empty())
1578
        return false;
1579
    adminHandler->jail(args);
1580
    return true;
1581
}
1582
1583
impHandler(commandUnjail)
1584
{
1585
    const std::string args = event.args;
1586
    if (args.empty())
1587
        return false;
1588
    adminHandler->unjail(args);
1589
    return true;
1590
}
1591
1592
impHandler(commandNpcMove)
1593
{
1594
    const std::string args = event.args;
1595
    if (args.empty())
1596
        return false;
1597
    StringVect pars;
1598
    if (!splitParameters(pars, args, " ,", '\"'))
1599
        return false;
1600
1601
    if (pars.size() != 3)
1602
        return false;
1603
1604
    adminHandler->npcMove(pars[0],
1605
        atoi(pars[1].c_str()),
1606
        atoi(pars[2].c_str()));
1607
    return true;
1608
}
1609
1610
impHandler(commandNpcHide)
1611
{
1612
    const std::string args = event.args;
1613
    if (args.empty())
1614
        return false;
1615
    adminHandler->hideNpc(args);
1616
    return true;
1617
}
1618
1619
impHandler(commandNpcShow)
1620
{
1621
    const std::string args = event.args;
1622
    if (args.empty())
1623
        return false;
1624
    adminHandler->showNpc(args);
1625
    return true;
1626
}
1627
1628
impHandler(commandChangePartyLeader)
1629
{
1630
    const std::string args = event.args;
1631
    if (args.empty())
1632
        return false;
1633
    adminHandler->changePartyLeader(args);
1634
    return true;
1635
}
1636
1637
impHandler(commandPartyRecall)
1638
{
1639
    const std::string args = event.args;
1640
    if (args.empty())
1641
        return false;
1642
    adminHandler->partyRecall(args);
1643
    return true;
1644
}
1645
1646
impHandler(commandBreakGuild)
1647
{
1648
    adminHandler->breakGuild(event.args);
1649
    return true;
1650
}
1651
1652
impHandler(commandGuildRecall)
1653
{
1654
    const std::string args = event.args;
1655
    if (args.empty())
1656
        return false;
1657
    adminHandler->guildRecall(args);
1658
    return true;
1659
}
1660
1661
impHandler(mailTo)
1662
{
1663
    if (mailWindow == nullptr)
1664
        return false;
1665
    const std::string args = event.args;
1666
    if (settings.enableNewMailSystem)
1667
    {
1668
        mail2Handler->queueCheckName(MailQueueType::EditMail,
1669
            args,
1670
            std::string(),
1671
            std::string(),
1672
            0);
1673
    }
1674
    else
1675
    {
1676
        MailWindow::createMail(args);
1677
    }
1678
    return true;
1679
}
1680
1681
impHandler(adoptChild)
1682
{
1683
    const std::string nick = getNick(event);
1684
    Being *const being = actorManager->findBeingByName(
1685
        nick, ActorType::Player);
1686
    if (being == nullptr)
1687
        return true;
1688
    familyHandler->askForChild(being);
1689
    return true;
1690
}
1691
1692
impHandler(showSkillLevels)
1693
{
1694
    const std::string args = event.args;
1695
    if (args.empty())
1696
        return false;
1697
    const SkillInfo *restrict const skill = skillDialog->getSkill(
1698
        atoi(args.c_str()));
1699
    if (skill == nullptr)
1700
        return false;
1701
    popupMenu->showSkillLevelPopup(skill);
1702
    return true;
1703
}
1704
1705
impHandler(showSkillType)
1706
{
1707
    const std::string args = event.args;
1708
    if (args.empty())
1709
        return false;
1710
    const SkillInfo *restrict const skill = skillDialog->getSkill(
1711
        atoi(args.c_str()));
1712
    if (skill == nullptr)
1713
        return false;
1714
    popupMenu->showSkillTypePopup(skill);
1715
    return true;
1716
}
1717
1718
impHandler(selectSkillType)
1719
{
1720
    int skill = 0;
1721
    int type = 0;
1722
1723
    if ((skillDialog != nullptr) && parse2Int(event.args, skill, type))
1724
    {
1725
        skillDialog->selectSkillCastType(skill,
1726
            static_cast<CastTypeT>(type));
1727
        return true;
1728
    }
1729
    return false;
1730
}
1731
1732
impHandler(showSkillOffsetX)
1733
{
1734
    const std::string args = event.args;
1735
    if (args.empty())
1736
        return false;
1737
    const SkillInfo *restrict const skill = skillDialog->getSkill(
1738
        atoi(args.c_str()));
1739
    if (skill == nullptr)
1740
        return false;
1741
    popupMenu->showSkillOffsetPopup(skill, true);
1742
    return true;
1743
}
1744
1745
impHandler(showSkillOffsetY)
1746
{
1747
    const std::string args = event.args;
1748
    if (args.empty())
1749
        return false;
1750
    const SkillInfo *restrict const skill = skillDialog->getSkill(
1751
        atoi(args.c_str()));
1752
    if (skill == nullptr)
1753
        return false;
1754
    popupMenu->showSkillOffsetPopup(skill, false);
1755
    return true;
1756
}
1757
1758
impHandler(setSkillOffsetX)
1759
{
1760
    int skill = 0;
1761
    int offset = 0;
1762
1763
    if ((skillDialog != nullptr) && parse2Int(event.args, skill, offset))
1764
    {
1765
        skillDialog->setSkillOffsetX(skill, offset);
1766
        return true;
1767
    }
1768
    return false;
1769
}
1770
1771
impHandler(setSkillOffsetY)
1772
{
1773
    int skill = 0;
1774
    int offset = 0;
1775
1776
    if ((skillDialog != nullptr) && parse2Int(event.args, skill, offset))
1777
    {
1778
        skillDialog->setSkillOffsetY(skill, offset);
1779
        return true;
1780
    }
1781
    return false;
1782
}
1783
1784
impHandler(partyItemShare)
1785
{
1786
    if (localPlayer == nullptr)
1787
        return false;
1788
1789
    if (localPlayer->isInParty() == false)
1790
        return true;
1791
1792
    ChatTab *tab = event.tab;
1793
    if (tab == nullptr)
1794
        tab = localChatTab;
1795
    if (tab == nullptr)
1796
        return true;
1797
1798
    const std::string args = event.args;
1799
    if (args.empty())
1800
    {
1801
        switch (partyHandler->getShareItems())
1802
        {
1803
            case PartyShare::YES:
1804
                // TRANSLATORS: chat message
1805
                tab->chatLog(_("Item sharing enabled."),
1806
                    ChatMsgType::BY_SERVER,
1807
                    IgnoreRecord_false,
1808
                    TryRemoveColors_true);
1809
                return true;
1810
            case PartyShare::NO:
1811
                // TRANSLATORS: chat message
1812
                tab->chatLog(_("Item sharing disabled."),
1813
                    ChatMsgType::BY_SERVER,
1814
                    IgnoreRecord_false,
1815
                    TryRemoveColors_true);
1816
                return true;
1817
            case PartyShare::NOT_POSSIBLE:
1818
                // TRANSLATORS: chat message
1819
                tab->chatLog(_("Item sharing not possible."),
1820
                    ChatMsgType::BY_SERVER,
1821
                    IgnoreRecord_false,
1822
                    TryRemoveColors_true);
1823
                return true;
1824
            case PartyShare::UNKNOWN:
1825
                // TRANSLATORS: chat message
1826
                tab->chatLog(_("Item sharing unknown."),
1827
                    ChatMsgType::BY_SERVER,
1828
                    IgnoreRecord_false,
1829
                    TryRemoveColors_true);
1830
                return true;
1831
            default:
1832
                break;
1833
        }
1834
    }
1835
1836
    const signed char opt = parseBoolean(args);
1837
1838
    switch (opt)
1839
    {
1840
        case 1:
1841
            partyHandler->setShareItems(
1842
                PartyShare::YES);
1843
            break;
1844
        case 0:
1845
            partyHandler->setShareItems(
1846
                PartyShare::NO);
1847
            break;
1848
        case -1:
1849
            tab->chatLog(strprintf(BOOLEAN_OPTIONS, "item"),
1850
                ChatMsgType::BY_SERVER,
1851
                IgnoreRecord_false,
1852
                TryRemoveColors_true);
1853
            break;
1854
        default:
1855
            break;
1856
    }
1857
    return true;
1858
}
1859
1860
impHandler(partyExpShare)
1861
{
1862
    if (localPlayer == nullptr)
1863
        return false;
1864
1865
    if (localPlayer->isInParty() == false)
1866
        return true;
1867
1868
    ChatTab *tab = event.tab;
1869
    if (tab == nullptr)
1870
        tab = localChatTab;
1871
    if (tab == nullptr)
1872
        return true;
1873
1874
    const std::string args = event.args;
1875
    if (args.empty())
1876
    {
1877
        switch (partyHandler->getShareExperience())
1878
        {
1879
            case PartyShare::YES:
1880
                // TRANSLATORS: chat message
1881
                tab->chatLog(_("Experience sharing enabled."),
1882
                    ChatMsgType::BY_SERVER,
1883
                    IgnoreRecord_false,
1884
                    TryRemoveColors_true);
1885
                return true;
1886
            case PartyShare::NO:
1887
                // TRANSLATORS: chat message
1888
                tab->chatLog(_("Experience sharing disabled."),
1889
                    ChatMsgType::BY_SERVER,
1890
                    IgnoreRecord_false,
1891
                    TryRemoveColors_true);
1892
                return true;
1893
            case PartyShare::NOT_POSSIBLE:
1894
                // TRANSLATORS: chat message
1895
                tab->chatLog(_("Experience sharing not possible."),
1896
                    ChatMsgType::BY_SERVER,
1897
                    IgnoreRecord_false,
1898
                    TryRemoveColors_true);
1899
                return true;
1900
            case PartyShare::UNKNOWN:
1901
                // TRANSLATORS: chat message
1902
                tab->chatLog(_("Experience sharing unknown."),
1903
                    ChatMsgType::BY_SERVER,
1904
                    IgnoreRecord_false,
1905
                    TryRemoveColors_true);
1906
                return true;
1907
            default:
1908
                break;
1909
        }
1910
    }
1911
1912
    const signed char opt = parseBoolean(args);
1913
1914
    switch (opt)
1915
    {
1916
        case 1:
1917
            partyHandler->setShareExperience(
1918
                PartyShare::YES);
1919
            break;
1920
        case 0:
1921
            partyHandler->setShareExperience(
1922
                PartyShare::NO);
1923
            break;
1924
        case -1:
1925
            tab->chatLog(strprintf(BOOLEAN_OPTIONS, "exp"),
1926
                ChatMsgType::BY_SERVER,
1927
                IgnoreRecord_false,
1928
                TryRemoveColors_true);
1929
            break;
1930
        default:
1931
            break;
1932
    }
1933
    return true;
1934
}
1935
1936
impHandler(partyAutoItemShare)
1937
{
1938
    if (localPlayer == nullptr)
1939
        return false;
1940
1941
    if (localPlayer->isInParty() == false)
1942
        return true;
1943
1944
    ChatTab *tab = event.tab;
1945
    if (tab == nullptr)
1946
        tab = localChatTab;
1947
    if (tab == nullptr)
1948
        return true;
1949
1950
    const std::string args = event.args;
1951
    if (args.empty())
1952
    {
1953
        switch (partyHandler->getShareAutoItems())
1954
        {
1955
            case PartyShare::YES:
1956
                // TRANSLATORS: chat message
1957
                tab->chatLog(_("Auto item sharing enabled."),
1958
                    ChatMsgType::BY_SERVER,
1959
                    IgnoreRecord_false,
1960
                    TryRemoveColors_true);
1961
                return true;
1962
            case PartyShare::NO:
1963
                // TRANSLATORS: chat message
1964
                tab->chatLog(_("Auto item sharing disabled."),
1965
                    ChatMsgType::BY_SERVER,
1966
                    IgnoreRecord_false,
1967
                    TryRemoveColors_true);
1968
                return true;
1969
            case PartyShare::NOT_POSSIBLE:
1970
                // TRANSLATORS: chat message
1971
                tab->chatLog(_("Auto item sharing not possible."),
1972
                    ChatMsgType::BY_SERVER,
1973
                    IgnoreRecord_false,
1974
                    TryRemoveColors_true);
1975
                return true;
1976
            case PartyShare::UNKNOWN:
1977
                // TRANSLATORS: chat message
1978
                tab->chatLog(_("Auto item sharing unknown."),
1979
                    ChatMsgType::BY_SERVER,
1980
                    IgnoreRecord_false,
1981
                    TryRemoveColors_true);
1982
                return true;
1983
            default:
1984
                break;
1985
        }
1986
    }
1987
1988
    const signed char opt = parseBoolean(args);
1989
1990
    switch (opt)
1991
    {
1992
        case 1:
1993
            partyHandler->setShareAutoItems(
1994
                PartyShare::YES);
1995
            break;
1996
        case 0:
1997
            partyHandler->setShareAutoItems(
1998
                PartyShare::NO);
1999
            break;
2000
        case -1:
2001
            tab->chatLog(strprintf(BOOLEAN_OPTIONS, "item"),
2002
                ChatMsgType::BY_SERVER,
2003
                IgnoreRecord_false,
2004
                TryRemoveColors_true);
2005
            break;
2006
        default:
2007
            break;
2008
    }
2009
    return true;
2010
}
2011
2012
impHandler0(outfitToChat)
2013
{
2014
    if ((outfitWindow == nullptr) || (chatWindow == nullptr))
2015
        return false;
2016
2017
    const std::string str = outfitWindow->getOutfitString();
2018
    if (!str.empty())
2019
        chatWindow->addInputText(str, true);
2020
    return true;
2021
}
2022
2023
impHandler0(outfitClear)
2024
{
2025
    if (outfitWindow == nullptr)
2026
        return false;
2027
2028
    outfitWindow->clearCurrentOutfit();
2029
    return true;
2030
}
2031
2032
impHandler(moveAttackUp)
2033
{
2034
    if (actorManager == nullptr)
2035
        return false;
2036
    const std::string args = event.args;
2037
    const int idx = actorManager->getAttackMobIndex(args);
2038
    if (idx > 0)
2039
    {
2040
        std::list<std::string> mobs
2041
            = actorManager->getAttackMobs();
2042
        std::list<std::string>::iterator it = mobs.begin();
2043
        std::list<std::string>::iterator it2 = it;
2044
        while (it != mobs.end())
2045
        {
2046
            if (*it == args)
2047
            {
2048
                -- it2;
2049
                mobs.splice(it2, mobs, it);
2050
                actorManager->setAttackMobs(mobs);
2051
                actorManager->rebuildAttackMobs();
2052
                break;
2053
            }
2054
            ++ it;
2055
            ++ it2;
2056
        }
2057
2058
        if (socialWindow != nullptr)
2059
            socialWindow->updateAttackFilter();
2060
        return true;
2061
    }
2062
    return false;
2063
}
2064
2065
impHandler(moveAttackDown)
2066
{
2067
    if (actorManager == nullptr)
2068
        return false;
2069
    const std::string args = event.args;
2070
    const int idx = actorManager->getAttackMobIndex(args);
2071
    const int size = actorManager->getAttackMobsSize();
2072
    if (idx + 1 < size)
2073
    {
2074
        std::list<std::string> mobs
2075
            = actorManager->getAttackMobs();
2076
        std::list<std::string>::iterator it = mobs.begin();
2077
        std::list<std::string>::iterator it2 = it;
2078
        while (it != mobs.end())
2079
        {
2080
            if (*it == args)
2081
            {
2082
                ++ it2;
2083
                if (it2 == mobs.end())
2084
                    break;
2085
2086
                mobs.splice(it, mobs, it2);
2087
                actorManager->setAttackMobs(mobs);
2088
                actorManager->rebuildAttackMobs();
2089
                break;
2090
            }
2091
            ++ it;
2092
            ++ it2;
2093
        }
2094
2095
        if (socialWindow != nullptr)
2096
            socialWindow->updateAttackFilter();
2097
        return true;
2098
    }
2099
    return false;
2100
}
2101
2102
impHandler(movePriorityAttackUp)
2103
{
2104
    if (actorManager == nullptr)
2105
        return false;
2106
    const std::string args = event.args;
2107
    const int idx = actorManager->
2108
        getPriorityAttackMobIndex(args);
2109
    if (idx > 0)
2110
    {
2111
        std::list<std::string> mobs
2112
            = actorManager->getPriorityAttackMobs();
2113
        std::list<std::string>::iterator it = mobs.begin();
2114
        std::list<std::string>::iterator it2 = it;
2115
        while (it != mobs.end())
2116
        {
2117
            if (*it == args)
2118
            {
2119
                -- it2;
2120
                mobs.splice(it2, mobs, it);
2121
                actorManager->setPriorityAttackMobs(mobs);
2122
                actorManager->rebuildPriorityAttackMobs();
2123
                break;
2124
            }
2125
            ++ it;
2126
            ++ it2;
2127
        }
2128
2129
        if (socialWindow != nullptr)
2130
            socialWindow->updateAttackFilter();
2131
        return true;
2132
    }
2133
    return false;
2134
}
2135
2136
impHandler(movePriorityAttackDown)
2137
{
2138
    if (actorManager == nullptr)
2139
        return false;
2140
    const std::string args = event.args;
2141
    const int idx = actorManager
2142
        ->getPriorityAttackMobIndex(args);
2143
    const int size = actorManager->getPriorityAttackMobsSize();
2144
    if (idx + 1 < size)
2145
    {
2146
        std::list<std::string> mobs
2147
            = actorManager->getPriorityAttackMobs();
2148
        std::list<std::string>::iterator it = mobs.begin();
2149
        std::list<std::string>::iterator it2 = it;
2150
        while (it != mobs.end())
2151
        {
2152
            if (*it == args)
2153
            {
2154
                ++ it2;
2155
                if (it2 == mobs.end())
2156
                    break;
2157
2158
                mobs.splice(it, mobs, it2);
2159
                actorManager->setPriorityAttackMobs(mobs);
2160
                actorManager->rebuildPriorityAttackMobs();
2161
                break;
2162
            }
2163
            ++ it;
2164
            ++ it2;
2165
        }
2166
2167
        if (socialWindow != nullptr)
2168
            socialWindow->updateAttackFilter();
2169
        return true;
2170
    }
2171
    return false;
2172
}
2173
2174
impHandler(addSkillShortcut)
2175
{
2176
    const std::string args = event.args;
2177
    if (args.empty() ||
2178
        itemShortcutWindow == nullptr)
2179
    {
2180
        return false;
2181
    }
2182
    const SkillInfo *restrict const skill = skillDialog->getSkill(
2183
        atoi(args.c_str()));
2184
    if (skill == nullptr)
2185
        return false;
2186
2187
    const int num = itemShortcutWindow->getTabIndex();
2188
    if (num < 0 ||
2189
        num >= CAST_S32(SHORTCUT_TABS) ||
2190
        num == CAST_S32(SHORTCUT_AUTO_TAB))
2191
    {
2192
        return false;
2193
    }
2194
2195
    ItemShortcut *const selShortcut = itemShortcut[num];
2196
    const size_t index = selShortcut->getFreeIndex();
2197
    if (index == SHORTCUT_ITEMS)
2198
        return true;
2199
2200
    selShortcut->setItem(index,
2201
        skill->id + SKILL_MIN_ID,
2202
        fromInt(skill->customSelectedLevel, ItemColor));
2203
    selShortcut->setItemData(index,
2204
        skill->toDataStr());
2205
2206
//    popupMenu->showSkillLevelPopup(skill);
2207
    return true;
2208
}
2209
2210
impHandler0(trimMemory)
2211
{
2212
#ifdef HAVE_MALLOC_TRIM
2213
    malloc_trim(0);
2214
#else
2215
    // TRANSLATORS: chat error about trim command
2216
    localChatTab->chatLog(_("Trim memory not supported"),
2217
        ChatMsgType::BY_SERVER,
2218
        IgnoreRecord_false,
2219
        TryRemoveColors_true);
2220
#endif
2221
    return true;
2222
}
2223
2224
2
}  // namespace Actions