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).
This commit is contained in:
jacksonmj 2012-08-11 09:53:02 +01:00
parent a4c15746b8
commit 8ec0f41fb1
8 changed files with 317 additions and 57 deletions

View File

@ -160,11 +160,9 @@
#define PT_PVOD 84 #define PT_PVOD 84
#define PT_CONV 85 #define PT_CONV 85
#define PT_CAUS 86 #define PT_CAUS 86
#define PT_LIGH 87 #define PT_LIGH 87
#define PT_TESC 88 #define PT_TESC 88
#define PT_DEST 89 #define PT_DEST 89
#define PT_SPNG 90 #define PT_SPNG 90
#define PT_RIME 91 #define PT_RIME 91
#define PT_FOG 92 #define PT_FOG 92
@ -237,7 +235,8 @@
#define PT_FIGH 158 #define PT_FIGH 158
#define PT_FRAY 159 #define PT_FRAY 159
#define PT_REPL 160 #define PT_REPL 160
#define PT_NUM 161 #define PT_PPIP 161
#define PT_NUM 162
#define R_TEMP 22 #define R_TEMP 22
#define MAX_TEMP 9999 #define MAX_TEMP 9999
@ -352,6 +351,7 @@ int graphics_SOAP(GRAPHICS_FUNC_ARGS);
int graphics_EXOT(GRAPHICS_FUNC_ARGS); int graphics_EXOT(GRAPHICS_FUNC_ARGS);
int graphics_WARP(GRAPHICS_FUNC_ARGS); int graphics_WARP(GRAPHICS_FUNC_ARGS);
int graphics_EMBR(GRAPHICS_FUNC_ARGS); int graphics_EMBR(GRAPHICS_FUNC_ARGS);
int graphics_BRCK(GRAPHICS_FUNC_ARGS);
void TRON_init_graphics(); void TRON_init_graphics();
@ -482,6 +482,7 @@ int update_legacy_all(UPDATE_FUNC_ARGS);
int run_stickman(playerst* playerp, UPDATE_FUNC_ARGS); int run_stickman(playerst* playerp, UPDATE_FUNC_ARGS);
void STKM_init_legs(playerst* playerp, int i); void STKM_init_legs(playerst* playerp, int i);
void STKM_interact(playerst* playerp, int i, int x, int y); void STKM_interact(playerst* playerp, int i, int x, int y);
void PPIP_flood_trigger(int x, int y, int sparkedBy);
struct part_type struct part_type
{ {
@ -759,6 +760,7 @@ extern int portal_ry[8];
extern int wire_placed; extern int wire_placed;
extern int force_stacking_check; extern int force_stacking_check;
extern int ppip_changed;
extern playerst player; extern playerst player;
extern playerst player2; extern playerst player2;

View File

@ -98,7 +98,7 @@ part_type ptypes[PT_NUM] =
{"DYST", PIXPACK(0xBBB0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 20, 0, 0, 30, 0, 1, 80, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Dead Yeast.", ST_SOLID, TYPE_PART, NULL, NULL}, {"DYST", PIXPACK(0xBBB0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 20, 0, 0, 30, 0, 1, 80, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Dead Yeast.", ST_SOLID, TYPE_PART, NULL, NULL},
{"THRM", PIXPACK(0xA08090), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 90, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 211, "Thermite. Burns at extremely high temperature.", ST_SOLID, TYPE_PART, &update_THRM, NULL}, {"THRM", PIXPACK(0xA08090), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 90, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 211, "Thermite. Burns at extremely high temperature.", ST_SOLID, TYPE_PART, &update_THRM, NULL},
{"GLOW", PIXPACK(0x445464), 0.3f, 0.02f * CFDS, 0.98f, 0.80f, 0.0f, 0.15f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 2, 1, 1, 40, SC_LIQUID, R_TEMP+20.0f+273.15f, 44, "Glow, Glows under pressure", ST_LIQUID, TYPE_LIQUID|PROP_LIFE_DEC, &update_GLOW, &graphics_GLOW}, {"GLOW", PIXPACK(0x445464), 0.3f, 0.02f * CFDS, 0.98f, 0.80f, 0.0f, 0.15f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 2, 1, 1, 40, SC_LIQUID, R_TEMP+20.0f+273.15f, 44, "Glow, Glows under pressure", ST_LIQUID, TYPE_LIQUID|PROP_LIFE_DEC, &update_GLOW, &graphics_GLOW},
{"BRCK", PIXPACK(0x808080), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "Brick, breakable building material.", ST_SOLID, TYPE_SOLID|PROP_HOT_GLOW, NULL, NULL}, {"BRCK", PIXPACK(0x808080), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "Brick, breakable building material.", ST_SOLID, TYPE_SOLID|PROP_HOT_GLOW, NULL, &graphics_BRCK},
{"CFLM", PIXPACK(0x8080FF), 0.9f, 0.04f * CFDS, 0.97f, 0.20f, 0.0f, -0.1f, 0.00f, 0.0005f * CFDS, 1, 0, 0, 0, 1, 1, 1, 2, SC_EXPLOSIVE, 0.0f, 88, "Sub-zero flame.", ST_LIQUID, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL, NULL, &graphics_HFLM}, {"CFLM", PIXPACK(0x8080FF), 0.9f, 0.04f * CFDS, 0.97f, 0.20f, 0.0f, -0.1f, 0.00f, 0.0005f * CFDS, 1, 0, 0, 0, 1, 1, 1, 2, SC_EXPLOSIVE, 0.0f, 88, "Sub-zero flame.", ST_LIQUID, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL, NULL, &graphics_HFLM},
{"FIRW", PIXPACK(0xFFA040), 0.2f, 0.01f * CFDS, 0.96f, 0.95f, -0.1f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 30, 1, 1, 55, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 70, "Fireworks!", ST_SOLID, TYPE_PART|PROP_LIFE_DEC, &update_FIRW, &graphics_FIRW}, {"FIRW", PIXPACK(0xFFA040), 0.2f, 0.01f * CFDS, 0.96f, 0.95f, -0.1f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 30, 1, 1, 55, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 70, "Fireworks!", ST_SOLID, TYPE_PART|PROP_LIFE_DEC, &update_FIRW, &graphics_FIRW},
{"FUSE", PIXPACK(0x0A5706), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.0f, 0.0f * CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 200, "Solid. Burns slowly. Ignites at somewhat high temperatures and electricity.", ST_SOLID, TYPE_SOLID, &update_FUSE, NULL}, {"FUSE", PIXPACK(0x0A5706), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.0f, 0.0f * CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 200, "Solid. Burns slowly. Ignites at somewhat high temperatures and electricity.", ST_SOLID, TYPE_SOLID, &update_FUSE, NULL},
@ -191,7 +191,8 @@ part_type ptypes[PT_NUM] =
{"GBMB", PIXPACK(0x1144BB), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 20, 1, 1, 30, SC_EXPLOSIVE, R_TEMP-2.0f +273.15f, 29, "Sticks to first object it touches then produces strong gravity push.", ST_NONE, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_GBMB, &graphics_GBMB}, {"GBMB", PIXPACK(0x1144BB), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 20, 1, 1, 30, SC_EXPLOSIVE, R_TEMP-2.0f +273.15f, 29, "Sticks to first object it touches then produces strong gravity push.", ST_NONE, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_GBMB, &graphics_GBMB},
{"FIGH", PIXPACK(0xFFE0A0), 0.5f, 0.00f * CFDS, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.00f * CFDS, 0, 0, 0, 0, 0, 1, 1, 50, SC_SPECIAL, R_TEMP+14.6f+273.15f, 0, "Fighter. Tries to kill stickmen.", ST_NONE, 0, &update_FIGH, &graphics_STKM}, {"FIGH", PIXPACK(0xFFE0A0), 0.5f, 0.00f * CFDS, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.00f * CFDS, 0, 0, 0, 0, 0, 1, 1, 50, SC_SPECIAL, R_TEMP+14.6f+273.15f, 0, "Fighter. Tries to kill stickmen.", ST_NONE, 0, &update_FIGH, &graphics_STKM},
{"FRAY", PIXPACK(0x00BBFF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_FORCE, 20.0f+0.0f +273.15f, 0, "Force Emitter. Push or pull objects based on temp value, use like ARAY", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_FRAY, NULL}, {"FRAY", PIXPACK(0x00BBFF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_FORCE, 20.0f+0.0f +273.15f, 0, "Force Emitter. Push or pull objects based on temp value, use like ARAY", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_FRAY, NULL},
{"RPEL", PIXPACK(0x99CC00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_FORCE, 20.0f+0.0f +273.15f, 0, "Repel or attract particles based on temp value.", ST_NONE, TYPE_SOLID, &update_REPL, NULL}, {"RPEL", PIXPACK(0x99CC00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_FORCE, 20.0f+0.0f +273.15f, 0, "Repel or attract particles based on temp value.", ST_NONE, TYPE_SOLID, &update_REPL, NULL},
{"PPIP", PIXPACK(0x444466), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_POWERED, 273.15f, 0, "Powered version of pipe", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_PIPE, &graphics_PIPE},
//Name Colour Advec Airdrag Airloss Loss Collid Grav Diffus Hotair Fal Burn Exp Mel Hrd M Use Weight Section H Ins Description //Name Colour Advec Airdrag Airloss Loss Collid Grav Diffus Hotair Fal Burn Exp Mel Hrd M Use Weight Section H Ins Description
}; };
@ -368,6 +369,7 @@ part_transition ptransitions[PT_NUM] =
/* FIGH */ {IPL, NT, IPH, NT, ITL, NT, 620.0f, PT_FIRE}, /* FIGH */ {IPL, NT, IPH, NT, ITL, NT, 620.0f, PT_FIRE},
/* FRAY */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, /* FRAY */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT},
/* REPL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, /* REPL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT},
/* PPIP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT},
}; };
// This is an enthalpy values table, converted into TPT imaginary units // This is an enthalpy values table, converted into TPT imaginary units
@ -535,6 +537,7 @@ unsigned int platent[PT_NUM] =
/* FIGH */ 0, /* FIGH */ 0,
/* FRAY */ 0, /* FRAY */ 0,
/* REPL */ 0, /* REPL */ 0,
/* PPIP */ 0,
}; };
#undef IPL #undef IPL
#undef IPH #undef IPH

View File

@ -514,3 +514,12 @@ int graphics_COAL(GRAPHICS_FUNC_ARGS) //Both COAL and Broken Coal
return 0; return 0;
} }
int graphics_BRCK(GRAPHICS_FUNC_ARGS)
{
if (cpart->tmp == 1)
{
*pixel_mode |= PMODE_GLOW;
*colb += 100;
}
return 0;
}

View File

@ -17,9 +17,150 @@
#define PFLAG_NORMALSPEED 0x00010000 #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_rx[] = {-1,-1,-1, 0, 0, 1, 1, 1};
signed char pos_1_ry[] = {-1, 0, 1,-1, 1,-1, 0, 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) void pushParticle(int i, int count, int original)
{ {
int rndstore, rnd, rx, ry, r, x, y, np, q, notctype=(((parts[i].ctype)%3)+2); 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(); rndstore = rand();
// RAND_MAX is at least 32767 on all platforms i.e. pow(8,5)-1 // RAND_MAX is at least 32767 on all platforms i.e. pow(8,5)-1
// so can go 5 cycles without regenerating rndstore // 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; rnd = rndstore&7;
rndstore = rndstore>>3; rndstore = rndstore>>3;
@ -44,19 +185,25 @@ void pushParticle(int i, int count, int original)
r = pmap[y+ry][x+rx]; r = pmap[y+ry][x+rx];
if (!r) if (!r)
continue; 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); PIPE_transfer_pipe_to_pipe(parts+i, parts+(r>>8));
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];
if (r>>8 > original) if (r>>8 > original)
parts[r>>8].flags |= PFLAG_NORMALSPEED;//skip particle push, normalizes speed parts[r>>8].flags |= PFLAG_NORMALSPEED;//skip particle push, normalizes speed
parts[i].tmp &= ~0xFF;
count++; count++;
pushParticle(r>>8,count,original); 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); int coords = 7 - ((parts[i].tmp>>10)&7);
r = pmap[y+ pos_1_ry[coords]][x+ pos_1_rx[coords]]; r = pmap[y+ pos_1_ry[coords]][x+ pos_1_rx[coords]];
if (!r) if (((r&0xFF)==PT_PIPE || (r&0xFF) == PT_PPIP) && parts[r>>8].ctype!=notctype && (parts[r>>8].tmp&0xFF)==0)
{ {
} PIPE_transfer_pipe_to_pipe(parts+i, parts+(r>>8));
else if ((r&0xFF)==PT_PIPE && 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];
if (r>>8 > original) if (r>>8 > original)
parts[r>>8].flags |= PFLAG_NORMALSPEED;//skip particle push, normalizes speed parts[r>>8].flags |= PFLAG_NORMALSPEED;//skip particle push, normalizes speed
parts[i].tmp &= ~0xFF;
count++; count++;
pushParticle(r>>8,count,original); 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; return;
} }
@ -89,7 +247,62 @@ void pushParticle(int i, int count, int original)
int update_PIPE(UPDATE_FUNC_ARGS) { int update_PIPE(UPDATE_FUNC_ARGS) {
int r, rx, ry, np; int r, rx, ry, np;
int rnd, rndstore; 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) if (parts[i].life==3)
{ {
@ -104,7 +317,7 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
r = pmap[y+ry][x+rx]; r = pmap[y+ry][x+rx];
if (!r) if (!r)
continue; 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].ctype = (((parts[i].ctype)%3)+2);//reverse
parts[r>>8].life = 6; 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 |= 0x200;//will transfer to a single pixel pipe
parts[r>>8].tmp |= count<<10;//coords of where it came from parts[r>>8].tmp |= count<<10;//coords of where it came from
parts[i].tmp |= ((7-count)<<14);
parts[i].tmp |= 0x2000;
} }
neighborcount ++; neighborcount ++;
lastneighbor = r>>8; 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 ++; neighborcount ++;
lastneighbor = r>>8; lastneighbor = r>>8;
@ -128,7 +343,7 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
} }
else 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; 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); np = create_part(-1,x+rx,y+ry,parts[i].tmp&0xFF);
if (np!=-1) if (np!=-1)
{ {
parts[np].temp = parts[i].temp;//pipe saves temp and life now PIPE_transfer_pipe_to_part(parts+i, parts+np);
parts[np].life = parts[i].tmp2;
parts[np].tmp = parts[i].pavg[0];
parts[np].ctype = parts[i].pavg[1];
parts[i].tmp &= ~0xFF;
} }
} }
//try eating particle at entrance //try eating particle at entrance
@ -166,22 +377,13 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
{ {
if ((r&0xFF)==PT_SOAP) if ((r&0xFF)==PT_SOAP)
detach(r>>8); detach(r>>8);
parts[i].tmp = (parts[i].tmp&~0xFF) | parts[r>>8].type; PIPE_transfer_part_to_pipe(parts+(r>>8), parts+i);
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;
kill_part(r>>8); 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))) 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; // STOR stores properties in the same places as PIPE does
parts[i].temp = parts[r>>8].temp; PIPE_transfer_pipe_to_pipe(parts+(r>>8), parts+i);
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;
} }
} }
} }
@ -217,7 +419,11 @@ int update_PIPE(UPDATE_FUNC_ARGS) {
{ {
r = pmap[y+ry][x+rx]; r = pmap[y+ry][x+rx];
if (!r) 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) 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)) if (x+rx>=0 && y+ry>0 && x+rx<XRES && y+ry<YRES && (rx || ry))
{ {
r = pmap[y+ry][x+rx]; 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; issingle = 0;
} }
if (issingle) if (issingle)
parts[i].tmp |= 0x100; parts[i].tmp |= 0x100;
} }
else if (parts[i].life==2) else if (parts[i].life==2)
{ {
@ -277,6 +483,7 @@ int graphics_PIPE(GRAPHICS_FUNC_ARGS)
if (graphicscache[t].isready) if (graphicscache[t].isready)
{ {
*pixel_mode = graphicscache[t].pixel_mode; *pixel_mode = graphicscache[t].pixel_mode;
*cola = graphicscache[t].cola;
*colr = graphicscache[t].colr; *colr = graphicscache[t].colr;
*colg = graphicscache[t].colg; *colg = graphicscache[t].colg;
*colb = graphicscache[t].colb; *colb = graphicscache[t].colb;
@ -288,8 +495,8 @@ int graphics_PIPE(GRAPHICS_FUNC_ARGS)
else else
{ {
*colr = PIXR(ptypes[t].pcolors); *colr = PIXR(ptypes[t].pcolors);
*colg = PIXR(ptypes[t].pcolors); *colg = PIXG(ptypes[t].pcolors);
*colb = PIXR(ptypes[t].pcolors); *colb = PIXB(ptypes[t].pcolors);
if (ptypes[t].graphics_func) if (ptypes[t].graphics_func)
{ {
(*(ptypes[t].graphics_func))(&tpart, nx, ny, pixel_mode, cola, colr, colg, colb, firea, firer, fireg, fireb); (*(ptypes[t].graphics_func))(&tpart, nx, ny, pixel_mode, cola, colr, colg, colb, firea, firer, fireg, fireb);

View File

@ -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; 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 // ct = spark from material, rt = spark to material. Make conduct_sprk = 0 if conduction not allowed

View File

@ -1896,7 +1896,7 @@ int main(int argc, char *argv[])
sprintf(nametext, "Molten %s", lowername); sprintf(nametext, "Molten %s", lowername);
} }
else if ((cr&0xFF)==PT_PIPE && (parts[cr>>8].tmp&0xFF) > 0 && (parts[cr>>8].tmp&0xFF) < PT_NUM ) else if (((cr&0xFF)==PT_PIPE || (cr&0xFF) == PT_PPIP) && (parts[cr>>8].tmp&0xFF) > 0 && (parts[cr>>8].tmp&0xFF) < PT_NUM )
{ {
char lowername[6]; char lowername[6];
int ix; int ix;
@ -1909,7 +1909,7 @@ int main(int argc, char *argv[])
else if (DEBUG_MODE) else if (DEBUG_MODE)
{ {
int tctype = parts[cr>>8].ctype; int tctype = parts[cr>>8].ctype;
if ((cr&0xFF)==PT_PIPE) if ((cr&0xFF)==PT_PIPE || (cr&0xFF) == PT_PPIP)
{ {
tctype = parts[cr>>8].tmp&0xFF; tctype = parts[cr>>8].tmp&0xFF;
} }

View File

@ -1027,6 +1027,7 @@ inline int create_part(int p, int x, int y, int tv)//the function for creating a
parts[i].life = 100; parts[i].life = 100;
break; break;
case PT_PIPE: case PT_PIPE:
case PT_PPIP:
parts[i].life = 60; parts[i].life = 60;
break; break;
case PT_BCOL: case PT_BCOL:
@ -1788,6 +1789,20 @@ void update_particles_i(pixel *vid, int start, int inc)
} }
} }
} }
if (ppip_changed)
{
for (i=0; i<=parts_lastActiveIndex; i++)
{
if (parts[i].type==PT_PPIP)
{
parts[i].tmp |= (parts[i].tmp&0xE0000000)>>3;
parts[i].tmp &= ~0xE0000000;
}
}
ppip_changed = 0;
}
//game of life! //game of life!
if (ISGOL==1&&++CGOL>=GSPEED)//GSPEED is frames per generation if (ISGOL==1&&++CGOL>=GSPEED)//GSPEED is frames per generation
{ {
@ -2599,7 +2614,7 @@ killed:
} }
r = pmap[fin_y][fin_x]; r = pmap[fin_y][fin_x];
if ((r & 0xFF) == PT_PIPE && !(parts[r>>8].tmp&0xFF)) if (((r&0xFF)==PT_PIPE || (r&0xFF) == PT_PPIP) && !(parts[r>>8].tmp&0xFF))
{ {
parts[r>>8].tmp = (parts[r>>8].tmp&~0xFF) | parts[i].type; parts[r>>8].tmp = (parts[r>>8].tmp&~0xFF) | parts[i].type;
parts[r>>8].temp = parts[i].temp; parts[r>>8].temp = parts[i].temp;

View File

@ -56,6 +56,7 @@ int parse_save(void *save, int size, int replace, int x0, int y0, unsigned char
return 1; return 1;
} }
force_stacking_check = 1;//check for excessive stacking of particles next time update_particles is run force_stacking_check = 1;//check for excessive stacking of particles next time update_particles is run
ppip_changed = 1;
if(saveData[0] == 'O' && saveData[1] == 'P' && saveData[2] == 'S') if(saveData[0] == 'O' && saveData[1] == 'P' && saveData[2] == 'S')
{ {
return parse_save_OPS(save, size, replace, x0, y0, bmap, vx, vy, pv, fvx, fvy, signs, partsptr, pmap); return parse_save_OPS(save, size, replace, x0, y0, bmap, vx, vy, pv, fvx, fvy, signs, partsptr, pmap);
@ -391,6 +392,11 @@ pixel *prerender_save_OPS(void *save, int size, int *width, int *height)
if(fieldDescriptor & 0x10) if(fieldDescriptor & 0x10)
{ {
if(i++ >= partsDataLen) goto fail; if(i++ >= partsDataLen) goto fail;
if(fieldDescriptor & 0x1000)
{
if(i+1 >= partsDataLen) goto fail;
i += 2;
}
} }
} }
@ -573,7 +579,7 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
//Copy parts data //Copy parts data
/* Field descriptor format: /* Field descriptor format:
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| tmp2[2] | tmp2[1] | ctype[2] | vy | vx | dcololour | ctype[1] | tmp[2] | tmp[1] | life[2] | life[1] | temp dbl len| tmp[3+4] | tmp2[2] | tmp2[1] | ctype[2] | vy | vx | dcololour | ctype[1] | tmp[2] | tmp[1] | life[2] | life[1] | temp dbl len|
life[2] means a second byte (for a 16 bit field) if life[1] is present life[2] means a second byte (for a 16 bit field) if life[1] is present
*/ */
partsData = malloc(NPART * (sizeof(particle)+1)); partsData = malloc(NPART * (sizeof(particle)+1));
@ -634,7 +640,7 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
} }
} }
//Tmp (optional), 1 to 2 bytes //Tmp (optional), 1, 2 or 4 bytes
if(partsptr[i].tmp) if(partsptr[i].tmp)
{ {
fieldDesc |= 1 << 3; fieldDesc |= 1 << 3;
@ -643,6 +649,12 @@ void *build_save_OPS(int *size, int orig_x0, int orig_y0, int orig_w, int orig_h
{ {
fieldDesc |= 1 << 4; fieldDesc |= 1 << 4;
partsData[partsDataLen++] = partsptr[i].tmp >> 8; partsData[partsDataLen++] = partsptr[i].tmp >> 8;
if(partsptr[i].tmp > 65535)
{
fieldDesc |= 1 << 12;
partsData[partsDataLen++] = (partsptr[i].tmp&0xFF000000)>>24;
partsData[partsDataLen++] = (partsptr[i].tmp&0x00FF0000)>>16;
}
} }
} }
@ -1307,6 +1319,13 @@ int parse_save_OPS(void *save, int size, int replace, int x0, int y0, unsigned c
{ {
if(i >= partsDataLen) goto fail; if(i >= partsDataLen) goto fail;
partsptr[newIndex].tmp |= (((unsigned)partsData[i++]) << 8); partsptr[newIndex].tmp |= (((unsigned)partsData[i++]) << 8);
//Read 3rd and 4th bytes
if(fieldDescriptor & 0x1000)
{
if(i+1 >= partsDataLen) goto fail;
partsptr[newIndex].tmp |= (((unsigned)partsData[i++]) << 24);
partsptr[newIndex].tmp |= (((unsigned)partsData[i++]) << 16);
}
} }
} }