Mana
Loading...
Searching...
No Matches
playerhandler.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
23
24#include "actorspritemanager.h"
25#include "being.h"
26#include "client.h"
27#include "configuration.h"
28#include "effectmanager.h"
29#include "game.h"
30#include "localplayer.h"
31#include "log.h"
32#include "playerinfo.h"
33#include "units.h"
34
35#include "gui/buydialog.h"
36#include "gui/buyselldialog.h"
37#include "gui/okdialog.h"
38#include "gui/selldialog.h"
39#include "gui/statuswindow.h"
40#include "gui/viewport.h"
41
42#include "net/tmwa/messagein.h"
43#include "net/tmwa/messageout.h"
44#include "net/tmwa/protocol.h"
45
46#include "utils/gettext.h"
47#include "utils/stringutils.h"
48#include "utils/time.h"
49
51extern OkDialog *deathNotice;
52
53// Max. distance we are willing to scroll after a teleport;
54// everything beyond will reset the port hard.
56
57// TODO Move somewhere else
58namespace {
59
63 struct WeightListener : public gcn::ActionListener
64 {
65 void action(const gcn::ActionEvent &event) override
66 {
67 weightNotice = nullptr;
68 }
69 } weightListener;
70
74 struct DeathListener : public gcn::ActionListener
75 {
76 void action(const gcn::ActionEvent &event) override
77 {
79 deathNotice = nullptr;
80
84
86
88 }
89 } deathListener;
90
91} // anonymous namespace
92
93static const char *randomDeathMessage()
94{
95 static char const *const deadMsg[] =
96 {
97 N_("You are dead."),
98 N_("We regret to inform you that your character was killed in "
99 "battle."),
100 N_("You are not that alive anymore."),
101 N_("The cold hands of the grim reaper are grabbing for your soul."),
102 N_("Game Over!"),
103 N_("Insert coin to continue."),
104 N_("No, kids. Your character did not really die. It... "
105 "err... went to a better place."),
106 N_("Your plan of breaking your enemies weapon by "
107 "bashing it with your throat failed."),
108 N_("I guess this did not run too well."),
109 // NetHack reference:
110 N_("Do you want your possessions identified?"),
111 // Secret of Mana reference:
112 N_("Sadly, no trace of you was ever found..."),
113 // Final Fantasy VI reference:
114 N_("Annihilated."),
115 // Earthbound reference:
116 N_("Looks like you got your head handed to you."),
117 // Leisure Suit Larry 1 reference:
118 N_("You screwed up again, dump your body down the tubes "
119 "and get you another one."),
120 // Monty Python references (Dead Parrot sketch mostly):
121 N_("You're not dead yet. You're just resting."),
122 N_("You are no more."),
123 N_("You have ceased to be."),
124 N_("You've expired and gone to meet your maker."),
125 N_("You're a stiff."),
126 N_("Bereft of life, you rest in peace."),
127 N_("If you weren't so animated, you'd be pushing up the daisies."),
128 N_("Your metabolic processes are now history."),
129 N_("You're off the twig."),
130 N_("You've kicked the bucket."),
131 N_("You've shuffled off your mortal coil, run down the "
132 "curtain and joined the bleedin' choir invisible."),
133 N_("You are an ex-player."),
134 N_("You're pining for the fjords.")
135 };
136
137 const int random = rand() % (sizeof(deadMsg) / sizeof(deadMsg[0]));
138 return gettext(deadMsg[random]);
139}
140
142
143namespace TmwAthena {
144
167
169{
170 if (!local_player)
171 return;
172
173 switch (msg.getId())
174 {
176 /*
177 * This client assumes that all walk messages succeed,
178 * and that the server will send a correction notice
179 * otherwise.
180 */
181 break;
182
183 case SMSG_PLAYER_WARP:
184 {
185 std::string mapPath = msg.readString(16);
186 int x = msg.readInt16();
187 int y = msg.readInt16();
188
189 Log::info("Warping to %s (%d, %d)", mapPath.c_str(), x, y);
190
191 /*
192 * We must clear the local player's target *before* the call
193 * to changeMap, as it deletes all beings.
194 */
196
197 Game *game = Game::instance();
198
199 const std::string &currentMapName = game->getCurrentMapName();
200 bool sameMap = (currentMapName == mapPath);
201
202 // Switch the actual map, deleting the previous one if necessary
203 mapPath = mapPath.substr(0, mapPath.rfind("."));
204 game->changeMap(mapPath);
205
206 float scrollOffsetX = 0.0f;
207 float scrollOffsetY = 0.0f;
208
209 /* Scroll if necessary */
210 Map *map = game->getCurrentMap();
211 int tileX = local_player->getTileX();
212 int tileY = local_player->getTileY();
213 if (!sameMap
214 || (abs(x - tileX) > MAP_TELEPORT_SCROLL_DISTANCE)
215 || (abs(y - tileY) > MAP_TELEPORT_SCROLL_DISTANCE))
216 {
217 scrollOffsetX = (x - tileX) * map->getTileWidth();
218 scrollOffsetY = (y - tileY) * map->getTileHeight();
219 }
220
222 Vector pos = map->getTileCenter(x, y);
224 // Stop movement
225 local_player->setDestination(pos.x, pos.y);
226
227 Log::info("Adjust scrolling by %d:%d", (int) scrollOffsetX,
228 (int) scrollOffsetY);
229
230 viewport->scrollBy(scrollOffsetX, scrollOffsetY);
231 }
232 break;
233
235 {
236 if (!local_player)
237 break;
238 int type = msg.readInt16();
239 int value = msg.readInt32();
240
241 switch (type)
242 {
243 case 0x0000:
244 local_player->setMoveSpeed(Vector(value / 10,
245 value / 10, 0));
246 break;
247 case 0x0004: break; // manner
248 case 0x0005: PlayerInfo::setAttribute(HP, value); break;
249 case 0x0006: PlayerInfo::setAttribute(MAX_HP, value); break;
250 case 0x0007: PlayerInfo::setAttribute(MP, value); break;
251 case 0x0008: PlayerInfo::setAttribute(MAX_MP, value); break;
252 case 0x0009: PlayerInfo::setAttribute(CHAR_POINTS, value); break;
253 case 0x000b: PlayerInfo::setAttribute(LEVEL, value); break;
254 case 0x000c: PlayerInfo::setAttribute(SKILL_POINTS, value); break;
255 case 0x0018:
256 if (value >= PlayerInfo::getAttribute(MAX_WEIGHT) / 2 &&
259 {
260 weightNotice = new OkDialog(_("Message"),
261 _("You are carrying more than "
262 "half your weight. You are "
263 "unable to regain health."));
264 weightNotice->addActionListener(
265 &weightListener);
266 }
268 break;
269 case 0x0019: PlayerInfo::setAttribute(MAX_WEIGHT, value); break;
270
271 case 0x0029: PlayerInfo::setStatBase(ATK, value); break;
272 case 0x002a: PlayerInfo::setStatMod(ATK, value); break;
273
274 case 0x002b: PlayerInfo::setStatBase(MATK, value); break;
275 case 0x002c: PlayerInfo::setStatMod(MATK, value); break;
276
277 case 0x002d: PlayerInfo::setStatBase(DEF, value); break;
278 case 0x002e: PlayerInfo::setStatMod(DEF, value); break;
279
280 case 0x002f: PlayerInfo::setStatBase(MDEF, value); break;
281 case 0x0030: PlayerInfo::setStatMod(MDEF, value); break;
282
283 case 0x0031: PlayerInfo::setStatBase(HIT, value); break;
284
285 case 0x0032: PlayerInfo::setStatBase(FLEE, value); break;
286 case 0x0033: PlayerInfo::setStatMod(FLEE, value); break;
287
288 case 0x0034: PlayerInfo::setStatBase(CRIT, value); break;
289
290 case 0x0035: local_player->setAttackSpeed(value); break;
291
292 case 0x0037: PlayerInfo::setStatBase(JOB, value); break;
293
294 case 500: local_player->setGMLevel(value); break;
295 }
296
298 {
299 viewport->shakeScreen(100);
300 deathNotice = new OkDialog(_("Message"),
301 randomDeathMessage(),
302 false);
303 deathNotice->addActionListener(&deathListener);
305 }
306 }
307
308 if (statusWindow)
310
311 break;
312
314 switch (msg.readInt16())
315 {
316 case 0x0001:
318 break;
319 case 0x0002:
322 break;
323
324 case 0x0014:
325 {
326 int oldMoney = PlayerInfo::getAttribute(MONEY);
327 int newMoney = msg.readInt32();
329 if (newMoney > oldMoney)
330 {
331 std::string money = Units::formatCurrency(newMoney - oldMoney);
333 serverNotice(strprintf(_("You picked up %s."), money.c_str()));
336 }
337 }
338 break;
339 case 0x0016:
341 break;
342 case 0x0017:
345 msg.readInt32());
346 break;
347 }
348 break;
349
350 case SMSG_PLAYER_STAT_UPDATE_3: // Update a base attribute
351 {
352 int type = msg.readInt32();
353 int base = msg.readInt32();
354 int bonus = msg.readInt32();
355
356 PlayerInfo::setStatBase(type, base, false);
357 PlayerInfo::setStatMod(type, bonus);
358 }
359 break;
360
361 case SMSG_PLAYER_STAT_UPDATE_4: // Attribute increase ack
362 {
363 int type = msg.readInt16();
364 int ok = msg.readInt8();
365 int value = msg.readInt8();
366
367 if (ok != 1)
368 serverNotice(_("Cannot raise skill!"));
369
370 PlayerInfo::setStatBase(type, value);
371 }
372 break;
373
374 // Updates stats and status points
377
378 {
379 int val = msg.readInt8();
381 if (val >= 99)
382 {
384 msg.readInt8();
385 }
386 else
387 {
389 }
390
391 val = msg.readInt8();
393 if (val >= 99)
394 {
396 msg.readInt8();
397 }
398 else
399 {
401 }
402
403 val = msg.readInt8();
405 if (val >= 99)
406 {
408 msg.readInt8();
409 }
410 else
411 {
413 }
414
415 val = msg.readInt8();
417 if (val >= 99)
418 {
420 msg.readInt8();
421 }
422 else
423 {
425 }
426
427 val = msg.readInt8();
429 if (val >= 99)
430 {
432 msg.readInt8();
433 }
434 else
435 {
437 }
438
439 val = msg.readInt8();
441 if (val >= 99)
442 {
444 msg.readInt8();
445 }
446 else
447 {
449 }
450
453
456
457
460
463
465
468
470 }
471
472 msg.readInt16(); // manner
473 break;
474
476 switch (msg.readInt16())
477 {
478 case 0x0020:
480 break;
481 case 0x0021:
483 break;
484 case 0x0022:
486 break;
487 case 0x0023:
489 break;
490 case 0x0024:
492 break;
493 case 0x0025:
495 break;
496 }
497 break;
498
500 {
501 int type = msg.readInt16();
502
503 switch (type)
504 {
505 case 0:
506 serverNotice(_("Equip arrows first."));
507 break;
508 default:
509 Log::info("0x013b: Unhandled message %i", type);
510 break;
511 }
512 }
513 break;
514
515 case SMSG_MAP_MASK:
516 {
517 const int mask = msg.readInt32();
518 msg.readInt32(); // unused
519 if (auto game = Game::instance())
520 if (Map *map = game->getCurrentMap())
521 map->setMask(mask);
522 }
523 break;
524
526 {
527 int variable = msg.readInt16();
528 int value = msg.readInt32();
529 int oldValue = mQuestVars.get(variable);
530
531 mQuestVars.set(variable, value);
534
536 {
537 switch (QuestDB::questChange(variable, oldValue, value))
538 {
540 break;
541 case QuestChange::New:
542 effectManager->trigger(paths.getIntValue("newQuestEffectId"), local_player);
543 break;
545 effectManager->trigger(paths.getIntValue("completeQuestEffectId"), local_player);
546 break;
547 }
548 }
549 break;
550 }
551
553 {
554 msg.readInt16(); // length
556 unsigned int count = (msg.getLength() - 4) / 6;
557 for (unsigned int i = 0; i < count; ++i)
558 {
559 int variable = msg.readInt16();
560 int value = msg.readInt32();
561 mQuestVars.set(variable, value);
562 }
565 break;
566 }
567 }
568}
569
571{
573 outMsg.writeInt32(id);
574 outMsg.writeInt8(0);
575}
576
577void PlayerHandler::emote(int emoteId)
578{
580 outMsg.writeInt8(emoteId + 1);
581}
582
584{
585 if (attr >= STRENGTH && attr <= LUCK)
586 {
588 outMsg.writeInt16(attr);
589 outMsg.writeInt8(1);
590 }
591}
592
594{
595 // Supported by eA?
596}
597
599{
601 return;
602
604 outMsg.writeInt16(skillId);
605}
606
608{
609 static Timer lastPickupTimer;
610
611 // Avoid spamming the server with pick-up requests to prevent the player
612 // from being kicked.
613 if (!floorItem || !lastPickupTimer.passed())
614 return;
615
617 outMsg.writeInt32(floorItem->getId());
618
619 lastPickupTimer.set(100);
620}
621
622void PlayerHandler::setDirection(char direction)
623{
625 outMsg.writeInt16(0);
626 outMsg.writeInt8(direction);
627}
628
629void PlayerHandler::setDestination(int x, int y, int direction)
630{
631 // The destination coordinates are received in pixel, so we translate them
632 // into tiles.
633 Map *map = Game::instance()->getCurrentMap();
635 outMsg.writeCoordinates(x / map->getTileWidth(), y / map->getTileHeight(),
636 direction);
637}
638
640{
641 char type;
642 switch (action)
643 {
644 case Being::SIT: type = 2; break;
645 case Being::STAND: type = 3; break;
646 default: return;
647 }
648
650 outMsg.writeInt32(0);
651 outMsg.writeInt8(type);
652}
653
655{
657 outMsg.writeInt8(0);
658}
659
660void PlayerHandler::ignorePlayer(const std::string &player, bool ignore)
661{
662 // TODO
663}
664
666{
667 // TODO
668}
669
674
676{
677 return false;
678}
679
681{
682 return JOB;
683}
684
686{
687 // Return an normalized speed for any side
688 // as the offset is calculated elsewhere.
689 // in ticks per tile.
690 return Vector(15.0f, 15.0f, 0.0f);
691}
692
694{
695 Game *game = Game::instance();
696
697 if (game && !map)
698 map = game->getCurrentMap();
699
700 if (!map || speed.x == 0 || speed.y == 0)
701 {
702 Log::info("TmwAthena::PlayerHandler: Speed set to default: "
703 "Map not yet initialized or invalid speed.");
704 return getDefaultMoveSpeed();
705 }
706
707 Vector pixelsPerSecond;
708
709 constexpr float ticksPerSecond = 1000.0 / MILLISECONDS_IN_A_TICK;
710
711 pixelsPerSecond.x = map->getTileWidth() / speed.x * ticksPerSecond;
712 pixelsPerSecond.y = map->getTileHeight() / speed.y * ticksPerSecond;
713
714 return pixelsPerSecond;
715}
716
717void PlayerHandler::event(Event::Channel channel, const Event &event)
718{
719 if (channel == Event::GameChannel)
720 {
721 if (event.getType() == Event::MapLoaded)
722 {
724 }
725 }
726}
727
729{
730 const auto npcId = npc->getSubType();
731 const auto effect = mActiveQuestEffects.get(npcId);
732 if (effect != 0)
733 npc->setStatusEffect(effect, true);
734}
735
737{
738 auto game = Game::instance();
739 if (!game)
740 return;
741
742 const auto &currentMapName = game->getCurrentMapName();
743 auto updatedQuestEffects = QuestDB::getActiveEffects(mQuestVars, currentMapName);
744
745 // Loop over all NPCs, disabling no longer active effects and enabling new ones
746 for (auto actor : actorSpriteManager->getAll()) {
747 if (actor->getType() != ActorSprite::NPC)
748 continue;
749
750 auto *npc = static_cast<Being *>(actor);
751 const auto npcId = npc->getSubType();
752 const auto oldEffect = mActiveQuestEffects.get(npcId);
753 const auto newEffect = updatedQuestEffects.get(npcId);
754
755 if (oldEffect != newEffect)
756 {
757 if (oldEffect != 0)
758 npc->setStatusEffect(oldEffect, false);
759 if (newEffect != 0)
760 npc->setStatusEffect(newEffect, true);
761 }
762 }
763
764 std::swap(mActiveQuestEffects, updatedQuestEffects);
765}
766
767} // namespace TmwAthena
ActorSpriteManager * actorSpriteManager
Definition game.cpp:110
const ActorSprites & getAll() const
Returns the whole list of beings.
int getId() const
Definition actorsprite.h:63
Definition being.h:65
void setPosition(const Vector &pos) final
Sets the pixel position of this actor.
Definition being.cpp:187
void setStatusEffect(int id, bool active)
Definition being.cpp:596
void setMoveSpeed(const Vector &speed)
Sets the move speed.
Definition being.cpp:173
int getTileX() const override
Returns the tile x coord.
Definition being.h:146
void setAttackSpeed(int speed)
Sets the attack speed.
Definition being.h:325
Action
Action the being is currently performing WARNING: Has to be in sync with the same enum in the Being c...
Definition being.h:73
@ SIT
Definition being.h:77
@ STAND
Definition being.h:74
@ DEAD
Definition being.h:78
int getTileY() const override
Returns the tile y coord.
Definition being.h:152
uint16_t getSubType() const
Definition being.h:292
static void closeAll()
Closes all instances.
static void closeAll()
Closes all instances.
int getIntValue(const std::string &key) const
returns a value corresponding to the given key.
bool trigger(int id, Being *being, int rotation=0)
Triggers a effect with the id, at the specified being, and with the given rotation in degree: 0° = Do...
void listen(Event::Channel channel)
Definition event.h:42
@ CloseAll
Definition event.h:66
@ QuestVarsChanged
Definition event.h:104
@ MapLoaded
Definition event.h:87
void trigger(Channel channel) const
Sends this event to all classes listening to the given channel.
Definition event.h:275
Channel
Definition event.h:45
@ QuestsChannel
Definition event.h:57
@ NpcChannel
Definition event.h:55
@ GameChannel
Definition event.h:52
An item lying on the floor.
Definition flooritem.h:32
The main class responsible for running the game.
Definition game.h:37
const std::string & getCurrentMapName()
Definition game.h:72
Map * getCurrentMap()
Returns the currently active map.
Definition game.h:70
static Game * instance()
Provides access to the game instance.
Definition game.h:53
void changeMap(const std::string &mapName)
Changes the currently active map.
Definition game.cpp:857
void setGMLevel(int level)
void addMessageToQueue(const std::string &message, int color=UserPalette::EXP_INFO)
void setAction(Action action, int attackId=1) override
Sets the current action.
virtual void setDestination(int x, int y)
Sets a new destination for this being to walk to.
void stopAttack()
void clear()
Definition questdb.h:47
Value get(Key key) const
Definition questdb.h:41
void set(Key key, Value value)
Definition questdb.h:36
A tile map.
Definition map.h:147
int getTileHeight() const
Returns the tile height used by this map.
Definition map.h:271
int getTileWidth() const
Returns the tile width of this map.
Definition map.h:265
Vector getTileCenter(int x, int y) const
Returns the tile center position in pixel coordinates.
Definition map.cpp:563
const uint16_t * handledMessages
virtual void respawn()=0
An 'Ok' button dialog.
Definition okdialog.h:34
static void closeAll()
Closes all instances.
void setPointsNeeded(int id, int needed)
Simple timer that can be used to check if a certain amount of time has passed.
Definition time.h:62
bool passed() const
Returns whether the timer has passed.
Definition time.h:88
void set(uint32_t ms=0)
Sets the timer with an optional duration in milliseconds.
Definition time.h:69
Used for parsing an incoming message from eAthena.
Definition messagein.h:35
std::string readString(int length=-1)
Reads a string.
uint16_t readInt16()
Reads an unsigned 16-bit integer from the message.
Definition messagein.cpp:57
uint8_t readInt8()
Reads an unsigned 8-bit integer from the message.
Definition messagein.cpp:46
uint16_t getId() const
Returns the message ID.
Definition messagein.h:42
uint32_t readInt32()
Reads an unsigned 32-bit integer from the message.
Definition messagein.cpp:69
unsigned int getLength() const
Returns the message length.
Definition messagein.h:47
Used for building an outgoing message to eAthena.
Definition messageout.h:35
void writeInt32(uint32_t value)
Writes an unsigned 32-bit integer to the message.
void writeInt8(uint8_t value)
Writes an unsigned 8-bit integer to the message.
void writeInt16(uint16_t value)
Writes an unsigned 16-bit integer to the message.
void writeCoordinates(uint16_t x, uint16_t y, uint8_t direction)
Encodes coordinates and direction in 3 bytes.
void ignorePlayer(const std::string &player, bool ignore) override
bool canCorrectAttributes() override
void emote(int emoteId) override
Vector getDefaultMoveSpeed() const override
Get the original default movement speed.
void setDirection(char direction) override
void applyQuestStatusEffects(Being *npc)
void changeAction(Being::Action action) override
void ignoreAll(bool ignore) override
QuestEffectMap mActiveQuestEffects
void setDestination(int x, int y, int direction=-1) override
void increaseAttribute(int attr) override
void attack(int id) override
void increaseSkill(int skillId) override
void event(Event::Channel channel, const Event &event) override
void pickUp(FloorItem *floorItem) override
Vector getPixelsPerSecondMoveSpeed(const Vector &speed, Map *map=nullptr) override
Convert the original server-dependant speed for internal use.
void decreaseAttribute(int attr) override
void handleMessage(MessageIn &msg) override
static std::string formatCurrency(int value)
Formats the given number in the correct currency format.
Definition units.cpp:216
Vector class.
Definition vector.h:33
float y
Definition vector.h:172
float x
Definition vector.h:171
void closePopupMenu()
Closes the popup menu.
Definition viewport.cpp:544
void scrollBy(float x, float y)
Changes viewpoint by relative pixel coordinates.
Definition viewport.h:141
void shakeScreen(int intensity)
Makes the screen shake in a random direction.
Definition viewport.cpp:243
Config config
Global settings (config.xml)
Definition client.cpp:97
Configuration paths
XML default paths information reader.
Definition client.cpp:99
EffectManager * effectManager
Definition game.cpp:114
void serverNotice(const std::string &message)
Definition event.h:319
OkDialog * deathNotice
Definition game.cpp:90
OkDialog * weightNotice
Definition game.cpp:89
Viewport * viewport
Viewport on the map.
Definition game.cpp:115
StatusWindow * statusWindow
Definition game.cpp:94
#define gettext(s)
Definition gettext.h:37
#define N_(s)
Definition gettext.h:39
#define _(s)
Definition gettext.h:38
LocalPlayer * local_player
const int MAP_TELEPORT_SCROLL_DISTANCE
Max.
Net::PlayerHandler * playerHandler
Definition net.cpp:56
void info(const char *log_text,...) LOG_PRINTF_ATTR
PlayerHandler * getPlayerHandler()
Definition net.cpp:110
int getStatEffective(int id)
Returns the current effective value of the given stat.
void setStatExperience(int id, int have, int need, bool notify)
Changes the experience of the given stat.
void setStatBase(int id, int value, bool notify)
Changes the base value of the given stat.
void setAttribute(int id, int value, bool notify)
Changes the value of the given attribute.
int getAttribute(int id)
Returns the value of the given attribute.
std::pair< int, int > getStatExperience(int id)
Returns the experience of the given stat.
void setStatMod(int id, int value, bool notify)
Changes the modifier for the given stat.
QuestChange questChange(int varId, int oldValue, int newValue)
Definition questdb.cpp:211
QuestEffectMap getActiveEffects(const QuestVars &questVars, const std::string &mapName)
Definition questdb.cpp:137
Warning: buffers and other variables are shared, so there can be only one connection active at a time...
@ DEXTERITY
Definition protocol.h:37
@ INTELLIGENCE
Definition protocol.h:36
@ SMSG_PLAYER_STAT_UPDATE_1
Definition protocol.h:202
@ SMSG_PLAYER_STAT_UPDATE_4
Definition protocol.h:213
@ CMSG_ITEM_PICKUP
Definition protocol.h:189
@ SMSG_PLAYER_ARROW_MESSAGE
Definition protocol.h:270
@ SMSG_PLAYER_STAT_UPDATE_5
Definition protocol.h:214
@ CMSG_PLAYER_CHANGE_DIR
Definition protocol.h:185
@ SMSG_PLAYER_WARP
Definition protocol.h:177
@ CMSG_PLAYER_REBOOT
Definition protocol.h:204
@ CMSG_STAT_UPDATE_REQUEST
Definition protocol.h:212
@ SMSG_QUEST_PLAYER_VARS
Definition protocol.h:300
@ CMSG_SKILL_LEVELUP_REQUEST
Definition protocol.h:265
@ SMSG_QUEST_SET_VAR
Definition protocol.h:299
@ SMSG_PLAYER_STAT_UPDATE_6
Definition protocol.h:215
@ CMSG_PLAYER_CHANGE_DEST
Definition protocol.h:168
@ SMSG_MAP_MASK
Definition protocol.h:302
@ SMSG_WALK_RESPONSE
Definition protocol.h:169
@ CMSG_PLAYER_CHANGE_ACT
Definition protocol.h:171
@ CMSG_PLAYER_EMOTE
Definition protocol.h:216
@ SMSG_PLAYER_STAT_UPDATE_2
Definition protocol.h:203
@ SMSG_PLAYER_STAT_UPDATE_3
Definition protocol.h:272
@ MAX_WEIGHT
Definition playerinfo.h:35
@ EXP
Definition playerinfo.h:33
@ HP
Definition playerinfo.h:31
@ TOTAL_WEIGHT
Definition playerinfo.h:35
@ MAX_HP
Definition playerinfo.h:31
@ LEVEL
Definition playerinfo.h:30
@ EXP_NEEDED
Definition playerinfo.h:33
@ CHAR_POINTS
Definition playerinfo.h:37
@ MP
Definition playerinfo.h:32
@ MAX_MP
Definition playerinfo.h:32
@ SKILL_POINTS
Definition playerinfo.h:36
@ MONEY
Definition playerinfo.h:34
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.
bool showPickupChat
bool showPickupParticle
OkDialog * deathNotice
Definition game.cpp:90
OkDialog * weightNotice
Definition game.cpp:89