1 #include "simulation/ElementCommon.h"
2
3 static int update(UPDATE_FUNC_ARGS);
4
Element_DRAY()5 void Element::Element_DRAY()
6 {
7 Identifier = "DEFAULT_PT_DRAY";
8 Name = "DRAY";
9 Colour = PIXPACK(0xFFAA22);
10 MenuVisible = 1;
11 MenuSection = SC_ELEC;
12 Enabled = 1;
13
14 Advection = 0.0f;
15 AirDrag = 0.00f * CFDS;
16 AirLoss = 0.90f;
17 Loss = 0.00f;
18 Collision = 0.0f;
19 Gravity = 0.0f;
20 Diffusion = 0.00f;
21 HotAir = 0.000f * CFDS;
22 Falldown = 0;
23
24 Flammable = 0;
25 Explosive = 0;
26 Meltable = 0;
27 Hardness = 1;
28
29 Weight = 100;
30
31 HeatConduct = 0;
32 Description = "Duplicator ray. Replicates a line of particles in front of it.";
33
34 Properties = TYPE_SOLID | PROP_LIFE_DEC;
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 = &update;
46 Graphics = nullptr; // is this needed?
47 CtypeDraw = &Element::ctypeDrawVInCtype;
48 }
49
50 //should probably be in Simulation.h
InBounds(int x,int y)51 static bool InBounds(int x, int y)
52 {
53 return (x>=0 && y>=0 && x<XRES && y<YRES);
54 }
55
update(UPDATE_FUNC_ARGS)56 static int update(UPDATE_FUNC_ARGS)
57 {
58 int ctype = TYP(parts[i].ctype), ctypeExtra = ID(parts[i].ctype), copyLength = parts[i].tmp, copySpaces = parts[i].tmp2;
59 if (copySpaces < 0)
60 copySpaces = parts[i].tmp2 = 0;
61 if (copyLength < 0)
62 copyLength = parts[i].tmp = 0;
63 else if (copyLength > 0)
64 copySpaces++; //strange hack
65 if (!parts[i].life) // only fire when life is 0, but nothing sets the life right now
66 {
67 for (int rx = -1; rx <= 1; rx++)
68 for (int ry = -1; ry <= 1; ry++)
69 if (BOUNDS_CHECK && (rx || ry))
70 {
71 int r = pmap[y+ry][x+rx];
72 if (TYP(r) == PT_SPRK && parts[ID(r)].life == 3) //spark found, start creating
73 {
74 bool overwrite = parts[ID(r)].ctype == PT_PSCN;
75 int partsRemaining = copyLength, xCopyTo, yCopyTo; //positions where the line will start being copied at
76 int localCopyLength = copyLength;
77
78 if (parts[ID(r)].ctype == PT_INWR && rx && ry) // INWR doesn't spark from diagonals
79 continue;
80
81 //figure out where the copying will start/end
82 bool foundParticle = false;
83 bool isEnergy = false;
84 for (int xStep = rx*-1, yStep = ry*-1, xCurrent = x+xStep, yCurrent = y+yStep; ; xCurrent+=xStep, yCurrent+=yStep)
85 {
86 int rr;
87 // haven't found a particle yet, keep looking for one
88 // the first particle it sees decides whether it will copy energy particles or not
89 if (!foundParticle)
90 {
91 rr = pmap[yCurrent][xCurrent];
92 if (!rr)
93 {
94 rr = sim->photons[yCurrent][xCurrent];
95 if (rr)
96 foundParticle = isEnergy = true;
97 }
98 else
99 foundParticle = true;
100 }
101 // now that it knows what kind of particle it is copying, do some extra stuff here so we can determine when to stop
102 if ((ctype && sim->elements[ctype].Properties&TYPE_ENERGY) || isEnergy)
103 rr = sim->photons[yCurrent][xCurrent];
104 else
105 rr = pmap[yCurrent][xCurrent];
106
107 // Checks for when to stop:
108 // 1: if .tmp isn't set, and the element in this spot is the ctype, then stop
109 // 2: if .tmp is set, stop when the length limit reaches 0
110 // 3. Stop when we are out of bounds
111 if ((!localCopyLength && TYP(rr) == ctype && (ctype != PT_LIFE || parts[ID(rr)].ctype == ctypeExtra))
112 || !(--partsRemaining && InBounds(xCurrent+xStep, yCurrent+yStep)))
113 {
114 localCopyLength -= partsRemaining;
115 xCopyTo = xCurrent + xStep*copySpaces;
116 yCopyTo = yCurrent + yStep*copySpaces;
117 break;
118 }
119 }
120
121 // now, actually copy the particles
122 partsRemaining = localCopyLength + 1;
123 int type, p;
124 for (int xStep = rx*-1, yStep = ry*-1, xCurrent = x+xStep, yCurrent = y+yStep; InBounds(xCopyTo, yCopyTo) && --partsRemaining; xCurrent+=xStep, yCurrent+=yStep, xCopyTo+=xStep, yCopyTo+=yStep)
125 {
126 // get particle to copy
127 if (isEnergy)
128 type = TYP(sim->photons[yCurrent][xCurrent]);
129 else
130 type = TYP(pmap[yCurrent][xCurrent]);
131
132 // if sparked by PSCN, overwrite whatever is in the target location, instead of just ignoring it
133 if (overwrite)
134 {
135 if (isEnergy)
136 {
137 if (sim->photons[yCopyTo][xCopyTo])
138 sim->kill_part(ID(sim->photons[yCopyTo][xCopyTo]));
139 }
140 else
141 {
142 if (pmap[yCopyTo][xCopyTo])
143 sim->kill_part(ID(pmap[yCopyTo][xCopyTo]));
144 }
145 }
146 if (type == PT_SPRK) // spark hack
147 p = sim->create_part(-1, xCopyTo, yCopyTo, PT_METL);
148 else if (type)
149 p = sim->create_part(-1, xCopyTo, yCopyTo, type);
150 else
151 continue;
152
153 // if new particle was created successfully
154 if (p >= 0)
155 {
156 if (type == PT_SPRK) // spark hack
157 sim->part_change_type(p, xCopyTo, yCopyTo, PT_SPRK);
158 if (isEnergy)
159 parts[p] = parts[ID(sim->photons[yCurrent][xCurrent])];
160 else
161 parts[p] = parts[ID(pmap[yCurrent][xCurrent])];
162 parts[p].x = xCopyTo;
163 parts[p].y = yCopyTo;
164 }
165 }
166 }
167 }
168 }
169 return 0;
170 }
171