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