1/*
2 * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#ifndef GAME_H
24#define GAME_H
25
26#include "declarations.h"
27#include "item.h"
28#include "animatedtext.h"
29#include "effect.h"
30#include "creature.h"
31#include "container.h"
32#include "protocolgame.h"
33#include "localplayer.h"
34#include "outfit.h"
35#include <framework/core/timer.h>
36
37#include <bitset>
38
39struct UnjustifiedPoints {
40 bool operator==(const UnjustifiedPoints& other) const {
41 return killsDay == other.killsDay &&
42 killsDayRemaining == other.killsDayRemaining &&
43 killsWeek == other.killsWeek &&
44 killsWeekRemaining == other.killsWeekRemaining &&
45 killsMonth == other.killsMonth &&
46 killsMonthRemaining == other.killsMonthRemaining &&
47 skullTime == other.skullTime;
48 }
49 uint8 killsDay;
50 uint8 killsDayRemaining;
51 uint8 killsWeek;
52 uint8 killsWeekRemaining;
53 uint8 killsMonth;
54 uint8 killsMonthRemaining;
55 uint8 skullTime;
56};
57
58typedef std::tuple<std::string, uint, std::string, int, bool> Vip;
59
60//@bindsingleton g_game
61class Game
62{
63public:
64 Game();
65
66 void init();
67 void terminate();
68
69private:
70 void resetGameStates();
71
72protected:
73 void processConnectionError(const boost::system::error_code& error);
74 void processDisconnect();
75 void processPing();
76 void processPingBack();
77 void processNewPing(uint32_t pingId);
78
79 void processUpdateNeeded(const std::string& signature);
80 void processLoginError(const std::string& error);
81 void processLoginAdvice(const std::string& message);
82 void processLoginWait(const std::string& message, int time);
83 void processLoginToken(bool unknown);
84 void processLogin();
85 void processPendingGame();
86 void processEnterGame();
87
88 void processGameStart();
89 void processGameEnd();
90 void processDeath(int deathType, int penality);
91
92 void processGMActions(const std::vector<uint8>& actions);
93 void processInventoryChange(int slot, const ItemPtr& item);
94 void processAttackCancel(uint seq);
95 void processWalkCancel(Otc::Direction direction);
96
97 void processNewWalkCancel(Otc::Direction dir);
98 void processPredictiveWalkCancel(const Position& pos, Otc::Direction dir);
99 void processWalkId(uint32_t walkId);
100
101 void processPlayerHelpers(int helpers);
102 void processPlayerModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeMode, Otc::PVPModes pvpMode);
103
104 // message related
105 void processTextMessage(Otc::MessageMode mode, const std::string& text);
106 void processTalk(const std::string& name, int level, Otc::MessageMode mode, const std::string& text, int channelId, const Position& pos);
107
108 // container related
109 void processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items, bool isUnlocked, bool hasPages, int containerSize, int firstIndex);
110 void processCloseContainer(int containerId);
111 void processContainerAddItem(int containerId, const ItemPtr& item, int slot);
112 void processContainerUpdateItem(int containerId, int slot, const ItemPtr& item);
113 void processContainerRemoveItem(int containerId, int slot, const ItemPtr& lastItem);
114
115 // channel related
116 void processChannelList(const std::vector<std::tuple<int, std::string> >& channelList);
117 void processOpenChannel(int channelId, const std::string& name);
118 void processOpenPrivateChannel(const std::string& name);
119 void processOpenOwnPrivateChannel(int channelId, const std::string& name);
120 void processCloseChannel(int channelId);
121
122 // rule violations
123 void processRuleViolationChannel(int channelId);
124 void processRuleViolationRemove(const std::string& name);
125 void processRuleViolationCancel(const std::string& name);
126 void processRuleViolationLock();
127
128 // vip related
129 void processVipAdd(uint id, const std::string& name, uint status, const std::string& description, int iconId, bool notifyLogin);
130 void processVipStateChange(uint id, uint status);
131
132 // tutorial hint
133 void processTutorialHint(int id);
134 void processAddAutomapFlag(const Position& pos, int icon, const std::string& message);
135 void processRemoveAutomapFlag(const Position& pos, int icon, const std::string& message);
136
137 // outfit
138 void processOpenOutfitWindow(const Outfit& currentOutfit, const std::vector<std::tuple<int, std::string, int>>& outfitList,
139 const std::vector<std::tuple<int, std::string>>& mountList,
140 const std::vector<std::tuple<int, std::string>>& wingList,
141 const std::vector<std::tuple<int, std::string>>& auraList,
142 const std::vector<std::tuple<int, std::string>>& shaderList,
143 const std::vector<std::tuple<int, std::string>>& healthBarList,
144 const std::vector<std::tuple<int, std::string>>& manaBarList);
145
146 // npc trade
147 void processOpenNpcTrade(const std::vector<std::tuple<ItemPtr, std::string, int, int64_t, int64_t> >& items);
148 void processPlayerGoods(uint64_t money, const std::vector<std::tuple<ItemPtr, int> >& goods);
149 void processCloseNpcTrade();
150
151 // player trade
152 void processOwnTrade(const std::string& name, const std::vector<ItemPtr>& items);
153 void processCounterTrade(const std::string& name, const std::vector<ItemPtr>& items);
154 void processCloseTrade();
155
156 // edit text/list
157 void processEditText(uint id, int itemId, int maxLength, const std::string& text, const std::string& writer, const std::string& date);
158 void processEditList(uint id, int doorId, const std::string& text);
159
160 // questlog
161 void processQuestLog(const std::vector<std::tuple<int, std::string, bool> >& questList);
162 void processQuestLine(int questId, const std::vector<std::tuple<std::string, std::string, int> >& questMissions);
163
164 // modal dialogs >= 970
165 void processModalDialog(uint32 id, std::string title, std::string message, std::vector<std::tuple<int, std::string> > buttonList, int enterButton, int escapeButton, std::vector<std::tuple<int, std::string> > choiceList, bool priority);
166
167 friend class ProtocolGame;
168 friend class Map;
169
170public:
171 // login related
172 void loginWorld(const std::string& account, const std::string& password, const std::string& worldName, const std::string& worldHost, int worldPort, const std::string& characterName, const std::string& authenticatorToken, const std::string& sessionKey, const std::string& recordTo = "");
173 void playRecord(const std::string& file);
174 void cancelLogin();
175 void forceLogout();
176 void safeLogout();
177
178 // walk related
179 void walk(Otc::Direction direction, bool withPreWalk);
180 void autoWalk(const std::vector<Otc::Direction>& dirs, Position startPos);
181 void turn(Otc::Direction direction);
182 void stop();
183
184 // item related
185 void look(const ThingPtr& thing, bool isBattleList = false);
186 void move(const ThingPtr& thing, const Position& toPos, int count);
187 void moveRaw(const Position& pos, int id, int stackpos, const Position& toPos, int count);
188 void moveToParentContainer(const ThingPtr& thing, int count);
189 void rotate(const ThingPtr& thing);
190 void wrap(const ThingPtr& thing);
191 void use(const ThingPtr& thing);
192 void useWith(const ItemPtr& fromThing, const ThingPtr& toThing, int subType = 0);
193 void useInventoryItem(int itemId, int subType = 0);
194 void useInventoryItemWith(int itemId, const ThingPtr& toThing, int subType = 0);
195 ItemPtr findItemInContainers(uint itemId, int subType);
196
197 // container related
198 int open(const ItemPtr& item, const ContainerPtr& previousContainer);
199 void openParent(const ContainerPtr& container);
200 void close(const ContainerPtr& container);
201 void refreshContainer(const ContainerPtr& container);
202
203 // attack/follow related
204 void attack(CreaturePtr creature, bool cancel = false);
205 void cancelAttack() { attack(nullptr, true); }
206 void follow(CreaturePtr creature);
207 void cancelFollow() { follow(nullptr); }
208 void cancelAttackAndFollow();
209
210 // talk related
211 void talk(const std::string& message);
212 void talkChannel(Otc::MessageMode mode, int channelId, const std::string& message);
213 void talkPrivate(Otc::MessageMode mode, const std::string& receiver, const std::string& message);
214
215 // channel related
216 void openPrivateChannel(const std::string& receiver);
217 void requestChannels();
218 void joinChannel(int channelId);
219 void leaveChannel(int channelId);
220 void closeNpcChannel();
221 void openOwnChannel();
222 void inviteToOwnChannel(const std::string& name);
223 void excludeFromOwnChannel(const std::string& name);
224
225 // party related
226 void partyInvite(int creatureId);
227 void partyJoin(int creatureId);
228 void partyRevokeInvitation(int creatureId);
229 void partyPassLeadership(int creatureId);
230 void partyLeave();
231 void partyShareExperience(bool active);
232
233 // outfit related
234 void requestOutfit();
235 void changeOutfit(const Outfit& outfit);
236
237 // vip related
238 void addVip(const std::string& name);
239 void removeVip(int playerId);
240 void editVip(int playerId, const std::string& description, int iconId, bool notifyLogin);
241
242 // fight modes related
243 void setChaseMode(Otc::ChaseModes chaseMode);
244 void setFightMode(Otc::FightModes fightMode);
245 void setSafeFight(bool on);
246 void setPVPMode(Otc::PVPModes pvpMode);
247 Otc::ChaseModes getChaseMode() { return m_chaseMode; }
248 Otc::FightModes getFightMode() { return m_fightMode; }
249 bool isSafeFight() { return m_safeFight; }
250 Otc::PVPModes getPVPMode() { return m_pvpMode; }
251
252 // pvp related
253 void setUnjustifiedPoints(UnjustifiedPoints unjustifiedPoints);
254 UnjustifiedPoints getUnjustifiedPoints() { return m_unjustifiedPoints; };
255 void setOpenPvpSituations(int openPvpSitations);
256 int getOpenPvpSituations() { return m_openPvpSituations; }
257
258 // npc trade related
259 void inspectNpcTrade(const ItemPtr& item);
260 void buyItem(const ItemPtr& item, int amount, bool ignoreCapacity, bool buyWithBackpack);
261 void sellItem(const ItemPtr& item, int amount, bool ignoreEquipped);
262 void closeNpcTrade();
263
264 // player trade related
265 void requestTrade(const ItemPtr& item, const CreaturePtr& creature);
266 void inspectTrade(bool counterOffer, int index);
267 void acceptTrade();
268 void rejectTrade();
269
270 // house window and editable items related
271 void editText(uint id, const std::string& text);
272 void editList(uint id, int doorId, const std::string& text);
273
274 // rule violations (only gms)
275 void openRuleViolation(const std::string& reporter);
276 void closeRuleViolation(const std::string& reporter);
277 void cancelRuleViolation();
278
279 // reports
280 void reportBug(const std::string& comment);
281 void reportRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment);
282 void debugReport(const std::string& a, const std::string& b, const std::string& c, const std::string& d);
283
284 // questlog related
285 void requestQuestLog();
286 void requestQuestLine(int questId);
287
288 // 870 only
289 void equipItem(const ItemPtr& item);
290 void equipItemId(int itemId, int subType);
291 void mount(bool mount);
292 void setOutfitExtensions(int mount, int wings, int aura, int shader, int healthBar, int manaBar);
293
294 // 910 only
295 void requestItemInfo(const ItemPtr& item, int index);
296
297 // >= 970 modal dialog
298 void answerModalDialog(uint32 dialog, int button, int choice);
299
300 // >= 984 browse field
301 void browseField(const Position& position);
302 void seekInContainer(int cid, int index);
303
304 // >= 1080 ingame store
305 void buyStoreOffer(int offerId, int productType, const std::string& name = "");
306 void requestTransactionHistory(int page, int entriesPerPage);
307 void requestStoreOffers(const std::string& categoryName, int serviceType = 0);
308 void openStore(int serviceType = 0);
309 void transferCoins(const std::string& recipient, int amount);
310 void openTransactionHistory(int entriesPerPage);
311
312 // >= 1100
313 void preyAction(int slot, int actionType, int index);
314 void preyRequest();
315
316 void applyImbuement(uint8_t slot, uint32_t imbuementId, bool protectionCharm);
317 void clearImbuement(uint8_t slot);
318 void closeImbuingWindow();
319
320 //void reportRuleViolation2();
321 void ping();
322 void newPing();
323 void setPingDelay(int delay) { m_pingDelay = delay; }
324
325 // otclient only
326 void changeMapAwareRange(int xrange, int yrange);
327
328 // dynamic support for game features
329 void resetFeatures() { m_features.reset(); }
330 void enableFeature(Otc::GameFeature feature) { m_features.set(feature, true); }
331 void disableFeature(Otc::GameFeature feature) { m_features.set(feature, false); }
332 void setFeature(Otc::GameFeature feature, bool enabled) { m_features.set(feature, enabled); }
333 bool getFeature(Otc::GameFeature feature) { return m_features.test(feature); }
334
335 void setProtocolVersion(int version);
336 int getProtocolVersion() { return m_protocolVersion; }
337 void setCustomProtocolVersion(int version) { m_customProtocolVersion = version; }
338 int getCustomProtocolVersion() { return m_customProtocolVersion != 0 ? m_customProtocolVersion : m_protocolVersion; }
339
340 void setClientVersion(int version);
341 int getClientVersion() { return m_clientVersion; }
342
343 void setCustomOs(int os) { m_clientCustomOs = os; }
344 int getOs();
345
346 bool canPerformGameAction();
347 bool checkBotProtection();
348
349 bool isOnline() { return m_online; }
350 bool isLogging() { return !m_online && m_protocolGame; }
351 bool isDead() { return m_dead; }
352 bool isAttacking() { return !!m_attackingCreature && !m_attackingCreature->isRemoved(); }
353 bool isFollowing() { return !!m_followingCreature && !m_followingCreature->isRemoved(); }
354 bool isConnectionOk() { return m_protocolGame && m_protocolGame->getElapsedTicksSinceLastRead() < 5000; }
355
356 int getPing() { return m_ping; }
357 ContainerPtr getContainer(int index) { if (m_containers.find(index) == m_containers.end()) { return nullptr; } return m_containers[index]; }
358 std::map<int, ContainerPtr> getContainers() { return m_containers; }
359 std::map<int, Vip> getVips() { return m_vips; }
360 CreaturePtr getAttackingCreature() { return m_attackingCreature; }
361 CreaturePtr getFollowingCreature() { return m_followingCreature; }
362 void setServerBeat(int beat) { m_serverBeat = beat; }
363 int getServerBeat() { return m_serverBeat; }
364 void setCanReportBugs(bool enable) { m_canReportBugs = enable; }
365 bool canReportBugs() { return m_canReportBugs; }
366 void setExpertPvpMode(bool enable) { m_expertPvpMode = enable; }
367 bool getExpertPvpMode() { return m_expertPvpMode; }
368 LocalPlayerPtr getLocalPlayer() { return m_localPlayer; }
369 ProtocolGamePtr getProtocolGame() { return m_protocolGame; }
370 std::string getCharacterName() { return m_characterName; }
371 std::string getWorldName() { return m_worldName; }
372 std::vector<uint8> getGMActions() { return m_gmActions; }
373 bool isGM() { return m_gmActions.size() > 0; }
374 Otc::Direction getLastWalkDir() { return m_lastWalkDir; }
375
376 std::string formatCreatureName(const std::string &name);
377 int findEmptyContainerId();
378
379 void setTibiaCoins(int coins, int transferableCoins)
380 {
381 m_coins = coins;
382 m_transferableCoins = transferableCoins;
383 }
384 int getTibiaCoins()
385 {
386 return m_coins;
387 }
388 int getTransferableTibiaCoins()
389 {
390 return m_transferableCoins;
391 }
392
393 void setMaxPreWalkingSteps(uint value) { m_maxPreWalkingSteps = value; }
394 uint getMaxPreWalkingSteps() { return m_maxPreWalkingSteps; }
395
396 void showRealDirection(bool value) { m_showRealDirection = value; }
397 bool shouldShowingRealDirection() { return m_showRealDirection; }
398
399 uint getWalkId() { return m_walkId; }
400 uint getWalkPreditionId() { return m_walkPrediction; }
401
402 void ignoreServerDirection(bool value) { m_ignoreServerDirection = value; }
403 bool isIgnoringServerDirection()
404 {
405 return m_ignoreServerDirection;
406 }
407
408 void enableTileThingLuaCallback(bool value) { m_tileThingsLuaCallback = value; }
409 bool isTileThingLuaCallbackEnabled() { return m_tileThingsLuaCallback; }
410
411 int getRecivedPacketsCount()
412 {
413 return m_protocolGame ? m_protocolGame->getRecivedPacketsCount() : 0;
414 }
415
416 int getRecivedPacketsSize()
417 {
418 return m_protocolGame ? m_protocolGame->getRecivedPacketsSize() : 0;
419 }
420
421protected:
422 void enableBotCall() { m_denyBotCall = false; }
423 void disableBotCall() { m_denyBotCall = true; }
424
425private:
426 void setAttackingCreature(const CreaturePtr& creature);
427 void setFollowingCreature(const CreaturePtr& creature);
428
429 LocalPlayerPtr m_localPlayer;
430 CreaturePtr m_attackingCreature;
431 CreaturePtr m_followingCreature;
432 ProtocolGamePtr m_protocolGame;
433 std::map<int, ContainerPtr> m_containers;
434 std::map<int, Vip> m_vips;
435
436 bool m_online;
437 bool m_denyBotCall;
438 bool m_dead;
439 bool m_expertPvpMode;
440 int m_serverBeat;
441 ticks_t m_ping;
442 uint m_pingSent;
443 uint m_pingReceived;
444 uint m_walkId = 0;
445 uint m_walkPrediction = 0;
446 uint m_maxPreWalkingSteps = 2;
447 stdext::timer m_pingTimer;
448 std::map<uint32_t, stdext::timer> m_newPingIds;
449 uint m_seq;
450 int m_pingDelay;
451 int m_newPingDelay;
452 Otc::FightModes m_fightMode;
453 Otc::ChaseModes m_chaseMode;
454 Otc::PVPModes m_pvpMode;
455 Otc::Direction m_lastWalkDir;
456 bool m_waitingForAnotherDir = false;
457 UnjustifiedPoints m_unjustifiedPoints;
458 int m_openPvpSituations;
459 bool m_safeFight;
460 bool m_canReportBugs;
461 std::vector<uint8> m_gmActions;
462 std::string m_characterName;
463 std::string m_worldName;
464 std::bitset<Otc::LastGameFeature> m_features;
465 ScheduledEventPtr m_pingEvent;
466 ScheduledEventPtr m_newPingEvent;
467 ScheduledEventPtr m_checkConnectionEvent;
468 bool m_connectionFailWarned;
469 int m_protocolVersion;
470 int m_customProtocolVersion = 0;
471 int m_clientVersion;
472 std::string m_clientSignature;
473 int m_clientCustomOs;
474 int m_coins;
475 int m_transferableCoins;
476
477 bool m_showRealDirection = false;
478 bool m_ignoreServerDirection = true;
479 bool m_tileThingsLuaCallback = false;
480};
481
482extern Game g_game;
483
484#endif
485