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, 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.
 Entire forum ➜ SMAUG ➜ SMAUG coding ➜ Question regarding CHAR_DATA's

Question regarding CHAR_DATA's

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


Pages: 1 2  

Posted by DjNiVeK   (48 posts)  Bio
Date Thu 09 Dec 2004 10:37 PM (UTC)
Message
Ok, I'll keep it short.
I made a new command that checks on the input, and according to that, uses a skill/spell. This is where the problem begins. I implented timers, which work fine and all, but the problem is the skill/spell doesn't know the victim. It probably is a pretty easy solution, but I can't find it yet (late here, lol).

Anyway, this is what I tried:
-Making the void have 3 elements, (CHAR_DATA *ch, char *argument, CHAR_DATA *victim). This doesn't work with the timers and results in stack dumps.

-Putting the char data of victim in a temporary CHAR_DATA victimt. This last CHAR_DATA is accessable to all commands and all, since it's not in a void or anything. This doesn't give any errors or so, but also won't do the damage and will think the enemy is yourself...
Having another player in the room with you will result in a stack dump error.

Any suggestions how to solve this problem?
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #1 on Thu 09 Dec 2004 11:34 PM (UTC)
Message
What does it mean to "make the void have 3 elements"? What kind of stack dumps are you getting?

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by DjNiVeK   (48 posts)  Bio
Date Reply #2 on Thu 09 Dec 2004 11:40 PM (UTC)
Message
I had this before:

void do_skillname(CHAR_DATA *ch, char *argument, CHAR_DATA *victim)

so you had to put in those three things.

I refered to it from a different void as:

do_skillname(ch, arg2, victim);

this part used to work, but because I can only use the ch and argument, the char_data of the victim disappears in the new function.

The last stack dump error I had (by using the skill in the same room as another player):
Exception: STATUS_ACCESS_VIOLATION at eip=004757ED
eax=00000000 ebx=0022E260 ecx=61113060 edx=00000000 esi=101A1930 edi=0022E260
ebp=0022C9B8 esp=00228830 program=D:\naruto mud\dist\area\smaug.exe, pid 924, thread main
cs=001B ds=0023 es=0023 fs=003B gs=0000 ss=0023
Stack trace:
Frame     Function  Args
0022C9B8  004757ED  (101A1930, 0022E260, 00000096, 00001770)
0022C9E8  0050E92E  (101A1930, 0054870F, 0022EA48, 004F202F)
0022EA48  00472ABD  (0000000C, 005B4FB0, 005B4F80, 005B5030)
0022EA78  004F48F1  (101D7DA8, 005B4F80, 005B5030, 0022E9F4)
0022EED8  00458958  (005BA4F0, 00000000, 0000009D, 0022EF10)
0022EF98  004580F1  (00000001, 10011570, 100100A8, 00000001)
0022F008  61006145  (0022F020, 7C916315, 00000000, 77FB6588)
0022FF88  61006350  (00000000, 00000000, 00000000, 00000000)
End of stack trace
Top

Posted by Nick Gammon   Australia  (23,057 posts)  Bio   Forum Administrator
Date Reply #3 on Fri 10 Dec 2004 12:37 AM (UTC)
Message
Let's get the terminology right.


void do_skillname ( ... )


is a function (do_skillname) returning void. That is, it does not return a value. It's a function, not a void.

- Nick Gammon

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

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #4 on Fri 10 Dec 2004 01:20 AM (UTC)
Message
That stack dump isn't very useful at all; you'd need to do a gdb backtrace to examine the stack. A collection of numbers like that don't mean a lot to us mere humans. :-)

And yeah - there seems to be a vocabulary issue here. If I may ask, how much programming do you know? You might be doing something more advanced than what you know. This isn't meant to be discouraging - it's meant to save you a lot of frustration by trying to do something too hard. Trust me, been there, done that. :-)

Since you can only have two arguments for the function, you seem to have two options:
- use the 'argument' parameter to store the victim's name and then resolve it again
- use a temporary pointer on the char_data structures to refer to the victim, already resolved in the first function

I think the timer function lets you specify which argument to use when the timer fires.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by DjNiVeK   (48 posts)  Bio
Date Reply #5 on Fri 10 Dec 2004 11:05 AM (UTC)
Message
@Nick: True, was late here, lol

@Ksilyan: Never did a gbd backtrace before, will check what it is and how to do it, lol.
I have average programming experience in C and C++.
I'll put the functions here so it might be easier to locate the mistake:


#include <stdarg.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <ctype.h>
#include "mud.h"
CHAR_DATA *victimt;

void do_skill( CHAR_DATA *ch, char *argument)
{
	CHAR_DATA *victim = victimt;
	if (ch->level <= 50)
    {
		send_to_char("-message\n\r", ch);
		return;
    }
	switch (ch->substate)
	{
	default:
		act(AT_WHITE, "-message", ch, victim, NULL, TO_CHAR);
		add_timer( ch, TIMER_DO_FUN, 1, do_skill, 1 );
		return;
	case 1:
		act( AT_RED, "-message", ch, NULL, victim, TO_CHAR);
		act( AT_RED, "-message", ch, NULL, victim, TO_CANSEE);
		add_timer( ch, TIMER_DO_FUN, 1, do_skill, 2 );
		return;
	case 2:
		act( AT_RED, "-message", ch, NULL, victim, TO_CHAR);
        act( AT_RED, "-message", ch, NULL, victim, TO_CANSEE);
		add_timer( ch, TIMER_DO_FUN, 1, do_skill, 3);
		return;
	case 3:
		damage( ch, victim, 150, TYPE_LIGHTNING );
		ch->mana -= 75;
		add_timer( ch, TIMER_DO_FUN, 1, do_skill, 4);
		return;
	case 4:
		act( AT_WHITE, -message" , ch, NULL, victim, TO_CHAR);
		act( AT_WHITE, -message" , ch, NULL, victim, TO_CANSEE);
		return;
	}
	return;
}

void do_handseal( CHAR_DATA *ch, char *argument)
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];

argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );

CHAR_DATA *victim;
victimt = victim;
victim = ch;
    if ( arg1[0] == '\0' )
    {
		send_to_char("&YWhat would u like to perform?\n\r", ch);
		return;
    }
    if ( !str_cmp( arg1, "mfbtobs" ) )
    {
		do_skill(ch, arg2);
		return;
    }
}

I removed a couple of unnecessary parts in it. This was the last thing I tried last night.
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #6 on Fri 10 Dec 2004 01:18 PM (UTC)
Message
Unfortunately there is not just "one mistake" in your code or even a series of particular mistakes, it seems that you aren't really clear on how to use the variables and on how to use the timers. I won't write out a full solution (that would take too much time) but here are a few problems to think about:


  • 'victimt' is a global variable, so only one person can be using it at a time. I don't think this is at all what you want!
  • CHAR_DATA *victim;
    victimt = victim;
    victim = ch;
    What exactly are you expecting this to do? You're assigning to victimt a completely uninitialized value ('victim') so effectively you're making victimt useless. What you wrote has the same problem as:
    int i;
    int j;
    i = j;
    j = 3;

  • Why not just store the victim argument (arg2) on the character structure? Global variable = evil and more importantly wrong. Have you looked at do_search and similar functions, or in fact anything that involves coming back on something after time such as editing room descriptions? (or indeed anything that uses a buffer.)


Nick wrote a tutorial on GDB, read it here:
http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=3653
It assumes of course that you are running in a Unixish environment e.g. cygwin.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by DjNiVeK   (48 posts)  Bio
Date Reply #7 on Fri 10 Dec 2004 04:36 PM (UTC)

Amended on Fri 10 Dec 2004 04:51 PM (UTC) by DjNiVeK

Message
Quote:
'victimt' is a global variable, so only one person can be using it at a time. I don't think this is at all what you want!

CHAR_DATA *victim;
victimt = victim;
victim = ch;

What exactly are you expecting this to do? You're assigning to victimt a completely uninitialized value ('victim') so effectively you're making victimt useless. What you wrote has the same problem as:
int i;
int j;
i = j;
j = 3;
Ack! you're right, lol. Really stupid mistake.

Quote:
Why not just store the victim argument (arg2) on the character structure? Global variable = evil and more importantly wrong. Have you looked at do_search and similar functions, or in fact anything that involves coming back on something after time such as editing room descriptions? (or indeed anything that uses a buffer.)
You mean making a thing like 'ch->victim' to store the argument (as a string?) there for the time being? I tried making the argument (arg2) a CHAR_DATA, but that doesn't work (kinda obvious it doesn't). Why would a thing like 'ch->victim' work then? (Could be I misunderstood).
I looked at do_search, but I don't think it has the solution to my problem, because my problem is to pass the CHAR_DATA *victim on to the next function (in my case the do_skill)
arg2 is the name of the victim, isn't there a way to get the CHAR_DATA with that argument? Because arg2 goes to the do_skill function.
//edit:
I understand what you mean now, I'll try it out some more then :)
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #8 on Fri 10 Dec 2004 07:48 PM (UTC)
Message
Quote:
I looked at do_search, but I don't think it has the solution to my problem, because my problem is to pass the CHAR_DATA *victim on to the next function (in my case the do_skill)
Look at the functions to set the description for an object or mob. Namely, look at how these functions use ch->dest_buf, ch->spare_ptr. Granted it's not too pretty, but it seems to be how you have to do it. You could either use spare_ptr yourself, or to be safe about it (better idea) create a new pointer for your purposes.

You can either point to a char_data (the result of a victim name string resolution) or point to merely char (the name of the victim) and do last-minute resolving. The latter is better, because the victim might leave the room during the start-to-timertick interval.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by DjNiVeK   (48 posts)  Bio
Date Reply #9 on Fri 10 Dec 2004 09:15 PM (UTC)
Message
Ok, I made a new pointer (victim_ptr), and I can get CHAR_DATA's to the new function now. But it seems like there is no way to get the char data of the victim passed on. I don't know why, because in the old function, it didn't have anything extra, but it did target the victim.
I didn't change anything in the code (so didn't remove the messages and all)
Old Code:

void do_handseal( CHAR_DATA *ch, char *argument)
{
char arg1[MAX_INPUT_LENGTH];
// char arg2[MAX_INPUT_LENGTH];

argument = one_argument( argument, arg1 );
// argument = one_argument( argument, arg2 );

CHAR_DATA *victim;
victim = ch;

     else if ( arg1[0] == '\0' )
     {
      send_to_char("&YWhat would u like to perform?\n\r", ch);
      return;
     }
     if ( !str_cmp( arg1, "mfbtobs" ) )
     {
     if (ch->level <= 50)
      {
       send_to_char("You cannot perform Chidori\n\r", ch);
       return;
      }
    if ( argument[0] == '\0' && (victim = who_fighting(ch)) == NULL )
    {
        ch_printf( ch, "You can't seem to focus for Chidori.\n\r" );
        global_retcode = damage( ch, ch, random_int(1, 1), TYPE_LIGHTNING );
        return;
    }
    else if ( argument[0] != '\0' && (victim = get_char_room(ch, argument)) == NULL )
    {
        send_to_char( "You can't seem to focus for Chidori.\n\r", ch );
        global_retcode = damage( ch, ch, random_int(1, 1), TYPE_LIGHTNING );
        return;
    }

//        if(ch->position == POS_STANDING )
//        {
//        send_to_char("You can't do that when your not fighting\n\r", ch);
//        return;
//        }
        if (can_use_skill(ch, number_percent(), gsn_lightning_bolt ))
        {
        act(AT_WHITE, "You quickly do some handseals for your jitsu.&R", ch, victim, NULL, TO_CHAR);
        act( AT_RED, "\n\r$n raises his hand out in front of $mself and focuses $s chakra.", victim, NULL, ch, TO_CHAR);
        act( AT_RED, "\n\r$n's chakra flows all over $s body. &YCHIDORI&r!!!", victim, NULL, ch, TO_CHAR);
        act( AT_RED, "\n\rYou raise your hand out infront of yourself and focus your chakra.", ch, NULL, victim, TO_CHAR);
        act( AT_RED, "\n\rYour chakra flows all over your body. &YCHIDORI&r!!! Victim: $N", ch, NULL, victim, TO_CHAR);
        act( AT_RED, "\n\r$N raises $s hands and focuses $s chakra.", ch, NULL, victim, TO_NOTVICT);
        act( AT_RED, "\n\r$N's chakra flows all over $s body. &YCHIDORI&r!!!", ch, NULL, victim, TO_NOTVICT);
        one_hit( ch, victim, TYPE_LIGHTNING );
        ch->mana -= 75;
        act( AT_WHITE, "&w$N lowers $S hand." , victim, NULL, ch, TO_CHAR);
        act( AT_WHITE, "&wYou lower your hand." , ch, NULL, victim, TO_CHAR);
        act( AT_WHITE, "&w$N lowers $S hand." , ch, NULL, victim, TO_NOTVICT);
//      learn_from_success( ch, spell_chidori );
        }
        else
        {
        act(AT_WHITE, "You quickly do some handseals for your jitsu.&R", ch, victim, NULL, TO_CHAR);
        act( AT_RED, "\n\r$n raises his hand out in front of $mself and focuses $s chakra.", victim, NULL, ch, TO_CHAR);
        act( AT_RED, "\n\r$n's chakra flows all over $s body. &YCHIDORI&r!!!", victim, NULL, ch, TO_CHAR);
        act( AT_RED, "\n\rYou raise your hand out infront of yourself and focus your chakra.", ch, NULL, victim, TO_CHAR);
        act( AT_RED, "\n\rYour chakra flows all over your body. &YCHIDORI&r!!! Victim: $N", ch, NULL, victim, TO_CHAR);
        act( AT_RED, "\n\r$N raises $s hands and focuses $s chakra.", ch, NULL, victim, TO_NOTVICT);
        act( AT_RED, "\n\r$N's chakra flows all over $s body. &YCHIDORI&r!!!", ch, NULL, victim, TO_NOTVICT);
        damage(ch, victim, 0, TYPE_LIGHTNING);
        ch->mana -= 150;
        act( AT_WHITE, "&w$N lowers $S hand." , victim, NULL, ch, TO_CHAR);
        act( AT_WHITE, "&wYou lower your hand." , ch, NULL, victim, TO_CHAR);
        act( AT_WHITE, "&w$N lowers $S hand." , ch, NULL, victim, TO_NOTVICT);
//      learn_from_failure( ch, spell_chidori );
        return;
                }
        WAIT_STATE( ch, 14 );
                }
        }
Top

Posted by DjNiVeK   (48 posts)  Bio
Date Reply #10 on Fri 10 Dec 2004 09:16 PM (UTC)
Message
New Code:

void do_chidori( CHAR_DATA *ch, char *argument/*, CHAR_DATA *victim*/)
{
	CHAR_DATA *victim = ch->victim_ptr;
	switch (ch->substate)
	{
	default:
		if (ch->level <= 50)
		{
		send_to_char("You cannot perform Chidori\n\r", ch);
		return;
		}
		if ( argument[0] == '\0' && (victim = who_fighting(ch)) == NULL )
		{
        ch_printf( ch, "You can't seem to focus for Chidori.\n\r" );
        return;
		}
		else if ( argument[0] != '\0' && (victim = get_char_room(ch, argument)) == NULL )
		{
        send_to_char( "You can't seem to focus for Chidori.\n\r", ch );
        return;
		}
		if ( ch == victim)
		{
		ch_printf( ch, "Using Chidori on yourself? Are you suicidal?\n\r");
		return;
		}
		act(AT_WHITE, "You quickly do some handseals for your jitsu.&R", ch, victim, NULL, TO_CHAR);
		add_timer( ch, TIMER_DO_FUN, 1, do_chidori, 1 );
		return;
	case 1:
		act( AT_RED, "\n\rYou raise your hand out infront of yourself and focus your chakra.", ch, NULL, victim, TO_CHAR);
		act( AT_RED, "\n\r$n raises $s hands and focuses $s chakra.", ch, NULL, victim, TO_CANSEE);
		add_timer( ch, TIMER_DO_FUN, 1, do_chidori, 2 );
		return;
	case 2:
		act( AT_RED, "\n\rYour chakra flows all over your body. &YCHIDORI&r!!! victim $N", ch, NULL, victim, TO_CHAR);
        act( AT_RED, "\n\r$n's chakra flows all over $s body. &YCHIDORI&r!!!", ch, NULL, victim, TO_CANSEE);
		add_timer( ch, TIMER_DO_FUN, 1, do_chidori, 3);
		return;
	case 3:
		damage( ch, victim, 150, TYPE_LIGHTNING );
		ch->mana -= 75;
		add_timer( ch, TIMER_DO_FUN, 1, do_chidori, 4);
		return;
	case 4:
		act( AT_WHITE, "&wYou lower your hand." , ch, NULL, victim, TO_CHAR);
		act( AT_WHITE, "&w$n lowers $s hand." , ch, NULL, victim, TO_CANSEE);
		return;
	}
	return;
}

void do_handseal( CHAR_DATA *ch, char *argument)
{
char arg1[MAX_INPUT_LENGTH];
//char arg2[MAX_INPUT_LENGTH];

argument = one_argument( argument, arg1 );
//argument = one_argument( argument, arg2 );

CHAR_DATA *victim;
victim = ch;

    if ( arg1[0] == '\0' )
    {
		send_to_char("&YWhat would u like to perform?\n\r", ch);
		return;
    }
    if ( !str_cmp( arg1, "mfbtobs" ) )
    {
		ch->victim_ptr = victim;
		do_chidori(ch, argument);
		return;
    }
}
Top

Posted by David Haley   USA  (3,881 posts)  Bio
Date Reply #11 on Fri 10 Dec 2004 10:38 PM (UTC)
Message
What exactly is the problem, and what are you asking me to look at?

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
Top

Posted by DjNiVeK   (48 posts)  Bio
Date Reply #12 on Fri 10 Dec 2004 11:12 PM (UTC)
Message
The problem is the fact that the CHAR_DATA *victim contains the same information as CHAR_DATA *ch.
Which is understandable because in the beginning of the handseal function, there is a 'victim = ch;'
I'm wondering why the old code is able to attack the victim, even with that 'victim = ch;' part.
So my question kinda is: "Why does the old code have a good 'victim' and the new code doesn't, as it has about the same code."
Top

Posted by Nick Cash   USA  (626 posts)  Bio
Date Reply #13 on Fri 10 Dec 2004 11:38 PM (UTC)
Message
Quote:


void do_handseal( CHAR_DATA *ch, char *argument)
{
char arg1[MAX_INPUT_LENGTH];
//char arg2[MAX_INPUT_LENGTH];

argument = one_argument( argument, arg1 );
//argument = one_argument( argument, arg2 );

CHAR_DATA *victim;
victim = ch;

    if ( arg1[0] == '\0' )
    {
		send_to_char("&YWhat would u like to perform?\n\r", ch);
		return;
    }
    if ( !str_cmp( arg1, "mfbtobs" ) )
    {
		ch->victim_ptr = victim;
		do_chidori(ch, argument);
		return;
    }
}



I have a concern. You do victim = ch;, but then later you do ch->victim_ptr = victim. Thus, arent you pointing to your own structure? As in, ch->victim_ptr->name would be the same as ch->name? Seems rather pointless to point to yourself.

Also, what exactly is the "old" code? What you should do, is when they specify the name of the victim, do something like,

if ( (victim = get_char_world( ch, arg2 ) ) == NULL )
{
  send_to_char( "They aren't here.\n\r", ch );
  return;
}


This will then give a pointer to the correct person, and if that person isn't found it will tell you "They aren't here."

~Nick Cash
http://www.nick-cash.com
Top

Posted by DjNiVeK   (48 posts)  Bio
Date Reply #14 on Fri 10 Dec 2004 11:52 PM (UTC)

Amended on Sat 11 Dec 2004 12:06 AM (UTC) by DjNiVeK

Message
Ahh, now I see what went wrong, lol. I'll try coding it in tomorrow, but I think you're right.
ty :)

Edit: hmm, didn't seem to solve the problem.
The old code was posted 1 post above the new code. The old 'code' was the old version of handseal, and it also had that victim = ch; in it.
But that didn't seem to make a difference, because the attack still hit the 'real' victim instead of ch.
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.


56,427 views.

This is page 1, subject is 2 pages long: 1 2  [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.