GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/eathena/homunculusrecv.cpp Lines: 1 125 0.8 %
Date: 2017-11-29 Branches: 0 144 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 "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
    msg.readUInt8("unused");
81
    const int cmd = msg.readUInt8("state");
82
    const BeingId id = msg.readBeingId("homunculus id");
83
    Being *const dstBeing = actorManager->findBeing(id);
84
    const int data = msg.readInt32("data");
85
    if (cmd == 0)  // pre init
86
    {
87
        HomunculusInfo *const info = new HomunculusInfo;
88
        info->id = id;
89
        PlayerInfo::setHomunculus(info);
90
        PlayerInfo::setHomunculusBeing(dstBeing);
91
        return;
92
    }
93
    HomunculusInfo *const info = PlayerInfo::getHomunculus();
94
    if (info == nullptr)
95
        return;
96
    switch (cmd)
97
    {
98
        case 1:  // intimacy
99
            info->intimacy = data;
100
            break;
101
        case 2:  // hunger
102
            info->hungry = data;
103
            break;
104
        case 3:  // accesory
105
            info->equip = data;
106
            break;
107
        default:
108
            break;
109
    }
110
}
111
112
void HomunculusRecv::processHomunculusInfo(Net::MessageIn &msg)
113
{
114
    const std::string name = msg.readString(24, "name");
115
    msg.readUInt8("flags");  // 0x01 - renamed, 0x02 - vaporize, 0x04 - alive
116
    const int level = msg.readInt16("level");
117
    PlayerInfo::setStatBase(Attributes::HOMUN_LEVEL, level);
118
    const int hungry = msg.readInt16("hungry");
119
    const int intimacy = msg.readInt16("intimacy");
120
    const int equip = msg.readInt16("equip");
121
    PlayerInfo::setStatBase(Attributes::HOMUN_ATK,
122
        msg.readInt16("atk"));
123
    PlayerInfo::setStatBase(Attributes::HOMUN_MATK,
124
        msg.readInt16("matk"));
125
    PlayerInfo::setStatBase(Attributes::HOMUN_HIT,
126
        msg.readInt16("hit"));
127
    PlayerInfo::setStatBase(Attributes::HOMUN_CRIT,
128
        msg.readInt16("luk/3 or crit/10"));
129
    PlayerInfo::setStatBase(Attributes::HOMUN_DEF,
130
        msg.readInt16("def"));
131
    PlayerInfo::setStatBase(Attributes::HOMUN_MDEF,
132
        msg.readInt16("mdef"));
133
    PlayerInfo::setStatBase(Attributes::HOMUN_FLEE,
134
        msg.readInt16("flee"));
135
    PlayerInfo::setStatBase(Attributes::HOMUN_ATTACK_DELAY,
136
        msg.readInt16("attack speed"));
137
    if (msg.getVersion() >= 20150513)
138
    {
139
        PlayerInfo::setStatBase(Attributes::HOMUN_HP,
140
            msg.readInt32("hp"));
141
        PlayerInfo::setStatBase(Attributes::HOMUN_MAX_HP,
142
            msg.readInt32("max hp"));
143
    }
144
    else
145
    {
146
        PlayerInfo::setStatBase(Attributes::HOMUN_HP,
147
            msg.readInt16("hp"));
148
        PlayerInfo::setStatBase(Attributes::HOMUN_MAX_HP,
149
            msg.readInt16("max hp"));
150
    }
151
    PlayerInfo::setStatBase(Attributes::HOMUN_MP,
152
        msg.readInt16("sp"));
153
    PlayerInfo::setStatBase(Attributes::HOMUN_MAX_MP,
154
        msg.readInt16("max sp"));
155
    PlayerInfo::setStatBase(Attributes::HOMUN_EXP,
156
        msg.readInt32("exp"));
157
    PlayerInfo::setStatBase(Attributes::HOMUN_EXP_NEEDED,
158
        msg.readInt32("next exp"));
159
    PlayerInfo::setStatBase(Attributes::HOMUN_SKILL_POINTS,
160
        msg.readInt16("skill points"));
161
    const int range = msg.readInt16("attack range");
162
    PlayerInfo::setStatBase(Attributes::HOMUN_ATTACK_RANGE,
163
        range);
164
165
    PlayerInfo::updateAttrs();
166
    HomunculusInfo *const info = PlayerInfo::getHomunculus();
167
    if (info == nullptr)
168
        return;
169
    Being *const dstBeing = actorManager->findBeing(info->id);
170
171
    info->name = name;
172
    info->level = level;
173
    info->range = range;
174
    info->hungry = hungry;
175
    info->intimacy = intimacy;
176
    info->equip = equip;
177
    PlayerInfo::setHomunculusBeing(dstBeing);
178
}
179
180
void HomunculusRecv::processHomunculusSkillUp(Net::MessageIn &msg)
181
{
182
    const int skillId = msg.readInt16("skill id");
183
    const int level = msg.readInt16("level");
184
    const int sp = msg.readInt16("sp");
185
    const int range = msg.readInt16("range");
186
    const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
187
188
    if (skillDialog != nullptr && PlayerInfo::getSkillLevel(skillId) != level)
189
        skillDialog->playUpdateEffect(skillId);
190
    PlayerInfo::setSkillLevel(skillId, level);
191
    if (skillDialog != nullptr)
192
    {
193
        if (!skillDialog->updateSkill(skillId, range,
194
            up, SkillType::Unknown, sp))
195
        {
196
            skillDialog->addSkill(SkillOwner::Homunculus,
197
                skillId, "", level,
198
                range, up, SkillType::Unknown, sp);
199
        }
200
    }
201
}
202
203
void HomunculusRecv::processHomunculusFood(Net::MessageIn &msg)
204
{
205
    const int flag = msg.readUInt8("fail");
206
    const int itemId = msg.readInt16("food id");
207
    if (flag != 0)
208
    {
209
        NotifyManager::notify(NotifyTypes::HOMUNCULUS_FEED_OK);
210
    }
211
    else
212
    {
213
        const std::string name = strprintf("[@@%d|%[email protected]@]", itemId,
214
            ItemDB::get(itemId).getName().c_str());
215
        NotifyManager::notify(NotifyTypes::HOMUNCULUS_FEED_FAIL, name);
216
    }
217
}
218
219
void HomunculusRecv::processHomunculusExp(Net::MessageIn &msg)
220
{
221
    const int exp = msg.readInt32("exp");
222
    msg.readInt32("unused");
223
    if (localPlayer != nullptr)
224
        localPlayer->addHomunXpMessage(exp);
225
}
226
227
4
}  // namespace EAthena