1 #include "stdafx.h"
2 #include "furniture_factory.h"
3 #include "furniture.h"
4 #include "furniture_type.h"
5 #include "view_id.h"
6 #include "view_layer.h"
7 #include "view_object.h"
8 #include "tribe.h"
9 #include "item_type.h"
10 #include "furniture_usage.h"
11 #include "furniture_click.h"
12 #include "furniture_tick.h"
13 #include "furniture_entry.h"
14 #include "furniture_dropped_items.h"
15 #include "level.h"
16 #include "creature.h"
17 #include "creature_factory.h"
18 #include "movement_set.h"
19 #include "lasting_effect.h"
20
get(FurnitureType type,TribeId tribe)21 static Furniture get(FurnitureType type, TribeId tribe) {
22 switch (type) {
23 case FurnitureType::TRAINING_WOOD:
24 return Furniture("wooden training dummy", ViewObject(ViewId::TRAINING_WOOD, ViewLayer::FLOOR), type, tribe)
25 .setBlocking()
26 .setUsageType(FurnitureUsageType::TRAIN)
27 .setFireInfo(Fire(500, 0.5))
28 .setCanHide()
29 .setDestroyable(80);
30 case FurnitureType::TRAINING_IRON:
31 return Furniture("iron training dummy", ViewObject(ViewId::TRAINING_IRON, ViewLayer::FLOOR), type, tribe)
32 .setBlocking()
33 .setUsageType(FurnitureUsageType::TRAIN)
34 .setCanHide()
35 .setDestroyable(80);
36 case FurnitureType::TRAINING_STEEL:
37 return Furniture("steel training dummy", ViewObject(ViewId::TRAINING_STEEL, ViewLayer::FLOOR), type, tribe)
38 .setBlocking()
39 .setUsageType(FurnitureUsageType::TRAIN)
40 .setCanHide()
41 .setDestroyable(80);
42 case FurnitureType::ARCHERY_RANGE:
43 return Furniture("archery target", ViewObject(ViewId::ARCHERY_RANGE, ViewLayer::FLOOR), type, tribe)
44 .setBlocking()
45 .setStopProjectiles()
46 .setUsageType(FurnitureUsageType::ARCHERY_RANGE)
47 .setCanHide()
48 .setDestroyable(80);
49 case FurnitureType::WORKSHOP:
50 return Furniture("workshop", ViewObject(ViewId::WORKSHOP, ViewLayer::FLOOR), type, tribe)
51 .setBlocking()
52 .setUsageTime(5)
53 .setCanHide()
54 .setFireInfo(Fire(500, 0.5))
55 .setDestroyable(80);
56 case FurnitureType::FORGE:
57 return Furniture("forge", ViewObject(ViewId::FORGE, ViewLayer::FLOOR), type, tribe)
58 .setBlocking()
59 .setUsageTime(5)
60 .setCanHide()
61 .setDestroyable(80);
62 case FurnitureType::LABORATORY:
63 return Furniture("laboratory", ViewObject(ViewId::LABORATORY, ViewLayer::FLOOR), type, tribe)
64 .setBlocking()
65 .setUsageTime(5)
66 .setCanHide()
67 .setDestroyable(80);
68 case FurnitureType::JEWELER:
69 return Furniture("jeweler", ViewObject(ViewId::JEWELER, ViewLayer::FLOOR), type, tribe)
70 .setBlocking()
71 .setUsageTime(5)
72 .setCanHide()
73 .setFireInfo(Fire(500, 0.5))
74 .setDestroyable(40);
75 case FurnitureType::STEEL_FURNACE:
76 return Furniture("steel furnace", ViewObject(ViewId::STEEL_FURNACE, ViewLayer::FLOOR), type, tribe)
77 .setBlocking()
78 .setUsageTime(5)
79 .setCanHide()
80 .setDestroyable(100);
81 case FurnitureType::BOOKCASE_WOOD:
82 return Furniture("wooden bookcase", ViewObject(ViewId::BOOKCASE_WOOD, ViewLayer::FLOOR), type, tribe)
83 .setBlocking()
84 .setUsageType(FurnitureUsageType::STUDY)
85 .setUsageTime(5)
86 .setCanHide()
87 .setFireInfo(Fire(700, 1.0))
88 .setDestroyable(50);
89 case FurnitureType::BOOKCASE_IRON:
90 return Furniture("iron bookcase", ViewObject(ViewId::BOOKCASE_IRON, ViewLayer::FLOOR), type, tribe)
91 .setBlocking()
92 .setUsageType(FurnitureUsageType::STUDY)
93 .setUsageTime(5)
94 .setCanHide()
95 .setFireInfo(Fire(700, 0.5))
96 .setDestroyable(50);
97 case FurnitureType::BOOKCASE_GOLD:
98 return Furniture("golden bookcase", ViewObject(ViewId::BOOKCASE_GOLD, ViewLayer::FLOOR), type, tribe)
99 .setBlocking()
100 .setUsageType(FurnitureUsageType::STUDY)
101 .setUsageTime(5)
102 .setCanHide()
103 .setFireInfo(Fire(700, 0.5))
104 .setDestroyable(50);
105 case FurnitureType::THRONE:
106 return Furniture("throne", ViewObject(ViewId::THRONE, ViewLayer::FLOOR), type, tribe)
107 .setCanHide()
108 .setDestroyable(80);
109 case FurnitureType::IMPALED_HEAD:
110 return Furniture("impaled head", ViewObject(ViewId::IMPALED_HEAD, ViewLayer::FLOOR), type, tribe)
111 .setDestroyable(10);
112 case FurnitureType::BEAST_CAGE:
113 return Furniture("beast cage", ViewObject(ViewId::BEAST_CAGE, ViewLayer::FLOOR), type, tribe)
114 .setUsageType(FurnitureUsageType::SLEEP)
115 .setTickType(FurnitureTickType::BED)
116 .setCanHide()
117 .setFireInfo(Fire(500, 0.5))
118 .setDestroyable(40);
119 case FurnitureType::BED:
120 return Furniture("bed", ViewObject(ViewId::BED, ViewLayer::FLOOR), type, tribe)
121 .setUsageType(FurnitureUsageType::SLEEP)
122 .setTickType(FurnitureTickType::BED)
123 .setCanHide()
124 .setFireInfo(Fire(500, 0.7))
125 .setDestroyable(40);
126 case FurnitureType::GRAVE:
127 return Furniture("grave", ViewObject(ViewId::GRAVE, ViewLayer::FLOOR), type, tribe)
128 .setUsageType(FurnitureUsageType::SLEEP)
129 .setCanHide()
130 .setTickType(FurnitureTickType::BED)
131 .setDestroyable(40);
132 case FurnitureType::DEMON_SHRINE:
133 return Furniture("demon shrine", ViewObject(ViewId::DEMON_SHRINE, ViewLayer::FLOOR), type, tribe)
134 .setBlocking()
135 .setCanHide()
136 .setUsageTime(5)
137 .setDestroyable(80);
138 case FurnitureType::PRISON:
139 return Furniture("prison", ViewObject(ViewId::PRISON, ViewLayer::FLOOR_BACKGROUND), type, tribe);
140 case FurnitureType::TREASURE_CHEST:
141 return Furniture("treasure chest", ViewObject(ViewId::TREASURE_CHEST, ViewLayer::FLOOR), type, tribe)
142 .setCanHide()
143 .setFireInfo(Fire(500, 0.5))
144 .setDestroyable(40);
145 case FurnitureType::EYEBALL:
146 return Furniture("eyeball", ViewObject(ViewId::EYEBALL, ViewLayer::FLOOR), type, tribe)
147 .setBlocking()
148 .setCanHide()
149 .setLightEmission(8.2)
150 .setDestroyable(30);
151 case FurnitureType::WHIPPING_POST:
152 return Furniture("whipping post", ViewObject(ViewId::WHIPPING_POST, ViewLayer::FLOOR), type, tribe)
153 .setUsageType(FurnitureUsageType::TIE_UP)
154 .setFireInfo(Fire(300, 0.5))
155 .setDestroyable(30);
156 case FurnitureType::GALLOWS:
157 return Furniture("gallows", ViewObject(ViewId::GALLOWS, ViewLayer::FLOOR), type, tribe)
158 .setUsageType(FurnitureUsageType::TIE_UP)
159 .setFireInfo(Fire(300, 0.5))
160 .setDestroyable(30);
161 case FurnitureType::MINION_STATUE:
162 return Furniture("statue", ViewObject(ViewId::MINION_STATUE, ViewLayer::FLOOR), type, tribe)
163 .setBlocking()
164 .setCanHide()
165 .setDestroyable(50);
166 case FurnitureType::BARRICADE:
167 return Furniture("barricade", ViewObject(ViewId::BARRICADE, ViewLayer::FLOOR), type, tribe)
168 .setBlocking()
169 .setFireInfo(Fire(500, 0.3))
170 .setDestroyable(80);
171 case FurnitureType::CANIF_TREE:
172 return Furniture("tree", ViewObject(ViewId::CANIF_TREE, ViewLayer::FLOOR), type, tribe)
173 .setCanHide()
174 .setBlockVision()
175 .setBlockVision(VisionId::ELF, false)
176 .setDestroyedRemains(FurnitureType::TREE_TRUNK)
177 .setBurntRemains(FurnitureType::BURNT_TREE)
178 .setDestroyable(100, DestroyAction::Type::BOULDER)
179 .setDestroyable(70, DestroyAction::Type::CUT)
180 .setFireInfo(Fire(1000, 0.7))
181 .setItemDrop(ItemFactory::singleType(ItemType::WoodPlank{}, Range(8, 14)))
182 .setSummonedElement(CreatureId::ENT);
183 case FurnitureType::DECID_TREE:
184 return Furniture("tree", ViewObject(ViewId::DECID_TREE, ViewLayer::FLOOR), type, tribe)
185 .setCanHide()
186 .setBlockVision()
187 .setBlockVision(VisionId::ELF, false)
188 .setDestroyedRemains(FurnitureType::TREE_TRUNK)
189 .setBurntRemains(FurnitureType::BURNT_TREE)
190 .setFireInfo(Fire(1000, 0.7))
191 .setDestroyable(100, DestroyAction::Type::BOULDER)
192 .setDestroyable(70, DestroyAction::Type::CUT)
193 .setItemDrop(ItemFactory::singleType(ItemType::WoodPlank{}, Range(8, 14)))
194 .setSummonedElement(CreatureId::ENT);
195 case FurnitureType::TREE_TRUNK:
196 return Furniture("tree trunk", ViewObject(ViewId::TREE_TRUNK, ViewLayer::FLOOR), type, tribe);
197 case FurnitureType::BURNT_TREE:
198 return Furniture("burnt tree", ViewObject(ViewId::BURNT_TREE, ViewLayer::FLOOR), type, tribe)
199 .setCanHide()
200 .setDestroyable(30);
201 case FurnitureType::BUSH:
202 return Furniture("bush", ViewObject(ViewId::BUSH, ViewLayer::FLOOR), type, tribe)
203 .setDestroyable(20, DestroyAction::Type::BOULDER)
204 .setDestroyable(10, DestroyAction::Type::CUT)
205 .setCanHide()
206 .setFireInfo(Fire(100, 0.8))
207 .setItemDrop(ItemFactory::singleType(ItemType::WoodPlank{}, Range(2, 4)));
208 case FurnitureType::CROPS:
209 return Furniture("wheat", ViewObject(Random.choose(ViewId::CROPS, ViewId::CROPS2), ViewLayer::FLOOR), type, tribe)
210 .setUsageType(FurnitureUsageType::CROPS)
211 .setUsageTime(3);
212 case FurnitureType::PIGSTY:
213 return Furniture("pigsty", ViewObject(ViewId::MUD, ViewLayer::FLOOR),
214 type, tribe)
215 .setTickType(FurnitureTickType::PIGSTY);
216 case FurnitureType::GROUND_TORCH:
217 return Furniture("torch", ViewObject(ViewId::TORCH, ViewLayer::FLOOR), type, tribe)
218 .setLightEmission(8.2);
219 case FurnitureType::TORCH_N:
220 return Furniture("torch", ViewObject(ViewId::TORCH, ViewLayer::TORCH1).setAttachmentDir(Dir::N), type, tribe)
221 .setLightEmission(8.2)
222 .setLayer(FurnitureLayer::CEILING);
223 case FurnitureType::TORCH_E:
224 return Furniture("torch", ViewObject(ViewId::TORCH, ViewLayer::TORCH2).setAttachmentDir(Dir::E), type, tribe)
225 .setLightEmission(8.2)
226 .setLayer(FurnitureLayer::CEILING);
227 case FurnitureType::TORCH_S:
228 return Furniture("torch", ViewObject(ViewId::TORCH, ViewLayer::TORCH2).setAttachmentDir(Dir::S), type, tribe)
229 .setLightEmission(8.2)
230 .setLayer(FurnitureLayer::CEILING);
231 case FurnitureType::TORCH_W:
232 return Furniture("torch", ViewObject(ViewId::TORCH, ViewLayer::TORCH2).setAttachmentDir(Dir::W), type, tribe)
233 .setLightEmission(8.2)
234 .setLayer(FurnitureLayer::CEILING);
235 case FurnitureType::TORTURE_TABLE:
236 return Furniture("torture table", ViewObject(ViewId::TORTURE_TABLE, ViewLayer::FLOOR), type,
237 tribe)
238 .setCanHide()
239 .setUsageType(FurnitureUsageType::TIE_UP)
240 .setDestroyable(80);
241 case FurnitureType::FOUNTAIN:
242 return Furniture("fountain", ViewObject(ViewId::FOUNTAIN, ViewLayer::FLOOR), type, tribe)
243 .setCanHide()
244 .setUsageType(FurnitureUsageType::FOUNTAIN)
245 .setSummonedElement(CreatureId::WATER_ELEMENTAL)
246 .setDestroyable(80);
247 case FurnitureType::CHEST:
248 return Furniture("chest", ViewObject(ViewId::CHEST, ViewLayer::FLOOR), type, tribe)
249 .setCanHide()
250 .setUsageType(FurnitureUsageType::CHEST)
251 .setFireInfo(Fire(500, 0.5))
252 .setDestroyable(30);
253 case FurnitureType::OPENED_CHEST:
254 return Furniture("opened chest", ViewObject(ViewId::OPENED_CHEST, ViewLayer::FLOOR), type, tribe)
255 .setCanHide()
256 .setFireInfo(Fire(500, 0.5))
257 .setDestroyable(30);
258 case FurnitureType::COFFIN:
259 return Furniture("coffin", ViewObject(ViewId::COFFIN, ViewLayer::FLOOR), type, tribe)
260 .setCanHide()
261 .setUsageType(FurnitureUsageType::COFFIN)
262 .setFireInfo(Fire(500, 0.5))
263 .setDestroyable(40);
264 case FurnitureType::VAMPIRE_COFFIN:
265 return Furniture("coffin", ViewObject(ViewId::COFFIN, ViewLayer::FLOOR), type, tribe)
266 .setCanHide()
267 .setUsageType(FurnitureUsageType::VAMPIRE_COFFIN)
268 .setFireInfo(Fire(500, 0.5))
269 .setDestroyable(40);
270 case FurnitureType::OPENED_COFFIN:
271 return Furniture("opened coffin", ViewObject(ViewId::OPENED_COFFIN, ViewLayer::FLOOR), type, tribe)
272 .setCanHide()
273 .setFireInfo(Fire(500, 0.5))
274 .setDestroyable(40);
275 case FurnitureType::DOOR:
276 return Furniture("door", ViewObject(ViewId::DOOR, ViewLayer::FLOOR), type, tribe)
277 .setBlockingEnemies()
278 .setCanHide()
279 .setBlockVision()
280 .setFireInfo(Fire(500, 0.5))
281 .setDestroyable(100)
282 .setClickType(FurnitureClickType::LOCK);
283 case FurnitureType::LOCKED_DOOR:
284 return Furniture("locked door", ViewObject(ViewId::LOCKED_DOOR, ViewLayer::FLOOR), type, tribe)
285 .setBlocking()
286 .setBlockVision()
287 .setFireInfo(Fire(500, 0.5))
288 .setDestroyable(100)
289 .setClickType(FurnitureClickType::UNLOCK);
290 case FurnitureType::WELL:
291 return Furniture("well", ViewObject(ViewId::WELL, ViewLayer::FLOOR), type, tribe)
292 .setCanHide()
293 .setFireInfo(Fire(500, 0.5))
294 .setSummonedElement(CreatureId::WATER_ELEMENTAL)
295 .setDestroyable(80);
296 case FurnitureType::KEEPER_BOARD:
297 return Furniture("message board", ViewObject(ViewId::NOTICE_BOARD, ViewLayer::FLOOR), type, tribe)
298 .setCanHide()
299 .setUsageType(FurnitureUsageType::KEEPER_BOARD)
300 .setFireInfo(Fire(500, 0.5))
301 .setDestroyable(50);
302 case FurnitureType::UP_STAIRS:
303 return Furniture("stairs", ViewObject(ViewId::UP_STAIRCASE, ViewLayer::FLOOR), type, tribe)
304 .setCanHide()
305 .setUsageType(FurnitureUsageType::STAIRS);
306 case FurnitureType::DOWN_STAIRS:
307 return Furniture("stairs", ViewObject(ViewId::DOWN_STAIRCASE, ViewLayer::FLOOR), type, tribe)
308 .setCanHide()
309 .setUsageType(FurnitureUsageType::STAIRS);
310 case FurnitureType::SOKOBAN_HOLE:
311 return Furniture("hole", ViewObject(ViewId::SOKOBAN_HOLE, ViewLayer::FLOOR), type, tribe)
312 .setEntryType(FurnitureEntry(FurnitureEntry::Sokoban{}));
313 case FurnitureType::BRIDGE:
314 return Furniture("bridge", ViewObject(ViewId::BRIDGE, ViewLayer::FLOOR), type, tribe)
315 .setOverrideMovement();
316 case FurnitureType::ROAD:
317 return Furniture("road", ViewObject(ViewId::ROAD, ViewLayer::FLOOR), type, tribe);
318 case FurnitureType::MOUNTAIN:
319 return Furniture("mountain", ViewObject(ViewId::MOUNTAIN, ViewLayer::FLOOR), type, tribe)
320 .setBlocking()
321 .setBlockVision()
322 .setConstructMessage(Furniture::FILL_UP)
323 .setIsWall()
324 .setDestroyable(200, DestroyAction::Type::BOULDER)
325 .setDestroyable(50, DestroyAction::Type::DIG)
326 .setDestroyable(200, DestroyAction::Type::HOSTILE_DIG)
327 .setDestroyable(2000, DestroyAction::Type::HOSTILE_DIG_NO_SKILL)
328 .setSummonedElement(CreatureId::EARTH_ELEMENTAL);
329 case FurnitureType::IRON_ORE:
330 return Furniture("iron ore", ViewObject(ViewId::IRON_ORE, ViewLayer::FLOOR), type, tribe)
331 .setBlocking()
332 .setBlockVision()
333 .setIsWall()
334 .setItemDrop(ItemFactory::singleType(ItemType::IronOre{}, Range(8, 14)))
335 .setDestroyable(200, DestroyAction::Type::BOULDER)
336 .setDestroyable(220, DestroyAction::Type::DIG)
337 .setDestroyable(200, DestroyAction::Type::HOSTILE_DIG)
338 .setDestroyable(2000, DestroyAction::Type::HOSTILE_DIG_NO_SKILL);
339 case FurnitureType::STONE:
340 return Furniture("granite", ViewObject(ViewId::STONE, ViewLayer::FLOOR), type, tribe)
341 .setBlocking()
342 .setBlockVision()
343 .setIsWall()
344 .setItemDrop(ItemFactory::singleType(ItemType::Rock{}, Range(8, 14)))
345 .setDestroyable(200, DestroyAction::Type::BOULDER)
346 .setDestroyable(250, DestroyAction::Type::DIG)
347 .setDestroyable(200, DestroyAction::Type::HOSTILE_DIG)
348 .setDestroyable(2000, DestroyAction::Type::HOSTILE_DIG_NO_SKILL);
349 case FurnitureType::GOLD_ORE:
350 return Furniture("gold ore", ViewObject(ViewId::GOLD_ORE, ViewLayer::FLOOR), type, tribe)
351 .setBlocking()
352 .setBlockVision()
353 .setIsWall()
354 .setItemDrop(ItemFactory::singleType(ItemType::GoldPiece{}, Range(8, 14)))
355 .setDestroyable(200, DestroyAction::Type::BOULDER)
356 .setDestroyable(220, DestroyAction::Type::DIG)
357 .setDestroyable(200, DestroyAction::Type::HOSTILE_DIG)
358 .setDestroyable(2000, DestroyAction::Type::HOSTILE_DIG_NO_SKILL);
359 case FurnitureType::DUNGEON_WALL:
360 return Furniture("wall", ViewObject(ViewId::DUNGEON_WALL, ViewLayer::FLOOR), type, tribe)
361 .setBlocking()
362 .setBlockVision()
363 .setIsWall()
364 .setConstructMessage(Furniture::REINFORCE)
365 .setDestroyable(300, DestroyAction::Type::BOULDER)
366 .setDestroyable(100, DestroyAction::Type::DIG)
367 .setDestroyable(1900, DestroyAction::Type::HOSTILE_DIG)
368 .setDestroyable(2000, DestroyAction::Type::HOSTILE_DIG_NO_SKILL);
369 case FurnitureType::CASTLE_WALL:
370 return Furniture("wall", ViewObject(ViewId::CASTLE_WALL, ViewLayer::FLOOR), type, tribe)
371 .setBlocking()
372 .setBlockVision()
373 .setIsWall()
374 .setDestroyable(300, DestroyAction::Type::BOULDER);
375 case FurnitureType::WOOD_WALL:
376 return Furniture("wall", ViewObject(ViewId::WOOD_WALL, ViewLayer::FLOOR), type, tribe)
377 .setBlocking()
378 .setBlockVision()
379 .setIsWall()
380 .setDestroyable(100, DestroyAction::Type::BOULDER)
381 .setSummonedElement(CreatureId::ENT)
382 .setFireInfo(Fire(1000, 0.7));
383 case FurnitureType::MUD_WALL:
384 return Furniture("wall", ViewObject(ViewId::MUD_WALL, ViewLayer::FLOOR), type, tribe)
385 .setBlocking()
386 .setBlockVision()
387 .setIsWall()
388 .setDestroyable(100, DestroyAction::Type::BOULDER);
389 case FurnitureType::FLOOR_WOOD1:
390 return Furniture("floor", ViewObject(ViewId::WOOD_FLOOR2, ViewLayer::FLOOR_BACKGROUND), type, tribe)
391 .setFireInfo(Fire(500, 0.5))
392 .setLayer(FurnitureLayer::FLOOR);
393 case FurnitureType::FLOOR_WOOD2:
394 return Furniture("floor", ViewObject(ViewId::WOOD_FLOOR4, ViewLayer::FLOOR_BACKGROUND), type, tribe)
395 .setFireInfo(Fire(500, 0.5))
396 .setLayer(FurnitureLayer::FLOOR);
397 case FurnitureType::FLOOR_STONE1:
398 return Furniture("floor", ViewObject(ViewId::STONE_FLOOR1, ViewLayer::FLOOR_BACKGROUND), type, tribe)
399 .setLayer(FurnitureLayer::FLOOR);
400 case FurnitureType::FLOOR_STONE2:
401 return Furniture("floor", ViewObject(ViewId::STONE_FLOOR5, ViewLayer::FLOOR_BACKGROUND), type, tribe)
402 .setLayer(FurnitureLayer::FLOOR);
403 case FurnitureType::FLOOR_CARPET1:
404 return Furniture("floor", ViewObject(ViewId::CARPET_FLOOR1, ViewLayer::FLOOR_BACKGROUND), type, tribe)
405 .setLayer(FurnitureLayer::FLOOR);
406 case FurnitureType::FLOOR_CARPET2:
407 return Furniture("floor", ViewObject(ViewId::CARPET_FLOOR4, ViewLayer::FLOOR_BACKGROUND), type, tribe)
408 .setLayer(FurnitureLayer::FLOOR);
409 case FurnitureType::ALARM_TRAP:
410 return Furniture("alarm trap", ViewObject(ViewId::ALARM_TRAP, ViewLayer::FLOOR), type, tribe)
411 .setEntryType(FurnitureEntry(FurnitureEntry::Trap(Effect::Alarm{})))
412 .setEmitsWarning()
413 .setConstructMessage(Furniture::SET_UP);
414 case FurnitureType::POISON_GAS_TRAP:
415 return Furniture("poison gas trap", ViewObject(ViewId::GAS_TRAP, ViewLayer::FLOOR), type, tribe)
416 .setEntryType(FurnitureEntry(FurnitureEntry::Trap(Effect::EmitPoisonGas{})))
417 .setEmitsWarning()
418 .setConstructMessage(Furniture::SET_UP);
419 case FurnitureType::WEB_TRAP:
420 return Furniture("web trap", ViewObject(ViewId::WEB_TRAP, ViewLayer::FLOOR), type, tribe)
421 .setEntryType(FurnitureEntry(FurnitureEntry::Trap(Effect::Lasting{LastingEffect::ENTANGLED})))
422 .setEmitsWarning()
423 .setConstructMessage(Furniture::SET_UP);
424 case FurnitureType::SPIDER_WEB:
425 return Furniture("spider web", ViewObject(ViewId::WEB_TRAP, ViewLayer::FLOOR), type, tribe)
426 .setEntryType(FurnitureEntry(FurnitureEntry::Trap(Effect::Lasting{LastingEffect::ENTANGLED},
427 true)));
428 case FurnitureType::SURPRISE_TRAP:
429 return Furniture("surprise trap", ViewObject(ViewId::SURPRISE_TRAP, ViewLayer::FLOOR), type, tribe)
430 .setEntryType(FurnitureEntry(FurnitureEntry::Trap(Effect::TeleEnemies{})))
431 .setEmitsWarning()
432 .setConstructMessage(Furniture::SET_UP);
433 case FurnitureType::TERROR_TRAP:
434 return Furniture("panic trap", ViewObject(ViewId::TERROR_TRAP, ViewLayer::FLOOR), type, tribe)
435 .setEntryType(FurnitureEntry(FurnitureEntry::Trap(Effect::Lasting{LastingEffect::PANIC})))
436 .setEmitsWarning()
437 .setConstructMessage(Furniture::SET_UP);
438 case FurnitureType::BOULDER_TRAP:
439 return Furniture("boulder trap", ViewObject(ViewId::BOULDER, ViewLayer::CREATURE), type, tribe)
440 .setBlocking()
441 .setCanHide()
442 .setTickType(FurnitureTickType::BOULDER_TRAP)
443 .setDestroyable(40)
444 .setEmitsWarning()
445 .setConstructMessage(Furniture::SET_UP);
446 case FurnitureType::PORTAL:
447 return Furniture("portal", ViewObject(ViewId::PORTAL, ViewLayer::FLOOR), type, tribe)
448 .setDestroyable(40)
449 .setUsageType(FurnitureUsageType::PORTAL)
450 .setTickType(FurnitureTickType::PORTAL);
451 case FurnitureType::METEOR_SHOWER:
452 return Furniture("meteor shower", none, type, tribe)
453 .setLayer(FurnitureLayer::CEILING)
454 .setConstructMessage(none)
455 .setTickType(FurnitureTickType::METEOR_SHOWER);
456 case FurnitureType::WATER: {
457 auto ret = Furniture("water", ViewObject(ViewId::WATER, ViewLayer::FLOOR_BACKGROUND)
458 .setAttribute(ViewObject::Attribute::WATER_DEPTH, 100.0), type, tribe)
459 .setLayer(FurnitureLayer::GROUND)
460 .setEntryType(FurnitureEntry::Water{})
461 .setDroppedItems(FurnitureDroppedItems::Water{"sinks", "sink", "You hear a splash."_s})
462 .setCanBuildBridgeOver()
463 .setSummonedElement(CreatureId::WATER_ELEMENTAL);
464 ret.modMovementSet()
465 .clearTraits()
466 .addTrait(MovementTrait::FLY)
467 .addTrait(MovementTrait::SWIM)
468 .addForcibleTrait(MovementTrait::WALK);
469 return ret;
470 }
471 case FurnitureType::SHALLOW_WATER1: {
472 auto ret = Furniture("shallow water", ViewObject(ViewId::WATER, ViewLayer::FLOOR_BACKGROUND)
473 .setAttribute(ViewObject::Attribute::WATER_DEPTH, 1.5), type, tribe)
474 .setLayer(FurnitureLayer::GROUND)
475 .setEntryType(FurnitureEntry::Water{})
476 .setCanBuildBridgeOver()
477 .setSummonedElement(CreatureId::WATER_ELEMENTAL);
478 ret.modMovementSet()
479 .clearTraits()
480 .addForcibleTrait(MovementTrait::WALK)
481 .addTrait(MovementTrait::FLY)
482 .addTrait(MovementTrait::SWIM)
483 .addTrait(MovementTrait::WADE);
484 return ret;
485 }
486 case FurnitureType::SHALLOW_WATER2: {
487 auto ret = Furniture("shallow water", ViewObject(ViewId::WATER, ViewLayer::FLOOR_BACKGROUND)
488 .setAttribute(ViewObject::Attribute::WATER_DEPTH, 0.5), type, tribe)
489 .setLayer(FurnitureLayer::GROUND)
490 .setEntryType(FurnitureEntry::Water{})
491 .setCanBuildBridgeOver()
492 .setSummonedElement(CreatureId::WATER_ELEMENTAL);
493 ret.modMovementSet()
494 .clearTraits()
495 .addForcibleTrait(MovementTrait::WALK)
496 .addTrait(MovementTrait::FLY)
497 .addTrait(MovementTrait::SWIM)
498 .addTrait(MovementTrait::WADE);
499 return ret;
500 }
501 case FurnitureType::MAGMA: {
502 auto ret = Furniture("magma", ViewObject(ViewId::MAGMA, ViewLayer::FLOOR_BACKGROUND), type, tribe)
503 .setLayer(FurnitureLayer::GROUND)
504 .setEntryType(FurnitureEntry::Magma{})
505 .setDroppedItems(FurnitureDroppedItems::Water{"burns", "burn", none})
506 .setLightEmission(8.2)
507 .setCanBuildBridgeOver()
508 .setSummonedElement(CreatureId::FIRE_ELEMENTAL);
509 ret.modMovementSet()
510 .clearTraits()
511 .addTrait(MovementTrait::FLY)
512 .addForcibleTrait(MovementTrait::WALK);
513 return ret;
514 }
515 case FurnitureType::SAND:
516 return Furniture("sand", ViewObject(ViewId::SAND, ViewLayer::FLOOR_BACKGROUND), type, tribe)
517 .setLayer(FurnitureLayer::GROUND);
518 case FurnitureType::GRASS:
519 return Furniture("grass", ViewObject(ViewId::GRASS, ViewLayer::FLOOR_BACKGROUND), type, tribe)
520 .setLayer(FurnitureLayer::GROUND);
521 case FurnitureType::MUD:
522 return Furniture("mud", ViewObject(ViewId::MUD, ViewLayer::FLOOR_BACKGROUND), type, tribe)
523 .setLayer(FurnitureLayer::GROUND);
524 case FurnitureType::HILL:
525 return Furniture("hill", ViewObject(ViewId::HILL, ViewLayer::FLOOR_BACKGROUND), type, tribe)
526 .setLayer(FurnitureLayer::GROUND);
527 case FurnitureType::FLOOR:
528 return Furniture("floor", ViewObject(ViewId::FLOOR, ViewLayer::FLOOR_BACKGROUND), type, tribe)
529 .setLayer(FurnitureLayer::GROUND);
530 case FurnitureType::BLACK_FLOOR:
531 return Furniture("floor", ViewObject(ViewId::EMPTY, ViewLayer::FLOOR_BACKGROUND), type, tribe)
532 .setLayer(FurnitureLayer::GROUND);
533 case FurnitureType::TUTORIAL_ENTRANCE:
534 return Furniture("tutorial entrance", ViewObject(ViewId::TUTORIAL_ENTRANCE, ViewLayer::TORCH2), type, tribe)
535 .setLayer(FurnitureLayer::CEILING);
536 }
537 }
538
operator ==(const FurnitureParams & p) const539 bool FurnitureParams::operator == (const FurnitureParams& p) const {
540
541 return type == p.type && tribe == p.tribe;
542 }
543
hasSupport(FurnitureType type,Position pos)544 bool FurnitureFactory::hasSupport(FurnitureType type, Position pos) {
545 switch (type) {
546 case FurnitureType::TORCH_N:
547 return pos.minus(Vec2(0, 1)).isWall();
548 case FurnitureType::TORCH_E:
549 return pos.plus(Vec2(1, 0)).isWall();
550 case FurnitureType::TORCH_S:
551 return pos.plus(Vec2(0, 1)).isWall();
552 case FurnitureType::TORCH_W:
553 return pos.minus(Vec2(1, 0)).isWall();
554 case FurnitureType::DOOR:
555 return (pos.minus(Vec2(0, 1)).isWall() && pos.minus(Vec2(0, -1)).isWall()) ||
556 (pos.minus(Vec2(1, 0)).isWall() && pos.minus(Vec2(-1, 0)).isWall());
557 default:
558 return true;
559 }
560 }
561
canBuild(FurnitureType type,Position pos)562 bool FurnitureFactory::canBuild(FurnitureType type, Position pos) {
563 switch (type) {
564 case FurnitureType::BRIDGE:
565 return pos.getFurniture(FurnitureLayer::GROUND)->canBuildBridgeOver();
566 case FurnitureType::DUNGEON_WALL:
567 if (auto furniture = pos.getFurniture(FurnitureLayer::MIDDLE))
568 return furniture->getType() == FurnitureType::MOUNTAIN;
569 else
570 return false;
571 default:
572 return pos.getFurniture(FurnitureLayer::GROUND)->getMovementSet().canEnter({MovementTrait::WALK}) &&
573 !pos.getFurniture(Furniture::getLayer(type)) &&
574 !pos.isWall();
575 }
576 }
577
isUpgrade(FurnitureType base,FurnitureType upgraded)578 bool FurnitureFactory::isUpgrade(FurnitureType base, FurnitureType upgraded) {
579 switch (base) {
580 case FurnitureType::TRAINING_WOOD:
581 return upgraded == FurnitureType::TRAINING_IRON || upgraded == FurnitureType::TRAINING_STEEL;
582 case FurnitureType::TRAINING_IRON:
583 return upgraded == FurnitureType::TRAINING_STEEL;
584 case FurnitureType::BOOKCASE_WOOD:
585 return upgraded == FurnitureType::BOOKCASE_IRON || upgraded == FurnitureType::BOOKCASE_GOLD;
586 case FurnitureType::BOOKCASE_IRON:
587 return upgraded == FurnitureType::BOOKCASE_GOLD;
588 default:
589 return false;
590 }
591 }
592
getUpgrades(FurnitureType base)593 const vector<FurnitureType>& FurnitureFactory::getUpgrades(FurnitureType base) {
594 static EnumMap<FurnitureType, vector<FurnitureType>> upgradeMap(
595 [](const FurnitureType& base) {
596 vector<FurnitureType> ret;
597 for (auto type2 : ENUM_ALL(FurnitureType))
598 if (FurnitureFactory::isUpgrade(base, type2))
599 ret.push_back(type2);
600 return ret;
601 });
602 return upgradeMap[base];
603 }
604
FurnitureFactory(TribeId t,const EnumMap<FurnitureType,double> & d,const vector<FurnitureType> & u)605 FurnitureFactory::FurnitureFactory(TribeId t, const EnumMap<FurnitureType, double>& d,
606 const vector<FurnitureType>& u) : tribe(t), distribution(d), unique(u) {
607 }
608
FurnitureFactory(TribeId t,FurnitureType f)609 FurnitureFactory::FurnitureFactory(TribeId t, FurnitureType f) : tribe(t), distribution({{f, 1}}) {
610 }
611
get(FurnitureType type,TribeId tribe)612 PFurniture FurnitureFactory::get(FurnitureType type, TribeId tribe) {
613 return makeOwner<Furniture>(::get(type, tribe));
614 }
615
roomFurniture(TribeId tribe)616 FurnitureFactory FurnitureFactory::roomFurniture(TribeId tribe) {
617 return FurnitureFactory(tribe, {
618 {FurnitureType::BED, 2},
619 {FurnitureType::GROUND_TORCH, 1},
620 {FurnitureType::CHEST, 2}
621 });
622 }
623
castleFurniture(TribeId tribe)624 FurnitureFactory FurnitureFactory::castleFurniture(TribeId tribe) {
625 return FurnitureFactory(tribe, {
626 {FurnitureType::BED, 2},
627 {FurnitureType::GROUND_TORCH, 1},
628 {FurnitureType::FOUNTAIN, 1},
629 {FurnitureType::CHEST, 2}
630 });
631 }
632
dungeonOutside(TribeId tribe)633 FurnitureFactory FurnitureFactory::dungeonOutside(TribeId tribe) {
634 return FurnitureFactory(tribe, {
635 {FurnitureType::GROUND_TORCH, 1},
636 });
637 }
638
castleOutside(TribeId tribe)639 FurnitureFactory FurnitureFactory::castleOutside(TribeId tribe) {
640 return FurnitureFactory(tribe, {
641 {FurnitureType::GROUND_TORCH, 1},
642 {FurnitureType::WELL, 1},
643 });
644 }
645
villageOutside(TribeId tribe)646 FurnitureFactory FurnitureFactory::villageOutside(TribeId tribe) {
647 return FurnitureFactory(tribe, {
648 {FurnitureType::GROUND_TORCH, 1},
649 {FurnitureType::WELL, 1},
650 });
651 }
652
cryptCoffins(TribeId tribe)653 FurnitureFactory FurnitureFactory::cryptCoffins(TribeId tribe) {
654 return FurnitureFactory(tribe, {
655 {FurnitureType::COFFIN, 1},
656 }, {
657 FurnitureType::VAMPIRE_COFFIN
658 });
659 }
660
getWaterType(double depth)661 FurnitureType FurnitureFactory::getWaterType(double depth) {
662 if (depth >= 2.0)
663 return FurnitureType::WATER;
664 else if (depth >= 1.0)
665 return FurnitureType::SHALLOW_WATER1;
666 else
667 return FurnitureType::SHALLOW_WATER2;
668 }
669
getRandom(RandomGen & random)670 FurnitureParams FurnitureFactory::getRandom(RandomGen& random) {
671 if (!unique.empty()) {
672 FurnitureType f = unique.back();
673 unique.pop_back();
674 return {f, *tribe};
675 } else
676 return {random.choose(distribution), *tribe};
677 }
678
679