GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/progs/manaplus/actions/commands.cpp Lines: 1 942 0.1 %
Date: 2019-10-15 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
        const int emotion = event.action - InputAction::HOMUN_EMOTE_1;
1040
        if (emoteShortcut != nullptr)
1041
            homunculusHandler->emote(emoteShortcut->getEmote(emotion));
1042
        if (Game::instance() != nullptr)
1043
            Game::instance()->setValidSpeed();
1044
        return true;
1045
    }
1046
1047
    return false;
1048
}
1049
1050
impHandler(commandHomunEmote)
1051
{
1052
    if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet())
1053
        return false;
1054
1055
    if (homunculusHandler != nullptr)
1056
    {
1057
        homunculusHandler->emote(CAST_U8(
1058
            atoi(event.args.c_str())));
1059
        return true;
1060
    }
1061
    return false;
1062
}
1063
1064
impHandler(createPublicChatRoom)
1065
{
1066
    if ((chatHandler == nullptr) || event.args.empty())
1067
        return false;
1068
    chatHandler->createChatRoom(event.args, "", 100, true);
1069
    return true;
1070
}
1071
1072
impHandler(joinChatRoom)
1073
{
1074
    if (chatHandler == nullptr)
1075
        return false;
1076
    const std::string args = event.args;
1077
    if (args.empty())
1078
        return false;
1079
    ChatObject *const chat = ChatObject::findByName(args);
1080
    if (chat == nullptr)
1081
        return false;
1082
    chatHandler->joinChat(chat, "");
1083
    return true;
1084
}
1085
1086
impHandler0(leaveChatRoom)
1087
{
1088
    if (chatHandler != nullptr)
1089
    {
1090
        chatHandler->leaveChatRoom();
1091
        return true;
1092
    }
1093
    return false;
1094
}
1095
1096
impHandler(confSet)
1097
{
1098
    std::string name;
1099
    std::string val;
1100
1101
    if (parse2Str(event.args, name, val))
1102
    {
1103
        config.setValue(name, val);
1104
        return true;
1105
    }
1106
    return false;
1107
}
1108
1109
impHandler(serverConfSet)
1110
{
1111
    std::string name;
1112
    std::string val;
1113
1114
    if (parse2Str(event.args, name, val))
1115
    {
1116
        serverConfig.setValue(name, val);
1117
        return true;
1118
    }
1119
    return false;
1120
}
1121
1122
impHandler(confGet)
1123
{
1124
    const std::string args = event.args;
1125
    if (args.empty())
1126
        return false;
1127
1128
    // TRANSLATORS: result from command /confget
1129
    const std::string str = strprintf(_("Config value: %s"),
1130
        config.getStringValue(args).c_str());
1131
    outStringNormal(event.tab, str, str);
1132
    return true;
1133
}
1134
1135
impHandler(serverConfGet)
1136
{
1137
    const std::string args = event.args;
1138
    if (args.empty())
1139
        return false;
1140
1141
    // TRANSLATORS: result from command /serverconfget
1142
    const std::string str = strprintf(_("Server config value: %s"),
1143
        serverConfig.getStringValue(args).c_str());
1144
    outStringNormal(event.tab, str, str);
1145
    return true;
1146
}
1147
1148
impHandler(slide)
1149
{
1150
    int x = 0;
1151
    int y = 0;
1152
1153
    if ((adminHandler != nullptr) && parse2Int(event.args, x, y))
1154
    {
1155
        adminHandler->slide(x, y);
1156
        return true;
1157
    }
1158
    return false;
1159
}
1160
1161
impHandler(selectSkillLevel)
1162
{
1163
    int skill = 0;
1164
    int level = 0;
1165
1166
    if ((skillDialog != nullptr) && parse2Int(event.args, skill, level))
1167
    {
1168
        skillDialog->selectSkillLevel(skill, level);
1169
        return true;
1170
    }
1171
    return false;
1172
}
1173
1174
impHandler(skill)
1175
{
1176
    StringVect vect;
1177
    splitToStringVector(vect, event.args, ' ');
1178
    const int sz = CAST_S32(vect.size());
1179
    if (sz < 1)
1180
        return true;
1181
    const int skillId = atoi(vect[0].c_str());
1182
    int level = 0;
1183
    std::string text;
1184
    if (sz > 1)
1185
    {
1186
        level = atoi(vect[1].c_str());
1187
        if (sz > 2)
1188
            text = vect[2];
1189
    }
1190
    // +++ add here also cast type and offsets
1191
    if (text.empty())
1192
    {
1193
        SkillDialog::useSkill(skillId,
1194
            AutoTarget_true,
1195
            level,
1196
            false,
1197
            "",
1198
            CastType::Default,
1199
            0,
1200
            0);
1201
    }
1202
    else
1203
    {
1204
        SkillDialog::useSkill(skillId,
1205
            AutoTarget_true,
1206
            level,
1207
            true,
1208
            text,
1209
            CastType::Default,
1210
            0,
1211
            0);
1212
    }
1213
    return true;
1214
}
1215
1216
impHandler(craft)
1217
{
1218
    const std::string args = event.args;
1219
    if (args.empty() || (inventoryWindow == nullptr))
1220
        return false;
1221
1222
    inventoryWindow->moveItemToCraft(atoi(args.c_str()));
1223
    return true;
1224
}
1225
1226
impHandler(npcClipboard)
1227
{
1228
    if (npcHandler != nullptr)
1229
    {
1230
        int x = 0;
1231
        int y = 0;
1232
1233
        NpcDialog *const dialog = npcHandler->getCurrentNpcDialog();
1234
1235
        if ((dialog != nullptr) && parse2Int(event.args, x, y))
1236
        {
1237
            dialog->copyToClipboard(x, y);
1238
            return true;
1239
        }
1240
    }
1241
    return false;
1242
}
1243
1244
impHandler(clipboardCopy)
1245
{
1246
    const std::string args = event.args;
1247
    if (args.empty())
1248
        return false;
1249
    sendBuffer(args);
1250
    return true;
1251
}
1252
1253
impHandler(addPickup)
1254
{
1255
    if (actorManager != nullptr)
1256
    {
1257
        actorManager->removePickupItem(event.args);
1258
        actorManager->addPickupItem(event.args);
1259
        if (socialWindow != nullptr)
1260
            socialWindow->updatePickupFilter();
1261
        return true;
1262
    }
1263
    return false;
1264
}
1265
1266
impHandler(removePickup)
1267
{
1268
    if (actorManager != nullptr)
1269
    {
1270
        if (event.args.empty())
1271
        {   // default pickup manipulation
1272
            if (actorManager->checkDefaultPickup())
1273
            {
1274
                actorManager->removePickupItem(event.args);
1275
                actorManager->addIgnorePickupItem(event.args);
1276
            }
1277
            else
1278
            {
1279
                actorManager->removePickupItem(event.args);
1280
                actorManager->addPickupItem(event.args);
1281
            }
1282
        }
1283
        else
1284
        {   // any other pickups
1285
            actorManager->removePickupItem(event.args);
1286
        }
1287
        if (socialWindow != nullptr)
1288
            socialWindow->updatePickupFilter();
1289
        return true;
1290
    }
1291
    return false;
1292
}
1293
1294
impHandler(ignorePickup)
1295
{
1296
    if (actorManager != nullptr)
1297
    {
1298
        actorManager->removePickupItem(event.args);
1299
        actorManager->addIgnorePickupItem(event.args);
1300
        if (socialWindow != nullptr)
1301
            socialWindow->updatePickupFilter();
1302
        return true;
1303
    }
1304
    return false;
1305
}
1306
1307
impHandler(monsterInfo)
1308
{
1309
    const std::string args = event.args;
1310
    if (args.empty())
1311
        return false;
1312
    adminHandler->monsterInfo(args);
1313
    return true;
1314
}
1315
1316
impHandler(itemInfo)
1317
{
1318
    const std::string args = event.args;
1319
    if (args.empty())
1320
        return false;
1321
    adminHandler->itemInfo(args);
1322
    return true;
1323
}
1324
1325
impHandler(whoDrops)
1326
{
1327
    const std::string args = event.args;
1328
    if (args.empty())
1329
        return false;
1330
    adminHandler->whoDrops(args);
1331
    return true;
1332
}
1333
1334
impHandler(mobSearch)
1335
{
1336
    const std::string args = event.args;
1337
    if (args.empty())
1338
        return false;
1339
    adminHandler->mobSearch(args);
1340
    return true;
1341
}
1342
1343
impHandler(mobSpawnSearch)
1344
{
1345
    const std::string args = event.args;
1346
    if (args.empty())
1347
        return false;
1348
    adminHandler->mobSpawnSearch(args);
1349
    return true;
1350
}
1351
1352
impHandler(playerGmCommands)
1353
{
1354
    adminHandler->playerGmCommands(event.args);
1355
    return true;
1356
}
1357
1358
impHandler(playerCharGmCommands)
1359
{
1360
    adminHandler->playerCharGmCommands(event.args);
1361
    return true;
1362
}
1363
1364
impHandler(commandShowLevel)
1365
{
1366
    adminHandler->showLevel(event.args);
1367
    return true;
1368
}
1369
1370
impHandler(commandShowStats)
1371
{
1372
    adminHandler->showStats(event.args);
1373
    return true;
1374
}
1375
1376
impHandler(commandShowStorage)
1377
{
1378
    adminHandler->showStorageList(event.args);
1379
    return true;
1380
}
1381
1382
impHandler(commandShowCart)
1383
{
1384
    adminHandler->showCartList(event.args);
1385
    return true;
1386
}
1387
1388
impHandler(commandShowInventory)
1389
{
1390
    adminHandler->showInventoryList(event.args);
1391
    return true;
1392
}
1393
1394
impHandler(locatePlayer)
1395
{
1396
    const std::string args = event.args;
1397
    if (args.empty())
1398
        return false;
1399
    adminHandler->locatePlayer(args);
1400
    return true;
1401
}
1402
1403
impHandler(commandShowAccountInfo)
1404
{
1405
    const std::string args = event.args;
1406
    if (args.empty())
1407
        return false;
1408
    adminHandler->showAccountInfo(args);
1409
    return true;
1410
}
1411
1412
impHandler(commandSpawn)
1413
{
1414
    const std::string args = event.args;
1415
    if (args.empty())
1416
        return false;
1417
    adminHandler->spawn(args);
1418
    return true;
1419
}
1420
1421
impHandler(commandSpawnSlave)
1422
{
1423
    const std::string args = event.args;
1424
    if (args.empty())
1425
        return false;
1426
    adminHandler->spawnSlave(args);
1427
    return true;
1428
}
1429
1430
impHandler(commandSpawnClone)
1431
{
1432
    const std::string args = event.args;
1433
    if (args.empty())
1434
        return false;
1435
    adminHandler->spawnClone(args);
1436
    return true;
1437
}
1438
1439
impHandler(commandSpawnSlaveClone)
1440
{
1441
    const std::string args = event.args;
1442
    if (args.empty())
1443
        return false;
1444
    adminHandler->spawnSlaveClone(args);
1445
    return true;
1446
}
1447
1448
impHandler(commandSpawnEvilClone)
1449
{
1450
    const std::string args = event.args;
1451
    if (args.empty())
1452
        return false;
1453
    adminHandler->spawnEvilClone(args);
1454
    return true;
1455
}
1456
1457
impHandler(commandSavePosition)
1458
{
1459
    adminHandler->savePosition(event.args);
1460
    return true;
1461
}
1462
1463
impHandler(commandLoadPosition)
1464
{
1465
    adminHandler->loadPosition(event.args);
1466
    return true;
1467
}
1468
1469
impHandler(commandRandomWarp)
1470
{
1471
    adminHandler->randomWarp(event.args);
1472
    return true;
1473
}
1474
1475
impHandler(commandGotoNpc)
1476
{
1477
    const std::string args = event.args;
1478
    if (args.empty())
1479
        return false;
1480
    adminHandler->gotoNpc(args);
1481
    return true;
1482
}
1483
1484
impHandler(commandGotoPc)
1485
{
1486
    const std::string args = event.args;
1487
    if (args.empty())
1488
        return false;
1489
    adminHandler->gotoName(args);
1490
    return true;
1491
}
1492
1493
impHandler(commandRecallPc)
1494
{
1495
    const std::string args = event.args;
1496
    if (args.empty())
1497
        return false;
1498
    adminHandler->recallName(args);
1499
    return true;
1500
}
1501
1502
impHandler(commandIpCheck)
1503
{
1504
    const std::string args = event.args;
1505
    if (args.empty())
1506
        return false;
1507
    adminHandler->ipcheckName(args);
1508
    return true;
1509
}
1510
1511
impHandler(commandKiller)
1512
{
1513
    adminHandler->killer(event.args);
1514
    return true;
1515
}
1516
1517
impHandler(commandKillable)
1518
{
1519
    adminHandler->killable(event.args);
1520
    return true;
1521
}
1522
1523
impHandler(commandHeal)
1524
{
1525
    adminHandler->heal(event.args);
1526
    return true;
1527
}
1528
1529
impHandler(commandAlive)
1530
{
1531
    adminHandler->alive(event.args);
1532
    return true;
1533
}
1534
1535
impHandler(commandDisguise)
1536
{
1537
    const std::string args = event.args;
1538
    if (args.empty())
1539
        return false;
1540
    adminHandler->disguise(args);
1541
    return true;
1542
}
1543
1544
impHandler(commandImmortal)
1545
{
1546
    adminHandler->immortal(event.args);
1547
    return true;
1548
}
1549
1550
impHandler(commandHide)
1551
{
1552
    adminHandler->hide(event.args);
1553
    return true;
1554
}
1555
1556
impHandler(commandNuke)
1557
{
1558
    const std::string args = event.args;
1559
    if (args.empty())
1560
        return false;
1561
    adminHandler->nuke(args);
1562
    return true;
1563
}
1564
1565
impHandler(commandKill)
1566
{
1567
    adminHandler->kill(event.args);
1568
    return true;
1569
}
1570
1571
impHandler(commandJail)
1572
{
1573
    const std::string args = event.args;
1574
    if (args.empty())
1575
        return false;
1576
    adminHandler->jail(args);
1577
    return true;
1578
}
1579
1580
impHandler(commandUnjail)
1581
{
1582
    const std::string args = event.args;
1583
    if (args.empty())
1584
        return false;
1585
    adminHandler->unjail(args);
1586
    return true;
1587
}
1588
1589
impHandler(commandNpcMove)
1590
{
1591
    const std::string args = event.args;
1592
    if (args.empty())
1593
        return false;
1594
    StringVect pars;
1595
    if (!splitParameters(pars, args, " ,", '\"'))
1596
        return false;
1597
1598
    if (pars.size() != 3)
1599
        return false;
1600
1601
    adminHandler->npcMove(pars[0],
1602
        atoi(pars[1].c_str()),
1603
        atoi(pars[2].c_str()));
1604
    return true;
1605
}
1606
1607
impHandler(commandNpcHide)
1608
{
1609
    const std::string args = event.args;
1610
    if (args.empty())
1611
        return false;
1612
    adminHandler->hideNpc(args);
1613
    return true;
1614
}
1615
1616
impHandler(commandNpcShow)
1617
{
1618
    const std::string args = event.args;
1619
    if (args.empty())
1620
        return false;
1621
    adminHandler->showNpc(args);
1622
    return true;
1623
}
1624
1625
impHandler(commandChangePartyLeader)
1626
{
1627
    const std::string args = event.args;
1628
    if (args.empty())
1629
        return false;
1630
    adminHandler->changePartyLeader(args);
1631
    return true;
1632
}
1633
1634
impHandler(commandPartyRecall)
1635
{
1636
    const std::string args = event.args;
1637
    if (args.empty())
1638
        return false;
1639
    adminHandler->partyRecall(args);
1640
    return true;
1641
}
1642
1643
impHandler(commandBreakGuild)
1644
{
1645
    adminHandler->breakGuild(event.args);
1646
    return true;
1647
}
1648
1649
impHandler(commandGuildRecall)
1650
{
1651
    const std::string args = event.args;
1652
    if (args.empty())
1653
        return false;
1654
    adminHandler->guildRecall(args);
1655
    return true;
1656
}
1657
1658
impHandler(mailTo)
1659
{
1660
    if (mailWindow == nullptr)
1661
        return false;
1662
    const std::string args = event.args;
1663
    if (settings.enableNewMailSystem)
1664
    {
1665
        mail2Handler->queueCheckName(MailQueueType::EditMail,
1666
            args,
1667
            std::string(),
1668
            std::string(),
1669
            0);
1670
    }
1671
    else
1672
    {
1673
        MailWindow::createMail(args);
1674
    }
1675
    return true;
1676
}
1677
1678
impHandler(adoptChild)
1679
{
1680
    const std::string nick = getNick(event);
1681
    Being *const being = actorManager->findBeingByName(
1682
        nick, ActorType::Player);
1683
    if (being == nullptr)
1684
        return true;
1685
    familyHandler->askForChild(being);
1686
    return true;
1687
}
1688
1689
impHandler(showSkillLevels)
1690
{
1691
    const std::string args = event.args;
1692
    if (args.empty())
1693
        return false;
1694
    const SkillInfo *restrict const skill = skillDialog->getSkill(
1695
        atoi(args.c_str()));
1696
    if (skill == nullptr)
1697
        return false;
1698
    popupMenu->showSkillLevelPopup(skill);
1699
    return true;
1700
}
1701
1702
impHandler(showSkillType)
1703
{
1704
    const std::string args = event.args;
1705
    if (args.empty())
1706
        return false;
1707
    const SkillInfo *restrict const skill = skillDialog->getSkill(
1708
        atoi(args.c_str()));
1709
    if (skill == nullptr)
1710
        return false;
1711
    popupMenu->showSkillTypePopup(skill);
1712
    return true;
1713
}
1714
1715
impHandler(selectSkillType)
1716
{
1717
    int skill = 0;
1718
    int type = 0;
1719
1720
    if ((skillDialog != nullptr) && parse2Int(event.args, skill, type))
1721
    {
1722
        skillDialog->selectSkillCastType(skill,
1723
            static_cast<CastTypeT>(type));
1724
        return true;
1725
    }
1726
    return false;
1727
}
1728
1729
impHandler(showSkillOffsetX)
1730
{
1731
    const std::string args = event.args;
1732
    if (args.empty())
1733
        return false;
1734
    const SkillInfo *restrict const skill = skillDialog->getSkill(
1735
        atoi(args.c_str()));
1736
    if (skill == nullptr)
1737
        return false;
1738
    popupMenu->showSkillOffsetPopup(skill, true);
1739
    return true;
1740
}
1741
1742
impHandler(showSkillOffsetY)
1743
{
1744
    const std::string args = event.args;
1745
    if (args.empty())
1746
        return false;
1747
    const SkillInfo *restrict const skill = skillDialog->getSkill(
1748
        atoi(args.c_str()));
1749
    if (skill == nullptr)
1750
        return false;
1751
    popupMenu->showSkillOffsetPopup(skill, false);
1752
    return true;
1753
}
1754
1755
impHandler(setSkillOffsetX)
1756
{
1757
    int skill = 0;
1758
    int offset = 0;
1759
1760
    if ((skillDialog != nullptr) && parse2Int(event.args, skill, offset))
1761
    {
1762
        skillDialog->setSkillOffsetX(skill, offset);
1763
        return true;
1764
    }
1765
    return false;
1766
}
1767
1768
impHandler(setSkillOffsetY)
1769
{
1770
    int skill = 0;
1771
    int offset = 0;
1772
1773
    if ((skillDialog != nullptr) && parse2Int(event.args, skill, offset))
1774
    {
1775
        skillDialog->setSkillOffsetY(skill, offset);
1776
        return true;
1777
    }
1778
    return false;
1779
}
1780
1781
impHandler(partyItemShare)
1782
{
1783
    if (localPlayer == nullptr)
1784
        return false;
1785
1786
    if (localPlayer->isInParty() == false)
1787
        return true;
1788
1789
    ChatTab *tab = event.tab;
1790
    if (tab == nullptr)
1791
        tab = localChatTab;
1792
    if (tab == nullptr)
1793
        return true;
1794
1795
    const std::string args = event.args;
1796
    if (args.empty())
1797
    {
1798
        switch (partyHandler->getShareItems())
1799
        {
1800
            case PartyShare::YES:
1801
                // TRANSLATORS: chat message
1802
                tab->chatLog(_("Item sharing enabled."),
1803
                    ChatMsgType::BY_SERVER,
1804
                    IgnoreRecord_false,
1805
                    TryRemoveColors_true);
1806
                return true;
1807
            case PartyShare::NO:
1808
                // TRANSLATORS: chat message
1809
                tab->chatLog(_("Item sharing disabled."),
1810
                    ChatMsgType::BY_SERVER,
1811
                    IgnoreRecord_false,
1812
                    TryRemoveColors_true);
1813
                return true;
1814
            case PartyShare::NOT_POSSIBLE:
1815
                // TRANSLATORS: chat message
1816
                tab->chatLog(_("Item sharing not possible."),
1817
                    ChatMsgType::BY_SERVER,
1818
                    IgnoreRecord_false,
1819
                    TryRemoveColors_true);
1820
                return true;
1821
            case PartyShare::UNKNOWN:
1822
                // TRANSLATORS: chat message
1823
                tab->chatLog(_("Item sharing unknown."),
1824
                    ChatMsgType::BY_SERVER,
1825
                    IgnoreRecord_false,
1826
                    TryRemoveColors_true);
1827
                return true;
1828
            default:
1829
                break;
1830
        }
1831
    }
1832
1833
    const signed char opt = parseBoolean(args);
1834
1835
    switch (opt)
1836
    {
1837
        case 1:
1838
            partyHandler->setShareItems(
1839
                PartyShare::YES);
1840
            break;
1841
        case 0:
1842
            partyHandler->setShareItems(
1843
                PartyShare::NO);
1844
            break;
1845
        case -1:
1846
            tab->chatLog(strprintf(BOOLEAN_OPTIONS, "item"),
1847
                ChatMsgType::BY_SERVER,
1848
                IgnoreRecord_false,
1849
                TryRemoveColors_true);
1850
            break;
1851
        default:
1852
            break;
1853
    }
1854
    return true;
1855
}
1856
1857
impHandler(partyExpShare)
1858
{
1859
    if (localPlayer == nullptr)
1860
        return false;
1861
1862
    if (localPlayer->isInParty() == false)
1863
        return true;
1864
1865
    ChatTab *tab = event.tab;
1866
    if (tab == nullptr)
1867
        tab = localChatTab;
1868
    if (tab == nullptr)
1869
        return true;
1870
1871
    const std::string args = event.args;
1872
    if (args.empty())
1873
    {
1874
        switch (partyHandler->getShareExperience())
1875
        {
1876
            case PartyShare::YES:
1877
                // TRANSLATORS: chat message
1878
                tab->chatLog(_("Experience sharing enabled."),
1879
                    ChatMsgType::BY_SERVER,
1880
                    IgnoreRecord_false,
1881
                    TryRemoveColors_true);
1882
                return true;
1883
            case PartyShare::NO:
1884
                // TRANSLATORS: chat message
1885
                tab->chatLog(_("Experience sharing disabled."),
1886
                    ChatMsgType::BY_SERVER,
1887
                    IgnoreRecord_false,
1888
                    TryRemoveColors_true);
1889
                return true;
1890
            case PartyShare::NOT_POSSIBLE:
1891
                // TRANSLATORS: chat message
1892
                tab->chatLog(_("Experience sharing not possible."),
1893
                    ChatMsgType::BY_SERVER,
1894
                    IgnoreRecord_false,
1895
                    TryRemoveColors_true);
1896
                return true;
1897
            case PartyShare::UNKNOWN:
1898
                // TRANSLATORS: chat message
1899
                tab->chatLog(_("Experience sharing unknown."),
1900
                    ChatMsgType::BY_SERVER,
1901
                    IgnoreRecord_false,
1902
                    TryRemoveColors_true);
1903
                return true;
1904
            default:
1905
                break;
1906
        }
1907
    }
1908
1909
    const signed char opt = parseBoolean(args);
1910
1911
    switch (opt)
1912
    {
1913
        case 1:
1914
            partyHandler->setShareExperience(
1915
                PartyShare::YES);
1916
            break;
1917
        case 0:
1918
            partyHandler->setShareExperience(
1919
                PartyShare::NO);
1920
            break;
1921
        case -1:
1922
            tab->chatLog(strprintf(BOOLEAN_OPTIONS, "exp"),
1923
                ChatMsgType::BY_SERVER,
1924
                IgnoreRecord_false,
1925
                TryRemoveColors_true);
1926
            break;
1927
        default:
1928
            break;
1929
    }
1930
    return true;
1931
}
1932
1933
impHandler(partyAutoItemShare)
1934
{
1935
    if (localPlayer == nullptr)
1936
        return false;
1937
1938
    if (localPlayer->isInParty() == false)
1939
        return true;
1940
1941
    ChatTab *tab = event.tab;
1942
    if (tab == nullptr)
1943
        tab = localChatTab;
1944
    if (tab == nullptr)
1945
        return true;
1946
1947
    const std::string args = event.args;
1948
    if (args.empty())
1949
    {
1950
        switch (partyHandler->getShareAutoItems())
1951
        {
1952
            case PartyShare::YES:
1953
                // TRANSLATORS: chat message
1954
                tab->chatLog(_("Auto item sharing enabled."),
1955
                    ChatMsgType::BY_SERVER,
1956
                    IgnoreRecord_false,
1957
                    TryRemoveColors_true);
1958
                return true;
1959
            case PartyShare::NO:
1960
                // TRANSLATORS: chat message
1961
                tab->chatLog(_("Auto item sharing disabled."),
1962
                    ChatMsgType::BY_SERVER,
1963
                    IgnoreRecord_false,
1964
                    TryRemoveColors_true);
1965
                return true;
1966
            case PartyShare::NOT_POSSIBLE:
1967
                // TRANSLATORS: chat message
1968
                tab->chatLog(_("Auto item sharing not possible."),
1969
                    ChatMsgType::BY_SERVER,
1970
                    IgnoreRecord_false,
1971
                    TryRemoveColors_true);
1972
                return true;
1973
            case PartyShare::UNKNOWN:
1974
                // TRANSLATORS: chat message
1975
                tab->chatLog(_("Auto item sharing unknown."),
1976
                    ChatMsgType::BY_SERVER,
1977
                    IgnoreRecord_false,
1978
                    TryRemoveColors_true);
1979
                return true;
1980
            default:
1981
                break;
1982
        }
1983
    }
1984
1985
    const signed char opt = parseBoolean(args);
1986
1987
    switch (opt)
1988
    {
1989
        case 1:
1990
            partyHandler->setShareAutoItems(
1991
                PartyShare::YES);
1992
            break;
1993
        case 0:
1994
            partyHandler->setShareAutoItems(
1995
                PartyShare::NO);
1996
            break;
1997
        case -1:
1998
            tab->chatLog(strprintf(BOOLEAN_OPTIONS, "item"),
1999
                ChatMsgType::BY_SERVER,
2000
                IgnoreRecord_false,
2001
                TryRemoveColors_true);
2002
            break;
2003
        default:
2004
            break;
2005
    }
2006
    return true;
2007
}
2008
2009
impHandler0(outfitToChat)
2010
{
2011
    if ((outfitWindow == nullptr) || (chatWindow == nullptr))
2012
        return false;
2013
2014
    const std::string str = outfitWindow->getOutfitString();
2015
    if (!str.empty())
2016
        chatWindow->addInputText(str, true);
2017
    return true;
2018
}
2019
2020
impHandler0(outfitClear)
2021
{
2022
    if (outfitWindow == nullptr)
2023
        return false;
2024
2025
    outfitWindow->clearCurrentOutfit();
2026
    return true;
2027
}
2028
2029
impHandler(moveAttackUp)
2030
{
2031
    if (actorManager == nullptr)
2032
        return false;
2033
    const std::string args = event.args;
2034
    const int idx = actorManager->getAttackMobIndex(args);
2035
    if (idx > 0)
2036
    {
2037
        std::list<std::string> mobs
2038
            = actorManager->getAttackMobs();
2039
        std::list<std::string>::iterator it = mobs.begin();
2040
        std::list<std::string>::iterator it2 = it;
2041
        while (it != mobs.end())
2042
        {
2043
            if (*it == args)
2044
            {
2045
                -- it2;
2046
                mobs.splice(it2, mobs, it);
2047
                actorManager->setAttackMobs(mobs);
2048
                actorManager->rebuildAttackMobs();
2049
                break;
2050
            }
2051
            ++ it;
2052
            ++ it2;
2053
        }
2054
2055
        if (socialWindow != nullptr)
2056
            socialWindow->updateAttackFilter();
2057
        return true;
2058
    }
2059
    return false;
2060
}
2061
2062
impHandler(moveAttackDown)
2063
{
2064
    if (actorManager == nullptr)
2065
        return false;
2066
    const std::string args = event.args;
2067
    const int idx = actorManager->getAttackMobIndex(args);
2068
    const int size = actorManager->getAttackMobsSize();
2069
    if (idx + 1 < size)
2070
    {
2071
        std::list<std::string> mobs
2072
            = actorManager->getAttackMobs();
2073
        std::list<std::string>::iterator it = mobs.begin();
2074
        std::list<std::string>::iterator it2 = it;
2075
        while (it != mobs.end())
2076
        {
2077
            if (*it == args)
2078
            {
2079
                ++ it2;
2080
                if (it2 == mobs.end())
2081
                    break;
2082
2083
                mobs.splice(it, mobs, it2);
2084
                actorManager->setAttackMobs(mobs);
2085
                actorManager->rebuildAttackMobs();
2086
                break;
2087
            }
2088
            ++ it;
2089
            ++ it2;
2090
        }
2091
2092
        if (socialWindow != nullptr)
2093
            socialWindow->updateAttackFilter();
2094
        return true;
2095
    }
2096
    return false;
2097
}
2098
2099
impHandler(movePriorityAttackUp)
2100
{
2101
    if (actorManager == nullptr)
2102
        return false;
2103
    const std::string args = event.args;
2104
    const int idx = actorManager->
2105
        getPriorityAttackMobIndex(args);
2106
    if (idx > 0)
2107
    {
2108
        std::list<std::string> mobs
2109
            = actorManager->getPriorityAttackMobs();
2110
        std::list<std::string>::iterator it = mobs.begin();
2111
        std::list<std::string>::iterator it2 = it;
2112
        while (it != mobs.end())
2113
        {
2114
            if (*it == args)
2115
            {
2116
                -- it2;
2117
                mobs.splice(it2, mobs, it);
2118
                actorManager->setPriorityAttackMobs(mobs);
2119
                actorManager->rebuildPriorityAttackMobs();
2120
                break;
2121
            }
2122
            ++ it;
2123
            ++ it2;
2124
        }
2125
2126
        if (socialWindow != nullptr)
2127
            socialWindow->updateAttackFilter();
2128
        return true;
2129
    }
2130
    return false;
2131
}
2132
2133
impHandler(movePriorityAttackDown)
2134
{
2135
    if (actorManager == nullptr)
2136
        return false;
2137
    const std::string args = event.args;
2138
    const int idx = actorManager
2139
        ->getPriorityAttackMobIndex(args);
2140
    const int size = actorManager->getPriorityAttackMobsSize();
2141
    if (idx + 1 < size)
2142
    {
2143
        std::list<std::string> mobs
2144
            = actorManager->getPriorityAttackMobs();
2145
        std::list<std::string>::iterator it = mobs.begin();
2146
        std::list<std::string>::iterator it2 = it;
2147
        while (it != mobs.end())
2148
        {
2149
            if (*it == args)
2150
            {
2151
                ++ it2;
2152
                if (it2 == mobs.end())
2153
                    break;
2154
2155
                mobs.splice(it, mobs, it2);
2156
                actorManager->setPriorityAttackMobs(mobs);
2157
                actorManager->rebuildPriorityAttackMobs();
2158
                break;
2159
            }
2160
            ++ it;
2161
            ++ it2;
2162
        }
2163
2164
        if (socialWindow != nullptr)
2165
            socialWindow->updateAttackFilter();
2166
        return true;
2167
    }
2168
    return false;
2169
}
2170
2171
impHandler(addSkillShortcut)
2172
{
2173
    const std::string args = event.args;
2174
    if (args.empty() ||
2175
        itemShortcutWindow == nullptr)
2176
    {
2177
        return false;
2178
    }
2179
    const SkillInfo *restrict const skill = skillDialog->getSkill(
2180
        atoi(args.c_str()));
2181
    if (skill == nullptr)
2182
        return false;
2183
2184
    const int num = itemShortcutWindow->getTabIndex();
2185
    if (num < 0 ||
2186
        num >= CAST_S32(SHORTCUT_TABS) ||
2187
        num == CAST_S32(SHORTCUT_AUTO_TAB))
2188
    {
2189
        return false;
2190
    }
2191
2192
    ItemShortcut *const selShortcut = itemShortcut[num];
2193
    const size_t index = selShortcut->getFreeIndex();
2194
    if (index == SHORTCUT_ITEMS)
2195
        return true;
2196
2197
    selShortcut->setItem(index,
2198
        skill->id + SKILL_MIN_ID,
2199
        fromInt(skill->customSelectedLevel, ItemColor));
2200
    selShortcut->setItemData(index,
2201
        skill->toDataStr());
2202
2203
//    popupMenu->showSkillLevelPopup(skill);
2204
    return true;
2205
}
2206
2207
impHandler0(trimMemory)
2208
{
2209
#ifdef HAVE_MALLOC_TRIM
2210
    malloc_trim(0);
2211
#else
2212
    // TRANSLATORS: chat error about trim command
2213
    localChatTab->chatLog(_("Trim memory not supported"),
2214
        ChatMsgType::BY_SERVER,
2215
        IgnoreRecord_false,
2216
        TryRemoveColors_true);
2217
#endif
2218
    return true;
2219
}
2220
2221
2
}  // namespace Actions