#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <string.h> #include <signal.h> #include <ctype.h> #include "global.h" #include "bug.h" #include "utils.h" #include "act_off.h" #include "comm.h" #include "db.h" #include "mudlimits.h" #include "multiclass.h" #include "spells.h" #define _BREATH_WEAPONS_C #include "breath_weapons.h" static funcp breaths[] = { (funcp)cast_acid_breath, NULL, (funcp)cast_frost_breath, NULL, (funcp)cast_lightning_breath, NULL, (funcp)cast_fire_breath, NULL, (funcp)cast_acid_breath, (funcp)cast_fire_breath, (funcp)cast_lightning_breath, NULL }; struct breather breath_monsters[] = { {5030, 15, breaths + 6}, {-1}, }; struct breath_victim *choose_victims(struct char_data *ch, struct char_data *first_victim) { /* * this is goofy, dopey extraordinaire */ struct char_data *cons = NULL; struct breath_victim *head = NULL; struct breath_victim *temp = NULL; if (DEBUG > 2) log_info("called %s with %s, %s", __PRETTY_FUNCTION__, SAFE_NAME(ch), SAFE_NAME(first_victim)); for (cons = real_roomp(ch->in_room)->people; cons; cons = cons->next_in_room) { CREATE_VOID(temp, struct breath_victim, 1); temp->ch = cons; temp->next = head; head = temp; if (first_victim == cons) { temp->yesno = 1; } else if (ch == cons) { temp->yesno = 0; } else if ((in_group(first_victim, cons) || cons == first_victim->master || cons->master == first_victim) && (temp->yesno = (3 != dice(1, 5)))) { /* * group members will get hit 4/5 times */ } else if (cons->specials.fighting == ch) { /* * people fighting the dragon get hit 4/5 times */ temp->yesno = (3 != dice(1, 5)); } else /* bystanders get his 2/5 times */ temp->yesno = (dice(1, 5) < 3); } return head; } void free_victims(struct breath_victim *head) { struct breath_victim *temp = NULL; if (DEBUG > 2) log_info("called %s with %08zx", __PRETTY_FUNCTION__, (size_t) head); while (head) { temp = head->next; DESTROY(head); head = temp; } } int breath_weapon(struct char_data *ch, struct char_data *target, int mana_cost, funcp func) { struct breath_victim *hitlist = NULL; struct breath_victim *scan = NULL; int victim = 0; if (DEBUG > 2) log_info("called %s with %s, %s, %d, %08zx", __PRETTY_FUNCTION__, SAFE_NAME(ch), SAFE_NAME(target), mana_cost, (size_t) func); hitlist = choose_victims(ch, target); act("$n rears back and inhales", 1, ch, 0, ch->specials.fighting, TO_ROOM); victim = 0; for (scan = hitlist; scan; scan = scan->next) { if (!scan->yesno || IS_IMMORTAL(scan->ch) || scan->ch->in_room != ch->in_room /* this should not happen */ ) continue; victim = 1; cast_fear(GetMaxLevel(ch), ch, "", SPELL_TYPE_SPELL, scan->ch, 0); } if (func != NULL && victim) { act("$n Breathes...", 1, ch, 0, ch->specials.fighting, TO_ROOM); for (scan = hitlist; scan; scan = scan->next) { if (!scan->yesno || IS_IMMORTAL(scan->ch) || scan->ch->in_room != ch->in_room /* this could happen if * someone fled, I * guess */ ) continue; func(GetMaxLevel(ch), ch, "", SPELL_TYPE_SPELL, scan->ch, 0); } GET_MANA(ch) -= mana_cost; } else { act("$n Breathes...coughs and sputters...", 1, ch, 0, ch->specials.fighting, TO_ROOM); do_flee(ch, "", 0); } free_victims(hitlist); return TRUE; } void use_breath_weapon(struct char_data *ch, struct char_data *target, int cost, funcp func) { if (DEBUG > 2) log_info("called %s with %s, %s, %d, %08zx", __PRETTY_FUNCTION__, SAFE_NAME(ch), SAFE_NAME(target), cost, (size_t) func); if (GET_MANA(ch) >= 0) { breath_weapon(ch, target, cost, func); } else if ((GET_HIT(ch) < GET_MAX_HIT(ch) / 2) && (GET_MANA(ch) >= -cost)) { breath_weapon(ch, target, cost, func); } else if ((GET_HIT(ch) < GET_MAX_HIT(ch) / 4) && (GET_MANA(ch) >= -2 * cost)) { breath_weapon(ch, target, cost, func); } else if (GET_MANA(ch) <= -3 * cost) { breath_weapon(ch, target, 0, NULL); /* sputter */ } } int BreathWeapon(struct char_data *ch, int cmd, const char *arg) { struct breather *scan = NULL; int count = 0; if (DEBUG > 2) log_info("called %s with %s, %d, %s", __PRETTY_FUNCTION__, SAFE_NAME(ch), cmd, VNULL(arg)); if (cmd) return FALSE; if (ch->specials.fighting && (ch->specials.fighting->in_room == ch->in_room)) { for (scan = breath_monsters; scan->vnum >= 0 && scan->vnum != mob_index[ch->nr].virtual; scan++); if (scan->vnum < 0) { log_info("monster %s tries to breath, but isn't listed.", ch->player.short_descr); return FALSE; } for (count = 0; scan->breaths[count]; count++); if (count < 1) { log_info("monster %s has no breath weapons", ch->player.short_descr); return FALSE; } use_breath_weapon(ch, ch->specials.fighting, scan->cost, scan->breaths[dice(1, count) - 1]); } return TRUE; }