1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "bladerunner/items.h"
24
25 #include "bladerunner/game_constants.h"
26 #include "bladerunner/savefile.h"
27 #include "bladerunner/scene.h"
28 #include "bladerunner/scene_objects.h"
29 #include "bladerunner/zbuffer.h"
30
31 namespace BladeRunner {
32
Items(BladeRunnerEngine * vm)33 Items::Items(BladeRunnerEngine *vm) {
34 _vm = vm;
35 }
36
~Items()37 Items::~Items() {
38 reset();
39 }
40
reset()41 void Items::reset() {
42 for (int i = _items.size() - 1; i >= 0; --i) {
43 delete _items.remove_at(i);
44 }
45 }
46
getXYZ(int itemId,float * x,float * y,float * z) const47 void Items::getXYZ(int itemId, float *x, float *y, float *z) const {
48 int itemIndex = findItem(itemId);
49 assert(itemIndex != -1);
50
51 _items[itemIndex]->getXYZ(x, y, z);
52 }
53
setXYZ(int itemId,Vector3 position)54 void Items::setXYZ(int itemId, Vector3 position) {
55 int itemIndex = findItem(itemId);
56 assert(itemIndex != -1);
57
58 _items[itemIndex]->setXYZ(position);
59 }
60
getWidthHeight(int itemId,int * width,int * height) const61 void Items::getWidthHeight(int itemId, int *width, int *height) const {
62 int itemIndex = findItem(itemId);
63 assert(itemIndex != -1);
64
65 _items[itemIndex]->getWidthHeight(width, height);
66 }
67
getAnimationId(int itemId,int * animationId) const68 void Items::getAnimationId(int itemId, int *animationId) const {
69 int itemIndex = findItem(itemId);
70 assert(itemIndex != -1);
71
72 _items[itemIndex]->getAnimationId(animationId);
73 }
74
tick()75 void Items::tick() {
76 int setId = _vm->_scene->getSetId();
77 for (int i = 0; i < (int)_items.size(); ++i) {
78 if (_items[i]->_setId != setId) {
79 continue;
80 }
81 bool notPoliceMazeTarget = setId == kSetPS10_PS11_PS12_PS13 && !_items[i]->isTarget();
82 Common::Rect screenRect;
83 if (_items[i]->tick(&screenRect, notPoliceMazeTarget)) {
84 _vm->_zbuffer->mark(screenRect);
85 }
86 }
87 }
88
addToWorld(int itemId,int animationId,int setId,Vector3 position,int facing,int height,int width,bool isTargetFlag,bool isVisibleFlag,bool isPoliceMazeEnemyFlag,bool addToSetFlag)89 bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetFlag, bool isVisibleFlag, bool isPoliceMazeEnemyFlag, bool addToSetFlag) {
90 if (_items.size() >= 100) {
91 return false;
92 }
93 int itemIndex = findItem(itemId);
94 if (itemIndex == -1) {
95 itemIndex = _items.size();
96 _items.push_back(new Item(_vm));
97 }
98
99 Item *item = _items[itemIndex];
100 item->setup(itemId, setId, animationId, position, facing, height, width, isTargetFlag, isVisibleFlag, isPoliceMazeEnemyFlag);
101
102 if (addToSetFlag && setId == _vm->_scene->getSetId()) {
103 return _vm->_sceneObjects->addItem(itemId + kSceneObjectOffsetItems, item->_boundingBox, item->_screenRectangle, isTargetFlag, isVisibleFlag);
104 }
105 return true;
106 }
107
addToSet(int setId)108 bool Items::addToSet(int setId) {
109 int itemCount = _items.size();
110 if (itemCount == 0) {
111 return true;
112 }
113 for (int i = 0; i < itemCount; ++i) {
114 Item *item = _items[i];
115 if (item->_setId == setId) {
116 _vm->_sceneObjects->addItem(item->_itemId + kSceneObjectOffsetItems, item->_boundingBox, item->_screenRectangle, item->isTarget(), item->_isVisible);
117 }
118 }
119 return true;
120 }
121
122 #if !BLADERUNNER_ORIGINAL_BUGS
removeFromCurrentSceneOnly(int itemId)123 bool Items::removeFromCurrentSceneOnly(int itemId) {
124 if (_items.size() == 0) {
125 return false;
126 }
127 int itemIndex = findItem(itemId);
128 if (itemIndex == -1) {
129 return false;
130 }
131
132 if (_items[itemIndex]->_setId == _vm->_scene->getSetId()) {
133 _vm->_sceneObjects->remove(itemId + kSceneObjectOffsetItems);
134 }
135 return true;
136 }
137 #endif // !BLADERUNNER_ORIGINAL_BUGS
138
remove(int itemId)139 bool Items::remove(int itemId) {
140 if (_items.size() == 0) {
141 return false;
142 }
143 int itemIndex = findItem(itemId);
144 if (itemIndex == -1) {
145 return false;
146 }
147
148 if (_items[itemIndex]->_setId == _vm->_scene->getSetId()) {
149 _vm->_sceneObjects->remove(itemId + kSceneObjectOffsetItems);
150 }
151
152 delete _items.remove_at(itemIndex);
153
154 return true;
155 }
156
setIsTarget(int itemId,bool val)157 void Items::setIsTarget(int itemId, bool val) {
158 int itemIndex = findItem(itemId);
159 if (itemIndex == -1) {
160 return;
161 }
162 _items[itemIndex]->setIsTarget(val);
163 _vm->_sceneObjects->setIsTarget(itemId + kSceneObjectOffsetItems, val);
164 }
165
isTarget(int itemId) const166 bool Items::isTarget(int itemId) const {
167 int itemIndex = findItem(itemId);
168 if (itemIndex == -1) {
169 return false;
170 }
171 return _items[itemIndex]->isTarget();
172 }
173
isSpinning(int itemId) const174 bool Items::isSpinning(int itemId) const {
175 int itemIndex = findItem(itemId);
176 if (itemIndex == -1) {
177 return false;
178 }
179 return _items[itemIndex]->isSpinning();
180 }
181
isVisible(int itemId) const182 bool Items::isVisible(int itemId) const {
183 int itemIndex = findItem(itemId);
184 if (itemIndex == -1) {
185 return false;
186 }
187 return _items[itemIndex]->isVisible();
188 }
189
isPoliceMazeEnemy(int itemId) const190 bool Items::isPoliceMazeEnemy(int itemId) const {
191 int itemIndex = findItem(itemId);
192 if (itemIndex == -1) {
193 return false;
194 }
195 return _items[itemIndex]->isPoliceMazeEnemy();
196 }
197
setPoliceMazeEnemy(int itemId,bool val)198 void Items::setPoliceMazeEnemy(int itemId, bool val) {
199 int itemIndex = findItem(itemId);
200 if (itemIndex == -1) {
201 return;
202 }
203 _items[itemIndex]->setPoliceMazeEnemy(val);
204 }
205
setIsObstacle(int itemId,bool val)206 void Items::setIsObstacle(int itemId, bool val) {
207 int itemIndex = findItem(itemId);
208 if (itemIndex == -1) {
209 return;
210 }
211 _items[itemIndex]->setVisible(val);
212 _vm->_sceneObjects->setIsClickable(itemId + kSceneObjectOffsetItems, val);
213 }
214
getBoundingBox(int itemId)215 const BoundingBox &Items::getBoundingBox(int itemId) {
216 int itemIndex = findItem(itemId);
217 // if (itemIndex == -1) {
218 // return nullptr;
219 // }
220 return _items[itemIndex]->getBoundingBox();
221 }
222
getScreenRectangle(int itemId)223 const Common::Rect &Items::getScreenRectangle(int itemId) {
224 int itemIndex = findItem(itemId);
225 // if (itemIndex == -1) {
226 // return nullptr;
227 // }
228 return _items[itemIndex]->getScreenRectangle();
229 }
230
getFacing(int itemId) const231 int Items::getFacing(int itemId) const {
232 int itemIndex = findItem(itemId);
233 if (itemIndex == -1) {
234 return 0;
235 }
236 return _items[itemIndex]->getFacing();
237 }
238
setFacing(int itemId,int facing)239 void Items::setFacing(int itemId, int facing) {
240 int itemIndex = findItem(itemId);
241 if (itemIndex == -1) {
242 return;
243 }
244 _items[itemIndex]->setFacing(facing);
245 }
246
spinInWorld(int itemId)247 void Items::spinInWorld(int itemId) {
248 int itemIndex = findItem(itemId);
249 if (itemIndex == -1) {
250 return;
251 }
252 _items[itemIndex]->spinInWorld();
253 }
254
findTargetUnderMouse(int mouseX,int mouseY) const255 int Items::findTargetUnderMouse(int mouseX, int mouseY) const {
256 int setId = _vm->_scene->getSetId();
257 for (int i = 0 ; i < (int)_items.size(); ++i) {
258 if (_items[i]->_setId == setId && _items[i]->isTarget() && _items[i]->isUnderMouse(mouseX, mouseY)) {
259 return _items[i]->_itemId;
260 }
261 }
262 return -1;
263 }
264
findItem(int itemId) const265 int Items::findItem(int itemId) const {
266 for (int i = 0; i < (int)_items.size(); ++i) {
267 if (_items[i]->_itemId == itemId) {
268 return i;
269 }
270 }
271 return -1;
272 }
273
save(SaveFileWriteStream & f)274 void Items::save(SaveFileWriteStream &f) {
275 int size = (int)_items.size();
276
277 f.writeInt(size);
278 int i;
279 for (i = 0; i != size; ++i) {
280 _items[i]->save(f);
281 }
282
283 // Always write out 100 items
284 for (; i != 100; ++i) {
285 f.padBytes(0x174); // bbox + rect + 18 float fields
286 }
287 }
288
load(SaveFileReadStream & f)289 void Items::load(SaveFileReadStream &f) {
290 for (int i = _items.size() - 1; i >= 0; --i) {
291 delete _items.remove_at(i);
292 }
293 _items.resize(f.readInt());
294
295 int size = (int)_items.size();
296
297 int i;
298 for (i = 0; i != size; ++i) {
299 _items[i] = new Item(_vm);
300 _items[i]->load(f);
301 }
302
303 // Always read out 100 items
304 for (; i != 100; ++i) {
305 f.skip(0x174); // bbox + rect + 18 float fields
306 }
307 }
308
309 } // End of namespace BladeRunner
310