@@ -1143,6 +1143,14 @@ int Simulation::eval_move(int pt, int nx, int ny, unsigned *rr) const
11431143 return 0 ;
11441144 }
11451145 break ;
1146+ case PT_PAPR:
1147+ // BCOL can always pass through PAPR in order to color it
1148+ // Most elements are blocked by marked PAPR, except for certified "weird" elements where it's inverse
1149+ if ((pt == PT_BCOL) || (!parts[ID (r)].life != !(pt != PT_H2 && pt != PT_ANAR && pt != PT_BIZR && pt != PT_BIZRG)))
1150+ result = 2 ;
1151+ else
1152+ result = 0 ;
1153+ break ;
11461154 default :
11471155 // This should never happen
11481156 // If it were to happen, try_move would interpret a 3 as a 1
@@ -1191,8 +1199,8 @@ int Simulation::try_move(int i, int x, int y, int nx, int ny)
11911199 {
11921200 if (rt == PT_COAL || rt == PT_BCOL)
11931201 parts[ID (r)].temp = parts[i].temp ;
1194-
1195- if (rt < PT_NUM && elements[rt]. HeatConduct && (rt!=PT_HSWC|| parts[ID (r)]. life == 10 ) && rt!= PT_FILT)
1202+
1203+ if (rt < PT_NUM && ! IsHeatInsulator ( parts[ID (r)]) && rt != PT_FILT && rt != PT_PAPR )
11961204 parts[i].temp = parts[ID (r)].temp = restrict_flt ((parts[ID (r)].temp +parts[i].temp )/2 , MIN_TEMP, MAX_TEMP);
11971205 }
11981206 else if ((parts[i].type ==PT_NEUT || parts[i].type ==PT_ELEC) && (rt==PT_CLNE || rt==PT_PCLN || rt==PT_BCLN || rt==PT_PBCN))
@@ -2198,6 +2206,11 @@ Simulation::PlanMoveResult Simulation::PlanMove(Sim &sim, int i, int x, int y)
21982206template
21992207Simulation::PlanMoveResult Simulation::PlanMove<false , const Simulation>(const Simulation &sim, int i, int x, int y);
22002208
2209+ bool Simulation::IsHeatInsulator (Particle p) const
2210+ {
2211+ return SimulationData::CRef ().elements [p.type ].HeatConduct == 0 || (p.type == PT_HSWC && p.life != 10 ) || ((p.type == PT_PIPE || p.type == PT_PPIP) && (p.tmp & PFLAG_CAN_CONDUCT) == 0 );
2212+ }
2213+
22012214void Simulation::UpdateParticles (int start, int end)
22022215{
22032216 // the main particle loop function, goes over all particles.
@@ -2355,7 +2368,7 @@ void Simulation::UpdateParticles(int start, int end)
23552368 // heat transfer code
23562369 auto h_count = 0 ;
23572370 bool cond;
2358- cond = t && (t!=PT_HSWC|| parts[i]. life == 10 ) && rng.chance (int (elements[t].HeatConduct *gel_scale), 250 );
2371+ cond = t && ! IsHeatInsulator ( parts[i]) && rng.chance (int (elements[t].HeatConduct *gel_scale), 250 );
23592372
23602373 if (cond)
23612374 {
@@ -2372,24 +2385,44 @@ void Simulation::UpdateParticles(int start, int end)
23722385 {
23732386 surround_hconduct[j] = i;
23742387 auto r = surround[j];
2388+
23752389 if (!r)
23762390 continue ;
2391+
23772392 auto rt = TYP (r);
2378- if (rt && elements[rt].HeatConduct && (rt!=PT_HSWC||parts[ID (r)].life ==10 )
2379- && (t!=PT_FILT||(rt!=PT_BRAY&&rt!=PT_BIZR&&rt!=PT_BIZRG))
2380- && (rt!=PT_FILT||(t!=PT_BRAY&&t!=PT_PHOT&&t!=PT_BIZR&&t!=PT_BIZRG))
2381- && (t!=PT_ELEC||rt!=PT_DEUT)
2382- && (t!=PT_DEUT||rt!=PT_ELEC)
2383- && (t!=PT_HSWC || rt!=PT_FILT || parts[i].tmp != 1 )
2384- && (t!=PT_FILT || rt!=PT_HSWC || parts[ID (r)].tmp != 1 ))
2393+
2394+ if (!rt || IsHeatInsulator (parts[ID (r)])
2395+ || (t == PT_FILT && (rt == PT_BRAY || rt == PT_BIZR || rt == PT_BIZRG))
2396+ || (rt == PT_FILT && (t == PT_BRAY || t == PT_PHOT || t == PT_BIZR || t == PT_BIZRG))
2397+ || (t == PT_ELEC && rt == PT_DEUT)
2398+ || (t == PT_DEUT && rt == PT_ELEC)
2399+ || (t == PT_HSWC && rt == PT_FILT && parts[i].tmp == 1 )
2400+ || (t == PT_FILT && rt == PT_HSWC && parts[ID (r)].tmp == 1 )
2401+ || (t == PT_PHOT && rt == PT_PAPR))
2402+ continue ;
2403+
2404+ surround_hconduct[j] = ID (r);
2405+ c_heat += parts[ID (r)].temp ;
2406+
2407+ if ((rt == PT_PIPE || rt == PT_PPIP) && parts[ID (r)].ctype != 0 )
2408+ {
2409+ c_heat += parts[ID (r)].temp ; // double count the particle to account for the heat capacity of both the PIPE/PPIP and its contents
2410+ }
2411+
2412+ h_count++;
2413+
2414+ if ((rt == PT_PIPE || rt == PT_PPIP) && parts[ID (r)].ctype != 0 )
23852415 {
2386- surround_hconduct[j] = ID (r);
2387- c_heat += parts[ID (r)].temp ;
2388- h_count++;
2416+ h_count++; // double count the particle to account for the heat capacity of both the PIPE/PPIP and its contents
23892417 }
23902418 }
23912419 float pt = R_TEMP;
2392- pt = (c_heat+parts[i].temp )/(h_count+1 );
2420+
2421+ if ((t == PT_PIPE || t == PT_PPIP) && parts[i].ctype != 0 )
2422+ pt = (c_heat+parts[i].temp *2 .0f )/(h_count+2 ); // double count the particle to account for the heat capacity of both the PIPE/PPIP and its contents
2423+ else
2424+ pt = (c_heat+parts[i].temp )/(h_count+1 );
2425+
23932426 pt = parts[i].temp = restrict_flt (pt, MIN_TEMP, MAX_TEMP);
23942427 for (auto j=0 ; j<8 ; j++)
23952428 {
@@ -3237,9 +3270,9 @@ void Simulation::RecalcFreeParticles(bool do_life_dec)
32373270 photons[y][x] = PMAP (i, t);
32383271 else
32393272 {
3240- // Particles are sometimes allowed to go inside INVS and FILT
3273+ // Particles are sometimes allowed to go inside INVS, FILT, and PAPR
32413274 // To make particles collide correctly when inside these elements, these elements must not overwrite an existing pmap entry from particles inside them
3242- if (!pmap[y][x] || (t!=PT_INVIS && t!= PT_FILT))
3275+ if (!pmap[y][x] || (t!=PT_INVIS && t!= PT_FILT && t != PT_PAPR ))
32433276 pmap[y][x] = PMAP (i, t);
32443277 // (there are a few exceptions, including energy particles - currently no limit on stacking those)
32453278 if (t!=PT_THDR && t!=PT_EMBR && t!=PT_FIGH && t!=PT_PLSM)
0 commit comments