Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 CrossFire, A Multiplayer game for X-windows 00003 00004 Copyright (C) 2007 Mark Wedel & 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 */ 00026 #include <global.h> 00027 #include <ob_methods.h> 00028 #include <ob_types.h> 00029 #include <sounds.h> 00030 #include <sproto.h> 00031 00032 static method_ret potion_type_apply(ob_methods *context, object *potion, 00033 object *applier, int aflags); 00034 00038 void init_type_potion(void) { 00039 register_apply(POTION, potion_type_apply); 00040 } 00041 00050 static method_ret potion_type_apply(ob_methods *context, object *potion, 00051 object *applier, int aflags) { 00052 int got_one = 0, i; 00053 object *force; 00054 00055 if (applier->type == PLAYER) { 00056 if (!QUERY_FLAG(potion, FLAG_IDENTIFIED)) 00057 identify(potion); 00058 } 00059 00060 handle_apply_yield(potion); 00061 00062 /* Potion of restoration - only for players */ 00063 if (applier->type == PLAYER && (potion->attacktype&AT_DEPLETE)) { 00064 object *depl; 00065 archetype *at; 00066 00067 if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) { 00068 drain_stat(applier); 00069 fix_object(applier); 00070 decrease_ob(potion); 00071 return METHOD_OK; 00072 } 00073 00074 if ((at = find_archetype(ARCH_DEPLETION)) == NULL) { 00075 LOG(llevError, "Could not find archetype depletion\n"); 00076 return METHOD_ERROR; 00077 } 00078 00079 depl = present_arch_in_ob(at, applier); 00080 if (depl != NULL 00081 && (potion->level != 0 && potion->level >= applier->level)) { 00082 for (i = 0; i < NUM_STATS; i++) 00083 if (get_attr_value(&depl->stats, i)) { 00084 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_STAT_GAIN, 00085 restore_msg[i], NULL); 00086 } 00087 remove_ob(depl); 00088 free_object(depl); 00089 fix_object(applier); 00090 } 00091 else 00092 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE, 00093 "You potion had no effect.", NULL); 00094 00095 decrease_ob(potion); 00096 return METHOD_OK; 00097 } 00098 00099 /* improvement potion - only for players */ 00100 if (applier->type == PLAYER && potion->attacktype&AT_GODPOWER) { 00101 for (i = 1; i < MIN(11, applier->level); i++) { 00102 if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) { 00103 if (applier->contr->levhp[i] != 1) { 00104 applier->contr->levhp[i] = 1; 00105 break; 00106 } 00107 if (applier->contr->levsp[i] != 1) { 00108 applier->contr->levsp[i] = 1; 00109 break; 00110 } 00111 if (applier->contr->levgrace[i] != 1) { 00112 applier->contr->levgrace[i] = 1; 00113 break; 00114 } 00115 } else { 00116 if (applier->contr->levhp[i] < 9) { 00117 applier->contr->levhp[i] = 9; 00118 break; 00119 } 00120 if (applier->contr->levsp[i] < 6) { 00121 applier->contr->levsp[i] = 6; 00122 break; 00123 } 00124 if (applier->contr->levgrace[i] < 3) { 00125 applier->contr->levgrace[i] = 3; 00126 break; 00127 } 00128 } 00129 } 00130 /* Just makes checking easier */ 00131 if (i < MIN(11, applier->level)) 00132 got_one = 1; 00133 if (!QUERY_FLAG(potion, FLAG_CURSED) && !QUERY_FLAG(potion, FLAG_DAMNED)) { 00134 if (got_one) { 00135 fix_object(applier); 00136 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS, 00137 "The Gods smile upon you and remake you a little more in their image." 00138 "You feel a little more perfect.", NULL); 00139 } else 00140 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE, 00141 "The potion had no effect - you are already perfect", NULL); 00142 } else { /* cursed potion */ 00143 if (got_one) { 00144 fix_object(applier); 00145 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_CURSED, 00146 "The Gods are angry and punish you.", NULL); 00147 } else 00148 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_CURSED, 00149 "You are fortunate that you are so pathetic.", NULL); 00150 } 00151 decrease_ob(potion); 00152 return METHOD_OK; 00153 } 00154 00155 /* A potion that casts a spell. Healing, restore spellpoint 00156 * (power potion) and heroism all fit into this category. 00157 * Given the spell object code, there is no limit to the number 00158 * of spells that potions can be cast, but direction is 00159 * problematic to try and imbue fireball potions for example. 00160 */ 00161 if (potion->inv) { 00162 if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) { 00163 object *fball; 00164 00165 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_CURSED, 00166 "Yech! Your lungs are on fire!", NULL); 00167 /* Explodes a fireball centered at player */ 00168 fball = create_archetype(EXPLODING_FIREBALL); 00169 fball->dam_modifier = random_roll(1, applier->level, applier, PREFER_LOW)/5+1; 00170 fball->stats.maxhp = random_roll(1, applier->level, applier, PREFER_LOW)/10+2; 00171 fball->x = applier->x; 00172 fball->y = applier->y; 00173 insert_ob_in_map(fball, applier->map, NULL, 0); 00174 } else 00175 cast_spell(applier, potion, applier->facing, potion->inv, NULL); 00176 00177 decrease_ob(potion); 00178 /* if youre dead, no point in doing this... */ 00179 if (!QUERY_FLAG(applier, FLAG_REMOVED)) 00180 fix_object(applier); 00181 return METHOD_OK; 00182 } 00183 00184 /* Deal with protection potions */ 00185 force = NULL; 00186 for (i = 0; i < NROFATTACKS; i++) { 00187 if (potion->resist[i]) { 00188 if (!force) 00189 force = create_archetype(FORCE_NAME); 00190 memcpy(force->resist, potion->resist, sizeof(potion->resist)); 00191 force->type = POTION_EFFECT; 00192 break; /* Only need to find one protection since we cappliery entire batch */ 00193 } 00194 } 00195 /* This is a protection potion */ 00196 if (force) { 00197 /* cursed items last longer */ 00198 if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) { 00199 force->stats.food *= 10; 00200 for (i = 0; i < NROFATTACKS; i++) 00201 if (force->resist[i] > 0) 00202 force->resist[i] = -force->resist[i]; /* prot => vuln */ 00203 } 00204 force->speed_left = -1; 00205 force = insert_ob_in_ob(force, applier); 00206 CLEAR_FLAG(potion, FLAG_APPLIED); 00207 SET_FLAG(force, FLAG_APPLIED); 00208 change_abil(applier, force); 00209 decrease_ob(potion); 00210 return METHOD_OK; 00211 } 00212 00213 /* Only thing left are the stat potions */ 00214 if (applier->type == PLAYER) { /* only for players */ 00215 if ((QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) 00216 && potion->value != 0) 00217 CLEAR_FLAG(potion, FLAG_APPLIED); 00218 else 00219 SET_FLAG(potion, FLAG_APPLIED); 00220 if (!change_abil(applier, potion)) 00221 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE, 00222 "Nothing happened.", NULL); 00223 } 00224 00225 /* CLEAR_FLAG is so that if the character has other potions 00226 * that were grouped with the one consumed, his 00227 * stat will not be raised by them. fix_object just clears 00228 * up all the stats. 00229 */ 00230 CLEAR_FLAG(potion, FLAG_APPLIED); 00231 fix_object(applier); 00232 decrease_ob(potion); 00233 return METHOD_OK; 00234 }