So I was strolling through the code one day...

Posted by Aqueus on Sun 25 Feb 2007 03:35 AM — 14 posts, 53,997 views.

USA #0
Ok, maybe I'm totally wrong about the code in here, but I am very sure that I did all the right steps.

I declared the function in mud.h "DECLARE_DO_FUN", and all that jazz...

Did all the do_fun fun in tables.c, and generally matched it so that it's declaration was everywhere that mpgoto was at...

Here's the code...


/* allows the mobile to gift pl to people */

void do_mpgivepl( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    long int pl_gain = 0;

    progbug( "Entering MPgivepl", ch );

    if ( !IS_NPC( ch ) )
    {
          send_to_char( "Huh?\n\r", ch );
          progbug( "Mpgivepl - ch not NPC", ch );
          return;
    }

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

    argument = one_argument(argument, arg);

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

    pl_gain = atoi(argument);

    if( (victim = get_char_room(ch,arg)) == NULL )
    {
	progbug( "Mpgivepl - Target not found", ch );
	return;
    }
    gain_exp(ch, pl_gain);
    bug( argument, 0 );
    sprintf( buf, "Your powerlevel increases by %s points!", num_punct(pl_gain) );
    act( AT_HIT, buf, ch, NULL, victim, TO_CHAR );
}


I can explain line-by-line if there are any questions, but now to the point:

It doesn't do anything. Period. When I write "mpgivepl $n 5000" in a prog it doesn't do anything. Not even the first bug "Entering MPgivepl"...

So I'm wondering if I need to declare it elsewhere, that somehow grepping couldn't find, or maybe I just screwed up in the code.

-Tiernan

P.S. this is DBSC, a derivative of SMAUG.
USA #1
Did you create the command in-game using cedit? (see the wiki commands section here for more info)
USA #2
Ok, it's a command now, and all of the bugs are properly showing, but it's still not doing anything...

I mean all the data is moving properly, but it's not effecting to the character.

I'll shuffle through the code, but could someone suggest potential errors?

Perhaps I'm not addressing the victim properly?
Amended on Mon 26 Feb 2007 05:31 AM by Nick Gammon
USA #3
Well, at a guess...

gain_exp(ch, pl_gain);

should be affecting the victim, not the actor (ch), ne?

Also; this block of code:

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

should come after you actually look up the victim with get_char_room.

Oh, and your ACT flag should probably be TO_VICT, not TO_CHAR.
USA #4
Funny enough I found those errors, too... this is the current block of code:



void do_mpgivepl( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    long int pl_gain = 0;

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

    argument = one_argument(argument, arg);
    pl_gain = atoi(argument);

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

    if( (victim = get_char_room(ch,arg)) == NULL )
    {
	progbug( "Mpgivepl - Target not found", ch );
	return;
    }

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

    gain_exp(victim, pl_gain);
    sprintf( buf, "Victim: %s", victim->name );
    bug( buf, 0 );
    sprintf( buf, "Your powerlevel increases by %s points!", num_punct(pl_gain) );
    act( AT_HIT, buf, ch, NULL, victim, TO_VICT );
}


The bug works better, but no difference occurs with the victim's PL(powerlevel) I've examined gain_exp, but found nothing... Damn, I suck. -.- >.> =(

Maybe it has something to do with pl_gain... How could I go about displaying a number somewhere? When I try and bug it, it's asking for a string, so... blarg...

The worst part about this is that I copied the code from another place (do_plset) so I could get it working inside a mprog, which would allow quest-stuffs to give PL. It works in the other code just fine. Double-blarg.
Amended on Sun 25 Feb 2007 05:31 AM by Aqueus
USA #5
Unless the mprog code was modded for the DBSC distro, I'm half remembering some serious limitations to what character attributes could be modified via mprog. Post a link to the main DBSC distro site and I'll have a look at it to be sure I'm remembering it right and it wasn't changed.
USA #6
Ok, well, I solved the problem, but in quite the inelegant way.

I copied the guts of exp_gain that I wanted to use into the mpcommand and everything worked... a little too well, actually and for a few minutes it leveled me down to a mortal. (I had mset myself really low, and it correct my level according to my pl, fun stuff. =p)

So, yeah, in short: copied what I needed, the code ended up looking like this:


void do_mpgivepl( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    long double modgain;
    int rank = 0, newRank = 0;
    int trueRank = 0;

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

    argument = one_argument(argument, arg);
    modgain = atoi(argument);

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

    if( (victim = get_char_room(ch,arg)) == NULL )
    {
	progbug( "Mpgivepl - Target not found", ch );
	return;
    }

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

    rank = get_rank_number(victim);
    trueRank = get_true_rank(victim);
    victim->exp += modgain;

    if (NOT_AUTHED(victim) && victim->exp >= MAX_EXP_PRE_AUTH)
    {
	send_to_char("Your power level can not increase until you are authorized.\n\r", victim);
	victim->exp = MAX_EXP_PRE_AUTH;
	victim->pl = (victim->pl - (victim->pl - MAX_EXP_PRE_AUTH ));
	return;
    }

	if ( rank != get_rank_number(victim) )
	{
		sprintf( buf, "%s's rank has changed to %s", victim->name, get_rank_color(victim));
		do_info(victim, buf);
	}

	if ( trueRank != (newRank = get_true_rank(victim)) && !IS_IMMORTAL(victim) )
	{
		victim->level = newRank;
	}

    if ( (victim->exp >= ( pow(victim->max_train, 1.916056) * 6000) )
    	&& (victim->max_train < 370) )
    {
	set_char_color( AT_LBLUE + AT_BLINK, victim );
	ch_printf( victim, "You gained an additional training point!\n\r" );
	victim->train += 1;
	victim->max_train += 1;
    }

    sprintf( buf, "Your powerlevel increases by %s points!", num_punct(modgain) );
    act( AT_HIT, buf, ch, NULL, victim, TO_VICT );
}
USA #7
You really don't want to copy things out like that. Really, really.

You should try tracing through the code of gain_exp to look at what it's doing. What you did (copying the lines you needed) goes against several rules of good programming practice, and can cause you much grief later on. I would really recommend fixing it the "clean" way.

This is a great opportunity to learn how to use gdb. Use Nick's guide here as a reference.
http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=3653
Set a breakpoint at the line that calls gain_exp. Go from there. Step through the code. See if the experience is actually being added. If not, see what's preventing it.

If you don't want to use gdb, then use printf or bug-call debugging. Do whatever you want, just don't copy-paste the function segments. :-)
USA #8
Don't worry, I went through everything thoroughly, and I only grabbed the specific parts of the code I needed. No fluff, and I kept all the integral parts of the code there.

Also, before I copied the code I did some bug-call debugging, as you call it, and found that no matter what I did when I called exp_gain it was getting sent 0 as the number to increase their PL.

I eventually tried "exp_gain(victim, 500000);" to see if that would work, but it didn't. Solutions only came when I grabbed the chunks of code I needed.

Again, don't worry, I know what the code does, I just can't get it to work the 'clean' way.
USA #9
The point isn't getting only the essential parts. It is still very wrong to duplicate the functionality. The point is to figure out why the function call as-is is not working. Trust me, you really, really don't want to be yanking out parts of functions.

So, when you were calling gain_exp, the parameter was zero, even though the pl_gain variable it was non-zero right before calling the function? Are you entirely sure of that? I don't have your code here so I cannot check this myself, but I have to admit that I find this rather surprising. Something fishy is going on; I have the impression that I'm not seeing the whole story. There is no reason for a non-zero parameter to suddenly become zero.
USA #10
how funny is this line:

victim->pl = (victim->pl - (victim->pl - MAX_EXP_PRE_AUTH ));

instead of just:

victim->pl = MAX_EXP_PRE_AUTH;
Australia Forum Administrator #11
Pretty funny.
USA #12
Yeah, I don't get it either. The only possibility that I can see is that it's trying to play games with integer overflow, but not only does that not make sense in principle, but it also doesn't seem to be the case anyhow. (Even with overflows, all that will just cancel itself out.)

This is probably a case of a more complex formula being trimmed down and modified, until it reached this state that was correct, and nobody really noticed or cared enough to change it.
#13
Hey, looking back on your code.. i'd hazard a guess here -

The first one (with the call to gain_exp) showed:

long int pl_gain = 0;
gain_exp(victim, pl_gain);

The second one (with the gain_exp code ripped and pasted in) showed:

long double modgain;
victim->exp += modgain;


So, could there maybe have been a problem with sending a long int to gain_exp rather than a long double?