1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 //This class represents .sto (store) files of the game.
22 //Inns, pubs, temples, backpacks are also implemented by stores.
30 #include "Interface.h"
32 #include "GameScript/GameScript.h"
37 purchased_categories
= NULL
;
48 for (i
= 0; i
< items
.size(); i
++) {
49 if (items
[i
]->trigger
)
50 items
[i
]->trigger
->Release();
57 if (purchased_categories
)
58 free( purchased_categories
);
61 bool Store::IsItemAvailable(unsigned int slot
) const
63 Game
* game
= core
->GetGame();
64 //0 - not infinite, not conditional
66 //other - pst trigger ref
68 Trigger
*trigger
= items
[slot
]->trigger
;
70 return trigger
->Evaluate(game
->GetPC(game
->GetSelectedPCSingle(), false))!=0;
75 int Store::GetRealStockSize()
81 for (unsigned int i
=0;i
<ItemsCount
;i
++) {
82 if (!IsItemAvailable(i
) ) {
89 int Store::AcceptableItemType(ieDword type
, ieDword invflags
, bool pc
) const
93 //don't allow any movement of undroppable items
94 if (invflags
&IE_INV_ITEM_UNDROPPABLE
) {
97 ret
= IE_STORE_BUY
|IE_STORE_SELL
|IE_STORE_STEAL
;
99 if (invflags
&IE_INV_ITEM_UNSTEALABLE
) {
100 ret
&= ~IE_STORE_STEAL
;
102 if (!(invflags
&IE_INV_ITEM_IDENTIFIED
) ) {
105 if (pc
&& (Type
<STT_BG2CONT
) ) {
106 //can't sell critical items
107 if (!(invflags
&IE_INV_ITEM_DESTRUCTIBLE
)) {
108 ret
&= ~IE_STORE_SELL
;
110 //don't allow selling of non destructible items
111 //don't allow selling of critical items (they could still be put in bags)
112 if ((invflags
&(IE_INV_ITEM_DESTRUCTIBLE
|IE_INV_ITEM_CRITICAL
))!=IE_INV_ITEM_DESTRUCTIBLE
) {
113 ret
&= ~IE_STORE_SELL
;
116 //check if store buys stolen items
117 if ((invflags
&IE_INV_ITEM_STOLEN
) && !(Type
&IE_STORE_FENCE
) ) {
118 ret
&= ~IE_STORE_SELL
;
126 for (ieDword i
=0;i
<PurchasedCategoriesCount
;i
++) {
127 if (type
==purchased_categories
[i
]) {
132 //Even if the store doesn't purchase the item, it can still ID it
133 return ret
& ~IE_STORE_SELL
;
136 STOCure
*Store::GetCure(unsigned int idx
) const
138 if (idx
>=CuresCount
) {
144 STODrink
*Store::GetDrink(unsigned int idx
) const
146 if (idx
>=DrinksCount
) {
152 //We need this weirdness for PST item lookup
153 STOItem
*Store::GetItem(unsigned int idx
)
156 if (idx
>=items
.size()) {
162 for (unsigned int i
=0;i
<ItemsCount
;i
++) {
163 if (IsItemAvailable(i
)) {
173 unsigned int Store::FindItem(const ieResRef itemname
, bool usetrigger
) const
175 for (unsigned int i
=0;i
<ItemsCount
;i
++) {
177 if (!IsItemAvailable(i
) ) {
181 STOItem
*temp
= items
[i
];
182 if (!strnicmp(itemname
, temp
->ItemResRef
, 8) ) {
186 return (unsigned int) -1;
189 STOItem
*Store::FindItem(CREItem
*item
, bool exact
)
191 for (unsigned int i
=0;i
<ItemsCount
;i
++) {
192 if (!IsItemAvailable(i
) ) {
195 STOItem
*temp
= items
[i
];
197 if (strnicmp(item
->ItemResRef
, temp
->ItemResRef
, 8) ) {
201 if (temp
->InfiniteSupply
==-1) {
204 //check if we could simply merge the item into the stock or need a new entry
205 if ((temp
->StackAmount
>=99) || memcmp(temp
->Usages
, item
->Usages
, sizeof(item
->Usages
))) {
214 //some stores can recharge items
215 void Store::RechargeItem(CREItem
*item
)
217 //is there any flag which store can recharge?
218 Item
*itm
= gamedata
->GetItem(item
->ItemResRef
);
222 if (!itm
->LoreToID
) {
223 item
->Flags
|= IE_INV_ITEM_IDENTIFIED
;
225 //gemrb extension, some shops won't recharge items
226 if (!(Flags
&IE_STORE_RECHARGE
)) {
227 for (int i
=0;i
<CHARGE_COUNTERS
;i
++) {
228 ITMExtHeader
*h
= itm
->GetExtHeader(i
);
233 if (h
->RechargeFlags
&IE_ITEM_RECHARGE
) {
234 item
->Usages
[i
] = h
->Charges
;
238 gamedata
->FreeItem(itm
, item
->ItemResRef
, 0);
241 void Store::AddItem(CREItem
*item
)
244 STOItem
*temp
= FindItem(item
, true);
247 if (temp
->InfiniteSupply
!=-1) {
253 temp
= new STOItem();
254 //It is important to initialize these fields, if STOItem ever changes to
255 //a real class from struct, make sure the fields are cleared
256 memset( temp
, 0, sizeof (STOItem
) );
257 memcpy( temp
, item
, sizeof( CREItem
) );
258 items
.push_back (temp
);
262 void Store::RemoveItem( unsigned int idx
)
264 if (items
.size()!=ItemsCount
) {
265 printMessage("Store","Inconsistent store", LIGHT_RED
);
268 if (ItemsCount
<=idx
) {
271 items
.erase(items
.begin()+idx
);
275 ieDword
Store::GetOwnerID() const
280 void Store::SetOwnerID(ieDword owner
)
282 StoreOwnerID
= owner
;