GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/homunculusrecv.cpp Lines: 1 198 0.5 %
Date: 2019-03-19 Branches: 0 226 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2011-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 "net/eathena/homunculusrecv.h"
22
23
#include "actormanager.h"
24
#include "notifymanager.h"
25
26
#include "being/homunculusinfo.h"
27
#include "being/playerinfo.h"
28
#include "being/localplayer.h"
29
30
#include "enums/resources/notifytypes.h"
31
32
#include "gui/windows/skilldialog.h"
33
34
#include "resources/iteminfo.h"
35
36
#include "resources/db/itemdb.h"
37
38
#include "net/messagein.h"
39
40
#include "utils/stringutils.h"
41
42
#include "debug.h"
43
44
namespace EAthena
45
{
46
47
void HomunculusRecv::processHomunculusSkills(Net::MessageIn &msg)
48
{
49
    if (skillDialog != nullptr)
50
        skillDialog->hideSkills(SkillOwner::Homunculus);
51
52
    const int count = (msg.readInt16("len") - 4) / 37;
53
    for (int f = 0; f < count; f ++)
54
    {
55
        const int skillId = msg.readInt16("skill id");
56
        const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
57
            msg.readInt16("inf"));
58
        msg.readInt16("unused");
59
        const int level = msg.readInt16("skill level");
60
        const int sp = msg.readInt16("sp");
61
        const int range = msg.readInt16("range");
62
        const std::string name = msg.readString(24, "skill name");
63
        const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
64
        PlayerInfo::setSkillLevel(skillId, level);
65
        if (skillDialog != nullptr)
66
        {
67
            if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
68
            {
69
                skillDialog->addSkill(SkillOwner::Homunculus,
70
                    skillId, name, level, range, up, inf, sp);
71
            }
72
        }
73
    }
74
    if (skillDialog != nullptr)
75
        skillDialog->updateModels();
76
}
77
78
void HomunculusRecv::processHomunculusData(Net::MessageIn &msg)
79
{
80
    if (actorManager == nullptr)
81
        return;
82
    msg.readUInt8("unused");
83
    const int cmd = msg.readUInt8("state");
84
    const BeingId id = msg.readBeingId("homunculus id");
85
    Being *const dstBeing = actorManager->findBeing(id);
86
    const int data = msg.readInt32("data");
87
    if (cmd == 0)  // pre init
88
    {
89
        HomunculusInfo *const info = new HomunculusInfo;
90
        info->id = id;
91
        PlayerInfo::setHomunculus(info);
92
        PlayerInfo::setHomunculusBeing(dstBeing);
93
        return;
94
    }
95
    HomunculusInfo *const info = PlayerInfo::getHomunculus();
96
    if (info == nullptr)
97
        return;
98
    switch (cmd)
99
    {
100
        case 1:  // intimacy
101
            info->intimacy = data;
102
            break;
103
        case 2:  // hunger
104
            info->hungry = data;
105
            break;
106
        case 3:  // accesory
107
            info->equip = data;
108
            break;
109
        default:
110
            break;
111
    }
112
}
113
114
void HomunculusRecv::processHomunculusInfo1(Net::MessageIn &msg)
115
{
116
    if (actorManager == nullptr)
117
        return;
118
    const std::string name = msg.readString(24, "name");
119
    msg.readUInt8("flags");  // 0x01 - renamed, 0x02 - vaporize, 0x04 - alive
120
    const int level = msg.readInt16("level");
121
    PlayerInfo::setStatBase(Attributes::HOMUN_LEVEL,
122
        level,
123
        Notify_true);
124
    const int hungry = msg.readInt16("hungry");
125
    const int intimacy = msg.readInt16("intimacy");
126
    const int equip = msg.readItemId("item id");
127
    PlayerInfo::setStatBase(Attributes::HOMUN_ATK,
128
        msg.readInt16("atk"),
129
        Notify_true);
130
    PlayerInfo::setStatBase(Attributes::HOMUN_MATK,
131
        msg.readInt16("matk"),
132
        Notify_true);
133
    PlayerInfo::setStatBase(Attributes::HOMUN_HIT,
134
        msg.readInt16("hit"),
135
        Notify_true);
136
    PlayerInfo::setStatBase(Attributes::HOMUN_CRIT,
137
        msg.readInt16("luk/3 or crit/10"),
138
        Notify_true);
139
    PlayerInfo::setStatBase(Attributes::HOMUN_DEF,
140
        msg.readInt16("def"),
141
        Notify_true);
142
    PlayerInfo::setStatBase(Attributes::HOMUN_MDEF,
143
        msg.readInt16("mdef"),
144
        Notify_true);
145
    PlayerInfo::setStatBase(Attributes::HOMUN_FLEE,
146
        msg.readInt16("flee"),
147
        Notify_true);
148
    PlayerInfo::setStatBase(Attributes::HOMUN_ATTACK_DELAY,
149
        msg.readInt16("attack speed"),
150
        Notify_true);
151
    PlayerInfo::setStatBase(Attributes::HOMUN_HP,
152
        msg.readInt16("hp"),
153
        Notify_true);
154
    PlayerInfo::setStatBase(Attributes::HOMUN_MAX_HP,
155
        msg.readInt16("max hp"),
156
        Notify_true);
157
    PlayerInfo::setStatBase(Attributes::HOMUN_MP,
158
        msg.readInt16("sp"),
159
        Notify_true);
160
    PlayerInfo::setStatBase(Attributes::HOMUN_MAX_MP,
161
        msg.readInt16("max sp"),
162
        Notify_true);
163
    PlayerInfo::setStatBase(Attributes::HOMUN_EXP,
164
        msg.readInt32("exp"),
165
        Notify_true);
166
    PlayerInfo::setStatBase(Attributes::HOMUN_EXP_NEEDED,
167
        msg.readInt32("next exp"),
168
        Notify_true);
169
    PlayerInfo::setStatBase(Attributes::HOMUN_SKILL_POINTS,
170
        msg.readInt16("skill points"),
171
        Notify_true);
172
    const int range = msg.readInt16("attack range");
173
    PlayerInfo::setStatBase(Attributes::HOMUN_ATTACK_RANGE,
174
        range,
175
        Notify_true);
176
177
    PlayerInfo::updateAttrs();
178
    HomunculusInfo *const info = PlayerInfo::getHomunculus();
179
    if (info == nullptr)
180
        return;
181
    Being *const dstBeing = actorManager->findBeing(info->id);
182
183
    info->name = name;
184
    info->level = level;
185
    info->range = range;
186
    info->hungry = hungry;
187
    info->intimacy = intimacy;
188
    info->equip = equip;
189
    PlayerInfo::setHomunculusBeing(dstBeing);
190
}
191
192
void HomunculusRecv::processHomunculusInfo2(Net::MessageIn &msg)
193
{
194
    if (actorManager == nullptr)
195
        return;
196
    const std::string name = msg.readString(24, "name");
197
    msg.readUInt8("flags");  // 0x01 - renamed, 0x02 - vaporize, 0x04 - alive
198
    const int level = msg.readInt16("level");
199
    PlayerInfo::setStatBase(Attributes::HOMUN_LEVEL,
200
        level,
201
        Notify_true);
202
    const int hungry = msg.readInt16("hungry");
203
    const int intimacy = msg.readInt16("intimacy");
204
    const int equip = msg.readItemId("item id");
205
    PlayerInfo::setStatBase(Attributes::HOMUN_ATK,
206
        msg.readInt16("atk"),
207
        Notify_true);
208
    PlayerInfo::setStatBase(Attributes::HOMUN_MATK,
209
        msg.readInt16("matk"),
210
        Notify_true);
211
    PlayerInfo::setStatBase(Attributes::HOMUN_HIT,
212
        msg.readInt16("hit"),
213
        Notify_true);
214
    PlayerInfo::setStatBase(Attributes::HOMUN_CRIT,
215
        msg.readInt16("luk/3 or crit/10"),
216
        Notify_true);
217
    PlayerInfo::setStatBase(Attributes::HOMUN_DEF,
218
        msg.readInt16("def"),
219
        Notify_true);
220
    PlayerInfo::setStatBase(Attributes::HOMUN_MDEF,
221
        msg.readInt16("mdef"),
222
        Notify_true);
223
    PlayerInfo::setStatBase(Attributes::HOMUN_FLEE,
224
        msg.readInt16("flee"),
225
        Notify_true);
226
    PlayerInfo::setStatBase(Attributes::HOMUN_ATTACK_DELAY,
227
        msg.readInt16("attack speed"),
228
        Notify_true);
229
    PlayerInfo::setStatBase(Attributes::HOMUN_HP,
230
        msg.readInt32("hp"),
231
        Notify_true);
232
    PlayerInfo::setStatBase(Attributes::HOMUN_MAX_HP,
233
        msg.readInt32("max hp"),
234
        Notify_true);
235
    PlayerInfo::setStatBase(Attributes::HOMUN_MP,
236
        msg.readInt16("sp"),
237
        Notify_true);
238
    PlayerInfo::setStatBase(Attributes::HOMUN_MAX_MP,
239
        msg.readInt16("max sp"),
240
        Notify_true);
241
    PlayerInfo::setStatBase(Attributes::HOMUN_EXP,
242
        msg.readInt32("exp"),
243
        Notify_true);
244
    PlayerInfo::setStatBase(Attributes::HOMUN_EXP_NEEDED,
245
        msg.readInt32("next exp"),
246
        Notify_true);
247
    PlayerInfo::setStatBase(Attributes::HOMUN_SKILL_POINTS,
248
        msg.readInt16("skill points"),
249
        Notify_true);
250
    const int range = msg.readInt16("attack range");
251
    PlayerInfo::setStatBase(Attributes::HOMUN_ATTACK_RANGE,
252
        range,
253
        Notify_true);
254
255
    PlayerInfo::updateAttrs();
256
    HomunculusInfo *const info = PlayerInfo::getHomunculus();
257
    if (info == nullptr)
258
        return;
259
    Being *const dstBeing = actorManager->findBeing(info->id);
260
261
    info->name = name;
262
    info->level = level;
263
    info->range = range;
264
    info->hungry = hungry;
265
    info->intimacy = intimacy;
266
    info->equip = equip;
267
    PlayerInfo::setHomunculusBeing(dstBeing);
268
}
269
270
void HomunculusRecv::processHomunculusSkillUp(Net::MessageIn &msg)
271
{
272
    const int skillId = msg.readInt16("skill id");
273
    const int level = msg.readInt16("level");
274
    const int sp = msg.readInt16("sp");
275
    const int range = msg.readInt16("range");
276
    const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
277
278
    if (skillDialog != nullptr && PlayerInfo::getSkillLevel(skillId) != level)
279
        skillDialog->playUpdateEffect(skillId);
280
    PlayerInfo::setSkillLevel(skillId, level);
281
    if (skillDialog != nullptr)
282
    {
283
        if (!skillDialog->updateSkill(skillId, range,
284
            up, SkillType::Unknown, sp))
285
        {
286
            skillDialog->addSkill(SkillOwner::Homunculus,
287
                skillId, "", level,
288
                range, up, SkillType::Unknown, sp);
289
        }
290
    }
291
}
292
293
void HomunculusRecv::processHomunculusFood(Net::MessageIn &msg)
294
{
295
    const int flag = msg.readUInt8("fail");
296
    const int itemId = msg.readItemId("food id");
297
    if (flag != 0)
298
    {
299
        NotifyManager::notify(NotifyTypes::HOMUNCULUS_FEED_OK);
300
    }
301
    else
302
    {
303
        const std::string name = strprintf("[@@%d|%[email protected]@]", itemId,
304
            ItemDB::get(itemId).getName().c_str());
305
        NotifyManager::notify(NotifyTypes::HOMUNCULUS_FEED_FAIL, name);
306
    }
307
}
308
309
void HomunculusRecv::processHomunculusExp(Net::MessageIn &msg)
310
{
311
    const int exp = msg.readInt32("exp");
312
    msg.readInt32("unused");
313
    if (localPlayer != nullptr)
314
        localPlayer->addHomunXpMessage(exp);
315
}
316
317
2
}  // namespace EAthena