1 /*
2  *  The ManaPlus Client
3  *  Copyright (C) 2009  The Mana World Development Team
4  *  Copyright (C) 2011-2019  The ManaPlus Developers
5  *  Copyright (C) 2009-2021  Andrei Karas
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 "gui/shortcut/dropshortcut.h"
24 
25 #include "settings.h"
26 
27 #include "being/localplayer.h"
28 #include "being/playerinfo.h"
29 
30 #include "resources/inventory/inventory.h"
31 
32 #include "resources/item/item.h"
33 
34 #include "net/packetlimiter.h"
35 
36 #include "debug.h"
37 
38 static const int DROP_SHORTCUT_ITEMS = 16;
39 
40 DropShortcut *dropShortcut = nullptr;
41 
DropShortcut()42 DropShortcut::DropShortcut() :
43     ShortcutBase("drop", "dropColor", DROP_SHORTCUT_ITEMS),
44     mLastDropIndex(0)
45 {
46     clear(false);
47     load();
48 }
49 
~DropShortcut()50 DropShortcut::~DropShortcut()
51 {
52 }
53 
dropFirst() const54 void DropShortcut::dropFirst() const
55 {
56     if (localPlayer == nullptr)
57         return;
58 
59     if (!PacketLimiter::limitPackets(PacketType::PACKET_DROP))
60         return;
61 
62     const int itemId = getItem(0);
63     const ItemColor itemColor = getItemColor(0);
64     if (PlayerInfo::isItemProtected(itemId))
65         return;
66 
67     if (itemId > 0)
68     {
69         const Item *const item = PlayerInfo::getInventory()
70             ->findItem(itemId, itemColor);
71         if ((item != nullptr) && (item->getQuantity() != 0))
72         {
73             const int cnt = settings.quickDropCounter;
74             if (localPlayer->isServerBuggy())
75             {
76                 PlayerInfo::dropItem(item, cnt, Sfx_true);
77             }
78             else
79             {
80                 for (int i = 0; i < cnt; i++)
81                     PlayerInfo::dropItem(item, 1, Sfx_false);
82             }
83         }
84     }
85 }
86 
dropItems(const int cnt)87 void DropShortcut::dropItems(const int cnt)
88 {
89     if (localPlayer == nullptr)
90         return;
91 
92     if (localPlayer->isServerBuggy())
93     {
94         dropItem(settings.quickDropCounter);
95         return;
96     }
97 
98     int n = 0;
99     const int sz = settings.quickDropCounter;
100     for (int f = 0; f < 9; f++)
101     {
102         for (int i = 0; i < sz; i++)
103         {
104             if (!PacketLimiter::limitPackets(PacketType::PACKET_DROP))
105                 return;
106             if (dropItem(1))
107                 n++;
108         }
109         if (n >= cnt)
110             break;
111     }
112 }
113 
dropItem(const int cnt)114 bool DropShortcut::dropItem(const int cnt)
115 {
116     const Inventory *const inv = PlayerInfo::getInventory();
117     if (inv == nullptr)
118         return false;
119 
120     int itemId = 0;
121     ItemColor itemColor = ItemColor_one;
122     while (mLastDropIndex < DROP_SHORTCUT_ITEMS &&
123            itemId < 1)
124     {
125         if (!PlayerInfo::isItemProtected(itemId))
126         {
127             itemId = getItem(mLastDropIndex);
128             itemColor = getItemColor(mLastDropIndex);
129         }
130         mLastDropIndex ++;
131     }
132 
133     if (itemId > 0)
134     {
135         const Item *const item = inv->findItem(itemId, itemColor);
136         if ((item != nullptr) &&
137             item->getQuantity() > 0)
138         {
139             PlayerInfo::dropItem(item, cnt, Sfx_true);
140             return true;
141         }
142     }
143     if (mLastDropIndex >= DROP_SHORTCUT_ITEMS)
144         mLastDropIndex = 0;
145 
146     if (itemId < 1)
147     {
148         while (mLastDropIndex < DROP_SHORTCUT_ITEMS &&
149                itemId < 1)
150         {
151             if (!PlayerInfo::isItemProtected(itemId))
152             {
153                 itemId = getItem(mLastDropIndex);
154                 itemColor = getItemColor(mLastDropIndex);
155             }
156             mLastDropIndex++;
157         }
158         if (itemId > 0)
159         {
160             const Item *const item = inv->findItem(itemId, itemColor);
161             if ((item != nullptr) && item->getQuantity() > 0)
162             {
163                 PlayerInfo::dropItem(item, cnt, Sfx_true);
164                 return true;
165             }
166         }
167         if (mLastDropIndex >= DROP_SHORTCUT_ITEMS)
168             mLastDropIndex = 0;
169     }
170     return false;
171 }
172