|
Atrinik Server 2.5
|
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 00037 void cast_magic_storm(object *op, object *tmp, int lvl) 00038 { 00039 /* Error */ 00040 if (!tmp) 00041 { 00042 return; 00043 } 00044 00045 tmp->level = SK_level(op); 00046 tmp->x = op->x; 00047 tmp->y = op->y; 00048 00049 /* increase the area of destruction */ 00050 tmp->stats.hp += lvl / 5; 00051 /* nasty recoils! */ 00052 tmp->stats.dam = lvl; 00053 tmp->stats.maxhp = tmp->count; 00054 insert_ob_in_map(tmp, op->map, op, 0); 00055 } 00056 00062 int recharge(object *op) 00063 { 00064 object *wand = find_marked_object(op); 00065 int cap; 00066 00067 if (wand == NULL || wand->type != WAND) 00068 { 00069 new_draw_info(0, COLOR_RED, op, "You need to mark the wand you want to recharge."); 00070 return 0; 00071 } 00072 00073 if (wand->stats.sp < 0 || wand->stats.sp >= NROFREALSPELLS || !spells[wand->stats.sp].charges) 00074 { 00075 new_draw_info_format(0, COLOR_RED, op, "The %s cannot be recharged.", query_name(wand, NULL)); 00076 return 0; 00077 } 00078 00079 if (!(rndm(0, 6))) 00080 { 00081 new_draw_info_format(0, COLOR_WHITE, op, "The %s vibrates violently, then explodes!", query_name(wand, NULL)); 00082 play_sound_map(op->map, CMD_SOUND_EFFECT, "explosion.ogg", op->x, op->y, 0, 0); 00083 esrv_del_item(CONTR(op), wand->count, wand->env); 00084 remove_ob(wand); 00085 return 1; 00086 } 00087 00088 new_draw_info_format(0, COLOR_WHITE, op, "The %s glows with power.", query_name(wand, NULL)); 00089 00090 wand->stats.food += 12 + rndm(1, spells[wand->stats.sp].charges); 00091 cap = spells[wand->stats.sp].charges + 12; 00092 00093 /* Place a cap on it. */ 00094 if (wand->stats.food > cap) 00095 { 00096 wand->stats.food = cap; 00097 } 00098 00099 if (wand->arch && QUERY_FLAG(&wand->arch->clone, FLAG_ANIMATE)) 00100 { 00101 SET_FLAG(wand, FLAG_ANIMATE); 00102 wand->speed = wand->arch->clone.speed; 00103 update_ob_speed(wand); 00104 } 00105 00106 return 1; 00107 } 00108 00121 int cast_create_food(object *op, object *caster, int dir, const char *stringarg) 00122 { 00123 int food_value; 00124 archetype *at = NULL; 00125 object *new_op; 00126 00127 food_value = 50 * SP_level_dam_adjust(caster, SP_CREATE_FOOD, -1, 0); 00128 00129 if (stringarg) 00130 { 00131 at = find_archetype(stringarg); 00132 00133 if (at == NULL || ((at->clone.type != FOOD && at->clone.type != DRINK) || (at->clone.stats.food > food_value))) 00134 { 00135 stringarg = NULL; 00136 } 00137 } 00138 00139 if (!stringarg) 00140 { 00141 archetype *at_tmp; 00142 00143 /* We try to find the archetype with the maximum food value. 00144 * This removes the dependency of hard coded food values in this 00145 * function, and addition of new food types is automatically added. 00146 * We don't use flesh types because the weight values of those need 00147 * to be altered from the donor. */ 00148 00149 /* We assume the food items don't have multiple parts */ 00150 for (at_tmp = first_archetype; at_tmp != NULL; at_tmp = at_tmp->next) 00151 { 00152 if (at_tmp->clone.type == FOOD || at_tmp->clone.type == DRINK) 00153 { 00154 /* Basically, if the food value is something that is creatable 00155 * under the limits of the spell and it is higher than 00156 * the item we have now, take it instead. */ 00157 if (at_tmp->clone.stats.food <= food_value && (!at || at_tmp->clone.stats.food > at->clone.stats.food)) 00158 { 00159 at = at_tmp; 00160 } 00161 } 00162 } 00163 } 00164 00165 /* Pretty unlikely (there are some very low food items), but you 00166 * never know */ 00167 if (!at) 00168 { 00169 new_draw_info(0, COLOR_WHITE, op, "You don't have enough experience to create any food."); 00170 return 0; 00171 } 00172 00173 food_value /= at->clone.stats.food; 00174 new_op = get_object(); 00175 copy_object(&at->clone, new_op, 0); 00176 new_op->nrof = food_value; 00177 00178 new_op->value = 0; 00179 SET_FLAG(new_op, FLAG_STARTEQUIP); 00180 SET_FLAG(new_op, FLAG_IDENTIFIED); 00181 00182 if (new_op->nrof < 1) 00183 { 00184 new_op->nrof = 1; 00185 } 00186 00187 cast_create_obj(op, new_op, dir); 00188 return 1; 00189 } 00190 00196 int probe(object *op) 00197 { 00198 object *tmp; 00199 00200 for (tmp = get_map_ob(op->map, op->x, op->y); tmp != NULL; tmp = tmp->above) 00201 { 00202 if (IS_LIVE(tmp)) 00203 { 00204 if (op->owner && op->owner->type == PLAYER) 00205 { 00206 new_draw_info_format(0, COLOR_WHITE, op->owner, "Your probe analyzes %s.", tmp->name); 00207 00208 if (tmp->head != NULL) 00209 { 00210 tmp = tmp->head; 00211 } 00212 00213 examine(op->owner, tmp); 00214 return 1; 00215 } 00216 } 00217 } 00218 00219 return 0; 00220 } 00221 00230 int cast_wor(object *op, object *caster) 00231 { 00232 object *dummy; 00233 00234 if (op->type != PLAYER) 00235 { 00236 return 0; 00237 } 00238 00239 if (blocks_magic(op->map, op->x, op->y)) 00240 { 00241 new_draw_info(0, COLOR_WHITE, op, "Something blocks your spell."); 00242 return 0; 00243 } 00244 00245 dummy = get_archetype("force"); 00246 00247 if (dummy == NULL) 00248 { 00249 LOG(llevBug, "cast_wor(): get_archetype failed (%s - %s)!\n", query_name(op, NULL), query_name(caster, NULL)); 00250 return 0; 00251 } 00252 00253 /* Better insert the spell in the player */ 00254 if (op->owner) 00255 { 00256 op = op->owner; 00257 } 00258 00259 dummy->speed = 0.002f * ((float) (spells[SP_WOR].bdur + SP_level_strength_adjust(caster, SP_WOR))); 00260 update_ob_speed(dummy); 00261 dummy->speed_left = -1; 00262 dummy->type = WORD_OF_RECALL; 00263 00264 FREE_AND_COPY_HASH(EXIT_PATH(dummy), CONTR(op)->savebed_map); 00265 EXIT_X(dummy) = CONTR(op)->bed_x; 00266 EXIT_Y(dummy) = CONTR(op)->bed_y; 00267 00268 insert_ob_in_ob(dummy, op); 00269 new_draw_info(0, COLOR_WHITE, op, "You feel a force starting to build up inside you."); 00270 00271 return 1; 00272 } 00273 00286 int cast_create_town_portal(object *op) 00287 { 00288 object *dummy, *force, *old_force, *current_obj; 00289 archetype *perm_portal; 00290 char portal_name[1024], portal_message[1024]; 00291 const char *exitpath = NULL; 00292 sint16 exitx = 15, exity = 15; 00293 mapstruct *exitmap = NULL; 00294 int op_level; 00295 00296 /* The first thing to do is to check if we have a marked destination 00297 * dummy is used to make a check inventory for the force */ 00298 if (!strncmp(op->map->path, settings.localdir, strlen(settings.localdir))) 00299 { 00300 new_draw_info(0, COLOR_NAVY, op, "You can't cast that here.\n"); 00301 return 0; 00302 } 00303 00304 dummy = get_archetype("force"); 00305 00306 if (!dummy) 00307 { 00308 LOG(llevBug, "cast_create_town_portal(): get_archetype failed (force) for %s!\n", op->name); 00309 return 0; 00310 } 00311 00312 FREE_AND_ADD_REF_HASH(dummy->slaying, shstr_cons.portal_destination_name); 00313 dummy->stats.sp = 1; 00314 force = check_inv_recursive(op, dummy); 00315 00316 /* Here we know there is no destination marked up. 00317 * We have 2 things to do: 00318 * 1. Mark the destination in the player inventory. 00319 * 2. Let the player know it worked. */ 00320 if (force == NULL) 00321 { 00322 FREE_AND_ADD_REF_HASH(dummy->name, op->map->path); 00323 FREE_AND_ADD_REF_HASH(dummy->race, op->map->path); 00324 EXIT_X(dummy) = op->x; 00325 EXIT_Y(dummy) = op->y; 00326 dummy->speed = 0.0; 00327 update_ob_speed(dummy); 00328 insert_ob_in_ob(dummy, op); 00329 new_draw_info(0, COLOR_NAVY, op, "You fix this place in your mind.\nYou feel you are able to come here from anywhere."); 00330 return 1; 00331 } 00332 00333 /* Here we know where the town portal should go to 00334 * We should kill any existing portal associated with the player. 00335 * Than we should create the 2 portals. 00336 * For each of them, we need: 00337 * - To create the portal with the name of the player+destination map 00338 * - set the owner of the town portal 00339 * - To mark the position of the portal in the player's inventory 00340 * for easier destruction. 00341 * 00342 * The mark works has follow: 00343 * slaying: Existing town portal 00344 * hp, sp : x & y of the associated portal 00345 * name : name of the portal 00346 * race : map the portal is in */ 00347 00348 /* First step: killing existing town portals */ 00349 dummy = get_archetype("force"); 00350 00351 if (dummy == NULL) 00352 { 00353 LOG(llevBug, "cast_create_town_portal(): get_archetype failed (force) for %s!\n", query_name(op, NULL)); 00354 return 0; 00355 } 00356 00357 /* Useful for string comparison later */ 00358 FREE_AND_COPY_HASH(dummy->name, portal_name); 00359 FREE_AND_ADD_REF_HASH(dummy->slaying, shstr_cons.portal_active_name); 00360 dummy->stats.sp = 1; 00361 perm_portal = spellarch[SP_TOWN_PORTAL]; 00362 00363 /* To kill a town portal, we go trough the player's inventory, 00364 * for each marked portal in player's inventory, 00365 * -We try load the associated map (if impossible, consider the portal destructed) 00366 * -We find any portal in the specified location. 00367 * If it has the good name, we destruct it. 00368 * -We destruct the force indicating that portal. */ 00369 while ((old_force = check_inv_recursive(op, dummy))) 00370 { 00371 FREE_AND_ADD_REF_HASH(exitpath, !strstr(old_force->name, op->name) ? old_force->name : old_force->race); 00372 exitx = EXIT_X(old_force); 00373 exity = EXIT_Y(old_force); 00374 00375 if (!strncmp(exitpath, settings.localdir, strlen(settings.localdir))) 00376 { 00377 exitmap = ready_map_name(exitpath, MAP_PLAYER_UNIQUE); 00378 } 00379 else 00380 { 00381 exitmap = ready_map_name(exitpath, 0); 00382 } 00383 00384 if (exitmap) 00385 { 00386 current_obj = present_arch(perm_portal, exitmap, exitx, exity); 00387 00388 while (current_obj) 00389 { 00390 if (strcmp(current_obj->name, strstr(old_force->name, op->name) ? old_force->name : old_force->race) == 0) 00391 { 00392 if (!QUERY_FLAG(current_obj, FLAG_REMOVED)) 00393 { 00394 remove_ob(current_obj); 00395 } 00396 00397 break; 00398 } 00399 else 00400 { 00401 current_obj = current_obj->above; 00402 } 00403 } 00404 } 00405 00406 if (!QUERY_FLAG(old_force, FLAG_REMOVED)) 00407 { 00408 remove_ob(old_force); 00409 } 00410 00411 FREE_AND_CLEAR_HASH2(exitpath); 00412 } 00413 00414 /* Creating the portals. 00415 * The very first thing to do is to ensure 00416 * access to the destination map. 00417 * If we can't, don't fizzle. Simply warn player. 00418 * This ensure player pays his mana for the spell 00419 * because HE is responsible of forgotting. */ 00420 op_level = SK_level(op); 00421 00422 if (op_level < 15) 00423 { 00424 snprintf(portal_message, sizeof(portal_message), "Air moves around you and a huge smell of ammoniac rounds you as you pass through %s's portal.\nPouah!", op->name); 00425 } 00426 else if (op_level < 30) 00427 { 00428 snprintf(portal_message, sizeof(portal_message), "%s's portal smells ozone.\nYou do a lot of movements and finally pass through the small hole in the air.", op->name); 00429 } 00430 else if (op_level < 60) 00431 { 00432 snprintf(portal_message, sizeof(portal_message), "A sort of door opens in the air in front of you, showing you the path to somewhere else."); 00433 } 00434 else 00435 { 00436 snprintf(portal_message, sizeof(portal_message), "As you walk on %s's portal, flowers come from the ground around you.\nYou feel quiet.", op->name); 00437 } 00438 00439 FREE_AND_CLEAR_HASH(exitpath); 00440 00441 /* we want ensure that the force->name is still in hash table */ 00442 if (!strstr(force->name, op->name)) 00443 { 00444 FREE_AND_ADD_REF_HASH(exitpath, force->name); 00445 } 00446 else 00447 { 00448 FREE_AND_ADD_REF_HASH(exitpath, force->race); 00449 } 00450 00451 exitx = EXIT_X(force); 00452 exity = EXIT_Y(force); 00453 00454 /* Delete the force inside the player */ 00455 if (!QUERY_FLAG(force, FLAG_REMOVED)) 00456 { 00457 remove_ob(force); 00458 } 00459 00460 /* Ensure exit map is loaded */ 00461 if (!strncmp(exitpath, settings.localdir, strlen(settings.localdir))) 00462 { 00463 exitmap = ready_map_name(exitpath, MAP_PLAYER_UNIQUE); 00464 } 00465 else 00466 { 00467 exitmap = ready_map_name(exitpath, 0); 00468 } 00469 00470 /* If we were unable to load (ex. random map deleted), warn player */ 00471 if (exitmap == NULL) 00472 { 00473 new_draw_info(0, COLOR_NAVY, op, "Something strange happened.\nYou can't remember where to go?!"); 00474 FREE_AND_CLEAR_HASH(exitpath); 00475 return 1; 00476 } 00477 00478 /* Create a portal in front of player dummy contain the portal and 00479 * force contain the track to kill it later. */ 00480 snprintf(portal_name, sizeof(portal_name), "%s's portal to %s", op->name, exitpath); 00481 /* The portal */ 00482 dummy = arch_to_object(spellarch[SP_TOWN_PORTAL]); 00483 00484 if (dummy == NULL) 00485 { 00486 LOG(llevBug, "cast_create_town_portal(): arch_to_object failed (perm_magic_portal) for %s!\n", query_name(op, NULL)); 00487 FREE_AND_CLEAR_HASH(exitpath); 00488 return 0; 00489 } 00490 00491 FREE_AND_ADD_REF_HASH(EXIT_PATH(dummy), exitpath); 00492 EXIT_X(dummy) = exitx; 00493 EXIT_Y(dummy) = exity; 00494 FREE_AND_COPY_HASH(dummy->name, portal_name); 00495 FREE_AND_COPY_HASH(dummy->msg, portal_message); 00496 CLEAR_FLAG(dummy, FLAG_WALK_ON); 00497 CLEAR_FLAG(dummy, FLAG_FLY_ON); 00498 00499 /* Set as a 2 ways exit (see manual_apply & is_legal_2ways_exit funcs) */ 00500 dummy->stats.exp = 1; 00501 /* Save the owner of the portal */ 00502 FREE_AND_COPY_HASH(dummy->race, op->name); 00503 cast_create_obj(op, dummy, 0); 00504 00505 /* The force */ 00506 force = get_archetype("force"); 00507 00508 if (force == NULL) 00509 { 00510 LOG(llevBug, "cast_create_town_portal(): get_archetype failed (force) for %s!\n", query_name(op, NULL)); 00511 FREE_AND_CLEAR_HASH(exitpath); 00512 return 0; 00513 } 00514 00515 FREE_AND_ADD_REF_HASH(force->slaying, shstr_cons.portal_active_name); 00516 FREE_AND_ADD_REF_HASH(force->race, op->map->path); 00517 FREE_AND_COPY_HASH(force->name, portal_name); 00518 EXIT_X(force) = dummy->x; 00519 EXIT_Y(force) = dummy->y; 00520 force->speed = 0.0; 00521 update_ob_speed(force); 00522 insert_ob_in_ob(force, op); 00523 /* Create a portal in the destination map 00524 * dummy contain the portal and 00525 * force the track to kill it later */ 00526 snprintf(portal_name, sizeof(portal_name), "%s's portal to %s", op->name, op->map->path); 00527 00528 /* The portal */ 00529 dummy = arch_to_object(spellarch[SP_TOWN_PORTAL]); 00530 00531 if (dummy == NULL) 00532 { 00533 LOG(llevBug, "cast_create_town_portal(): arch_to_object failed (perm_magic_portal) for %s!\n", query_name(op, NULL)); 00534 FREE_AND_CLEAR_HASH(exitpath); 00535 return 0; 00536 } 00537 00538 FREE_AND_ADD_REF_HASH(EXIT_PATH(dummy), op->map->path); 00539 EXIT_X(dummy) = op->x; 00540 EXIT_Y(dummy) = op->y; 00541 FREE_AND_COPY_HASH(dummy->name, portal_name); 00542 FREE_AND_COPY_HASH(dummy->msg, portal_message); 00543 CLEAR_FLAG(dummy, FLAG_WALK_ON); 00544 CLEAR_FLAG(dummy, FLAG_FLY_ON); 00545 dummy->x = exitx; 00546 dummy->y = exity; 00547 00548 /* Set as a 2 ways exit (see manual_apply & is_legal_2ways_exit funcs) */ 00549 dummy->stats.exp = 1; 00550 /* Save the owner of the portal */ 00551 FREE_AND_COPY_HASH(dummy->race, op->name); 00552 insert_ob_in_map(dummy, exitmap, op, INS_NO_MERGE | INS_NO_WALK_ON); 00553 /* The force */ 00554 force = get_archetype("force"); 00555 00556 if (force == NULL) 00557 { 00558 LOG(llevBug, "cast_create_town_portal(): get_archetype failed (force) for %s!\n", query_name(op, NULL)); 00559 FREE_AND_CLEAR_HASH(exitpath); 00560 return 0; 00561 } 00562 00563 FREE_AND_ADD_REF_HASH(force->slaying, shstr_cons.portal_active_name); 00564 FREE_AND_ADD_REF_HASH(force->race, exitpath); 00565 FREE_AND_COPY_HASH(force->name, portal_name); 00566 EXIT_X(force) = dummy->x; 00567 EXIT_Y(force) = dummy->y; 00568 force->speed = 0.0; 00569 update_ob_speed(force); 00570 insert_ob_in_ob(force, op); 00571 00572 /* Describe the player what happened */ 00573 new_draw_info(0, COLOR_NAVY, op, "You see air moving and showing you the way home."); 00574 FREE_AND_CLEAR_HASH(exitpath); 00575 return 1; 00576 } 00577 00585 int cast_destruction(object *op, object *caster, int dam, int attacktype) 00586 { 00587 int i, j, range, xt, yt; 00588 object *tmp, *hitter; 00589 mapstruct *m; 00590 00591 /* The hitter object. */ 00592 hitter = arch_to_object(spellarch[SP_DESTRUCTION]); 00593 set_owner(hitter, op); 00594 hitter->level = SK_level(caster); 00595 00596 /* Calculate maximum range of the spell */ 00597 range = MAX(SP_level_strength_adjust(caster, SP_DESTRUCTION), spells[SP_DESTRUCTION].bdur); 00598 dam += SP_level_dam_adjust(caster, SP_DESTRUCTION, -1, 0); 00599 00600 for (i = -range; i <= range; i++) 00601 { 00602 for (j = -range; j <= range; j++) 00603 { 00604 xt = op->x + i; 00605 yt = op->y + j; 00606 00607 if (!(m = get_map_from_coord(op->map, &xt, &yt))) 00608 { 00609 continue; 00610 } 00611 00612 /* Nothing alive here? Move on... */ 00613 if (!(GET_MAP_FLAGS(m, xt, yt) & (P_IS_ALIVE | P_IS_PLAYER))) 00614 { 00615 continue; 00616 } 00617 00618 /* Try to get an object to hit */ 00619 for (tmp = GET_MAP_OB(m, xt, yt); tmp; tmp = tmp->above) 00620 { 00621 /* Get head. */ 00622 if (tmp->head) 00623 { 00624 tmp = tmp->head; 00625 } 00626 00627 /* Skip the caster and not alive objects. */ 00628 if (tmp == caster || !IS_LIVE(tmp) || spell_attack_missed(hitter, tmp)) 00629 { 00630 continue; 00631 } 00632 00633 if (!is_friend_of(op, tmp)) 00634 { 00635 sint16 damage = dam; 00636 00637 if (tmp->quick_pos) 00638 { 00639 damage /= (tmp->quick_pos >> 4) + 1; 00640 } 00641 00642 hit_player(tmp, damage, hitter, attacktype); 00643 break; 00644 } 00645 } 00646 } 00647 } 00648 00649 return 1; 00650 } 00651 00658 int cast_heal_around(object *op, int level, int type) 00659 { 00660 int success = 0; 00661 00662 switch (type) 00663 { 00664 case SP_RAIN_HEAL: 00665 { 00666 int i, x, y; 00667 mapstruct *m; 00668 object *tmp; 00669 00670 for (i = 0; i <= SIZEOFFREE1; i++) 00671 { 00672 x = op->x + freearr_x[i]; 00673 y = op->y + freearr_y[i]; 00674 00675 if (!(m = get_map_from_coord(op->map, &x, &y))) 00676 { 00677 continue; 00678 } 00679 00680 if (!(GET_MAP_FLAGS(m, x, y) & (P_IS_ALIVE | P_IS_PLAYER))) 00681 { 00682 continue; 00683 } 00684 00685 for (tmp = GET_MAP_OB_LAYER(m, x, y, LAYER_LIVING - 1); tmp && tmp->layer == LAYER_LIVING; tmp = tmp->above) 00686 { 00687 tmp = HEAD(tmp); 00688 00689 if (tmp == op || !IS_LIVE(tmp) || !is_friend_of(op, tmp)) 00690 { 00691 continue; 00692 } 00693 00694 cast_heal(op, level, tmp, SP_MINOR_HEAL); 00695 success = 1; 00696 } 00697 } 00698 00699 break; 00700 } 00701 00702 case SP_PARTY_HEAL: 00703 { 00704 objectlink *ol; 00705 00706 if (op->type != PLAYER) 00707 { 00708 return 0; 00709 } 00710 else if (!CONTR(op)->party) 00711 { 00712 new_draw_info(0, COLOR_WHITE, op, "You need to be in a party to cast this spell."); 00713 return 0; 00714 } 00715 00716 for (ol = CONTR(op)->party->members; ol; ol = ol->next) 00717 { 00718 if (on_same_map(ol->objlink.ob, op)) 00719 { 00720 cast_heal(op, level, ol->objlink.ob, SP_MINOR_HEAL); 00721 } 00722 } 00723 00724 success = 1; 00725 break; 00726 } 00727 } 00728 00729 return success; 00730 } 00731 00738 int cast_heal(object *op, int level, object *target, int spell_type) 00739 { 00740 archetype *at; 00741 object *temp; 00742 int heal = 0, success = 0; 00743 00744 if (!op || !target) 00745 { 00746 LOG(llevBug, "cast_heal(): target or caster NULL (op: %s target: %s)\n", query_name(op, NULL), query_name(target, NULL)); 00747 return 0; 00748 } 00749 00750 switch (spell_type) 00751 { 00752 case SP_CURE_DISEASE: 00753 if (cure_disease(target, op)) 00754 { 00755 success = 1; 00756 } 00757 00758 break; 00759 00760 case SP_CURE_POISON: 00761 at = find_archetype("poisoning"); 00762 00763 if (op != target && target->type == PLAYER) 00764 { 00765 new_draw_info_format(0, COLOR_WHITE, target, "%s casts cure poison on you!", op->name ? op->name : "Someone"); 00766 } 00767 00768 if (op != target && op->type == PLAYER) 00769 { 00770 new_draw_info_format(0, COLOR_WHITE, op, "You cast cure poison on %s!", target->name ? target->name : "someone"); 00771 } 00772 00773 for (temp = target->inv; temp != NULL; temp = temp->below) 00774 { 00775 if (temp->arch == at) 00776 { 00777 success = 1; 00778 temp->stats.food = 1; 00779 } 00780 } 00781 00782 if (success) 00783 { 00784 if (target->type == PLAYER) 00785 { 00786 new_draw_info(0, COLOR_WHITE, target, "Your body feels cleansed."); 00787 } 00788 00789 if (op != target && op->type == PLAYER) 00790 { 00791 new_draw_info_format(0, COLOR_WHITE, op, "%s's body seems cleansed.", target->name ? target->name : "Someone"); 00792 } 00793 } 00794 else 00795 { 00796 if (target->type == PLAYER) 00797 { 00798 new_draw_info(0, COLOR_WHITE, target, "You are not poisoned."); 00799 } 00800 00801 if (op != target && op->type == PLAYER) 00802 { 00803 new_draw_info_format(0, COLOR_WHITE, op, "%s is not poisoned.", target->name ? target->name : "Someone"); 00804 } 00805 } 00806 00807 break; 00808 00809 case SP_CURE_CONFUSION: 00810 at = find_archetype("confusion"); 00811 00812 if (op != target && target->type == PLAYER) 00813 { 00814 new_draw_info_format(0, COLOR_WHITE, target, "%s casts cure confusion on you!", op->name ? op->name : "Someone"); 00815 } 00816 00817 if (op != target && op->type == PLAYER) 00818 { 00819 new_draw_info_format(0, COLOR_WHITE, op, "You cast cure confusion on %s!", target->name ? target->name : "someone"); 00820 } 00821 00822 for (temp = target->inv; temp != NULL; temp = temp->below) 00823 { 00824 if (temp->arch == at) 00825 { 00826 success = 1; 00827 temp->stats.food = 1; 00828 } 00829 } 00830 00831 if (success) 00832 { 00833 if (target->type == PLAYER) 00834 { 00835 new_draw_info(0, COLOR_WHITE, target, "Your mind feels clearer."); 00836 } 00837 00838 if (op != target && op->type == PLAYER) 00839 { 00840 new_draw_info_format(0, COLOR_WHITE, op, "%s's mind seems clearer.", target->name ? target->name : "Someone"); 00841 } 00842 } 00843 else 00844 { 00845 if (target->type == PLAYER) 00846 { 00847 new_draw_info(0, COLOR_WHITE, target, "You are not confused."); 00848 } 00849 00850 if (op != target && op->type == PLAYER) 00851 { 00852 new_draw_info_format(0, COLOR_WHITE, op, "%s is not confused.", target->name ? target->name : "Someone"); 00853 } 00854 } 00855 00856 break; 00857 00858 case SP_MINOR_HEAL: 00859 success = 1; 00860 heal = rndm(2, 5 + level) + 6; 00861 00862 if (op->type == PLAYER) 00863 { 00864 if (heal > 0) 00865 { 00866 new_draw_info_format(0, COLOR_WHITE, op, "The prayer heals %s for %d hp!", op == target ? "you" : (target ? target->name : "NULL"), heal); 00867 } 00868 else 00869 { 00870 new_draw_info(0, COLOR_WHITE, op, "The healing prayer fails!"); 00871 } 00872 } 00873 00874 if (op != target && target->type == PLAYER) 00875 { 00876 if (heal > 0) 00877 { 00878 new_draw_info_format(0, COLOR_WHITE, target, "%s casts minor healing on you healing %d hp!", op->name, heal); 00879 } 00880 else 00881 { 00882 new_draw_info_format(0, COLOR_WHITE, target, "%s casts minor healing on you but it fails!", op->name); 00883 } 00884 } 00885 00886 break; 00887 00888 case SP_GREATER_HEAL: 00889 success = 1; 00890 heal = rndm(4, 5 + level) + rndm(4, 5 + level) + 12; 00891 00892 if (op->type == PLAYER) 00893 { 00894 if (heal > 0) 00895 { 00896 new_draw_info_format(0, COLOR_WHITE, op, "The prayer heals %s for %d hp!", op == target ? "you" : (target ? target->name : "NULL"), heal); 00897 } 00898 else 00899 { 00900 new_draw_info(0, COLOR_WHITE, op, "The healing prayer fails!"); 00901 } 00902 } 00903 00904 if (op != target && target->type == PLAYER) 00905 { 00906 if (heal > 0) 00907 { 00908 new_draw_info_format(0, COLOR_WHITE, target, "%s casts greater healing on you healing %d hp!", op->name, heal); 00909 } 00910 else 00911 { 00912 new_draw_info_format(0, COLOR_WHITE, target, "%s casts greater healing on you but it fails!", op->name); 00913 } 00914 } 00915 00916 break; 00917 00918 case SP_RESTORATION: 00919 if (cast_heal(op, level, target, SP_CURE_POISON)) 00920 { 00921 success = 1; 00922 } 00923 00924 if (cast_heal(op, level, target, SP_CURE_CONFUSION)) 00925 { 00926 success = 1; 00927 } 00928 00929 if (cast_heal(op, level, target, SP_CURE_DISEASE)) 00930 { 00931 success = 1; 00932 } 00933 00934 if (target->stats.food < 999) 00935 { 00936 success = 1; 00937 target->stats.food = 999; 00938 } 00939 00940 if (cast_heal(op, level, target, SP_MINOR_HEAL)) 00941 { 00942 success = 1; 00943 } 00944 00945 return success; 00946 } 00947 00948 if (heal > 0) 00949 { 00950 if (reduce_symptoms(target, heal)) 00951 { 00952 success = 1; 00953 } 00954 00955 if (target->stats.hp < target->stats.maxhp) 00956 { 00957 if (target == op) 00958 { 00959 if (op->type == PLAYER) 00960 { 00961 CONTR(op)->stat_damage_healed += MIN(heal, target->stats.maxhp - target->stats.hp); 00962 } 00963 } 00964 else 00965 { 00966 if (op->type == PLAYER) 00967 { 00968 CONTR(op)->stat_damage_healed_other += MIN(heal, target->stats.maxhp - target->stats.hp); 00969 } 00970 00971 if (target->type == PLAYER) 00972 { 00973 CONTR(target)->stat_damage_heal_received += MIN(heal, target->stats.maxhp - target->stats.hp); 00974 } 00975 } 00976 00977 success = 1; 00978 target->stats.hp += heal; 00979 00980 if (target->stats.hp > target->stats.maxhp) 00981 { 00982 target->stats.hp = target->stats.maxhp; 00983 } 00984 } 00985 00986 if (target->damage_round_tag != ROUND_TAG) 00987 { 00988 target->last_damage = 0; 00989 target->damage_round_tag = ROUND_TAG; 00990 } 00991 00992 target->last_damage -= heal; 00993 } 00994 00995 if (success) 00996 { 00997 op->speed_left = -FABS(op->speed) * 3; 00998 } 00999 01000 if (insert_spell_effect(spells[spell_type].archname, target->map, target->x, target->y)) 01001 { 01002 LOG(llevDebug, "insert_spell_effect() failed: spell:%d, obj:%s target:%s\n", spell_type, query_name(op, NULL), query_name(target, NULL)); 01003 } 01004 01005 return success; 01006 } 01007 01016 int cast_change_attr(object *op, object *caster, object *target, int spell_type) 01017 { 01018 object *tmp = target, *tmp2 = NULL, *force = NULL; 01019 int is_refresh = 0, msg_flag = 1, i = 0; 01020 01021 if (tmp == NULL) 01022 { 01023 return 0; 01024 } 01025 01026 /* We ID the buff force with spell_type... if we find one, we have 01027 * old effect. If not, we create a fresh force. */ 01028 for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below) 01029 { 01030 if (tmp2->type == FORCE) 01031 { 01032 if (tmp2->value == spell_type) 01033 { 01034 /* The old effect will be "refreshed" */ 01035 force = tmp2; 01036 is_refresh = 1; 01037 new_draw_info(0, COLOR_WHITE, op, "You recast the spell while in effect."); 01038 } 01039 } 01040 } 01041 01042 if (force == NULL) 01043 { 01044 force = get_archetype("force"); 01045 } 01046 01047 /* Mark this force with the originating spell */ 01048 force->value = spell_type; 01049 01050 switch (spell_type) 01051 { 01052 case SP_STRENGTH: 01053 force->speed_left = -1; 01054 01055 if (tmp->type != PLAYER) 01056 { 01057 if (op->type == PLAYER) 01058 { 01059 new_draw_info(0, COLOR_WHITE, op, "You can't cast this kind of spell on your target."); 01060 } 01061 01062 return 0; 01063 } 01064 else if (op->type == PLAYER && op != tmp) 01065 { 01066 new_draw_info_format(0, COLOR_WHITE, tmp, "%s casts strength on you!", op->name ? op->name : "Someone"); 01067 } 01068 01069 if (force->stats.Str < 2) 01070 { 01071 force->stats.Str++; 01072 01073 if (op->type == PLAYER && op != tmp) 01074 { 01075 new_draw_info_format(0, COLOR_WHITE, op, "%s gets stronger.", tmp->name ? tmp->name : "Someone"); 01076 } 01077 } 01078 else 01079 { 01080 msg_flag = 0; 01081 new_draw_info(0, COLOR_WHITE, tmp, "You don't grow stronger but the spell is refreshed."); 01082 01083 if (op->type == PLAYER && op != tmp) 01084 { 01085 new_draw_info_format(0, COLOR_WHITE, op, "%s doesn't grow stronger but the spell is refreshed.", tmp->name ? tmp->name : "Someone"); 01086 } 01087 } 01088 01089 if (insert_spell_effect(spells[SP_STRENGTH].archname, target->map, target->x, target->y)) 01090 { 01091 LOG(llevDebug, "insert_spell_effect() failed: spell:%d, obj:%s caster:%s target:%s\n", spell_type, query_name(op, NULL), query_name(caster, NULL), query_name(target, NULL)); 01092 } 01093 01094 break; 01095 01096 /* Attacktype protection spells */ 01097 case SP_PROT_COLD: 01098 i = ATNR_COLD; 01099 break; 01100 01101 case SP_PROT_FIRE: 01102 i = ATNR_FIRE; 01103 break; 01104 01105 case SP_PROT_ELEC: 01106 i = ATNR_ELECTRICITY; 01107 break; 01108 01109 case SP_PROT_POISON: 01110 i = ATNR_POISON; 01111 break; 01112 } 01113 01114 if (i) 01115 { 01116 new_draw_info_format(0, COLOR_WHITE, op, "Your protection to %s grows.", attack_name[i]); 01117 force->protection[i] = MIN(SP_level_dam_adjust(caster, spell_type, -1, 0), 50); 01118 } 01119 01120 force->speed_left = -1 - SP_level_strength_adjust(caster, spell_type) * 0.1f; 01121 01122 if (!is_refresh) 01123 { 01124 SET_FLAG(force, FLAG_APPLIED); 01125 force = insert_ob_in_ob(force, tmp); 01126 } 01127 01128 if (msg_flag) 01129 { 01130 /* Mostly to display any messages */ 01131 change_abil(tmp, force); 01132 /* This takes care of some stuff that change_abil() */ 01133 fix_player(tmp); 01134 } 01135 01136 return 1; 01137 } 01138 01147 int create_bomb(object *op, object *caster, int dir, int spell_type) 01148 { 01149 object *tmp; 01150 int dx = op->x + freearr_x[dir], dy = op->y + freearr_y[dir]; 01151 01152 if (wall(op->map, dx, dy)) 01153 { 01154 new_draw_info(0, COLOR_WHITE, op, "There is something in the way."); 01155 return 0; 01156 } 01157 01158 tmp = arch_to_object(spellarch[spell_type]); 01159 01160 /* level dependencies for bomb */ 01161 tmp->stats.dam = SP_level_dam_adjust(caster, spell_type, -1, 0); 01162 tmp->stats.hp = spells[spell_type].bdur + SP_level_strength_adjust(caster, spell_type); 01163 tmp->level = SK_level(caster); 01164 set_owner(tmp,op); 01165 tmp->x = dx, tmp->y = dy; 01166 insert_ob_in_map(tmp, op->map, op, 0); 01167 01168 return 1; 01169 } 01170 01174 void animate_bomb(object *op) 01175 { 01176 int i; 01177 archetype *at; 01178 01179 if (!op->map) 01180 { 01181 return; 01182 } 01183 01184 if (op->state != NUM_ANIMATIONS(op) - 1) 01185 { 01186 op->state++; 01187 SET_ANIMATION(op, op->state); 01188 return; 01189 } 01190 01191 at = find_archetype("splint"); 01192 01193 if (at) 01194 { 01195 for (i = 1; i < 9; i++) 01196 { 01197 fire_arch_from_position(op, op, op->x, op->y, i, at, 0, NULL); 01198 } 01199 } 01200 01201 explode_object(op); 01202 } 01203 01210 int remove_depletion(object *op, object *target) 01211 { 01212 archetype *at; 01213 object *depl; 01214 int i, success = 0; 01215 01216 if ((at = find_archetype("depletion")) == NULL) 01217 { 01218 LOG(llevBug, "Could not find archetype depletion"); 01219 return 0; 01220 } 01221 01222 if (!op || !target) 01223 { 01224 return 0; 01225 } 01226 01227 if (target->type != PLAYER) 01228 { 01229 /* Fake messages for non player... */ 01230 if (op->type == PLAYER) 01231 { 01232 new_draw_info_format(0, COLOR_WHITE, op, "You cast depletion on %s.", query_base_name(target, NULL)); 01233 new_draw_info(0, COLOR_WHITE, op, "There is no depletion."); 01234 } 01235 01236 return 0; 01237 } 01238 01239 if (op != target) 01240 { 01241 if (op->type == PLAYER) 01242 { 01243 new_draw_info_format(0, COLOR_WHITE, op, "You cast depletion on %s.", query_base_name(target, NULL)); 01244 } 01245 else if (target->type == PLAYER) 01246 { 01247 new_draw_info_format(0, COLOR_WHITE, target, "%s casts remove depletion on you.", query_base_name(op, NULL)); 01248 } 01249 } 01250 01251 if ((depl = present_arch_in_ob(at, target)) != NULL) 01252 { 01253 for (i = 0; i < NUM_STATS; i++) 01254 { 01255 if (get_attr_value(&depl->stats, i)) 01256 { 01257 success++; 01258 new_draw_info(0, COLOR_WHITE, target, restore_msg[i]); 01259 } 01260 } 01261 01262 remove_ob(depl); 01263 fix_player(target); 01264 } 01265 01266 if (op != target && op->type == PLAYER) 01267 { 01268 if (success) 01269 { 01270 new_draw_info(0, COLOR_WHITE, op, "Your prayer removes some depletion."); 01271 } 01272 else 01273 { 01274 new_draw_info(0, COLOR_WHITE, op, "There is no depletion."); 01275 } 01276 } 01277 01278 /* If success, target got info before */ 01279 if (op != target && target->type == PLAYER && !success) 01280 { 01281 new_draw_info(0, COLOR_WHITE, target, "There is no depletion."); 01282 } 01283 01284 insert_spell_effect(spells[SP_REMOVE_DEPLETION].archname, target->map, target->x, target->y); 01285 01286 return success; 01287 } 01288 01297 int remove_curse(object *op, object *target, int type, int src) 01298 { 01299 object *tmp; 01300 int success = 0; 01301 01302 if (!op || !target) 01303 { 01304 return 0; 01305 } 01306 01307 if (op != target) 01308 { 01309 if (op->type == PLAYER) 01310 { 01311 new_draw_info_format(0, COLOR_WHITE, op, "You cast remove %s on %s.", type == SP_REMOVE_CURSE ? "curse" : "damnation", query_base_name(target, NULL)); 01312 } 01313 else if (target->type == PLAYER) 01314 { 01315 new_draw_info_format(0, COLOR_WHITE, target, "%s casts remove %s on you.", query_base_name(op, NULL), type == SP_REMOVE_CURSE ? "curse" : "damnation"); 01316 } 01317 } 01318 01319 /* Player remove xx only removes applied stuff, npc remove clears ALL */ 01320 for (tmp = target->inv; tmp; tmp = tmp->below) 01321 { 01322 if ((src == CAST_NPC || QUERY_FLAG(tmp, FLAG_APPLIED)) && (QUERY_FLAG(tmp, FLAG_CURSED) || (type == SP_REMOVE_DAMNATION && QUERY_FLAG(tmp, FLAG_DAMNED)))) 01323 { 01324 if (tmp->level <= SK_level(op)) 01325 { 01326 success++; 01327 01328 if (type == SP_REMOVE_DAMNATION) 01329 { 01330 CLEAR_FLAG(tmp, FLAG_DAMNED); 01331 } 01332 01333 CLEAR_FLAG(tmp, FLAG_CURSED); 01334 01335 if (target->type == PLAYER) 01336 { 01337 esrv_send_item(target, tmp); 01338 } 01339 } 01340 /* Level of the items is too high for this remove curse */ 01341 else 01342 { 01343 if (target->type == PLAYER) 01344 { 01345 new_draw_info_format(0, COLOR_WHITE, target, "The %s's curse is stronger than the prayer!", query_base_name(tmp, NULL)); 01346 } 01347 else if (op != target && op->type == PLAYER) 01348 { 01349 new_draw_info_format(0, COLOR_WHITE, op, "The %s's curse of %s is stronger than your prayer!", query_base_name(tmp, NULL), query_base_name(target, NULL)); 01350 } 01351 } 01352 } 01353 } 01354 01355 if (op != target && op->type == PLAYER) 01356 { 01357 if (success) 01358 { 01359 new_draw_info(0, COLOR_WHITE, op, "Your prayer removes some curses."); 01360 } 01361 else 01362 { 01363 new_draw_info_format(0, COLOR_WHITE, op, "%s's items seem uncursed.", query_base_name(target, NULL)); 01364 } 01365 } 01366 01367 if (target->type == PLAYER) 01368 { 01369 if (success) 01370 { 01371 new_draw_info(0, COLOR_WHITE, target, "You feel like someone is helping you."); 01372 } 01373 else 01374 { 01375 if (src == CAST_NORMAL) 01376 { 01377 new_draw_info(0, COLOR_WHITE, target, "You are not using any cursed items."); 01378 } 01379 else 01380 { 01381 new_draw_info(0, COLOR_WHITE, target, "You hear maniacal laughter in the distance."); 01382 } 01383 } 01384 } 01385 01386 insert_spell_effect(spells[SP_REMOVE_CURSE].archname, target->map, target->x, target->y); 01387 01388 return success; 01389 } 01390 01399 int do_cast_identify(object *tmp, object *op, int mode, int *done, int level) 01400 { 01401 if (QUERY_FLAG(tmp, FLAG_IDENTIFIED) || IS_SYS_INVISIBLE(tmp) || !need_identify(tmp)) 01402 { 01403 return 1; 01404 } 01405 01406 if (level < tmp->level) 01407 { 01408 if (op->type == PLAYER) 01409 { 01410 new_draw_info_format(0, COLOR_WHITE, op, "The %s is too powerful for this identify!", query_base_name(tmp, NULL)); 01411 } 01412 } 01413 else 01414 { 01415 identify(tmp); 01416 01417 if (op->type == PLAYER) 01418 { 01419 new_draw_info_format(0, COLOR_WHITE, op, "You have %s.", long_desc(tmp, NULL)); 01420 01421 if (tmp->msg) 01422 { 01423 new_draw_info(0, COLOR_WHITE, op, "The item has a story:"); 01424 new_draw_info(0, COLOR_WHITE, op, tmp->msg); 01425 } 01426 } 01427 01428 *done += 1; 01429 } 01430 01431 if (mode == IDENTIFY_NORMAL && op->type == PLAYER && *done > CONTR(op)->skill_ptr[SK_LITERACY]->level + op->stats.Int) 01432 { 01433 return 0; 01434 } 01435 01436 return 1; 01437 } 01438 01448 int cast_identify(object *op, int level, object *single_ob, int mode) 01449 { 01450 int done = 0; 01451 01452 insert_spell_effect(spells[SP_IDENTIFY].archname, op->map, op->x, op->y); 01453 01454 if (mode == IDENTIFY_MARKED) 01455 { 01456 do_cast_identify(single_ob, op, mode, &done, level); 01457 } 01458 else 01459 { 01460 object *tmp = op->inv; 01461 01462 if (single_ob && single_ob->type == CONTAINER) 01463 { 01464 tmp = single_ob->inv; 01465 } 01466 01467 for ( ; tmp; tmp = tmp->below) 01468 { 01469 if (!do_cast_identify(tmp, op, mode, &done, level)) 01470 { 01471 break; 01472 } 01473 } 01474 } 01475 01476 if (op->type == PLAYER && !done) 01477 { 01478 new_draw_info(0, COLOR_WHITE, op, "You can't reach anything unidentified in your inventory."); 01479 } 01480 01481 return done; 01482 } 01483 01489 int cast_consecrate(object *op) 01490 { 01491 object *tmp, *god = find_god(determine_god(op)); 01492 01493 if (!god) 01494 { 01495 new_draw_info(0, COLOR_WHITE, op, "You can't consecrate anything if you don't worship a god!"); 01496 return 0; 01497 } 01498 01499 for (tmp = op->below; tmp; tmp = tmp->below) 01500 { 01501 if (QUERY_FLAG(tmp, FLAG_IS_FLOOR)) 01502 { 01503 break; 01504 } 01505 01506 if (tmp->type == HOLY_ALTAR) 01507 { 01508 /* We use SK_level here instead of path_level mod because I think 01509 * all the gods should give equal chance of re-consecrating altars */ 01510 if (tmp->level > SK_level(op)) 01511 { 01512 new_draw_info_format(0, COLOR_WHITE, op, "You are not powerful enough to reconsecrate the %s.", tmp->name); 01513 return 0; 01514 } 01515 else if (tmp->other_arch == god->arch) 01516 { 01517 new_draw_info_format(0, COLOR_WHITE, op, "That altar is already consecrated to %s.", god->name); 01518 return 0; 01519 } 01520 else 01521 { 01522 char buf[MAX_BUF], *cp; 01523 object *new_altar; 01524 01525 snprintf(buf, sizeof(buf), "altar_%s", god->name); 01526 01527 for (cp = buf; *cp != '\0'; cp++) 01528 { 01529 *cp = tolower(*cp); 01530 } 01531 01532 new_altar = get_archetype(buf); 01533 new_altar->level = tmp->level; 01534 new_altar->x = tmp->x; 01535 new_altar->y = tmp->y; 01536 new_altar->direction = tmp->direction; 01537 01538 if (QUERY_FLAG(new_altar, FLAG_IS_TURNABLE)) 01539 { 01540 SET_ANIMATION(new_altar, (NUM_ANIMATIONS(new_altar) / NUM_FACINGS(new_altar)) * new_altar->direction); 01541 } 01542 01543 if (QUERY_FLAG(tmp, FLAG_IS_BUILDABLE)) 01544 { 01545 SET_FLAG(new_altar, FLAG_IS_BUILDABLE); 01546 } 01547 01548 insert_ob_in_map(new_altar, tmp->map, NULL, 0); 01549 remove_ob(tmp); 01550 01551 new_draw_info_format(0, COLOR_WHITE, op, "You consecrated the altar to %s!", god->name); 01552 return 1; 01553 } 01554 } 01555 } 01556 01557 new_draw_info(0, COLOR_WHITE, op, "You are not standing over an altar!"); 01558 return 0; 01559 } 01560 01569 int finger_of_death(object *op, object *target) 01570 { 01571 object *hitter; 01572 int dam; 01573 01574 if (QUERY_FLAG(target, FLAG_UNDEAD)) 01575 { 01576 new_draw_info_format(0, COLOR_WHITE, op, "The %s looks stronger!", query_name(target, NULL)); 01577 target->stats.hp = target->stats.maxhp; 01578 01579 if (!OBJECT_VALID(target->enemy, target->enemy_count)) 01580 { 01581 set_npc_enemy(target, op, NULL); 01582 } 01583 01584 return 1; 01585 } 01586 01587 /* We create a hitter object -- the spell */ 01588 hitter = arch_to_object(spellarch[SP_FINGER_DEATH]); 01589 hitter->level = SK_level(op); 01590 set_owner(hitter, op); 01591 hitter->x = target->x; 01592 hitter->y = target->y; 01593 insert_ob_in_map(hitter, target->map, op, 0); 01594 01595 if (spell_attack_missed(hitter, target)) 01596 { 01597 new_draw_info_format(0, COLOR_ORANGE, op, "Your finger of death misses %s!", target->name); 01598 remove_ob(hitter); 01599 return 1; 01600 } 01601 01602 dam = SP_level_dam_adjust(op, SP_FINGER_DEATH, spells[SP_FINGER_DEATH].bdam, 0); 01603 hit_player(target, dam, hitter, AT_INTERNAL); 01604 remove_ob(hitter); 01605 01606 return 1; 01607 } 01608 01618 int cast_cause_disease(object *op, object *caster, int dir, archetype *disease_arch, int type) 01619 { 01620 int x = op->x, y = op->y, i, xt, yt; 01621 object *walk; 01622 mapstruct *m; 01623 01624 /* Search in a line for a victim */ 01625 for (i = 0; i < 5; i++) 01626 { 01627 x += freearr_x[dir]; 01628 y += freearr_y[dir]; 01629 xt = x; 01630 yt = y; 01631 01632 if (!(m = get_map_from_coord(op->map, &xt, &yt))) 01633 { 01634 continue; 01635 } 01636 01637 /* Check map flags for alive object */ 01638 if (!(GET_MAP_FLAGS(m, xt, yt) & P_IS_ALIVE)) 01639 { 01640 continue; 01641 } 01642 01643 /* Search this square for a victim */ 01644 for (walk = GET_MAP_OB(m, xt, yt); walk; walk = walk->above) 01645 { 01646 object *disease; 01647 int dam, strength; 01648 01649 /* Found a victim */ 01650 if (!QUERY_FLAG(walk, FLAG_MONSTER) && (walk->type != PLAYER || !pvp_area(op, walk))) 01651 { 01652 continue; 01653 } 01654 01655 disease = arch_to_object(disease_arch); 01656 dam = SP_level_dam_adjust(caster, type, spells[type].bdam, 0); 01657 strength = SP_level_strength_adjust(caster, type); 01658 01659 set_owner(disease, op); 01660 disease->stats.exp = 0; 01661 disease->level = SK_level(caster); 01662 01663 /* Try to get the experience into the correct category */ 01664 if (op->chosen_skill && op->chosen_skill->exp_obj) 01665 { 01666 disease->exp_obj = op->chosen_skill->exp_obj; 01667 } 01668 01669 /* Do level adjustments */ 01670 if (disease->stats.wc) 01671 { 01672 disease->stats.wc += strength / 2; 01673 } 01674 01675 if (disease->magic > 0) 01676 { 01677 disease->magic += strength / 4; 01678 } 01679 01680 if (disease->stats.maxhp > 0) 01681 { 01682 disease->stats.maxhp += strength; 01683 } 01684 01685 if (disease->stats.maxgrace > 0) 01686 { 01687 disease->stats.maxgrace += strength; 01688 } 01689 01690 if (disease->stats.dam) 01691 { 01692 if (disease->stats.dam > 0) 01693 { 01694 disease->stats.dam += dam; 01695 } 01696 else 01697 { 01698 disease->stats.dam -= dam; 01699 } 01700 } 01701 01702 if (disease->last_sp) 01703 { 01704 disease->last_sp -= 2 * dam; 01705 01706 if (disease->last_sp < 1) 01707 { 01708 disease->last_sp = 1; 01709 } 01710 } 01711 01712 if (disease->stats.maxsp) 01713 { 01714 if (disease->stats.maxsp > 0) 01715 { 01716 disease->stats.maxsp += dam; 01717 } 01718 else 01719 { 01720 disease->stats.maxsp -= dam; 01721 } 01722 } 01723 01724 if (disease->stats.ac) 01725 { 01726 disease->stats.ac += dam; 01727 } 01728 01729 if (disease->last_eat) 01730 { 01731 disease->last_eat -= dam; 01732 } 01733 01734 if (disease->stats.hp) 01735 { 01736 disease->stats.hp -= dam; 01737 } 01738 01739 if (disease->stats.sp) 01740 { 01741 disease->stats.sp -= dam; 01742 } 01743 01744 if (infect_object(walk, disease, 1)) 01745 { 01746 new_draw_info_format(0, COLOR_WHITE, op, "You inflict %s on %s!", disease->name, walk->name); 01747 return 1; 01748 } 01749 } 01750 01751 /* No more infecting through walls. */ 01752 if (wall(m, xt, yt)) 01753 { 01754 return 0; 01755 } 01756 } 01757 01758 new_draw_info(0, COLOR_WHITE, op, "No one caught anything!"); 01759 return 0; 01760 } 01761 01766 int cast_transform_wealth(object *op) 01767 { 01768 object *marked; 01769 sint64 val; 01770 01771 if (op->type != PLAYER) 01772 { 01773 return 0; 01774 } 01775 01776 /* Find the marked wealth. */ 01777 marked = find_marked_object(op); 01778 01779 if (!marked) 01780 { 01781 new_draw_info(0, COLOR_WHITE, op, "You need to mark an object to cast this spell."); 01782 return 0; 01783 } 01784 01785 /* Check that it's really money. */ 01786 if (marked->type != MONEY) 01787 { 01788 new_draw_info(0, COLOR_WHITE, op, "You can only cast this spell on wealth objects."); 01789 return 0; 01790 } 01791 01792 /* Only allow coppers and silvers to be transformed. */ 01793 if (strcmp(marked->arch->name, coins[NUM_COINS - 1]) && strcmp(marked->arch->name, coins[NUM_COINS - 2])) 01794 { 01795 new_draw_info_format(0, COLOR_WHITE, op, "You don't see a way to transform %s.", query_name(marked, op)); 01796 return 0; 01797 } 01798 01799 /* Figure out our value of money to give to player. */ 01800 val = (marked->value * (marked->nrof ? marked->nrof : 1)) * TRANSFORM_WEALTH_SACRIFICE; 01801 /* We remove the money. */ 01802 remove_ob(marked); 01803 esrv_del_item(CONTR(op), marked->count, marked->env); 01804 /* Now give the player the new money. */ 01805 insert_coins(op, val); 01806 new_draw_info_format(0, COLOR_WHITE, op, "You transform %s into %s.", query_name(marked, op), cost_string_from_value(val)); 01807 return 1; 01808 }
1.7.4