1 #include "stdafx.h"
2 #include "furniture_entry.h"
3 #include "level.h"
4 #include "position.h"
5 #include "creature.h"
6 #include "creature_attributes.h"
7 #include "furniture.h"
8 #include "player_message.h"
9 #include "game.h"
10 #include "effect.h"
11 #include "movement_set.h"
12 
FurnitureEntry(FurnitureEntry::EntryData d)13 FurnitureEntry::FurnitureEntry(FurnitureEntry::EntryData d) : entryData(d) {
14 }
15 
handle(WFurniture f,WCreature c)16 void FurnitureEntry::handle(WFurniture f, WCreature c) {
17   entryData.match(
18       [&](Sokoban) {
19         if (c->getAttributes().isBoulder()) {
20           Position pos = c->getPosition();
21           pos.globalMessage(c->getName().the() + " fills the " + f->getName());
22           pos.removeFurniture(f);
23           c->dieNoReason(Creature::DropType::NOTHING);
24         } else {
25           if (!c->isAffected(LastingEffect::FLYING))
26             c->you(MsgType::FALL, "into the " + f->getName() + "!");
27           else
28             c->you(MsgType::ARE, "sucked into the " + f->getName() + "!");
29           auto level = c->getPosition().getLevel();
30           level->changeLevel(level->getAllStairKeys().getOnlyElement(), c);
31         }
32       },
33       [&](Trap type) {
34         auto position = c->getPosition();
35         if (auto game = c->getGame()) // check in case the creature is placed here during level generation
36           if (game->getTribe(f->getTribe())->isEnemy(c)) {
37             if (type.spiderWeb || !c->getAttributes().getSkills().hasDiscrete(SkillId::DISARM_TRAPS)) {
38               if (!type.spiderWeb)
39                 c->you(MsgType::TRIGGER_TRAP, "");
40               type.effect.applyToCreature(c);
41               position.getGame()->addEvent(EventInfo::TrapTriggered{c->getPosition()});
42             } else {
43               c->you(MsgType::DISARM_TRAP, type.effect.getName() + " trap");
44               position.getGame()->addEvent(EventInfo::TrapDisarmed{c->getPosition(), c});
45             }
46             position.removeFurniture(f);
47           }
48       },
49       [&](Water) {
50         MovementType realMovement = c->getMovementType();
51         realMovement.setForced(false);
52         if (!f->getMovementSet().canEnter(realMovement)) {
53           if (auto holding = c->getHoldingCreature()) {
54             c->you(MsgType::ARE, "drowned by " + holding->getName().the());
55             c->dieWithAttacker(holding, Creature::DropType::NOTHING);
56           } else {
57             c->you(MsgType::DROWN, f->getName());
58             c->dieWithReason("drowned", Creature::DropType::NOTHING);
59           }
60         }
61       },
62       [&](Magma) {
63         MovementType realMovement = c->getMovementType();
64         realMovement.setForced(false);
65         if (!f->getMovementSet().canEnter(realMovement)) {
66           c->you(MsgType::BURN, f->getName());
67           c->dieWithReason("burned to death", Creature::DropType::NOTHING);
68         }
69       }
70   );
71 }
72 
isVisibleTo(WConstFurniture f,WConstCreature c) const73 bool FurnitureEntry::isVisibleTo(WConstFurniture f, WConstCreature c) const {
74   return entryData.visit(
75       [&](const Trap& type) {
76         return !c->getGame()->getTribe(f->getTribe())->isEnemy(c)
77             || (!type.spiderWeb && c->getAttributes().getSkills().hasDiscrete(SkillId::DISARM_TRAPS));
78       },
79       [&](const auto&) {
80         return true;
81       }
82   );
83 }
84 
85 SERIALIZE_DEF(FurnitureEntry, entryData)
86 SERIALIZATION_CONSTRUCTOR_IMPL(FurnitureEntry)
87