Atrinik Server 2.5
types/spellbook.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00032 static void spellbook_failure(object *op, int failure, int power);
00033 
00038 void apply_spellbook(object *op, object *tmp)
00039 {
00040     if (QUERY_FLAG(op, FLAG_BLIND) && !QUERY_FLAG(op,FLAG_WIZ))
00041     {
00042         new_draw_info(0, COLOR_WHITE, op, "You are unable to read while blind.");
00043         return;
00044     }
00045 
00046     /* artifact_spellbooks have 'slaying' field point to a spell name,
00047      * instead of having their spell stored in stats.sp.  We should update
00048      * stats->sp to point to that spell */
00049     if (tmp->slaying != NULL)
00050     {
00051         if ((tmp->stats.sp = look_up_spell_name(tmp->slaying)) < 0)
00052         {
00053             tmp->stats.sp = -1;
00054             new_draw_info_format(0, COLOR_WHITE, op, "The book's formula for %s is incomplete.", tmp->slaying);
00055             return;
00056         }
00057         /* now clear tmp->slaying since we no longer need it */
00058         FREE_AND_CLEAR_HASH2(tmp->slaying);
00059     }
00060 
00061     /* need a literacy skill to learn spells. Also, having a literacy level
00062      * lower than the spell will make learning the spell more difficult */
00063     if (!change_skill(op, SK_LITERACY))
00064     {
00065         new_draw_info(0, COLOR_WHITE, op, "You can't read! Your attempt fails.");
00066         return;
00067     }
00068 
00069     if (tmp->stats.sp < 0 || tmp->stats.sp >= NROFREALSPELLS || spells[tmp->stats.sp].level > (SK_level(op) + 10))
00070     {
00071         new_draw_info(0, COLOR_WHITE, op, "You are unable to decipher the strange symbols.");
00072         return;
00073     }
00074 
00075     new_draw_info_format(0, COLOR_WHITE, op, "The spellbook contains the %s level spell %s.", get_levelnumber(spells[tmp->stats.sp].level), spells[tmp->stats.sp].name);
00076 
00077     if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED))
00078     {
00079         identify(tmp);
00080 
00081         if (tmp->env)
00082         {
00083             esrv_update_item(UPD_FLAGS | UPD_NAME, op, tmp);
00084         }
00085         else
00086         {
00087             CONTR(op)->socket.update_tile = 0;
00088         }
00089     }
00090 
00091     if (check_spell_known(op, tmp->stats.sp) && (tmp->stats.Wis || find_special_prayer_mark(op, tmp->stats.sp) == NULL))
00092     {
00093         new_draw_info(0, COLOR_WHITE, op, "You already know that spell.\n");
00094         return;
00095     }
00096 
00097     /* I changed spell learning in 3 ways:
00098      *
00099      *  1- MU spells use Int to learn, Cleric spells use Wisdom
00100      *
00101      *  2- The learner's level (in skills system level==literacy level; if no
00102      *     skills level == overall level) impacts the chances of spell learning.
00103      *
00104      *  3 -Automatically fail to learn if you read while confused
00105      *
00106      * Overall, chances are the same but a player will find having a high
00107      * literacy rate very useful!  -b.t. */
00108     if (QUERY_FLAG(op, FLAG_CONFUSED))
00109     {
00110         new_draw_info(0, COLOR_WHITE, op, "In your confused state you flub the wording of the text!");
00111         spellbook_failure(op, 0 - rndm(0, spells[tmp->stats.sp].level), spells[tmp->stats.sp].sp);
00112     }
00113     else if (QUERY_FLAG(tmp, FLAG_STARTEQUIP) || rndm(0, 149) - (2 * SK_level(op)) < learn_spell[spells[tmp->stats.sp].type == SPELL_TYPE_PRIEST ? op->stats.Wis : op->stats.Int])
00114     {
00115         new_draw_info(0, COLOR_WHITE, op, "You succeed in learning the spell!");
00116         do_learn_spell(op, tmp->stats.sp, 0);
00117 
00118         /* xp gain to literacy for spell learning */
00119         if (!QUERY_FLAG(tmp, FLAG_STARTEQUIP))
00120         {
00121             add_exp(op, calc_skill_exp(op, tmp, -1), op->chosen_skill->stats.sp, 0);
00122         }
00123     }
00124     else
00125     {
00126         play_sound_player_only(CONTR(op), CMD_SOUND_EFFECT, "missspell.ogg", 0, 0, 0, 0);
00127         new_draw_info(0, COLOR_WHITE, op, "You fail to learn the spell.\n");
00128     }
00129 
00130     decrease_ob(tmp);
00131 }
00132 
00139 static void spellbook_failure(object *op, int failure, int power)
00140 {
00141     /* set minimum effect */
00142     if (abs(failure / 4) > power)
00143     {
00144         power = abs(failure / 4);
00145     }
00146 
00147     /* wonder */
00148     if (failure <= -1 && failure > -15)
00149     {
00150         new_draw_info(0, COLOR_WHITE, op, "Your spell warps!");
00151 #if 0
00152         cast_cone(op, op, 0, 10, SP_WOW, spellarch[SP_WOW]);
00153 #endif
00154     }
00155     /* drain mana */
00156     else if (failure <= -15 && failure > -35)
00157     {
00158         new_draw_info(0, COLOR_WHITE, op, "Your mana is drained!");
00159         op->stats.sp -= rndm(0, power - 1);
00160 
00161         if (op->stats.sp < 0)
00162         {
00163             op->stats.sp = 0;
00164         }
00165     }
00166 }