empiremud/cnf/
empiremud/doc/
empiremud/lib/boards/
empiremud/lib/etc/
empiremud/lib/misc/
empiremud/lib/plralias/F-J/
empiremud/lib/plralias/K-O/
empiremud/lib/plralias/P-T/
empiremud/lib/plralias/U-Z/
empiremud/lib/plrobjs/
empiremud/lib/plrobjs/F-J/
empiremud/lib/plrobjs/K-O/
empiremud/lib/plrobjs/P-T/
empiremud/lib/plrobjs/U-Z/
empiremud/lib/world/
empiremud/lib/world/mob/
empiremud/lib/world/obj/
empiremud/log/
/* ************************************************************************
*   File: morph.c                                          EmpireMUD 0.0b *
*  Usage: morph-related code                                              *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Code base by Paul Clarke.  EmpireMUD Project, a tbgMUD Production.     *
*  Based upon CircleMUD 3.0, beta patch level 17, by Jeremy Elson.        *
*                                                                         *
*  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 "structs.h"
#include "utils.h"
#include "db.h"
#include "skills.h"
#include "handler.h"
#include "interpreter.h"


/* The main data structure */
struct morph_data_structure {
	int strength, dexterity, stamina;
	int charisma, manipulation, appearance;
	int perception, intelligence, wits;
	int move, attack_type, aff_bits;
	int morph_flags;
	char *short_desc;
	char *extra_desc;
	} morph_data[] = {
		/* Notes on adding forms:
		 *  1. add a MORPH_x definition for your morph
		 *  2. add an entry to this table (the extra desc should NOT end in \r\n)
		 *  3. find a place to cause the morph
		 * It's that easy.
		 */

		/* Normal form */
		{	0, 0, 0,
			0, 0, 0,
			0, 0, 0,
			0, 0, 0,
			0,
			"",
			""
			},

		/* Protean Bat form */
		{	-2, 0, 0,
			-2, -2, -2,
			1, 0, 0,
			100, TYPE_BITE, AFF_FLY,
			MORPH_FLAG_NPC | MORPH_FLAG_NO_TALONS,
			"a black bat",
			"   The bat is small and awkward as it flaps its wings around.  It flitters\r\naround you menacingly, but keeps its distance.  Though its size is not\r\nthreatening, the bat seems somehow capable of more."
			},

		/* Protean Wolf form */
		{	1, 1, 0,
			0, 0, 0,
			1, 0, 0,
			25, TYPE_CLAW, 0,
			MORPH_FLAG_NPC,
			"a brown wolf",
			"   As you look at the wolf, you first see $s cold, black eyes which stare you\r\ndown harshly.  Larger than the other wolves which roam the plains, $s this\r\ncreature frightens you deeply.  Wolves of this stature are known to be\r\nvicious, and you feel like running."
			},

		/* Zulo shape */
		{	3, 3, 3,
			-5, -5, -5,
			0, 0, 0,
			25, TYPE_CLAW, 0,
			0,
			"a zulo",
			"   The zulo is huge!  Well over eight feet tall, with greenish-gray flesh, it\r\nis like nothing you've ever seen!  Its army are long and thin, edged with\r\nblack nails, and its face is something out of a nightmare!  A row of spines\r\nruns down its back, and bony plates protect its skin!"
			},

		/* Chiropteran marauder */
		{	3, 3, 3,
			-5, -5, -5,
			-1, 0, 0,
			500, TYPE_CLAW, AFF_FLY,
			0,
			"a hideous giant bat",
			"   This is nothing, if not a giant bipedal bat.  It is hideously ugly,\r\ngrayish-black in color, with spines down its arms, legs, and back!  When it\r\nleaps into the air, you are knocked over by the force of its wings!"
			},

		/* Protean Mist */
		{	0, 0, 0,
			0, 0, 0,
			0, 0, 0,
			200, -1, AFF_FLY | AFF_NO_ATTACK | AFF_IMMUNE_PHYSICAL,
			0,
			"a cloud of swirling mist",
			"   The mist swirls around, periodically taking form and then swirling away\r\nagain.  It floats around you, chilling your flesh, then covers the ground,\r\nfeeling the terrain.  It swirls up again, and again seems to take some shape."
			},

		/* Plasma Form */
		{	0, 0, 0,
			0, 0, 0,
			0, 0, 0,
			-20, 0, AFF_NO_ATTACK | AFF_IMMUNE_PHYSICAL,
			0,
			"a gelatenous mass of blood",
			"   This large spheroid of blood looks gelatenous, and very unusual.  It has a\r\ndeep red hue and almost seems to scream as it flows along.  Surprisingly, no\r\ntrail is left behind it as it moves!  It is also difficult to separate it, not\r\nthat you want to try..."
			},

		/* Form of the Cobra */
		{	0, 0, 0,
			0, 0, 0,
			1, 0, 0,
			0, TYPE_BITE, 0,
			MORPH_FLAG_NO_TALONS,
			"a huge black cobra",
			"   You find a gigantic black cobra rising in front of you!  From nose to tail,\r\nit's over eight feel long and easily weighs as much as you do!  It cocks its\r\nmouth open and spreads its hood in an act of horrific intimidation!"
			},

		/* Glabro */
		{	2, 0, 2,
			0, -1, -1,
			0, 0, 0,
			0, TYPE_HIT, 0,
			0,
			"a large, ugly man",
			"   Description unwritten."
			},

		/* Crinos */
		{	4, 1, 3,
			0, -3, -5,
			0, 0, 0,
			100, TYPE_PROTEAN_CLAWS, AFF_INFRAVISION,
			0,
			"a giant wolf-man",
			"   Shaking with rage a huge half wolf half man is standing infront of you! Your body ceases to move despite your urge to run as fast as possible."
			},

		/* Hispo */
		{	3, 2, 3,
			0, -3, 0,
			0, 0, 0,
			150, TYPE_PROTEAN_CLAWS, AFF_INFRAVISION,
			0,
			"a huge wolf",
			"   Description unwritten."
			},

		/* Lupus */
		{	1, 2, 3,
			0, -3, 0,
			2, 0, 0,
			200, TYPE_CLAW, AFF_INFRAVISION,
			MORPH_FLAG_NPC,
			"a brown wolf",
			"   Description unwritten."
			},

		/* This must go last */
		{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", ""}

		};


/* return a short or extra description */
char *morph_string(Creature ch, byte type) {
	if (GET_MORPH(ch) > MORPH_NONE && GET_MORPH(ch) < NUM_MORPHS) {
		if (type == MORPH_STRING_NAME)
			return morph_data[(int) GET_MORPH(ch)].short_desc;
		else
			return morph_data[(int) GET_MORPH(ch)].extra_desc;
		}

	/* Oops */
	if (type == MORPH_STRING_NAME)
		return "a morphed creature";
	else
		return "There is no string provided for this morph.\r\n";
	}


/* get a morph's attack type */
int get_morph_attack_type(Creature ch) {
	if (GET_MORPH(ch) > MORPH_NONE && GET_MORPH(ch) < NUM_MORPHS)
		if (morph_data[(int) GET_MORPH(ch)].attack_type != -1)
			return morph_data[(int) GET_MORPH(ch)].attack_type;

	return TYPE_HIT;
	}


/* check for morph flags */
int MORPH_FLAGGED(Creature ch, int flag) {
	if (IS_NPC(ch))
		return 0;

	if (GET_MORPH(ch) > MORPH_NONE && GET_MORPH(ch) < NUM_MORPHS)
		return IS_SET(morph_data[(int) GET_MORPH(ch)].morph_flags, flag);
	return 0;
	}


/* return the modifier to a certain APPLY_x */
int morph_modifier(Creature ch, byte loc) {
	switch (loc) {
		case APPLY_STRENGTH:	return (morph_data[GET_MORPH(ch)].strength);
		case APPLY_DEXTERITY:	return (morph_data[GET_MORPH(ch)].dexterity);
		case APPLY_STAMINA:		return (morph_data[GET_MORPH(ch)].stamina);
		case APPLY_CHARISMA:	return (morph_data[GET_MORPH(ch)].charisma);
		case APPLY_MANIPULATION:return (morph_data[GET_MORPH(ch)].manipulation);
		case APPLY_APPEARANCE:	return (morph_data[GET_MORPH(ch)].appearance);
		case APPLY_INTELLIGENCE:return (morph_data[GET_MORPH(ch)].intelligence);
		case APPLY_PERCEPTION:	return (morph_data[GET_MORPH(ch)].perception);
		case APPLY_WITS:		return (morph_data[GET_MORPH(ch)].wits);
		case APPLY_MOVE:		return (morph_data[GET_MORPH(ch)].move);
		}
	return 0;
	}


/* Update the stats on a morph */
void update_morph_stats(Creature ch, bool add) {
	if (IS_NPC(ch) || GET_MORPH(ch) == MORPH_NONE)
		return;

	if (morph_data[GET_MORPH(ch)].aff_bits)
		affect_modify(ch, 0, 0, morph_data[GET_MORPH(ch)].aff_bits, 0, add);

	affect_modify(ch, APPLY_STRENGTH, morph_modifier(ch, APPLY_STRENGTH), 0, 0, add);
	affect_modify(ch, APPLY_DEXTERITY, morph_modifier(ch, APPLY_DEXTERITY), 0, 0, add);
	affect_modify(ch, APPLY_STAMINA, morph_modifier(ch, APPLY_STAMINA), 0, 0, add);
	affect_modify(ch, APPLY_CHARISMA, morph_modifier(ch, APPLY_CHARISMA), 0, 0, add);
	affect_modify(ch, APPLY_MANIPULATION, morph_modifier(ch, APPLY_MANIPULATION), 0, 0, add);
	affect_modify(ch, APPLY_APPEARANCE, morph_modifier(ch, APPLY_APPEARANCE), 0, 0, add);
	affect_modify(ch, APPLY_PERCEPTION, morph_modifier(ch, APPLY_PERCEPTION), 0, 0, add);
	affect_modify(ch, APPLY_INTELLIGENCE, morph_modifier(ch, APPLY_INTELLIGENCE), 0, 0, add);
	affect_modify(ch, APPLY_WITS, morph_modifier(ch, APPLY_WITS), 0, 0, add);
	affect_modify(ch, APPLY_MOVE, morph_modifier(ch, APPLY_MOVE), 0, 0, add);
	}


/* cause the morph to happen: universal thru this function to prevent errors */
void perform_morph(Creature ch, ubyte form) {
	ACMD(do_dismount);
	float mod;

	if (IS_NPC(ch))
		return;

	if (GET_RIDING(ch) && form != MORPH_NONE)
		do_dismount(ch, "", 0, 0);

	/* read current moves */
	mod = (float) GET_MOVE(ch) / GET_MAX_MOVE(ch);

	/* Remove his morph bonuses from his current form */
	update_morph_stats(ch, FALSE);

	/* Set the new form */
	GET_MORPH(ch) = form;

	/* Add new morph bonuses */
	update_morph_stats(ch, TRUE);

	/* set new moves */
	GET_MOVE(ch) = (sh_int) GET_MAX_MOVE(ch) * mod;

	/* check for talons */
	if (MORPH_FLAGGED(ch, MORPH_FLAG_NO_TALONS))
		REMOVE_BIT(DSC_FLAGS(ch), DSC_TALONS_OF_THE_BEAST);
	}