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