GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gamemodifiers.cpp Lines: 1 138 0.7 %
Date: 2017-11-29 Branches: 0 194 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2011-2017  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 "gamemodifiers.h"
22
23
#include "configuration.h"
24
#include "game.h"
25
#include "settings.h"
26
#include "soundmanager.h"
27
28
#include "being/localplayer.h"
29
30
#include "gui/viewport.h"
31
32
#include "gui/windows/chatwindow.h"
33
#include "gui/windows/okdialog.h"
34
#include "gui/windows/outfitwindow.h"
35
36
#include "gui/widgets/createwidget.h"
37
38
#include "gui/widgets/tabs/chat/chattab.h"
39
40
#include "listeners/gamemodifierlistener.h"
41
42
#include "resources/map/map.h"
43
44
#include "listeners/awaylistener.h"
45
#include "listeners/updatestatuslistener.h"
46
47
#include "utils/gettext.h"
48
49
#include "debug.h"
50
51
#define addModifier(name1, name2, sz, ...) \
52
    const unsigned GameModifiers::m##name1##Size = sz; \
53
    const char *const GameModifiers::m##name1##Strings[] = \
54
    __VA_ARGS__; \
55
    std::string GameModifiers::get##name1##String() \
56
    { \
57
        return gettext(getVarItem(&m##name1##Strings[0], \
58
        CAST_U32(settings.name2), m##name1##Size)); \
59
    }
60
61
#define addModifier2(name1, name2, str, sz, ...) \
62
    const unsigned GameModifiers::m##name1##Size = sz; \
63
    const char *const GameModifiers::m##name1##Strings[] = \
64
    __VA_ARGS__; \
65
    void GameModifiers::change##name1(const bool forward) \
66
    { \
67
        changeMode(&settings.name2, m##name1##Size, str, \
68
            &GameModifiers::get##name1##String, 0, true, forward); \
69
    } \
70
    std::string GameModifiers::get##name1##String() \
71
    { \
72
        return gettext(getVarItem(&m##name1##Strings[0], \
73
        settings.name2, m##name1##Size)); \
74
    }
75
76
#define changeMethod(name1, name2, str) \
77
    void GameModifiers::change##name1(const bool forward) \
78
    { \
79
        changeMode(&settings.name2, m##name1##Size, str, \
80
            &GameModifiers::get##name1##String, 0, true, forward); \
81
    }
82
83
void GameModifiers::init()
84
{
85
    settings.crazyMoveType = config.getIntValue("crazyMoveType");
86
    settings.moveToTargetType = config.getIntValue("moveToTargetType");
87
    settings.followMode = config.getIntValue("followMode");
88
    settings.attackWeaponType = config.getIntValue("attackWeaponType");
89
    settings.attackType = config.getIntValue("attackType");
90
    settings.targetingType = config.getIntValue("targetingType");
91
    settings.quickDropCounter = config.getIntValue("quickDropCounter");
92
    settings.pickUpType = config.getIntValue("pickUpType");
93
    settings.magicAttackType = config.getIntValue("magicAttackType");
94
    settings.pvpAttackType = config.getIntValue("pvpAttackType");
95
    settings.imitationMode = config.getIntValue("imitationMode");
96
    settings.disableGameModifiers = config.getBoolValue(
97
        "disableGameModifiers");
98
    settings.awayMode = false;
99
    settings.mapDrawType = MapType::NORMAL;
100
//    UpdateStatusListener::distributeEvent();
101
}
102
103
void GameModifiers::changeMode(unsigned *restrict const var,
104
                               const unsigned limit,
105
                               const char *restrict const conf,
106
                               std::string (*const func)(),
107
                               const unsigned def,
108
                               const bool save,
109
                               const bool forward)
110
{
111
    if (var == nullptr)
112
        return;
113
114
    if (forward)
115
    {
116
        (*var) ++;
117
        if (*var >= limit)
118
            *var = def;
119
    }
120
    else
121
    {
122
        if (*var == 0u)
123
            *var = limit - 1;
124
        else
125
            (*var) --;
126
    }
127
128
    if (save)
129
        config.setValue(conf, *var);
130
    UpdateStatusListener::distributeEvent();
131
    GameModifierListener::distributeEvent();
132
    const std::string str = (*func)();
133
    if (str.size() > 4)
134
        debugMsg(str.substr(4));
135
}
136
137
const char *GameModifiers::getVarItem(const char *const *const arr,
138
                                      const unsigned index,
139
                                      const unsigned sz)
140
{
141
    if (index < sz)
142
        return arr[index];
143
    return arr[sz];
144
}
145
146
addModifier(MoveType, moveType, 5,
147
{
148
    // TRANSLATORS: move type in status bar
149
    N_("(D) default moves"),
150
    // TRANSLATORS: move type in status bar
151
    N_("(I) invert moves"),
152
    // TRANSLATORS: move type in status bar
153
    N_("(c) moves with some crazy moves"),
154
    // TRANSLATORS: move type in status bar
155
    N_("(C) moves with crazy moves"),
156
    // TRANSLATORS: move type in status bar
157
    N_("(d) double normal + crazy"),
158
    // TRANSLATORS: move type in status bar
159
    N_("(?) unknown move")
160
})
161
162
void GameModifiers::changeMoveType(const bool forward)
163
{
164
    localPlayer->setMoveState(0);
165
    changeMode(&settings.moveType, mMoveTypeSize, "invertMoveDirection",
166
        &GameModifiers::getMoveTypeString, 0, false, forward);
167
}
168
169
const unsigned GameModifiers::mCrazyMoveTypeSize = 11;
170
171
void GameModifiers::changeCrazyMoveType(const bool forward)
172
{
173
    settings.crazyMoveState = 0U;
174
    changeMode(&settings.crazyMoveType, mCrazyMoveTypeSize, "crazyMoveType",
175
        &GameModifiers::getCrazyMoveTypeString, 1, true, forward);
176
}
177
178
std::string GameModifiers::getCrazyMoveTypeString()
179
{
180
    const unsigned int crazyMoveType = settings.crazyMoveType;
181
    if (crazyMoveType < mCrazyMoveTypeSize - 1)
182
    {
183
        // TRANSLATORS: crazy move type in status bar
184
        return strprintf(_("(%u) crazy move number %u"),
185
            crazyMoveType, crazyMoveType);
186
    }
187
    else if (crazyMoveType == mCrazyMoveTypeSize - 1)
188
    {
189
        // TRANSLATORS: crazy move type in status bar
190
        return _("(a) custom crazy move");
191
    }
192
    else
193
    {
194
        // TRANSLATORS: crazy move type in status bar
195
        return _("(?) crazy move");
196
    }
197
}
198
199
addModifier2(MoveToTargetType, moveToTargetType, "moveToTargetType", 13,
200
{
201
    // TRANSLATORS: move to target type in status bar
202
    N_("(0) default moves to target"),
203
    // TRANSLATORS: move to target type in status bar
204
    N_("(1) moves to target in distance 1"),
205
    // TRANSLATORS: move to target type in status bar
206
    N_("(2) moves to target in distance 2"),
207
    // TRANSLATORS: move to target type in status bar
208
    N_("(3) moves to target in distance 3"),
209
    // TRANSLATORS: move to target type in status bar
210
    N_("(4) moves to target in distance 4"),
211
    // TRANSLATORS: move to target type in status bar
212
    N_("(5) moves to target in distance 5"),
213
    // TRANSLATORS: move to target type in status bar
214
    N_("(6) moves to target in distance 6"),
215
    // TRANSLATORS: move to target type in status bar
216
    N_("(7) moves to target in distance 7"),
217
    // TRANSLATORS: move to target type in status bar
218
    N_("(8) moves to target in distance 8"),
219
    // TRANSLATORS: move to target type in status bar
220
    N_("(9) moves to target in distance 9"),
221
    // TRANSLATORS: move to target type in status bar
222
    N_("(A) moves to target in attack range"),
223
    // TRANSLATORS: move to target type in status bar
224
    N_("(a) archer attack range"),
225
    // TRANSLATORS: move to target type in status bar
226
    N_("(B) moves to target in attack range - 1"),
227
    // TRANSLATORS: move to target type in status bar
228
    N_("(?) move to target")
229
})
230
231
addModifier2(FollowMode, followMode, "followMode", 4,
232
{
233
    // TRANSLATORS: folow mode in status bar
234
    N_("(D) default follow"),
235
    // TRANSLATORS: folow mode in status bar
236
    N_("(R) relative follow"),
237
    // TRANSLATORS: folow mode in status bar
238
    N_("(M) mirror follow"),
239
    // TRANSLATORS: folow mode in status bar
240
    N_("(P) pet follow"),
241
    // TRANSLATORS: folow mode in status bar
242
    N_("(?) unknown follow")
243
})
244
245
addModifier2(AttackWeaponType, attackWeaponType, "attackWeaponType", 4,
246
{
247
    // TRANSLATORS: switch attack type in status bar
248
    N_("(?) attack"),
249
    // TRANSLATORS: switch attack type in status bar
250
    N_("(D) default attack"),
251
    // TRANSLATORS: switch attack type in status bar
252
    N_("(s) switch attack without shield"),
253
    // TRANSLATORS: switch attack type in status bar
254
    N_("(S) switch attack with shield"),
255
    // TRANSLATORS: switch attack type in status bar
256
    N_("(?) attack")
257
})
258
259
addModifier2(AttackType, attackType, "attackType", 4,
260
{
261
    // TRANSLATORS: attack type in status bar
262
    N_("(D) default attack"),
263
    // TRANSLATORS: attack type in status bar
264
    N_("(G) go and attack"),
265
    // TRANSLATORS: attack type in status bar
266
    N_("(A) go, attack, pickup"),
267
    // TRANSLATORS: attack type in status bar
268
    N_("(d) without auto attack"),
269
    // TRANSLATORS: attack type in status bar
270
    N_("(?) attack")
271
})
272
273
addModifier2(TargetingType, targetingType, "targetingType", 2,
274
{
275
    // TRANSLATORS: targeting type in status bar
276
    N_("(D) don't switch target"),
277
    // TRANSLATORS: targeting type in status bar
278
    N_("(C) always attack closest"),
279
    // TRANSLATORS: targeting type in status bar
280
    N_("(?) targeting")
281
})
282
283
const unsigned GameModifiers::mQuickDropCounterSize = 31;
284
285
changeMethod(QuickDropCounter, quickDropCounter, "quickDropCounter")
286
287
std::string GameModifiers::getQuickDropCounterString()
288
{
289
    const unsigned int cnt = settings.quickDropCounter;
290
    if (cnt > 9)
291
    {
292
        return strprintf("(%c) drop counter %u", CAST_S8(
293
            'a' + cnt - 10), cnt);
294
    }
295
    return strprintf("(%u) drop counter %u", cnt, cnt);
296
}
297
298
void GameModifiers::setQuickDropCounter(const int n)
299
{
300
    if (n < 1 || n >= CAST_S32(mQuickDropCounterSize))
301
        return;
302
    settings.quickDropCounter = n;
303
    config.setValue("quickDropCounter", n);
304
    UpdateStatusListener::distributeEvent();
305
    GameModifierListener::distributeEvent();
306
}
307
308
addModifier2(PickUpType, pickUpType, "pickUpType", 7,
309
{
310
    // TRANSLATORS: pickup size in status bar
311
    N_("(S) small pick up 1x1 cells"),
312
    // TRANSLATORS: pickup size in status bar
313
    N_("(D) default pick up 2x1 cells"),
314
    // TRANSLATORS: pickup size in status bar
315
    N_("(F) forward pick up 2x3 cells"),
316
    // TRANSLATORS: pickup size in status bar
317
    N_("(3) pick up 3x3 cells"),
318
    // TRANSLATORS: pickup size in status bar
319
    N_("(g) go and pick up in distance 4"),
320
    // TRANSLATORS: pickup size in status bar
321
    N_("(G) go and pick up in distance 8"),
322
    // TRANSLATORS: pickup size in status bar
323
    N_("(A) go and pick up in max distance"),
324
    // TRANSLATORS: pickup size in status bar
325
    N_("(?) pick up")
326
})
327
328
addModifier2(MagicAttackType, magicAttackType, "magicAttackType", 5,
329
{
330
    // TRANSLATORS: magic attack in status bar
331
    N_("(f) use #flar for magic attack"),
332
    // TRANSLATORS: magic attack in status bar
333
    N_("(c) use #chiza for magic attack"),
334
    // TRANSLATORS: magic attack in status bar
335
    N_("(I) use #ingrav for magic attack"),
336
    // TRANSLATORS: magic attack in status bar
337
    N_("(F) use #frillyar for magic attack"),
338
    // TRANSLATORS: magic attack in status bar
339
    N_("(U) use #upmarmu for magic attack"),
340
    // TRANSLATORS: magic attack in status bar
341
    N_("(?) magic attack")
342
})
343
344
addModifier2(PvpAttackType, pvpAttackType, "pvpAttackType", 4,
345
{
346
    // TRANSLATORS: player attack type in status bar
347
    N_("(a) attack all players"),
348
    // TRANSLATORS: player attack type in status bar
349
    N_("(f) attack all except friends"),
350
    // TRANSLATORS: player attack type in status bar
351
    N_("(b) attack bad relations"),
352
    // TRANSLATORS: player attack type in status bar
353
    N_("(d) don't attack players"),
354
    // TRANSLATORS: player attack type in status bar
355
    N_("(?) pvp attack")
356
})
357
358
addModifier2(ImitationMode, imitationMode, "imitationMode", 2,
359
{
360
    // TRANSLATORS: imitation type in status bar
361
    N_("(D) default imitation"),
362
    // TRANSLATORS: imitation type in status bar
363
    N_("(O) outfits imitation"),
364
    // TRANSLATORS: imitation type in status bar
365
    N_("(?) imitation")
366
})
367
368
addModifier(GameModifiers, disableGameModifiers, 2,
369
{
370
    // TRANSLATORS: game modifiers state in status bar
371
    N_("Game modifiers are enabled"),
372
    // TRANSLATORS: game modifiers state in status bar
373
    N_("Game modifiers are disabled"),
374
    // TRANSLATORS: game modifiers state in status bar
375
    N_("Game modifiers are unknown")
376
})
377
378
void GameModifiers::changeGameModifiers(const bool forward A_UNUSED)
379
{
380
    settings.disableGameModifiers = !settings.disableGameModifiers;
381
    config.setValue("disableGameModifiers", settings.disableGameModifiers);
382
    UpdateStatusListener::distributeEvent();
383
    GameModifierListener::distributeEvent();
384
}
385
386
addModifier(MapDrawType, mapDrawType, 7,
387
{
388
    // TRANSLATORS: map view type in status bar
389
    N_("(N) normal map view"),
390
    // TRANSLATORS: map view type in status bar
391
    N_("(D) debug map view"),
392
    // TRANSLATORS: map view type in status bar
393
    N_("(u) ultra map view"),
394
    // TRANSLATORS: map view type in status bar
395
    N_("(U) ultra map view 2"),
396
    // TRANSLATORS: map view type in status bar
397
    N_("(e) empty map view with collision"),
398
    // TRANSLATORS: map view type in status bar
399
    N_("(E) empty map view"),
400
    // TRANSLATORS: map view type in status bar
401
    N_("(b) black & white map view"),
402
    // TRANSLATORS: pickup size in status bar
403
    N_("(?) map view")
404
})
405
406
void GameModifiers::changeMapDrawType(const bool forward A_UNUSED)
407
{
408
    if (viewport != nullptr)
409
        viewport->toggleMapDrawType();
410
}
411
412
addModifier(AwayMode, awayMode, 2,
413
{
414
    // TRANSLATORS: away type in status bar
415
    N_("(O) on keyboard"),
416
    // TRANSLATORS: away type in status bar
417
    N_("(A) away"),
418
    // TRANSLATORS: away type in status bar
419
    N_("(?) away")
420
})
421
422
void GameModifiers::changeAwayMode(const bool forward A_UNUSED)
423
{
424
    if (localPlayer == nullptr)
425
        return;
426
427
    settings.awayMode = !settings.awayMode;
428
    localPlayer->setAfkTime(0);
429
    localPlayer->setHalfAway(false);
430
    localPlayer->updateName();
431
    Game::instance()->updateFrameRate(0);
432
    UpdateStatusListener::distributeEvent();
433
    GameModifierListener::distributeEvent();
434
    if (settings.awayMode)
435
    {
436
        if (chatWindow != nullptr)
437
            chatWindow->clearAwayLog();
438
439
        localPlayer->cancelFollow();
440
        localPlayer->navigateClean();
441
        if (outfitWindow != nullptr)
442
            outfitWindow->wearAwayOutfit();
443
        OkDialog *const dialog = CREATEWIDGETR(OkDialog,
444
            // TRANSLATORS: away message box header
445
            _("Away"),
446
            serverConfig.getValue("afkMessage", "I am away from keyboard."),
447
            // TRANSLATORS: ok dialog button
448
            _("OK"),
449
            DialogType::SILENCE,
450
            Modal_true,
451
            ShowCenter_false,
452
            nullptr,
453
            260);
454
        localPlayer->setAwayDialog(dialog);
455
        dialog->addActionListener(localPlayer->getAwayListener());
456
        soundManager.volumeOff();
457
        localPlayer->addAfkEffect();
458
    }
459
    else
460
    {
461
        localPlayer->setAwayDialog(nullptr);
462
        soundManager.volumeRestore();
463
        if (chatWindow != nullptr)
464
        {
465
            chatWindow->displayAwayLog();
466
            chatWindow->clearAwayLog();
467
        }
468
        localPlayer->removeAfkEffect();
469
    }
470
}
471
472
addModifier(CameraMode, cameraMode, 2,
473
{
474
    // TRANSLATORS: camera mode in status bar
475
    N_("(G) game camera mode"),
476
    // TRANSLATORS: camera mode in status bar
477
    N_("(F) free camera mode"),
478
    // TRANSLATORS: camera mode in status bar
479
    N_("(?) away")
480
})
481
482
483
void GameModifiers::changeCameraMode(const bool forward A_UNUSED)
484
{
485
    if (viewport != nullptr)
486
        viewport->toggleCameraMode();
487
}
488
489
void GameModifiers::resetModifiers()
490
{
491
    settings.moveType = 0;
492
    settings.crazyMoveType = config.resetIntValue("crazyMoveType");
493
    settings.moveToTargetType = config.resetIntValue("moveToTargetType");
494
    settings.followMode = config.resetIntValue("followMode");
495
    settings.attackWeaponType = config.resetIntValue("attackWeaponType");
496
    settings.attackType = config.resetIntValue("attackType");
497
    settings.magicAttackType = config.resetIntValue("magicAttackType");
498
    settings.pvpAttackType = config.resetIntValue("pvpAttackType");
499
    settings.quickDropCounter = config.resetIntValue("quickDropCounter");
500
    settings.pickUpType = config.resetIntValue("pickUpType");
501
    settings.targetingType = config.resetIntValue("targetingType");
502
    settings.mapDrawType = MapType::NORMAL;
503
    if (viewport != nullptr)
504
    {
505
        if (settings.cameraMode != 0u)
506
            viewport->toggleCameraMode();
507
        Map *const map = viewport->getMap();
508
        if (map != nullptr)
509
            map->setDrawLayersFlags(MapType::NORMAL);
510
    }
511
    settings.imitationMode = config.resetIntValue("imitationMode");
512
    settings.disableGameModifiers = config.resetBoolValue(
513
        "disableGameModifiers");
514
515
    UpdateStatusListener::distributeEvent();
516
    GameModifierListener::distributeEvent();
517
4
}