1 /**
2 * @file
3 * @brief Functions for handling multi-turn actions.
4 **/
5
6 #include "AppHdr.h"
7
8 #include "delay.h"
9
10 #include <cstdio>
11 #include <cstring>
12
13 #include "ability.h"
14 #include "areas.h"
15 #include "artefact.h"
16 #include "bloodspatter.h"
17 #include "clua.h"
18 #include "command.h"
19 #include "coord.h"
20 #include "corpse.h"
21 #include "database.h"
22 #include "describe.h"
23 #include "directn.h"
24 #include "dungeon.h"
25 #include "english.h"
26 #include "env.h"
27 #include "fineff.h"
28 #include "fprop.h"
29 #include "god-companions.h"
30 #include "god-passive.h"
31 #include "god-wrath.h"
32 #include "hints.h"
33 #include "invent.h"
34 #include "item-prop.h"
35 #include "items.h"
36 #include "item-use.h"
37 #include "item-status-flag-type.h"
38 #include "libutil.h"
39 #include "macro.h"
40 #include "message.h"
41 #include "mon-act.h"
42 #include "mon-behv.h"
43 #include "mon-gear.h"
44 #include "mon-tentacle.h"
45 #include "mon-util.h"
46 #include "mutation.h"
47 #include "nearby-danger.h"
48 #include "notes.h"
49 #include "options.h"
50 #include "ouch.h"
51 #include "output.h"
52 #include "player-equip.h"
53 #include "player.h"
54 #include "prompt.h"
55 #include "random.h"
56 #include "religion.h"
57 #include "shout.h"
58 #include "sound.h"
59 #include "spl-selfench.h"
60 #include "spl-util.h"
61 #include "stairs.h"
62 #include "state.h"
63 #include "stringutil.h"
64 #include "teleport.h"
65 #include "terrain.h"
66 #include "timed-effects.h"
67 #include "transform.h"
68 #include "traps.h"
69 #include "travel.h"
70 #include "xom.h"
71
72 int interrupt_block::interrupts_blocked = 0;
73
74 static const char *_activity_interrupt_name(activity_interrupt ai);
75
_eq_category(const item_def & equip)76 static string _eq_category(const item_def &equip)
77 {
78 return equip.base_type == OBJ_JEWELLERY ? "amulet" : "armour";
79 }
80
push_delay(shared_ptr<Delay> delay)81 void push_delay(shared_ptr<Delay> delay)
82 {
83 if (delay->is_run())
84 clear_travel_trail();
85 for (auto i = you.delay_queue.begin(); i != you.delay_queue.end(); ++i)
86 {
87 if ((*i)->is_parent())
88 {
89 you.delay_queue.insert(i, delay);
90 you.redraw_evasion = true;
91 return;
92 }
93 }
94 you.delay_queue.push_back(delay);
95 you.redraw_evasion = true;
96 }
97
_pop_delay()98 static void _pop_delay()
99 {
100 if (!you.delay_queue.empty())
101 you.delay_queue.erase(you.delay_queue.begin());
102
103 you.redraw_evasion = true;
104 }
105
_clear_pending_delays(size_t after_index=1)106 static void _clear_pending_delays(size_t after_index = 1)
107 {
108 while (you.delay_queue.size() > after_index)
109 {
110 auto delay = you.delay_queue.back();
111
112 you.delay_queue.pop_back();
113
114 if (delay->is_run() && you.running)
115 // If you got here, you're already clearing the delays and there's
116 // no need to clear them again.
117 stop_running(false);
118 }
119 }
120
try_interrupt()121 bool MemoriseDelay::try_interrupt()
122 {
123 // Losing work here is okay... having to start from
124 // scratch is a reasonable behaviour. -- bwr
125 mpr("Your memorisation is interrupted.");
126 return true;
127 }
128
try_interrupt()129 bool MultidropDelay::try_interrupt()
130 {
131 // No work lost
132 if (!items.empty())
133 mpr("You stop dropping stuff.");
134 return true;
135 }
136
try_interrupt()137 bool BaseRunDelay::try_interrupt()
138 {
139 // Keep things consistent, otherwise disturbing phenomena can occur.
140 if (you.running)
141 stop_running(false);
142 update_turn_count();
143
144 // Always interruptible.
145 return true;
146 }
147
try_interrupt()148 bool MacroDelay::try_interrupt()
149 {
150 // Always interruptible.
151 return true;
152 // There's no special action needed for macros - if we don't call out
153 // to the Lua function, it can't do damage.
154 }
155
try_interrupt()156 bool EquipOnDelay::try_interrupt()
157 {
158 if (duration > 1 && !was_prompted)
159 {
160 if (!crawl_state.disables[DIS_CONFIRMATIONS]
161 && !yesno("Keep equipping yourself?", false, 0, false))
162 {
163 mprf("You stop putting on your %s.", _eq_category(equip).c_str());
164 return true;
165 }
166 else
167 was_prompted = true;
168 }
169 return false;
170 }
171
try_interrupt()172 bool EquipOffDelay::try_interrupt()
173 {
174 if (duration > 1 && !was_prompted)
175 {
176 if (!crawl_state.disables[DIS_CONFIRMATIONS]
177 && !yesno("Keep disrobing?", false, 0, false))
178 {
179 mprf("You stop removing your %s.", _eq_category(equip).c_str());
180 return true;
181 }
182 else
183 was_prompted = true;
184 }
185 return false;
186 }
187
try_interrupt()188 bool AscendingStairsDelay::try_interrupt()
189 {
190 mpr("You stop ascending the stairs.");
191 return true; // short... and probably what people want
192 }
193
try_interrupt()194 bool DescendingStairsDelay::try_interrupt()
195 {
196 mpr("You stop descending the stairs.");
197 return true; // short... and probably what people want
198 }
199
try_interrupt()200 bool PasswallDelay::try_interrupt()
201 {
202 mpr("Your meditation is interrupted.");
203 return true;
204 }
205
try_interrupt()206 bool ShaftSelfDelay::try_interrupt()
207 {
208 mpr("You stop digging.");
209 return true;
210 }
211
try_interrupt()212 bool ExsanguinateDelay::try_interrupt()
213 {
214 if (duration > 1 && !was_prompted)
215 {
216 if (!crawl_state.disables[DIS_CONFIRMATIONS]
217 && !yesno("Keep bloodletting?", false, 0, false))
218 {
219 mpr("You stop emptying yourself of blood.");
220 return true;
221 }
222 else
223 was_prompted = true;
224 }
225 return false;
226 }
227
try_interrupt()228 bool RevivifyDelay::try_interrupt()
229 {
230 if (duration > 1 && !was_prompted)
231 {
232 if (!crawl_state.disables[DIS_CONFIRMATIONS]
233 && !yesno("Continue your ritual?", false, 0, false))
234 {
235 mpr("You stop revivifying.");
236 return true;
237 }
238 else
239 was_prompted = true;
240 }
241 return false;
242 }
243
stop_delay(bool stop_stair_travel)244 void stop_delay(bool stop_stair_travel)
245 {
246 if (you.delay_queue.empty())
247 return;
248
249 set_more_autoclear(false);
250
251 ASSERT(!crawl_state.game_is_arena());
252
253 auto delay = current_delay();
254
255 // At the very least we can remove any queued delays, right
256 // now there is no problem with doing this... note that
257 // any queuing here can only happen from a single command,
258 // as the effect of a delay doesn't normally allow interaction
259 // until it is done... it merely chains up individual actions
260 // into a single action. -- bwr
261 // Butcher delays do this on their own, in order to determine the old
262 // list of delays before clearing it.
263 _clear_pending_delays();
264
265 if ((!delay->is_stair_travel() || stop_stair_travel)
266 && delay->try_interrupt())
267 {
268 _pop_delay();
269 }
270 }
271
you_are_delayed()272 bool you_are_delayed()
273 {
274 return !you.delay_queue.empty();
275 }
276
current_delay()277 shared_ptr<Delay> current_delay()
278 {
279 return you_are_delayed() ? you.delay_queue.front()
280 : nullptr;
281 }
282
player_stair_delay()283 bool player_stair_delay()
284 {
285 auto delay = current_delay();
286 return delay && delay->is_stairs();
287 }
288
289 /**
290 * Is the player currently in the middle of memorising a spell?
291 *
292 * @param spell A specific spell, or -1 to check if we're memorising any
293 * spell at all.
294 * @return Whether the player is currently memorising the given type
295 * of spell.
296 */
already_learning_spell(int spell)297 bool already_learning_spell(int spell)
298 {
299 for (const auto &delay : you.delay_queue)
300 {
301 auto mem = dynamic_cast<MemoriseDelay*>(delay.get());
302 if (!mem)
303 continue;
304
305 if (spell == -1 || mem->spell == spell)
306 return true;
307 }
308 return false;
309 }
310
_get_running_command()311 static command_type _get_running_command()
312 {
313 if (Options.travel_key_stop && kbhit()
314 || !in_bounds(you.pos() + you.running.pos))
315 {
316 stop_running();
317 return CMD_NO_CMD;
318 }
319
320 if (is_resting())
321 {
322 you.running.rest();
323
324 #ifdef USE_TILE
325 if (Options.rest_delay >= 0 && tiles.need_redraw())
326 tiles.redraw();
327 #endif
328
329 if (!is_resting() && you.running.hp == you.hp
330 && you.running.mp == you.magic_points)
331 {
332 mpr("Done waiting.");
333 }
334
335 if (Options.rest_delay > 0)
336 delay(Options.rest_delay);
337
338 return CMD_WAIT;
339 }
340 else if (you.running.is_explore() && Options.explore_delay > -1)
341 delay(Options.explore_delay);
342 else if (Options.travel_delay > 0)
343 delay(Options.travel_delay);
344
345 return direction_to_command(you.running.pos.x, you.running.pos.y);
346 }
347
clear_macro_process_key_delay()348 void clear_macro_process_key_delay()
349 {
350 if (dynamic_cast<MacroProcessKeyDelay*>(current_delay().get()))
351 _pop_delay();
352 }
353
start()354 void EquipOnDelay::start()
355 {
356 mprf(MSGCH_MULTITURN_ACTION, "You start putting on your %s.",
357 _eq_category(equip).c_str());
358 }
359
start()360 void EquipOffDelay::start()
361 {
362 mprf(MSGCH_MULTITURN_ACTION, "You start removing your %s.",
363 _eq_category(equip).c_str());
364 }
365
start()366 void MemoriseDelay::start()
367 {
368 if (vehumet_is_offering(spell))
369 {
370 string message = make_stringf(" grants you knowledge of %s.",
371 spell_title(spell));
372 simple_god_message(message.c_str());
373 }
374 mprf(MSGCH_MULTITURN_ACTION, "You start memorising the spell.");
375 }
376
start()377 void PasswallDelay::start()
378 {
379 mprf(MSGCH_MULTITURN_ACTION, "You begin to meditate on the wall.");
380 }
381
start()382 void ShaftSelfDelay::start()
383 {
384 mprf(MSGCH_MULTITURN_ACTION, "You begin to dig a shaft.");
385 }
386
start()387 void ExsanguinateDelay::start()
388 {
389 mprf(MSGCH_MULTITURN_ACTION, "You begin bloodletting.");
390 }
391
start()392 void RevivifyDelay::start()
393 {
394 mprf(MSGCH_MULTITURN_ACTION, "You begin the revivification ritual.");
395 }
396
move_cmd() const397 command_type RunDelay::move_cmd() const
398 {
399 return _get_running_command();
400 }
401
move_cmd() const402 command_type RestDelay::move_cmd() const
403 {
404 return _get_running_command();
405 }
406
move_cmd() const407 command_type TravelDelay::move_cmd() const
408 {
409 return travel();
410 }
411
handle()412 void BaseRunDelay::handle()
413 {
414 bool first_move = false;
415 if (!started)
416 {
417 first_move = true;
418 started = true;
419 }
420 // Handle inconsistencies between the delay queue and you.running.
421 // We don't want to send the game into a deadlock.
422 if (!you.running)
423 {
424 update_turn_count();
425 _pop_delay();
426 return;
427 }
428
429 if (you.turn_is_over)
430 return;
431
432 command_type cmd = CMD_NO_CMD;
433
434 if ((want_move() && you.confused()) ||
435 (!(unsafe_once && first_move) && !i_feel_safe(true, want_move())))
436 {
437 stop_running();
438 }
439 else
440 cmd = move_cmd();
441
442 if (cmd != CMD_NO_CMD)
443 {
444 if (want_clear_messages())
445 clear_messages();
446 process_command(cmd);
447 if (you.turn_is_over
448 && (you.running.is_any_travel() || you.running.is_rest()))
449 {
450 you.running.turns_passed++;
451 // sanity check: if we get up to a large number of turns on
452 // an explore, run, or rest delay, something is extremely buggy
453 // and we should both rescue the player, and generate a crash
454 // report. The thresholds are very heuristic:
455 // Rest delay, 500 turns. This is a bit more than 2x what it takes
456 // a maxed troll to heal.
457 // Travel delay, 2000. Just a big number that is quite a bit
458 // bigger than any travel delay I have been able to generate. If
459 // anyone can generate this on demand it should be raised. (Or
460 // eventually, removed?)
461 // For debuggers: runmode if negative is a meaningful delay type,
462 // but when positive is used as a counter, so if it's a very large
463 // number in the assert message, this is a wait delay
464
465 const int buggy_threshold = you.running.is_rest()
466 ? 500
467 : (ZOT_CLOCK_PER_FLOOR / BASELINE_DELAY / 3);
468 ASSERTM(you.running.turns_passed < buggy_threshold,
469 "Excessive delay, %d turns passed, delay type %d",
470 you.running.turns_passed, you.running.runmode);
471 }
472 }
473
474 if (!you.turn_is_over)
475 you.time_taken = 0;
476
477 // If you.running has gone to zero, and the run delay was not
478 // removed, remove it now. This is needed to clean up after
479 // find_travel_pos() function in travel.cc.
480 if (!you.running
481 && !you.delay_queue.empty()
482 && you.delay_queue.front()->is_run())
483 {
484 update_turn_count();
485 _pop_delay();
486 }
487 }
488
handle()489 void MacroDelay::handle()
490 {
491 if (!started)
492 started = true;
493 if (!duration)
494 {
495 dprf("Expiring macro delay on turn: %d", you.num_turns);
496 stop_delay();
497 }
498 else
499 run_macro();
500
501 // Macros may not use up turns, but unless we zero time_taken,
502 // main.cc will call world_reacts and increase turn count.
503 if (!you.turn_is_over && you.time_taken)
504 you.time_taken = 0;
505 }
506
invalidated()507 bool MultidropDelay::invalidated()
508 {
509 // Throw away invalid items. XXX: what are they?
510 while (!items.empty()
511 // Don't look for gold in inventory
512 && items[0].slot != PROMPT_GOT_SPECIAL
513 && !you.inv[items[0].slot].defined())
514 {
515 items.erase(items.begin());
516 }
517
518 if (items.empty())
519 {
520 // Ran out of things to drop.
521 you.turn_is_over = false;
522 you.time_taken = 0;
523 return true;
524 }
525 return false;
526 }
527
tick()528 void MultidropDelay::tick()
529 {
530 if (!drop_item(items[0].slot, items[0].quantity))
531 {
532 you.turn_is_over = false;
533 you.time_taken = 0;
534 }
535 items.erase(items.begin());
536 }
537
tick()538 void JewelleryOnDelay::tick()
539 {
540 // This is a 1-turn delay where the time cost is handled
541 // in finish().
542 // FIXME: get rid of this hack!
543 you.time_taken = 0;
544 }
545
tick()546 void DropItemDelay::tick()
547 {
548 // This is a 1-turn delay where the time cost is handled
549 // in finish().
550 // FIXME: get rid of this hack!
551 you.time_taken = 0;
552 }
553
handle()554 void Delay::handle()
555 {
556 if (!started)
557 {
558 started = true;
559 start();
560 }
561
562 // First check cases where delay may no longer be valid:
563 // XXX: need to handle PasswallDelay when monster digs -- bwr
564 if (invalidated())
565 {
566 _pop_delay();
567 return;
568 }
569
570 // Actually handle delay:
571 if (duration > 0)
572 {
573 dprf("Delay type: %s, duration: %d", name(), duration);
574 --duration;
575 tick();
576 }
577 else
578 {
579 finish();
580 you.wield_change = true;
581 _pop_delay();
582 print_stats(); // force redraw of the stats
583 update_screen();
584 #ifdef USE_TILE
585 tiles.update_tabs();
586 #endif
587 if (!you.turn_is_over)
588 you.time_taken = 0;
589 }
590 }
591
handle_delay()592 void handle_delay()
593 {
594 if (!you_are_delayed())
595 return;
596
597 shared_ptr<Delay> delay = current_delay();
598 delay->handle();
599 }
600
finish()601 void JewelleryOnDelay::finish()
602 {
603 // Recheck -Tele here, since our condition may have changed since starting
604 // the amulet swap process.
605 // Just breaking here is okay because swapping jewellery is a one-turn
606 // action, so conceptually there is nothing to interrupt - in other words,
607 // this is equivalent to if the user took off the previous amulet and was
608 // affected by tele other before putting the -Tele amulet on as a separate
609 // action on the next turn.
610 // XXX: duplicates a check in invent.cc:check_warning_inscriptions()
611 if (!crawl_state.disables[DIS_CONFIRMATIONS]
612 && needs_notele_warning(jewellery, OPER_PUTON)
613 && item_ident(jewellery, ISFLAG_KNOW_TYPE))
614 {
615 string prompt = "Really put on ";
616 prompt += jewellery.name(DESC_INVENTORY);
617 prompt += " while about to teleport?";
618 if (!yesno(prompt.c_str(), false, 'n'))
619 return;
620 }
621
622 #ifdef USE_SOUND
623 parse_sound(WEAR_JEWELLERY_SOUND);
624 #endif
625 puton_ring(jewellery, false, false, true);
626 }
627
finish()628 void EquipOnDelay::finish()
629 {
630 const unsigned int old_talents = your_talents(false).size();
631 const bool is_amulet = equip.base_type == OBJ_JEWELLERY;
632 const equipment_type eq_slot = is_amulet ? EQ_AMULET :
633 get_armour_slot(equip);
634
635 #ifdef USE_SOUND
636 if (!is_amulet)
637 parse_sound(EQUIP_ARMOUR_SOUND);
638 #endif
639 mprf("You finish putting on %s.", equip.name(DESC_YOUR).c_str());
640
641 equip_item(eq_slot, equip.link);
642
643 check_item_hint(equip, old_talents);
644 }
645
invalidated()646 bool EquipOffDelay::invalidated()
647 {
648 return !equip.defined();
649 }
650
finish()651 void EquipOffDelay::finish()
652 {
653 const bool is_amu = equip.base_type == OBJ_JEWELLERY;
654 const equipment_type slot = is_amu ? EQ_AMULET : get_armour_slot(equip);
655 ASSERT(you.equip[slot] == equip.link);
656
657 #ifdef USE_SOUND
658 parse_sound(is_amu ? REMOVE_JEWELLERY_SOUND : DEQUIP_ARMOUR_SOUND);
659 #endif
660 mprf("You finish taking off %s.", equip.name(DESC_YOUR).c_str());
661 unequip_item(slot);
662 }
663
finish()664 void MemoriseDelay::finish()
665 {
666 #ifdef USE_SOUND
667 parse_sound(MEMORISE_SPELL_SOUND);
668 #endif
669 mpr("You finish memorising.");
670 add_spell_to_memory(spell);
671 vehumet_accept_gift(spell);
672 quiver::on_actions_changed();
673 }
674
finish()675 void PasswallDelay::finish()
676 {
677 mpr("You finish merging with the rock.");
678 // included in default force_more_message
679
680 if (dest.x == 0 || dest.y == 0)
681 return;
682
683 switch (env.grid(dest))
684 {
685 default:
686 if (!you.is_habitable(dest))
687 {
688 mpr("...yet there is something new on the other side. "
689 "You quickly turn back.");
690 redraw_screen();
691 update_screen();
692 return;
693 }
694 break;
695
696 case DNGN_CLOSED_DOOR: // open the door
697 case DNGN_CLOSED_CLEAR_DOOR:
698 case DNGN_RUNED_DOOR:
699 case DNGN_RUNED_CLEAR_DOOR:
700 // Once opened, former runed doors become normal doors.
701 dgn_open_door(dest);
702 break;
703 }
704
705 // Move any monsters out of the way.
706 if (monster* m = monster_at(dest))
707 {
708 // One square, a few squares, anywhere...
709 if (!m->shift() && !monster_blink(m, true))
710 monster_teleport(m, true, true);
711 // Might still fail.
712 if (monster_at(dest))
713 {
714 mpr("...and sense your way blocked. You quickly turn back.");
715 redraw_screen();
716 update_screen();
717 return;
718 }
719
720 move_player_to_grid(dest, false);
721
722 // Wake the monster if it's asleep.
723 if (m)
724 behaviour_event(m, ME_ALERT, &you);
725 }
726 else
727 move_player_to_grid(dest, false);
728
729 // the last phase of the delay is a fake (0-time) turn, so world_reacts
730 // and player_reacts aren't triggered. Need to do a tiny bit of cleanup.
731 // This isn't very elegant, and perhaps a version of player_reacts that is
732 // triggered by changing location would be better (per Pleasingfungus),
733 // but player_reacts is very sensitive to order and can't be easily
734 // refactored in this way.
735 you.update_beholders();
736 you.update_fearmongers();
737 }
738
finish()739 void ShaftSelfDelay::finish()
740 {
741 you.do_shaft_ability();
742 }
743
finish()744 void DropItemDelay::finish()
745 {
746 // We're here if dropping the item required some action to be done
747 // first, like removing armour. At this point, it should be droppable
748 // immediately.
749
750 // Make sure item still exists.
751 if (!item.defined())
752 return;
753
754 if (!drop_item(item.link, 1))
755 {
756 you.turn_is_over = false;
757 you.time_taken = 0;
758 }
759 }
760
finish()761 void AscendingStairsDelay::finish()
762 {
763 up_stairs();
764 }
765
finish()766 void DescendingStairsDelay::finish()
767 {
768 down_stairs();
769 }
770
finish()771 void ExsanguinateDelay::finish()
772 {
773 blood_spray(you.pos(), MONS_PLAYER, 10);
774 you.vampire_alive = false;
775 you.redraw_status_lights = true;
776 calc_hp(true);
777 mpr("You become bloodless.");
778 vampire_update_transformations();
779 }
780
finish()781 void RevivifyDelay::finish()
782 {
783 you.vampire_alive = true;
784 you.redraw_status_lights = true;
785 mpr("You return to life.");
786 temp_mutate(MUT_FRAIL, "vampire revification");
787 vampire_update_transformations();
788 }
789
run_macro(const char * macroname)790 void run_macro(const char *macroname)
791 {
792 #ifdef CLUA_BINDINGS
793 if (!clua)
794 {
795 mprf(MSGCH_DIAGNOSTICS, "Lua not initialised");
796 stop_delay();
797 return;
798 }
799
800 shared_ptr<Delay> delay;
801 if (!macroname)
802 {
803 delay = current_delay();
804 ASSERT(delay->is_macro());
805 }
806 else
807 delay = start_delay<MacroDelay>();
808
809 // If callbooleanfn returns false, that means the macro either exited
810 // normally by returning or by calling coroutine.yield(false). Either way,
811 // decrement the macro duration.
812 if (!clua.callbooleanfn(false, "c_macro", "s", macroname))
813 {
814 if (!clua.error.empty())
815 {
816 mprf(MSGCH_ERROR, "Lua error: %s", clua.error.c_str());
817 stop_delay();
818 }
819 else if (delay->duration > 0)
820 --delay->duration;
821 }
822 #else
823 mprf(MSGCH_ERROR, "CLua bindings not available on this build!");
824 UNUSED(macroname);
825 stop_delay();
826 #endif
827 }
828
829 // Returns TRUE if the delay should be interrupted, MAYBE if the user function
830 // had no opinion on the matter, FALSE if the delay should not be interrupted.
_userdef_interrupt_activity(Delay * delay,activity_interrupt ai,const activity_interrupt_data & at)831 static maybe_bool _userdef_interrupt_activity(Delay* delay,
832 activity_interrupt ai,
833 const activity_interrupt_data &at)
834 {
835 lua_State *ls = clua.state();
836 if (!ls || ai == activity_interrupt::force)
837 return MB_TRUE;
838
839 const char *interrupt_name = _activity_interrupt_name(ai);
840
841 bool ran = clua.callfn("c_interrupt_activity", "1:ssA",
842 delay->name(), interrupt_name, &at);
843 if (ran)
844 {
845 // If the function returned nil, we want to cease processing.
846 if (lua_isnil(ls, -1))
847 {
848 lua_pop(ls, 1);
849 return MB_FALSE;
850 }
851
852 bool stopact = lua_toboolean(ls, -1);
853 lua_pop(ls, 1);
854 if (stopact)
855 return MB_TRUE;
856 }
857
858 if (delay->is_macro() && clua.callbooleanfn(true, "c_interrupt_macro",
859 "sA", interrupt_name, &at))
860 {
861 return MB_TRUE;
862 }
863 return MB_MAYBE;
864 }
865
866 // Returns true if the activity should be interrupted, false otherwise.
_should_stop_activity(Delay * delay,activity_interrupt ai,const activity_interrupt_data & at)867 static bool _should_stop_activity(Delay* delay,
868 activity_interrupt ai,
869 const activity_interrupt_data &at)
870 {
871 switch (_userdef_interrupt_activity(delay, ai, at))
872 {
873 case MB_TRUE:
874 return true;
875 case MB_FALSE:
876 return false;
877 case MB_MAYBE:
878 break;
879 }
880
881 // Don't interrupt player on monster's turn, they might wander off.
882 if (you.turn_is_over
883 && (at.context == SC_ALREADY_SEEN || at.context == SC_UNCHARM))
884 {
885 return false;
886 }
887
888 // No monster will attack you inside a sanctuary,
889 // so presence of monsters won't matter.
890 if (ai == activity_interrupt::see_monster && is_sanctuary(you.pos()))
891 return false;
892
893 auto curr = current_delay(); // Not necessarily what we were passed.
894
895 if ((ai == activity_interrupt::see_monster
896 || ai == activity_interrupt::mimic)
897 && player_stair_delay())
898 {
899 return false;
900 }
901
902 if (ai == activity_interrupt::full_hp || ai == activity_interrupt::full_mp
903 || ai == activity_interrupt::ancestor_hp)
904 {
905 if ((Options.rest_wait_both && curr->is_resting()
906 && !you.is_sufficiently_rested())
907 || (Options.rest_wait_ancestor && curr->is_resting()
908 && !ancestor_full_hp()))
909 {
910 return false;
911 }
912 }
913
914 // Don't interrupt feeding or butchering for monsters already in view.
915 if (ai == activity_interrupt::see_monster
916 && testbits(at.mons_data->flags, MF_WAS_IN_VIEW))
917 {
918 return false;
919 }
920
921 return ai == activity_interrupt::force
922 || Options.activity_interrupts[delay->name()][static_cast<int>(ai)];
923 }
924
_abyss_monster_creation_message(const monster * mon)925 static string _abyss_monster_creation_message(const monster* mon)
926 {
927 if (mon->type == MONS_DEATH_COB)
928 {
929 return coinflip() ? " appears in a burst of microwaves!"
930 : " pops from nullspace!";
931 }
932
933 // You may ask: "Why these weights?" So would I!
934 const vector<pair<string, int>> messages = {
935 { " appears in a shower of translocational energy.", 17 },
936 { " appears in a shower of sparks.", 34 },
937 { " materialises.", 45 },
938 { " emerges from chaos.", 13 },
939 { " emerges from the beyond.", 26 },
940 { make_stringf(" assembles %s!",
941 mon->pronoun(PRONOUN_REFLEXIVE).c_str()), 33 },
942 { " erupts from nowhere.", 9 },
943 { " bursts from nowhere.", 18 },
944 { " is cast out of space.", 7 },
945 { " is cast out of reality.", 14 },
946 { " coalesces out of pure chaos.", 5 },
947 { " coalesces out of seething chaos.", 10 },
948 { " punctures the fabric of time!", 2 },
949 { " punctures the fabric of the universe.", 7 },
950 { make_stringf(" manifests%s!",
951 silenced(you.pos()) ? "" : " with a bang"), 3 },
952
953
954 };
955
956 return *random_choose_weighted(messages);
957 }
958
_monster_warning(activity_interrupt ai,const activity_interrupt_data & at,shared_ptr<Delay> delay,vector<string> * msgs_buf=nullptr)959 static inline bool _monster_warning(activity_interrupt ai,
960 const activity_interrupt_data &at,
961 shared_ptr<Delay> delay,
962 vector<string>* msgs_buf = nullptr)
963 {
964 if (ai == activity_interrupt::sense_monster)
965 {
966 mprf(MSGCH_WARN, "You sense a monster nearby.");
967 return true;
968 }
969 if (ai != activity_interrupt::see_monster)
970 return false;
971 if (delay && !delay->is_run())
972 return false;
973 if (at.context != SC_NEWLY_SEEN && !delay)
974 return false;
975
976 ASSERT(at.apt == ai_payload::monster);
977 monster* mon = at.mons_data;
978 ASSERT(mon);
979 if (!you.can_see(*mon))
980 return false;
981
982 // Disable message for summons.
983 if (mon->is_summoned() && !delay)
984 return false;
985
986 if (at.context == SC_ALREADY_SEEN || at.context == SC_UNCHARM)
987 {
988 // Only say "comes into view" if the monster wasn't in view
989 // during the previous turn.
990 if (testbits(mon->flags, MF_WAS_IN_VIEW) && delay)
991 {
992 mprf(MSGCH_WARN, "%s is too close now for your liking.",
993 mon->name(DESC_THE).c_str());
994 }
995 }
996 else if (mon->seen_context == SC_JUST_SEEN)
997 return false;
998 else
999 {
1000 // XXX: This needs to be here to ensure correct messaging for
1001 // autoexplore, even though the correct place to process it is
1002 // seen_monster
1003 view_monster_equipment(mon);
1004
1005 string text = getMiscString(mon->name(DESC_DBNAME) + " title");
1006 if (text.empty())
1007 text = mon->full_name(DESC_A);
1008 if (mon->type == MONS_PLAYER_GHOST)
1009 {
1010 text += make_stringf(" (%s)",
1011 short_ghost_description(mon).c_str());
1012 }
1013
1014 if (at.context == SC_DOOR)
1015 text += " opens the door.";
1016 else if (at.context == SC_GATE)
1017 text += " opens the gate.";
1018 else if (at.context == SC_TELEPORT_IN)
1019 text += " appears from thin air!";
1020 else if (at.context == SC_LEAP_IN)
1021 text += " leaps into view!";
1022 else if (at.context == SC_FISH_SURFACES)
1023 {
1024 text += " bursts forth from the ";
1025 if (mons_primary_habitat(*mon) == HT_LAVA)
1026 text += "lava";
1027 else if (mons_primary_habitat(*mon) == HT_WATER)
1028 text += "water";
1029 else
1030 text += "realm of bugdom";
1031 text += ".";
1032 }
1033 else if (at.context == SC_NONSWIMMER_SURFACES_FROM_DEEP)
1034 text += " emerges from the water.";
1035 else if (at.context == SC_UPSTAIRS)
1036 text += " comes up the stairs.";
1037 else if (at.context == SC_DOWNSTAIRS)
1038 text += " comes down the stairs.";
1039 else if (at.context == SC_ARCH)
1040 text += " comes through the gate.";
1041 else if (at.context == SC_ABYSS)
1042 text += _abyss_monster_creation_message(mon);
1043 else if (at.context == SC_THROWN_IN)
1044 text += " is thrown into view!";
1045 else
1046 text += " comes into view.";
1047
1048 bool zin_id = false;
1049 string god_warning;
1050
1051 if (have_passive(passive_t::warn_shapeshifter)
1052 && mon->is_shapeshifter()
1053 && !(mon->flags & MF_KNOWN_SHIFTER))
1054 {
1055 zin_id = true;
1056 mon->props["zin_id"] = true;
1057 discover_shifter(*mon);
1058 god_warning = uppercase_first(god_name(you.religion))
1059 + " warns you: "
1060 + uppercase_first(mon->pronoun(PRONOUN_SUBJECTIVE))
1061 + " "
1062 + conjugate_verb("are", mon->pronoun_plurality())
1063 + " a foul ";
1064 if (mon->has_ench(ENCH_GLOWING_SHAPESHIFTER))
1065 god_warning += "glowing ";
1066 god_warning += "shapeshifter.";
1067 }
1068
1069 monster_info mi(mon);
1070
1071 const string mweap = get_monster_equipment_desc(mi, DESC_IDENTIFIED,
1072 DESC_NONE);
1073
1074 if (!mweap.empty())
1075 {
1076 text += " " + uppercase_first(mon->pronoun(PRONOUN_SUBJECTIVE))
1077 + " " + conjugate_verb("are", mi.pronoun_plurality())
1078 + (mweap[0] != ' ' ? " " : "")
1079 + mweap + ".";
1080 }
1081
1082 if (msgs_buf)
1083 msgs_buf->push_back(text);
1084 else
1085 {
1086 mprf(MSGCH_MONSTER_WARNING, "%s", text.c_str());
1087 if (zin_id)
1088 mprf(MSGCH_GOD, "%s", god_warning.c_str());
1089 #ifndef USE_TILE_LOCAL
1090 if (zin_id)
1091 update_monster_pane();
1092 #endif
1093 if (player_under_penance(GOD_GOZAG)
1094 && !mon->wont_attack()
1095 && !mon->is_stationary()
1096 && !mons_is_object(mon->type)
1097 && !mons_is_tentacle_or_tentacle_segment(mon->type))
1098 {
1099 if (coinflip()
1100 && mon->get_experience_level() >=
1101 random2(you.experience_level))
1102 {
1103 mprf(MSGCH_GOD, GOD_GOZAG, "Gozag incites %s against you.",
1104 mon->name(DESC_THE).c_str());
1105 gozag_incite(mon);
1106 }
1107 }
1108 }
1109 if (you.has_mutation(MUT_SCREAM)
1110 && x_chance_in_y(you.get_mutation_level(MUT_SCREAM) * 6, 100))
1111 {
1112 yell(mon);
1113 }
1114 mons_set_just_seen(mon);
1115 }
1116
1117 if (crawl_state.game_is_hints())
1118 hints_monster_seen(*mon);
1119
1120 return true;
1121 }
1122
1123 // Turns autopickup off if we ran into an invisible monster or saw a monster
1124 // turn invisible.
1125 // Turns autopickup on if we saw an invisible monster become visible or
1126 // killed an invisible monster.
autotoggle_autopickup(bool off)1127 void autotoggle_autopickup(bool off)
1128 {
1129 if (off)
1130 {
1131 if (Options.autopickup_on > 0)
1132 {
1133 Options.autopickup_on = -1;
1134 mprf(MSGCH_WARN,
1135 "Deactivating autopickup; reactivate with <w>%s</w>.",
1136 command_to_string(CMD_TOGGLE_AUTOPICKUP).c_str());
1137 }
1138 if (crawl_state.game_is_hints())
1139 {
1140 learned_something_new(HINT_INVISIBLE_DANGER);
1141 Hints.hints_seen_invisible = you.num_turns;
1142 }
1143 }
1144 else if (Options.autopickup_on < 0) // was turned off automatically
1145 {
1146 Options.autopickup_on = 1;
1147 mprf(MSGCH_WARN, "Reactivating autopickup.");
1148 }
1149 }
1150
1151 // Returns true if any activity was stopped. Not reentrant.
interrupt_activity(activity_interrupt ai,const activity_interrupt_data & at,vector<string> * msgs_buf)1152 bool interrupt_activity(activity_interrupt ai,
1153 const activity_interrupt_data &at,
1154 vector<string>* msgs_buf)
1155 {
1156 if (interrupt_block::blocked())
1157 return false;
1158
1159 const interrupt_block block_recursive_interrupts;
1160 if (ai == activity_interrupt::hit_monster
1161 || ai == activity_interrupt::monster_attacks)
1162 {
1163 const monster* mon = at.mons_data;
1164 if (mon && !mon->visible_to(&you) && !mon->submerged())
1165 autotoggle_autopickup(true);
1166 }
1167
1168 if (crawl_state.is_repeating_cmd())
1169 return interrupt_cmd_repeat(ai, at);
1170
1171 if (!you_are_delayed())
1172 {
1173 // Printing "[foo] comes into view." messages even when not
1174 // auto-exploring/travelling.
1175 if (ai == activity_interrupt::see_monster)
1176 return _monster_warning(ai, at, nullptr, msgs_buf);
1177 else
1178 return false;
1179 }
1180
1181 const auto delay = current_delay();
1182
1183 dprf("Activity interrupt: %s", _activity_interrupt_name(ai));
1184
1185 // First try to stop the current delay.
1186 if (ai == activity_interrupt::full_hp && !you.running.notified_hp_full)
1187 {
1188 you.running.notified_hp_full = true;
1189 mpr("HP restored.");
1190 }
1191 else if (ai == activity_interrupt::full_mp && !you.running.notified_mp_full)
1192 {
1193 you.running.notified_mp_full = true;
1194 mpr("Magic restored.");
1195 }
1196 else if (ai == activity_interrupt::ancestor_hp
1197 && !you.running.notified_ancestor_hp_full)
1198 {
1199 // This interrupt only triggers when the ancestor is in LOS,
1200 // so this message does not leak information.
1201 you.running.notified_ancestor_hp_full = true;
1202 mpr("Ancestor HP restored.");
1203 }
1204
1205 if (_should_stop_activity(delay.get(), ai, at))
1206 {
1207 _monster_warning(ai, at, delay, msgs_buf);
1208 // Teleport stops stair delays.
1209 stop_delay(ai == activity_interrupt::teleport);
1210 quiver::set_needs_redraw();
1211
1212 return true;
1213 }
1214
1215 // Check the other queued delays; the first delay that is interruptible
1216 // will kill itself and all subsequent delays. This is so that a travel
1217 // delay stacked behind a delay such as stair/autopickup will be killed
1218 // correctly by interrupts that the simple stair/autopickup delay ignores.
1219 for (int i = 1, size = you.delay_queue.size(); i < size; ++i)
1220 {
1221 if (_should_stop_activity(you.delay_queue[i].get(), ai, at))
1222 {
1223 quiver::set_needs_redraw();
1224 // Do we have a queued run delay? If we do, flush the delay queue
1225 // so that stop running Lua notifications happen.
1226 for (int j = i; j < size; ++j)
1227 {
1228 if (you.delay_queue[j]->is_run())
1229 {
1230 _monster_warning(ai, at, you.delay_queue[j], msgs_buf);
1231 _clear_pending_delays(i);
1232 return true;
1233 }
1234 }
1235
1236 // Non-run queued delays can be discarded without any processing.
1237 you.delay_queue.erase(you.delay_queue.begin() + i,
1238 you.delay_queue.end());
1239 return true;
1240 }
1241 }
1242
1243 return false;
1244 }
1245
1246 // Must match the order of activity_interrupt.h!
1247 static const char *activity_interrupt_names[] =
1248 {
1249 "force", "keypress", "full_hp", "full_mp", "ancestor_hp", "message",
1250 "hp_loss", "stat", "monster", "monster_attack", "teleport", "hit_monster",
1251 "sense_monster", "mimic"
1252 };
1253
_activity_interrupt_name(activity_interrupt ai)1254 static const char *_activity_interrupt_name(activity_interrupt ai)
1255 {
1256 COMPILE_CHECK(ARRAYSZ(activity_interrupt_names) == NUM_ACTIVITY_INTERRUPTS);
1257
1258 if (ai == activity_interrupt::COUNT)
1259 return "";
1260
1261 return activity_interrupt_names[static_cast<int>(ai)];
1262 }
1263
get_activity_interrupt(const string & name)1264 activity_interrupt get_activity_interrupt(const string &name)
1265 {
1266 COMPILE_CHECK(ARRAYSZ(activity_interrupt_names) == NUM_ACTIVITY_INTERRUPTS);
1267
1268 for (int i = 0; i < NUM_ACTIVITY_INTERRUPTS; ++i)
1269 if (name == activity_interrupt_names[i])
1270 return activity_interrupt(i);
1271
1272 return activity_interrupt::COUNT;
1273 }
1274