Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

src/spell.c

Go to the documentation of this file.
00001 /* {{{
00002  * CalcRogue, a roguelike game for PCs, calculators and PDAs
00003  * Copyright (C) 2003 Jim Babcock
00004  * 
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  * 
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  * }}} */
00019 // spell.c
00024 
00025 #include "crogue.h"
00026 #include "export.h"
00027 
00028 #define SPELL_TIME 4000
00029 
00030 #define SPELL_INCREMENT 15
00031 
00032 #define MAX_SPELL_TIME 9000
00033 
00034 
00035 static int numSpellsKnown(void);
00036 static int spellByIndex(int n);
00037 static void study_spell(int spell, int type);
00038 static void learn_spell(int spell);
00039 static void refresh_spell(int spell);
00040 static void spellbookString(int n, char *buf);
00041 
00042 static const struct spelldesc **spell_list;
00043 
00044 //{{{
00045 sint study_book(ushort num_spells, ushort type, va_list spells) 
00046 {
00047     const struct spelldesc *spell_data[16];
00048     int spellnum;
00049     int i;
00050     spell_list = spell_data;
00051     
00052     if(w->playerclasses[w->plr.class].spellcasting[type] == 0)
00053     {
00054         if(type == SPELLTYPE_ARCANE)
00055             message(gettext("You don't understand the language."));
00056         else if(type == SPELLTYPE_DIVINE)
00057             message(gettext("This book is filled with religious mumbo-jumbo."));
00058         else if(type == SPELLTYPE_NECROMANCY)
00059             message(gettext("This book is filled with evil rituals."));
00060         return 0;
00061     }
00062     
00063 
00064     for(i=0; i<num_spells; i++)
00065     {
00066         spellnum = va_arg(spells, ulong);
00067         spell_data[i] = &w->spelldescs[spellnum];
00068     }
00069     
00070     message(gettext("Study which spell?"));
00071     setTabStops(spell_menu_tabs);
00072     spellnum = UI_Menu_Pick(learn_spell_rect, num_spells, &spellbookString, 0);
00073     full_redraw();
00074     
00075     if(spellnum < 0)
00076     {
00077         message(gettext("Never mind."));
00078         return 0;
00079     }
00080     else
00081     {
00082         study_spell(spell_data[spellnum]->num, type);
00083         return 1;
00084     }
00085 }
00086 //}}}
00087 
00088 //{{{
00089 static void study_spell(int spell, int type)
00090 {
00091     int i;
00092     int read_success;
00093     int slots_used = 1;
00094     
00095     if( w->spelldescs[spell].difficulty >
00096         (w->playerclasses[w->plr.class].spellcasting[type]
00097         + w->plr.extrinsic[STAT_WILLPOWER]/4) * w->plr.level / 3
00098         ||
00099         w->spelldescs[spell].pp_cost > w->plr.pps_max
00100         )
00101             read_success = 0;
00102     else
00103             read_success = 1;
00104 
00105     if(w->plr.spellknowledge[spell] > (slong)(w->time) + SPELL_TIME + 500)
00106     {
00107         message(gettext("You know that spell practically by heart."));
00108         return;
00109     }
00110     else if(w->plr.spellknowledge[spell] > (slong)(w->time) + (SPELL_TIME/2))
00111     {
00112         message(gettext("You know that spell already."));
00113         return;
00114     }
00115     else if(w->plr.spellknowledge[spell] >= 0)
00116     {
00117         read_success = 1;
00118         slots_used = 0;
00119     }
00120     
00121     if( read_success == 0 )
00122     {
00123         message(gettext("That spell is beyond your ability."));
00124         return;
00125     }
00126     
00127     if( slots_used &&
00128         numSpellsKnown() >= (w->playerclasses[w->plr.class].spellcasting[type]
00129                              * (w->plr.level+1))/20 )
00130     {
00131         if(w->plr.extrinsic[STAT_FLAGS] & STAT_FLAG_HALLUCINATING)
00132             message(gettext("Sorry, Mr. Osbourne, but my brain is full."));
00133         else
00134             message(gettext("You can't learn any more spells yet."));
00135         return;
00136     }
00137 
00138     w->interrupt = 0;
00139     for(i=0; i<w->spelldescs[spell].difficulty; i++)
00140     {
00141         timepass(1);
00142         if(w->interrupt)
00143         {
00144             message(gettext("Your concentration is broken."));
00145             return;
00146         }
00147     }
00148     
00149     if(slots_used)
00150         learn_spell(spell);
00151     else
00152         refresh_spell(spell);
00153 }
00154 //}}}
00155 //{{{
00156 static void refresh_spell(int spell)
00157 {
00158     w->plr.spellknowledge[spell] = (slong)(w->time + SPELL_TIME);
00159     message(gettext("You refresh your memory of the '%s' spell."),
00160         deref_file_ptr(w->spelldescs[spell].name));
00161 }
00162 //}}}
00163 //{{{
00164 static void learn_spell(int spell)
00165 {
00166     w->plr.spellknowledge[spell] = (slong)(w->time + SPELL_TIME);
00167     message(gettext("You learn the '%s' spell."),
00168         deref_file_ptr(w->spelldescs[spell].name));
00169     call_genericfunc(w->spelldescs[spell].learn_func);
00170 }
00171 //}}}
00172 
00173 //{{{
00174 void init_spells(void)
00175 {
00176     int i;
00177     
00178     w->plr.spellknowledge = debug_malloc( sizeof(slong)*w->desc.numspells );
00179     
00180     for(i=0; i<w->desc.numspells; i++)
00181         w->plr.spellknowledge[i] = -1;
00182 }
00183 //}}}
00184 //{{{
00185 static int numSpellsKnown(void)
00186 {
00187     int i, n=0;
00188     
00189     for(i=0; i<w->desc.numspells; i++)
00190         if(w->plr.spellknowledge[i] != -1) n++;
00191     
00192     return n;
00193 }
00194 //}}}
00195 //{{{
00196 static int spellByIndex(int n)
00197 {
00198     int i;
00199     
00200     for(i=0; n>=0; i++) {
00201         if(w->plr.spellknowledge[i] != -1)
00202             n--;
00203     }
00204     
00205     return i-1;
00206 }
00207 //}}}
00208 //{{{
00209 static void spellString(int n, char *buf)
00210 {
00211     const struct spelldesc *s;
00212     const char *spell_status;
00213     int spell_index = spellByIndex(n);
00214     
00215     s = &w->spelldescs[spell_index];
00216     
00217     if(w->plr.spellknowledge[spell_index] > w->time + 800)
00218         spell_status = gettext("memorized");
00219     else if(w->plr.spellknowledge[spell_index] >= w->time)
00220         spell_status = gettext("known");
00221     else
00222         spell_status = gettext("forgotten");
00223     
00224 #ifdef IS_CALCULATOR
00225     sprintf(buf, "%i\t%s\t"   "%i " gettext("pp") "\t"   "%s", (n+1)%10, (const char*)deref_file_ptr(s->name), s->pp_cost, spell_status);
00226 #else
00227     sprintf(buf, "%s\t"   "%i " gettext("pp") "\t"   "%s", (const char*)deref_file_ptr(s->name), s->pp_cost, spell_status);
00228 #endif
00229 }
00230 //}}}
00231 //{{{
00232 static void spellbookString(int n, char *buf)
00233 {
00234     const struct spelldesc *s;
00235     
00236     s = spell_list[n];
00237     
00238 #ifdef IS_CALCULATOR
00239     sprintf(buf, "%i\t%s\t%i " gettext("pp") "\t", (n+1)%10, (const char*)deref_file_ptr(s->name), s->pp_cost);
00240 #else
00241     sprintf(buf, "%s\t%i " gettext("pp") "\t", (const char*)deref_file_ptr(s->name), s->pp_cost);
00242 #endif
00243 }
00244 //}}}
00245 
00246 //{{{
00247 void cast_spell(void)
00248 {
00249     int which;
00250     
00251     if(!numSpellsKnown())
00252     {
00253         message(gettext("You don\'t know any spells."));
00254         return;
00255     }
00256     
00257     if(w->plr.extrinsic[STAT_FLAGS] & STAT_FLAG_CONFUSED)
00258     {
00259         message(gettext("You are too confused to cast spells!"));
00260         return;
00261     }
00262     
00263     setTabStops(spell_menu_tabs);
00264     which = UI_Menu_Pick( cast_spell_rect, numSpellsKnown(), &spellString, 0 );
00265     full_redraw();
00266     
00267     if(which==-1)
00268     {
00269         message(gettext("Never mind."));
00270         return;
00271     }
00272     
00273     which = spellByIndex(which);
00274     
00275     if(w->plr.spellknowledge[which] < w->time)
00276     {
00277         message(gettext("You've forgotten that spell.\n"));
00278         return;
00279     }
00280     
00281     if(w->plr.pps < w->spelldescs[which].pp_cost)
00282     {
00283         message(gettext("You don\'t have enough power to cast that spell."));
00284         return;
00285     }
00286     w->plr.spellknowledge[which]+=SPELL_INCREMENT*w->spelldescs[which].pp_cost;
00287     if(w->plr.spellknowledge[which] > w->time+MAX_SPELL_TIME)
00288         w->plr.spellknowledge[which] = w->time+MAX_SPELL_TIME;
00289     w->plr.pps -= w->spelldescs[which].pp_cost;
00290     
00291     call_genericfunc(w->spelldescs[which].function);
00292     
00293     timepass(1);
00294 }
00295 //}}}
00296 

Generated on Thu May 20 13:12:11 2004 for CalcRogue by doxygen 1.3.6