Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ SMAUG ➜ Compiling the server ➜ Source Code

Source Code

It is now over 60 days since the last post. This thread is closed.     Refresh page


Pages: 1  2  3  4 5  

Posted by Kris   USA  (198 posts)  Bio
Date Reply #45 on Tue 24 Jul 2001 04:40 AM (UTC)
Message
I realize that, but at very worst, if the player disconnects and the pointer thus becomes invalid, it'll just show the immortals a BUG; the same bug I'm getting right now. I could also put in an ifcheck to ensure the player is connected before it makes any attempt.

This is just one use of this coding I'm trying to set up. If successful, we can also create bards, as well as other things that would require some sort of paced message. I.e. on many muds, when a bard sings, he sings in several verses (in this case, wait_state wouldn't be used btw). Now, it looks really stupid if the bard sings 4 verses of a song in just a fraction of a second; not to mention it makes it very difficult for other players to follow. Wouldn't a delay- the exact type of delay I'm trying to add- be nice in that case? That wouldn't work, however, if it couldn't leave the function without forgetting/screwing-up the victim variable, making it impossible to send the next message in the sequence.

I apologize if the example of my attempt seems silly and pointless, but there are -many- other potential uses for this, if I can get it set up. That's why I'm being so persistent; there's a lot of things I want to do that I can't, simply because I can't get this bloody thing to work. Is there anybody out there who would have some sort of idea as to how I can fix this apparently-complex problem? Thanks for your patience and help :)
Top

Posted by Kris   USA  (198 posts)  Bio
Date Reply #46 on Wed 08 Aug 2001 03:15 AM (UTC)
Message
I'm sorry to keep persisting, but this problem is still the 'public enemy #1' in our source code, and I have been at a loss to fix it for some time. If -anyone- could help me, give me some fresh ideas, etc, I would be more than greatful. The last several posts about this describe everything in detail. Please, PLEASE read through it if you know anything descent about C programming; we really need an answer, and I cannot provide any. Thank you for your help :)
Top

Posted by Kris   USA  (198 posts)  Bio
Date Reply #47 on Fri 10 Aug 2001 09:24 AM (UTC)
Message
How bad is my coding? Where have I gone wrong? Is the problem so complex that nobody who is proficient in C programming can determine the problem, let alone help solve it? Or is my question somehow offending or annoying anyone? If so, please tell me, so I can stop making a fool out of myself by posting here. I just want some technical help with this vital (I cannot stress how vital) code. If I can get this to work, that will open the door to so many possibilities, and enable work on many other things I've got planned. Aside from an opinion as to why this is or is not good for my mud, does *anybody* have *anything* to offer that could help me fix this? I'm beyond stumped, and for all I know, it's a simple C syntax error. It makes no sense; I really need a step in the right direction from someone who has experience with this. Somebody, if you're out there, please help us! Thanks for your time :)
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #48 on Fri 10 Aug 2001 09:12 PM (UTC)

Amended on Thu 16 Aug 2001 07:20 AM (UTC) by Nick Gammon

Message
Email me your C files - the ones you have changed, not the whole lot, and any relevant .h files, and I'll take a look. It is very hard to debug without running the code. You can tell from the date modified which files have changed, and you ought to know anyway which ones they are.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #49 on Thu 16 Aug 2001 06:52 AM (UTC)

Amended on Thu 16 Aug 2001 07:21 AM (UTC) by Nick Gammon

Message
OK, now that Kris has sent me the code, I'll comment here on what happened, so it will hopefully help others as well as Kris.

What he had done was put the messages into do_mptransformcat like this:



void do_mptransformcat ( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    int level;
    int iLevel;
    int iLang;
    CHAR_DATA *tempchb=ch;
    char *tempvictimb=argument;

    if ( !IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ))
    {
          send_to_char( "Huh?\n\r", ch );
          return;
    }


    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
    progbug( "Mptransform - Bad syntax", ch );
    return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
    progbug( "Mptransform - Victim not there", ch );
    return;
    }

    if ( IS_NPC(victim) )
    {
    progbug( "Mptransform - Victim is NPC", ch );
    return;
    }

    if ( ( victim->tempch != tempchb ) || ( victim->tempvictim != tempvictimb )
)
    {
     victim->tempch = tempchb;
     victim->tempvictim = tempvictimb;
    }

/*
To remember where in the message sequence the player is; part of the institution
 of a delay
--Kris
*/

    if ( victim->tempwaitb >=1 && victim->tempwaitb <=23 )
    {
     switch ( victim->tempwaitb )
     {

      case 1:
       send_to_char( "\nWhat the bloody hell?!\n", victim );
       TEMPWAIT_STATE(victim, 20);
       break;

      case 2:
       send_to_char( "\n\n\nA vast, open field flashes before your eyes....\n",
victim );
       TEMPWAIT_STATE(victim, 20);
       break;

      case 3:
       send_to_char( "\nYou are standing in this field....\n", victim );
       TEMPWAIT_STATE(victim, 20);
       break;

      case 4:
       send_to_char( "\nYour ears perk-up, your eyes focus, and you crouch down
low in the grass....\n", victim );
       TEMPWAIT_STATE(victim, 20);
       break;

... and so on ...

    if ( victim->race == RACE_CAT )
    {
     send_to_char( "A mystical voice says:  You're already a cat, you mook!\n",
victim );
     return;
    }


    send_to_char( "\n\nYou start to feel a strange sensation in your body....\n"
, victim );
    TEMPWAIT_STATE(victim, 20);
    victim->tempwaitb = 1;
    victim->tempwaitc = 1;
    return;

}




The problem with this is that do_mptransformcat is only called once by the mob, and thus that the sequence of messages won't be displayed.

However he tried to work around this by re-calling do_mptransformcat from the main game_loop ...




        if ( FD_ISSET( d->descriptor, &in_set ) )
        {
            d->idle = 0;
            if ( d->character )
              d->character->timer = 0;
            if ( !read_from_descriptor( d ) )
            {
                FD_CLR( d->descriptor, &out_set );
                if ( d->character
                && ( d->connected == CON_PLAYING
                ||   d->connected == CON_EDITING ) )
                save_char_obj( d->character );
                d->outtop   = 0;
                close_socket( d, FALSE );
                continue;
            }
        }

        if ( d->character && d->character->wait > 0 )
        {
            --d->character->wait;
            continue;
        }

        if ( d->character && d->character->tempwait > 0 )
        {
            --d->character->tempwait;
                write_to_descriptor( d->descriptor,
         "debug1.\n\r", 0 );

            if (d->character->tempwait < 1)
            {
            write_to_descriptor( d->descriptor,
         "debug2.\n\r", 0 );

/*           if (d->character->tempwaitc == 1)  */
              do_mptransformcat(d->character->tempch, d->character->tempvictim);

            }

            continue;
        }

        read_from_buffer( d );




I can see what he is trying to do here, but I think that this approach is doomed to failure, particularly when do_mptransformcat is recalled from the game loop, because he has had to "dummy up" the arguments to do_mptransformcat, which then eventually gives the error messages that he reported.

My approach would be to split the delayed messages into a totally different routine, because you are really doing two things here:


  1. Initiating the transformation into a cat
  2. Displaying a message to the player every second or so


Thus, I have only the following code in do_mptransformcat:



void do_mptransformcat ( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
        
    if ( !IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ))
    {
          send_to_char( "Huh?\n\r", ch );
          return;
    }


    argument = one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	progbug( "Mptransformcat - Bad syntax", ch );
	return;
    }

    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	progbug( "Mptransformcat - Victim not there", ch );
	return;
    }

    if ( IS_NPC(victim) )
    {
	progbug( "Mptransformcat - Victim is NPC", ch );
	return;
    }

    if ( victim->race == RACE_CAT )
    {
     send_to_char( "A mystical voice says:  You're already a cat, you mook!\n", victim );
     return;
    }
    
    send_to_char( "\n\nYou start to feel a strange sensation in your body....\n", victim );
    

    victim->tempwait = 1;  /* initiate message sequence */

}




Basically I deleted all the message stuff (and pasted elsewhere) - the only thing left, to initiate the messages to the player, is setting the tempwait flag to 1 (shown in bold), which means that message number 1 is due to be shown to the player.

Now we make another function "special_messages" that will display the messages in sequence (adding 1 to tempwait each time). When we get to the end of the sequence we set tempwait to zero to indicate that we have finished.




void special_messages (CHAR_DATA *ch)
  {
    int iLang;
     switch ( ch->tempwait++ )
     {
      case 1:
       send_to_char( "\nWhat the bloody hell?!\n", ch );
       break;

      case 2:
       send_to_char( "\n\n\nA vast, open field flashes before your eyes....\n", ch );
       break;
      
      case 3:
       send_to_char( "\nYou are standing in this field....\n", ch );
       break;

... and so on ...
      
      case 22:
       send_to_char( "\n\nYou have been transformed into a CAT!!\n", ch );
       ch->tempwait = 0;		/* no more messages */
       break;
     } /* end of switch */
  }



The remaining trick is to call this function each second, which can be easily done by following what game_loop does. Amongst other things, it calls "update_handler", which calls "char_check" every second.

Some way into char_check, after deciding that we have a player and not a mob, we add a couple of lines:



  if (ch->tempwait)
     special_messages (ch);  /* extra messages for Kris */



Finally, we need to zero out ch->tempwait when a player connects, otherwise if it happened to have a non-zero value when a player connected, they might start seeing messages about turning into a cat ...




    add_char( ch );
    d->connected    = CON_PLAYING;
    ch->tempwait = 0;



I will send the complete changes to Kris as a patchfile, hopefully he will be able to get his messages working, and the technique could be used for other muds as well.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #50 on Thu 16 Aug 2001 07:20 AM (UTC)
Message
I should point out that you could use this same technique to implement things like the bard's songs Kris mentioned in earlier messages. After all, only 'wait' states 1 to 22 are used at present. You could use, say, 30 to 40, for the lines of a song.

You could also implement multi-second delays by having a second field (seconds_to_go for example). You could set this at (say) 3, and when going into the special_messages function subtract 1 from it, and when it reached zero display the message, otherwise do nothing.

Also, a more general implementation would read the messages from a file, rather than hard coding them in. You could have a file of messages, with a number in front of each one, and then read them into an array, or linked list, at mud startup time. That way you can change the messages without having to recompile every time.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Kris   USA  (198 posts)  Bio
Date Reply #51 on Sat 22 Sep 2001 08:41 PM (UTC)
Message
Heyas. I've been revamping the time structure (i.e. months, years, hours, etc) on the mud. Among other things, I wanted to make it so that I could set the current year from a seperate .dat file (in case some large quest or whatever demanded that we return to a year 1 or something like that), rather than having it determined by time_info.year. The year (variable is int 'newyear') would go up by 1 whenever the month resets to 1. I haven't had any problems with this. My problem is something really basic; something a more seasoned C programmer would probably be able to do in his sleep. Basically, how do I read in the number from the next file as a number, not as a string? Obviously I can't read it in as a string; it'd display just fine, but I wouldn't be able to have the number go up when month 17 is past. So I tried doing it in db.c, and I put the following code right below the line that loads the wizlist:

log_string("Loading Current Year");
if ( ( fp = fopen( NEWYEAR_FILE, "r" ) ) != NULL )
{
top_sn = 0;

newyear = fread_number( fp );

fclose( fp );
}
else
{
bug( "Cannot open current_year.dat", 0 );
exit(0);
}

And yes, NEWYEAR_FILE is defined correctly in mud.h, as is the newyear variable. However, when the mud boots up, I get a stackdump error message when it's loading newgate.are. When I comment the code above, the mud boots up just fine. The line "newyear = fread_number( fp );" is what I'm thinking the problem is, but I'm not sure. And yes, I defined FILE *fp; at the top of the function.

Any idea what I'm doing wrong, and how I can fix it? Thanks fer the help :)
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #52 on Sat 22 Sep 2001 10:28 PM (UTC)
Message
Looks OK to me - I would run it under gdb to see exactly what line it is crashing on.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Kris   USA  (198 posts)  Bio
Date Reply #53 on Sun 23 Sep 2001 08:08 AM (UTC)
Message
Not quite sure what you mean by that; I tried running gdb from cygwin, but all it appeared to be was a text viewer, with line #s on the left.

Anyways, these are the details about the errors. No compile errors. When aethia is booted up, it works just fine until it tries to read-in newgate.are (seems to be totally unrelated to what I'm doing!). This is the error as it displays:

[*****] FILE: newgate.are LINE: 533
[*****] BUG: Slot_lookup: bad slot 32.
0 [sig] AETHIA 890121 open_stackdumpfile: Dumping stack trace to AETHIA.EXE.stackdump

After that, aethia.exe terminates. And no, at least so far as I recall, I haven't made any changes to newgate.are. When I comment out the little block of code in db.c I listed above, this error does not occur. Heh I don't even know where to begin with this one; the syntax looks perfectly ok to me as well, and yet....
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #54 on Mon 24 Sep 2001 09:55 PM (UTC)

Amended on Mon 24 Sep 2001 09:56 PM (UTC) by Nick Gammon

Message
OK, I've worked it out. The problem is the line:


top_sn = 0;


Why did you have that there? It wasn't relevant to what you were trying to do. You could almost guess what would happen.

Things like spells, skills and herbs use a "slot". In the previous few lines the spells etc. were loaded.

Then however you set "top_sn" (top slot number) to zero.

Your error message was: "Slot_lookup: bad slot 32".

In other words, by setting top_sn to zero, you "deleted" all spells, skills, etc. Thus the areas could not load.

Simply delete that line.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Creeper386   USA  (62 posts)  Bio
Date Reply #55 on Wed 31 Oct 2001 04:25 AM (UTC)
Message
Okay. Not extremely good at coding and know a few things and in reply to the wait thing to display messages wouldn't it be easier to display two to three lines then set a timer for so long when it runs out it prints up two to three or four more lines that are seperate from the first set of lines?

Creep

May not work but if it did I would think that'd be more sensible way to go about it, but then might be more coding... SHRUG.
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #56 on Thu 01 Nov 2001 04:04 AM (UTC)
Message
Depends what you mean by "set a timer". If you mean just have the server wait a couple of seconds, then all other players would freeze while the server waited for the timer to finish.

The tricky thing about timers in a server with lots of players is knowing what to do to whom when the timer expires.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Creeper386   USA  (62 posts)  Bio
Date Reply #57 on Thu 01 Nov 2001 04:50 AM (UTC)
Message
Would it be possible to have the first few lines done then have it check the time add so much to it then stick it somewhere that when that time comes up it does the next few lines or whatever else you have in the code?

Creep

I'm just wondering if it's possible coding wise or if it'd be efficient, not asking how to do it. Just so you know...
Top

Posted by Nick Gammon   Australia  (23,173 posts)  Bio   Forum Administrator
Date Reply #58 on Sun 04 Nov 2001 07:28 AM (UTC)
Message
It is efficient enough if you do it the way that was described earlier on in this thread.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Kris   USA  (198 posts)  Bio
Date Reply #59 on Sat 15 Dec 2001 10:17 PM (UTC)
Message
I'm trying to make it so that a player can connect to a seperate port for telnet/java telnet. The obvious reason for this is that telnet and java, as well as some other clients, don't display large chunks of text too well. I.e. my graphic greeting screens show up as a jumbled mess of text on telnet and java, and whois also jumbles up like crap. Msp would also seem kinda weird with !!SOUND things popping up on the screen for the telnet folks.

The logical solution is to have a seperate port for telnet that players would connect to (like 4100 instead of 4000). Then, I could have an ifcheck in various places that display 'jumbled' text. This ifcheck would have it display a more concise, 'less pretty', form of text/title screen which would display correctly on java and telnet, whereas the more jumbled stuff could still be displayed on clients like zmud that show them correctly.

I looked in comm.c, and examined the init_socket and accept_new functions. However, I wasn't able to determine a reliable ifcheck from that. Could you look at that and tell me how you think that could be accomplished? Thanks :)
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


196,394 views.

This is page 4, subject is 5 pages long:  [Previous page]  1  2  3  4 5  [Next page]

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.