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