146209d5881cd5489d4c9b487a21ef31f04815e6
[oweals/minetest.git] / src / materials.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "materials.h"
21 #include "mapnode.h"
22 #include "nodedef.h"
23 #include "utility.h"
24
25 void MaterialProperties::serialize(std::ostream &os)
26 {
27         writeU8(os, 0); // version
28         writeU8(os, diggability);
29         writeF1000(os, constant_time);
30         writeF1000(os, weight);
31         writeF1000(os, crackiness);
32         writeF1000(os, crumbliness);
33         writeF1000(os, cuttability);
34         writeF1000(os, flammability);
35 }
36
37 void MaterialProperties::deSerialize(std::istream &is)
38 {
39         int version = readU8(is);
40         if(version != 0)
41                 throw SerializationError("unsupported MaterialProperties version");
42         diggability = (enum Diggability)readU8(is);
43         constant_time = readF1000(is);
44         weight = readF1000(is);
45         crackiness = readF1000(is);
46         crumbliness = readF1000(is);
47         cuttability = readF1000(is);
48         flammability = readF1000(is);
49 }
50
51 ToolDiggingProperties::ToolDiggingProperties(float full_punch_interval_,
52                 float a, float b, float c, float d, float e,
53                 float f, float g, float h, float i, float j):
54         full_punch_interval(full_punch_interval_),
55         basetime(a),
56         dt_weight(b),
57         dt_crackiness(c),
58         dt_crumbliness(d),
59         dt_cuttability(e),
60         basedurability(f),
61         dd_weight(g),
62         dd_crackiness(h),
63         dd_crumbliness(i),
64         dd_cuttability(j)
65 {}
66
67 void ToolDiggingProperties::serialize(std::ostream &os)
68 {
69         writeU8(os, 0); // version
70         writeF1000(os, full_punch_interval);
71         writeF1000(os, basetime);
72         writeF1000(os, dt_weight);
73         writeF1000(os, dt_crackiness);
74         writeF1000(os, dt_crumbliness);
75         writeF1000(os, dt_cuttability);
76         writeF1000(os, basedurability);
77         writeF1000(os, dd_weight);
78         writeF1000(os, dd_crackiness);
79         writeF1000(os, dd_crumbliness);
80         writeF1000(os, dd_cuttability);
81 }
82
83 void ToolDiggingProperties::deSerialize(std::istream &is)
84 {
85         int version = readU8(is);
86         if(version != 0) throw SerializationError(
87                         "unsupported ToolDiggingProperties version");
88         full_punch_interval = readF1000(is);
89         basetime = readF1000(is);
90         dt_weight = readF1000(is);
91         dt_crackiness = readF1000(is);
92         dt_crumbliness = readF1000(is);
93         dt_cuttability = readF1000(is);
94         basedurability = readF1000(is);
95         dd_weight = readF1000(is);
96         dd_crackiness = readF1000(is);
97         dd_crumbliness = readF1000(is);
98         dd_cuttability = readF1000(is);
99 }
100
101 DiggingProperties getDiggingProperties(const MaterialProperties *mp,
102                 const ToolDiggingProperties *tp, float time_from_last_punch)
103 {
104         if(mp->diggability == DIGGABLE_NOT)
105                 return DiggingProperties(false, 0, 0);
106         if(mp->diggability == DIGGABLE_CONSTANT)
107                 return DiggingProperties(true, mp->constant_time, 0);
108
109         float time = tp->basetime;
110         time += tp->dt_weight * mp->weight;
111         time += tp->dt_crackiness * mp->crackiness;
112         time += tp->dt_crumbliness * mp->crumbliness;
113         time += tp->dt_cuttability * mp->cuttability;
114         if(time < 0.2)
115                 time = 0.2;
116
117         float durability = tp->basedurability;
118         durability += tp->dd_weight * mp->weight;
119         durability += tp->dd_crackiness * mp->crackiness;
120         durability += tp->dd_crumbliness * mp->crumbliness;
121         durability += tp->dd_cuttability * mp->cuttability;
122         if(durability < 1)
123                 durability = 1;
124         
125         if(time_from_last_punch < tp->full_punch_interval){
126                 float f = time_from_last_punch / tp->full_punch_interval;
127                 time /= f;
128                 durability /= f;
129         }
130
131         float wear = 1.0 / durability;
132         u16 wear_i = 65535.*wear;
133         return DiggingProperties(true, time, wear_i);
134 }
135
136 DiggingProperties getDiggingProperties(const MaterialProperties *mp,
137                 const ToolDiggingProperties *tp)
138 {
139         return getDiggingProperties(mp, tp, 1000000);
140 }
141
142 DiggingProperties getDiggingProperties(u16 content,
143                 const ToolDiggingProperties *tp, INodeDefManager *nodemgr)
144 {
145         const MaterialProperties &mp = nodemgr->get(content).material;
146         return getDiggingProperties(&mp, tp);
147 }
148
149 HittingProperties getHittingProperties(const MaterialProperties *mp,
150                 const ToolDiggingProperties *tp, float time_from_last_punch)
151 {
152         DiggingProperties digprop = getDiggingProperties(mp, tp,
153                         time_from_last_punch);
154         
155         // If digging time would be 1 second, 2 hearts go in 1 second.
156         s16 hp = 2.0 * 2.0 / digprop.time;
157         // Wear is the same as for digging a single node
158         s16 wear = (float)digprop.wear;
159
160         return HittingProperties(hp, wear);
161 }
162