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 "ultima/ultima8/gumps/weasel_gump.h"
24 #include "ultima/ultima8/gumps/weasel_dat.h"
25 #include "ultima/ultima8/games/game_data.h"
26 #include "ultima/ultima8/graphics/gump_shape_archive.h"
27 #include "ultima/ultima8/graphics/main_shape_archive.h"
28 #include "ultima/ultima8/graphics/shape.h"
29 #include "ultima/ultima8/graphics/shape_frame.h"
30 #include "ultima/ultima8/ultima8.h"
31 #include "ultima/ultima8/kernel/mouse.h"
32 #include "ultima/ultima8/gumps/widgets/button_widget.h"
33 #include "ultima/ultima8/gumps/widgets/text_widget.h"
34 #include "ultima/ultima8/gumps/movie_gump.h"
35 #include "ultima/ultima8/world/actors/main_actor.h"
36 #include "ultima/ultima8/audio/audio_process.h"
37 #include "ultima/ultima8/world/get_object.h"
38 #include "ultima/ultima8/world/item_factory.h"
39 #include "ultima/ultima8/filesys/file_system.h"
40 
41 namespace Ultima {
42 namespace Ultima8 {
43 
44 DEFINE_RUNTIME_CLASSTYPE_CODE(WeaselGump)
45 
46 static const uint16 WEASEL_CANT_BUY_SFXNO = 0xb0;
47 static const int WEASEL_FONT = 6;
48 static const int WEASEL_SHAPE_TOP = 22;
49 
50 enum WeaselUiElements {
51 	kBtnLeft = 0,
52 	kBtnBlank = 1,
53 	kBtnRight = 2,
54 	kBtnYes = 3,
55 	kBtnNo = 4,
56 	kBtnBuy = 5,
57 	kBtnAmmo = 6,
58 	kBtnWeapons = 7,
59 	kBtnExit = 8,
60 	kTxtCredits = 9,
61 	kIconItem = 10,
62 	kTxtItemName = 11,
63 	kTxtItemCost = 12,
64 	kTxtItemPurch = 13,
65 	kTxtItemOwned = 14,
66 	kTxtQuestion = 15
67 };
68 // Coords and shapes for above list of buttons
69 static const int WEASEL_BTN_X[] = { 14,  76, 138,  18, 113,  20,  19,  19,  44};
70 static const int WEASEL_BTN_Y[] = {213, 213, 213, 237, 237, 280, 319, 319, 368};
71 static const int WEASEL_BTN_SHAPES[] = {13, 26, 14, 16, 15, 28, 27, 83, 29};
72 
73 static const char *FIRST_INTRO_MOVIE = "17A";
74 static const char *INTRO_MOVIES[] = {"18A", "18B", "18C"};
75 static const char *BUYMORE_MOVIES[] = {"21A", "21B"};
76 static const char *CONFIRM_BUY_MOVIES[] = {"21A", "21B"};
77 static const char *CANCELLED_PURCHASE_MOVIES[] = {"19C", "19D"};
78 static const char *COMPLETED_PURCHASE_MOVIES[] = {"21C", "21D"};
79 static const char *INSUFFICIENT_FUND_MOVIES[] = {"20C", "20D"};
80 
81 
82 namespace {
83 // A small container gump that doesn't do anything except pass notifications to the parent
84 class WeaselUIContainerGump : public Gump {
ChildNotify(Gump * child,uint32 message)85 	void ChildNotify(Gump *child, uint32 message) override {
86 		_parent->ChildNotify(child, message);
87 	}
88 };
89 
_closeIfExists(Gump * gump)90 static void _closeIfExists(Gump *gump) {
91 	if (gump)
92 		gump->Close();
93 }
94 
_getRandomMovie(const char ** movies,int nmovies)95 static const char *_getRandomMovie(const char **movies, int nmovies) {
96 	int offset = Ultima8Engine::get_instance()->getRandomNumber(nmovies - 1);
97 	return movies[offset];
98 }
99 }
100 
101 bool WeaselGump::_playedIntroMovie = false;
102 
WeaselGump(uint16 level)103 WeaselGump::WeaselGump(uint16 level)
104 	: ModalGump(0, 0, 640, 480), _credits(0), _level(level),
105 	  _state(kWeaselStart), _curItem(0), _ammoMode(false), _curItemCost(1),
106 	  _curItemShape(0), _ui(nullptr), _movie(nullptr), _weaselDat(nullptr) {
107 	Mouse *mouse = Mouse::get_instance();
108 	mouse->pushMouseCursor();
109 	mouse->setMouseCursor(Mouse::MOUSE_HAND);
110 }
111 
~WeaselGump()112 WeaselGump::~WeaselGump() {
113 }
114 
115 
Close(bool no_del)116 void WeaselGump::Close(bool no_del) {
117 	Mouse *mouse = Mouse::get_instance();
118 	mouse->popMouseCursor();
119 	ModalGump::Close(no_del);
120 }
121 
InitGump(Gump * newparent,bool take_focus)122 void WeaselGump::InitGump(Gump *newparent, bool take_focus) {
123 	ModalGump::InitGump(newparent, take_focus);
124 
125 	GumpShapeArchive *shapeArchive = GameData::get_instance()->getGumps();
126 
127 	const Shape *top = shapeArchive->getShape(WEASEL_SHAPE_TOP);
128 	const Shape *midhi = shapeArchive->getShape(WEASEL_SHAPE_TOP + 1);
129 	const Shape *midlo = shapeArchive->getShape(WEASEL_SHAPE_TOP + 2);
130 	const Shape *bot = shapeArchive->getShape(WEASEL_SHAPE_TOP + 3);
131 
132 	if (!top || !midhi || !midlo || !bot) {
133 		error("Couldn't load shapes for weasel");
134 		return;
135 	}
136 
137 	const ShapeFrame *tFrame = top->getFrame(0);
138 	const ShapeFrame *mhFrame = midhi->getFrame(0);
139 	const ShapeFrame *mlFrame = midlo->getFrame(0);
140 	const ShapeFrame *bFrame = bot->getFrame(0);
141 	if (!tFrame || !mhFrame || !mlFrame || !bFrame) {
142 		error("Couldn't load shape frames for weasel");
143 		return;
144 	}
145 
146 	_ui = new WeaselUIContainerGump();
147 	_ui->SetDims(Rect(0, 0, mhFrame->_width,
148 					  tFrame->_height + mhFrame->_height + mlFrame->_height + bFrame->_height));
149 	_ui->InitGump(this, false);
150 	_ui->setRelativePosition(CENTER);
151 
152 	Gump *tGump = new Gump(3, 0, tFrame->_width, tFrame->_height);
153 	tGump->SetShape(top, 0);
154 	tGump->InitGump(_ui, false);
155 	Gump *mhGump = new Gump(0, tFrame->_height, mhFrame->_width, mhFrame->_height);
156 	mhGump->SetShape(midhi, 0);
157 	mhGump->InitGump(_ui, false);
158 	Gump *mlGump = new Gump(5, tFrame->_height + mhFrame->_height, mlFrame->_width, mlFrame->_height);
159 	mlGump->SetShape(midlo, 0);
160 	mlGump->InitGump(_ui, false);
161 	Gump *bGump = new Gump(9, tFrame->_height + mhFrame->_height + mlFrame->_height, bFrame->_width, bFrame->_height);
162 	bGump->SetShape(bot, 0);
163 	bGump->InitGump(_ui, false);
164 
165 	for (int i = 0; i < ARRAYSIZE(WEASEL_BTN_X); i++) {
166 		uint32 buttonShapeNum = WEASEL_BTN_SHAPES[i];
167 		const Shape *buttonShape = shapeArchive->getShape(buttonShapeNum);
168 		if (!buttonShape) {
169 			error("Couldn't load shape for weasel button %d", i);
170 			return;
171 		}
172 
173 		const ShapeFrame *buttonFrame = buttonShape->getFrame(0);
174 		if (!buttonFrame || buttonShape->frameCount() != 2) {
175 			error("Couldn't load shape frame for weasel button %d", i);
176 			return;
177 		}
178 
179 		FrameID frame_up(GameData::GUMPS, buttonShapeNum, 0);
180 		FrameID frame_down(GameData::GUMPS, buttonShapeNum, 1);
181 		Gump *widget = new ButtonWidget(WEASEL_BTN_X[i], WEASEL_BTN_Y[i], frame_up, frame_down, false);
182 		widget->InitGump(_ui, false);
183 		widget->SetIndex(i);
184 		// some buttons start hidden, the browsingMode() call below does that.
185 	}
186 
187 	MainActor *av = getMainActor();
188 	assert(av);
189 	Item *item = av->getFirstItemWithShape(0x4ed, true);
190 	if (item)
191 		_credits = item->getQuality();
192 
193 	_weaselDat = GameData::get_instance()->getWeaselDat(_level);
194 	if (!_weaselDat || _weaselDat->getNumItems() == 0)
195 		Close();
196 }
197 
playMovie(const Std::string & filename)198 Gump *WeaselGump::playMovie(const Std::string &filename) {
199 	MovieGump *gump = MovieGump::CruMovieViewer(filename, 600, 450, nullptr, this, 0);
200 	if (!gump) {
201 		warning("Couldn't load flic %s", filename.c_str());
202 		return nullptr;
203 	}
204 	gump->CreateNotifier();
205 	return gump;
206 }
207 
run()208 void WeaselGump::run() {
209 	ModalGump::run();
210 	// Don't do much while a movie is playing.
211 	if (_movie)
212 		return;
213 	_ui->UnhideGump();
214 	switch (_state) {
215 		case kWeaselStart:
216 			_state = kWeaselShowIntro;
217 			break;
218 		case kWeaselShowIntro: {
219 			if (_level == 2 && !_playedIntroMovie) {
220 				_movie = playMovie(FIRST_INTRO_MOVIE);
221 				_playedIntroMovie = true;
222 			} else {
223 				_movie = playMovie(_getRandomMovie(INTRO_MOVIES, ARRAYSIZE(INTRO_MOVIES)));
224 			}
225 			_state = kWeaselBrowsing;
226 			browsingMode(true);
227 			break;
228 		}
229 		case kWeaselCheckBuyMoreMovie:
230 			_movie = playMovie(_getRandomMovie(BUYMORE_MOVIES, ARRAYSIZE(BUYMORE_MOVIES)));
231 			_state = kWeaselCheckBuyMoreText;
232 			break;
233 		case kWeaselCheckBuyMoreText:
234 			checkBuyMore();
235 			break;
236 		case kWeaselClosing:
237 			Close();
238 			break;
239 		case kWeaselConfirmPurchaseMovie:
240 			_movie = playMovie(_getRandomMovie(CONFIRM_BUY_MOVIES, ARRAYSIZE(CONFIRM_BUY_MOVIES)));
241 			_state = kWeaselConfirmPurchaseText;
242 			break;
243 		case kWeaselConfirmPurchaseText:
244 			confirmPurchase();
245 			break;
246 		case kWeaselCancelledPurchaseMovie:
247 			browsingMode(true);
248 			_movie = playMovie(_getRandomMovie(CANCELLED_PURCHASE_MOVIES, ARRAYSIZE(CANCELLED_PURCHASE_MOVIES)));
249 			_state = kWeaselBrowsing;
250 			break;
251 		case kWeaselCompletedPurchase:
252 			_movie = playMovie(_getRandomMovie(COMPLETED_PURCHASE_MOVIES, ARRAYSIZE(COMPLETED_PURCHASE_MOVIES)));
253 			_state = kWeaselCheckBuyMoreText;
254 			break;
255 		case kWeaselInsufficientFunds:
256 			// TODO: how does it get to this situation?
257 			_movie = playMovie(_getRandomMovie(INSUFFICIENT_FUND_MOVIES, ARRAYSIZE(INSUFFICIENT_FUND_MOVIES)));
258 			break;
259 		case kWeaselBrowsing:
260 			_ui->UnhideGump();
261 		default:
262 			break;
263 	}
264 	if (_movie) {
265 		_ui->HideGump();
266 	}
267 }
268 
PaintThis(RenderSurface * surf,int32 lerp_factor,bool scaled)269 void WeaselGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
270 	Gump::PaintThis(surf, lerp_factor, scaled);
271 }
272 
OnKeyDown(int key,int mod)273 bool WeaselGump::OnKeyDown(int key, int mod) {
274 	if (Gump::OnKeyDown(key, mod)) return true;
275 
276 	// TODO: support more keyboard input
277 	switch (key) {
278 		case Common::KEYCODE_LEFT:
279 			if (_state == kWeaselBrowsing)
280 				prevItem();
281 			break;
282 		case Common::KEYCODE_RIGHT:
283 			if (_state == kWeaselBrowsing)
284 				nextItem();
285 			break;
286 	}
287 
288 	return true;
289 }
290 
ChildNotify(Gump * child,uint32 message)291 void WeaselGump::ChildNotify(Gump *child, uint32 message) {
292 	ButtonWidget *buttonWidget = dynamic_cast<ButtonWidget *>(child);
293 	MovieGump *movieGump = dynamic_cast<MovieGump *>(child);
294 	if (buttonWidget && message == ButtonWidget::BUTTON_CLICK) {
295 		onButtonClick(child->GetIndex());
296 	} else if (movieGump && message == Gump::GUMP_CLOSING) {
297 		// Movie has finished.
298 		_movie = nullptr;
299 	}
300 }
301 
onButtonClick(int entry)302 void WeaselGump::onButtonClick(int entry) {
303 	switch (entry) {
304 	case kBtnWeapons:
305 		_ammoMode = false;
306 		updateForAmmoMode();
307 		break;
308 	case kBtnAmmo:
309 		_ammoMode = true;
310 		updateForAmmoMode();
311 		break;
312 	case kBtnLeft:
313 		prevItem();
314 		break;
315 	case kBtnRight:
316 		nextItem();
317 		break;
318 	case kBtnBuy:
319 		buyItem();
320 		break;
321 	case kBtnExit:
322 		checkClose();
323 		break;
324 	case kBtnYes:
325 		if (_state == kWeaselConfirmPurchaseText)
326 			completePurchase();
327 		else if (_state == kWeaselCheckBuyMoreText)
328 			browsingMode(true);
329 		break;
330 	case kBtnNo:
331 		if (_state == kWeaselConfirmPurchaseText)
332 			abortPurchase();
333 		else if (_state == kWeaselCheckBuyMoreText)
334 			Close();
335 		break;
336 	case kBtnBlank:
337 	default:
338 		break;
339 	}
340 }
341 
updateForAmmoMode()342 void WeaselGump::updateForAmmoMode() {
343 	Gump *ammobtn = _ui->FindGump(&FindByIndex<kBtnAmmo>);
344 	Gump *wpnbtn = _ui->FindGump(&FindByIndex<kBtnWeapons>);
345 	assert(ammobtn && wpnbtn);
346 	ammobtn->SetVisibility(!_ammoMode);
347 	wpnbtn->SetVisibility(_ammoMode);
348 	_curItem = 0;
349 
350 	_weaselDat = GameData::get_instance()->getWeaselDat(_ammoMode ? 1 : _level);
351 	if (!_weaselDat || _weaselDat->getNumItems() == 0)
352 		Close();
353 
354 	updateItemDisplay();
355 }
356 
357 
prevItem()358 void WeaselGump::prevItem() {
359 	_curItem--;
360 	if (_curItem < 0)
361 		_curItem = _weaselDat->getNumItems() - 1;
362 	updateItemDisplay();
363 }
364 
nextItem()365 void WeaselGump::nextItem() {
366 	_curItem++;
367 	if (_curItem >= _weaselDat->getNumItems())
368 		_curItem = 0;
369 	updateItemDisplay();
370 }
371 
buyItem()372 void WeaselGump::buyItem() {
373 	if (_curItemCost < _credits) {
374 		_purchases.push_back(_curItemShape);
375 		_credits -= _curItemCost;
376 	} else {
377 		AudioProcess::get_instance()->playSFX(WEASEL_CANT_BUY_SFXNO, 0x80, 0, 0);
378 	}
379 	updateItemDisplay();
380 }
381 
confirmPurchase()382 void WeaselGump::confirmPurchase() {
383 	static const char *confirm = "Are you sure you want to buy this?";
384 	setYesNoQuestion(confirm);
385 }
386 
checkClose()387 void WeaselGump::checkClose() {
388 	if (_purchases.size()) {
389 		_state = kWeaselConfirmPurchaseMovie;
390 	} else {
391 		Close();
392 	}
393 }
394 
completePurchase()395 void WeaselGump::completePurchase() {
396 	assert(_state == kWeaselConfirmPurchaseText);
397 	MainActor *av = getMainActor();
398 	uint16 mapno = av->getMapNum();
399 	assert(av);
400 	Item *item = av->getFirstItemWithShape(0x4ed, true);
401 	if (item)
402 		item->setQuality(_credits);
403 	for (Std::vector<uint16>::const_iterator iter = _purchases.begin();
404 		 iter != _purchases.end(); iter++) {
405 		Item *newitem = ItemFactory::createItem(*iter, 0, 0, 0, 0, mapno, 0, true);
406 		av->addItemCru(newitem, false);
407 	}
408 	_state = kWeaselCompletedPurchase;
409 }
410 
checkBuyMore()411 void WeaselGump::checkBuyMore() {
412 	static const char *buymore = "Do you want anything else?";
413 	setYesNoQuestion(buymore);
414 }
415 
setYesNoQuestion(const Std::string & msg)416 void WeaselGump::setYesNoQuestion(const Std::string &msg) {
417 	browsingMode(false);
418 	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtQuestion>));
419 	TextWidget *textWidget = new TextWidget(30, 100, msg, true, WEASEL_FONT, 150);
420 	textWidget->InitGump(_ui);
421 	textWidget->SetIndex(kTxtQuestion);
422 }
423 
browsingMode(bool browsing)424 void WeaselGump::browsingMode(bool browsing) {
425 	_ui->UnhideGump();
426 
427 	updateForAmmoMode();
428 	updateItemDisplay();
429 
430 	// Note: all these searches are not super effieient but it's
431 	// not a time-sensitive function and the search is relatively short
432 	Gump *yesbtn = _ui->FindGump(&FindByIndex<kBtnYes>);
433 	Gump *nobtn = _ui->FindGump(&FindByIndex<kBtnNo>);
434 	Gump *qtxt = _ui->FindGump(&FindByIndex<kTxtQuestion>);
435 
436 	Gump *buybtn = _ui->FindGump(&FindByIndex<kBtnBuy>);
437 	Gump *wpnbtn = _ui->FindGump(&FindByIndex<kBtnWeapons>);
438 	Gump *ammobtn = _ui->FindGump(&FindByIndex<kBtnAmmo>);
439 	Gump *exitbtn = _ui->FindGump(&FindByIndex<kBtnExit>);
440 	Gump *blankbtn = _ui->FindGump(&FindByIndex<kBtnBlank>);
441 	Gump *leftbtn = _ui->FindGump(&FindByIndex<kBtnLeft>);
442 	Gump *rightbtn = _ui->FindGump(&FindByIndex<kBtnRight>);
443 	Gump *credtxt = _ui->FindGump(&FindByIndex<kTxtCredits>);
444 	Gump *nametxt = _ui->FindGump(&FindByIndex<kTxtItemName>);
445 	Gump *costtxt = _ui->FindGump(&FindByIndex<kTxtItemCost>);
446 	Gump *purchtxt = _ui->FindGump(&FindByIndex<kTxtItemPurch>);
447 	Gump *ownedtxt = _ui->FindGump(&FindByIndex<kTxtItemOwned>);
448 	Gump *icon = _ui->FindGump(&FindByIndex<kIconItem>);
449 
450 	yesbtn->SetVisibility(!browsing);
451 	nobtn->SetVisibility(!browsing);
452 	if (qtxt)
453 		qtxt->SetVisibility(!browsing);
454 
455 	buybtn->SetVisibility(browsing);
456 	wpnbtn->SetVisibility(browsing && _ammoMode);
457 	ammobtn->SetVisibility(browsing && !_ammoMode);
458 	exitbtn->SetVisibility(browsing);
459 	blankbtn->SetVisibility(browsing);
460 	leftbtn->SetVisibility(browsing);
461 	rightbtn->SetVisibility(browsing);
462 	credtxt->SetVisibility(browsing);
463 	nametxt->SetVisibility(browsing);
464 	costtxt->SetVisibility(browsing);
465 	purchtxt->SetVisibility(browsing);
466 	ownedtxt->SetVisibility(browsing);
467 	icon->SetVisibility(browsing);
468 }
469 
abortPurchase()470 void WeaselGump::abortPurchase() {
471 	assert(_state == kWeaselConfirmPurchaseText);
472 	_state = kWeaselCancelledPurchaseMovie;
473 	_purchases.clear();
474 }
475 
purchasedCount(uint16 shape) const476 int WeaselGump::purchasedCount(uint16 shape) const {
477 	int count = 0;
478 	for (Std::vector<uint16>::const_iterator iter = _purchases.begin();
479 		 iter != _purchases.end(); iter++) {
480 		 if (*iter == shape)
481 			 count++;
482 	}
483 	return count;
484 }
485 
updateItemDisplay()486 void WeaselGump::updateItemDisplay() {
487 	const Std::vector<WeaselDat::WeaselEntry> &items = _weaselDat->getItems();
488 
489 	// should always have the item..
490 	assert(_curItem < (int)items.size());
491 
492 	_curItemCost = items[_curItem]._cost;
493 	_curItemShape = items[_curItem]._shapeNo;
494 
495 	const ShapeInfo *shapeinfo = GameData::get_instance()->getMainShapes()->getShapeInfo(_curItemShape);
496 	if (!shapeinfo || !shapeinfo->_weaponInfo) {
497 		warning("Weasel: no info for shape %d", _curItemShape);
498 		return;
499 	}
500 	const Shape *shape = GameData::get_instance()->getGumps()->getShape(shapeinfo->_weaponInfo->_displayGumpShape);
501 
502 	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtCredits>));
503 	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemName>));
504 	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemCost>));
505 	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemPurch>));
506 	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemOwned>));
507 	_closeIfExists(_ui->FindGump(&FindByIndex<kIconItem>));
508 
509 	Std::string credstr = Std::string::format("Credits:%d", _credits);
510 	TextWidget *textWidget = new TextWidget(30, 57, credstr, true, WEASEL_FONT);
511 	textWidget->InitGump(_ui);
512 	textWidget->SetIndex(kTxtCredits);
513 
514 	const ShapeFrame *frame = shape->getFrame(shapeinfo->_weaponInfo->_displayGumpFrame);
515 	Gump *icon = new Gump(105 - frame->_xoff, 120 - frame->_yoff, 200, 200);
516 	icon->SetShape(shape, shapeinfo->_weaponInfo->_displayGumpFrame);
517 	icon->UpdateDimsFromShape();
518 	icon->setRelativePosition(CENTER);
519 	icon->InitGump(_ui, false);
520 	icon->SetIndex(kIconItem);
521 
522 	Std::string coststr = Std::string::format("Cost:%d", _curItemCost);
523 	Std::string purchstr = Std::string::format("Purchased:%02d", purchasedCount(_curItemShape));
524 
525 	MainActor *av = getMainActor();
526 	const Item *item = av->getFirstItemWithShape(_curItemShape, true);
527 	int count = 0;
528 	if (item) {
529 		if (shapeinfo->_family == ShapeInfo::SF_CRUWEAPON) {
530 			count = 1;
531 		} else {
532 			count = item->getQuality();
533 		}
534 	}
535 	Std::string ownedstr = Std::string::format("Owned:%02d", count);
536 
537 	TextWidget *nametxt = new TextWidget(27, 161, shapeinfo->_weaponInfo->_name, true, WEASEL_FONT);
538 	nametxt->InitGump(_ui, false);
539 	nametxt->SetIndex(kTxtItemName);
540 	TextWidget *costtxt = new TextWidget(27, 171, coststr, true, WEASEL_FONT);
541 	costtxt->InitGump(_ui, false);
542 	costtxt->SetIndex(kTxtItemCost);
543 	TextWidget *purchtxt = new TextWidget(27, 181, purchstr, true, WEASEL_FONT);
544 	purchtxt->InitGump(_ui, false);
545 	purchtxt->SetIndex(kTxtItemPurch);
546 	TextWidget *ownedtxt = new TextWidget(27, 191, ownedstr, true, WEASEL_FONT);
547 	ownedtxt->InitGump(_ui, false);
548 	ownedtxt->SetIndex(kTxtItemOwned);
549 }
550 
OnTextInput(int unicode)551 bool WeaselGump::OnTextInput(int unicode) {
552 	if (Gump::OnTextInput(unicode)) return true;
553 
554 	return true;
555 }
556 
557 //static
I_showWeaselGump(const uint8 * args,unsigned int)558 uint32 WeaselGump::I_showWeaselGump(const uint8 *args, unsigned int /*argsize*/) {
559 	ARG_UINT16(level);
560 
561 	WeaselGump *gump = new WeaselGump(level);
562 	gump->InitGump(0);
563 	gump->setRelativePosition(CENTER);
564 
565 	return 0;
566 }
567 
568 } // End of namespace Ultima8
569 } // End of namespace Ultima
570