#include <stdlib.h>
#include <time.h>
#include "structs.h"
#include "awake.h"
#include "db.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "newmagic.h"
#include "utils.h"
#include "screen.h"
#include "constants.h"
#include "olc.h"
#define POWER(name) void (name)(struct char_data *ch, struct char_data *spirit, struct spirit_data *spiritdata, char *arg)
#define SPELLCASTING 0
#define CONJURING 1
#define FAILED_CAST "You fail to bind the mana to your will.\r\n"
extern void die(struct char_data *ch);
extern void damage_equip(struct char_data *ch, struct char_data *vict, int power, int type);
extern void damage_obj(struct char_data *ch, struct obj_data *obj, int power, int type);
extern void check_killer(struct char_data * ch, struct char_data * vict);
extern void nonsensical_reply(struct char_data *ch);
struct char_data *find_spirit_by_id(int spiritid, long playerid)
{
for (struct char_data *ch = character_list; ch; ch = ch->next)
if (IS_NPC(ch) && GET_ACTIVE(ch) == playerid && GET_GRADE(ch) == spiritid)
return ch;
return NULL;
}
void end_sustained_spell(struct char_data *ch, struct sustain_data *sust)
{
struct sustain_data *temp, *vsust;
if (sust->other)
for (vsust = GET_SUSTAINED(sust->other); vsust; vsust = vsust->next)
if (sust->caster != vsust->caster && vsust->other == ch && vsust->idnum == sust->idnum)
{
if (vsust->spirit) {
GET_SUSTAINED_FOCI(sust->other)--;
GET_SUSTAINED_NUM(vsust->spirit--);
}
REMOVE_FROM_LIST(vsust, GET_SUSTAINED(sust->other), next);
delete [] vsust;
break;
}
spell_modify(sust->caster ? sust->other : ch, sust, FALSE);
REMOVE_FROM_LIST(sust, GET_SUSTAINED(ch), next);
if (sust->focus)
{
GET_SUSTAINED_FOCI(sust->caster ? ch : sust->other)--;
GET_FOCI(sust->caster ? ch : sust->other)--;
GET_OBJ_VAL(sust->focus, 4)--;
}
if (sust->spirit)
{
GET_SUSTAINED_FOCI(ch)--;
GET_SUSTAINED_NUM(sust->spirit)--;
GET_SUSTAINED(sust->spirit) = NULL;
}
GET_SUSTAINED_NUM(sust->caster ? ch : sust->other)--;
send_to_char(sust->caster ? ch : sust->other, "You stop sustaining %s.\r\n", spells[sust->spell].name);
delete [] sust;
}
void totem_bonus(struct char_data *ch, int action, int type, int &target, int &skill)
{
extern struct time_info_data time_info;
if (GET_TOTEM(ch) == TOTEM_OWL)
{
if (time_info.hours > 6 || time_info.hours < 19)
target += 2;
else
skill += 2;
} else if (GET_TOTEM(ch) == TOTEM_RAVEN)
{
if (ROOM_FLAGGED(ch->in_room, ROOM_INDOORS) || SECT(ch->in_room) == SPIRIT_HEARTH)
target += 1;
} else if (GET_TOTEM(ch) == TOTEM_SNAKE && FIGHTING(ch))
skill--;
else if ((GET_TOTEM(ch) == TOTEM_BAT || GET_TOTEM(ch) == TOTEM_PUMA)
&& (time_info.hours > 6 && time_info.hours < 19) && OUTSIDE(ch))
target += 2;
else if (GET_TOTEM(ch) == TOTEM_PUMA && world[ch->in_room].crowd > 4)
target += 2;
else if (GET_TOTEM(ch) == TOTEM_SCORPION && (time_info.hours > 6 && time_info.hours < 19))
target += 2;
else if (GET_TOTEM(ch) == TOTEM_SPIDER && OUTSIDE(ch))
target++;
if (action == SPELLCASTING)
{
type = spells[type].category;
switch (GET_TOTEM(ch)) {
case TOTEM_PRAIRIEDOG:
if (type == DETECTION)
skill += 2;
else if (type == ILLUSION)
skill++;
else if (type == COMBAT)
skill -= 2;
break;
case TOTEM_SPIDER:
if (type == ILLUSION)
skill += 2;
break;
case TOTEM_LEOPARD:
if (type == COMBAT || type == HEALTH)
skill += 2;
break;
case TOTEM_BEAR:
case TOTEM_HORSE:
case TOTEM_LIZARD:
case TOTEM_PYTHON:
if (type == HEALTH)
skill += 2;
break;
case TOTEM_ELK:
if (type == HEALTH)
skill++;
else if (type == COMBAT)
skill -= 2;
break;
case TOTEM_TURTLE:
if (type == ILLUSION)
skill += 2;
else if (type == COMBAT)
skill -= 2;
break;
case TOTEM_BUFFALO:
if (type == HEALTH)
skill += 2;
else if (type == ILLUSION)
skill--;
break;
case TOTEM_PUMA:
case TOTEM_CAT:
case TOTEM_PARROT:
if (type == ILLUSION)
skill += 2;
break;
case TOTEM_DOG:
case TOTEM_EAGLE:
if (type == DETECTION)
skill += 2;
break;
case TOTEM_DOLPHIN:
case TOTEM_FISH:
if (type == DETECTION)
skill += 2;
else if (type == COMBAT)
skill--;
break;
case TOTEM_GATOR:
if (type == COMBAT || type == DETECTION)
skill += 2;
else if (type == ILLUSION)
skill--;
break;
case TOTEM_LION:
case TOTEM_HYENA:
if (type == COMBAT)
skill += 2;
else if (type == HEALTH)
skill--;
case TOTEM_MOUSE:
if (type == DETECTION || type == HEALTH)
skill += 2;
else if (type == COMBAT)
skill -= 2;
break;
case TOTEM_RACCOON:
case TOTEM_MONKEY:
if (type == MANIPULATION)
skill += 2;
else if (type == COMBAT)
skill--;
break;
case TOTEM_RAT:
case TOTEM_JACKAL:
if (type == DETECTION || type == ILLUSION)
skill += 2;
else if (type == COMBAT)
skill--;
case TOTEM_JAGUAR:
if (type == DETECTION)
skill += 2;
else if (type == HEALTH)
skill--;
case TOTEM_RAVEN:
if (type == MANIPULATION)
skill += 2;
break;
case TOTEM_SHARK:
case TOTEM_WOLF:
if (type == COMBAT || type == DETECTION)
skill += 2;
break;
case TOTEM_SNAKE:
if (type == DETECTION || type == HEALTH || type == ILLUSION)
skill += 2;
break;
case TOTEM_CRAB:
if (type == ILLUSION)
skill--;
break;
case TOTEM_CROCODILE:
if (type == COMBAT)
skill += 2;
else if (type == ILLUSION)
skill++;
break;
case TOTEM_BOAR:
case TOTEM_WHALE:
if (type == ILLUSION)
skill--;
case TOTEM_BADGER:
if (type == COMBAT)
skill += 2;
break;
case TOTEM_CHEETAH:
if (type == COMBAT)
skill += 2;
else if (type == HEALTH)
skill--;
break;
case TOTEM_BAT:
if (type == DETECTION || type == MANIPULATION)
skill += 2;
break;
case TOTEM_BULL:
if (type == HEALTH)
skill +=2;
else if (type == COMBAT || type == DETECTION)
skill++;
break;
case TOTEM_SCORPION:
case TOTEM_COBRA:
if (type == COMBAT || type == ILLUSION)
skill += 2;
break;
case TOTEM_DOVE:
if (type == HEALTH)
skill += 2;
else if (type == DETECTION)
skill++;
break;
case TOTEM_GOOSE:
if (type == DETECTION)
skill += 2;
else if (type == COMBAT)
skill++;
break;
case TOTEM_FOX:
case TOTEM_OTTER:
if (type == ILLUSION)
skill += 2;
else if (type == COMBAT)
skill--;
break;
case TOTEM_GECKO:
if (type == GET_TOTEMSPIRIT(ch))
skill += 2;
else if (type == COMBAT)
skill--;
break;
case TOTEM_POLECAT:
if (type == COMBAT) {
skill++;
if (time_info.hours < 6 || time_info.hours > 19)
skill++;
} else if (type == HEALTH)
skill--;
break;
case TOTEM_STAG:
if (type == HEALTH || type == ILLUSION)
skill += 2;
else if (type == MANIPULATION)
skill--;
break;
}
} else if (action == CONJURING)
{
switch (GET_TOTEM(ch)) {
case TOTEM_SCORPION:
skill--;
break;
case TOTEM_SPIDER:
skill++;
break;
case TOTEM_PRAIRIEDOG:
case TOTEM_ELK:
case TOTEM_POLECAT:
if (type == SPIRIT_FOREST || type == SPIRIT_DESERT || type == SPIRIT_MOUNTAIN || type == SPIRIT_PRAIRIE)
skill += 2;
break;
case TOTEM_STAG:
case TOTEM_PYTHON:
case TOTEM_BEAR:
case TOTEM_BADGER:
case TOTEM_JAGUAR:
case TOTEM_PARROT:
if (type == SPIRIT_FOREST)
skill += 2;
break;
case TOTEM_COBRA:
if (type == SPIRIT_FOREST)
skill++;
break;
case TOTEM_JACKAL:
case TOTEM_HORSE:
case TOTEM_BUFFALO:
case TOTEM_LION:
case TOTEM_CHEETAH:
if (type == SPIRIT_PRAIRIE)
skill += 2;
break;
case TOTEM_CAT:
case TOTEM_RAT:
case TOTEM_RACCOON:
if (type == SPIRIT_CITY)
skill += 2;
break;
case TOTEM_DOG:
case TOTEM_MOUSE:
if (type == SPIRIT_FIELD || type == SPIRIT_HEARTH)
skill += 2;
break;
case TOTEM_MONKEY:
if (type == SPIRIT_FIELD || type == SPIRIT_HEARTH || type == SPIRIT_CITY)
skill += 2;
break;
case TOTEM_WHALE:
case TOTEM_DOLPHIN:
case TOTEM_SHARK:
case TOTEM_CRAB:
case TOTEM_CROCODILE:
if (type == SPIRIT_SEA)
skill += 2;
break;
case TOTEM_EAGLE:
case TOTEM_RAVEN:
case TOTEM_BAT:
case TOTEM_DOVE:
if (type == SPIRIT_MIST || type == SPIRIT_STORM || type == SPIRIT_WIND)
skill += 2;
break;
case TOTEM_PUMA:
if (type == SPIRIT_MOUNTAIN)
skill += 2;
break;
case TOTEM_LEOPARD:
if (time_info.hours < 6 || time_info.hours > 19)
skill += 2;
break;
case TOTEM_LIZARD:
case TOTEM_GATOR:
case TOTEM_SNAKE:
case TOTEM_WOLF:
case TOTEM_FISH:
case TOTEM_GOOSE:
case TOTEM_OTTER:
case TOTEM_TURTLE:
if (GET_TOTEMSPIRIT(ch) == type)
skill += 2;
break;
}
}
}
void end_spirit_existance(struct char_data *ch, bool message)
{
struct char_data *tempc;
for (struct descriptor_data *d = descriptor_list; d; d = d->next) {
tempc = d->original ? d->original : d->character;
if (tempc && GET_IDNUM(tempc) == GET_ACTIVE(ch))
{
for (struct spirit_data *spirit = GET_SPIRIT(tempc); spirit; spirit = spirit->next)
if (spirit->id == GET_GRADE(ch)) {
struct spirit_data *temp;
REMOVE_FROM_LIST(spirit, GET_SPIRIT(tempc), next);
delete [] spirit;
break;
}
GET_NUM_SPIRITS(tempc)--;
if (message && d->character)
send_to_char(d->character, "%s returns to the metaplanes, it's existance in this world finished.\r\n", CAP(GET_NAME(ch)));
break;
}
}
extract_char(ch);
}
void elemental_fulfilled_services(struct char_data *ch, struct char_data *mob, struct spirit_data *spirit)
{
if (spirit->services < 1 && !(MOB_FLAGGED(mob, MOB_SPIRITGUARD) || MOB_FLAGGED(mob, MOB_STUDY) || GET_SUSTAINED(mob) || GET_SUSTAINED_NUM(mob) || FIGHTING(mob)))
{
send_to_char(ch, "It's services fulfilled, %s departs to the metaplanes.\r\n", CAP(GET_NAME(mob)));
end_spirit_existance(mob, FALSE);
}
}
bool conjuring_drain(struct char_data *ch, int force)
{
if (world[ch->in_room].background[1] != 13)
force += world[ch->in_room].background[0] / 2;
int drain = 0;
if (force <= GET_CHA(ch) / 2)
drain = LIGHT;
else if (force <= GET_CHA(ch))
drain = MODERATE;
else if (force > GET_CHA(ch) * 1.5)
drain = DEADLY;
else
drain = SERIOUS;
drain = convert_damage(stage(-success_test(GET_CHA(ch), force), drain));
if (force > GET_MAG(ch) / 100)
GET_PHYSICAL(ch) -= drain *100;
else
{
GET_MENTAL(ch) -= drain * 100;
if (GET_MENTAL(ch) < 0) {
GET_PHYSICAL(ch) += GET_MENTAL(ch);
GET_MENTAL(ch) = 0;
}
}
update_pos(ch);
if ((GET_POS(ch) <= POS_STUNNED) && (GET_POS(ch) > POS_DEAD))
{
if (FIGHTING(ch))
stop_fighting(ch);
send_to_char("You are unable to resist the drain from conjuring and fall unconcious!\r\n", ch);
act("$n collapses unconscious!", FALSE, ch, 0, 0, TO_ROOM);
struct sustain_data *next;
for (struct sustain_data *sust = GET_SUSTAINED(ch); sust; sust = next) {
next = sust->next;
if (sust->caster && !sust->focus && !sust->spirit)
end_sustained_spell(ch, sust);
}
} else if (GET_POS(ch) == POS_DEAD)
{
if (FIGHTING(ch))
stop_fighting(ch);
send_to_char("The energy from the conjuring ritual overloads your body with energy, killing you...\r\n", ch);
act("$n suddenly collapases, dead!", FALSE, ch, 0, 0, TO_ROOM);
die(ch);
return TRUE;
}
return FALSE;
}
void magic_perception(struct char_data *ch, int force, int spell)
{
int base = 4 + (int)(GET_MAG(ch) / 100) - force, target = 0, skill = 0, starg = 0;
totem_bonus(ch, SPELLCASTING, spell, starg, skill);
if (skill > 0)
base--;
for (struct char_data *vict = ch->in_veh ? ch->in_veh->people : world[ch->in_room].people; vict; vict = ch->in_veh ? vict->next_in_veh : vict->next_in_room) {
if (ch == vict)
continue;
target = base;
if (GET_MAG(vict) > 0)
target -= 2;
if (IS_DUAL(vict) || IS_ASTRAL(vict))
target -= 2;
if (success_test(GET_INT(ch) + (GET_TRADITION(ch) == TRAD_ADEPT ? GET_POWER(ch, ADEPT_IMPROVED_PERCEPT) : 0), target)) {
if (IS_DUAL(vict) || IS_ASTRAL(vict))
act("You notice $n manipulating the astral plane.", FALSE, ch, 0, vict, TO_VICT);
else act("You notice $n performing magic.", TRUE, ch, 0, vict, TO_VICT);
}
}
}
bool spell_drain(struct char_data *ch, int type, int force, int damage)
{
char buf[MAX_STRING_LENGTH];
int target = (int)(force / 2), success = 0;
target += spells[type].drainpower;
if (world[ch->in_room].background[1] != 13)
target += (world[ch->in_room].background[0] / 2);
if (!damage)
damage = spells[type].draindamage;
else
damage += spells[type].draindamage + 3;
magic_perception(ch, force, type);
sprintf(buf, "Drain Test: F:%d%s T:%d Sk: %d", force, wound_name[damage], target, GET_WIL(ch) + GET_DRAIN(ch));
success = success_test(GET_WIL(ch) + GET_DRAIN(ch), target);
damage = convert_damage(stage(-success, damage));
sprintf(ENDOF(buf), " S:%d S:%d", success, damage);
act(buf, FALSE, ch, NULL, NULL, TO_ROLLS);
if (force > GET_MAG(ch) / 100 || IS_PROJECT(ch)) {
GET_PHYSICAL(ch) -= damage *100;
if (IS_PROJECT(ch)) {
GET_PHYSICAL(ch->desc->original) -= damage * 100;
AFF_FLAGS(ch->desc->original).SetBit(AFF_DAMAGED);
}
} else
{
GET_MENTAL(ch) -= damage * 100;
if (GET_MENTAL(ch) < 0) {
GET_PHYSICAL(ch) += GET_MENTAL(ch);
GET_MENTAL(ch) = 0;
}
}
update_pos(ch);
if ((GET_POS(ch) <= POS_STUNNED) && (GET_POS(ch) > POS_DEAD))
{
if (FIGHTING(ch))
stop_fighting(ch);
send_to_char("You are unable to resist the drain from spell casting and fall unconcious!\r\n", ch);
act("$n collapses unconscious!", FALSE, ch, 0, 0, TO_ROOM);
} else if (GET_POS(ch) == POS_DEAD)
{
if (FIGHTING(ch))
stop_fighting(ch);
send_to_char("The feedback from spell casting floods your body, killing you...\r\n", ch);
act("$n suddenly collapases, dead!", FALSE, ch, 0, 0, TO_ROOM);
die(ch);
return TRUE;
}
return FALSE;
}
struct char_data *find_target_at_range(struct char_data *ch, char *name, char *direction)
{
return NULL;
}
void create_sustained(struct char_data *ch, struct char_data *vict, int spell, int force, int sub, int success, int drain)
{
struct obj_data *focus = NULL;
for (int i = 0; !focus && i < NUM_WEARS; i++)
if (GET_EQ(vict, i) && GET_OBJ_TYPE(GET_EQ(vict, i)) == ITEM_FOCUS && !GET_OBJ_VAL(GET_EQ(vict, i), 4) &&
GET_OBJ_VAL(GET_EQ(vict, i), 3) == spell && GET_OBJ_VAL(GET_EQ(vict, i), 1) >= force && !GET_OBJ_VAL(GET_EQ(vict, i), 9))
focus = GET_EQ(vict, i);
GET_SUSTAINED_NUM(ch)++;
if (focus)
{
GET_SUSTAINED_FOCI(ch)++;
GET_OBJ_VAL(focus, 4)++;
GET_FOCI(ch)++;
}
struct sustain_data *sust = new sustain_data;
sust->spell = spell;
sust->subtype = sub;
sust->force = force;
sust->success = success;
sust->other = vict;
sust->caster = TRUE;
sust->drain = drain;
sust->idnum = number(0, 1000);
sust->next = GET_SUSTAINED(ch);
sust->focus = focus;
GET_SUSTAINED(ch) = sust;
struct sustain_data *vsust = new sustain_data;
*vsust = *sust;
vsust->caster = FALSE;
vsust->other = ch;
vsust->next = GET_SUSTAINED(vict);
vsust->focus = focus;
GET_SUSTAINED(vict) = vsust;
spell_modify(vict, vsust, TRUE);
}
void spell_bonus(struct char_data *ch, int spell, int &skill, int &target)
{
if (world[ch->in_room].background[1] == AURA_POWERSITE)
skill += world[ch->in_room].background[0];
else target += world[ch->in_room].background[0];
if (GET_TRADITION(ch) == TRAD_SHAMANIC)
totem_bonus(ch, SPELLCASTING, spell, target, skill);
else if (GET_TRADITION(ch) == TRAD_HERMETIC && GET_SPIRIT(ch) && spells[spell].category != HEALTH)
{
for (struct spirit_data *spirit = GET_SPIRIT(ch); spirit; spirit = spirit->next)
if (((spells[spell].category == MANIPULATION && spirit->type == ELEM_EARTH) ||
(spells[spell].category == COMBAT && spirit->type == ELEM_FIRE) ||
(spells[spell].category == ILLUSION && spirit->type == ELEM_WATER) ||
(spells[spell].category == DETECTION && spirit->type == ELEM_AIR)) &&
spirit->called == TRUE) {
struct char_data *mob = find_spirit_by_id(spirit->id, GET_IDNUM(ch));
if (mob && MOB_FLAGGED(mob, MOB_AIDSORCERY)) {
send_to_char(ch, "%s aids your spell casting.\r\n", CAP(GET_NAME(mob)));
MOB_FLAGS(mob).RemoveBit(MOB_AIDSORCERY);
skill += GET_LEVEL(mob);
}
}
}
int origskill = skill;
if (GET_FOCI(ch) > 0)
{
for (int i = 0; i < NUM_WEARS && skill == origskill; i++)
if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_FOCUS)
switch (GET_OBJ_VAL(GET_EQ(ch, i), 0)) {
case FOCI_EXPENDABLE:
if (spells[spell].category == GET_OBJ_VAL(GET_EQ(ch, i), 3)) {
skill += GET_OBJ_VAL(GET_EQ(ch, i), 1);
extract_obj(GET_EQ(ch, i));
}
break;
case FOCI_SPEC_SPELL:
if (spell == GET_OBJ_VAL(GET_EQ(ch, i), 3))
skill += GET_OBJ_VAL(GET_EQ(ch, i), 1);
break;
case FOCI_SPELL_CAT:
if (spells[spell].category == GET_OBJ_VAL(GET_EQ(ch, i), 3))
skill += GET_OBJ_VAL(GET_EQ(ch, i), 1);
break;
}
}
}
bool find_duplicate_spell(struct char_data *ch, struct char_data *vict, int spell, int sub)
{
if (spells[spell].duration == INSTANT)
return FALSE;
struct sustain_data *sus;
if (!vict || vict == ch)
sus = GET_SUSTAINED(ch);
else
sus = GET_SUSTAINED(vict);
for (; sus; sus = sus->next)
if (!sus->caster && sus->spell == spell && sus->subtype == sub)
{
send_to_char(ch, "%s are already affected by that spell.\r\n", (!vict || vict == ch) ? "You" : "They");
return TRUE;
}
return FALSE;
}
bool check_spell_victim(struct char_data *ch, struct char_data *vict, int spell)
{
if (!vict)
send_to_char(NOPERSON, ch);
else if (((IS_PROJECT(ch) || IS_ASTRAL(ch)) && !(IS_DUAL(vict) || IS_ASTRAL(vict) || IS_PROJECT(vict))) ||
((IS_PROJECT(vict) || IS_ASTRAL(vict)) && !(IS_DUAL(ch) || IS_ASTRAL(ch) || IS_PROJECT(ch))))
send_to_char("They aren't accessible from this plane.\r\n", ch);
else if (spells[spell].physical && IS_ASTRAL(vict))
send_to_char("That spell can't affect beings with no physical form.\r\n", ch);
else
return TRUE;
return FALSE;
}
int reflect_spell(struct char_data *ch, struct char_data *vict, int spell, int force, int sub, int target, int &success)
{
success -= success_test(GET_REFLECT(vict), force);
if (success < 0) {
success *= -1;
success = success_test(success, target);
send_to_char("You reflect the spell back!\r\n", vict);
send_to_char("Your spell is reflected back at you!\r\n", ch);
return TRUE;
}
return FALSE;
}
int resist_spell(struct char_data *ch, int spell, int force, int sub)
{
int skill = 0;
if (sub)
skill = GET_ATT(ch, sub);
else if (spell == SPELL_CHAOS)
skill = GET_INT(ch);
else if (spells[spell].physical)
skill = GET_BOD(ch);
else
skill = GET_WIL(ch);
if (GET_TRADITION(ch) == TRAD_SHAMANIC) {
if (GET_TOTEM(ch) == TOTEM_HORSE && spells[spell].category == GET_TOTEMSPIRIT(ch))
skill--;
else if (GET_TOTEM(ch) == TOTEM_LEOPARD && spells[spell].category == ILLUSION)
skill--;
}
if (GET_TRADITION(ch) == TRAD_ADEPT)
{
if (GET_POWER(ch, ADEPT_MAGIC_RESISTANCE))
skill += GET_POWER(ch, ADEPT_MAGIC_RESISTANCE);
if (GET_POWER(ch, ADEPT_SPELL_SHROUD) && spells[spell].category == DETECTION)
skill += GET_POWER(ch, ADEPT_SPELL_SHROUD);
if (GET_POWER(ch, ADEPT_TRUE_SIGHT) && spells[spell].category == ILLUSION)
skill += GET_POWER(ch, ADEPT_TRUE_SIGHT);
}
skill += GET_SDEFENSE(ch);
return success_test(skill, force);
}
void cast_combat_spell(struct char_data *ch, int spell, int force, char *arg)
{
struct char_data *vict = NULL;
two_arguments(arg, buf, buf1);
bool reflected = FALSE;
int basedamage = 0;
if (!*buf)
{
send_to_char("What damage level do you wish to cast that spell at?\r\n", ch);
return;
} else
{
for (basedamage = 0; *wound_name[basedamage] != '\n'; basedamage++)
if (is_abbrev(buf, wound_name[basedamage]))
break;
if (basedamage > 4 || basedamage == 0) {
send_to_char("That is not a valid damage level, please choose between Light, Moderate, Serious and Deadly.\r\n", ch);
return;
}
}
if (*buf1)
vict = get_char_room_vis(ch, buf1);
if (!check_spell_victim(ch, vict, spell))
return;
if (ch == vict) {
send_to_char("You can't target yourself with a combat spell!\r\n", ch);
return;
}
if (world[ch->in_room].peaceful) {
send_to_char("This room just has a peaceful, easy feeling...\r\n", ch);
return;
}
int target = modify_target(ch), skill = GET_SKILL(ch, SKILL_SORCERY) + MIN(GET_SKILL(ch, SKILL_SORCERY), GET_CASTING(ch)), success = 0;
spell_bonus(ch, spell, skill, target);
if (skill == -1)
return;
check_killer(ch, vict);
struct char_data *temp = vict;
switch (spell)
{
case SPELL_MANABOLT:
target += GET_WIL(vict);
if (!IS_NPC(ch) && (IS_NPC(vict) && MOB_FLAGGED(vict, MOB_INANIMATE)) || (PLR_FLAGGED(ch, PLR_KILLER) && !IS_NPC(vict)))
success = -1;
else
success = success_test(skill, target);
if (success > 0 && GET_REFLECT(vict) && (reflected = reflect_spell(ch, vict, spell, force, 0, target, success))) {
vict = ch;
ch = temp;
}
success -= resist_spell(vict, spell, force, 0);
if (success > 0) {
int dam = convert_damage(stage(success, basedamage));
if (GET_MENTAL(vict) - (dam * 100) <= 0) {
act("$n falls to the floor as ^Rblood^n erupts from every pore on $s head.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("Your world turns to red as you feel blood flow from every pore on your head.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 300) {
act("$n grabs $s head in pain as blood flows from $s ears.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("Your head is filled with immense pain as your ears begin to bleed.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 700) {
act("$n grabs ahold of $s head in pain.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("A sudden flash of pain in your head causes you to reflexivly grab it.\r\n", vict);
} else {
act("$n seems to flinch slightly as blood trickles from $s nose.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("Slight pain fills your mind from an unknown source.\r\n", vict);
}
damage(ch, vict, dam, TYPE_COMBAT_SPELL, PHYSICAL);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(reflected ? vict : ch, spell, force, basedamage);
break;
case SPELL_STUNBOLT:
target += GET_WIL(vict);
if (!IS_NPC(ch) && IS_NPC(vict) && MOB_FLAGGED(vict, MOB_INANIMATE) || (PLR_FLAGGED(ch, PLR_KILLER) && !IS_NPC(vict)))
success = -1;
else
success = success_test(skill, target);
if (success > 0 && GET_REFLECT(vict) && (reflected = reflect_spell(ch, vict, spell, force, 0, target, success))) {
vict = ch;
ch = temp;
}
success -= resist_spell(vict, spell, force, 0);
if (success > 0) {
int dam = convert_damage(stage(success, basedamage));
if (GET_MENTAL(vict) - (dam * 100) <= 0) {
act("$n falls to the floor unconcious.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("The world turns black around you as you suddenly fall unconcious.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 300) {
act("$n grabs $s head and cringes.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("Your head is filled with an unbarable pressure as your vision begins to fade.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 700) {
act("$n shakes $s head forcibly as though trying to clear it.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("A wave of tiredness comes over you, but seems to clear slightly as you shake your head.\r\n", vict);
} else {
act("$n recoils slightly as though hit by an invisble force.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You mind goes slighlty hazy as though you had just been punched.\r\n", vict);
}
damage(ch, vict, dam, TYPE_COMBAT_SPELL, MENTAL);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(reflected ? vict : ch, spell, force, basedamage);
break;
case SPELL_POWERBOLT:
target += GET_BOD(vict);
if (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_KILLER) && !IS_NPC(vict))
success = -1;
else
success = success_test(skill, target);
if (success > 0 && GET_REFLECT(vict) && (reflected = reflect_spell(ch, vict, spell, force, 0, target, success))) {
vict = ch;
ch = temp;
}
success -= resist_spell(vict, spell, force, 0);
if (success > 0) {
int dam = convert_damage(stage(success, basedamage));
if (GET_MENTAL(vict) - (dam * 100) <= 0) {
act("$n screams loudly as $s body is torn asunder by magic.", FALSE, vict, 0, 0, TO_ROOM);
send_to_char("You begin to feel yourself tearing apart.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 300) {
act("$n cries out in pain as $s begins to bleed from nearly every pore on $s body.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You uncontrollable scream as an immense force tears at your body.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 700) {
act("$n grabs $s stomach as a trickle of blood comes from $s mouth.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("Your torso is filled with a sharp stabbing pain as you cough up some blood.\r\n", vict);
} else {
act("$n grimaces, obviously afflicted with mild pain.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You feel a dull throb of pain flow through your body.\r\n", vict);
}
damage(ch, vict, dam, TYPE_COMBAT_SPELL, PHYSICAL);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(reflected ? vict : ch, spell, force, basedamage);
break;
}
}
void cast_detection_spell(struct char_data *ch, int spell, int force, char *arg, struct char_data *mob)
{
struct char_data *vict = NULL;
if (mob)
vict = mob;
else if (*arg)
vict = get_char_room_vis(ch, arg);
if (!check_spell_victim(ch, vict, spell))
return;
if (find_duplicate_spell(ch, vict, spell, 0))
return;
int target = modify_target(ch), skill = GET_SKILL(ch, SKILL_SORCERY) + MIN(GET_SKILL(ch, SKILL_SORCERY), GET_CASTING(ch)), success = 0;
spell_bonus(ch, spell, skill, target);
if (skill == -1)
return;
switch (spell)
{
case SPELL_MINDLINK:
success = success_test(skill, 4 + target);
for (struct sustain_data *sust = GET_SUSTAINED(ch); sust; sust = sust->next)
if (sust->spell == SPELL_MINDLINK) {
send_to_char("You are already under the influence of a mindlink.\r\n", ch);
return;
}
for (struct sustain_data *sust = GET_SUSTAINED(vict); sust; sust = sust->next)
if (sust->spell == SPELL_MINDLINK) {
send_to_char("They are already under the influence of a mindlink.\r\n", ch);
return;
}
if (success > 0) {
create_sustained(ch, vict, spell, force, 0, success, spells[spell].draindamage);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
vict->char_specials.mindlink = ch;
ch->char_specials.mindlink = vict;
} else send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_COMBATSENSE:
success = success_test(skill, 4 + target);
if (success > 0) {
create_sustained(ch, vict, spell, force, 0, success, spells[spell].draindamage);
send_to_char("The world seems to slow down around you as your sense of your surroundings becomes clearer.\r\n", vict);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
}
}
void cast_health_spell(struct char_data *ch, int spell, int sub, int force, char *arg, struct char_data *mob)
{
struct char_data *vict = NULL;
if (mob)
vict = mob;
else if (*arg)
vict = get_char_room_vis(ch, arg);
if (!check_spell_victim(ch, vict, spell))
return;
if (find_duplicate_spell(ch, vict, spell, sub))
return;
int target = modify_target(ch), skill = GET_SKILL(ch, SKILL_SORCERY) + MIN(GET_SKILL(ch, SKILL_SORCERY), GET_CASTING(ch)), success = 0, drain = LIGHT;
spell_bonus(ch, spell, skill, target);
if (skill == -1)
return;
bool cyber = TRUE;
switch (spell)
{
case SPELL_DETOX:
if ((GET_DRUG_STAGE(vict) == 1 || GET_DRUG_STAGE(vict) == 2) && GET_DRUG_AFFECT(vict))
target = drug_types[GET_DRUG_AFFECT(vict)].power;
if (!target) {
send_to_char("They aren't affected by any drugs.\r\n", ch);
return;
}
success = success_test(skill, target);
if (success > 0 && !AFF_FLAGGED(vict, AFF_DETOX)) {
create_sustained(ch, vict, spell, force, 0, success, spells[SPELL_STABILIZE].draindamage);
send_to_char("You notice the affects of the drugs suddenly wear off.\r\n", vict);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_STABILIZE:
target += 4 + ((GET_LAST_DAMAGETIME(vict) - time(0)) / SECS_PER_MUD_HOUR);
success = success_test(skill, target);
if (success > 0 && force >= (GET_PHYSICAL(vict) <= 0 ? -(GET_PHYSICAL(vict) / 100) : 50)) {
create_sustained(ch, vict, spell, force, 0, success, spells[SPELL_STABILIZE].draindamage);
send_to_char("Your condition stabilizes, you manage to grab a thin hold on life.\r\n", vict);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_RESISTPAIN:
success = success_test(skill, target + 4);
if (GET_PHYSICAL(vict) <= 0)
drain = DEADLY;
else if (GET_PHYSICAL(vict) <= 300)
drain = SERIOUS;
else if (GET_PHYSICAL(vict) <= 700)
drain = MODERATE;
if (success > 0 && !AFF_FLAGGED(ch, AFF_RESISTPAIN)) {
create_sustained(ch, vict, spell, force, 0, success, spells[SPELL_RESISTPAIN].draindamage);
send_to_char("Your pain begins to fade.\r\n", vict);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
vict->points.resistpain = MIN(force, success) * 100;
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_HEALTHYGLOW:
success = success_test(skill, 4 + target);
if (success > 0) {
create_sustained(ch, vict, spell, force, 0, success, spells[SPELL_HEALTHYGLOW].draindamage);
send_to_char("You begin to feel healthier and more attractive.\r\n", vict);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_TREAT:
if (!AFF_FLAGGED(vict, AFF_DAMAGED)) {
send_to_char("They are beyond the help of this spell.\r\n", ch);
return;
}
case SPELL_HEAL:
success = MIN(force, success_test(skill, 10 - (int)(GET_ESS(vict) / 100) + target + (int)(GET_INDEX(ch) / 200)));
if (GET_PHYSICAL(vict) <= 0)
drain = DEADLY;
else if (GET_PHYSICAL(vict) <= 300)
drain = SERIOUS;
else if (GET_PHYSICAL(vict) <= 700)
drain = MODERATE;
if (success < 1 || AFF_FLAGGED(vict, AFF_HEALED) || GET_PHYSICAL(vict) == GET_MAX_PHYSICAL(vict)) {
send_to_char(FAILED_CAST, ch);
} else {
AFF_FLAGS(vict).SetBit(AFF_HEALED);
send_to_char("A warm feeling floods your body.\r\n", vict);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
create_sustained(ch, vict, spell, force, 0, success, drain);
update_pos(vict);
}
spell_drain(ch, spell, force, drain);
break;
case SPELL_INCREF1:
case SPELL_INCREF2:
case SPELL_INCREF3:
if (GET_REAL_REA(vict) != GET_REA(vict) || GET_INIT_DICE(ch))
success = -1;
else
success = success_test(skill, GET_REA(vict) + target);
if (success > 0) {
create_sustained(ch, vict, spell, force, 0, success, spells[spell].draindamage);
send_to_char("The world slows down around you.\r\n", ch);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_INCREA:
sub = REA;
case SPELL_DECATTR:
case SPELL_DECCYATTR:
case SPELL_INCATTR:
case SPELL_INCCYATTR:
if (GET_ATT(vict, sub) != GET_REAL_ATT(vict, sub)) {
if (GET_TRADITION(vict) == TRAD_ADEPT && sub < CHA) {
switch (sub) {
case BOD:
if (BOOST(vict)[2][0] || GET_POWER(vict, ADEPT_IMPROVED_BOD))
cyber = false;
break;
case QUI:
if (BOOST(vict)[1][0] || GET_POWER(vict, ADEPT_IMPROVED_QUI))
cyber = false;
break;
case STR:
if (BOOST(vict)[0][0] || GET_POWER(vict, ADEPT_IMPROVED_STR))
cyber = false;
break;
}
} else if (GET_SUSTAINED(vict))
for (struct sustain_data *sus = GET_SUSTAINED(vict); sus; sus = sus->next)
if (sus->caster == FALSE && (sus->spell == SPELL_INCATTR || sus->spell == SPELL_DECATTR) && sus->subtype == sub) {
cyber = false;
break;
}
if (cyber && (spell == SPELL_DECATTR || spell == SPELL_INCATTR || spell == SPELL_INCREA)) {
sprintf(buf, "$N's %s has been modified by technological means and is immune to this spell.\r\n", attributes[sub]);
act(buf, TRUE, ch, 0, vict, TO_CHAR);
return;
}
}
if ((spell == SPELL_DECCYATTR || spell == SPELL_INCCYATTR) && (!cyber || GET_ATT(vict, sub) == GET_REAL_ATT(vict, sub))) {
sprintf(buf, "$N's %s has not been modified by technological means and is immune to this spell.\r\n", attributes[sub]);
act(buf, TRUE, ch, 0, vict, TO_CHAR);
return;
}
if (spell == SPELL_INCREA)
target += GET_REA(vict);
else if (spell == SPELL_INCATTR || spell == SPELL_INCCYATTR)
target += GET_ATT(vict, sub);
else
target += 10 - (GET_ESS(vict) / 100);
success = (int)(success_test(skill, target) -
((spell == SPELL_DECATTR || spell == SPELL_DECCYATTR) ? resist_spell(vict, spell, force, sub) : 0));
if (success > 0) {
create_sustained(ch, vict, spell, force, sub, success, spells[spell].draindamage);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
send_to_char("You feel your body tingle.\r\n", vict);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
}
}
void cast_illusion_spell(struct char_data *ch, int spell, int force, char *arg, struct char_data *mob)
{
struct char_data *vict = NULL;
bool reflected = FALSE;
if (mob)
vict = mob;
else if (*arg)
vict = get_char_room_vis(ch, arg);
if (find_duplicate_spell(ch, vict, spell, 0))
return;
int target = modify_target(ch), skill = GET_SKILL(ch, SKILL_SORCERY) + MIN(GET_SKILL(ch, SKILL_SORCERY), GET_CASTING(ch)), success = 0;
spell_bonus(ch, spell, skill, target);
if (skill == -1)
return;
struct char_data *temp = vict;
switch (spell)
{
case SPELL_CONFUSION:
case SPELL_CHAOS:
if (!check_spell_victim(ch, vict, spell))
return;
check_killer(ch, vict);
if (spell == SPELL_CONFUSION)
target += GET_WIL(vict);
else
target += GET_INT(vict);
if (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_KILLER) && !IS_NPC(vict))
success = -1;
else
success = success_test(skill, target);
if (success > 0 && GET_REFLECT(vict) && (reflected = reflect_spell(ch, vict, spell, force, 0, target, success))) {
vict = ch;
ch = temp;
}
success -= resist_spell(vict, spell, force, 0);
if (success > 0) {
send_to_char("Coherent thought is suddenly a foreign concept.\r\n", vict);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
create_sustained(ch, vict, spell, force, 0, success, spells[spell].draindamage);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(reflected ? vict : ch, spell, force, 0);
break;
case SPELL_INVIS:
case SPELL_IMP_INVIS:
if (!check_spell_victim(ch, vict, spell))
return;
success = success_test(skill, target + 4);
if (success > 0) {
act("You blink and suddenly $n is gone!", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You feel your body tingle.\r\n", vict);
create_sustained(ch, vict, spell, force, 0, success, spells[spell].draindamage);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_STEALTH:
if (!check_spell_victim(ch, vict, spell))
return;
success = success_test(skill, target + 4);
if (success > 0) {
act("You successfully sustain that spell on $n.", FALSE, vict, 0, ch, TO_VICT);
send_to_char("Your every move becomes silent.", vict);
create_sustained(ch, vict, spell, force, 0, success, spells[spell].draindamage);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_SILENCE:
success = success_test(skill, target + 4);
if (success > 0) {
act("The room falls silent.", FALSE, ch, 0, 0, TO_ROOM);
act("The room falls silent.", FALSE, ch, 0, 0, TO_CHAR);
create_sustained(ch, ch, spell, force, 0, success, spells[spell].draindamage);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
}
}
void cast_manipulation_spell(struct char_data *ch, int spell, int force, char *arg, struct char_data *mob)
{
struct char_data *vict = NULL;
bool reflected = FALSE;
int basedamage = 0;
switch (spell)
{
case SPELL_ACIDSTREAM:
case SPELL_TOXICWAVE:
case SPELL_FLAMETHROWER:
case SPELL_FIREBALL:
case SPELL_LIGHTNINGBOLT:
case SPELL_BALLLIGHTNING:
case SPELL_CLOUT:
two_arguments(arg, buf, buf1);
if (world[ch->in_room].peaceful) {
send_to_char("This room just has a peaceful, easy feeling...\r\n", ch);
return;
}
if (!*buf) {
send_to_char("What damage level do you wish to cast that spell at?\r\n", ch);
return;
} else {
for (basedamage = 0; *wound_name[basedamage] != '\n'; basedamage++)
if (is_abbrev(buf, wound_name[basedamage]))
break;
if (basedamage > 4 || basedamage == 0) {
send_to_char("That is not a valid damage level, please choose between Light, Moderate, Serious and Deadly.\r\n", ch);
return;
}
}
if (*buf1)
vict = get_char_room_vis(ch, buf1);
if (ch == vict) {
send_to_char("You can't target yourself with a combat spell!\r\n", ch);
return;
}
break;
default:
if (mob)
vict = mob;
else if (*arg)
vict = get_char_room_vis(ch, arg);
}
if (find_duplicate_spell(ch, vict, spell, 0))
return;
int target = modify_target(ch), skill = IS_ELEMENTAL(ch) || IS_SPIRIT(ch) ? GET_LEVEL(ch) : GET_SKILL(ch, SKILL_SORCERY) + MIN(GET_SKILL(ch, SKILL_SORCERY), GET_CASTING(ch)), success = 0;
if (!(IS_ELEMENTAL(ch) || IS_SPIRIT(ch)))
spell_bonus(ch, spell, skill, target);
if (skill == -1)
return;
struct char_data *temp = vict;
switch (spell)
{
case SPELL_ARMOUR:
if (!check_spell_victim(ch, vict, spell))
return;
success = success_test(skill, target + 6);
if (success > 0) {
create_sustained(ch, vict, spell, force, 0, success, spells[spell].draindamage);
send_to_char("You feel your body tingle.\r\n", vict);
act("You successfully sustain that spell on $N.", FALSE, ch, 0, vict, TO_CHAR);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_POLTERGEIST:
success = success_test(skill, target + 4);
if (success > 0) {
create_sustained(ch, ch, spell, force, 0, success, spells[spell].draindamage);
act("An invisible wind begins to spin small objects around the area!", FALSE, ch, 0, 0, TO_ROOM);
act("An invisible wind begins to spin small objects around the area!", FALSE, ch, 0, 0, TO_CHAR);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_LIGHT:
success = success_test(skill, target + 4);
if (success > 0) {
create_sustained(ch, ch, spell, force, 0, success, spells[spell].draindamage);
act("Light radiates from $n, illuminating the area!", FALSE, ch, 0, 0, TO_ROOM);
act("The area brightens as your light spell takes affect!", FALSE, ch, 0, 0, TO_CHAR);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_ICESHEET:
if (!ch->in_room) {
send_to_char("You can't create ice in here!\r\n", ch);
return;
}
success = success_test(skill, target + 4);
if (success > 0) {
world[ch->in_room].icesheet[0] = (int)(3.14 * ((GET_MAG(ch) * GET_MAG(ch)) / 10000));
world[ch->in_room].icesheet[1] = force + MIN(force, success / 2);
act("The floor is suddenly covered in ice!", FALSE, ch, 0, 0, TO_ROOM);
act("The floor is suddenly covered in ice!", FALSE, ch, 0, 0, TO_CHAR);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_IGNITE:
if (!check_spell_victim(ch, vict, spell))
return;
check_killer(ch, vict);
if (ch == vict) {
send_to_char("You can't target yourself with a combat spell!\r\n", ch);
return;
}
if (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_KILLER) && !IS_NPC(vict))
success = -1;
else success = success_test(skill, target + 4);
if (success > 0 && GET_REFLECT(vict) && (reflected = reflect_spell(ch, vict, spell, force, 0, target + 4, success))) {
vict = ch;
ch = temp;
}
success -= resist_spell(vict, spell, force, 0);
success -= GET_BOD(vict) / 2;
if (success > 0) {
send_to_char("You feel the room temperature sharply rise.\r\n", vict);
act("You succeed in raising the body temperature of $N to dangerous levels.", FALSE, ch, 0, vict, TO_CHAR);
create_sustained(ch, vict, spell, force, 0, success, MAX(1, 10 / MIN(force, success)));
if (!FIGHTING(vict) && vict != ch && AWAKE(vict))
set_fighting(vict, ch);
} else {
send_to_char("You feel your body heat slightly then return to normal.\r\n", vict);
send_to_char("You fail to generate enough heat in your target.\r\n", ch);
}
spell_drain(reflected ? vict : ch, spell, force, 0);
break;
case SPELL_SHADOW:
success = success_test(skill, target + 4);
if (success > 0) {
create_sustained(ch, ch, spell, force, 0, success, spells[spell].draindamage);
act("Dark shadows fall over the area.", FALSE, ch, 0, 0, TO_ROOM);
act("Dark shadows fall over the area as your spell takes affect.", FALSE, ch, 0, 0, TO_CHAR);
} else
send_to_char(FAILED_CAST, ch);
spell_drain(ch, spell, force, 0);
break;
case SPELL_CLOUT:
if (!check_spell_victim(ch, vict, spell))
return;
check_killer(ch, vict);
if (!AWAKE(vict))
target -= 2;
send_to_char("You feel a rush of air head towards you!", vict);
if (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_KILLER) && !IS_NPC(vict))
success = -1;
else
success = success_test(skill, 4 + target) - success_test(GET_DEFENSE(vict) + GET_DEFENSE(vict) ? GET_POWER(vict, ADEPT_SIDESTEP) : 0, 4 + damage_modifier(vict, buf));
if (success <= 0) {
act("Your clout spell harmlessly disperses as $n dodges it.", FALSE, vict, 0, ch, TO_VICT);
send_to_char("You easily dodge it!\r\n", vict);
act("$n dodges out of the way of unseen force.", TRUE, vict, 0, ch, TO_NOTVICT);
} else {
success -= success_test(GET_BOD(vict) + GET_BODY(vict), force - GET_IMPACT(vict));
int dam = convert_damage(stage(success, basedamage));
if (!AWAKE(vict)) {
act("$n's body recoils as though hit.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You feel a dull thud in the back of your mind.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 0) {
act("$n is thrown to the ground, unconcious, from an immense invisible force.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("It slams into you with the force of a freight train, knocking you to the ground, unconcious.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 300) {
act("$n stumbles backwards, almost losing $s footing, as $e is hit by an invisible force.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You stumble backwards, feeling groggy as the air slams into you at full force.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 700) {
act("$n steps back, and shakes $s head to clear it.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You step back as the force hits you, feeling a little worse for wear.\r\n", vict);
} else if (dam > 0) {
act("$n recoils, as if from a light punch.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You feel as though a fist strikes you across the face.\r\n", vict);
} else {
send_to_char("It rushes past you, not causing any damage.\r\n", vict);
act("$n doesn't seem hurt by your clout spell.", FALSE, vict, 0, ch, TO_VICT);
}
damage(ch, vict, dam, TYPE_MANIPULATION_SPELL, MENTAL);
}
spell_drain(ch, spell, force, basedamage);
break;
case SPELL_FLAMETHROWER:
if (!check_spell_victim(ch, vict, spell))
return;
check_killer(ch, vict);
if (!AWAKE(vict))
target -= 2;
else
success -= success_test(GET_DEFENSE(vict) + GET_DEFENSE(vict) ? GET_POWER(vict, ADEPT_SIDESTEP) : 0, 4 + damage_modifier(vict, buf));
act("$n's hands seem to spontaneously combust as $e directs a stream of flame at $N!", TRUE, ch, 0, vict, TO_ROOM);
if (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_KILLER) && !IS_NPC(vict))
success = -1;
else success = success_test(skill, target + 4);
if (success > 0 && GET_REFLECT(vict) && (reflected = reflect_spell(ch, vict, spell, force, 0, target + 4, success))) {
vict = ch;
ch = temp;
}
if (success <= 0) {
act("$n dodges the flames, which disperese as they past $s.", FALSE, vict, 0, 0, TO_ROOM);
send_to_char("You easily dodge the flames!\r\n", vict);
} else {
success -= success_test(GET_BOD(vict) + GET_BODY(vict) + GET_POWER(ch, ADEPT_TEMPERATURE_TOLERANCE), force - (GET_IMPACT(vict) / 2));
int dam = convert_damage(stage(success, basedamage));
if (!AWAKE(vict)) {
act("$n spasms as the flames hit $m.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You feel a slight burning sensation in the back of your mind.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 0) {
act("$n is hit full force by the intense flames causing $m to fall to the ground, gurgling.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("The flames burn intensely around you, your last memory before falling unconcious is the hideous pain.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 300) {
act("Screams as the flames impact $s body, horribly burning $m.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("The flames crash into you, causing you great pain as they horribly burn you.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 700) {
act("$n cringes as the flames hit, patting at the spots where the flame continues to burn.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("As the flames hit you quickly pat at the spots that continue to burn, causing searing pain.\r\n", vict);
} else if (dam > 0) {
act("The flames burst around $m, causing seemingly little damage.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("The flames burst around you causing you slight pain as it burns some of your hair.\r\n", vict);
} else {
act("The flames impact $n, but disperse on impact.", FALSE, vict, 0, ch, TO_ROOM);
send_to_char("The flames rapidly disperse around you, causing only mild discomfort.\r\n", vict);
}
damage_equip(ch, vict, force, TYPE_FIRE);
if (!damage(ch, vict, dam, TYPE_MANIPULATION_SPELL, PHYSICAL) && number(0, 6) <= basedamage + 1) {
act("^RThe flames continue to burn around $m!^N", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("^RYou continue to burn!\r\n", vict);
vict->points.fire[0] = srdice();
vict->points.fire[1] = 0;
}
}
spell_drain(reflected ? vict : ch, spell, force, basedamage);
break;
case SPELL_ACIDSTREAM:
if (!check_spell_victim(ch, vict, spell))
return;
check_killer(ch, vict);
if (!AWAKE(vict))
target -= 2;
else
success -= success_test(GET_DEFENSE(vict) + GET_DEFENSE(vict) ? GET_POWER(vict, ADEPT_SIDESTEP) : 0, 4 + damage_modifier(vict, buf));
act("Dark clouds form around $n moments before it condenses into a dark sludge and flies towards $N!", TRUE, ch, 0, vict, TO_ROOM);
if (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_KILLER) && !IS_NPC(vict))
success = -1;
else success = success_test(skill, target + 4);
if (success > 0 && GET_REFLECT(vict) && (reflected = reflect_spell(ch, vict, spell, force, 0, target + 4, success))) {
vict = ch;
ch = temp;
}
if (success <= 0) {
act("$n dodges the acid, which evaporates as it passes $s.", FALSE, vict, 0, 0, TO_ROOM);
send_to_char("You easily dodge the acid!\r\n", vict);
} else {
success -= success_test(GET_BOD(vict) + GET_BODY(vict) + GET_POWER(ch, ADEPT_TEMPERATURE_TOLERANCE), force - (GET_IMPACT(vict) / 2));
int dam = convert_damage(stage(success, basedamage));
if (!AWAKE(vict)) {
act("$n spasms as the acid hits $m.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You feel a slight burning sensation in the back of your mind.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 0) {
act("As the acid hits $n $e falls to the ground twitching and screaming as $s body smokes.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("The fumes from the acid burning through your body fill your lungs, burning you from the inside out as you fade into unconciousness.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 300) {
act("The acid hits $n, $e cries out in pain as trails of smoke come from $s body.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("The acid impacts you with a great force, causing you to step back as it burns through your skin.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 700) {
act("$n cringes as the acid hits.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("The acid begins to burn your skin as it hits you, causing a bit of pain.\r\n", vict);
} else if (dam > 0) {
act("$n is splashed by the acid, causing nothing but mild irritation.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("The acid splashes against you causing a mild burning sensation.\r\n", vict);
} else {
act("The acid splashes on $n, but $e doesn't seem to flinch.", FALSE, vict, 0, ch, TO_ROOM);
send_to_char("You are splashed by the acid, but it causes nothing more than a moments irritation.\r\n", vict);
}
damage_equip(ch, vict, force, TYPE_ACID);
AFF_FLAGS(vict).SetBit(AFF_ACID);
damage(ch, vict, dam, TYPE_MANIPULATION_SPELL, PHYSICAL);
}
spell_drain(reflected ? vict : ch, spell, force, basedamage);
break;
case SPELL_LIGHTNINGBOLT:
if (!check_spell_victim(ch, vict, spell))
return;
check_killer(ch, vict);
if (!AWAKE(vict))
target -= 2;
else
success -= success_test(GET_DEFENSE(vict), 4 + damage_modifier(vict, buf));
act("Lightning bursts forth from $n and heads directly towards $N!", TRUE, ch, 0, vict, TO_ROOM);
if (!IS_NPC(ch) && PLR_FLAGGED(ch, PLR_KILLER) && !IS_NPC(vict))
success = -1;
else success = success_test(skill, target + 4);
if (success > 0 && GET_REFLECT(vict) && (reflected = reflect_spell(ch, vict, spell, force, 0, target + 4, success))) {
vict = ch;
ch = temp;
}
if (success <= 0) {
act("$n easily dodges it, and it vanishes to nothing.", FALSE, vict, 0, 0, TO_ROOM);
send_to_char("You easily dodge it!\r\n", vict);
} else {
success -= success_test(GET_BOD(vict) + GET_BODY(vict) + GET_POWER(ch, ADEPT_TEMPERATURE_TOLERANCE), force - (GET_IMPACT(vict) / 2));
int dam = convert_damage(stage(success, basedamage));
if (!AWAKE(vict)) {
act("$n's body goes into convulsions as the lightning flows through it.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You feel a slight burning sensation in the back of your mind.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 0) {
act("$n is propelled backwards by the force of the lightning bolt, $s body smoking as it lands, not a sign of life from it.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You feel your body begin to spasm as the huge charge of electricity fries your nervous system.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 300) {
act("$n is almost lifted in the air by the lightning, spasms filling $s body, as a thin trail of smoke rise from $m.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("Your body is filled with pain as the lightning hits you, your limbs going into an uncontrolable seizure.\r\n", vict);
} else if (GET_MENTAL(vict) - (dam * 100) <= 700) {
act("$n spasms as the lightning hits $m, his body wracked with spasms as the lightning disipates.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("Pain flashes through your body as the lightning hits, your body wracked with serveral serious spasms.\r\n", vict);
} else if (dam > 0) {
act("$n visibly recoils as the lightning hits, but otherwise seems fine.", TRUE, vict, 0, 0, TO_ROOM);
send_to_char("You recoil as the lightning hits you, your mind going fuzzy for a moment.\r\n", vict);
} else {
act("The lightning hits $n, but seems to be easily absorbed.", FALSE, vict, 0, ch, TO_ROOM);
send_to_char("Your body absorbs the lightning without harm.\r\n", vict);
}
for (int i = 0; i < NUM_WEARS; i++)
if (GET_EQ(vict, i) && (GET_OBJ_MATERIAL(GET_EQ(vict, i)) == 10 || GET_OBJ_MATERIAL(GET_EQ(vict, i)) == 11))
damage_obj(vict, GET_EQ(vict, i), force, DAMOBJ_LIGHTNING);
damage(ch, vict, dam, TYPE_MANIPULATION_SPELL, PHYSICAL);
}
spell_drain(reflected ? vict : ch, spell, force, basedamage);
break;
}
}
void cast_spell(struct char_data *ch, int spell, int sub, int force, char *arg)
{
if (spells[spell].duration == SUSTAINED)
{
if (GET_SUSTAINED_NUM(ch) >= GET_SKILL(ch, SKILL_SORCERY)) {
send_to_char("You cannot sustain anymore spells.\r\n", ch);
return;
}
}
switch (spells[spell].category)
{
case COMBAT:
cast_combat_spell(ch, spell, force, arg);
break;
case DETECTION:
cast_detection_spell(ch, spell, force, arg, NULL);
break;
case HEALTH:
cast_health_spell(ch, spell, sub, force, arg, NULL);
break;
case ILLUSION:
cast_illusion_spell(ch, spell, force, arg, NULL);
break;
case MANIPULATION:
cast_manipulation_spell(ch, spell, force, arg, NULL);
break;
}
}
void mob_magic(struct char_data *ch)
{
if (!FIGHTING(ch))
return;
char buf[MAX_STRING_LENGTH];
int spell = 0, sub = 0, force, magic = GET_MAG(ch) / 100;
if (GET_WIL(ch) <= 2)
force = magic;
else force = MIN(magic, number(1, 8));
while (!spell) {
switch (number (0, 12)) {
case 0:
spell = SPELL_POWERBOLT;
break;
case 1:
spell = SPELL_MANABOLT;
break;
case 2:
spell = SPELL_STUNBOLT;
break;
case 3:
spell = SPELL_DECCYATTR;
sub = number(0, 2);
break;
case 4:
spell = SPELL_DECATTR;
sub = number(0, 2);
break;
case 5:
if (!affected_by_spell(FIGHTING(ch), SPELL_CONFUSION))
spell = SPELL_CONFUSION;
break;
case 6:
spell = SPELL_FLAMETHROWER;
break;
case 7:
spell = SPELL_ACIDSTREAM;
break;
case 8:
spell = SPELL_LIGHTNINGBOLT;
break;
case 9:
spell = SPELL_CLOUT;
break;
case 10:
/* if (!affected_by_spell(ch, SPELL_POLTERGEIST))
spell = SPELL_POLTERGEIST;
break;
*/ case 11:
if (!world[ch->in_room].icesheet[1])
spell = SPELL_ICESHEET;
break;
case 12:
if (!affected_by_spell(FIGHTING(ch), SPELL_IGNITE) && !ch->points.fire[0])
spell = SPELL_IGNITE;
break;
}
}
switch (spell) {
case SPELL_FLAMETHROWER:
case SPELL_MANABOLT:
case SPELL_STUNBOLT:
case SPELL_POWERBOLT:
case SPELL_ACIDSTREAM:
case SPELL_LIGHTNINGBOLT:
case SPELL_CLOUT:
sprintf(buf, "%s %s", wound_name[number(1, 4)], GET_CHAR_NAME(FIGHTING(ch)));
break;
default:
strcpy(buf, GET_CHAR_NAME(FIGHTING(ch)));
}
cast_spell(ch, spell, sub, force, buf);
}
bool check_spirit_sector(rnum_t room, int spirit)
{
if ((spirit == SPIRIT_WIND || spirit == SPIRIT_MIST || spirit == SPIRIT_STORM)) {
if (SECT(room) == SPIRIT_HEARTH || SECT(room) == SPIRIT_FOREST || ROOM_FLAGGED(room, ROOM_INDOORS))
return FALSE;
} else if (SECT(room) != spirit)
return FALSE;
return TRUE;
}
void circle_build(struct char_data *ch, char *type, int force)
{
if (IS_WORKING(ch))
{
send_to_char(TOOBUSY, ch);
return;
}
if (GET_TRADITION(ch) != TRAD_HERMETIC || GET_ASPECT(ch) == ASPECT_SORCERER)
{
send_to_char("Only hermetic mages need to construct a hermetic circle.\r\n", ch);
return;
}
if (ch->in_veh) {
send_to_char("You can't build a lodge in a vehicle.\r\n", ch);
return;
}
if (GET_NUYEN(ch) < force * force)
{
send_to_char(ch, "You need %d nuyen for the materials needed to construct that circle.\r\n", force * force);
return;
}
int element = 0;
for (;element < NUM_ELEMENTS; element++)
if (is_abbrev(type, elements[element].name))
break;
if (element == NUM_ELEMENTS)
{
send_to_char("What element do you wish to dedicate this circle to?\r\n", ch);
return;
}
GET_NUYEN(ch) -= force * force;
struct obj_data *obj = read_object(115, VIRTUAL);
GET_OBJ_VAL(obj, 1) = force;
GET_OBJ_VAL(obj, 2) = element;
GET_OBJ_VAL(obj, 3) = GET_IDNUM(ch);
GET_OBJ_VAL(obj, 9) = force * 60;
AFF_FLAGS(ch).SetBit(AFF_CIRCLE);
GET_BUILDING(ch) = obj;
obj_to_room(obj, ch->in_room);
send_to_char("You begin to draw a hermetic circle.\r\n", ch);
act("$n begins to draw a hermetic circle.\r\n", FALSE, ch, 0, 0, TO_ROOM);
}
void lodge_build(struct char_data *ch, int force)
{
if (IS_WORKING(ch))
{
send_to_char(TOOBUSY, ch);
return;
}
if (GET_TRADITION(ch) != TRAD_SHAMANIC)
{
send_to_char("Only shamans need to build a lodge.\r\n", ch);
return;
}
if (ch->in_veh) {
send_to_char("You can't build a lodge in a vehicle.\r\n", ch);
return;
}
if (GET_NUYEN(ch) < force * 500)
{
send_to_char(ch, "You need %d nuyen worth of materials to construct that lodge.\r\n", force * 500);
return;
}
if (force > GET_REAL_MAG(ch) / 50) {
send_to_char("You can't create a lodge higher than twice your magic rating.\r\n", ch);
return;
}
GET_NUYEN(ch) -= force * 500;
struct obj_data *obj = read_object(114, VIRTUAL);
GET_OBJ_VAL(obj, 1) = force;
GET_OBJ_VAL(obj, 2) = GET_TOTEM(ch);
GET_OBJ_VAL(obj, 3) = GET_IDNUM(ch);
GET_OBJ_VAL(obj, 9) = force * 60 * 5;
AFF_FLAGS(ch).SetBit(AFF_LODGE);
GET_BUILDING(ch) = obj;
obj_to_room(obj, ch->in_room);
send_to_char(ch, "You begin to build a lodge to %s.\r\n", totem_types[GET_TOTEM(ch)]);
act("$n begins to build a lodge.\r\n", FALSE, ch, 0, 0, TO_ROOM);
}
struct char_data *create_elemental(struct char_data *ch, int type, int force, int idnum, int trad)
{
struct char_data *mob;
if (trad == TRAD_HERMETIC)
mob = read_mobile(elements[type].vnum, VIRTUAL);
else
mob = read_mobile(spirits[type].vnum, VIRTUAL);
GET_REAL_BOD(mob) = force;
GET_REAL_QUI(mob) = force;
GET_REAL_STR(mob) = force;
GET_REAL_CHA(mob) = force;
GET_REAL_INT(mob) = force;
GET_REAL_WIL(mob) = force;
GET_ESS(mob) = force * 100;
GET_LEVEL(mob) = force;
GET_ACTIVE(mob) = GET_IDNUM(ch);
GET_SPARE1(mob) = type;
GET_SPARE2(mob) = force;
GET_GRADE(mob) = idnum;
if (trad == TRAD_HERMETIC)
switch (type)
{
case ELEM_EARTH:
GET_REAL_BOD(mob) += 4;
GET_REAL_QUI(mob) -= 2;
GET_REAL_STR(mob) += 4;
break;
case ELEM_FIRE:
GET_REAL_BOD(mob)++;
GET_REAL_QUI(mob) += 2;
GET_REAL_STR(mob) -= 2;
break;
case ELEM_AIR:
GET_REAL_BOD(mob) -= 2;
GET_REAL_QUI(mob) += 3;
GET_REAL_STR(mob) -= 3;
break;
case ELEM_WATER:
GET_REAL_BOD(mob) += 2;
break;
}
else
switch (type)
{
case SPIRIT_CITY:
case SPIRIT_FIELD:
case SPIRIT_HEARTH:
GET_REAL_BOD(mob)++;
GET_REAL_QUI(mob) += 2;
GET_REAL_STR(mob) -= 2;
break;
case SPIRIT_DESERT:
case SPIRIT_FOREST:
case SPIRIT_MOUNTAIN:
case SPIRIT_PRAIRIE:
GET_REAL_BOD(mob) += 4;
GET_REAL_QUI(mob) -= 2;
GET_REAL_STR(mob) += 4;
break;
case SPIRIT_MIST:
case SPIRIT_STORM:
case SPIRIT_WIND:
GET_REAL_BOD(mob) -= 2;
GET_REAL_QUI(mob) += 3;
GET_REAL_STR(mob) -= 3;
break;
case SPIRIT_LAKE:
case SPIRIT_RIVER:
case SPIRIT_SEA:
case SPIRIT_SWAMP:
GET_REAL_BOD(mob) += 2;
break;
}
if (ch->in_veh)
char_to_room(mob, ch->in_veh->in_room);
else
char_to_room(mob, ch->in_room);
add_follower(mob, ch);
affect_total(mob);
return mob;
}
ACMD(do_contest)
{
if (GET_ASPECT(ch) == ASPECT_SORCERER || GET_TRADITION(ch) == TRAD_ADEPT || GET_TRADITION(ch) == TRAD_MUNDANE || !GET_SKILL(ch, SKILL_CONJURING)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
struct char_data *mob, *caster = NULL;
skip_spaces(&argument);
if (!(mob = get_char_room_vis(ch, argument))) {
send_to_char(ch, "Contest the binding of which %s?\r\n", GET_TRADITION(ch) ? "nature spirit" : "elemental");
return;
}
if (GET_CHA(ch) <= GET_NUM_SPIRITS(ch)) {
send_to_char(ch, "You cannot have any more %ss bound to you.\r\n", GET_TRADITION(ch) ? "nature spirit" : "elemental");
return;
}
if (GET_TRADITION(ch) == TRAD_SHAMANIC && (GET_MOB_VNUM(mob) < 29 || GET_MOB_VNUM(mob) > 42)) {
send_to_char("You can only contest the binding of a nature spirit.\r\n", ch);
return;
} else if (GET_TRADITION(ch) == TRAD_HERMETIC && (GET_MOB_VNUM(mob) < 25 || GET_MOB_VNUM(mob) > 28)) {
send_to_char("You can only contest the binding of an elemental.\r\n", ch);
return;
}
if (GET_ACTIVE(mob) == GET_IDNUM(ch)) {
send_to_char(ch, "You already have that %s bound to you!\r\n", GET_TRADITION(ch) ? "nature spirit" : "elemental");
return;
}
if (!GET_ACTIVE(mob)) {
send_to_char("You can't bind a free spirit!\r\n", ch);
return;
}
for (struct descriptor_data *d = descriptor_list; d; d = d->next)
if (d->character && GET_IDNUM(d->character) == GET_ACTIVE(mob)) {
caster = d->character;
break;
}
if (!caster) {
send_to_char("You fain to gain control!\r\n", ch);
return;
}
int chskill = GET_SKILL(ch, SKILL_CONJURING), caskill = GET_SKILL(ch, SKILL_CONJURING) + GET_CHA(ch);
for (int i = 0; i < NUM_WEARS; i++)
if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_FOCUS && GET_OBJ_VAL(GET_EQ(ch, i), 0) == FOCI_SPIRIT
&& GET_OBJ_VAL(GET_EQ(ch, i), 2) == GET_IDNUM(ch) && GET_OBJ_VAL(GET_EQ(ch, i), 3) == GET_SPARE1(mob) &&
GET_OBJ_VAL(GET_EQ(ch, i), 4)) {
chskill += GET_OBJ_VAL(GET_EQ(ch, i), 1);
break;
}
for (int i = 0; i < NUM_WEARS; i++)
if (GET_EQ(caster, i) && GET_OBJ_TYPE(GET_EQ(caster, i)) == ITEM_FOCUS && GET_OBJ_VAL(GET_EQ(caster, i), 0) == FOCI_SPIRIT
&& GET_OBJ_VAL(GET_EQ(caster, i), 2) == GET_IDNUM(ch) && GET_OBJ_VAL(GET_EQ(caster, i), 3) == GET_SPARE1(mob) &&
GET_OBJ_VAL(GET_EQ(caster, i), 4)) {
chskill += GET_OBJ_VAL(GET_EQ(ch, i), 1);
break;
}
int chsuc = success_test(chskill, GET_LEVEL(mob)), casuc = success_test(caskill, GET_LEVEL(mob));
struct spirit_data *temp;
if (chsuc < 1 && casuc < 1) {
for (struct spirit_data *sdata = GET_SPIRIT(caster); sdata; sdata = sdata->next)
if (sdata->id == GET_GRADE(mob)) {
REMOVE_FROM_LIST(sdata, GET_SPIRIT(caster), next);
delete [] sdata;
break;
}
if (GET_MOB_VNUM(mob) < 25 || GET_MOB_VNUM(mob) > 28) {
act("$n senses an opportunity and vanishes!", TRUE, mob, 0, 0, TO_ROOM);
extract_char(mob);
} else {
MOB_FLAGS(mob).SetBit(MOB_AGGRESSIVE);
act("$n becomes uncontrolled!", TRUE, mob, 0, 0, TO_ROOM);
GET_ACTIVE(mob) = 0;
}
conjuring_drain(caster, GET_LEVEL(mob));
conjuring_drain(ch, GET_LEVEL(mob));
} else if (chsuc > casuc) {
send_to_char(ch, "You steal control of %s!\r\n", GET_NAME(mob));
sprintf(buf, "$n steals control of %s!", GET_NAME(mob));
act(buf, FALSE, ch, 0, caster, TO_VICT);
for (struct spirit_data *sdata = GET_SPIRIT(caster); sdata; sdata = sdata->next)
if (sdata->id == GET_GRADE(mob)) {
REMOVE_FROM_LIST(sdata, GET_SPIRIT(caster), next);
sdata->services = chsuc - casuc;
sdata->next = GET_SPIRIT(ch);
GET_SPIRIT(ch) = sdata->next;
GET_NUM_SPIRITS(ch)++;
GET_NUM_SPIRITS(caster)--;
break;
}
GET_ACTIVE(mob) = GET_IDNUM(ch);
conjuring_drain(caster, GET_LEVEL(mob));
conjuring_drain(ch, GET_LEVEL(mob));
} else {
send_to_char("You fail to gain control!\r\n", ch);
sprintf(buf, "$n tries to steal control of %s.", GET_NAME(mob));
act(buf, FALSE, ch, 0, caster, TO_VICT);
conjuring_drain(ch, GET_LEVEL(mob));
}
}
ACMD(do_unbond)
{
if (GET_TRADITION(ch) == TRAD_MUNDANE) {
send_to_char("You can't unbond something with no sense of the astral plane.\r\n", ch);
return;
}
struct obj_data *obj = NULL;
struct char_data *vict;
if (!generic_find(argument, FIND_OBJ_INV | FIND_OBJ_EQUIP, ch, &vict, &obj)) {
send_to_char("You don't have that item.\r\n", ch);
return;
}
if (GET_OBJ_TYPE(obj) == ITEM_FOCUS && GET_OBJ_VAL(obj, 2)) {
send_to_char("You severe the focus's bond with the astral plane.\r\n", ch);
GET_OBJ_VAL(obj, 2) = 0;
} else send_to_char("You can't unbond that.\r\n", ch);
}
ACMD(do_bond)
{
if (!*argument) {
send_to_char("What do you want to bond?\r\n", ch);
return;
}
half_chop(argument, buf1, buf2);
struct obj_data *obj;
int karma = 0, spirit = 0;
struct spell_data *spell = GET_SPELLS(ch);
for (obj = ch->carrying; obj; obj = obj->next_content)
if (isname(buf1, obj->text.keywords) || isname(buf2, GET_OBJ_NAME(obj)))
break;
if (!obj)
for (int i = 0; i < NUM_WEARS && !obj; i++)
if (GET_EQ(ch, i) && (isname(buf1, GET_EQ(ch, i)->text.keywords) || isname(buf1, GET_OBJ_NAME(GET_EQ(ch, i)))))
obj = GET_EQ(ch, i);
if (!obj) {
send_to_char("You don't have that item.\r\n", ch);
return;
}
if (GET_OBJ_TYPE(obj) == ITEM_DOCWAGON) {
if (GET_OBJ_VAL(obj, 1)) {
act("$p has already been activated.", FALSE, ch, obj, 0, TO_CHAR);
return;
}
GET_OBJ_VAL(obj, 1) = GET_IDNUM(ch);
act("$p's lights begin to subtly flash in a rhythmic sequence.", FALSE,
ch, obj, 0, TO_CHAR);
return;
}
if (GET_OBJ_TYPE(obj) == ITEM_FOCUS) {
if (GET_TRADITION(ch) == TRAD_MUNDANE)
send_to_char(ch, "You can't bond foci.\r\n");
else if (GET_TRADITION(ch) == TRAD_ADEPT && GET_OBJ_VAL(obj, 0) != FOCI_WEAPON)
send_to_char("Adepts can only bond weapon foci.\r\n", ch);
else if (IS_WORKING(ch))
send_to_char(TOOBUSY, ch);
else if (GET_POS(ch) > POS_SITTING)
send_to_char("You must be sitting to perform a bonding ritual.\r\n", ch);
else if (GET_OBJ_VAL(obj, 2) == GET_IDNUM(ch)) {
if (GET_OBJ_VAL(obj, 9)) {
GET_OBJ_VAL(obj, 9) = GET_OBJ_VAL(obj, 1) * 60;
send_to_char(ch, "You restart the ritual to bond %s.\r\n", GET_OBJ_NAME(obj));
act("$n begins a ritual to bond $o.", TRUE, ch, obj, 0, TO_ROOM);
AFF_FLAGS(ch).SetBit(AFF_BONDING);
ch->char_specials.programming = obj;
} else
send_to_char("You have already bonded this focus.\r\n", ch);
} else {
switch (GET_OBJ_VAL(obj, 0)) {
case FOCI_SPEC_SPELL:
karma = GET_OBJ_VAL(obj, 1);
break;
case FOCI_EXPENDABLE:
case FOCI_SPELL_CAT:
if (!*buf2) {
send_to_char("Bond which spell category?\r\n", ch);
return;
}
for (; spirit <= MANIPULATION; spirit++)
if (is_abbrev(buf2, spell_category[spirit]))
break;
if (spirit > MANIPULATION) {
send_to_char("That is not a valid category.\r\n", ch);
return;
}
if (GET_OBJ_VAL(obj, 0) == FOCI_SPELL_CAT)
karma = GET_OBJ_VAL(obj, 1) * 3;
break;
case FOCI_SPIRIT:
if (!*buf2) {
send_to_char("Bond which spirit type?\r\n", ch);
return;
}
if (GET_TRADITION(ch) == TRAD_HERMETIC) {
for (; spirit < NUM_ELEMENTS; spirit++)
if (is_abbrev(buf2, elements[spirit].name))
break;
} else
for (; spirit < NUM_SPIRITS; spirit++)
if (is_abbrev(buf2, spirits[spirit].name))
break;
if (GET_TRADITION(ch) == TRAD_HERMETIC ? spirit == NUM_ELEMENTS : spirit == NUM_SPIRITS) {
send_to_char(ch, "That is not a valid %s.\r\n", GET_TRADITION(ch) == TRAD_HERMETIC ? "elemental" : "spirit");
return;
}
karma = GET_OBJ_VAL(obj, 1) * 2;
break;
case FOCI_POWER:
karma = GET_OBJ_VAL(obj, 1) * 5;
break;
case FOCI_SUSTAINED:
karma = GET_OBJ_VAL(obj, 1);
break;
}
if (GET_OBJ_VAL(obj, 0) == FOCI_SUSTAINED || GET_OBJ_VAL(obj, 0) == FOCI_SPEC_SPELL) {
for (;spell; spell = spell->next)
if (is_abbrev(buf2, spell->name)) {
spirit = spell->type;
break;
}
if (!spell) {
send_to_char("You don't know that spell to bond.\r\n", ch);
return;
}
if (GET_OBJ_VAL(obj, 0) == FOCI_SUSTAINED && spells[spirit].duration != SUSTAINED) {
send_to_char("You don't need to bond a sustaining foci for this spell.\r\n", ch);
return;
}
}
if (PLR_FLAGGED(ch, PLR_AUTH)) {
if (GET_FORCE_POINTS(ch) < karma) {
send_to_char(ch, "You don't have enough force points to bond that (Need %d).\r\n", karma);
return;
}
GET_FORCE_POINTS(ch) -= karma;
GET_OBJ_VAL(obj, 9) = 1;
} else {
if (GET_KARMA(ch) < karma * 100) {
send_to_char(ch, "You don't have enough karma to bond that (Need %d).\r\n", karma);
return;
}
GET_KARMA(ch) -= karma * 100;
GET_OBJ_VAL(obj, 9) = GET_OBJ_VAL(obj, 1) * 60;
}
GET_OBJ_VAL(obj, 2) = GET_IDNUM(ch);
GET_OBJ_VAL(obj, 3) = spirit;
GET_OBJ_VAL(obj, 5) = GET_TRADITION(ch) == TRAD_HERMETIC ? 1 : 0;
send_to_char(ch, "You begin the ritual to bond %s.\r\n", GET_OBJ_NAME(obj));
act("$n begins a ritual to bond $o.", TRUE, ch, obj, 0, TO_ROOM);
AFF_FLAGS(ch).SetBit(AFF_BONDING);
ch->char_specials.programming = obj;
return;
}
} else
send_to_char("You cannot bond that item.\r\n", ch);
}
ACMD(do_release)
{
if (GET_TRADITION(ch) == TRAD_ADEPT || GET_TRADITION(ch) == TRAD_MUNDANE) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
two_arguments(argument, buf, buf1);
int i = 0;
if (is_abbrev(buf, "spirit") || is_abbrev(buf, "elemental")) {
if (GET_ASPECT(ch) == ASPECT_SORCERER || !GET_SKILL(ch, SKILL_CONJURING)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
}
if (!GET_SPIRIT(ch)) {
send_to_char("You don't have any elementals bound to you.\r\n", ch);
return;
}
int i;
if (!(i = atoi(buf1)) || i > GET_NUM_SPIRITS(ch)) {
send_to_char("Which spirit do you wish to release from your services?\r\n", ch);
return;
}
for (struct spirit_data *spirit = GET_SPIRIT(ch); spirit; spirit = spirit->next)
if (--i == 0) {
struct spirit_data *temp;
if (GET_TRADITION(ch) == TRAD_HERMETIC)
send_to_char(ch, "You release %s from its obligations and it departs to the metaplanes.\r\n", GET_NAME(&mob_proto[real_mobile(elements[spirit->type].vnum)]));
else
send_to_char(ch, "You release %s from its obligations and it departs to the metaplanes.\r\n", GET_NAME(&mob_proto[real_mobile(spirits[spirit->type].vnum)]));
if (spirit->called)
for (struct char_data *mob = character_list; mob; mob = mob->next)
if (IS_NPC(mob) && GET_ACTIVE(mob) == GET_IDNUM(ch) && GET_GRADE(mob) == spirit->id) {
act("Freed from its services, $n returns to the metaplanes", TRUE, mob, 0, ch, TO_NOTVICT);
extract_char(mob);
break;
}
REMOVE_FROM_LIST(spirit, GET_SPIRIT(ch), next);
delete [] spirit;
GET_NUM_SPIRITS(ch)--;
return;
}
} else if ((i = atoi(buf)) > 0) {
if (i > GET_SUSTAINED_NUM(ch))
send_to_char("You don't have that many spells sustained.\r\n", ch);
else {
struct sustain_data *sust;
for (sust = GET_SUSTAINED(ch); sust; sust = sust->next)
if (sust->caster && --i == 0)
break;
end_sustained_spell(ch, sust);
}
return;
}
send_to_char("Release what?\r\n", ch);
}
ACMD(do_cast)
{
if (GET_ASPECT(ch) == ASPECT_CONJURER || GET_TRADITION(ch) == TRAD_ADEPT || GET_TRADITION(ch) == TRAD_MUNDANE || !GET_SKILL(ch, SKILL_SORCERY)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
int force = 0;
char spell_name[120], tokens[MAX_STRING_LENGTH], *s;
struct spell_data *spell = GET_SPELLS(ch);
if (!*argument) {
send_to_char("Cast what spell?\r\n", ch);
return;
}
strcpy(tokens, argument);
if (strtok(tokens, "\"") && (s = strtok(NULL, "\""))) {
strcpy(spell_name, s);
if ((s = strtok(NULL, "\0"))) {
skip_spaces(&s);
strcpy(buf1, s);
} else
*buf1 = '\0';
one_argument(argument, buf);
force = atoi(buf);
} else {
half_chop(argument, buf, buf1);
if (!(force = atoi(buf))) {
strcpy(spell_name, buf);
} else {
half_chop(buf1, buf2, buf1);
strcpy(spell_name, buf2);
}
}
for (;spell; spell = spell->next)
if (is_abbrev(spell_name, spell->name) && !(!str_cmp(spell_name, "heal") && spell->type == SPELL_HEALTHYGLOW))
break;
if (!spell) {
send_to_char("You don't know that spell.\r\n", ch);
return;
}
if (!force)
force = spell->force;
else if (force > spell->force) {
send_to_char("You don't know that spell at that high a force.\r\n", ch);
return;
}
if (spells[spell->type].physical && IS_PROJECT(ch)) {
send_to_char("You can only cast mana spells on the astral plane.\r\n", ch);
return;
}
cast_spell(ch, spell->type, spell->subtype, force, buf1);
WAIT_STATE(ch, PULSE_VIOLENCE);
}
ACMD(do_conjure)
{
if (GET_ASPECT(ch) == ASPECT_SORCERER || GET_TRADITION(ch) == TRAD_ADEPT || GET_TRADITION(ch) == TRAD_MUNDANE || !GET_SKILL(ch, SKILL_CONJURING)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
if (IS_WORKING(ch)) {
send_to_char(TOOBUSY, ch);
return;
}
if (ch->in_veh) {
send_to_char("There is not enough room to conjure in here.\r\n", ch);
return;
}
if (IS_PROJECT(ch)) {
send_to_char("You cannot conjure while projecting.\r\n", ch);
return;
}
int force, spirit = 0;
two_arguments(argument, buf, buf1);
if (!(force = atoi(buf))) {
send_to_char("What force do you wish to conjure at?\r\n", ch);
return;
}
if (force > (GET_MAG(ch) / 100) * 2) {
send_to_char("You can't conjure a spirit of force more than twice your magic rating.\r\n", ch);
return;
}
if (GET_TRADITION(ch) == TRAD_HERMETIC) {
if (GET_NUM_SPIRITS(ch) >= GET_CHA(ch)) {
send_to_char("You have too many spirit summoned.\r\n", ch);
return;
}
for (; spirit < NUM_ELEMENTS; spirit++)
if (is_abbrev(buf1, elements[spirit].name))
break;
if (spirit == NUM_ELEMENTS) {
send_to_char("What elemental do you wish to conjure?\r\n", ch);
return;
}
if ((GET_ASPECT(ch) == ASPECT_ELEMFIRE && spirit != ELEM_FIRE) ||
(GET_ASPECT(ch) == ASPECT_ELEMWATER && spirit != ELEM_WATER) ||
(GET_ASPECT(ch) == ASPECT_ELEMAIR && spirit != ELEM_AIR) ||
(GET_ASPECT(ch) == ASPECT_ELEMEARTH && spirit != ELEM_EARTH)) {
send_to_char("You cannot summon elementals of that type.\r\n", ch);
return;
}
bool library = FALSE, circle = FALSE;
struct obj_data *obj;
for (struct obj_data *obj = world[ch->in_room].contents; obj; obj = obj->next_content)
if (GET_OBJ_TYPE(obj) == ITEM_MAGIC_TOOL)
if (GET_OBJ_VAL(obj, 0) == TYPE_LIBRARY_CONJURE) {
if (GET_OBJ_VAL(obj, 1) < force) {
send_to_char("Your library isn't of a high enough rating to conjure that elemental.\r\n", ch);
return;
}
library = TRUE;
} else if (GET_OBJ_VAL(obj, 0) == TYPE_CIRCLE && !GET_OBJ_VAL(obj, 9)) {
if (GET_OBJ_VAL(obj, 1) < force) {
send_to_char("Your hermetic circle isn't of a high enough rating to conjure that elemental.\r\n", ch);
return;
} else if (GET_OBJ_VAL(obj, 2) != spirit) {
send_to_char("That circle is for a different type of elemental.\r\n", ch);
return;
}
circle = TRUE;
}
if (!circle || !library) {
send_to_char("You need a conjuring library and a hermetic circle to conjure spirits.\r\n", ch);
return;
}
for (obj = ch->carrying; obj; obj = obj->next_content)
if (GET_OBJ_TYPE(obj) == ITEM_MAGIC_TOOL && GET_OBJ_VAL(obj, 0) == TYPE_SUMMONING)
if (GET_OBJ_COST(obj) < force * 1000) {
send_to_char("You don't have enough materials to summon at that high a force.\r\n", ch);
return;
} else
break;
if (!obj) {
send_to_char("You need conjuring materials to conjure an elemental.\r\n", ch);
return;
}
AFF_FLAGS(ch).SetBit(AFF_CONJURE);
ch->char_specials.conjure[0] = spirit;
ch->char_specials.conjure[1] = force;
ch->char_specials.conjure[2] = force * 30;
ch->char_specials.programming = obj;
send_to_char(ch, "You begin to conjure a %s elemental.\r\n", elements[spirit].name);
} else {
if (GET_NUM_SPIRITS(ch)) {
send_to_char("You already have summoned a nature spirit.\r\n", ch);
return;
}
for (; spirit < NUM_SPIRITS; spirit++)
if (is_abbrev(buf1, spirits[spirit].name))
break;
if (spirit == NUM_SPIRITS) {
send_to_char("Which spirit do you wish to conjure?\r\n", ch);
return;
}
if (GET_DOMAIN(ch) != ((spirit == SPIRIT_MIST || spirit == SPIRIT_STORM || spirit == SPIRIT_WIND) ? SPIRIT_SKY : spirit)) {
send_to_char("You aren't in the correct domain to conjure that spirit.\r\n", ch);
return;
}
int skill = GET_SKILL(ch, SKILL_CONJURING), target = force;
if (world[ch->in_room].background[1] == AURA_POWERSITE)
skill += world[ch->in_room].background[0];
else target += world[ch->in_room].background[0];
totem_bonus(ch, CONJURING, spirit, target, skill);
if (GET_ASPECT(ch) == ASPECT_SHAMANIST && skill == GET_SKILL(ch, SKILL_CONJURING)) {
send_to_char("Your totem will not let you conjure that spirit!\r\n", ch);
return;
}
for (int i = 0; i < NUM_WEARS; i++)
if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_FOCUS && GET_OBJ_VAL(GET_EQ(ch, i), 0) == FOCI_SPIRIT
&& GET_OBJ_VAL(GET_EQ(ch, i), 2) == GET_IDNUM(ch) && GET_OBJ_VAL(GET_EQ(ch, i), 3) == ch->char_specials.conjure[0]
&& GET_OBJ_VAL(GET_EQ(ch, i), 4)) {
skill += GET_OBJ_VAL(GET_EQ(ch, i), 1);
break;
}
int success = success_test(skill, target);
if (!conjuring_drain(ch, force) && AWAKE(ch)) {
if (success < 1)
send_to_char("You fail to conjure forth that spirit.\r\n", ch);
else {
struct spirit_data *spirdata = new spirit_data;
spirdata->type = spirit;
spirdata->force = force;
spirdata->id = number(0, 1000);
spirdata->services = success;
spirdata->called = TRUE;
spirdata->next = GET_SPIRIT(ch);
GET_SPIRIT(ch) = spirdata;
GET_NUM_SPIRITS(ch)++;
struct char_data *mob = create_elemental(ch, spirit, force, spirdata->id, TRAD_SHAMANIC);
send_to_char("The spirit hears your call and comes forth from the metaplanes.\r\n", ch);
act("$n fades into existance on the astral plane.", TRUE, mob, 0, 0, TO_ROOM);
}
}
}
}
ACMD(do_spells)
{
if (GET_ASPECT(ch) == ASPECT_CONJURER || GET_TRADITION(ch) == TRAD_ADEPT || GET_TRADITION(ch) == TRAD_MUNDANE || !GET_SKILL(ch, SKILL_SORCERY)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
if (!GET_SPELLS(ch)) {
send_to_char("You don't know any spells.\r\n", ch);
return;
}
send_to_char("You know the following spells:\r\n", ch);
for (struct spell_data *spell = GET_SPELLS(ch); spell; spell = spell->next)
send_to_char(ch, "%-50s Type: %10s Force: %d\r\n", spell->name, spells[spell->type].name, spell->force);
}
ACMD(do_learn)
{
if (GET_ASPECT(ch) == ASPECT_CONJURER || GET_TRADITION(ch) == TRAD_ADEPT || GET_TRADITION(ch) == TRAD_MUNDANE || !GET_SKILL(ch, SKILL_SORCERY)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
two_arguments(argument, buf, buf1);
struct obj_data *obj = ch->carrying;
struct spell_data *spell = NULL;
int force, oldforce = 0;
if (!*buf || !(obj = get_obj_in_list_vis(ch, buf, ch->carrying))) {
send_to_char("Learn which spell?\r\n", ch);
return;
}
if (GET_OBJ_TYPE(obj) != ITEM_SPELL_FORMULA) {
send_to_char("You can't learn anything from that.\r\n", ch);
return;
}
if (GET_OBJ_TIMER(obj) <= -2) {
send_to_char("That spell design isn't complete.\r\n", ch);
return;
}
if ((GET_TRADITION(ch) == TRAD_HERMETIC && GET_OBJ_VAL(obj, 2)) || (GET_TRADITION(ch) == TRAD_SHAMANIC && !GET_OBJ_VAL(obj, 2))) {
send_to_char("You don't understand this formula.\r\n", ch);
return;
}
if (!*buf2 || atoi(buf1) == 0)
force = GET_OBJ_VAL(obj, 0);
else
force = MIN(GET_OBJ_VAL(obj, 0), atoi(buf1));
for (spell = GET_SPELLS(ch); spell; spell = spell->next)
if (spell->type == GET_OBJ_VAL(obj, 1) && spell->subtype == GET_OBJ_VAL(obj, 3)) {
if (spell->force >= force) {
send_to_char("You already know this spell at an equal or higher force.\r\n", ch);
return;
} else {
oldforce = spell->force;
break;
}
}
if (GET_KARMA(ch) < (force - oldforce) * 100) {
send_to_char(ch, "You don't have enough karma to learn this spell at that force! (You need %d)\r\n", force);
return;
}
if ((GET_ASPECT(ch) == ASPECT_ELEMFIRE && spells[GET_OBJ_VAL(obj, 1)].category != COMBAT) ||
(GET_ASPECT(ch) == ASPECT_ELEMEARTH && spells[GET_OBJ_VAL(obj, 1)].category != MANIPULATION) ||
(GET_ASPECT(ch) == ASPECT_ELEMWATER && spells[GET_OBJ_VAL(obj, 1)].category != ILLUSION) ||
(GET_ASPECT(ch) == ASPECT_ELEMAIR && spells[GET_OBJ_VAL(obj, 1)].category != DETECTION)) {
send_to_char("Glancing over the formula you realise you can't bind mana in that fashion.\r\n", ch);
}
if (GET_ASPECT(ch) == ASPECT_SHAMANIST) {
int skill = 0, target = 0;
totem_bonus(ch, 0, GET_OBJ_VAL(obj, 1), target, skill);
if (skill < 1) {
send_to_char(ch, "%s forbids you from learning this spell.\r\n", totem_types[GET_TOTEM(ch)]);
}
}
struct obj_data *library = world[ch->in_room].contents;
for (;library; library = library->next_content)
if (GET_OBJ_TYPE(library) == ITEM_MAGIC_TOOL && GET_OBJ_VAL(library, 1) >= force &&
((GET_TRADITION(ch) == TRAD_SHAMANIC
&& GET_OBJ_VAL(library, 0) == TYPE_LODGE && GET_OBJ_VAL(library, 3) == GET_IDNUM(ch)) ||
(GET_TRADITION(ch) == TRAD_HERMETIC && GET_OBJ_VAL(library, 0) == TYPE_LIBRARY_SPELL)))
break;
if (!library) {
send_to_char("You don't have the right tools here to learn that spell.\r\n", ch);
return;
}
if (GET_TRADITION(ch) == TRAD_SHAMANIC && GET_OBJ_VAL(library, 9)) {
send_to_char("You need to finish building that lodge before you can use it.\r\n", ch);
return;
}
int skill = GET_SKILL(ch, SKILL_SORCERY);
if (GET_TRADITION(ch) == TRAD_SHAMANIC) {
int target = 0;
totem_bonus(ch, 0, GET_OBJ_VAL(obj, 1), target, skill);
} else if (GET_TRADITION(ch) == TRAD_HERMETIC && GET_SPIRIT(ch)) {
for (struct spirit_data *spir = GET_SPIRIT(ch); spir && skill == GET_SKILL(ch, SKILL_SORCERY); spir = spir->next)
if (spir->called) {
struct char_data *spirit = find_spirit_by_id(spir->id, GET_IDNUM(ch));
if (MOB_FLAGS(spirit).IsSet(MOB_STUDY)) {
switch(spir->type) {
case ELEM_FIRE:
if (spells[GET_OBJ_VAL(obj, 1)].category == COMBAT) {
skill += spir->force;
MOB_FLAGS(spirit).RemoveBit(MOB_STUDY);
}
break;
case ELEM_WATER:
if (spells[GET_OBJ_VAL(obj, 1)].category == ILLUSION) {
skill += spir->force;
MOB_FLAGS(spirit).RemoveBit(MOB_STUDY);
}
break;
case ELEM_AIR:
if (spells[GET_OBJ_VAL(obj, 1)].category == DETECTION) {
skill += spir->force;
MOB_FLAGS(spirit).RemoveBit(MOB_STUDY);
}
break;
case ELEM_EARTH:
if (spells[GET_OBJ_VAL(obj, 1)].category == MANIPULATION) {
skill += spir->force;
MOB_FLAGS(spirit).RemoveBit(MOB_STUDY);
}
break;
}
elemental_fulfilled_services(ch, spirit, spir);
break;
}
}
}
if (success_test(skill, force * 2) < 1) {
send_to_char("You can't get your head around how to cast that spell.\r\n", ch);
return;
}
if (spell) {
struct spell_data *temp;
REMOVE_FROM_LIST(spell, GET_SPELLS(ch), next);
delete [] spell;
spell = NULL;
}
GET_KARMA(ch) -= (force - oldforce) * 100;
spell = new spell_data;
if (GET_OBJ_VAL(obj, 1) == SPELL_INCATTR || GET_OBJ_VAL(obj, 1) == SPELL_INCCYATTR ||
GET_OBJ_VAL(obj, 1) == SPELL_DECATTR || GET_OBJ_VAL(obj, 1) == SPELL_DECCYATTR) {
strcpy(buf, spells[GET_OBJ_VAL(obj, 1)].name);
sprintf(ENDOF(buf), " (%s)", attributes[GET_OBJ_VAL(obj, 3)]);
spell->name = str_dup(buf);
} else
spell->name = str_dup(spells[GET_OBJ_VAL(obj, 1)].name);
spell->type = GET_OBJ_VAL(obj, 1);
spell->subtype = GET_OBJ_VAL(obj, 3);
spell->force = force;
spell->next = GET_SPELLS(ch);
GET_SPELLS(ch) = spell;
send_to_char(ch, "You spend %d karma and learn %s.\r\n", force - oldforce, spell->name);
extract_obj(obj);
}
ACMD(do_elemental)
{
if (GET_ASPECT(ch) == ASPECT_SORCERER || GET_TRADITION(ch) == TRAD_MUNDANE || GET_TRADITION(ch) == TRAD_ADEPT || !GET_SKILL(ch, SKILL_CONJURING)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
if (!GET_NUM_SPIRITS(ch)) {
send_to_char("You don't have any elementals bound to you.\r\n", ch);
return;
}
int i = 1;
strcpy(buf, "You currently have the following elementals bound:\r\n");
for (struct spirit_data *elem = GET_SPIRIT(ch); elem; elem = elem->next, i++) {
if (GET_TRADITION(ch) == TRAD_SHAMANIC)
sprintf(ENDOF(buf), "%d) %-30s (Force %d) Services %d\r\n", i, GET_NAME(&mob_proto[real_mobile(spirits[elem->type].vnum)]), elem->force, elem->services);
else
sprintf(ENDOF(buf), "%d) %-30s (Force %d) Services: %d%10s\r\n", i, GET_NAME(&mob_proto[real_mobile(elements[elem->type].vnum)]),
elem->force, elem->services, elem->called ? " Present" : " ");
}
send_to_char(buf, ch);
}
ACMD(do_banish)
{
if (GET_ASPECT(ch) == ASPECT_SORCERER || GET_TRADITION(ch) == TRAD_ADEPT || GET_TRADITION(ch) == TRAD_MUNDANE || !GET_SKILL(ch, SKILL_CONJURING)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
if (IS_DUAL(ch) || IS_PROJECT(ch)) {
send_to_char("You cannot banish while perceiving or projecting.\r\n", ch);
return;
}
if (AFF_FLAGGED(ch, AFF_BANISH)) {
if (GET_EXTRA(ch)) {
if (FIGHTING(ch)) {
act("You give up trying to banish $n.", FALSE, FIGHTING(ch), 0, ch, TO_VICT);
AFF_FLAGS(FIGHTING(ch)).RemoveBit(AFF_BANISH);
}
stop_fighting(ch);
AFF_FLAGS(ch).RemoveBit(AFF_BANISH);
} else
send_to_char(ch, "Try as you might, you can't wrest your mind away!\r\n");
return;
}
struct char_data *mob;
skip_spaces(&argument);
if (!(mob = get_char_room_vis(ch, argument))) {
send_to_char("Attempt to banish which spirit?\r\n", ch);
return;
}
if (GET_RACE(mob) != RACE_SPIRIT && GET_RACE(mob) != RACE_ELEMENTAL) {
send_to_char("You can only banish a nature spirit or elemental.\r\n", ch);
return;
}
AFF_FLAGS(ch).SetBit(AFF_BANISH);
AFF_FLAGS(mob).SetBit(AFF_BANISH);
stop_fighting(ch);
stop_fighting(mob);
set_fighting(ch, mob);
set_fighting(mob, ch);
send_to_char(ch, "You begin attempting to banish %s.\r\n", GET_NAME(mob));
act("$n begins attempting to banish $N.", FALSE, ch, 0, mob, TO_ROOM);
GET_EXTRA(ch) = 1;
GET_EXTRA(mob) = 0;
}
bool spirit_can_perform(int type, int order, int tradition)
{
if (order == SERV_MATERIALIZE || order == SERV_DEMATERIAL || order == SERV_ATTACK)
return TRUE;
if (tradition == TRAD_HERMETIC) {
if (order == SERV_ENGULF || order == SERV_APPEAR || order == SERV_SORCERY || order == SERV_STUDY || order == SERV_SUSTAIN || order == SERV_LEAVE)
return TRUE;
switch (type) {
case ELEM_FIRE:
if (order == SERV_FLAMEAURA || order == SERV_GUARD || order == SERV_FLAMETHROWER)
return TRUE;
break;
case ELEM_AIR:
if (order == SERV_MOVEMENT || order == SERV_BREATH || order == SERV_PSYCHOKINESIS)
return TRUE;
break;
case ELEM_WATER:
case ELEM_EARTH:
if (order == SERV_MOVEMENT)
return TRUE;
break;
}
} else {
if ((type != SPIRIT_STORM && type != SPIRIT_DESERT) && order == SERV_ACCIDENT)
return TRUE;
if ((type != SPIRIT_LAKE && type != SPIRIT_WIND) && order == SERV_CONCEAL)
return TRUE;
if (type != SPIRIT_STORM && order == SERV_GUARD)
return TRUE;
if ((type != SPIRIT_FOREST && type != SPIRIT_STORM && type != SPIRIT_MIST) && order == SERV_SEARCH)
return TRUE;
switch(type) {
case SPIRIT_CITY:
if (order == SERV_CONFUSION || order == SERV_FEAR)
return TRUE;
break;
case SPIRIT_FIELD:
break;
case SPIRIT_HEARTH:
if (order == SERV_CONFUSION)
return TRUE;
break;
case SPIRIT_DESERT:
if (order == SERV_MOVEMENT)
return TRUE;
break;
case SPIRIT_FOREST:
if (order == SERV_CONFUSION || order == SERV_FEAR)
return TRUE;
break;
case SPIRIT_MOUNTAIN:
case SPIRIT_PRAIRIE:
if (order == SERV_MOVEMENT)
return TRUE;
break;
case SPIRIT_MIST:
if (order == SERV_CONFUSION || order == SERV_MOVEMENT)
return TRUE;
break;
case SPIRIT_STORM:
if (order == SERV_CONFUSION || order == SERV_FEAR)
return TRUE;
break;
case SPIRIT_WIND:
if (order == SERV_CONFUSION || order == SERV_MOVEMENT)
return TRUE;
break;
case SPIRIT_LAKE:
if (order == SERV_ENGULF || order == SERV_FEAR || order == SERV_MOVEMENT)
return TRUE;
break;
case SPIRIT_RIVER:
if (order == SERV_ENGULF || order == SERV_FEAR || order == SERV_MOVEMENT)
return TRUE;
break;
case SPIRIT_SEA:
if (order == SERV_CONFUSION || order == SERV_ENGULF || order == SERV_MOVEMENT)
return TRUE;
break;
case SPIRIT_SWAMP:
if (order == SERV_BINDING || order == SERV_CONFUSION || order == SERV_ENGULF || order == SERV_FEAR ||
order == SERV_MOVEMENT)
return TRUE;
break;
}
}
return FALSE;
}
void make_spirit_power(struct char_data *spirit, struct char_data *tch, int type)
{
struct spirit_sustained *ssust = new spirit_sustained;
ssust->type = type;
ssust->caster = TRUE;
ssust->target = tch;
ssust->next = SPIRIT_SUST(spirit);
SPIRIT_SUST(spirit) = ssust;
ssust = new spirit_sustained;
ssust->type = type;
ssust->caster = FALSE;
ssust->target = spirit;
ssust->next = SPIRIT_SUST(tch);
SPIRIT_SUST(tch) = ssust;
}
void stop_spirit_power(struct char_data *spirit, int type)
{
struct spirit_sustained *temp;
for (struct spirit_sustained *ssust = SPIRIT_SUST(spirit); ssust; ssust = ssust->next)
if (ssust->type == type && ssust->caster == TRUE)
{
for (struct spirit_sustained *tsust = SPIRIT_SUST(ssust->target); tsust; tsust = tsust->next)
if (tsust->type == type && tsust->target == spirit) {
if (type == ENGULF) {
if (IS_SPIRIT(spirit) || (IS_ELEMENTAL(spirit) && GET_SPARE1(spirit) == ELEM_WATER)) {
act("The water surrounding $n falls away and soaks into the ground almost instantly.", TRUE, ssust->target, 0, 0, TO_ROOM);
send_to_char("The water surrounding you suddenly vanishes allowing you to gasp for breath!", ssust->target);
} else {
switch (GET_SPARE1(spirit)) {
case ELEM_FIRE:
act("The fire engulfing $n suddenly goes out.", TRUE, ssust->target, 0, 0, TO_ROOM);
send_to_char("The water fire surrounding you suddenly vanishes!", ssust->target);
break;
case ELEM_EARTH:
act("The dirt and rock engulfing $n suddenly bursts apart, covering everyone close by.", TRUE, ssust->target, 0, 0, TO_ROOM);
send_to_char("The earth surrounding you suddenly bursts open, allowing you to gasp for air!", ssust->target);
break;
case ELEM_AIR:
act("$n begins to gasp for breath as though $s was just chocked.", TRUE, ssust->target, 0, 0, TO_ROOM);
send_to_char("The mysterious force oppressing your lungs is suddenly gone!", ssust->target);
break;
}
}
} else if (type == CONFUSION)
send_to_char("Your mind clears.\r\n", ssust->target);
else if (type == CONCEAL)
send_to_char("You suddenly feel very exposed.\r\n", ssust->target);
else if (type == MOVEMENTUP || type == MOVEMENTDOWN)
send_to_char("The force pushing you forward seems to lessen.\r\n", ssust->target);
REMOVE_FROM_LIST(tsust, SPIRIT_SUST(ssust->target), next);
delete [] tsust;
break;
}
REMOVE_FROM_LIST(ssust, SPIRIT_SUST(spirit), next);
delete [] ssust;
break;
}
}
POWER(spirit_appear)
{
spiritdata->called = TRUE;
spirit = create_elemental(ch, spiritdata->type, spiritdata->force, spiritdata->id, GET_TRADITION(ch));
act("$n appears in the astral plane.", TRUE, spirit, 0, ch, TO_NOTVICT);
send_to_char(ch, "%s heeds your call and arrives from the metaplanes ready to do your bidding.\r\n", CAP(GET_NAME(spirit)));
}
POWER(spirit_sorcery)
{
if (!MOB_FLAGS(spirit).IsSet(MOB_AIDSORCERY)) {
spiritdata->services--;
MOB_FLAGS(spirit).SetBit(MOB_AIDSORCERY);
send_to_char(ch, "%s will now asist you in casting a spell next time it is able.\r\n", CAP(GET_NAME(spirit)));
} else
send_to_char(ch, "%s will already asist in spell casting next time it is able.\r\n", CAP(GET_NAME(spirit)));
}
POWER(spirit_study)
{
if (!MOB_FLAGS(spirit).IsSet(MOB_STUDY)) {
spiritdata->services--;
MOB_FLAGS(spirit).SetBit(MOB_STUDY);
send_to_char(ch, "%s will now asist you in studying a spell next time it is able.\r\n", CAP(GET_NAME(spirit)));
} else
send_to_char(ch, "%s will already asist you the next time it is able.\r\n", CAP(GET_NAME(spirit)));
}
POWER(spirit_sustain)
{
struct sustain_data *sust;
if (GET_SUSTAINED_NUM(spirit))
send_to_char("That spirit is already sustaining a spell.\r\n", ch);
else {
int i = atoi(arg);
if (i <= 0 || i > GET_SUSTAINED_NUM(ch)) {
send_to_char("You aren't sustaining that many spells.\r\n", ch);
return;
}
for (sust = GET_SUSTAINED(ch); sust; sust = sust->next)
if (sust->caster && --i == 0)
break;
if (sust->focus || sust->spirit) {
send_to_char("You aren't sustaining that spell yourself.\r\n", ch);
return;
}
if ((spells[sust->spell].category == MANIPULATION && spiritdata->type == ELEM_EARTH) ||
(spells[sust->spell].category == COMBAT && spiritdata->type == ELEM_FIRE) ||
(spells[sust->spell].category == ILLUSION && spiritdata->type == ELEM_WATER) ||
(spells[sust->spell].category == DETECTION && spiritdata->type == ELEM_AIR)) {
sust->spirit = spirit;
GET_SUSTAINED_FOCI(ch)++;
GET_SUSTAINED_NUM(spirit)++;
spiritdata->services--;
GET_SUSTAINED(spirit) = sust;
send_to_char(ch, "%s sustains %s for you.\r\n", CAP(GET_NAME(spirit)), spells[sust->spell].name);
} else
send_to_char("That spirit can't sustain that type of spell.\r\n", ch);
}
}
POWER(spirit_accident)
{
struct char_data *tch = get_char_room_vis(spirit, arg);
if (!tch)
send_to_char("Use accident against which target?\r\n", ch);
else if (tch == ch)
send_to_char("You cannot target yourself with that power.\r\n", ch);
else if (tch == spirit)
send_to_char("The spirit refuses to perform that service.\r\n", ch);
else {
int success = success_test(MAX(GET_INT(tch), GET_QUI(tch)), GET_SPARE2(spirit));
for (struct char_data *mob = world[spirit->in_room].people; mob; mob = mob->next)
if (IS_NPC(mob) && (GET_RACE(mob) == RACE_SPIRIT || GET_RACE(mob) == RACE_ELEMENTAL) &&
MOB_FLAGGED(mob, MOB_SPIRITGUARD)) {
success = -1;
break;
}
if (success < 1) {
act("$n trips and stumbles.", TRUE, tch, 0, 0, TO_ROOM);
send_to_char(tch, "You trip and stumble!");
GET_INIT_ROLL(tch) -= 10;
} else {
sprintf(buf, "%s fails to cause $N to have an accident.", CAP(GET_NAME(spirit)));
act(buf, TRUE, ch, 0, tch, TO_CHAR);
}
spiritdata->services--;
}
}
POWER(spirit_binding)
{
struct char_data *tch = get_char_room_vis(spirit, arg);
if (!tch)
send_to_char("Use binding against which target?\r\n", ch);
else if (tch == spirit || tch == ch)
send_to_char("The spirit refuses to perform that service.\r\n", ch);
else {
act("$N suddenly becomes incapable of movement!", FALSE, spirit, 0, ch, TO_VICT);
send_to_char("You suddenly notice you are stuck fast to the ground!", tch);
AFF_FLAGS(tch).SetBit(AFF_BINDING);
tch->points.binding = GET_LEVEL(spirit) * 2;
spiritdata->services--;
}
}
POWER(spirit_conceal)
{
struct char_data *tch = get_char_room_vis(spirit, arg);
if (affected_by_power(spirit, CONCEAL)) {
act("$N stops providing that services.", FALSE, ch, 0, spirit, TO_CHAR);
stop_spirit_power(spirit, CONCEAL);
return;
}
if (!tch)
send_to_char("Use conceal against which target?\r\n", ch);
else if (tch == spirit || affected_by_power(tch, CONCEAL))
send_to_char("The spirit refuses to perform that service.\r\n", ch);
else {
act("$n vanishes from sight.", FALSE, spirit, 0, ch, TO_VICT);
send_to_char("The terrain seems to cover your tracks.", tch);
make_spirit_power(spirit, tch, CONCEAL);
spiritdata->services--;
}
}
POWER(spirit_confusion)
{
struct char_data *tch = get_char_room_vis(spirit, arg);
if (affected_by_power(spirit, CONFUSION)) {
act("$N stops providing that services.", FALSE, ch, 0, spirit, TO_CHAR);
stop_spirit_power(spirit, CONFUSION);
return;
}
if (!tch)
send_to_char("Use confusion against which target?\r\n", ch);
else if (tch == spirit || tch == ch || affected_by_power(tch, CONFUSION))
send_to_char("The spirit refuses to perform that service.\r\n", ch);
else {
act("$n vanishes from sight.", FALSE, spirit, 0, ch, TO_VICT);
send_to_char("The terrain seems to cover your tracks.", tch);
make_spirit_power(spirit, tch, CONFUSION);
spiritdata->services--;
}
}
POWER(spirit_engulf)
{
struct char_data *tch = get_char_room_vis(spirit, arg);
if (affected_by_power(spirit, ENGULF)) {
act("$N stops providing that services.", FALSE, ch, 0, spirit, TO_CHAR);
stop_spirit_power(spirit, ENGULF);
return;
}
if (!tch)
send_to_char("Use movement against which target?\r\n", ch);
else if (tch == spirit || tch == ch || affected_by_power(tch, ENGULF))
send_to_char("The spirit refuses to perform that service.\r\n", ch);
else {
act("$n rushes towards $N and attempts to engulf them!", FALSE, spirit, 0, tch, TO_ROOM);
int target = GET_QUI(spirit), targskill = get_skill(tch, SKILL_UNARMED_COMBAT, target);
int success = success_test(GET_QUI(spirit), targskill) - success_test(targskill, GET_QUI(spirit));
if (success < 1) {
act("$n successfully dodges the attack!", TRUE, ch, 0, 0, TO_ROOM);
send_to_char("You successfully dodge!\r\n", tch);
return;
}
if (IS_SPIRIT(spirit) || (IS_ELEMENTAL(spirit) && GET_SPARE1(spirit) == ELEM_WATER)) {
act("The water in the air surrounding $n seems to quickly condense and engulf $s!", TRUE, tch, 0, 0, TO_ROOM);
send_to_char("The water in the air around you seems to condense and swallow you up!", tch);
} else {
switch (GET_SPARE1(spirit)) {
case ELEM_FIRE:
act("A strange, unnatural fire suddenly engulfs $n!", TRUE, tch, 0, 0, TO_ROOM);
send_to_char("Fire suddenly engulfs your entire body!", tch);
break;
case ELEM_EARTH:
act("The ground seems to rise up from below and encase $n!", TRUE, tch, 0, 0, TO_ROOM);
send_to_char("The earth surrounding you suddenly bursts open, allowing you to gasp for air!", tch);
break;
case ELEM_AIR:
act("$n suddenly falls to $s knees and begins to wretch!", TRUE, tch, 0, 0, TO_ROOM);
send_to_char("A huge pressure falls on your lungs and you find it impossible to breath!", tch);
break;
}
}
make_spirit_power(spirit, tch, ENGULF);
set_fighting(spirit, tch);
set_fighting(tch, spirit);
GET_EXTRA(tch) = 0;
spiritdata->services--;
}
}
POWER(spirit_fear)
{
struct char_data *tch = get_char_room_vis(spirit, arg);
if (!tch)
send_to_char("Use fear against which target?\r\n", ch);
else if (tch == ch)
send_to_char("You cannot target yourself with that power.\r\n", ch);
else if (tch == spirit)
send_to_char("The spirit refuses to perform that service.\r\n", ch);
else {
int success = success_test(GET_SPARE2(spirit), GET_WIL(tch)) - success_test(GET_WIL(tch), GET_SPARE2(spirit));
if (success < 1) {
send_to_char("A dark shadow passes over your mind, but is quickly gone.\r\n", tch);
sprintf(buf, "%s fails to instill fear in $N.", CAP(GET_NAME(spirit)));
act(buf, FALSE, ch, 0, tch, TO_CHAR);
} else {
AFF_FLAGS(tch).SetBit(AFF_FEAR);
send_to_char("An all consuming terror overcomes you!\r\n", tch);
sprintf(buf, "%s succeeds in instilling fear in $N.", CAP(GET_NAME(spirit)));
act(buf, FALSE, ch, 0, tch, TO_CHAR);
extern ACMD(do_flee);
do_flee(tch, "", 0, 0);
}
spiritdata->services--;
}
}
POWER(spirit_flameaura)
{
if (!MOB_FLAGGED(spirit, MOB_FLAMEAURA))
act("$n's body erupts in flames.", TRUE, spirit, 0, 0, TO_ROOM);
else
act("The flames surrounding $n subsides.", TRUE, spirit, 0, 0, TO_ROOM);
MOB_FLAGS(spirit).ToggleBit(MOB_FLAMEAURA);
spiritdata->services--;
}
POWER(spirit_flamethrower)
{
struct char_data *tch = get_char_room_vis(spirit, arg);
if (!tch)
send_to_char("Use flamethrower against which target?\r\n", ch);
else if (tch == ch)
send_to_char("You cannot target yourself with that power.\r\n", ch);
else if (tch == spirit)
send_to_char("The spirit refuses to perform that service.\r\n", ch);
else {
sprintf(buf, "moderate %s", arg);
cast_spell(spirit, SPELL_FLAMETHROWER, 0, GET_LEVEL(spirit), buf);
}
}
POWER(spirit_guard)
{
if (!MOB_FLAGGED(spirit, MOB_SPIRITGUARD))
act("$n begins to guard the area from accidents.", FALSE, spirit, 0, ch, TO_VICT);
else
act("$n stops guarding the area from accidents.", FALSE, spirit, 0, ch, TO_VICT);
MOB_FLAGS(spirit).ToggleBit(MOB_SPIRITGUARD);
spiritdata->services--;
}
POWER(spirit_leave)
{
act("$n vanishes back into the metaplanes.", TRUE, spirit, 0, ch, TO_NOTVICT);
send_to_char(ch, "%s returns to the metaplanes to await further orders.\r\n", CAP(GET_NAME(spirit)));
spiritdata->called = FALSE;
extract_char(spirit);
}
POWER(spirit_dematerialize)
{
act("$n fades from the physical realm.\r\n", TRUE, spirit, 0, ch, TO_ROOM);
MOB_FLAGS(spirit).RemoveBits(MOB_DUAL_NATURE, MOB_FLAMEAURA, ENDBIT);
MOB_FLAGS(spirit).SetBit(MOB_ASTRAL);
spiritdata->services--;
}
POWER(spirit_materialize)
{
if (IS_DUAL(spirit)) {
send_to_char(ch, "%s is already materialized.\r\n", CAP(GET_NAME(spirit)));
return;
}
MOB_FLAGS(spirit).SetBit(MOB_DUAL_NATURE);
MOB_FLAGS(spirit).RemoveBit(MOB_ASTRAL);
spiritdata->services--;
act("$n takes on a physical form.\r\n", TRUE, spirit, 0, ch, TO_ROOM);
}
POWER(spirit_movement)
{
int increase = 0;
if (affected_by_power(spirit, MOVEMENTUP)) {
act("$N stops providing that services.", FALSE, ch, 0, spirit, TO_CHAR);
stop_spirit_power(spirit, MOVEMENTUP);
return;
}
if (affected_by_power(spirit, MOVEMENTDOWN)) {
act("$N stops providing that services.", FALSE, ch, 0, spirit, TO_CHAR);
stop_spirit_power(spirit, MOVEMENTDOWN);
return;
}
two_arguments(arg, buf, buf1);
if (!(*buf1 || *buf)) {
send_to_char("Do you want to increase or decrease the movement of the target?\r\n", ch);
return;
}
if (is_abbrev(buf1, "increase"))
increase = 1;
else if (is_abbrev(buf1, "decrease"))
increase = -1;
if (!increase) {
send_to_char("You must specify increase or decrease.\r\n", ch);
return;
}
struct char_data *tch = get_char_room_vis(spirit, buf);
if (!tch)
send_to_char("Use movement against which target?\r\n", ch);
else if (tch == spirit || affected_by_power(tch, increase > 0 ? MOVEMENTUP : MOVEMENTDOWN))
send_to_char("The spirit refuses to perform that service.\r\n", ch);
else {
act("$n performs that service for you.", FALSE, spirit, 0, ch, TO_VICT);
if (increase > 0)
send_to_char("You feel something pushing you forward faster.\r\n", tch);
else
send_to_char("You face heavy resistance as you try and move forward.\r\n", ch);
make_spirit_power(spirit, tch, increase > 0 ? MOVEMENTUP : MOVEMENTDOWN);
spiritdata->services--;
}
}
POWER(spirit_breath)
{
struct char_data *tch = get_char_room_vis(spirit, arg);
if (!tch)
send_to_char("Use noxious breath against which target?\r\n", ch);
else if (tch == ch)
send_to_char("You cannot target yourself with that power.\r\n", ch);
else if (tch == spirit)
send_to_char("The spirit refuses to perform that service.\r\n", ch);
else {
act("$n turns towards $N as a cloud of noxious fumes forms around $S.", TRUE, spirit, 0, tch, TO_NOTVICT);
act("$n lets forth a stream of noxious fumes in your direction.", FALSE, spirit, 0, tch, TO_VICT);
int dam = convert_damage(stage(-success_test(MAX(GET_WIL(tch), GET_BOD(tch)), GET_SPARE2(spirit)), SERIOUS));
if (dam > 0) {
act("$n chokes and coughs.", TRUE, tch, 0, 0, TO_ROOM);
send_to_char("The noxious fumes fill your throat and lungs, causing your vision to swim.\r\n", tch);
damage(spirit, tch, dam, TYPE_FUMES, MENTAL);
} else {
act("$n waves $s hand infront of $s face, dispersing the fumes.", TRUE, tch, 0, 0, TO_ROOM);
send_to_char("You easily resist the noxious fumes.\r\n", tch);
}
spiritdata->services--;
}
}
POWER(spirit_attack)
{
struct char_data *tch = get_char_room_vis(spirit, arg);
if (!tch)
send_to_char("Use attack which target?\r\n", ch);
else if (tch == ch)
send_to_char("Ordering your own spirit to attack you is not a good idea.\r\n", ch);
else if (tch == spirit)
send_to_char("The spirit refuses to perform that service.\r\n", ch);
else {
check_killer(ch, tch);
set_fighting(spirit, tch);
spiritdata->services--;
}
}
POWER(spirit_psychokinesis)
{}
POWER(spirit_search)
{}
struct order_data services[] =
{
{"Appear", spirit_appear, 0
},
{"Sorcery", spirit_sorcery, 0},
{"Study", spirit_study, 0},
{"Sustain", spirit_sustain, 0},
{"Accident", spirit_accident, 1},
{"Binding", spirit_binding, 1},
{"Concealment", spirit_conceal, 1},
{"Confusion", spirit_confusion, 0},
{"Dematerialize", spirit_dematerialize, 1},
{"Engulf", spirit_engulf, 1},
{"Fear", spirit_fear, 0},
{"Flame Aura", spirit_flameaura, 1},
{"Flamethrower", spirit_flamethrower, 1},
{"Guard", spirit_guard, 1},
{"Leave", spirit_leave, 0},
{"Materialize", spirit_materialize, 0},
{"Movement", spirit_movement, 1},
{"Breath", spirit_breath, 1},
{"Psychokinesis", spirit_psychokinesis, 1},
{"Search", spirit_search, 1},
{"Attack", spirit_attack, 1}
};
ACMD(do_order)
{
if (GET_ASPECT(ch) == ASPECT_SORCERER || GET_TRADITION(ch) == TRAD_ADEPT || GET_TRADITION(ch) == TRAD_MUNDANE || !GET_SKILL(ch, SKILL_CONJURING)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
half_chop(argument, buf, buf1);
struct spirit_data *spirit;
int i, order = 0;
if (!(i = atoi(buf)) || i > GET_NUM_SPIRITS(ch)) {
send_to_char("Which spirit do you wish to give an order to?\r\n", ch);
return;
}
for (spirit = GET_SPIRIT(ch); spirit; spirit = spirit->next)
if (--i == 0)
break;
if (!*buf1) {
send_to_char("Available Services: \r\n", ch);
if (GET_TRADITION(ch) == TRAD_HERMETIC) {
if (!spirit->called)
send_to_char(" ^WAppear^n\r\n", ch);
else {
send_to_char(" Aid ^WSorcery^n\r\n"
" Aid ^WStudy^n\r\n"
" ^WSustain^n Spell\r\n"
" ^WMaterialize^n\r\n"
" ^WDematerialize^n\r\n"
" ^WLeave^n\r\n"
" ^WEngulf^n\r\n", ch);
switch(spirit->type) {
case ELEM_FIRE:
send_to_char(" ^WFlame Aura^n\r\n"
" ^WFlamethrower^n\r\n", ch);
break;
case ELEM_WATER:
case ELEM_EARTH:
send_to_char(" ^WMovement^n\r\n", ch);
break;
case ELEM_AIR:
send_to_char(" ^WMovement^n\r\n"
" Noxious ^WBreath^n\r\n"
" ^WPsychokinesis^n\r\n", ch);
break;
}
}
} else {
send_to_char(" ^WMaterialize^n\r\n"
" ^WDematerialize^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_ACCIDENT, TRAD_SHAMANIC))
send_to_char(" ^WAccident^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_BINDING, TRAD_SHAMANIC))
send_to_char(" ^WBinding^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_CONCEAL, TRAD_SHAMANIC))
send_to_char(" ^WConcealment^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_CONFUSION, TRAD_SHAMANIC))
send_to_char(" ^WConfusion^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_ENGULF, TRAD_SHAMANIC))
send_to_char(" ^WEngulf^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_FEAR, TRAD_SHAMANIC))
send_to_char(" ^WFear^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_GUARD, TRAD_SHAMANIC))
send_to_char(" ^WGuard^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_MOVEMENT, TRAD_SHAMANIC))
send_to_char(" ^WMovement^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_BREATH, TRAD_SHAMANIC))
send_to_char(" Noxious ^WBreath^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_PSYCHOKINESIS, TRAD_SHAMANIC))
send_to_char(" ^WPsychokinesis^n\r\n", ch);
if (spirit_can_perform(spirit->type, SERV_SEARCH, TRAD_SHAMANIC))
send_to_char(" ^WSearch^n\r\n", ch);
}
send_to_char(" Attack\r\n", ch);
} else {
half_chop(buf1, buf, buf2);
for (;order < NUM_SERVICES; order++)
if (is_abbrev(buf, services[order].name) && spirit_can_perform(spirit->type, order, GET_TRADITION(ch)))
break;
if (order == NUM_SERVICES) {
send_to_char("Which service do you wish to order the elemental to perform?\r\n", ch);
return;
}
if (GET_TRADITION(ch) == TRAD_HERMETIC) {
if (order == SERV_APPEAR && spirit->called) {
send_to_char("That elemental is already here!\r\n", ch);
return;
} else if (!spirit->called && order != SERV_APPEAR) {
send_to_char("That elemental is waiting on the metaplanes.\r\n", ch);
return;
}
}
struct char_data *mob = find_spirit_by_id(spirit->id, GET_IDNUM(ch));
if (services[order].type == 1 && MOB_FLAGGED(mob, MOB_ASTRAL)) {
send_to_char("That elemental must materialize before it can use that power.\r\n", ch);
return;
}
if (spirit->services < 1 && order != SERV_LEAVE) {
send_to_char("The spirit no longer listens to you.\r\n", ch);
return;
}
((*services[order].func) (ch, mob, spirit, buf2));
if (order != SERV_LEAVE)
elemental_fulfilled_services(ch, mob, spirit);
}
}
ACMD(do_domain)
{
if (GET_TRADITION(ch) != TRAD_SHAMANIC) {
send_to_char("You have no sense of domain.\r\n", ch);
return;
}
if (!*argument) {
send_to_char(ch, "You are currently in the %s domain.\r\n", spirits[GET_DOMAIN(ch)].name);
if (SECT(ch->in_room) != SPIRIT_FOREST && SECT(ch->in_room) != SPIRIT_HEARTH && !ROOM_FLAGGED(ch->in_room, ROOM_INDOORS)) {
send_to_char(ch, "You can switch to the following domains:\r\n %s\r\n Sky Spirit\r\n", spirits[SECT(ch->in_room)].name);
}
} else {
struct spirit_data *next;
skip_spaces(&argument);
int newdomain = -1;
if (SECT(ch->in_room) != SPIRIT_FOREST && SECT(ch->in_room) != SPIRIT_HEARTH && !ROOM_FLAGGED(ch->in_room, ROOM_INDOORS)) {
if (is_abbrev(argument, spirits[SECT(ch->in_room)].name))
newdomain = SECT(ch->in_room);
else if (is_abbrev(argument, "sky spirit"))
newdomain = SPIRIT_SKY;
}
if (newdomain == GET_DOMAIN(ch))
send_to_char("You are already focusing on that domain.\r\n", ch);
else if (newdomain == -1)
send_to_char("Which domain do you wish to focus on?\r\n", ch);
else {
GET_DOMAIN(ch) = newdomain;
send_to_char(ch, "You switch your focus to the %s domain.\r\n", GET_DOMAIN(ch) == SPIRIT_SKY ? "Sky spirit" : spirits[GET_DOMAIN(ch)].name);
for (struct spirit_data *spirit = GET_SPIRIT(ch); spirit; spirit = next) {
next = spirit->next;
if (GET_DOMAIN(ch) != spirit->type) {
struct spirit_data *temp;
struct char_data *tch = find_spirit_by_id(spirit->id, GET_IDNUM(ch));
if (tch) {
send_to_char(ch, "You release %s from the rest of its services.\r\n", GET_NAME(tch));
act("$n returns to the metaplanes.", TRUE, tch, 0, ch, TO_NOTVICT);
extract_char(tch);
}
REMOVE_FROM_LIST(spirit, GET_SPIRIT(ch), next);
GET_NUM_SPIRITS(ch)--;
delete [] spirit;
}
}
}
}
}
ACMD(do_drain)
{
if (!GET_MAGIC(ch)) {
send_to_char("You don't have any spell pool dice to allocate.\r\n", ch);
return;
}
skip_spaces(&argument);
int i = atoi(argument), total = GET_CASTING(ch);
switch (subcmd) {
case SCMD_DRAIN:
total += GET_DRAIN(ch);
break;
case SCMD_SDEFENSE:
total += GET_SDEFENSE(ch);
break;
case SCMD_REFLECT:
total += GET_REFLECT(ch);
break;
}
if (i > total) {
send_to_char("You don't have that many dice to allocate.\r\n", ch);
return;
}
switch (subcmd) {
case SCMD_SDEFENSE:
GET_SDEFENSE(ch) = ch->real_abils.spell_defense_pool = i;
send_to_char(ch, "You allocate %d dice to your spell defense pool.\r\n", GET_SDEFENSE(ch));
break;
case SCMD_REFLECT:
GET_REFLECT(ch) = ch->real_abils.reflection_pool = i;
send_to_char(ch, "You allocate %d dice to your reflecting pool.\r\n", GET_REFLECT(ch));
break;
case SCMD_DRAIN:
GET_DRAIN(ch) = ch->real_abils.drain_pool = i;
send_to_char(ch, "You allocate %d dice to your drain pool.\r\n", GET_DRAIN(ch));
break;
}
GET_CASTING(ch) = ch->real_abils.casting_pool = GET_MAGIC(ch) - GET_DRAIN(ch) - GET_REFLECT(ch) - GET_SDEFENSE(ch);
affect_total(ch);
}
void sedit_parse(struct descriptor_data *d, char *arg)
{}
ACMD(do_deactivate)
{
skip_spaces(&argument);
struct obj_data *obj;
int i;
if (is_abbrev(argument, "pain editor")) {
for (obj = ch->bioware; obj; obj = obj->next_content)
if (GET_OBJ_VAL(obj, 0) == BIO_PAINEDITOR) {
if (!GET_OBJ_VAL(obj, 3))
send_to_char("Your Pain Editor isn't activated.\r\n", ch);
else {
GET_OBJ_VAL(obj, 3) = 0;
send_to_char("Your body starts to tingle as your perception of touch returns.\r\n", ch);
update_pos(ch);
}
return;
}
}
if (GET_TRADITION(ch) == TRAD_ADEPT) {
char name[120], tokens[MAX_STRING_LENGTH], *s;
extern int ability_cost(int abil, int level);
strcpy(tokens, argument);
if (strtok(tokens, "\"") && (s = strtok(NULL, "\""))) {
strcpy(name, s);
if ((s = strtok(NULL, "\0"))) {
skip_spaces(&s);
strcpy(buf1, s);
} else
*buf1 = '\0';
one_argument(argument, buf);
} else strcpy(name, argument);
for (i = 0; i < ADEPT_NUMPOWER; i++)
if (GET_POWER_TOTAL(ch, i) && is_abbrev(name, adept_powers[i]))
break;
if (i < ADEPT_NUMPOWER) {
if (!GET_POWER_ACT(ch, i))
send_to_char("You don't have that power activated.\r\n", ch);
else {
int total = 0;
for (int q = GET_POWER_ACT(ch, i);q > 0; q--)
total += ability_cost(i, q);
GET_POWER_ACT(ch, i) = 0;
GET_POWER_POINTS(ch) -= total;
send_to_char(ch, "You completely deactivate your %s power.\r\n", adept_powers[i]);
if (i == ADEPT_PERCEPTION) {
PLR_FLAGS(ch).RemoveBit(PLR_PERCEIVE);
send_to_char("You return to your physical senses.\r\n", ch);
}
}
return;
}
}
if (!GET_FOCI(ch)) {
send_to_char("You have no foci activated!\r\n", ch);
return;
}
if (!(obj = get_object_in_equip_vis(ch, argument, ch->equipment, &i)) &&
!(obj = get_obj_in_list_vis(ch, argument, ch->carrying))) {
send_to_char("Deactive which focus?\r\n", ch);
return;
}
if (GET_OBJ_TYPE(obj) != ITEM_FOCUS)
send_to_char("That isn't a focus.\r\n", ch);
else if (GET_OBJ_VAL(obj, 4) < 1)
send_to_char("That focus isn't activated.\r\n", ch);
else {
GET_OBJ_VAL(obj, 4) = 0;
GET_FOCI(ch)--;
affect_total(ch);
send_to_char(ch, "You deactivate %s.\r\n", GET_OBJ_NAME(obj));
}
}
ACMD(do_destroy)
{
if (!*argument) {
send_to_char("Destroy which magic construct?\r\n", ch);
return;
}
skip_spaces(&argument);
struct obj_data *obj;
if (!(obj = get_obj_in_list_vis(ch, argument, world[ch->in_room].contents))) {
send_to_char("That object isn't here.\r\n", ch);
return;
}
if (GET_OBJ_TYPE(obj) == ITEM_MAGIC_TOOL && (GET_OBJ_VAL(obj, 0) == TYPE_LODGE || GET_OBJ_VAL(obj, 0) == TYPE_CIRCLE)) {
if (GET_OBJ_VAL(obj, 0) == TYPE_LODGE) {
send_to_char(ch, "You kick at the supports and smash the talismans.\r\n");
act("$n roughly pulls down $o.", TRUE, ch, obj, 0, TO_ROOM);
} else {
send_to_char(ch, "You rub your feet along the lines making up the hermetic circle, erasing them.\r\n");
act("$n uses $s feet to rub out $o.", TRUE, ch, obj, 0, TO_ROOM);
}
extract_obj(obj);
} else
send_to_char("You can't destroy that object.\r\n", ch);
}
ACMD(do_track)
{
if (!IS_PROJECT(ch)) {
send_to_char("You have to be projecting to astrally track.\r\n", ch);
return;
}
if (AFF_FLAGGED(ch->desc->original, AFF_TRACKING)) {
AFF_FLAGS(ch->desc->original).RemoveBit(AFF_TRACKING);
send_to_char("You stop searching the astral plane.\r\n", ch);
return;
}
int success;
skip_spaces(&argument);
if (!*argument) {
if (HUNTING(ch->desc->original)) {
success = success_test(MAX(GET_INT(ch), GET_MAG(ch)/100), HOURS_SINCE_TRACK(ch->desc->original));
if (success > 0) {
AFF_FLAGS(ch->desc->original).SetBit(AFF_TRACKING);
send_to_char("You pick up the trail and continue tracking the astral signature.\r\n", ch);
} else {
HUNTING(ch->desc->original) = NULL;
send_to_char("You seem to have lost the trail.\r\n", ch);
}
} else
send_to_char("What do you wish to track the owner of?\r\n", ch);
return;
}
struct char_data *vict;
struct obj_data *obj;
two_arguments(argument, buf, buf1);
if (!generic_find(buf, FIND_OBJ_INV | FIND_OBJ_ROOM | FIND_OBJ_EQUIP |
FIND_CHAR_ROOM, ch, &vict, &obj)) {
send_to_char(NOOBJECT, ch);
return;
}
if (vict) {
if (*buf1) {
obj = NULL;
two_arguments(buf1, buf2, argument);
int i = 0;
if (!str_cmp(buf1, "spell")) {
int spell = 0;
if (*buf2)
spell = atoi(buf2);
for (struct sustain_data *sust = GET_SUSTAINED(vict); sust; sust = sust->next)
if (!sust->caster && !spell--) {
vict = sust->other;
break;
}
} else if (!(obj = get_object_in_equip_vis(vict, buf1, vict->equipment, &i))) {
send_to_char("They aren't wearing that.\r\n", ch);
return;
}
} else if (IS_NPC(vict) && (GET_RACE(vict) == RACE_SPIRIT || GET_RACE(vict) == RACE_ELEMENTAL) && GET_ACTIVE(vict)) {
for (struct descriptor_data *desc = descriptor_list; desc; desc = desc->next)
if (desc->original && GET_IDNUM(desc->original) == GET_ACTIVE(vict)) {
vict = desc->original;
break;
} else if (desc->character && GET_IDNUM(desc->character) == GET_ACTIVE(vict)) {
vict = desc->character;
break;
}
} else {
send_to_char("They are right here!\r\n", ch);
return;
}
}
if (obj) {
vict = NULL;
if (GET_OBJ_TYPE(obj) != ITEM_FOCUS && !(GET_OBJ_TYPE(obj) == ITEM_MAGIC_TOOL && (GET_OBJ_VAL(obj, 0) == TYPE_CIRCLE || GET_OBJ_VAL(obj, 0) == TYPE_LODGE))) {
send_to_char("There is no astral signature present on that item.\r\n", ch);
return;
}
int num = 3;
if (GET_OBJ_TYPE(obj) == ITEM_FOCUS)
num = 2;
if (!GET_OBJ_VAL(obj, num)) {
send_to_char("There is no astral signature present on that item.\r\n", ch);
return;
}
for (struct descriptor_data *desc = descriptor_list; desc; desc = desc->next)
if (desc->original && GET_IDNUM(desc->original) == GET_OBJ_VAL(obj, num)) {
vict = desc->original;
break;
} else if (desc->character && GET_IDNUM(desc->character) == GET_OBJ_VAL(obj, num)) {
vict = desc->character;
break;
}
}
success = success_test(GET_INT(ch), 4);
if (vict && success > 0) {
if (vict->in_room == ch->in_room) {
send_to_char("They're right here!\r\n", ch);
return;
}
HUNTING(ch->desc->original) = vict;
AFF_FLAGS(ch->desc->original).SetBit(AFF_TRACKING);
HOURS_SINCE_TRACK(ch->desc->original) = 0;
HOURS_LEFT_TRACK(ch->desc->original) = MAX(1, 4 / success);
AFF_FLAGS(vict).SetBit(AFF_TRACKED);
send_to_char("You begin to trace that astral signature back to its owner.\r\n", ch);
} else {
send_to_char("You can't seem to track them down.\r\n", ch);
return;
}
}
ACMD(do_manifest)
{
if (!IS_PROJECT(ch)) {
send_to_char("You can't manifest when you're not astrally projecting.\r\n", ch);
return;
}
AFF_FLAGS(ch).ToggleBit(AFF_MANIFEST);
if (AFF_FLAGGED(ch, AFF_MANIFEST)) {
act("$n fades slowly into view.", TRUE, ch, 0, 0, TO_ROOM);
send_to_char("You manifest your presence on the physical plane.\r\n", ch);
} else {
act("$n fades from the physical plane.", FALSE, ch, 0, 0, TO_ROOM);
send_to_char("You vanish back into the astral plane.\r\n", ch);
}
}
ACMD(do_dispell)
{
if (GET_ASPECT(ch) == ASPECT_CONJURER || GET_TRADITION(ch) == TRAD_ADEPT || GET_TRADITION(ch) == TRAD_MUNDANE || !GET_SKILL(ch, SKILL_SORCERY)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
if (!*argument) {
send_to_char("What spell do you wish to dispell?\r\n", ch);
return;
}
skip_spaces(&argument);
struct char_data *vict;
two_arguments(argument, buf, buf2);
if (!(vict = get_char_room_vis(ch, buf))) {
send_to_char(NOPERSON, ch);
return;
}
int x = atoi(buf2);
if (x <= 0) {
send_to_char("Dispell which spell?\r\n", ch);
return;
}
struct sustain_data *sust = GET_SUSTAINED(vict);
for (;sust; sust = sust->next)
if (!sust->caster && !--x)
break;
if (!sust) {
send_to_char("They don't have that many spells cast on them.\r\n", ch);
return;
}
int success = success_test(GET_SKILL(ch, SKILL_SORCERY) + MIN(GET_SKILL(ch, SKILL_SORCERY), GET_CASTING(ch)), sust->force);
int type = sust->spell, force = sust->force;
if (success > 0) {
spell_modify(vict, sust, FALSE);
sust->success -= success;
if (sust->success < 1) {
send_to_char("You succeed in completly dispelling that spell.\r\n", ch);
sust->success += success;
spell_modify(vict, sust, TRUE);
end_sustained_spell(vict, sust);
} else {
spell_modify(vict, sust, TRUE);
send_to_char("You succeed in weakening that spell.\r\n", ch);
}
} else
send_to_char("You fail to weaken that spell.\r\n", ch);
spell_drain(ch, type, force, 0);
}
ACMD(do_heal)
{
if (GET_TRADITION(ch) != TRAD_ADEPT || !GET_POWER(ch, ADEPT_EMPATHICHEAL)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
struct char_data *vict;
skip_spaces(&argument);
if (!*argument) {
send_to_char("Who do you wish to heal?\r\n", ch);
return;
}
two_arguments(argument, arg, buf);
if (!*buf)
send_to_char("What damage level do you wish to heal them at?\r\n", ch);
else if (GET_POS(ch) == POS_FIGHTING)
send_to_char(TOOBUSY, ch);
else if (!(vict = get_char_room_vis(ch, arg)))
send_to_char(NOPERSON, ch);
else if (GET_PHYSICAL(ch) <= 100)
send_to_char("Succeeding in that task would surely kill you.\r\n", ch);
else if (GET_PHYSICAL(vict) == GET_MAX_PHYSICAL(vict))
send_to_char("They don't need your help.\r\n", ch);
else if (GET_POS(vict) > POS_LYING)
send_to_char("They have to be lying down to receive your help.\r\n", ch);
else {
int basedamage = 0;
for (; *wound_name[basedamage] != '\n'; basedamage++)
if (is_abbrev(buf, wound_name[basedamage]))
break;
if (basedamage > 4 || basedamage == 0) {
send_to_char("That is not a valid damage level, please choose between Light, Moderate, Serious and Deadly.\r\n", ch);
return;
}
int success = success_test(GET_MAG(ch) / 100, 10 - (GET_ESS(vict) / 100));
if (success < 1) {
send_to_char("You fail to channel your energy into that pursuit.\r\n", ch);
return;
}
success = MIN(damage_array[basedamage], MIN((GET_PHYSICAL(ch) / 100) - 1, success)) * 100;
success = MIN(GET_MAX_PHYSICAL(vict) - GET_PHYSICAL(vict), success);
GET_PHYSICAL(vict) += success;
GET_PHYSICAL(ch) -= success;
WAIT_STATE(ch, 3 RL_SEC);
act("You feel $n place $s hands on you, $s minstrations seem to cause your wounds to fade!", TRUE, ch, 0, vict, TO_VICT);
act("You place your hands on $N, you feel $S pain and suffering transfered to your body!", TRUE, ch, 0, vict, TO_CHAR);
act("$n places $s hands on $N seemingly transfering the wound to $mself!", TRUE, ch, 0, vict, TO_NOTVICT);
}
}
ACMD(do_relieve)
{
if (GET_TRADITION(ch) != TRAD_ADEPT || !GET_POWER(ch, ADEPT_PAINRELIEF)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
struct char_data *vict;
skip_spaces(&argument);
if (!*argument) {
send_to_char("Who do you wish to heal?\r\n", ch);
return;
}
if (GET_POS(ch) == POS_FIGHTING)
send_to_char(TOOBUSY, ch);
else if (!(vict = get_char_room_vis(ch, argument)))
send_to_char(NOPERSON, ch);
else if (GET_MENTAL(vict) == GET_MAX_MENTAL(vict))
send_to_char("They don't need your help.\r\n", ch);
else if (GET_POS(vict) > POS_LYING)
send_to_char("They have to be lying down to receive your help.\r\n", ch);
else {
int success = success_test(GET_MAG(ch) / 100, 10 - (GET_ESS(vict) / 100));
if (success < 1) {
send_to_char("You fail to channel your energy into that pursuit.\r\n", ch);
return;
}
if (GET_MENTAL(vict) <= 0)
GET_MENTAL(vict) = (int)(GET_MAX_MENTAL(vict) * 0.4);
else if (GET_MENTAL(vict) <= GET_MAX_MENTAL(vict) * 0.4)
GET_MENTAL(vict) = (int)(GET_MAX_MENTAL(vict) * 0.7);
else if (GET_MENTAL(vict) <= GET_MAX_MENTAL(vict) * 0.7)
GET_MENTAL(vict) = (int)(GET_MAX_MENTAL(vict) * 0.9);
else
GET_MENTAL(vict) = GET_MAX_MENTAL(vict);
act("You feel $n place $s hands on you, a tingling feeling feels your body as your pain begins to subside", TRUE, ch, 0, vict, TO_VICT);
act("You hands warm slightly at the energy being channeled through them into $N's chakra points.", TRUE, ch, 0, vict, TO_CHAR);
act("$n places $s hands on $N. $N appears to feel better.", TRUE, ch, 0, vict, TO_NOTVICT);
WAIT_STATE(ch, 5 RL_SEC);
}
}
ACMD(do_nervestrike)
{
if (GET_TRADITION(ch) != TRAD_ADEPT || !GET_POWER(ch, ADEPT_NERVE_STRIKE)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
if (IS_NERVE(ch)) {
IS_NERVE(ch) = FALSE;
send_to_char("You will no longer use nerve strike.\r\n", ch);
} else {
IS_NERVE(ch) = TRUE;
send_to_char("You will now use nerve strike.\r\n", ch);
}
}
#define CH d->character
void disp_init_menu(struct descriptor_data *d)
{
CLS(CH);
send_to_char("1) Increase magic and learn metamagic technique\r\n"
"2) Increase magic and change astral signature\r\n"
"3) Shed a gaes\r\n"
"4) Return to game\r\n"
"Enter initiation option: ", CH);
d->edit_mode = INIT_MAIN;
}
bool can_metamagic(struct char_data *ch, int i)
{
if (GET_TRADITION(ch) == TRAD_ADEPT) {
if (i != META_CENTERING && i != META_MASKING)
return FALSE;
if (i == META_CENTERING && GET_METAMAGIC(ch, i) == 2)
return TRUE;
}
if (GET_METAMAGIC(ch, i))
return FALSE;
if (GET_ASPECT(ch) == ASPECT_CONJURER && (i == META_QUICKENING || i == META_REFLECTING || i == META_ANCHORING || i == META_SHIELDING))
return FALSE;
if (GET_ASPECT(ch) == ASPECT_SORCERER && i == META_INVOKING)
return FALSE;
return TRUE;
}
void disp_gaes_menu(struct descriptor_data *d)
{
CLS(CH);
int x = 0;
for (int i = 0; i < NUM_WEARS; i++)
if (GET_EQ(CH, i) && GET_OBJ_TYPE(GET_EQ(CH, i)) == ITEM_FOCUS && GET_OBJ_VAL(GET_EQ(CH, i), 9) == GET_IDNUM(CH))
send_to_char(CH, "%d) %s\r\n", x++, GET_OBJ_NAME(GET_EQ(CH, i)));
send_to_char("q) Quit Initiation\r\nSelect gaes to shed: ", CH);
d->edit_mode = INIT_GAES;
}
void disp_meta_menu(struct descriptor_data *d)
{
CLS(CH);
for (int i = 0; i < META_MAX; i++)
send_to_char(CH, "%d) %s%s^n\r\n", i + 1, can_metamagic(CH, i) ? "" : "^r", metamagic[i]);
send_to_char("q) Quit Initiation\r\nSelect ability to learn: ", CH);
d->edit_mode = INIT_META;
}
bool init_cost(struct char_data *ch, bool spend)
{
int karmacost = (GET_GRADE(ch) + 6) * 300, nuyencost = MIN(825000, (25000 + (25000 * 1<<GET_GRADE(ch)))), tke = 0;
if (karmacost > GET_KARMA(ch)) {
send_to_char("You do not have enough karma to initiate\n\r", ch);
return FALSE;
}
if (nuyencost > GET_NUYEN(ch)) {
send_to_char("You do not have enough nuyen to initiate.\r\n", ch);
return FALSE;
}
switch (GET_GRADE(ch)+1) {
case 1:
tke = 0;
break;
case 2:
tke = 100;
break;
case 3:
tke = 200;
break;
default:
tke = 200 + ((GET_GRADE(ch)-2)*200);
break;
}
if (tke > GET_TKE(ch)) {
send_to_char("You do not have high enough TKE to initiate.\r\n", ch);
return FALSE;
}
if (spend) {
GET_NUYEN(ch) -= nuyencost;
GET_KARMA(ch) -= karmacost;
}
return TRUE;
}
ACMD(do_initiate)
{
if (GET_TRADITION(ch) == TRAD_MUNDANE)
nonsensical_reply(ch);
if (subcmd == SCMD_INITIATE && init_cost(ch, FALSE)) {
STATE(ch->desc) = CON_INITIATE;
PLR_FLAGS(ch).SetBit(PLR_INITIATE);
disp_init_menu(ch->desc);
} else if (subcmd == SCMD_POWERPOINT) {
if (GET_TRADITION(ch) != TRAD_ADEPT)
nonsensical_reply(ch);
else if (GET_KARMA(ch) < 2000 || ch->points.extrapp > (int)(GET_REP(ch) / 50))
send_to_char("You do not have enough karma to purchase a powerpoint.\r\n", ch);
else {
GET_KARMA(ch) -= 2000;
GET_PP(ch) += 100;
ch->points.extrapp++;
send_to_char(ch, "You have purchased an additional powerpoint.\r\n");
}
}
}
void init_parse(struct descriptor_data *d, char *arg)
{
struct obj_data *obj = NULL;
int number, i;
switch (d->edit_mode)
{
case INIT_MAIN:
switch (*arg)
{
case '1':
disp_meta_menu(d);
break;
case '2':
STATE(d) = CON_PLAYING;
init_cost(CH, TRUE);
GET_SIG(CH)++;
GET_GRADE(CH)++;
GET_REAL_MAG(CH) += 100;
if (GET_TRADITION(CH) == TRAD_ADEPT)
GET_PP(CH) += 100;
send_to_char("You feel yourself astral reflection shift and mold itself closer to the astral plane.\r\n", CH);
STATE(d) = CON_PLAYING;
PLR_FLAGS(CH).RemoveBit(PLR_INITIATE);
break;
case '3':
disp_gaes_menu(d);
break;
case '4':
STATE(d) = CON_PLAYING;
PLR_FLAGS(CH).RemoveBit(PLR_INITIATE);
send_to_char("Initiation cancelled.\r\n", CH);
break;
default:
disp_init_menu(d);
break;
}
break;
case INIT_GAES:
number = atoi(arg);
if (*arg == 'q') {
STATE(d) = CON_PLAYING;
send_to_char("Initiation cancelled.\r\n", CH);
} else if (number < 0) {
send_to_char("Invalid Response. Select gaes to shed: ", CH);
} else {
for (i = 0; i < NUM_WEARS; i++)
if (GET_EQ(CH, i) && GET_OBJ_TYPE(GET_EQ(CH, i)) == ITEM_FOCUS && GET_OBJ_VAL(GET_EQ(CH, i), 9) == GET_IDNUM(CH) && --number < 0) {
obj = GET_EQ(CH, i);
break;
}
if (!obj) {
send_to_char("You don't have that many gaesa. Select gaes to shed: ", CH);
return;
}
init_cost(CH, TRUE);
GET_GRADE(CH)++;
GET_REAL_MAG(CH) += 100;
GET_OBJ_VAL(obj, 9) = 0;
if (GET_TRADITION(CH) == TRAD_ADEPT)
GET_PP(CH) += 100;
send_to_char(CH, "You feel your magic return from that object, once again binding to your spirit.\r\n", CH);
STATE(d) = CON_PLAYING;
PLR_FLAGS(CH).RemoveBit(PLR_INITIATE);
}
break;
case INIT_META:
number = atoi(arg);
if (!number) {
STATE(d) = CON_PLAYING;
send_to_char("Initiation cancelled.\r\n", CH);
} else if (--number > META_MAX) {
send_to_char("Invalid Response. Select ability to learn: ", CH);
} else if (!can_metamagic(CH, number)) {
send_to_char("You can't learn that metamagic technique. Select ability to learn: ", CH);
} else {
init_cost(CH, TRUE);
GET_METAMAGIC(CH, number)++;
GET_GRADE(CH)++;
GET_REAL_MAG(CH) += 100;
if (GET_TRADITION(CH) == TRAD_ADEPT)
GET_PP(CH) += 100;
send_to_char(CH, "You feel yourself grow closer to the astral plane as you become ready to learn %s.\r\n", metamagic[number]);
STATE(d) = CON_PLAYING;
PLR_FLAGS(CH).RemoveBit(PLR_INITIATE);
}
break;
}
}
ACMD(do_masking)
{
if (GET_METAMAGIC(ch, META_MASKING) < 2) {
nonsensical_reply(ch);
return;
}
skip_spaces(&argument);
if (!*argument) {
if (!GET_MASKING(ch))
send_to_char("You aren't masking anything.\r\n", ch);
else {
send_to_char("You are masking: \r\n", ch);
if (IS_SET(GET_MASKING(ch), MASK_COMPLETE))
send_to_char(" Awakened State\r\n", ch);
if (IS_SET(GET_MASKING(ch), MASK_INIT))
send_to_char(" Initiation Grades\r\n", ch);
if (IS_SET(GET_MASKING(ch), MASK_DUAL))
send_to_char(" Perceiving State\r\n", ch);
}
} else if (is_abbrev(argument, "initiation")) {
TOGGLE_BIT(GET_MASKING(ch), MASK_INIT);
send_to_char(ch, "You will %s mask your initiation grades.\r\n", IS_SET(GET_MASKING(ch), MASK_INIT) ? "now" : "no longer");
} else if (is_abbrev(argument, "complete")) {
TOGGLE_BIT(GET_MASKING(ch), MASK_COMPLETE);
send_to_char(ch, "You will %s mask your awakened state.\r\n", IS_SET(GET_MASKING(ch), MASK_COMPLETE) ? "now" : "no longer");
} else if (is_abbrev(argument, "dual")) {
TOGGLE_BIT(GET_MASKING(ch), MASK_DUAL);
send_to_char(ch, "You will %s mask your perceiving state.\r\n", IS_SET(GET_MASKING(ch), MASK_DUAL) ? "now" : "no longer");
} else send_to_char("What do you wish to mask?\r\n", ch);
}
ACMD(do_focus)
{
if (GET_TRADITION(ch) != TRAD_ADEPT || !GET_POWER(ch, ADEPT_LIVINGFOCUS)) {
send_to_char("You don't have the ability to do that.\r\n", ch);
return;
}
skip_spaces(&argument);
if (!*argument) {
if (GET_SUSTAINED_NUM(ch)) {
send_to_char("You are already sustaining a spell.\r\n", ch);
return;
}
struct sustain_data *spell = GET_SUSTAINED(ch);
for (; spell; spell = spell->next)
if (!spell->caster && !spell->spirit && !spell->focus && spells[spell->spell].duration == SUSTAINED)
break;
if (!spell) {
send_to_char("You are not affected by any spells that need sustaining.\r\n", ch);
return;
}
spell->spirit = ch;
GET_SUSTAINED_NUM(ch)++;
GET_SUSTAINED_FOCI(spell->other)++;
for (struct sustain_data *ospell = GET_SUSTAINED(spell->other); ospell; ospell = ospell->next)
if (ospell->idnum == spell->idnum && ospell->other == ch) {
ospell->spirit = ch;
break;
}
strcpy(buf, spells[spell->spell].name);
if (spell->spell == SPELL_INCATTR || spell->spell == SPELL_INCCYATTR ||
spell->spell == SPELL_DECATTR || spell->spell == SPELL_DECCYATTR)
sprintf(ENDOF(buf), " (%s)", attributes[spell->subtype]);
send_to_char(ch, "You begin to concentrate on sustaining %s.\r\n", buf);
send_to_char(spell->other, "You feel a weight lifted from you as someone takes over sustaining your %s spell.\r\n", buf);
} else if (!str_cmp(argument, "release")) {
if (!GET_SUSTAINED_NUM(ch)) {
send_to_char("You aren't sustaining any spells.\r\n", ch);
return;
}
struct sustain_data *spell = GET_SUSTAINED(ch);
for (; spell; spell = spell->next)
if (spell->spirit == ch)
break;
GET_SUSTAINED_NUM(ch)--;
GET_SUSTAINED_FOCI(spell->other)--;
spell->spirit = NULL;
for (struct sustain_data *ospell = GET_SUSTAINED(spell->other); ospell; ospell = ospell->next)
if (ospell->idnum == spell->idnum && ospell->other == ch) {
ospell->spirit = NULL;
break;
}
strcpy(buf, spells[spell->spell].name);
if (spell->spell == SPELL_INCATTR || spell->spell == SPELL_INCCYATTR ||
spell->spell == SPELL_DECATTR || spell->spell == SPELL_DECCYATTR)
sprintf(ENDOF(buf), " (%s)", attributes[spell->subtype]);
send_to_char(ch, "You stop sustaining %s.\r\n", buf);
send_to_char(spell->other, "You suddenly feel the burden of your %s spell fall back on to you.\r\n", buf);
} else send_to_char("You can only release sustained spells.\r\n", ch);
}
ACMD(do_metamagic)
{
if (GET_GRADE(ch) == 0) {
send_to_char("You are not close enough to the astral plane to have any metamagic powers.\r\n", ch);
return;
}
int i = 0;
*buf = '\0';
for (int x = 0; x < META_MAX; x++)
if (GET_METAMAGIC(ch, x)) {
i++;
sprintf(ENDOF(buf), " %s%s^n\r\n", GET_METAMAGIC(ch, x) == 2 ? "" : "^r", metamagic[x]);
}
if (i > 0)
send_to_char(ch, "You know the following metamagic techniques:\r\n%s", buf);
else send_to_char("You don't know any metamagic techniques.\r\n", ch);
}
ACMD(do_cleanse)
{
if (GET_METAMAGIC(ch, META_CLEANSING) < 2) {
nonsensical_reply(ch);
return;
}
if (!(IS_ASTRAL(ch) || IS_DUAL(ch)))
send_to_char("You have no sense of the astral plane.\r\n", ch);
else if (!GET_SKILL(ch, SKILL_SORCERY))
send_to_char("You need practical knowledge of sorcery to cleanse the astral plane.\r\n", ch);
else if (!world[ch->in_room].background[0])
send_to_char("The astral plane in this area is calm.\r\n", ch);
else if (world[ch->in_room].background[0] > GET_GRADE(ch))
send_to_char("Cleansing a disturbance of this magnitude is beyond your abilities.\r\n", ch);
else if (world[ch->in_room].background[1] == AURA_POWERSITE)
send_to_char("You cannot cleanse a power site.\r\n", ch);
else {
int success = success_test(GET_SKILL(ch, SKILL_SORCERY), world[ch->in_room].background[0] * 2), background = world[ch->in_room].background[0];
success /= 2;
if (success <= 0)
send_to_char("You fail to reduce the astral disturbances in this area.\r\n", ch);
else {
world[ch->in_room].background[0] = MAX(0, world[ch->in_room].background[0] - success);
if (!world[ch->in_room].background[0]) {
send_to_char("You successfully remove all astral disturbances from the area.\r\n", ch);
sprintf(buf, "The astral disturbances in this area completely vanish.\r\n");
} else {
send_to_char("You succeed in lowering the astral disturbances in the area.\r\n", ch);
sprintf(buf, "The astral disturbances in the are seem to diminish slightly.\r\n");
}
for (struct char_data *targ = world[ch->in_room].people; targ; targ = targ->next_in_room)
if (ch != targ && (IS_ASTRAL(targ) || IS_DUAL(targ)))
send_to_char(buf, targ);
}
spell_drain(ch, 0, background, DEADLY);
}
}
ACMD(do_think)
{
struct sustain_data *spell = NULL;
for (spell = GET_SUSTAINED(ch); spell; spell = spell->next)
if (spell->spell == SPELL_MINDLINK)
break;
if (!spell || !*argument) {
send_to_char("You think about life, the universe and everything.\r\n", ch);
return;
}
skip_spaces(&argument);
sprintf(buf, "^rYou hear $v in your mind say, \"%s\"", argument);
act(buf, FALSE, ch, 0, ch->char_specials.mindlink, TO_VICT);
send_to_char(ch, "You think, \"%s\"\r\n", argument);
}