Question regarding CHAR_DATA's

Posted by DjNiVeK on Thu 09 Dec 2004 10:37 PM — 24 posts, 85,102 views.

#0
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?
USA #1
What does it mean to "make the void have 3 elements"? What kind of stack dumps are you getting?
#2
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
Australia Forum Administrator #3
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.
USA #4
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.
#5
@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.
USA #6
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.
#7
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 :)
Amended on Fri 10 Dec 2004 04:51 PM by DjNiVeK
USA #8
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.
#9
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 );
                }
        }
#10
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;
    }
}
USA #11
What exactly is the problem, and what are you asking me to look at?
#12
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."
USA #13
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."
#14
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.
Amended on Sat 11 Dec 2004 12:06 AM by DjNiVeK
USA #15
I don't see how the 'old code' could work in the first place because it starts out with an else if - but where's the if?

It does have a victim = ch at the top, but if you look carefully you'll see that victim gets changed right afterwards - the victim = ch seems to be a useless statement.
Canada #16
The reason that it was working before and not now was this part
victim = who_fighting(ch)
This was reseting victim to the proper setting. You can put something like that back in.
USA #17
The error I pointed out is one of syntax, not semantics:

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;

     // Where is the opening if statement here?
     else if ( arg1[0] == '\0' )
     {
          send_to_char("&YWhat would u like to perform?\n\r", ch);
          return;
     }
     ...
It shouldn't have even compiled to begin with.
Amended on Sat 11 Dec 2004 02:01 AM by David Haley
Canada #18
Very true, I was simply refering to this
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;
    }
}
All I meant was to get this to work would be to initialize(with the appropraite checks, of course) victim to who_fighting(ch) instead of ch. Though setting up ch->victim_ptr to who_fighting(ch) would be pointless here, and should just be done and checked in do_chidori anyways.


As to how the other was working... yeah, your right, it shouldn't have been. Looks like these are not full functions anyways, as the one above really does very little anyways except call do_chidori. I would assume, possibly erroneously, that there is more that is not posted.
Amended on Sat 11 Dec 2004 02:13 AM by Greven
#19
Yea, it misses a small part. I removed it because it took up quite a few lines, but doesn't affect the call to do_chidori. All it did was remove some affects if you had them on you
USA #20
If you're going to paste code, you should probably paste all of it so that we don't have to play guessing games with what you left out. :-) If you omit stuff, who knows if it might be doing something wrong that we should know about as we read your code?
#21
Ok, here's the full code as it is right now. Right now, I only get the 'They aren't here' messages, because the victim is NULL.

void do_chidori( CHAR_DATA *ch, char *argument/*, CHAR_DATA *victim*/)
{
	CHAR_DATA *victim = ch->victim_ptr;
//	CHAR_DATA *victim;
	switch (ch->substate)
	{
	default:
		if (ch->level <= 50)
		{
		send_to_char("You cannot perform Chidori\n\r", ch);
		return;
		}
		if ( (victim = get_char_world( ch, argument ) ) == NULL )
		{
			send_to_char( "They aren't here.\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 = who_fighting(ch);

//victim = ch->victim;
    if ( arg1[0] == '\0' && (xIS_SET(ch->affected_by, AFF_SHARINGAN) ) )
    {
		send_to_char("You place your palms together.\n\r&WYour eyes return to normal as you stop using Sharingan.\n\r", ch);
		act(AT_GREEN, "$n places $s palms together.\n\r$n's chakra fades as $e stops using sharingan", ch, NULL, NULL,TO_CANSEE );
		xREMOVE_BIT(ch->affected_by, AFF_SHARINGAN);
		ch->mod_str = 0;
		ch->mod_dex = 0;
		ch->mod_lck = 0;
		ch->mod_wis = 0;
		ch->mod_int = 0;
		ch->mod_con = 0;
		return;
    }
    else if ( arg1[0] == '\0' )
    {
		send_to_char("&YWhat would u like to perform?\n\r", ch);
		return;
    }
	if ( !str_cmp( arg1, "mfotb" ) )
    {
		do_sharingan(ch, argument);
		return;
    }

	else if ( !str_cmp( arg1, "mfbtobs" ) )
    {
		ch->victim_ptr = victim;
		do_chidori(ch, argument);
		return;
    }
}
USA #22
That's because argument is null... this is a timer function, remember . . . you don't always have data in the char*argument to the function! you have to retrieve victim from those temporary pointers you created, or, from the who_fighting call.

Besides... your argument handling in do_handseal is wrong. Look at what you do with arg2 and argument, and think about what the value of 'argument' is as you pass it in to the do_chidori function...
#23
I changed those things, and it is working fine now :)
Thanks alot =)