… | |
… | |
122 | * The # of arrows created also goes up with level, so if a 30th level mage |
122 | * The # of arrows created also goes up with level, so if a 30th level mage |
123 | * wants LOTS of arrows, and doesn't care what the plus is he could |
123 | * wants LOTS of arrows, and doesn't care what the plus is he could |
124 | * create nonnmagic arrows, or even -1, etc... |
124 | * create nonnmagic arrows, or even -1, etc... |
125 | */ |
125 | */ |
126 | int |
126 | int |
127 | cast_create_missile (object *op, object *caster, object *spell, int dir, const char *stringarg) |
127 | cast_create_missile (object *op, object *caster, object *spell, int dir, const char *spellparam) |
128 | { |
128 | { |
129 | int bonus_plus = 0; |
129 | int bonus_plus = 0; |
130 | const char *missile_name = "arrow"; |
130 | const char *missile_name = "arrow"; |
131 | |
131 | |
132 | for (object *tmp = op->inv; tmp; tmp = tmp->below) |
132 | for (object *tmp = op->inv; tmp; tmp = tmp->below) |
… | |
… | |
143 | return 0; |
143 | return 0; |
144 | } |
144 | } |
145 | |
145 | |
146 | object *missile = missile_arch->instance (); |
146 | object *missile = missile_arch->instance (); |
147 | |
147 | |
148 | if (stringarg) |
148 | if (spellparam) |
149 | { |
149 | { |
150 | /* If it starts with a letter, presume it is a description */ |
150 | /* If it starts with a letter, presume it is a description */ |
151 | if (isalpha (*stringarg)) |
151 | if (isalpha (*spellparam)) |
152 | { |
152 | { |
153 | artifact *al = find_artifactlist (missile->type)->items; |
153 | artifact *al = find_artifactlist (missile->type)->items; |
154 | |
154 | |
155 | for (; al; al = al->next) |
155 | for (; al; al = al->next) |
156 | if (!strcasecmp (al->item->name, stringarg)) |
156 | if (!strcasecmp (al->item->name, spellparam)) |
157 | break; |
157 | break; |
158 | |
158 | |
159 | if (!al) |
159 | if (!al) |
160 | { |
160 | { |
161 | missile->destroy (); |
161 | missile->destroy (); |
162 | new_draw_info_format (NDI_UNIQUE, 0, op, "No such object %ss of %s", missile_name, stringarg); |
162 | new_draw_info_format (NDI_UNIQUE, 0, op, "No such object %ss of %s", missile_name, spellparam); |
163 | return 0; |
163 | return 0; |
164 | } |
164 | } |
165 | |
165 | |
166 | if (al->item->slaying) |
166 | if (al->item->slaying) |
167 | { |
167 | { |
168 | missile->destroy (); |
168 | missile->destroy (); |
169 | new_draw_info_format (NDI_UNIQUE, 0, op, "You are not allowed to create %ss of %s", missile_name, stringarg); |
169 | new_draw_info_format (NDI_UNIQUE, 0, op, "You are not allowed to create %ss of %s", missile_name, spellparam); |
170 | return 0; |
170 | return 0; |
171 | } |
171 | } |
172 | |
172 | |
173 | give_artifact_abilities (missile, al->item); |
173 | give_artifact_abilities (missile, al->item); |
174 | /* These special arrows cost something extra. Don't have them also be magical - |
174 | /* These special arrows cost something extra. Don't have them also be magical - |
… | |
… | |
176 | * the parsing of having to do both plus and type. |
176 | * the parsing of having to do both plus and type. |
177 | */ |
177 | */ |
178 | bonus_plus = 1 + (al->item->value / 5); |
178 | bonus_plus = 1 + (al->item->value / 5); |
179 | missile_plus = 0; |
179 | missile_plus = 0; |
180 | } |
180 | } |
181 | else if (atoi (stringarg) < missile_plus) |
181 | else if (atoi (spellparam) < missile_plus) |
182 | missile_plus = atoi (stringarg); |
182 | missile_plus = atoi (spellparam); |
183 | } |
183 | } |
184 | |
184 | |
185 | missile_plus = clamp (missile_plus, -4, 4); |
185 | missile_plus = clamp (missile_plus, -4, 4); |
186 | |
186 | |
187 | missile->nrof = spell->duration + SP_level_duration_adjust (caster, spell); |
187 | missile->nrof = spell->duration + SP_level_duration_adjust (caster, spell); |
… | |
… | |
202 | return 1; |
202 | return 1; |
203 | } |
203 | } |
204 | |
204 | |
205 | |
205 | |
206 | /* allows the choice of what sort of food object to make. |
206 | /* allows the choice of what sort of food object to make. |
207 | * If stringarg is NULL, it will create food dependent on level --PeterM*/ |
207 | * If spellparam is NULL, it will create food dependent on level --PeterM*/ |
208 | int |
208 | int |
209 | cast_create_food (object *op, object *caster, object *spell_ob, int dir, const char *stringarg) |
209 | cast_create_food (object *op, object *caster, object *spell_ob, int dir, const char *spellparam) |
210 | { |
210 | { |
211 | int food_value; |
211 | int food_value; |
212 | archetype *at = NULL; |
212 | archetype *at = NULL; |
213 | object *new_op; |
213 | object *new_op; |
214 | |
214 | |
215 | food_value = spell_ob->stats.food + 50 * SP_level_duration_adjust (caster, spell_ob); |
215 | food_value = spell_ob->stats.food + 50 * SP_level_duration_adjust (caster, spell_ob); |
216 | |
216 | |
217 | if (stringarg) |
217 | if (spellparam) |
218 | { |
218 | { |
219 | at = find_archetype_by_object_type_name (FOOD, stringarg); |
219 | at = find_archetype_by_object_type_name (FOOD, spellparam); |
220 | if (at == NULL) |
220 | if (at == NULL) |
221 | at = find_archetype_by_object_type_name (DRINK, stringarg); |
221 | at = find_archetype_by_object_type_name (DRINK, spellparam); |
222 | if (at == NULL || at->stats.food > food_value) |
222 | if (at == NULL || at->stats.food > food_value) |
223 | stringarg = NULL; |
223 | spellparam = NULL; |
224 | } |
224 | } |
225 | |
225 | |
226 | if (!stringarg) |
226 | if (!spellparam) |
227 | { |
227 | { |
228 | archetype *at_tmp; |
228 | archetype *at_tmp; |
229 | |
229 | |
230 | /* We try to find the archetype with the maximum food value. |
230 | /* We try to find the archetype with the maximum food value. |
231 | * This removes the dependancy of hard coded food values in this |
231 | * This removes the dependancy of hard coded food values in this |
… | |
… | |
345 | |
345 | |
346 | return 1; |
346 | return 1; |
347 | } |
347 | } |
348 | |
348 | |
349 | /* invis_race is set if we get here */ |
349 | /* invis_race is set if we get here */ |
350 | if (!strcmp (pl->contr->invis_race, "undead") && is_true_undead (mon)) |
350 | if (pl->contr->invis_race == shstr_undead && is_true_undead (mon)) |
351 | return 1; |
351 | return 1; |
352 | |
352 | |
353 | /* No race, can't be invisible to it */ |
353 | /* No race, can't be invisible to it */ |
354 | if (!mon->race) |
354 | if (!mon->race) |
355 | return 0; |
355 | return 0; |
… | |
… | |
425 | /* earth to dust spell. Basically destroys earthwalls in the area. |
425 | /* earth to dust spell. Basically destroys earthwalls in the area. |
426 | */ |
426 | */ |
427 | int |
427 | int |
428 | cast_earth_to_dust (object *op, object *caster, object *spell_ob) |
428 | cast_earth_to_dust (object *op, object *caster, object *spell_ob) |
429 | { |
429 | { |
430 | object *tmp, *next; |
|
|
431 | int range, i, j, mflags; |
430 | int range, i, j, mflags; |
432 | sint16 sx, sy; |
431 | sint16 sx, sy; |
433 | maptile *m; |
432 | maptile *m; |
434 | |
|
|
435 | if (op->type != PLAYER) |
|
|
436 | return 0; |
|
|
437 | |
433 | |
438 | range = spell_ob->range + SP_level_range_adjust (caster, spell_ob); |
434 | range = spell_ob->range + SP_level_range_adjust (caster, spell_ob); |
439 | |
435 | |
440 | for (i = -range; i <= range; i++) |
436 | for (i = -range; i <= range; i++) |
441 | for (j = -range; j <= range; j++) |
437 | for (j = -range; j <= range; j++) |
… | |
… | |
446 | mflags = get_map_flags (m, &m, sx, sy, &sx, &sy); |
442 | mflags = get_map_flags (m, &m, sx, sy, &sx, &sy); |
447 | |
443 | |
448 | if (mflags & P_OUT_OF_MAP) |
444 | if (mflags & P_OUT_OF_MAP) |
449 | continue; |
445 | continue; |
450 | |
446 | |
451 | // earth to dust tears down everything that can be teared down |
447 | // earth to dust tears down everything that can be torn down |
452 | for (tmp = GET_MAP_OB (m, sx, sy); tmp != NULL; tmp = next) |
448 | for (object *next, *tmp = m->at (sx, sy).bot; tmp; tmp = next) |
453 | { |
449 | { |
454 | next = tmp->above; |
450 | next = tmp->above; |
|
|
451 | |
455 | if (QUERY_FLAG (tmp, FLAG_TEAR_DOWN)) |
452 | if (QUERY_FLAG (tmp, FLAG_TEAR_DOWN)) |
456 | hit_player (tmp, 9998, op, AT_PHYSICAL, 0); |
453 | hit_player (tmp, 9998, op, AT_PHYSICAL, 0); |
457 | } |
454 | } |
458 | } |
455 | } |
459 | |
456 | |
… | |
… | |
569 | perceive_self (object *op) |
566 | perceive_self (object *op) |
570 | { |
567 | { |
571 | const char *cp = describe_item (op, op); |
568 | const char *cp = describe_item (op, op); |
572 | archetype *at = archetype::find (ARCH_DEPLETION); |
569 | archetype *at = archetype::find (ARCH_DEPLETION); |
573 | |
570 | |
574 | dynbuf_text buf; |
571 | dynbuf_text &buf = msg_dynbuf; buf.clear (); |
575 | |
572 | |
576 | if (player *pl = op->contr) |
573 | if (!op->is_player ()) |
|
|
574 | return 0; |
|
|
575 | |
577 | if (object *race = archetype::find (op->race)) |
576 | if (object *race = archetype::find (op->race)) |
578 | buf << " - You are a G<male|female> " << &race->name << ".\n"; |
577 | buf << " - You are a G<male|female> " << &race->name << ".\n"; |
579 | |
578 | |
580 | if (object *god = find_god (determine_god (op))) |
579 | if (object *god = find_god (determine_god (op))) |
581 | buf << " - You worship " << &god->name << ".\n"; |
580 | buf << " - You worship " << &god->name << ".\n"; |
582 | else |
581 | else |
583 | buf << " - You worship no god.\n"; |
582 | buf << " - You worship no god.\n"; |
… | |
… | |
609 | |
608 | |
610 | break; |
609 | break; |
611 | } |
610 | } |
612 | } |
611 | } |
613 | |
612 | |
614 | buf << '\0'; // zero-terminate |
613 | op->contr->infobox (MSG_CHANNEL ("perceiveself"), buf); |
615 | |
|
|
616 | new_draw_info (NDI_UNIQUE, 0, op, buf.linearise ()); |
|
|
617 | |
614 | |
618 | return 1; |
615 | return 1; |
619 | } |
616 | } |
620 | |
617 | |
621 | /* This creates magic walls. Really, it can create most any object, |
618 | /* This creates magic walls. Really, it can create most any object, |
… | |
… | |
780 | |
777 | |
781 | return 1; |
778 | return 1; |
782 | } |
779 | } |
783 | |
780 | |
784 | int |
781 | int |
785 | dimension_door (object *op, object *caster, object *spob, int dir) |
782 | dimension_door (object *op, object *caster, object *spob, int dir, const char *spellparam) |
786 | { |
783 | { |
787 | uint32 dist, maxdist; |
784 | uint32 dist, maxdist; |
788 | int mflags; |
785 | int mflags; |
789 | maptile *m; |
786 | maptile *m; |
790 | sint16 sx, sy; |
787 | sint16 sx, sy; |
… | |
… | |
801 | /* Given the new outdoor maps, can't let players dimension door for |
798 | /* Given the new outdoor maps, can't let players dimension door for |
802 | * ever, so put limits in. |
799 | * ever, so put limits in. |
803 | */ |
800 | */ |
804 | maxdist = spob->range + SP_level_range_adjust (caster, spob); |
801 | maxdist = spob->range + SP_level_range_adjust (caster, spob); |
805 | |
802 | |
806 | if (op->contr->count) |
803 | if (spellparam) |
807 | { |
804 | { |
|
|
805 | int count = atoi (spellparam); |
|
|
806 | |
808 | if (op->contr->count > maxdist) |
807 | if (count > maxdist) |
809 | { |
808 | { |
810 | new_draw_info (NDI_UNIQUE, 0, op, "You can't dimension door that far!"); |
809 | new_draw_info (NDI_UNIQUE, 0, op, "You can't dimension door that far!"); |
811 | return 0; |
810 | return 0; |
812 | } |
811 | } |
813 | |
812 | |
814 | for (dist = 0; dist < op->contr->count; dist++) |
813 | for (dist = 0; dist < count; dist++) |
815 | { |
814 | { |
816 | mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy); |
815 | mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy); |
817 | |
816 | |
818 | if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP)) |
817 | if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP)) |
819 | break; |
818 | break; |
820 | |
819 | |
821 | if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy))) |
820 | if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy))) |
822 | break; |
821 | break; |
823 | } |
822 | } |
824 | |
823 | |
825 | if (dist < op->contr->count) |
824 | if (dist < count) |
826 | { |
825 | { |
827 | new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the spell.\n"); |
826 | new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the spell.\n"); |
828 | op->contr->count = 0; |
|
|
829 | return 0; |
827 | return 0; |
830 | } |
828 | } |
831 | |
|
|
832 | op->contr->count = 0; |
|
|
833 | |
829 | |
834 | /* Remove code that puts player on random space on maps. IMO, |
830 | /* Remove code that puts player on random space on maps. IMO, |
835 | * a lot of maps probably have areas the player should not get to, |
831 | * a lot of maps probably have areas the player should not get to, |
836 | * but may not be marked as NO_MAGIC (as they may be bounded |
832 | * but may not be marked as NO_MAGIC (as they may be bounded |
837 | * by such squares). Also, there are probably treasure rooms and |
833 | * by such squares). Also, there are probably treasure rooms and |
… | |
… | |
1034 | "You don't feel any more powerful." |
1030 | "You don't feel any more powerful." |
1035 | "You are no easier to look at.", |
1031 | "You are no easier to look at.", |
1036 | }; |
1032 | }; |
1037 | |
1033 | |
1038 | int |
1034 | int |
|
|
1035 | change_ability_duration (object *spell, object *caster) |
|
|
1036 | { |
|
|
1037 | return spell->duration + SP_level_duration_adjust (caster, spell) * 50; |
|
|
1038 | } |
|
|
1039 | |
|
|
1040 | int |
1039 | cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent) |
1041 | cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent) |
1040 | { |
1042 | { |
1041 | object *force = 0; |
1043 | object *force = 0; |
1042 | int i; |
1044 | int i; |
1043 | |
1045 | |
… | |
… | |
1083 | new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force."); |
1085 | new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force."); |
1084 | |
1086 | |
1085 | } |
1087 | } |
1086 | else |
1088 | else |
1087 | { |
1089 | { |
1088 | int duration; |
1090 | int duration = change_ability_duration (spell_ob, caster); |
1089 | |
1091 | |
1090 | duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50; |
|
|
1091 | if (duration > force->duration) |
1092 | if (duration > force->duration) |
1092 | { |
1093 | { |
1093 | force->duration = duration; |
1094 | force->duration = duration; |
1094 | new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect."); |
1095 | new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect."); |
1095 | } |
1096 | } |
… | |
… | |
1418 | * items. |
1419 | * items. |
1419 | */ |
1420 | */ |
1420 | int |
1421 | int |
1421 | remove_curse (object *op, object *caster, object *spell) |
1422 | remove_curse (object *op, object *caster, object *spell) |
1422 | { |
1423 | { |
1423 | object *tmp; |
|
|
1424 | int success = 0, was_one = 0; |
1424 | int success = 0, was_one = 0; |
1425 | |
1425 | |
1426 | for (tmp = op->inv; tmp; tmp = tmp->below) |
1426 | for (object *tmp = op->inv; tmp; tmp = tmp->below) |
1427 | if (QUERY_FLAG (tmp, FLAG_APPLIED) && |
1427 | if (QUERY_FLAG (tmp, FLAG_APPLIED) && |
1428 | ((QUERY_FLAG (tmp, FLAG_CURSED) && QUERY_FLAG (spell, FLAG_CURSED)) || |
1428 | ((QUERY_FLAG (tmp, FLAG_CURSED) && QUERY_FLAG (spell, FLAG_CURSED)) || |
1429 | (QUERY_FLAG (tmp, FLAG_DAMNED) && QUERY_FLAG (spell, FLAG_DAMNED)))) |
1429 | (QUERY_FLAG (tmp, FLAG_DAMNED) && QUERY_FLAG (spell, FLAG_DAMNED)))) |
1430 | { |
1430 | { |
1431 | was_one++; |
1431 | was_one++; |
… | |
… | |
1463 | |
1463 | |
1464 | /* Identifies objects in the players inventory/on the ground */ |
1464 | /* Identifies objects in the players inventory/on the ground */ |
1465 | int |
1465 | int |
1466 | cast_identify (object *op, object *caster, object *spell) |
1466 | cast_identify (object *op, object *caster, object *spell) |
1467 | { |
1467 | { |
1468 | dynbuf_text buf; |
|
|
1469 | object *tmp; |
1468 | object *tmp; |
|
|
1469 | dynbuf_text &buf = msg_dynbuf; buf.clear (); |
1470 | |
1470 | |
1471 | int num_ident = spell->stats.dam + SP_level_dam_adjust (caster, spell); |
1471 | int num_ident = max (1, spell->stats.dam + SP_level_dam_adjust (caster, spell)); |
1472 | |
|
|
1473 | if (num_ident < 1) |
|
|
1474 | num_ident = 1; |
|
|
1475 | |
1472 | |
1476 | for (tmp = op->inv; tmp; tmp = tmp->below) |
1473 | for (tmp = op->inv; tmp; tmp = tmp->below) |
1477 | { |
1474 | { |
1478 | if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp)) |
1475 | if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp)) |
1479 | { |
1476 | { |
… | |
… | |
1485 | |
1482 | |
1486 | if (tmp->msg) |
1483 | if (tmp->msg) |
1487 | buf << "The item has a story:\r" << tmp->msg << "\n\n"; |
1484 | buf << "The item has a story:\r" << tmp->msg << "\n\n"; |
1488 | } |
1485 | } |
1489 | |
1486 | |
1490 | num_ident--; |
|
|
1491 | if (!num_ident) |
1487 | if (!--num_ident) |
1492 | break; |
1488 | break; |
1493 | } |
1489 | } |
1494 | } |
1490 | } |
1495 | |
1491 | |
1496 | /* If all the power of the spell has been used up, don't go and identify |
1492 | /* If all the power of the spell has been used up, don't go and identify |
… | |
… | |
1510 | |
1506 | |
1511 | if (tmp->msg) |
1507 | if (tmp->msg) |
1512 | buf << "The item has a story:\r" << tmp->msg << "\n\n"; |
1508 | buf << "The item has a story:\r" << tmp->msg << "\n\n"; |
1513 | } |
1509 | } |
1514 | |
1510 | |
1515 | num_ident--; |
|
|
1516 | if (!num_ident) |
1511 | if (!--num_ident) |
1517 | break; |
1512 | break; |
1518 | } |
1513 | } |
1519 | } |
1514 | } |
1520 | |
1515 | |
1521 | if (buf.empty ()) |
1516 | if (buf.empty ()) |
… | |
… | |
1549 | range = spell->range + SP_level_range_adjust (caster, spell); |
1544 | range = spell->range + SP_level_range_adjust (caster, spell); |
1550 | |
1545 | |
1551 | if (!skill) |
1546 | if (!skill) |
1552 | skill = caster; |
1547 | skill = caster; |
1553 | |
1548 | |
1554 | for (x = op->x - range; x <= op->x + range; x++) |
1549 | unordered_mapwalk (op, -range, -range, range, range) |
1555 | for (y = op->y - range; y <= op->y + range; y++) |
|
|
1556 | { |
1550 | { |
1557 | m = op->map; |
|
|
1558 | mflags = get_map_flags (m, &m, x, y, &nx, &ny); |
|
|
1559 | if (mflags & P_OUT_OF_MAP) |
|
|
1560 | continue; |
|
|
1561 | |
|
|
1562 | /* For most of the detections, we only detect objects above the |
1551 | /* For most of the detections, we only detect objects above the |
1563 | * floor. But this is not true for show invisible. |
1552 | * floor. But this is not true for show invisible. |
1564 | * Basically, we just go and find the top object and work |
1553 | * Basically, we just go and find the top object and work |
1565 | * down - that is easier than working up. |
1554 | * down - that is easier than working up. |
1566 | */ |
1555 | */ |
1567 | |
1556 | |
1568 | for (last = NULL, tmp = GET_MAP_OB (m, nx, ny); tmp; tmp = tmp->above) |
1557 | for (last = NULL, tmp = m->at (nx, ny).bot; tmp; tmp = tmp->above) |
1569 | last = tmp; |
1558 | last = tmp; |
1570 | |
1559 | |
1571 | /* Shouldn't happen, but if there are no objects on a space, this |
1560 | /* Shouldn't happen, but if there are no objects on a space, this |
1572 | * would happen. |
1561 | * would happen. |
1573 | */ |
1562 | */ |
1574 | if (!last) |
1563 | if (!last) |
1575 | continue; |
1564 | continue; |
1576 | |
1565 | |
1577 | done_one = 0; |
1566 | done_one = 0; |
1578 | floor = 0; |
1567 | floor = 0; |
1579 | detect = NULL; |
1568 | detect = NULL; |
1580 | for (tmp = last; tmp; tmp = tmp->below) |
1569 | for (tmp = last; tmp; tmp = tmp->below) |
1581 | { |
1570 | { |
1582 | /* show invisible */ |
1571 | /* show invisible */ |
1583 | if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) && |
1572 | if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) && |
1584 | /* Might there be other objects that we can make visible? */ |
1573 | /* Might there be other objects that we can make visible? */ |
1585 | (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER) || |
1574 | (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER) |
1586 | (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ)) || |
1575 | || (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ)) |
1587 | tmp->type == CF_HANDLE || |
1576 | || tmp->type == CF_HANDLE |
1588 | tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE || |
1577 | || tmp->type == TRAPDOOR |
|
|
1578 | || tmp->type == EXIT |
|
|
1579 | || tmp->type == HOLE |
|
|
1580 | || tmp->type == BUTTON |
1589 | tmp->type == BUTTON || tmp->type == TELEPORTER || |
1581 | || tmp->type == TELEPORTER |
|
|
1582 | || tmp->type == GATE |
1590 | tmp->type == GATE || tmp->type == LOCKED_DOOR || |
1583 | || tmp->type == LOCKED_DOOR |
1591 | tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN || |
1584 | || tmp->type == WEAPON |
|
|
1585 | || tmp->type == ALTAR |
|
|
1586 | || tmp->type == SIGN |
1592 | tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY || |
1587 | || tmp->type == TRIGGER_PEDESTAL |
1593 | tmp->type == TREASURE || tmp->type == BOOK || tmp->type == HOLY_ALTAR))) |
1588 | || tmp->type == SPECIAL_KEY |
|
|
1589 | || tmp->type == TREASURE |
|
|
1590 | || tmp->type == BOOK |
|
|
1591 | || tmp->type == HOLY_ALTAR |
|
|
1592 | || tmp->type == CONTAINER))) |
1594 | { |
1593 | { |
1595 | if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4) |
1594 | if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4) |
1596 | { |
1595 | { |
1597 | tmp->invisible = 0; |
1596 | tmp->invisible = 0; |
1598 | done_one = 1; |
1597 | done_one = 1; |
1599 | } |
1598 | } |
1600 | } |
1599 | } |
1601 | |
1600 | |
1602 | if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) |
1601 | if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) |
1603 | floor = 1; |
1602 | floor = 1; |
1604 | |
1603 | |
1605 | /* All detections below this point don't descend beneath the floor, |
1604 | /* All detections below this point don't descend beneath the floor, |
1606 | * so just continue on. We could be clever and look at the type of |
1605 | * so just continue on. We could be clever and look at the type of |
1607 | * detection to completely break out if we don't care about objects beneath |
1606 | * detection to completely break out if we don't care about objects beneath |
1608 | * the floor, but once we get to the floor, not likely a very big issue anyways. |
1607 | * the floor, but once we get to the floor, not likely a very big issue anyways. |
1609 | */ |
1608 | */ |
1610 | if (floor) |
1609 | if (floor) |
1611 | continue; |
1610 | continue; |
1612 | |
1611 | |
1613 | /* I had thought about making detect magic and detect curse |
1612 | /* I had thought about making detect magic and detect curse |
1614 | * show the flash the magic item like it does for detect monster. |
1613 | * show the flash the magic item like it does for detect monster. |
1615 | * however, if the object is within sight, this would then make it |
1614 | * however, if the object is within sight, this would then make it |
1616 | * difficult to see what object is magical/cursed, so the |
1615 | * difficult to see what object is magical/cursed, so the |
1617 | * effect wouldn't be as apparant. |
1616 | * effect wouldn't be as apparent. |
1618 | */ |
1617 | */ |
1619 | |
1618 | |
1620 | /* detect magic */ |
1619 | /* detect magic */ |
1621 | if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && |
1620 | if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && |
1622 | !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp)) |
1621 | !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp)) |
1623 | { |
1622 | { |
1624 | SET_FLAG (tmp, FLAG_KNOWN_MAGICAL); |
1623 | SET_FLAG (tmp, FLAG_KNOWN_MAGICAL); |
1625 | /* make runes more visibile */ |
1624 | /* make runes more visibile */ |
1626 | if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC) |
1625 | if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC) |
1627 | tmp->stats.Cha /= 4; |
1626 | tmp->stats.Cha /= 4; |
|
|
1627 | |
1628 | done_one = 1; |
1628 | done_one = 1; |
1629 | } |
1629 | } |
|
|
1630 | |
1630 | /* detect monster */ |
1631 | /* detect monster */ |
1631 | if (QUERY_FLAG (spell, FLAG_MONSTER) && (QUERY_FLAG (tmp, FLAG_MONSTER) || tmp->type == PLAYER)) |
1632 | if (QUERY_FLAG (spell, FLAG_MONSTER) && (QUERY_FLAG (tmp, FLAG_MONSTER) || tmp->type == PLAYER)) |
1632 | { |
1633 | { |
1633 | done_one = 2; |
1634 | done_one = 2; |
|
|
1635 | |
1634 | if (!detect) |
1636 | if (!detect) |
1635 | detect = tmp; |
1637 | detect = tmp; |
1636 | } |
1638 | } |
|
|
1639 | |
1637 | /* Basically, if race is set in the spell, then the creatures race must |
1640 | /* Basically, if race is set in the spell, then the creatures race must |
1638 | * match that. if the spell race is set to GOD, then the gods opposing |
1641 | * match that. if the spell race is set to GOD, then the gods opposing |
1639 | * race must match. |
1642 | * race must match. |
1640 | */ |
1643 | */ |
1641 | if (spell->race && QUERY_FLAG (tmp, FLAG_MONSTER) && tmp->race && |
1644 | if (spell->race && QUERY_FLAG (tmp, FLAG_MONSTER) && tmp->race && |
1642 | ((!strcmp (spell->race, "GOD") && god && god->slaying && god->slaying.contains (tmp->race)) || |
1645 | ((spell->race == shstr_GOD && god && god->slaying.contains (tmp->race)) || |
1643 | spell->race.contains (tmp->race))) |
1646 | spell->race.contains (tmp->race))) |
1644 | { |
1647 | { |
1645 | done_one = 2; |
1648 | done_one = 2; |
|
|
1649 | |
1646 | if (!detect) |
1650 | if (!detect) |
1647 | detect = tmp; |
1651 | detect = tmp; |
1648 | } |
1652 | } |
|
|
1653 | |
1649 | if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) && |
1654 | if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) && |
1650 | (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))) |
1655 | (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))) |
1651 | { |
1656 | { |
1652 | SET_FLAG (tmp, FLAG_KNOWN_CURSED); |
1657 | SET_FLAG (tmp, FLAG_KNOWN_CURSED); |
1653 | done_one = 1; |
1658 | done_one = 1; |
1654 | } |
1659 | } |
1655 | } /* for stack of objects on this space */ |
1660 | } /* for stack of objects on this space */ |
1656 | |
1661 | |
1657 | /* Code here puts an effect of the spell on the space, so you can see |
1662 | /* Code here puts an effect of the spell on the space, so you can see |
1658 | * where the magic is. |
1663 | * where the magic is. |
1659 | */ |
1664 | */ |
1660 | if (done_one) |
1665 | if (done_one) |
1661 | { |
1666 | { |
1662 | object *detect_ob = arch_to_object (spell->other_arch); |
1667 | object *detect_ob = arch_to_object (spell->other_arch); |
1663 | |
1668 | |
1664 | /* if this is set, we want to copy the face */ |
1669 | /* if this is set, we want to copy the face */ |
1665 | if (done_one == 2 && detect) |
1670 | if (done_one == 2 && detect) |
1666 | { |
1671 | { |
1667 | detect_ob->face = detect->face; |
1672 | detect_ob->face = detect->face; |
1668 | detect_ob->animation_id = detect->animation_id; |
1673 | detect_ob->animation_id = detect->animation_id; |
1669 | detect_ob->anim_speed = detect->anim_speed; |
1674 | detect_ob->anim_speed = detect->anim_speed; |
1670 | detect_ob->last_anim = 0; |
1675 | detect_ob->last_anim = 0; |
1671 | /* by default, the detect_ob is already animated */ |
1676 | /* by default, the detect_ob is already animated */ |
1672 | if (!QUERY_FLAG (detect, FLAG_ANIMATE)) |
1677 | if (!QUERY_FLAG (detect, FLAG_ANIMATE)) |
1673 | CLEAR_FLAG (detect_ob, FLAG_ANIMATE); |
1678 | CLEAR_FLAG (detect_ob, FLAG_ANIMATE); |
1674 | } |
1679 | } |
1675 | |
1680 | |
1676 | m->insert (detect_ob, nx, ny, op); |
1681 | m->insert (detect_ob, nx, ny, op); |
1677 | } |
1682 | } |
1678 | } /* for processing the surrounding spaces */ |
1683 | } /* for processing the surrounding spaces */ |
1679 | |
1684 | |
1680 | |
1685 | |
1681 | /* Now process objects in the players inventory if detect curse or magic */ |
1686 | /* Now process objects in the players inventory if detect curse or magic */ |
1682 | if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) || QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL)) |
1687 | if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) || QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL)) |
1683 | { |
1688 | { |
… | |
… | |
1727 | |
1732 | |
1728 | new_draw_info (NDI_UNIQUE, 0, victim, "You feel energy course through you."); |
1733 | new_draw_info (NDI_UNIQUE, 0, victim, "You feel energy course through you."); |
1729 | |
1734 | |
1730 | if (victim->stats.sp >= victim->stats.maxsp * 2) |
1735 | if (victim->stats.sp >= victim->stats.maxsp * 2) |
1731 | { |
1736 | { |
1732 | object *tmp; |
|
|
1733 | |
|
|
1734 | new_draw_info (NDI_UNIQUE, 0, victim, "Your head explodes!"); |
1737 | new_draw_info (NDI_UNIQUE, 0, victim, "Your head explodes!"); |
1735 | |
|
|
1736 | /* Explodes a fireball centered at player */ |
|
|
1737 | tmp = get_archetype (EXPLODING_FIREBALL); |
|
|
1738 | tmp->dam_modifier = random_roll (1, caster_level, victim, PREFER_LOW) / 5 + 1; |
|
|
1739 | tmp->stats.maxhp = random_roll (1, caster_level, victim, PREFER_LOW) / 10 + 2; |
|
|
1740 | |
|
|
1741 | tmp->insert_at (victim); |
|
|
1742 | victim->stats.sp = 2 * victim->stats.maxsp; |
1738 | victim->stats.sp = 2 * victim->stats.maxsp; |
|
|
1739 | create_exploding_ball_at (victim, caster_level); |
1743 | } |
1740 | } |
1744 | else if (victim->stats.sp >= victim->stats.maxsp * 1.88) |
1741 | else if (victim->stats.sp >= victim->stats.maxsp * 1.88) |
1745 | new_draw_info (NDI_UNIQUE | NDI_ORANGE, 0, victim, "You feel like your head is going to explode."); |
1742 | new_draw_info (NDI_UNIQUE | NDI_ORANGE, 0, victim, "You feel like your head is going to explode."); |
1746 | else if (victim->stats.sp >= victim->stats.maxsp * 1.66) |
1743 | else if (victim->stats.sp >= victim->stats.maxsp * 1.66) |
1747 | new_draw_info (NDI_UNIQUE, 0, victim, "You get a splitting headache!"); |
1744 | new_draw_info (NDI_UNIQUE, 0, victim, "You get a splitting headache!"); |
… | |
… | |
2325 | * There really isn't any adjustments we make. |
2322 | * There really isn't any adjustments we make. |
2326 | */ |
2323 | */ |
2327 | int |
2324 | int |
2328 | write_mark (object *op, object *spell, const char *msg) |
2325 | write_mark (object *op, object *spell, const char *msg) |
2329 | { |
2326 | { |
2330 | char rune[HUGE_BUF]; |
|
|
2331 | object *tmp; |
|
|
2332 | |
|
|
2333 | if (!msg || msg[0] == 0) |
2327 | if (!msg || msg[0] == 0) |
2334 | { |
2328 | { |
2335 | new_draw_info (NDI_UNIQUE, 0, op, "Write what?"); |
2329 | new_draw_info (NDI_UNIQUE, 0, op, "Write what?"); |
2336 | return 0; |
2330 | return 0; |
2337 | } |
2331 | } |
… | |
… | |
2340 | { |
2334 | { |
2341 | new_draw_info (NDI_UNIQUE, 0, op, "Trying to cheat are we?"); |
2335 | new_draw_info (NDI_UNIQUE, 0, op, "Trying to cheat are we?"); |
2342 | LOG (llevInfo, "write_rune: player %s tried to write bogus rune %s\n", &op->name, msg); |
2336 | LOG (llevInfo, "write_rune: player %s tried to write bogus rune %s\n", &op->name, msg); |
2343 | return 0; |
2337 | return 0; |
2344 | } |
2338 | } |
|
|
2339 | |
2345 | if (!spell->other_arch) |
2340 | if (!spell->other_arch) |
2346 | return 0; |
2341 | return 0; |
|
|
2342 | |
2347 | tmp = arch_to_object (spell->other_arch); |
2343 | object *tmp = arch_to_object (spell->other_arch); |
2348 | |
|
|
2349 | snprintf (rune, sizeof (rune), "%s\n", msg); |
|
|
2350 | |
2344 | |
2351 | tmp->race = op->name; /*Save the owner of the rune */ |
2345 | tmp->race = op->name; /*Save the owner of the rune */ |
2352 | tmp->msg = rune; |
2346 | tmp->msg = msg; |
2353 | |
2347 | |
2354 | tmp->insert_at (op, op, INS_BELOW_ORIGINATOR); |
2348 | tmp->insert_at (op, op, INS_BELOW_ORIGINATOR); |
|
|
2349 | |
2355 | return 1; |
2350 | return 1; |
2356 | } |
2351 | } |
|
|
2352 | |