00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028
00029 #include "spellbook.h"
00030 #include "gamewin.h"
00031 #include "gamemap.h"
00032 #include "utils.h"
00033 #include "game.h"
00034 #include "Gump_manager.h"
00035 #include "databuf.h"
00036 #include "ucsched.h"
00037 #include "actors.h"
00038 #include "cheat.h"
00039 #include "ucmachine.h"
00040
00041 #ifndef UNDER_CE
00042 using std::memcpy;
00043 using std::ostream;
00044 #endif
00045
00046 const int REAGENTS = 842;
00047
00048
00049
00050
00051 const int bp = 1;
00052 const int bm = 2;
00053 const int ns = 4;
00054 const int mr = 8;
00055 const int gr = 16;
00056 const int gn = 32;
00057 const int ss = 64;
00058 const int sa = 128;
00059 const int bs = 256;
00060 const int sc = 512;
00061 const int wh = 1024;
00062
00063
00064 unsigned short Spellbook_object::bg_reagents[9*8] = {
00065 0, 0, 0, 0, 0, 0, 0, 0,
00066
00067 gr|gn|mr, gr|gn, ns|ss, gr|ss, sa|ss, sa, ns, gr|gn,
00068
00069 bm|sa, bp|mr, bp|sa, mr|sa, gr|gn|mr, gr|gn|sa, bp|bm|mr,
00070 bm|ns|mr|sa|bp|ss,
00071
00072 gr|ns|sa, gr|gn|ss, ns|ss, ns|mr, ns|bm|bp, gr|gn|mr|sa,
00073 bp|ns|ss, ns|mr|bm,
00074
00075 ss|mr, bp|sa|mr, mr|bp|bm, gr|mr|ns|sa, mr|bp|bm, bm|sa,
00076 bm|mr|ns|ss|sa, bm|sa,
00077
00078 bp|ns|ss, mr|gr|bm, gr|bp|sa|ss, bm|bp|mr|sa, bp|ss|sa,
00079 gr|gn|mr|ss, bm|ns, gn|ns|ss,
00080
00081 gr|mr|ns, sa|ss|bm|gn|ns|mr, bp|mr|ss|sa, sa|bp|bm, mr|ns|sa|bm,
00082 ns|ss|bp, gn|ss|bp, bm|sa|mr,
00083
00084 mr|ss, bp|ns|sa, bm|bp|mr|ss|sa, bp|mr|ss|sa, bm|mr|ns|sa,
00085 bp|ns|ss|mr, bp|gn|mr, gr|gn|mr|sa,
00086
00087 bp|bm|gr|gn|mr|ns|ss|sa, bm|mr|ns|sa, bp|bm|mr|ns, bm|gr|gn|mr|ns,
00088 gr|gn|ss|sa, bm|gr|mr, bp|mr|ns, bm|gr|mr
00089 };
00090
00091 unsigned short Spellbook_object::si_reagents[9*8] = {
00092
00093 gr|gn|mr, gr|gn, ns|ss, gr|ss, sa|ss, sa, ns, bp|bm|mr,
00094
00095 gr|gn, bm|sa, ns|sa, bp|sa|wh, mr|sa, gr|gn|ss, gr|gn|mr, gr|gn|sa,
00096
00097 gr|gn|wh,gr|ns|sa, bp|mr, bp|gr, gr|gn|mr|sa, ns|ss, bp|ns|ss, bp|mr|sa|sa,
00098
00099 bm|mr, gr|ss, mr|sa, sa|bm|gr|mr|ss|sc, gr|mr|ns|sa, bm|sa, bp|ss, bm|sa,
00100
00101 mr|ss, bp|gr|ss|sa, bm|bp|mr|sa, gr|gn|mr|ss, bm|ns, gn|ns|ss, sa|bm|mr|ns|ss,
00102 bp|gr|mr|sa,
00103
00104 bp|ns|ss, gr|mr|ns, gr|mr|ns, bp|wh|ss|sa, bp|wh|mr|ss|sa,
00105 bm|bp|wh|sa, bm|gn|sa, mr|sa|ss|sc,
00106
00107 bp|mr|ss|sa, bm|mr|ns|sa, gr|gn, bp|gn|mr, bm|ns|sa, gr|gn|mr|ss,
00108 bp|bm|mr|ss, bp|mr|sa,
00109
00110 wh|ss, bs|bp|ns|sa, bm|bp|mr|ss|sa, bm|bp|mr, bm|gr|ss|wh|sc,
00111 bm|bp|gr|ss|wh|sc, gr|mr|sa, bp|bs|mr|ns,
00112
00113 bm|mr|ns|sa, bm|bs|gr|gn|mr|ns, bp|bm|mr|ns, bm|bs|bp|ns|sa,
00114 bp|gr|mr|ss|sa, bm|gr|mr|ss, bm|gr|mr, ns|sa|wh|sc
00115 };
00116
00117
00118
00119
00120 int Get_usecode(int spell)
00121 { return 0x640 + spell; }
00122
00123
00124
00125
00126
00127 bool Spellbook_object::has_ring
00128 (
00129 Actor *act
00130 )
00131 {
00132 if (Game::get_game_type() == SERPENT_ISLE)
00133 {
00134 Game_object *obj = act->get_readied(Actor::lfinger);
00135 if (obj && obj->get_shapenum() == 0x128 &&
00136 obj->get_framenum() == 3)
00137 return true;
00138 obj = act->get_readied(Actor::rfinger);
00139 if (obj && obj->get_shapenum() == 0x128 &&
00140 obj->get_framenum() == 3)
00141 return true;
00142 }
00143 return false;
00144 }
00145
00146
00147
00148
00149
00150 Spellbook_object::Spellbook_object
00151 (
00152 int shapenum, int framenum,
00153 unsigned int shapex, unsigned int shapey,
00154 unsigned int lft,
00155 unsigned char *c,
00156 unsigned char bmark
00157 ) : Ireg_game_object(shapenum, framenum,
00158 shapex, shapey, lft), bookmark(bmark == 255 ? -1 : bmark)
00159 {
00160 memcpy(circles, c, sizeof(circles));
00161
00162 reagents = GAME_SI ? si_reagents : bg_reagents;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171 int Spellbook_object::add_spell
00172 (
00173 int spell
00174 )
00175 {
00176 int circle = spell/8;
00177 int num = spell%8;
00178 if (circles[circle] & (1<<num))
00179 return 0;
00180 circles[circle] |= (1<<num);
00181 return 1;
00182 }
00183
00184
00185
00186
00187
00188 bool Spellbook_object::can_do_spell
00189 (
00190 Actor *act,
00191 int spell
00192 )
00193 {
00194 if (cheat.in_wizard_mode())
00195 return true;
00196 int circle = spell/8;
00197 unsigned char cflags = circles[circle];
00198 if ((cflags & (1<<(spell%8))) == 0)
00199 return false;
00200 int mana = act->get_property(Actor::mana);
00201 int level = act->get_level();
00202 if ((mana < circle) || (level < circle))
00203
00204 return false;
00205 if (has_ring(act))
00206 return true;
00207
00208 unsigned short flags = reagents[spell];
00209
00210 for (int r = 0; flags; r++, flags = flags >> 1)
00211
00212 if ((flags&1) &&
00213 act->count_objects(REAGENTS, c_any_qual, r) == 0)
00214 return false;
00215 return true;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224 bool Spellbook_object::do_spell
00225 (
00226 Actor *act,
00227 int spell,
00228 bool can_do,
00229 bool in_combat
00230 )
00231 {
00232 if (can_do || can_do_spell(act, spell))
00233 {
00234 int circle = spell/8;
00235 if (cheat.in_wizard_mode())
00236 circle = 0;
00237 int mana = act->get_property(Actor::mana);
00238 act->set_property(Actor::mana, mana-circle);
00239
00240 unsigned short flags = reagents[spell];
00241
00242 if (!cheat.in_wizard_mode() && !has_ring(act))
00243 {
00244
00245 for (int r = 0; flags; r++, flags = flags >> 1)
00246
00247 if (flags&1)
00248 act->remove_quantity(1,
00249 REAGENTS, c_any_qual, r);
00250 }
00251 execute_spell(act, spell, in_combat);
00252 return true;
00253 }
00254 return false;
00255 }
00256
00257
00258
00259
00260
00261 void Spellbook_object::execute_spell
00262 (
00263 Actor *act,
00264 int spell,
00265 bool in_combat
00266 )
00267 {
00268 ucmachine->call_usecode(Get_usecode(spell), act,
00269 in_combat ? Usecode_machine::weapon :
00270 Usecode_machine::double_click);
00271 }
00272
00273
00274
00275
00276
00277 void Spellbook_object::activate
00278 (
00279 int event
00280 )
00281 {
00282 gumpman->add_gump(this, Game::get_game_type() == BLACK_GATE ? 43 : 38);
00283 }
00284
00285
00286
00287
00288
00289 void Spellbook_object::write_ireg
00290 (
00291 DataSource *out
00292 )
00293 {
00294 unsigned char buf[19];
00295 buf[0] = 18;
00296 uint8 *ptr = &buf[1];
00297 write_common_ireg(ptr);
00298 ptr += 4;
00299 memcpy(ptr, &circles[0], 5);
00300 ptr += 5;
00301 *ptr++ = (get_lift()&15)<<4;
00302 memcpy(ptr, &circles[5], 4);
00303 ptr += 4;
00304 *ptr++ = 0;
00305 *ptr++ = 0;
00306 *ptr++ = 0;
00307 *ptr++ = bookmark >= 0 ? bookmark : 255;
00308 out->write((char*)buf, sizeof(buf));
00309
00310 Game_map::write_scheduled(out, this);
00311 }
00312
00313
00314 int Spellbook_object::get_ireg_size()
00315 {
00316
00317 if (gumpman->find_gump(this) || Usecode_script::find(this))
00318 return -1;
00319
00320 return 19;
00321 }