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

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