00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022
00023 #include <SDL_timer.h>
00024 #include "actors.h"
00025 #include "cheat.h"
00026 #include "gamewin.h"
00027 #include "Gump_button.h"
00028 #include "items.h"
00029 #include "mouse.h"
00030 #include "Spellbook_gump.h"
00031 #include "spellbook.h"
00032 #include "game.h"
00033 #include "Gump_manager.h"
00034
00035 #ifndef ALPHA_LINUX_CXX
00036 # include <cstdio>
00037 #endif
00038
00039
00040
00041 const int REAGENTS = 842;
00042
00043
00044
00045
00046 #define SPELLBOOK (GAME_BG ? 43 : 38)
00047 #define SPELLS (GAME_BG ? 33 : 28) // First group of 9 spells.
00048 #define TURNINGPAGE (GAME_BG ? 41 : 36) // Animation?? (4 frames).
00049 #define BOOKMARK (GAME_BG ? 42 : 37) // Red ribbon, 5 frames.
00050 #define LEFTPAGE (GAME_BG ? 44 : 39) // At top-left of left page.
00051 #define RIGHTPAGE (GAME_BG ? 45 : 40) // At top-right of right page.
00052 #define SCROLLSPELLS 66 // First group of scroll spells (SI).
00053
00054
00055
00056
00057 #define CIRCLE (GAME_BG ? 0x545 : 0x551)
00058 #define CIRCLENUM (GAME_BG ? 0x545 : 0x552)
00059
00060
00061
00062
00063 inline int Get_circle(int spell)
00064 { return spell/8; }
00065
00066
00067
00068
00069
00070 inline int Get_spell_gump_shape
00071 (
00072 int spell,
00073 int& shape,
00074 int& frame
00075 )
00076 {
00077 if (spell < 0 || spell >= 0x48)
00078 return 0;
00079 shape = spell%8;
00080 frame = spell/8;
00081 return (1);
00082 }
00083
00084
00085
00086
00087 class Page_button : public Gump_button
00088 {
00089 int leftright;
00090 public:
00091 Page_button(Gump *par, int px, int py, int lr)
00092 : Gump_button(par, lr ? RIGHTPAGE : LEFTPAGE, px, py),
00093 leftright(lr)
00094 { }
00095
00096 virtual void activate();
00097 virtual void push() {}
00098 virtual void unpush() {}
00099 };
00100
00101
00102
00103
00104
00105 void Page_button::activate
00106 (
00107 )
00108 {
00109 ((Spellbook_gump *) parent)->change_page(leftright ? 1 : -1);
00110 }
00111
00112
00113
00114
00115 class Bookmark_button : public Gump_button
00116 {
00117 public:
00118 Bookmark_button(Gump *par)
00119 : Gump_button(par, BOOKMARK, 0, 0)
00120 { }
00121 void set();
00122
00123 virtual void activate();
00124 virtual void push() {}
00125 virtual void unpush() {}
00126 };
00127
00128
00129
00130
00131
00132 void Bookmark_button::set
00133 (
00134 )
00135 {
00136 Spellbook_gump *sgump = (Spellbook_gump *) parent;
00137 Rectangle& object_area = sgump->object_area;
00138 int spwidth = sgump->spwidth;
00139 Spellbook_object *book = sgump->book;
00140 int page = sgump->page;
00141 int bmpage = book->bookmark/8;
00142 int s = book->bookmark%8;
00143
00144 bool left = bmpage == page ? (s < 4) : bmpage < page;
00145
00146 x = left ? object_area.x + spwidth/2
00147 : object_area.x + object_area.w - spwidth/2 - 2;
00148 Shape_frame *bshape = get_shape();
00149 x += bshape->get_xleft();
00150 y = object_area.y - 14 + bshape->get_yabove();
00151 set_frame(bmpage == page ? (1 + s%4) : 0);
00152 }
00153
00154
00155
00156
00157
00158 void Bookmark_button::activate
00159 (
00160 )
00161 {
00162
00163 Spellbook_gump *sgump = (Spellbook_gump *) parent;
00164 int bmpage = sgump->book->bookmark/8;
00165
00166 if (bmpage >= 0 && bmpage != sgump->page)
00167 sgump->change_page(bmpage - sgump->page);
00168 }
00169
00170
00171
00172
00173 class Spell_button : public Gump_button
00174 {
00175 int spell;
00176 public:
00177 Spell_button(Gump *par, int px, int py, int sp, int shnum, int frnum)
00178 : Gump_button(par, shnum, px, py), spell(sp)
00179 {
00180 set_frame(frnum);
00181 }
00182
00183 virtual void activate();
00184 virtual void double_clicked(int x, int y);
00185 virtual void push() { }
00186 virtual void unpush() { }
00187 };
00188
00189
00190
00191
00192
00193 void Spell_button::activate
00194 (
00195 )
00196 {
00197 ((Spelltype_gump *) parent)->select_spell(spell);
00198 }
00199
00200
00201
00202
00203
00204 void Spell_button::double_clicked
00205 (
00206 int x, int y
00207 )
00208 {
00209 ((Spelltype_gump *) parent)->do_spell(spell);
00210 }
00211
00212
00213
00214
00215
00216 void Spellbook_gump::set_avail
00217 (
00218 )
00219 {
00220 int i;
00221 for (i = 0; i < 9*8; i++)
00222 avail[i] = 0;
00223 if (book_owner == book)
00224 return;
00225 int reagent_counts[NREAGENTS];
00226 int r;
00227 for (r = 0; r < NREAGENTS; r++)
00228 reagent_counts[r] = book_owner->count_objects(
00229 REAGENTS, c_any_qual, r);
00230 bool has_ring = book->has_ring(gwin->get_main_actor());
00231 for (i = 0; i < 9*8; i++)
00232 {
00233 if (has_ring)
00234 {
00235 avail[i] = 10000;
00236 continue;
00237 }
00238 avail[i] = 10000;
00239 unsigned short flags = book->reagents[i];
00240
00241 for (r = 0; flags; r++, flags = flags >> 1)
00242
00243 if ((flags&1) && reagent_counts[r] < avail[i])
00244 avail[i] = reagent_counts[r];
00245 }
00246 }
00247
00248
00249
00250
00251
00252 Spellbook_gump::Spellbook_gump
00253 (
00254 Spellbook_object *b
00255 ) : Spelltype_gump(SPELLBOOK), page(0), book(b), turning_page(0)
00256 {
00257 set_object_area(Rectangle(36, 28, 102, 66), 7, 54);
00258
00259
00260 const int lpagex = 38, rpagex = 142, lrpagey = 25;
00261
00262 book_owner = book->get_outermost();
00263 set_avail();
00264 if (book->bookmark >= 0)
00265 page = Get_circle(book->bookmark);
00266 leftpage = new Page_button(this, lpagex, lrpagey, 0);
00267 rightpage = new Page_button(this, rpagex, lrpagey, 1);
00268 bookmark = new Bookmark_button(this);
00269
00270 Shape_frame *spshape = ShapeID(SPELLS, 0, SF_GUMPS_VGA).get_shape();
00271 spwidth = spshape->get_width();
00272 spheight = spshape->get_height();
00273 bookmark->set();
00274 int vertspace = (object_area.h - 4*spheight)/4;
00275 int spells0 = SPELLS;
00276 for (int c = 0; c < 9; c++)
00277 {
00278 int spindex = c*8;
00279 unsigned char cflags = book->circles[c];
00280 for (int s = 0; s < 8; s++)
00281 if ((cflags & (1<<s)) || cheat.in_wizard_mode())
00282 {
00283 int spnum = spindex + s;
00284 spells[spnum] = new Spell_button(this,
00285 s < 4 ? object_area.x +
00286 spshape->get_xleft() + 1
00287 : object_area.x + object_area.w -
00288 spshape->get_xright() - 2,
00289 object_area.y + spshape->get_yabove() +
00290 (spheight + vertspace)*(s%4),
00291 spnum,
00292 spells0 + spnum%8, spnum/8);
00293 }
00294 else
00295 spells[spindex + s] = 0;
00296 }
00297 }
00298
00299
00300
00301
00302
00303 Spellbook_gump::~Spellbook_gump
00304 (
00305 )
00306 {
00307 delete leftpage;
00308 delete rightpage;
00309 delete bookmark;
00310 for (int i = 0; i < 9*8; i++)
00311 delete spells[i];
00312 }
00313
00314
00315
00316
00317
00318 void Spellbook_gump::do_spell
00319 (
00320 int spell
00321 )
00322 {
00323 if (!book->can_do_spell(gwin->get_main_actor(), spell))
00324 Mouse::mouse->flash_shape(Mouse::redx);
00325 else
00326 {
00327 Spellbook_object *save_book = book;
00328 close();
00329 gwin->paint();
00330 gwin->show();
00331
00332 save_book->do_spell(gwin->get_main_actor(), spell, true);
00333
00334
00335 gumpman->close_all_gumps();
00336 }
00337 }
00338
00339
00340
00341
00342
00343 void Spellbook_gump::change_page
00344 (
00345 int delta
00346 )
00347 {
00348 if (delta > 0)
00349 {
00350 if (page == 8)
00351 return;
00352 turning_page = -1;
00353 }
00354 else if (delta < 0)
00355 {
00356 if (page == 0)
00357 return;
00358 turning_page = 1;
00359 }
00360 ShapeID shape(TURNINGPAGE, 0, SF_GUMPS_VGA);
00361 int nframes = shape.get_num_frames();
00362 int i;
00363 turning_frame = turning_page == 1 ? 0 : nframes - 1;
00364 for (i = 0; i < nframes; i++)
00365 {
00366 if (i == nframes/2)
00367 {
00368 page += delta;
00369 bookmark->set();
00370 }
00371 gwin->add_dirty(get_rect());
00372 gwin->paint_dirty();
00373 gwin->show();
00374 SDL_Delay(50);
00375 }
00376 paint();
00377 }
00378
00379
00380
00381
00382
00383 void Spellbook_gump::select_spell
00384 (
00385 int spell
00386 )
00387 {
00388 if (spells[spell])
00389 {
00390 book->bookmark = spell;
00391 bookmark->set();
00392 paint();
00393 }
00394 }
00395
00396
00397
00398
00399 Game_object *Spellbook_gump::get_owner()
00400 {
00401 return book;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410 Gump_button *Spellbook_gump::on_button
00411 (
00412 int mx, int my
00413 )
00414 {
00415 Gump_button *btn = Gump::on_button(mx, my);
00416 if (btn)
00417 return btn;
00418 else if (leftpage->on_button(mx, my))
00419 return leftpage;
00420 else if (rightpage->on_button(mx, my))
00421 return rightpage;
00422 int spindex = page*8;
00423 for (int s = 0; s < 8; s++)
00424 {
00425 Gump_button *spell = spells[spindex + s];
00426 if (spell && spell->on_button(mx, my))
00427 return spell;
00428 }
00429 if (bookmark->on_button(mx, my))
00430 return bookmark;
00431 return 0;
00432 }
00433
00434
00435
00436
00437
00438 void Spellbook_gump::paint_button
00439 (
00440 Gump_button *btn
00441 )
00442 {
00443 btn->paint();
00444 }
00445
00446
00447
00448
00449
00450 void Spellbook_gump::paint
00451 (
00452 )
00453 {
00454 const int numx = 1, numy = -4;
00455
00456 Gump::paint();
00457 if (page > 0)
00458 paint_button(leftpage);
00459 if (page < 8)
00460 paint_button(rightpage);
00461 int spindex = page*8;
00462 for (int s = 0; s < 8; s++)
00463 if (spells[spindex + s])
00464 {
00465 Gump_button *spell = spells[spindex + s];
00466 paint_button(spell);
00467 if (page == 0)
00468 continue;
00469 int num = avail[spindex + s];
00470 char text[6];
00471 if (num > 0 && num < 1000)
00472 {
00473 snprintf(text, 6, "%d", num < 100 ? num : 99);
00474 sman->paint_text(5, text,
00475 x + spell->x + numx -
00476 sman->get_text_width(4, text),
00477 y + spell->y + numy);
00478 }
00479 else if (num >= 1000)
00480 {
00481 std::strcpy(text, "oo");
00482 int px = x + spell->x + numx + 2 -
00483 sman->get_text_width(4, text);
00484 sman->paint_text(5, text + 1, px,
00485 y + spell->y + numy);
00486 sman->paint_text(5, text + 1, px + 3,
00487 y + spell->y + numy);
00488 }
00489 }
00490 if (page > 0 ||
00491 Game::get_game_type() == SERPENT_ISLE)
00492 {
00493 char *circ = item_names[CIRCLE];
00494 char *cnum = item_names[CIRCLENUM + page];
00495 sman->paint_text(5, cnum, x + 40 +
00496 (44 - sman->get_text_width(4, cnum))/2, y + 20);
00497 sman->paint_text(5, circ, x + 92 +
00498 (44 - sman->get_text_width(4, circ))/2, y + 20);
00499 }
00500 if (book->bookmark >= 0)
00501 paint_button(bookmark);
00502 if (turning_page)
00503 {
00504 const int TPXOFF = 5, TPYOFF = 3;
00505 ShapeID shape(TURNINGPAGE, turning_frame, SF_GUMPS_VGA);
00506 Shape_frame *fr = shape.get_shape();
00507 int spritex = x + object_area.x + fr->get_xleft() + TPXOFF;
00508 int spritey = y + fr->get_yabove() + TPYOFF;
00509 shape.paint_shape(spritex, spritey);
00510 turning_frame += turning_page;
00511 if (turning_frame < 0 || turning_frame >=
00512 shape.get_num_frames())
00513 turning_page = 0;
00514 }
00515 gwin->set_painted();
00516 }
00517
00518
00519
00520
00521
00522 Spellscroll_gump::Spellscroll_gump
00523 (
00524 Game_object *s
00525 ) : Spelltype_gump(65), scroll(s), spell(0)
00526 {
00527 set_object_area(Rectangle(30, 29, 50, 29), 8, 68);
00528
00529
00530 Shape_frame *spshape = ShapeID(SCROLLSPELLS, 0, SF_GUMPS_VGA).get_shape();
00531 spwidth = spshape->get_width();
00532 spheight = spshape->get_height();
00533 int spellnum = scroll->get_quality();
00534 if (spellnum >= 0 && spellnum < 8*9)
00535 spell = new Spell_button(this,
00536 object_area.x + 4 + spshape->get_xleft(),
00537 object_area.y + 4 + spshape->get_yabove(),
00538 spellnum, SCROLLSPELLS + spellnum/8,
00539 spellnum%8);
00540 }
00541
00542
00543
00544
00545
00546 Spellscroll_gump::~Spellscroll_gump
00547 (
00548 )
00549 {
00550 delete spell;
00551 }
00552
00553
00554
00555
00556
00557 void Spellscroll_gump::do_spell
00558 (
00559 int spellnum
00560 )
00561 {
00562 scroll->remove_this();
00563 scroll = 0;
00564 close();
00565 gwin->paint();
00566 gwin->show();
00567 Spellbook_object::execute_spell(gwin->get_main_actor(), spellnum);
00568 }
00569
00570
00571
00572
00573
00574 Game_object *Spellscroll_gump::get_owner
00575 (
00576 )
00577 {
00578 return scroll;
00579 }
00580
00581
00582
00583
00584
00585
00586
00587 Gump_button *Spellscroll_gump::on_button
00588 (
00589 int mx, int my
00590 )
00591 {
00592 Gump_button *btn = Gump::on_button(mx, my);
00593 if (btn)
00594 return btn;
00595 else if (spell && spell->on_button(mx, my))
00596 return spell;
00597 return 0;
00598 }
00599
00600
00601
00602
00603
00604 void Spellscroll_gump::paint_button
00605 (
00606 Gump_button *btn
00607 )
00608 {
00609 btn->paint();
00610 }
00611
00612
00613
00614
00615
00616 void Spellscroll_gump::paint
00617 (
00618 )
00619 {
00620 Gump::paint();
00621 if (spell)
00622 paint_button(spell);
00623 gwin->set_painted();
00624 }
00625