AwakeMUD-0.8.18B/
AwakeMUD-0.8.18B/doc/
AwakeMUD-0.8.18B/lib/
AwakeMUD-0.8.18B/lib/etc/
AwakeMUD-0.8.18B/lib/etc/pfiles/
AwakeMUD-0.8.18B/lib/misc/
AwakeMUD-0.8.18B/lib/text/
AwakeMUD-0.8.18B/lib/text/help/
AwakeMUD-0.8.18B/lib/text/wizhelp/
AwakeMUD-0.8.18B/lib/veh/
AwakeMUD-0.8.18B/lib/world/
AwakeMUD-0.8.18B/lib/world/mob/
AwakeMUD-0.8.18B/lib/world/mtx/
AwakeMUD-0.8.18B/lib/world/qst/
AwakeMUD-0.8.18B/lib/world/shp/
AwakeMUD-0.8.18B/lib/world/veh/
#include "structs.h"
#include "awake.h"
#include "db.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "utils.h"
#include "screen.h"
#include "constants.h"
#include "olc.h"
#include "newmagic.h"

#define CH d->character
#define SPELL d->edit_obj
#define SPEDIT_MENU	1
#define SPEDIT_NAME	2
#define SPEDIT_DESC	3
#define SPEDIT_CATEGORY	4
#define SPEDIT_FORCE	5
#define SPEDIT_TYPE	7
#define SPEDIT_ATTR	8

void spedit_disp_menu(struct descriptor_data *d)
{
  CLS(CH);
  send_to_char(CH, "1) Name: ^c%s^n\r\n", SPELL->restring);
  send_to_char(CH, "2) Look Desc:\r\n^c%s^n\r\n", SPELL->photo);
  send_to_char(CH, "3) Category: ^c%s^n\r\n", spell_category[GET_OBJ_VAL(SPELL, 9)]);
  send_to_char(CH, "4) Type: ^c%s^n\r\n", spells[GET_OBJ_VAL(SPELL, 1)]);
  send_to_char(CH, "5) Force: ^c%d^n\r\n", GET_OBJ_VAL(SPELL, 0));
  if (GET_OBJ_VAL(SPELL, 1) == SPELL_INCATTR || GET_OBJ_VAL(SPELL, 1) == SPELL_INCCYATTR ||
      GET_OBJ_VAL(SPELL, 1) == SPELL_DECATTR || GET_OBJ_VAL(SPELL, 1) == SPELL_DECCYATTR)
    send_to_char(CH, "6) Attribute: ^c%s^n\r\n", attributes[GET_OBJ_VAL(SPELL, 3)]);
  send_to_char(CH, "q) Quit\r\nEnter your choice: ");
  d->edit_mode = SPEDIT_MENU;
}

void spedit_disp_spell_type(struct descriptor_data *d)
{
  int x = 1;
  for (int i = 0; i < MAX_SPELLS; i++) 
    if (spells[i].category == GET_OBJ_VAL(SPELL, 9)) {
      send_to_char(CH, "%d) %s\r\n", x, spells[i]);
      x++;
    }
  send_to_char("Enter spell type: ", CH);
  d->edit_mode = SPEDIT_TYPE;
}

void create_spell(struct char_data *ch)
{
  struct obj_data *design = read_object(117, VIRTUAL);
  STATE(ch->desc) = CON_SPELL_CREATE;
  GET_OBJ_TIMER(design) = -2;
  GET_OBJ_VAL(design, 0) = 1;
  GET_OBJ_VAL(design, 2) = GET_TRADITION(ch) == TRAD_SHAMANIC ? 1 : 0;
  GET_OBJ_VAL(design, 8) = GET_IDNUM(ch);
  design->restring = str_dup("A blank spell formula");
  design->photo = str_dup("It looks very blank.");
  ch->desc->edit_obj = design;
  spedit_disp_menu(ch->desc);
}

void spedit_parse(struct descriptor_data *d, char *arg)
{
  int number = atoi(arg), i = 0, x = 1;
  switch(d->edit_mode)
  {
  case SPEDIT_MENU:  
    switch (*arg) { 
    case '1':
      send_to_char("Enter spell name: ", CH);
      d->edit_mode = SPEDIT_NAME;
      break;
    case '2':
      send_to_char(CH, "Enter spell design description:\r\n");
      d->edit_mode = SPEDIT_DESC;
      d->str = new (char *);
      *(d->str) = NULL;
      d->max_str = MAX_MESSAGE_LENGTH;
      d->mail_to = 0;
      break;
    case '3':
      CLS(CH);
      for (i = 1; i < 6; i++)
        send_to_char(CH, "%d) %s\r\n", i, spell_category[i]);
      send_to_char("Enter spell category: ", CH);
      d->edit_mode = SPEDIT_CATEGORY;
      break;
    case '4':
      if (!GET_OBJ_VAL(SPELL, 9))
        send_to_char("You must select a category first. Enter your choice: ", CH);
      else spedit_disp_spell_type(d);
      break;
    case '5':
      send_to_char("Enter spell force: ", CH);
      d->edit_mode = SPEDIT_FORCE;
      break;
    case 'Q':
    case 'q':
      send_to_char(CH, "Design saved!\r\n");
      obj_to_char(d->edit_obj, CH);
      STATE(d) = CON_PLAYING;
      d->edit_obj = NULL;
      break;
    case '6':
      if (GET_OBJ_VAL(SPELL, 1) == SPELL_INCATTR || GET_OBJ_VAL(SPELL, 1) == SPELL_INCCYATTR ||
          GET_OBJ_VAL(SPELL, 1) == SPELL_DECATTR || GET_OBJ_VAL(SPELL, 1) == SPELL_DECCYATTR) {
        CLS(CH);
        for (int i = 0; i < 6; i++)
          send_to_char(CH, "%d) %s\r\n", i, attributes[i]);
        send_to_char("Select attribute: ", CH);
        d->edit_mode = SPEDIT_ATTR;
        break;
       }
    default:
      send_to_char(CH, "Invalid option!\r\n");
      break;
    }
    break;
    case SPEDIT_ATTR:
      if (number > 5) {
        send_to_char("Invalid Attributes. Select attribute: ", CH);
        return;
      }
      GET_OBJ_VAL(SPELL, 3) = number;
      spedit_disp_menu(d);
      break;
    case SPEDIT_NAME:
      if (strlen(arg) >= LINE_LENGTH) {
        spedit_disp_menu(d);
        return;
      }
      if (SPELL->restring)
        delete [] SPELL->restring;
      SPELL->restring = str_dup(arg);
      spedit_disp_menu(d);
      break;
    case SPEDIT_FORCE: 
      x = MIN(d->edit_number2, GET_SKILL(CH, SKILL_SPELLDESIGN) ? GET_SKILL(CH, SKILL_SPELLDESIGN) : GET_SKILL(CH, SKILL_SORCERY));
      if (number > x || number < 1)
        send_to_char(CH, "Force must be between 1 and %d. Enter Force: ", x);
      else {
        GET_OBJ_VAL(SPELL, 0) = number;
        spedit_disp_menu(d);
      }
      break;
    case SPEDIT_CATEGORY: 
      if (number < 1 || number > 5)
        send_to_char("Please select from the list. Enter Category: ", CH);
      else {
        GET_OBJ_VAL(SPELL, 9) = number;
        spedit_disp_menu(d);
      }
      break;
    case SPEDIT_TYPE:
      for (i = 0; i < MAX_SPELLS; i++)
        if (spells[i].category == GET_OBJ_VAL(SPELL, 9) && x++ == number)
          break;
      if (i == MAX_SPELLS)
        send_to_char("Invalid spell type. Enter spell type: ", CH);
      else {
        GET_OBJ_VAL(SPELL, 1) = i;
        spedit_disp_menu(d);
      }
      break;
  }
}

void spell_design(struct char_data *ch, struct obj_data *formula)
{
  if (GET_OBJ_VAL(formula, 8) != GET_IDNUM(ch)) {
    send_to_char("You don't understand where the creator of this spell is coming from.\r\n", ch);
    return;
  }
  if (IS_WORKING(ch)) {
    send_to_char("You are already working on something.\r\n", ch);
    return;
  }
  if (GET_POS(ch) > POS_SITTING) {
    send_to_char("Take a seat before beginning to design a spell.\r\n", ch);
    return;
  }
  struct obj_data *lib = world[ch->in_room].contents;
  for (; lib; lib = lib->next_content)
    if (GET_OBJ_TYPE(lib) == ITEM_MAGIC_TOOL && GET_OBJ_VAL(lib, 1) >= GET_OBJ_VAL(formula, 0) &&
        ((GET_TRADITION(ch) == TRAD_SHAMANIC
          && GET_OBJ_VAL(lib, 0) == TYPE_LODGE && GET_OBJ_VAL(lib, 3) == GET_IDNUM(ch)) ||
         (GET_TRADITION(ch) == TRAD_HERMETIC && GET_OBJ_VAL(lib, 0) == TYPE_LIBRARY_SPELL)))
      break;
  if (!lib) {
    send_to_char("You don't have the right tools here to design that spell.\r\n", ch);
    return;
  }
  if (GET_TRADITION(ch) == TRAD_SHAMANIC && GET_OBJ_VAL(lib, 9)) {
    send_to_char("You need to finish building that lodge before you can use it.\r\n", ch);
    return;
  }
  if (GET_OBJ_VAL(formula, 6))
    send_to_char("You continue to design that spell.\r\n", ch);
  else if (!GET_OBJ_TIMER(formula))
    send_to_char("That spell is already complete.\r\n", ch);
  else {
    int skill = GET_SKILL(ch, SKILL_SPELLDESIGN), target = 0, x = 0;
    if (!skill || skill < GET_OBJ_VAL(formula, 0)) {
      skill = GET_SKILL(ch, SKILL_SORCERY);
      target = 2;
    }
    if (skill < GET_OBJ_VAL(formula, 0)) {
      send_to_char("You don't have the neccesary skills to design this spell.\r\n", ch);
      return;
    }
    int drain = spells[GET_OBJ_VAL(formula, 1)].draindamage;
    if (drain < 1 || drain == DEADLY)
      drain = 60;
    else if (drain == SERIOUS)
      drain = 36;
    else if (drain == MODERATE)
      drain = 18;
    else drain = 6;
    drain *= 1440;
    target += (GET_OBJ_VAL(formula, 0) * 2) - (int)(GET_REAL_MAG(ch) / 100);
    if (spells[GET_OBJ_VAL(formula, 1)].category == DETECTION || spells[GET_OBJ_VAL(formula, 1)].category == ILLUSION)
      target--;
    if (spells[GET_OBJ_VAL(formula, 1)].physical)
      target++;
    if (spells[GET_OBJ_VAL(formula, 1)].duration == SUSTAINED)
      target++;
    if (GET_OBJ_VAL(formula, 1) == SPELL_DETOX || GET_OBJ_VAL(formula, 1) == SPELL_RESISTPAIN)
      target -=2;
    if (GET_OBJ_VAL(formula, 1) == SPELL_CLOUT || GET_OBJ_VAL(formula, 1) == SPELL_STUNBALL ||
        GET_OBJ_VAL(formula, 1) == SPELL_STUNBOLT)
      target--;
    if (GET_TRADITION(ch) == TRAD_SHAMANIC)
      totem_bonus(ch, 0, GET_OBJ_VAL(formula, 1), x, skill);
    else if (GET_TRADITION(ch) == TRAD_HERMETIC && GET_SPIRIT(ch)) {
    int startskill = skill;
    for (struct spirit_data *spir = GET_SPIRIT(ch); spir && skill == startskill; 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(formula, 1)].category == COMBAT) {
              skill += spir->force;
              MOB_FLAGS(spirit).RemoveBit(MOB_STUDY);
            }
            break;
          case ELEM_WATER:
            if (spells[GET_OBJ_VAL(formula, 1)].category == ILLUSION) {
              skill += spir->force;
              MOB_FLAGS(spirit).RemoveBit(MOB_STUDY);
            }
            break;
          case ELEM_AIR:
            if (spells[GET_OBJ_VAL(formula, 1)].category == DETECTION) {
              skill += spir->force;
              MOB_FLAGS(spirit).RemoveBit(MOB_STUDY);
            }
            break;
          case ELEM_EARTH:
            if (spells[GET_OBJ_VAL(formula, 1)].category == MANIPULATION) {
              skill += spir->force;
              MOB_FLAGS(spirit).RemoveBit(MOB_STUDY);
            }
            break;
          }
          elemental_fulfilled_services(ch, spirit, spir);
          break;
        }
      }
    }
    if (GET_OBJ_VAL(lib, 1) > skill)
      skill += (GET_OBJ_VAL(lib, 1) - skill) / 2;
    int success = success_test(skill, target);
    if (success < 1) {
      GET_OBJ_VAL(formula, 6) = drain / 2;
      GET_OBJ_VAL(formula, 7) = drain;
      GET_OBJ_TIMER(formula) = -3;
    } else
      GET_OBJ_VAL(formula, 6) = GET_OBJ_VAL(formula, 7) = drain / success;
    send_to_char(ch, "You start designing %s.\r\n", GET_OBJ_NAME(formula));
  }
  act("$n sits down and begins to design a spell.", TRUE, ch, 0, 0, TO_ROOM);
  GET_BUILDING(ch) = formula;
  AFF_FLAGS(ch).SetBit(AFF_SPELLDESIGN);
}