19 Mar, 2009, boblinski wrote in the 1st comment:
Votes: 0
I've added the affect2 snippet, and I'm having troubles all over the show, so I thought I'd open a topic specifically for Affect2!

Current Problem:
Affect2 affects are not being removed when a character dies..

Do I just add this to 'raw_kill':
while (victim->affected2)
affect_remove (victim, victim->affected2);
victim->affected2_by = race_table[victim->race].aff2;
20 Mar, 2009, boblinski wrote in the 2nd comment:
Votes: 0
void raw_kill (CHAR_DATA * victim)
{
int i;

stop_fighting (victim, TRUE);
death_cry (victim);
make_corpse (victim);

if (IS_NPC (victim))
{
victim->pIndexData->killed++;
kill_table[URANGE (0, victim->level, MAX_LEVEL - 1)].killed++;
extract_char (victim, TRUE);
return;
}

extract_char (victim, FALSE);
while (victim->affected)
affect_remove (victim, victim->affected);
victim->affected_by = race_table[victim->race].aff;
while (victim->affected2) /*added to original*/
affect_remove (victim, victim->affected2); /*added to original*/
victim->affected2_by = race_table[victim->race].aff2; /*added to original*/
for (i = 0; i < 4; i++)
victim->armor[i] = 100;
victim->position = POS_RESTING;
victim->hit = UMAX (1, victim->hit);
victim->mana = UMAX (1, victim->mana);
victim->move = UMAX (1, victim->move);
/* save_char_obj( victim ); we're stable enough to not need this :) */
return;
}

If I use that, I get these errors:
Quote
gcc -Wall -O -ggdb -DNOCRYPT -DQMFIXES -c -o obj/fight.o fight.c
fight.c: In function `raw_kill':
fight.c:1737: error: structure has no member named `affected2'
fight.c:1738: error: structure has no member named `affected2'
fight.c:1739: error: structure has no member named `aff2'
make: *** [obj/fight.o] Error 1
20 Mar, 2009, Skol wrote in the 3rd comment:
Votes: 0
Look in merc.h for character structure. Look for affected in there, you'll find it needs another one.

In :struct mob_index_data find:
long                affected_by;

and add underneath it:
long                affected_by2;


Then in struct char_data, do the same thing.
Then in the struct race_type,
long aff; /* aff bits for the race */
long aff2; /* aff2 bits for the race */

You'll also have to extend _every_ race with a ,0 after the part where it has 'aff' in const.c.
That part might be a nightmare.
20 Mar, 2009, Skol wrote in the 4th comment:
Votes: 0
const struct race_type race_table[] = {
/*
{
name, pc_race?,
act bits, aff_by bits, off bits,
imm, res, vuln,
form, parts
},
*/
{
"elf", TRUE,
0, AFF_INFRARED, 0,
0, RES_CHARM, VULN_IRON,
A | H | M | V, A | B | C | D | E | F | G | H | I | J | K},


I put elf in there because humans aren't stock affected by anything.
See where it has AFF_INFRARED? Your structure will change to this:
/*
{
name, pc_race?,
act bits, aff_by bits, aff2_by bits, off bits,
imm, res, vuln,
form, parts
},
*/

So the above elf structure might be:
{
"elf", TRUE,
0, AFF_INFRARED, AFF_CREEP, 0,
0, RES_CHARM, VULN_IRON,
A | H | M | V, A | B | C | D | E | F | G | H | I | J | K},

AFF_CREEP, in a race with no affect2, would just be 0.
Or if it had a couple it could be AFF_CREEP|AFF_GLIDE etc.

So you'll have to go through and add that ,0 at the correct spot in each race. Not too terrible, but if you do it in the wrong spot, it might think AFF_DETECT_HIDDEN is OFF_DISARM or something as it's just a number replacement.
20 Mar, 2009, boblinski wrote in the 5th comment:
Votes: 0
I just did all the things you said (some of it I already had) but I'm still getting the following error:

Quote
gcc -Wall -O -ggdb -DNOCRYPT -DQMFIXES -c -o obj/fight.o fight.c
fight.c: In function `raw_kill':
fight.c:1737: error: structure has no member named `affected2'
fight.c:1738: error: structure has no member named `affected2'
make: *** [obj/fight.o] Error 1


while (victim->affected2)                            /*line 1737*/
affect_remove (victim, victim->affected2); /*line 1738*/
victim->affected2_by = race_table[victim->race].aff2;


I did make clean.
20 Mar, 2009, Igabod wrote in the 6th comment:
Votes: 0
I think it needs to be added in several places in save.c as well but I could be wrong. I don't know of any stock codebases that already have aff2 installed, but if you know of any I'd look at that codebase and search for aff2 as well as affected2 and affected2_by (or affected_by2), then just figure out what you're missing from there.

[edit to add] actually, i just looked through my personal repository and found that davion's old mud which is available for download HERE has affected2_by and all that, so just download that code and use it as a guide for what you're missing, you might also find some other interesting things with that code (though I warn you it's full of bugs)
20 Mar, 2009, boblinski wrote in the 7th comment:
Votes: 0
Has no one actually implemented affect2 on their mud?
20 Mar, 2009, Igabod wrote in the 8th comment:
Votes: 0
I personally haven't, but obviously Davion has, look at the codebase I linked to above, it has all the info you need. You'll learn better if you look for it yourself anyway than you will by being told exactly how to do it. Eventually you'll get to the point where you have a copy of the code repository here so that you have a LOT of reference material. I've gotten so much help from other codebases.
20 Mar, 2009, boblinski wrote in the 9th comment:
Votes: 0
I just looked at it, and it doesn't seem to have it implemented completely. Does anyone know of a mud that has affect2 implemented and working 100% including saving/loading the affect2's.. and setting them on mobs etc etc?
20 Mar, 2009, Sharmair wrote in the 10th comment:
Votes: 0
boblinski said:
I just did all the things you said (some of it I already had) but I'm still getting the following error:

Quote
gcc -Wall -O -ggdb -DNOCRYPT -DQMFIXES -c -o obj/fight.o fight.c
fight.c: In function `raw_kill':
fight.c:1737: error: structure has no member named `affected2'
fight.c:1738: error: structure has no member named `affected2'
make: *** [obj/fight.o] Error 1


while (victim->affected2)                            /*line 1737*/
affect_remove (victim, victim->affected2); /*line 1738*/
victim->affected2_by = race_table[victim->race].aff2;


I did make clean.

I would delete those two lines as they are probably not doing anything close to what
you are trying to go for here.

I think you might be getting the members affected and affected_by confused here.
The affected_by member is the existing effect flags (and is an int or preferably an
unsigned int) and is the one you are basically cloning with the new affected2_by
flag set to handle more effects.

On the other hand, the affected member is the head of a list of spell/skill effects on
the character (a list of affect_type structs). The only thing you have to do with that,
is adding that TO_AFFECTS2 where define and the code to use that. As a note on this -
I gave some code for this before, but I only showed one place in affect_modify() as an
example, there are in fact two places in that function, one for setting the bits and the
other for resetting. Doing a quick scan of stock ROM, it looks like the support for
TO_AFFECTS2 should be add two places in spell_identify(), three places in affect_check(),
the 2 places in affect_modify(), 2 places in do_ostat() and once in load_objects(). In
all the cases look for TO_AFFECTS (all cases are in switch statements) and add the
code for TO_AFFECTS2 to do the same type of thing. BUT what you DON'T want to do
is add a new version of affected, there is NO reason to have a 2nd list of effects.
20 Mar, 2009, Hades_Kane wrote in the 11th comment:
Votes: 0
I have a lot more affects in my game than what my bitvectors allow.

I didn't implement affect2 or extended bitvectors.

Let's say the affect confused… I don't have an AFF_CONFUSED to handle all that. As an example, I add the confuse spell, declared in const.c as spell_confuse, but then I also declare in the skill table in the gsn part for gsn_confuse.

Now in the code where confuse is checked for, rather than…

if (IS_AFFECTED (ch, AFF_CONFUSE))


I check for:

if(is_affected(ch,skill_lookup("confuse")))


Same with adding the affect.

af.where     = TO_AFFECTS;
af.type = gsn_confused;
af.level = ch->level;
af.location = 0;
af.modifier = 1;
af.duration = number_range(1, 3);
af.bitvector = 0;
affect_to_char(victim,&af);


There may be some reason as to why this might be "bad", I don't know, but its served me quite well. You might be overcomplicating something that your code can currently do.
20 Mar, 2009, Vladaar wrote in the 12th comment:
Votes: 0
Wow that is interesting Hades. No ill effects from doing that eh?

Vladaar
20 Mar, 2009, Hades_Kane wrote in the 13th comment:
Votes: 0
Vladaar said:
Wow that is interesting Hades. No ill effects from doing that eh?

Vladaar


The biggest problem I would have with it would be the inability to set affects on mobs in the way that OLC is written or set them on objects under the addaffect stuff, that would be the only limitation I've noticed. And on that note, I've taken to reserving the AFF_ flags for affects that I would want to be on mobs or objects on load. There are other easy ways around this, though, such as adding a program command for a mob or object to be able to directly set an affect on itself on load or under specific conditions without casting.

One of the only other issues that come to mind is this scenario… I added a 'fatigue' affect that is added to the Fighter's blitz skill, basically as a cool down timer for using the skill again. I've since expanded it to work based on other skills such as the Moogle 'float' ability, and have added in a few things here and there that cause the fatigue status affect aside from the skills that use as a cool down timer. Now, I don't have a fatigue skill, but I have added in 'fatigue' in the skill table so I have a gsn_fatigue to base the affect off of. So, now, I 'set skill self all 100' for example, and now I have 'fatigue' in my skill list. It doesn't actually do anything, I can't use fatigue or cast fatigue, but it is a little bit of a side affect. I'm sure there would be way some way to keep this from happening, maybe adding a value in my skill table that defines whether or not something is a true, usable skill (or even having skill setting not work on a skill that has a level value of -2 [in fact, I might try that later…]), or something to that extent, but it's relatively minor.

Also, I noticed that in one spot I had skill_lookup("confuse") and in the affect type I had gsn_confuse. I'm rather sure that those two are basically interchangeable. Skill_lookup works based on the name of the skill/spell and grabs the associated sn or gsn, while using gsn_ directly bypasses that. Also, on removing affects, those that are handled this way is as simple as: affect_strip ( ch, gsn_confuse ); None of that need to REMOVE_BIT.

But, that's the way I've gone about it. I'm sure there are better ways. Ideally, extended bit vectors would be present in most forms of stock code, and while I might eventually consider trying to add that in since I'm running really low on act, comm, and plr flags, and already ran out of room flags and had to add room2, it's just not something very pressing right now since there are easily accessible alternatives.

On a side note, if the RaM project has gotten to extended bitvectors, the OP might want to consider looking into how far along they've come and if converting to that codebase and re-adding some of his stuff would end up being less work in the long run.
20 Mar, 2009, Davion wrote in the 14th comment:
Votes: 0
HK, is IS_AFFECTED different from is_affected? You can't just throw random numbers at IS_AFFECTED and hope it works. It uses bitwise operators to set things.

For example, when you set a bit of value 3, you'll get '…0011'. Now if you check for IS_SET for 1 or 2, they'll both return true.
20 Mar, 2009, Hades_Kane wrote in the 15th comment:
Votes: 0
Davion said:
HK, is IS_AFFECTED different from is_affected?


In merc.h under my character macros, I have:
#define IS_AFFECTED(ch, sn)	(IS_SET((ch)->affected_by, (sn)))


In handler.c:
/*
* Return true if a char is affected by a spell.
*/
bool is_affected( CHAR_DATA *ch, int sn )
{
AFFECT_DATA *paf;

for ( paf = ch->affected; paf != NULL; paf = paf->next )
{
if ( paf->type == sn )
return TRUE;
}

return FALSE;
}
21 Mar, 2009, Sandi wrote in the 16th comment:
Votes: 0
IIRC, in Rom, the skill numbers are a set of integers from 1 to 1000, and there's something (hand_to_hand?) cleverly above that range. Pfiles store affects by name, the sn's are generated at boot.
21 Mar, 2009, Rendelven wrote in the 17th comment:
Votes: 0
Hades_Kane said:
I have a lot more affects in my game than what my bitvectors allow.

I didn't implement affect2 or extended bitvectors.

Let's say the affect confused… I don't have an AFF_CONFUSED to handle all that. As an example, I add the confuse spell, declared in const.c as spell_confuse, but then I also declare in the skill table in the gsn part for gsn_confuse.

Now in the code where confuse is checked for, rather than…

if (IS_AFFECTED (ch, AFF_CONFUSE))


I check for:

if(is_affected(ch,skill_lookup("confuse")))



There may be some reason as to why this might be "bad", I don't know, but its served me quite well. You might be overcomplicating something that your code can currently do.


I can give you one example that I have used in my own MUD that is useful for not relying solely on is_affected. Certain classes have a natural fly ability. I implemented 'fly' and 'land' commands that allow a player to… fly or land. This works if they have the FLY SPELL as well as if they have the ability to fly ( wings ). I obviously don't want to remove a flying spell if a player with a natural flying ability lands. A player that is 'flying' naturally isn't really "affected" by anything. They are just set to flying.
21 Mar, 2009, Skol wrote in the 18th comment:
Votes: 0
Rend, I did the same, nice ;).
Although mine doesn't have any flying players, but mobs with wings can fly/land (and players flying can 'land'). but yeah, I did the same with it just removing AFF_FLYING vs removing spell effect depending on if they're affected by the spell or just actually flying.
22 Mar, 2009, boblinski wrote in the 19th comment:
Votes: 0
Sharmair said:
I think you might be getting the members affected and affected_by confused here.
The affected_by member is the existing effect flags (and is an int or preferably an
unsigned int) and is the one you are basically cloning with the new affected2_by
flag set to handle more effects.

On the other hand, the affected member is the head of a list of spell/skill effects on
the character (a list of affect_type structs). The only thing you have to do with that,
is adding that TO_AFFECTS2 where define and the code to use that. As a note on this -
I gave some code for this before, but I only showed one place in affect_modify() as an
example, there are in fact two places in that function, one for setting the bits and the
other for resetting. Doing a quick scan of stock ROM, it looks like the support for
TO_AFFECTS2 should be add two places in spell_identify(), three places in affect_check(),
the 2 places in affect_modify(), 2 places in do_ostat() and once in load_objects(). In
all the cases look for TO_AFFECTS (all cases are in switch statements) and add the
code for TO_AFFECTS2 to do the same type of thing. BUT what you DON'T want to do
is add a new version of affected, there is NO reason to have a 2nd list of effects.


I'm trying to add it in all the places you said, the only one I don't know what to do is in load_objects()… Is it something to do with this part of the code?
else if (letter == 'F')
{
AFFECT_DATA *paf;

paf = alloc_perm (sizeof (*paf));
letter = fread_letter (fp);
switch (letter)
{
case 'A':
paf->where = TO_AFFECTS;
break;
case 'I':
paf->where = TO_IMMUNE;
break;
case 'R':
paf->where = TO_RESIST;
break;
case 'V':
paf->where = TO_VULN;
break;
default:
bug ("Load_objects: Bad where on flag set.", 0);
exit (1);
}

What do I add for the AFFECTS2 ?
22 Mar, 2009, Sharmair wrote in the 20th comment:
Votes: 0
boblinski said:
I'm trying to add it in all the places you said, the only one I don't know what to do is in load_objects()… Is it something to do with this part of the code?
else if (letter == 'F')
{
AFFECT_DATA *paf;

paf = alloc_perm (sizeof (*paf));
letter = fread_letter (fp);
switch (letter)
{
case 'A':
paf->where = TO_AFFECTS;
break;
case 'I':
paf->where = TO_IMMUNE;
break;
case 'R':
paf->where = TO_RESIST;
break;
case 'V':
paf->where = TO_VULN;
break;
default:
bug ("Load_objects: Bad where on flag set.", 0);
exit (1);
}

What do I add for the AFFECTS2 ?

Yes, that is the place. This part of the code handles loading an object from an area file that
has effects that modify flags. As an example of how the area file might look, here is the stock
olympus.are object vnum 904:
#904
sandals winged~
a pair of winged sandals~
A pair of well made sandals lies here.~
oldstyle~
armor FGK AG
8 8 8 4 0
25 50 2200 P
F //This is the start of the 'flag' effect
A 0 0 T //The A is affected_by and T is AFF_FLYING

This puts an effect on the object to set the AFF_FLYING affected_by flag on the character when
worn. As a side note, this effect also has APPLY_NONE of 0, but you could have the effect do
double duty and also apply something. As an example, this effect will add flying and add 3 to dex:
F
A 2 3 T

To add support for your new affected2_by flags, you will have to expand the area file format to
have an option for TO_AFFECTS2. I will assume here that the snippet you added does not
support this at all, as it appears that ROM (stock) has no support at all for on line editing of
area files. To get the list of places to change in my last post, I did a quick scan of stock ROM
2.4b6, if you do have area OLC there will also be a place to add affected2_by support on writing
the area file and probably editing effects on objects. But I am giving all this detail so you can
directly edit your area files (ick). Anyway, you just have to add a new letter for the affected2_by
flags, if your snippet adds one, use that letter. But for this I am going to add the letter E (you
can use anything other then A, I, R or V though), but if you like something else better, feel
free to use that. Your code segment would look something like:
else if (letter == 'F')
{
AFFECT_DATA *paf;

paf = alloc_perm (sizeof (*paf));
letter = fread_letter (fp);
switch (letter)
{
case 'A':
paf->where = TO_AFFECTS;
break;
case 'E':
paf->where = TO_AFFECTS2;
break;
case 'I':
paf->where = TO_IMMUNE;
break;
case 'R':
paf->where = TO_RESIST;
break;
case 'V':
paf->where = TO_VULN;
break;
default:
bug ("Load_objects: Bad where on flag set.", 0);
exit (1);
}
0.0/47