Crossfire Server, Branch 1.12  R12190
armour_improver.c
Go to the documentation of this file.
00001 /*
00002     CrossFire, A Multiplayer game for X-windows
00003 
00004     Copyright (C) 2007 Crossfire Development Team
00005     Copyright (C) 1992 Frank Tore Johansen
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 
00021     The authors can be reached via e-mail at crossfire-devel@real-time.com
00022 */
00023 
00027 #include <global.h>
00028 #include <ob_methods.h>
00029 #include <ob_types.h>
00030 #include <sounds.h>
00031 #include <sproto.h>
00032 
00033 static method_ret armour_improver_type_apply(ob_methods *context, object *lighter, object *applier, int aflags);
00034 
00038 void init_type_armour_improver(void) {
00039     register_apply(ARMOUR_IMPROVER, armour_improver_type_apply);
00040 }
00041 
00058 static void improve_armour(object *op, object *improver, object *armour) {
00059     object *tmp;
00060     int oldmagic = armour->magic;
00061 
00062     if (armour->magic >= settings.armor_max_enchant) {
00063         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR,
00064             "This armour can not be enchanted any further.",
00065             NULL);
00066         return;
00067     }
00068 
00069     /* Dealing with random artifact armor is a lot trickier
00070      * (in terms of value, weight, etc), so take the easy way out
00071      * and don't worry about it. Note - maybe add scrolls which
00072      * make the random artifact versions (eg, armour of gnarg and
00073      * what not?) */
00074     if (armour->title) {
00075         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR,
00076             "This armour will not accept further enchantment.",
00077             NULL);
00078         return;
00079     }
00080 
00081     /* Check item power: if player has it equipped, unequip if armor
00082      * would become unwearable. */
00083     if (QUERY_FLAG(armour, FLAG_APPLIED)
00084     && op->type == PLAYER
00085     && (op->contr->item_power+1) > (settings.item_power_factor*op->level)) {
00086         apply_special(op, armour, AP_UNAPPLY);
00087         if (QUERY_FLAG(armour, FLAG_APPLIED)) {
00088                 /* Armour is cursed, too bad */
00089             draw_ext_info(NDI_UNIQUE, 0, op,
00090                 MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR,
00091                 "You can't enchant this armour without unapplying it because it would consume your soul!", NULL);
00092             return;
00093         }
00094     }
00095 
00096     /* Split objects if needed.  Can't insert tmp until the
00097      * end of this function - otherwise it will just re-merge. */
00098     if (armour->nrof > 1)
00099         tmp = get_split_ob(armour, armour->nrof-1, NULL, 0);
00100     else
00101         tmp = NULL;
00102 
00103     armour->magic++;
00104 
00105     if (!settings.armor_speed_linear) {
00106         int base = 100;
00107         int pow = 0;
00108 
00109         while (pow < armour->magic) {
00110             base = base-(base*settings.armor_speed_improvement)/100;
00111             pow++;
00112         }
00113 
00114         ARMOUR_SPEED(armour) = (ARMOUR_SPEED(&armour->arch->clone)*base)/100;
00115     } else
00116         ARMOUR_SPEED(armour) = (ARMOUR_SPEED(&armour->arch->clone)*(100+armour->magic*settings.armor_speed_improvement))/100;
00117 
00118     if (!settings.armor_weight_linear) {
00119         int base = 100;
00120         int pow = 0;
00121 
00122         while (pow < armour->magic) {
00123             base = base-(base*settings.armor_weight_reduction)/100;
00124             pow++;
00125         }
00126         armour->weight = (armour->arch->clone.weight*base)/100;
00127     } else
00128         armour->weight = (armour->arch->clone.weight*(100-armour->magic*settings.armor_weight_reduction))/100;
00129 
00130     if (armour->weight <= 0) {
00131         LOG(llevInfo, "Warning: enchanted armours can have negative weight\n.");
00132         armour->weight = 1;
00133     }
00134 
00135     armour->item_power += (armour->magic-oldmagic)*3;
00136     if (armour->item_power < 0)
00137         armour->item_power = 0;
00138 
00139     if (op->type == PLAYER) {
00140         esrv_update_item(UPD_WEIGHT|UPD_NAME|UPD_NROF, op, armour);
00141         if (QUERY_FLAG(armour, FLAG_APPLIED))
00142             fix_object(op);
00143     }
00144     decrease_ob(improver);
00145     if (tmp) {
00146         insert_ob_in_ob(tmp, op);
00147     }
00148     return;
00149 }
00150 
00165 static method_ret armour_improver_type_apply(ob_methods *context, object *scroll, object *applier, int aflags) {
00166     object *armor;
00167 
00168     if (applier->type != PLAYER)
00169         return METHOD_UNHANDLED;
00170 
00171     if (!QUERY_FLAG(applier, FLAG_WIZCAST)
00172     && (get_map_flags(applier->map, NULL, applier->x, applier->y, NULL, NULL)&P_NO_MAGIC)) {
00173         draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR,
00174             "Something blocks the magic of the scroll.", NULL);
00175         return METHOD_OK;
00176     }
00177     armor = find_marked_object(applier);
00178     if (!armor) {
00179         draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR,
00180                       "You need to mark an armor object.", NULL);
00181         return METHOD_OK;
00182     }
00183     if (armor->type != ARMOUR
00184     && armor->type != CLOAK
00185     && armor->type != BOOTS
00186     && armor->type != GLOVES
00187     && armor->type != BRACERS
00188     && armor->type != SHIELD
00189     && armor->type != HELMET) {
00190         draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR,
00191             "Your marked item is not armour!", NULL);
00192         return METHOD_OK;
00193     }
00194 
00195     draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS,
00196         "Applying armour enchantment.", NULL);
00197     improve_armour(applier, scroll, armor);
00198     return METHOD_OK;
00199 }