Achieved by adding a new element property called CarriesTypeIn, whose bits signal to save loading code which properties of particles of the element class in question carry element IDs. The bits in this property are numbered the same way as sim.FIELD_* constants for consistency. One would signal from Lua that a custom element carries element IDs in its tmp like this: elem.property(id, "CarriesTypeIn", 2 ^ sim.FIELD_TMP) "Carrying an element ID in a property" is to be interpreted as follows: the property is treated as a combination of a PMAPBITS-bit (so, currently 9-bit) unsigned integer lower part holding an element ID and a 32-PMAPBITS-bit (so, currently 23-bit) signed integer upper part holding whatever makes sense for the element. CONV, for example, uses this signed integer in its ctype as the extra "v" parameter for particle creation.
580 lines
16 KiB
C++
580 lines
16 KiB
C++
#include "simulation/ElementCommon.h"
|
|
|
|
int Element_PIPE_update(UPDATE_FUNC_ARGS);
|
|
int Element_PIPE_graphics(GRAPHICS_FUNC_ARGS);
|
|
void Element_PIPE_transfer_pipe_to_part(Simulation * sim, Particle *pipe, Particle *part, bool STOR);
|
|
static void transfer_part_to_pipe(Particle *part, Particle *pipe);
|
|
static void transfer_pipe_to_pipe(Particle *src, Particle *dest, bool STOR);
|
|
static void pushParticle(Simulation * sim, int i, int count, int original);
|
|
void Element_SOAP_detach(Simulation * sim, int i);
|
|
|
|
void Element::Element_PIPE()
|
|
{
|
|
Identifier = "DEFAULT_PT_PIPE";
|
|
Name = "PIPE";
|
|
Colour = PIXPACK(0x444444);
|
|
MenuVisible = 1;
|
|
MenuSection = SC_FORCE;
|
|
Enabled = 1;
|
|
|
|
Advection = 0.0f;
|
|
AirDrag = 0.00f * CFDS;
|
|
AirLoss = 0.95f;
|
|
Loss = 0.00f;
|
|
Collision = 0.0f;
|
|
Gravity = 0.0f;
|
|
Diffusion = 0.00f;
|
|
HotAir = 0.000f * CFDS;
|
|
Falldown = 0;
|
|
|
|
Flammable = 0;
|
|
Explosive = 0;
|
|
Meltable = 0;
|
|
Hardness = 0;
|
|
|
|
Weight = 100;
|
|
|
|
DefaultProperties.temp = 273.15f;
|
|
HeatConduct = 0;
|
|
Description = "PIPE, moves particles around. Once the BRCK generates, erase some for the exit. Then the PIPE generates and is usable.";
|
|
|
|
Properties = TYPE_SOLID|PROP_LIFE_DEC;
|
|
CarriesTypeIn = 1U << FIELD_CTYPE;
|
|
|
|
LowPressure = IPL;
|
|
LowPressureTransition = NT;
|
|
HighPressure = 10.0f;
|
|
HighPressureTransition = PT_BRMT;
|
|
LowTemperature = ITL;
|
|
LowTemperatureTransition = NT;
|
|
HighTemperature = ITH;
|
|
HighTemperatureTransition = NT;
|
|
|
|
DefaultProperties.life = 60;
|
|
|
|
Update = &Element_PIPE_update;
|
|
Graphics = &Element_PIPE_graphics;
|
|
}
|
|
|
|
// 0x000000FF element
|
|
// 0x00000100 is single pixel pipe
|
|
// 0x00000200 will transfer like a single pixel pipe when in forward mode
|
|
// 0x00001C00 forward single pixel pipe direction
|
|
// 0x00002000 will transfer like a single pixel pipe when in reverse mode
|
|
// 0x0001C000 reverse single pixel pipe direction
|
|
// 0x000E0000 PIPE color data stored here
|
|
|
|
constexpr int PFLAG_NORMALSPEED = 0x00010000;
|
|
constexpr int PFLAG_INITIALIZING = 0x00020000; // colors haven't been set yet
|
|
constexpr int PFLAG_COLOR_RED = 0x00040000;
|
|
constexpr int PFLAG_COLOR_GREEN = 0x00080000;
|
|
constexpr int PFLAG_COLOR_BLUE = 0x000C0000;
|
|
constexpr int PFLAG_COLORS = 0x000C0000;
|
|
|
|
constexpr int PPIP_TMPFLAG_REVERSED = 0x01000000;
|
|
constexpr int PPIP_TMPFLAG_PAUSED = 0x02000000;
|
|
constexpr int PPIP_TMPFLAG_TRIGGER_REVERSE = 0x04000000;
|
|
constexpr int PPIP_TMPFLAG_TRIGGER_OFF = 0x08000000;
|
|
constexpr int PPIP_TMPFLAG_TRIGGER_ON = 0x10000000;
|
|
constexpr int PPIP_TMPFLAG_TRIGGERS = 0x1C000000;
|
|
|
|
signed char pos_1_rx[] = { -1,-1,-1, 0, 0, 1, 1, 1 };
|
|
signed char pos_1_ry[] = { -1, 0, 1,-1, 1,-1, 0, 1 };
|
|
|
|
static void transformPatch(Particle &part, const int (&patch)[8])
|
|
{
|
|
if (part.tmp & 0x00000200) part.tmp = (part.tmp & 0xFFFFE3FF) | (patch[(part.tmp & 0x00001C00) >> 10] << 10);
|
|
if (part.tmp & 0x00002000) part.tmp = (part.tmp & 0xFFFE3FFF) | (patch[(part.tmp & 0x0001C000) >> 14] << 14);
|
|
}
|
|
|
|
void Element_PIPE_patchR(Particle &part)
|
|
{
|
|
// 035 -> 210
|
|
// 1 6 -> 4 3
|
|
// 247 -> 765
|
|
const int patchR[] = { 2, 4, 7, 1, 6, 0, 3, 5 };
|
|
transformPatch(part, patchR);
|
|
}
|
|
|
|
void Element_PIPE_patchH(Particle &part)
|
|
{
|
|
// 035 -> 530
|
|
// 1 6 -> 6 1
|
|
// 247 -> 742
|
|
const int patchH[] = { 5, 6, 7, 3, 4, 0, 1, 2 };
|
|
transformPatch(part, patchH);
|
|
}
|
|
|
|
void Element_PIPE_patchV(Particle &part)
|
|
{
|
|
// 035 -> 247
|
|
// 1 6 -> 1 6
|
|
// 247 -> 035
|
|
const int patchV[] = { 2, 1, 0, 4, 3, 7, 6, 5 };
|
|
transformPatch(part, patchV);
|
|
}
|
|
|
|
static unsigned int prevColor(unsigned int flags)
|
|
{
|
|
unsigned int color = flags & PFLAG_COLORS;
|
|
if (color == PFLAG_COLOR_RED)
|
|
return PFLAG_COLOR_GREEN;
|
|
else if (color == PFLAG_COLOR_GREEN)
|
|
return PFLAG_COLOR_BLUE;
|
|
else if (color == PFLAG_COLOR_BLUE)
|
|
return PFLAG_COLOR_RED;
|
|
return PFLAG_COLOR_RED;
|
|
}
|
|
|
|
static unsigned int nextColor(unsigned int flags)
|
|
{
|
|
unsigned int color = flags & PFLAG_COLORS;
|
|
if (color == PFLAG_COLOR_RED)
|
|
return PFLAG_COLOR_BLUE;
|
|
else if (color == PFLAG_COLOR_BLUE)
|
|
color = PFLAG_COLOR_GREEN;
|
|
else if (color == PFLAG_COLOR_GREEN)
|
|
return PFLAG_COLOR_RED;
|
|
return PFLAG_COLOR_GREEN;
|
|
}
|
|
|
|
int Element_PIPE_update(UPDATE_FUNC_ARGS)
|
|
{
|
|
int r, rx, ry, np;
|
|
int rnd, rndstore;
|
|
if (parts[i].ctype && !sim->elements[TYP(parts[i].ctype)].Enabled)
|
|
parts[i].ctype = 0;
|
|
if (parts[i].tmp & PPIP_TMPFLAG_TRIGGERS)
|
|
{
|
|
int pause_changed = 0;
|
|
if (parts[i].tmp & PPIP_TMPFLAG_TRIGGER_ON) // TRIGGER_ON overrides TRIGGER_OFF
|
|
{
|
|
if (parts[i].tmp & PPIP_TMPFLAG_PAUSED)
|
|
pause_changed = 1;
|
|
parts[i].tmp &= ~PPIP_TMPFLAG_PAUSED;
|
|
}
|
|
else if (parts[i].tmp & PPIP_TMPFLAG_TRIGGER_OFF)
|
|
{
|
|
if (!(parts[i].tmp & PPIP_TMPFLAG_PAUSED))
|
|
pause_changed = 1;
|
|
parts[i].tmp |= PPIP_TMPFLAG_PAUSED;
|
|
}
|
|
if (pause_changed)
|
|
{
|
|
int rx, ry, r;
|
|
for (rx=-2; rx<3; rx++)
|
|
for (ry=-2; ry<3; ry++)
|
|
{
|
|
if (BOUNDS_CHECK && (rx || ry))
|
|
{
|
|
r = pmap[y+ry][x+rx];
|
|
if (TYP(r) == PT_BRCK)
|
|
{
|
|
if (parts[i].tmp & PPIP_TMPFLAG_PAUSED)
|
|
parts[ID(r)].tmp = 0;
|
|
else
|
|
parts[ID(r)].tmp = 1; //make surrounding BRCK glow
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (parts[i].tmp & PPIP_TMPFLAG_TRIGGER_REVERSE)
|
|
{
|
|
parts[i].tmp ^= PPIP_TMPFLAG_REVERSED;
|
|
// Switch colors so it goes in reverse
|
|
if ((parts[i].tmp&PFLAG_COLORS) != PFLAG_COLOR_GREEN)
|
|
parts[i].tmp ^= PFLAG_COLOR_GREEN;
|
|
if (parts[i].tmp & 0x100) //Switch one pixel pipe direction
|
|
{
|
|
int coords = (parts[i].tmp>>13)&0xF;
|
|
int coords2 = (parts[i].tmp>>9)&0xF;
|
|
parts[i].tmp &= ~0x1FE00;
|
|
parts[i].tmp |= coords<<9;
|
|
parts[i].tmp |= coords2<<13;
|
|
}
|
|
}
|
|
|
|
parts[i].tmp &= ~PPIP_TMPFLAG_TRIGGERS;
|
|
}
|
|
if ((parts[i].tmp&PFLAG_COLORS) && !(parts[i].tmp & PPIP_TMPFLAG_PAUSED))
|
|
{
|
|
if (parts[i].life==3)
|
|
{
|
|
int lastneighbor = -1;
|
|
int neighborcount = 0;
|
|
int count = 0;
|
|
// make automatic pipe pattern
|
|
for (rx=-1; rx<2; rx++)
|
|
for (ry=-1; ry<2; ry++)
|
|
if (BOUNDS_CHECK && (rx || ry))
|
|
{
|
|
count++;
|
|
r = pmap[y+ry][x+rx];
|
|
if (!r)
|
|
continue;
|
|
if (TYP(r) != PT_PIPE && TYP(r) != PT_PPIP)
|
|
continue;
|
|
unsigned int next = nextColor(parts[i].tmp);
|
|
unsigned int prev = prevColor(parts[i].tmp);
|
|
if (parts[ID(r)].tmp&PFLAG_INITIALIZING)
|
|
{
|
|
parts[ID(r)].tmp |= next;
|
|
parts[ID(r)].tmp &= ~PFLAG_INITIALIZING;
|
|
parts[ID(r)].life = 6;
|
|
// Is a single pixel pipe
|
|
if (parts[i].tmp&0x100)
|
|
{
|
|
// Will transfer to a single pixel pipe
|
|
parts[ID(r)].tmp |= 0x200;
|
|
// Coords of where it came from
|
|
parts[ID(r)].tmp |= (count - 1) << 10;
|
|
parts[i].tmp |= (8 - count) << 14;
|
|
parts[i].tmp |= 0x2000;
|
|
}
|
|
neighborcount ++;
|
|
lastneighbor = ID(r);
|
|
}
|
|
else if ((parts[ID(r)].tmp&PFLAG_COLORS) != prev)
|
|
{
|
|
neighborcount ++;
|
|
lastneighbor = ID(r);
|
|
}
|
|
}
|
|
if (neighborcount == 1)
|
|
parts[lastneighbor].tmp |= 0x100;
|
|
}
|
|
else
|
|
{
|
|
if (parts[i].flags&PFLAG_NORMALSPEED)//skip particle push to prevent particle number being higher causing speed up
|
|
{
|
|
parts[i].flags &= ~PFLAG_NORMALSPEED;
|
|
}
|
|
else
|
|
{
|
|
pushParticle(sim, i,0,i);
|
|
}
|
|
|
|
if (nt)//there is something besides PIPE around current particle
|
|
{
|
|
rndstore = RNG::Ref().gen();
|
|
rnd = rndstore&7;
|
|
//rndstore = rndstore>>3;
|
|
rx = pos_1_rx[rnd];
|
|
ry = pos_1_ry[rnd];
|
|
if (BOUNDS_CHECK)
|
|
{
|
|
r = pmap[y+ry][x+rx];
|
|
if(!r)
|
|
r = sim->photons[y+ry][x+rx];
|
|
if (surround_space && !r && TYP(parts[i].ctype)) //creating at end
|
|
{
|
|
np = sim->create_part(-1, x+rx, y+ry, TYP(parts[i].ctype));
|
|
if (np!=-1)
|
|
{
|
|
Element_PIPE_transfer_pipe_to_part(sim, parts+i, parts+np, false);
|
|
}
|
|
}
|
|
//try eating particle at entrance
|
|
else if (!TYP(parts[i].ctype) && (sim->elements[TYP(r)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)))
|
|
{
|
|
if (TYP(r)==PT_SOAP)
|
|
Element_SOAP_detach(sim, ID(r));
|
|
transfer_part_to_pipe(parts+(ID(r)), parts+i);
|
|
sim->kill_part(ID(r));
|
|
}
|
|
else if (!TYP(parts[i].ctype) && TYP(r)==PT_STOR && sim->IsElement(parts[ID(r)].tmp) && (sim->elements[parts[ID(r)].tmp].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)))
|
|
{
|
|
// STOR stores properties in the same places as PIPE does
|
|
transfer_pipe_to_pipe(parts+(ID(r)), parts+i, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (!(parts[i].tmp&(PFLAG_COLORS|PFLAG_INITIALIZING)) && parts[i].life<=10)
|
|
{
|
|
// make a border
|
|
for (rx=-2; rx<3; rx++)
|
|
for (ry=-2; ry<3; ry++)
|
|
{
|
|
if (BOUNDS_CHECK && (rx || ry))
|
|
{
|
|
r = pmap[y+ry][x+rx];
|
|
if (!r)
|
|
{
|
|
// BRCK border
|
|
int index = sim->create_part(-1,x+rx,y+ry,PT_BRCK);
|
|
if (parts[i].type == PT_PPIP && index != -1)
|
|
parts[index].tmp = 1;
|
|
}
|
|
}
|
|
}
|
|
if (parts[i].life <= 1)
|
|
parts[i].tmp |= PFLAG_INITIALIZING;
|
|
}
|
|
// Wait for empty space before starting to generate automatic pipe pattern
|
|
else if (parts[i].tmp & PFLAG_INITIALIZING)
|
|
{
|
|
if (!parts[i].life)
|
|
{
|
|
for (rx=-1; rx<2; rx++)
|
|
for (ry=-1; ry<2; ry++)
|
|
if (BOUNDS_CHECK && (rx || ry))
|
|
{
|
|
if (!pmap[y+ry][x+rx] && sim->bmap[(y+ry)/CELL][(x+rx)/CELL]!=WL_ALLOWAIR && sim->bmap[(y+ry)/CELL][(x+rx)/CELL]!=WL_WALL && sim->bmap[(y+ry)/CELL][(x+rx)/CELL]!=WL_WALLELEC && (sim->bmap[(y+ry)/CELL][(x+rx)/CELL]!=WL_EWALL || sim->emap[(y+ry)/CELL][(x+rx)/CELL]))
|
|
parts[i].life=50;
|
|
}
|
|
}
|
|
else if (parts[i].life==5)//check for beginning of pipe single pixel
|
|
{
|
|
int issingle = 1;
|
|
for (rx=-1; rx<2; rx++)
|
|
for (ry=-1; ry<2; ry++)
|
|
if (BOUNDS_CHECK && (rx || ry))
|
|
{
|
|
r = pmap[y+ry][x+rx];
|
|
if ((TYP(r)==PT_PIPE || TYP(r) == PT_PPIP) && parts[i].life)
|
|
issingle = 0;
|
|
}
|
|
if (issingle)
|
|
parts[i].tmp |= 0x100;
|
|
}
|
|
else if (parts[i].life == 2)
|
|
{
|
|
parts[i].tmp |= PFLAG_COLOR_RED;
|
|
parts[i].tmp &= ~PFLAG_INITIALIZING;
|
|
parts[i].life = 6;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Element_PIPE_graphics(GRAPHICS_FUNC_ARGS)
|
|
{
|
|
int t = TYP(cpart->ctype);
|
|
if (t>0 && t<PT_NUM && ren->sim->elements[t].Enabled)
|
|
{
|
|
if (t == PT_STKM || t == PT_STKM2 || t == PT_FIGH)
|
|
return 0;
|
|
if (ren->graphicscache[t].isready)
|
|
{
|
|
*pixel_mode = ren->graphicscache[t].pixel_mode;
|
|
*cola = ren->graphicscache[t].cola;
|
|
*colr = ren->graphicscache[t].colr;
|
|
*colg = ren->graphicscache[t].colg;
|
|
*colb = ren->graphicscache[t].colb;
|
|
*firea = ren->graphicscache[t].firea;
|
|
*firer = ren->graphicscache[t].firer;
|
|
*fireg = ren->graphicscache[t].fireg;
|
|
*fireb = ren->graphicscache[t].fireb;
|
|
}
|
|
else
|
|
{
|
|
// Temp particle used for graphics.
|
|
Particle tpart = *cpart;
|
|
|
|
// Emulate the graphics of stored particle.
|
|
memset(cpart, 0, sizeof(Particle));
|
|
cpart->type = t;
|
|
cpart->temp = tpart.temp;
|
|
cpart->life = tpart.tmp2;
|
|
cpart->tmp = tpart.tmp3;
|
|
cpart->ctype = tpart.tmp4;
|
|
|
|
*colr = PIXR(ren->sim->elements[t].Colour);
|
|
*colg = PIXG(ren->sim->elements[t].Colour);
|
|
*colb = PIXB(ren->sim->elements[t].Colour);
|
|
if (ren->sim->elements[t].Graphics)
|
|
{
|
|
(*(ren->sim->elements[t].Graphics))(ren, cpart, nx, ny, pixel_mode, cola, colr, colg, colb, firea, firer, fireg, fireb);
|
|
}
|
|
else
|
|
{
|
|
Element::defaultGraphics(ren, cpart, nx, ny, pixel_mode, cola, colr, colg, colb, firea, firer, fireg, fireb);
|
|
}
|
|
|
|
// Restore original particle data.
|
|
*cpart = tpart;
|
|
}
|
|
//*colr = PIXR(elements[t].pcolors);
|
|
//*colg = PIXG(elements[t].pcolors);
|
|
//*colb = PIXB(elements[t].pcolors);
|
|
}
|
|
else
|
|
{
|
|
switch (cpart->tmp & PFLAG_COLORS)
|
|
{
|
|
case PFLAG_COLOR_RED:
|
|
*colr = 50;
|
|
*colg = 1;
|
|
*colb = 1;
|
|
break;
|
|
case PFLAG_COLOR_GREEN:
|
|
*colr = 1;
|
|
*colg = 50;
|
|
*colb = 1;
|
|
break;
|
|
case PFLAG_COLOR_BLUE:
|
|
*colr = 1;
|
|
*colg = 1;
|
|
*colb = 50;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void Element_PIPE_transfer_pipe_to_part(Simulation * sim, Particle *pipe, Particle *part, bool STOR)
|
|
{
|
|
// STOR also calls this function to move particles from STOR to PRTI
|
|
// PIPE was changed, so now PIPE and STOR don't use the same particle storage format
|
|
if (STOR)
|
|
{
|
|
part->type = TYP(pipe->tmp);
|
|
pipe->tmp = 0;
|
|
}
|
|
else
|
|
{
|
|
part->type = TYP(pipe->ctype);
|
|
pipe->ctype = 0;
|
|
}
|
|
part->temp = pipe->temp;
|
|
part->life = pipe->tmp2;
|
|
part->tmp = pipe->tmp3;
|
|
part->ctype = pipe->tmp4;
|
|
|
|
if (!(sim->elements[part->type].Properties & TYPE_ENERGY))
|
|
{
|
|
part->vx = 0.0f;
|
|
part->vy = 0.0f;
|
|
}
|
|
part->tmp2 = 0;
|
|
part->flags = 0;
|
|
part->dcolour = 0;
|
|
}
|
|
|
|
static void transfer_part_to_pipe(Particle *part, Particle *pipe)
|
|
{
|
|
pipe->ctype = part->type;
|
|
pipe->temp = part->temp;
|
|
pipe->tmp2 = part->life;
|
|
pipe->tmp3 = part->tmp;
|
|
pipe->tmp4 = part->ctype;
|
|
}
|
|
|
|
static void transfer_pipe_to_pipe(Particle *src, Particle *dest, bool STOR)
|
|
{
|
|
// STOR to PIPE
|
|
if (STOR)
|
|
{
|
|
dest->ctype = src->tmp;
|
|
src->tmp = 0;
|
|
}
|
|
else
|
|
{
|
|
dest->ctype = src->ctype;
|
|
src->ctype = 0;
|
|
}
|
|
dest->temp = src->temp;
|
|
dest->tmp2 = src->tmp2;
|
|
dest->tmp3 = src->tmp3;
|
|
dest->tmp4 = src->tmp4;
|
|
}
|
|
|
|
static void pushParticle(Simulation * sim, int i, int count, int original)
|
|
{
|
|
int rndstore, rnd, rx, ry, r, x, y, np, q;
|
|
unsigned int notctype = nextColor(sim->parts[i].tmp);
|
|
if (!TYP(sim->parts[i].ctype) || count >= 2)//don't push if there is nothing there, max speed of 2 per frame
|
|
return;
|
|
x = (int)(sim->parts[i].x+0.5f);
|
|
y = (int)(sim->parts[i].y+0.5f);
|
|
if( !(sim->parts[i].tmp&0x200) )
|
|
{
|
|
//normal random push
|
|
rndstore = RNG::Ref().gen();
|
|
// RAND_MAX is at least 32767 on all platforms i.e. pow(8,5)-1
|
|
// so can go 5 cycles without regenerating rndstore
|
|
// (although now we use our own randomizer so maybe should reevaluate all the rndstore usages in every element)
|
|
for (q=0; q<3; q++)//try to push 3 times
|
|
{
|
|
rnd = rndstore&7;
|
|
rndstore = rndstore>>3;
|
|
rx = pos_1_rx[rnd];
|
|
ry = pos_1_ry[rnd];
|
|
if (BOUNDS_CHECK)
|
|
{
|
|
r = sim->pmap[y+ry][x+rx];
|
|
if (!r)
|
|
continue;
|
|
else if ((TYP(r)==PT_PIPE || TYP(r) == PT_PPIP) && (sim->parts[ID(r)].tmp&PFLAG_COLORS) != notctype && !TYP(sim->parts[ID(r)].ctype))
|
|
{
|
|
transfer_pipe_to_pipe(sim->parts+i, sim->parts+(ID(r)), false);
|
|
if (ID(r) > original)
|
|
sim->parts[ID(r)].flags |= PFLAG_NORMALSPEED;//skip particle push, normalizes speed
|
|
count++;
|
|
pushParticle(sim, ID(r),count,original);
|
|
}
|
|
else if (TYP(r) == PT_PRTI) //Pass particles into PRTI for a pipe speed increase
|
|
{
|
|
int portaltmp = sim->parts[ID(r)].tmp;
|
|
if (portaltmp >= CHANNELS)
|
|
portaltmp = CHANNELS-1;
|
|
else if (portaltmp < 0)
|
|
portaltmp = 0;
|
|
for (int nnx = 0; nnx < 80; nnx++)
|
|
if (!sim->portalp[portaltmp][count][nnx].type)
|
|
{
|
|
Element_PIPE_transfer_pipe_to_part(sim, sim->parts+i, &(sim->portalp[portaltmp][count][nnx]), false);
|
|
count++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else //predefined 1 pixel thick pipe movement
|
|
{
|
|
int coords = 7 - ((sim->parts[i].tmp>>10)&7);
|
|
r = sim->pmap[y+ pos_1_ry[coords]][x+ pos_1_rx[coords]];
|
|
if ((TYP(r)==PT_PIPE || TYP(r) == PT_PPIP) && (sim->parts[ID(r)].tmp&PFLAG_COLORS) != notctype && !TYP(sim->parts[ID(r)].ctype))
|
|
{
|
|
transfer_pipe_to_pipe(sim->parts+i, sim->parts+(ID(r)), false);
|
|
if (ID(r) > original)
|
|
sim->parts[ID(r)].flags |= PFLAG_NORMALSPEED;//skip particle push, normalizes speed
|
|
count++;
|
|
pushParticle(sim, ID(r),count,original);
|
|
}
|
|
else if (TYP(r) == PT_PRTI) //Pass particles into PRTI for a pipe speed increase
|
|
{
|
|
int portaltmp = sim->parts[ID(r)].tmp;
|
|
if (portaltmp >= CHANNELS)
|
|
portaltmp = CHANNELS-1;
|
|
else if (portaltmp < 0)
|
|
portaltmp = 0;
|
|
for (int nnx = 0; nnx < 80; nnx++)
|
|
if (!sim->portalp[portaltmp][count][nnx].type)
|
|
{
|
|
Element_PIPE_transfer_pipe_to_part(sim, sim->parts+i, &(sim->portalp[portaltmp][count][nnx]), false);
|
|
count++;
|
|
break;
|
|
}
|
|
}
|
|
else if (!r) //Move particles out of pipe automatically, much faster at ends
|
|
{
|
|
rx = pos_1_rx[coords];
|
|
ry = pos_1_ry[coords];
|
|
np = sim->create_part(-1,x+rx,y+ry,TYP(sim->parts[i].ctype));
|
|
if (np!=-1)
|
|
{
|
|
Element_PIPE_transfer_pipe_to_part(sim, sim->parts+i, sim->parts+np, false);
|
|
}
|
|
}
|
|
|
|
}
|
|
return;
|
|
}
|