GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/mercenaryrecv.cpp Lines: 1 115 0.9 %
Date: 2021-03-17 Branches: 0 98 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2011-2019  The ManaPlus Developers
4
 *  Copyright (C) 2019-2021  Andrei Karas
5
 *
6
 *  This file is part of The ManaPlus Client.
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License as published by
10
 *  the Free Software Foundation; either version 2 of the License, or
11
 *  any later version.
12
 *
13
 *  This program is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *  GNU General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU General Public License
19
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
#include "net/eathena/mercenaryrecv.h"
23
24
#include "actormanager.h"
25
#include "notifymanager.h"
26
27
#include "being/localplayer.h"
28
#include "being/mercenaryinfo.h"
29
#include "being/playerinfo.h"
30
31
#include "enums/resources/notifytypes.h"
32
33
#include "gui/windows/skilldialog.h"
34
35
#include "net/messagein.h"
36
37
#include "net/eathena/sp.h"
38
39
#include "utils/checkutils.h"
40
41
#include "debug.h"
42
43
namespace EAthena
44
{
45
46
#define setMercStat(sp, stat) \
47
        case sp: \
48
            PlayerInfo::setStatBase(stat, \
49
                val, \
50
                Notify_true); \
51
            break
52
53
void MercenaryRecv::processMercenaryUpdate(Net::MessageIn &msg)
54
{
55
    const int sp = msg.readInt16("type");
56
    const int val = msg.readInt32("value");
57
    switch (sp)
58
    {
59
        setMercStat(Sp::ATK1, Attributes::MERC_ATK);
60
        setMercStat(Sp::MATK1, Attributes::MERC_MATK);
61
        setMercStat(Sp::HIT, Attributes::MERC_HIT);
62
        setMercStat(Sp::CRITICAL, Attributes::MERC_CRIT);
63
        setMercStat(Sp::DEF1, Attributes::MERC_DEF);
64
        setMercStat(Sp::MDEF1, Attributes::MERC_MDEF);
65
        setMercStat(Sp::MERCFLEE, Attributes::MERC_FLEE);
66
        setMercStat(Sp::ASPD, Attributes::MERC_ATTACK_DELAY);
67
        setMercStat(Sp::HP, Attributes::MERC_HP);
68
        setMercStat(Sp::MAXHP, Attributes::MERC_MAX_HP);
69
        setMercStat(Sp::SP, Attributes::MERC_MP);
70
        setMercStat(Sp::MAXSP, Attributes::MERC_MAX_MP);
71
        setMercStat(Sp::MERCKILLS, Attributes::MERC_KILLS);
72
        setMercStat(Sp::MERCFAITH, Attributes::MERC_FAITH);
73
        default:
74
            reportAlways("Unknown mercenary stat %d",
75
                sp)
76
            break;
77
    }
78
}
79
80
void MercenaryRecv::processMercenaryInfo(Net::MessageIn &msg)
81
{
82
    if (actorManager == nullptr)
83
        return;
84
    // +++ need create if need mercenary being and update stats
85
    Being *const dstBeing = actorManager->findBeing(
86
        msg.readBeingId("being id"));
87
    PlayerInfo::setStatBase(Attributes::MERC_ATK,
88
        msg.readInt16("atk"),
89
        Notify_true);
90
    PlayerInfo::setStatBase(Attributes::MERC_MATK,
91
        msg.readInt16("matk"),
92
        Notify_true);
93
    PlayerInfo::setStatBase(Attributes::MERC_HIT,
94
        msg.readInt16("hit"),
95
        Notify_true);
96
    PlayerInfo::setStatBase(Attributes::MERC_CRIT,
97
        msg.readInt16("crit/10"),
98
        Notify_true);
99
    PlayerInfo::setStatBase(Attributes::MERC_DEF,
100
        msg.readInt16("def"),
101
        Notify_true);
102
    PlayerInfo::setStatBase(Attributes::MERC_MDEF,
103
        msg.readInt16("mdef"),
104
        Notify_true);
105
    PlayerInfo::setStatBase(Attributes::MERC_FLEE,
106
        msg.readInt16("flee"),
107
        Notify_true);
108
    PlayerInfo::setStatBase(Attributes::MERC_ATTACK_DELAY,
109
        msg.readInt16("attack speed"),
110
        Notify_true);
111
    const std::string name = msg.readString(24, "name");
112
    const int level = msg.readInt16("level");
113
    PlayerInfo::setStatBase(Attributes::MERC_LEVEL,
114
        level,
115
        Notify_true);
116
    PlayerInfo::setStatBase(Attributes::MERC_HP,
117
        msg.readInt32("hp"),
118
        Notify_true);
119
    PlayerInfo::setStatBase(Attributes::MERC_MAX_HP,
120
        msg.readInt32("max hp"),
121
        Notify_true);
122
    PlayerInfo::setStatBase(Attributes::MERC_MP,
123
        msg.readInt32("sp"),
124
        Notify_true);
125
    PlayerInfo::setStatBase(Attributes::MERC_MAX_MP,
126
        msg.readInt32("max sp"),
127
        Notify_true);
128
    PlayerInfo::setStatBase(Attributes::MERC_EXPIRE,
129
        msg.readInt32("expire time"),
130
        Notify_true);
131
    PlayerInfo::setStatBase(Attributes::MERC_FAITH,
132
        msg.readInt16("faith"),
133
        Notify_true);
134
    PlayerInfo::setStatBase(Attributes::MERC_CALLS,
135
        msg.readInt32("calls"),
136
        Notify_true);
137
    PlayerInfo::setStatBase(Attributes::MERC_KILLS,
138
        msg.readInt32("kills"),
139
        Notify_true);
140
    const int range = msg.readInt16("attack range");
141
    PlayerInfo::setStatBase(Attributes::MERC_ATTACK_RANGE,
142
        range,
143
        Notify_true);
144
    PlayerInfo::updateAttrs();
145
146
    if ((dstBeing != nullptr) && (localPlayer != nullptr))
147
    {
148
        MercenaryInfo *const mercenary = new MercenaryInfo;
149
        mercenary->id = dstBeing->getId();
150
        mercenary->name = name;
151
        mercenary->level = level;
152
        mercenary->range = range;
153
        PlayerInfo::setMercenary(mercenary);
154
        PlayerInfo::setMercenaryBeing(dstBeing);
155
    }
156
}
157
158
void MercenaryRecv::processMercenarySkills(Net::MessageIn &msg)
159
{
160
    if (skillDialog != nullptr)
161
        skillDialog->hideSkills(SkillOwner::Mercenary);
162
    const int count = (msg.readInt16("len") - 4) / 37;
163
    for (int f = 0; f < count; f ++)
164
    {
165
        const int skillId = msg.readInt16("skill id");
166
        const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
167
            msg.readInt32("inf"));
168
        const int level = msg.readInt16("skill level");
169
        const int sp = msg.readInt16("sp");
170
        const int range = msg.readInt16("range");
171
        const std::string name = msg.readString(24, "skill name");
172
        const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
173
        PlayerInfo::setSkillLevel(skillId, level);
174
        if (skillDialog != nullptr)
175
        {
176
            if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
177
            {
178
                skillDialog->addSkill(SkillOwner::Mercenary,
179
                    skillId, name, level, range, up, inf, sp);
180
            }
181
        }
182
    }
183
    if (skillDialog != nullptr)
184
        skillDialog->updateModels();
185
}
186
187
void MercenaryRecv::handleMercenaryMessage(const int cmd)
188
{
189
    PlayerInfo::setMercenary(nullptr);
190
    if (skillDialog != nullptr)
191
    {
192
        skillDialog->hideSkills(SkillOwner::Mercenary);
193
        skillDialog->updateModels();
194
    }
195
196
    switch (cmd)
197
    {
198
        case 0:
199
            NotifyManager::notify(NotifyTypes::MERCENARY_EXPIRED);
200
            break;
201
        case 1:
202
            NotifyManager::notify(NotifyTypes::MERCENARY_KILLED);
203
            break;
204
        case 2:
205
            NotifyManager::notify(NotifyTypes::MERCENARY_FIRED);
206
            break;
207
        case 3:
208
            NotifyManager::notify(NotifyTypes::MERCENARY_RUN);
209
            break;
210
        default:
211
            NotifyManager::notify(NotifyTypes::MERCENARY_UNKNOWN);
212
            break;
213
    }
214
}
215
216
2
}  // namespace EAthena