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