summaryrefslogtreecommitdiff
path: root/src/elements
diff options
context:
space:
mode:
authorjacksonmj <mj-pt@jacksonmj.co.uk>2012-08-11 08:53:02 (GMT)
committer jacksonmj <mj-pt@jacksonmj.co.uk>2012-08-13 22:48:55 (GMT)
commit8ec0f41fb143a6bda08d078232f3d70b36328dc4 (patch)
tree93b52bfef3bd66f04c62fa944728bb152079e56c /src/elements
parenta4c15746b8b3f6c187fbc7403fe5082883a8d9b7 (diff)
downloadpowder-8ec0f41fb143a6bda08d078232f3d70b36328dc4.zip
powder-8ec0f41fb143a6bda08d078232f3d70b36328dc4.tar.gz
Powered pipe, based on jacob1's commits
PSCN to turn on, NSCN to turn off, INST to reverse. Differences from jacob1's commit include: flood fill function that includes 1px diagonal pipes, powered/reversed state stored in tmp instead of flags, sparks from PSCN/NSCN/INST always take effect the following frame, single pixel pipe directions are a number from 0 to 7 so "if(coords)" does not check whether one is set (store another "transfers according to 1px pipe direction" bit for reverse flow).
Diffstat (limited to 'src/elements')
-rw-r--r--src/elements/newgraphics.c9
-rw-r--r--src/elements/pipe.c301
-rw-r--r--src/elements/sprk.c5
3 files changed, 268 insertions, 47 deletions
diff --git a/src/elements/newgraphics.c b/src/elements/newgraphics.c
index c8581f6..06bc74e 100644
--- a/src/elements/newgraphics.c
+++ b/src/elements/newgraphics.c
@@ -514,3 +514,12 @@ int graphics_COAL(GRAPHICS_FUNC_ARGS) //Both COAL and Broken Coal
return 0;
}
+int graphics_BRCK(GRAPHICS_FUNC_ARGS)
+{
+ if (cpart->tmp == 1)
+ {
+ *pixel_mode |= PMODE_GLOW;
+ *colb += 100;
+ }
+ return 0;
+}
diff --git a/src/elements/pipe.c b/src/elements/pipe.c
index aa6e16b..3aeaf7b 100644
--- a/src/elements/pipe.c
+++ b/src/elements/pipe.c
@@ -17,9 +17,150 @@
#define PFLAG_NORMALSPEED 0x00010000
+// parts[].tmp flags
+// trigger flags to be processed this frame (trigger flags for next frame are shifted 3 bits to the left):
+#define PPIP_TMPFLAG_TRIGGER_ON 0x10000000
+#define PPIP_TMPFLAG_TRIGGER_OFF 0x08000000
+#define PPIP_TMPFLAG_TRIGGER_REVERSE 0x04000000
+#define PPIP_TMPFLAG_TRIGGERS 0x1C000000
+// current status of the pipe
+#define PPIP_TMPFLAG_PAUSED 0x02000000
+#define PPIP_TMPFLAG_REVERSED 0x01000000
+// 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
+
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};
+int ppip_changed = 0;
+
+void PPIP_flood_trigger(int x, int y, int sparkedBy)
+{
+ int coord_stack_limit = XRES*YRES;
+ unsigned short (*coord_stack)[2];
+ int coord_stack_size = 0;
+ int x1, x2;
+
+ // Separate flags for on and off in case PPIP is sparked by PSCN and NSCN on the same frame
+ // - then PSCN can override NSCN and behaviour is not dependent on particle order
+ int prop = 0;
+ if (sparkedBy==PT_PSCN) prop = PPIP_TMPFLAG_TRIGGER_ON << 3;
+ else if (sparkedBy==PT_NSCN) prop = PPIP_TMPFLAG_TRIGGER_OFF << 3;
+ else if (sparkedBy==PT_INST) prop = PPIP_TMPFLAG_TRIGGER_REVERSE << 3;
+
+ if (prop==0 || (pmap[y][x]&0xFF)!=PT_PPIP || (parts[pmap[y][x]>>8].tmp & prop))
+ return;
+
+ coord_stack = malloc(sizeof(unsigned short)*2*coord_stack_limit);
+ coord_stack[coord_stack_size][0] = x;
+ coord_stack[coord_stack_size][1] = y;
+ coord_stack_size++;
+
+ do
+ {
+ coord_stack_size--;
+ x = coord_stack[coord_stack_size][0];
+ y = coord_stack[coord_stack_size][1];
+ x1 = x2 = x;
+ // go left as far as possible
+ while (x1>=CELL)
+ {
+ if ((pmap[y][x1-1]&0xFF)!=PT_PPIP)
+ {
+ break;
+ }
+ x1--;
+ }
+ // go right as far as possible
+ while (x2<XRES-CELL)
+ {
+ if ((pmap[y][x2+1]&0xFF)!=PT_PPIP)
+ {
+ break;
+ }
+ x2++;
+ }
+ // fill span
+ for (x=x1; x<=x2; x++)
+ {
+ if (!(parts[pmap[y][x]>>8].tmp & prop))
+ ppip_changed = 1;
+ parts[pmap[y][x]>>8].tmp |= prop;
+ }
+
+ // add adjacent pixels to stack
+ // +-1 to x limits to include diagonally adjacent pixels
+ // Don't need to check x bounds here, because already limited to [CELL, XRES-CELL]
+ if (y>=CELL+1)
+ for (x=x1-1; x<=x2+1; x++)
+ if ((pmap[y-1][x]&0xFF)==PT_PPIP && !(parts[pmap[y-1][x]>>8].tmp & prop))
+ {
+ coord_stack[coord_stack_size][0] = x;
+ coord_stack[coord_stack_size][1] = y-1;
+ coord_stack_size++;
+ if (coord_stack_size>=coord_stack_limit)
+ {
+ free(coord_stack);
+ return;
+ }
+ }
+ if (y<YRES-CELL-1)
+ for (x=x1-1; x<=x2+1; x++)
+ if ((pmap[y+1][x]&0xFF)==PT_PPIP && !(parts[pmap[y+1][x]>>8].tmp & prop))
+ {
+ coord_stack[coord_stack_size][0] = x;
+ coord_stack[coord_stack_size][1] = y+1;
+ coord_stack_size++;
+ if (coord_stack_size>=coord_stack_limit)
+ {
+ free(coord_stack);
+ return;
+ }
+ }
+ } while (coord_stack_size>0);
+ free(coord_stack);
+}
+
+void PIPE_transfer_pipe_to_part(particle *pipe, particle *part)
+{
+ part->type = (pipe->tmp & 0xFF);
+ part->temp = pipe->temp;
+ part->life = pipe->tmp2;
+ part->tmp = pipe->pavg[0];
+ part->ctype = pipe->pavg[1];
+ pipe->tmp &= ~0xFF;
+
+ part->vx = 0.0f;
+ part->vy = 0.0f;
+ part->tmp2 = 0;
+ part->flags = 0;
+ part->dcolour = 0;
+}
+
+void PIPE_transfer_part_to_pipe(particle *part, particle *pipe)
+{
+ pipe->tmp = (pipe->tmp&~0xFF) | part->type;
+ pipe->temp = part->temp;
+ pipe->tmp2 = part->life;
+ pipe->pavg[0] = part->tmp;
+ pipe->pavg[1] = part->ctype;
+}
+
+void PIPE_transfer_pipe_to_pipe(particle *src, particle *dest)
+{
+ dest->tmp = (dest->tmp&~0xFF) | (src->tmp&0xFF);
+ dest->temp = src->temp;
+ dest->tmp2 = src->tmp2;
+ dest->pavg[0] = src->pavg[0];
+ dest->pavg[1] = src->pavg[1];
+ src->tmp &= ~0xFF;
+}
+
+
void pushParticle(int i, int count, int original)
{
int rndstore, rnd, rx, ry, r, x, y, np, q, notctype=(((parts[i].ctype)%3)+2);
@@ -33,7 +174,7 @@ void pushParticle(int i, int count, int original)
rndstore = rand();
// RAND_MAX is at least 32767 on all platforms i.e. pow(8,5)-1
// so can go 5 cycles without regenerating rndstore
- for (q=0; q<3; q++)//try to push twice
+ for (q=0; q<3; q++)//try to push 3 times
{
rnd = rndstore&7;
rndstore = rndstore>>3;
@@ -44,19 +185,25 @@ void pushParticle(int i, int count, int original)
r = pmap[y+ry][x+rx];
if (!r)
continue;
- else if ((r&0xFF)==PT_PIPE && parts[r>>8].ctype!=notctype && (parts[r>>8].tmp&0xFF)==0)
+ else if (((r&0xFF)==PT_PIPE || (r&0xFF) == PT_PPIP) && parts[r>>8].ctype!=notctype && (parts[r>>8].tmp&0xFF)==0)
{
- parts[r>>8].tmp = (parts[r>>8].tmp&~0xFF) | (parts[i].tmp&0xFF);
- parts[r>>8].temp = parts[i].temp;
- parts[r>>8].tmp2 = parts[i].tmp2;
- parts[r>>8].pavg[0] = parts[i].pavg[0];
- parts[r>>8].pavg[1] = parts[i].pavg[1];
+ PIPE_transfer_pipe_to_pipe(parts+i, parts+(r>>8));
if (r>>8 > original)
parts[r>>8].flags |= PFLAG_NORMALSPEED;//skip particle push, normalizes speed
- parts[i].tmp &= ~0xFF;
count++;
pushParticle(r>>8,count,original);
}
+ else if ((r&0xFF) == PT_PRTI) //Pass particles into PRTI for a pipe speed increase
+ {
+ int nnx;
+ for (nnx=0; nnx<80; nnx++)
+ if (!portalp[parts[r>>8].tmp][count][nnx].type)
+ {
+ PIPE_transfer_pipe_to_part(parts+i, &(portalp[parts[r>>8].tmp][count][nnx]));
+ count++;
+ break;
+ }
+ }
}
}
}
@@ -64,24 +211,35 @@ void pushParticle(int i, int count, int original)
{
int coords = 7 - ((parts[i].tmp>>10)&7);
r = pmap[y+ pos_1_ry[coords]][x+ pos_1_rx[coords]];
- if (!r)
- {
- }
- else if ((r&0xFF)==PT_PIPE && parts[r>>8].ctype!=notctype && (parts[r>>8].tmp&0xFF)==0)
+ if (((r&0xFF)==PT_PIPE || (r&0xFF) == PT_PPIP) && parts[r>>8].ctype!=notctype && (parts[r>>8].tmp&0xFF)==0)
{
- parts[r>>8].tmp = (parts[r>>8].tmp&~0xFF) | (parts[i].tmp&0xFF);
- parts[r>>8].temp = parts[i].temp;
- parts[r>>8].tmp2 = parts[i].tmp2;
- parts[r>>8].pavg[0] = parts[i].pavg[0];
- parts[r>>8].pavg[1] = parts[i].pavg[1];
+ PIPE_transfer_pipe_to_pipe(parts+i, parts+(r>>8));
if (r>>8 > original)
parts[r>>8].flags |= PFLAG_NORMALSPEED;//skip particle push, normalizes speed
- parts[i].tmp &= ~0xFF;
count++;
pushParticle(r>>8,count,original);
}
-
-
+ else if ((r&0xFF) == PT_PRTI) //Pass particles into PRTI for a pipe speed increase
+ {
+ int nnx;
+ for (nnx=0; nnx<80; nnx++)
+ if (!portalp[parts[r>>8].tmp][count][nnx].type)
+ {
+ PIPE_transfer_pipe_to_part(parts+i, &(portalp[parts[r>>8].tmp][count][nnx]));
+ count++;
+ break;
+ }
+ }
+ else if ((r&0xFF) == PT_NONE) //Move particles out of pipe automatically, much faster at ends
+ {
+ rx = pos_1_rx[coords];
+ ry = pos_1_ry[coords];
+ np = create_part(-1,x+rx,y+ry,parts[i].tmp&0xFF);
+ if (np!=-1)
+ {
+ PIPE_transfer_pipe_to_part(parts+i, parts+np);
+ }
+ }
}
return;
}
@@ -89,7 +247,62 @@ void pushParticle(int i, int count, int original)
int update_PIPE(UPDATE_FUNC_ARGS) {
int r, rx, ry, np;
int rnd, rndstore;
- if (parts[i].ctype>=2 && parts[i].ctype<=4)
+ 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 (x+rx>=0 && y+ry>0 && x+rx<XRES && y+ry<YRES && (rx || ry))
+ {
+ r = pmap[y+ry][x+rx];
+ if ((r&0xFF) == PT_BRCK)
+ {
+ if (parts[i].tmp & PPIP_TMPFLAG_PAUSED)
+ parts[r>>8].tmp = 0;
+ else
+ parts[r>>8].tmp = 1; //make surrounding BRCK glow
+ }
+ }
+ }
+ }
+
+ if (parts[i].tmp & PPIP_TMPFLAG_TRIGGER_REVERSE)
+ {
+ parts[i].tmp ^= PPIP_TMPFLAG_REVERSED;
+ if (parts[i].ctype == 2) //Switch colors so it goes in reverse
+ parts[i].ctype = 4;
+ else if (parts[i].ctype == 4)
+ parts[i].ctype = 2;
+ 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].ctype>=2 && parts[i].ctype<=4 && !(parts[i].tmp & PPIP_TMPFLAG_PAUSED))
{
if (parts[i].life==3)
{
@@ -104,7 +317,7 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
r = pmap[y+ry][x+rx];
if (!r)
continue;
- if ((r&0xFF)==PT_PIPE&&parts[r>>8].ctype==1)
+ if (((r&0xFF)==PT_PIPE || (r&0xFF) == PT_PPIP)&&parts[r>>8].ctype==1)
{
parts[r>>8].ctype = (((parts[i].ctype)%3)+2);//reverse
parts[r>>8].life = 6;
@@ -112,11 +325,13 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
{
parts[r>>8].tmp |= 0x200;//will transfer to a single pixel pipe
parts[r>>8].tmp |= count<<10;//coords of where it came from
+ parts[i].tmp |= ((7-count)<<14);
+ parts[i].tmp |= 0x2000;
}
neighborcount ++;
lastneighbor = r>>8;
}
- else if ((r&0xFF)==PT_PIPE&&parts[r>>8].ctype!=(((parts[i].ctype-1)%3)+2))
+ else if (((r&0xFF)==PT_PIPE || (r&0xFF) == PT_PPIP)&&parts[r>>8].ctype!=(((parts[i].ctype-1)%3)+2))
{
neighborcount ++;
lastneighbor = r>>8;
@@ -128,7 +343,7 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
}
else
{
- if (parts[i].flags&PFLAG_NORMALSPEED)//skip particle push to prevent particle number being higher causeing speed up
+ if (parts[i].flags&PFLAG_NORMALSPEED)//skip particle push to prevent particle number being higher causing speed up
{
parts[i].flags &= ~PFLAG_NORMALSPEED;
}
@@ -154,11 +369,7 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
np = create_part(-1,x+rx,y+ry,parts[i].tmp&0xFF);
if (np!=-1)
{
- parts[np].temp = parts[i].temp;//pipe saves temp and life now
- parts[np].life = parts[i].tmp2;
- parts[np].tmp = parts[i].pavg[0];
- parts[np].ctype = parts[i].pavg[1];
- parts[i].tmp &= ~0xFF;
+ PIPE_transfer_pipe_to_part(parts+i, parts+np);
}
}
//try eating particle at entrance
@@ -166,22 +377,13 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
{
if ((r&0xFF)==PT_SOAP)
detach(r>>8);
- parts[i].tmp = (parts[i].tmp&~0xFF) | parts[r>>8].type;
- parts[i].temp = parts[r>>8].temp;
- parts[i].tmp2 = parts[r>>8].life;
- parts[i].pavg[0] = parts[r>>8].tmp;
- parts[i].pavg[1] = parts[r>>8].ctype;
+ PIPE_transfer_part_to_pipe(parts+(r>>8), parts+i);
kill_part(r>>8);
}
else if ((parts[i].tmp&0xFF) == 0 && (r&0xFF)==PT_STOR && parts[r>>8].tmp && (ptypes[parts[r>>8].tmp].properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)))
{
- parts[i].tmp = parts[r>>8].tmp;
- parts[i].temp = parts[r>>8].temp;
- parts[i].tmp2 = parts[r>>8].tmp2;
- parts[i].pavg[0] = parts[r>>8].pavg[0];
- parts[i].pavg[1] = parts[r>>8].pavg[1];
- parts[r>>8].tmp = 0;
- parts[r>>8].life = 0;
+ // STOR stores properties in the same places as PIPE does
+ PIPE_transfer_pipe_to_pipe(parts+(r>>8), parts+i);
}
}
}
@@ -217,7 +419,11 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
{
r = pmap[y+ry][x+rx];
if (!r)
- create_part(-1,x+rx,y+ry,PT_BRCK);//BRCK border, people didn't like DMND
+ {
+ int index = create_part(-1,x+rx,y+ry,PT_BRCK);//BRCK border, people didn't like DMND
+ if (parts[i].type == PT_PPIP && index != -1)
+ parts[index].tmp = 1;
+ }
}
}
if (parts[i].life<=1)
@@ -244,11 +450,11 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
if (x+rx>=0 && y+ry>0 && x+rx<XRES && y+ry<YRES && (rx || ry))
{
r = pmap[y+ry][x+rx];
- if ((r&0xFF)==PT_PIPE && parts[i].ctype==1 && parts[i].life )
+ if (((r&0xFF)==PT_PIPE || (r&0xFF) == PT_PPIP) && parts[i].ctype==1 && parts[i].life )
issingle = 0;
}
- if (issingle)
- parts[i].tmp |= 0x100;
+ if (issingle)
+ parts[i].tmp |= 0x100;
}
else if (parts[i].life==2)
{
@@ -277,6 +483,7 @@ int graphics_PIPE(GRAPHICS_FUNC_ARGS)
if (graphicscache[t].isready)
{
*pixel_mode = graphicscache[t].pixel_mode;
+ *cola = graphicscache[t].cola;
*colr = graphicscache[t].colr;
*colg = graphicscache[t].colg;
*colb = graphicscache[t].colb;
@@ -288,8 +495,8 @@ int graphics_PIPE(GRAPHICS_FUNC_ARGS)
else
{
*colr = PIXR(ptypes[t].pcolors);
- *colg = PIXR(ptypes[t].pcolors);
- *colb = PIXR(ptypes[t].pcolors);
+ *colg = PIXG(ptypes[t].pcolors);
+ *colb = PIXB(ptypes[t].pcolors);
if (ptypes[t].graphics_func)
{
(*(ptypes[t].graphics_func))(&tpart, nx, ny, pixel_mode, cola, colr, colg, colb, firea, firer, fireg, fireb);
diff --git a/src/elements/sprk.c b/src/elements/sprk.c
index 291937a..1c4c5bc 100644
--- a/src/elements/sprk.c
+++ b/src/elements/sprk.c
@@ -154,6 +154,11 @@ int update_SPRK(UPDATE_FUNC_ARGS) {
else if (ct==PT_NSCN && parts[r>>8].tmp == 3) parts[r>>8].tmp = 1;
}
+ if (rt == PT_PPIP && parts[i].life == 3 && pavg!=PT_INSL)
+ {
+ if (ct == PT_NSCN || ct == PT_PSCN || ct == PT_INST)
+ PPIP_flood_trigger(x+rx, y+ry, ct);
+ }
// ct = spark from material, rt = spark to material. Make conduct_sprk = 0 if conduction not allowed