--- deliantra/server/server/spell_attack.C 2006/08/26 23:36:34 1.5 +++ deliantra/server/server/spell_attack.C 2006/08/29 08:01:38 1.6 @@ -1,6 +1,6 @@ /* * static char *rcsid_spell_attack_c = - * "$Id: spell_attack.C,v 1.5 2006/08/26 23:36:34 root Exp $"; + * "$Id: spell_attack.C,v 1.6 2006/08/29 08:01:38 root Exp $"; */ @@ -50,53 +50,53 @@ void check_spell_knockback(object *op) { object *tmp, *tmp2; /* object on the map */ int weight_move; - int frictionmod=2; /*poor man's physics - multipy targets weight by this amount */ + int frictionmod=2; /*poor man's physics - multipy targets weight by this amount */ - if(! op->weight) { /*shouldn't happen but if cone object has no weight drop out*/ - /*LOG (llevDebug, "DEBUG: arch weighs nothing\n");*/ - return; - }else{ - weight_move = op->weight +(op->weight * op->level) / 3; - /*LOG (llevDebug, "DEBUG: arch weighs %d and masses %d (%s,level %d)\n", op->weight,weight_move,op->name,op->level);*/ - } - + if(! op->weight) { /*shouldn't happen but if cone object has no weight drop out*/ + /*LOG (llevDebug, "DEBUG: arch weighs nothing\n");*/ + return; + }else{ + weight_move = op->weight +(op->weight * op->level) / 3; + /*LOG (llevDebug, "DEBUG: arch weighs %d and masses %d (%s,level %d)\n", op->weight,weight_move,op->name,op->level);*/ + } + for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above) { - int num_sections = 1; + int num_sections = 1; - /* don't move DM */ - if(QUERY_FLAG(tmp, FLAG_WIZ)) - return; - - /* don't move parts of objects */ - if(tmp->head) continue; - - /* don't move floors or immobile objects */ - if(QUERY_FLAG(tmp,FLAG_IS_FLOOR)||(!QUERY_FLAG(tmp,FLAG_ALIVE)&&QUERY_FLAG(tmp,FLAG_NO_PICK))) continue; - - /* count the object's sections */ - for(tmp2 = tmp; tmp2!=NULL;tmp2=tmp2->more) num_sections++; - - /* I'm not sure if it makes sense to divide by num_sections - bigger - * objects should be harder to move, and we are moving the entire - * object, not just the head, so the total weight should be relevant. - */ - - /* surface area? -tm */ - - if (tmp->move_type & MOVE_FLYING) - frictionmod = 1 ; /* flying objects loose the friction modifier */ - - if(rndm(0, weight_move-1) > ((tmp->weight / num_sections) * frictionmod)) { /* move it. */ - /* move_object is really for monsters, but looking at - * the move_object function, it appears that it should - * also be safe for objects. - * This does return if successful or not, but - * I don't see us doing anything useful with that information - * right now. - */ - move_object(tmp, absdir(op->stats.sp)); - } + /* don't move DM */ + if(QUERY_FLAG(tmp, FLAG_WIZ)) + return; + + /* don't move parts of objects */ + if(tmp->head) continue; + + /* don't move floors or immobile objects */ + if(QUERY_FLAG(tmp,FLAG_IS_FLOOR)||(!QUERY_FLAG(tmp,FLAG_ALIVE)&&QUERY_FLAG(tmp,FLAG_NO_PICK))) continue; + + /* count the object's sections */ + for(tmp2 = tmp; tmp2!=NULL;tmp2=tmp2->more) num_sections++; + + /* I'm not sure if it makes sense to divide by num_sections - bigger + * objects should be harder to move, and we are moving the entire + * object, not just the head, so the total weight should be relevant. + */ + + /* surface area? -tm */ + + if (tmp->move_type & MOVE_FLYING) + frictionmod = 1 ; /* flying objects loose the friction modifier */ + + if(rndm(0, weight_move-1) > ((tmp->weight / num_sections) * frictionmod)) { /* move it. */ + /* move_object is really for monsters, but looking at + * the move_object function, it appears that it should + * also be safe for objects. + * This does return if successful or not, but + * I don't see us doing anything useful with that information + * right now. + */ + move_object(tmp, absdir(op->stats.sp)); + } } } @@ -123,19 +123,19 @@ * Should start out at 50, down to 25 for one already going left * down to 0 for one going 90 degrees left off original path */ - + if(rndm(0, 99) < tmp->stats.Con) /* fork left */ - new_dir = -1; - + new_dir = -1; + /* check the new dir for a wall and in the map*/ t_dir = absdir(tmp->direction + new_dir); if(get_map_flags(tmp->map,&m, tmp->x + freearr_x[t_dir],tmp->y + freearr_y[t_dir], - &sx, &sy) & P_OUT_OF_MAP) - return; + &sx, &sy) & P_OUT_OF_MAP) + return; if (OB_TYPE_MOVE_BLOCK(tmp, GET_MAP_MOVE_BLOCK(m, sx, sy))) - return; + return; /* OK, we made a fork */ new_bolt = get_object(); @@ -169,95 +169,95 @@ mapstruct *m; if(--(op->duration)<0) { - remove_ob(op); - free_object(op); - return; + remove_ob(op); + free_object(op); + return; } hit_map(op,0,op->attacktype,1); - + if(!op->direction) - return; + return; if (--op->range<0) { - op->range=0; + op->range=0; } else { - x = op->x+DIRX(op); - y = op->y+DIRY(op); - m = op->map; - mflags = get_map_flags(m, &m, x, y, &x, &y); - - if (mflags & P_OUT_OF_MAP) return; - - /* We are about to run into something - we may bounce */ - /* Calling reflwall is pretty costly, as it has to look at all the objects - * on the space. So only call reflwall if we think the data it returns - * will be useful. - */ - if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y)) || - ((mflags & P_IS_ALIVE) && reflwall(m, x, y, op))) { - - if(!QUERY_FLAG(op, FLAG_REFLECTING)) - return; - - /* Since walls don't run diagonal, if the bolt is in - * one of 4 main directions, it just reflects back in the - * opposite direction. However, if the bolt is travelling - * on the diagonal, it is trickier - eg, a bolt travelling - * northwest bounces different if it hits a north/south - * wall (bounces to northeast) vs an east/west (bounces - * to the southwest. - */ - if(op->direction&1) - op->direction=absdir(op->direction+4); - else { - int left, right; - int mflags; - - /* Need to check for P_OUT_OF_MAP: if the bolt is tavelling - * over a corner in a tiled map, it is possible that - * op->direction is within an adjacent map but either - * op->direction-1 or op->direction+1 does not exist. - */ - mflags = get_map_flags(op->map, &m, op->x+freearr_x[absdir(op->direction-1)], - op->y+freearr_y[absdir(op->direction-1)], &x, &y); + x = op->x+DIRX(op); + y = op->y+DIRY(op); + m = op->map; + mflags = get_map_flags(m, &m, x, y, &x, &y); + + if (mflags & P_OUT_OF_MAP) return; + + /* We are about to run into something - we may bounce */ + /* Calling reflwall is pretty costly, as it has to look at all the objects + * on the space. So only call reflwall if we think the data it returns + * will be useful. + */ + if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y)) || + ((mflags & P_IS_ALIVE) && reflwall(m, x, y, op))) { + + if(!QUERY_FLAG(op, FLAG_REFLECTING)) + return; + + /* Since walls don't run diagonal, if the bolt is in + * one of 4 main directions, it just reflects back in the + * opposite direction. However, if the bolt is travelling + * on the diagonal, it is trickier - eg, a bolt travelling + * northwest bounces different if it hits a north/south + * wall (bounces to northeast) vs an east/west (bounces + * to the southwest. + */ + if(op->direction&1) + op->direction=absdir(op->direction+4); + else { + int left, right; + int mflags; + + /* Need to check for P_OUT_OF_MAP: if the bolt is tavelling + * over a corner in a tiled map, it is possible that + * op->direction is within an adjacent map but either + * op->direction-1 or op->direction+1 does not exist. + */ + mflags = get_map_flags(op->map, &m, op->x+freearr_x[absdir(op->direction-1)], + op->y+freearr_y[absdir(op->direction-1)], &x, &y); - left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y)); + left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y)); - mflags = get_map_flags(op->map, &m, op->x+freearr_x[absdir(op->direction+1)], + mflags = get_map_flags(op->map, &m, op->x+freearr_x[absdir(op->direction+1)], op->y+freearr_y[absdir(op->direction+1)], &x, &y); - right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y)); + right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y)); + + if(left==right) + op->direction=absdir(op->direction+4); + else if(left) + op->direction=absdir(op->direction+2); + else if(right) + op->direction=absdir(op->direction-2); + } + update_turn_face(op); /* A bolt *must* be IS_TURNABLE */ + return; + } + else { /* Create a copy of this object and put it ahead */ + tmp=get_object(); + copy_object(op,tmp); + tmp->speed_left= -0.1; + tmp->x+=DIRX(tmp),tmp->y+=DIRY(tmp); + tmp = insert_ob_in_map(tmp,op->map,op,0); + /* To make up for the decrease at the top of the function */ + tmp->duration++; + + /* New forking code. Possibly create forks of this object + * going off in other directions. + */ - if(left==right) - op->direction=absdir(op->direction+4); - else if(left) - op->direction=absdir(op->direction+2); - else if(right) - op->direction=absdir(op->direction-2); - } - update_turn_face(op); /* A bolt *must* be IS_TURNABLE */ - return; - } - else { /* Create a copy of this object and put it ahead */ - tmp=get_object(); - copy_object(op,tmp); - tmp->speed_left= -0.1; - tmp->x+=DIRX(tmp),tmp->y+=DIRY(tmp); - tmp = insert_ob_in_map(tmp,op->map,op,0); - /* To make up for the decrease at the top of the function */ - tmp->duration++; - - /* New forking code. Possibly create forks of this object - * going off in other directions. - */ - - if(rndm(0, 99)< tmp->stats.Dex) { /* stats.Dex % of forking */ - forklightning(op,tmp); - } - /* In this way, the object left behind sticks on the space, but - * doesn't create any bolts that continue to move onward. - */ - op->range = 0; - } /* copy object and move it along */ + if(rndm(0, 99)< tmp->stats.Dex) { /* stats.Dex % of forking */ + forklightning(op,tmp); + } + /* In this way, the object left behind sticks on the space, but + * doesn't create any bolts that continue to move onward. + */ + op->range = 0; + } /* copy object and move it along */ } /* if move bolt along */ } @@ -275,11 +275,11 @@ int mflags; if (!spob->other_arch) - return 0; + return 0; tmp=arch_to_object(spob->other_arch); if(tmp==NULL) - return 0; + return 0; /* peterm: level dependency for bolts */ tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust(caster,spob); @@ -292,7 +292,7 @@ tmp->direction=dir; if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE)) - SET_ANIMATION(tmp, dir); + SET_ANIMATION(tmp, dir); set_owner(tmp,op); set_spell_skill(op, caster, spob, tmp); @@ -303,18 +303,18 @@ mflags = get_map_flags(tmp->map, &tmp->map, tmp->x, tmp->y, &tmp->x, &tmp->y); if (mflags & P_OUT_OF_MAP) { - free_object(tmp); - return 0; + free_object(tmp); + return 0; } if (OB_TYPE_MOVE_BLOCK(tmp, GET_MAP_MOVE_BLOCK(tmp->map, tmp->x, tmp->y))) { - if(!QUERY_FLAG(tmp, FLAG_REFLECTING)) { - free_object(tmp); - return 0; - } - tmp->x=op->x; - tmp->y=op->y; - tmp->direction=absdir(tmp->direction+4); - tmp->map = op->map; + if(!QUERY_FLAG(tmp, FLAG_REFLECTING)) { + free_object(tmp); + return 0; + } + tmp->x=op->x; + tmp->y=op->y; + tmp->direction=absdir(tmp->direction+4); + tmp->map = op->map; } if ((tmp = insert_ob_in_map(tmp,tmp->map,op,0)) != NULL) move_bolt (tmp); @@ -339,33 +339,33 @@ int i; if(--(op->duration)<0) { - remove_ob(op); - free_object(op); - return; + remove_ob(op); + free_object(op); + return; } hit_map(op,0,op->attacktype,0); if(op->range>0) { - for(i=1;i<9;i++) { - sint16 dx,dy; + for(i=1;i<9;i++) { + sint16 dx,dy; - dx=op->x+freearr_x[i]; - dy=op->y+freearr_y[i]; - /* ok_to_put_more already does things like checks for walls, - * out of map, etc. - */ - if(ok_to_put_more(op->map,dx,dy,op,op->attacktype)) { - tmp=get_object(); - copy_object(op,tmp); - tmp->state=0; - tmp->speed_left= -0.21; - tmp->range--; - tmp->value=0; - tmp->x=dx; - tmp->y=dy; - insert_ob_in_map(tmp,m,op,0); - } - } + dx=op->x+freearr_x[i]; + dy=op->y+freearr_y[i]; + /* ok_to_put_more already does things like checks for walls, + * out of map, etc. + */ + if(ok_to_put_more(op->map,dx,dy,op,op->attacktype)) { + tmp=get_object(); + copy_object(op,tmp); + tmp->state=0; + tmp->speed_left= -0.21; + tmp->range--; + tmp->value=0; + tmp->x=dx; + tmp->y=dy; + insert_ob_in_map(tmp,m,op,0); + } + } } } @@ -380,31 +380,31 @@ object *tmp, *owner; if (op->other_arch == NULL) { - LOG (llevError, "BUG: explode_bullet(): op without other_arch\n"); - remove_ob (op); - free_object (op); - return; + LOG (llevError, "BUG: explode_bullet(): op without other_arch\n"); + remove_ob (op); + free_object (op); + return; } if (op->env) { - object *env; + object *env; - env = object_get_env_recursive(op); - if (env->map == NULL || out_of_map (env->map, env->x, env->y)) { - LOG (llevError, "BUG: explode_bullet(): env out of map\n"); - remove_ob (op); - free_object (op); - return; - } - remove_ob (op); - op->x = env->x; - op->y = env->y; - insert_ob_in_map(op, env->map, op, INS_NO_MERGE | INS_NO_WALK_ON); + env = object_get_env_recursive(op); + if (env->map == NULL || out_of_map (env->map, env->x, env->y)) { + LOG (llevError, "BUG: explode_bullet(): env out of map\n"); + remove_ob (op); + free_object (op); + return; + } + remove_ob (op); + op->x = env->x; + op->y = env->y; + insert_ob_in_map(op, env->map, op, INS_NO_MERGE | INS_NO_WALK_ON); } else if (out_of_map (op->map, op->x, op->y)) { - LOG (llevError, "BUG: explode_bullet(): op out of map\n"); - remove_ob (op); - free_object (op); - return; + LOG (llevError, "BUG: explode_bullet(): op out of map\n"); + remove_ob (op); + free_object (op); + return; } // elmex Tue Aug 15 17:46:51 CEST 2006: Prevent explosions of any kind on safe maps @@ -418,9 +418,9 @@ } if (op->attacktype) { - hit_map (op, 0, op->attacktype, 1); - if (was_destroyed (op, op_tag)) - return; + hit_map (op, 0, op->attacktype, 1); + if (was_destroyed (op, op_tag)) + return; } /* other_arch contains what this explodes into */ @@ -433,34 +433,34 @@ owner = get_owner(op); if ((tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) && owner && !tailor_god_spell(tmp, owner)) { - remove_ob (op); - free_object (op); - return; + remove_ob (op); + free_object (op); + return; } tmp->x = op->x; tmp->y = op->y; /* special for bombs - it actually has sane values for these */ if (op->type == SPELL_EFFECT && op->subtype == SP_BOMB) { - tmp->attacktype = op->attacktype; - tmp->range = op->range; - tmp->stats.dam = op->stats.dam; - tmp->duration = op->duration; + tmp->attacktype = op->attacktype; + tmp->range = op->range; + tmp->stats.dam = op->stats.dam; + tmp->duration = op->duration; } else { - if (op->attacktype & AT_MAGIC) tmp->attacktype|=AT_MAGIC; - /* Spell doc describes what is going on here */ - tmp->stats.dam = op->dam_modifier; - tmp->range = op->stats.maxhp; - tmp->duration = op->stats.hp; - /* Used for spell tracking - just need a unique val for this spell - - * the count of the parent should work fine. - */ - tmp->stats.maxhp = op->count; + if (op->attacktype & AT_MAGIC) tmp->attacktype|=AT_MAGIC; + /* Spell doc describes what is going on here */ + tmp->stats.dam = op->dam_modifier; + tmp->range = op->stats.maxhp; + tmp->duration = op->stats.hp; + /* Used for spell tracking - just need a unique val for this spell - + * the count of the parent should work fine. + */ + tmp->stats.maxhp = op->count; } /* Set direction of cone explosion */ if (tmp->type == SPELL_EFFECT && tmp->subtype == SP_CONE) - tmp->stats.sp = op->direction; + tmp->stats.sp = op->direction; /* Prevent recursion */ op->move_on = 0; @@ -468,8 +468,8 @@ insert_ob_in_map(tmp, op->map, op, 0); /* remove the firebullet */ if ( ! was_destroyed (op, op_tag)) { - remove_ob (op); - free_object (op); + remove_ob (op); + free_object (op); } } @@ -493,7 +493,7 @@ return; if (op->other_arch) { - /* explode object will also remove op */ + /* explode object will also remove op */ explode_bullet (op); return; } @@ -509,11 +509,11 @@ if (was_destroyed (op, op_tag) || ! was_destroyed (tmp, tmp_tag) || (op->stats.dam -= dam) < 0) { - if(!QUERY_FLAG(op,FLAG_REMOVED)) { - remove_ob (op); - free_object(op); - return; - } + if(!QUERY_FLAG(op,FLAG_REMOVED)) { + remove_ob (op); + free_object(op); + return; + } } } } @@ -536,7 +536,7 @@ /* We need a better general purpose way to do this */ /* peterm: added to make comet leave a trail of burnouts - it's an unadulterated hack, but the effect is cool. */ + it's an unadulterated hack, but the effect is cool. */ if(op->stats.sp == SP_METEOR) { replace_insert_ob_in_map("fire_trail",op); if (was_destroyed (op, op_tag)) @@ -548,10 +548,10 @@ if (--op->range <=0) { if (op->other_arch) { explode_bullet (op); - } else { - remove_ob (op); - free_object (op); - } + } else { + remove_ob (op); + free_object (op); + } return; } @@ -607,11 +607,11 @@ int mflags; if (!spob->other_arch) - return 0; + return 0; tmp=arch_to_object(spob->other_arch); if(tmp==NULL) - return 0; + return 0; /* peterm: level dependency for bolts */ tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust(caster,spob); @@ -627,7 +627,7 @@ tmp->direction=dir; if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE)) - SET_ANIMATION(tmp, dir); + SET_ANIMATION(tmp, dir); set_owner(tmp,op); set_spell_skill(op, caster, spob, tmp); @@ -638,21 +638,21 @@ mflags = get_map_flags(tmp->map, &tmp->map, tmp->x, tmp->y, &tmp->x, &tmp->y); if (mflags & P_OUT_OF_MAP) { - free_object(tmp); - return 0; + free_object(tmp); + return 0; } if (OB_TYPE_MOVE_BLOCK(tmp, GET_MAP_MOVE_BLOCK(tmp->map, tmp->x, tmp->y))) { - if(!QUERY_FLAG(tmp, FLAG_REFLECTING)) { - free_object(tmp); - return 0; - } - tmp->x=op->x; - tmp->y=op->y; - tmp->direction=absdir(tmp->direction+4); - tmp->map = op->map; + if(!QUERY_FLAG(tmp, FLAG_REFLECTING)) { + free_object(tmp); + return 0; + } + tmp->x=op->x; + tmp->y=op->y; + tmp->direction=absdir(tmp->direction+4); + tmp->map = op->map; } if ((tmp = insert_ob_in_map(tmp,tmp->map,op,0)) != NULL) { - check_bullet (tmp); + check_bullet (tmp); } return 1; } @@ -678,8 +678,8 @@ /* preserve skill ownership */ if(op->skill && op->skill != new_ob->skill) { - if (new_ob->skill) free_string(new_ob->skill); - new_ob->skill = add_refcount(op->skill); + if (new_ob->skill) free_string(new_ob->skill); + new_ob->skill = add_refcount(op->skill); } insert_ob_in_map(new_ob,op->map,op,0); @@ -693,17 +693,17 @@ /* if no map then hit_map will crash so just ignore object */ if (! op->map) { - LOG(llevError,"Tried to move_cone object %s without a map.\n", - op->name ? op->name : "unknown"); + LOG(llevError,"Tried to move_cone object %s without a map.\n", + op->name ? op->name : "unknown"); op->speed = 0; update_ob_speed (op); - return; + return; } /* lava saves it's life, but not yours :) */ if (QUERY_FLAG(op, FLAG_LIFESAVE)) { - hit_map(op,0,op->attacktype,0); - return; + hit_map(op,0,op->attacktype,0); + return; } #if 0 @@ -712,9 +712,9 @@ */ /* If no owner left, the spell dies out. */ if(get_owner(op)==NULL) { - remove_ob(op); - free_object(op); - return; + remove_ob(op); + free_object(op); + return; } #endif @@ -731,36 +731,36 @@ return; if((op->duration--)<0) { - remove_ob(op); - free_object(op); - return; + remove_ob(op); + free_object(op); + return; } /* Object has hit maximum range, so don't have it move * any further. When the duration above expires, * then the object will get removed. */ if (--op->range < 0) { - op->range=0; /* just so it doesn't wrap */ - return; + op->range=0; /* just so it doesn't wrap */ + return; } for(i= -1;i<2;i++) { - sint16 x=op->x+freearr_x[absdir(op->stats.sp+i)], - y=op->y+freearr_y[absdir(op->stats.sp+i)]; + sint16 x=op->x+freearr_x[absdir(op->stats.sp+i)], + y=op->y+freearr_y[absdir(op->stats.sp+i)]; - if(ok_to_put_more(op->map,x,y,op,op->attacktype)) { - object *tmp=get_object(); + if(ok_to_put_more(op->map,x,y,op,op->attacktype)) { + object *tmp=get_object(); copy_object(op, tmp); - tmp->x=x; - tmp->y=y; + tmp->x=x; + tmp->y=y; - tmp->duration = op->duration + 1; + tmp->duration = op->duration + 1; - /* Use for spell tracking - see ok_to_put_more() */ - tmp->stats.maxhp = op->stats.maxhp; - insert_ob_in_map(tmp,op->map,op,0); - if (tmp->other_arch) cone_drop(tmp); - } + /* Use for spell tracking - see ok_to_put_more() */ + tmp->stats.maxhp = op->stats.maxhp; + insert_ob_in_map(tmp,op->map,op,0); + if (tmp->other_arch) cone_drop(tmp); + } } } @@ -784,14 +784,14 @@ if (op->type == PLAYER && QUERY_FLAG(op, FLAG_UNDEAD) && op->attacktype & AT_TURN_UNDEAD) { - new_draw_info(NDI_UNIQUE, 0,op, - "Your undead nature prevents you from turning undead!"); - return 0; + new_draw_info(NDI_UNIQUE, 0,op, + "Your undead nature prevents you from turning undead!"); + return 0; } if(!dir) { - range_min= 0; - range_max=8; + range_min= 0; + range_max=8; } /* Need to know what the movetype of the object we are about @@ -801,97 +801,97 @@ movetype = spell->other_arch->clone.move_type; for(i=range_min;i<=range_max;i++) { - sint16 x,y, d; + sint16 x,y, d; + + /* We can't use absdir here, because it never returns + * 0. If this is a rune, we want to hit the person on top + * of the trap (d==0). If it is not a rune, then we don't want + * to hit that person. + */ + d = dir + i; + while (d < 0) d+=8; + while (d > 8) d-=8; + + /* If it's not a rune, we don't want to blast the caster. + * In that case, we have to see - if dir is specified, + * turn this into direction 8. If dir is not specified (all + * direction) skip - otherwise, one line would do more damage + * becase 0 direction will go through 9 directions - necessary + * for the rune code. + */ + if (caster->type != RUNE && d==0) { + if (dir!=0) d=8; + else continue; + } + + x = op->x+freearr_x[d]; + y = op->y+freearr_y[d]; - /* We can't use absdir here, because it never returns - * 0. If this is a rune, we want to hit the person on top - * of the trap (d==0). If it is not a rune, then we don't want - * to hit that person. - */ - d = dir + i; - while (d < 0) d+=8; - while (d > 8) d-=8; - - /* If it's not a rune, we don't want to blast the caster. - * In that case, we have to see - if dir is specified, - * turn this into direction 8. If dir is not specified (all - * direction) skip - otherwise, one line would do more damage - * becase 0 direction will go through 9 directions - necessary - * for the rune code. - */ - if (caster->type != RUNE && d==0) { - if (dir!=0) d=8; - else continue; - } - - x = op->x+freearr_x[d]; - y = op->y+freearr_y[d]; - - if(get_map_flags(op->map, &m, x,y, &sx, &sy) & P_OUT_OF_MAP) - continue; - - if ((movetype & GET_MAP_MOVE_BLOCK(m, sx, sy)) == movetype) - continue; - - success=1; - tmp=arch_to_object(spell->other_arch); - set_owner(tmp,op); - set_spell_skill(op, caster, spell, tmp); - tmp->level = caster_level (caster, spell); - tmp->x = sx; - tmp->y = sy; - tmp->attacktype=spell->attacktype; + if(get_map_flags(op->map, &m, x,y, &sx, &sy) & P_OUT_OF_MAP) + continue; - /* holy word stuff */ - if((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER)) { + if ((movetype & GET_MAP_MOVE_BLOCK(m, sx, sy)) == movetype) + continue; + + success=1; + tmp=arch_to_object(spell->other_arch); + set_owner(tmp,op); + set_spell_skill(op, caster, spell, tmp); + tmp->level = caster_level (caster, spell); + tmp->x = sx; + tmp->y = sy; + tmp->attacktype=spell->attacktype; + + /* holy word stuff */ + if((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER)) { if(!tailor_god_spell(tmp,op)) return 0; - } - - if(dir) - tmp->stats.sp=dir; - else - tmp->stats.sp=i; - - tmp->range=spell->range + SP_level_range_adjust(caster,spell); - - /* If casting it in all directions, it doesn't go as far */ - if (dir == 0) { - tmp->range /= 4; - if (tmp->range < 2 && spell->range >=2) tmp->range = 2; - } - tmp->stats.dam=spell->stats.dam + SP_level_dam_adjust(caster,spell); - tmp->duration=spell->duration + SP_level_duration_adjust(caster,spell); - - /* Special bonus for fear attacks */ - if (tmp->attacktype & AT_FEAR) { - if (caster->type == PLAYER) tmp->duration += fear_bonus[caster->stats.Cha]; - else - tmp->duration += caster->level/3; - } - if (tmp->attacktype & (AT_HOLYWORD | AT_TURN_UNDEAD)) { - if (caster->type == PLAYER) tmp->duration += turn_bonus[caster->stats.Wis]/5; - else - tmp->duration += caster->level/3; - } - - - if ( !(tmp->move_type & MOVE_FLY_LOW)) - LOG (llevDebug, "cast_cone(): arch %s doesn't have flying 1\n", - spell->other_arch->name); - - if (!tmp->move_on && tmp->stats.dam) { - LOG (llevDebug, - "cast_cone(): arch %s doesn't have move_on set\n", - spell->other_arch->name); - } - insert_ob_in_map(tmp,m,op,0); - - /* This is used for tracking spells so that one effect doesn't hit - * a single space too many times. - */ - tmp->stats.maxhp = tmp->count; + } + + if(dir) + tmp->stats.sp=dir; + else + tmp->stats.sp=i; + + tmp->range=spell->range + SP_level_range_adjust(caster,spell); + + /* If casting it in all directions, it doesn't go as far */ + if (dir == 0) { + tmp->range /= 4; + if (tmp->range < 2 && spell->range >=2) tmp->range = 2; + } + tmp->stats.dam=spell->stats.dam + SP_level_dam_adjust(caster,spell); + tmp->duration=spell->duration + SP_level_duration_adjust(caster,spell); + + /* Special bonus for fear attacks */ + if (tmp->attacktype & AT_FEAR) { + if (caster->type == PLAYER) tmp->duration += fear_bonus[caster->stats.Cha]; + else + tmp->duration += caster->level/3; + } + if (tmp->attacktype & (AT_HOLYWORD | AT_TURN_UNDEAD)) { + if (caster->type == PLAYER) tmp->duration += turn_bonus[caster->stats.Wis]/5; + else + tmp->duration += caster->level/3; + } + + + if ( !(tmp->move_type & MOVE_FLY_LOW)) + LOG (llevDebug, "cast_cone(): arch %s doesn't have flying 1\n", + spell->other_arch->name); + + if (!tmp->move_on && tmp->stats.dam) { + LOG (llevDebug, + "cast_cone(): arch %s doesn't have move_on set\n", + spell->other_arch->name); + } + insert_ob_in_map(tmp,m,op,0); - if(tmp->other_arch) cone_drop(tmp); + /* This is used for tracking spells so that one effect doesn't hit + * a single space too many times. + */ + tmp->stats.maxhp = tmp->count; + + if(tmp->other_arch) cone_drop(tmp); } return success; } @@ -912,7 +912,7 @@ archetype *at; if(op->state!=NUM_ANIMATIONS(op)-1) - return; + return; env = object_get_env_recursive(op); @@ -921,14 +921,14 @@ if (env->map == NULL) return; - if (env->type == PLAYER) - esrv_del_item(env->contr, op->count); + if (env->type == PLAYER) + esrv_del_item(env->contr, op->count); - remove_ob(op); - op->x = env->x; - op->y = env->y; - if ((op = insert_ob_in_map (op, env->map, op,0)) == NULL) - return; + remove_ob(op); + op->x = env->x; + op->y = env->y; + if ((op = insert_ob_in_map (op, env->map, op,0)) == NULL) + return; } // elmex Tue Aug 15 17:46:51 CEST 2006: Prevent bomb from exploding @@ -947,27 +947,27 @@ */ at = find_archetype(SPLINT); if (at) { - for(i=1;i<9;i++) { - if (out_of_map(op->map, op->x + freearr_x[i], op->y + freearr_x[i])) - continue; - tmp = arch_to_object(at); - tmp->direction = i; - tmp->range = op->range; - tmp->stats.dam = op->stats.dam; - tmp->duration = op->duration; - tmp->attacktype = op->attacktype; + for(i=1;i<9;i++) { + if (out_of_map(op->map, op->x + freearr_x[i], op->y + freearr_x[i])) + continue; + tmp = arch_to_object(at); + tmp->direction = i; + tmp->range = op->range; + tmp->stats.dam = op->stats.dam; + tmp->duration = op->duration; + tmp->attacktype = op->attacktype; copy_owner (tmp, op); - if(op->skill && op->skill != tmp->skill) { - if (tmp->skill) free_string(tmp->skill); - tmp->skill = add_refcount(op->skill); - } - if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE)) - SET_ANIMATION(tmp, i); - tmp->x = op->x + freearr_x[i]; - tmp->y = op->y + freearr_x[i]; - insert_ob_in_map(tmp, op->map, op, 0); - move_bullet(tmp); - } + if(op->skill && op->skill != tmp->skill) { + if (tmp->skill) free_string(tmp->skill); + tmp->skill = add_refcount(op->skill); + } + if(QUERY_FLAG(tmp, FLAG_IS_TURNABLE)) + SET_ANIMATION(tmp, i); + tmp->x = op->x + freearr_x[i]; + tmp->y = op->y + freearr_x[i]; + insert_ob_in_map(tmp, op->map, op, 0); + move_bullet(tmp); + } } explode_bullet(op); @@ -982,8 +982,8 @@ mflags = get_map_flags(op->map, &m, dx,dy, &dx,&dy); if ((mflags & P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK(m, dx, dy) & MOVE_WALK)) { - new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way."); - return 0; + new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way."); + return 0; } tmp=arch_to_object(spell->other_arch); @@ -1026,23 +1026,23 @@ if (dir==0) return NULL; for (dist=1; distx + freearr_x[dir] * dist; - y = op->y + freearr_y[dir] * dist; - mp = op->map; - mflags = get_map_flags(op->map, &mp, x, y, &x, &y); - - if (mflags & P_OUT_OF_MAP) return NULL; - if ((type & SPELL_MANA) && (mflags & P_NO_MAGIC)) return NULL; - if ((type & SPELL_GRACE) && (mflags & P_NO_CLERIC)) return NULL; - if (GET_MAP_MOVE_BLOCK(mp, x, y) & MOVE_FLY_LOW) return NULL; - - if (mflags & P_IS_ALIVE) { - for(target=get_map_ob(mp,x,y); target; target=target->above) { - if(QUERY_FLAG(target->head?target->head:target,FLAG_MONSTER)) { - return target; - } - } - } + x = op->x + freearr_x[dir] * dist; + y = op->y + freearr_y[dir] * dist; + mp = op->map; + mflags = get_map_flags(op->map, &mp, x, y, &x, &y); + + if (mflags & P_OUT_OF_MAP) return NULL; + if ((type & SPELL_MANA) && (mflags & P_NO_MAGIC)) return NULL; + if ((type & SPELL_GRACE) && (mflags & P_NO_CLERIC)) return NULL; + if (GET_MAP_MOVE_BLOCK(mp, x, y) & MOVE_FLY_LOW) return NULL; + + if (mflags & P_IS_ALIVE) { + for(target=get_map_ob(mp,x,y); target; target=target->above) { + if(QUERY_FLAG(target->head?target->head:target,FLAG_MONSTER)) { + return target; + } + } + } } return NULL; } @@ -1083,9 +1083,9 @@ } if (spell->other_arch) - effect = arch_to_object(spell->other_arch); + effect = arch_to_object(spell->other_arch); else - return 0; + return 0; /* tailor the effect by priest level and worshipped God */ effect->level = caster_level (caster, spell); @@ -1097,7 +1097,7 @@ else { new_draw_info(NDI_UNIQUE,0,op,"Your request is ignored."); return 0; - } + } } /* size of the area of destruction */ @@ -1107,26 +1107,26 @@ SP_level_range_adjust(caster,spell); if (effect->attacktype & AT_DEATH) { - effect->level=spell->stats.dam + + effect->level=spell->stats.dam + SP_level_dam_adjust(caster,spell); - /* casting death spells at undead isn't a good thing */ - if QUERY_FLAG(target, FLAG_UNDEAD) { - if(random_roll(0, 2, op, PREFER_LOW)) { - new_draw_info(NDI_UNIQUE,0,op,"Idiot! Your spell boomerangs!"); - effect->x=op->x; - effect->y=op->y; - } else { - new_draw_info_format(NDI_UNIQUE,0,op,"The %s looks stronger!", - query_name(target)); - target->stats.hp = target->stats.maxhp*2; - free_object(effect); - return 0; - } - } + /* casting death spells at undead isn't a good thing */ + if QUERY_FLAG(target, FLAG_UNDEAD) { + if(random_roll(0, 2, op, PREFER_LOW)) { + new_draw_info(NDI_UNIQUE,0,op,"Idiot! Your spell boomerangs!"); + effect->x=op->x; + effect->y=op->y; + } else { + new_draw_info_format(NDI_UNIQUE,0,op,"The %s looks stronger!", + query_name(target)); + target->stats.hp = target->stats.maxhp*2; + free_object(effect); + return 0; + } + } } else { - /* how much woe to inflict :) */ - effect->stats.dam=spell->stats.dam + + /* how much woe to inflict :) */ + effect->stats.dam=spell->stats.dam + SP_level_dam_adjust(caster,spell); } @@ -1157,9 +1157,9 @@ mapstruct *m; if (op->range-- <=0) { - remove_ob(op); - free_object(op); - return; + remove_ob(op); + free_object(op); + return; } owner = get_owner(op); @@ -1168,9 +1168,9 @@ * monster that are then killed would continue to survive */ if (owner == NULL) { - remove_ob(op); - free_object(op); - return; + remove_ob(op); + free_object(op); + return; } #endif @@ -1180,31 +1180,31 @@ mflags = get_map_flags(op->map, &m, new_x, new_y, &new_x, &new_y); if (!(mflags & P_OUT_OF_MAP) && - ((mflags & P_IS_ALIVE) || OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, new_x, new_y)))) { - tag_t tag = op->count; - hit_map (op, op->direction, AT_MAGIC, 1); - /* Basically, missile only hits one thing then goes away. - * we need to remove it if someone hasn't already done so. - */ - if ( ! was_destroyed (op, tag)) { - remove_ob (op); - free_object(op); - } - return; + ((mflags & P_IS_ALIVE) || OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, new_x, new_y)))) { + tag_t tag = op->count; + hit_map (op, op->direction, AT_MAGIC, 1); + /* Basically, missile only hits one thing then goes away. + * we need to remove it if someone hasn't already done so. + */ + if ( ! was_destroyed (op, tag)) { + remove_ob (op); + free_object(op); + } + return; } remove_ob(op); if ( ! op->direction || (mflags & P_OUT_OF_MAP)) { - free_object(op); - return; + free_object(op); + return; } op->x = new_x; op->y = new_y; op->map = m; i=spell_find_dir(op->map, op->x, op->y, get_owner(op)); if(i > 0 && i != op->direction){ - op->direction=i; - SET_ANIMATION(op, op->direction); + op->direction=i; + SET_ANIMATION(op, op->direction); } insert_ob_in_map(op,op->map,op,0); } @@ -1224,7 +1224,7 @@ /* some things are unaffected... */ if(op->path_denied&PATH_LIGHT) - return 0; + return 0; tmp=get_archetype(FORCE_NAME); tmp->speed = 0.01; @@ -1232,19 +1232,19 @@ SET_FLAG(tmp, FLAG_IS_USED_UP); tmp->glow_radius=radius; if (tmp->glow_radius > MAX_LIGHT_RADII) - tmp->glow_radius = MAX_LIGHT_RADII; + tmp->glow_radius = MAX_LIGHT_RADII; tmp->x=op->x; tmp->y=op->y; if(tmp->speedspeed = MIN_ACTIVE_SPEED; /* safety */ tmp=insert_ob_in_ob(tmp,op); if (tmp->glow_radius > op->glow_radius) - op->glow_radius = tmp->glow_radius; + op->glow_radius = tmp->glow_radius; if(!tmp->env||op!=tmp->env) { - LOG(llevError,"make_object_glow() failed to insert glowing force in %s\n", - op->name); - return 0; + LOG(llevError,"make_object_glow() failed to insert glowing force in %s\n", + op->name); + return 0; } return 1; } @@ -1278,43 +1278,43 @@ change_skill(op, find_skill_by_name(op, op->skill), 1); for(i= -range; imap; - sx = op->x + i; - sy = op->y + j; - mflags = get_map_flags(m, &m, sx, sy, &sx, &sy); - if (mflags & P_OUT_OF_MAP) continue; - if (mflags & P_IS_ALIVE) { - for (tmp=get_map_ob(m, sx, sy); tmp; tmp=tmp->above) { - if (QUERY_FLAG(tmp, FLAG_ALIVE) || tmp->type==PLAYER) break; - } - if (tmp) { - if (tmp->head) tmp=tmp->head; - - if ((friendly && !QUERY_FLAG(tmp, FLAG_FRIENDLY) && tmp->type!=PLAYER) || - (!friendly && (QUERY_FLAG(tmp, FLAG_FRIENDLY) || tmp->type==PLAYER))) { - if (spell_ob->subtype == SP_DESTRUCTION) { - hit_player(tmp,dam,op,spell_ob->attacktype,0); - if (spell_ob->other_arch) { - tmp = arch_to_object(spell_ob->other_arch); - tmp->x = sx; - tmp->y = sy; - insert_ob_in_map(tmp, m, op, 0); - } - } - else if (spell_ob->subtype == SP_FAERY_FIRE && - tmp->resist[ATNR_MAGIC]!=100) { - if (make_object_glow(tmp, 1, dur) && spell_ob->other_arch) { - object *effect = arch_to_object(spell_ob->other_arch); - effect->x = sx; - effect->y = sy; - insert_ob_in_map(effect, m, op, 0); - } - } - } - } - } - } + for(j=-range; jmap; + sx = op->x + i; + sy = op->y + j; + mflags = get_map_flags(m, &m, sx, sy, &sx, &sy); + if (mflags & P_OUT_OF_MAP) continue; + if (mflags & P_IS_ALIVE) { + for (tmp=get_map_ob(m, sx, sy); tmp; tmp=tmp->above) { + if (QUERY_FLAG(tmp, FLAG_ALIVE) || tmp->type==PLAYER) break; + } + if (tmp) { + if (tmp->head) tmp=tmp->head; + + if ((friendly && !QUERY_FLAG(tmp, FLAG_FRIENDLY) && tmp->type!=PLAYER) || + (!friendly && (QUERY_FLAG(tmp, FLAG_FRIENDLY) || tmp->type==PLAYER))) { + if (spell_ob->subtype == SP_DESTRUCTION) { + hit_player(tmp,dam,op,spell_ob->attacktype,0); + if (spell_ob->other_arch) { + tmp = arch_to_object(spell_ob->other_arch); + tmp->x = sx; + tmp->y = sy; + insert_ob_in_map(tmp, m, op, 0); + } + } + else if (spell_ob->subtype == SP_FAERY_FIRE && + tmp->resist[ATNR_MAGIC]!=100) { + if (make_object_glow(tmp, 1, dur) && spell_ob->other_arch) { + object *effect = arch_to_object(spell_ob->other_arch); + effect->x = sx; + effect->y = sy; + insert_ob_in_map(effect, m, op, 0); + } + } + } + } + } + } } op->skill = skill; return 1; @@ -1331,50 +1331,50 @@ object *tmp, *force; tmp = get_pointed_target(op, (dir==0)?op->direction:dir, - spell_ob->range, SPELL_GRACE); + spell_ob->range, SPELL_GRACE); if (!tmp) { - new_draw_info(NDI_UNIQUE, 0, op, - "There is no one in that direction to curse."); - return 0; + new_draw_info(NDI_UNIQUE, 0, op, + "There is no one in that direction to curse."); + return 0; } /* If we've already got a force of this type, don't add a new one. */ for(force=tmp->inv; force!=NULL; force=force->below) { - if (force->type==FORCE && force->subtype == FORCE_CHANGE_ABILITY) { - if (force->name == spell_ob->name) { - break; - } - else if (spell_ob->race && spell_ob->race == force->name) { - new_draw_info_format(NDI_UNIQUE, 0, op, - "You can not cast %s while %s is in effect", + if (force->type==FORCE && force->subtype == FORCE_CHANGE_ABILITY) { + if (force->name == spell_ob->name) { + break; + } + else if (spell_ob->race && spell_ob->race == force->name) { + new_draw_info_format(NDI_UNIQUE, 0, op, + "You can not cast %s while %s is in effect", spell_ob->name, force->name_pl); - return 0; - } - } + return 0; + } + } } if(force==NULL) { - force=get_archetype(FORCE_NAME); - force->subtype = FORCE_CHANGE_ABILITY; - free_string(force->name); - if (spell_ob->race) - force->name = add_refcount(spell_ob->race); - else - force->name = add_refcount(spell_ob->name); - free_string(force->name_pl); - force->name_pl = add_refcount(spell_ob->name); + force=get_archetype(FORCE_NAME); + force->subtype = FORCE_CHANGE_ABILITY; + free_string(force->name); + if (spell_ob->race) + force->name = add_refcount(spell_ob->race); + else + force->name = add_refcount(spell_ob->name); + free_string(force->name_pl); + force->name_pl = add_refcount(spell_ob->name); } else { - int duration; + int duration; - duration = spell_ob->duration + SP_level_duration_adjust(caster, spell_ob) * 50; - if (duration > force->duration) { - force->duration = duration; - new_draw_info(NDI_UNIQUE, 0, op, "You recast the spell while in effect."); - } else { - new_draw_info(NDI_UNIQUE, 0, op, "Recasting the spell had no effect."); - } - return 1; + duration = spell_ob->duration + SP_level_duration_adjust(caster, spell_ob) * 50; + if (duration > force->duration) { + force->duration = duration; + new_draw_info(NDI_UNIQUE, 0, op, "You recast the spell while in effect."); + } else { + new_draw_info(NDI_UNIQUE, 0, op, "Recasting the spell had no effect."); + } + return 1; } force->duration = spell_ob->duration + SP_level_duration_adjust(caster, spell_ob) * 50; force->speed = 1.0; @@ -1382,18 +1382,18 @@ SET_FLAG(force, FLAG_APPLIED); if(god) { - if (spell_ob->last_grace) - force->path_repelled=god->path_repelled; - if (spell_ob->last_grace) - force->path_denied=god->path_denied; - new_draw_info_format(NDI_UNIQUE, 0,tmp, - "You are a victim of %s's curse!",god->name); + if (spell_ob->last_grace) + force->path_repelled=god->path_repelled; + if (spell_ob->last_grace) + force->path_denied=god->path_denied; + new_draw_info_format(NDI_UNIQUE, 0,tmp, + "You are a victim of %s's curse!",god->name); } else - new_draw_info(NDI_UNIQUE, 0,op,"Your curse seems empty."); + new_draw_info(NDI_UNIQUE, 0,op,"Your curse seems empty."); if(tmp!=op && op->type==PLAYER) - new_draw_info_format(NDI_UNIQUE, 0, op, "You curse %s!",tmp->name); + new_draw_info_format(NDI_UNIQUE, 0, op, "You curse %s!",tmp->name); force->stats.ac = spell_ob->stats.ac; force->stats.wc = spell_ob->stats.wc; @@ -1440,47 +1440,47 @@ for (x = op->x - range; x <= op->x + range; x++) - for (y = op->y - range; y <= op->y + range; y++) { + for (y = op->y - range; y <= op->y + range; y++) { - done_one=0; - m = op->map; - nx = x; - ny = y; - mflags = get_map_flags(m, &m, x, y, &nx, &ny); - if (mflags & P_OUT_OF_MAP) continue; - - /* If there is nothing living on this space, no need to go further */ - if (!(mflags & P_IS_ALIVE)) continue; - - for (tmp = get_map_ob(m, nx, ny); tmp; tmp = tmp->above) - if (QUERY_FLAG(tmp, FLAG_MONSTER)) break; - - /* There can be living objects that are not monsters */ - if (!tmp || tmp->type==PLAYER) continue; - - /* Only the head has meaningful data, so resolve to that */ - if (tmp->head) head=tmp->head; - else head=tmp; - - /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */ - if (race && head->race && !strstr(race, head->race)) continue; - if (QUERY_FLAG(head, FLAG_UNDEAD) && !QUERY_FLAG(spell, FLAG_UNDEAD)) continue; - - /* Now do a bunch of stuff related to saving throws */ - best_at = -1; - if (spell->attacktype) { - for (at=0; at < NROFATTACKS; at++) - if (spell->attacktype & (1 << at)) - if (best_at == -1 || head->resist[at] > head->resist[best_at]) best_at = at; + done_one=0; + m = op->map; + nx = x; + ny = y; + mflags = get_map_flags(m, &m, x, y, &nx, &ny); + if (mflags & P_OUT_OF_MAP) continue; + + /* If there is nothing living on this space, no need to go further */ + if (!(mflags & P_IS_ALIVE)) continue; + + for (tmp = get_map_ob(m, nx, ny); tmp; tmp = tmp->above) + if (QUERY_FLAG(tmp, FLAG_MONSTER)) break; + + /* There can be living objects that are not monsters */ + if (!tmp || tmp->type==PLAYER) continue; + + /* Only the head has meaningful data, so resolve to that */ + if (tmp->head) head=tmp->head; + else head=tmp; + + /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */ + if (race && head->race && !strstr(race, head->race)) continue; + if (QUERY_FLAG(head, FLAG_UNDEAD) && !QUERY_FLAG(spell, FLAG_UNDEAD)) continue; + + /* Now do a bunch of stuff related to saving throws */ + best_at = -1; + if (spell->attacktype) { + for (at=0; at < NROFATTACKS; at++) + if (spell->attacktype & (1 << at)) + if (best_at == -1 || head->resist[at] > head->resist[best_at]) best_at = at; if (best_at == -1) at=0; - else { - if (head->resist[best_at] == 100) continue; - else at = head->resist[best_at] / 5; - } - at -= level / 5; - if (did_make_save(head, head->level, at)) continue; - } + else { + if (head->resist[best_at] == 100) continue; + else at = head->resist[best_at] / 5; + } + at -= level / 5; + if (did_make_save(head, head->level, at)) continue; + } else /* spell->attacktype */ /* Spell has no attacktype (charm & such), so we'll have a specific saving: @@ -1501,54 +1501,54 @@ continue; } - /* Done with saving throw. Now start effecting the monster */ + /* Done with saving throw. Now start effecting the monster */ + + /* aggravation */ + if (QUERY_FLAG(spell, FLAG_MONSTER)) { + CLEAR_FLAG(head, FLAG_SLEEP); + if (QUERY_FLAG(head, FLAG_FRIENDLY)) + remove_friendly_object(head); + + done_one = 1; + head->enemy = op; + } - /* aggravation */ - if (QUERY_FLAG(spell, FLAG_MONSTER)) { - CLEAR_FLAG(head, FLAG_SLEEP); - if (QUERY_FLAG(head, FLAG_FRIENDLY)) - remove_friendly_object(head); - - done_one = 1; - head->enemy = op; - } - - /* calm monsters */ - if (QUERY_FLAG(spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG(head, FLAG_UNAGGRESSIVE)) { - SET_FLAG(head, FLAG_UNAGGRESSIVE); - head->enemy = NULL; - done_one = 1; - } - - /* berserk monsters */ - if (QUERY_FLAG(spell, FLAG_BERSERK) && !QUERY_FLAG(head, FLAG_BERSERK)) { - SET_FLAG(head, FLAG_BERSERK); - done_one = 1; - } - /* charm */ - if (QUERY_FLAG(spell, FLAG_NO_ATTACK) && !QUERY_FLAG(head, FLAG_FRIENDLY)) { - SET_FLAG(head, FLAG_FRIENDLY); + /* calm monsters */ + if (QUERY_FLAG(spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG(head, FLAG_UNAGGRESSIVE)) { + SET_FLAG(head, FLAG_UNAGGRESSIVE); + head->enemy = NULL; + done_one = 1; + } + + /* berserk monsters */ + if (QUERY_FLAG(spell, FLAG_BERSERK) && !QUERY_FLAG(head, FLAG_BERSERK)) { + SET_FLAG(head, FLAG_BERSERK); + done_one = 1; + } + /* charm */ + if (QUERY_FLAG(spell, FLAG_NO_ATTACK) && !QUERY_FLAG(head, FLAG_FRIENDLY)) { + SET_FLAG(head, FLAG_FRIENDLY); /* Prevent uncontolled outbreaks of self replicating monsters. Typical use case is charm, go somwhere, use aggravation to make hostile. This could lead to fun stuff like mice outbreak in bigworld and server crawl. */ CLEAR_FLAG(head, FLAG_GENERATOR); set_owner(head, op); - set_spell_skill(op, caster, spell, head); - add_friendly_object(head); - head->attack_movement = PETMOVE; - done_one = 1; - change_exp(op, head->stats.exp / 2, head->skill, SK_EXP_ADD_SKILL); - head->stats.exp = 0; - } - - /* If a monster was effected, put an effect in */ - if (done_one && spell->other_arch) { - tmp = arch_to_object(spell->other_arch); - tmp->x = nx; - tmp->y = ny; - insert_ob_in_map(tmp, m, op, 0); - } - } /* for y */ + set_spell_skill(op, caster, spell, head); + add_friendly_object(head); + head->attack_movement = PETMOVE; + done_one = 1; + change_exp(op, head->stats.exp / 2, head->skill, SK_EXP_ADD_SKILL); + head->stats.exp = 0; + } + + /* If a monster was effected, put an effect in */ + if (done_one && spell->other_arch) { + tmp = arch_to_object(spell->other_arch); + tmp->x = nx; + tmp->y = ny; + insert_ob_in_map(tmp, m, op, 0); + } + } /* for y */ return 1; } @@ -1578,36 +1578,36 @@ dir = 0; if(!(rndm(0, 3))) - j = rndm(0, 1); + j = rndm(0, 1); else j=0; for(i = 1; i < 9; i++) { - /* i bit 0: alters sign of offset - * other bits (i / 2): absolute value of offset - */ - - int offset = ((i ^ j) & 1) ? (i / 2) : - (i / 2); - int tmpdir = absdir (op->direction + offset); - - nx = op->x + freearr_x[tmpdir]; - ny = op->y + freearr_y[tmpdir]; - if ( ! (get_map_flags(op->map, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) && - !(OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, nx, ny)))) { - dir = tmpdir; - break; - } + /* i bit 0: alters sign of offset + * other bits (i / 2): absolute value of offset + */ + + int offset = ((i ^ j) & 1) ? (i / 2) : - (i / 2); + int tmpdir = absdir (op->direction + offset); + + nx = op->x + freearr_x[tmpdir]; + ny = op->y + freearr_y[tmpdir]; + if ( ! (get_map_flags(op->map, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) && + !(OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, nx, ny)))) { + dir = tmpdir; + break; + } } if (dir == 0) { - nx = op->x; - ny = op->y; - m = op->map; + nx = op->x; + ny = op->y; + m = op->map; } remove_ob(op); op->y=ny; op->x=nx; insert_ob_in_map(op,m,op,0); - + dam_save = op->stats.dam; /* save the original dam: we do halfdam on surrounding squares */ @@ -1616,33 +1616,33 @@ * the surround spaces. */ for(j=0;j<9;j++) { - object *new_ob; + object *new_ob; - hx = nx+freearr_x[j]; - hy = ny+freearr_y[j]; + hx = nx+freearr_x[j]; + hy = ny+freearr_y[j]; - m = op->map; - mflags = get_map_flags(m, &m, hx, hy, &hx, &hy); + m = op->map; + mflags = get_map_flags(m, &m, hx, hy, &hx, &hy); - if (mflags & P_OUT_OF_MAP) continue; + if (mflags & P_OUT_OF_MAP) continue; - /* first, don't ever, ever hit the owner. Don't hit out - * of the map either. - */ + /* first, don't ever, ever hit the owner. Don't hit out + * of the map either. + */ - if((mflags & P_IS_ALIVE) && (!owner || owner->x!=hx || owner->y!=hy || !on_same_map(owner,op))) { - if(j) op->stats.dam = dam_save/2; - hit_map(op,j,op->attacktype,1); + if((mflags & P_IS_ALIVE) && (!owner || owner->x!=hx || owner->y!=hy || !on_same_map(owner,op))) { + if(j) op->stats.dam = dam_save/2; + hit_map(op,j,op->attacktype,1); - } + } - /* insert the other arch */ - if(op->other_arch && !(OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, hx, hy)))) { - new_ob = arch_to_object(op->other_arch); - new_ob->x = hx; - new_ob->y = hy; - insert_ob_in_map(new_ob,m,op,0); - } + /* insert the other arch */ + if(op->other_arch && !(OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, hx, hy)))) { + new_ob = arch_to_object(op->other_arch); + new_ob->x = hx; + new_ob->y = hy; + insert_ob_in_map(new_ob,m,op,0); + } } /* restore to the center location and damage*/ @@ -1651,12 +1651,12 @@ i=spell_find_dir(op->map,op->x,op->y,get_owner(op)); if(i>=0) { /* we have a preferred direction! */ - /* pick another direction if the preferred dir is blocked. */ - if (get_map_flags(op->map,&m, nx + freearr_x[i], ny + freearr_y[i],&hx,&hy) & P_OUT_OF_MAP || - OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, hx, hy))) { - i= absdir(i + rndm(0, 2) -1); /* -1, 0, +1 */ - } - op->direction=i; + /* pick another direction if the preferred dir is blocked. */ + if (get_map_flags(op->map,&m, nx + freearr_x[i], ny + freearr_y[i],&hx,&hy) & P_OUT_OF_MAP || + OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, hx, hy))) { + i= absdir(i + rndm(0, 2) -1); /* -1, 0, +1 */ + } + op->direction=i; } } @@ -1680,9 +1680,9 @@ owner = get_owner(op); if(op->duration == 0 || owner == NULL) { - remove_ob(op); - free_object(op); - return; + remove_ob(op); + free_object(op); + return; } op->duration--; @@ -1730,14 +1730,14 @@ */ if (op->spell && op->spell->type == SPELL && - !(get_map_flags(op->map, &m, target_x, target_y, &target_x, &target_y) & P_OUT_OF_MAP) && - !(OB_TYPE_MOVE_BLOCK(op->spell, GET_MAP_MOVE_BLOCK(m, target_x, target_y)))) { + !(get_map_flags(op->map, &m, target_x, target_y, &target_x, &target_y) & P_OUT_OF_MAP) && + !(OB_TYPE_MOVE_BLOCK(op->spell, GET_MAP_MOVE_BLOCK(m, target_x, target_y)))) { - /* Bullet spells have a bunch more customization that needs to be done */ - if (op->spell->subtype == SP_BULLET) - fire_bullet(owner, op, basedir, op->spell); - else if (op->spell->subtype == SP_MAGIC_MISSILE) - fire_arch_from_position (owner, op, origin_x, origin_y, basedir, op->spell); + /* Bullet spells have a bunch more customization that needs to be done */ + if (op->spell->subtype == SP_BULLET) + fire_bullet(owner, op, basedir, op->spell); + else if (op->spell->subtype == SP_MAGIC_MISSILE) + fire_arch_from_position (owner, op, origin_x, origin_y, basedir, op->spell); } #endif @@ -1749,11 +1749,11 @@ if (op->spell && op->spell->type == SPELL) { - /* Bullet spells have a bunch more customization that needs to be done */ - if (op->spell->subtype == SP_BULLET) - fire_bullet(owner, op, basedir, op->spell); - else if (op->spell->subtype == SP_MAGIC_MISSILE) - fire_arch_from_position (owner, op, op->x, op->y, basedir, op->spell); + /* Bullet spells have a bunch more customization that needs to be done */ + if (op->spell->subtype == SP_BULLET) + fire_bullet(owner, op, basedir, op->spell); + else if (op->spell->subtype == SP_MAGIC_MISSILE) + fire_arch_from_position (owner, op, op->x, op->y, basedir, op->spell); } } @@ -1791,12 +1791,12 @@ tmp->attacktype = tmp->spell->attacktype; if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) { - if ( ! tailor_god_spell (tmp, op)) - return 1; + if ( ! tailor_god_spell (tmp, op)) + return 1; } tmp->duration = SP_level_duration_adjust(caster, spell); for (i=0; i< spell->duration; i++) - tmp->duration += die_roll(1, 3, op, PREFER_HIGH); + tmp->duration += die_roll(1, 3, op, PREFER_HIGH); tmp->direction=dir; tmp->invisible=1; @@ -1817,8 +1817,8 @@ dam = spell->stats.dam + SP_level_dam_adjust(caster,spell); if(!dir) { - new_draw_info(NDI_UNIQUE, 0,op,"In what direction?"); - return 0; + new_draw_info(NDI_UNIQUE, 0,op,"In what direction?"); + return 0; } x=op->x+freearr_x[dir]; @@ -1828,36 +1828,36 @@ mflags = get_map_flags(m, &m, x, y, &x, &y); if (mflags & P_OUT_OF_MAP) { - new_draw_info(NDI_UNIQUE, 0,op,"Nothing is there."); - return 0; + new_draw_info(NDI_UNIQUE, 0,op,"Nothing is there."); + return 0; } if (mflags & P_IS_ALIVE && spell->attacktype) { - for(target=get_map_ob(m,x,y);target;target=target->above) - if(QUERY_FLAG(target,FLAG_MONSTER)) { - /* oky doky. got a target monster. Lets make a blinding attack */ - if(target->head) target = target->head; - (void) hit_player(target,dam,op,spell->attacktype,1); - return 1; /* one success only! */ - } + for(target=get_map_ob(m,x,y);target;target=target->above) + if(QUERY_FLAG(target,FLAG_MONSTER)) { + /* oky doky. got a target monster. Lets make a blinding attack */ + if(target->head) target = target->head; + (void) hit_player(target,dam,op,spell->attacktype,1); + return 1; /* one success only! */ + } } /* no live target, perhaps a wall is in the way? */ if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y))) { - new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way."); - return 0; + new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way."); + return 0; } /* ok, looks groovy to just insert a new light on the map */ tmp=arch_to_object(spell->other_arch); if(!tmp) { - LOG(llevError,"Error: spell arch for cast_light() missing.\n"); - return 0; + LOG(llevError,"Error: spell arch for cast_light() missing.\n"); + return 0; } tmp->stats.food = spell->duration + SP_level_duration_adjust(caster,spell); if (tmp->glow_radius) { - tmp->glow_radius= spell->range + SP_level_range_adjust(caster,spell); - if (tmp->glow_radius > MAX_LIGHT_RADII) tmp->glow_radius = MAX_LIGHT_RADII; + tmp->glow_radius= spell->range + SP_level_range_adjust(caster,spell); + if (tmp->glow_radius > MAX_LIGHT_RADII) tmp->glow_radius = MAX_LIGHT_RADII; } tmp->x=x; tmp->y=y; @@ -1897,87 +1897,87 @@ /* search in a line for a victim */ for(i=1; ix + i * freearr_x[dir]; - y = op->y + i * freearr_y[dir]; - m = op->map; - - mflags = get_map_flags(m, &m, x, y, &x, &y); - - if (mflags & P_OUT_OF_MAP) return 0; - - /* don't go through walls - presume diseases are airborne */ - if (GET_MAP_MOVE_BLOCK(m, x, y) & MOVE_FLY_LOW) return 0; - - /* Only bother looking on this space if there is something living here */ - if (mflags & P_IS_ALIVE) { - /* search this square for a victim */ - for(walk=get_map_ob(m,x,y);walk;walk=walk->above) - if (QUERY_FLAG(walk,FLAG_MONSTER) || (walk->type==PLAYER)) { /* found a victim */ - object *disease = arch_to_object(spell->other_arch); - - set_owner(disease,op); - set_spell_skill(op, caster, spell, disease); - disease->stats.exp = 0; - disease->level = caster_level(caster, spell); - - /* do level adjustments */ - if(disease->stats.wc) - disease->stats.wc += dur_mod/2; - - if(disease->magic> 0) - disease->magic += dur_mod/4; - - if(disease->stats.maxhp>0) - disease->stats.maxhp += dur_mod; - - if(disease->stats.maxgrace>0) - disease->stats.maxgrace += dur_mod; - - if(disease->stats.dam) { - if(disease->stats.dam > 0) - disease->stats.dam += dam_mod; - else disease->stats.dam -= dam_mod; - } - - if(disease->last_sp) { - disease->last_sp -= 2*dam_mod; - if(disease->last_sp <1) disease->last_sp = 1; - } - - if(disease->stats.maxsp) { - if(disease->stats.maxsp > 0) - disease->stats.maxsp += dam_mod; - else disease->stats.maxsp -= dam_mod; - } - - if(disease->stats.ac) - disease->stats.ac += dam_mod; - - if(disease->last_eat) - disease->last_eat -= dam_mod; - - if(disease->stats.hp) - disease->stats.hp -= dam_mod; - - if(disease->stats.sp) - disease->stats.sp -= dam_mod; - - if(infect_object(walk,disease,1)) { - object *flash; /* visual effect for inflicting disease */ - - new_draw_info_format(NDI_UNIQUE, 0, op, "You inflict %s on %s!",disease->name,walk->name); - - free_object(disease); /* don't need this one anymore */ - flash=get_archetype(ARCH_DETECT_MAGIC); - flash->x = x; - flash->y = y; - flash->map = walk->map; - insert_ob_in_map(flash,walk->map,op,0); - return 1; - } - free_object(disease); - } - } /* if living creature */ + x = op->x + i * freearr_x[dir]; + y = op->y + i * freearr_y[dir]; + m = op->map; + + mflags = get_map_flags(m, &m, x, y, &x, &y); + + if (mflags & P_OUT_OF_MAP) return 0; + + /* don't go through walls - presume diseases are airborne */ + if (GET_MAP_MOVE_BLOCK(m, x, y) & MOVE_FLY_LOW) return 0; + + /* Only bother looking on this space if there is something living here */ + if (mflags & P_IS_ALIVE) { + /* search this square for a victim */ + for(walk=get_map_ob(m,x,y);walk;walk=walk->above) + if (QUERY_FLAG(walk,FLAG_MONSTER) || (walk->type==PLAYER)) { /* found a victim */ + object *disease = arch_to_object(spell->other_arch); + + set_owner(disease,op); + set_spell_skill(op, caster, spell, disease); + disease->stats.exp = 0; + disease->level = caster_level(caster, spell); + + /* do level adjustments */ + if(disease->stats.wc) + disease->stats.wc += dur_mod/2; + + if(disease->magic> 0) + disease->magic += dur_mod/4; + + if(disease->stats.maxhp>0) + disease->stats.maxhp += dur_mod; + + if(disease->stats.maxgrace>0) + disease->stats.maxgrace += dur_mod; + + if(disease->stats.dam) { + if(disease->stats.dam > 0) + disease->stats.dam += dam_mod; + else disease->stats.dam -= dam_mod; + } + + if(disease->last_sp) { + disease->last_sp -= 2*dam_mod; + if(disease->last_sp <1) disease->last_sp = 1; + } + + if(disease->stats.maxsp) { + if(disease->stats.maxsp > 0) + disease->stats.maxsp += dam_mod; + else disease->stats.maxsp -= dam_mod; + } + + if(disease->stats.ac) + disease->stats.ac += dam_mod; + + if(disease->last_eat) + disease->last_eat -= dam_mod; + + if(disease->stats.hp) + disease->stats.hp -= dam_mod; + + if(disease->stats.sp) + disease->stats.sp -= dam_mod; + + if(infect_object(walk,disease,1)) { + object *flash; /* visual effect for inflicting disease */ + + new_draw_info_format(NDI_UNIQUE, 0, op, "You inflict %s on %s!",disease->name,walk->name); + + free_object(disease); /* don't need this one anymore */ + flash=get_archetype(ARCH_DETECT_MAGIC); + flash->x = x; + flash->y = y; + flash->map = walk->map; + insert_ob_in_map(flash,walk->map,op,0); + return 1; + } + free_object(disease); + } + } /* if living creature */ } /* for range of spaces */ new_draw_info(NDI_UNIQUE,0,op,"No one caught anything!"); return 1;