version 1.24 | | version 1.25 |
---|
| | |
/* | | /* |
* static char *rcsid_spell_util_c = | | * static char *rcsid_spell_util_c = |
* "$Id: spell_util.c,v 1.24 2000/10/31 22:11:46 peterm Exp $"; | | * "$Id: spell_util.c,v 1.25 2000/11/06 23:06:47 jec Exp $"; |
*/ | | */ |
| | |
/* | | /* |
| | |
if ( ! QUERY_FLAG (tmp, FLAG_FLYING)) | | if ( ! QUERY_FLAG (tmp, FLAG_FLYING)) |
LOG (llevDebug, "cast_cone(): arch %s doesn't have flying 1\n", | | LOG (llevDebug, "cast_cone(): arch %s doesn't have flying 1\n", |
spell_arch->name); | | spell_arch->name); |
if ( ! QUERY_FLAG (tmp, FLAG_WALK_ON) || ! QUERY_FLAG (tmp, FLAG_FLY_ON)) | | if (( ! QUERY_FLAG (tmp, FLAG_WALK_ON) || ! QUERY_FLAG (tmp, FLAG_FLY_ON)) |
| | && tmp->stats.dam) |
LOG (llevDebug, "cast_cone(): arch %s doesn't have walk_on 1 and " | | LOG (llevDebug, "cast_cone(): arch %s doesn't have walk_on 1 and " |
"fly_on 1\n", spell_arch->name); | | "fly_on 1\n", spell_arch->name); |
insert_ob_in_map(tmp,op->map,op); | | insert_ob_in_map(tmp,op->map,op); |
| | |
int i; | | int i; |
tag_t tag; | | tag_t tag; |
| | |
if (op->env) { | | |
/* handle flowers in icecubes */ | | |
op->speed = 0; | | |
update_ob_speed (op); | | |
return; | | |
} | | |
| | |
/* if no map then hit_map will crash so just ignore object */ | | /* if no map then hit_map will crash so just ignore object */ |
if (! op->map) { | | if (! op->map) { |
LOG(llevError,"Tried to move_cone object %s without a map.\n", | | LOG(llevError,"Tried to move_cone object %s without a map.\n", |
op->name ? op->name : "unknown"); | | op->name ? op->name : "unknown"); |
| | op->speed = 0; |
| | update_ob_speed (op); |
return; | | return; |
} | | } |
| | |
| | |
insert_ob_in_map(op,op->map,op); | | insert_ob_in_map(op,op->map,op); |
} | | } |
| | |
int explode_object(object *op) { | | void 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; | | tag_t op_tag = op->count; |
| | object *tmp; |
| | mapstruct *map; |
| | |
| | if (op->other_arch == NULL) { |
| | LOG (llevError, "BUG: explode_object(): op without other_arch\n"); |
| | remove_ob (op); |
| | free_object (op); |
| | return; |
} | | } |
| | |
| | if (op->env) { |
| | object *env; |
for(env=op;env->env!=NULL;env=env->env); | | for(env=op;env->env!=NULL;env=env->env); |
if (env->map == NULL) | | if (env->map == NULL || out_of_map (env->map, env->x, env->y)) { |
return 0; | | LOG (llevError, "BUG: explode_object(): env out of map\n"); |
if(op->other_arch==NULL) | | remove_ob (op); |
return 0; | | free_object (op); |
tmp=arch_to_object(op->other_arch); | | return; |
| | } |
| | remove_ob (op); |
| | op->x = env->x; |
| | op->y = env->y; |
| | insert_ob_in_map_simple (op, env->map); |
| | } else if (out_of_map (op->map, op->x, op->y)) { |
| | LOG (llevError, "BUG: explode_object(): op out of map\n"); |
| | remove_ob (op); |
| | free_object (op); |
| | return; |
| | } |
| | |
/* peterm: Hack added to make objects be able to both hit for damage and | | |
then explode. */ | | |
if(op->attacktype){ | | if(op->attacktype){ |
for(victim=get_map_ob(op->map,op->x,op->y);victim!=NULL;victim=victim->above) | | |
if(QUERY_FLAG(victim,FLAG_ALIVE)) | | |
break; | | |
hit_map(op,0,op->attacktype); | | hit_map(op,0,op->attacktype); |
| | if (was_destroyed (op, op_tag)) |
#if 0 | | return; |
/* Hit_map will also do a hit_player for us. Leaving this call in | | |
* effectively doubles the amount of damage the bullet is doing. | | |
*/ | | |
/* Should hit_map also be doing this? Why call hit_player | | |
* again? Also, make sure victim has not been killed - it | | |
* is possible that hit_map killed the object. | | |
*/ | | |
if(victim!=NULL && !QUERY_FLAG(victim,FLAG_FREED)) | | |
hit_player(victim,op->stats.dam,op,op->attacktype); | | |
#endif | | |
} | | } |
| | |
/* peterm: hack added to make fireballs and other explosions level | | /* peterm: hack added to make fireballs and other explosions level |
* dependent: | | * dependent: |
*/ | | */ |
| | |
/* op->stats.sp stores the spell which made this object here. */ | | /* op->stats.sp stores the spell which made this object here. */ |
| | tmp = arch_to_object (op->other_arch); |
tmp->stats.dam += SP_level_dam_adjust(op,op,op->stats.sp); | | tmp->stats.dam += SP_level_dam_adjust(op,op,op->stats.sp); |
if(op->attacktype&AT_MAGIC) | | if(op->attacktype&AT_MAGIC) |
tmp->attacktype|=AT_MAGIC; | | tmp->attacktype|=AT_MAGIC; |
| | |
if(op->stats.hp) | | if(op->stats.hp) |
tmp->stats.hp=op->stats.hp; | | tmp->stats.hp=op->stats.hp; |
tmp->stats.maxhp=op->count; /* Unique ID */ | | tmp->stats.maxhp=op->count; /* Unique ID */ |
tmp->x=env->x,tmp->y=env->y; | | tmp->x = op->x; |
| | tmp->y = op->y; |
| | |
#ifdef MULTIPLE_GODS /* needed for AT_HOLYWORD stuff -b.t. */ | | #ifdef MULTIPLE_GODS /* needed for AT_HOLYWORD stuff -b.t. */ |
if(tmp->attacktype&AT_HOLYWORD||tmp->attacktype&AT_GODPOWER) | | if(tmp->attacktype&AT_HOLYWORD||tmp->attacktype&AT_GODPOWER) |
if(!tailor_god_spell(tmp,op)) return 0; | | if ( ! tailor_god_spell (tmp, op)) { |
| | remove_ob (op); |
| | free_object (op); |
| | return; |
| | } |
#endif | | #endif |
| | |
if (wall(env->map,env->x,env->y)) | | /* Prevent recursion */ |
tmp->x-=DIRX(env),tmp->y-=DIRY(env); | | CLEAR_FLAG (op, FLAG_WALK_ON); |
if (out_of_map(env->map, env->x, env->y)) | | CLEAR_FLAG (op, FLAG_FLY_ON); |
free_object(tmp); | | |
else | | insert_ob_in_map (tmp, op->map, op); |
insert_ob_in_map(tmp,env->map,op); | | if ( ! was_destroyed (op, op_tag)) { |
| | remove_ob (op); |
free_object(op); | | free_object(op); |
return 1; | | } |
} | | } |
| | |
void check_fired_arch(object *op) { | | void check_fired_arch (object *op) |
if(blocked(op->map,op->x,op->y)) { | | { |
| | tag_t op_tag = op->count, tmp_tag; |
object *tmp; | | object *tmp; |
remove_ob(op); | | int dam; |
if(out_of_map(op->map,op->x,op->y)) { | | |
free_object(op); | | if ( ! blocked (op->map, op->x, op->y)) |
return; | | return; |
} | | |
if(explode_object(op)) | | if (op->other_arch) { |
| | explode_object (op); |
return; | | return; |
| | } |
| | |
for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above) | | for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above) |
if(QUERY_FLAG(tmp, FLAG_ALIVE)) | | { |
break; | | if (QUERY_FLAG (tmp, FLAG_ALIVE)) { |
if(tmp!=NULL) | | tmp_tag = tmp->count; |
op->stats.dam-=hit_player(tmp,op->stats.dam,op,op->attacktype); | | dam = hit_player (tmp, op->stats.dam, op, op->attacktype); |
if(blocked(op->map,op->x,op->y)) { | | if (was_destroyed (op, op_tag) || ! was_destroyed (tmp, tmp_tag) |
| | || (op->stats.dam -= dam) < 0) |
| | { |
| | remove_ob (op); |
free_object(op); | | free_object(op); |
return; | | return; |
} | | } |
insert_ob_in_map(op,op->map,op); | | } |
} | | } |
} | | } |
| | |
void move_fired_arch(object *op) { | | void move_fired_arch (object *op) |
remove_ob(op); | | { |
| | tag_t op_tag = op->count; |
| | int new_x, new_y; |
| | |
/* peterm: added to make comet leave a trail of burnouts | | /* 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. */ |
| | |
| | |
tmp1->x = op->x; tmp1->y = op->y; | | tmp1->x = op->x; tmp1->y = op->y; |
insert_ob_in_map(tmp1,op->map,op); | | insert_ob_in_map(tmp1,op->map,op); |
| | if (was_destroyed (op, op_tag)) |
| | return; |
} /* end addition. */ | | } /* end addition. */ |
| | |
op->x+=DIRX(op),op->y+=DIRY(op); | | new_x = op->x + DIRX(op); |
if(!op->direction||wall(op->map,op->x,op->y)) { | | new_y = op->y + DIRY(op); |
if(explode_object(op)) | | if (out_of_map (op->map, new_x, new_y)) { |
return; | | remove_ob (op); |
free_object(op); | | free_object(op); |
return; | | return; |
} | | } |
| | |
if(reflwall(op->map,op->x,op->y)) { | | if ( ! op->direction || wall (op->map, new_x, new_y)) { |
op->direction=absdir(op->direction+4); | | if (op->other_arch) { |
if ((op = insert_ob_in_map(op,op->map,op)) != NULL) | | explode_object (op); |
update_turn_face(op); | | } else { |
return; | | remove_ob (op); |
} | | |
if(blocked(op->map,op->x,op->y)) { | | |
object *tmp; | | |
| | |
if(out_of_map(op->map,op->x,op->y)) { | | |
free_object(op); | | free_object(op); |
return; | | |
} | | } |
| | |
if(explode_object(op)) | | |
return; | | |
| | |
for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above) | | |
if(QUERY_FLAG(tmp, FLAG_ALIVE)) | | |
break; | | |
| | |
if(tmp!=NULL) { | | |
/* Certain items, like speedballs, have attacktype ghosthit. | | |
* hit_player wants to remove the object after it hits the player. | | |
* Since it is already removed, just don't make it ghosthit, and | | |
* remove it here | | |
*/ | | |
| | |
if (op->attacktype & AT_GHOSTHIT) { | | |
hit_player(tmp,op->stats.dam,op,(op->attacktype & ~AT_GHOSTHIT)); | | |
free_object(op); | | |
return; | | return; |
} | | } |
else | | |
op->stats.dam-=hit_player(tmp,op->stats.dam,op,op->attacktype); | | remove_ob (op); |
} | | op->x = new_x; |
/* I guess this can be applicable if the object blocking the | | op->y = new_y; |
* space was destroyed? | | if ((op = insert_ob_in_map (op, op->map, op)) == NULL) |
*/ | | |
if(blocked(op->map,op->x,op->y)) { | | |
free_object(op); | | |
return; | | return; |
| | if (reflwall (op->map, op->x, op->y)) { |
| | op->direction = absdir (op->direction + 4); |
| | update_turn_face (op); |
| | } else { |
| | check_fired_arch (op); |
} | | } |
} /* if space is blocked */ | | |
insert_ob_in_map(op,op->map,op); | | |
} | | } |
| | |
| | |