1 /* Copyright (C) 2013-2014 Michal Brzozowski (rusolis@poczta.fm)
2
3 This file is part of KeeperRL.
4
5 KeeperRL is free software; you can redistribute it and/or modify it under the terms of the
6 GNU General Public License as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 KeeperRL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with this program.
14 If not, see http://www.gnu.org/licenses/ . */
15
16 #include "stdafx.h"
17
18 #include "view_object.h"
19 #include "view_id.h"
20 #include "experience_type.h"
21
22 SERIALIZE_DEF(ViewObject, resource_id, viewLayer, description, modifiers, attributes, attachmentDir, creatureId, goodAdjectives, badAdjectives, creatureAttributes)
23
24 SERIALIZATION_CONSTRUCTOR_IMPL(ViewObject);
25
ViewObject(ViewId id,ViewLayer l,const string & d)26 ViewObject::ViewObject(ViewId id, ViewLayer l, const string& d)
27 : resource_id(id), viewLayer(l), description(d) {
28 }
29
ViewObject(ViewId id,ViewLayer l)30 ViewObject::ViewObject(ViewId id, ViewLayer l)
31 : resource_id(id), viewLayer(l) {
32 }
33
setCreatureId(UniqueEntity<Creature>::Id id)34 void ViewObject::setCreatureId(UniqueEntity<Creature>::Id id) {
35 creatureId = id;
36 }
37
getCreatureId() const38 optional<UniqueEntity<Creature>::Id> ViewObject::getCreatureId() const {
39 return creatureId;
40 }
41
MovementInfo(Vec2 dir,double b,double e,Type t)42 MovementInfo::MovementInfo(Vec2 dir, double b, double e, Type t) : direction(dir), tBegin(b), tEnd(e),
43 type(t) {
44 }
45
MovementInfo()46 MovementInfo::MovementInfo() {
47 }
48
addMovementInfo(MovementInfo info)49 void ViewObject::addMovementInfo(MovementInfo info) {
50 movementQueue.add(info);
51 }
52
hasAnyMovementInfo() const53 bool ViewObject::hasAnyMovementInfo() const {
54 return movementQueue.hasAny();
55 }
56
getLastMovementInfo() const57 MovementInfo ViewObject::getLastMovementInfo() const {
58 return movementQueue.getLast();
59 }
60
getMovementInfo(double tBegin) const61 Vec2 ViewObject::getMovementInfo(double tBegin) const {
62 if (!movementQueue.hasAny())
63 return Vec2(0, 0);
64 CHECK(creatureId);
65 return movementQueue.getTotalMovement(tBegin);
66 }
67
clearMovementInfo()68 void ViewObject::clearMovementInfo() {
69 movementQueue.clear();
70 }
71
clear()72 void ViewObject::MovementQueue::clear() {
73 index = totalMoves = 0;
74 }
75
add(MovementInfo info)76 void ViewObject::MovementQueue::add(MovementInfo info) {
77 elems[index] = info;
78 ++totalMoves;
79 index = makeGoodIndex(index + 1);
80 }
81
getLast() const82 const MovementInfo& ViewObject::MovementQueue::getLast() const {
83 CHECK(hasAny());
84 return elems[makeGoodIndex(index - 1)];
85 }
86
getTotalMovement(double tBegin) const87 Vec2 ViewObject::MovementQueue::getTotalMovement(double tBegin) const {
88 Vec2 ret;
89 bool attack = false;
90 for (int i : Range(min<int>(totalMoves, elems.size())))
91 if (elems[i].tBegin >= tBegin) {
92 if (elems[i].type == MovementInfo::ATTACK/* && ret.length8() == 0*/) {
93 attack = true;
94 ret = elems[i].direction;
95 } else {
96 if (attack) {
97 attack = false;
98 ret = Vec2(0, 0);
99 }
100 ret += elems[i].direction;
101 }
102 }
103 return ret;
104 }
105
hasAny() const106 bool ViewObject::MovementQueue::hasAny() const {
107 return totalMoves > 0;
108 }
109
makeGoodIndex(int index) const110 int ViewObject::MovementQueue::makeGoodIndex(int index) const {
111 return (index + elems.size()) % elems.size();
112 }
113
setModifier(Modifier mod)114 ViewObject& ViewObject::setModifier(Modifier mod) {
115 modifiers.insert(mod);
116 return *this;
117 }
118
removeModifier(Modifier mod)119 ViewObject& ViewObject::removeModifier(Modifier mod) {
120 modifiers.erase(mod);
121 return *this;
122 }
123
hasModifier(Modifier mod) const124 bool ViewObject::hasModifier(Modifier mod) const {
125 return modifiers.contains(mod);
126 }
127
setAttribute(Attribute attr,double d)128 ViewObject& ViewObject::setAttribute(Attribute attr, double d) {
129 attributes[attr] = d;
130 return *this;
131 }
132
getAttribute(Attribute attr) const133 optional<float> ViewObject::getAttribute(Attribute attr) const {
134 return attributes[attr];
135 }
136
setCreatureAttributes(ViewObject::CreatureAttributes attribs)137 void ViewObject::setCreatureAttributes(ViewObject::CreatureAttributes attribs) {
138 creatureAttributes = attribs;
139 }
140
getCreatureAttributes() const141 const optional<ViewObject::CreatureAttributes>& ViewObject::getCreatureAttributes() const {
142 return creatureAttributes;
143 }
144
setDescription(const string & s)145 void ViewObject::setDescription(const string& s) {
146 description = s;
147 }
148
getDefaultDescription() const149 const char* ViewObject::getDefaultDescription() const {
150 switch (resource_id) {
151 case ViewId::UNKNOWN_MONSTER: return "Unknown creature";
152 case ViewId::ALTAR: return "Shrine";
153 case ViewId::UP_STAIRCASE:
154 case ViewId::DOWN_STAIRCASE: return "Stairs";
155 case ViewId::BRIDGE: return "Bridge";
156 case ViewId::GRASS: return "Grass";
157 case ViewId::CROPS2:
158 case ViewId::CROPS: return "Wheat";
159 case ViewId::MUD: return "Mud";
160 case ViewId::ROAD: return "Road";
161 case ViewId::CASTLE_WALL:
162 case ViewId::MUD_WALL:
163 case ViewId::WALL: return "Wall";
164 case ViewId::GOLD_ORE: return "Gold ore";
165 case ViewId::IRON_ORE: return "Iron ore";
166 case ViewId::STONE: return "Granite";
167 case ViewId::WOOD_WALL: return "Wooden wall";
168 case ViewId::MOUNTAIN: return "Mountain";
169 case ViewId::HILL: return "Hill";
170 case ViewId::WATER: return "Water";
171 case ViewId::MAGMA: return "Magma";
172 case ViewId::SAND: return "Sand";
173 case ViewId::DECID_TREE:
174 case ViewId::CANIF_TREE: return "Tree";
175 case ViewId::BUSH: return "Bush";
176 case ViewId::TREE_TRUNK: return "Tree trunk";
177 case ViewId::BURNT_TREE: return "Burnt tree";
178 case ViewId::BED: return "Bed";
179 case ViewId::DORM: return "Dormitory";
180 case ViewId::TORCH: return "Torch";
181 case ViewId::PRISON: return "Prison";
182 case ViewId::WELL: return "Well";
183 case ViewId::TORTURE_TABLE: return "Torture room";
184 case ViewId::BEAST_CAGE: return "Beast cage";
185 case ViewId::TRAINING_WOOD: return "Wooden training dummy";
186 case ViewId::TRAINING_IRON: return "Iron training dummy";
187 case ViewId::TRAINING_STEEL: return "Steel training dummy";
188 case ViewId::THRONE: return "Throne";
189 case ViewId::WHIPPING_POST: return "Whipping post";
190 case ViewId::NOTICE_BOARD: return "Message board";
191 case ViewId::SOKOBAN_HOLE: return "Hole";
192 case ViewId::DEMON_SHRINE: return "Demon shrine";
193 case ViewId::IMPALED_HEAD: return "Impaled head";
194 case ViewId::EYEBALL: return "Eyeball";
195 case ViewId::BOOKCASE_WOOD: return "Wooden bookcase";
196 case ViewId::BOOKCASE_IRON: return "Iron bookcase";
197 case ViewId::BOOKCASE_GOLD: return "Golden bookcase";
198 case ViewId::CAULDRON: return "Cauldron";
199 case ViewId::LABORATORY: return "Laboratory";
200 case ViewId::FORGE: return "Forge";
201 case ViewId::WORKSHOP: return "Workshop";
202 case ViewId::JEWELER: return "Jeweler";
203 case ViewId::STEEL_FURNACE: return "Steel furnace";
204 case ViewId::MINION_STATUE: return "Statue";
205 case ViewId::CREATURE_ALTAR: return "Shrine";
206 case ViewId::FOUNTAIN: return "Fountain";
207 case ViewId::TREASURE_CHEST:
208 case ViewId::CHEST: return "Chest";
209 case ViewId::OPENED_CHEST: return "Opened chest";
210 case ViewId::COFFIN: return "Coffin";
211 case ViewId::CEMETERY: return "Cemetery";
212 case ViewId::GRAVE: return "Grave";
213 case ViewId::DOOR: return "Door (click to lock)";
214 case ViewId::LOCKED_DOOR: return "Door (click to unlock)";
215 case ViewId::BARRICADE: return "Barricade";
216 case ViewId::WOOD_FLOOR1:
217 case ViewId::WOOD_FLOOR2:
218 case ViewId::STONE_FLOOR1:
219 case ViewId::STONE_FLOOR2:
220 case ViewId::CARPET_FLOOR1:
221 case ViewId::CARPET_FLOOR2:
222 case ViewId::KEEPER_FLOOR:
223 case ViewId::FLOOR: return "Floor";
224 case ViewId::BORDER_GUARD: return "Wall";
225 default: return "";
226 }
227 }
228
getDescription() const229 const char* ViewObject::getDescription() const {
230 if (description)
231 return description->c_str();
232 else
233 return getDefaultDescription();
234 }
235
setAttachmentDir(Dir dir)236 ViewObject& ViewObject::setAttachmentDir(Dir dir) {
237 attachmentDir = dir;
238 return *this;
239 }
240
getAttachmentDir() const241 optional<Dir> ViewObject::getAttachmentDir() const {
242 return attachmentDir;
243 }
244
getAttributeString(Attribute attr) const245 string ViewObject::getAttributeString(Attribute attr) const {
246 if (attr == Attribute::EFFICIENCY)
247 return toString<int>(*getAttribute(attr) * 100);
248 else
249 return toString(*getAttribute(attr));
250 }
251
layer() const252 ViewLayer ViewObject::layer() const {
253 return viewLayer;
254 }
255
256 static vector<ViewId> creatureIds {
257 ViewId::PLAYER,
258 ViewId::KEEPER,
259 ViewId::RETIRED_KEEPER,
260 ViewId::ELF,
261 ViewId::ELF_ARCHER,
262 ViewId::ELF_CHILD,
263 ViewId::ELF_LORD,
264 ViewId::SHOPKEEPER,
265 ViewId::LIZARDMAN,
266 ViewId::LIZARDLORD,
267 ViewId::DWARF,
268 ViewId::DWARF_BARON,
269 ViewId::IMP,
270 ViewId::PRISONER,
271 ViewId::OGRE,
272 ViewId::CHICKEN,
273 ViewId::GREEN_DRAGON,
274 ViewId::RED_DRAGON,
275 ViewId::CYCLOPS,
276 ViewId::WITCH,
277 ViewId::GHOST,
278 ViewId::SPIRIT,
279 ViewId::KNIGHT,
280 ViewId::DUKE,
281 ViewId::ARCHER,
282 ViewId::UNICORN,
283 ViewId::PESEANT,
284 ViewId::CHILD,
285 ViewId::SHAMAN,
286 ViewId::WARRIOR,
287 ViewId::ORC,
288 ViewId::DEMON_DWELLER,
289 ViewId::DEMON_LORD,
290 ViewId::BANDIT,
291 ViewId::CLAY_GOLEM,
292 ViewId::STONE_GOLEM,
293 ViewId::IRON_GOLEM,
294 ViewId::LAVA_GOLEM,
295 ViewId::ZOMBIE,
296 ViewId::SKELETON,
297 ViewId::VAMPIRE,
298 ViewId::VAMPIRE_LORD,
299 ViewId::MUMMY,
300 ViewId::HORSE,
301 ViewId::COW,
302 ViewId::PIG,
303 ViewId::GOAT,
304 ViewId::JACKAL,
305 ViewId::DEER,
306 ViewId::BOAR,
307 ViewId::FOX,
308 ViewId::BEAR,
309 ViewId::WOLF,
310 ViewId::BAT,
311 ViewId::RAT,
312 ViewId::SPIDER,
313 ViewId::FLY,
314 ViewId::SNAKE,
315 ViewId::VULTURE,
316 ViewId::RAVEN,
317 ViewId::GOBLIN,
318 ViewId::KRAKEN_HEAD,
319 ViewId::KRAKEN_LAND,
320 ViewId::KRAKEN_WATER,
321 ViewId::FIRE_SPHERE,
322 ViewId::DEATH,
323 ViewId::SPECIAL_BLBN,
324 ViewId::SPECIAL_BLBW,
325 ViewId::SPECIAL_BLGN,
326 ViewId::SPECIAL_BLGW,
327 ViewId::SPECIAL_BMBN,
328 ViewId::SPECIAL_BMBW,
329 ViewId::SPECIAL_BMGN,
330 ViewId::SPECIAL_BMGW,
331 ViewId::SPECIAL_HLBN,
332 ViewId::SPECIAL_HLBW,
333 ViewId::SPECIAL_HLGN,
334 ViewId::SPECIAL_HLGW,
335 ViewId::SPECIAL_HMBN,
336 ViewId::SPECIAL_HMBW,
337 ViewId::SPECIAL_HMGN,
338 ViewId::SPECIAL_HMGW,
339 ViewId::CANIF_TREE,
340 ViewId::DECID_TREE,
341 };
342
343 static vector<ViewId> itemIds {
344 ViewId::BODY_PART,
345 ViewId::BONE,
346 ViewId::SPEAR,
347 ViewId::SWORD,
348 ViewId::SPECIAL_SWORD,
349 ViewId::ELVEN_SWORD,
350 ViewId::KNIFE,
351 ViewId::WAR_HAMMER,
352 ViewId::SPECIAL_WAR_HAMMER,
353 ViewId::BATTLE_AXE,
354 ViewId::SPECIAL_BATTLE_AXE,
355 ViewId::BOW,
356 ViewId::ELVEN_BOW,
357 ViewId::SCROLL,
358 ViewId::AMULET1,
359 ViewId::AMULET2,
360 ViewId::AMULET3,
361 ViewId::AMULET4,
362 ViewId::AMULET5,
363 ViewId::BOOK,
364 ViewId::FIRST_AID,
365 ViewId::POTION1,
366 ViewId::POTION2,
367 ViewId::POTION3,
368 ViewId::POTION4,
369 ViewId::POTION5,
370 ViewId::POTION6,
371 ViewId::GOLD,
372 ViewId::LEATHER_ARMOR,
373 ViewId::LEATHER_HELM,
374 ViewId::TELEPATHY_HELM,
375 ViewId::CHAIN_ARMOR,
376 ViewId::IRON_HELM,
377 ViewId::LEATHER_BOOTS,
378 ViewId::IRON_BOOTS,
379 ViewId::SPEED_BOOTS,
380 ViewId::BOULDER,
381 ViewId::PORTAL,
382 ViewId::GAS_TRAP,
383 ViewId::ALARM_TRAP,
384 ViewId::WEB_TRAP,
385 ViewId::SURPRISE_TRAP,
386 ViewId::TERROR_TRAP,
387 ViewId::ROCK,
388 ViewId::IRON_ROCK,
389 ViewId::WOOD_PLANK,
390 ViewId::MUSHROOM1,
391 ViewId::MUSHROOM2,
392 ViewId::MUSHROOM3,
393 ViewId::MUSHROOM4,
394 ViewId::MUSHROOM5,
395 ViewId::MUSHROOM6
396 };
397
398 static bool hallu = false;
399
400 vector<ViewId> shuffledCreatures;
401 vector<ViewId> shuffledItems;
402
setHallu(bool b)403 void ViewObject::setHallu(bool b) {
404 if (!hallu && b) {
405 shuffledCreatures = Random.permutation(creatureIds);
406 shuffledItems = Random.permutation(itemIds);
407 }
408 hallu = b;
409 }
410
setId(ViewId id)411 void ViewObject::setId(ViewId id) {
412 resource_id = id;
413 }
414
setGoodAdjectives(const string & v)415 void ViewObject::setGoodAdjectives(const string& v) {
416 goodAdjectives = v;
417 }
418
setBadAdjectives(const string & v)419 void ViewObject::setBadAdjectives(const string& v) {
420 badAdjectives = v;
421 }
422
getGoodAdjectives() const423 const string& ViewObject::getGoodAdjectives() const {
424 return goodAdjectives;
425 }
426
getBadAdjectives() const427 const string& ViewObject::getBadAdjectives() const {
428 return badAdjectives;
429 }
430
id() const431 ViewId ViewObject::id() const {
432 if (hallu) {
433 if (auto elem = creatureIds.findElement(resource_id))
434 return shuffledCreatures[*elem];
435 if (auto elem = itemIds.findElement(resource_id))
436 return shuffledItems[*elem];
437 }
438 return resource_id;
439 }
440
unknownMonster()441 const ViewObject& ViewObject::unknownMonster() {
442 static ViewObject ret(ViewId::UNKNOWN_MONSTER, ViewLayer::CREATURE);
443 return ret;
444 }
445
empty()446 const ViewObject& ViewObject::empty() {
447 static ViewObject ret(ViewId::BORDER_GUARD, ViewLayer::FLOOR);
448 return ret;
449 }
450