11 Nov, 2012, triskaledia wrote in the 1st comment:
Votes: 0
Where is the best place to stick this code bit?
I am trying to combine it with my random_armor and random_weapon code.
Also, since it is based off of affect_join…
pAf->where = TO_OBJECT;
pAf->type = 10;
pAf->duration = -1;
pAf->bitvector = 0;
pAf->level = ch->level;
pAf->next = weapon->affected;
weapon->affected = pAf;
// affect_join_obj(weapon, &pAf); //<——-Crashes MUD.

… appears to be how I should define it, but it crashes the mud.
11 Nov, 2012, Runter wrote in the 2nd comment:
Votes: 0
Just a wild guess but maybe &pAf should be pAf. I don't suspect it wants a point to a pointer there. I think in some cases (many) the structure isn't a pointer when manipulating it, and so it may be written in other places like that.
12 Nov, 2012, triskaledia wrote in the 3rd comment:
Votes: 0
Starting to get somewhere with this code bit…
Moved the affect_join_obj function into handler.c below affect_join.
Defined it in merc.h so I could pull it globally, this removed the warnings.
void affect_join_obj (OBJ_DATA * obj, AFFECT_DATA * paf)
{
AFFECT_DATA *paf_old;
bool found;

found = FALSE;
for (paf_old = obj->affected; paf_old != NULL; paf_old = paf_old->next)
{
if (paf_old->type == paf->type)
{
paf->level = (paf->level += paf_old->level) / 2;
paf->duration += paf_old->duration;
paf->modifier += paf_old->modifier;
// affect_remove_obj (obj, paf_old);
break;
}
}

affect_to_obj (obj, paf);
return;
}

When I comment out the affect_remove_obj it combines the old with the new and gives me a correct output of the combined numbers.
… Does not like it when I try to add this code bit to update.c in the obj_update function.
I'm starting to think the if statement is incorrect… I think I need an if obj->type == new->objtype then do the loop… is that what thri's code is doing?
12 Nov, 2012, triskaledia wrote in the 4th comment:
Votes: 0
To further add to the code to show where I am trying to affect_join_obj…
for (i = 0; i < 5; i++)
{
p -= 10;
int affdec = number_range (0, 11);
if (number_chance(p))
{
pAf = new_affect ();
pAf->location = aff_values_table[affdec].afftype;
if(ch->level <= 20)
pAf->modifier = number_range(aff_values_table[affdec].min_value, aff_values_table[affdec].max_value);
if(ch->level <= 40)
pAf->modifier = number_range(aff_values_table[affdec].min_value * 1, aff_values_table[affdec].max_value * 2);
if(ch->level <= 60)
pAf->modifier = number_range(aff_values_table[affdec].min_value * 1, aff_values_table[affdec].max_value * 3);
if(ch->level <= 80)
pAf->modifier = number_range(aff_values_table[affdec].min_value * 1, aff_values_table[affdec].max_value * 4);
else
pAf->modifier = number_range(aff_values_table[affdec].min_value * 1, aff_values_table[affdec].max_value * 5);

pAf->where = TO_OBJECT;
pAf->type = 10;
pAf->duration = -1;
pAf->bitvector = 0;
pAf->level = ch->level;
pAf->next = weapon->affected;
weapon->affected = pAf;
affect_join_obj(weapon, pAf); //<—-Right here
}
}

Maybe I have affect_join in the wrong spot in my for statement?
Also, for the void affect_join_obj function, I moved affect_remove_obj(obj, paf_old below the affect_to_obj(obj, paf); right before the return.
It at least now gives the weapons stats now when trying to affect instead of clearing them out.
12 Nov, 2012, quixadhal wrote in the 5th comment:
Votes: 0
As Runter said, you're using pAf->thing, which means pAf is already a pointer, so passing &pAf is passing a pointer to that pointer (AKA a handle), which isn't what the function prototype wants.

Just so you know, a->b is equivalent to (*a).b. When you're using &a, you're adding a level of indirection, which *a removes.
14 Nov, 2012, triskaledia wrote in the 6th comment:
Votes: 0
quixadhal said:
Just so you know, a->b is equivalent to (*a).b. When you're using &a, you're adding a level of indirection, which *a removes.


I'm desperately trying to figure this code out. So, a->b = (*a).b what is (*a).b Is that simliar to the CHAR_DATA *ch, defining CHAR_DATA as ch?
I did a grep of the code to find all references of affect_join, and all of them had them defined as affect_join(TARGET", &af) except for the updates on plague, and that redefined af as &plague.
After finding those references, I assumed that to be how join_affect_obj should work.
How do you go about properly handling a handle?

I'm just tired of seeing
Affects damage roll by 18.
Affects constitution by 6.
Affects intelligence by 24.
Affects constitution by 14.
I just want to see it affect by con by 24.
14 Nov, 2012, quixadhal wrote in the 7th comment:
Votes: 0
You need to step back and understand pointers (and the associated notation) first.

CHAR_DATA is a type. Technically, it's a typedef shorthand for struct char_data, but same idea. If you declare a variable such as "CHAR_DATA a;", you are creating an object of the size and format defined by struct char_data.

When you use the pointer notation to declare something, such as "CHAR_DATA *b;", you are creating a pointer which can point to objects of type CHAR_DATA. The pointer, itself, doesn't have any storage beyond the memory address it points to, which is nothing until you set it.

The '&' is the address-of operator. It gives you a pointer to the object it's applied to. So, if you do something like:

CHAR_DATA a;
CHAR_DATA *b;

b = &a;


The pointer "b" now points to the object "a". You assigned b the address-of a. Now, the other piece of the puzzles is the "->" operator, and the "." operator. When you use ".", you are accessing a member of a structure. So, in our example above, "a.level" would be the "level" variable in the CHAR_DATA object a. When you use "->", you are accessing a member in a structure that is being pointed to… we call that dereferenceing. So, "b->level" is the same as "a.level", in our example, because "b" points to "a". The hint I dropped earlier was that *b also dereferences when used outside a declaration… so just to complete that thought…. "b->level" is the same as "a.level", and also the same as "(*b).level".

Now, where this is relevant to your code above… your function prototype is:

void affect_join_obj (OBJ_DATA * obj, AFFECT_DATA * paf)


That means your function expects to get pointers to objects of type OBJ_DATA and AFFECT_DATA. Since you're using the notation paf->type (etc), paf is already a pointer. You don't want to pass in a pointer to a pointer, because your prototype expects a pointer to a structure of type AFFECT_DATA. Hence, passing in &paf is wrong. The function will expect paf to be pointing directly to an affect structure, but if you pass in &paf, you're pointing an extra layer deep, and it will likely crash because it only dereferences it one layer.

We call a pointer to a pointer, a handle. It's used sometimes when you need to pass pointers around but want the pointer itself to be able to change. Advanced concept, you'll run into later.

It's just a convention, but notice that some places may use affect_join(thing, &af) and others might use affect_join(thing, paf)… many people like to preface their variable names with "p" to mean "pointer".

So, your first example posted was wrong, because you were passing a pointer to a pointer. Your second and third examples were right, in that they were passing pointers. Hopefully the above helps explain why.
14 Nov, 2012, Runter wrote in the 8th comment:
Votes: 0
It may be useful to realize that pointers are just integers. So you don't want to do operations on the value of the pointer itself in most cases. To goto the thing it points to we call that dereferencing. And we do that with *variable notation. This lets us change the memory representing the thing you're pointing to. Not the pointer itself. As Quix mentioned you may have as many levels as you want. Pointers pointing to pointers pointing to pointers. int ***lol; The important thing to take away here is that s->val hides the syntax of (*s).val and if s wasn't a pointer it would simply be s.val
14 Nov, 2012, Davion wrote in the 9th comment:
Votes: 0
For even more on the subject of pointers :D. Because, honestly, you can never understand them TOO well! There's even more detail in here an definitely worth the read.

[link=article]C_Pointers:_The_Basics[/link]
15 Nov, 2012, triskaledia wrote in the 10th comment:
Votes: 0
So, if I was coding it right without properly understanding that which I was doing,
it is just a matter of the join_affect_obj not being properly coded (working right)
since it is still returning my objects as having two instances of a given attribute.
Either that or I have it defined to join in the wrong spot… I'll look at it some more.
21 Nov, 2012, triskaledia wrote in the 11th comment:
Votes: 0
void affect_join_obj (OBJ_DATA *obj, AFFECT_DATA *paf)
{
AFFECT_DATA *paf_old;
bool found;

found = FALSE;
for (paf_old = obj->affected; paf_old != NULL; paf_old = paf_old->next)
{
if (paf_old->type == paf->type)
{
paf->where = paf_old->where;
paf->level = paf_old->level;
paf->duration = paf_old->duration;
paf->location = paf_old->location;
paf->modifier += paf_old->modifier;
paf->bitvector = paf->bitvector;
// affect_to_obj (obj, paf);
// affect_remove_obj (obj, paf_old);
// free_affect (paf_old);
break;
}
}
affect_to_obj (obj, paf);
free_affect(paf_old);
affect_remove_obj (obj, paf_old);
return;
}

Defining it like this, I no longer have multiple definitions of affects on items. However, I am not sure if I am clearing the objects data and only entering it once.
(Still driving me nuts until i get this working) Am I getting closer?
21 Nov, 2012, Runter wrote in the 12th comment:
Votes: 0
void affect_join_obj (OBJ_DATA *obj, AFFECT_DATA *affect_to_add) {
AFFECT_DATA *existing_affect;

for (existing_affect = obj->affected;existing_affect != NULL;existing_affect = existing_affect->next) {
if (existing_affect->type == affect_to_add->type) {
existing_affect->duration = affect_to_add->duration;
existing_affect->modifier = affect_to_add->modifier;
return;
}
}

affect_to_obj (obj, affect_to_add);
}
21 Nov, 2012, Rarva.Riendf wrote in the 13th comment:
Votes: 0
I would suggest something like this instead because Runter code while being perfectly valid, does not ensure the affect are properly applied. (affect_obj could do more than just fill the list, we dont know)

This is for character but it is the same for object.

void affect_join(CHAR_DATA *ch, AFFECT_DATA *paf) {
AFFECT_DATA *paf_old;
for (paf_old = ch->affected;paf_old ;paf_old = paf_old->next) {
if (paf_old->type == paf->type) {
paf->duration += paf->level > paf_old->level ? paf_old->duration / 2 : paf->duration / 2;
paf->modifier += paf_old->modifier;
paf->level = paf->level > paf_old->level ? paf->level : paf_old->level;
affect_remove(ch, paf_old);
break;
}
}
affect_to_char(ch, paf);
}
23 Nov, 2012, triskaledia wrote in the 14th comment:
Votes: 0
Quote
This is for character but it is the same for object.


This is exactly what the snippet is, Rarva. It is the character affect_join changed to be objects.
I don't know why it doesn't like to properly remove the original value of the item. Maybe because I
have it added in the wrong place within my weapon/armor_load definitions. Not sure. I do a lot of
guessing and checking, that's why I come over here when I get in a jam. (Not bitching)
Runters code suggestion seems to work also, but like the final steps of mine, it doesn't appear
that it is properly adding the original values to the incoming values.
23 Nov, 2012, Runter wrote in the 15th comment:
Votes: 0
It's perhaps that the code doesn't actually calculate values that way and you'll need to use the affect_to_* function again rather than adding to the old value to make it effectual.
23 Nov, 2012, Rarva.Riendf wrote in the 16th comment:
Votes: 0
Your problem then definitely is not here. when you change values on object that affect a player, you have to check the player after that to apply values.
Thre is a very simple way to do that, as the add/remove object do that. Remove object from the player, add the values, make it wear again, problem solved.
I suggest this because this way you avoid to scatter the checks everywhere. They stay in wear/remove objects.

void affect_to_obj(OBJ_DATA *obj, AFFECT_DATA *paf) {
if (objLogOn)
log_param("affect object:%s with %d", obj->keyword, paf->type);

short int slotUsed = obj->wear_loc;
//we remove the item from the char to get all affect properly applied
CHAR_DATA *ch = obj->carried_by;
if (slotUsed != -1 && ch)
unequip_char(ch, obj); // this is what I am talking about


And this is also why I suggested my code instead of Runters one.
0.0/16