Atrinik Server 2.5
commands/range.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 
00042 static int find_spell_byname(object *op, char *params, int options)
00043 {
00044     /* number of spells known by op */
00045     int numknown;
00046     /* number of spell that is being cast */
00047     int spnum, match = -1, i;
00048     size_t paramlen = 0;
00049 
00050     /* DMs know all spells */
00051     if (QUERY_FLAG(op, FLAG_WIZ))
00052     {
00053         numknown = NROFREALSPELLS;
00054     }
00055     else
00056     {
00057         numknown = CONTR(op)->nrofknownspells;
00058     }
00059 
00060     for (i = 0; i < numknown; i++)
00061     {
00062         if (QUERY_FLAG(op, FLAG_WIZ))
00063         {
00064             spnum = i;
00065         }
00066         else
00067         {
00068             spnum = CONTR(op)->known_spells[i];
00069         }
00070 
00071         if (!options)
00072         {
00073             paramlen = strlen(params);
00074         }
00075 
00076         if (!strncmp(params, spells[spnum].name, options ? strlen(spells[spnum].name) : paramlen))
00077         {
00078             /* We already found a match previously - thus params is not
00079              * not unique, so return -2 stating this. */
00080             if (match >= 0)
00081             {
00082                 return -2;
00083             }
00084             else
00085             {
00086                 match = spnum;
00087             }
00088         }
00089     }
00090 
00091     return match;
00092 }
00093 
00099 int command_cast_spell(object *op, char *params)
00100 {
00101     char *cp = NULL;
00102     rangetype orig_rangetype = CONTR(op)->shoottype;
00103     int orig_spn = CONTR(op)->chosen_spell;
00104     /* number of spell that is being cast */
00105     int spnum = -1, spnum2 = -1, value;
00106 
00107     if (!CONTR(op)->nrofknownspells && !QUERY_FLAG(op, FLAG_WIZ))
00108     {
00109         new_draw_info(0, COLOR_WHITE, op, "You don't know any spells.");
00110         return 0;
00111     }
00112 
00113     if (params == NULL)
00114     {
00115         new_draw_info(0, COLOR_WHITE, op, "Cast which spell?");
00116         return 0;
00117     }
00118 
00119     /* This assumes simply that if the name of
00120      * the spell being cast as input by the player is shorter than or
00121      * equal to the length of the spell name, then there is no options
00122      * but if it is longer, then everything after the spell name is
00123      * an option.  It determines if the spell name is shorter or
00124      * longer by first iterating through the actual spell names, checking
00125      * to the length of the typed in name.  If that fails, then it checks
00126      * to the length of each spell name.  If that passes, it assumes that
00127      * anything after the length of the actual spell name is extra options
00128      * typed in by the player (ie: marking rune Hello there)  */
00129     if (((spnum2 = spnum = find_spell_byname(op, params, 0)) < 0) && ((spnum = find_spell_byname(op, params, 1)) >= 0))
00130     {
00131         params[strlen(spells[spnum].name)] = '\0';
00132         cp = &params[strlen(spells[spnum].name) + 1];
00133 
00134         if (strncmp(cp, "of ", 3) == 0)
00135         {
00136             cp += 3;
00137         }
00138     }
00139 
00140     /* We don't know this spell name */
00141     if (spnum == -1)
00142     {
00143         new_draw_info_format(0, COLOR_WHITE, op, "You don't know the spell %s.", params);
00144         return 0;
00145     }
00146 
00147     CONTR(op)->shoottype = range_magic;
00148     CONTR(op)->chosen_spell = spnum;
00149 
00150     if (!check_skill_to_fire(op))
00151     {
00152         if (!QUERY_FLAG(op, FLAG_WIZ))
00153         {
00154             CONTR(op)->chosen_spell = orig_spn;
00155             return 0;
00156         }
00157     }
00158 
00159     CONTR(op)->chosen_spell = orig_spn;
00160     CONTR(op)->shoottype = orig_rangetype;
00161 
00162     /* We still need to wait */
00163     if (!check_skill_action_time(op, op->chosen_skill))
00164     {
00165         return 0;
00166     }
00167 
00168     value = cast_spell(op, op, op->facing, spnum, 0, CAST_NORMAL, cp);
00169 
00170     if (value)
00171     {
00172         CONTR(op)->action_casting = ROUND_TAG + spells[spnum].time;
00173 
00174         if (spells[spnum].type == SPELL_TYPE_PRIEST)
00175         {
00176             op->stats.grace -= value;
00177         }
00178         else
00179         {
00180             op->stats.sp -= value;
00181         }
00182 
00183         CONTR(op)->action_timer = (float) (CONTR(op)->action_casting - global_round_tag) / (1000000 / MAX_TIME) * 1000.0f;
00184 
00185         if (CONTR(op)->last_action_timer > 0)
00186         {
00187             CONTR(op)->action_timer *= -1;
00188         }
00189     }
00190 
00191     return 1;
00192 }
00193 
00200 int fire_cast_spell(object *op, char *params)
00201 {
00202     char *cp = NULL;
00203     rangetype orig_rangetype = CONTR(op)->shoottype;
00204     int orig_spn = CONTR(op)->chosen_spell;
00205     /* number of spell that is being cast */
00206     int spnum = -1, spnum2 = -1;
00207 
00208     if (!CONTR(op)->nrofknownspells && !QUERY_FLAG(op, FLAG_WIZ))
00209     {
00210         new_draw_info(0, COLOR_WHITE, op, "You don't know any spells.");
00211         return 0;
00212     }
00213 
00214     if (params == NULL)
00215     {
00216         new_draw_info(0, COLOR_WHITE, op, "Cast which spell?");
00217         return 0;
00218     }
00219 
00220     /* This assumes simply that if the name of
00221      * the spell being cast as input by the player is shorter than or
00222      * equal to the length of the spell name, then there is no options
00223      * but if it is longer, then everything after the spell name is
00224      * an option.  It determines if the spell name is shorter or
00225      * longer by first iterating through the actual spell names, checking
00226      * to the length of the typed in name.  If that fails, then it checks
00227      * to the length of each spell name.  If that passes, it assumes that
00228      * anything after the length of the actual spell name is extra options
00229      * typed in by the player (ie: marking rune Hello there) */
00230     if (((spnum2 = spnum = find_spell_byname(op, params, 0)) < 0) && ((spnum = find_spell_byname(op, params, 1)) >= 0))
00231     {
00232         params[strlen(spells[spnum].name)] = '\0';
00233         cp = &params[strlen(spells[spnum].name) + 1];
00234 
00235         if (strncmp(cp, "of ", 3) == 0)
00236         {
00237             cp += 3;
00238         }
00239     }
00240 
00241     /* We don't know this spell name */
00242     if (spnum == -1)
00243     {
00244         new_draw_info_format(0, COLOR_WHITE, op, "You don't know the spell %s.", params);
00245         return 0;
00246     }
00247 
00248     CONTR(op)->shoottype = range_magic;
00249     CONTR(op)->chosen_spell = spnum;
00250 
00251     if (!QUERY_FLAG(op, FLAG_WIZ))
00252     {
00253         if (!check_skill_to_fire(op))
00254         {
00255             CONTR(op)->chosen_spell = orig_spn;
00256             CONTR(op)->shoottype = orig_rangetype;
00257             return 0;
00258         }
00259     }
00260 
00261     return 1;
00262 }
00263 
00271 int legal_range(object *op, int r)
00272 {
00273     int i;
00274     object *tmp;
00275 
00276     switch (r)
00277     {
00278         /* "Nothing" is always legal */
00279         case range_none:
00280             return 1;
00281 
00282         /* Bows */
00283         case range_bow:
00284             for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
00285             {
00286                 if (tmp->type == BOW && QUERY_FLAG(tmp, FLAG_APPLIED))
00287                 {
00288                     return 1;
00289                 }
00290             }
00291 
00292             return 0;
00293 
00294         /* Cast spells */
00295         case range_magic:
00296             if (CONTR(op)->nrofknownspells == 0)
00297             {
00298                 return 0;
00299             }
00300 
00301             for (i = 0; i < CONTR(op)->nrofknownspells; i++)
00302             {
00303                 if (CONTR(op)->known_spells[i] == CONTR(op)->chosen_spell)
00304                 {
00305                     return 1;
00306                 }
00307             }
00308 
00309             CONTR(op)->chosen_spell = CONTR(op)->known_spells[0];
00310             return 1;
00311 
00312         /* Use wands */
00313         case range_wand:
00314             for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
00315             {
00316                 if (tmp->type == WAND && QUERY_FLAG(tmp, FLAG_APPLIED))
00317                 {
00318                     return 1;
00319                 }
00320             }
00321 
00322             return 0;
00323 
00324         /* Rod */
00325         case range_rod:
00326             for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
00327             {
00328                 if (tmp->type == ROD && QUERY_FLAG(tmp, FLAG_APPLIED))
00329                 {
00330                     return 1;
00331                 }
00332             }
00333 
00334             return 0;
00335 
00336         /* Horn */
00337         case range_horn:
00338             for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
00339             {
00340                 if (tmp->type == HORN && QUERY_FLAG(tmp, FLAG_APPLIED))
00341                 {
00342                     return 1;
00343                 }
00344             }
00345 
00346             return 0;
00347 
00348         /* Use scrolls */
00349         case range_scroll:
00350             return 0;
00351 
00352         case range_skill:
00353             if (op->chosen_skill)
00354             {
00355                 return 1;
00356             }
00357 
00358             return 0;
00359     }
00360 
00361     return 0;
00362 }