| 1000 | } |
| 1001 | |
| 1002 | staticfn void |
| 1003 | cast_chain_lightning(void) |
| 1004 | { |
| 1005 | struct chain_lightning_queue clq = { |
| 1006 | {{0}}, 0, 0, Hallucination ? rn2_on_display_rng(6) : (AD_ELEC - 1) |
| 1007 | }; |
| 1008 | |
| 1009 | if (u.uswallow) { |
| 1010 | // TODO: damage the engulfer |
| 1011 | return; |
| 1012 | } |
| 1013 | |
| 1014 | /* set the type of beam we're using; the direction here is arbitrary |
| 1015 | because we change the beam direction just before drawing the beam |
| 1016 | anyway */ |
| 1017 | tmp_at(DISP_BEAM, zapdir_to_glyph(0, 1, clq.displayed_beam)); |
| 1018 | |
| 1019 | /* start by propagating in all directions from the caster */ |
| 1020 | for (int dir = 0; dir < N_DIRS; dir++) { |
| 1021 | struct chain_lightning_zap zap = { dir, u.ux, u.uy, 2 }; |
| 1022 | |
| 1023 | propagate_chain_lightning(&clq, zap); |
| 1024 | } |
| 1025 | nh_delay_output(); |
| 1026 | |
| 1027 | while (clq.head < clq.tail) { |
| 1028 | int delay_tail = clq.tail; |
| 1029 | |
| 1030 | while (clq.head < delay_tail) { |
| 1031 | struct chain_lightning_zap zap = clq.q[clq.head++]; |
| 1032 | /* damage any monster that was hit */ |
| 1033 | struct monst *mon = m_at(zap.x, zap.y); |
| 1034 | |
| 1035 | if (mon) { |
| 1036 | struct obj *unused = 0; /* AD_ELEC can't destroy armor */ |
| 1037 | int dmg; |
| 1038 | |
| 1039 | gn.notonhead = (mon->mx != gb.bhitpos.x |
| 1040 | || mon->my != gb.bhitpos.y); |
| 1041 | dmg = zhitm(mon, BZ_U_SPELL(AD_ELEC - 1), 2, &unused); |
| 1042 | |
| 1043 | if (dmg) { |
| 1044 | /* mon has been damaged, but we haven't yet printed the |
| 1045 | messages or given kill credit; assume the hero can |
| 1046 | sense their spell hitting monsters, because they can |
| 1047 | steer it away from peacefuls */ |
| 1048 | if (DEADMONSTER(mon)) { |
| 1049 | xkilled(mon, XKILL_GIVEMSG); |
| 1050 | } else { |
| 1051 | pline("You shock %s%s", mon_nam(mon), exclam(dmg)); |
| 1052 | /* if a long worm, only map 'I' for its head */ |
| 1053 | if (!canseemon(mon) && !gn.notonhead) |
| 1054 | /* FIXME: this doesn't work, possibly because |
| 1055 | cleaning up tmp_at() restores old glyph? */ |
| 1056 | map_invisible(zap.x, zap.y); |
| 1057 | } |
| 1058 | } else if (canseemon(mon)) { |
| 1059 | pline("%s resists.", Monnam(mon)); |
no test coverage detected