1 #include "simulation/ElementCommon.h"
2 #include "common/tpt-minmax.h"
3
4 static int update(UPDATE_FUNC_ARGS);
5 static int graphics(GRAPHICS_FUNC_ARGS);
6
Element_DEUT()7 void Element::Element_DEUT()
8 {
9 Identifier = "DEFAULT_PT_DEUT";
10 Name = "DEUT";
11 Colour = PIXPACK(0x00153F);
12 MenuVisible = 1;
13 MenuSection = SC_NUCLEAR;
14 Enabled = 1;
15
16 Advection = 0.6f;
17 AirDrag = 0.01f * CFDS;
18 AirLoss = 0.98f;
19 Loss = 0.95f;
20 Collision = 0.0f;
21 Gravity = 0.1f;
22 Diffusion = 0.00f;
23 HotAir = 0.000f * CFDS;
24 Falldown = 2;
25
26 Flammable = 0;
27 Explosive = 0;
28 Meltable = 0;
29 Hardness = 20;
30
31 Weight = 31;
32
33 DefaultProperties.temp = R_TEMP - 2.0f + 273.15f;
34 HeatConduct = 251;
35 Description = "Deuterium oxide. Volume changes with temp, radioactive with neutrons.";
36
37 Properties = TYPE_LIQUID|PROP_NEUTPASS;
38
39 LowPressure = IPL;
40 LowPressureTransition = NT;
41 HighPressure = IPH;
42 HighPressureTransition = NT;
43 LowTemperature = ITL;
44 LowTemperatureTransition = NT;
45 HighTemperature = ITH;
46 HighTemperatureTransition = NT;
47
48 DefaultProperties.life = 10;
49
50 Update = &update;
51 Graphics = &graphics;
52 }
53
update(UPDATE_FUNC_ARGS)54 static int update(UPDATE_FUNC_ARGS)
55 {
56 int r, rx, ry, trade, np;
57 float gravtot = fabs(sim->gravy[(y/CELL)*(XRES/CELL)+(x/CELL)])+fabs(sim->gravx[(y/CELL)*(XRES/CELL)+(x/CELL)]);
58 // Prevent division by 0
59 float temp = std::max(1.0f, (parts[i].temp + 1));
60 int maxlife = ((10000/(temp + 1))-1);
61 if (RNG::Ref().chance(10000 % static_cast<int>(temp + 1), static_cast<int>(temp + 1)))
62 maxlife++;
63 // Compress when Newtonian gravity is applied
64 // multiplier=1 when gravtot=0, multiplier -> 5 as gravtot -> inf
65 maxlife = maxlife*(5.0f - 8.0f/(gravtot+2.0f));
66 if (parts[i].life < maxlife)
67 {
68 for (rx=-1; rx<2; rx++)
69 for (ry=-1; ry<2; ry++)
70 if (BOUNDS_CHECK && (rx || ry))
71 {
72 r = pmap[y+ry][x+rx];
73 if (!r || (parts[i].life >=maxlife))
74 continue;
75 if (TYP(r)==PT_DEUT&& RNG::Ref().chance(1, 3))
76 {
77 // If neighbour life+1 fits in the free capacity for this particle, absorb neighbour
78 // Condition is written in this way so that large neighbour life values don't cause integer overflow
79 if (parts[ID(r)].life <= maxlife - parts[i].life - 1)
80 {
81 parts[i].life += parts[ID(r)].life + 1;
82 sim->kill_part(ID(r));
83 }
84 }
85 }
86 }
87 else
88 for (rx=-1; rx<2; rx++)
89 for (ry=-1; ry<2; ry++)
90 if (BOUNDS_CHECK && (rx || ry))
91 {
92 //Leave if there is nothing to do
93 if (parts[i].life <= maxlife)
94 goto trade;
95 r = pmap[y+ry][x+rx];
96 if ((!r)&&parts[i].life>=1)//if nothing then create deut
97 {
98 np = sim->create_part(-1,x+rx,y+ry,PT_DEUT);
99 if (np<0) continue;
100 parts[i].life--;
101 parts[np].temp = parts[i].temp;
102 parts[np].life = 0;
103 }
104 }
105 trade:
106 for ( trade = 0; trade<4; trade ++)
107 {
108 rx = RNG::Ref().between(-2, 2);
109 ry = RNG::Ref().between(-2, 2);
110 if (BOUNDS_CHECK && (rx || ry))
111 {
112 r = pmap[y+ry][x+rx];
113 if (!r)
114 continue;
115 if (TYP(r)==PT_DEUT&&(parts[i].life>parts[ID(r)].life)&&parts[i].life>0)//diffusion
116 {
117 int temp = parts[i].life - parts[ID(r)].life;
118 if (temp ==1)
119 {
120 parts[ID(r)].life ++;
121 parts[i].life --;
122 }
123 else if (temp>0)
124 {
125 parts[ID(r)].life += temp/2;
126 parts[i].life -= temp/2;
127 }
128 }
129 }
130 }
131 return 0;
132 }
133
graphics(GRAPHICS_FUNC_ARGS)134 static int graphics(GRAPHICS_FUNC_ARGS)
135 {
136 if(cpart->life>=240)
137 {
138 *firea = 60;
139 *firer = *colr += 255;
140 *fireg = *colg += 255;
141 *fireb = *colb += 255;
142 *pixel_mode |= PMODE_GLOW | FIRE_ADD;
143 }
144 else if(cpart->life>0)
145 {
146 *colr += cpart->life*1;
147 *colg += cpart->life*2;
148 *colb += cpart->life*3;
149 *pixel_mode |= PMODE_BLUR;
150 }
151 else
152 {
153 *pixel_mode |= PMODE_BLUR;
154 }
155 return 0;
156 }
157