00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00026 #include <global.h>
00027 #include <ob_methods.h>
00028 #include <ob_types.h>
00029 #include <sounds.h>
00030 #include <sproto.h>
00031 #include <math.h>
00032
00033 static method_ret food_type_apply(ob_methods *context, object *food, object *applier, int aflags);
00034 static void eat_special_food(object *who, object *food);
00035 static int dragon_eat_flesh(object *op, object *meal);
00036
00040 void init_type_food(void) {
00041 register_apply(FOOD, food_type_apply);
00042 register_apply(DRINK, food_type_apply);
00043 register_apply(FLESH, food_type_apply);
00044 }
00045
00055 static method_ret food_type_apply(ob_methods *context, object *food, object *applier, int aflags) {
00056 int capacity_remaining;
00057
00058 if (QUERY_FLAG(food, FLAG_NO_PICK)) {
00059 draw_ext_info_format(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE, "You can't %s that!", NULL, food->type == DRINK ? "drink" : "eat");
00060 return METHOD_OK;
00061 }
00062
00063 if (applier->type != PLAYER)
00064 applier->stats.hp = applier->stats.maxhp;
00065 else {
00066
00067 if (food->type == FLESH && is_dragon_pl(applier))
00068 dragon_eat_flesh(applier, food);
00069
00070
00071 else if (is_old_wraith_pl(applier)) {
00072 object *skill = give_skill_by_name(applier, "wraith feed");
00073
00074 if (skill) {
00075 char buf[MAX_BUF];
00076
00077 SET_FLAG(skill, FLAG_CAN_USE_SKILL);
00078 link_player_skills(applier);
00079
00080 snprintf(buf, sizeof(buf), "You have been dead for too long to taste %s, ", food->name);
00081 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE,
00082 buf, NULL);
00083 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE,
00084 "and seem to have obtained a taste for living flesh.", NULL);
00085 } else
00086 LOG(llevError, "wraith feed skill not found\n");
00087
00088 } else if (is_wraith_pl(applier)) {
00089 char buf[MAX_BUF];
00090
00091 snprintf(buf, sizeof(buf), "You can no longer taste %s, and do not feel less hungry after %s it.", food->name, food->type == DRINK ? "drinking" : "eating");
00092 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE,
00093 buf, NULL);
00094
00095 } else {
00096 if (applier->stats.food+food->stats.food > 999) {
00097 if (food->type == FOOD || food->type == FLESH)
00098 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE,
00099 "You feel full, but what a waste of food!", NULL);
00100 else
00101 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE,
00102 "Most of the drink goes down your face not your throat!", NULL);
00103 }
00104
00105 if (!QUERY_FLAG(food, FLAG_CURSED)) {
00106 char buf[MAX_BUF];
00107
00108 if (!is_dragon_pl(applier)) {
00109
00110 if (food->type == DRINK)
00111 snprintf(buf, sizeof(buf), "Ahhh...that %s tasted good.", food->name);
00112 else
00113 snprintf(buf, sizeof(buf), "The %s tasted %s", food->name, food->type == FLESH ? "terrible!" : "good.");
00114 } else {
00115
00116 snprintf(buf, sizeof(buf), "The %s tasted terrible!", food->name);
00117 }
00118
00119 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS,
00120 buf, NULL);
00121 capacity_remaining = 999-applier->stats.food;
00122 applier->stats.food += food->stats.food;
00123 if (capacity_remaining < food->stats.food)
00124 applier->stats.hp += capacity_remaining/50;
00125 else
00126 applier->stats.hp += food->stats.food/50;
00127 if (applier->stats.hp > applier->stats.maxhp)
00128 applier->stats.hp = applier->stats.maxhp;
00129 if (applier->stats.food > 999)
00130 applier->stats.food = 999;
00131 }
00132
00133
00134 if (food->title || QUERY_FLAG(food, FLAG_CURSED))
00135 eat_special_food(applier, food);
00136 }
00137 }
00138 handle_apply_yield(food);
00139 decrease_ob(food);
00140 return METHOD_OK;
00141 }
00142
00155 static void eat_special_food(object *who, object *food) {
00156 object *force;
00157 int i, did_one = 0;
00158 sint8 k;
00159
00160 force = create_archetype(FORCE_NAME);
00161
00162 for (i = 0; i < NUM_STATS; i++) {
00163 k = get_attr_value(&food->stats, i);
00164 if (k) {
00165 set_attr_value(&force->stats, i, k);
00166 did_one = 1;
00167 }
00168 }
00169
00170
00171 for (i = 0; i < NROFATTACKS; i++) {
00172 if (food->resist[i] > 0) {
00173 force->resist[i] = food->resist[i]/2;
00174 did_one = 1;
00175 }
00176 }
00177 if (did_one) {
00178 force->speed = 0.1;
00179 update_ob_speed(force);
00180
00181 force->stats.food = food->stats.food/5;
00182 SET_FLAG(force, FLAG_IS_USED_UP);
00183 SET_FLAG(force, FLAG_APPLIED);
00184 change_abil(who, force);
00185 insert_ob_in_ob(force, who);
00186 } else {
00187 free_object(force);
00188 }
00189
00190
00191 if (food->stats.hp != 0 && !is_wraith_pl(who)) {
00192 if (QUERY_FLAG(food, FLAG_CURSED)) {
00193 strcpy(who->contr->killer, food->name);
00194 hit_player(who, food->stats.hp, food, AT_POISON, 1);
00195 draw_ext_info(NDI_UNIQUE, 0, who, MSG_TYPE_APPLY, MSG_TYPE_APPLY_CURSED,
00196 "Eck!...that was poisonous!", NULL);
00197 } else {
00198 if (food->stats.hp > 0)
00199 draw_ext_info(NDI_UNIQUE, 0, who, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS,
00200 "You begin to feel better.", NULL);
00201 else
00202 draw_ext_info(NDI_UNIQUE, 0, who, MSG_TYPE_APPLY, MSG_TYPE_APPLY_CURSED,
00203 "Eck!...that was poisonous!", NULL);
00204 who->stats.hp += food->stats.hp;
00205 }
00206 }
00207 if (food->stats.sp != 0) {
00208 if (QUERY_FLAG(food, FLAG_CURSED)) {
00209 draw_ext_info(NDI_UNIQUE, 0, who, MSG_TYPE_APPLY, MSG_TYPE_APPLY_CURSED,
00210 "You are drained of mana!", NULL);
00211 who->stats.sp -= food->stats.sp;
00212 if (who->stats.sp < 0)
00213 who->stats.sp = 0;
00214 } else {
00215 draw_ext_info(NDI_UNIQUE, 0, who, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS,
00216 "You feel a rush of magical energy!", NULL);
00217 who->stats.sp += food->stats.sp;
00218
00219 }
00220 }
00221 fix_object(who);
00222 }
00223
00237 static int dragon_eat_flesh(object *op, object *meal) {
00238 object *skin = NULL;
00239 object *abil = NULL;
00240 object *tmp = NULL;
00241
00242 char buf[MAX_BUF];
00243 double chance;
00244 double totalchance = 1;
00245 double bonus = 0;
00246 double mbonus = 0;
00247 int atnr_winner[NROFATTACKS];
00248 int winners = 0;
00249 int i;
00250
00251
00252 if (meal->type != FLESH || !is_dragon_pl(op))
00253 return 0;
00254
00255
00256
00257
00258 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
00259 if (tmp->type == FORCE) {
00260 if (strcmp(tmp->arch->name, "dragon_skin_force") == 0)
00261 skin = tmp;
00262 else if (strcmp(tmp->arch->name, "dragon_ability_force") == 0)
00263 abil = tmp;
00264 }
00265 }
00266
00267
00268
00269
00270 if (skin == NULL || abil == NULL)
00271 return 0;
00272
00273
00274 if ((999-op->stats.food) < meal->stats.food)
00275 op->stats.hp += (999-op->stats.food)/50;
00276 else
00277 op->stats.hp += meal->stats.food/50;
00278 if (op->stats.hp > op->stats.maxhp)
00279 op->stats.hp = op->stats.maxhp;
00280
00281 op->stats.food = MIN(999, op->stats.food+meal->stats.food);
00282
00283
00284
00285
00286 for (i = 0; i < NROFATTACKS; i++) {
00287 if (meal->resist[i] > 0 && atnr_is_dragon_enabled(i)) {
00288
00289
00290
00291 bonus = (settings.max_level-op->level)*30./((double)settings.max_level);
00292 if (i == abil->stats.exp)
00293 bonus += 5;
00294
00295
00296
00297
00298 mbonus = op->level*20./((double)settings.max_level);
00299
00300 chance = (((double)MIN(op->level+bonus, meal->level+bonus+mbonus))*100./((double)settings.max_level))-skin->resist[i];
00301
00302 if (chance >= 0.)
00303 chance += 1.;
00304 else
00305 chance = (chance < -12) ? 0. : 1./pow(2., -chance);
00306
00307
00308 chance *= ((double)(MIN(meal->resist[i], 50)))/50.;
00309
00310
00311 if (i == abil->stats.exp)
00312 chance = MIN(100., chance*2.);
00313
00314
00315 if (RANDOM()%10000 < (int)(chance*100)) {
00316 atnr_winner[winners] = i;
00317 winners++;
00318 }
00319
00320 if (chance >= 0.01)
00321 totalchance *= 1-chance/100;
00322
00323
00324 }
00325 }
00326
00327
00328 totalchance = 100-totalchance*100;
00329
00330 if (totalchance > 50.)
00331 snprintf(buf, sizeof(buf), "Hmm! The %s tasted delicious!", meal->name);
00332 else if (totalchance > 10.)
00333 snprintf(buf, sizeof(buf), "The %s tasted very good.", meal->name);
00334 else if (totalchance > 1.)
00335 snprintf(buf, sizeof(buf), "The %s tasted good.", meal->name);
00336 else if (totalchance > 0.1)
00337 snprintf(buf, sizeof(buf), "The %s tasted bland.", meal->name);
00338 else if (totalchance >= 0.01)
00339 snprintf(buf, sizeof(buf), "The %s had a boring taste.", meal->name);
00340 else if (meal->last_eat > 0 && atnr_is_dragon_enabled(meal->last_eat))
00341 snprintf(buf, sizeof(buf), "The %s tasted strange.", meal->name);
00342 else
00343 snprintf(buf, sizeof(buf), "The %s had no taste.", meal->name);
00344 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS,
00345 buf, NULL);
00346
00347
00348 i = -1;
00349 if (winners > 0)
00350 i = atnr_winner[RANDOM()%winners];
00351
00352 if (i >= 0 && i < NROFATTACKS && skin->resist[i] < 95) {
00353
00354 skin->resist[i]++;
00355 fix_object(op);
00356
00357 draw_ext_info_format(NDI_UNIQUE|NDI_RED, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_PROTECTION_GAIN,
00358 "Your skin is now more resistant to %s!",
00359 "Your skin is now more resistant to %s!",
00360 change_resist_msg[i]);
00361 }
00362
00363
00364
00365
00366 if (meal->last_eat > 0
00367 && atnr_is_dragon_enabled(meal->last_eat)
00368 && meal->last_eat != abil->last_eat) {
00369 abil->last_eat = meal->last_eat;
00370
00371 if (meal->last_eat != abil->stats.exp) {
00372 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_RACE,
00373 "Your metabolism prepares to focus on %s!",
00374 "Your metabolism prepares to focus on %s!",
00375 change_resist_msg[meal->last_eat]);
00376 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_RACE,
00377 "The change will happen at level %d",
00378 "The change will happen at level %d",
00379 abil->level+1);
00380 } else {
00381 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_RACE,
00382 "Your metabolism will continue to focus on %s.",
00383 "Your metabolism will continue to focus on %s.",
00384 change_resist_msg[meal->last_eat]);
00385 abil->last_eat = 0;
00386 }
00387 }
00388 return 1;
00389 }