This is not a complete list for Smaug1.4a since I have made some bug changes already,
before I started this webpage up. But if you have some changes I missed please send them
to me and I will add them to this page.
-Nivek
/*
* Generate a random number.
* Ooops was (number_mm() % to) + from which doesn't work -Shaddai
*/
int number_range( int from, int to )
{
if ( (to-from) < 1 )
return from;
return ((number_mm() % (to-from+1)) + from);
}
/*
* Generate a percentile roll.
* number_mm() % 100 only does 0-99, changed to do 1-100 -Shaddai
*/
int number_percent( void )
{
return (number_mm() % 100)+1;
}
DELETE: fchmod(fileno(fp), S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | S_IROTH|S_IWOTH);
CHANGE:
if ( !str_cmp( arg2, "filename" ) )
{
DISPOSE( council->filename );
To:
if ( !str_cmp( arg2, "filename" ) )
{
if ( council->filename && council->filename[0] != '\0' )
DISPOSE( council->filename );
Then around line 218 in save_council change:
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 );
if ( council->head2 != NULL)
fprintf (fp, "Head2 %s~\n", council->head2);
fprintf( fp, "Members %d\n", council->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" );
To:
fprintf( fp, "#COUNCIL\n" );
if ( council-> name )
fprintf( fp, "Name %s~\n", council->name );
if ( council->filename )
fprintf( fp, "Filename %s~\n", council->filename );
if ( council->description )
fprintf( fp, "Description %s~\n", council->description );
if ( council->head )
fprintf( fp, "Head %s~\n", council->head );
if ( council->head2 != NULL)
fprintf (fp, "Head2 %s~\n", council->head2);
fprintf( fp, "Members %d\n", council->members );
fprintf( fp, "Board %d\n", council->board );
fprintf( fp, "Meeting %d\n", council->meeting );
if ( council->powers )
fprintf( fp, "Powers %s~\n", council->powers );
fprintf( fp, "End\n\n" );
fprintf( fp, "#END\n" );
BEFORE: for ( x = 0; x < MAX_CLASS; x++ ) Change to: for ( x = 0; x < MAX_PC_CLASS; x++ )
BEFORE:
act( AT_TELL, "You tell $N '$t'", ch, argument, victim, TO_CHAR );
position = victim->position;
ADD:
/* Bug fix by guppy@wavecomputers.net */
MOBtrigger = FALSE;
AFTER:
else
act( AT_TELL, "$n tells you '$t'", ch, argument, victim, TO_VICT );
ADD:
MOBtrigger = TRUE;
Then do similar things for do_whisper and do_retell
/* short cut crash bug fix provided by gfinello@mail.karmanet.it*/
typedef enum {
relMSET_ON, relOSET_ON
} relation_type;
typedef struct rel_data REL_DATA;
struct rel_data {
void *Actor;
void *Subject;
REL_DATA *next;
REL_DATA *prev;
relation_type Type;
};
Then around line 4533 right after /* build.c */ add the following:
void RelCreate( relation_type, void *, void * ); void RelDestroy( relation_type, void *, void * );
Next open up build.c and around line 31 add the following:
REL_DATA *first_relation = NULL; REL_DATA *last_relation = NULL;
Then at the end of build.c add the following:
/*
* Relations created to fix a crash bug with oset on and rset on
* code by: gfinello@mail.karmanet.it
*/
void RelCreate( relation_type tp, void *actor, void *subject ) {
REL_DATA *tmp;
if ( tp < relMSET_ON || tp > relOSET_ON ) {
bug( "RelCreate: invalid type (%d)", tp );
return;
}
if ( !actor ) {
bug( "RelCreate: NULL actor" );
return;
}
if ( !subject ) {
bug( "RelCreate: NULL subject" );
return;
}
for ( tmp = first_relation; tmp; tmp = tmp->next )
if ( tmp->Type == tp && tmp->Actor == actor && tmp->Subject ==
subject ) {
bug( "RelCreate: duplicated relation" );
return;
}
CREATE( tmp, REL_DATA, 1 );
tmp->Type = tp;
tmp->Actor = actor;
tmp->Subject = subject;
LINK( tmp, first_relation, last_relation, next, prev );
}
/*
* Relations created to fix a crash bug with oset on and rset on
* code by: gfinello@mail.karmanet.it
*/
void RelDestroy( relation_type tp, void *actor, void *subject ) {
REL_DATA * rq;
if ( tp < relMSET_ON || tp > relOSET_ON ) {
bug( "RelDestroy: invalid type (%d)", tp );
return;
}
if ( !actor ) {
bug( "RelDestroy: NULL actor" );
return;
}
if ( !subject ) {
bug( "RelDestroy: NULL subject" );
return;
}
for ( rq = first_relation; rq; rq = rq->next )
if ( rq->Type == tp && rq->Actor == actor && rq->Subject == subject ) {
UNLINK( rq, first_relation, last_relation, next, prev );
/* Dispose will also set to NULL the passed parameter */
DISPOSE( rq );
break;
}
}
Next in do_mset find the following line which should be
around line 1104
if ( ch->substate == SUB_REPEATCMD )
Change:
if ( char_died(victim) )
{
send_to_char( "Your victim died!\n\r", ch );
victim = NULL;
argument = "done";
}
TO:
if ( !victim )
{
send_to_char( "Your victim died!\n\r", ch );
argument = "done";
}
Then find the following line which should be around line 1123
if ( !str_cmp( argument, "done" ) || !str_cmp(
argument, "off" ) )
Then add the following two lines right before the send_to_char line
if ( ch->dest_buf )
RelDestroy( relMSET_ON, ch, ch->dest_buf );
Next in do_mset find the following line which should be around line 1237
if ( !str_cmp( arg2, "on") )
Right before the return after that statement (around 1254) add the following:
RelCreate( relMSET_ON, ch, victim );
Ok, now we have to do oset :)
In do_oset find the following line which should be around line 3017
Change:
if ( ch->substate == SUB_REPEATCMD )
{
obj = ch->dest_buf;
if ( obj && obj_extracted(obj) )
{
send_to_char( "Your object was extracted!\n\r", ch );
obj = NULL;
argument = "done";
}
TO:
if ( ch->substate == SUB_REPEATCMD )
{
obj = ch->dest_buf;
if ( !obj )
{
send_to_char( "Your object was extracted!\n\r", ch );
argument = "done";
}
Next find the following around line 3035:
if ( !str_cmp( argument, "done" ) || !str_cmp( argument, "off" ) )
Add the following above the send_to_char line:
if ( ch->dest_buf )
RelDestroy( relOSET_ON, ch, ch->dest_buf );
Next find the following around line 3122:
if ( !str_cmp( arg2, "on" ) )
{
ch_printf( ch, "Oset mode on. (Editing '%s' vnum %d).\n\r",
obj->name, obj->pIndexData->vnum );
Right before the return; add the following:
RelCreate( relOSET_ON, ch, obj );
Now open up handler.c around line 36 right after:
extern OBJ_DATA * gobj_prev; Add: extern REL_DATA * first_relation; extern REL_DATA * last_relation;
Next go to extract_char and around line 1717:
After:
ROOM_INDEX_DATA *location;
Add:
REL_DATA *RQueue, *rq_next;
Next in extract_char around line 1747:
After:
/* shove onto extraction queue */
queue_extracted_char( ch, fPull );
Add:
for ( RQueue = first_relation; RQueue; RQueue = rq_next ) {
rq_next = RQueue->next;
if ( fPull && RQueue->Type == relMSET_ON ) {
if ( ch == RQueue->Subject )
( ( CHAR_DATA * ) RQueue->Actor )->dest_buf = NULL;
else if ( ch != RQueue->Actor )
continue;
UNLINK( RQueue, first_relation, last_relation, next, prev );
DISPOSE( RQueue );
}
}
Next in extract_obj around line 1636:
After:
OBJ_DATA *obj_content;
Add:
REL_DATA *RQueue, *rq_next;
Next around line 1687:
After:
if ( obj == gobj_prev )
gobj_prev = obj->prev;
Add:
for ( RQueue = first_relation; RQueue; RQueue = rq_next ) {
rq_next = RQueue->next;
if ( RQueue->Type == relOSET_ON ) {
if ( obj == RQueue->Subject )
( ( CHAR_DATA * ) RQueue->Actor )->dest_buf = NULL;
else
continue;
UNLINK( RQueue, first_relation, last_relation, next, prev );
DISPOSE( RQueue );
}
}
Open up handler.c and go to line 3520 and Change:
STRFREE( obj->name );
STRFREE( obj->description );
STRFREE( obj->short_descr );
DISPOSE( obj );
To:
STRFREE( obj->name );
STRFREE( obj->description );
STRFREE( obj->short_descr );
STRFREE( obj->action_desc );
DISPOSE( obj );
pager_printf( ch,
"You have scored %s exp, and have %s gold coins.\n\r",
num_punct(ch->exp), num_punct(ch->gold) );
*** To:
pager_printf(ch, "You have scored %s exp, and have ",num_punct(ch->exp)); pager_printf(ch, "%s gold coins.\n\r", num_punct(ch->gold) );
Then in update.c starting at line 2291
*** Change from:
sprintf(buf, "The auctioneer pays you %s gold, charging an auction fee of %s.\n\r",
num_punct(pay),
num_punct(tax) );
send_to_char(buf, auction->seller);
*** To:
ch_printf( auction->seller, "The auctioneer pays you %s gold, charging an auction fee of ",
num_punct(pay));
ch_printf( auction->seller, "%s.\n\r", num_punct(tax));
*** Note the send_to_char(buf, auction->seller); line was deleted.
if ( is_mage )
chance += 5;
else
chance -= 15;
if ( ch == victim )
{
if ( ch->first_affect )
And right before the if ( ch == victim ) add the following:
/* Bug Fix to prevent possesed mobs from being dispelled -Shaddai */
if ( IS_NPC(victim) && IS_AFFECTED( victim, AFF_POSSESS) )
{
immune_casting ( skill, ch, victim, NULL );
return rVICT_IMMUNE;
}
*** Remove the following lines:
Around line 554:
if ( (paf->location % REVERSE_APPLY) == APPLY_REMOVESPELL )
return;
*** Then Remove the line 576:
case APPLY_WEARSPELL: /* affect only on wear */ return;
and ADD after case APPLY_REMOVE:
default: break;
Then in the if check starting at line 692....
*** Change from:
if ( IS_SET(ch->in_room->room_flags, ROOM_NO_MAGIC)
|| IS_SET(ch->immune, RIS_MAGIC)
|| saving_char == ch /* so save/quit doesn't trigger */
|| loading_char == ch ) /* so loading doesn't trigger */
return;
*** To:
if ( IS_SET(ch->in_room->room_flags, ROOM_NO_MAGIC)
|| IS_SET(ch->immune, RIS_MAGIC)
|| ( ( paf->location % REVERSE_APPLY ) == APPLY_WEARSPELL && !fAdd )
|| ( ( paf->location % REVERSE_APPLY ) == APPLY_REMOVESPELL && !fAdd )
|| saving_char == ch /* so save/quit doesn't trigger */
|| loading_char == ch ) /* so loading doesn't trigger */
return;
Open up comm.c and in write_to_buffer around line 1380
CHANGE:
if (d->outsize > 32000)
{
/* empty buffer */
d->outtop = 0;
close_socket(d, TRUE);
bug("Buffer overflow. Closing (%s).", d->character ? d->character->name : "???" );
return;
}
TO:
if (d->outsize > 32000)
{
/* empty buffer */
d->outtop = 0;
bug("Buffer overflow. Closing (%s).", d->character ? d->character->name : "???" );
close_socket(d, TRUE);
return;
}
Open up mud.h and in affect_data around line 1300
CHANGE:
sh_int duration;
TO:
int duration;
THEN:
make sure you recompile the whole mud (make clean)
AFTER:
if ( level <= victim->level )
{
int sn;
char buf[MAX_INPUT_LENGTH];
set_char_color( AT_IMMORT, victim );
ADD:
if ( victim->level <= LEVEL_AVATAR && IS_IMMORTAL(victim)) {
if ( victim->pcdata->bestowments )
DISPOSE( victim->pcdata->bestowments );
victim->pcdata->bestowments = str_dup("");
xREMOVE_BIT( victim->act, PLR_HOLYLIGHT );
if ( !IS_RETIRED( victim ) ) {
sprintf( buf, "%s%s", GOD_DIR, capitalize(victim->name) );
remove( buf );
}
}
CHANGE: "grip", "scribe", "brew", "wearspell", "removespell", "mentalstate", "emotion", TO: "grip", "scribe", "brew", "wearspell", "removespell", "emotion", "mentalstate",
Which is just switching mentalstate with emotion.
CHANGE:
case DFND_DISPELMAGIC:
if ( ch->first_affect )
TO:
/* Thanks to guppy@wavecomputers.net for catching this */
case DFND_DISPELMAGIC:
if ( victim->first_affect )
AFTER:
if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
{
act( AT_TELL, "$n tells you 'You don't have that item.'",
keeper, NULL, ch, TO_VICT );
ch->reply = keeper;
return;
}
ADD:
/* Bug report and solution thanks to animal@netwin.co.nz */
if ( !can_see_obj( keeper, obj) ) {
send_to_char("What are you trying to sell me? I don't buy thin air!\n\r", ch );
return;
}
extract_obj( obj );
***ADD:
separate_obj(obj);
In do_empty find the line marked: || xIS_SET( ch->act, PLR_LITTERBUG ) )
which should be around line 1606 in misc.c.
Change to:
|| (!IS_NPC( ch )
|| xIS_SET( ch->act, PLR_LITTERBUG ) ) )
*** Change from:
if ( arg1[0] == '\0' )
{
send_to_char( "Syntax: showrace \n\r", ch );
/* Show the races code addition by Blackmane */
for ( i=0;i<MAX_RACE;i++) i { if (i>9 )
pager_printf(ch, "%d> %-11s",i,race_table[i]->race_name );
else
pager_printf(ch, "%d> %-12s",i,race_table[i]->race_name);
if ( i%5==0 )
send_to_pager("\n\r", ch );
}
send_to_pager("\n\r", ch );
return;
}
*** To:
if ( arg1[0] == '\0' )
{
send_to_char( "Syntax: showrace \n\r", ch );
/* Show the races code addition by Blackmane */
/* fixed printout by Miki */
ct=0;
for ( i=0;i<MAX_RACE;i++)
{
++ct;
pager_printf(ch, "%2d> %-11s",i,race_table[i]->race_name);
if ( ct%5==0 )
send_to_pager("\n\r", ch );
}
send_to_pager("\n\r", ch );
return;
}
*** Change from:
if ( x < APPLY_STR || (x > APPLY_CON && x != APPLY_LCK) )
send_to_char( "Invalid second attribute!\n\r", ch );
*** To:
if ( x < APPLY_STR || (x > APPLY_CON && x != APPLY_LCK && x != APPLY_CHA) )
send_to_char( "Invalid second attribute!\n\r", ch );
*** Then you will also need to change the if checks on lines 7578 and 7591
that look just like before:
if ( x < APPLY_STR || (x > APPLY_CON && x != APPLY_LCK) )
*** Note the send_to_char is different on each one but that shouldn't change
case ITEM_COOK:
strcpy( buf, "As you examine it carefully you notice that it " );
dam = obj->value[2];
if (dam >= 3) strcat( buf, "is burned to a crisp.");
else if (dam == 1) strcat( buf, "is a little over cooked.");
else if (dam == 1) strcat( buf, "is perfectly roasted.");
else strcat( buf, "is raw.");
*** Change the else if ( dam == 1) strcat( buf,
"is a little over cooked.");
*** To: else if (dam == 2) strcat( buf, "is a little over cooked.");
Change:
/*
* Take this out SHADDAI
*/
for ( iClass = 0; iClass < MAX_PC_CLASS-2; iClass++ )
To:
for ( iClass = 0; iClass < MAX_PC_CLASS; iClass++ )
While creating a new race I encountered a small inconvience. doing a
'setrace giant create' adds "Giant.race" to race.lst and creates the file
"Giant.race" (emphasis on the capital letter). Although not needed I did a
'setrace giant name giant' then a 'setrace giant save' and continued with
creating the race. The problem encountered is that smaug began saving the
changes to "giant.race" (uncapitalized) and did not change race.lst
accordingly. Since *nix is case sensative smaug was loading the wrong
racefile. A quick fix:
act_wiz.c:
under do_setrace look for:
Change:
if ( !str_cmp( arg2, "name" ) )
{
sprintf(race->race_name,"%-.16s",argument);
To:
if ( !str_cmp( arg2, "name" ) )
{
sprintf(race->race_name,"%-.16s",capitalize(argument));
For a more detailed description see the race problem above.
Change:
if ( !str_cmp( arg2, "name" ) )
{
STRFREE(class->who_name );
class->who_name = STRALLOC( argument );
change to:
if ( !str_cmp( arg2, "name" ) )
{
STRFREE(class->who_name );
class->who_name = STRALLOC( capitalize(argument) );
Change:
if ( morph->timeto != -1 && morph->timefrom != -1 &&
( morph->timeto < time_info.hour || morph->timefrom > time_info.hour ) )
return FALSE;
change TO:
if ( morph->timeto != -1 && morph->timefrom != -1 ) {
int tmp,i;
bool found = FALSE;
/* i is a sanity check, just in case things go haywire so it doesn't
* loop forever here. -Shaddai
*/
for ( i=0,tmp=morph->timefrom; i<25&&tmp!=morph->timeto;i++ ){
if ( tmp == time_info.hour ) {
found = TRUE;
break;
}
if ( tmp == 23 ) tmp = 0;
else tmp++;
}
if ( !found ) return FALSE;
}