GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/homunculusrecv.cpp Lines: 1 123 0.8 %
Date: 2018-06-18 21:15:20 Branches: 0 148 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2011-2018  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::processHomunculusInfo(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.readInt16("equip");
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
    if (msg.getVersion() >= 20150513)
152
    {
153
        PlayerInfo::setStatBase(Attributes::HOMUN_HP,
154
            msg.readInt32("hp"),
155
            Notify_true);
156
        PlayerInfo::setStatBase(Attributes::HOMUN_MAX_HP,
157
            msg.readInt32("max hp"),
158
            Notify_true);
159
    }
160
    else
161
    {
162
        PlayerInfo::setStatBase(Attributes::HOMUN_HP,
163
            msg.readInt16("hp"),
164
            Notify_true);
165
        PlayerInfo::setStatBase(Attributes::HOMUN_MAX_HP,
166
            msg.readInt16("max hp"),
167
            Notify_true);
168
    }
169
    PlayerInfo::setStatBase(Attributes::HOMUN_MP,
170
        msg.readInt16("sp"),
171
        Notify_true);
172
    PlayerInfo::setStatBase(Attributes::HOMUN_MAX_MP,
173
        msg.readInt16("max sp"),
174
        Notify_true);
175
    PlayerInfo::setStatBase(Attributes::HOMUN_EXP,
176
        msg.readInt32("exp"),
177
        Notify_true);
178
    PlayerInfo::setStatBase(Attributes::HOMUN_EXP_NEEDED,
179
        msg.readInt32("next exp"),
180
        Notify_true);
181
    PlayerInfo::setStatBase(Attributes::HOMUN_SKILL_POINTS,
182
        msg.readInt16("skill points"),
183
        Notify_true);
184
    const int range = msg.readInt16("attack range");
185
    PlayerInfo::setStatBase(Attributes::HOMUN_ATTACK_RANGE,
186
        range,
187
        Notify_true);
188
189
    PlayerInfo::updateAttrs();
190
    HomunculusInfo *const info = PlayerInfo::getHomunculus();
191
    if (info == nullptr)
192
        return;
193
    Being *const dstBeing = actorManager->findBeing(info->id);
194
195
    info->name = name;
196
    info->level = level;
197
    info->range = range;
198
    info->hungry = hungry;
199
    info->intimacy = intimacy;
200
    info->equip = equip;
201
    PlayerInfo::setHomunculusBeing(dstBeing);
202
}
203
204
void HomunculusRecv::processHomunculusSkillUp(Net::MessageIn &msg)
205
{
206
    const int skillId = msg.readInt16("skill id");
207
    const int level = msg.readInt16("level");
208
    const int sp = msg.readInt16("sp");
209
    const int range = msg.readInt16("range");
210
    const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
211
212
    if (skillDialog != nullptr && PlayerInfo::getSkillLevel(skillId) != level)
213
        skillDialog->playUpdateEffect(skillId);
214
    PlayerInfo::setSkillLevel(skillId, level);
215
    if (skillDialog != nullptr)
216
    {
217
        if (!skillDialog->updateSkill(skillId, range,
218
            up, SkillType::Unknown, sp))
219
        {
220
            skillDialog->addSkill(SkillOwner::Homunculus,
221
                skillId, "", level,
222
                range, up, SkillType::Unknown, sp);
223
        }
224
    }
225
}
226
227
void HomunculusRecv::processHomunculusFood(Net::MessageIn &msg)
228
{
229
    const int flag = msg.readUInt8("fail");
230
    const int itemId = msg.readInt16("food id");
231
    if (flag != 0)
232
    {
233
        NotifyManager::notify(NotifyTypes::HOMUNCULUS_FEED_OK);
234
    }
235
    else
236
    {
237
        const std::string name = strprintf("[@@%d|%[email protected]@]", itemId,
238
            ItemDB::get(itemId).getName().c_str());
239
        NotifyManager::notify(NotifyTypes::HOMUNCULUS_FEED_FAIL, name);
240
    }
241
}
242
243
void HomunculusRecv::processHomunculusExp(Net::MessageIn &msg)
244
{
245
    const int exp = msg.readInt32("exp");
246
    msg.readInt32("unused");
247
    if (localPlayer != nullptr)
248
        localPlayer->addHomunXpMessage(exp);
249
}
250
251
4
}  // namespace EAthena