Crossfire Mailing List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
CF: Some owner fixes
- To: crossfire (at) ifi.uio.no
- Subject: CF: Some owner fixes
- From: Jan Echternach <>
- Date: Mon, 22 May 2000 15:14:31 +0200
- Mail-Followup-To:
- Reply-To: Jan Echternach <>
- Sender:
This patch is already in the CVS tree. It fixes explode_object() which
used op->owner directly and it fixes move_swarm_spell() which didn't
cast the spells with the correct skill and experience object pointers
set. Furthermore, it might fix something in tailor_god_spell() (there
was some suspicious code which should now be at least more robust).
common/object.c: Splitted set_owner() into set_owner_simple() and
set_owner(). copy_owner(): New function.
server/spell_util.c: explode_object(): Use copy_owner() instead of setting
skill and experience objects manually. Bugfix: Don't use op->owner
directly (fixed by using the caster in call to SP_level_dam_adjust(),
not the owner, which was wrong anyway).
server/spell_util.c: fire_arch_from_position(): Use copy_owner() instead
of set_owner() if 'op' isn't the real owner but only a spell object
owned by somebody else.
server/spell_util.c: move_swarm_spell(): Use the swarm spell object as
the owner in call to fire_arch_from_position(), which now handles this
case correctly.
server/spell_util.c: fire_swarm(): Call tailor_god_spell().
server/gods.c: determine_god(): op->type==SWARM_SPELL is a spell.
server/gods.c: tailor_god_spell(): op->type==SWARM_SPELL is a spell.
Always abort function if we couldn't find a god. Always add god's
attacktype if the spellop's attacktype has AT_GODPOWER.
*** orig/crossfire-0.95.5-cvs1-patch-pre13-urgent5/common/object.c Thu Mar 16 08:06:57 2000
--- crossfire-0.95.5-cvs1/common/object.c Mon May 22 13:53:17 2000
***************
*** 355,372 ****
/*
* Sets the owner of the first object to the second object.
* Also checkpoints a backup id-scheme which detects freeing (and reusage)
* of the owner object.
* See also get_owner()
- * The real purpose of setting an owner is so we know who kills something
- * so we can properly credit EXP.
*/
! void set_owner(object *op, object *owner) {
!
! if(owner==NULL||op==NULL)
! return;
/* next line added to allow objects which own objects */
/* Add a check for ownercounts in here, as I got into an endless loop
* with the fireball owning a poison cloud which then owned the
* fireball. I believe that was caused by one of the objects getting
* freed and then another object replacing it. Since the ownercounts
--- 355,368 ----
/*
* Sets the owner of the first object to the second object.
* Also checkpoints a backup id-scheme which detects freeing (and reusage)
* of the owner object.
* See also get_owner()
*/
! static void set_owner_simple (object *op, object *owner)
! {
/* next line added to allow objects which own objects */
/* Add a check for ownercounts in here, as I got into an endless loop
* with the fireball owning a poison cloud which then owned the
* fireball. I believe that was caused by one of the objects getting
* freed and then another object replacing it. Since the ownercounts
***************
*** 382,409 ****
op->owner=owner;
op->ownercount=owner->count;
owner->refcount++;
#ifdef ALLOW_SKILLS /* set the pointers in op to inherit owners skill, exp_obj */
! if(owner->type==PLAYER&&owner->chosen_skill) {
! op->chosen_skill = owner->chosen_skill;
! op->exp_obj = owner->chosen_skill->exp_obj;
!
! /* unfortunately, we can't allow summoned monsters skill use
! * because we will need the chosen_skill field to pick the
! * right skill/stat modifiers for calc_skill_exp(). See
! * hit_player() in server/attack.c -b.t.
! */
! if(QUERY_FLAG(op,FLAG_CAN_USE_SKILL))
! CLEAR_FLAG(op,FLAG_CAN_USE_SKILL);
! if(QUERY_FLAG(op,FLAG_READY_SKILL))
! CLEAR_FLAG(op,FLAG_READY_SKILL);
! } else if(op->type!=PLAYER && QUERY_FLAG(op,FLAG_READY_SKILL))
! CLEAR_FLAG(op,FLAG_READY_SKILL);
#endif
}
/*
* Resets vital variables in an object
--- 378,447 ----
op->owner=owner;
op->ownercount=owner->count;
owner->refcount++;
+ }
+
+ #ifdef ALLOW_SKILLS
+ static void set_skill_pointers (object *op, object *chosen_skill,
+ object *exp_obj)
+ {
+ op->chosen_skill = chosen_skill;
+ op->exp_obj = exp_obj;
+
+ /* unfortunately, we can't allow summoned monsters skill use
+ * because we will need the chosen_skill field to pick the
+ * right skill/stat modifiers for calc_skill_exp(). See
+ * hit_player() in server/attack.c -b.t.
+ */
+ CLEAR_FLAG (op, FLAG_CAN_USE_SKILL);
+ CLEAR_FLAG (op, FLAG_READY_SKILL);
+ }
+ #endif
+
+ /*
+ * Sets the owner and sets the skill and exp pointers to owner's current
+ * skill and experience objects.
+ */
+ void set_owner (object *op, object *owner)
+ {
+ if(owner==NULL||op==NULL)
+ return;
+ set_owner_simple (op, owner);
#ifdef ALLOW_SKILLS /* set the pointers in op to inherit owners skill, exp_obj */
! if (owner->type == PLAYER && owner->chosen_skill)
! set_skill_pointers (op, owner->chosen_skill,
! owner->chosen_skill->exp_obj);
! else if (op->type != PLAYER)
! CLEAR_FLAG (op, FLAG_READY_SKILL);
! #endif
! }
! /* Set the owner to clone's current owner and set the skill and experience
! * objects to clone's objects (typically those objects that where the owner's
! * current skill and experience objects at the time when clone's owner was
! * set - not the owner's current skill and experience objects).
! *
! * Use this function if player created an object (e.g. fire bullet, swarm
! * spell), and this object creates further objects whose kills should be
! * accounted for the player's original skill, even if player has changed
! * skills meanwhile.
! */
! void copy_owner (object *op, object *clone)
! {
! object *owner = get_owner (clone);
! if (owner == NULL)
! return;
! set_owner_simple (op, owner);
!
! #ifdef ALLOW_SKILLS
! if (clone->chosen_skill)
! set_skill_pointers (op, clone->chosen_skill, clone->exp_obj);
! else if (op->type != PLAYER)
! CLEAR_FLAG (op, FLAG_READY_SKILL);
#endif
}
/*
* Resets vital variables in an object
*** orig/crossfire-0.95.5-cvs1-patch-pre13-urgent5/server/gods.c Mon May 15 22:35:14 2000
--- crossfire-0.95.5-cvs1/server/gods.c Mon May 22 13:26:44 2000
***************
*** 287,297 ****
char *determine_god(object *op) {
int godnr = -1;
/* spells */
! if((op->type==FBULLET||op->type==CONE||op->type==FBALL)&&op->title) {
if(lookup_god_by_name(op->title)>=0) return op->title;
}
if(op->type!= PLAYER && QUERY_FLAG(op,FLAG_ALIVE)) {
if(!op->title) {
--- 287,299 ----
char *determine_god(object *op) {
int godnr = -1;
/* spells */
! if ((op->type == FBULLET || op->type == CONE || op->type == FBALL
! || op->type == SWARM_SPELL) && op->title)
! {
if(lookup_god_by_name(op->title)>=0) return op->title;
}
if(op->type!= PLAYER && QUERY_FLAG(op,FLAG_ALIVE)) {
if(!op->title) {
***************
*** 639,657 ****
object *god=find_god(determine_god(caster));
int caster_is_spell=0;
if(caster->type==FBULLET
||caster->type==CONE
! ||caster->type==FBALL) caster_is_spell=1;
! if(!caster_is_spell)
! if(!god||(spellop->attacktype&AT_HOLYWORD&&!god->race)) {
! new_draw_info(NDI_UNIQUE, 0, caster,
! "This prayer is useless unless you worship an appropriate god");
! free_object(spellop);
! return 0;
! }
/* either holy word or godpower attacks will set the slaying field */
if(spellop->attacktype&AT_HOLYWORD||spellop->attacktype&AT_GODPOWER) {
if(spellop->slaying) free_string(spellop->slaying);
if(!caster_is_spell)
--- 641,662 ----
object *god=find_god(determine_god(caster));
int caster_is_spell=0;
if(caster->type==FBULLET
||caster->type==CONE
! ||caster->type==FBALL
! ||caster->type==SWARM_SPELL) caster_is_spell=1;
! if ( ! god || (spellop->attacktype & AT_HOLYWORD && ! god->race)) {
! if ( ! caster_is_spell)
! new_draw_info(NDI_UNIQUE, 0, caster,
! "This prayer is useless unless you worship an appropriate god");
! else
! LOG (llevError, "BUG: tailor_god_spell(): no god\n");
! free_object(spellop);
! return 0;
! }
/* either holy word or godpower attacks will set the slaying field */
if(spellop->attacktype&AT_HOLYWORD||spellop->attacktype&AT_GODPOWER) {
if(spellop->slaying) free_string(spellop->slaying);
if(!caster_is_spell)
***************
*** 659,672 ****
else if(caster->slaying)
spellop->slaying = add_string(caster->slaying);
}
/* only the godpower attacktype adds the god's attack onto the spell */
! if((spellop->attacktype&AT_GODPOWER)&&!caster_is_spell)
spellop->attacktype=spellop->attacktype|god->attacktype;
! /* a little cosmetic for fun, we tack on the god's name to the spell */
if(spellop->attacktype&AT_HOLYWORD||spellop->attacktype&AT_GODPOWER) {
if(spellop->title)
free_string(spellop->title);
spellop->title=add_string(god->name);
if(spellop->title){
--- 664,677 ----
else if(caster->slaying)
spellop->slaying = add_string(caster->slaying);
}
/* only the godpower attacktype adds the god's attack onto the spell */
! if(spellop->attacktype & AT_GODPOWER)
spellop->attacktype=spellop->attacktype|god->attacktype;
! /* tack on the god's name to the spell */
if(spellop->attacktype&AT_HOLYWORD||spellop->attacktype&AT_GODPOWER) {
if(spellop->title)
free_string(spellop->title);
spellop->title=add_string(god->name);
if(spellop->title){
*** orig/crossfire-0.95.5-cvs1-patch-pre13-urgent5/server/spell_util.c Mon May 15 22:35:15 2000
--- crossfire-0.95.5-cvs1/server/spell_util.c Mon May 22 13:41:23 2000
***************
*** 974,985 ****
/* peterm added a type field to fire_arch. Needed it for making
fireball etall level dependent.
Later added a ball-lightning firing routine.
* dir is direction, at is spell we are firing. Type is index of spell
* array. If magic is 1, then add magical attacktype to spell.
! * op is the owner of the spell (player who gets exp), caster is the
! * casting object.
*/
int fire_arch (object *op, object *caster, int dir, archetype *at, int type,
int magic)
{
--- 976,987 ----
/* peterm added a type field to fire_arch. Needed it for making
fireball etall level dependent.
Later added a ball-lightning firing routine.
* dir is direction, at is spell we are firing. Type is index of spell
* array. If magic is 1, then add magical attacktype to spell.
! * op is either the owner of the spell (player who gets exp) or the
! * casting object owned by the owner. caster is the casting object.
*/
int fire_arch (object *op, object *caster, int dir, archetype *at, int type,
int magic)
{
***************
*** 1003,1013 ****
tmp->stats.sp=type;
tmp->stats.dam=SP_PARAMETERS[type].bdam+SP_level_dam_adjust(op,caster,type);
tmp->stats.hp=SP_PARAMETERS[type].bdur+SP_level_strength_adjust(op,caster,type);
tmp->x=x, tmp->y=y;
tmp->direction=dir;
! set_owner(tmp,op);
tmp->level = casting_level (caster, type);
#ifdef MULTIPLE_GODS /* needed for AT_HOLYWORD,AT_GODPOWER stuff */
if(tmp->attacktype&AT_HOLYWORD||tmp->attacktype&AT_GODPOWER) {
if(!tailor_god_spell(tmp,op)) return 0;
} else /* Ugly else going across endif */
--- 1005,1018 ----
tmp->stats.sp=type;
tmp->stats.dam=SP_PARAMETERS[type].bdam+SP_level_dam_adjust(op,caster,type);
tmp->stats.hp=SP_PARAMETERS[type].bdur+SP_level_strength_adjust(op,caster,type);
tmp->x=x, tmp->y=y;
tmp->direction=dir;
! if (get_owner (op) != NULL)
! copy_owner (tmp, op);
! else
! set_owner (tmp, op);
tmp->level = casting_level (caster, type);
#ifdef MULTIPLE_GODS /* needed for AT_HOLYWORD,AT_GODPOWER stuff */
if(tmp->attacktype&AT_HOLYWORD||tmp->attacktype&AT_GODPOWER) {
if(!tailor_god_spell(tmp,op)) return 0;
} else /* Ugly else going across endif */
***************
*** 1411,1421 ****
}
insert_ob_in_map(op,op->map);
}
int explode_object(object *op) {
! object *tmp, *victim, *owner, *env;
if(out_of_map(op->map,op->x,op->y)) /* peterm: check for out of map obj's.*/
{
return 0;
}
--- 1416,1426 ----
}
insert_ob_in_map(op,op->map);
}
int explode_object(object *op) {
! object *tmp, *victim, *env;
if(out_of_map(op->map,op->x,op->y)) /* peterm: check for out of map obj's.*/
{
return 0;
}
***************
*** 1450,1470 ****
/* peterm: hack added to make fireballs and other explosions level
* dependent:
*/
/* op->stats.sp stores the spell which made this object here. */
! if(op->owner)
! tmp->stats.dam += SP_level_dam_adjust(op->owner,op->owner,op->stats.sp);
if(op->attacktype&AT_MAGIC)
tmp->attacktype|=AT_MAGIC;
! if((owner = get_owner(op)) != (object *) NULL) {
! set_owner(tmp,owner);
! if(op->chosen_skill && (op->chosen_skill != tmp->chosen_skill)){
! tmp->exp_obj = op->exp_obj;
! tmp->chosen_skill = op->chosen_skill;
! }
! }
if(op->stats.hp)
tmp->stats.hp=op->stats.hp;
tmp->stats.maxhp=op->count; /* Unique ID */
tmp->x=env->x,tmp->y=env->y;
--- 1455,1468 ----
/* peterm: hack added to make fireballs and other explosions level
* dependent:
*/
/* op->stats.sp stores the spell which made this object here. */
! tmp->stats.dam += SP_level_dam_adjust(op,op,op->stats.sp);
if(op->attacktype&AT_MAGIC)
tmp->attacktype|=AT_MAGIC;
! copy_owner (tmp, op);
if(op->stats.hp)
tmp->stats.hp=op->stats.hp;
tmp->stats.maxhp=op->count; /* Unique ID */
tmp->x=env->x,tmp->y=env->y;
***************
*** 1787,1799 ****
void move_swarm_spell(object *op)
{
sint16 x,y;
int di;
- object *owner = get_owner (op);
! if(op->stats.hp == 0 || owner == NULL) {
remove_ob(op);
free_object(op);
return;
}
op->stats.hp--;
--- 1785,1796 ----
void move_swarm_spell(object *op)
{
sint16 x,y;
int di;
! if(op->stats.hp == 0 || get_owner (op) == NULL) {
remove_ob(op);
free_object(op);
return;
}
op->stats.hp--;
***************
*** 1806,1816 ****
y = op->y + freearr_y[absdir(op->direction +di)];
/* for level dependence, we need to know what spell is fired. */
/* that's stored in op->stats.sp by fire_swarm */
if ( ! wall (op->map, x, y))
! fire_arch_from_position (owner, op, x, y, op->direction, op->other_arch,
op->stats.sp, op->magic);
}
--- 1803,1813 ----
y = op->y + freearr_y[absdir(op->direction +di)];
/* for level dependence, we need to know what spell is fired. */
/* that's stored in op->stats.sp by fire_swarm */
if ( ! wall (op->map, x, y))
! fire_arch_from_position (op, op, x, y, op->direction, op->other_arch,
op->stats.sp, op->magic);
}
***************
*** 1837,1846 ****
tmp->x=op->x;
tmp->y=op->y;
set_owner(tmp,op); /* needed so that if swarm elements kill, caster gets xp.*/
tmp->level=casting_level(caster, spell_type); /*needed later, to get level dep. right.*/
tmp->stats.sp=spell_type; /* needed later, see move_swarm_spell */
tmp->magic = magic;
tmp->stats.hp=n; /* n in swarm*/
tmp->other_arch=swarm_type; /* the archetype of the things to be fired*/
tmp->direction=dir;
tmp->invisible=1;
--- 1834,1850 ----
tmp->x=op->x;
tmp->y=op->y;
set_owner(tmp,op); /* needed so that if swarm elements kill, caster gets xp.*/
tmp->level=casting_level(caster, spell_type); /*needed later, to get level dep. right.*/
tmp->stats.sp=spell_type; /* needed later, see move_swarm_spell */
+ #ifdef MULTIPLE_GODS
+ tmp->attacktype = swarm_type->clone.attacktype;
+ if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) {
+ if ( ! tailor_god_spell (tmp, op))
+ return;
+ }
+ #endif
tmp->magic = magic;
tmp->stats.hp=n; /* n in swarm*/
tmp->other_arch=swarm_type; /* the archetype of the things to be fired*/
tmp->direction=dir;
tmp->invisible=1;
*** orig/crossfire-0.95.5-cvs1-patch-pre13-urgent5/include/libproto.h Fri Apr 2 21:10:04 1999
--- crossfire-0.95.5-cvs1/include/libproto.h Mon May 22 13:30:37 2000
***************
*** 313,322 ****
--- 314,324 ----
extern void set_max_time ( long t );
extern void set_monster_check_apply ( type_func_ob_ob addr );
extern void set_move_creator ( type_func_ob addr );
extern void set_move_teleporter ( type_func_ob addr );
extern void set_owner ( object *op, object *owner );
+ extern void copy_owner ( object *op, object *clone );
extern void set_process_active_maps ( type_func_void addr );
extern void set_remove_friendly_object ( type_func_ob addr );
extern void set_ring_bonus ( object *op, int bonus );
extern void set_trap_adjust ( type_func_ob_int addr );
extern void set_update_buttons ( type_func_map addr );
--
Jan
-
[you can put yourself on the announcement list only or unsubscribe altogether
by sending an email stating your wishes to ]