/* * I had several cases where I had disabled commands for a quest and * forgot to enable them. This snippet lets a you decide how long * the command should be disabled for (or forever if they really want too). * * Here's the complete source code for the disable command. There's also * some slight modifications to the DISABLED_DATA structure, and some code * to add to one of your update cycles (I chose char_update). * * My color macros have a '#' followed by a single character. Change those * to whatever you use, or remove them completely. The memory allocation * macros (CREATE, DISPOSE) will need to be replaced with whatever you use * to free and allocate memory. * * This adds a number to the disabled.txt file so I recommend deleting the * file and re-disabling the commands you had disabled after adding this * new code. * * Just to be clear, I didn't write the do_disable, load_disabled, and * save_disabled functions, just modified them to do the time thing and * display the disabled commands differently. * * The new display looks like this: * -=-=-=-=-=-=-=-=-=-=-= Disabled commands =-=-=-=-=-=-=-=-=-=-=- * | Command Level Disabled by Until | * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * | roll 12 Puck Sat Jun 23 13:37:51 | * | order 12 Puck (indefinitely) | * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * * If you find it useful, let me know. * * Puck, Implementor and Coder for GodWars the Gathering * cuervo@castleamber.net */ /* Here's the helpfile: */ 5 DISABLE~ Syntax: disable disable The disable command is used to prevent players from using a command. DISABLE by itself will list any disabled commands, the disabler, the disabler's level, and the amount of time the command is disabled. DISABLE followed by the name of a disabled command will re-enable that command. You must be at least the same level as the god who disabled it. Commands can be disabled indefinitely or they can be set to re-enable automatically. The following examples show several ways to disable a command: > disable decapitate 15 minutes > disable chant 1 hour 15 minutes > disable order forever (Timer stuff created by Puck) ~ /* End help file */ /* Your disabled_data struct should look something like this. The * enable_ts member is new. */ struct disabled_data { DISABLED_DATA *next; /* pointer to next node */ struct cmd_type const *command; /* pointer to the command struct*/ char *disabled_by; /* name of disabler */ sh_int level; /* level of disabler */ time_t enable_ts; /* time to automatically enable */ }; /* End merc.h additions */ /* Here's the 'disable' command. */ void do_disable (CHAR_DATA *ch, char *argument) { int i; DISABLED_DATA *p,*q; char buf[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH], cmdname[MAX_INPUT_LENGTH]; time_t enable_ts = 0; if (IS_NPC(ch)) { send_to_char ("RETURN first.\n\r",ch); return; } if (!argument[0]) /* Nothing specified. Show disabled commands. */ { char szEnabled[MAX_INPUT_LENGTH]; if (!disabled_first) /* Any disabled at all ? */ { send_to_char ("There are no commands disabled.\n\r",ch); return; } send_to_char ("#g-=-=-=-=-=-=-=-=-=-=-= #WDisabled commands #g=-=-=-=-=-=-=-=-=-=-=-\n\r" "#g| #wCommand Level Disabled by Until #g|\n\r",ch); send_to_char ("#g-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\r", ch); for (p = disabled_first; p; p = p->next) { if ( p->enable_ts > 0 ) { strcpy(szEnabled, ctime(&p->enable_ts)); szEnabled[19] = '\0'; } else strcpy(szEnabled, "#c(indefinitely) "); sprintf (buf, "#g| #Y%-12s #n%5d #W%-14s #C%s #g|\r\n", p->command->name, p->level, p->disabled_by, szEnabled); sprintf(buf2, "%-63s", buf); send_to_char (buf2,ch); } send_to_char ("#g-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\r", ch); return; } /* command given */ argument = one_argument(argument, cmdname); /* First check if it is one of the disabled commands */ for (p = disabled_first; p ; p = p->next) if (!str_cmp(cmdname, p->command->name)) break; if (p) /* this command is disabled */ { /* Optional: The level of the imm to enable the command must equal or exceed level of the one that disabled it */ if (get_trust(ch) < p->level) { send_to_char ("This command was disabled by a higher power.\n\r",ch); return; } /* Remove */ if (disabled_first == p) /* node to be removed == head ? */ disabled_first = p->next; else /* Find the node before this one */ { for (q = disabled_first; q->next != p; q = q->next); /* empty for */ q->next = p->next; } free_string (p->disabled_by); /* free name of disabler */ DISPOSE(p); save_disabled(); /* save to disk */ send_to_char ("Command enabled.\n\r",ch); } else /* not a disabled command, check if that command exists */ { /* IQ test */ if (!str_cmp(cmdname,"disable")) { send_to_char("You cannot disable the disable command.\n\r",ch); return; } /* Search for the command */ for (i = 0; cmd_table[i].name[0] != '\0'; i++) if (!str_cmp(cmd_table[i].name, cmdname)) break; /* Found? */ if (cmd_table[i].name[0] == '\0') { send_to_char ("No such command.\n\r",ch); return; } /* Can the imm use this command at all ? */ if (cmd_table[i].level > get_trust(ch)) { send_to_char ("You don't have access to that command; you cannot disable it.\n\r",ch); return; } /* Parse time argument */ if ( argument[0] == '\0' ) { send_to_char("Syntax: disable \r\n", ch); return; } else { char duration[MAX_INPUT_LENGTH], time_unit[MAX_INPUT_LENGTH]; int durationqty; argument = one_argument(argument, duration); if ( !str_cmp(duration, "forever") ) enable_ts = 0; /* else if ( !str_cmp(duration, "test") ) enable_ts = 1; */ else { for ( enable_ts = (int)current_time, argument = one_argument(argument, time_unit); duration[0] != '\0'; argument = one_argument(argument, duration), argument = one_argument(argument, time_unit) ) { durationqty = atoi(duration); if ( atoi(duration) <= 0 ) { send_to_char("Syntax: disable \r\n", ch); return; } /* Chop off time unit to "day", "hou" and "min" */ time_unit[3] = '\0'; if ( !str_cmp(time_unit, "day") ) enable_ts += (durationqty * 24 * 60 * 60); else if ( !str_cmp(time_unit, "hou") ) enable_ts += (durationqty * 60 * 60); else if ( !str_cmp(time_unit, "min") ) enable_ts += (durationqty * 60); else { send_to_char("Syntax: disable \r\n", ch); return; } } /* End while */ } /* End days/hours/minutes parsing */ } /* End time argument parsing */ /* Disable the command */ CREATE(p,DISABLED_DATA,1); p->command = &cmd_table[i]; p->disabled_by = str_dup (ch->name); p->level = get_trust(ch); p->enable_ts = enable_ts; p->next = disabled_first; disabled_first = p; /* add before the current first element */ send_to_char ("Command disabled.\n\r",ch); save_disabled(); /* save to disk */ } } /* End do_disable() */ /* In char_update(), add this code. It will check to see if any commands need * to be re-enabled. It will only re-enable one command per update cycle. */ void char_update ( void ) { /* ...Existing definitions for char_update... */ DISABLED_DATA *pDisabled, *pDisabled_prev = NULL; /* Check for disabled commands that need to be re-enabled */ for (pDisabled = disabled_first; pDisabled ; pDisabled_prev = pDisabled, pDisabled = pDisabled->next) { if ( pDisabled->enable_ts > 0 && pDisabled->enable_ts < current_time ) { logf("\'%s\' enabled automatically.", pDisabled->command->name); /* Repair the linked list */ if ( pDisabled == disabled_first ) disabled_first = pDisabled->next; else pDisabled_prev->next = pDisabled->next; if (pDisabled == disabled_first ) pDisabled->next = disabled_first; else pDisabled->next = pDisabled_prev; free_string (pDisabled->disabled_by); DISPOSE(pDisabled); save_disabled(); } } /* Here's the rest of char_update... */ for ( ch = char_list; ch != NULL; ch = ch_next ) /* ... */ } /* End char_update() */ /* Modify load_disabled() to load the time. Here's the whole function. */ void load_disabled() { FILE *fp; DISABLED_DATA *p; char *name; int i; disabled_first = NULL; fp = fopen (DISABLED_FILE, "r"); if (!fp) /* No disabled file.. no disabled commands : */ { bug("No disabled file",0); return; } name = fread_word (fp); while (str_cmp(name, END_MARKER)) /* as long as name is NOT END_MARKER */ { /* Find the command in the table */ for (i = 0; cmd_table[i].name[0] ; i++) if (!str_cmp(cmd_table[i].name, name)) break; if (!cmd_table[i].name[0]) /* command does not exist? */ { bug ("Skipping uknown command in " DISABLED_FILE " file.",0); fread_number(fp); /* level */ fread_word(fp); /* disabled_by */ } else /* add new disabled command */ { CREATE(p,DISABLED_DATA,1); p->command = &cmd_table[i]; p->level = fread_number(fp); p->disabled_by = str_dup(fread_word(fp)); p->enable_ts = fread_number(fp); /* Timed disable stuff */ p->next = disabled_first; disabled_first = p; } name = fread_word(fp); } fclose (fp); } /* End load_disabled() */ /* Modify save_disabled() to save the time. Here's the whole function. */ void save_disabled() { FILE *fp; DISABLED_DATA *p; if (!disabled_first) /* delete file if no commands are disabled */ { unlink (DISABLED_FILE); return; } fp = fopen (DISABLED_FILE, "w"); if (!fp) { bug ("Could not open " DISABLED_FILE " for writing",0); return; } for (p = disabled_first; p ; p = p->next) fprintf (fp, "%s %d %s %d\n", /* Timed disable stuff */ p->command->name, p->level, p->disabled_by, (int)p->enable_ts); fprintf (fp, "%s\n",END_MARKER); fclose (fp); } /* End save_disabled() */