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