#include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "mud.h" bool quit_flag = FALSE; void clear_tracks (CHAR_DATA * ch) { ROOM_DATA *rid; int hash; TRACK_DATA *tr; TRACK_DATA *tr_n; TRACK_DATA *tt; if (!ch) return; if (IS_PLAYER(ch)) return; if (notracks) return; for (hash = 0; hash < HASH_MAX; hash++) { for (rid = room_hash[hash]; rid != NULL; rid = rid->next) { if (rid->tracks && rid->tracks->who == ch) { tt = rid->tracks; rid->tracks = rid->tracks->next; free_m (tt); continue; } for (tr = rid->tracks; tr != NULL; tr = tr_n) { tr_n = tr->next; if (tr_n && tr_n->who == ch) { tt = tr->next; tr->next = tr_n->next; free_m (tt); break; } } } } return; } void do_busy (CHAR_DATA * ch, char *argy) { DEFINE_COMMAND ("busy", do_busy, POSITION_DEAD, MAX_LEVEL, LOG_NORMAL, "Allows you to enter busy mode.") if (IS_MOB (ch)) return; if (ch->pcdata->quiet != 2) ch->pcdata->quiet = 2; else ch->pcdata->quiet = 0; if (ch->pcdata->quiet == 0) send_to_char ("You are no longer in busy mode! Prepare yourself!\n\r", ch); if (ch->pcdata->quiet == 2) send_to_char ("You have entered busy mode.\n\r", ch); return; } /* +---------------------------------------------------------------------+ */ /* Center a "argy" in "i" length */ /* +---------------------------------------------------------------------+ */ char * center_argument (int i, char *argy) { int j = 0; int prespace = 0; int afterspace = 0; char prebuff[100]; char afterbuff[100]; static char general_buff[SML_LENGTH]; if (strlen(argy) > i) return " "; prebuff[0] = '\0'; afterbuff[0] = '\0'; general_buff[0] = '\0'; prespace = ((i - (strlen(argy)))/2); for (j = 0;j < prespace;j++) { strcat(prebuff, " "); } afterspace = (i - (strlen(prebuff) + strlen(argy))); for (j = 0;j < afterspace;j++) { strcat(afterbuff, " "); } sprintf(general_buff, "%s%s%s", prebuff, argy, afterbuff); return general_buff; } /* +---------------------------------------------------------------------+ */ /* Check for looping aliases */ /* +---------------------------------------------------------------------+ */ bool check_alias_loop (char *aliasname, char *s) { if (!isalpha (*s) && !isdigit (*s)) while (*s && !isalpha (*s) && !isdigit (*s)) s++; if (*s && !str_cmp (first (s), aliasname)) return FALSE; while (*s != '\0') { if (!str_cmp (first (s), aliasname)) return FALSE; while (*s && *s != '*') s++; if (*s == '*') s++; } return TRUE; } /* +---------------------------------------------------------------------+ */ /* Check for right char values in alias expansion */ /* +---------------------------------------------------------------------+ */ bool alias_expansion_check (char *arg) { if (arg == NULL) return FALSE; for (; *arg != '\0'; arg++) { if (!isdigit (*arg) && !isalpha (*arg) && *arg != '*' && *arg != ' ' && *arg != '\'' && *arg != '$' && *arg != '%') return FALSE; } return TRUE; } void do_alias (CHAR_DATA * ch, char *argy) { int k; int free_slot = 0; char arg[SML_LENGTH]; DEFINE_COMMAND ("alias", do_alias, POSITION_DEAD, 0, LOG_NORMAL, "Allows you to set up an alias expansion, or delete/modify existing aliases.") if (!ch || IS_MOB (ch)) return; /* +---------------------------------------------------------------------+ */ /* Check for free slots */ /* +---------------------------------------------------------------------+ */ for (k = 0; k < MAXALIAS; k++) { if (!ch->pcdata->alias[k] || ch->pcdata->alias[k][0] == '\0' || !ch->pcdata->aliasname[k] || ch->pcdata->aliasname[k][0] == '\0') { free_slot++; } } /* +---------------------------------------------------------------------+ */ /* Display current aliases when argy == '\0' */ /* +---------------------------------------------------------------------+ */ if (!argy || argy[0] == '\0') { if (free_slot == MAXALIAS) { send_to_char ("\n\rYou have no aliases, to set one up, use: alias \x1B[1;30m<\x1B[0mname\x1B[1;30m> <\x1B[0mexpansion\x1B[1;30m>\x1B[0m.\n\r", ch); return; } hugebuf_o[0] = '\0'; sprintf(hugebuf_o, "\n\r\x1B[1;30m+-----+----------+------------------------------------------------------------+\n\r"); sprintf(hugebuf_o + strlen(hugebuf_o), "|\x1B[0m Num\x1B[1;30m |\x1B[0m Alias \x1B[1;30m | \x1B[0m Expansion \x1B[1;30m |\n\r"); sprintf(hugebuf_o + strlen(hugebuf_o), "+-----+----------+------------------------------------------------------------+\n\r"); for (k = 0; k < MAXALIAS; k++) { if (ch->pcdata->alias[k] && ch->pcdata->aliasname[k]) { char *temp_char; /* +-------------------------------------------+ */ /* | Change all the ~ chars into * for sprintf | */ /* +-------------------------------------------+ */ for (temp_char = ch->pcdata->alias[k]; *temp_char != '\0'; temp_char++) { if (*temp_char == '~') *temp_char = '*'; } sprintf(hugebuf_o + strlen(hugebuf_o), "| \x1B[1;31m%2d\x1B[1;30m ", k + 1); sprintf(hugebuf_o + strlen(hugebuf_o), "| \x1B[1;32m%s\x1B[1;30m ", center_argument(8, ch->pcdata->aliasname[k])); sprintf(hugebuf_o + strlen(hugebuf_o), "| \x1B[1;37m%s\x1B[1;30m |\n\r", center_argument(58, ch->pcdata->alias[k])); /* +------------------------------------+ */ /* | Change back all the * chars into ~ | */ /* +------------------------------------+ */ for (temp_char = ch->pcdata->alias[k]; *temp_char != '\0'; temp_char++) { if (*temp_char == '*') *temp_char = '~'; } } } sprintf(hugebuf_o + strlen(hugebuf_o), "+-----+----------+------------------------------------------------------------+\x1B[0m\n\r"); page_to_char (hugebuf_o, ch); return; } /* +---------------------------------------------------------------------+ */ /* Check if second argument = '\0' to delete existing aliases */ /* +---------------------------------------------------------------------+ */ argy = one_argy (argy, arg); if (!str_cmp (arg, "delete")) { char general_buff[1000]; if (!is_number(argy)) { send_to_char("\n\rSyntax: alias delete \x1B[1;30m<\x1B[0mnumber\x1B[1;30m>\x1B[0m.\n\r", ch); return; } if (atoi(argy) > 0 && atoi(argy) <= MAXALIAS) { if (ch->pcdata->aliasname[atoi(argy) - 1]) { sprintf (general_buff, "\x1B[1;34m[\x1B[37mDeleted alias #%d\x1B[34m]\x1B[0m\n\r", atoi(argy)); send_to_char (general_buff, ch); free_string (ch->pcdata->aliasname[atoi(argy) - 1]); free_string (ch->pcdata->alias[atoi(argy) - 1]); ch->pcdata->aliasname[atoi(argy) - 1] = NULL; ch->pcdata->alias[atoi(argy) - 1] = NULL; return; } } sprintf (general_buff, "\x1B[1;34m[\x1B[37mAlias not found\x1B[34m]\x1B[0m\n\r"); send_to_char (general_buff, ch); return; } /* +---------------------------------------------------------------------+ */ /* Check if second argy == '\0' and first is number to list single alias */ /* +---------------------------------------------------------------------+ */ if (argy[0] == '\0' && is_number(arg)) { char general_buff[1000]; if ((atoi(arg) - 1) <= MAXALIAS && ch->pcdata->alias[atoi(arg) - 1] && ch->pcdata->aliasname[atoi(arg) - 1]) { char *temp_char; sprintf(general_buff, "\n\r\x1B[1;30m+-----+----------+------------------------------------------------------------+\n\r"); sprintf(general_buff + strlen(general_buff), "|\x1B[0m Num\x1B[1;30m |\x1B[0m Alias \x1B[1;30m | \x1B[0m Expansion \x1B[1;30m |\n\r"); sprintf(general_buff + strlen(general_buff), "+-----+----------+------------------------------------------------------------+\n\r"); /* +-------------------------------------------+ */ /* | Change all the ~ chars into * for sprintf | */ /* +-------------------------------------------+ */ for (temp_char = ch->pcdata->alias[atoi(arg) - 1]; *temp_char != '\0'; temp_char++) { if (*temp_char == '~') *temp_char = '*'; } sprintf(general_buff + strlen(general_buff), "| \x1B[1;31m%2d\x1B[1;30m ", atoi(arg)); sprintf(general_buff + strlen(general_buff), "| \x1B[1;32m%s\x1B[1;30m ", center_argument(8, ch->pcdata->aliasname[atoi(arg) - 1])); sprintf(general_buff + strlen(general_buff), "| \x1B[1;37m%s\x1B[1;30m |\n\r", center_argument(58, ch->pcdata->alias[atoi(arg) - 1])); /* +------------------------------------+ */ /* | Change back all the * chars into ~ | */ /* +------------------------------------+ */ for (temp_char = ch->pcdata->alias[atoi(arg) - 1]; *temp_char != '\0'; temp_char++) { if (*temp_char == '*') *temp_char = '~'; } sprintf(general_buff + strlen(general_buff), "+-----+----------+------------------------------------------------------------+\x1B[0m\n\r"); send_to_char (general_buff, ch); return; } sprintf (general_buff, "\x1B[1;34m[\x1B[37mAlias not found\x1B[34m]\x1B[0m\n\r"); send_to_char (general_buff, ch); return; } /* +---------------------------------------------------------------------+ */ /* Check if second argy == '\0' and first is letter to list single alias */ /* +---------------------------------------------------------------------+ */ if (argy[0] == '\0' && is_letter(arg)) { char general_buff[1000]; for (k = 0; k < MAXALIAS; k++) { if (ch->pcdata->aliasname[k] && !str_cmp (arg, ch->pcdata->aliasname[k])) { char *temp_char; sprintf(general_buff, "\n\r\x1B[1;30m+-----+----------+------------------------------------------------------------+\n\r"); sprintf(general_buff + strlen(general_buff), "|\x1B[0m Num\x1B[1;30m |\x1B[0m Alias \x1B[1;30m | \x1B[0m Expansion \x1B[1;30m |\n\r"); sprintf(general_buff + strlen(general_buff), "+-----+----------+------------------------------------------------------------+\n\r"); /* +-------------------------------------------+ */ /* | Change all the ~ chars into * for sprintf | */ /* +-------------------------------------------+ */ for (temp_char = ch->pcdata->alias[k]; *temp_char != '\0'; temp_char++) { if (*temp_char == '~') *temp_char = '*'; } sprintf(general_buff + strlen(general_buff), "| \x1B[1;31m%2d\x1B[1;30m ", k + 1); sprintf(general_buff + strlen(general_buff), "| \x1B[1;32m%s\x1B[1;30m ", center_argument(8, ch->pcdata->aliasname[k])); sprintf(general_buff + strlen(general_buff), "| \x1B[1;37m%s\x1B[1;30m |\n\r", center_argument(58, ch->pcdata->alias[k])); /* +------------------------------------+ */ /* | Change back all the * chars into ~ | */ /* +------------------------------------+ */ for (temp_char = ch->pcdata->alias[k]; *temp_char != '\0'; temp_char++) { if (*temp_char == '*') *temp_char = '~'; } sprintf(general_buff + strlen(general_buff), "+-----+----------+------------------------------------------------------------+\x1B[0m\n\r"); send_to_char (general_buff, ch); return; } } sprintf (general_buff, "\x1B[1;34m[\x1B[37mAlias not found\x1B[34m]\x1B[0m\n\r"); send_to_char (general_buff, ch); return; } /* +---------------------------------------------------------------------+ */ /* Check if second argument != '\0' to create new aliases */ /* +---------------------------------------------------------------------+ */ if (argy[0] == '\0') { send_to_char("\n\rSyntax: alias \x1B[1;30m<\x1B[0mkeyword\x1B[1;30m> <\x1B[0mexpansion\x1B[1;30m>\x1B[0m.\n\r", ch); return; } if (!is_letter(arg)) { send_to_char("\n\rIllegal value in alias keyword, could not create.\n\r", ch); return; } if (free_slot == 0) { send_to_char ("\n\rYou have no free alias entries, you must delete one before adding any more.\n\r", ch); return; } if (strlen (arg) > 8 || strlen (argy) > 58) { send_to_char("\n\rYour alias was too long, could not create.\n\r", ch); return; } if (!alias_expansion_check(argy)) { send_to_char ("\n\rIllegal value in alias expansion, could not create.\n\r", ch); return; } if (!str_cmp (arg, argy)) { send_to_char ("\n\rRecursive aliases are not acceptable.\n\r", ch); return; } for (k = 0; k < MAXALIAS; k++) { if (ch->pcdata->aliasname[k] && !check_alias_loop (ch->pcdata->aliasname[k], argy)) { send_to_char ("\n\rRecursive aliases are not acceptable.\n\r", ch); return; } } for (k = 0; k < MAXALIAS; k++) { if (ch->pcdata->aliasname[k] && !str_cmp (arg, ch->pcdata->aliasname[k])) { char general_buff[1000]; char *temp_char; free_string (ch->pcdata->alias[k]); free_string (ch->pcdata->aliasname[k]); ch->pcdata->aliasname[k] = str_dup (arg); ch->pcdata->alias[k] = str_dup (argy); for (temp_char = ch->pcdata->alias[k]; *temp_char != '\0'; temp_char++) { if (*temp_char == '*') *temp_char = '~'; } sprintf (general_buff, "\x1B[1;34m[\x1B[37mReplaced alias #%d\x1B[34m]\x1B[37;0m\n\r", k + 1); send_to_char (general_buff, ch); return; } } for (k = 0; k < MAXALIAS; k++) { if (ch->pcdata->aliasname[k] && !str_cmp (ch->pcdata->aliasname[k], arg)) { send_to_char ("\n\rRecursive aliases are not acceptable.\n\r", ch); return; } } for (k = 0; k < MAXALIAS; k++) { if (ch->pcdata->aliasname[k] == '\0' || !ch->pcdata->aliasname[k] || !ch->pcdata->alias[k] || ch->pcdata->alias[k] == '\0') { char general_buff[1000]; char *temp_char; ch->pcdata->aliasname[k] = str_dup (arg); ch->pcdata->alias[k] = str_dup (argy); for (temp_char = ch->pcdata->alias[k]; *temp_char != '\0'; temp_char++) { if (*temp_char == '*') *temp_char = '~'; } sprintf (general_buff, "\x1B[1;34m[\x1B[37mAdded alias #%d\x1B[34m]\x1B[37;0m\n\r", k + 1); send_to_char (general_buff, ch); return; } } } void do_quit (CHAR_DATA * ch, char *argy) { DESCRIPTOR_DATA *d; CHAR_DATA *bah_nir; CHAR_DATA *bah; AUCTION *auct; char general_use[STD_LENGTH]; DEFINE_COMMAND ("quit", do_quit, POSITION_DEAD, 0, LOG_NORMAL, "This command saves your character and terminates the session.") if (IS_MOB (ch)) { if (ch->desc != NULL) { do_return (ch, ""); return; } else return; } if (ch->in_room && ch->in_room->sector_type == SECT_WATER_NOSWIM) { send_to_char ("You may not quit in an unswimmable water sector.\n\r", ch); return; } if (ch->desc && !ch->desc->character) { ch->desc->character = ch; } if (IS_HURT (ch, CHARM)) return; if (IN_BATTLE (ch)) { send_to_char ("You cannot quit in the battleground!\n\r", ch); return; } if (ch->pcdata && ch->pcdata->online_spot && ch->pcdata->online_spot->typed_who && (current_time - ch->pcdata->logon < 60)) { char buff[SML_LENGTH]; sprintf(buff, "SPY %s typed who and then logged off after %d seconds.\n\r", NAME(ch), (current_time - ch->pcdata->logon)); log_string (buff); } if (ch->in_room && ch->in_room->vnum > 440 && ch->in_room->vnum < 700 && !ch->in_room->area->can_quit) { send_to_char ("You are not in a valid place in the world to quit.\n\r", ch); return; } if (CHALLENGE (ch) == (ARENA_PREPARING | ARENA_FIGHTING)) { send_to_char ("You must wait until after the arena battle!\n\r", ch); return; } for (auct = auction_list; auct != NULL; auct = auct->next) { if (auct->bychar == ch || auct->tochar == ch) { send_to_char("You cannot quit while you are involved in an auction!\n\r", ch); return; } } if ((ch->pcdata->no_quit_pk > 0 || ch->pcdata->no_quit > 0) && LEVEL(ch) < MAX_LEVEL) { send_to_char("You have been in or near combat or you have used a spell of power.\n\r", ch); sprintf (general_use, "You must wait %d more game hours to quit.\n\r", UMAX(ch->pcdata->no_quit, ch->pcdata->no_quit_pk)); send_to_char (general_use, ch); return; } if (ch->position == POSITION_FIGHTING) { send_to_char ("You may not quit during combat.\n\r", ch); return; } if (ch->position < POSITION_STUNNED) { send_to_char ("You must wait until you die or recover to quit.\n\r", ch); return; } if (ch->pcdata->wasroom != 0) { char_from_room (ch); char_to_room (ch, get_room_index (ch->pcdata->wasroom)); } if (ch->in_room && ch->in_room->vnum > 500 && ch->in_room->vnum < 550) { fprintf (stderr, "Moved %s back into portal room from arena/waiting rooms.\n", NAME (ch)); char_from_room (ch); char_to_room(ch, get_room_index(ch->pcdata->alignment+100)); } do_help (ch, "FAREWELL"); update_pbase (ch); sprintf (log_buf, "%s (%s@%s) has left the world.", NAME (ch), (ch->desc ? ch->desc->username : "nodesc"), (ch->desc ? ch->desc->host : "nodesc")); log_string (log_buf); sprintf (general_use, "Notify> %s has left the world.", NAME (ch)); do_global (general_use, LEVEL_IMMORTAL, WIZ_NOTIFY_LOGIN); if (LEVEL (ch) < LEVEL_IMMORTAL) act ("$n logged off.", ch, NULL, NULL, TO_NOTVICT); NEW_POSITION(ch, POSITION_STANDING); ch->pcdata->number_pets = 0; sprintf (general_use, "%s logged off.\n\r", NAME (ch)); do_chan_notify (ch, general_use); REMOVE_BIT(ch->act, ACT_CRASHER); save_char_obj (ch); if (ch->in_room) { for (bah = ch->in_room->people; bah != NULL; bah = bah_nir) { bah_nir = bah->next_in_room; if (IS_MOB (bah) && MASTER (bah) == ch && IS_HURT (bah, CHARM)) { char_from_room (bah); check_fgt (bah); bah->fgt->master = NULL; extract_char (bah, TRUE); } } } d = ch->desc; quit_flag = TRUE; extract_char (ch, TRUE); quit_flag = FALSE; if (d != NULL) { close_socket (d); } return; } void do_delete (CHAR_DATA * ch, char *argy) { DESCRIPTOR_DATA *d; PLAYERBASE_DATA *playerbase; char general_use[STD_LENGTH]; DEFINE_COMMAND ("delete", do_delete, POSITION_DEAD, 0, LOG_ALWAYS, "This command is used to delete your character permanently and irreversably.") if (FIGHTING (ch) != NULL || ch->position == POSITION_FIGHTING) return; if (ch->in_room && ch->in_room->vnum > 400 && ch->in_room->vnum < 700) { send_to_char ("You are not in a valid place in the world to delete.\n\r", ch); return; } if (IS_HURT (ch, CHARM) || IS_MOB (ch)) return; if (IN_BATTLE (ch)) { send_to_char ("You cannot delete in the battleground!\n\r", ch); return; } if (!str_cmp (argy, "character forever")) { AUCTION *auct; if (CHALLENGE (ch) == (ARENA_PREPARING | ARENA_FIGHTING)) { send_to_char ("You must wait until after the arena battle!\n\r", ch); return; } for (auct = auction_list; auct != NULL; auct = auct->next) { if (auct->bychar == ch || auct->tochar == ch) { send_to_char("You cannot quit while you are involved in an auction!\n\r", ch); return; } } clear_tracks (ch); save_char_obj (ch); sprintf (general_use, "%s%s.cor", PLAYER_DIR_2, NAME (ch)); unlink (general_use); sprintf (general_use, "%s%s", PLAYER_DIR_2, NAME (ch)); unlink (general_use); for (playerbase = playerbase_zero; playerbase != NULL; playerbase = playerbase->next) { if (!str_cmp (playerbase->player_name, NAME (ch))) { playerbase->player_level = -1; save_playerbase (); break; } } sprintf (log_buf, "--> %s deleted self.", NAME (ch)); log_string (log_buf); sprintf (general_use, "Notify> %s has deleted self.", NAME (ch)); do_global (general_use, LEVEL_IMMORTAL, WIZ_NOTIFY_LOGIN); /*sprintf(general_use,"rm \"%s%s\" &",PLAYER_DIR_2,jumble_name(NAME(ch),FALSE)); system(general_use); */ d = ch->desc; extract_char (ch, TRUE); if (d != NULL) close_socket (d); return; } if (argy[0] == '\0') { send_to_char ("To delete this character permanently, type delete character forever\n\r", ch); return; } return; } void do_allsave (CHAR_DATA * ch, char *argy) { DESCRIPTOR_DATA *dd; DEFINE_COMMAND ("allsave", do_allsave, POSITION_DEAD, MAX_LEVEL, LOG_ALWAYS, "This command forces a complete save of all characters.") for (dd = descriptor_list; dd != NULL; dd = dd->next) { if (!dd->character || dd->connected != CON_PLAYING) continue; write_to_descriptor2 (dd, "Forced save... saving your character.\n\r", 0); save_char_obj (dd->character); } return; } void do_save (CHAR_DATA * ch, char *argy) { DEFINE_COMMAND ("save", do_save, POSITION_DEAD, 0, LOG_NORMAL, "This command is used to save your character.") if (IS_MOB (ch)) return; if (argy && argy != NULL && !str_cmp (argy, "xx2xx11")) { save_char_obj (ch); return; } send_to_char ("Saving... Successful.\n\r", ch); return; } void do_beat (CHAR_DATA *ch, char *argy) { CHAR_DATA *victim; DEFINE_COMMAND ("beat", do_beat, POSITION_STANDING, 0, LOG_NORMAL, "This command beats an animal to make it follow you.") if ((victim = get_char_room (ch, argy)) == NULL) { send_to_char ("Which animal did you want to beat?\n\r", ch); return; } check_fgt (victim); act ("You beat on $N for a while, and piss $M off.", ch, NULL, victim, TO_CHAR); act ("$n beats on you for a while, pissing you off.", ch, NULL, victim, TO_VICT); act ("$n beats on $N for a while, pissing $M off.", ch, NULL, victim, TO_NOTVICT); if (IS_PLAYER (victim) || victim->pIndexData->mobtype != MOB_GENERAL_ANIMAL) { do_kill (victim, NAME(ch)); return; } if (victim->fgt->hunting && !str_cmp (victim->fgt->hunting, NAME(ch)) && number_range (1,10) == 2) { act ("$n stops looking so pissed at $N.", victim, NULL, ch, TO_NOTVICT); act ("$n stops looking so pissed at you.", victim, NULL, ch, TO_VICT); free_string (victim->fgt->hunting); victim->fgt->hunting = NULL; } if (victim->fgt->compliance > 50) { act ("$n whimpers softly...", victim, NULL, NULL, TO_ROOM); return; } else if (number_range(1,5) == 3) { if (number_range (1,2) == 2) act ("$n howls in pain!", victim, NULL, NULL, TO_ROOM); else act ("$n moans in agony.", victim, NULL, NULL, TO_ROOM); victim->hit--; if (victim->hit < 0) { raw_kill (victim, FALSE); return; } } victim->fgt->compliance += number_range (1,5); if (number_range(1,40) == 2) { do_kill (victim, NAME(ch)); } return; } void do_pull (CHAR_DATA *ch, char *argy) { CHAR_DATA *victim; int door = MAX_DIR; char arg1[SML_LENGTH]; char arg2[SML_LENGTH]; ROOM_DATA *start_room; DEFINE_COMMAND ("pull", do_pull, POSITION_STANDING, 0, LOG_NORMAL, "This command lets you pull an animal from room to room.") if (ch->position != POSITION_STANDING) return; argy = one_argy (argy, arg1); if ((victim = get_char_room (ch, arg1)) == NULL) { send_to_char ("Syntax: Pull <creature> <direction>.\n\r", ch); return; } argy = one_argy (argy, arg2); if ((door = get_direction_number (arg2)) == MAX_DIR) { send_to_char ("Syntax: Pull <creature> <direction>.\n\r", ch); return; } start_room = victim->in_room; check_fgt (victim); victim->fgt->compliance--; if (victim->fgt->compliance < 10) { if (number_range(1, 10) > victim->fgt->compliance) { act ("$n refuses to budge.", victim, NULL, NULL, TO_ROOM); return; } } if (IS_MOB (victim) && victim->pIndexData->mobtype != MOB_GENERAL_ANIMAL) { multi_hit (victim, ch, TYPE_UNDEFINED); return; } ch->move -= 10; if (!move_char (ch, door)) return; if (IS_PLAYER (victim)) WAIT_STATE (ch, 2*PULSE_VIOLENCE); if (!move_char (victim, door)) { if (victim->fgt->pulling) act ("$n couldn't pull the load!", victim, NULL, NULL, TO_ROOM); else act ("$n couldn't move!", victim, NULL, NULL, TO_ROOM); act ("$B$1$N just tried to pull you $t!$R", victim, dir_name[door], ch, TO_CHAR); return; } else if (number_range(1,200) == 3 && victim->fgt->pulling) { act ("$n just broke free of it's load!", victim, NULL, NULL, TO_ROOM); victim->fgt->pulling = NULL; } act ("$B$1$N just pulled you $t!$R", victim, dir_name[door], ch, TO_CHAR); return; } void do_hitch (CHAR_DATA *ch, char *argy) { CHAR_DATA *victim; SINGLE_OBJECT *obj; char arg1[SML_LENGTH]; char arg2[SML_LENGTH]; DEFINE_COMMAND ("hitch", do_hitch, POSITION_STANDING, 0, LOG_NORMAL, "This command lets you hitch an animal up to an object to pull it.") argy = one_argy (argy, arg1); argy = one_argy (argy, arg2); if ((victim = get_char_room (ch, arg1)) == NULL) { send_to_char ("Syntax: Hitch <person> <thing>.\n\r", ch); return; } if ((obj = get_obj_list (ch, arg2, ch->in_room->contents)) == NULL) { send_to_char ("That thing is not in the room, so it cannot be hitched up.\n\r", ch); return; } if (CAN_WEAR (obj, ITEM_TAKE)) { send_to_char ("That item is takeable so it is too small to be hitched up to an animal.\n\r", ch); return; } if (obj->pIndexData->item_type != ITEM_SIEGE && (obj->pIndexData->item_type != ITEM_CONTAINER || !IS_SET(((I_CONTAINER *)obj->more)->flags, CONT_WHEELED))) { send_to_char ("You can only pull siege engines and containers with wheels.\n\r", ch); return; } check_fgt (victim); if ((IS_PLAYER (victim) && DIFF_ALIGN (ch, victim)) || (IS_MOB (victim) && (victim->pIndexData->mobtype != MOB_GENERAL_ANIMAL || number_range (1,40) > victim->fgt->compliance))) { act ("$N will not pull $p for you!\n\r", ch, obj, victim, TO_CHAR); act ("$n just tried to hitch you up to $p.", ch, obj, victim, TO_VICT); act ("$n just tried to hitch $N up to $p.", ch, obj, victim, TO_NOTVICT); if (IS_MOB (victim)) do_kill(victim, NAME(ch)); return; } if (victim->fgt->pulling) { act ("$N is already pulling $p", ch, victim->fgt->pulling, victim, TO_CHAR); return; } victim->fgt->pulling = obj; act ("Ok, $n is hitched up to $p.", victim, obj, NULL, TO_ROOM); act ("Ok, you are hitched up to $p.", victim, obj, NULL, TO_CHAR); return; } void do_unhitch (CHAR_DATA *ch, char *argy) { CHAR_DATA *victim; DEFINE_COMMAND ("unhitch", do_unhitch, POSITION_STANDING, 0, LOG_NORMAL, "This command lets you unhitch an animal from an object.") if ((victim = get_char_room (ch, argy)) == NULL) { send_to_char ("Syntax: Unhitch who?\n\r", ch); return; } check_fgt (victim); if (victim->fgt->pulling == NULL) { send_to_char ("They weren't pulling anything to start with.\n\r", ch); return; } check_fgt (victim); act ("$n is unhitched from $p.", victim, victim->fgt->pulling, NULL, TO_ROOM); act ("You are unhitched from $p.", victim, victim->fgt->pulling, NULL, TO_CHAR); victim->fgt->pulling = NULL; return; } void do_follow (CHAR_DATA * ch, char *argy) { char arg[SML_LENGTH]; CHAR_DATA *victim; int ch_followers = 0; int victim_followers = 0; DEFINE_COMMAND ("follow", do_follow, POSITION_STANDING, 0, LOG_NORMAL, "This command allows you to follow a player or mob. See also Ditch and Group.") one_argy (argy, arg); if (arg[0] == '\0') { send_to_char ("Syntax: Follow <person>\n\r", ch); return; } if ((victim = get_char_room (ch, arg)) == NULL) { send_to_char ("That person is either not here, or not visible to you.\n\r", ch); return; } if (LEVEL (victim) > 100 && LEVEL (ch) < 100) { send_to_char ("Mortals may not follow immorts!\n\r", ch); return; } if (IS_HURT (ch, CHARM) && MASTER (ch) != NULL) { act ("You'd rather follow your master... $N!", ch, NULL, MASTER (ch), TO_CHAR); return; } if (victim == ch) { if (MASTER (ch) == NULL) { send_to_char ("Okay. You stop following anyone you were following.\n\r", ch); return; } stop_follower (ch); return; } if (DIFF_ALIGN(ch, victim)) { send_to_char ("Follow someone not of your own alignment? No Way!\n\r", ch); return; } /* This is the way the new follow code works. It is not based on groupsize or anything that difficult. Basically, if you have anyone at all following you, you cannot follow anyone else. If the person you are trying to follow already has too many people following them, no more can follow. If the person you want to follow is already following someone else, you cannot follow. */ ch_followers = get_num_followers(ch); victim_followers = get_num_followers(victim); if (IS_PLAYER(ch)) { ch_followers += ch->pcdata->remort_times/5 +1; } if (victim_followers > (MAX_GROUPSIZE + (get_stat(victim, CHA)/4))) { send_to_char("That person already has too many people following them.\n\r", ch); return; } if (MASTER(victim) != NULL && MASTER(victim) != ch) { send_to_char("That person is already following someone else!\n\r", ch); return; } if (ch_followers > 1 && MASTER(victim) != ch) { send_to_char("You already have followers and are not loop following.\n\r", ch); return; } if (MASTER (ch) != NULL) stop_follower (ch); add_follower (ch, victim); return; } void add_follower (CHAR_DATA * ch, CHAR_DATA * master) { if (MASTER (ch) != NULL) { bug ("Add_follower: non-null master.", 0); return; } if (IS_PLAYER(ch) && IS_MOB(master)) { send_to_char("Players cannot follow mobs..", ch); return; } /* JRAJRA - dont follow mobs */ check_fgt (ch); ch->fgt->master = master; ch->fgt->leader = NULL; if (can_see (master, ch)) act ("$n now follows you.", ch, NULL, master, TO_VICT); act ("You now follow $N.", ch, NULL, master, TO_CHAR); return; } void stop_follower (CHAR_DATA * ch) { char general_use[STD_LENGTH]; if (MASTER (ch) == NULL) { bug ("Stop_follower: null master.", 0); return; } if (IS_HURT (ch, CHARM)) { REMOVE_BIT (ch->aff[HURT], CHARM); affect_strip (ch, gsn_charm_person); } if (can_see (MASTER (ch), ch)) act ("$n stops following you around.", ch, NULL, MASTER (ch), TO_VICT); act ("You stop following $N.", ch, NULL, MASTER (ch), TO_CHAR); if (LEADER (ch) != NULL) { sprintf (general_use, "%s has left the group.", NAME (ch)); group_notify (general_use, ch); } check_fgt (ch); ch->fgt->master = NULL; ch->fgt->leader = NULL; return; } void die_follower (CHAR_DATA * ch) { int i; CHAR_DATA *fch; if (MASTER (ch) != NULL) stop_follower (ch); if (!ch->fgt) return; ch->fgt->leader = NULL; for (i = 0; i < TOTAL_LIST; i++) { for (fch = char_list[i]; fch != NULL; fch = fch->next) { if (fch->fgt) { if (MASTER (fch) == ch) stop_follower (fch); if (LEADER (fch) == ch) fch->fgt->leader = fch; } } } return; } int chars_in_group (CHAR_DATA * ch) { DESCRIPTOR_DATA *tch; int tally; tally = 0; if (IS_MOB (ch)) return 1; /*Just dummy value */ for (tch = descriptor_list; tch != NULL; tch = tch->next) { if (tch->character == NULL || tch->connected != CON_PLAYING) continue; if (is_same_group (ch, tch->character)) tally++; } if (tally == 0) tally = 1; return tally; } int rchars_in_group (CHAR_DATA * ch) { CHAR_DATA *tch; int tally; tally = 0; if (IS_MOB (ch)) return 1; /*Just dummy value */ for (tch = ch->in_room->people; tch != NULL; tch = tch->next_in_room) { if (IS_MOB (tch)) continue; if (is_same_group (ch, tch)) tally++; } if (tally == 0) tally = 1; return tally; } int tchars_in_group (CHAR_DATA * ch) { CHAR_DATA *tch; int tally; tally = 0; if (IS_MOB (ch)) return 1; for (tch = char_list[PLAYER_LIST]; tch != NULL; tch = tch->next) { if (is_same_group (ch, tch)) tally++; } if (tally == 0) tally = 1; return tally; } void do_ditch (CHAR_DATA * ch, char *argy) { CHAR_DATA *ditchee; DEFINE_COMMAND ("ditch", do_ditch, POSITION_DEAD, 0, LOG_NORMAL, "This command allows you to ditch a following character.") if (argy == "" || argy[0] == '\0') { send_to_char ("Ditch whom?\n\r", ch); return; } if ((ditchee = get_char_world (ch, argy)) == NULL) { send_to_char ("Ditch Whom?\n\r", ch); return; } if (ditchee == ch) { send_to_char ("Ditch yourself? Get a clue...\n\r", ch); return; } if ((!MASTER (ditchee) || MASTER (ditchee) != ch) && (!LEADER (ditchee) || LEADER (ditchee) != ch)) { send_to_char ("Ditch Whom?\n\r", ch); return; } send_to_char ("Player successfully ditched.\n\r", ch); check_fgt (ditchee); ditchee->fgt->master = NULL; ditchee->fgt->leader = NULL; if (IS_HURT (ditchee, CHARM)) REMOVE_BIT (ditchee->aff[HURT], CHARM); send_to_char ("The group leader has ditched you!\n\r", ditchee); return; } void do_group (CHAR_DATA * ch, char *argy) { char buf[STD_LENGTH]; char arg[SML_LENGTH]; int cig; int gppt = 0; CHAR_DATA *victim; DEFINE_COMMAND ("group", do_group, POSITION_DEAD, 0, LOG_NORMAL, "This command allows you to group 'all' or playername. With no arguments, it shows info on your current group.") one_argy (argy, arg); if (arg[0] == '\0') { CHAR_DATA *gch; CHAR_DATA *leader; leader = (LEADER (ch) != NULL) ? LEADER (ch) : ch; sprintf (buf, "Group Leader [\x1B[1;37m%s\x1B[0m]\n\r\n\r", NAME (leader)); send_to_char (buf, ch); sprintf (buf, "%14s %-14s %-18s %-14s %s\n\r", "[-Char Power-]", "--Name--", "+-Health-+", "*-Stamina-*", "=-Exp2Lvl-="); send_to_char (buf, ch); for (gch = char_list[PLAYER_LIST]; gch != NULL; gch = gch->next) { if (is_same_group (gch, ch)) { char tmp[40]; if (gch == ch) sprintf(tmp, "%13d", LEVEL(ch)); else if (LEVEL (gch) < 4) strcpy (tmp, "Inexperienced"); else if (LEVEL (gch) < 12) strcpy (tmp, "Knowledgable"); else if (LEVEL (gch) < 27) strcpy (tmp, "Experienced"); else if (LEVEL (gch) < 45) strcpy (tmp, "Well-Known"); else if (LEVEL (gch) < 70) strcpy (tmp, "---Famous---"); else if (LEVEL (gch) < 99) strcpy (tmp, "-> LEGEND <-"); else strcpy(tmp, " Immortal "); sprintf (buf, "[\x1B[1;30m%13s\x1B[0;37m] \x1B[1;37m%-14s\x1B[0m \x1B[1;31m%-18s\x1B[34m %-14s\x1B[0;37m (%ld)%s\n\r", tmp, (IS_MOB (gch) ? gch->pIndexData->short_descr : capitalize (PERS (gch, ch))), STRING_HITS (gch), STRING_MOVES (gch), ((FIND_EXP (LEVEL (gch), gch->race)) - gch->pcdata->exp), (gch->pcdata->remort_times ? "R" : " ")); send_to_char (buf, ch); } } if (LEADER (ch) == NULL) cig = tchars_in_group (ch); else cig = tchars_in_group (LEADER (ch)); if (cig > 1) { sprintf (buf, "--Members in group: [\x1B[1;34m%d\x1B[37;0m]\n\r", cig); send_to_char (buf, ch); sprintf (buf, "--Total Group Points is: [\x1B[1;34m%d\x1B[37;0m]\n\r", check_group_pts(ch)); send_to_char (buf, ch); } return; } gppt = check_group_pts(ch); gppt += (1 + (IS_PLAYER(ch) ? ch->pcdata->remort_times/5 : 0)); if (!str_cmp (arg, "all")) { CHAR_DATA *gch; if (LEADER (ch) != NULL) { send_to_char ("You must be the leader of the group someone or ALL!\n\r", ch); return; } for (gch = char_list[PLAYER_LIST]; gch != NULL; gch = gch->next) { if (ch->in_room != NULL && !is_same_group (gch, ch) && ch->in_room == gch->in_room && MASTER (gch) != NULL && MASTER (gch) == ch && LEADER (gch) == NULL && IS_PLAYER(gch)) { if ((gppt + (1 + gch->pcdata->remort_times/5)) < (MAX_GROUPSIZE + get_stat (ch, CHA)/4)) { check_fgt (gch); gch->fgt->leader = ch; act ("$N joins $n's group.", ch, NULL, gch, TO_NOTVICT); act ("You join $n's group.", ch, NULL, gch, TO_VICT); act ("$N joins your group.", ch, NULL, gch, TO_CHAR); sprintf (buf, "%s has joined the group!", NAME (gch)); group_notify (buf, ch); gppt += (1 + gch->pcdata->remort_times/5); } } } return; } /*end all */ if ((victim = get_player_world (ch, arg, FALSE)) == NULL || !can_see (ch, victim)) { send_to_char ("They aren't here.\n\r", ch); return; } if (DIFF_ALIGN(ch, victim)) { send_to_char ("They aren't here.\n\r", ch); return; } if (MASTER (ch) != NULL || (LEADER (ch) != NULL && LEADER (ch) != ch)) { send_to_char ("You can follow two people at once!\n\r", ch); return; } if (MASTER (victim) != ch && ch != victim) { act ("$N must be following you in order to group up.", ch, NULL, victim, TO_CHAR); return; } if (ch == victim) { CHAR_DATA *tch; send_to_char ("You disband your group. All players stop following you.\n\r", ch); for (tch = char_list[PLAYER_LIST]; tch != NULL; tch = tch->next) { if (is_same_group (tch, ch)) { check_fgt (tch); tch->fgt->leader = NULL; if (IS_PLAYER (tch)) tch->fgt->master = NULL; send_to_char ("The leader has disbanded the group, and you now follow no-one.\n\r", tch); } } return; } if (is_same_group (victim, ch)) { char buffy[200]; check_fgt (victim); victim->fgt->leader = NULL; sprintf (buffy, "%s removed %s from the group.", NAME (ch), NAME (victim)); group_notify (buffy, ch); return; } if (gppt + (1 + victim->pcdata->remort_times/5) >= (MAX_GROUPSIZE + get_stat(ch, CHA)/4)) { send_to_char ("You have reached the maximum amount of people in your group.\n\r", ch); return; } check_fgt (victim); victim->fgt->leader = ch; sprintf (buf, "%s has joined the group!", NAME (victim)); group_notify (buf, ch); return; } /* Group points are now 1 + remorts/5 (rounded down) */ int check_group_pts (CHAR_DATA * ch) { CHAR_DATA *mch; int group_pts = 0; for (mch = char_list[PLAYER_LIST]; mch != NULL; mch = mch->next) { if (is_same_group (mch, ch)) { group_pts += mch->pcdata->remort_times/5 + 1; } } return group_pts; } int get_num_followers (CHAR_DATA *ch) { CHAR_DATA *mch; int follow_number = 0; for (mch = char_list[PLAYER_LIST]; mch != NULL; mch=mch->next) { if (MASTER(mch) == ch && mch != ch) { follow_number += mch->pcdata->remort_times/5 +1; } } return follow_number; } void do_split (CHAR_DATA * ch, char *argy) { char buf[STD_LENGTH]; char arg[STD_LENGTH]; CHAR_DATA *gch; char str1[1000]; char str2[1000]; int amt_to_split[MAX_COINS]; int total_less_eq[MAX_COINS]; int i; int total_coinage; int members; int amount; int each_share; int leftover; int coin_amount[MAX_COINS]; int type = -1; DEFINE_COMMAND ("split", do_split, POSITION_RESTING, 0, LOG_NORMAL, "This command can be used to split up coins. It will not make change.") if (!ch->in_room) return; argy = one_argy (argy, arg); if (arg[0] == '\0') { send_to_char ("Split how much?\n\r", ch); return; } amount = atoi (arg); members = 0; ch->pcdata->voting_on = 0; for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) { if (is_same_group (gch, ch) && IS_PLAYER (gch)) { gch->pcdata->voting_on = 0; members++; } } if (members < 2) return; for (i = 0; i < MAX_COINS; i++) { amt_to_split[i] = 0; coin_amount[i] = 0; total_less_eq[i] = 0; } for (i = 0; i < MAX_COINS; i++) { if (!str_cmp(argy, coin_name[i])) { type = i; break; } } if (amount <= 0) { send_to_char ("Your group wouldn't like that.\n\r", ch); return; } if (type >= 0 && ch->coins[type] < amount) { sprintf(str1, "You dont have %d %s %s to split.\n\r", amount, coin_color[i], (amount > 1 ? "coins" : "coin")); send_to_char(str1, ch); return; } else if (tally_coins (ch) < amount) { send_to_char ("You don't have that much money.\n\r", ch); return; } sprintf (str1, "%s", name_amount (amount)); /* First do splitting a specific type... */ if (type >= 0) { total_coinage = amount; amount = total_coinage/members; leftover = total_coinage % members; ch->coins[i] -= total_coinage; if (amount > 0) { for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) { if (IS_PLAYER(gch) && is_same_group(ch, gch)) { gch->coins[i] += amount; gch->pcdata->voting_on += amount; } } } if (leftover > 0) /* First splitter "keeps one coin" */ { leftover--; ch->pcdata->voting_on++; ch->coins[i]++; /* There should not be enough coins to go around to all the groupies, since its amt % members, so we just go down the list once. */ for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) { if (IS_PLAYER(gch) && is_same_group(ch, gch) && gch != ch) { gch->coins[i]++; gch->pcdata->voting_on++; } } } for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) { if (IS_PLAYER(gch) && is_same_group(ch, gch)) { if (ch == gch) { sprintf(buf, "You split %d %s %s. ", amount, coin_color[type], (amount > 1 ? "coins" : "coin")); send_to_char(buf, gch); if (gch->pcdata->voting_on == 0) send_to_char("Your share is NOTHING!n\r", ch); else { sprintf(buf, "Your share is %d %s.\n\r", gch->pcdata->voting_on, (gch->pcdata->voting_on > 1 ? "coins" : "coin")); send_to_char(buf, gch); } } else { sprintf(buf, "%s split %d %s %s. ", rNAME(ch, gch), amount, coin_color[type], (amount > 1 ? "coins" : "coin")); send_to_char(buf, gch); if (gch->pcdata->voting_on == 0) send_to_char("Your share is NOTHING!n\r", ch); else { sprintf(buf, "Your share is %d %s.\n\r", gch->pcdata->voting_on, (gch->pcdata->voting_on > 1 ? "coins" : "coin")); send_to_char(buf, gch); } } } } return; } /* GENERAL SPLITTING...NO COINS SPECIFIED!!!! */ /* We first start splitting coins up to the level required. */ /* Remove coins from ch first. */ sub_coins(amount, ch); each_share = amount/members; leftover = amount % members; create_amount(each_share, ch, NULL, NULL); if (IS_PLAYER(ch)) { ch->pcdata->voting_on = each_share; if (leftover > 0) { leftover--; ch->coins[0]++; ch->pcdata->voting_on++; } if (ch->pcdata->voting_on != 0) { sprintf (buf, "You split %s coins. You keep your share of %s coins.\n\r", str1, name_amount (ch->pcdata->voting_on)); ch->pcdata->voting_on = 0; send_to_char (buf, ch); } } for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) { if (IS_MOB (gch)) continue; if (gch != ch && is_same_group (gch, ch)) { create_amount (each_share, gch, NULL, NULL); gch->pcdata->voting_on = each_share; if (leftover > 0) { leftover--; gch->coins[0]++; gch->pcdata->voting_on++; } if (gch->pcdata->voting_on == 0) { sprintf (buf, "$n splits %s coins, but there is not enough to go around, and you receive nothing.", str1); act (buf, ch, NULL, gch, TO_VICT); continue; } sprintf (str2, "%s", name_amount (gch->pcdata->voting_on)); sprintf (buf, "$n splits %s coins. Your get your portion... %s coins.", str1, str2); gch->pcdata->voting_on = 0; act (buf, ch, NULL, gch, TO_VICT); } } return; } bool is_same_group (CHAR_DATA * ach, CHAR_DATA * bch) { if (LEADER(ach) != NULL) ach = LEADER (ach); if (LEADER (bch) != NULL) bch = LEADER (bch); return ach == bch; }