| 833 | } |
| 834 | |
| 835 | staticfn void |
| 836 | dosinkfall(void) |
| 837 | { |
| 838 | static const char fell_on_sink[] = "fell onto a sink"; |
| 839 | struct obj *obj; |
| 840 | int dmg; |
| 841 | boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS), |
| 842 | innate_lev = ((HLevitation & (FROMOUTSIDE | FROMFORM)) != 0L), |
| 843 | /* to handle being chained to buried iron ball, trying to |
| 844 | levitate but being blocked, then moving onto adjacent sink; |
| 845 | no need to worry about being blocked by terrain because we |
| 846 | couldn't be over a sink at the same time */ |
| 847 | blockd_lev = (BLevitation == I_SPECIAL), |
| 848 | ufall = (!innate_lev && !blockd_lev |
| 849 | && !(HFlying || EFlying)); /* BFlying */ |
| 850 | |
| 851 | if (!ufall) { |
| 852 | You((innate_lev || blockd_lev) ? "wobble unsteadily for a moment." |
| 853 | : "gain control of your flight."); |
| 854 | } else { |
| 855 | long save_ELev = ELevitation, save_HLev = HLevitation; |
| 856 | |
| 857 | /* fake removal of levitation in advance so that final |
| 858 | disclosure will be right in case this turns out to |
| 859 | be fatal; fortunately the fact that rings and boots |
| 860 | are really still worn has no effect on bones data */ |
| 861 | ELevitation = HLevitation = 0L; |
| 862 | You("crash to the floor!"); |
| 863 | dmg = rn1(8, 25 - (int) ACURR(A_CON)); |
| 864 | losehp(Maybe_Half_Phys(dmg), fell_on_sink, NO_KILLER_PREFIX); |
| 865 | exercise(A_DEX, FALSE); |
| 866 | selftouch("Falling, you"); |
| 867 | for (obj = svl.level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) |
| 868 | if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) { |
| 869 | You("fell on %s.", doname(obj)); |
| 870 | losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink, |
| 871 | NO_KILLER_PREFIX); |
| 872 | exercise(A_CON, FALSE); |
| 873 | } |
| 874 | ELevitation = save_ELev; |
| 875 | HLevitation = save_HLev; |
| 876 | } |
| 877 | |
| 878 | /* |
| 879 | * Interrupt multi-turn putting on/taking off of armor (in which |
| 880 | * case we reached the sink due to being teleported while busy; |
| 881 | * in 3.4.3, Boots_on()/Boots_off() [called via (*afternmv)() when |
| 882 | * 'multi' reaches 0] triggered a crash if we were donning/doffing |
| 883 | * levitation boots [because the Boots_off() below causes 'uarmf' |
| 884 | * to be null by the time 'afternmv' gets called]). |
| 885 | * |
| 886 | * Interrupt donning/doffing if we fall onto the sink, or if the |
| 887 | * code below is going to remove levitation boots even when we |
| 888 | * haven't fallen (innate floating or flying becoming unblocked). |
| 889 | */ |
| 890 | if (ufall || lev_boots) { |
| 891 | (void) stop_donning(lev_boots ? uarmf : (struct obj *) 0); |
| 892 | /* recalculate in case uarmf just got set to null */ |
no test coverage detected