#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); }