/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | *
* -----------------------------------------------------------| \\._.// *
* SmaugWiz (C) 1998 by Russ Pillsbury (Windows NT version) | (0...0) *
* -----------------------------------------------------------| ).:.( *
* SMAUG (C) 1994, 1995, 1996 by Derek Snider | {o o} *
* -----------------------------------------------------------| / ' ' \ *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, |~'~.VxvxV.~'~*
* Scryn, Swordbearer, Rennard, Tricops, and Gorog. | *
* ------------------------------------------------------------------------ *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik Staerfeldt, Tom Madsen, and Katja Nyboe. *
****************************************************************************/
#include "stdafx.h"
#include "smaug.h"
#include "Smaugx.h"
#include "language.h"
#include "skill.h"
#include "objects.h"
#include "rooms.h"
#include "clans.h"
#include "class.h"
#include "races.h"
#include "Exits.h"
#include "SmaugWizDoc.h"
#include "SmaugFiles.h"
#include "descriptor.h"
#include "character.h"
#define MAX_NEST 100
static CObjData * rgObjNest [MAX_NEST];
CCouncilData *first_council;
CCouncilData *last_council;
// local routines
void MakeClanGuildOrOrder (CCharacter& Ch, char *name, ClanTypes type);
void SetclanGuildOrOrder (CCharacter& Ch, char *argument, ClanTypes type);
void ShowClanGuildOrOrder (CCharacter& Ch, const char *name, ClanTypes type);
BOOL load_clan_file (char *clanfile);
void fread_council (CCouncilData *council, FILE *fp);
BOOL load_council_file (char *councilfile);
void write_council_list ();
// Load in all the clan files.
void load_clans ()
{
FILE *fp;
char *pFname, *pLine;
gpDoc->LogString ("Loading clans...", LOG_BOOT);
fclose (fpReserve);
if (! (fp = fopen (FileTable.GetName (SM_CLAN_LIST), "r"))) {
perror (FileTable.GetName (SM_CLAN_LIST));
ThrowSmaugException (SE_CLANS);
}
while (! feof (fp)) {
pLine = fread_line (fp);
pFname = ParseLine (pLine);
if (pFname [0] == '$') then break;
gpDoc->LogString (pFname, LOG_BOOT);
if (! load_clan_file (pFname))
bug ("Cannot load clan file: %s", pFname);
}
fclose (fp);
fpReserve = fopen (FileTable.GetName (SM_NULL_FILE), "r");
}
CClanData::CClanData (const char* name, const char* fname, ClanTypes type)
{
memset (this, 0, sizeof (CClanData));
SetName (name);
SetFilename (fname);
SetType (type);
motto = STRALLOC ("");
SetDescription ("");
deity = STRALLOC ("");
leader = STRALLOC ("");
number1 = STRALLOC ("");
number2 = STRALLOC ("");
}
// Save a clan's data to its data file
void CClanData::Save ()
{
FILE *fp;
CString Fname = FileTable.MakeName (SD_CLAN_DIR, m_pFilename);
fclose (fpReserve);
if ((fp = fopen (Fname, "w")) == NULL)
bug ("CClanData::Save: fopen. Filename = %s", NCCP Fname);
else {
fprintf (fp, "#CLAN\n");
fprintf (fp, "Name %s~\n", m_pName);
fprintf (fp, "Filename %s~\n", m_pFilename);
fprintf (fp, "Type %d\n", m_Type);
fprintf (fp, "Motto %s~\n", motto);
fprintf (fp, "Description %s~\n", m_pDescription);
fprintf (fp, "Deity %s~\n", deity);
fprintf (fp, "Leader %s~\n", leader);
fprintf (fp, "NumberOne %s~\n", number1);
fprintf (fp, "NumberTwo %s~\n", number2);
fprintf (fp, "PKills %d\n", pkills);
fprintf (fp, "PDeaths %d\n", pdeaths);
fprintf (fp, "MKills %d\n", mkills);
fprintf (fp, "MDeaths %d\n", mdeaths);
fprintf (fp, "IllegalPK %d\n", illegal_pk);
fprintf (fp, "Score %d\n", score);
fprintf (fp, "Class %d\n", m_Class);
fprintf (fp, "Favour %d\n", favour);
fprintf (fp, "Strikes %d\n", strikes);
fprintf (fp, "Members %d\n", m_Members);
fprintf (fp, "Alignment %d\n", alignment);
fprintf (fp, "Board %d\n", board);
fprintf (fp, "ClanObjOne %d\n", clanobj1);
fprintf (fp, "ClanObjTwo %d\n", clanobj2);
fprintf (fp, "ClanObjThree %d\n", clanobj3);
fprintf (fp, "Recall %d\n", recall);
fprintf (fp, "Storeroom %d\n", storeroom);
fprintf (fp, "GuardOne %d\n", guard1);
fprintf (fp, "GuardTwo %d\n", guard2);
fprintf (fp, "End\n\n");
fprintf (fp, "#END\n");
}
fclose (fp);
fpReserve = fopen (FileTable.GetName (SM_NULL_FILE), "r");
}
// Read in actual clan data.
#if defined (KEY)
#undef KEY
#endif
#define KEY(literal,field,value) \
if (!str_cmp (word, literal)) { \
field = value; \
fMatch = TRUE; \
break; \
}
void CClanData::Read (FILE *fp)
{
char *word, *pLine;
BOOL fMatch;
for (;;) {
fMatch = FALSE;
if (! feof (fp)) {
pLine = fread_line (fp);
word = ParseWord (pLine);
}
else word = "End";
switch (UPPER (word [0])) {
case '*':
fMatch = TRUE;
break;
case 'A':
KEY ("Alignment", alignment, ParseNumber (pLine));
break;
case 'B':
KEY ("Board", board, ParseNumber (pLine));
break;
case 'C':
KEY ("ClanObjOne", clanobj1, ParseNumber (pLine));
KEY ("ClanObjTwo", clanobj2, ParseNumber (pLine));
KEY ("ClanObjThree",clanobj3, ParseNumber (pLine));
KEY ("Class", m_Class, ParseNumber (pLine));
break;
case 'D':
KEY ("Deity", deity, ParseString (pLine, fp));
KEY ("Description", m_pDescription, ParseString (pLine, fp));
break;
case 'E':
if (!str_cmp (word, "End")) {
if (! GetName ())
SetName ("");
if (! leader)
leader = STRALLOC ("");
if (! GetDescription ())
SetDescription ("");
if (! motto)
motto = STRALLOC ("");
if (! number1)
number1 = STRALLOC ("");
if (! number2)
number2 = STRALLOC ("");
if (! deity)
deity = STRALLOC ("");
return;
}
break;
case 'F':
KEY ("Favour", favour, ParseNumber (pLine));
KEY ("Filename", m_pFilename, ParseStringNohash (pLine, fp));
case 'G':
KEY ("GuardOne", guard1, ParseNumber (pLine));
KEY ("GuardTwo", guard2, ParseNumber (pLine));
break;
case 'I':
KEY ("IllegalPK", illegal_pk, ParseNumber (pLine));
break;
case 'L':
KEY ("Leader", leader, ParseString (pLine, fp));
break;
case 'M':
KEY ("MDeaths", mdeaths, ParseNumber (pLine));
KEY ("Members", m_Members, ParseNumber (pLine));
KEY ("MKills", mkills, ParseNumber (pLine));
KEY ("Motto", motto, ParseString (pLine, fp));
break;
case 'N':
KEY ("Name", m_pName, ParseString (pLine, fp));
KEY ("NumberOne", number1, ParseString (pLine, fp));
KEY ("NumberTwo", number2, ParseString (pLine, fp));
break;
case 'P':
KEY ("PDeaths", pdeaths, ParseNumber (pLine));
KEY ("PKills", pkills, ParseNumber (pLine));
break;
case 'R':
KEY ("Recall", recall, ParseNumber (pLine));
break;
case 'S':
KEY ("Score", score, ParseNumber (pLine));
KEY ("Strikes", strikes, ParseNumber (pLine));
KEY ("Storeroom", storeroom, ParseNumber (pLine));
break;
case 'T':
KEY ("Type", m_Type, (ClanTypes)ParseNumber (pLine));
break;
}
if (! fMatch)
bug ("CClanData::Read: no match: %s", word);
}
}
CClanData::~CClanData ()
{
delete m_pFilename;
}
void do_makeclan (CCharacter *ch, char *argument)
{
MakeClanGuildOrOrder (*ch, argument, CLAN_PLAIN);
}
void do_makeguild (CCharacter *ch, char *argument)
{
MakeClanGuildOrOrder (*ch, argument, CLAN_GUILD);
}
void do_makeorder (CCharacter *ch, char *argument)
{
MakeClanGuildOrOrder (*ch, argument, CLAN_ORDER);
}
void MakeClanGuildOrOrder (CCharacter& Ch, char *name, ClanTypes type)
{
CClanData *clan;
char *tname = ClanList.GetTypeName (type);
if (! name || name [0] == '\0') {
Ch.SendTextf ("Usage: make%s <%s name>\n\r", tname, tname);
return;
}
CString Fname = name;
if (Fname.Find ('.') >= 0) {
Ch.SendText ("Use name of Clan, Guild or Order. Not filename\n\r");
return;
}
POSITION pos = ClanList.GetHeadPosition ();
while (pos) {
CClanData &Cl = *ClanList.GetNext (pos);
if (Cl.GetType () == type && ! stricmp (Cl.GetName (), name)) {
Ch.SendTextf ("%s: %s Already Exists as %s.\n\r", tname, name,
Cl.GetFilename ());
return;
}
}
Fname += '.';
Fname += tname;
clan = new CClanData (name, Fname, type);
ClanList.AddTail (clan);
clan->Save ();
ClanList.Write ();
}
void do_showclan (CCharacter *ch, char *argument)
{
ShowClanGuildOrOrder (*ch, argument, CLAN_PLAIN);
}
void do_showguild (CCharacter *ch, char *argument)
{
ShowClanGuildOrOrder (*ch, argument, CLAN_GUILD);
}
void do_showorder (CCharacter *ch, char *argument)
{
ShowClanGuildOrOrder (*ch, argument, CLAN_ORDER);
}
void ShowClanGuildOrOrder (CCharacter& Ch, const char *name, ClanTypes type)
{
CClanData *clan;
if (Ch.IsNpc ()) {
Ch.SendText ("Huh?\n\r");
return;
}
char *tname = ClanList.GetTypeName (type);
if (name [0] == '\0') {
Ch.SendTextf ("Usage: show%s <%s name>\n\r", tname, tname);
return;
}
clan = ClanList.Find (name, type);
if (! clan) {
Ch.SendTextf ("No such %s.\n\r", tname);
return;
}
Ch.SendTextf ("%s : %s\n\rFilename: %s\n\rMotto : %s\n\r",
tname, clan->GetName (), clan->GetFilename (), clan->motto);
Ch.SendTextf ("Description: %s\n\rDeity: %s\n\rLeader: %s\n\r",
clan->GetDescription (), clan->deity, clan->leader);
Ch.SendTextf ("Number1: %s\n\rNumber2: %s\n\rPKills: %6d "
"PDeaths: %6d\n\r",
clan->number1, clan->number2, clan->pkills, clan->pdeaths);
Ch.SendTextf ("MKills: %6d MDeaths: %6d\n\r",
clan->mkills, clan->mdeaths);
Ch.SendTextf ("IllegalPK: %-6d Score: %d\n\r",
clan->illegal_pk, clan->score);
Ch.SendTextf ("Favour: %6d Strikes: %d\n\r",
clan->favour, clan->strikes);
Ch.SendTextf ("Members: %3d Alignment: %d Class: %d\n\r",
clan->GetMembers (), clan->alignment, clan->m_Class);
Ch.SendTextf ("Board: %5d Object1: %5d Object2: %5d Object3: %5d\n\r",
clan->board, clan->clanobj1, clan->clanobj2, clan->clanobj3);
Ch.SendTextf ("Recall: %5d Storeroom: %5d Guard1: %5d Guard2: %5d\n\r",
clan->recall, clan->storeroom, clan->guard1, clan->guard2);
}
void do_setclan (CCharacter *ch, char *argument)
{
SetclanGuildOrOrder (*ch, argument, CLAN_PLAIN);
}
void do_setguild (CCharacter *ch, char *argument)
{
SetclanGuildOrOrder (*ch, argument, CLAN_GUILD);
}
void do_setorder (CCharacter *ch, char *argument)
{
SetclanGuildOrOrder (*ch, argument, CLAN_ORDER);
}
void SetclanGuildOrOrder (CCharacter& Ch, char *argument, ClanTypes type)
{
char arg1 [MAX_INPUT_LENGTH];
char arg2 [MAX_INPUT_LENGTH];
CClanData *clan;
if (Ch.IsNpc ()) {
Ch.SendText ("Huh?\n\r");
return;
}
char *tname = ClanList.GetTypeName (type);
argument = one_argument (argument, arg1);
argument = one_argument (argument, arg2);
if (arg1 [0] == '\0') {
Ch.SendText ("Usage: setclan <clan> <field>\n\r");
Ch.SendText ("\n\rField being one of:\n\r");
Ch.SendText (" deity leader number1 number2\n\r");
Ch.SendText (" members board recall storage\n\r");
Ch.SendText (" align");
Ch.SendText (" obj1 obj2 obj3 guard1 guard2\n\r");
if (Ch.GetTrustLevel () >= LEVEL_SUB_IMPLEM) {
Ch.SendText (" name filename motto desc\n\r");
Ch.SendText (" favour strikes delete\n\r");
}
return;
}
clan = ClanList.Find (arg1, type);
if (! clan) {
Ch.SendText ("No such clan.\n\r");
return;
}
if (! strcmp (arg2, "deity")) {
STRFREE (clan->deity);
clan->deity = STRALLOC (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "leader")) {
STRFREE (clan->leader);
clan->leader = STRALLOC (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "number1")) {
STRFREE (clan->number1);
clan->number1 = STRALLOC (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "number2")) {
STRFREE (clan->number2);
clan->number2 = STRALLOC (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "board")) {
clan->board = atoi (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "members")) {
clan->SetMembers (atoi (argument));
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "recall")) {
clan->recall = atoi (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "storage")) {
clan->storeroom = atoi (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "obj1")) {
clan->clanobj1 = atoi (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "obj2")) {
clan->clanobj2 = atoi (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "obj3")) {
clan->clanobj3 = atoi (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "guard1")) {
clan->guard1 = atoi (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "guard2")) {
clan->guard2 = atoi (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (Ch.GetTrustLevel () < LEVEL_SUB_IMPLEM) {
SetclanGuildOrOrder (Ch, "", type);
return;
}
if (! strcmp (arg2, "align")) {
clan->alignment = atoi (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "class")) {
clan->m_Class = atoi (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "name")) {
STRFREE (clan->GetName ());
clan->SetName (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "filename")) {
delete clan->GetFilename ();
clan->SetFilename (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
ClanList.Write ();
return;
}
if (! strcmp (arg2, "motto")) {
STRFREE (clan->motto);
clan->motto = STRALLOC (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! strcmp (arg2, "desc")) {
clan->SetDescription (argument);
Ch.SendText ("Done.\n\r");
clan->Save ();
return;
}
if (! stricmp (arg2, "delete")) {
CString FName = FileTable.MakeName (SD_CLAN_DIR,
clan->GetFilename ());
CString BName = FileTable.MakeBackupName (FName);
remove (BName);
rename (FName, BName);
ClanList.Remove (clan);
delete clan;
ClanList.Write ();
Ch.SendTextf ("%s %s Deleted.\n\r", tname, arg1);
return;
}
SetclanGuildOrOrder (Ch, "", type);
}
//Load a clan file
BOOL load_clan_file (char *clanfile)
{
CClanData *clan;
FILE *fp;
char *pLine;
clan = new CClanData;
BOOL bFound = FALSE;
if ((fp = fopen (FileTable.MakeName (SD_CLAN_DIR, clanfile), "r"))) {
bFound = TRUE;
for (;;) {
char letter;
char *word;
pLine = fread_line (fp);
letter = *pLine++;
if (letter == '*')
continue;
if (letter != '#') {
bug ("Load_clan_file: # not found.");
break;
}
word = ParseWord (pLine);
if (! str_cmp (word, "CLAN")) {
clan->Read (fp);
break;
}
else if (! str_cmp (word, "END" ))
break;
else {
bug ("Load_clan_file: bad section: %s.", word);
break;
}
}
fclose (fp);
}
if (bFound) {
CRoomIndexData *storeroom;
ClanList.AddTail (clan);
if (clan->storeroom == 0
|| (storeroom = RoomTable.GetRoom (clan->storeroom)) == NULL) {
gpDoc->LogString ("Storeroom not found", LOG_BOOT);
return bFound;
}
CString Fname = FileTable.MakeName (SD_CLAN_DIR, clan->GetFilename ());
Fname += ".vault";
if ((fp = fopen (Fname, "r")) != NULL) {
int iNest;
CObjData *tobj;
gpDoc->LogString ("Loading clan storage room", LOG_BOOT);
rset_supermob (storeroom);
for (iNest = 0; iNest < MAX_NEST; iNest++)
rgObjNest [iNest] = NULL;
for (;;) {
char letter;
char *word;
pLine = fread_line (fp);
letter = *pLine++;
if (letter == '*')
continue;
if (letter != '#') {
bug ("Load_clan_vault: # char not found (%s).",
clan->GetName ());
break;
}
word = ParseWord (pLine);
if (! str_cmp (word, "OBJECT")) // Objects
fread_obj (supermob, fp, OS_CARRY);
else if (! str_cmp (word, "END" )) // Done
break;
else {
bug ("Load_clan_vault: bad section (%s).",
clan->GetName ());
break;
}
}
fclose (fp);
POSITION pos = supermob->GetHeadCarryPos ();
while (tobj = supermob->GetNextCarrying (pos)) {
obj_from_char (tobj);
obj_to_room (tobj, storeroom);
}
release_supermob ();
}
else gpDoc->LogString ("Cannot open clan vault", LOG_BOOT);
}
else delete clan;
return bFound;
}
// Save items in a clan storage room -Scryn & Thoric
void CClanData::SaveStoreroom (CCharacter *ch)
{
FILE *fp;
short templvl;
if (!ch) {
bug ("save_clan_storeroom: Null ch pointer!");
return;
}
CString FName = FileTable.MakeName (SD_CLAN_DIR, GetFilename ());
FName += ".vault";
if ((fp = fopen (FName, "w")) == NULL)
bug ("CClanData::SaveStoreroom: fopen: %s", NCCP FName);
else {
templvl = ch->GetLevel ();
ch->SetLevel (LEVEL_HERO); // make sure EQ doesn't get lost
if (! ch->GetInRoom ()->IsEmpty ())
fwrite_obj (ch->GetInRoom ()->GetContentList (), fp,
0, OS_CARRY);
fprintf (fp, "#END\n");
ch->SetLevel (templvl);
fclose (fp);
}
}
CCouncilData::~CCouncilData ()
{
delete filename;
}
CCouncilData *get_council (char *name)
{
CCouncilData *council;
for (council = first_council; council; council = council->GetNext ())
if (! str_cmp (name, council->name))
return council;
return NULL;
}
void write_council_list ()
{
CCouncilData *tcouncil;
FILE *fpout;
fpout = fopen (FileTable.GetName (SM_COUNCIL_LIST), "w");
if (!fpout) {
bug ("FATAL: cannot open council.lst for writing!\n\r", 0);
return;
}
for (tcouncil = first_council; tcouncil; tcouncil = tcouncil->GetNext ())
fprintf (fpout, "%s\n", tcouncil->filename);
fprintf (fpout, "$\n");
fclose (fpout);
}
// Save a council's data to its data file
void save_council (CCouncilData *council)
{
if (! council) {
bug ("save_council: null council pointer!");
return;
}
if (! council->filename || council->filename [0] == '\0') {
bug ("save_council: %s has no filename", council->name);
return;
}
CString Fname = FileTable.MakeName (SD_COUNCIL_DIR, council->filename);
fclose (fpReserve);
FILE *fp = fopen (Fname, "w");
if (fp) {
fprintf (fp, "#COUNCIL\n");
fprintf (fp, "Name %s~\n", council->name);
fprintf (fp, "Filename %s~\n", council->filename);
fprintf (fp, "Description %s~\n", council->description);
fprintf (fp, "Head %s~\n", council->head);
fprintf (fp, "Members %d\n", council->m_Members);
fprintf (fp, "Board %d\n", council->board);
fprintf (fp, "Meeting %d\n", council->meeting);
fprintf (fp, "Powers %s~\n", council->powers);
fprintf (fp, "End\n\n");
fprintf (fp, "#END\n");
fclose (fp);
}
else bug ("save_council: Cannot create %s", NCCP Fname);
fpReserve = fopen (FileTable.GetName (SM_NULL_FILE), "r");
}
// Read in actual council data.
#if defined (KEY)
#undef KEY
#endif
#define KEY(literal,field,value) \
if (!str_cmp (word, literal)) { \
field = value; \
fMatch = TRUE; \
break; \
}
void fread_council (CCouncilData *council, FILE *fp)
{
char buf [MAX_STRING_LENGTH];
char *word, *pLine;
BOOL fMatch;
for (;;) {
fMatch = FALSE;
if (! feof (fp)) {
pLine = fread_line (fp);
word = ParseWord (pLine);
}
else word = "End";
switch (UPPER (word [0])) {
case '*':
fMatch = TRUE;
break;
case 'B':
KEY ("Board", council->board, ParseNumber (pLine));
break;
case 'D':
KEY ("Description", council->description, ParseString (pLine, fp));
break;
case 'E':
if (! str_cmp (word, "End")) {
if (!council->name)
council->name = STRALLOC ("");
if (!council->description)
council->description = STRALLOC ("");
if (!council->powers)
council->powers = STRALLOC ("");
return;
}
break;
case 'F':
KEY ("Filename", council->filename, ParseStringNohash (pLine, fp));
break;
case 'H':
KEY ("Head", council->head, ParseString (pLine, fp));
break;
case 'M':
KEY ("Members", council->m_Members, ParseNumber (pLine));
KEY ("Meeting", council->meeting, ParseNumber (pLine));
break;
case 'N':
KEY ("Name", council->name, ParseString (pLine, fp));
break;
case 'P':
KEY ("Powers", council->powers, ParseString (pLine, fp));
break;
}
if (! fMatch) {
sprintf (buf, "Fread_council: no match: %s", word);
bug (buf);
}
}
}
// Load a council file
BOOL load_council_file (char *councilfile)
{
CCouncilData *council;
FILE *fp;
char *pLine;
council = new CCouncilData;
BOOL found = FALSE;
if ((fp = fopen (FileTable.MakeName (SD_COUNCIL_DIR, councilfile), "r"))){
found = TRUE;
for (;;) {
char letter;
char *word;
pLine = fread_line (fp);
letter = *pLine++;
if (letter == '*')
continue;
if (letter != '#') {
bug ("Load_council_file: # not found.");
break;
}
word = ParseWord (pLine);
if (! str_cmp (word, "COUNCIL")) {
fread_council (council, fp);
break;
}
else
if (! str_cmp (word, "END"))
break;
else {
bug ("Load_council_file: bad section.");
break;
}
}
fclose (fp);
}
if (found)
LINK (council, first_council, last_council);
else
delete council;
return found;
}
// Load in all the council files.
void load_councils ()
{
FILE *fp;
char *pFname, *pLine;
first_council = NULL;
last_council = NULL;
gpDoc->LogString ("Loading councils...", LOG_BOOT);
fclose (fpReserve);
if (! (fp = fopen (FileTable.GetName (SM_COUNCIL_LIST), "r"))) {
perror (FileTable.GetName (SM_COUNCIL_LIST));
ThrowSmaugException (SE_COUNCIL);
}
while (! feof (fp)) {
pLine = fread_line (fp);
pFname = ParseLine (pLine);
if (pFname [0] == '$') then break;
gpDoc->LogString (pFname, LOG_BOOT);
if (!load_council_file (pFname))
bug ("Cannot load council file: %s", pFname);
}
fclose (fp);
fpReserve = fopen (FileTable.GetName (SM_NULL_FILE), "r");
}
void do_make (CCharacter *ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
CObjIndexData *pObjIndex;
CObjData *obj;
CClanData *clan;
int level;
if (ch->IsNpc () || !ch->GetPcData ()->GetClan ())
{
ch->SendText ("Huh?\n\r");
return;
}
clan = ch->GetPcData ()->GetClan ();
if (str_cmp (ch->GetName (), clan->leader)
&& str_cmp (ch->GetName (), clan->deity)
&& (clan->GetType () != CLAN_GUILD
|| str_cmp (ch->GetName (), clan->number1)))
{
ch->SendText ("Huh?\n\r");
return;
}
argument = one_argument (argument, arg);
if (arg[0] == '\0')
{
ch->SendText ("Make what?\n\r");
return;
}
pObjIndex = OIdxTable.GetObj (clan->clanobj1);
level = 40;
if (!pObjIndex || !is_name (arg, pObjIndex->GetName ()))
{
pObjIndex = OIdxTable.GetObj (clan->clanobj2);
level = 45;
}
if (!pObjIndex || !is_name (arg, pObjIndex->GetName ()))
{
pObjIndex = OIdxTable.GetObj (clan->clanobj3);
level = 50;
}
if (!pObjIndex || !is_name (arg, pObjIndex->GetName ()))
{
ch->SendText ("You don't know how to make that.\n\r");
return;
}
obj = create_object (pObjIndex, level);
obj->SetClanObject ();
if (obj->CanWear (ITEM_TAKE))
obj = obj_to_char (obj, ch);
else
obj = obj_to_room (obj, ch->GetInRoom ());
act (AT_MAGIC, "$n makes $p!", ch, obj, NULL, TO_ROOM);
act (AT_MAGIC, "You make $p!", ch, obj, NULL, TO_CHAR);
return;
}
void do_induct (CCharacter *ch, char *argument)
{
char arg [MAX_INPUT_LENGTH];
CCharacter *victim;
pc_data &Pc = *ch->GetPcData ();
if (! &Pc || ch->IsNpc () || ! Pc.GetClan ()) {
ch->SendText ("Huh?\n\r");
return;
}
CClanData *pClan = Pc.GetClan ();
if ((Pc.GetBestowments () && is_name ("induct", Pc.GetBestowments ()))
|| !str_cmp (ch->GetName (), pClan->deity)
|| !str_cmp (ch->GetName (), pClan->leader)
|| !str_cmp (ch->GetName (), pClan->number1)
|| !str_cmp (ch->GetName (), pClan->number2))
;
else {
ch->SendText ("Huh?\n\r");
return;
}
argument = one_argument (argument, arg);
if (arg [0] == '\0') {
ch->SendText ("Induct whom?\n\r");
return;
}
if ((victim = get_char_room (ch, arg)) == NULL) {
ch->SendText ("That player is not here.\n\r");
return;
}
if (victim->IsNpc ()) {
ch->SendText ("Not on NPC's.\n\r");
return;
}
if (pClan->GetType () == CLAN_GUILD) {
if (victim->GetClass () != pClan->m_Class) {
ch->SendText ("This player's will is not in accordance with "
"your guild.\n\r");
return;
}
} else {
if (victim->GetLevel () < 10) {
ch->SendText ("This player is not worthy of joining yet.\n\r");
return;
}
if (victim->GetLevel () > ch->GetLevel ()) {
ch->SendText ("This player is too powerful for you to induct.\n\r");
return;
}
}
if (victim->GetPcData ()->GetClan ()) {
if (victim->GetPcData ()->GetClan ()->GetType () == CLAN_ORDER) {
if (victim->GetPcData ()->GetClan () == pClan)
ch->SendText ("This player already belongs to your order!\n\r");
else
ch->SendText ("This player already belongs to an order!\n\r");
return;
}
else if (victim->GetPcData ()->GetClan ()->GetType () == CLAN_GUILD) {
if (victim->GetPcData ()->GetClan () == pClan)
ch->SendText ("This player already belongs to your guild!\n\r");
else
ch->SendText ("This player already belongs to a guild!\n\r");
return;
} else {
if (victim->GetPcData ()->GetClan () == pClan)
ch->SendText ("This player already belongs to your clan!\n\r");
else
ch->SendText ("This player already belongs to a clan!\n\r");
return;
}
}
pClan->AddMembers (1);
if (pClan->GetType () != CLAN_ORDER && pClan->GetType () != CLAN_GUILD)
victim->SetSpeaks (LanguageTable.GetClan ());
if (pClan->GetType () != CLAN_NOKILL && pClan->GetType () != CLAN_ORDER
&& pClan->GetType () != CLAN_GUILD)
victim->SetPkiller ();
if (pClan->GetType () == CLAN_GUILD) {
for (int sn = 0; sn < SkillTable.GetCount (); sn++) {
if (SkillTable.GetGuild (sn) == pClan->m_Class &&
SkillTable.GetName (sn) != NULL) {
victim->GetPcData ()->learned [sn] =
SkillTable.GetClassAdept (sn, victim->GetClass ());
victim->SendTextf ("%s instructs you in the ways of %s.\n\r",
ch->GetName (), SkillTable.GetName (sn));
}
}
}
victim->GetPcData ()->SetClan (pClan);
STRFREE (victim->GetPcData ()->GetClanName ());
victim->GetPcData ()->SetClanName (QUICKLINK (pClan->GetName ()));
act (AT_MAGIC, "You induct $N into $t", ch, pClan->GetName (), victim, TO_CHAR);
act (AT_MAGIC, "$n inducts $N into $t", ch, pClan->GetName (), victim, TO_NOTVICT);
act (AT_MAGIC, "$n inducts you into $t", ch, pClan->GetName (), victim, TO_VICT);
save_char_obj (victim);
}
void do_council_induct (CCharacter *ch, char *argument)
{
char arg [MAX_INPUT_LENGTH];
CCharacter *victim;
CCouncilData *council;
if (ch->IsNpc () || ! ch->GetPcData ()->council) {
ch->SendText ("Huh?\n\r");
return;
}
council = ch->GetPcData ()->council;
if (str_cmp (ch->GetName (), council->head)) {
ch->SendText ("Huh?\n\r");
return;
}
argument = one_argument (argument, arg);
if (arg [0] == '\0') {
ch->SendText ("Induct whom into your council?\n\r");
return;
}
if ((victim = get_char_room (ch, arg)) == NULL) {
ch->SendText ("That player is not here.\n\r");
return;
}
if (victim->IsNpc ()) {
ch->SendText ("Not on NPC's.\n\r");
return;
}
if (victim->GetPcData ()->council) {
ch->SendText ("This player already belongs to a council!\n\r");
return;
}
council->AddMembers (1);
victim->GetPcData ()->council = council;
STRFREE (victim->GetPcData ()->GetCouncilName ());
victim->GetPcData ()->SetCouncilName (QUICKLINK (council->name));
act (AT_MAGIC, "You induct $N into $t", ch, council->name, victim, TO_CHAR);
act (AT_MAGIC, "$n inducts $N into $t", ch, council->name, victim, TO_ROOM);
act (AT_MAGIC, "$n inducts you into $t", ch, council->name, victim, TO_VICT);
save_char_obj (victim);
save_council (council);
}
void do_outcast (CCharacter *ch, char *argument)
{
char arg [MAX_INPUT_LENGTH];
char buf [MAX_STRING_LENGTH];
CCharacter *victim;
pc_data &Pc = *ch->GetPcData ();
if (! &Pc || ch->IsNpc () || ! Pc.GetClan ()) {
ch->SendText ("Huh?\n\r");
return;
}
CClanData *pClan = Pc.GetClan ();
if ((Pc.GetBestowments () && is_name ("outcast", Pc.GetBestowments ()))
|| !str_cmp (ch->GetName (), pClan->deity )
|| !str_cmp (ch->GetName (), pClan->leader )
|| !str_cmp (ch->GetName (), pClan->number1)
|| !str_cmp (ch->GetName (), pClan->number2))
;
else {
ch->SendText ("Huh?\n\r");
return;
}
argument = one_argument (argument, arg);
if (arg [0] == '\0') {
ch->SendText ("Outcast whom?\n\r");
return;
}
if ((victim = get_char_room (ch, arg)) == NULL) {
ch->SendText ("That player is not here.\n\r");
return;
}
if (victim->IsNpc ()) {
ch->SendText ("Not on NPC's.\n\r");
return;
}
if (victim == ch) {
if (ch->GetPcData ()->GetClan ()->GetType () == CLAN_ORDER) {
ch->SendText ("Kick yourself out of your own order?\n\r");
return;
}
else if (ch->GetPcData ()->GetClan ()->GetType () == CLAN_GUILD) {
ch->SendText ("Kick yourself out of your own guild?\n\r");
return;
} else {
ch->SendText ("Kick yourself out of your own clan?\n\r");
return;
}
}
if (victim->GetLevel () > ch->GetLevel ()) {
ch->SendText ("This player is too powerful for you to outcast.\n\r");
return;
}
if (victim->GetPcData ()->GetClan () != ch->GetPcData ()->GetClan ()) {
if (ch->GetPcData ()->GetClan ()->GetType () == CLAN_ORDER) {
ch->SendText ("This player does not belong to your order!\n\r");
return;
}
else if (ch->GetPcData ()->GetClan ()->GetType () == CLAN_GUILD) {
ch->SendText ("This player does not belong to your guild!\n\r");
return;
} else {
ch->SendText ("This player does not belong to your clan!\n\r");
return;
}
}
if (pClan->GetType () == CLAN_GUILD) {
for (int sn = 0; sn < SkillTable.GetCount (); sn++)
if (SkillTable.GetGuild (sn) ==
victim->GetPcData ()->GetClan ()->m_Class
&& SkillTable.GetName (sn) != NULL) {
victim->GetPcData ()->learned [sn] = 0;
ch->SendTextf ("You forget the ways of %s.\n\r",
SkillTable.GetName (sn));
}
}
if (victim->IsSpeaking (LanguageTable.GetClan ()))
victim->SetSpeaking (LanguageTable.GetCommon ());
victim->ClrSpeaks (LanguageTable.GetClan ());
pClan->AddMembers (-1);
if (!str_cmp (victim->GetName (), ch->GetPcData ()->GetClan ()->number1)){
STRFREE (ch->GetPcData ()->GetClan ()->number1);
ch->GetPcData ()->GetClan ()->number1 = STRALLOC ("");
}
if (!str_cmp (victim->GetName (), ch->GetPcData ()->GetClan ()->number2)){
STRFREE (ch->GetPcData ()->GetClan ()->number2);
ch->GetPcData ()->GetClan ()->number2 = STRALLOC ("");
}
victim->GetPcData ()->SetClan (NULL);
STRFREE (victim->GetPcData ()->GetClanName ());
victim->GetPcData ()->SetClanName (STRALLOC (""));
act (AT_MAGIC, "You outcast $N from $t", ch, pClan->GetName (), victim, TO_CHAR);
act (AT_MAGIC, "$n outcasts $N from $t", ch, pClan->GetName (), victim, TO_ROOM);
act (AT_MAGIC, "$n outcasts you from $t", ch, pClan->GetName (), victim, TO_VICT);
if (pClan->GetType () != CLAN_GUILD) {
sprintf (buf, "%s has been outcast from %s!", victim->GetName (),
pClan->GetName ());
echo_to_all (AT_MAGIC, buf, ECHOTAR_ALL);
}
save_char_obj (victim); // clan gets saved when pfile is saved
}
void do_council_outcast (CCharacter *ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
CCharacter *victim;
CCouncilData *council;
if (ch->IsNpc () || ! ch->GetPcData ()->council) {
ch->SendText ("Huh?\n\r");
return;
}
council = ch->GetPcData ()->council;
if (str_cmp (ch->GetName (), council->head)) {
ch->SendText ("Huh?\n\r");
return;
}
argument = one_argument (argument, arg);
if (arg [0] == '\0') {
ch->SendText ("Outcast whom from your council?\n\r");
return;
}
if ((victim = get_char_room (ch, arg)) == NULL) {
ch->SendText ("That player is not here.\n\r");
return;
}
if (victim->IsNpc ()) {
ch->SendText ("Not on NPC's.\n\r");
return;
}
if (victim == ch) {
ch->SendText ("Kick yourself out of your own council?\n\r");
return;
}
if (victim->GetPcData ()->council != ch->GetPcData ()->council) {
ch->SendText ("This player does not belong to your council!\n\r");
return;
}
council->AddMembers (-1);
victim->GetPcData ()->council = NULL;
STRFREE (victim->GetPcData ()->GetCouncilName ());
victim->GetPcData ()->SetCouncilName (STRALLOC (""));
act (AT_MAGIC, "You outcast $N from $t", ch, council->name, victim, TO_CHAR);
act (AT_MAGIC, "$n outcasts $N from $t", ch, council->name, victim, TO_ROOM);
act (AT_MAGIC, "$n outcasts you from $t", ch, council->name, victim, TO_VICT);
save_char_obj (victim);
save_council (council);
}
void do_setcouncil (CCharacter *ch, char *argument)
{
char arg1 [MAX_INPUT_LENGTH];
char arg2 [MAX_INPUT_LENGTH];
if (ch->IsNpc ()) {
ch->SendText ("Huh?\n\r");
return;
}
argument = one_argument (argument, arg1);
argument = one_argument (argument, arg2);
if (arg1 [0] == '\0') {
ch->SendText ("Usage: setcouncil <council> <field> <deity|leader"
"|number1|number2> <player>\n\r");
ch->SendText ("\n\rField being one of:\n\r");
ch->SendText (" head members board meeting\n\r");
if (ch->GetTrustLevel () >= LEVEL_GOD)
ch->SendText (" name filename desc\n\r");
if (ch->GetTrustLevel () >= LEVEL_SUB_IMPLEM)
ch->SendText (" powers\n\r");
return;
}
CCouncilData *council = get_council (arg1);
if (! council) {
ch->SendText ("No such council.\n\r");
return;
}
if (! strcmp (arg2, "head")) {
STRFREE (council->head);
council->head = STRALLOC (argument);
ch->SendText ("Done.\n\r");
save_council (council);
return;
}
if (! strcmp (arg2, "board")) {
council->board = atoi (argument);
ch->SendText ("Done.\n\r");
save_council (council);
return;
}
if (! strcmp (arg2, "members")) {
council->SetMembers (atoi (argument));
ch->SendText ("Done.\n\r");
save_council (council);
return;
}
if (! strcmp (arg2, "meeting")) {
council->meeting = atoi (argument);
ch->SendText ("Done.\n\r");
save_council (council);
return;
}
if (ch->GetTrustLevel () < LEVEL_GOD) {
do_setcouncil (ch, "");
return;
}
if (! strcmp (arg2, "name")) {
STRFREE (council->name);
council->name = STRALLOC (argument);
ch->SendText ("Done.\n\r");
save_council (council);
return;
}
if (! strcmp (arg2, "filename")) {
CString OldName =
FileTable.MakeName (SD_COUNCIL_DIR, council->filename);
CString NewName = FileTable.MakeName (SD_COUNCIL_DIR, argument);
if (FileTable.Exists (NewName)) then
remove (NewName);
if (FileTable.Exists (OldName))
rename (OldName, NewName);
delete council->filename;
council->filename = str_dup (argument);
ch->SendText ("Done.\n\r");
save_council (council);
write_council_list ();
return;
}
if (! strcmp (arg2, "desc")) {
STRFREE (council->description);
council->description = STRALLOC (argument);
ch->SendText ("Done.\n\r");
save_council (council);
return;
}
if (ch->GetTrustLevel () < LEVEL_SUB_IMPLEM) {
do_setcouncil (ch, "");
return;
}
if (! strcmp (arg2, "powers")) {
STRFREE (council->powers);
council->powers = STRALLOC (argument);
ch->SendText ("Done.\n\r");
save_council (council);
return;
}
do_setcouncil (ch, "");
}
void do_showcouncil (CCharacter *ch, char *argument)
{
CCouncilData *council;
if (ch->IsNpc ()) {
ch->SendText ("Huh?\n\r");
return;
}
if (argument [0] == '\0') {
ch->SendText ("Usage: showcouncil <council>\n\r");
return;
}
council = get_council (argument);
if (! council) {
ch->SendText ("No such council.\n\r");
return;
}
ch->SendTextf ("Council : %s\n\rFilename: %s\n\r",
council->name, council->filename);
ch->SendTextf ("Description: %s\n\rHead: %s\n\rMembers: %3d\n\r",
council->description, council->head, council->GetMembers ());
ch->SendTextf ("Board: %5d\n\rMeeting: %5d\n\rPowers: %s\n\r",
council->board, council->meeting, council->powers);
}
void do_makecouncil (CCharacter *ch, char *argument)
{
if (! argument || argument [0] == '\0') {
ch->SendText ("Usage: makecouncil <council name>\n\r");
return;
}
if (get_council (argument)) {
ch->SendTextf ("%s Already exists.\n\r", argument);
return;
}
CCouncilData *co = new CCouncilData;
CString Fname;
Fname.Format ("%s.council", argument);
co->filename = str_dup (Fname);
LINK (co, first_council, last_council);
co->name = STRALLOC (argument);
co->head = STRALLOC ("");
co->powers = STRALLOC ("");
save_council (co);
write_council_list ();
}
void do_clans (CCharacter *ch, char *argument)
{
int count = 0;
// Switched deadly clan mobkills/mobdeaths to pkills -- Blodkai
set_char_color (AT_BLOOD, ch);
ch->SendText ("\n\rClan Deity Leader "
"Pkills\n\r");
POSITION pos = ClanList.GetHeadPosition ();
while (pos) {
CClanData &Cl = *ClanList.GetNext (pos);
if (Cl.GetType () == CLAN_PLAIN) {
set_char_color (AT_NOTE, ch);
ch->SendTextf ("%-14s %-14s %-14s", Cl.GetName (), Cl.deity,
Cl.leader);
set_char_color (AT_BLOOD, ch);
ch->SendTextf (" %7d\n\r", Cl.pkills);
++count;
}
}
if (! count) {
set_char_color (AT_BLOOD, ch);
ch->SendText ("There are no clans currently formed.\n\r");
}
}
void do_orders (CCharacter *ch, char *argument)
{
int count = 0;
// Added displaying of mkills and mdeaths - Brittany
set_char_color (AT_NOTE, ch);
ch->SendText ("Order Deity Leader Mkills Mdeaths\n\r");
POSITION pos = ClanList.GetHeadPosition ();
while (pos) {
CClanData &Ord = *ClanList.GetNext (pos);
if (Ord.GetType () == CLAN_ORDER) {
ch->SendTextf ("%-16s %-14s %-14s %5d %5d\n\r",
Ord.GetName (), Ord.deity, Ord.leader,
Ord.mkills, Ord.mdeaths);
count++;
}
}
if (! count)
ch->SendText ("There are no Orders currently formed.\n\r");
}
void do_councils (CCharacter *ch, char *argument)
{
CCouncilData *council;
if (! first_council) {
ch->SendText ("There are no councils currently formed.\n\r");
return;
}
set_char_color (AT_NOTE, ch);
ch->SendText ("Name Head\n\r");
for (council = first_council; council; council = council->GetNext ())
ch->SendTextf ("%-21s %-14s\n\r", council->name, council->head);
}
void do_guilds (CCharacter *ch, char *argument)
{
int count = 0;
// Added guild mobkills/mobdeaths -- Blodkai
set_char_color (AT_NOTE, ch);
ch->SendText ("\n\rGuild Leader Mkills Mdeaths\n\r");
POSITION pos = ClanList.GetHeadPosition ();
while (pos) {
CClanData &Gui = *ClanList.GetNext (pos);
if (Gui.GetType () == CLAN_GUILD) {
set_char_color (AT_YELLOW, ch);
ch->SendTextf ("%-20s %-14s %-6d %6d\n\r",
Gui.GetName (), Gui.leader, Gui.mkills, Gui.mdeaths);
++count;
}
}
set_char_color (AT_NOTE, ch);
if (! count)
ch->SendText ("There are no Guilds currently formed.\n\r");
else
ch->SendTextf ("%d guilds found.\n\r", count);
}
void do_shove (CCharacter *ch, char *argument)
{
char arg [MAX_INPUT_LENGTH];
char arg2 [MAX_INPUT_LENGTH];
int exit_dir;
CExitData *pexit;
CCharacter *victim;
BOOL nogo;
CRoomIndexData *to_room;
argument = one_argument (argument, arg);
argument = one_argument (argument, arg2);
if (ch->IsNpc () || ! ch->IsPkiller ()) {
ch->SendText ("Only deadly characters can shove.\n\r");
return;
}
if (arg [0] == '\0') {
ch->SendText ("Shove whom?\n\r");
return;
}
if ((victim = get_char_room (ch, arg)) == NULL) {
ch->SendText ("They aren't here.\n\r");
return;
}
if (victim == ch) {
ch->SendText ("You shove yourself around, to no avail.\n\r");
return;
}
if (victim->IsNpc () || ! victim->IsPkiller ()) {
ch->SendText ("You can only shove deadly characters.\n\r");
return;
}
if (ch->GetLevel () - victim->GetLevel () > 5
|| victim->GetLevel () - ch->GetLevel () > 5) {
ch->SendText ("There is too great an experience difference for "
"you to even bother.\n\r");
return;
}
if ((victim->GetPosition ()) != POS_STANDING) {
act (AT_PLAIN, "$N isn't standing up.", ch, NULL, victim, TO_CHAR);
return;
}
if (arg2 [0] == '\0') {
ch->SendText ("Shove them in which direction?\n\r");
return;
}
exit_dir = get_dir (arg2);
if (victim->GetInRoom ()->IsSafe ()
&& get_timer (victim, TIMER_SHOVEDRAG) <= 0) {
ch->SendText ("That character cannot be shoved right now.\n\r");
return;
}
victim->SetPosition (POS_SHOVE);
nogo = FALSE;
if ((pexit = get_exit (ch->GetInRoom (), exit_dir)) == NULL)
nogo = TRUE;
else if (pexit->IsClosed () && (! victim->CanPass ()
|| pexit->IsNoPass ()))
nogo = TRUE;
if (nogo) {
ch->SendText ("There's no exit in that direction.\n\r");
victim->SetPosition (POS_STANDING);
return;
}
to_room = pexit->GetToRoom ();
if (to_room->IsDeathRoom ()) {
ch->SendText ("You cannot shove someone into a death trap.\n\r");
victim->SetPosition (POS_STANDING);
return;
}
if (ch->GetInRoom ()->GetArea () != to_room->GetArea ()
&& !in_hard_range (victim, to_room->GetArea ())) {
ch->SendText ("That character cannot enter that area.\n\r");
victim->SetPosition (POS_STANDING);
return;
}
// Check for class, assign percentage based on that.
int chance = ClassTable.GetShoveDragPercent (ch->GetClass ());
// Add 3 points to chance for every str point above 15, subtract for
// below 15
chance += ((ch->GetCurrentStrength () - 15) * 3);
chance += (ch->GetLevel () - victim->GetLevel ());
chance += RaceTable.GetShoveDragModifier (ch->GetRace ());
if (chance < number_percent ()) {
ch->SendText ("You failed.\n\r");
victim->SetPosition (POS_STANDING);
return;
}
act (AT_ACTION, "You shove $M.", ch, NULL, victim, TO_CHAR);
act (AT_ACTION, "$n shoves you.", ch, NULL, victim, TO_VICT);
move_char (victim, get_exit (ch->GetInRoom (),exit_dir), 0);
if (! char_died (victim))
victim->SetPosition (POS_STANDING);
WAIT_STATE (ch, 12);
// Remove protection from shove/drag if char shoves -- Blodkai
if (ch->GetInRoom ()->IsSafe ()
&& get_timer (ch, TIMER_SHOVEDRAG) <= 0)
add_timer (ch, TIMER_SHOVEDRAG, 10, NULL, 0);
}
void do_drag (CCharacter *ch, char *argument)
{
char arg [MAX_INPUT_LENGTH];
char arg2 [MAX_INPUT_LENGTH];
int exit_dir;
CCharacter *victim;
CExitData *pexit;
CRoomIndexData *to_room;
BOOL nogo;
argument = one_argument (argument, arg);
argument = one_argument (argument, arg2);
if (ch->IsNpc () || ! ch->IsPkiller ()) {
ch->SendText ("Only deadly characters can drag.\n\r");
return;
}
if (arg [0] == '\0') {
ch->SendText ("Drag whom?\n\r");
return;
}
if ((victim = get_char_room (ch, arg)) == NULL) {
ch->SendText ("They aren't here.\n\r");
return;
}
if (victim == ch) {
ch->SendText ("You take yourself by the scruff of your neck, but"
" go nowhere.\n\r");
return;
}
if (victim->IsNpc () || ! victim->IsPkiller ()) {
ch->SendText ("You can only drag deadly characters.\n\r");
return;
}
if (victim->GetFightData ()) {
ch->SendText ("You try, but can't get close enough.\n\r");
return;
}
if (arg2 [0] == '\0') {
ch->SendText ("Drag them in which direction?\n\r");
return;
}
if (ch->GetLevel () - victim->GetLevel () > 5
|| victim->GetLevel () - ch->GetLevel () > 5) {
ch->SendText ("There is too great an experience difference for you to even bother.\n\r");
return;
}
exit_dir = get_dir (arg2);
if (victim->GetInRoom ()->IsSafe ()
&& get_timer (victim, TIMER_SHOVEDRAG) <= 0) {
ch->SendText ("That character cannot be dragged right now.\n\r");
return;
}
nogo = FALSE;
if ((pexit = get_exit (ch->GetInRoom (), exit_dir)) == NULL)
nogo = TRUE;
else
if (pexit->IsClosed () && (! victim->CanPass ()
|| pexit->IsNoPass ()))
nogo = TRUE;
if (nogo) {
ch->SendText ("There's no exit in that direction.\n\r");
return;
}
to_room = pexit->GetToRoom ();
if (to_room->IsDeathRoom ()) {
ch->SendText ("You cannot drag someone into a death trap.\n\r");
return;
}
if (ch->GetInRoom ()->GetArea () != to_room->GetArea ()
&& !in_hard_range (victim, to_room->GetArea ())) {
ch->SendText ("That character cannot enter that area.\n\r");
victim->SetPosition (POS_STANDING);
return;
}
// Check for class, assign percentage based on that.
int chance = ClassTable.GetShoveDragPercent (ch->GetClass ());
// Add 3 points to chance for every str point above 15, subtract for
// below 15
chance += ((ch->GetCurrentStrength () - 15) * 3);
chance += (ch->GetLevel () - victim->GetLevel ());
chance += RaceTable.GetShoveDragModifier (ch->GetRace ());
// sprintf (buf, "Drag percentage of %s = %d", ch->GetName (), chance);
// act (AT_ACTION, buf, ch, NULL, NULL, TO_ROOM);
if (chance < number_percent ()) {
ch->SendText ("You failed.\n\r");
victim->SetPosition (POS_STANDING);
return;
}
if (victim->GetPosition () < POS_STANDING) {
short temp = victim->GetPosition ();
victim->SetPosition (POS_DRAG);
act (AT_ACTION, "You drag $M into the next room.", ch, NULL, victim, TO_CHAR);
act (AT_ACTION, "$n grabs your hair and drags you.", ch, NULL, victim, TO_VICT);
move_char (victim, get_exit (ch->GetInRoom (),exit_dir), 0);
if (!char_died (victim))
victim->SetPosition (temp);
// Move ch to the room too.. they are doing dragging - Scryn
move_char (ch, get_exit (ch->GetInRoom (),exit_dir), 0);
WAIT_STATE (ch, 12);
return;
}
ch->SendText ("You cannot do that to someone who is standing.\n\r");
}
void CClanList::Write ()
{
FILE *fp;
CString Fname = FileTable.GetName (SM_CLAN_LIST);
if (! (fp = fopen (Fname, "w"))) {
bug ("ClanList::Write: cannot open %s for writing!\n\r", NCCP Fname);
return;
}
POSITION pos = GetHeadPosition ();
while (pos)
fprintf (fp, "%s\n", GetNext (pos)->GetFilename ());
fprintf (fp, "$\n");
fclose (fp);
}
char* CClanList::GetTypeName (ClanTypes type)
{
static char *CTnames [] = { "Clan", "VAMPIRE", "WARRIOR", "DRUID",
"MAGE", "CELTIC", "THIEF", "CLERIC",
"UNDEAD", "CHAOTIC", "NEUTRAL", "LAWFUL",
"NOKILL", "Order", "Guild", "ALL" };
return CTnames [type];
}
// Get pointer to clan structure from clan name & type.
CClanData *CClanList::Find (const char *name, ClanTypes type)
{
POSITION pos = ClanList.GetHeadPosition ();
while (pos) {
CClanData *clan = ClanList.GetNext (pos);
if ((type == CLAN_ALL || clan->GetType () == type)
&& ! stricmp (clan->GetName (), name))
return clan;
}
return NULL;
}
void CClanList::Remove (CClanData* clan)
{
POSITION pos = CPtrList::Find (clan);
if (pos)
RemoveAt (pos);
}
void CClanList::RemoveAll ()
{
while (! IsEmpty ())
delete (CClanData*) RemoveTail ();
CPtrList::RemoveAll ();
}