… | |
… | |
403 | int last = op->value; |
403 | int last = op->value; |
404 | int detected; |
404 | int detected; |
405 | |
405 | |
406 | detected = 0; |
406 | detected = 0; |
407 | |
407 | |
408 | for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp && !detected; tmp = tmp->above) |
408 | for (tmp = op->ms ().bot; tmp && !detected; tmp = tmp->above) |
409 | { |
409 | { |
410 | object *tmp2; |
410 | object *tmp2; |
411 | |
411 | |
412 | if (op->stats.hp) |
412 | if (op->stats.hp) |
413 | { |
413 | { |
… | |
… | |
455 | op->value = 1; |
455 | op->value = 1; |
456 | push_button (op); |
456 | push_button (op); |
457 | } |
457 | } |
458 | } |
458 | } |
459 | } |
459 | } |
460 | |
|
|
461 | |
460 | |
462 | void |
461 | void |
463 | animate_trigger (object *op) |
462 | animate_trigger (object *op) |
464 | { |
463 | { |
465 | if ((unsigned char) ++op->stats.wc >= NUM_ANIMATIONS (op)) |
464 | if ((unsigned char) ++op->stats.wc >= NUM_ANIMATIONS (op)) |
… | |
… | |
497 | |
496 | |
498 | SET_ANIMATION (op, op->stats.wc); |
497 | SET_ANIMATION (op, op->stats.wc); |
499 | update_object (op, UP_OBJ_FACE); |
498 | update_object (op, UP_OBJ_FACE); |
500 | return; |
499 | return; |
501 | } |
500 | } |
|
|
501 | |
502 | /* We're closing */ |
502 | /* We're closing */ |
503 | op->move_on = 0; |
503 | op->move_on = 0; |
504 | |
504 | |
505 | op->stats.wc++; |
505 | op->stats.wc++; |
506 | if ((int) op->stats.wc >= NUM_ANIMATIONS (op)) |
506 | if ((int) op->stats.wc >= NUM_ANIMATIONS (op)) |
… | |
… | |
647 | /* Move an arrow along its course. op is the arrow or thrown object. |
647 | /* Move an arrow along its course. op is the arrow or thrown object. |
648 | */ |
648 | */ |
649 | void |
649 | void |
650 | move_arrow (object *op) |
650 | move_arrow (object *op) |
651 | { |
651 | { |
652 | object *tmp; |
|
|
653 | sint16 new_x, new_y; |
|
|
654 | int was_reflected, mflags; |
652 | int was_reflected; |
655 | maptile *m; |
|
|
656 | |
653 | |
657 | if (op->map == NULL) |
654 | if (!op->map) |
658 | { |
655 | { |
659 | LOG (llevError, "BUG: Arrow had no map.\n"); |
656 | LOG (llevError, "BUG: Arrow had no map.\n"); |
660 | op->destroy (); |
657 | op->destroy (); |
661 | return; |
658 | return; |
662 | } |
659 | } |
… | |
… | |
692 | stop_arrow (op); |
689 | stop_arrow (op); |
693 | return; |
690 | return; |
694 | } |
691 | } |
695 | |
692 | |
696 | /* Calculate target map square */ |
693 | /* Calculate target map square */ |
697 | new_x = op->x + DIRX (op); |
|
|
698 | new_y = op->y + DIRY (op); |
|
|
699 | was_reflected = 0; |
694 | was_reflected = 0; |
700 | |
695 | |
701 | m = op->map; |
696 | mapxy pos (op); pos.move (op->direction); |
702 | mflags = get_map_flags (m, &m, new_x, new_y, &new_x, &new_y); |
|
|
703 | |
697 | |
704 | if (mflags & P_OUT_OF_MAP) |
698 | if (!pos.normalise ()) |
705 | { |
699 | { |
706 | stop_arrow (op); |
700 | stop_arrow (op); |
707 | return; |
701 | return; |
708 | } |
702 | } |
709 | |
703 | |
710 | /* only need to look for living creatures if this flag is set */ |
704 | /* only need to look for living creatures if this flag is set */ |
711 | if (mflags & P_IS_ALIVE) |
705 | if (pos->flags () & P_IS_ALIVE) |
712 | { |
706 | { |
713 | for (tmp = GET_MAP_OB (m, new_x, new_y); tmp != NULL; tmp = tmp->above) |
707 | object *tmp; |
|
|
708 | |
|
|
709 | for (tmp = pos->bot; tmp; tmp = tmp->above) |
714 | if (QUERY_FLAG (tmp, FLAG_ALIVE)) |
710 | if (QUERY_FLAG (tmp, FLAG_ALIVE)) |
715 | break; |
711 | break; |
716 | |
712 | |
717 | /* Not really fair, but don't let monsters hit themselves with |
713 | /* Not really fair, but don't let monsters hit themselves with |
718 | * their own arrow - this can be because they fire it then |
714 | * their own arrow - this can be because they fire it then |
… | |
… | |
741 | return; |
737 | return; |
742 | } |
738 | } |
743 | } /* if this is not hitting its owner */ |
739 | } /* if this is not hitting its owner */ |
744 | } /* if there is something alive on this space */ |
740 | } /* if there is something alive on this space */ |
745 | |
741 | |
746 | if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, new_x, new_y))) |
742 | if (OB_TYPE_MOVE_BLOCK (op, pos->move_block)) |
747 | { |
743 | { |
748 | int retry = 0; |
744 | int retry = 0; |
749 | |
745 | |
750 | /* if the object doesn't reflect, stop the arrow from moving |
746 | /* if the object doesn't reflect, stop the arrow from moving |
751 | * note that this code will now catch cases where a monster is |
747 | * note that this code will now catch cases where a monster is |
… | |
… | |
764 | if (op->direction & 1) |
760 | if (op->direction & 1) |
765 | { |
761 | { |
766 | op->direction = absdir (op->direction + 4); |
762 | op->direction = absdir (op->direction + 4); |
767 | retry = 1; |
763 | retry = 1; |
768 | } |
764 | } |
|
|
765 | |
769 | /* There were two blocks with identical code - |
766 | /* There were two blocks with identical code - |
770 | * use this retry here to make this one block |
767 | * use this retry here to make this one block |
771 | * that did the same thing. |
768 | * that did the same thing. |
772 | */ |
769 | */ |
773 | while (retry < 2) |
770 | while (retry < 2) |
774 | { |
771 | { |
775 | int left, right, mflags; |
|
|
776 | maptile *m1; |
|
|
777 | sint16 x1, y1; |
|
|
778 | |
|
|
779 | retry++; |
772 | retry++; |
780 | |
773 | |
781 | /* Need to check for P_OUT_OF_MAP: if the arrow is tavelling |
774 | /* Need to check for P_OUT_OF_MAP: if the arrow is travelling |
782 | * over a corner in a tiled map, it is possible that |
775 | * over a corner in a tiled map, it is possible that |
783 | * op->direction is within an adjacent map but either |
776 | * op->direction is within an adjacent map but either |
784 | * op->direction-1 or op->direction+1 does not exist. |
777 | * op->direction-1 or op->direction+1 does not exist. |
785 | */ |
778 | */ |
786 | mflags = get_map_flags (op->map, &m1, op->x + freearr_x[absdir (op->direction - 1)], |
779 | mapxy pos1 (pos); pos1.move (absdir (op->direction - 1)); |
787 | op->y + freearr_y[absdir (op->direction - 1)], &x1, &y1); |
780 | bool left = pos1.normalise () && OB_TYPE_MOVE_BLOCK (op, pos1->move_block); |
788 | left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, (GET_MAP_MOVE_BLOCK (m1, x1, y1))); |
|
|
789 | |
781 | |
790 | mflags = get_map_flags (op->map, &m1, op->x + freearr_x[absdir (op->direction + 1)], |
782 | mapxy pos2 (pos); pos2.move (absdir (op->direction + 1)); |
791 | op->y + freearr_y[absdir (op->direction + 1)], &x1, &y1); |
783 | bool right = pos2.normalise () && OB_TYPE_MOVE_BLOCK (op, pos2->move_block); |
792 | right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, (GET_MAP_MOVE_BLOCK (m1, x1, y1))); |
|
|
793 | |
784 | |
794 | if (left == right) |
785 | if (left == right) |
795 | op->direction = absdir (op->direction + 4); |
786 | op->direction = absdir (op->direction + 4); |
796 | else if (left) |
787 | else if (left) |
797 | op->direction = absdir (op->direction + 2); |
788 | op->direction = absdir (op->direction + 2); |
798 | else if (right) |
789 | else if (right) |
799 | op->direction = absdir (op->direction - 2); |
790 | op->direction = absdir (op->direction - 2); |
800 | |
791 | |
801 | mflags = get_map_flags (op->map, &m1, op->x + DIRX (op), op->y + DIRY (op), &x1, &y1); |
|
|
802 | |
|
|
803 | /* If this space is not out of the map and not blocked, valid space - |
792 | /* If this space is not out of the map and not blocked, valid space - |
804 | * don't need to retry again. |
793 | * don't need to retry again. |
805 | */ |
794 | */ |
806 | if (!(mflags & P_OUT_OF_MAP) && !OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m1, x1, y1))) |
795 | mapxy pos3 (pos); pos3.move (op->direction); |
|
|
796 | if (pos3.normalise () && !OB_TYPE_MOVE_BLOCK (op, pos3->move_block)) |
807 | break; |
797 | break; |
808 | |
|
|
809 | } |
798 | } |
|
|
799 | |
810 | /* Couldn't find a direction to move the arrow to - just |
800 | /* Couldn't find a direction to move the arrow to - just |
811 | * top it from moving. |
801 | * stop it from moving. |
812 | */ |
802 | */ |
813 | if (retry == 2) |
803 | if (retry == 2) |
814 | { |
804 | { |
815 | stop_arrow (op); |
805 | stop_arrow (op); |
816 | return; |
806 | return; |
817 | } |
807 | } |
|
|
808 | |
818 | /* update object image for new facing */ |
809 | /* update object image for new facing */ |
819 | /* many thrown objects *don't* have more than one face */ |
810 | /* many thrown objects *don't* have more than one face */ |
820 | if (GET_ANIM_ID (op)) |
811 | if (GET_ANIM_ID (op)) |
821 | SET_ANIMATION (op, op->direction); |
812 | SET_ANIMATION (op, op->direction); |
822 | } /* object is reflected */ |
813 | } /* object is reflected */ |
823 | } /* object ran into a wall */ |
814 | } /* object ran into a wall */ |
824 | |
815 | |
825 | /* Move the arrow. */ |
|
|
826 | op->remove (); |
|
|
827 | op->x = new_x; |
|
|
828 | op->y = new_y; |
|
|
829 | |
|
|
830 | /* decrease the speed as it flies. 0.05 means a standard bow will shoot |
816 | /* decrease the speed as it flies. 0.05 means a standard bow will shoot |
831 | * about 17 squares. Tune as needed. |
817 | * about 17 squares. Tune as needed. |
832 | */ |
818 | */ |
833 | op->speed -= 0.05; |
819 | op->speed -= 0.05; |
834 | insert_ob_in_map (op, m, op, 0); |
820 | |
|
|
821 | /* Move the arrow. */ |
|
|
822 | op->move_to (pos); |
835 | } |
823 | } |
836 | |
824 | |
837 | /* This routine doesnt seem to work for "inanimate" objects that |
825 | /* This routine doesnt seem to work for "inanimate" objects that |
838 | * are being carried, ie a held torch leaps from your hands!. |
826 | * are being carried, ie a held torch leaps from your hands!. |
839 | * Modified this routine to allow held objects. b.t. */ |
827 | * Modified this routine to allow held objects. b.t. */ |
840 | |
|
|
841 | void |
828 | void |
842 | change_object (object *op) |
829 | change_object (object *op) |
843 | { /* Doesn`t handle linked objs yet */ |
830 | { /* Doesn`t handle linked objs yet */ |
844 | int i, j; |
831 | int i, j; |
845 | |
832 | |