Added protocols,lists and events, and fixed some bugs... refer to changelog.

This commit is contained in:
Vatiken 2012-02-12 22:07:50 +00:00
parent 6dadf24c51
commit dd280c1b58
22 changed files with 419 additions and 89 deletions

View file

@ -35,6 +35,25 @@ export (QQ's a zone into a tarball)
Xlist (mlist, olist, rlist, zlist, slist, tlist, qlist)
(lots of major bugfixes too)
@
[Feb 12 2012] - Vatiken
bug: do_score, changed level 30 to LVL_IMMORT
idea: Mortals can't see immortals levels
bug: the NOHASSLE flag allows imms to carry unlimited weight
idea: dexterity now affects whether a character gets the first hit
idea: advance to immortal now sets hunger/thirst to -1
feature: color is now an option on do_show, which shows all 256 color options
feature: active lists has now been added to do_show, under 'stats'
feature: added KaVir's protocol snippet
bug: protocol snippet should now properly detect xterm color
bug: protocol settings should now be preserved after copyover
idea: ibt now time stamps when something is submitted
feature: added a new MUD event system (mud_event.c)
feature: added a display_usage() event, which is basically an event/list tester.
feature: added two new parsing commands to modify.c for converting tabs to @ and back
feature: added a new MUD list system (lists.c)
improve: qedit now uses '\t' instead of '@' to show color
improve: sedit now uses '\t' instead of '@' to show color
issues: may be bugs with strfrmt() while converting '@' to '\t'
[Feb 04 2012] - Vatiken
Feature: Added 'Experience' and 'Thaco' to the do_show() command.
Bug Fix: Nipped a bug where shopkeepers weren't sending tells.

View file

@ -20,6 +20,7 @@
#include "screen.h"
#include "constants.h"
#include "dg_scripts.h"
#include "mud_event.h"
#include "mail.h" /**< For the has_mail function */
#include "act.h"
#include "class.h"
@ -808,7 +809,7 @@ ACMD(do_score)
send_to_char(ch, "You have %d exp, %d gold coins, and %d questpoints.\r\n",
GET_EXP(ch), GET_GOLD(ch), GET_QUESTPOINTS(ch));
if (GET_LEVEL(ch) < 30)
if (GET_LEVEL(ch) < LVL_IMMORT)
send_to_char(ch, "You need %d exp to reach your next level.\r\n",
level_exp(GET_CLASS(ch), GET_LEVEL(ch) + 1) - GET_EXP(ch));
@ -1262,11 +1263,19 @@ ACMD(do_who)
CCNRM(ch, C_SPR), ((!(++num_can_see % 4)) ? "\r\n" : ""));
} else {
num_can_see++;
send_to_char(ch, "%s[%2d %s] %s%s%s%s",
if (GET_LEVEL(tch) >= LVL_GOD) {
send_to_char(ch, "%s%s%s%s%s",
(GET_LEVEL(tch) >= LVL_IMMORT ? CCYEL(ch, C_SPR) : ""),
GET_NAME(tch), (*GET_TITLE(tch) ? " " : ""), GET_TITLE(tch),
CCNRM(ch, C_SPR));
} else {
send_to_char(ch, "%s[%2d %s] %s%s%s%s",
(GET_LEVEL(tch) >= LVL_IMMORT ? CCYEL(ch, C_SPR) : ""),
GET_LEVEL(tch), CLASS_ABBR(tch),
GET_NAME(tch), (*GET_TITLE(tch) ? " " : ""), GET_TITLE(tch),
CCNRM(ch, C_SPR));
}
if (GET_INVIS_LEV(tch))
send_to_char(ch, " (i%d)", GET_INVIS_LEV(tch));

View file

@ -161,19 +161,24 @@ ACMD(do_put)
static int can_take_obj(struct char_data *ch, struct obj_data *obj)
{
if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch)) {
act("$p: you can't carry that many items.", FALSE, ch, obj, 0, TO_CHAR);
return (0);
} else if ((IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj)) > CAN_CARRY_W(ch)) {
act("$p: you can't carry that much weight.", FALSE, ch, obj, 0, TO_CHAR);
return (0);
} else if (!(CAN_WEAR(obj, ITEM_WEAR_TAKE))) {
act("$p: you can't take that!", FALSE, ch, obj, 0, TO_CHAR);
return (0);
} else if (OBJ_SAT_IN_BY(obj)){
if (!PRF_FLAGGED(ch, PRF_NOHASSLE)) {
if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch)) {
act("$p: you can't carry that many items.", FALSE, ch, obj, 0, TO_CHAR);
return (0);
} else if ((IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj)) > CAN_CARRY_W(ch)) {
act("$p: you can't carry that much weight.", FALSE, ch, obj, 0, TO_CHAR);
return (0);
} else if (!(CAN_WEAR(obj, ITEM_WEAR_TAKE))) {
act("$p: you can't take that!", FALSE, ch, obj, 0, TO_CHAR);
return (0);
}
}
if (OBJ_SAT_IN_BY(obj)){
act("It appears someone is sitting on $p..", FALSE, ch, obj, 0, TO_CHAR);
return (0);
}
return (1);
}

View file

@ -84,12 +84,14 @@ ACMD(do_hit)
if (!CONFIG_PK_ALLOWED && !IS_NPC(vict) && !IS_NPC(ch))
check_killer(ch, vict);
if ((GET_POS(ch) == POS_STANDING) && (vict != FIGHTING(ch))) {
hit(ch, vict, TYPE_UNDEFINED);
WAIT_STATE(ch, PULSE_VIOLENCE + 2);
} else
send_to_char(ch, "You do the best you can!\r\n");
}
if ((GET_POS(ch) == POS_STANDING) && (vict != FIGHTING(ch))) {
if (GET_DEX(ch) > GET_DEX(vict) || (GET_DEX(ch) == GET_DEX(vict) && rand_number(1, 2) == 1)) /* if faster */
hit(ch, vict, TYPE_UNDEFINED); /* first */
else hit(vict, ch, TYPE_UNDEFINED); /* or the victim is first */
WAIT_STATE(ch, PULSE_VIOLENCE + 2);
} else
send_to_char(ch, "You're fighting the best you can!\r\n");
}
}
ACMD(do_kill)

View file

@ -1546,6 +1546,9 @@ ACMD(do_advance)
for (i = 1; i <= MAX_SKILLS; i++)
SET_SKILL(victim, i, 100);
GET_OLC_ZONE(victim) = NOWHERE;
GET_COND(victim, HUNGER) = -1;
GET_COND(victim, THIRST) = -1;
GET_COND(victim, DRUNK) = -1;
}
gain_exp_regardless(victim, level_exp(GET_CLASS(victim), newlevel) - GET_EXP(victim));
@ -2459,7 +2462,9 @@ ACMD(do_show)
struct obj_data *obj;
struct descriptor_data *d;
char field[MAX_INPUT_LENGTH], value[MAX_INPUT_LENGTH],
arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH], temp[MAX_STRING_LENGTH];
int r, g, b;
char colour[16];
struct show_struct {
const char *cmd;
@ -2477,7 +2482,8 @@ ACMD(do_show)
{ "houses", LVL_IMMORT },
{ "snoop", LVL_IMMORT }, /* 10 */
{ "thaco", LVL_IMMORT },
{ "experience", LVL_IMMORT },
{ "exp", LVL_IMMORT },
{ "colour", LVL_IMMORT },
{ "\n", 0 }
};
@ -2617,7 +2623,8 @@ ACMD(do_show)
" %5d rooms %5d zones\r\n"
" %5d triggers %5d shops\r\n"
" %5d large bufs %5d autoquests\r\n"
" %5d buf switches %5d overflows\r\n",
" %5d buf switches %5d overflows\r\n"
" %5d lists\r\n",
i, con,
top_of_p_table + 1,
j, top_of_mobt + 1,
@ -2625,7 +2632,7 @@ ACMD(do_show)
top_of_world + 1, top_of_zone_table + 1,
top_of_trigt + 1, top_shop + 1,
buf_largecount, total_quests,
buf_switches, buf_overflows
buf_switches, buf_overflows, global_lists->iSize
);
break;
@ -2742,6 +2749,21 @@ ACMD(do_show)
page_string(ch->desc, buf, TRUE);
break;
case 13:
len = strlcpy(buf, "Colours\r\n--------------------------\r\n", sizeof(buf));
k = 0;
for (r = 0; r < 6; r++)
for (g = 0; g < 6; g++)
for (b = 0; b < 6; b++) {
sprintf(colour, "F%d%d%d", r, g, b);
nlen = snprintf(buf + len, sizeof(buf) - len, "%s%s%s", ColourRGB(ch->desc, colour), colour, ++k % 6 == 0 ? "\tn\r\n" : " ");
if (len + nlen >= sizeof(buf))
break;
len += nlen;
}
page_string(ch->desc, buf, TRUE);
break;
/* show what? */
default:
send_to_char(ch, "Sorry, I don't understand that.\r\n");
@ -4135,7 +4157,7 @@ ACMD(do_copyover)
write_to_descriptor (d->descriptor, "\n\rSorry, we are rebooting. Come back in a few minutes.\n\r");
close_socket (d); /* throw'em out */
} else {
fprintf (fp, "%d %ld %s %s\n", d->descriptor, GET_PREF(och), GET_NAME(och), d->host);
fprintf (fp, "%d %ld %s %s %s\n", d->descriptor, GET_PREF(och), GET_NAME(och), d->host, CopyoverGet(d));
/* save och */
GET_LOADROOM(och) = GET_ROOM_VNUM(IN_ROOM(och));
Crash_rentsave(och,0);

View file

@ -81,6 +81,7 @@
#include "modify.h"
#include "quest.h"
#include "ibt.h" /* for free_ibt_lists */
#include "mud_event.h"
#ifndef INVALID_SOCKET
#define INVALID_SOCKET (-1)
@ -164,6 +165,8 @@ static RETSIGTYPE websterlink(int sig);
static size_t proc_colors(char *txt, size_t maxlen, int parse);
static void handle_webster_file();
static void msdp_update(void); /* KaVir plugin*/
/* externally defined functions, used locally */
#ifdef __CXREF__
#undef FD_ZERO
@ -390,7 +393,7 @@ void copyover_recover()
{
struct descriptor_data *d;
FILE *fp;
char host[1024];
char host[1024], guiopt[1024];
int desc, i, player_i;
bool fOld;
char name[MAX_INPUT_LENGTH];
@ -414,7 +417,7 @@ void copyover_recover()
for (;;) {
fOld = TRUE;
i = fscanf (fp, "%d %ld %s %s\n", &desc, &pref, name, host);
i = fscanf (fp, "%d %ld %s %s %s\n", &desc, &pref, name, host, guiopt);
if (desc == -1)
break;
@ -435,6 +438,8 @@ void copyover_recover()
d->connected = CON_CLOSE;
CopyoverSet(d,guiopt);
/* Now, find the pfile */
CREATE(d->character, struct char_data, 1);
clear_char(d->character);
@ -815,8 +820,12 @@ void game_loop(socket_t local_mother_desc)
for (d = descriptor_list; d; d = next_d) {
next_d = d->next;
if (FD_ISSET(d->descriptor, &input_set))
{
if ( d->pProtocol != NULL ) /* KaVir's plugin */
d->pProtocol->WriteOOB = 0; /* KaVir's plugin */
if (process_input(d) < 0)
close_socket(d);
}
}
/* Process commands we just read from process_input */
@ -950,6 +959,7 @@ void heartbeat(int heart_pulse)
script_trigger_check();
if (!(heart_pulse % PASSES_PER_SEC)) { /* EVERY second */
msdp_update();
next_tick--;
}
@ -1337,6 +1347,12 @@ size_t vwrite_to_output(struct descriptor_data *t, const char *format, va_list a
wantsize = size = vsnprintf(txt, sizeof(txt), format, args);
if (t->character)
wantsize = size = proc_colors(txt, sizeof(txt), COLOR_ON(t->character));
strcpy(txt, ProtocolOutput( t, txt, (int*)&wantsize )); /* <--- Add this line */
size = wantsize; /* <--- Add this line */
if ( t->pProtocol->WriteOOB > 0 ) /* <--- Add this line */
--t->pProtocol->WriteOOB; /* <--- Add this line */
/* If exceeding the size of the buffer, truncate it for the overflow message */
if (size < 0 || wantsize >= sizeof(txt)) {
size = sizeof(txt) - 1;
@ -1494,11 +1510,14 @@ static void init_descriptor (struct descriptor_data *newd, int desc)
*newd->output = '\0';
newd->bufptr = 0;
newd->has_prompt = 1; /* prompt is part of greetings */
STATE(newd) = CON_GET_NAME;
STATE(newd) = CON_GET_PROTOCOL;
CREATE(newd->history, char *, HISTORY_SIZE);
if (++last_desc == 1000)
last_desc = 1;
newd->desc_num = last_desc;
newd->pProtocol = ProtocolCreate(); /* KaVir's plugin*/
newd->events = create_list();
}
static int new_descriptor(socket_t s)
@ -1509,8 +1528,7 @@ static int new_descriptor(socket_t s)
struct descriptor_data *newd;
struct sockaddr_in peer;
struct hostent *from;
char greet_copy[MAX_STRING_LENGTH];
/* accept the new connection */
i = sizeof(peer);
if ((desc = accept(s, (struct sockaddr *) &peer, &i)) == INVALID_SOCKET) {
@ -1564,18 +1582,18 @@ static int new_descriptor(socket_t s)
}
/* initialize descriptor data */
init_descriptor(newd, desc);
init_descriptor(newd, desc);
/* prepend to list */
newd->next = descriptor_list;
descriptor_list = newd;
/* This is where the greetings are actually sent to the new player */
/* Adjusted by Jamdog to show color codes on the greetings page */
*greet_copy = '\0';
sprintf(greet_copy, "%s", GREETINGS);
proc_colors(greet_copy, MAX_STRING_LENGTH, TRUE);
write_to_output(newd, "%s", greet_copy);
/* Attach Event */
attach_mud_event(get_protocols, new_mud_event(EVENT_DESC, newd, NULL), 1.5 * PASSES_PER_SEC);
/* KaVir's plugin*/
write_to_output(newd, "Attempting to Detect Client, Please Wait...\r\n");
ProtocolNegotiate(newd);
return (0);
}
@ -1605,8 +1623,11 @@ static int process_output(struct descriptor_data *t)
if (STATE(t) == CON_PLAYING && t->character && !IS_NPC(t->character) && !PRF_FLAGGED(t->character, PRF_COMPACT))
strcat(osb, "\r\n"); /* strcpy: OK (osb:MAX_SOCK_BUF-2 reserves space) */
if (!t->pProtocol->WriteOOB)
{
/* add a prompt */
strcat(i, make_prompt(t)); /* strcpy: OK (i:MAX_SOCK_BUF reserves space) */
}
/* now, send the output. If this is an 'interruption', use the prepended
* CRLF, otherwise send the straight output sans CRLF. */
@ -1861,6 +1882,9 @@ static int process_input(struct descriptor_data *t)
char *ptr, *read_point, *write_point, *nl_pos = NULL;
char tmp[MAX_INPUT_LENGTH];
static char read_buf[MAX_PROTOCOL_BUFFER]; /* KaVir's plugin */
read_buf[0] = '\0'; /* KaVir's plugin */
/* first, find the point where we left off reading data */
buf_length = strlen(t->inbuf);
read_point = t->inbuf + buf_length;
@ -1872,7 +1896,14 @@ static int process_input(struct descriptor_data *t)
return (-1);
}
bytes_read = perform_socket_read(t->descriptor, read_point, space_left);
bytes_read = perform_socket_read(t->descriptor, read_buf, MAX_PROTOCOL_BUFFER);
if ( bytes_read >= 0 )
{
read_buf[bytes_read] = '\0';
ProtocolInput( t, read_buf, bytes_read, t->inbuf );
bytes_read = strlen(t->inbuf);
}
if (bytes_read < 0) /* Error, disconnect them. */
return (-1);
@ -2122,6 +2153,19 @@ void close_socket(struct descriptor_data *d)
free(d->showstr_head);
if (d->showstr_count)
free(d->showstr_vector);
/* KaVir's plugin*/
ProtocolDestroy( d->pProtocol );
/* Mud Events */
if (d->events->iSize > 0) {
struct event * pEvent;
while ((pEvent = simple_list(d->events)) != NULL)
event_cancel(pEvent);
}
free_list(d->events);
/*. Kill any OLC stuff .*/
switch (d->connected) {
@ -2794,3 +2838,66 @@ static void handle_webster_file(void) {
send_to_char(ch, "You get this feedback from Merriam-Webster:\r\n");
page_string(ch->desc, retval, 1);
}
/* KaVir's plugin*/
static void msdp_update( void )
{
struct descriptor_data *d;
int PlayerCount = 0;
char buf[MAX_STRING_LENGTH];
extern const char *pc_class_types[];
for (d = descriptor_list; d; d = d->next)
{
struct char_data *ch = d->character;
if ( ch && !IS_NPC(ch) && d->connected == CON_PLAYING )
{
struct char_data *pOpponent = FIGHTING(ch);
++PlayerCount;
MSDPSetString( d, eMSDP_CHARACTER_NAME, GET_NAME(ch) );
MSDPSetNumber( d, eMSDP_ALIGNMENT, GET_ALIGNMENT(ch) );
MSDPSetNumber( d, eMSDP_EXPERIENCE, GET_EXP(ch) );
MSDPSetNumber( d, eMSDP_HEALTH, GET_HIT(ch) );
MSDPSetNumber( d, eMSDP_HEALTH_MAX, GET_MAX_HIT(ch) );
MSDPSetNumber( d, eMSDP_LEVEL, GET_LEVEL(ch) );
sprinttype( ch->player.chclass, pc_class_types, buf, sizeof(buf) );
MSDPSetString( d, eMSDP_CLASS, buf );
MSDPSetNumber( d, eMSDP_MANA, GET_MANA(ch) );
MSDPSetNumber( d, eMSDP_MANA_MAX, GET_MAX_MANA(ch) );
MSDPSetNumber( d, eMSDP_WIMPY, GET_WIMP_LEV(ch) );
MSDPSetNumber( d, eMSDP_MONEY, GET_GOLD(ch) );
MSDPSetNumber( d, eMSDP_MOVEMENT, GET_MOVE(ch) );
MSDPSetNumber( d, eMSDP_MOVEMENT_MAX, GET_MAX_MOVE(ch) );
MSDPSetNumber( d, eMSDP_AC, compute_armor_class(ch) );
/* This would be better moved elsewhere */
if ( pOpponent != NULL )
{
int hit_points = (GET_HIT(pOpponent) * 100) / GET_MAX_HIT(pOpponent);
MSDPSetNumber( d, eMSDP_OPPONENT_HEALTH, hit_points );
MSDPSetNumber( d, eMSDP_OPPONENT_HEALTH_MAX, 100 );
MSDPSetNumber( d, eMSDP_OPPONENT_LEVEL, GET_LEVEL(pOpponent) );
MSDPSetString( d, eMSDP_OPPONENT_NAME, PERS(pOpponent, ch) );
}
else /* Clear the values */
{
MSDPSetNumber( d, eMSDP_OPPONENT_HEALTH, 0 );
MSDPSetNumber( d, eMSDP_OPPONENT_LEVEL, 0 );
MSDPSetString( d, eMSDP_OPPONENT_NAME, "" );
}
MSDPUpdate( d );
}
/* Ideally this should be called once at startup, and again whenever
* someone leaves or joins the mud. But this works, and it keeps the
* snippet simple. Optimise as you see fit.
*/
MSSPSetPlayers( PlayerCount );
}
}

View file

@ -320,6 +320,7 @@ const char *connected_types[] = {
"Quest edit",
"Preference edit",
"IBT edit",
"Protocol Detection",
"\n"
};

View file

@ -37,6 +37,7 @@
#include "shop.h"
#include "quest.h"
#include "ibt.h"
#include "mud_event.h"
#include <sys/stat.h>
/* declarations of most of the 'global' variables */
@ -628,6 +629,9 @@ void destroy_db(void)
/* Events */
event_free_all();
/* Lists */
free_list(world_events);
}
/* body of the booting system */
@ -639,6 +643,12 @@ void boot_db(void)
log("Resetting the game time:");
reset_time();
log("Initialize Global Lists");
global_lists = create_list();
log("Initializing Events");
init_events();
log("Reading news, credits, help, ihelp, bground, info & motds.");
file_to_string_alloc(NEWS_FILE, &news);

View file

@ -24,7 +24,7 @@
#include "dg_event.h"
#include "constants.h"
#include "comm.h" /* For access to the game pulse */
#include "mud_event.h"
/***************************************************************************
* Begin mud specific event queue functions
@ -65,6 +65,7 @@ struct event *event_create(EVENTFUNC(*func), void *event_obj, long when)
new_event->func = func;
new_event->event_obj = event_obj;
new_event->q_el = queue_enq(event_q, new_event, when + pulse);
new_event->isMudEvent = FALSE;
return new_event;
}
@ -85,10 +86,23 @@ void event_cancel(struct event *event)
queue_deq(event_q, event->q_el);
if (event->event_obj)
free(event->event_obj);
cleanup_event_obj(event);
free(event);
}
/* The memory freeing routine tied into the mud event system */
void cleanup_event_obj(struct event *event)
{
struct mud_event_data * mud_event;
if (event->isMudEvent) {
mud_event = (struct mud_event_data *) event->event_obj;
free_mud_event(mud_event);
} else
free(event->event_obj);
}
/** Process any events whose time has come. Should be called from, and at, every
* pulse of heartbeat. Re-enqueues multi-use events.
*/
@ -314,7 +328,8 @@ void queue_free(struct dg_queue *q)
if ((event = (struct event *) qe->data) != NULL)
{
if (event->event_obj)
free(event->event_obj);
cleanup_event_obj(event);
free(event);
}
free(qe);

View file

@ -33,6 +33,7 @@ struct event {
EVENTFUNC(*func); /**< The function called when this event comes up. */
void *event_obj; /**< event_obj is passed to func when func is called */
struct q_element *q_el; /**< Where this event is located in the queue */
bool isMudEvent; /**< used by the memory routines */
};
/**************************************************************************
* End event structures and defines.
@ -67,6 +68,7 @@ void event_cancel(struct event *event);
void event_process(void);
long event_time(struct event *event);
void event_free_all(void);
void cleanup_event_obj(struct event *event);
/* - queues - function protos need by other modules */
struct dg_queue *queue_init(void);

View file

@ -79,6 +79,7 @@ static IBT_DATA *new_ibt(void)
ibtData->level = 0;
ibtData->id_num = NOBODY;
ibtData->room = NOWHERE;
ibtData->dated = 0;
for (i=0; i<IBT_ARRAY_MAX; i++)
ibtData->flags[i] = 0;
@ -117,7 +118,7 @@ static void free_ibt_list(IBT_DATA *first_ibt, IBT_DATA *last_ibt)
static IBT_DATA *read_ibt( char *filename, FILE *fp )
{
IBT_DATA *ibtData;
char *word, *id_num=NULL;
char *word, *id_num=NULL, *dated=NULL;
char buf[MAX_STRING_LENGTH];
bool fMatch, flgCheck;
char letter;
@ -150,13 +151,20 @@ static IBT_DATA *read_ibt( char *filename, FILE *fp )
if (!str_cmp(word, "Body")) STRFREE(ibtData->body);
KEY("Body", ibtData->body, fread_clean_string( fp, buf ));
break;
case 'D':
TXT_KEY("Dated", dated, fread_line(fp));
break;
case 'E':
if (!str_cmp(word, "End"))
{
if ( id_num )
if ( id_num ) {
ibtData->id_num = atol(id_num);
STRFREE( id_num );
}
if ( dated ) {
ibtData->dated = atol(dated);
STRFREE( dated );
}
if ( !ibtData->name )
ibtData->name = STRALLOC("");
if ( !ibtData->text )
@ -219,7 +227,11 @@ static IBT_DATA *read_ibt( char *filename, FILE *fp )
STRFREE( ibtData->text);
if ( ibtData->body)
STRFREE( ibtData->body);
if ( id_num )
STRFREE( id_num );
if ( dated )
STRFREE( dated );
DISPOSE( ibtData);
return NULL;
}
@ -316,6 +328,8 @@ void save_ibt_file(int mode)
fprintf(fp,"Notes %s~\n",ibtData->notes);
if (ibtData->id_num != NOBODY)
fprintf(fp,"IdNum %ld\n",ibtData->id_num);
if (ibtData->dated != 0)
fprintf(fp,"Dated %ld\n",ibtData->dated);
fprintf(fp,"Level %d\n",ibtData->level);
fprintf(fp,"Room %d\n",ibtData->room);
fprintf(fp,"Flags %d %d %d %d\n",ibtData->flags[0],ibtData->flags[1],
@ -504,6 +518,7 @@ ACMD(do_ibt)
} else {
send_to_char(ch, "%s%s by %s%s\r\n",QCYN, ibt_types[subcmd], QYEL, ibtData->name);
send_to_char(ch, "%sSubmitted: %s%s", QCYN, QYEL, ibtData->dated ? ctime(&ibtData->dated) : "Unknown\r\n");
if (GET_LEVEL(ch) >= LVL_IMMORT) {
send_to_char(ch, "%sLevel: %s%d\r\n",QCYN, QYEL, ibtData->level);
send_to_char(ch, "%sRoom : %s%d\r\n",QCYN, QYEL, ibtData->room);
@ -640,6 +655,8 @@ ACMD(do_ibt)
ibtData->text = STRALLOC(arg_text);
ibtData->name = STRALLOC(GET_NAME(ch));
ibtData->id_num = GET_IDNUM(ch);
ibtData->dated = time(0);
switch(subcmd) {
case SCMD_BUG : LINK( ibtData, first_bug, last_bug, next, prev );
break;

View file

@ -81,6 +81,7 @@ struct ibt_data
room_vnum room; /**< Room in which this IBT was reported */
long id_num; /**< The ID number of the player who logged it */
int flags[IBT_ARRAY_MAX]; /**< IBT flags */
long dated; /**< When the IBT what reported */
};
extern IBT_DATA *first_bug;

View file

@ -38,6 +38,7 @@
#include "asciimap.h"
#include "prefedit.h"
#include "ibt.h"
#include "mud_event.h"
/* local (file scope) functions */
static int perform_dupe_check(struct descriptor_data *d);
@ -1138,6 +1139,7 @@ static int perform_dupe_check(struct descriptor_data *d)
REMOVE_BIT_AR(PLR_FLAGS(d->character), PLR_WRITING);
REMOVE_BIT_AR(AFF_FLAGS(d->character), AFF_GROUP);
STATE(d) = CON_PLAYING;
MXPSendTag( d, "<VERSION>" );
switch (mode) {
case RECON:
@ -1267,6 +1269,43 @@ int enter_player_game (struct descriptor_data *d)
return load_result;
}
EVENTFUNC(get_protocols)
{
struct descriptor_data *d;
struct mud_event_data *pMudEvent;
char buf[MAX_STRING_LENGTH];
int len;
if (event_obj == NULL)
return 0;
pMudEvent = (struct mud_event_data *) event_obj;
d = (struct descriptor_data *) pMudEvent->pStruct;
/* Clear extra white space from the "protocol scroll" */
write_to_output(d, "");
len = snprintf(buf, MAX_STRING_LENGTH, "\tO[\toClient\tO] \tw%s\tn | ", d->pProtocol->pVariables[eMSDP_CLIENT_ID]->pValueString);
if (d->pProtocol->pVariables[eMSDP_XTERM_256_COLORS]->ValueInt)
len += snprintf(buf + len, MAX_STRING_LENGTH - len, "\tO[\toColors\tO] \tw256\tn | ");
else if (d->pProtocol->pVariables[eMSDP_ANSI_COLORS]->ValueInt)
len += snprintf(buf + len, MAX_STRING_LENGTH - len, "\tO[\toColors\tO] \twAnsi\tn | ");
else
len += snprintf(buf + len, MAX_STRING_LENGTH - len, "[Colors] No Color | ");
len += snprintf(buf + len, MAX_STRING_LENGTH - len, "\tO[\toMXP\tO] \tw%s\tn | ", d->pProtocol->bMXP ? "Yes" : "No");
len += snprintf(buf + len, MAX_STRING_LENGTH - len, "\tO[\toMSDP\tO] \tw%s\tn | ", d->pProtocol->bMSDP ? "Yes" : "No");
len += snprintf(buf + len, MAX_STRING_LENGTH - len, "\tO[\toATCP\tO] \tw%s\tn\r\n\r\n", d->pProtocol->bATCP ? "Yes" : "No");
write_to_output(d, buf, 0);
write_to_output(d, GREETINGS, 0);
STATE(d) = CON_GET_NAME;
free_mud_event(pMudEvent);
return 0;
}
/* deal with newcomers and other non-playing sockets */
void nanny(struct descriptor_data *d, char *arg)
{
@ -1304,6 +1343,10 @@ void nanny(struct descriptor_data *d, char *arg)
/* Not in OLC. */
switch (STATE(d)) {
case CON_GET_PROTOCOL:
write_to_output(d, "Collecting Protocol Information... Please Wait.\r\n");
return;
break;
case CON_GET_NAME: /* wait for input of name */
if (d->character == NULL) {
CREATE(d->character, struct char_data, 1);
@ -1619,6 +1662,7 @@ void nanny(struct descriptor_data *d, char *arg)
act("$n has entered the game.", TRUE, d->character, 0, 0, TO_ROOM);
STATE(d) = CON_PLAYING;
MXPSendTag( d, "<VERSION>" );
if (GET_LEVEL(d->character) == 0) {
do_start(d->character);
send_to_char(d->character, "%s", CONFIG_START_MESSG);

View file

@ -21,6 +21,7 @@
#include "class.h"
#include "fight.h"
#include "screen.h"
#include "mud_event.h"
/* local file scope function prototypes */
static int graf(int grafage, int p0, int p1, int p2, int p3, int p4, int p5, int p6);
@ -527,3 +528,31 @@ int decrease_bank(struct char_data *ch, int deduction)
increase_bank(ch, amt);
return (GET_BANK_GOLD(ch));
}
EVENTFUNC(display_usage)
{
struct descriptor_data * d;
struct char_data * tch;
struct list_data * player_list;
player_list = create_list();
for (d = descriptor_list; d; d = d->next)
if (d->character && STATE(d) == CON_PLAYING)
add_to_list(d->character, player_list);
game_info("News:");
game_info("Currently %d Players Online", player_list->iSize);
if (player_list->iSize) {
tch = (struct char_data *) random_from_list(player_list);
if (player_list->iSize == 1)
game_info("%s is apparently very lonely.", GET_NAME(tch));
else
game_info("%s last seen at %s", GET_NAME(tch), world[IN_ROOM(tch)].name);
}
free_list(player_list);
return (10 * 60 * PASSES_PER_SEC);
}

View file

@ -75,6 +75,24 @@ void smash_tilde(char *str)
*p=' ';
}
/* Parse out the @ character and replace it with the '\t' to work with
* KaVir's protocol snippet */
void parse_at(char *str)
{
char *p = str;
for (; *p; p++)
if (*p == '@')
*p = '\t';
}
void parse_tab(char *str)
{
char *p = str;
for (; *p; p++)
if (*p == '\t')
*p = '@';
}
/* Basic API function to start writing somewhere. 'data' isn't used, but you
* can use it to pass whatever else you may want through it. The improved
* editor patch when updated could use it to pass the old text buffer, for

View file

@ -22,6 +22,8 @@
/* Public functions */
void show_string(struct descriptor_data *d, char *input);
void smash_tilde(char *str);
void parse_at(char *str);
void parse_tab(char *str);
void paginate_string(char *str, struct descriptor_data *d);
/** @todo should this really be in modify.c? */
ACMD(do_skillset);

View file

@ -293,29 +293,29 @@ static void qedit_disp_menu(struct descriptor_data *d)
break;
}
write_to_output(d,
"-- Quest Number : @n[@c%6d@n]\r\n"
"@g 1@n) Quest Name : @y%s\r\n"
"@g 2@n) Description : @y%s\r\n"
"@g 3@n) Accept Message\r\n@y%s"
"@g 4@n) Completion Message\r\n@y%s"
"@g 5@n) Quit Message\r\n@y%s"
"@g 6@n) Quest Flags : @c%s\r\n"
"@g 7@n) Quest Type : @c%s %s\r\n"
"@g 8@n) Quest Master : [@c%6d@n] @y%s\r\n"
"@g 9@n) Quest Target : [@c%6d@n] @y%s\r\n"
"@g A@n) Quantity : [@c%6d@n]\r\n"
"@n Quest Point Rewards\r\n"
"@g B@n) Completed : [@c%6d@n] @g C@n) Abandoned : [@c%6d@n]\r\n"
"@n Other Rewards Rewards\r\n"
"@g G@n) Gold Coins : [@c%6d@n] @g T@n) Exp Points : [@c%6d@n] @g O@n) Object : [@c%6d@n]\r\n"
"@n Level Limits to Accept Quest\r\n"
"@g D@n) Lower Level : [@c%6d@n] @g E@n) Upper Level : [@c%6d@n]\r\n"
"@g F@n) Prerequisite : [@c%6d@n] @y%s\r\n"
"@g L@n) Time Limit : [@c%6d@n]\r\n"
"@g N@n) Next Quest : [@c%6d@n] @y%s\r\n"
"@g P@n) Previous Quest : [@c%6d@n] @y%s\r\n"
"@g X@n) Delete Quest\r\n"
"@g Q@n) Quit\r\n"
"-- Quest Number : \tn[\tc%6d\tn]\r\n"
"\tg 1\tn) Quest Name : \ty%s\r\n"
"\tg 2\tn) Description : \ty%s\r\n"
"\tg 3\tn) Accept Message\r\n\ty%s"
"\tg 4\tn) Completion Message\r\n\ty%s"
"\tg 5\tn) Quit Message\r\n\ty%s"
"\tg 6\tn) Quest Flags : \tc%s\r\n"
"\tg 7\tn) Quest Type : \tc%s %s\r\n"
"\tg 8\tn) Quest Master : [\tc%6d\tn] \ty%s\r\n"
"\tg 9\tn) Quest Target : [\tc%6d\tn] \ty%s\r\n"
"\tg A\tn) Quantity : [\tc%6d\tn]\r\n"
"\tn Quest Point Rewards\r\n"
"\tg B\tn) Completed : [\tc%6d\tn] \tg C\tn) Abandoned : [\tc%6d\tn]\r\n"
"\tn Other Rewards Rewards\r\n"
"\tg G\tn) Gold Coins : [\tc%6d\tn] \tg T\tn) Exp Points : [\tc%6d\tn] \tg O\tn) Object : [\tc%6d\tn]\r\n"
"\tn Level Limits to Accept Quest\r\n"
"\tg D\tn) Lower Level : [\tc%6d\tn] \tg E\tn) Upper Level : [\tc%6d\tn]\r\n"
"\tg F\tn) Prerequisite : [\tc%6d\tn] \ty%s\r\n"
"\tg L\tn) Time Limit : [\tc%6d\tn]\r\n"
"\tg N\tn) Next Quest : [\tc%6d\tn] \ty%s\r\n"
"\tg P\tn) Previous Quest : [\tc%6d\tn] \ty%s\r\n"
"\tg X\tn) Delete Quest\r\n"
"\tg Q\tn) Quit\r\n"
"Enter Choice : ",
quest->vnum,
quest->name,

View file

@ -248,9 +248,9 @@ static void sedit_compact_rooms_menu(struct descriptor_data *d)
clear_screen(d);
for (i = 0; S_ROOM(shop, i) != NOWHERE; i++) {
if (real_room(S_ROOM(shop, i)) != NOWHERE) {
write_to_output(d, "%2d - [@c%5d@n] - @y%s@n\r\n", i, S_ROOM(shop, i), world[real_room(S_ROOM(shop, i))].name);
write_to_output(d, "%2d - [@\t%5d\tn] - \ty%s\tn\r\n", i, S_ROOM(shop, i), world[real_room(S_ROOM(shop, i))].name);
} else {
write_to_output(d, "%2d - [@R!Removed Room!@n]\r\n", i);
write_to_output(d, "%2d - [\tR!Removed Room!\tn]\r\n", i);
}
}
write_to_output(d, "\r\n"

View file

@ -85,7 +85,7 @@ static char *times_message(struct obj_data *obj, char *name, int num);
static int buy_price(struct obj_data *obj, int shop_nr, struct char_data *keeper, struct char_data *buyer);
static int sell_price(struct obj_data *obj, int shop_nr, struct char_data *keeper, struct char_data *seller);
static int ok_shop_room(int shop_nr, room_vnum room);
static int add_to_list(struct shop_buy_data *list, int type, int *len, int *val);
static int add_to_shop_list(struct shop_buy_data *list, int type, int *len, int *val);
static int end_read_list(struct shop_buy_data *list, int len, int error);
static void read_line(FILE *shop_f, const char *string, void *data);
@ -532,14 +532,18 @@ static void shopping_buy(char *arg, struct char_data *ch, struct char_data *keep
}
}
}
if (IS_CARRYING_N(ch) + 1 > CAN_CARRY_N(ch)) {
send_to_char(ch, "%s: You can't carry any more items.\r\n", fname(obj->name));
return;
}
if (IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj) > CAN_CARRY_W(ch)) {
send_to_char(ch, "%s: You can't carry that much weight.\r\n", fname(obj->name));
return;
if (IS_NPC(ch) || (!IS_NPC(ch) && !PRF_FLAGGED(ch, PRF_NOHASSLE))) {
if (IS_CARRYING_N(ch) + 1 > CAN_CARRY_N(ch)) {
send_to_char(ch, "%s: You can't carry any more items.\r\n", fname(obj->name));
return;
}
if (IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj) > CAN_CARRY_W(ch)) {
send_to_char(ch, "%s: You can't carry that much weight.\r\n", fname(obj->name));
return;
}
}
if (OBJ_FLAGGED(obj, ITEM_QUEST)) {
while (obj &&
(GET_QUESTPOINTS(ch) >= GET_OBJ_COST(obj) || IS_GOD(ch))
@ -1019,7 +1023,7 @@ int ok_damage_shopkeeper(struct char_data *ch, struct char_data *victim)
}
/* val == obj_vnum and obj_rnum (?) */
static int add_to_list(struct shop_buy_data *list, int type, int *len, int *val)
static int add_to_shop_list(struct shop_buy_data *list, int type, int *len, int *val)
{
if (*val != NOTHING && *val >= 0) { /* necessary after changing to unsigned v/rnums -- Welcor */
if (*len < MAX_SHOP_OBJ) {
@ -1066,12 +1070,12 @@ static int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format,
read_line(shop_f, "%d", &temp);
if (temp < 0) /* Always "-1" the string. */
break;
error += add_to_list(list, type, &len, &temp);
error += add_to_shop_list(list, type, &len, &temp);
}
} else
for (count = 0; count < max; count++) {
read_line(shop_f, "%d", &temp);
error += add_to_list(list, type, &len, &temp);
error += add_to_shop_list(list, type, &len, &temp);
}
return (end_read_list(list, len, error));
}
@ -1115,7 +1119,7 @@ static int read_type_list(FILE *shop_f, struct shop_buy_data *list,
ptr++;
while (isspace(*(END_OF(ptr) - 1)))
*(END_OF(ptr) - 1) = '\0';
error += add_to_list(list, LIST_TRADE, &len, &num);
error += add_to_shop_list(list, LIST_TRADE, &len, &num);
if (*ptr)
BUY_WORD(list[len - 1]) = strdup(ptr);
} while (num >= 0);

View file

@ -452,7 +452,7 @@ SPECIAL(guild_guard)
/* Allow the people of the guild through. */
if (!IS_NPC(ch) && GET_CLASS(ch) == guild_info[i].pc_class)
continue;
send_to_char(ch, "%s", buf);
act(buf2, FALSE, ch, 0, 0, TO_ROOM);
return (TRUE);

View file

@ -12,6 +12,9 @@
#ifndef _STRUCTS_H_
#define _STRUCTS_H_
#include "protocol.h" /* Kavir Plugin*/
#include "lists.h"
/** Intended use of this macro is to allow external packages to work with a
* variety of versions without modifications. For instance, an IS_CORPSE()
* macro was introduced in pl13. Any future code add-ons could take into
@ -326,6 +329,7 @@
#define CON_QEDIT 28 /**< OLC mode - quest edit */
#define CON_PREFEDIT 29 /**< OLC mode - preference edit */
#define CON_IBTEDIT 30 /**< OLC mode - idea/bug/typo edit */
#define CON_GET_PROTOCOL 31 /**< Used at log-in while attempting to get protocols > */
/* OLC States range - used by IS_IN_OLC and IS_PLAYING */
#define FIRST_OLC_STATE CON_OEDIT /**< The first CON_ state that is an OLC */
@ -1031,6 +1035,8 @@ struct char_data
struct char_data *master; /**< List of character being followed */
long pref; /**< unique session id */
struct list_data * events;
};
/** descriptor-related structures */
@ -1085,6 +1091,9 @@ struct descriptor_data
struct descriptor_data *snoop_by; /**< And who is snooping this char */
struct descriptor_data *next; /**< link to next descriptor */
struct oasis_olc_data *olc; /**< OLC info */
protocol_t *pProtocol; /**< Kavir plugin */
struct list_data * events;
};
/* other miscellaneous structures */

View file

@ -809,8 +809,9 @@ int count_color_chars(char *string)
len = strlen(string);
for (i = 0; i < len; i++) {
while (string[i] == '@') {
if (string[i + 1] == '@')
while (string[i] == '\t' || string[i] == '@') {
if ((string[i] == '\t' && string[i + 1] == '\t') ||
(string[i] == '@' && string[i + 1] == '@'))
num++;
else
num += 2;
@ -1290,6 +1291,7 @@ IDXTYPE atoidx( const char *str_to_conv )
return (IDXTYPE) result;
}
#define isspace_ignoretabs(c) ((c)!='\t' && isspace(c))
/*
strfrmt (String Format) function
@ -1316,17 +1318,17 @@ char *strfrmt(char *str, int w, int h, int justify, int hpad, int vpad)
/* Split into lines, including convert \\ into \r\n */
while(*sp) {
/* eat leading space */
while(*sp && isspace(*sp)) sp++;
while(*sp && isspace_ignoretabs(*sp)) sp++;
/* word begins */
wp = sp;
wlen = 0;
while(*sp) { /* Find the end of the word */
if(isspace(*sp)) break;
if(isspace_ignoretabs(*sp)) break;
if(*sp=='\\' && sp[1] && sp[1]=='\\') {
if(sp!=wp)
break; /* Finish dealing with the current word */
sp += 2; /* Eat the marker and any trailing space */
while(*sp && isspace(*sp)) sp++;
while(*sp && isspace_ignoretabs(*sp)) sp++;
wp = sp;
/* Start a new line */
if(hpad)
@ -1345,6 +1347,18 @@ char *strfrmt(char *str, int w, int h, int justify, int hpad, int vpad)
if (*sp=='@' && (sp[1]!=*sp)) /* Color code, not @@ */
last_color = sp[1];
sp += 2; /* Eat the whole code regardless */
} else if (*sp=='\t'&&sp[1]) {
char MXPcode = sp[1]=='[' ? ']' : sp[1]=='<' ? '>' : '\0';
if (!MXPcode)
last_color = sp[1];
sp += 2; /* Eat the code */
if (MXPcode)
{
while (*sp!='\0'&&*sp!=MXPcode)
++sp; /* Eat the rest of the code */
}
} else {
wlen++;
sp++;
@ -1355,7 +1369,7 @@ char *strfrmt(char *str, int w, int h, int justify, int hpad, int vpad)
if(hpad)
for(; llen < w; llen++)
*lp++ = ' ';
*lp++ = '@'; /* 'normal' color */
*lp++ = '\t'; /* 'normal' color */
*lp++ = 'n';
*lp++ = '\r'; /* New line */
*lp++ = '\n';
@ -1366,7 +1380,7 @@ char *strfrmt(char *str, int w, int h, int justify, int hpad, int vpad)
lcount++;
lp = line;
if (last_color != 'n') {
*lp++ = '@'; /* restore previous color */
*lp++ = '\t'; /* restore previous color */
*lp++ = last_color;
new_line_started = TRUE;
}