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 // FIX need to subclass this class for U6, MD & SE
24 #include "ultima/nuvie/conf/configuration.h"
25 #include "ultima/nuvie/core/nuvie_defs.h"
26 #include "ultima/nuvie/misc/u6_misc.h"
27 #include "ultima/nuvie/files/u6_lib_n.h"
28 #include "ultima/nuvie/files/u6_shape.h"
29 #include "ultima/nuvie/gui/widgets/msg_scroll.h"
30 #include "ultima/nuvie/core/events.h"
31 
32 #include "ultima/nuvie/actors/actor.h"
33 #include "ultima/nuvie/actors/actor_manager.h"
34 #include "ultima/nuvie/screen/game_palette.h"
35 #include "ultima/nuvie/views/doll_widget.h"
36 #include "ultima/nuvie/gui/widgets/command_bar.h"
37 #include "ultima/nuvie/gui/widgets/map_window.h"
38 #include "ultima/nuvie/core/player.h"
39 #include "ultima/nuvie/views/view_manager.h"
40 #include "ultima/nuvie/files/nuvie_bmp_file.h"
41 
42 namespace Ultima {
43 namespace Nuvie {
44 
45 static const byte gump_blocked_tile_data[] = {
46 	170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
47 	170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
48 	170, 170, 170, 170, 64, 178, 55, 54, 54, 55, 178, 64, 170, 170, 170, 170,
49 	170, 170, 170, 64, 55, 168, 64, 170, 170, 64, 168, 55, 64, 170, 170, 170,
50 	170, 170, 64, 55, 64, 170, 170, 170, 170, 170, 12, 12, 55, 64, 170, 170,
51 	170, 170, 178, 130, 170, 170, 170, 170, 170, 12, 12, 12, 168, 178, 170, 170,
52 	170, 170, 55, 64, 170, 170, 170, 170, 12, 12, 12, 170, 64, 55, 170, 170,
53 	170, 170, 54, 170, 170, 170, 170, 12, 12, 12, 170, 170, 170, 54, 170, 170,
54 	170, 170, 54, 170, 170, 170, 12, 12, 12, 170, 170, 170, 170, 54, 170, 170,
55 	170, 170, 55, 64, 170, 12, 12, 12, 170, 170, 170, 170, 64, 55, 170, 170,
56 	170, 170, 178, 168, 12, 12, 12, 170, 170, 170, 170, 170, 168, 178, 170, 170,
57 	170, 170, 64, 55, 12, 12, 170, 170, 170, 170, 170, 64, 55, 64, 170, 170,
58 	170, 170, 170, 64, 55, 168, 64, 170, 170, 64, 168, 55, 64, 170, 170, 170,
59 	170, 170, 170, 170, 64, 178, 55, 54, 54, 55, 178, 64, 170, 170, 170, 170,
60 	170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
61 	170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170
62 };
63 
64 static const byte gump_empty_tile_data[] = {
65 	170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
66 	170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
67 	170, 170, 170, 170, 64, 178, 55, 54, 54, 55, 178, 64, 170, 170, 170, 170,
68 	170, 170, 170, 64, 55, 168, 64, 170, 170, 64, 168, 55, 64, 170, 170, 170,
69 	170, 170, 64, 55, 64, 170, 170, 170, 170, 170, 170, 64, 55, 64, 170, 170,
70 	170, 170, 178, 130, 170, 170, 170, 170, 170, 170, 170, 170, 168, 178, 170, 170,
71 	170, 170, 55, 64, 170, 170, 170, 170, 170, 170, 170, 170, 64, 55, 170, 170,
72 	170, 170, 54, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 54, 170, 170,
73 	170, 170, 54, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 54, 170, 170,
74 	170, 170, 55, 64, 170, 170, 170, 170, 170, 170, 170, 170, 64, 55, 170, 170,
75 	170, 170, 178, 168, 170, 170, 170, 170, 170, 170, 170, 170, 168, 178, 170, 170,
76 	170, 170, 64, 55, 64, 170, 170, 170, 170, 170, 170, 64, 55, 64, 170, 170,
77 	170, 170, 170, 64, 55, 168, 64, 170, 170, 64, 168, 55, 64, 170, 170, 170,
78 	170, 170, 170, 170, 64, 178, 55, 54, 54, 55, 178, 64, 170, 170, 170, 170,
79 	170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
80 	170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170
81 };
82 
DollWidget(Configuration * cfg,GUI_CallBack * callback)83 DollWidget::DollWidget(Configuration *cfg, GUI_CallBack *callback): GUI_Widget(NULL, 0, 0, 0, 0) {
84 	config = cfg;
85 	callback_object = callback;
86 
87 	actor = NULL;
88 	tile_manager = NULL;
89 	selected_obj = NULL;
90 	obj_manager = NULL;
91 	unready_obj = NULL;
92 	empty_tile = NULL;
93 	blocked_tile = NULL;
94 
95 	bg_color = Game::get_game()->get_palette()->get_bg_color();
96 	need_to_free_tiles = false;
97 
98 	use_new_dolls = true;
99 	old_use_new_dolls = true;
100 	actor_doll = NULL;
101 	doll_bg = NULL;
102 	md_doll_shp = NULL;
103 
104 	// Set up hit rects
105 	item_hit_rects[0] = Common::Rect(24, 0,  24 + 16,  0 + 16); // ACTOR_HEAD
106 	item_hit_rects[1] = Common::Rect(0, 8,   0 + 16,  8 + 16);  // ACTOR_NECK
107 	item_hit_rects[2] = Common::Rect(48, 8,  48 + 16,  8 + 16); // ACTOR_BODY
108 	item_hit_rects[3] = Common::Rect(0, 24,  0 + 16, 24 + 16);  // ACTOR_ARM
109 	item_hit_rects[4] = Common::Rect(48, 24, 48 + 16, 24 + 16); // ACTOR_ARM_2
110 	item_hit_rects[5] = Common::Rect(0, 40,  0 + 16, 40 + 16);  // ACTOR_HAND
111 	item_hit_rects[6] = Common::Rect(48, 40, 48 + 16, 40 + 16); // ACTOR_HAND_2
112 	item_hit_rects[7] = Common::Rect(24, 48, 24 + 16, 48 + 16); // ACTOR_FOOT
113 }
114 
~DollWidget()115 DollWidget::~DollWidget() {
116 	if (need_to_free_tiles) {
117 		if (blocked_tile)
118 			delete blocked_tile;
119 		if (empty_tile)
120 			delete empty_tile;
121 	}
122 	free_doll_shapes();
123 }
124 
init(Actor * a,uint16 x,uint16 y,TileManager * tm,ObjManager * om,bool in_portrait_view)125 bool DollWidget::init(Actor *a, uint16 x, uint16 y, TileManager *tm, ObjManager *om, bool in_portrait_view) {
126 	tile_manager = tm;
127 	obj_manager = om;
128 	is_in_portrait_view = in_portrait_view;
129 	if (!Game::get_game()->is_new_style() || is_in_portrait_view) {
130 		switch (Game::get_game()->get_game_type()) {
131 		case NUVIE_GAME_U6 :
132 			blocked_tile = tile_manager->get_tile(TILE_U6_BLOCKED_EQUIP);
133 			empty_tile = tile_manager->get_tile(TILE_U6_EQUIP);
134 			break;
135 
136 		case NUVIE_GAME_SE :
137 			blocked_tile = tile_manager->get_tile(TILE_SE_BLOCKED_EQUIP);
138 			empty_tile = tile_manager->get_tile(TILE_SE_EQUIP);
139 			break;
140 
141 		case NUVIE_GAME_MD :
142 			blocked_tile = tile_manager->get_tile(TILE_MD_BLOCKED_EQUIP); // FIXME: different depending on npc
143 			empty_tile = tile_manager->get_tile(TILE_MD_EQUIP); // FIXME: different depending on npc
144 			break;
145 		}
146 	} else {
147 		blocked_tile = new Tile();
148 		memcpy(&blocked_tile->data, &gump_blocked_tile_data, 256);
149 		empty_tile = new Tile();
150 		memcpy(&empty_tile->data, &gump_empty_tile_data, 256);
151 		need_to_free_tiles = true;
152 	}
153 
154 	GUI_Widget::Init(NULL, x, y, 64, 64);
155 
156 	set_actor(a);
157 	set_accept_mouseclick(true, USE_BUTTON); // accept [double]clicks from button1 (even if double-click disabled we need clicks)
158 
159 	return true;
160 }
161 
free_doll_shapes()162 void DollWidget::free_doll_shapes() {
163 	if (actor_doll) {
164 		SDL_FreeSurface(actor_doll);
165 		actor_doll = NULL;
166 	}
167 	if (doll_bg) {
168 		SDL_FreeSurface(doll_bg);
169 		doll_bg = NULL;
170 	}
171 	if (md_doll_shp) {
172 		delete md_doll_shp;
173 		md_doll_shp = NULL;
174 	}
175 }
176 
setColorKey(Graphics::ManagedSurface * image)177 void DollWidget::setColorKey(Graphics::ManagedSurface *image) {
178 	if (image) {
179 		uint32 bg_color_key = SDL_MapRGB(image->format, 0xf1, 0x0f, 0xc4);
180 		SDL_SetColorKey(image, SDL_TRUE, bg_color_key);
181 	}
182 }
183 
set_actor(Actor * a)184 void DollWidget::set_actor(Actor *a) {
185 	actor = a;
186 	if (!Game::get_game()->is_new_style()) { // needed so it can be changed in the menus
187 		config->value(config_get_game_key(config) + "/use_new_dolls", use_new_dolls, false);
188 		if (old_use_new_dolls != use_new_dolls) {
189 			if (!use_new_dolls)
190 				free_doll_shapes();
191 			old_use_new_dolls = use_new_dolls;
192 		}
193 	}
194 	if (use_new_dolls) {
195 		free_doll_shapes();
196 		if (actor) {
197 			ViewManager *vm = Game::get_game()->get_view_manager();
198 			if (actor->is_avatar())
199 				actor_doll = vm->loadAvatarDollImage(actor_doll, true);
200 			else
201 				actor_doll = vm->loadCustomActorDollImage(actor_doll, actor->get_actor_num(), true);
202 			setColorKey(actor_doll);
203 			if (actor_doll) {
204 				Std::string imagefile;
205 				build_path(vm->getDollDataDirString(), "orig_style", imagefile);
206 				build_path(imagefile, "doll_bg.bmp", imagefile);
207 				NuvieBmpFile bmp;
208 				doll_bg = bmp.getSdlSurface32(imagefile);
209 				if (doll_bg) {
210 					Common::Rect dst(3, 1, 30, 31);
211 					SDL_BlitSurface(actor_doll, NULL, doll_bg, &dst);
212 					setColorKey(doll_bg);
213 				}
214 			}
215 		}
216 	} else if (Game::get_game()->get_game_type() == NUVIE_GAME_MD) {
217 		load_md_doll_shp();
218 	}
219 	Redraw();
220 }
221 
load_md_doll_shp()222 void DollWidget::load_md_doll_shp() {
223 	if (actor == NULL) {
224 		return;
225 	}
226 
227 	if (md_doll_shp)
228 		delete md_doll_shp;
229 
230 	md_doll_shp = new U6Shape();
231 	U6Lib_n file;
232 	Std::string filename;
233 	config_get_path(config, "mdinv.lzc", filename);
234 	file.open(filename, 4, NUVIE_GAME_MD);
235 	uint8 num = actor->get_actor_num() + 1;
236 	if (actor->is_avatar() && Game::get_game()->get_player()->get_gender() == 0) {
237 		num--;
238 	}
239 	unsigned char *temp_buf = file.get_item(num);
240 	if (temp_buf) {
241 		md_doll_shp->load(temp_buf + 8);
242 		free(temp_buf);
243 	} else {
244 		delete md_doll_shp;
245 		md_doll_shp = NULL;
246 	}
247 }
248 
get_item_hit_rect(uint8 location)249 Common::Rect *DollWidget::get_item_hit_rect(uint8 location) {
250 	if (location < 8)
251 		return (&item_hit_rects[location]);
252 	return (NULL);
253 }
254 
255 
Display(bool full_redraw)256 void DollWidget::Display(bool full_redraw) {
257 //if(full_redraw || update_display)
258 // {
259 	update_display = false;
260 
261 	if (actor != NULL)
262 		display_doll();
263 	screen->update(area.left, area.top, area.width(), area.height());
264 //  }
265 
266 }
267 
display_new_doll()268 inline void DollWidget::display_new_doll() {
269 	if (doll_bg) {
270 		Common::Rect dst;
271 		dst = area;
272 		dst.translate(15, 15);
273 		dst.setWidth(33);
274 		dst.setHeight(33);
275 		SDL_BlitSurface(doll_bg, NULL, surface, &dst);
276 	}
277 }
278 
display_old_doll()279 inline void DollWidget::display_old_doll() {
280 	Tile *tile;
281 	uint16 i, j;
282 	int tilenum = 368;
283 	if (Game::get_game()->get_game_type() == NUVIE_GAME_MD) // FIXME: different depending on npc - Also needs npc doll info code
284 		tilenum = 275;
285 	else if (Game::get_game()->get_game_type() == NUVIE_GAME_SE) {
286 		if (actor->get_obj_n() == 310 || actor->get_obj_n() == 311
287 		        || actor->get_obj_n() == 312)
288 			tilenum = 404;
289 		else if (actor->get_obj_n() == 318)
290 			tilenum = 408;
291 		else
292 			tilenum = 400;
293 	}
294 //	 screen->fill(bg_color, area.left, area.top, area.width(), area.height()); // should be taken care of by the main view
295 	for (i = 0; i < 2; i++) {
296 		for (j = 0; j < 2; j++) { // draw doll
297 			tile = tile_manager->get_tile(tilenum + i * 2 + j);
298 			screen->blit(area.left + 16 + j * 16, area.top + 16 + i * 16, tile->data, 8, 16, 16, 16, true);
299 		}
300 	}
301 	if (md_doll_shp) {
302 		uint16 w, h;
303 		md_doll_shp->get_size(&w, &h);
304 		screen->blit(area.left + 20, area.top + 18, md_doll_shp->get_data(), 8, w, h, w, true);
305 	}
306 }
307 
display_doll()308 inline void DollWidget::display_doll() {
309 	if (!Game::get_game()->is_new_style() || is_in_portrait_view) {
310 		if (use_new_dolls)
311 			display_new_doll();
312 		else
313 			display_old_doll();
314 	}
315 	display_readied_object(ACTOR_NECK, area.left, (area.top + 8) + 0 * 16, actor, empty_tile);
316 	display_readied_object(ACTOR_BODY, area.left + 3 * 16, (area.top + 8) + 0 * 16, actor, empty_tile);
317 
318 	display_readied_object(ACTOR_ARM, area.left, (area.top + 8) + 1 * 16, actor, empty_tile);
319 	display_readied_object(ACTOR_ARM_2, area.left + 3 * 16, (area.top + 8) + 1 * 16, actor, actor->is_double_handed_obj_readied() ? blocked_tile : empty_tile);
320 
321 	display_readied_object(ACTOR_HAND, area.left, (area.top + 8) + 2 * 16, actor, empty_tile);
322 	display_readied_object(ACTOR_HAND_2, area.left + 3 * 16, (area.top + 8) + 2 * 16, actor, empty_tile);
323 
324 	display_readied_object(ACTOR_HEAD, area.left + 16 + 8, area.top, actor, empty_tile);
325 	display_readied_object(ACTOR_FOOT, area.left + 16 + 8, area.top + 3 * 16, actor, empty_tile);
326 
327 	return;
328 }
329 
display_readied_object(uint8 location,uint16 x,uint16 y,Actor * theActor,Tile * emptyTile)330 inline void DollWidget::display_readied_object(uint8 location, uint16 x, uint16 y, Actor *theActor, Tile *emptyTile) {
331 	Obj *obj;
332 	Tile *tile;
333 
334 	obj = theActor->inventory_get_readied_object(location);
335 
336 	if (obj)
337 		tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(obj->obj_n) + obj->frame_n);
338 	else
339 		tile = emptyTile;
340 
341 	screen->blit(x, y, tile->data, 8, 16, 16, 16, true);
342 
343 	return;
344 }
345 
346 // when no action is pending the Use button may be used to start dragging,
347 // otherwise it has the same effect as ENTER (using InventoryView's callback)
MouseDown(int x,int y,Shared::MouseButton button)348 GUI_status DollWidget::MouseDown(int x, int y, Shared::MouseButton button) {
349 	Events *event = Game::get_game()->get_event();
350 	uint8 location;
351 	Obj *obj;
352 	x -= area.left;
353 	y -= area.top;
354 
355 	CommandBar *command_bar = Game::get_game()->get_command_bar();
356 	if (button == ACTION_BUTTON && event->get_mode() == MOVE_MODE
357 	        && command_bar->get_selected_action() > 0) { // Exclude attack mode too
358 		if (command_bar->try_selected_action() == false) // start new action
359 			return GUI_YUM; // false if new event doesn't need target
360 	}
361 
362 	if (actor && selected_obj == NULL && (button == USE_BUTTON || button == ACTION_BUTTON || button == DRAG_BUTTON)) {
363 		for (location = 0; location < 8; location++) {
364 			if (HitRect(x, y, item_hit_rects[location])) { // FIXME: duplicating code in InventoryWidget
365 				DEBUG(0, LEVEL_DEBUGGING, "Hit %d\n", location);
366 				obj = actor->inventory_get_readied_object(location);
367 				if (button == ACTION_BUTTON && command_bar->get_selected_action() > 0
368 				        && event->get_mode() == INPUT_MODE) {
369 					if (obj) {
370 						event->select_obj(obj, actor);
371 						return GUI_YUM;
372 					} else {
373 						// has not found a target yet
374 						Game::get_game()->get_scroll()->display_string("nothing!\n");
375 						event->endAction(true);
376 						event->set_mode(MOVE_MODE);
377 					}
378 					return GUI_PASS;
379 				}
380 				if (obj) {
381 
382 					if ((event->get_mode() == MOVE_MODE || event->get_mode() == EQUIP_MODE)
383 					        && button == DRAG_BUTTON)
384 						selected_obj = obj; // start dragging
385 					else // send to View
386 						callback_object->callback(INVSELECT_CB, this, obj);
387 				}
388 				return GUI_YUM;
389 			}
390 		}
391 	}
392 
393 	return GUI_PASS;
394 }
395 
396 // un-ready selected item
MouseUp(int x,int y,Shared::MouseButton button)397 GUI_status DollWidget::MouseUp(int x, int y, Shared::MouseButton button) {
398 	Events *event = Game::get_game()->get_event();
399 
400 // only act now if double-click is disabled
401 	if (selected_obj && !Game::get_game()->get_map_window()->is_doubleclick_enabled()) {
402 		event->unready(selected_obj);
403 		Redraw();
404 		unready_obj = NULL;
405 	} else if (selected_obj) {
406 		wait_for_mouseclick(USE_BUTTON);
407 		unready_obj = selected_obj;
408 	}
409 
410 	selected_obj = NULL;
411 	return GUI_PASS;
412 }
413 
MouseClick(int x,int y,Shared::MouseButton button)414 GUI_status DollWidget::MouseClick(int x, int y, Shared::MouseButton button) {
415 	return (MouseUp(x, y, button));
416 }
417 
MouseMotion(int x,int y,uint8 state)418 GUI_status DollWidget::MouseMotion(int x, int y, uint8 state) {
419 	Tile *tile;
420 
421 	if (selected_obj && !dragging && Game::get_game()->is_dragging_enabled()) {
422 		dragging = true;
423 		tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(selected_obj->obj_n) + selected_obj->frame_n);
424 		return gui_drag_manager->start_drag(this, GUI_DRAG_OBJ, selected_obj, tile->data, 16, 16, 8);
425 	}
426 
427 	return GUI_PASS;
428 }
429 
drag_drop_success(int x,int y,int message,void * data)430 void DollWidget::drag_drop_success(int x, int y, int message, void *data) {
431 	DEBUG(0, LEVEL_DEBUGGING, "DollWidget::drag_drop_success()\n");
432 	dragging = false;
433 // handled by drop target
434 // actor->remove_readied_object(selected_obj);
435 // actor->inventory_remove_obj(selected_obj);
436 	selected_obj = NULL;
437 	Redraw();
438 }
439 
drag_drop_failed(int x,int y,int message,void * data)440 void DollWidget::drag_drop_failed(int x, int y, int message, void *data) {
441 	DEBUG(0, LEVEL_DEBUGGING, "DollWidget::drag_drop_failed()\n");
442 	dragging = false;
443 	selected_obj = NULL;
444 }
445 
drag_accept_drop(int x,int y,int message,void * data)446 bool DollWidget::drag_accept_drop(int x, int y, int message, void *data) {
447 	DEBUG(0, LEVEL_DEBUGGING, "DollWidget::drag_accept_drop()\n");
448 	if (message == GUI_DRAG_OBJ) {
449 		Obj *obj = (Obj *)data;
450 		if (obj->is_readied() && obj->get_actor_holding_obj() == actor) {
451 			// FIXME: need to detect ready location so player can switch hands
452 			DEBUG(0, LEVEL_WARNING, "DollWidget: Object already equipped!\n");
453 			return false;
454 		}
455 		if (obj->get_actor_holding_obj() != actor) {
456 			if (obj->is_in_inventory()) {
457 				Events *event = Game::get_game()->get_event();
458 				event->display_move_text(actor, obj);
459 				if (event->can_move_obj_between_actors(obj, obj->get_actor_holding_obj(), actor, false)) {
460 					Game::get_game()->get_player()->subtract_movement_points(3);
461 					DEBUG(0, LEVEL_DEBUGGING, "Drop Accepted\n");
462 					return true;
463 				}
464 			}
465 		}
466 		if (obj->get_actor_holding_obj() == actor
467 		        || Game::get_game()->get_map_window()->can_get_obj(actor, obj)) {
468 			DEBUG(0, LEVEL_DEBUGGING, "Drop Accepted\n");
469 			return true;
470 		} else {
471 			DEBUG(0, LEVEL_WARNING, "DollWidget: Must be holding object!\n");
472 			return false;
473 		}
474 	}
475 
476 	DEBUG(0, LEVEL_DEBUGGING, "Drop Refused\n");
477 	return false;
478 }
479 
drag_perform_drop(int x,int y,int message,void * data)480 void DollWidget::drag_perform_drop(int x, int y, int message, void *data) {
481 	DEBUG(0, LEVEL_DEBUGGING, "DollWidget::drag_perform_drop()\n");
482 	Obj *obj;
483 
484 	x -= area.left;
485 	y -= area.top;
486 
487 	if (message == GUI_DRAG_OBJ) {
488 		DEBUG(0, LEVEL_DEBUGGING, "Ready item.\n");
489 		obj = (Obj *)data;
490 
491 		bool can_equip = true;
492 		if (!obj->is_in_inventory()) { // get
493 			// event->newAction(GET_MODE);
494 			Game::get_game()->get_scroll()->display_string("Get-");
495 			can_equip = Game::get_game()->get_event()->perform_get(obj, NULL, actor);
496 //       if(!can_equip)
497 //       {
498 //        assert(!(obj->status & OBJ_STATUS_IN_CONTAINER));
499 //        obj_manager->add_obj(obj); // add back to map
500 //       }
501 		} else
502 			obj_manager->moveto_inventory(obj, actor);
503 		if (can_equip) { // ready
504 			assert(!obj->is_readied());
505 			Game::get_game()->get_event()->ready(obj, actor);
506 		}
507 		Redraw();
508 	}
509 
510 	return;
511 }
512 
drag_draw(int x,int y,int message,void * data)513 void DollWidget::drag_draw(int x, int y, int message, void *data) {
514 	Tile *tile;
515 
516 	if (!selected_obj)
517 		return;
518 
519 	tile = tile_manager->get_tile(obj_manager->get_obj_tile_num(selected_obj) + selected_obj->frame_n);
520 
521 	int nx = x - 8;
522 	int ny = y - 8;
523 
524 	if (nx + 16 >= screen->get_width())
525 		nx = screen->get_width() - 17;
526 	else if (nx < 0)
527 		nx = 0;
528 
529 	if (ny + 16 >= screen->get_height())
530 		ny = screen->get_height() - 17;
531 	else if (ny < 0)
532 		ny = 0;
533 
534 	screen->blit(nx, ny, tile->data, 8, 16, 16, 16, true);
535 	screen->update(nx, ny, 16, 16);
536 }
537 
538 
539 /* Use object.
540  */
MouseDouble(int x,int y,Shared::MouseButton button)541 GUI_status DollWidget::MouseDouble(int x, int y, Shared::MouseButton button) {
542 	// we have to check if double-clicks are allowed here, since we use single-clicks
543 	if (!Game::get_game()->get_map_window()->is_doubleclick_enabled())
544 		return (GUI_PASS);
545 	Events *event = Game::get_game()->get_event();
546 	Obj *obj = selected_obj;
547 
548 	unready_obj = NULL;
549 	selected_obj = NULL;
550 
551 	if (!(actor && obj))
552 		return (GUI_YUM);
553 
554 	if (event->newAction(USE_MODE))
555 		event->select_obj(obj);
556 	return (GUI_YUM);
557 }
558 
559 // change container, ready/unready object, activate arrows
MouseDelayed(int x,int y,Shared::MouseButton button)560 GUI_status DollWidget::MouseDelayed(int x, int y, Shared::MouseButton button) {
561 	Events *event = Game::get_game()->get_event();
562 	if (unready_obj) {
563 		event->unready(unready_obj);
564 		Redraw();
565 		unready_obj = NULL;
566 	}
567 	return GUI_PASS;
568 }
569 
570 } // End of namespace Nuvie
571 } // End of namespace Ultima
572