Crossfire Mailing List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
CF: animate_weapon() fixes
- To: crossfire (at) ifi.uio.no
- Subject: CF: animate_weapon() fixes
- From: Jan Echternach <>
- Date: Fri, 9 Jun 2000 14:09:25 +0200
- Mail-Followup-To:
- Reply-To: Jan Echternach <>
- Sender:
This patch is already in the CVS tree. I have not updated
common/loader.c in the CVS because it is a generated file. From the
CHANGES file:
common/loader.l: Fix handling of objects with no animation. Fixes server
crash if object's archetype has an animation, but object doesn't.
common/loader.l: get_ob_diff(): Bugfix: Issue a "is_animated 0" line
if the object has an animation, but doesn't have FLAG_ANIMATE.
server/apply.c: manual_apply() and monster_apply_special(): Don't check
for FLAG_UNPAID if object is applied. This should make the code more
robust if an unpaid item get's applied accidently.
server/apply.c: apply_special(): New optional flags AP_NO_MERGE and
AP_IGNORE_CURSE.
server/monster.c: find_mon_throw_ob(); server/skills.c: find_throw_ob():
Bugfix: Use AP_NO_MERGE flag to prevent unapplied object be merged with
other objects.
server/spell_effect.c: animate_weapon: Bugfixes: Correctly unapply
weapon. Don't set FLAG_APPLIED directly on weapon in golem, but use
apply_special(). Don't call esrv_send_item() when caster is not a player
(fixes server crash if monster casts this spell).
--
Jan
diff -ru orig/crossfire-0.95.5-cvs3-patch23/common/loader.l crossfire-0.95.5-cvs3/common/loader.l
--- orig/crossfire-0.95.5-cvs3-patch23/common/loader.l Mon May 15 22:29:08 2000
+++ crossfire-0.95.5-cvs3/common/loader.l Fri Jun 9 13:22:27 2000
@@ -181,8 +181,13 @@
^other_arch{S} op->other_arch=find_archetype(yval());
^animation{S} {
- op->animation_id = find_animation(yval());
- SET_FLAG(op,FLAG_ANIMATE);
+ if (strcmp (yval(), "NONE") == 0) {
+ op->animation_id = 0;
+ CLEAR_FLAG (op, FLAG_ANIMATE);
+ } else {
+ op->animation_id = find_animation (yval());
+ SET_FLAG (op, FLAG_ANIMATE);
+ }
}
^more{WS}$ { /* We need to record that this is a multipart object,
@@ -619,8 +624,16 @@
strcat(buf,buf2);
}
if (op->animation_id != op2->animation_id) {
- sprintf(buf2,"animation %s\n", animations[GET_ANIM_ID(op)].name);
- strcat(buf, buf2);
+ if (op->animation_id) {
+ sprintf(buf2,"animation %s\n", animations[GET_ANIM_ID(op)].name);
+ if ( ! QUERY_FLAG (op, FLAG_ANIMATE)) {
+ strcat (buf, buf2);
+ sprintf (buf2, "is_animated 0\n");
+ }
+ } else {
+ sprintf (buf2, "animation NONE\n");
+ }
+ strcat (buf, buf2);
}
if(op->stats.Str!=op2->stats.Str)
save_long(buf,variable_const[V_STR],op->stats.Str);
diff -ru orig/crossfire-0.95.5-cvs3-patch23/include/define.h crossfire-0.95.5-cvs3/include/define.h
--- orig/crossfire-0.95.5-cvs3-patch23/include/define.h Sun May 28 20:27:00 2000
+++ crossfire-0.95.5-cvs3/include/define.h Fri Jun 9 12:28:18 2000
@@ -710,8 +710,19 @@
safe_strcat(retbuf,")", len, maxlen); \
}
-#define AP_APPLY 1
-#define AP_UNAPPLY 2
+/* Flags for apply_special() */
+enum apply_flag {
+ /* Basic flags, always use one of these */
+ AP_NULL = 0,
+ AP_APPLY = 1,
+ AP_UNAPPLY = 2,
+
+ AP_BASIC_FLAGS = 15,
+
+ /* Optional flags, for bitwise or with a basic flag */
+ AP_NO_MERGE = 16,
+ AP_IGNORE_CURSE = 32,
+};
/* Cut off point of when an object is put on the active list or not */
#define MIN_ACTIVE_SPEED 0.00001
diff -ru orig/crossfire-0.95.5-cvs3-patch23/server/apply.c crossfire-0.95.5-cvs3/server/apply.c
--- orig/crossfire-0.95.5-cvs3-patch23/server/apply.c Mon May 29 18:31:26 2000
+++ crossfire-0.95.5-cvs3/server/apply.c Fri Jun 9 12:44:23 2000
@@ -1654,7 +1654,7 @@
int manual_apply (object *op, object *tmp, int aflag)
{
- if (QUERY_FLAG (tmp, FLAG_UNPAID)) {
+ if (QUERY_FLAG (tmp, FLAG_UNPAID) && ! QUERY_FLAG (tmp, FLAG_APPLIED)) {
if (op->type == PLAYER) {
new_draw_info (NDI_UNIQUE, 0, op, "You should pay for it first.");
return 1;
@@ -1936,12 +1936,20 @@
/* who is the object using the object.
* op is the object they are using.
- * aflags is special flags (0 - normal/toggel, 1=always apply, 2=always unapply
- * (see define.h, AP_* values)
+ * aflags is special flags (0 - normal/toggle, AP_APPLY=always apply,
+ * AP_UNAPPLY=always unapply).
+ *
+ * Optional flags:
+ * AP_NO_MERGE: don't merge an unapplied object with other objects
+ * AP_IGNORE_CURSE: unapply cursed items
+ *
+ * Usage example: apply_special (who, op, AP_UNAPPLY | AP_IGNORE_CURSE)
*
* apply_special() doesn't check for unpaid items.
*/
-int apply_special(object *who,object *op, int aflags) { /* wear/wield */
+int apply_special (object *who, object *op, int aflags)
+{ /* wear/wield */
+ int basic_flag = aflags & AP_BASIC_FLAGS;
object *tmp;
char buf[MAX_BUF];
int i;
@@ -1955,10 +1963,11 @@
if(op->env!=who)
return 1; /* op is not in inventory */
- if(QUERY_FLAG(op,FLAG_APPLIED)) {
+ if (QUERY_FLAG(op,FLAG_APPLIED)) {
/* always apply, so no reason to unapply */
- if (aflags == AP_APPLY) return 0;
- if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))
+ if (basic_flag == AP_APPLY) return 0;
+ if ( ! (aflags & AP_IGNORE_CURSE)
+ && (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED)))
{
new_draw_info_format(NDI_UNIQUE, 0, who,
"No matter how hard you try, you just can't\nremove %s.",
@@ -2040,20 +2049,23 @@
}
if (buf[0] != '\0')
new_draw_info(NDI_UNIQUE, 0,who,buf);
- del_tag = op->count;
- tmp=merge_ob(op,NULL);
fix_player(who);
- if(who->type==PLAYER) {
- if (tmp) { /* it was merged */
- esrv_del_item (who->contr, del_tag);
- op = tmp;
- }
- esrv_send_item(who, op);
+
+ if ( ! (aflags & AP_NO_MERGE)) {
+ tag_t del_tag = op->count;
+ tmp = merge_ob (op, NULL);
+ if (who->type == PLAYER) {
+ if (tmp) { /* it was merged */
+ esrv_del_item (who->contr, del_tag);
+ op = tmp;
+ }
+ esrv_send_item (who, op);
+ }
}
return 0;
}
- if (aflags == AP_UNAPPLY) return 0;
+ if (basic_flag == AP_UNAPPLY) return 0;
i=0;
/* This goes through and checks to see if the player already has something
* of that type applied - if so, unapply it.
@@ -2229,7 +2241,7 @@
int monster_apply_special (object *who, object *op, int aflags)
{
- if (QUERY_FLAG (op, FLAG_UNPAID))
+ if (QUERY_FLAG (op, FLAG_UNPAID) && ! QUERY_FLAG (op, FLAG_APPLIED))
return 1;
return apply_special (who, op, aflags);
}
diff -ru orig/crossfire-0.95.5-cvs3-patch23/server/c_object.c crossfire-0.95.5-cvs3/server/c_object.c
--- orig/crossfire-0.95.5-cvs3-patch23/server/c_object.c Thu Jun 8 13:01:20 2000
+++ crossfire-0.95.5-cvs3/server/c_object.c Fri Jun 9 12:07:37 2000
@@ -205,7 +205,7 @@
return 0;
}
else {
- int aflag=0;
+ enum apply_flag aflag = 0;
object *inv;
while (*params==' ') params++;
@@ -525,14 +525,9 @@
if (! sack_can_hold (op, sack, tmp,(nrof?nrof:tmp->nrof)))
return;
- /* Small hack to avoid autojoining in apply_special(): */
if(QUERY_FLAG(tmp, FLAG_APPLIED)) {
- int nrof = tmp->nrof, a;
- tmp->nrof = 0;
- a = apply_special(op,tmp,0);
- tmp->nrof = nrof;
- if (a)
- return;
+ if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE))
+ return;
}
/* we want to put some portion of the item into the container */
@@ -593,14 +588,9 @@
return;
}
- /* Small hack to avoid autojoining in apply_special(): */
if(QUERY_FLAG(tmp, FLAG_APPLIED)) {
- int nrof = tmp->nrof,a;
- tmp->nrof = 0;
- a = apply_special (op, tmp,0);
- tmp->nrof = nrof;
- if (a) /* can't unapply it */
- return;
+ if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE))
+ return; /* can't unapply it */
}
/* We are only dropping some of the items. We split the current objec
diff -ru orig/crossfire-0.95.5-cvs3-patch23/server/monster.c crossfire-0.95.5-cvs3/server/monster.c
--- orig/crossfire-0.95.5-cvs3-patch23/server/monster.c Sun May 28 20:27:01 2000
+++ crossfire-0.95.5-cvs3/server/monster.c Fri Jun 9 12:15:35 2000
@@ -1410,7 +1410,7 @@
if ( ! tmp)
tmp = heaviest;
if (tmp && QUERY_FLAG (tmp, FLAG_APPLIED)) {
- if (monster_apply_special (op, tmp, AP_UNAPPLY)) {
+ if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) {
LOG (llevError, "BUG: find_mon_throw_ob(): couldn't unapply\n");
tmp = NULL;
}
diff -ru orig/crossfire-0.95.5-cvs3-patch23/server/skills.c crossfire-0.95.5-cvs3/server/skills.c
--- orig/crossfire-0.95.5-cvs3-patch23/server/skills.c Mon May 29 18:31:26 2000
+++ crossfire-0.95.5-cvs3/server/skills.c Fri Jun 9 12:15:00 2000
@@ -1318,11 +1318,7 @@
"The %s sticks to your hand!",query_name(tmp));
tmp = NULL;
} else {
- tag_t tag = tmp->count;
- player_apply (op, tmp, AP_UNAPPLY, 0);
- if (was_destroyed (tmp, tag)) {
- tmp = NULL;
- } else if (QUERY_FLAG (tmp, FLAG_APPLIED)) {
+ if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) {
LOG (llevError, "BUG: find_throw_ob(): couldn't unapply\n");
tmp = NULL;
}
diff -ru orig/crossfire-0.95.5-cvs3-patch23/server/spell_effect.c crossfire-0.95.5-cvs3/server/spell_effect.c
--- orig/crossfire-0.95.5-cvs3-patch23/server/spell_effect.c Fri Jun 9 13:02:31 2000
+++ crossfire-0.95.5-cvs3/server/spell_effect.c Fri Jun 9 13:52:25 2000
@@ -3056,7 +3056,8 @@
op->contr->golem=tmp;
op->contr->shoottype=range_scroll;
} else {
- /* if uncursed and animated by a pet(???), make the golem a pet */
+ /* If spell is cast by a pet, and the weapon is not cursed, make the animated
+ * weapon a pet. */
if(QUERY_FLAG(op, FLAG_FRIENDLY)
&& !QUERY_FLAG(weapon,FLAG_CURSED)
&& !QUERY_FLAG(weapon,FLAG_DAMNED)){
@@ -3073,18 +3074,24 @@
}
/* ok, tailor the golem's characteristics based on the weapon */
- tmp->stats.Str += weapon->stats.Str;
- tmp->stats.Dex += weapon->stats.Dex;
- tmp->stats.Con += weapon->stats.Con;
- tmp->stats.Int += weapon->stats.Int;
- tmp->stats.Wis += weapon->stats.Wis;
- tmp->stats.Pow += weapon->stats.Pow;
- tmp->stats.Cha += weapon->stats.Cha;
- LOG(llevDebug, "animate_weapon: Str:%d Dex:%d Con:%d Int:%d Wis:%d Pow:%d Cha:%d.\n",
- tmp->stats.Str, tmp->stats.Dex, tmp->stats.Con, tmp->stats.Int, tmp->stats.Wis, tmp->stats.Pow, tmp->stats.Cha);
+ if (spellnum == SP_STAFF_TO_SNAKE || spellnum == SP_ANIMATE_WEAPON) {
+ if (apply_special (op, weapon,
+ AP_UNAPPLY | AP_IGNORE_CURSE | AP_NO_MERGE))
+ {
+ LOG (llevError, "BUG: animate_weapon(): can't unapply weapon\n");
+ return 0;
+ }
+ remove_ob (weapon);
+ insert_ob_in_ob (weapon, tmp);
+ if (op->type == PLAYER)
+ esrv_send_item(op, weapon);
+ SET_FLAG (tmp, FLAG_USE_WEAPON);
+ if (apply_special (tmp, weapon, AP_APPLY))
+ LOG (llevError, "BUG: animate_weapon(): golem can't apply weapon\n");
+ }
+
/* modify weapon's animated wc */
tmp->stats.wc = tmp->stats.wc
- - weapon->stats.wc
- SP_level_dam_adjust(op,caster,spellnum)
- 5 * weapon->stats.Dex
- 2 * weapon->stats.Str
@@ -3108,15 +3115,8 @@
if(tmp->stats.dam<0) tmp->stats.dam=127;
LOG(llevDebug,"animate_weapon: wc:%d hp:%d dam:%d.\n", tmp->stats.wc, tmp->stats.hp, tmp->stats.dam);
/* attacktype */
- if (weapon->attacktype) {
- tmp->attacktype = weapon->attacktype;
- } else {
+ if ( ! tmp->attacktype)
tmp->attacktype = AT_PHYSICAL;
- }
- /* Set weapon's protection according to material and protected attribute */
- tmp->protected = weapon->protected;
- /* Set vulnerability according to weapon's material and vulnerability attribute */
- tmp->vulnerable = weapon->vulnerable;
for(i=0; i<NROFMATERIALS; i++)
for(j=0; j<NROFATTACKS; j++)
if(weapon->material & (1<<i)) {
@@ -3138,12 +3138,8 @@
}
}
tmp->armour = 100 - (int)((100.0-(float)tmp->armour)/(30.0-2.0*(a>14?14.0:(float)a)));
- /* If the weapon has a Slaying list, so does the golem */
- if (tmp->slaying) {
- free_string (tmp->slaying);
- tmp->slaying = NULL;
- }
- if(weapon->slaying) tmp->slaying = add_string(weapon->slaying);
+ LOG (llevDebug, "animate_weapon: slaying %s\n",
+ tmp->slaying ? tmp->slaying : "nothing");
/* Determine golem's speed */
tmp->speed = ((weapon->last_sp>0.1)?weapon->last_sp:0.1) -
@@ -3163,26 +3159,13 @@
switch(spellnum) {
case SP_STAFF_TO_SNAKE:
- /* now, remove object from op inv, insert into golem */
- remove_ob(weapon);
- /* apply_special(op, weapon, AP_UNAPPLY);*/
- insert_ob_in_ob(weapon,tmp);
- fix_player(op);
- esrv_send_item(op, weapon);
new_draw_info(NDI_UNIQUE, 0,op,"Your staff becomes a serpent and leaps to the ground!");
break;
case SP_ANIMATE_WEAPON:
- /* now, remove object from op inv, insert into golem */
- remove_ob(weapon);
- /* apply_special(op, weapon, AP_UNAPPLY);*/
- insert_ob_in_ob(weapon,tmp);
- fix_player(op);
- esrv_send_item(op, weapon);
-
new_draw_info_format(NDI_UNIQUE, 0,op,"Your %s flies from your hand and hovers in mid-air!", weapon->name);
- if(tmp->name) free_string(tmp->name);
sprintf(buf, "animated %s", weapon->name);
+ if(tmp->name) free_string(tmp->name);
tmp->name = add_string(buf);
tmp->face = weapon->face;
@@ -3196,7 +3179,6 @@
CLEAR_FLAG(tmp,FLAG_ANIMATE);
}
update_ob_speed(tmp);
- SET_FLAG(weapon,FLAG_APPLIED); /* so it can take acid damage */
break;
case SP_DANCING_SWORD: