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