version 1.21 | | version 1.22 |
---|
| | |
/* | | /* |
* static char *rcsid_apply_c = | | * static char *rcsid_apply_c = |
* "$Id: apply.c,v 1.21 2000/10/30 22:09:59 jec Exp $"; | | * "$Id: apply.c,v 1.22 2000/11/06 23:06:47 jec Exp $"; |
*/ | | */ |
/* | | /* |
CrossFire, A Multiplayer game for X-windows | | CrossFire, A Multiplayer game for X-windows |
| | |
*/ | | */ |
void move_apply (object *trap, object *victim, object *originator) | | void move_apply (object *trap, object *victim, object *originator) |
{ | | { |
| | static int recursion_depth = 0; |
| | |
| | /* move_apply() is the most likely candidate for causing unwanted and |
| | * possibly unlimited recursion. */ |
| | if (recursion_depth >= 5) { |
| | LOG (llevError, "WARNING: move_apply(): aborting recursion " |
| | "[trap arch %s, name %s; victim arch %s, name %s]\n", |
| | trap->arch->name, trap->name, victim->arch->name, victim->name); |
| | return; |
| | } |
| | recursion_depth++; |
| | |
switch (trap->type) | | switch (trap->type) |
{ | | { |
case PLAYERMOVER: | | case PLAYERMOVER: |
| | |
if (victim->speed_left<-50.0) victim->speed_left=-50.0; | | if (victim->speed_left<-50.0) victim->speed_left=-50.0; |
/* fprintf(stderr,"apply, playermove, player speed_left=%f\n", victim->speed_left);*/ | | /* fprintf(stderr,"apply, playermove, player speed_left=%f\n", victim->speed_left);*/ |
} | | } |
return; | | goto leave; |
| | |
case SPINNER: | | case SPINNER: |
if(victim->direction) { | | if(victim->direction) { |
victim->direction=absdir(victim->direction-trap->stats.sp); | | victim->direction=absdir(victim->direction-trap->stats.sp); |
update_turn_face(victim); | | update_turn_face(victim); |
} | | } |
return; | | goto leave; |
| | |
case DIRECTOR: | | case DIRECTOR: |
if(victim->direction) { | | if(victim->direction) { |
victim->direction=trap->stats.sp; | | victim->direction=trap->stats.sp; |
update_turn_face(victim); | | update_turn_face(victim); |
} | | } |
return; | | goto leave; |
| | |
case BUTTON: | | case BUTTON: |
case PEDESTAL: | | case PEDESTAL: |
update_button(trap); | | update_button(trap); |
return; | | goto leave; |
| | |
case ALTAR: | | case ALTAR: |
/* sacrifice victim on trap */ | | /* sacrifice victim on trap */ |
apply_altar (trap, victim, originator); | | apply_altar (trap, victim, originator); |
return; | | goto leave; |
| | |
case MMISSILE: | | case MMISSILE: |
if (QUERY_FLAG (victim, FLAG_ALIVE)) { | | if (QUERY_FLAG (victim, FLAG_ALIVE)) { |
| | |
free_object (trap); | | free_object (trap); |
} | | } |
} | | } |
return; | | goto leave; |
| | |
case THROWN_OBJ: | | case THROWN_OBJ: |
| | if (trap->inv == NULL) |
| | goto leave; |
| | /* fallthrough */ |
case ARROW: | | case ARROW: |
if(QUERY_FLAG(victim, FLAG_ALIVE)&&trap->speed) { | | if (QUERY_FLAG (victim, FLAG_ALIVE) && trap->speed) |
tag_t trap_tag = trap->count; | | hit_with_arrow (trap, victim); |
if(attack_ob(victim,trap)) { | | goto leave; |
/* There can be cases where a monster 'kills' an arrow. Typically | | |
* happens for things like black puddings that have hitback properties. | | |
*/ | | |
if ( ! was_destroyed (trap, trap_tag)) { | | |
remove_ob(trap); | | |
stop_arrow(trap,victim); | | |
} | | |
} | | |
} | | |
return; | | |
| | |
case CANCELLATION: | | case CANCELLATION: |
case BALL_LIGHTNING: | | case BALL_LIGHTNING: |
if (QUERY_FLAG (victim, FLAG_ALIVE)) | | if (QUERY_FLAG (victim, FLAG_ALIVE)) |
hit_player (victim, trap->stats.dam, trap, trap->attacktype); | | hit_player (victim, trap->stats.dam, trap, trap->attacktype); |
else if (victim->material) | | else if (victim->material) |
save_throw_object (victim, trap->attacktype); | | save_throw_object (victim, trap->attacktype, trap); |
return; | | goto leave; |
| | |
case CONE: | | case CONE: |
if(QUERY_FLAG(victim, FLAG_ALIVE)&&trap->speed) { | | if(QUERY_FLAG(victim, FLAG_ALIVE)&&trap->speed) { |
| | |
if (attacktype) | | if (attacktype) |
hit_player(victim,trap->stats.dam,trap,attacktype); | | hit_player(victim,trap->stats.dam,trap,attacktype); |
} | | } |
return; | | goto leave; |
| | |
case FBULLET: | | case FBULLET: |
case BULLET: | | case BULLET: |
| | if (QUERY_FLAG (victim, FLAG_NO_PASS) |
| | || QUERY_FLAG (victim, FLAG_ALIVE)) |
check_fired_arch(trap); | | check_fired_arch(trap); |
return; | | goto leave; |
| | |
case TRAPDOOR: | | case TRAPDOOR: |
{ | | { |
| | |
if(!QUERY_FLAG(ab,FLAG_FLYING)) | | if(!QUERY_FLAG(ab,FLAG_FLYING)) |
tot += (ab->nrof ? ab->nrof : 1) * ab->weight + ab->carrying; | | tot += (ab->nrof ? ab->nrof : 1) * ab->weight + ab->carrying; |
if(!(trap->value=(tot>trap->weight)?1:0)) | | if(!(trap->value=(tot>trap->weight)?1:0)) |
return; | | goto leave; |
SET_ANIMATION(trap, trap->value); | | SET_ANIMATION(trap, trap->value); |
update_object(trap); | | update_object(trap); |
} | | } |
| | |
new_draw_info(NDI_UNIQUE, 0,ab,"You fall into a trapdoor!"); | | new_draw_info(NDI_UNIQUE, 0,ab,"You fall into a trapdoor!"); |
transfer_ob(ab,(int)EXIT_X(trap),(int)EXIT_Y(trap),0,ab); | | transfer_ob(ab,(int)EXIT_X(trap),(int)EXIT_Y(trap),0,ab); |
} | | } |
return; | | goto leave; |
} | | } |
| | |
case CONVERTER: | | case CONVERTER: |
convert_item (victim, trap); | | convert_item (victim, trap); |
return; | | goto leave; |
| | |
case TRIGGER_BUTTON: | | case TRIGGER_BUTTON: |
case TRIGGER_PEDESTAL: | | case TRIGGER_PEDESTAL: |
case TRIGGER_ALTAR: | | case TRIGGER_ALTAR: |
check_trigger (trap, victim); | | check_trigger (trap, victim); |
return; | | goto leave; |
| | |
case DEEP_SWAMP: | | case DEEP_SWAMP: |
walk_on_deep_swamp (trap, victim); | | walk_on_deep_swamp (trap, victim); |
return; | | goto leave; |
| | |
case CHECK_INV: | | case CHECK_INV: |
check_inv (victim, trap); | | check_inv (victim, trap); |
return; | | goto leave; |
| | |
case HOLE: | | case HOLE: |
/* Hole not open? */ | | /* Hole not open? */ |
if(trap->stats.wc > 0) | | if(trap->stats.wc > 0) |
return; | | goto leave; |
/* Is this a multipart monster and not the head? If so, return. | | /* Is this a multipart monster and not the head? If so, return. |
* Processing will happen if the head runs into the pit | | * Processing will happen if the head runs into the pit |
*/ | | */ |
if (victim->head) | | if (victim->head) |
return; | | goto leave; |
play_sound_map (victim->map, victim->x, victim->y, SOUND_FALL_HOLE); | | play_sound_map (victim->map, victim->x, victim->y, SOUND_FALL_HOLE); |
new_draw_info (NDI_UNIQUE, 0, victim, "You fall through the hole!\n"); | | new_draw_info (NDI_UNIQUE, 0, victim, "You fall through the hole!\n"); |
transfer_ob (victim, EXIT_X (trap), EXIT_Y (trap), 1, victim); | | transfer_ob (victim, EXIT_X (trap), EXIT_Y (trap), 1, victim); |
return; | | goto leave; |
| | |
case EXIT: | | case EXIT: |
if (victim->type == PLAYER && EXIT_PATH (trap)) { | | if (victim->type == PLAYER && EXIT_PATH (trap)) { |
| | |
new_draw_info (NDI_NAVY, 0, victim, trap->msg); | | new_draw_info (NDI_NAVY, 0, victim, trap->msg); |
enter_exit (victim, trap); | | enter_exit (victim, trap); |
} | | } |
return; | | goto leave; |
| | |
case ENCOUNTER: | | case ENCOUNTER: |
#ifdef RANDOM_ENCOUNTERS | | #ifdef RANDOM_ENCOUNTERS |
if (victim->type == PLAYER && QUERY_FLAG (trap, FLAG_IS_FLOOR)) | | if (victim->type == PLAYER && QUERY_FLAG (trap, FLAG_IS_FLOOR)) |
random_encounter (victim, trap); | | random_encounter (victim, trap); |
#endif | | #endif |
return; | | goto leave; |
| | |
case SHOP_MAT: | | case SHOP_MAT: |
apply_shop_mat (trap, victim); | | apply_shop_mat (trap, victim); |
return; | | goto leave; |
| | |
/* Drop a certain amount of gold, and have one item identified */ | | /* Drop a certain amount of gold, and have one item identified */ |
case IDENTIFY_ALTAR: | | case IDENTIFY_ALTAR: |
apply_id_altar (victim, trap, originator); | | apply_id_altar (victim, trap, originator); |
return; | | goto leave; |
| | |
case SIGN: | | case SIGN: |
apply_sign (victim, trap); | | apply_sign (victim, trap); |
return; | | goto leave; |
| | |
case CONTAINER: | | case CONTAINER: |
if (victim->type==PLAYER) | | if (victim->type==PLAYER) |
(void) esrv_apply_container (victim, trap); | | (void) esrv_apply_container (victim, trap); |
else | | else |
(void) apply_container (victim, trap); | | (void) apply_container (victim, trap); |
return; | | goto leave; |
| | |
case RUNE: | | case RUNE: |
if (trap->level && QUERY_FLAG (victim, FLAG_ALIVE)) | | if (trap->level && QUERY_FLAG (victim, FLAG_ALIVE)) |
spring_trap (trap, victim); | | spring_trap (trap, victim); |
return; | | goto leave; |
| | |
default: | | default: |
LOG (llevDebug, "name %s, arch %s, type %d with fly/walk on/off not " | | LOG (llevDebug, "name %s, arch %s, type %d with fly/walk on/off not " |
"handled in move_apply()\n", trap->name, trap->arch->name, | | "handled in move_apply()\n", trap->name, trap->arch->name, |
trap->type); | | trap->type); |
return; | | goto leave; |
} | | } |
| | |
| | leave: |
| | recursion_depth--; |
} | | } |
| | |
| | |
| | |
*/ | | */ |
strcpy(item_name, item->name); | | strcpy(item_name, item->name); |
| | |
save_throw_object(item,AT_FIRE); | | save_throw_object(item,AT_FIRE,who); |
/* Change to check count and not freed, since the object pointer | | /* Change to check count and not freed, since the object pointer |
* may have gotten recycled | | * may have gotten recycled |
*/ | | */ |