deltamud/deltamud/
deltamud/deltamud/bin/
deltamud/deltamud/cnf/
deltamud/deltamud/lib/
deltamud/deltamud/lib/etc/
deltamud/deltamud/lib/misc/
deltamud/deltamud/lib/plrobjs/
deltamud/deltamud/lib/text/
deltamud/deltamud/lib/text/help/
deltamud/deltamud/lib/world/
deltamud/deltamud/lib/world/trg/
/* ************************************************************************
*   File: act.create.c					Part of CircleMUD *
*  Usage: Player-level object creation stuff				  *
*									  *
*  All rights reserved.	 See license.doc for complete information.	  *
*									  *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.		  *
************************************************************************ */

#include "conf.h"
#include "sysdep.h"

#include <sys/stat.h>

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "spells.h"

/* struct for syls */
struct syllable {
  char *org;
  char *new;
};

/* extern variables */
extern char *spells[];
extern struct spell_info_type spell_info[];
extern struct syllable syls[];

/* extern procedures */
int mag_manacost(struct char_data * ch, int spellnum);


char *get_spell_name(char *argument)
{
  char *s;

  s = strtok(argument, "'");
  s = strtok(NULL, "'");
  
  return s;
}


char *potion_names[] = {
	"milky white",
	"&Wbubbling white&n",
	"&Mglowing ivory&n",
	"&Bglowing blue&n",
	"&ybubbling yellow&n",
	"&Glight green&n",
	"&ygritty brown&n",
	"&Rblood red&n",
	"&Mswirling purple&n",
	"&gflickering green&n",
	"&ccloudy blue&n",
	"&Rglowing red&n",
	"&Wsparkling white&n",
	"&bincandescent blue&n",
	"&wtranslucent grey&n", 
	"&bmidnight blue&n"  
};

void make_potion(struct char_data *ch, int potion, struct obj_data *container)
{
	struct obj_data *final_potion;
	struct extra_descr_data *new_descr;
	int can_make = TRUE, mana, dam, num = 0;
    
	/* Modify this list to suit which spells you
	   want to be able to mix. */
	switch (potion) {
	case SPELL_CURE_BLIND:
	  num = 0;
	  break;

	case SPELL_CURE_LIGHT:
	  num = 1;
	  break;

	case SPELL_CURE_CRITIC:
	  num = 2;
	  break;

	case SPELL_DETECT_MAGIC:
	  num = 3;
	  break;

	case SPELL_DETECT_INVIS:
	  num = 4;
	  break;

	case SPELL_DETECT_POISON:
	  num = 5;
	  break;

	case SPELL_REMOVE_POISON:
	  num = 6;
	  break;

	case SPELL_STRENGTH:
	  num = 7;
	  break;

	case SPELL_WORD_OF_RECALL:
	  num = 8;
	  break;

	case SPELL_SENSE_LIFE:
	  num = 9;
	  break;

	case SPELL_WATERWALK:
	  num = 10;
	  break;

	case SPELL_INFRAVISION:
	  num = 11;
	  break;

	case SPELL_HEAL:
	  num = 12;
	  break;

	case SPELL_SANCTUARY:
	  num = 13;
	  break;

	case SPELL_INVISIBLE:
	  num = 14;
	  break;

	case SPELL_STONE_SKIN:
	  num = 15;
	  break;

	default:
	  can_make = FALSE;
	  break;
	}

	if (can_make == FALSE) {
		send_to_char("That spell cannot be mixed into a"
			     " potion.\r\n", ch);
		return;
	}
	else if ((number(1, 3) == 3) && (GET_LEVEL(ch) < LVL_IMMORT)) {
		send_to_char("As you begin mixing the potion, it violently"
			     " explodes!\r\n",ch);
		act("$n begins to mix a potion, but it suddenly explodes!",
		    FALSE, ch, 0,0, TO_ROOM);
		extract_obj(container);
		dam = number(15, mag_manacost(ch, potion) * 2);
		GET_HIT(ch) -= dam;
		update_pos(ch);
		return;
	}

	/* requires x3 mana to mix a potion than the spell */
	mana = mag_manacost(ch, potion) * 3;
	if (GET_MANA(ch) - mana > 0) {
	    if (GET_LEVEL(ch) < LVL_IMMORT) GET_MANA(ch) -= mana;
		sprintf(buf, "You create a %s potion.\r\n",
		    spells[potion]);
		send_to_char(buf, ch);
		act("$n creates a potion!", FALSE, ch, 0, 0, TO_ROOM);
		extract_obj(container);
	}
	else {
		send_to_char("You don't have enough mana to mix"
			     " that potion!\r\n", ch);
		return;
	}
	
	final_potion = create_obj();

	final_potion->item_number = NOTHING;
	final_potion->in_room = NOWHERE;
	sprintf(buf2, "%s %s potion", potion_names[num], spells[potion]);
	final_potion->name = str_dup(buf2);

	sprintf(buf2, "A %s potion lies here.", potion_names[num]);
	final_potion->description = str_dup(buf2);

	sprintf(buf2, "a %s potion", potion_names[num]);
	final_potion->short_description = str_dup(buf2);

	/* extra description coolness! */
	CREATE(new_descr, struct extra_descr_data, 1);
	new_descr->keyword = str_dup(final_potion->name);
	sprintf(buf2, "It appears to be a %s potion.", spells[potion]);
	new_descr->description = str_dup(buf2);
	new_descr->next = NULL;
	final_potion->ex_description = new_descr;
 
	GET_OBJ_TYPE(final_potion) = ITEM_POTION;
	GET_OBJ_WEAR(final_potion) = ITEM_WEAR_TAKE;
	GET_OBJ_EXTRA(final_potion) = ITEM_NORENT;
	GET_OBJ_VAL(final_potion, 0) = GET_LEVEL(ch);
	GET_OBJ_VAL(final_potion, 1) = potion;
	GET_OBJ_VAL(final_potion, 2) = -1;
	GET_OBJ_VAL(final_potion, 3) = -1;
	GET_OBJ_COST(final_potion) = GET_LEVEL(ch) * 500;
	GET_OBJ_WEIGHT(final_potion) = 1;
	GET_OBJ_RENT(final_potion) = 0;
		
	obj_to_char(final_potion, ch);
}

ACMD(do_brew)
{
	struct obj_data *container = NULL;
	struct obj_data *obj, *next_obj;
	char bottle_name[MAX_STRING_LENGTH];
	char spell_name[MAX_STRING_LENGTH];
	char *temp1, *temp2;
	int potion, found = FALSE;

	temp1 = one_argument(argument, bottle_name);
	
	/* sanity check */
	if (temp1) {
	    temp2 = get_spell_name(temp1);
	    if (temp2)
		strcpy(spell_name, temp2);
	} else {
	    bottle_name[0] = '\0';
	    spell_name[0] = '\0';
	} 
	
     
	/* Can't make scrolls in arena */
	if (IS_ARENACOMBATANT(ch)){
	  send_to_char("Strangely enough, you find your ability to brew potions dimunished while you're in the arena.\r\n",ch);
	  return;
	}

	if (!(GET_CLASS(ch) == CLASS_ARTISAN || GET_LEVEL(ch) >= LVL_IMMORT)) {
		send_to_char("You have no idea how to mix potions!\r\n", ch);
		return;
	}

        if (GET_SKILL(ch, SKILL_BREW) == 0) {
        send_to_char("You have no idea how to mix potions!\r\n", ch);
             return;
}
	if (!*bottle_name || !*spell_name) {
		send_to_char("What do you wish to mix in where?\r\n", ch);
		return;
	}

	for (obj = ch->carrying; obj; obj = next_obj) {
		next_obj = obj->next_content;
		if (obj == NULL)
			return;
		else if (!(container = get_obj_in_list_vis(ch, bottle_name,
			ch->carrying))) 
			continue;
		else
			found = TRUE;
	}
	if (found != FALSE && (GET_OBJ_TYPE(container) != ITEM_DRINKCON)) {
		send_to_char("That item is not a drink container!\r\n", ch);
		return;
	}
	if (found == FALSE) {
		sprintf(buf, "You don't have %s in your inventory!\r\n",
			bottle_name);
		send_to_char(buf, ch);
		return;
	}

	if (!spell_name || !*spell_name) {
	    send_to_char("Spell names must be enclosed in single quotes!\r\n",
			 ch);
	    return;
	}
 
	potion = find_skill_num(spell_name);	

	if ((potion < 1) || (potion > MAX_SPELLS)) {
		send_to_char("Mix what spell?!?\r\n", ch);
		return;
	}
//	if (GET_LEVEL(ch) < spell_info[potion].min_level[(int) GET_CLASS(ch)]) {
//		 send_to_char("You do not know how to make that potion!\r\n",
//			      ch);
//		return;
//	}
//	if (GET_SKILL(ch, potion) == 0) {
//		 send_to_char("You don't know any spell like that\r\n",
//		 ch);
//		return;
//	}
	make_potion(ch, potion, container);
}


char *garble_spell(int spellnum)
{
  char lbuf[256];
  int j, ofs = 0;

  *buf = '\0';
  strcpy(lbuf, spells[spellnum]);

  while (*(lbuf + ofs)) {
    for (j = 0; *(syls[j].org); j++) {
      if (!strncmp(syls[j].org, lbuf + ofs, strlen(syls[j].org))) {
	strcat(buf, syls[j].new);
	ofs += strlen(syls[j].org);
      }
    }
  }
  return buf;
}

void make_scroll(struct char_data *ch, int scroll, struct obj_data *paper)
{
	struct obj_data *final_scroll;
	struct extra_descr_data *new_descr;
	int can_make = TRUE, mana, dam = 0;
	
	/* add a case statement here for prohibited spells */	

	if (can_make == FALSE) {
		send_to_char("That spell cannot be scribed into a"
			     " scroll.\r\n", ch);
		return;
	}
	else if ((number(1, 3) == 3) && (GET_LEVEL(ch) < LVL_IMMORT)) {
		send_to_char("As you begin inscribing the final rune, the"
			     " scroll violently explodes!\r\n",ch);
		act("$n tries to scribe a spell, but it explodes!",
		    FALSE, ch, 0,0, TO_ROOM);
		extract_obj(paper);
		dam = number(15, mag_manacost(ch, scroll) * 2);
		GET_HIT(ch) -= dam;
		update_pos(ch);
		return;
	}
	/* requires x3 mana to scribe a scroll than the spell */
	mana = mag_manacost(ch, scroll) * 3;

	if (GET_MANA(ch) - mana > 0) {
		if (GET_LEVEL(ch) < LVL_IMMORT) GET_MANA(ch) -= mana;
		sprintf(buf, "You create a scroll of %s.\r\n",
			spells[scroll]);
		send_to_char(buf, ch);
		act("$n creates a scroll!", FALSE, ch, 0, 0, TO_ROOM);
		extract_obj(paper);
	}
	else {
		send_to_char("You don't have enough mana to scribe such"
			     " a powerful spell!\r\n", ch);
		return;
	}
	
	final_scroll = create_obj();

	final_scroll->item_number = NOTHING;
	final_scroll->in_room = NOWHERE;
	sprintf(buf2, "%s %s scroll", 
		spells[scroll], garble_spell(scroll));
	final_scroll->name = str_dup(buf2);

	sprintf(buf2, "A parchment inscribed with the runes '%s' lies here.", garble_spell(scroll));
	final_scroll->description = str_dup(buf2);

	sprintf(buf2, "a %s scroll", garble_spell(scroll));
	final_scroll->short_description = str_dup(buf2);

	/* extra description coolness! */
	CREATE(new_descr, struct extra_descr_data, 1);
	new_descr->keyword = str_dup(final_scroll->name);
	sprintf(buf2, "It appears to be a %s scroll.", spells[scroll]);
	new_descr->description = str_dup(buf2);
	new_descr->next = NULL;
	final_scroll->ex_description = new_descr;
 
	GET_OBJ_TYPE(final_scroll) = ITEM_SCROLL;
	GET_OBJ_WEAR(final_scroll) = ITEM_WEAR_TAKE;
	GET_OBJ_EXTRA(final_scroll) = ITEM_NORENT;
	GET_OBJ_VAL(final_scroll, 0) = GET_LEVEL(ch);
	GET_OBJ_VAL(final_scroll, 1) = scroll;
	GET_OBJ_VAL(final_scroll, 2) = -1;
	GET_OBJ_VAL(final_scroll, 3) = -1;
	GET_OBJ_COST(final_scroll) = GET_LEVEL(ch) * 500;
	GET_OBJ_WEIGHT(final_scroll) = 1;
	GET_OBJ_RENT(final_scroll) = 0;
	
	obj_to_char(final_scroll, ch);
}


ACMD(do_scribe)
{
	struct obj_data *paper = NULL;
	struct obj_data *obj, *next_obj;
	char paper_name[MAX_STRING_LENGTH];
	char spell_name[MAX_STRING_LENGTH];
	char *temp1, *temp2;
	int scroll = 0, found = FALSE;

	temp1 = one_argument(argument, paper_name);

	/* sanity check */
	if (temp1) {
	    temp2 = get_spell_name(temp1);
	    if (temp2)
		strcpy(spell_name, temp2);
	} else {
	    paper_name[0] = '\0';
	    spell_name[0] = '\0';
	}


	/* Can't make scrolls in arena */
	if (IS_ARENACOMBATANT(ch)){
	  send_to_char("Strangely enough, you find your ability to scribe scrolls diminished while you're in the arena.\r\n",ch);
	  return;
	}

	if (!(GET_CLASS(ch) == CLASS_ARTISAN || GET_LEVEL(ch) >= LVL_IMMORT)) {
		send_to_char("You have no idea how to scribe scrolls!\r\n", ch);
		return;
	}
        if (GET_SKILL(ch, SKILL_SCRIBE) == 0) {
        send_to_char("You have no idea how to scribe scrolls!\r\n", ch);
             return;
}
	if (!*paper_name || !*spell_name) {
		send_to_char("What do you wish to scribe where?\r\n", ch);
		return;
	}

	for (obj = ch->carrying; obj; obj = next_obj) {
		next_obj = obj->next_content;
		if (obj == NULL)
			return;
		else if (!(paper = get_obj_in_list_vis(ch, paper_name,
			ch->carrying))) 
			continue;
		else
			found = TRUE;
	}
	if (found && (GET_OBJ_TYPE(paper) != ITEM_NOTE)) {
		send_to_char("You can't write on that!\r\n", ch);
		return;
	}
	if (found == FALSE) {
		sprintf(buf, "You don't have %s in your inventory!\r\n",
			paper_name);
		send_to_char(buf, ch);
		return;
	}

	if (!spell_name || !*spell_name) {
	    send_to_char("Spell names must be enclosed in single quotes!\r\n",
			 ch);
	    return;
	} 

	scroll = find_skill_num(spell_name);	

	if ((scroll < 1) || (scroll > MAX_SPELLS)) {
		send_to_char("Scribe what spell?!?\r\n", ch);
		return;
	}
//	if (GET_LEVEL(ch) < spell_info[scroll].min_level[(int) GET_CLASS(ch)]) {
//		 send_to_char("You are not schooled enough to cast that spell!\r\n",
//			      ch);
//		return;
//	}
//	if (GET_SKILL(ch, scroll) == 0) {
//		 send_to_char("You don't know any spell like that!\r\n",
//		 ch);
//		return;
//	}
	make_scroll(ch, scroll, paper);
}


ACMD(do_forge)
{
	/* PLEASE NOTE!!!  This command alters the object_values of the target
	   weapon, and this will save to the rent files.  It should not cause
	   a problem with stock Circle, but if your weapons use the first 
	   position [ GET_OBJ_VAL(weapon, 0); ], then you WILL have a problem.
	   This command stores the character's level in the first value to 
	   prevent the weapon from being "forged" more than once by mortals.
	   Install at your own risk.  You have been warned...
	*/
	
	struct obj_data *weapon = NULL;
	struct obj_data *obj, *next_obj;
	char weapon_name[MAX_STRING_LENGTH];
	int found = FALSE, prob = 0, dam = 0;

	one_argument(argument, weapon_name);

	if (!(GET_CLASS(ch) == CLASS_ARTISAN || GET_LEVEL(ch) >= LVL_IMMORT)) {
		send_to_char("You have no idea how to forge weapons!\r\n", ch);
		return;
	}
        if (GET_SKILL(ch, SKILL_FORGE) == 0) {
        send_to_char("You have no idea how to forge weapons!\r\n", ch);
             return;
}
	if (!*weapon_name) {
		send_to_char("What do you wish to forge?\r\n", ch);
		return;
	}

	for (obj = ch->carrying; obj; obj = next_obj) {
		next_obj = obj->next_content;
		if (obj == NULL)
			return;
		else if (!(weapon = get_obj_in_list_vis(ch, weapon_name,
			ch->carrying))) 
			continue;
		else
			found = TRUE;
	}
	
	if (found == FALSE) {
		sprintf(buf, "You don't have %s in your inventory!\r\n",
			weapon_name);
		send_to_char(buf, ch);
		return;
	}

	if (found && (GET_OBJ_TYPE(weapon) != ITEM_WEAPON)) {
		sprintf(buf, "It doesn't look like %s would make a"
			" good weapon...\r\n", weapon_name);
		send_to_char(buf, ch);
		return;
	}

	if ((GET_OBJ_VAL(weapon, 0) > 0) && (GET_LEVEL(ch) < LVL_GOD)) {
	    send_to_char("You cannot forge a weapon more than once!\r\n", ch);
	    return;
	}

	if (GET_OBJ_EXTRA(weapon) & ITEM_MAGIC) {
	    send_to_char("The weapon is imbued with magical powers beyond"
			 "your grasp.\r\nYou cannot further affect its form.\r\n", ch);
	    return;
	}

	/* determine success probability */
	prob += ((GET_DEX(ch) - 11) << 1);
	prob += ((GET_STR(ch) - 11) << 1) + (GET_ADD(ch) >> 3);
	prob -= number(10,30);

	if ((number((prob*0.7), (prob*1.5)) > 
	     (prob+(GET_LEVEL(ch)/number(5,10)))) 
	    && (GET_LEVEL(ch) < LVL_IMMORT)) {
		send_to_char("As you pound out the dents in the weapon,"
			     " you hit a weak spot and it explodes!\r\n", ch);
		act("$n tries to forge a weapon, but it explodes!",
		    FALSE, ch, 0,0, TO_ROOM);
		extract_obj(weapon);
		dam = number(10, 22);
		GET_HIT(ch) -= dam;
		update_pos(ch);
		return;
	}

	GET_OBJ_VAL(weapon, 0) = GET_LEVEL(ch);
	GET_OBJ_VAL(weapon, 1) += (GET_LEVEL(ch) % 3) + number(-1, 2); 
	GET_OBJ_VAL(weapon, 2) += (GET_LEVEL(ch) % 2) + number(-1, 2);
	if (dice (GET_OBJ_VAL (weapon, 1), GET_OBJ_VAL (weapon, 2)) > 
	    (GET_LEVEL(ch)/2.5)){
	  send_to_char("As you pound out the dents in the weapon,"
		       " you stress it beyond it's ability and it explodes!\r\n", ch);
	  act("$n tries to forge a weapon, but it explodes!",
	      FALSE, ch, 0,0, TO_ROOM);
	  extract_obj(weapon);
	  dam = number(10, 50);
	  GET_HIT(ch) -= dam;
	  update_pos(ch);
	  return;
	}
	GET_OBJ_RENT(weapon) += (GET_LEVEL(ch) << 3); 
	GET_OBJ_RENT(weapon) *= number(2,5);
	/* GET_OBJ_RENT(weapon) += GET_LEVEL(ch) * 50 * number(5,10); */

	send_to_char("You have forged new life into the weapon!\r\n", ch);
	act("$n vigorously pounds on a weapon!",
		    FALSE, ch, 0, 0, TO_ROOM);
}