freg  0.3
Free-Roaming Elementary Game
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Block.cpp
Go to the documentation of this file.
1  /* freg, Free-Roaming Elementary Game with open and interactive world
2  * Copyright (C) 2012-2014 Alexander 'mmaulwurff' Kromm
3  * mmaulwurff@gmail.com
4  *
5  * This file is part of FREG.
6  *
7  * FREG is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * FREG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with FREG. If not, see <http://www.gnu.org/licenses/>. */
19 
20 #include "blocks/Block.h"
21 #include "BlockManager.h"
22 #include "World.h"
23 #include "Inventory.h"
24 
25 const static QString dir_strings[] = {
26  QObject::tr("Up"),
27  QObject::tr("Down"),
28  QObject::tr("North"),
29  QObject::tr("South"),
30  QObject::tr("East"),
31  QObject::tr("West")
32 };
33 
34 const static QString sub_names[] = {
35  QObject::tr("stone"),
36  QObject::tr("stone"),
37  QObject::tr("nullstone"),
38  QObject::tr("air"),
39  QObject::tr("air"),
40  QObject::tr("diamond"),
41  QObject::tr("soil"),
42  QObject::tr("meat of rational"),
43  QObject::tr("meat"),
44  QObject::tr("glass"),
45  QObject::tr("wood"),
46  QObject::tr("different"),
47  QObject::tr("iron"),
48  QObject::tr("water"),
49  QObject::tr("greenery"),
50  QObject::tr("sand"),
51  QObject::tr("hazelnut"),
52  QObject::tr("rose"),
53  QObject::tr("clay"),
54  QObject::tr("air"),
55  QObject::tr("paper"),
56  QObject::tr("gold"),
57  QObject::tr("bone"),
58  QObject::tr("steel"),
59  QObject::tr("adamantine"),
60  QObject::tr("fire"),
61  QObject::tr("coal"),
62  QObject::tr("explosive"),
63  QObject::tr("acid"),
64  QObject::tr("cloud"),
65  QObject::tr("dust"),
66  QObject::tr("plastic"),
67 };
68 
69 QString Block::SubName(const int sub) {
70  static_assert(sizeof_array(sub_names) == LAST_SUB,
71  "invalid number of strings in sub_names");
72  return sub_names[sub];
73 }
74 
75 QString Block::DirString(const dirs dir) { return dir_strings[dir]; }
76 
77 QString Block::SubNameUpper(const int sub) {
78  QString result = SubName(sub);
79  result.replace(0, 1, result.at(0).toUpper());
80  return result;
81 }
82 
83 dirs Block::MakeDirFromDamage(const int dmg_kind) {
84  Q_ASSERT(dmg_kind >= DAMAGE_PUSH_UP);
85  return static_cast<dirs>(dmg_kind - DAMAGE_PUSH_UP);
86 }
87 
88 QString Block::FullName() const {
89  switch ( Sub() ) {
90  default: return SubNameUpper(Sub());
91  case WATER: return QObject::tr("Ice");
92  case SAND: return QObject::tr("Sandstone");
93  case CLAY: return QObject::tr("Clay brick");
94  case ACID: return QObject::tr("Acid concentrate");
95  case IRON:
96  case GOLD:
97  case COAL: return QObject::tr("Block (%1)").arg(SubName(Sub()));
98  }
99 }
100 
101 int Block::Transparency(const int transp, const int sub) const {
102  if ( UNDEF == transp ) {
103  switch ( sub ) {
104  default: return BLOCK_OPAQUE;
105  case AIR: return INVISIBLE;
106  case WATER:
107  case GREENERY:
108  case ACID:
109  case SUB_CLOUD:
110  case GLASS: return BLOCK_TRANSPARENT;
111  }
112  } else {
113  return transp;
114  }
115 }
116 
117 void Block::Damage(const int dmg, int dmg_kind) {
118  if ( dmg_kind > DAMAGE_PUSH_UP ) {
119  dmg_kind = DAMAGE_PUSH_UP;
120  }
121  // Fragile or undestructible substances:
122  switch ( Sub() ) {
123  case SUB_DUST:
124  case GREENERY:
125  case ROSE:
126  case SUB_NUT: durability = 0; return;
127  case NULLSTONE:
128  case STAR:
129  case AIR:
130  case SKY: return;
131  }
132  // Special damage kinds:
133  switch ( dmg_kind ) {
134  case DAMAGE_PUSH_UP: switch ( Sub() ) {
135  default: return;
136  case A_MEAT:
137  case H_MEAT: durability -= dmg * ( dmg > 10 ); return;
138  case GLASS: durability -= dmg * (MAX_DURABILITY+9) / 10; return;
139  } break;
140  case DAMAGE_HANDS: switch ( Sub() ) {
141  default: return;
142  case SOIL:
143  case A_MEAT:
144  case H_MEAT: break;
145  } break;
146  case DAMAGE_ULTIMATE: durability = 0; return;
147  case DAMAGE_NO: return;
148  case DAMAGE_TIME: durability -= dmg; return;
149  case DAMAGE_ACID:
150  switch ( Sub() ) {
151  default: durability -= 2 * dmg; return;
152  case DIFFERENT: durability = 0; return;
153  case ACID:
154  case ADAMANTINE:
155  case GLASS: return;
156  } break;
157  }
158  // Common substances and damage kinds:
159  int mult = 1; // default
160  switch ( Sub() ) {
161  case DIFFERENT: return;
162  case MOSS_STONE:
163  case STONE: switch ( dmg_kind ) {
164  case DAMAGE_HEAT:
165  case DAMAGE_CUT: return;
166  case DAMAGE_MINE: mult = 2; break;
167  } break;
168  case WOOD: mult += ( DAMAGE_CUT == dmg_kind ); break;
169  case A_MEAT:
170  case H_MEAT: switch ( dmg_kind ) {
171  case DAMAGE_HEAT:
172  case DAMAGE_THRUST: mult = 2; break;
173  } break;
174  case SAND:
175  case SOIL: mult += ( DAMAGE_DIG == dmg_kind ); break;
176  case ADAMANTINE:
177  case FIRE: mult = ( DAMAGE_FREEZE == dmg_kind ); break;
178  case WATER: mult = ( DAMAGE_HEAT == dmg_kind ); break;
179  case GLASS: durability *= ( DAMAGE_HEAT == dmg_kind ); return;
180  }
181  durability -= mult * dmg;
182 } // Block::Damage(const ind dmg, const int dmg_kind)
183 
184 Block * Block::DropAfterDamage(bool * const delete_block) {
185  switch ( Sub() ) {
186  case SUB_DUST:
187  case GLASS:
188  case AIR: return block_manager.Normal(AIR);
189  case STONE: if ( BLOCK==Kind() ) {
191  } // no break;
192  default: {
193  Block * const pile = BlockManager::NewBlock(BOX, DIFFERENT);
194  pile->HasInventory()->Get(this);
195  *delete_block = false;
196  return pile;
197  }
198  }
199 }
200 
202  return ( AIR==Sub() ) ? ENVIRONMENT : NOT_MOVABLE;
203 }
204 
205 int Block::GetId() const { return BlockManager::MakeId(Kind(), Sub()); }
206 bool Block::Catchable() const { return false; }
208 int Block::DamageKind() const { return DAMAGE_CRUSH; }
209 int Block::DamageLevel() const { return 1; }
210 int Block::LightRadius() const { return 0; }
211 void Block::ReceiveSignal(QString) {}
215 
216 bool Block::Inscribe(const QString str) {
217  if ( Sub() == AIR ) return false;
218  noteId = ( noteId == 0 ) ? // new note
219  world->SetNote(str.left(MAX_NOTE_LENGTH)) :
220  world->ChangeNote(str.left(MAX_NOTE_LENGTH), noteId);
221  return true;
222 }
223 
224 Inventory * Block::HasInventory() { return nullptr; }
225 Animal * Block::IsAnimal() { return nullptr; }
226 Active * Block::ActiveBlock() { return nullptr; }
227 Falling * Block::ShouldFall() { return nullptr; }
228 
230 void Block::Break() { durability = 0; }
231 dirs Block::GetDir() const { return static_cast<dirs>(direction); }
232 int Block::GetDurability() const { return durability; }
233 
234 QString Block::GetNote() const {
235  return (noteId == 0) ? QString() : world->GetNote(noteId);
236 }
237 
238 void Block::Mend(const int plus) {
239  durability = qMin(MAX_DURABILITY, durability+plus);
240 }
241 
242 int Block::Weight() const {
243  switch ( Sub() ) {
244  default: return WEIGHT_WATER;
245  case SUB_CLOUD:
246  case AIR: return WEIGHT_AIR;
247  case STONE: return WEIGHT_STONE;
248  case SOIL: return WEIGHT_SAND+WEIGHT_WATER;
249  case GREENERY: return WEIGHT_GREENERY;
250  case NULLSTONE: return WEIGHT_NULLSTONE;
251  case SAND: return WEIGHT_SAND;
252  case GLASS: return WEIGHT_GLASS;
253  case WOOD: return WEIGHT_WATER-1;
254  case IRON: return WEIGHT_IRON;
255  case PAPER:
256  case ROSE:
257  case SUB_NUT: return WEIGHT_MINIMAL;
258  case MOSS_STONE:
259  case A_MEAT:
260  case H_MEAT: return WEIGHT_WATER+10;
261  case SKY:
262  case STAR:
263  case FIRE:
264  case DIFFERENT: return WEIGHT_WATER;
265  case SUB_DUST: return WEIGHT_MINIMAL;
266  }
267 }
268 
269 void Block::SetDir(const int dir) {
270  if ( BLOCK!=Kind() || WOOD==Sub() ) {
271  direction = dir;
272  }
273 }
274 
276  switch ( sub ) {
277  default: return GROUP_NONE;
278  case AIR:
279  case SKY:
280  case STAR: return GROUP_AIR;
281 
282  case H_MEAT:
283  case A_MEAT: return GROUP_MEAT;
284 
285  case STONE:
286  case DIAMOND:
287  case WOOD:
288  case BONE: return GROUP_HANDY;
289 
290  case IRON:
291  case GOLD:
292  case ADAMANTINE:
293  case STEEL: return GROUP_METAL;
294  }
295 }
296 
297 bool Block::operator!=(const Block & block) const { return !(*this == block); }
298 
299 bool Block::operator==(const Block & block) const {
300  return ( block.Kind() == Kind()
301  && block.Sub() == Sub()
302  && block.GetDurability() == GetDurability()
303  && block.GetDir() == GetDir()
304  && block.GetNote() == GetNote() );
305 }
306 
307 void Block::SaveAttributes(QDataStream &) const {}
308 
309 void Block::SaveToFile(QDataStream & out) {
310  if ( this == block_manager.Normal(sub) ) {
311  SaveNormalToFile(out);
312  } else {
313  out << sub << kind <<
314  ( ( ( ( durability
315  <<= 3 ) |= direction )
316  <<= 1 ) |= (noteId != 0) );
317  if ( Q_UNLIKELY(noteId != 0) ) {
318  out << noteId;
319  }
320  SaveAttributes(out);
321  }
322 }
323 
324 void Block::SaveNormalToFile(QDataStream & out) const {
325  out << quint8( 0x80 | sub );
326 }
327 
329 
330 Block::Block(const int kind_, const int sub_, const int transp) :
331  noteId(0),
332  durability(MAX_DURABILITY),
333  transparent(Transparency(transp, sub_)),
334  kind(kind_),
335  sub(sub_),
336  direction(UP)
337 {}
338 
339 Block::Block(QDataStream & str, const int kind_, const int sub_,
340  const int transp)
341  :
342  noteId(),
343  durability(),
344  transparent(Transparency(transp, sub_)),
345  kind(kind_),
346  sub(sub_),
347  direction()
348 {
349  // use durability as buffer, set actual value in the end:
350  str >> durability;
351  if ( Q_UNLIKELY(durability & 1) ) {
352  str >> noteId;
353  }
354  direction = ( durability >>= 1 ) & 0x7;
355  durability >>= 3;
356 }
357 
virtual usage_types UseOnShredMove(Block *user)
Definition: Block.cpp:214
const int MAX_DURABILITY
10 bits to store durability in file, signed.
Definition: World.h:43
virtual QString FullName() const
Definition: Block.cpp:88
virtual void SaveAttributes(QDataStream &) const
Definition: Block.cpp:307
quint16 noteId
To convert DAMAGE_PUSH_UP...WEST to corresponding direction.
Definition: Block.h:169
void Mend(int plus)
Increase durability, no more than MAX_DURABILITY.
Definition: Block.cpp:238
16
Definition: header.h:176
void SaveNormalToFile(QDataStream &out) const
Definition: Block.cpp:324
10
Definition: header.h:170
int Transparency(int transp, int sub) const
Definition: Block.cpp:101
void SetDir(int dir)
Definition: Block.cpp:269
virtual bool Catchable() const
Definition: Block.cpp:206
BlockManager block_manager
29
Definition: header.h:189
push_reaction
Definition: header.h:95
static QString SubName(int sub)
Returns translated substance name.
Definition: Block.cpp:69
World * world
Definition: World.cpp:32
28
Definition: header.h:188
static QString SubNameUpper(int sub)
Returns translated substance name with first upper letter.
Definition: Block.cpp:77
Definition: header.h:211
void RestoreDurabilityAfterSave()
Importart! Use it if block won't be deleted after SaveToFile.
Definition: Block.cpp:328
virtual void Damage(int dmg, int dmg_kind)
Definition: Block.cpp:117
13
Definition: Block.h:52
virtual int DamageKind() const
Definition: Block.cpp:208
Block * Normal(int sub) const
Use this to receive a pointer to normal block.
virtual int Weight() const
Definition: Block.cpp:242
0
Definition: header.h:87
18
Definition: header.h:178
4
Definition: header.h:164
21
Definition: header.h:181
sub_groups
Definition: Block.h:76
virtual push_reaction PushResult(dirs) const
Definition: Block.cpp:201
virtual bool Get(Block *block, int start=0)
Returns true on success.
Definition: Inventory.cpp:78
0
Definition: header.h:115
dirs GetDir() const
Definition: Block.cpp:231
Nothing is made from LAST_SUB.
Definition: header.h:193
int SetNote(QString note)
Definition: World.cpp:133
static sub_groups GetSubGroup(int sub)
Definition: Block.cpp:275
2
Definition: Block.h:41
void Restore()
Set maximum durability.
Definition: Block.cpp:229
26
Definition: header.h:186
virtual Inventory * HasInventory()
Definition: Block.cpp:224
bool operator==(const Block &) const
Definition: Block.cpp:299
6
Definition: header.h:166
7 (hominid meat)
Definition: header.h:167
QString GetNote(int note_id) const
Definition: World.cpp:147
5
Definition: Block.h:44
weights in measures - mz (mezuro)
Definition: Block.h:65
1
Definition: Block.h:40
virtual int LightRadius() const
Definition: Block.cpp:210
9
Definition: header.h:169
14
Definition: Block.h:53
11
Definition: header.h:171
static dirs MakeDirFromDamage(int damage_kind)
Definition: Block.cpp:83
bool operator!=(const Block &) const
Definition: Block.cpp:297
3
Definition: header.h:163
20
Definition: header.h:180
virtual int DamageLevel() const
Definition: Block.cpp:209
Provides declaration for class Inventory for freg.
virtual Falling * ShouldFall()
Definition: Block.cpp:227
static const QString sub_names[]
Definition: Block.cpp:34
Definition: Animal.h:27
virtual Animal * IsAnimal()
Definition: Block.cpp:225
14
Definition: header.h:129
2
Definition: header.h:162
static QString DirString(dirs)
Definition: Block.cpp:75
int Kind() const
Definition: Block.h:145
int Sub() const
Definition: Block.h:144
#define sizeof_array(ARRAY)
Definition: header.h:224
virtual wearable Wearable() const
Definition: Block.cpp:212
virtual usage_types Use(Block *user)
Definition: Block.cpp:213
wearable
Definition: Block.h:28
12
Definition: header.h:172
19
Definition: header.h:179
static Block * NewBlock(int kind, int sub)
Use this to receive a pointer to new not-normal block.
QString GetNote() const
Definition: Block.cpp:234
qint16 durability
Definition: Block.h:174
Block(int sub, int kind, int transp=UNDEF)
Definition: Block.cpp:330
virtual Block * DropAfterDamage(bool *delete_self)
Should return dropped block.
Definition: Block.cpp:184
0
Definition: Block.h:39
5
Definition: header.h:165
quint8 direction
Definition: Block.h:178
Definition: Active.h:46
23
Definition: header.h:183
13
Definition: header.h:173
25
Definition: header.h:185
usage_types
Definition: header.h:196
24
Definition: header.h:184
int GetId() const
Determines kind and sub, unique for every kind-sub pair.
Definition: Block.cpp:205
dirs
Definition: header.h:85
22
Definition: header.h:182
virtual Active * ActiveBlock()
Definition: Block.cpp:226
Provides block ability to contain other blocks inside.
Definition: Inventory.h:33
0
Definition: header.h:160
virtual ~Block()
Definition: Block.cpp:358
const quint8 kind
Definition: Block.h:176
static const QString dir_strings[]
Definition: Block.cpp:25
int GetDurability() const
Definition: Block.cpp:232
const quint8 sub
Definition: Block.h:177
const int MAX_NOTE_LENGTH
Definition: World.h:44
16
Definition: header.h:131
void Break()
Set durability to null.
Definition: Block.cpp:230
void SaveToFile(QDataStream &out)
Definition: Block.cpp:309
11
Definition: Block.h:50
15
Definition: header.h:175
virtual void Move(dirs direction)
Definition: Block.cpp:207
virtual void ReceiveSignal(QString)
Receive text signal.
Definition: Block.cpp:211
int ChangeNote(QString note, int note_id)
Definition: World.cpp:138
Block without special physics and attributes.
Definition: Block.h:89
12
Definition: Block.h:51
8 (animal meat)
Definition: header.h:168
17
Definition: header.h:177
Provides definition for class Block.
static constexpr int MakeId(const int kind, const int sub)
Definition: BlockManager.h:72
30
Definition: header.h:190
14
Definition: header.h:174
virtual bool Inscribe(QString str)
Returns true on success.
Definition: Block.cpp:216