ManaPlus
skillrecv.cpp
Go to the documentation of this file.
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-2018 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/skillrecv.h"
24 
25 #include "notifymanager.h"
26 
27 #include "being/localplayer.h"
28 #include "being/playerinfo.h"
29 
30 #include "const/net/skill.h"
31 
33 
35 
38 
40 
41 #include "net/messagein.h"
42 
43 #include "net/eathena/menu.h"
44 
45 #include "resources/iteminfo.h"
46 
47 #include "resources/db/itemdb.h"
48 
50 
51 #include "utils/gettext.h"
52 #include "utils/stringutils.h"
53 
54 #include "debug.h"
55 
56 static const unsigned int RFAIL = 10;
57 static const unsigned int RFAIL_SUMMON = 19;
58 static const unsigned int RFAIL_NEED_ITEM = 71;
59 static const unsigned int RFAIL_NEED_EQUIPMENT = 72;
60 static const unsigned int RFAIL_SPIRITS = 74;
61 
62 extern int serverVersion;
63 extern int itemIdLen;
64 
65 namespace EAthena
66 {
67 
69 {
70  msg.readInt16("len");
71  const int sz = (serverVersion > 0) ? 41 : 37;
72  const int skillCount = (msg.getLength() - 4) / sz;
73  int updateSkill = 0;
74 
75  if (skillDialog != nullptr)
77  for (int k = 0; k < skillCount; k++)
78  {
79  const int skillId = msg.readInt16("skill id");
80  const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
81  msg.readInt32("inf"));
82  if (serverVersion > 0)
83  msg.readInt32("inf2");
84  const int level = msg.readInt16("skill level");
85  const int sp = msg.readInt16("sp");
86  const int range = msg.readInt16("range");
87  const std::string name = msg.readString(24, "skill name");
88  const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
89  const int oldLevel = PlayerInfo::getSkillLevel(skillId);
90  if ((oldLevel != 0) && oldLevel != level)
91  updateSkill = skillId;
92  PlayerInfo::setSkillLevel(skillId, level);
93  if (skillDialog != nullptr)
94  {
95  if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
96  {
98  skillId, name, level, range, up, inf, sp);
99  }
100  }
101  }
102  if (skillDialog != nullptr)
103  {
104  skillDialog->update();
106  if (updateSkill != 0)
107  skillDialog->playUpdateEffect(updateSkill);
108  }
109 }
110 
112 {
113  int updateSkill = 0;
114  const int skillId = msg.readInt16("skill id");
115  const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
116  msg.readInt32("inf"));
117  const int level = msg.readInt16("skill level");
118  const int sp = msg.readInt16("sp");
119  const int range = msg.readInt16("range");
120  const std::string name = msg.readString(24, "skill name");
121  const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
122  const int oldLevel = PlayerInfo::getSkillLevel(skillId);
123  if ((oldLevel != 0) && oldLevel != level)
124  updateSkill = skillId;
125  PlayerInfo::setSkillLevel(skillId, level);
126  if (skillDialog != nullptr)
127  {
128  if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
129  {
131  skillId, name, level, range, up, inf, sp);
132  }
133  skillDialog->update();
134  if (updateSkill != 0)
135  skillDialog->playUpdateEffect(updateSkill);
136  }
137 }
138 
140 {
141  int updateSkill = 0;
142  msg.readInt16("len"); // for now unused
143  const int skillId = msg.readInt16("skill id");
144  const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
145  msg.readInt32("inf"));
146  msg.readInt32("inf2");
147  const int level = msg.readInt16("skill level");
148  const int sp = msg.readInt16("sp");
149  const int range = msg.readInt16("range");
150  const std::string name = msg.readString(24, "skill name");
151  const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
152  const int oldLevel = PlayerInfo::getSkillLevel(skillId);
153  if ((oldLevel != 0) && oldLevel != level)
154  updateSkill = skillId;
155  PlayerInfo::setSkillLevel(skillId, level);
156  if (skillDialog != nullptr)
157  {
158  if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
159  {
161  skillId, name, level, range, up, inf, sp);
162  }
163  skillDialog->update();
164  if (updateSkill != 0)
165  skillDialog->playUpdateEffect(updateSkill);
166  }
167 }
168 
170 {
171  int updateSkill = 0;
172  const int skillId = msg.readInt16("skill id");
173  const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
174  msg.readInt32("inf"));
175  const int level = msg.readInt16("skill level");
176  const int sp = msg.readInt16("sp");
177  const int range = msg.readInt16("range");
178  const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
179  const int oldLevel = PlayerInfo::getSkillLevel(skillId);
180  if ((oldLevel != 0) && oldLevel != level)
181  updateSkill = skillId;
182  PlayerInfo::setSkillLevel(skillId, level);
183  if (skillDialog != nullptr)
184  {
185  if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
186  {
188  skillId, "", level, range, up, inf, sp);
189  }
190  skillDialog->update();
191  if (updateSkill != 0)
192  skillDialog->playUpdateEffect(updateSkill);
193  }
194 }
195 
197 {
198  int updateSkill = 0;
199  msg.readInt16("len"); // for now unused
200  const int skillId = msg.readInt16("skill id");
201  const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
202  msg.readInt32("inf"));
203  msg.readInt32("inf2");
204  const int level = msg.readInt16("skill level");
205  const int sp = msg.readInt16("sp");
206  const int range = msg.readInt16("range");
207  const Modifiable up = fromBool(msg.readUInt8("up flag"), Modifiable);
208  const int oldLevel = PlayerInfo::getSkillLevel(skillId);
209  if ((oldLevel != 0) && oldLevel != level)
210  updateSkill = skillId;
211  PlayerInfo::setSkillLevel(skillId, level);
212  if (skillDialog != nullptr)
213  {
214  if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
215  {
217  skillId, "", level, range, up, inf, sp);
218  }
219  skillDialog->update();
220  if (updateSkill != 0)
221  skillDialog->playUpdateEffect(updateSkill);
222  }
223 }
224 
226 {
227  int updateSkill = 0;
228  const int skillId = msg.readInt16("skill id");
229  const int oldLevel = PlayerInfo::getSkillLevel(skillId);
230  if (oldLevel != 0)
231  updateSkill = skillId;
232  PlayerInfo::setSkillLevel(skillId, 0);
233  if (skillDialog != nullptr)
234  {
235  skillDialog->removeSkill(skillId);
236  skillDialog->update();
237  if (updateSkill != 0)
238  skillDialog->playRemoveEffect(updateSkill);
239  }
240 }
241 
243 {
244  const int skillId = msg.readInt16("skill id");
245  const int duration = msg.readInt32("duration");
246  if (skillDialog != nullptr)
247  skillDialog->setSkillDuration(SkillOwner::Player, skillId, duration);
248 }
249 
251 {
252  int packetLen;
253  if (msg.getVersion() >= 20120604)
254  packetLen = 10;
255  else
256  packetLen = 6;
257  const int count = (msg.readInt16("len") - 4) / packetLen;
258  for (int f = 0; f < count; f ++)
259  {
260  const int skillId = msg.readInt16("skill id");
261  if (msg.getVersion() >= 20120604)
262  msg.readInt32("total");
263  const int duration = msg.readInt32("duration");
264  if (skillDialog != nullptr)
265  {
267  skillId, duration);
268  }
269  }
270 }
271 
273 {
274  // Action failed (ex. sit because you have not reached the
275  // right level)
276  const int skillId = msg.readInt16("skill id");
277  const int bskill = msg.readItemId("btype");
278  const int itemId = msg.readItemId("item id");
279  const signed char success = msg.readUInt8("success");
280  const signed char reason = msg.readUInt8("reason");
281  if (success != CAST_S32(SKILL_FAILED)
282  && bskill == CAST_S32(BSKILL_EMOTE))
283  {
284  logger->log("Action: %d/%d", bskill, success);
285  }
286 
287  if (localPlayer != nullptr)
288  localPlayer->stopCast(true);
289  std::string txt;
290  if (success == CAST_S32(SKILL_FAILED) && bskill != 0)
291  {
292  if ((localPlayer != nullptr) && bskill == CAST_S32(BSKILL_EMOTE)
293  && reason == CAST_S32(RFAIL_SKILLDEP))
294  {
296  }
297 
298  const SkillInfo *const info = skillDialog->getSkill(bskill);
299  if (info != nullptr)
300  {
301  txt = info->errorText;
302  }
303  else
304  {
305  // TRANSLATORS: skill error message
306  txt = strprintf(_("Unknown skill error: %d"), bskill);
307  }
308  }
309  else
310  {
311  const SkillInfo *const info = skillDialog->getSkill(skillId);
312  if (info != nullptr)
313  {
314  txt = info->errorText + ".";
315  }
316  else
317  {
318  // TRANSLATORS: skill error message
319  txt = strprintf(_("Unknown skill error: %d."), skillId);
320  }
321  }
322 
323  txt.append(" ");
324  switch (reason)
325  {
326  case RFAIL_SKILLDEP:
327  // TRANSLATORS: error message
328  txt.append(_("You have not yet reached a high enough lvl!"));
329  break;
330  case RFAIL_INSUFHP:
331  // TRANSLATORS: error message
332  txt.append(_("Insufficient HP!"));
333  break;
334  case RFAIL_INSUFSP:
335  // TRANSLATORS: error message
336  txt.append(_("Insufficient SP!"));
337  break;
338  case RFAIL_NOMEMO:
339  // TRANSLATORS: error message
340  txt.append(_("You have no memos!"));
341  break;
342  case RFAIL_SKILLDELAY:
343  // TRANSLATORS: error message
344  txt.append(_("You cannot do that right now!"));
345  break;
346  case RFAIL_ZENY:
347  // TRANSLATORS: error message
348  txt.append(_("Seems you need more money... ;-)"));
349  break;
350  case RFAIL_WEAPON:
351  // TRANSLATORS: error message
352  txt.append(_("You cannot use this skill with that "
353  "kind of weapon!"));
354  break;
355  case RFAIL_REDGEM:
356  // TRANSLATORS: error message
357  txt.append(_("You need another red gem!"));
358  break;
359  case RFAIL_BLUEGEM:
360  // TRANSLATORS: error message
361  txt.append(_("You need another blue gem!"));
362  break;
363  case RFAIL_OVERWEIGHT:
364  // TRANSLATORS: error message
365  txt.append(_("You're carrying to much to do this!"));
366  break;
367  case RFAIL_SUMMON:
368  // TRANSLATORS: error message
369  txt.append(_("Fail summon."));
370  break;
371  case RFAIL_SPIRITS:
372  // TRANSLATORS: error message
373  txt.append(_("Need spirits."));
374  break;
376  {
377  const int amount = bskill;
378  const ItemInfo &info = ItemDB::get(itemId);
379  if (amount == 1)
380  {
381  // TRANSLATORS: skill error message
382  txt.append(strprintf(_("Need equipment %s."),
383  info.getLink().c_str()));
384  }
385  else
386  {
387  // TRANSLATORS: skill error message
388  txt.append(strprintf(_("Need equipment %s and amount %d"),
389  info.getLink().c_str(),
390  amount));
391  }
392  break;
393  }
394  case RFAIL_NEED_ITEM:
395  {
396  const int amount = bskill;
397  const ItemInfo &info = ItemDB::get(itemId);
398  if (amount == 1)
399  {
400  // TRANSLATORS: skill error message
401  txt.append(strprintf(_("Need item %s."),
402  info.getLink().c_str()));
403  }
404  else
405  {
406  // TRANSLATORS: skill error message
407  txt.append(strprintf(_("Need item %s and amount %d"),
408  info.getLink().c_str(),
409  amount));
410  }
411  break;
412  }
413  case RFAIL:
414  {
415  // TRANSLATORS: error message
416  txt.append(_("Skill failed!"));
417  break;
418  }
419 
420  default:
421  UNIMPLEMENTEDPACKETFIELD(reason);
422  break;
423  }
424 
426 }
427 
429 {
430  const int skillId = msg.readInt16("skill id");
431 
433  // TRANSLATORS: warp select window name
434  _("Select warp target"),
435  // TRANSLATORS: warp select button
436  _("Warp"),
439  skillWarpListener.setSkill(skillId);
441  for (int f = 0; f < 4; f ++)
442  dialog->addText(msg.readString(16, "map name"));
443 }
444 
446 {
447  const int type = msg.readUInt8("type");
448  switch (type)
449  {
450  case 0:
452  break;
453  case 1:
455  break;
456  case 2:
458  break;
459  default:
461  break;
462  }
463 }
464 
466 {
468 
469  const int count = (msg.readInt16("len") - 4) / 4 * itemIdLen;
470  for (int f = 0; f < count; f ++)
471  {
472  msg.readItemId("item id");
473  for (int d = 0; d < 3; d ++)
474  msg.readItemId("material id");
475  }
476 }
477 
479 {
481 
482  msg.readInt16("flag");
483  msg.readItemId("item id");
484 }
485 
487 {
489 
490  msg.readBeingId("being id");
491 }
492 
494 {
496 
497  const int count = (msg.readInt16("len") - 4) / itemIdLen;
498  for (int f = 0; f < count; f ++)
499  msg.readItemId("item id");
500 }
501 
503 {
505 
506  for (int f = 0; f < 7; f ++)
507  msg.readInt32("skill id");
508 
510 }
511 
513 {
515 
516  msg.readBeingId("being id");
517  for (int f = 0; f < 5; f ++)
518  msg.readInt32("devotee id");
519  msg.readInt16("range");
520 }
521 
523 {
525 
526  msg.readInt32("skill level");
527  msg.readInt32("unused");
528 }
529 
531 {
532  msg.readBeingId("being id");
533  msg.readInt16("skill id");
534  msg.readInt16("skill level");
535  msg.readInt16("x");
536  msg.readInt16("y");
537  msg.readInt32("cast time");
538 }
539 
540 } // namespace EAthena
void processSkillItemListWindow(Net::MessageIn &msg)
Definition: skillrecv.cpp:522
unsigned char readUInt8(const char *const str)
Definition: messagein.cpp:103
#define _(s)
Definition: gettext.h:34
const ItemInfo & get(const int id)
Definition: itemdb.cpp:792
BeingId readBeingId(const char *const str)
Definition: messagein.cpp:223
int itemIdLen
Definition: client.cpp:129
void processSkillUnitUpdate(Net::MessageIn &msg)
Definition: skillrecv.cpp:486
void stopAdvert()
static const unsigned int RFAIL_NEED_ITEM
Definition: skillrecv.cpp:58
static const unsigned int RFAIL_SKILLDEP
Definition: skill.h:43
static const unsigned int RFAIL_REDGEM
Definition: skill.h:50
const std::string getLink() const
Definition: iteminfo.cpp:480
void addActionListener(ActionListener *const actionListener)
Definition: widget.cpp:251
const bool AllowQuit_false
Definition: allowquit.h:29
bool updateSkill(const int id, const int range, const Modifiable modifiable, const SkillType::SkillType type, const int sp)
void removeSkill(const int id)
unsigned int getLength() const
Definition: messagein.h:58
void processPlayerSkills(Net::MessageIn &msg)
Definition: skillrecv.cpp:68
void processSkillAutoSpells(Net::MessageIn &msg)
Definition: skillrecv.cpp:502
void processSkillMemoMessage(Net::MessageIn &msg)
Definition: skillrecv.cpp:445
bool msg(InputEvent &event)
Definition: chat.cpp:38
void setSkillDuration(const SkillOwner::Type owner, const int id, const int duration)
void processSkillProduceEffect(Net::MessageIn &msg)
Definition: skillrecv.cpp:478
static const unsigned int RFAIL_BLUEGEM
Definition: skill.h:51
void notify(const unsigned int message)
void setSkill(const int skillId)
void hideSkills(const SkillOwner::Type owner)
static const unsigned int RFAIL_SPIRITS
Definition: skillrecv.cpp:60
bool Modifiable
Definition: modifiable.h:29
std::string errorText
Definition: skillinfo.h:54
Logger * logger
Definition: logger.cpp:88
void updateModelsHidden()
void processSkillFailed(Net::MessageIn &msg)
Definition: skillrecv.cpp:272
int16_t readInt16(const char *const str)
Definition: messagein.cpp:130
SkillInfo * getSkill(const int id) const
static const unsigned int RFAIL_SKILLDELAY
Definition: skill.h:47
#define CAST_S32
Definition: cast.h:29
std::string strprintf(const char *const format,...)
Definition: stringutils.cpp:99
void processSkillWarpPoint(Net::MessageIn &msg)
Definition: skillrecv.cpp:428
std::string update(const int id)
void addText(const std::string &text)
void stopCast(const bool b)
Definition: being.cpp:5522
#define fromBool(val, name)
Definition: booldefines.h:48
void processSkillUpdate(Net::MessageIn &msg)
Definition: skillrecv.cpp:169
bool info(InputEvent &event)
Definition: commands.cpp:56
static const unsigned int RFAIL_INSUFSP
Definition: skill.h:44
void processSkillDelete(Net::MessageIn &msg)
Definition: skillrecv.cpp:225
void processSkillScale(Net::MessageIn &msg)
Definition: skillrecv.cpp:530
int getVersion() const
Definition: messagein.h:133
static const unsigned int BSKILL_EMOTE
Definition: skill.h:36
LocalPlayer * localPlayer
static const unsigned int RFAIL_INSUFHP
Definition: skill.h:45
void processSkillCoolDown(Net::MessageIn &msg)
Definition: skillrecv.cpp:242
MenuTypeT menu
Definition: menu.cpp:27
static const unsigned int RFAIL_ZENY
Definition: skill.h:48
void playUpdateEffect(const int id) const
void setSkillLevel(const int id, const int value)
Definition: playerinfo.cpp:126
void processSkillUpdate2(Net::MessageIn &msg)
Definition: skillrecv.cpp:196
int readItemId(const char *const str)
Definition: messagein.cpp:216
static const unsigned int RFAIL_SUMMON
Definition: skillrecv.cpp:57
static const unsigned int RFAIL_NEED_EQUIPMENT
Definition: skillrecv.cpp:59
SkillDialog * skillDialog
Definition: skilldialog.cpp:65
void processSkillProduceMixList(Net::MessageIn &msg)
Definition: skillrecv.cpp:465
int getSkillLevel(const int id)
Definition: playerinfo.cpp:118
void processSkillDevotionEffect(Net::MessageIn &msg)
Definition: skillrecv.cpp:512
void processSkillAdd(Net::MessageIn &msg)
Definition: skillrecv.cpp:111
static const unsigned int RFAIL_NOMEMO
Definition: skill.h:46
void setDialog(TextSelectDialog *const dialog)
void addSkill(const SkillOwner::Type owner, const int id, const std::string &name, const int level, const int range, const Modifiable modifiable, const SkillType::SkillType type, const int sp)
SkillWarpListener skillWarpListener
void processSkillAdd2(Net::MessageIn &msg)
Definition: skillrecv.cpp:139
std::string readString(int length, const char *const dstr)
Definition: messagein.cpp:367
#define UNIMPLEMENTEDPACKET
Definition: logger.h:55
static const unsigned int RFAIL_OVERWEIGHT
Definition: skill.h:52
#define CREATEWIDGETR(type,...)
Definition: createwidget.h:35
void log(const char *const log_text,...)
Definition: logger.cpp:264
void processSkillCoolDownList(Net::MessageIn &msg)
Definition: skillrecv.cpp:250
int32_t readInt32(const char *const str)
Definition: messagein.cpp:174
void processSkillArrowCreateList(Net::MessageIn &msg)
Definition: skillrecv.cpp:493
void playRemoveEffect(const int id) const
static const unsigned int RFAIL
Definition: skillrecv.cpp:56
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:58
static const unsigned int RFAIL_WEAPON
Definition: skill.h:49
int serverVersion
Definition: client.cpp:123
static const unsigned int SKILL_FAILED
Definition: skill.h:55