1 #include "simulation/ElementCommon.h"
2 
3 int Element_PIPE_update(UPDATE_FUNC_ARGS);
4 int Element_PIPE_graphics(GRAPHICS_FUNC_ARGS);
5 
Element_PPIP()6 void Element::Element_PPIP()
7 {
8 	Identifier = "DEFAULT_PT_PPIP";
9 	Name = "PPIP";
10 	Colour = PIXPACK(0x444466);
11 	MenuVisible = 1;
12 	MenuSection = SC_POWERED;
13 	Enabled = 1;
14 
15 	Advection = 0.0f;
16 	AirDrag = 0.00f * CFDS;
17 	AirLoss = 0.95f;
18 	Loss = 0.00f;
19 	Collision = 0.0f;
20 	Gravity = 0.0f;
21 	Diffusion = 0.00f;
22 	HotAir = 0.000f	* CFDS;
23 	Falldown = 0;
24 
25 	Flammable = 0;
26 	Explosive = 0;
27 	Meltable = 0;
28 	Hardness = 0;
29 
30 	Weight = 100;
31 
32 	DefaultProperties.temp = 273.15f;
33 	HeatConduct = 0;
34 	Description = "Powered version of PIPE, use PSCN/NSCN to Activate/Deactivate.";
35 
36 	Properties = TYPE_SOLID|PROP_LIFE_DEC;
37 
38 	LowPressure = IPL;
39 	LowPressureTransition = NT;
40 	HighPressure = IPH;
41 	HighPressureTransition = NT;
42 	LowTemperature = ITL;
43 	LowTemperatureTransition = NT;
44 	HighTemperature = ITH;
45 	HighTemperatureTransition = NT;
46 
47 	DefaultProperties.life = 60;
48 
49 	Update = &Element_PIPE_update;
50 	Graphics = &Element_PIPE_graphics;
51 }
52 
53 // parts[].tmp flags
54 // trigger flags to be processed this frame (trigger flags for next frame are shifted 3 bits to the left):
55 constexpr int PPIP_TMPFLAG_TRIGGER_ON      = 0x10000000;
56 constexpr int PPIP_TMPFLAG_TRIGGER_OFF     = 0x08000000;
57 constexpr int PPIP_TMPFLAG_TRIGGER_REVERSE = 0x04000000;
58 // 0x000000FF element
59 // 0x00000100 is single pixel pipe
60 // 0x00000200 will transfer like a single pixel pipe when in forward mode
61 // 0x00001C00 forward single pixel pipe direction
62 // 0x00002000 will transfer like a single pixel pipe when in reverse mode
63 // 0x0001C000 reverse single pixel pipe direction
64 
65 int Element_PPIP_ppip_changed = 0;
66 
Element_PPIP_flood_trigger(Simulation * sim,int x,int y,int sparkedBy)67 void Element_PPIP_flood_trigger(Simulation * sim, int x, int y, int sparkedBy)
68 {
69 	int coord_stack_limit = XRES*YRES;
70 	unsigned short (*coord_stack)[2];
71 	int coord_stack_size = 0;
72 	int x1, x2;
73 
74 	Particle * parts = sim->parts;
75 	int (*pmap)[XRES] = sim->pmap;
76 
77 	// Separate flags for on and off in case PPIP is sparked by PSCN and NSCN on the same frame
78 	// - then PSCN can override NSCN and behaviour is not dependent on particle order
79 	int prop = 0;
80 	if (sparkedBy==PT_PSCN) prop = PPIP_TMPFLAG_TRIGGER_ON << 3;
81 	else if (sparkedBy==PT_NSCN) prop = PPIP_TMPFLAG_TRIGGER_OFF << 3;
82 	else if (sparkedBy==PT_INST) prop = PPIP_TMPFLAG_TRIGGER_REVERSE << 3;
83 
84 	if (prop==0 || TYP(pmap[y][x])!=PT_PPIP || (parts[ID(pmap[y][x])].tmp & prop))
85 		return;
86 
87 	coord_stack = new unsigned short[coord_stack_limit][2];
88 	coord_stack[coord_stack_size][0] = x;
89 	coord_stack[coord_stack_size][1] = y;
90 	coord_stack_size++;
91 
92 	do
93 	{
94 		coord_stack_size--;
95 		x = coord_stack[coord_stack_size][0];
96 		y = coord_stack[coord_stack_size][1];
97 		x1 = x2 = x;
98 		// go left as far as possible
99 		while (x1>=CELL)
100 		{
101 			if (TYP(pmap[y][x1-1]) != PT_PPIP)
102 			{
103 				break;
104 			}
105 			x1--;
106 		}
107 		// go right as far as possible
108 		while (x2<XRES-CELL)
109 		{
110 			if (TYP(pmap[y][x2+1]) != PT_PPIP)
111 			{
112 				break;
113 			}
114 			x2++;
115 		}
116 		// fill span
117 		for (x=x1; x<=x2; x++)
118 		{
119 			if (!(parts[ID(pmap[y][x])].tmp & prop))
120 			Element_PPIP_ppip_changed = 1;
121 			parts[ID(pmap[y][x])].tmp |= prop;
122 		}
123 
124 		// add adjacent pixels to stack
125 		// +-1 to x limits to include diagonally adjacent pixels
126 		// Don't need to check x bounds here, because already limited to [CELL, XRES-CELL]
127 		if (y>=CELL+1)
128 			for (x=x1-1; x<=x2+1; x++)
129 			if (TYP(pmap[y-1][x]) == PT_PPIP && !(parts[ID(pmap[y-1][x])].tmp & prop))
130 			{
131 				coord_stack[coord_stack_size][0] = x;
132 				coord_stack[coord_stack_size][1] = y-1;
133 				coord_stack_size++;
134 				if (coord_stack_size>=coord_stack_limit)
135 				{
136 					delete[] coord_stack;
137 					return;
138 				}
139 			}
140 		if (y<YRES-CELL-1)
141 			for (x=x1-1; x<=x2+1; x++)
142 				if (TYP(pmap[y+1][x]) == PT_PPIP && !(parts[ID(pmap[y+1][x])].tmp & prop))
143 				{
144 					coord_stack[coord_stack_size][0] = x;
145 					coord_stack[coord_stack_size][1] = y+1;
146 					coord_stack_size++;
147 					if (coord_stack_size>=coord_stack_limit)
148 					{
149 						delete[] coord_stack;
150 						return;
151 					}
152 				}
153 	} while (coord_stack_size>0);
154 	delete[] coord_stack;
155 }
156