ManaPlus
npchandler.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/npchandler.h"
24 
25 #include "being/localplayer.h"
26 
27 #include "const/net/inventory.h"
28 
29 #include "gui/windows/npcdialog.h"
30 
32 
33 #include "net/messagein.h"
34 
35 #include "net/ea/npcrecv.h"
36 
37 #include "net/eathena/messageout.h"
38 #include "net/eathena/npcrecv.h"
39 
41 
42 #include "utils/foreach.h"
43 
45 
46 #include "debug.h"
47 
48 extern int packetVersion;
49 extern int packetVersionRe;
50 
51 namespace EAthena
52 {
53 
55  Ea::NpcHandler()
56 {
57  npcHandler = this;
58 }
59 
61 {
62  npcHandler = nullptr;
63 }
64 
65 void NpcHandler::talk(const Being *const being) const
66 {
67  if (being == nullptr)
68  return;
70  outMsg.writeBeingId(being->getId(), "npc id");
71  outMsg.writeInt8(0, "unused");
73 }
74 
75 void NpcHandler::nextDialog(const BeingId npcId) const
76 {
78  outMsg.writeBeingId(npcId, "npc id");
79 }
80 
82 {
84  outMsg.writeBeingId(npcId, "npc id");
85 
86  const NpcDialogs::iterator it = NpcDialog::mNpcDialogs.find(npcId);
87  if (it != NpcDialog::mNpcDialogs.end())
88  {
89  NpcDialog *const dialog = (*it).second;
90  if (dialog != nullptr)
91  dialog->close();
92  if (dialog == Ea::NpcRecv::mDialog)
93  Ea::NpcRecv::mDialog = nullptr;
94  NpcDialog::mNpcDialogs.erase(it);
95  }
96 }
97 
98 void NpcHandler::listInput(const BeingId npcId,
99  const unsigned char value) const
100 {
102  outMsg.writeBeingId(npcId, "npc id");
103  outMsg.writeInt8(value, "value");
104 }
105 
107  const int value) const
108 {
110  outMsg.writeBeingId(npcId, "npc id");
111  outMsg.writeInt32(value, "value");
112 }
113 
115  const std::string &value) const
116 {
118  if (packetVersion >= 20151029)
119  {
120  outMsg.writeInt16(CAST_S16(value.length() + 8), "len");
121  outMsg.writeBeingId(npcId, "npc id");
122  outMsg.writeString(value, CAST_S32(value.length()), "value");
123  }
124  else
125  {
126  outMsg.writeInt16(CAST_S16(value.length() + 9), "len");
127  outMsg.writeBeingId(npcId, "npc id");
128  outMsg.writeString(value, CAST_S32(value.length()), "value");
129  outMsg.writeInt8(0, "null byte");
130  }
131 }
132 
133 void NpcHandler::buy(const Being *const being) const
134 {
135  if (being == nullptr)
136  return;
138  outMsg.writeBeingId(being->getId(), "npc id");
139  outMsg.writeInt8(0, "action");
141 }
142 
143 void NpcHandler::buy(const BeingId beingId) const
144 {
146  outMsg.writeBeingId(beingId, "npc id");
147  outMsg.writeInt8(0, "action");
149 }
150 
151 void NpcHandler::sell(const BeingId beingId) const
152 {
154  outMsg.writeBeingId(beingId, "npc id");
155  outMsg.writeInt8(1, "action");
156 }
157 
159  const int itemId,
160  const ItemColor color A_UNUSED,
161  const int amount) const
162 {
164  outMsg.writeInt16(8, "len");
165  outMsg.writeInt16(CAST_S16(amount), "amount");
166  outMsg.writeInt16(CAST_S16(itemId), "item id");
167 }
168 
169 void NpcHandler::buyItems(STD_VECTOR<ShopItem*> &items) const
170 {
171  int cnt = 0;
172  const int pairSize = 4;
173 
174  FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, items)
175  {
176  ShopItem *const item = *it;
177  const int usedQuantity = item->getUsedQuantity();
178  const ItemTypeT type = item->getType();
179  if (usedQuantity == 0)
180  continue;
181  if (type == ItemType::Weapon ||
182  type == ItemType::Armor ||
183  type == ItemType::PetEgg ||
184  type == ItemType::PetArmor)
185  {
186  cnt += item->getUsedQuantity();
187  }
188  else
189  {
190  cnt ++;
191  }
192  }
193 
194  if (cnt > 100)
195  return;
196 
198  outMsg.writeInt16(CAST_S16(4 + pairSize * cnt), "len");
199  FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, items)
200  {
201  ShopItem *const item = *it;
202  const int usedQuantity = item->getUsedQuantity();
203  if (usedQuantity == 0)
204  continue;
205  item->increaseUsedQuantity(-usedQuantity);
206  item->update();
207  const ItemTypeT type = item->getType();
208  if (type == ItemType::Weapon ||
209  type == ItemType::Armor ||
210  type == ItemType::PetEgg ||
211  type == ItemType::PetArmor)
212  {
213  for (int f = 0; f < usedQuantity; f ++)
214  {
215  outMsg.writeInt16(CAST_S16(1), "amount");
216  outMsg.writeInt16(CAST_S16(item->getId()),
217  "item id");
218  }
219  }
220  else
221  {
222  outMsg.writeInt16(CAST_S16(usedQuantity), "amount");
223  outMsg.writeInt16(CAST_S16(item->getId()), "item id");
224  }
225  }
226 }
227 
229  const int itemId, const int amount) const
230 {
232  outMsg.writeInt16(8, "len");
233  outMsg.writeInt16(CAST_S16(itemId + INVENTORY_OFFSET),
234  "item index");
235  outMsg.writeInt16(CAST_S16(amount), "amount");
236 }
237 
238 void NpcHandler::sellItems(STD_VECTOR<ShopItem*> &items) const
239 {
240  const int pairSize = 4;
241  int cnt = 0;
242 
243  FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, items)
244  {
245  ShopItem *const item = *it;
246  const int usedQuantity = item->getUsedQuantity();
247  if (usedQuantity == 0)
248  continue;
249  cnt ++;
250  }
251 
253  outMsg.writeInt16(CAST_S16(4 + pairSize * cnt), "len");
254  FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, items)
255  {
256  ShopItem *const item = *it;
257  const int usedQuantity = item->getUsedQuantity();
258  if (usedQuantity == 0)
259  continue;
260  item->increaseUsedQuantity(-usedQuantity);
261  item->update();
262  outMsg.writeInt16(CAST_S16(
264  "item index");
265  outMsg.writeInt16(CAST_S16(usedQuantity), "amount");
266  }
267 }
268 
270 {
272 }
273 
274 void NpcHandler::produceMix(const int nameId,
275  const int materialId1,
276  const int materialId2,
277  const int materialId3) const
278 {
280  outMsg.writeInt16(CAST_S16(nameId), "name id");
281  outMsg.writeInt16(CAST_S16(materialId1), "material 1");
282  outMsg.writeInt16(CAST_S16(materialId2), "material 2");
283  outMsg.writeInt16(CAST_S16(materialId3), "material 3");
284 }
285 
287  const int nameId) const
288 {
290  outMsg.writeInt16(CAST_S16(type), "type");
291  outMsg.writeInt16(CAST_S16(nameId), "name id");
292 }
293 
294 void NpcHandler::repair(const int index) const
295 {
297  outMsg.writeInt16(CAST_S16(index), "index");
298 }
299 
300 void NpcHandler::refine(const int index) const
301 {
303  outMsg.writeInt32(index, "index");
304 }
305 
306 void NpcHandler::identify(const int index) const
307 {
309  outMsg.writeInt16(CAST_S16(index), "index");
310 }
311 
312 void NpcHandler::selectArrow(const int nameId) const
313 {
315  outMsg.writeInt16(CAST_S16(nameId), "name id");
316 }
317 
318 void NpcHandler::selectAutoSpell(const int skillId) const
319 {
321  outMsg.writeInt32(CAST_S16(skillId), "skill id");
322 }
323 
325  const NpcActionT action)
326 {
327  const BeingId npcId = msg.readBeingId("npc id");
328 
329  const NpcDialogs::const_iterator diag = NpcDialog::mNpcDialogs.find(npcId);
330 
331  if (diag == NpcDialog::mNpcDialogs.end())
332  {
333  Ea::NpcRecv::mDialog = nullptr;
334  // Empty dialogs don't help
335  if (action == NpcAction::Close)
336  {
337  closeDialog(npcId);
338  return npcId;
339  }
340  else if (action == NpcAction::Next)
341  {
342  nextDialog(npcId);
343  return npcId;
344  }
345  else
346  {
349  if (localPlayer != nullptr)
350  localPlayer->stopWalking(false);
352  }
353  }
354  else
355  {
356  NpcDialog *const dialog = diag->second;
357  if (Ea::NpcRecv::mDialog != nullptr && Ea::NpcRecv::mDialog != dialog)
359  Ea::NpcRecv::mDialog = dialog;
360  if (Ea::NpcRecv::mDialog != nullptr)
362  }
363  return npcId;
364 }
365 
366 void NpcHandler::requestAirship(const std::string &mapName,
367  const int itemId) const
368 {
369  if (packetVersionRe < 20180321)
370  return;
372  outMsg.writeString(mapName, 16, "map name");
373  outMsg.writeInt16(CAST_S16(itemId), "item");
374 }
375 
376 } // namespace EAthena
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
int CMSG_NPC_PRODUCE_MIX
void produceMix(const int nameId, const int materialId1, const int materialId2, const int materialId3) const
Definition: npchandler.cpp:274
NpcAction ::T NpcActionT
Definition: npcaction.h:32
void cooking(const CookingTypeT type, const int nameId) const
Definition: npchandler.cpp:286
BeingId readBeingId(const char *const str)
Definition: messagein.cpp:211
void selectArrow(const int nameId) const
Definition: npchandler.cpp:312
int CMSG_NPC_INT_RESPONSE
int CMSG_NPC_REFINE
void selectAutoSpell(const int skillId) const
Definition: npchandler.cpp:318
BeingId getId() const
Definition: actorsprite.h:63
NpcDialog * mDialog
Definition: npcrecv.cpp:41
void stopWalking(const bool sendToServer)
int getUsedQuantity() const
Definition: shopitem.h:150
const BeingTypeId BeingTypeId_zero
Definition: beingtypeid.h:29
int BeingId
Definition: beingid.h:29
static const int INVENTORY_OFFSET
Definition: inventory.h:26
void listInput(const BeingId npcId, const unsigned char value) const
Definition: npchandler.cpp:98
BeingId getNpc(Net::MessageIn &msg, const NpcActionT action)
Definition: npchandler.cpp:324
void sellItem(const BeingId beingId, const int itemId, const int amount) const
Definition: npchandler.cpp:228
uint16_t ItemColor
Definition: itemcolor.h:29
bool msg(InputEvent &event)
Definition: chat.cpp:38
void requestAirship(const std::string &mapName, const int itemId) const
Definition: npchandler.cpp:366
int CMSG_NPC_REPAIR
void talk(const Being *const being) const
Definition: npchandler.cpp:65
int getCurrentInvIndex() const
Definition: shopitem.h:107
void buyItem(const BeingId beingId, const int itemId, const ItemColor color, const int amount) const
Definition: npchandler.cpp:158
int CMSG_NPC_TALK
#define CREATEWIDGETV(var, type,...)
Definition: createwidget.h:24
void repair(const int index) const
Definition: npchandler.cpp:294
void update()
Definition: shopitem.cpp:118
int CMSG_NPC_IDENTIFY
int CMSG_NPC_SELECT_AUTO_SPELL
void restoreCamera()
Definition: npcdialog.cpp:1114
virtual void close()
Definition: window.cpp:897
void stringInput(const BeingId npcId, const std::string &value) const
Definition: npchandler.cpp:114
int packetVersionRe
Definition: client.cpp:126
void buy(const Being *const being) const
Definition: npchandler.cpp:133
#define CAST_S32
Definition: cast.h:29
static NpcDialogs mNpcDialogs
Definition: npcdialog.h:241
int CMSG_PRIVATE_AIRSHIP_REQUEST
void identify(const int index) const
Definition: npchandler.cpp:306
LocalPlayer * localPlayer
void refine(const int index) const
Definition: npchandler.cpp:300
int CMSG_NPC_SELECT_ARROW
void buyItems(std::vector< ShopItem *> &items) const
Definition: npchandler.cpp:169
void closeDialog(const BeingId npcId)
Definition: npchandler.cpp:81
int CMSG_NPC_CLOSE
BeingTypeId mNpcTypeId
Definition: npcrecv.cpp:42
void increaseUsedQuantity(const int amount)
Definition: shopitem.cpp:158
int CMSG_NPC_COMPLETE_PROGRESS_BAR
#define createOutPacket(name)
Definition: messageout.h:36
int CMSG_NPC_STR_RESPONSE
void saveCamera()
Definition: npcdialog.cpp:1104
ItemType ::T ItemTypeT
Definition: itemtype.h:42
int CMSG_NPC_COOKING
int getId() const
Definition: item.h:80
#define A_UNUSED
Definition: localconsts.h:151
int packetVersion
Definition: client.cpp:124
void integerInput(const BeingId npcId, const int value) const
Definition: npchandler.cpp:106
void sell(const BeingId beingId) const
Definition: npchandler.cpp:151
CookingType ::T CookingTypeT
Definition: cookingtype.h:35
int CMSG_NPC_NEXT_REQUEST
ItemTypeT getType() const
Definition: item.h:224
Net::NpcHandler * npcHandler
Definition: net.cpp:89
#define CAST_S16
Definition: cast.h:27
int CMSG_NPC_LIST_CHOICE
int CMSG_NPC_SELL_REQUEST
Definition: being.h:93
int CMSG_NPC_BUY_REQUEST
void nextDialog(const BeingId npcId) const
Definition: npchandler.cpp:75
BeingTypeId getSubType() const
Definition: being.h:399
int CMSG_NPC_BUY_SELL_REQUEST
void completeProgressBar() const
Definition: npchandler.cpp:269
void sellItems(std::vector< ShopItem *> &items) const
Definition: npchandler.cpp:238