27 Mar, 2009, Igabod wrote in the 1st comment:
Votes: 0
Ok, I have a player telling me that his dr bonus from being in demonform is intermittent, he's not having problems with his hitroll, just his damroll. I've done everything I can think of to make this work but nothing is working. Here's what I've got in int char_damroll

if (IS_CLASS(ch,CLASS_DEMON))
{
if (IS_DEMPOWER(ch,DEM_FORM) && IS_POLYAFF(ch,POLY_ZULO))
{
dr += 300;
}
}
else if (IS_POLYAFF(ch, POLY_ZULO))
dr += 300;
return dr;
}


that's the end of int char_damroll in act_info.c I changed it from the way it was in stock in an attempt to fix the problem but wound up with the same results. If anybody has any insight into this I'd appreciate all the help I can get. I'm running godwars/low4.
27 Mar, 2009, David Haley wrote in the 2nd comment:
Votes: 0
The question is very underspecified, right…? What is "intermittent"? What is the expected behavior, very precisely, in terms of the predicates you have given us above?
27 Mar, 2009, Igabod wrote in the 3rd comment:
Votes: 0
expected behavior is that while the player has demonform active they receive a damroll bonus of 300. This is supposed to be a constant bonus to damroll. By intermittent I mean he'll type score, see his damroll then 5 minutes later, without typing demonform again, he types score again to see 300 less damroll than he's supposed to have. I don't really know what's so underspecified about the question there, it's a very simple function. Player types demonform, his char transforms into a giant hulking demon and stays that way till player types demonform again.
27 Mar, 2009, ghasatta wrote in the 4th comment:
Votes: 0
As a former professional bug wrangler, I suggest that you keep trying to reproduce the problem yourself until you can get a consistent feel for what is actually happening vs. what is expected to happen. Once you are able to reproduce the problem consistently yourself, you can then use a debugger to step through the code, as well as example all the relevant data objects, and verify that your code is working the way it is supposed to (or not working).

Good luck.
27 Mar, 2009, Igabod wrote in the 5th comment:
Votes: 0
the thing is, demonform uses POLY_ZULO and so do a few other things in the game, there's nothing wrong with those. I've noticed the problem myself on a test character, and it doesn't happen at a set time, like every 4 ticks or anything, it just happens randomly (apparently). One minute you'll have 984 damroll and start fighting something, then halfway through the fight your damroll drops to 684. I've even put my damroll on my prompt so I could see exactly when it happened. It doesn't happen during every fight (and I tested using the exact same mob over and over) nor does it happen at the same time during the fight. The only reason you have to be fighting is cause it won't update the displayed number till you start fighting. I can't make it happen on command but it generally happens frequently. What other steps do I need to take here?
27 Mar, 2009, David Haley wrote in the 6th comment:
Votes: 0
What I meant by underspecified is that that function is so simple that the problem is likely to be lurking somewhere in the huge codebase around it. There's an awful lot that could be going on here. For example, let's start with what this means:

IS_DEMPOWER(ch,DEM_FORM)

And then, what this means:

IS_POLYAFF(ch,POLY_ZULO)

Once it's clear what these are really doing in terms of code (the intention behind them is all but irrelevant) you can start looking for where the data structures they touch are modified. Maybe there's some kind of polymorph function that removes effects or something. Maybe powers wear off after a while. There's so much that could be going on here and that one function is just a little symptom of something else. My guess is that the power or effect are being inappropriately removed, but that could be happening in any number of places.
28 Mar, 2009, Igabod wrote in the 7th comment:
Votes: 0
Alright, further testing has determined that demonform isn't affecting damroll at all, however it is affecting hitroll as it should. Here's a copy of the entire char_damroll function after I formatted it up so that it's easier to see everything.

int char_damroll( CHAR_DATA *ch )
{
int dr = GET_DAMROLL(ch);
int min;

if (!IS_NPC(ch))
{
if (IS_CLASS(ch,CLASS_VAMPIRE) && ch->pcdata->stats[UNI_RAGE] > 0)
dr += ch->pcdata->stats[UNI_RAGE];
else if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->stats[UNI_RAGE] > 0)
dr += ch->pcdata->stats[UNI_RAGE];
else if (IS_CLASS(ch, CLASS_PALADIN))
{
dr += 25;
}
else if (IS_SET(ch->special,SPC_WOLFMAN) && ch->pcdata->stats[UNI_RAGE] > 0)
dr += ch->pcdata->stats[UNI_RAGE] * 1.5;
else if (IS_CLASS( ch,CLASS_DEMON ) && ch->pcdata->stats[DEMON_POWER] > 0)
dr += ((ch->pcdata->stats[DEMON_POWER]) * ch->pcdata->stats[DEMON_POWER]);

if (IS_SET(ch->special,SPC_CHAMPION) && ch->pcdata->stats[DEMON_POWER] > 0)
dr += ((ch->pcdata->stats[DEMON_POWER]) * ch->pcdata->stats[DEMON_POWER]);

if (ch->hit < ch->max_hit && !IS_SET(ch->newbits, NEW_NOPAIN))
{
return dr;
min = dr * 0.75;

if (ch->hit < 1 || ch->max_hit < 1)
dr *= 0.75;
else
{
dr = dr * ch->hit / ch->max_hit;

if (dr < min) dr = min;
}
}

if (IS_CLASS(ch, CLASS_NINJA) && ch->pcdata->powers[NPOWER_CHIKYU] >= 6
&& ch->pcdata->powers[HARA_KIRI] > 0)
dr += 50;

if (IS_CLASS(ch, CLASS_HIGHLANDER) && (get_eq_char(ch, WEAR_WIELD) != NULL))
{
int wpn = ch->wpn[1];

if (wpn >= 500)
dr += 500;
else
dr += wpn;
}

if (IS_SET(ch->hforms,HFORM_KENSAI))
dr += 500;
if (IS_SET(ch->hforms,HFORM_BATTLEFORM))
dr += 250;
if (IS_CLASS(ch, CLASS_DROW) && IS_POLYAFF(ch,POLY_SPIDERFORM))
dr += 250;
if (IS_DEMPOWER(ch,DEM_FORM) && IS_CLASS(ch,CLASS_DEMON))
{
if (IS_POLYAFF(ch,POLY_ZULO))
{
dr += 300;
}
}
else if (IS_POLYAFF(ch, POLY_ZULO))
dr += 300;
}
return dr;
}


the corresponding piece of code in char_hitroll for demonform is as follows:

if (IS_DEMPOWER(ch,DEM_FORM) && IS_CLASS(ch,CLASS_DEMON))
{
if (IS_POLYAFF(ch,POLY_ZULO))
{
hr += 300;
}
}


both are identical yet the damroll doesn't change. The other things in char_damroll are working fine as well so it's not a problem with char_damroll itself or any calls to it in the code.

the definition of IS_DEMPOWER is as follows:

#define IS_DEMPOWER(ch, sn)     (IS_SET((ch)->pcdata->powers[DPOWER_FLAGS], (sn)))


IS_POLYAFF is defined below:

#define IS_POLYAFF(ch, sn)      (IS_SET((ch)->polyaff, (sn)))


Any further insight would be very much appreciated.
28 Mar, 2009, David Haley wrote in the 8th comment:
Votes: 0
For starters, as a general principle, you should format your code correctly even if you're not showing other people, because if it helps you read it better, it helps you debug it. Sometimes the code isn't doing what you think it's doing, and that discrepancy is made clear when the formatting is correct. This is particularly true with braceless if statements, for example.

Anyhow, here is your likely problem.

if (ch->hit < ch->max_hit && !IS_SET(ch->newbits, NEW_NOPAIN))
{
return dr;
min = dr * 0.75;
if (ch->hit < 1 || ch->max_hit < 1)
dr *= 0.75;
else
{
dr = dr * ch->hit / ch->max_hit;
if (dr < min) dr = min;
}
}


Oftentimes, as we see above, the problem comes from a completely irrelevant part of the function.

This is why stepping through with a debugger is very helpful, because (and I'm assuming that this actually is the problem) you would have seen immediately that you're never getting to the check you thought you were. In fact, even putting in print statements would show that. A good technique for this kind of thing if you're allergic to debuggers is to simply have print statements that tell you what lines of code are actually being executed.
28 Mar, 2009, Igabod wrote in the 9th comment:
Votes: 0
I do format any code I write correctly, it's just that the stock release was butchered by sage copy/pasting without a care in the world. That and it was probably pretty messy when he got it, and when kavir got merc it was probably messy too. So all in all I'm doing pretty good on the cleaning up of the code.

So what in particular is wrong with that piece of code? It looks correct to me, the only thing that sticks out to me is the return dr; but that should be there I'm pretty sure.
28 Mar, 2009, ghasatta wrote in the 10th comment:
Votes: 0
Please walk through your code with a debugger. It might take a little bit of effort on your part but it will help you avoid these sorts of problems in the future. I suspect that in the future some people may feel like answering the same questions repeatedly is not worthwhile if you don't show that you are going to make some effort on your own.
28 Mar, 2009, ghasatta wrote in the 11th comment:
Votes: 0
Here is a gdb tutorial.

http://www.cs.princeton.edu/~benjasik/gd...

Read up on setting a breakpoint. Then create a breakpoint on the function that calculates damroll.

Read up on stepping through code. Then step through the function that you set the breakpoint on.

Read up on examining values. Then examine the damroll value before and after operations as you step through the code.

HTH.
28 Mar, 2009, Igabod wrote in the 12th comment:
Votes: 0
It's not that I'm unwilling to use gdb, it's just that none of the information it spits out makes much sense to me. I'll give your link and instructions a shot though and see what I come up with. I'm sure I'll still need to ask questions but I'll still try it.
28 Mar, 2009, Igabod wrote in the 13th comment:
Votes: 0
Ok now that I know how to set a breakpoint, where would I need to set it? On int char_damroll or on the particular line that NEW_NOPAIN begins? By the way, that tutorial was way to confusing for me since it's not geared toward mud coding. I am using one from nick gammon's website though.
28 Mar, 2009, Igabod wrote in the 14th comment:
Votes: 0
Well I figured out a fix for this, it's probably not the best way to do it but I just moved the portion in question down to the bottom of the char_damroll function and now everything works as planned. Though I'm betting NEW_NOPAIN is probably buggy so that'll be the next thing I test. I still need to learn gdb a little better but I think I'll have to find someone who can answer my questions as I come to them cause all the tutorials I've found or been told about have left me with more questions than I had to begin with.
28 Mar, 2009, David Haley wrote in the 15th comment:
Votes: 0
Why exactly do you think that the return statement is supposed to be there? (Do you know what a return statement does?) Did you try putting in print statements to see what code is being executed?
0.0/15