1 #include "ElementCommon.h"
2 #include "StructProperty.h"
3 
Element()4 Element::Element():
5 	Identifier("DEFAULT_INVALID"),
6 	Name(""),
7 	Colour(PIXPACK(0xFF00FF)),
8 	MenuVisible(0),
9 	MenuSection(0),
10 	Enabled(0),
11 
12 	Advection(0.0f),
13 	AirDrag(-0.0f * CFDS),
14 	AirLoss(1.0f),
15 	Loss(1.0f),
16 	Collision(0.0f),
17 	Gravity(0.0f),
18 	NewtonianGravity(1.0f),
19 	Diffusion(0.0f),
20 	HotAir(0.0f * CFDS),
21 	Falldown(0),
22 
23 	Flammable(0),
24 	Explosive(0),
25 	Meltable(0),
26 	Hardness(30),
27 	PhotonReflectWavelengths(0x3FFFFFFF),
28 
29 	Weight(50),
30 
31 	HeatConduct(128),
32 	Description("No description"),
33 
34 	Properties(TYPE_SOLID),
35 
36 	LowPressure(IPL),
37 	LowPressureTransition(NT),
38 	HighPressure(IPH),
39 	HighPressureTransition(NT),
40 	LowTemperature(ITL),
41 	LowTemperatureTransition(NT),
42 	HighTemperature(ITH),
43 	HighTemperatureTransition(NT),
44 
45 	Update(nullptr),
46 	Graphics(&Element::defaultGraphics),
47 	CtypeDraw(nullptr),
48 	IconGenerator(nullptr)
49 {
50 	memset(&DefaultProperties, 0, sizeof(Particle));
51 	DefaultProperties.temp = R_TEMP + 273.15f;
52 }
53 
GetProperties()54 std::vector<StructProperty> const &Element::GetProperties()
55 {
56 	static std::vector<StructProperty> properties = {
57 		{ "Name",                      StructProperty::String,   offsetof(Element, Name                     ) },
58 		{ "Colour",                    StructProperty::Colour,   offsetof(Element, Colour                   ) },
59 		{ "Color",                     StructProperty::Colour,   offsetof(Element, Colour                   ) },
60 		{ "MenuVisible",               StructProperty::Integer,  offsetof(Element, MenuVisible              ) },
61 		{ "MenuSection",               StructProperty::Integer,  offsetof(Element, MenuSection              ) },
62 		{ "Enabled",                   StructProperty::Integer,  offsetof(Element, Enabled                  ) },
63 		{ "Advection",                 StructProperty::Float,    offsetof(Element, Advection                ) },
64 		{ "AirDrag",                   StructProperty::Float,    offsetof(Element, AirDrag                  ) },
65 		{ "AirLoss",                   StructProperty::Float,    offsetof(Element, AirLoss                  ) },
66 		{ "Loss",                      StructProperty::Float,    offsetof(Element, Loss                     ) },
67 		{ "Collision",                 StructProperty::Float,    offsetof(Element, Collision                ) },
68 		{ "Gravity",                   StructProperty::Float,    offsetof(Element, Gravity                  ) },
69 		{ "NewtonianGravity",          StructProperty::Float,    offsetof(Element, NewtonianGravity         ) },
70 		{ "Diffusion",                 StructProperty::Float,    offsetof(Element, Diffusion                ) },
71 		{ "HotAir",                    StructProperty::Float,    offsetof(Element, HotAir                   ) },
72 		{ "Falldown",                  StructProperty::Integer,  offsetof(Element, Falldown                 ) },
73 		{ "Flammable",                 StructProperty::Integer,  offsetof(Element, Flammable                ) },
74 		{ "Explosive",                 StructProperty::Integer,  offsetof(Element, Explosive                ) },
75 		{ "Meltable",                  StructProperty::Integer,  offsetof(Element, Meltable                 ) },
76 		{ "Hardness",                  StructProperty::Integer,  offsetof(Element, Hardness                 ) },
77 		{ "PhotonReflectWavelengths",  StructProperty::UInteger, offsetof(Element, PhotonReflectWavelengths ) },
78 		{ "Weight",                    StructProperty::Integer,  offsetof(Element, Weight                   ) },
79 		{ "Temperature",               StructProperty::Float,    offsetof(Element, DefaultProperties.temp   ) },
80 		{ "HeatConduct",               StructProperty::UChar,    offsetof(Element, HeatConduct              ) },
81 		{ "Description",               StructProperty::String,   offsetof(Element, Description              ) },
82 		{ "State",                     StructProperty::Removed,  0                                            },
83 		{ "Properties",                StructProperty::Integer,  offsetof(Element, Properties               ) },
84 		{ "LowPressure",               StructProperty::Float,    offsetof(Element, LowPressure              ) },
85 		{ "LowPressureTransition",     StructProperty::TransitionType,  offsetof(Element, LowPressureTransition    ) },
86 		{ "HighPressure",              StructProperty::Float,    offsetof(Element, HighPressure             ) },
87 		{ "HighPressureTransition",    StructProperty::TransitionType,  offsetof(Element, HighPressureTransition   ) },
88 		{ "LowTemperature",            StructProperty::Float,    offsetof(Element, LowTemperature           ) },
89 		{ "LowTemperatureTransition",  StructProperty::TransitionType,  offsetof(Element, LowTemperatureTransition ) },
90 		{ "HighTemperature",           StructProperty::Float,    offsetof(Element, HighTemperature          ) },
91 		{ "HighTemperatureTransition", StructProperty::TransitionType,  offsetof(Element, HighTemperatureTransition) }
92 	};
93 	return properties;
94 }
95 
legacyUpdate(UPDATE_FUNC_ARGS)96 int Element::legacyUpdate(UPDATE_FUNC_ARGS) {
97 	int r, rx, ry;
98 	int t = parts[i].type;
99 	if (t==PT_WTRV) {
100 		for (rx=-2; rx<3; rx++)
101 			for (ry=-2; ry<3; ry++)
102 				if (x+rx>=0 && y+ry>0 &&
103 				        x+rx<XRES && y+ry<YRES && (rx || ry))
104 				{
105 					r = pmap[y+ry][x+rx];
106 					if (!r)
107 						continue;
108 					if ((TYP(r)==PT_WATR||TYP(r)==PT_DSTW||TYP(r)==PT_SLTW) && RNG::Ref().chance(1, 1000))
109 					{
110 						sim->part_change_type(i,x,y,PT_WATR);
111 						sim->part_change_type(ID(r),x+rx,y+ry,PT_WATR);
112 					}
113 					if ((TYP(r)==PT_ICEI || TYP(r)==PT_SNOW) && RNG::Ref().chance(1, 1000))
114 					{
115 						sim->part_change_type(i,x,y,PT_WATR);
116 						if (RNG::Ref().chance(1, 1000))
117 							sim->part_change_type(ID(r),x+rx,y+ry,PT_WATR);
118 					}
119 				}
120 	}
121 	else if (t==PT_WATR) {
122 		for (rx=-2; rx<3; rx++)
123 			for (ry=-2; ry<3; ry++)
124 				if (x+rx>=0 && y+ry>0 &&
125 				        x+rx<XRES && y+ry<YRES && (rx || ry))
126 				{
127 					r = pmap[y+ry][x+rx];
128 					if (!r)
129 						continue;
130 					if ((TYP(r)==PT_FIRE || TYP(r)==PT_LAVA) && RNG::Ref().chance(1, 10))
131 					{
132 						sim->part_change_type(i,x,y,PT_WTRV);
133 					}
134 				}
135 	}
136 	else if (t==PT_SLTW) {
137 		for (rx=-2; rx<3; rx++)
138 			for (ry=-2; ry<3; ry++)
139 				if (x+rx>=0 && y+ry>0 &&
140 				        x+rx<XRES && y+ry<YRES && (rx || ry))
141 				{
142 					r = pmap[y+ry][x+rx];
143 					if (!r)
144 						continue;
145 					if ((TYP(r)==PT_FIRE || TYP(r)==PT_LAVA) && RNG::Ref().chance(1, 10))
146 					{
147 						if (RNG::Ref().chance(1, 4))
148 							sim->part_change_type(i,x,y,PT_SALT);
149 						else
150 							sim->part_change_type(i,x,y,PT_WTRV);
151 					}
152 				}
153 	}
154 	else if (t==PT_DSTW) {
155 		for (rx=-2; rx<3; rx++)
156 			for (ry=-2; ry<3; ry++)
157 				if (x+rx>=0 && y+ry>0 &&
158 				        x+rx<XRES && y+ry<YRES && (rx || ry))
159 				{
160 					r = pmap[y+ry][x+rx];
161 					if (!r)
162 						continue;
163 					if ((TYP(r)==PT_FIRE || TYP(r)==PT_LAVA) && RNG::Ref().chance(1, 10))
164 					{
165 						sim->part_change_type(i,x,y,PT_WTRV);
166 					}
167 				}
168 	}
169 	else if (t==PT_ICEI) {
170 		for (rx=-2; rx<3; rx++)
171 			for (ry=-2; ry<3; ry++)
172 				if (x+rx>=0 && y+ry>0 && x+rx<XRES && y+ry<YRES && (rx || ry))
173 				{
174 					r = pmap[y+ry][x+rx];
175 					if (!r)
176 						continue;
177 					if ((TYP(r)==PT_WATR || TYP(r)==PT_DSTW) && RNG::Ref().chance(1, 1000))
178 					{
179 						sim->part_change_type(i,x,y,PT_ICEI);
180 						sim->part_change_type(ID(r),x+rx,y+ry,PT_ICEI);
181 					}
182 				}
183 	}
184 	else if (t==PT_SNOW) {
185 		for (rx=-2; rx<3; rx++)
186 			for (ry=-2; ry<3; ry++)
187 				if (x+rx>=0 && y+ry>0 && x+rx<XRES && y+ry<YRES && (rx || ry))
188 				{
189 					r = pmap[y+ry][x+rx];
190 					if (!r)
191 						continue;
192 					if ((TYP(r)==PT_WATR || TYP(r)==PT_DSTW) && RNG::Ref().chance(1, 1000))
193 					{
194 						sim->part_change_type(i,x,y,PT_ICEI);
195 						sim->part_change_type(ID(r),x+rx,y+ry,PT_ICEI);
196 					}
197 					if ((TYP(r)==PT_WATR || TYP(r)==PT_DSTW) && RNG::Ref().chance(3, 200))
198 						sim->part_change_type(i,x,y,PT_WATR);
199 				}
200 	}
201 	if (t==PT_WTRV && sim->pv[y/CELL][x/CELL]>4.0f)
202 		sim->part_change_type(i,x,y,PT_DSTW);
203 	if (t==PT_OIL && sim->pv[y/CELL][x/CELL]<-6.0f)
204 		sim->part_change_type(i,x,y,PT_GAS);
205 	if (t==PT_GAS && sim->pv[y/CELL][x/CELL]>6.0f)
206 		sim->part_change_type(i,x,y,PT_OIL);
207 	if (t==PT_DESL && sim->pv[y/CELL][x/CELL]>12.0f)
208 	{
209 		sim->part_change_type(i,x,y,PT_FIRE);
210 		parts[i].life = RNG::Ref().between(120, 169);
211 	}
212 	return 0;
213 }
214 
defaultGraphics(GRAPHICS_FUNC_ARGS)215 int Element::defaultGraphics(GRAPHICS_FUNC_ARGS)
216 {
217 	int t = cpart->type;
218 	//Property based defaults
219 	if(ren->sim->elements[t].Properties & PROP_RADIOACTIVE) *pixel_mode |= PMODE_GLOW;
220 	if(ren->sim->elements[t].Properties & TYPE_LIQUID)
221 	{
222 		*pixel_mode |= PMODE_BLUR;
223 	}
224 	if(ren->sim->elements[t].Properties & TYPE_GAS)
225 	{
226 		*pixel_mode &= ~PMODE;
227 		*pixel_mode |= FIRE_BLEND;
228 		*firer = *colr/2;
229 		*fireg = *colg/2;
230 		*fireb = *colb/2;
231 		*firea = 125;
232 		*pixel_mode |= DECO_FIRE;
233 	}
234 	return 1;
235 }
236 
basicCtypeDraw(CTYPEDRAW_FUNC_ARGS)237 bool Element::basicCtypeDraw(CTYPEDRAW_FUNC_ARGS)
238 {
239 	if (sim->parts[i].type == t || sim->elements[t].Properties & PROP_NOCTYPEDRAW)
240 	{
241 		return false;
242 	}
243 	sim->parts[i].ctype = t;
244 	return true;
245 }
246 
ctypeDrawVInTmp(CTYPEDRAW_FUNC_ARGS)247 bool Element::ctypeDrawVInTmp(CTYPEDRAW_FUNC_ARGS)
248 {
249 	if (!Element::basicCtypeDraw(CTYPEDRAW_FUNC_SUBCALL_ARGS))
250 	{
251 		return false;
252 	}
253 	if (t == PT_LIFE && v >= 0 && v < NGOL)
254 	{
255 		sim->parts[i].tmp = v;
256 	}
257 	return true;
258 }
259 
ctypeDrawVInCtype(CTYPEDRAW_FUNC_ARGS)260 bool Element::ctypeDrawVInCtype(CTYPEDRAW_FUNC_ARGS)
261 {
262 	if (!Element::basicCtypeDraw(CTYPEDRAW_FUNC_SUBCALL_ARGS))
263 	{
264 		return false;
265 	}
266 	if (t == PT_LIFE && v >= 0 && v < NGOL)
267 	{
268 		sim->parts[i].ctype |= PMAPID(v);
269 	}
270 	return true;
271 }
272