/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Dystopia Mud improvements copyright (C) 2000, 2001 by Brian Graversen *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "merc.h"
/*
===========================================================================
This snippet was written by Erwin S. Andreasen, erwin@pip.dknet.dk. You may
use this code freely, as long as you retain my name in all of the files. You
also have to mail me telling that you are using it. I am giving this,
hopefully useful, piece of source code to you for free, and all I require
from you is some feedback.
Please mail me if you find any bugs or have any new ideas or just comments.
All my snippets are publically available at:
http://pip.dknet.dk/~pip1773/
If you do not have WWW access, try ftp'ing to pip.dknet.dk and examine
the /pub/pip1773 directory.
===========================================================================
*/
extern ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH];
typedef enum
{ exit_from, exit_to, exit_both }
exit_status;
const sh_int opposite_dir[6] = { DIR_SOUTH, DIR_WEST, DIR_NORTH, DIR_EAST, DIR_DOWN, DIR_UP };
/*
* get the 'short' name of an area (e.g. MIDGAARD, MIRROR etc.
* assumes that the filename saved in the AREA_DATA struct is something like midgaard.are
*/
char *area_name(AREA_DATA * pArea)
{
static char buffer[64];
char *period;
assert(pArea != NULL);
strncpy(buffer, pArea->filename, 64);
period = strchr(buffer, '.');
if (period)
*period = '\0';
return buffer;
}
void room_pair(ROOM_INDEX_DATA * left, ROOM_INDEX_DATA * right, exit_status ex, char *buffer)
{
char *sExit;
switch (ex)
{
default:
sExit = "??";
break; /* invalid usage */
case exit_from:
sExit = "< ";
break;
case exit_to:
sExit = " >";
break;
case exit_both:
sExit = "<>";
break;
}
sprintf(buffer, "%5d %-26.26s %s%5d %-26.26s(%-8.8s)\n\r", left->vnum, left->name, sExit, right->vnum, right->name, area_name(right->area));
return;
}
/* for every exit in 'room' which leads to or from pArea but NOT both, print it */
void checkexits(ROOM_INDEX_DATA * room, AREA_DATA * pArea, char *buffer)
{
char buf[MAX_STRING_LENGTH];
int i;
EXIT_DATA *exit;
ROOM_INDEX_DATA *to_room;
strcpy(buffer, "");
for (i = 0; i < 6; i++)
{
exit = room->exit[i];
if (!exit)
continue;
else
to_room = exit->to_room;
if (to_room)
{
if ((room->area == pArea) && (to_room->area != pArea))
{
if (to_room->exit[opposite_dir[i]] && to_room->exit[opposite_dir[i]]->to_room == room)
room_pair(room, to_room, exit_both, buf); /* <> */
else
room_pair(room, to_room, exit_to, buf); /* > */
strcat(buffer, buf);
}
else
{
if ((room->area != pArea) && (exit->to_room->area == pArea))
{ /* an exit from another area to our area */
if (!(to_room->exit[opposite_dir[i]] && to_room->exit[opposite_dir[i]]->to_room == room))
{ /* two-way exits are handled in the other if */
room_pair(to_room, room, exit_from, buf);
strcat(buffer, buf);
}
} /* if room->area */
} /* for */
}
}
return;
}
/* for now, no arguments, just list the current area */
void do_exlist(CHAR_DATA * ch, char *argument)
{
AREA_DATA *pArea;
ROOM_INDEX_DATA *room;
int i;
char buffer[MAX_STRING_LENGTH];
pArea = ch->in_room->area;
for (i = 0; i < MAX_KEY_HASH; i++)
{
for (room = room_index_hash[i]; room != NULL; room = room->next)
{
checkexits(room, pArea, buffer);
send_to_char(buffer, ch);
}
}
return;
}
void set_switchname(CHAR_DATA * ch, char *title)
{
char buf[MAX_STRING_LENGTH];
if (IS_NPC(ch))
{
bug("Set_switchname: NPC.", 0);
return;
}
strcpy(buf, title);
free_string(ch->pcdata->switchname);
ch->pcdata->switchname = str_dup(buf);
return;
}
void do_reimb(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *vch;
char arg[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
int v;
argument = one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("Reimburse <target> <xp|qp> <amount>\n\r", ch);
return;
}
if ((vch = get_char_world(ch, arg)) == NULL)
{
send_to_char("They aren't logged on.\n\r", ch);
return;
}
if (IS_NPC(vch))
{
send_to_char("That is a mob.\n\r", ch);
return;
}
argument = one_argument(argument, arg);
argument = one_argument(argument, arg2);
v = atoi(arg2);
if (arg[0] == '\0' || arg2[0] == '\0' || (!is_number(arg2) && v >= 0))
{
do_reimb(ch, "");
return;
}
if (!str_cmp(arg, "xp"))
{
vch->exp += v;
vch->pcdata->score[SCORE_TOTAL_XP] += v;
}
else if (!str_cmp(arg, "qp"))
{
vch->pcdata->quest += v;
vch->pcdata->questtotal += v;
}
else
{
send_to_char("Please specify XP or QP.\n\r", ch);
return;
}
if (vch->mkill < 5)
{
vch->mkill = 5;
do_autosave(ch, "");
}
sprintf(arg2, "%s reimbursed %d %s.\n\r", vch->name, v, arg);
send_to_char(arg2, ch);
sprintf(arg2, "%s has reimbursed you %d %s.\n\r", ch->name, v, arg);
send_to_char(arg2, vch);
}
void do_affects(CHAR_DATA * ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
AFFECT_DATA *paf;
if (IS_NPC(ch))
return;
if (IS_ITEMAFF(ch, ITEMA_CHAOSSHIELD))
send_to_char("#pChaosshield#n.\n\r", ch);
if (IS_AFFECTED(ch, AFF_SANCTUARY))
send_to_char("#7Sanctuary#n.\n\r", ch);
if (IS_AFFECTED(ch, AFF_PROTECT))
send_to_char("#LProtection from evil#n.\n\r", ch);
if (IS_AFFECTED(ch, AFF_PROTECT_GOOD))
send_to_char("#LProtection from good#n.\n\r", ch);
if (IS_AFFECTED(ch, AFF_FLYING))
send_to_char("#cFly#n\n\r", ch);
send_to_char("\n\r", ch);
if (ch->affected == NULL)
{
send_to_char("You have nothing affecting you at this time.\n\r", ch);
return;
}
if (ch->affected != NULL)
{
send_to_char("You are affected by:\n\r", ch);
for (paf = ch->affected; paf != NULL; paf = paf->next)
{
sprintf(buf, "Spell: '%s'", skill_table[paf->type].name);
send_to_char(buf, ch);
if (ch->level >= 0)
{
sprintf(buf, " modifies %s by %d for %d hours with bits %s.\n\r", affect_loc_name(paf->location), paf->modifier, paf->duration, affect_bit_name(paf->bitvector));
send_to_char(buf, ch);
}
}
}
return;
}
char *plr_bit_name(int arg)
{
static char buf[512];
buf[0] = '\0';
if (arg & PLR_IS_NPC)
strcat(buf, " npc");
if (arg & PLR_AUTOEXIT)
strcat(buf, " autoexit");
if (arg & PLR_AUTOLOOT)
strcat(buf, " autoloot");
if (arg & PLR_AUTOSAC)
strcat(buf, " autosac");
if (arg & PLR_BRIEF1)
strcat(buf, " brief");
if (arg & PLR_PROMPT)
strcat(buf, " prompt");
if (arg & PLR_TELNET_GA)
strcat(buf, " telnet_ga");
if (arg & PLR_HOLYLIGHT)
strcat(buf, " holylight");
if (arg & PLR_WIZINVIS)
strcat(buf, " wizinvis");
if (arg & PLR_ANSI)
strcat(buf, " ansi");
if (arg & PLR_SILENCE)
strcat(buf, " silenced");
if (arg & PLR_LOG)
strcat(buf, " log");
if (arg & PLR_FREEZE)
strcat(buf, " freeze");
return (buf[0] != '\0') ? buf + 1 : "none";
}
char *extra_plr_bit_name(int arg)
{
static char buf[512];
buf[0] = '\0';
if (arg & EXTRA_NEWPASS)
strcat(buf, " newpass");
if (arg & EXTRA_OSWITCH)
strcat(buf, " oswitch");
if (arg & TIED_UP)
strcat(buf, " tied_up");
if (arg & GAGGED)
strcat(buf, " gagged");
if (arg & BLINDFOLDED)
strcat(buf, " blindfolded");
if (arg & EXTRA_DONE)
strcat(buf, " non_virgin");
if (arg & EXTRA_EXP)
strcat(buf, " got_exp");
if (arg & EXTRA_PREGNANT)
strcat(buf, " pregnant");
if (arg & EXTRA_LABOUR)
strcat(buf, " labour");
if (arg & EXTRA_BORN)
strcat(buf, " born");
if (arg & EXTRA_PROMPT)
strcat(buf, " prompt");
if (arg & EXTRA_MARRIED)
strcat(buf, " married");
if (arg & EXTRA_CALL_ALL)
strcat(buf, " call_all");
return (buf[0] != '\0') ? buf + 1 : "none";
}
char *get_position_name(int arg)
{
switch (arg)
{
case 0:
return "dead";
case 1:
return "mortal";
case 2:
return "incap";
case 3:
return "stunned";
case 4:
return "sleeping";
case 5:
return "meditating";
case 6:
return "sitting";
case 7:
return "resting";
case 8:
return "fighting";
case 9:
return "standing";
}
bug("Get_position_name: unknown type %d.", arg);
return "(unknown)";
}
/*
* Itemaffect bit names :)
*/
char *itemaffect_bit_name(int arg)
{
static char buf[512];
buf[0] = '\0';
if (arg & ITEMA_CHAOSSHIELD)
strcat(buf, " Chaoshield");
if (arg & ITEMA_ARTIFACT)
strcat(buf, " Artifact");
if (arg & ITEMA_REGENERATE)
strcat(buf, " Regeneration");
if (arg & ITEMA_SPEED)
strcat(buf, " Speed");
if (arg & ITEMA_VORPAL)
strcat(buf, " Vorpal");
if (arg & ITEMA_RESISTANCE)
strcat(buf, " Resistance");
if (arg & ITEMA_VISION)
strcat(buf, " Vision");
if (arg & ITEMA_STALKER)
strcat(buf, " Stalker");
if (arg & ITEMA_VANISH)
strcat(buf, " Vanish");
return (buf[0] != '\0') ? buf + 1 : "none";
}
/*
* Pstat code by Tijer
*/
void do_pstat(CHAR_DATA * ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
CHAR_DATA *victim;
argument = one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("Pstat whom?\n\r", ch);
return;
}
if ((victim = get_char_world(ch, arg)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
sprintf(buf, "Name : %s.\n\r", IS_NPC(victim) ? victim->short_descr : victim->name);
send_to_char(buf, ch);
sprintf(buf, "Sex : %s. Room : %d. Align : %d. Primal : %d. Quest : %d.\n\r",
victim->sex == SEX_MALE ? "Male" :
victim->sex == SEX_FEMALE ? "Female" : "None", victim->in_room == NULL ? 0 : victim->in_room->vnum, victim->alignment, victim->practice, IS_NPC(victim) ? 0 : victim->pcdata->quest);
send_to_char(buf, ch);
sprintf(buf, "Level : %d. Trust : %d. Exp : %d.", victim->level, victim->trust, victim->exp);
send_to_char(buf, ch);
if (!IS_NPC(victim))
{
sprintf(buf, " PlayerID : %d.\n\r", victim->pcdata->playerid);
send_to_char(buf, ch);
}
else
send_to_char("\n\r", ch);
sprintf(buf, "Hit : %d. Dam : %d. AC : %d. Position : %s\n\r", char_hitroll(victim), char_damroll(victim), char_ac(victim), capitalize(get_position_name(victim->position)));
send_to_char(buf, ch);
sprintf(buf, "HP %d/%d. Mana %d/%d. Move %d/%d.\n\r", victim->hit, victim->max_hit, victim->mana, victim->max_mana, victim->move, victim->max_move);
send_to_char(buf, ch);
sprintf(buf, "Str: %d. Int: %d. Wis: %d. Dex: %d. Con: %d.\n\r", get_curr_str(victim), get_curr_int(victim), get_curr_wis(victim), get_curr_dex(victim), get_curr_con(victim));
send_to_char(buf, ch);
sprintf(buf, "Fighting : %s. (%d)\n\r", victim->fighting ? victim->fighting->name : "(None)", victim->fighting ? victim->fighting->level : 0);
send_to_char(buf, ch);
sprintf(buf, "Pkill : %d. Pdeath : %d. Mkill : %d. Mdeath : %d.\n\r",
IS_NPC(victim) ? 0 : victim->pkill, IS_NPC(victim) ? 0 : victim->pdeath, IS_NPC(victim) ? 0 : victim->mkill, IS_NPC(victim) ? 0 : victim->mdeath);
send_to_char(buf, ch);
sprintf(buf, "TotExp : %12d. TotMobLev : %10d. TotQuestPoints : %10d.\n\r",
IS_NPC(victim) ? 0 : victim->pcdata->score[SCORE_TOTAL_XP], IS_NPC(victim) ? 0 : victim->pcdata->score[SCORE_TOTAL_LEVEL], IS_NPC(victim) ? 0 : victim->pcdata->score[SCORE_QUEST]);
send_to_char(buf, ch);
sprintf(buf, "HighExp : %12d. HighMobLev : %10d. Tot#Quests : %10d.\n\r",
IS_NPC(victim) ? 0 : victim->pcdata->score[SCORE_HIGH_XP], IS_NPC(victim) ? 0 : victim->pcdata->score[SCORE_HIGH_LEVEL], IS_NPC(victim) ? 0 : victim->pcdata->score[SCORE_NUM_QUEST]);
send_to_char(buf, ch);
if (!IS_NPC(victim))
{
sprintf(buf, "Unarmed : %4d.", victim->wpn[0]);
send_to_char(buf, ch);
sprintf(buf, " Slice : %4d.", victim->wpn[1]);
send_to_char(buf, ch);
sprintf(buf, " Stab : %4d.", victim->wpn[2]);
send_to_char(buf, ch);
sprintf(buf, " Slash : %4d.", victim->wpn[3]);
send_to_char(buf, ch);
sprintf(buf, " Whip : %4d.\n\r", victim->wpn[4]);
send_to_char(buf, ch);
sprintf(buf, "Claw : %4d.", victim->wpn[5]);
send_to_char(buf, ch);
sprintf(buf, " Blast : %4d.", victim->wpn[6]);
send_to_char(buf, ch);
sprintf(buf, " Pound : %4d.", victim->wpn[7]);
send_to_char(buf, ch);
sprintf(buf, " Crush : %4d.", victim->wpn[8]);
send_to_char(buf, ch);
sprintf(buf, " Grep : %4d.\n\r", victim->wpn[9]);
send_to_char(buf, ch);
sprintf(buf, "Bite : %4d.", victim->wpn[10]);
send_to_char(buf, ch);
sprintf(buf, " Pierce : %4d.", victim->wpn[11]);
send_to_char(buf, ch);
sprintf(buf, " Suck : %4d.\n\r", victim->wpn[12]);
send_to_char(buf, ch);
sprintf(buf, "%-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d.\n\r",
"Purple", victim->spl[PURPLE_MAGIC], "Red", victim->spl[RED_MAGIC], "Blue", victim->spl[BLUE_MAGIC], "Green", victim->spl[GREEN_MAGIC], "Yellow", victim->spl[YELLOW_MAGIC]);
send_to_char(buf, ch);
sprintf(buf, "%-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d.\n\r",
"Viper", victim->stance[STANCE_VIPER],
"Crane", victim->stance[STANCE_CRANE], "Crab", victim->stance[STANCE_CRAB], "Mongoose", victim->stance[STANCE_MONGOOSE], "Bull", victim->stance[STANCE_BULL]);
send_to_char(buf, ch);
sprintf(buf, "%-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d.\n\r",
"Mantis", victim->stance[STANCE_MANTIS],
"Dragon", victim->stance[STANCE_DRAGON], "Tiger", victim->stance[STANCE_TIGER], "Monkey", victim->stance[STANCE_MONKEY], "Swallow", victim->stance[STANCE_SWALLOW]);
send_to_char(buf, ch);
sprintf(buf, "%-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d.\n\r",
"ss1", victim->stance[STANCE_SS1], "ss2", victim->stance[STANCE_SS2], "ss3", victim->stance[STANCE_SS3], "ss4", victim->stance[STANCE_SS4], "ss5", victim->stance[STANCE_SS5]);
send_to_char(buf, ch);
sprintf(buf, "Act : %s\n\r", plr_bit_name(victim->act));
send_to_char(buf, ch);
sprintf(buf, "Extra : %s\n\r", victim->extra <= 0 ? "(None)" : extra_plr_bit_name(victim->extra));
send_to_char(buf, ch);
sprintf(buf, "ItemAff : %s\n\r", victim->itemaffect <= 0 ? "(None)" : itemaffect_bit_name(victim->itemaffect));
send_to_char(buf, ch);
sprintf(buf, "Affected by : %s.\n\r", affect_bit_name(victim->affected_by));
send_to_char(buf, ch);
return;
}
}
/* agrr_test by blade of E, version 1.31. */
void aggr_test(CHAR_DATA * ch)
{
char buf[60];
CHAR_DATA *wch;
CHAR_DATA *wch_next;
CHAR_DATA *victim;
if (!IS_NPC(ch) && ch->level < 7 && ch->in_room != NULL && !IS_SET(ch->in_room->room_flags, ROOM_SAFE))
{
for (wch = ch->in_room->people; wch != NULL; wch = wch_next)
{
wch_next = wch->next_in_room;
if (!IS_NPC(wch) || !IS_SET(wch->act, ACT_AGGRESSIVE)
|| wch->fighting != NULL || IS_AFFECTED(wch, AFF_CHARM) || !IS_AWAKE(wch) || (IS_SET(wch->act, ACT_WIMPY) && IS_AWAKE(ch)) || !can_see(wch, ch) || number_bits(2) == 0)
{
continue;
}
victim = wch;
if (victim == NULL)
continue;
sprintf(buf, "%s screams and attacks!\n\r", victim->name);
send_to_char(buf, ch);
multi_hit(victim, ch, TYPE_UNDEFINED);
}
}
return;
}