GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/playerhandler.cpp Lines: 8 428 1.9 %
Date: 2017-11-29 Branches: 0 589 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2017  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "net/eathena/playerhandler.h"
24
25
#include "notifymanager.h"
26
#include "party.h"
27
28
#include "being/localplayer.h"
29
#include "being/playerinfo.h"
30
31
#include "const/net/nostat.h"
32
33
#include "enums/resources/notifytypes.h"
34
35
#include "gui/windows/skilldialog.h"
36
#include "gui/windows/statuswindow.h"
37
38
#include "net/ea/inventoryhandler.h"
39
40
#include "net/eathena/messageout.h"
41
#include "net/eathena/protocolout.h"
42
#include "net/eathena/sp.h"
43
44
#include "resources/db/unitsdb.h"
45
46
#include "debug.h"
47
48
extern int packetVersion;
49
extern int serverVersion;
50
51
namespace EAthena
52
{
53
54
152
PlayerHandler::PlayerHandler() :
55
152
    Ea::PlayerHandler()
56
{
57
152
    playerHandler = this;
58
152
}
59
60
456
PlayerHandler::~PlayerHandler()
61
{
62
152
    playerHandler = nullptr;
63
152
}
64
65
void PlayerHandler::attack(const BeingId id,
66
                           const Keep keep) const
67
{
68
    createOutPacket(CMSG_PLAYER_CHANGE_ACT);
69
    outMsg.writeBeingId(id, "target id");
70
    if (keep == Keep_true)
71
        outMsg.writeInt8(7, "action");
72
    else
73
        outMsg.writeInt8(0, "action");
74
}
75
76
void PlayerHandler::stopAttack() const
77
{
78
    createOutPacket(CMSG_PLAYER_STOP_ATTACK);
79
}
80
81
void PlayerHandler::emote(const uint8_t emoteId) const
82
{
83
    createOutPacket(CMSG_PLAYER_EMOTE);
84
    outMsg.writeInt8(emoteId, "emote id");
85
}
86
87
void PlayerHandler::increaseAttribute(const AttributesT attr,
88
                                      const int amount) const
89
{
90
    if (attr >= Attributes::PLAYER_STR && attr <= Attributes::PLAYER_LUK)
91
    {
92
        createOutPacket(CMSG_STAT_UPDATE_REQUEST);
93
        outMsg.writeInt16(CAST_S16(attr), "attribute id");
94
        outMsg.writeInt8(CAST_S8(amount), "increase");
95
    }
96
}
97
98
void PlayerHandler::increaseSkill(const uint16_t skillId) const
99
{
100
    if (PlayerInfo::getAttribute(Attributes::PLAYER_SKILL_POINTS) <= 0)
101
        return;
102
103
    createOutPacket(CMSG_SKILL_LEVELUP_REQUEST);
104
    outMsg.writeInt16(skillId, "skill id");
105
}
106
107
void PlayerHandler::pickUp(const FloorItem *const floorItem) const
108
{
109
    if (floorItem == nullptr)
110
        return;
111
112
    createOutPacket(CMSG_ITEM_PICKUP);
113
    const BeingId id = floorItem->getId();
114
    if (packetVersion >= 20101124)
115
    {
116
        outMsg.writeBeingId(id, "object id");
117
    }
118
    else if (packetVersion >= 20080827)
119
    {
120
        outMsg.writeInt32(0, "unused");
121
        outMsg.writeInt8(0, "unused");
122
        outMsg.writeBeingId(id, "object id");
123
    }
124
    else if (packetVersion >= 20070212)
125
    {
126
        outMsg.writeInt32(0, "unused");
127
        outMsg.writeBeingId(id, "object id");
128
    }
129
    else if (packetVersion >= 20070108)
130
    {
131
        outMsg.writeInt32(0, "unused");
132
        outMsg.writeInt8(0, "unused");
133
        outMsg.writeBeingId(id, "object id");
134
    }
135
    else if (packetVersion >= 20050719)
136
    {
137
        outMsg.writeInt32(0, "unused");
138
        outMsg.writeInt16(0, "unused");
139
        outMsg.writeInt8(0, "unused");
140
        outMsg.writeBeingId(id, "object id");
141
    }
142
    else if (packetVersion >= 20050718)
143
    {
144
        outMsg.writeInt8(0, "unused");
145
        outMsg.writeBeingId(id, "object id");
146
    }
147
    else if (packetVersion >= 20050628)
148
    {
149
        outMsg.writeInt32(0, "unused");
150
        outMsg.writeInt8(0, "unused");
151
        outMsg.writeBeingId(id, "object id");
152
    }
153
    else if (packetVersion >= 20050509)
154
    {
155
        outMsg.writeInt16(0, "unused");
156
        outMsg.writeBeingId(id, "object id");
157
    }
158
    else if (packetVersion >= 20050110)
159
    {
160
        outMsg.writeInt16(0, "unused");
161
        outMsg.writeInt8(0, "unused");
162
        outMsg.writeBeingId(id, "object id");
163
    }
164
    else if (packetVersion >= 20041129)
165
    {
166
        outMsg.writeInt8(0, "unused");
167
        outMsg.writeBeingId(id, "object id");
168
    }
169
    else if (packetVersion >= 20041025)
170
    {
171
        outMsg.writeInt16(0, "unused");
172
        outMsg.writeInt8(0, "unused");
173
        outMsg.writeBeingId(id, "object id");
174
    }
175
    else if (packetVersion >= 20041005)
176
    {
177
        outMsg.writeInt32(0, "unused");
178
        outMsg.writeBeingId(id, "object id");
179
    }
180
    else if (packetVersion >= 20040920)
181
    {
182
        outMsg.writeInt32(0, "unused");
183
        outMsg.writeInt32(0, "unused");
184
        outMsg.writeBeingId(id, "object id");
185
    }
186
    else if (packetVersion >= 20040906)
187
    {
188
        outMsg.writeInt32(0, "unused");
189
        outMsg.writeInt8(0, "unused");
190
        outMsg.writeBeingId(id, "object id");
191
    }
192
    else if (packetVersion >= 20040809)
193
    {
194
        outMsg.writeInt32(0, "unused");
195
        outMsg.writeInt16(0, "unused");
196
        outMsg.writeInt8(0, "unused");
197
        outMsg.writeBeingId(id, "object id");
198
    }
199
    else if (packetVersion >= 20040713)
200
    {
201
        outMsg.writeInt32(0, "unused");
202
        outMsg.writeBeingId(id, "object id");
203
    }
204
    else
205
    {
206
        outMsg.writeBeingId(id, "object id");
207
    }
208
209
    Ea::InventoryHandler::pushPickup(floorItem->getId());
210
}
211
212
void PlayerHandler::setDirection(const unsigned char direction) const
213
{
214
    createOutPacket(CMSG_PLAYER_CHANGE_DIR);
215
    if (packetVersion >= 20101124)
216
    {
217
        outMsg.writeInt8(0, "head direction");
218
        outMsg.writeInt8(0, "unused");
219
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
220
            "player direction");
221
    }
222
    else if (packetVersion >= 20080827)
223
    {
224
        outMsg.writeInt16(0, "unused");
225
        outMsg.writeInt8(0, "head direction");
226
        outMsg.writeInt32(0, "unused");
227
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
228
            "player direction");
229
    }
230
    else if (packetVersion >= 20070212)
231
    {
232
        outMsg.writeInt32(0, "unused");
233
        outMsg.writeInt16(0, "unused");
234
        outMsg.writeInt8(0, "head direction");
235
        outMsg.writeInt16(0, "unused");
236
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
237
            "player direction");
238
    }
239
    else if (packetVersion >= 20070108)
240
    {
241
        outMsg.writeInt32(0, "unused");
242
        outMsg.writeInt32(0, "unused");
243
        outMsg.writeInt8(0, "head direction");
244
        outMsg.writeInt16(0, "unused");
245
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
246
            "player direction");
247
    }
248
    else if (packetVersion >= 20060327)
249
    {
250
        outMsg.writeInt32(0, "unused");
251
        outMsg.writeInt8(0, "unused");
252
        outMsg.writeInt8(0, "head direction");
253
        outMsg.writeInt8(0, "unused");
254
        outMsg.writeInt16(0, "unused");
255
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
256
            "player direction");
257
    }
258
    else if (packetVersion >= 20050719)
259
    {
260
        outMsg.writeInt32(0, "unused");
261
        outMsg.writeInt16(0, "unused");
262
        outMsg.writeInt8(0, "head direction");
263
        outMsg.writeInt8(0, "unused");
264
        outMsg.writeInt32(0, "unused");
265
        outMsg.writeInt16(0, "unused");
266
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
267
            "player direction");
268
    }
269
    else if (packetVersion >= 20050718)
270
    {
271
        outMsg.writeInt32(0, "unused");
272
        outMsg.writeInt8(0, "head direction");
273
        outMsg.writeInt8(0, "unused");
274
        outMsg.writeInt16(0, "unused");
275
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
276
            "player direction");
277
    }
278
    else if (packetVersion >= 20050628)
279
    {
280
        outMsg.writeInt32(0, "unused");
281
        outMsg.writeInt16(0, "unused");
282
        outMsg.writeInt8(0, "head direction");
283
        outMsg.writeInt8(0, "unused");
284
        outMsg.writeInt32(0, "unused");
285
        outMsg.writeInt16(0, "unused");
286
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
287
            "player direction");
288
    }
289
    else if (packetVersion >= 20050509)
290
    {
291
        outMsg.writeInt8(0, "unused");
292
        outMsg.writeInt32(0, "unused");
293
        outMsg.writeInt16(0, "unused");
294
        outMsg.writeInt8(0, "head direction");
295
        outMsg.writeInt8(0, "unused");
296
        outMsg.writeInt16(0, "unused");
297
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
298
            "player direction");
299
    }
300
    else if (packetVersion >= 20050110)
301
    {
302
        outMsg.writeInt32(0, "unused");
303
        outMsg.writeInt32(0, "unused");
304
        outMsg.writeInt16(0, "unused");
305
        outMsg.writeInt8(0, "head direction");
306
        outMsg.writeInt8(0, "unused");
307
        outMsg.writeInt32(0, "unused");
308
        outMsg.writeInt32(0, "unused");
309
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
310
            "player direction");
311
    }
312
    else if (packetVersion >= 20041129)
313
    {
314
        outMsg.writeInt8(0, "unused");
315
        outMsg.writeInt8(0, "head direction");
316
        outMsg.writeInt8(0, "unused");
317
        outMsg.writeInt16(0, "unused");
318
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
319
            "player direction");
320
    }
321
    else if (packetVersion >= 20041025)
322
    {
323
        outMsg.writeInt32(0, "unused");
324
        outMsg.writeInt8(0, "head direction");
325
        outMsg.writeInt8(0, "unused");
326
        outMsg.writeInt32(0, "unused");
327
        outMsg.writeInt16(0, "unused");
328
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
329
            "player direction");
330
    }
331
    else if (packetVersion >= 20041005)
332
    {
333
        outMsg.writeInt16(0, "unused");
334
        outMsg.writeInt8(0, "unused");
335
        outMsg.writeInt8(0, "head direction");
336
        outMsg.writeInt32(0, "unused");
337
        outMsg.writeInt16(0, "unused");
338
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
339
            "player direction");
340
    }
341
    else if (packetVersion >= 20040920)
342
    {
343
        outMsg.writeInt32(0, "unused");
344
        outMsg.writeInt16(0, "unused");
345
        outMsg.writeInt8(0, "head direction");
346
        outMsg.writeInt32(0, "unused");
347
        outMsg.writeInt32(0, "unused");
348
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
349
            "player direction");
350
    }
351
    else if (packetVersion >= 20040906)
352
    {
353
        outMsg.writeInt16(0, "unused");
354
        outMsg.writeInt8(0, "head direction");
355
        outMsg.writeInt16(0, "unused");
356
        outMsg.writeInt16(0, "unused");
357
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
358
            "player direction");
359
    }
360
    else if (packetVersion >= 20040809)
361
    {
362
        outMsg.writeInt16(0, "unused");
363
        outMsg.writeInt16(0, "unused");
364
        outMsg.writeInt8(0, "unused");
365
        outMsg.writeInt8(0, "head direction");
366
        outMsg.writeInt16(0, "unused");
367
        outMsg.writeInt8(0, "unused");
368
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
369
            "player direction");
370
    }
371
    else if (packetVersion >= 20040713)
372
    {
373
        outMsg.writeInt8(0, "unused");
374
        outMsg.writeInt8(0, "unused");
375
        outMsg.writeInt8(0, "unused");
376
        outMsg.writeInt8(0, "head direction");
377
        outMsg.writeInt16(0, "unused");
378
        outMsg.writeInt16(0, "unused");
379
        outMsg.writeInt16(0, "unused");
380
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
381
            "player direction");
382
    }
383
    else
384
    {
385
        outMsg.writeInt8(0, "head direction");
386
        outMsg.writeInt8(0, "unused");
387
        outMsg.writeInt8(MessageOut::toServerDirection(direction),
388
            "player direction");
389
    }
390
}
391
392
void PlayerHandler::setDestination(const int x, const int y,
393
                                   const int direction) const
394
{
395
    createOutPacket(CMSG_PLAYER_CHANGE_DEST);
396
    if (packetVersion >= 20080827 && packetVersion < 20101124)
397
        outMsg.writeInt32(0, "unused");
398
    outMsg.writeCoordinates(CAST_U16(x),
399
        CAST_U16(y),
400
        CAST_U8(direction), "destination");
401
}
402
403
void PlayerHandler::changeAction(const BeingActionT &action) const
404
{
405
    unsigned char type;
406
    switch (action)
407
    {
408
        case BeingAction::SIT:
409
            type = 2;
410
            break;
411
        case BeingAction::STAND:
412
        case BeingAction::PRESTAND:
413
            type = 3;
414
            break;
415
        default:
416
        case BeingAction::MOVE:
417
        case BeingAction::ATTACK:
418
        case BeingAction::DEAD:
419
        case BeingAction::HURT:
420
        case BeingAction::SPAWN:
421
        case BeingAction::CAST:
422
            return;
423
    }
424
425
    createOutPacket(CMSG_PLAYER_CHANGE_ACT);
426
    outMsg.writeInt32(0, "unused");
427
    outMsg.writeInt8(type, "action");
428
}
429
430
void PlayerHandler::respawn() const
431
{
432
    createOutPacket(CMSG_PLAYER_RESTART);
433
    outMsg.writeInt8(0, "action");
434
}
435
436
void PlayerHandler::requestOnlineList() const
437
{
438
    createOutPacket(CMSG_ONLINE_LIST);
439
}
440
441
void PlayerHandler::updateStatus(const uint8_t status) const
442
{
443
    createOutPacket(CMSG_SET_STATUS);
444
    outMsg.writeInt8(status, "status");
445
    outMsg.writeInt8(0, "unused");
446
}
447
448
void PlayerHandler::setShortcut(const int idx,
449
                                const uint8_t type,
450
                                const int id,
451
                                const int level) const
452
{
453
    createOutPacket(CMSG_SET_SHORTCUTS);
454
    outMsg.writeInt16(CAST_S16(idx), "index");
455
    outMsg.writeInt8(CAST_S8(type), "type");
456
    outMsg.writeInt32(id, "id");
457
    outMsg.writeInt16(CAST_S16(level), "level");
458
}
459
460
void PlayerHandler::shortcutShiftRow(const int row) const
461
{
462
    if (packetVersion < 20140129)
463
        return;
464
    createOutPacket(CMSG_SHORTCUTS_ROW_SHIFT);
465
    outMsg.writeInt8(CAST_S8(row), "row");
466
}
467
468
void PlayerHandler::removeOption() const
469
{
470
    createOutPacket(CMSG_REMOVE_OPTION);
471
}
472
473
void PlayerHandler::changeCart(const int type) const
474
{
475
    createOutPacket(CMSG_CHANGE_CART);
476
    outMsg.writeInt16(CAST_S16(type), "type");
477
}
478
479
void PlayerHandler::setMemo() const
480
{
481
    createOutPacket(CMSG_PLAYER_SET_MEMO);
482
}
483
484
void PlayerHandler::doriDori() const
485
{
486
    createOutPacket(CMSG_DORI_DORI);
487
}
488
489
void PlayerHandler::explosionSpirits() const
490
{
491
    createOutPacket(CMSG_EXPLOSION_SPIRITS);
492
}
493
494
void PlayerHandler::requestPvpInfo() const
495
{
496
    createOutPacket(CMSG_PVP_INFO);
497
    outMsg.writeInt32(0, "char id");
498
    outMsg.writeInt32(0, "account id");
499
}
500
501
void PlayerHandler::revive() const
502
{
503
    createOutPacket(CMSG_PLAYER_AUTO_REVIVE);
504
}
505
506
void PlayerHandler::setViewEquipment(const bool allow) const
507
{
508
    createOutPacket(CMSG_PLAYER_SET_EQUIPMENT_VISIBLE);
509
    outMsg.writeInt32(0, "unused");
510
    outMsg.writeInt32(allow ? 1 : 0, "allow");
511
}
512
513
#define setStatComplex(stat) \
514
    PlayerInfo::setStatBase(stat, base, notify); \
515
    if (mod != NoStat) \
516
        PlayerInfo::setStatMod(stat, mod)
517
518
void PlayerHandler::setStat(Net::MessageIn &msg,
519
                            const int type,
520
                            const int64_t base,
521
                            const int mod,
522
                            const Notify notify) const
523
{
524
    switch (type)
525
    {
526
        case Sp::SPEED:
527
            localPlayer->setWalkSpeed(base);
528
            PlayerInfo::setStatBase(Attributes::PLAYER_WALK_SPEED, base);
529
            PlayerInfo::setStatMod(Attributes::PLAYER_WALK_SPEED, 0);
530
            break;
531
        case Sp::BASEEXP:
532
            PlayerInfo::setAttribute(Attributes::PLAYER_EXP, base);
533
            break;
534
        case Sp::JOBEXP:
535
            PlayerInfo::setAttribute(Attributes::PLAYER_JOB_EXP, base);
536
            break;
537
        case Sp::KARMA:
538
            PlayerInfo::setStatBase(Attributes::PLAYER_KARMA, base);
539
            PlayerInfo::setStatMod(Attributes::PLAYER_KARMA, 0);
540
            break;
541
        case Sp::MANNER:
542
            PlayerInfo::setStatBase(Attributes::PLAYER_MANNER, base);
543
            PlayerInfo::setStatMod(Attributes::PLAYER_MANNER, 0);
544
            break;
545
        case Sp::HP:
546
            PlayerInfo::setAttribute(Attributes::PLAYER_HP, base);
547
            if (localPlayer->isInParty() && (Party::getParty(1) != nullptr))
548
            {
549
                PartyMember *const m = Party::getParty(1)
550
                    ->getMember(localPlayer->getId());
551
                if (m != nullptr)
552
                {
553
                    m->setHp(base);
554
                    m->setMaxHp(PlayerInfo::getAttribute(
555
                        Attributes::PLAYER_MAX_HP));
556
                }
557
            }
558
            break;
559
        case Sp::MAXHP:
560
            PlayerInfo::setAttribute(Attributes::PLAYER_MAX_HP, base);
561
562
            if (localPlayer->isInParty() && (Party::getParty(1) != nullptr))
563
            {
564
                PartyMember *const m = Party::getParty(1)->getMember(
565
                    localPlayer->getId());
566
                if (m != nullptr)
567
                {
568
                    m->setHp(PlayerInfo::getAttribute(Attributes::PLAYER_HP));
569
                    m->setMaxHp(base);
570
                }
571
            }
572
            break;
573
        case Sp::SP:
574
            PlayerInfo::setAttribute(Attributes::PLAYER_MP, base);
575
            break;
576
        case Sp::MAXSP:
577
            PlayerInfo::setAttribute(Attributes::PLAYER_MAX_MP, base);
578
            break;
579
        case Sp::STATUSPOINT:
580
            PlayerInfo::setAttribute(Attributes::PLAYER_CHAR_POINTS, base);
581
            break;
582
        case Sp::BASELEVEL:
583
            PlayerInfo::setAttribute(Attributes::PLAYER_BASE_LEVEL, base);
584
            if (localPlayer != nullptr)
585
            {
586
                localPlayer->setLevel(base);
587
                localPlayer->updateName();
588
            }
589
            break;
590
        case Sp::SKILLPOINT:
591
            PlayerInfo::setAttribute(Attributes::PLAYER_SKILL_POINTS, base);
592
            if (skillDialog != nullptr)
593
                skillDialog->update();
594
            break;
595
        case Sp::STR:
596
            setStatComplex(Attributes::PLAYER_STR);
597
            break;
598
        case Sp::AGI:
599
            setStatComplex(Attributes::PLAYER_AGI);
600
            break;
601
        case Sp::VIT:
602
            setStatComplex(Attributes::PLAYER_VIT);
603
            break;
604
        case Sp::INT:
605
            setStatComplex(Attributes::PLAYER_INT);
606
            break;
607
        case Sp::DEX:
608
            setStatComplex(Attributes::PLAYER_DEX);
609
            break;
610
        case Sp::LUK:
611
            setStatComplex(Attributes::PLAYER_LUK);
612
            break;
613
        case Sp::ZENY:
614
        {
615
            const int oldMoney = PlayerInfo::getAttribute(Attributes::MONEY);
616
            const int newMoney = base;
617
            if (newMoney > oldMoney)
618
            {
619
                NotifyManager::notify(NotifyTypes::MONEY_GET,
620
                    UnitsDb::formatCurrency(newMoney - oldMoney));
621
            }
622
            else if (newMoney < oldMoney)
623
            {
624
                NotifyManager::notify(NotifyTypes::MONEY_SPENT,
625
                    UnitsDb::formatCurrency(oldMoney - newMoney).c_str());
626
            }
627
628
            PlayerInfo::setAttribute(Attributes::MONEY, newMoney);
629
            break;
630
        }
631
        case Sp::NEXTBASEEXP:
632
            PlayerInfo::setAttribute(Attributes::PLAYER_EXP_NEEDED, base);
633
            break;
634
        case Sp::NEXTJOBEXP:
635
            PlayerInfo::setAttribute(Attributes::PLAYER_JOB_EXP_NEEDED, base);
636
            break;
637
        case Sp::WEIGHT:
638
            PlayerInfo::setAttribute(Attributes::TOTAL_WEIGHT, base);
639
            break;
640
        case Sp::MAXWEIGHT:
641
            PlayerInfo::setAttribute(Attributes::MAX_WEIGHT, base);
642
            break;
643
        case Sp::USTR:
644
            statusWindow->setPointsNeeded(Attributes::PLAYER_STR, base);
645
            break;
646
        case Sp::UAGI:
647
            statusWindow->setPointsNeeded(Attributes::PLAYER_AGI, base);
648
            break;
649
        case Sp::UVIT:
650
            statusWindow->setPointsNeeded(Attributes::PLAYER_VIT, base);
651
            break;
652
        case Sp::UINT:
653
            statusWindow->setPointsNeeded(Attributes::PLAYER_INT, base);
654
            break;
655
        case Sp::UDEX:
656
            statusWindow->setPointsNeeded(Attributes::PLAYER_DEX, base);
657
            break;
658
        case Sp::ULUK:
659
            statusWindow->setPointsNeeded(Attributes::PLAYER_LUK, base);
660
            break;
661
662
        case Sp::ATK1:
663
            PlayerInfo::setStatBase(Attributes::PLAYER_ATK, base);
664
            PlayerInfo::updateAttrs();
665
            break;
666
        case Sp::ATK2:
667
            PlayerInfo::setStatMod(Attributes::PLAYER_ATK, base);
668
            PlayerInfo::updateAttrs();
669
            break;
670
        case Sp::MATK1:
671
            PlayerInfo::setStatBase(Attributes::PLAYER_MATK, base);
672
            break;
673
        case Sp::MATK2:
674
            PlayerInfo::setStatMod(Attributes::PLAYER_MATK, base);
675
            break;
676
        case Sp::DEF1:
677
            PlayerInfo::setStatBase(Attributes::PLAYER_DEF, base);
678
            break;
679
        case Sp::DEF2:
680
            PlayerInfo::setStatMod(Attributes::PLAYER_DEF, base);
681
            break;
682
        case Sp::MDEF1:
683
            PlayerInfo::setStatBase(Attributes::PLAYER_MDEF, base);
684
            break;
685
        case Sp::MDEF2:
686
            PlayerInfo::setStatMod(Attributes::PLAYER_MDEF, base);
687
            break;
688
        case Sp::HIT:
689
            PlayerInfo::setStatBase(Attributes::PLAYER_HIT, base);
690
            break;
691
        case Sp::FLEE1:
692
            PlayerInfo::setStatBase(Attributes::PLAYER_FLEE, base);
693
            break;
694
        case Sp::FLEE2:
695
            PlayerInfo::setStatMod(Attributes::PLAYER_FLEE, base);
696
            break;
697
        case Sp::CRITICAL:
698
            PlayerInfo::setStatBase(Attributes::PLAYER_CRIT, base);
699
            break;
700
        case Sp::ASPD:
701
            localPlayer->setAttackSpeed(base);
702
            PlayerInfo::setStatBase(Attributes::PLAYER_ATTACK_DELAY, base);
703
            PlayerInfo::setStatMod(Attributes::PLAYER_ATTACK_DELAY, 0);
704
            PlayerInfo::updateAttrs();
705
            break;
706
        case Sp::JOBLEVEL:
707
            PlayerInfo::setAttribute(Attributes::PLAYER_JOB_LEVEL, base);
708
            break;
709
710
        default:
711
            UNIMPLEMENTEDPACKETFIELD(type);
712
            break;
713
    }
714
}
715
716
#undef setStatComplex
717
718
4
}  // namespace EAthena