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 
50 namespace EAthena
51 {
52 
54  Ea::NpcHandler()
55 {
56  npcHandler = this;
57 }
58 
60 {
61  npcHandler = nullptr;
62 }
63 
64 void NpcHandler::talk(const Being *const being) const
65 {
66  if (being == nullptr)
67  return;
69  outMsg.writeBeingId(being->getId(), "npc id");
70  outMsg.writeInt8(0, "unused");
72 }
73 
74 void NpcHandler::nextDialog(const BeingId npcId) const
75 {
77  outMsg.writeBeingId(npcId, "npc id");
78 }
79 
81 {
83  outMsg.writeBeingId(npcId, "npc id");
84 
85  const NpcDialogs::iterator it = NpcDialog::mNpcDialogs.find(npcId);
86  if (it != NpcDialog::mNpcDialogs.end())
87  {
88  NpcDialog *const dialog = (*it).second;
89  if (dialog != nullptr)
90  dialog->close();
91  if (dialog == Ea::NpcRecv::mDialog)
92  Ea::NpcRecv::mDialog = nullptr;
93  NpcDialog::mNpcDialogs.erase(it);
94  }
95 }
96 
97 void NpcHandler::listInput(const BeingId npcId,
98  const unsigned char value) const
99 {
101  outMsg.writeBeingId(npcId, "npc id");
102  outMsg.writeInt8(value, "value");
103 }
104 
106  const int value) const
107 {
109  outMsg.writeBeingId(npcId, "npc id");
110  outMsg.writeInt32(value, "value");
111 }
112 
114  const std::string &value) const
115 {
117  if (packetVersion >= 20151029)
118  {
119  outMsg.writeInt16(CAST_S16(value.length() + 8), "len");
120  outMsg.writeBeingId(npcId, "npc id");
121  outMsg.writeString(value, CAST_S32(value.length()), "value");
122  }
123  else
124  {
125  outMsg.writeInt16(CAST_S16(value.length() + 9), "len");
126  outMsg.writeBeingId(npcId, "npc id");
127  outMsg.writeString(value, CAST_S32(value.length()), "value");
128  outMsg.writeInt8(0, "null byte");
129  }
130 }
131 
132 void NpcHandler::buy(const Being *const being) const
133 {
134  if (being == nullptr)
135  return;
137  outMsg.writeBeingId(being->getId(), "npc id");
138  outMsg.writeInt8(0, "action");
140 }
141 
142 void NpcHandler::buy(const BeingId beingId) const
143 {
145  outMsg.writeBeingId(beingId, "npc id");
146  outMsg.writeInt8(0, "action");
148 }
149 
150 void NpcHandler::sell(const BeingId beingId) const
151 {
153  outMsg.writeBeingId(beingId, "npc id");
154  outMsg.writeInt8(1, "action");
155 }
156 
158  const int itemId,
159  const ItemColor color A_UNUSED,
160  const int amount) const
161 {
163  outMsg.writeInt16(8, "len");
164  outMsg.writeInt16(CAST_S16(amount), "amount");
165  outMsg.writeInt16(CAST_S16(itemId), "item id");
166 }
167 
168 void NpcHandler::buyItems(STD_VECTOR<ShopItem*> &items) const
169 {
170  int cnt = 0;
171  const int pairSize = 4;
172 
173  FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, items)
174  {
175  ShopItem *const item = *it;
176  const int usedQuantity = item->getUsedQuantity();
177  const ItemTypeT type = item->getType();
178  if (usedQuantity == 0)
179  continue;
180  if (type == ItemType::Weapon ||
181  type == ItemType::Armor ||
182  type == ItemType::PetEgg ||
183  type == ItemType::PetArmor)
184  {
185  cnt += item->getUsedQuantity();
186  }
187  else
188  {
189  cnt ++;
190  }
191  }
192 
193  if (cnt > 100)
194  return;
195 
197  outMsg.writeInt16(CAST_S16(4 + pairSize * cnt), "len");
198  FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, items)
199  {
200  ShopItem *const item = *it;
201  const int usedQuantity = item->getUsedQuantity();
202  if (usedQuantity == 0)
203  continue;
204  item->increaseUsedQuantity(-usedQuantity);
205  item->update();
206  const ItemTypeT type = item->getType();
207  if (type == ItemType::Weapon ||
208  type == ItemType::Armor ||
209  type == ItemType::PetEgg ||
210  type == ItemType::PetArmor)
211  {
212  for (int f = 0; f < usedQuantity; f ++)
213  {
214  outMsg.writeInt16(CAST_S16(1), "amount");
215  outMsg.writeInt16(CAST_S16(item->getId()),
216  "item id");
217  }
218  }
219  else
220  {
221  outMsg.writeInt16(CAST_S16(usedQuantity), "amount");
222  outMsg.writeInt16(CAST_S16(item->getId()), "item id");
223  }
224  }
225 }
226 
228  const int itemId, const int amount) const
229 {
231  outMsg.writeInt16(8, "len");
232  outMsg.writeInt16(CAST_S16(itemId + INVENTORY_OFFSET),
233  "item index");
234  outMsg.writeInt16(CAST_S16(amount), "amount");
235 }
236 
237 void NpcHandler::sellItems(STD_VECTOR<ShopItem*> &items) const
238 {
239  const int pairSize = 4;
240  int cnt = 0;
241 
242  FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, items)
243  {
244  ShopItem *const item = *it;
245  const int usedQuantity = item->getUsedQuantity();
246  if (usedQuantity == 0)
247  continue;
248  cnt ++;
249  }
250 
252  outMsg.writeInt16(CAST_S16(4 + pairSize * cnt), "len");
253  FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, items)
254  {
255  ShopItem *const item = *it;
256  const int usedQuantity = item->getUsedQuantity();
257  if (usedQuantity == 0)
258  continue;
259  item->increaseUsedQuantity(-usedQuantity);
260  item->update();
261  outMsg.writeInt16(CAST_S16(
263  "item index");
264  outMsg.writeInt16(CAST_S16(usedQuantity), "amount");
265  }
266 }
267 
269 {
271 }
272 
273 void NpcHandler::produceMix(const int nameId,
274  const int materialId1,
275  const int materialId2,
276  const int materialId3) const
277 {
279  outMsg.writeInt16(CAST_S16(nameId), "name id");
280  outMsg.writeInt16(CAST_S16(materialId1), "material 1");
281  outMsg.writeInt16(CAST_S16(materialId2), "material 2");
282  outMsg.writeInt16(CAST_S16(materialId3), "material 3");
283 }
284 
286  const int nameId) const
287 {
289  outMsg.writeInt16(CAST_S16(type), "type");
290  outMsg.writeInt16(CAST_S16(nameId), "name id");
291 }
292 
293 void NpcHandler::repair(const int index) const
294 {
296  outMsg.writeInt16(CAST_S16(index), "index");
297 }
298 
299 void NpcHandler::refine(const int index) const
300 {
302  outMsg.writeInt32(index, "index");
303 }
304 
305 void NpcHandler::identify(const int index) const
306 {
308  outMsg.writeInt16(CAST_S16(index), "index");
309 }
310 
311 void NpcHandler::selectArrow(const int nameId) const
312 {
314  outMsg.writeInt16(CAST_S16(nameId), "name id");
315 }
316 
317 void NpcHandler::selectAutoSpell(const int skillId) const
318 {
320  outMsg.writeInt32(CAST_S16(skillId), "skill id");
321 }
322 
324  const NpcActionT action)
325 {
326  const BeingId npcId = msg.readBeingId("npc id");
327 
328  const NpcDialogs::const_iterator diag = NpcDialog::mNpcDialogs.find(npcId);
329  Ea::NpcRecv::mDialog = nullptr;
330 
331  if (diag == NpcDialog::mNpcDialogs.end())
332  {
333  // Empty dialogs don't help
334  if (action == NpcAction::Close)
335  {
336  closeDialog(npcId);
337  return npcId;
338  }
339  else if (action == NpcAction::Next)
340  {
341  nextDialog(npcId);
342  return npcId;
343  }
344  else
345  {
348  if (localPlayer != nullptr)
349  localPlayer->stopWalking(false);
351  }
352  }
353  else
354  {
355  NpcDialog *const dialog = diag->second;
356  if (Ea::NpcRecv::mDialog != nullptr && Ea::NpcRecv::mDialog != dialog)
358  Ea::NpcRecv::mDialog = dialog;
359  if (Ea::NpcRecv::mDialog != nullptr)
361  }
362  return npcId;
363 }
364 
365 } // 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:273
NpcAction ::T NpcActionT
Definition: npcaction.h:32
void cooking(const CookingTypeT type, const int nameId) const
Definition: npchandler.cpp:285
void selectArrow(const int nameId) const
Definition: npchandler.cpp:311
virtual BeingId readBeingId(const char *const str)=0
int CMSG_NPC_INT_RESPONSE
int CMSG_NPC_REFINE
void selectAutoSpell(const int skillId) const
Definition: npchandler.cpp:317
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:97
BeingId getNpc(Net::MessageIn &msg, const NpcActionT action)
Definition: npchandler.cpp:323
void sellItem(const BeingId beingId, const int itemId, const int amount) const
Definition: npchandler.cpp:227
uint16_t ItemColor
Definition: itemcolor.h:29
bool msg(InputEvent &event)
Definition: chat.cpp:38
int CMSG_NPC_REPAIR
void talk(const Being *const being) const
Definition: npchandler.cpp:64
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:157
int CMSG_NPC_TALK
#define CREATEWIDGETV(var, type,...)
Definition: createwidget.h:24
void repair(const int index) const
Definition: npchandler.cpp:293
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:113
void buy(const Being *const being) const
Definition: npchandler.cpp:132
#define CAST_S32
Definition: cast.h:29
static NpcDialogs mNpcDialogs
Definition: npcdialog.h:241
void identify(const int index) const
Definition: npchandler.cpp:305
LocalPlayer * localPlayer
void refine(const int index) const
Definition: npchandler.cpp:299
int CMSG_NPC_SELECT_ARROW
void buyItems(std::vector< ShopItem *> &items) const
Definition: npchandler.cpp:168
void closeDialog(const BeingId npcId)
Definition: npchandler.cpp:80
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:171
int packetVersion
Definition: client.cpp:120
void integerInput(const BeingId npcId, const int value) const
Definition: npchandler.cpp:105
void sell(const BeingId beingId) const
Definition: npchandler.cpp:150
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:86
#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:74
BeingTypeId getSubType() const
Definition: being.h:393
int CMSG_NPC_BUY_SELL_REQUEST
void completeProgressBar() const
Definition: npchandler.cpp:268
void sellItems(std::vector< ShopItem *> &items) const
Definition: npchandler.cpp:237