summaryrefslogtreecommitdiff
path: root/src/powder.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/powder.c')
-rw-r--r--src/powder.c271
1 files changed, 134 insertions, 137 deletions
diff --git a/src/powder.c b/src/powder.c
index c869e59..233fa32 100644
--- a/src/powder.c
+++ b/src/powder.c
@@ -1,6 +1,7 @@
#include <stdint.h>
#include <math.h>
#include <defines.h>
+#include <squares.h>
#include <powder.h>
#include <air.h>
#include <misc.h>
@@ -317,43 +318,17 @@ int try_move(int i, int x, int y, int nx, int ny)
if (parts[i].type==PT_NEUT && (ptypes[r&0xFF].properties&PROP_NEUTABSORB))
{
- parts[i].type=PT_NONE;
+ kill_part(i);
return 0;
}
if ((r&0xFF)==PT_VOID || (r&0xFF)==PT_PVOD) //this is where void eats particles
{
- if (parts[i].type == PT_STKM)
- {
- player.spwn = 0;
- }
- if (parts[i].type == PT_STKM2)
- {
- player2.spwn = 0;
- }
- if (parts[i].type == PT_FIGH)
- {
- fighters[(unsigned char)parts[i].tmp].spwn = 0;
- fighcount--;
- }
- parts[i].type=PT_NONE;
+ kill_part(i);
return 0;
}
if ((r&0xFF)==PT_BHOL || (r&0xFF)==PT_NBHL) //this is where blackhole eats particles
{
- if (parts[i].type == PT_STKM)
- {
- player.spwn = 0;
- }
- if (parts[i].type == PT_STKM2)
- {
- player2.spwn = 0;
- }
- if (parts[i].type == PT_FIGH)
- {
- fighters[(unsigned char)parts[i].tmp].spwn = 0;
- fighcount--;
- }
- parts[i].type=PT_NONE;
+ kill_part(i);
if (!legacy_enable)
{
parts[r>>8].temp = restrict_flt(parts[r>>8].temp+parts[i].temp/2, MIN_TEMP, MAX_TEMP);//3.0f;
@@ -363,7 +338,7 @@ int try_move(int i, int x, int y, int nx, int ny)
}
if (((r&0xFF)==PT_WHOL||(r&0xFF)==PT_NWHL) && parts[i].type==PT_ANAR) //whitehole eats anar
{
- parts[i].type=PT_NONE;
+ kill_part(i);
if (!legacy_enable)
{
parts[r>>8].temp = restrict_flt(parts[r>>8].temp- (MAX_TEMP-parts[i].temp)/2, MIN_TEMP, MAX_TEMP);
@@ -414,8 +389,10 @@ int try_move(int i, int x, int y, int nx, int ny)
// try to move particle, and if successful update pmap and parts[i].x,y
int do_move(int i, int x, int y, float nxf, float nyf)
{
- int nx = (int)(nxf+0.5f), ny = (int)(nyf+0.5f);
- int result = try_move(i, x, y, nx, ny);
+ int nx = (int)(nxf+0.5f), ny = (int)(nyf+0.5f), result;
+ if (parts[i].type == PT_NONE)
+ return 0;
+ result = try_move(i, x, y, nx, ny);
if (result)
{
int t = parts[i].type;
@@ -612,6 +589,9 @@ void kill_part(int i)//kills particle number i
{
int x, y;
+ if (parts[i].type == PT_NONE) //This shouldn't happen anymore, but it's here just in case
+ return;
+
x = (int)(parts[i].x+0.5f);
y = (int)(parts[i].y+0.5f);
if (parts[i].type == PT_STKM)
@@ -1831,8 +1811,14 @@ void update_particles_i(pixel *vid, int start, int inc)
if (ptypes[t].diffusion)//the random diffusion that gasses have
{
+#ifdef REALISTIC
+ //The magic number controlls diffusion speed
+ parts[i].vx += 0.05*squares[(unsigned int)round(parts[i].temp)]*ptypes[t].diffusion*(rand()/(0.5f*RAND_MAX)-1.0f);
+ parts[i].vy += 0.05*squares[(unsigned int)round(parts[i].temp)]*ptypes[t].diffusion*(rand()/(0.5f*RAND_MAX)-1.0f);
+#else
parts[i].vx += ptypes[t].diffusion*(rand()/(0.5f*RAND_MAX)-1.0f);
parts[i].vy += ptypes[t].diffusion*(rand()/(0.5f*RAND_MAX)-1.0f);
+#endif
}
j = surround_space = nt = 0;//if nt is 1 after this, then there is a particle around the current particle, that is NOT the current particle's type, for water movement.
@@ -1863,8 +1849,8 @@ void update_particles_i(pixel *vid, int start, int inc)
//heat transfer code
h_count = 0;
-#ifdef REALHEAT
- if (t&&(t!=PT_HSWC||parts[i].life==10))
+#ifdef REALISTIC
+ if (t&&(t!=PT_HSWC||parts[i].life==10)&&ptypes[t].hconduct)
{
float c_Cm = 0.0f;
#else
@@ -1874,12 +1860,25 @@ void update_particles_i(pixel *vid, int start, int inc)
#endif
if (aheat_enable)
{
+#ifdef REALISTIC
+ c_heat = parts[i].temp*96.645/ptypes[t].hconduct*fabs(ptypes[t].weight)
+ + hv[y/CELL][x/CELL]*100*(pv[y/CELL][x/CELL]+273.15f)/256;
+ c_Cm = 96.645/ptypes[t].hconduct*fabs(ptypes[t].weight)
+ + 100*(pv[y/CELL][x/CELL]+273.15f)/256;
+ pt = c_heat/c_Cm;
+ pt = restrict_flt(pt, -MAX_TEMP+MIN_TEMP, MAX_TEMP-MIN_TEMP);
+ parts[i].temp = pt;
+ //Pressure increase from heat (temporary)
+ pv[y/CELL][x/CELL] += (pt-hv[y/CELL][x/CELL])*0.004;
+ hv[y/CELL][x/CELL] = pt;
+#else
c_heat = (hv[y/CELL][x/CELL]-parts[i].temp)*0.04;
c_heat = restrict_flt(c_heat, -MAX_TEMP+MIN_TEMP, MAX_TEMP-MIN_TEMP);
parts[i].temp += c_heat;
hv[y/CELL][x/CELL] -= c_heat;
+#endif
}
- c_heat = 0.0f;
+ c_heat = 0.0f; c_Cm = 0.0f;
for (j=0; j<8; j++)
{
surround_hconduct[j] = i;
@@ -1892,7 +1891,7 @@ void update_particles_i(pixel *vid, int start, int inc)
&&(rt!=PT_FILT||(t!=PT_BRAY&&t!=PT_PHOT&&t!=PT_BIZR&&t!=PT_BIZRG)))
{
surround_hconduct[j] = r>>8;
-#ifdef REALHEAT
+#ifdef REALISTIC
c_heat += parts[r>>8].temp*96.645/ptypes[rt].hconduct*fabs(ptypes[rt].weight);
c_Cm += 96.645/ptypes[rt].hconduct*fabs(ptypes[rt].weight);
#else
@@ -1901,7 +1900,7 @@ void update_particles_i(pixel *vid, int start, int inc)
h_count++;
}
}
-#ifdef REALHEAT
+#ifdef REALISTIC
if (t == PT_PHOT)
pt = (c_heat+parts[i].temp*96.645)/(c_Cm+96.645);
else
@@ -2196,7 +2195,7 @@ killed:
clear_y = (int)(clear_yf+0.5f);
break;
}
- if (fin_x<CELL || fin_y<CELL || fin_x>=XRES-CELL || fin_y>=YRES-CELL || pmap[fin_y][fin_x] || (bmap[fin_y/CELL][fin_x/CELL] && (bmap[fin_y/CELL][fin_x/CELL]==WL_DESTROYALL || bmap[fin_y/CELL][fin_x/CELL]==WL_DETECT || !eval_move(t,fin_x,fin_y,NULL))))
+ if (fin_x<CELL || fin_y<CELL || fin_x>=XRES-CELL || fin_y>=YRES-CELL || pmap[fin_y][fin_x] || (bmap[fin_y/CELL][fin_x/CELL] && (bmap[fin_y/CELL][fin_x/CELL]==WL_DESTROYALL || !eval_move(t,fin_x,fin_y,NULL))))
{
// found an obstacle
clear_xf = fin_xf-dx;
@@ -2205,7 +2204,8 @@ killed:
clear_y = (int)(clear_yf+0.5f);
break;
}
-
+ if (bmap[fin_y/CELL][fin_x/CELL]==WL_DETECT && emap[fin_y/CELL][fin_x/CELL]<8)
+ set_emap(fin_x/CELL, fin_y/CELL);
}
}
@@ -2263,13 +2263,15 @@ killed:
if (stagnant)//FLAG_STAGNANT set, was reflected on previous frame
{
// cast coords as int then back to float for compatibility with existing saves
- if (!do_move(i, x, y, (float)fin_x, (float)fin_y)) {
+ if (!do_move(i, x, y, (float)fin_x, (float)fin_y) && parts[i].type) {
kill_part(i);
continue;
}
}
else if (!do_move(i, x, y, fin_xf, fin_yf))
{
+ if (parts[i].type == PT_NONE)
+ continue;
// reflection
parts[i].flags |= FLAG_STAGNANT;
if (t==PT_NEUT && 100>(rand()%1000))
@@ -2329,6 +2331,8 @@ killed:
// gasses and solids (but not powders)
if (!do_move(i, x, y, fin_xf, fin_yf))
{
+ if (parts[i].type == PT_NONE)
+ continue;
// can't move there, so bounce off
// TODO
if (fin_x>x+ISTP) fin_x=x+ISTP;
@@ -2360,6 +2364,8 @@ killed:
// liquids and powders
if (!do_move(i, x, y, fin_xf, fin_yf))
{
+ if (parts[i].type == PT_NONE)
+ continue;
if (fin_x!=x && do_move(i, x, y, fin_xf, clear_yf))
{
parts[i].vx *= ptypes[t].collision;
@@ -2703,7 +2709,7 @@ void create_box(int x1, int y1, int x2, int y2, int c, int flags)
}
for (j=y1; j<=y2; j++)
for (i=x1; i<=x2; i++)
- create_parts(i, j, 0, 0, c, flags);
+ create_parts(i, j, 0, 0, c, flags, 1);
}
int flood_prop_2(int x, int y, size_t propoffset, void * propvalue, int proptype, int parttype, char * bitmap)
@@ -2828,7 +2834,7 @@ int flood_parts(int x, int y, int fullc, int cm, int bm, int flags)
if (create_part(-1,x, y, fullc)==-1)
return 0;
}
- else if (!create_parts(x, y, 0, 0, fullc, flags))
+ else if (!create_parts(x, y, 0, 0, fullc, flags, 1))
return 0;
}
// fill children
@@ -2951,9 +2957,9 @@ int create_part_add_props(int p, int x, int y, int tv, int rx, int ry)
}
//this creates particles from a brush, don't use if you want to create one particle
-int create_parts(int x, int y, int rx, int ry, int c, int flags)
+int create_parts(int x, int y, int rx, int ry, int c, int flags, int fill)
{
- int i, j, r, f = 0, u, v, oy, ox, b = 0, dw = 0, stemp = 0, p;//n;
+ int i, j, r, f = 0, u, v, oy, ox, b = 0, dw = 0, stemp = 0, p, fn;
int wall = c - 100;
if (c==SPC_WIND || c==PT_FIGH)
@@ -2963,6 +2969,8 @@ int create_parts(int x, int y, int rx, int ry, int c, int flags)
prop_edit_ui(vid_buf, x, y);
return 0;
}
+ if (c == SPC_AIR || c == SPC_HEAT || c == SPC_COOL || c == SPC_VACUUM || c == SPC_PGRV || c == SPC_NGRV)
+ fill = 1;
for (r=UI_ACTUALSTART; r<=UI_ACTUALSTART+UI_WALLCOUNT; r++)
{
if (wall==r)
@@ -3054,114 +3062,102 @@ int create_parts(int x, int y, int rx, int ry, int c, int flags)
return 1;
}
- //eraser
- if (c == 0 && !(flags&BRUSH_REPLACEMODE))
- {
- if (rx==0&&ry==0)
- {
- delete_part(x, y, 0);
- }
- else
- for (j=-ry; j<=ry; j++)
- for (i=-rx; i<=rx; i++)
- if (InCurrentBrush(i ,j ,rx ,ry))
- delete_part(x+i, y+j, 0);
- return 1;
- }
+ if (c == 0 && !(flags&BRUSH_REPLACEMODE)) // delete
+ fn = 0;
+ else if ((flags&BRUSH_SPECIFIC_DELETE) && !(flags&BRUSH_REPLACEMODE)) // specific delete
+ fn = 1;
+ else if (flags&BRUSH_REPLACEMODE) // replace
+ fn = 2;
+ else // normal draw
+ fn = 3;
- //specific deletion
- if ((flags&BRUSH_SPECIFIC_DELETE)&& !(flags&BRUSH_REPLACEMODE))
+ if (rx<=0) //workaround for rx == 0 crashing. todo: find a better fix later.
{
- if (rx==0&&ry==0)
- {
- delete_part(x, y, flags);
- }
- else
- for (j=-ry; j<=ry; j++)
- for (i=-rx; i<=rx; i++)
- if (InCurrentBrush(i ,j ,rx ,ry))
- delete_part(x+i, y+j, flags);
- return 1;
+ for (j = y - ry; j <= y + ry; j++)
+ if (create_parts2(fn,x,j,c,rx,ry,flags))
+ f = 1;
}
-
- //why do these need a special if
- if (c == SPC_AIR || c == SPC_HEAT || c == SPC_COOL || c == SPC_VACUUM || c == SPC_PGRV || c == SPC_NGRV)
+ else
{
- if (rx==0&&ry==0)
- {
- create_part(-2, x, y, c);
+ int tempy = y, i, j, jmax, oldy;
+ if (CURRENT_BRUSH == TRI_BRUSH)
+ tempy = y + ry;
+ for (i = x - rx; i <= x; i++) {
+ oldy = tempy;
+ while (InCurrentBrush(i-x,tempy-y,rx,ry))
+ tempy = tempy - 1;
+ tempy = tempy + 1;
+ jmax = 2*y - tempy;
+ if (CURRENT_BRUSH == TRI_BRUSH)
+ jmax = y + ry;
+ if (fill)
+ {
+ for (j = tempy; j <= jmax; j++) {
+ if (create_parts2(fn,i,j,c,rx,ry,flags))
+ f = 1;
+ if (create_parts2(fn,2*x-i,j,c,rx,ry,flags))
+ f = 1;
+ }
+ }
+ else
+ {
+ if ((oldy != tempy && CURRENT_BRUSH != SQUARE_BRUSH) || i == x-rx)
+ oldy--;
+ if (CURRENT_BRUSH == TRI_BRUSH)
+ oldy = tempy;
+ for (j = tempy; j <= oldy+1; j++) {
+ int i2 = 2*x-i, j2 = 2*y-j;
+ if (CURRENT_BRUSH == TRI_BRUSH)
+ j2 = y+ry;
+ if (create_parts2(fn,i,j,c,rx,ry,flags))
+ f = 1;
+ if (create_parts2(fn,i2,j,c,rx,ry,flags))
+ f = 1;
+ if (create_parts2(fn,i,j2,c,rx,ry,flags))
+ f = 1;
+ if (create_parts2(fn,i2,j2,c,rx,ry,flags))
+ f = 1;
+ }
+ }
}
- else
- for (j=-ry; j<=ry; j++)
- for (i=-rx; i<=rx; i++)
- if (InCurrentBrush(i ,j ,rx ,ry))
- {
- if ( x+i<0 || y+j<0 || x+i>=XRES || y+j>=YRES)
- continue;
- if (!REPLACE_MODE)
- create_part(-2, x+i, y+j, c);
- else if ((pmap[y+j][x+i]&0xFF)==SLALT&&SLALT!=0)
- create_part(-2, x+i, y+j, c);
- }
- return 1;
}
+ return !f;
+}
- if (flags&BRUSH_REPLACEMODE)
+int create_parts2(int f, int x, int y, int c, int rx, int ry, int flags)
+{
+ if (f == 0) //delete
+ delete_part(x, y, 0);
+ else if (f == 1) //specific delete
+ delete_part(x, y, flags);
+ else if (f == 2) //replace mode
{
- if (rx==0&&ry==0)
+ if (x<0 || y<0 || x>=XRES || y>=YRES)
+ return 0;
+ if ((pmap[y][x]&0xFF)!=SLALT&&SLALT!=0)
+ return 0;
+ if ((pmap[y][x]))
{
- if ((pmap[y][x]&0xFF)==SLALT || SLALT==0)
- {
- if ((pmap[y][x]))
- {
- delete_part(x, y, 0);
- if (c!=0)
- create_part_add_props(-2, x, y, c, rx, ry);
- }
- }
+ delete_part(x, y, 0);
+ if (c!=0)
+ create_part_add_props(-2, x, y, c, rx, ry);
}
- else
- for (j=-ry; j<=ry; j++)
- for (i=-rx; i<=rx; i++)
- if (InCurrentBrush(i ,j ,rx ,ry))
- {
- if ( x+i<0 || y+j<0 || x+i>=XRES || y+j>=YRES)
- continue;
- if ((pmap[y+j][x+i]&0xFF)!=SLALT&&SLALT!=0)
- continue;
- if ((pmap[y+j][x+i]))
- {
- delete_part(x+i, y+j, 0);
- if (c!=0)
- create_part_add_props(-2, x+i, y+j, c, rx, ry);
- }
- }
- return 1;
-
}
- //else, no special modes, draw element like normal.
- if (rx==0&&ry==0)//workaround for 1pixel brush/floodfill crashing. todo: find a better fix later.
- {
+ else if (f == 3) //normal draw
if (create_part_add_props(-2, x, y, c, rx, ry)==-1)
- f = 1;
- }
- else
- for (j=-ry; j<=ry; j++)
- for (i=-rx; i<=rx; i++)
- if (InCurrentBrush(i ,j ,rx ,ry))
- if (create_part_add_props(-2, x+i, y+j, c, rx, ry)==-1)
- f = 1;
- return !f;
+ return 1;
+ return 0;
}
+
int InCurrentBrush(int i, int j, int rx, int ry)
{
switch(CURRENT_BRUSH)
{
case CIRCLE_BRUSH:
- return (pow(i,2)*pow(ry,2)+pow(j,2)*pow(rx,2)<=pow(rx,2)*pow(ry,2));
+ return (pow((double)i,2)*pow((double)ry,2)+pow((double)j,2)*pow((double)rx,2)<=pow((double)rx,2)*pow((double)ry,2));
break;
case SQUARE_BRUSH:
- return (i*j<=ry*rx);
+ return (abs(i) <= rx && abs(j) <= ry);
break;
case TRI_BRUSH:
return (j <= ry ) && ( j >= (((-2.0*ry)/rx)*i) -ry) && ( j >= (((-2.0*ry)/(-rx))*i)-ry ) ;
@@ -3184,7 +3180,7 @@ int get_brush_flags()
}
void create_line(int x1, int y1, int x2, int y2, int rx, int ry, int c, int flags)
{
- int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy;
+ int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy, fill = 1;
float e, de;
if (c==SPC_PROP)
return;
@@ -3218,9 +3214,10 @@ void create_line(int x1, int y1, int x2, int y2, int rx, int ry, int c, int flag
for (x=x1; x<=x2; x++)
{
if (cp)
- create_parts(y, x, rx, ry, c, flags);
+ create_parts(y, x, rx, ry, c, flags, fill);
else
- create_parts(x, y, rx, ry, c, flags);
+ create_parts(x, y, rx, ry, c, flags, fill);
+ fill = 0;
e += de;
if (e >= 0.5f)
{
@@ -3229,9 +3226,9 @@ void create_line(int x1, int y1, int x2, int y2, int rx, int ry, int c, int flag
&& ((y1<y2) ? (y<=y2) : (y>=y2)))
{
if (cp)
- create_parts(y, x, rx, ry, c, flags);
+ create_parts(y, x, rx, ry, c, flags, fill);
else
- create_parts(x, y, rx, ry, c, flags);
+ create_parts(x, y, rx, ry, c, flags, fill);
}
e -= 1.0f;
}