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 "common/scummsys.h"
24 
25 #include "zvision/scripting/controls/slot_control.h"
26 
27 #include "zvision/zvision.h"
28 #include "zvision/scripting/script_manager.h"
29 #include "zvision/graphics/cursors/cursor_manager.h"
30 #include "zvision/graphics/render_manager.h"
31 
32 #include "common/stream.h"
33 
34 namespace ZVision {
35 
SlotControl(ZVision * engine,uint32 key,Common::SeekableReadStream & stream)36 SlotControl::SlotControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
37 	: Control(engine, key, CONTROL_SLOT),
38 	  _cursor(CursorIndex_Active),
39 	  _distanceId('0') {
40 
41 	_renderedItem = 0;
42 	_bkg = NULL;
43 
44 	// Loop until we find the closing brace
45 	Common::String line = stream.readLine();
46 	_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
47 	Common::String param;
48 	Common::String values;
49 	getParams(line, param, values);
50 
51 	while (!stream.eos() && !line.contains('}')) {
52 		if (param.matchString("hotspot", true)) {
53 			int x;
54 			int y;
55 			int width;
56 			int height;
57 
58 			sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height);
59 
60 			_hotspot = Common::Rect(x, y, width, height);
61 		} else if (param.matchString("rectangle", true)) {
62 			int x;
63 			int y;
64 			int width;
65 			int height;
66 
67 			sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height);
68 
69 			_rectangle = Common::Rect(x, y, width, height);
70 		} else if (param.matchString("cursor", true)) {
71 			_cursor = _engine->getCursorManager()->getCursorId(values);
72 		} else if (param.matchString("distance_id", true)) {
73 			sscanf(values.c_str(), "%c", &_distanceId);
74 		} else if (param.matchString("venus_id", true)) {
75 			_venusId = atoi(values.c_str());
76 		} else if (param.matchString("eligible_objects", true)) {
77 			char buf[256];
78 			memset(buf, 0, 256);
79 			strncpy(buf, values.c_str(), 255);
80 
81 			char *curpos = buf;
82 			char *strend = buf + strlen(buf);
83 			while (true) {
84 				char *st = curpos;
85 
86 				if (st >= strend)
87 					break;
88 
89 				while (*curpos != ' ' && curpos < strend)
90 					curpos++;
91 
92 				*curpos = 0;
93 				curpos++;
94 
95 				int obj = atoi(st);
96 
97 				_eligibleObjects.push_back(obj);
98 			}
99 		}
100 
101 		line = stream.readLine();
102 		_engine->getScriptManager()->trimCommentsAndWhiteSpace(&line);
103 		getParams(line, param, values);
104 	}
105 
106 	if (_hotspot.isEmpty() || _rectangle.isEmpty()) {
107 		warning("Slot %u was parsed incorrectly", key);
108 	}
109 }
110 
~SlotControl()111 SlotControl::~SlotControl() {
112 	// Clear the state value back to 0
113 	//_engine->getScriptManager()->setStateValue(_key, 0);
114 
115 	if (_bkg)
116 		delete _bkg;
117 }
118 
onMouseUp(const Common::Point & screenSpacePos,const Common::Point & backgroundImageSpacePos)119 bool SlotControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
120 	if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
121 		return false;
122 
123 	if (_hotspot.contains(backgroundImageSpacePos)) {
124 		setVenus();
125 
126 		int item = _engine->getScriptManager()->getStateValue(_key);
127 		int mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem);
128 		if (item != 0) {
129 			if (mouseItem != 0) {
130 				if (eligeblity(mouseItem)) {
131 					_engine->getScriptManager()->inventoryDrop(mouseItem);
132 					_engine->getScriptManager()->inventoryAdd(item);
133 					_engine->getScriptManager()->setStateValue(_key, mouseItem);
134 				}
135 			} else {
136 				_engine->getScriptManager()->inventoryAdd(item);
137 				_engine->getScriptManager()->setStateValue(_key, 0);
138 			}
139 		} else if (mouseItem == 0) {
140 			if (eligeblity(0)) {
141 				_engine->getScriptManager()->inventoryDrop(0);
142 				_engine->getScriptManager()->setStateValue(_key, 0);
143 			}
144 		} else if (eligeblity(mouseItem)) {
145 			_engine->getScriptManager()->setStateValue(_key, mouseItem);
146 			_engine->getScriptManager()->inventoryDrop(mouseItem);
147 		}
148 	}
149 	return false;
150 }
151 
onMouseMove(const Common::Point & screenSpacePos,const Common::Point & backgroundImageSpacePos)152 bool SlotControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
153 	if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
154 		return false;
155 
156 	if (_hotspot.contains(backgroundImageSpacePos)) {
157 		_engine->getCursorManager()->changeCursor(_cursor);
158 		return true;
159 	}
160 
161 	return false;
162 }
163 
process(uint32 deltaTimeInMillis)164 bool SlotControl::process(uint32 deltaTimeInMillis) {
165 	if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
166 		return false;
167 
168 	if (_engine->canRender()) {
169 		int curItem = _engine->getScriptManager()->getStateValue(_key);
170 		if (curItem != _renderedItem) {
171 			if (_renderedItem != 0 && curItem == 0) {
172 				_engine->getRenderManager()->blitSurfaceToBkg(*_bkg, _rectangle.left, _rectangle.top);
173 				_renderedItem = curItem;
174 			} else {
175 				if (_renderedItem == 0) {
176 					if (_bkg)
177 						delete _bkg;
178 
179 					_bkg = _engine->getRenderManager()->getBkgRect(_rectangle);
180 				} else {
181 					_engine->getRenderManager()->blitSurfaceToBkg(*_bkg, _rectangle.left, _rectangle.top);
182 				}
183 
184 				char buf[16];
185 				if (_engine->getGameId() == GID_NEMESIS)
186 					sprintf(buf, "%d%cobj.tga", curItem, _distanceId);
187 				else
188 					sprintf(buf, "g0z%cu%2.2x1.tga", _distanceId, curItem);
189 
190 				Graphics::Surface *srf = _engine->getRenderManager()->loadImage(buf);
191 
192 				int16 drawx = _rectangle.left;
193 				int16 drawy = _rectangle.top;
194 
195 				if (_rectangle.width() > srf->w)
196 					drawx = _rectangle.left + (_rectangle.width() - srf->w) / 2;
197 
198 				if (_rectangle.height() > srf->h)
199 					drawy = _rectangle.top + (_rectangle.height() - srf->h) / 2;
200 
201 				_engine->getRenderManager()->blitSurfaceToBkg(*srf, drawx, drawy, 0);
202 
203 				delete srf;
204 
205 				_renderedItem = curItem;
206 			}
207 		}
208 	}
209 	return false;
210 }
211 
eligeblity(int itemId)212 bool SlotControl::eligeblity(int itemId) {
213 	for (Common::List<int>::iterator it = _eligibleObjects.begin(); it != _eligibleObjects.end(); it++)
214 		if (*it == itemId)
215 			return true;
216 	return false;
217 }
218 
219 } // End of namespace ZVision
220