diff --git a/src/simulation/ElementNumbers.h b/src/simulation/ElementNumbers.h index 7fa29efa5..6c92f23c3 100644 --- a/src/simulation/ElementNumbers.h +++ b/src/simulation/ElementNumbers.h @@ -196,5 +196,6 @@ ELEMENT_DEFINE(RFGL, 184); ELEMENT_DEFINE(LSNS, 185); ELEMENT_DEFINE(LDTC, 186); ELEMENT_DEFINE(SLCN, 187); +ELEMENT_DEFINE(PTNM, 188); #undef ELEMENT_DEFINE diff --git a/src/simulation/elements/PTNM.cpp b/src/simulation/elements/PTNM.cpp new file mode 100644 index 000000000..d17b063ff --- /dev/null +++ b/src/simulation/elements/PTNM.cpp @@ -0,0 +1,236 @@ +#include "simulation/ElementCommon.h" + +static int update(UPDATE_FUNC_ARGS); +static int graphics(GRAPHICS_FUNC_ARGS); +static void create(ELEMENT_CREATE_FUNC_ARGS); + +void Element::Element_PTNM() +{ + Identifier = "DEFAULT_PT_PTNM"; + Name = "PTNM"; + Colour = PIXPACK(0xD5E0EB); + MenuVisible = 1; + MenuSection = SC_SOLIDS; + Enabled = 1; + + Advection = 0.0f; + AirDrag = 0.00f * CFDS; + AirLoss = 0.90f; + Loss = 0.00f; + Collision = 0.0f; + Gravity = 0.0f; + Diffusion = 0.00f; + HotAir = 0.000f * CFDS; + Falldown = 0; + + Flammable = 0; + Explosive = 0; + Meltable = 1; + Hardness = 0; + Weight = 100; + + HeatConduct = 251; + Description = "Platinum. Catalyzes certain reactions."; + + Properties = TYPE_SOLID | PROP_CONDUCTS | PROP_LIFE_DEC | PROP_HOT_GLOW | PROP_SPARKSETTLE; + + LowPressure = IPL; + LowPressureTransition = NT; + HighPressure = IPH; + HighPressureTransition = NT; + LowTemperature = ITL; + LowTemperatureTransition = NT; + HighTemperature = 1768.0f + 273.15f; + HighTemperatureTransition = PT_LAVA; + + Update = &update; + Graphics = &graphics; + Create = &create; +} + +static void hygn_reactions(int hygn1_id, UPDATE_FUNC_ARGS) +{ + for (int rx = -1; rx <= 1; rx++) + { + for (int ry = -1; ry <= 1; ry++) + { + if (BOUNDS_CHECK && (rx || ry)) + { + int r = pmap[y + ry][x + rx]; + if (!r || ID(r) == hygn1_id) + continue; + int rt = TYP(r); + + // HYGN + DESL -> OIL + WATR + if (rt == PT_DESL) + { + sim->part_change_type(ID(r), x + rx, y + ry, PT_WATR); + sim->part_change_type(hygn1_id, (int)(parts[hygn1_id].x + 0.5f), (int)(parts[hygn1_id].y + 0.5f), PT_OIL); + return; + } + + // HYGN + OXYG -> DSTW + SPRK + Heat + if (rt == PT_O2 && !parts[i].life) + { + sim->part_change_type(ID(r), x + rx, y + ry, PT_DSTW); + sim->part_change_type(hygn1_id, (int)(parts[hygn1_id].x + 0.5f), (int)(parts[hygn1_id].y + 0.5f), PT_DSTW); + parts[ID(r)].temp += 5.0f; + parts[hygn1_id].temp += 5.0f; + + parts[i].ctype = PT_PTNM; + parts[i].life = 4; + sim->part_change_type(i, x, y, PT_SPRK); + return; + } + + // Cold fusion: 2 hydrogen > 500 C has a chance to fuse + if (rt == PT_H2 && RNG::Ref().chance(1, 1000) && parts[ID(r)].temp > 500.0f + 273.15f && parts[hygn1_id].temp > 500.0f + 273.15f) + { + sim->part_change_type(ID(r), x + rx, y + ry, PT_NBLE); + sim->part_change_type(hygn1_id, (int)(parts[hygn1_id].x + 0.5f), (int)(parts[hygn1_id].y + 0.5f), PT_NEUT); + + parts[ID(r)].temp += 1000.0f; + parts[hygn1_id].temp += 1000.0f; + sim->pv[y / CELL][x / CELL] += 10.0f; + + int j = sim->create_part(-3, x + rx, y + ry, PT_PHOT); + if (j > -1) + { + parts[j].ctype = 0x7C0000; + parts[j].temp = parts[ID(r)].temp; + parts[j].tmp = 0x1; + } + if (RNG::Ref().chance(1, 10)) + { + int j = sim->create_part(-3, x + rx, y + ry, PT_ELEC); + if (j > -1) + parts[j].temp = parts[ID(r)].temp; + } + return; + } + } + } + } +} + +static int update(UPDATE_FUNC_ARGS) +{ + int hygn1_id = -1; // Id of a hydrogen particle for hydrogen multi-particle reactions + + // Fast conduction (like GOLD) + if (!parts[i].life) + { + for (int j = 0; j < 4; j++) + { + static const int checkCoordsX[] = { -4, 4, 0, 0 }; + static const int checkCoordsY[] = { 0, 0, -4, 4 }; + int rx = checkCoordsX[j]; + int ry = checkCoordsY[j]; + int r = pmap[y + ry][x + rx]; + if (r && TYP(r) == PT_SPRK && parts[ID(r)].life && parts[ID(r)].life < 4) + { + sim->part_change_type(i, x, y, PT_SPRK); + parts[i].life = 4; + parts[i].ctype = PT_PTNM; + } + } + } + + // Single element reactions + for (int rx = -1; rx <= 1; rx++) + { + for (int ry = -1; ry <= 1; ry++) + { + if (BOUNDS_CHECK && (rx || ry)) + { + int r = pmap[y + ry][x + rx]; + if (!r) + continue; + int rt = TYP(r); + + if (rt == PT_H2 && hygn1_id < 0) + hygn1_id = ID(r); + + // These reactions will occur instantly in contact with PTNM + // -------------------------------------------------------- + + // Shield instantly grows (even without SPRK) + if (!parts[ID(r)].life && (rt == PT_SHLD1 || rt == PT_SHLD2 || rt == PT_SHLD3)) + { + int next = PT_SHLD1; + switch (rt) + { + case PT_SHLD1: next = PT_SHLD2; break; + case PT_SHLD2: next = PT_SHLD3; break; + case PT_SHLD3: next = PT_SHLD4; break; + } + sim->part_change_type(ID(r), x + rx, y + ry, next); + parts[ID(r)].life = 7; + continue; + } + + // ISZS / ISOZ -> PHOT + PLUT + if (rt == PT_ISZS || rt == PT_ISOZ) + { + sim->part_change_type(ID(r), x + rx, y + ry, PT_PLUT); + sim->create_part(-3, x + rx, y + ry, PT_PHOT); + continue; + } + + // These reactions are dependent on temperature + // Probability goes quadratically from 0% / frame to 100% / frame from 0 C to 1500 C + // -------------------------------------------------------- + float prob = std::min(1.0f, parts[i].temp / (273.15f + 1500.0f)); + prob *= prob; + + if (RNG::Ref().uniform01() <= prob) + { + switch (rt) + { + case PT_GAS: // GAS + > 2 pressure + >= 200 C -> INSL + if (parts[ID(r)].temp >= 200.0f + 273.15f && sim->pv[y / CELL][x / CELL] > 2.0f) + { + sim->part_change_type(ID(r), x + rx, y + ry, PT_INSL); + parts[i].temp += 60.0f; // Other part is INSL, adding temp is useless + } + break; + + case PT_BREC: // BREL + > 1000 C + > 50 pressure -> EXOT + if (parts[ID(r)].temp > 1000.0f + 273.15f && sim->pv[y / CELL][x / CELL] > 50.0f) + { + sim->part_change_type(ID(r), x + rx, y + ry, PT_EXOT); + parts[ID(r)].temp -= 30.0f; + parts[i].temp -= 30.0f; + } + break; + + case PT_SMKE: // SMKE -> CO2 + sim->part_change_type(ID(r), x + rx, y + ry, PT_CO2); + break; + } + } + } + } + } + + // Hydrogen reactions + if (hygn1_id >= 0) + { + hygn_reactions(hygn1_id, UPDATE_FUNC_SUBCALL_ARGS); + } + + return 0; +} + +static int graphics(GRAPHICS_FUNC_ARGS) +{ + if (cpart->tmp) + *pixel_mode |= PMODE_FLARE; + return 0; +} + +static void create(ELEMENT_CREATE_FUNC_ARGS) +{ + if (RNG::Ref().chance(1, 15)) + sim->parts[i].tmp = 1; +}