43 opcode = msg->
getU8();
49 m_gameInitialized =
true;
55 if(callLuaField<bool>(
"onOpcode", opcode, msg))
63 parsePendingGame(msg);
71 parseUpdateNeeded(msg);
77 parseLoginAdvice(msg);
100 parseMapDescription(msg);
103 parseMapMoveNorth(msg);
106 parseMapMoveEast(msg);
109 parseMapMoveSouth(msg);
112 parseMapMoveWest(msg);
115 parseUpdateTile(msg);
118 parseTileAddThing(msg);
121 parseTileTransformThing(msg);
124 parseTileRemoveThing(msg);
127 parseCreatureMove(msg);
130 parseOpenContainer(msg);
133 parseCloseContainer(msg);
136 parseContainerAddItem(msg);
139 parseContainerUpdateItem(msg);
142 parseContainerRemoveItem(msg);
145 parseAddInventoryItem(msg);
148 parseRemoveInventoryItem(msg);
151 parseOpenNpcTrade(msg);
154 parsePlayerGoods(msg);
157 parseCloseNpcTrade(msg);
163 parseCounterTrade(msg);
166 parseCloseTrade(msg);
169 parseWorldLight(msg);
172 parseMagicEffect(msg);
175 parseAnimatedText(msg);
178 parseDistanceMissile(msg);
181 parseCreatureMark(msg);
187 parseCreatureHealth(msg);
190 parseCreatureLight(msg);
193 parseCreatureOutfit(msg);
196 parseCreatureSpeed(msg);
199 parseCreatureSkulls(msg);
202 parseCreatureShields(msg);
205 parseCreatureUnpass(msg);
215 parsePremiumTrigger(msg);
218 parsePlayerStats(msg);
221 parsePlayerSkills(msg);
224 parsePlayerState(msg);
227 parsePlayerCancelAttack(msg);
230 parsePlayerModes(msg);
236 parseChannelList(msg);
239 parseOpenChannel(msg);
242 parseOpenPrivateChannel(msg);
245 parseRuleViolationChannel(msg);
248 parseRuleViolationRemove(msg);
251 parseRuleViolationCancel(msg);
254 parseRuleViolationLock(msg);
257 parseOpenOwnPrivateChannel(msg);
260 parseCloseChannel(msg);
263 parseTextMessage(msg);
266 parseCancelWalk(msg);
272 parseFloorChangeUp(msg);
275 parseFloorChangeDown(msg);
278 parseOpenOutfitWindow(msg);
290 parseTutorialHint(msg);
293 parseAutomapFlag(msg);
303 parseSpellCooldown(msg);
306 parseSpellGroupCooldown(msg);
309 parseMultiUseCooldown(msg);
313 parseChannelEvent(msg);
319 parsePlayerInventory(msg);
323 parsePlayerInfo(msg);
327 parseModalDialog(msg);
337 parsePlayerHelpers(msg);
341 parseCreaturesMark(msg);
344 parseCreatureType(msg);
351 parseUnjustifiedStats(msg);
354 parsePvpSituations(msg);
361 parseCoinBalanceUpdating(msg);
364 parseCoinBalance(msg);
367 parseRequestPurchaseData(msg);
370 parseCompleteStorePurchase(msg);
373 parseStoreOffers(msg);
376 parseStoreTransactionHistory(msg);
379 parseStoreError(msg);
386 parseStoreButtonIndicators(msg);
389 parseSetStoreDeepLink(msg);
393 parseExtendedOpcode(msg);
396 parseChangeMapAwareRange(msg);
413 const int serverBeat = msg->
getU16();
427 const int expertModeEnabled = msg->
getU8();
440 m_localPlayer->
setId(playerId);
458 if(!m_gameInitialized) {
460 m_gameInitialized =
true;
464 void ProtocolGame::parseStoreButtonIndicators(
const InputMessagePtr& msg)
486 void ProtocolGame::parseRequestPurchaseData(
const InputMessagePtr& msg)
494 parseCoinBalance(msg);
496 const int categories = msg->
getU16();
497 for(
int i = 0; i < categories; ++i) {
499 std::string description = msg->
getString();
501 int highlightState = 0;
503 highlightState = msg->
getU8();
505 std::vector<std::string> icons;
506 const int iconCount = msg->
getU8();
507 for(
int j = 0; j < iconCount; ++j) {
509 icons.push_back(icon);
520 const bool update = msg->
getU8() == 1;
522 int transferableCoins = -1;
530 transferableCoins = msg->
getU32();
534 void ProtocolGame::parseCoinBalanceUpdating(
const InputMessagePtr& msg)
540 void ProtocolGame::parseCompleteStorePurchase(
const InputMessagePtr& msg)
545 const std::string message = msg->
getString();
546 const int coins = msg->
getU32();
547 const int transferableCoins = msg->
getU32();
549 g_logger.
info(
stdext::format(
"Purchase Complete: %s\nAvailable coins: %d (transferable: %d)", message, coins, transferableCoins));
552 void ProtocolGame::parseStoreTransactionHistory(
const InputMessagePtr& msg)
556 currentPage = msg->
getU16();
559 currentPage = msg->
getU32();
563 const int entries = msg->
getU8();
564 for(
int i = 0; i < entries; ++i) {
566 int productType = msg->
getU8();
567 int coinChange = msg->
getU32();
568 std::string productName = msg->
getString();
577 const int offers = msg->
getU16();
578 for(
int i = 0; i < offers; ++i) {
584 const int highlightState = msg->
getU8();
590 const int disabledState = msg->
getU8();
595 std::vector<std::string> icons;
596 const int iconCount = msg->
getU8();
597 for(
int j = 0; j < iconCount; ++j) {
599 icons.push_back(icon);
602 const int subOffers = msg->
getU16();
603 for(
int j = 0; j < subOffers; ++j) {
607 const int subIcons = msg->
getU8();
608 for(
int k = 0; k < subIcons; k++) {
618 const int errorType = msg->
getU8();
619 const std::string message = msg->
getString();
647 const int helpers = msg->
getU16();
658 std::vector<uint8> actions;
660 int numViolationReasons;
663 numViolationReasons = 20;
665 numViolationReasons = 23;
667 numViolationReasons = 32;
669 for(
int i = 0; i < numViolationReasons; ++i)
670 actions.push_back(msg->
getU8());
676 const std::string signature = msg->
getString();
682 const std::string error = msg->
getString();
689 const std::string message = msg->
getString();
696 const std::string message = msg->
getString();
704 const bool unknown = msg->
getU8() == 0;
732 deathType = msg->
getU8();
735 penality = msg->
getU8();
829 stackPos = msg->
getU8();
845 const Position pos = thing->getPosition();
846 const int stackpos = thing->getStackPos();
849 g_logger.traceError(
"unable to remove thing");
865 g_logger.traceError(
"unable to remove thing");
873 if(!thing || !thing->isCreature()) {
874 g_logger.traceError(
"no creature found to move");
879 g_logger.traceError(
"unable to remove creature");
884 creature->allowAppearWalk();
891 const int containerId = msg->
getU8();
893 const std::string name = msg->
getString();
894 const int capacity = msg->
getU8();
895 const bool hasParent = msg->
getU8() != 0;
897 bool isUnlocked =
true;
898 bool hasPages =
false;
899 int containerSize = 0;
903 isUnlocked = msg->
getU8() != 0;
904 hasPages = msg->
getU8() != 0;
905 containerSize = msg->
getU16();
906 firstIndex = msg->
getU16();
909 const int itemCount = msg->
getU8();
911 std::vector<ItemPtr> items(itemCount);
912 for(
int i = 0; i < itemCount; ++i)
915 g_game.
processOpenContainer(containerId, containerItem, name, capacity, hasParent, items, isUnlocked, hasPages, containerSize, firstIndex);
920 const int containerId = msg->
getU8();
926 const int containerId = msg->
getU8();
935 void ProtocolGame::parseContainerUpdateItem(
const InputMessagePtr& msg)
937 const int containerId = msg->
getU8();
948 void ProtocolGame::parseContainerRemoveItem(
const InputMessagePtr& msg)
950 const int containerId = msg->
getU8();
956 const int itemId = msg->
getU16();
958 lastItem =
getItem(msg, itemId);
967 const int slot = msg->
getU8();
972 void ProtocolGame::parseRemoveInventoryItem(
const InputMessagePtr& msg)
974 const int slot = msg->
getU8();
980 std::vector<std::tuple<ItemPtr, std::string, int, int, int>> items;
988 listCount = msg->
getU16();
990 listCount = msg->
getU8();
992 for(
int i = 0; i < listCount; ++i) {
1000 int weight = msg->
getU32();
1001 int buyPrice = msg->
getU32();
1002 int sellPrice = msg->
getU32();
1003 items.emplace_back(item, name, weight, buyPrice, sellPrice);
1011 std::vector<std::tuple<ItemPtr, int>> goods;
1019 const int size = msg->
getU8();
1020 for(
int i = 0; i < size; ++i) {
1021 const int itemId = msg->
getU16();
1027 amount = msg->
getU8();
1043 const int count = msg->
getU8();
1045 std::vector<ItemPtr> items(count);
1046 for(
int i = 0; i < count; ++i)
1055 const int count = msg->
getU8();
1057 std::vector<ItemPtr> items(count);
1058 for(
int i = 0; i < count; ++i)
1083 effectId = msg->
getU16();
1085 effectId = msg->
getU8();
1093 effect->setId(effectId);
1100 const int color = msg->
getU8();
1101 const std::string text = msg->
getString();
1104 animatedText->setColor(color);
1105 animatedText->setText(text);
1113 const int shotId = msg->
getU8();
1121 missile->setId(shotId);
1122 missile->setPath(fromPos, toPos);
1129 const int color = msg->
getU8();
1133 creature->addTimedSquare(color);
1135 g_logger.traceError(
"could not get creature");
1140 const int numTrappers = msg->
getU8();
1143 g_logger.traceError(
"too many trappers");
1145 for(
int i = 0; i < numTrappers; ++i) {
1151 g_logger.traceError(
"could not get creature");
1158 const int healthPercent = msg->
getU8();
1161 if(creature) creature->setHealthPercent(healthPercent);
1174 g_logger.traceError(
"could not get creature");
1178 creature->setLight(light);
1189 g_logger.traceError(
"could not get creature");
1193 creature->setOutfit(outfit);
1202 baseSpeed = msg->
getU16();
1204 const int speed = msg->
getU16();
1207 if(!creature)
return;
1209 creature->setSpeed(speed);
1211 creature->setBaseSpeed(baseSpeed);
1217 const int skull = msg->
getU8();
1221 g_logger.traceError(
"could not get creature");
1225 creature->setSkull(skull);
1231 const int shield = msg->
getU8();
1235 g_logger.traceError(
"could not get creature");
1239 creature->setShield(shield);
1245 const bool unpass = msg->
getU8();
1249 g_logger.traceError(
"could not get creature");
1253 creature->setPassable(!unpass);
1264 itemId = item->
getId();
1268 const int maxLength = msg->
getU16();
1269 const std::string text = msg->
getString();
1271 const std::string writer = msg->
getString();
1272 std::string date =
"";
1281 const int doorId = msg->
getU8();
1283 const std::string& text = msg->
getString();
1290 const int triggerCount = msg->
getU8();
1291 std::vector<int> triggers;
1293 for(
int i = 0; i < triggerCount; ++i) {
1294 triggers.push_back(msg->
getU8());
1304 const bool premium = msg->
getU8();
1307 const int vocation = msg->
getU8();
1309 const int spellCount = msg->
getU16();
1310 std::vector<int> spells;
1311 for(
int i = 0; i < spellCount; ++i)
1312 spells.push_back(msg->
getU8());
1326 maxHealth = msg->
getU32();
1329 maxHealth = msg->
getU16();
1332 double freeCapacity;
1334 freeCapacity = msg->
getU32() / 100.0;
1336 freeCapacity = msg->
getU16() / 100.0;
1338 double totalCapacity = 0;
1340 totalCapacity = msg->
getU32() / 100.0;
1344 experience = msg->
getU64();
1346 experience = msg->
getU32();
1348 const double level = msg->
getU16();
1349 const double levelPercent = msg->
getU8();
1374 const double magicLevel = msg->
getU8();
1376 double baseMagicLevel;
1378 baseMagicLevel = msg->
getU8();
1380 baseMagicLevel = magicLevel;
1382 const double magicLevelPercent = msg->
getU8();
1383 const double soul = msg->
getU8();
1388 double baseSpeed = 0;
1390 baseSpeed = msg->
getU16();
1392 double regeneration = 0;
1394 regeneration = msg->
getU16();
1396 double training = 0;
1398 training = msg->
getU16();
1405 m_localPlayer->
setHealth(health, maxHealth);
1409 m_localPlayer->
setLevel(level, levelPercent);
1410 m_localPlayer->
setMana(mana, maxMana);
1411 m_localPlayer->
setMagicLevel(magicLevel, magicLevelPercent);
1426 for(
int skill = 0; skill < lastSkill; ++skill) {
1432 level = msg->
getU8();
1437 baseLevel = msg->
getU16();
1439 baseLevel = msg->
getU8();
1443 int levelPercent = 0;
1446 levelPercent = msg->
getU8();
1459 states = msg->
getU8();
1464 void ProtocolGame::parsePlayerCancelAttack(
const InputMessagePtr& msg)
1476 int fightMode = msg->
getU8();
1477 int chaseMode = msg->
getU8();
1478 const bool safeMode = msg->
getU8();
1482 pvpMode = msg->
getU8();
1489 const int spellId = msg->
getU8();
1490 const int delay = msg->
getU32();
1495 void ProtocolGame::parseSpellGroupCooldown(
const InputMessagePtr& msg)
1497 const int groupId = msg->
getU8();
1498 const int delay = msg->
getU32();
1505 const int delay = msg->
getU32();
1542 channelId = msg->
getU16();
1559 const std::string text = msg->
getString();
1566 const int count = msg->
getU8();
1567 std::vector<std::tuple<int, std::string> > channelList;
1568 for(
int i = 0; i < count; ++i) {
1571 channelList.emplace_back(
id, name);
1579 const int channelId = msg->
getU16();
1580 const std::string name = msg->
getString();
1583 const int joinedPlayers = msg->
getU16();
1584 for(
int i = 0; i < joinedPlayers; ++i)
1586 const int invitedPlayers = msg->
getU16();
1587 for(
int i = 0; i < invitedPlayers; ++i)
1594 void ProtocolGame::parseOpenPrivateChannel(
const InputMessagePtr& msg)
1601 void ProtocolGame::parseOpenOwnPrivateChannel(
const InputMessagePtr& msg)
1603 const int channelId = msg->
getU16();
1604 const std::string name = msg->
getString();
1611 const int channelId = msg->
getU16();
1616 void ProtocolGame::parseRuleViolationChannel(
const InputMessagePtr& msg)
1618 const int channelId = msg->
getU16();
1623 void ProtocolGame::parseRuleViolationRemove(
const InputMessagePtr& msg)
1625 const std::string name = msg->
getString();
1630 void ProtocolGame::parseRuleViolationCancel(
const InputMessagePtr& msg)
1632 const std::string name = msg->
getString();
1643 const int code = msg->
getU8();
1671 value[0] = msg->
getU32();
1672 color[0] = msg->
getU8();
1675 value[1] = msg->
getU32();
1676 color[1] = msg->
getU8();
1679 for(
int i = 0; i < 2; ++i) {
1683 animatedText->setColor(color[i]);
1697 const int color = msg->
getU8();
1701 animatedText->setColor(color);
1778 std::vector<std::tuple<int, std::string, int> > outfitList;
1781 const int outfitCount = msg->
getU8();
1782 for(
int i = 0; i < outfitCount; ++i) {
1783 int outfitId = msg->
getU16();
1784 std::string outfitName = msg->
getString();
1785 int outfitAddons = msg->
getU8();
1787 outfitList.emplace_back(outfitId, outfitName, outfitAddons);
1790 int outfitStart, outfitEnd;
1792 outfitStart = msg->
getU16();
1793 outfitEnd = msg->
getU16();
1795 outfitStart = msg->
getU8();
1796 outfitEnd = msg->
getU8();
1799 for(
int i = outfitStart; i <= outfitEnd; ++i)
1800 outfitList.emplace_back(i,
"", 0);
1803 std::vector<std::tuple<int, std::string> > mountList;
1805 const int mountCount = msg->
getU8();
1806 for(
int i = 0; i < mountCount; ++i) {
1807 int mountId = msg->
getU16();
1808 std::string mountName = msg->
getString();
1810 mountList.emplace_back(mountId, mountName);
1820 std::string desc =
"";
1821 bool notifyLogin =
false;
1828 notifyLogin = msg->
getU8();
1854 const int id = msg->
getU8();
1861 const int icon = msg->
getU8();
1862 const std::string description = msg->
getString();
1864 bool remove =
false;
1866 remove = msg->
getU8() != 0;
1876 std::vector<std::tuple<int, std::string, bool> > questList;
1877 const int questsCount = msg->
getU16();
1878 for(
int i = 0; i < questsCount; ++i) {
1881 bool completed = msg->
getU8();
1882 questList.emplace_back(
id, name, completed);
1890 std::vector<std::tuple<std::string, std::string>> questMissions;
1891 const int questId = msg->
getU16();
1892 const int missionCount = msg->
getU8();
1893 for(
int i = 0; i < missionCount; ++i) {
1894 std::string missionName = msg->
getString();
1895 std::string missionDescrition = msg->
getString();
1896 questMissions.emplace_back(missionName, missionDescrition);
1913 std::vector<std::tuple<ItemPtr, std::string>> list;
1914 const int size = msg->
getU8();
1915 for(
int i = 0; i < size; ++i) {
1921 list.emplace_back(item, desc);
1929 const int size = msg->
getU16();
1930 for(
int i = 0; i < size; ++i) {
1940 const std::string title = msg->
getString();
1941 const std::string message = msg->
getString();
1943 const int sizeButtons = msg->
getU8();
1944 std::vector<std::tuple<int, std::string> > buttonList;
1945 for(
int i = 0; i < sizeButtons; ++i) {
1947 int buttonId = msg->
getU8();
1948 buttonList.push_back(std::make_tuple(buttonId, value));
1951 const int sizeChoices = msg->
getU8();
1952 std::vector<std::tuple<int, std::string> > choiceList;
1953 for(
int i = 0; i < sizeChoices; ++i) {
1955 int choideId = msg->
getU8();
1956 choiceList.push_back(std::make_tuple(choideId, value));
1959 int enterButton, escapeButton;
1961 escapeButton = msg->
getU8();
1962 enterButton = msg->
getU8();
1964 enterButton = msg->
getU8();
1965 escapeButton = msg->
getU8();
1968 const bool priority = msg->
getU8() == 0x01;
1975 const int opcode = msg->
getU8();
1976 const std::string buffer = msg->
getString();
1979 m_enableSendExtendedOpcode =
true;
1980 else if(opcode == 2)
1986 void ProtocolGame::parseChangeMapAwareRange(
const InputMessagePtr& msg)
1988 const int xrange = msg->
getU8();
1989 const int yrange = msg->
getU8();
1992 range.
left = xrange / 2 - (xrange + 1) % 2;
1993 range.
right = xrange / 2;
1994 range.
top = yrange / 2 - (yrange + 1) % 2;
1995 range.
bottom = yrange / 2;
2010 for(
int i = 0; i < len; ++i) {
2012 const bool isPermanent = msg->
getU8() != 1;
2018 if(markType == 0xff)
2019 creature->hideStaticSquare();
2023 creature->addTimedSquare(markType);
2025 g_logger.traceError(
"could not get creature");
2036 creature->setType(type);
2038 g_logger.traceError(
"could not get creature");
2043 int startz, endz, zstep;
2056 for(
int nz = startz; nz != endz + zstep; nz += zstep)
2062 for(
int nx = 0; nx < width; ++nx) {
2063 for(
int ny = 0; ny < height; ++ny) {
2064 Position tilePos(x + nx + offset, y + ny + offset,
z);
2080 bool gotEffect =
false;
2081 for(
int stackPos = 0; stackPos < 256; ++stackPos) {
2083 return msg->
getU16() & 0xff;
2106 lookType = msg->
getU16();
2108 lookType = msg->
getU8();
2112 const int head = msg->
getU8();
2113 const int body = msg->
getU8();
2114 const int legs = msg->
getU8();
2115 const int feet = msg->
getU8();
2118 addons = msg->
getU8();
2125 outfit.
setId(lookType);
2132 int lookTypeEx = msg->
getU16();
2133 if(lookTypeEx == 0) {
2158 const int id = msg->
getU16();
2183 assert(stackpos != 255);
2209 g_logger.traceError(
"server said that a creature is known, but it's not");
2220 creatureType = msg->
getU8();
2229 if(
id == m_localPlayer->
getId())
2230 creature = m_localPlayer;
2233 if(m_localPlayer->
getId() == 0 && name == m_localPlayer->
getName())
2234 creature = m_localPlayer;
2242 g_logger.traceError(
"creature type is invalid");
2245 creature->
setId(
id);
2252 const int healthPercent = msg->
getU8();
2260 const int speed = msg->
getU16();
2261 const int skull = msg->
getU8();
2262 const int shield = msg->
getU8();
2266 int8 creatureType = -1;
2271 emblem = msg->
getU8();
2274 creatureType = msg->
getU8();
2278 icon = msg->
getU8();
2294 unpass = msg->
getU8();
2309 if(creatureType != -1)
2310 creature->
setType(creatureType);
2315 if(creature == m_localPlayer && !m_localPlayer->
isKnown())
2323 g_logger.traceError(
"invalid creature");
2327 creature->
turn(direction);
2330 const bool unpass = msg->
getU8();
2349 if(item->
getId() == 0)
2374 const int colorByte = msg->
getU8();
2376 const std::string fontName = msg->
getString();
2377 const std::string text = msg->
getString();
2379 staticText->setText(text);
2380 staticText->setFont(fontName);
2381 staticText->setColor(color);