Enable basic rendering of custom elements in secondary Renderers
By factoring element and other static-ish data out of Simulation and protecting basic graphical element properties (i.e. everything that contributes to graphics other than the Graphics callback) with an std::shared_mutex. This is taken exclusively (std::unique_lock) by the main thread when it changes these properties, and inclusively (std::shared_lock) by non-main-thread code that uses Renderer.
This commit is contained in:
parent
9f8449357f
commit
dd875987b9
@ -12,6 +12,7 @@
|
||||
#include "common/platform/Platform.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "simulation/SaveRenderer.h"
|
||||
#include "simulation/SimulationData.h"
|
||||
#include "common/tpt-rand.h"
|
||||
#include "gui/game/Favorite.h"
|
||||
#include "gui/Style.h"
|
||||
@ -180,6 +181,7 @@ struct ExplicitSingletons
|
||||
std::unique_ptr<SaveRenderer> saveRenderer;
|
||||
std::unique_ptr<Favorite> favorite;
|
||||
std::unique_ptr<ui::Engine> engine;
|
||||
std::unique_ptr<SimulationData> simulationData;
|
||||
std::unique_ptr<GameController> gameController;
|
||||
};
|
||||
static std::unique_ptr<ExplicitSingletons> explicitSingletons;
|
||||
@ -416,6 +418,7 @@ int Main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
auto wrapWithBluescreen = [&]() {
|
||||
explicitSingletons->simulationData = std::make_unique<SimulationData>();
|
||||
explicitSingletons->gameController = std::make_unique<GameController>();
|
||||
auto *gameController = explicitSingletons->gameController.get();
|
||||
engine.ShowWindow(gameController->GetView());
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "gui/interface/Engine.h"
|
||||
#include "client/GameSave.h"
|
||||
#include "simulation/Simulation.h"
|
||||
#include "simulation/SimulationData.h"
|
||||
#include "common/platform/Platform.h"
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
@ -39,6 +40,7 @@ int main(int argc, char *argv[])
|
||||
throw e;
|
||||
}
|
||||
|
||||
auto simulationData = std::make_unique<SimulationData>();
|
||||
Simulation * sim = new Simulation();
|
||||
Renderer * ren = new Renderer(sim);
|
||||
|
||||
|
@ -328,6 +328,7 @@ static void CheckBsonFieldFloat(bson_iterator iter, const char *field, float *se
|
||||
|
||||
void GameSave::readOPS(const std::vector<char> &data)
|
||||
{
|
||||
auto &builtinGol = SimulationData::builtinGol;
|
||||
constexpr auto currentVersion = Version(currentVersionMajor, 0);
|
||||
constexpr auto nextVersion = Version(nextVersionMajor, 0);
|
||||
|
||||
@ -1185,6 +1186,7 @@ void GameSave::readOPS(const std::vector<char> &data)
|
||||
#define MTOS(str) MTOS_EXPAND(str)
|
||||
void GameSave::readPSv(const std::vector<char> &dataVec)
|
||||
{
|
||||
auto &builtinGol = SimulationData::builtinGol;
|
||||
Renderer::PopulateTables();
|
||||
|
||||
unsigned char * saveData = (unsigned char *)&dataVec[0];
|
||||
@ -1197,7 +1199,7 @@ void GameSave::readPSv(const std::vector<char> &dataVec)
|
||||
char tempSignText[255];
|
||||
sign tempSign("", 0, 0, sign::Left);
|
||||
|
||||
auto &elements = GetElements();
|
||||
auto &builtinElements = GetElements();
|
||||
|
||||
//New file header uses PSv, replacing fuC. This is to detect if the client uses a new save format for temperatures
|
||||
//This creates a problem for old clients, that display and "corrupt" error instead of a "newer version" error
|
||||
@ -1607,7 +1609,7 @@ void GameSave::readPSv(const std::vector<char> &dataVec)
|
||||
}
|
||||
else
|
||||
{
|
||||
particles[i-1].temp = elements[particles[i-1].type].DefaultProperties.temp;
|
||||
particles[i-1].temp = builtinElements[particles[i-1].type].DefaultProperties.temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1970,7 +1972,7 @@ std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
|
||||
That way, if we ever need a 25th bit, we won't have to change the save format
|
||||
*/
|
||||
|
||||
auto &elements = GetElements();
|
||||
auto &builtinElements = GetElements();
|
||||
auto &possiblyCarriesType = Particle::PossiblyCarriesType();
|
||||
auto &properties = Particle::GetProperties();
|
||||
// Allocate enough space to store all Particles and 3 bytes on top of that per Particle, for the field descriptors.
|
||||
@ -2200,7 +2202,7 @@ std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
|
||||
{
|
||||
for (auto index : possiblyCarriesType)
|
||||
{
|
||||
if (elements[particles[i].type].CarriesTypeIn & (1U << index))
|
||||
if (builtinElements[particles[i].type].CarriesTypeIn & (1U << index))
|
||||
{
|
||||
auto *prop = reinterpret_cast<const int *>(reinterpret_cast<const char *>(&particles[i]) + properties[index].Offset);
|
||||
if (TYP(*prop) > 0xFF)
|
||||
|
@ -28,4 +28,9 @@ public:
|
||||
{
|
||||
return *Instance();
|
||||
}
|
||||
|
||||
static const Type &CRef()
|
||||
{
|
||||
return Ref();
|
||||
}
|
||||
};
|
||||
|
@ -1,9 +1,7 @@
|
||||
#include "ElementPopulation.h"
|
||||
|
||||
#include "gui/interface/Engine.h"
|
||||
|
||||
#include "simulation/Simulation.h"
|
||||
|
||||
#include "simulation/SimulationData.h"
|
||||
#include "graphics/Graphics.h"
|
||||
|
||||
ElementPopulationDebug::ElementPopulationDebug(unsigned int id, Simulation * sim):
|
||||
@ -16,6 +14,8 @@ ElementPopulationDebug::ElementPopulationDebug(unsigned int id, Simulation * sim
|
||||
|
||||
void ElementPopulationDebug::Draw()
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
Graphics * g = ui::Engine::Ref().g;
|
||||
|
||||
int yBottom = YRES-10;
|
||||
@ -30,7 +30,7 @@ void ElementPopulationDebug::Draw()
|
||||
int bars = 0;
|
||||
for(int i = 0; i < PT_NUM; i++)
|
||||
{
|
||||
if(sim->elements[i].Enabled)
|
||||
if(elements[i].Enabled)
|
||||
{
|
||||
if(maxVal < sim->elementCount[i])
|
||||
maxVal = float(sim->elementCount[i]);
|
||||
@ -49,13 +49,13 @@ void ElementPopulationDebug::Draw()
|
||||
bars = 0;
|
||||
for(int i = 0; i < PT_NUM; i++)
|
||||
{
|
||||
if(sim->elements[i].Enabled)
|
||||
if(elements[i].Enabled)
|
||||
{
|
||||
auto count = sim->elementCount[i];
|
||||
auto barSize = int(count * scale - 0.5f);
|
||||
int barX = bars;//*2;
|
||||
|
||||
RGB<uint8_t> colour = sim->elements[i].Colour;
|
||||
RGB<uint8_t> colour = elements[i].Colour;
|
||||
|
||||
g->DrawLine({ xStart+barX, yBottom+3 }, { xStart+barX, yBottom+2 }, colour);
|
||||
if(sim->elementCount[i])
|
||||
|
@ -11,7 +11,8 @@
|
||||
|
||||
std::unique_ptr<VideoBuffer> Renderer::WallIcon(int wallID, Vec2<int> size)
|
||||
{
|
||||
auto wtypes = LoadWalls();
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &wtypes = sd.wtypes;
|
||||
if (wallID < 0 || wallID >= int(wtypes.size()))
|
||||
return nullptr;
|
||||
wall_type const &wtype = wtypes[wallID];
|
||||
@ -170,14 +171,14 @@ void Renderer::DrawSigns()
|
||||
|
||||
void Renderer::render_parts()
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int deca, decr, decg, decb, cola, colr, colg, colb, firea, firer, fireg, fireb, pixel_mode, q, i, t, nx, ny, x, y;
|
||||
int orbd[4] = {0, 0, 0, 0}, orbl[4] = {0, 0, 0, 0};
|
||||
Particle * parts;
|
||||
Element *elements;
|
||||
if(!sim)
|
||||
return;
|
||||
parts = sim->parts;
|
||||
elements = sim->elements.data();
|
||||
if (gridSize)//draws the grid
|
||||
{
|
||||
for (ny=0; ny<YRES; ny++)
|
||||
@ -199,7 +200,7 @@ void Renderer::render_parts()
|
||||
|
||||
if(nx >= XRES || nx < 0 || ny >= YRES || ny < 0)
|
||||
continue;
|
||||
if(TYP(sim->photons[ny][nx]) && !(sim->elements[t].Properties & TYPE_ENERGY) && t!=PT_STKM && t!=PT_STKM2 && t!=PT_FIGH)
|
||||
if(TYP(sim->photons[ny][nx]) && !(elements[t].Properties & TYPE_ENERGY) && t!=PT_STKM && t!=PT_STKM2 && t!=PT_FIGH)
|
||||
continue;
|
||||
|
||||
//Defaults
|
||||
@ -242,7 +243,8 @@ void Renderer::render_parts()
|
||||
}
|
||||
else if(!(colour_mode & COLOUR_BASC))
|
||||
{
|
||||
if (!elements[t].Graphics || (*(elements[t].Graphics))(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb)) //That's a lot of args, a struct might be better
|
||||
auto *graphics = useGraphicsFunction ? elements[t].Graphics : nullptr;
|
||||
if (!graphics || graphics(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb)) //That's a lot of args, a struct might be better
|
||||
{
|
||||
graphicscache[t].isready = 1;
|
||||
graphicscache[t].pixel_mode = pixel_mode;
|
||||
@ -927,6 +929,8 @@ void Renderer::draw_air()
|
||||
|
||||
void Renderer::DrawWalls()
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &wtypes = sd.wtypes;
|
||||
for (int y = 0; y < YCELLS; y++)
|
||||
for (int x =0; x < XCELLS; x++)
|
||||
if (sim->bmap[y][x])
|
||||
@ -935,8 +939,8 @@ void Renderer::DrawWalls()
|
||||
if (wt >= UI_WALLCOUNT)
|
||||
continue;
|
||||
unsigned char powered = sim->emap[y][x];
|
||||
RGB<uint8_t> prgb = sim->wtypes[wt].colour;
|
||||
RGB<uint8_t> grgb = sim->wtypes[wt].eglow;
|
||||
RGB<uint8_t> prgb = wtypes[wt].colour;
|
||||
RGB<uint8_t> grgb = wtypes[wt].eglow;
|
||||
|
||||
if (findingElement)
|
||||
{
|
||||
@ -951,7 +955,7 @@ void Renderer::DrawWalls()
|
||||
pixel pc = prgb.Pack();
|
||||
pixel gc = grgb.Pack();
|
||||
|
||||
switch (sim->wtypes[wt].drawstyle)
|
||||
switch (wtypes[wt].drawstyle)
|
||||
{
|
||||
case 0:
|
||||
if (wt == WL_EWALL || wt == WL_STASIS)
|
||||
@ -1075,7 +1079,7 @@ void Renderer::DrawWalls()
|
||||
// when in blob view, draw some blobs...
|
||||
if (render_mode & PMODE_BLOB)
|
||||
{
|
||||
switch (sim->wtypes[wt].drawstyle)
|
||||
switch (wtypes[wt].drawstyle)
|
||||
{
|
||||
case 0:
|
||||
if (wt == WL_EWALL || wt == WL_STASIS)
|
||||
@ -1156,10 +1160,10 @@ void Renderer::DrawWalls()
|
||||
}
|
||||
}
|
||||
|
||||
if (sim->wtypes[wt].eglow.Pack() && powered)
|
||||
if (wtypes[wt].eglow.Pack() && powered)
|
||||
{
|
||||
// glow if electrified
|
||||
RGB<uint8_t> glow = sim->wtypes[wt].eglow;
|
||||
RGB<uint8_t> glow = wtypes[wt].eglow;
|
||||
int alpha = 255;
|
||||
int cr = (alpha*glow.Red + (255-alpha)*fire_r[y/CELL][x/CELL]) >> 8;
|
||||
int cg = (alpha*glow.Green + (255-alpha)*fire_g[y/CELL][x/CELL]) >> 8;
|
||||
|
@ -167,6 +167,8 @@ public:
|
||||
#undef RENDERER_TABLE
|
||||
static void PopulateTables();
|
||||
|
||||
bool useGraphicsFunction = false;
|
||||
|
||||
private:
|
||||
int gridSize;
|
||||
};
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "client/Client.h"
|
||||
#include "common/tpt-rand.h"
|
||||
#include "simulation/GOLString.h"
|
||||
#include "simulation/Simulation.h"
|
||||
#include "simulation/SimulationData.h"
|
||||
|
||||
#include "gui/Style.h"
|
||||
#include "gui/interface/Button.h"
|
||||
@ -135,6 +135,7 @@ void GOLWindow::updateGradient()
|
||||
|
||||
void GOLWindow::validate()
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto nameString = nameField->GetText();
|
||||
auto ruleString = ruleField->GetText();
|
||||
if (!ValidateGOLName(nameString))
|
||||
@ -149,7 +150,7 @@ void GOLWindow::validate()
|
||||
new ErrorMessage("Could not add GOL type", "Invalid rule provided");
|
||||
return;
|
||||
}
|
||||
if (sim->GetCustomGOLByRule(rule))
|
||||
if (sd.GetCustomGOLByRule(rule))
|
||||
{
|
||||
new ErrorMessage("Could not add GOL type", "This Custom GoL rule already exists");
|
||||
return;
|
||||
|
@ -757,11 +757,12 @@ void GameController::ResetAir()
|
||||
|
||||
void GameController::ResetSpark()
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
Simulation * sim = gameModel->GetSimulation();
|
||||
for (int i = 0; i < NPART; i++)
|
||||
if (sim->parts[i].type == PT_SPRK)
|
||||
{
|
||||
if (sim->parts[i].ctype >= 0 && sim->parts[i].ctype < PT_NUM && sim->elements[sim->parts[i].ctype].Enabled)
|
||||
if (sim->parts[i].ctype >= 0 && sim->parts[i].ctype < PT_NUM && sd.elements[sim->parts[i].ctype].Enabled)
|
||||
{
|
||||
sim->parts[i].type = sim->parts[i].ctype;
|
||||
sim->parts[i].ctype = sim->parts[i].life = 0;
|
||||
@ -849,6 +850,7 @@ void GameController::LoadRenderPreset(int presetNum)
|
||||
|
||||
void GameController::Update()
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
ui::Point pos = gameView->GetMousePosition();
|
||||
gameModel->GetRenderer()->mousePos = PointTranslate(pos);
|
||||
if (pos.X < XRES && pos.Y < YRES)
|
||||
@ -875,7 +877,7 @@ void GameController::Update()
|
||||
if (activeTool->Identifier.BeginsWith("DEFAULT_PT_"))
|
||||
{
|
||||
int sr = activeTool->ToolID;
|
||||
if (sr && sim->IsElementOrNone(sr))
|
||||
if (sr && sd.IsElementOrNone(sr))
|
||||
rightSelected = sr;
|
||||
}
|
||||
|
||||
@ -1497,20 +1499,14 @@ String GameController::ElementResolve(int type, int ctype)
|
||||
// "NONE" should never be displayed in the HUD
|
||||
if (!type)
|
||||
return "";
|
||||
if (gameModel && gameModel->GetSimulation())
|
||||
{
|
||||
return gameModel->GetSimulation()->ElementResolve(type, ctype);
|
||||
}
|
||||
return "";
|
||||
auto &sd = SimulationData::CRef();
|
||||
return sd.ElementResolve(type, ctype);
|
||||
}
|
||||
|
||||
String GameController::BasicParticleInfo(Particle const &sample_part)
|
||||
{
|
||||
if (gameModel && gameModel->GetSimulation())
|
||||
{
|
||||
return gameModel->GetSimulation()->BasicParticleInfo(sample_part);
|
||||
}
|
||||
return "";
|
||||
auto &sd = SimulationData::CRef();
|
||||
return sd.BasicParticleInfo(sample_part);
|
||||
}
|
||||
|
||||
void GameController::ReloadSim()
|
||||
@ -1529,18 +1525,15 @@ void GameController::ReloadSim()
|
||||
|
||||
bool GameController::IsValidElement(int type)
|
||||
{
|
||||
if (gameModel && gameModel->GetSimulation())
|
||||
{
|
||||
return (type && gameModel->GetSimulation()->IsElement(type));
|
||||
}
|
||||
else
|
||||
return false;
|
||||
auto &sd = SimulationData::CRef();
|
||||
return type && sd.IsElement(type);
|
||||
}
|
||||
|
||||
String GameController::WallName(int type)
|
||||
{
|
||||
if(gameModel && gameModel->GetSimulation() && type >= 0 && type < UI_WALLCOUNT)
|
||||
return gameModel->GetSimulation()->wtypes[type].name;
|
||||
auto &sd = SimulationData::CRef();
|
||||
if(type >= 0 && type < UI_WALLCOUNT)
|
||||
return sd.wtypes[type].name;
|
||||
else
|
||||
return String();
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ GameModel::GameModel():
|
||||
{
|
||||
sim = new Simulation();
|
||||
ren = new Renderer(sim);
|
||||
ren->useGraphicsFunction = true;
|
||||
|
||||
activeTools = regularToolset;
|
||||
|
||||
@ -219,6 +220,9 @@ void GameModel::BuildQuickOptionMenu(GameController * controller)
|
||||
|
||||
void GameModel::BuildMenus()
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
auto &elements = sd.elements;
|
||||
auto &builtinGol = SimulationData::builtinGol;
|
||||
int lastMenu = -1;
|
||||
if(activeMenu != -1)
|
||||
lastMenu = activeMenu;
|
||||
@ -253,35 +257,35 @@ void GameModel::BuildMenus()
|
||||
//Create menus
|
||||
for (int i = 0; i < SC_TOTAL; i++)
|
||||
{
|
||||
menuList.push_back(new Menu(sim->msections[i].icon, sim->msections[i].name, sim->msections[i].doshow));
|
||||
menuList.push_back(new Menu(sd.msections[i].icon, sd.msections[i].name, sd.msections[i].doshow));
|
||||
}
|
||||
|
||||
//Build menus from Simulation elements
|
||||
for(int i = 0; i < PT_NUM; i++)
|
||||
{
|
||||
if(sim->elements[i].Enabled)
|
||||
if(elements[i].Enabled)
|
||||
{
|
||||
Tool * tempTool;
|
||||
if(i == PT_LIGH)
|
||||
{
|
||||
tempTool = new Element_LIGH_Tool(i, sim->elements[i].Name, sim->elements[i].Description, sim->elements[i].Colour, sim->elements[i].Identifier, sim->elements[i].IconGenerator);
|
||||
tempTool = new Element_LIGH_Tool(i, elements[i].Name, elements[i].Description, elements[i].Colour, elements[i].Identifier, elements[i].IconGenerator);
|
||||
}
|
||||
else if(i == PT_TESC)
|
||||
{
|
||||
tempTool = new Element_TESC_Tool(i, sim->elements[i].Name, sim->elements[i].Description, sim->elements[i].Colour, sim->elements[i].Identifier, sim->elements[i].IconGenerator);
|
||||
tempTool = new Element_TESC_Tool(i, elements[i].Name, elements[i].Description, elements[i].Colour, elements[i].Identifier, elements[i].IconGenerator);
|
||||
}
|
||||
else if(i == PT_STKM || i == PT_FIGH || i == PT_STKM2)
|
||||
{
|
||||
tempTool = new PlopTool(i, sim->elements[i].Name, sim->elements[i].Description, sim->elements[i].Colour, sim->elements[i].Identifier, sim->elements[i].IconGenerator);
|
||||
tempTool = new PlopTool(i, elements[i].Name, elements[i].Description, elements[i].Colour, elements[i].Identifier, elements[i].IconGenerator);
|
||||
}
|
||||
else
|
||||
{
|
||||
tempTool = new ElementTool(i, sim->elements[i].Name, sim->elements[i].Description, sim->elements[i].Colour, sim->elements[i].Identifier, sim->elements[i].IconGenerator);
|
||||
tempTool = new ElementTool(i, elements[i].Name, elements[i].Description, elements[i].Colour, elements[i].Identifier, elements[i].IconGenerator);
|
||||
}
|
||||
|
||||
if (sim->elements[i].MenuSection >= 0 && sim->elements[i].MenuSection < SC_TOTAL && sim->elements[i].MenuVisible)
|
||||
if (elements[i].MenuSection >= 0 && elements[i].MenuSection < SC_TOTAL && elements[i].MenuVisible)
|
||||
{
|
||||
menuList[sim->elements[i].MenuSection]->AddTool(tempTool);
|
||||
menuList[elements[i].MenuSection]->AddTool(tempTool);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -301,7 +305,7 @@ void GameModel::BuildMenus()
|
||||
auto &prefs = GlobalPrefs::Ref();
|
||||
auto customGOLTypes = prefs.Get("CustomGOL.Types", std::vector<ByteString>{});
|
||||
std::vector<ByteString> validatedCustomLifeTypes;
|
||||
std::vector<Simulation::CustomGOLData> newCustomGol;
|
||||
std::vector<CustomGOLData> newCustomGol;
|
||||
bool removedAny = false;
|
||||
for (auto gol : customGOLTypes)
|
||||
{
|
||||
@ -311,7 +315,7 @@ void GameModel::BuildMenus()
|
||||
removedAny = true;
|
||||
continue;
|
||||
}
|
||||
Simulation::CustomGOLData gd;
|
||||
CustomGOLData gd;
|
||||
gd.nameString = parts[0];
|
||||
gd.ruleString = parts[1];
|
||||
auto &colour1String = parts[2];
|
||||
@ -350,26 +354,25 @@ void GameModel::BuildMenus()
|
||||
Tool * tempTool = new ElementTool(PT_LIFE|PMAPID(gd.rule), gd.nameString, "Custom GOL type: " + gd.ruleString, RGB<uint8_t>::Unpack(gd.colour1), "DEFAULT_PT_LIFECUST_"+gd.nameString.ToAscii(), NULL);
|
||||
menuList[SC_LIFE]->AddTool(tempTool);
|
||||
}
|
||||
sim->SetCustomGOL(newCustomGol);
|
||||
sd.SetCustomGOL(newCustomGol);
|
||||
}
|
||||
|
||||
//Build other menus from wall data
|
||||
for(int i = 0; i < UI_WALLCOUNT; i++)
|
||||
{
|
||||
Tool * tempTool = new WallTool(i, sim->wtypes[i].descs, sim->wtypes[i].colour, sim->wtypes[i].identifier, sim->wtypes[i].textureGen);
|
||||
Tool * tempTool = new WallTool(i, sd.wtypes[i].descs, sd.wtypes[i].colour, sd.wtypes[i].identifier, sd.wtypes[i].textureGen);
|
||||
menuList[SC_WALL]->AddTool(tempTool);
|
||||
//sim->wtypes[i]
|
||||
}
|
||||
|
||||
//Build menu for tools
|
||||
for (size_t i = 0; i < sim->tools.size(); i++)
|
||||
for (size_t i = 0; i < sd.tools.size(); i++)
|
||||
{
|
||||
Tool *tempTool = new Tool(
|
||||
i,
|
||||
sim->tools[i].Name,
|
||||
sim->tools[i].Description,
|
||||
sim->tools[i].Colour,
|
||||
sim->tools[i].Identifier
|
||||
sd.tools[i].Name,
|
||||
sd.tools[i].Description,
|
||||
sd.tools[i].Colour,
|
||||
sd.tools[i].Identifier
|
||||
);
|
||||
menuList[SC_TOOL]->AddTool(tempTool);
|
||||
}
|
||||
|
@ -114,6 +114,8 @@ void PropertyWindow::Update()
|
||||
|
||||
void PropertyWindow::CheckProperty()
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
configuration.reset();
|
||||
PropertyTool::Configuration newConfiguration;
|
||||
if (!(property->GetOption().second!=-1 && textField->GetText().length() > 0))
|
||||
@ -142,7 +144,7 @@ void PropertyWindow::CheckProperty()
|
||||
else
|
||||
{
|
||||
// Try to parse as particle name
|
||||
v = sim->GetParticleType(value.ToUtf8());
|
||||
v = sd.GetParticleType(value.ToUtf8());
|
||||
|
||||
// Try to parse special GoL rules
|
||||
if (v == -1 && properties[property->GetOption().second].Name == "ctype")
|
||||
@ -160,7 +162,7 @@ void PropertyWindow::CheckProperty()
|
||||
}
|
||||
else
|
||||
{
|
||||
v = sim->GetParticleType(value.ToUtf8());
|
||||
v = sd.GetParticleType(value.ToUtf8());
|
||||
if (v == -1)
|
||||
{
|
||||
for (auto *elementTool : tool->gameModel.GetMenuList()[SC_LIFE]->GetToolList())
|
||||
@ -182,7 +184,7 @@ void PropertyWindow::CheckProperty()
|
||||
}
|
||||
}
|
||||
|
||||
if (properties[property->GetOption().second].Name == "type" && (v < 0 || v >= PT_NUM || !sim->elements[v].Enabled))
|
||||
if (properties[property->GetOption().second].Name == "type" && (v < 0 || v >= PT_NUM || !elements[v].Enabled))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -152,6 +152,8 @@ int luacon_partswrite(lua_State* l)
|
||||
|
||||
int luacon_transitionread(lua_State* l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
ByteString key = tpt_lua_optByteString(l, 2, "");
|
||||
if (legacyTransitionNames.find(key) == legacyTransitionNames.end())
|
||||
return luaL_error(l, "Invalid property");
|
||||
@ -162,12 +164,12 @@ int luacon_transitionread(lua_State* l)
|
||||
lua_rawget(l, 1);
|
||||
int i = lua_tointeger (l, lua_gettop(l));
|
||||
lua_pop(l, 1);
|
||||
if (!luacon_sim->IsElement(i))
|
||||
if (!sd.IsElement(i))
|
||||
{
|
||||
return luaL_error(l, "Invalid index");
|
||||
}
|
||||
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
||||
intptr_t propertyAddress = (intptr_t)(((const unsigned char*)&elements[i]) + prop.Offset);
|
||||
LuaScriptInterface::LuaGetProperty(l, prop, propertyAddress);
|
||||
|
||||
return 1;
|
||||
@ -175,6 +177,8 @@ int luacon_transitionread(lua_State* l)
|
||||
|
||||
int luacon_transitionwrite(lua_State* l)
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
auto &elements = sd.elements;
|
||||
ByteString key = tpt_lua_optByteString(l, 2, "");
|
||||
if (legacyTransitionNames.find(key) == legacyTransitionNames.end())
|
||||
return luaL_error(l, "Invalid property");
|
||||
@ -185,7 +189,7 @@ int luacon_transitionwrite(lua_State* l)
|
||||
lua_rawget(l, 1);
|
||||
int i = lua_tointeger (l, lua_gettop(l));
|
||||
lua_pop(l, 1);
|
||||
if (!luacon_sim->IsElement(i))
|
||||
if (!sd.IsElement(i))
|
||||
{
|
||||
return luaL_error(l, "Invalid index");
|
||||
}
|
||||
@ -193,13 +197,13 @@ int luacon_transitionwrite(lua_State* l)
|
||||
if (prop.Type == StructProperty::TransitionType)
|
||||
{
|
||||
int type = luaL_checkinteger(l, 3);
|
||||
if (!luacon_sim->IsElementOrNone(type) && type != NT && type != ST)
|
||||
if (!sd.IsElementOrNone(type) && type != NT && type != ST)
|
||||
{
|
||||
return luaL_error(l, "Invalid element");
|
||||
}
|
||||
}
|
||||
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&elements[i]) + prop.Offset);
|
||||
LuaScriptInterface::LuaSetProperty(l, prop, propertyAddress, 3);
|
||||
|
||||
return 0;
|
||||
@ -207,6 +211,8 @@ int luacon_transitionwrite(lua_State* l)
|
||||
|
||||
int luacon_elementread(lua_State* l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
ByteString key = tpt_lua_optByteString(l, 2, "");
|
||||
if (legacyPropNames.find(key) == legacyPropNames.end())
|
||||
return luaL_error(l, "Invalid property");
|
||||
@ -217,12 +223,12 @@ int luacon_elementread(lua_State* l)
|
||||
lua_rawget(l, 1);
|
||||
int i = lua_tointeger (l, lua_gettop(l));
|
||||
lua_pop(l, 1);
|
||||
if (!luacon_sim->IsElement(i))
|
||||
if (!sd.IsElement(i))
|
||||
{
|
||||
return luaL_error(l, "Invalid index");
|
||||
}
|
||||
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
||||
intptr_t propertyAddress = (intptr_t)(((const unsigned char*)&elements[i]) + prop.Offset);
|
||||
LuaScriptInterface::LuaGetProperty(l, prop, propertyAddress);
|
||||
|
||||
return 1;
|
||||
@ -230,6 +236,9 @@ int luacon_elementread(lua_State* l)
|
||||
|
||||
int luacon_elementwrite(lua_State* l)
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
std::unique_lock lk(sd.elementGraphicsMx);
|
||||
auto &elements = sd.elements;
|
||||
ByteString key = tpt_lua_optByteString(l, 2, "");
|
||||
if (legacyPropNames.find(key) == legacyPropNames.end())
|
||||
return luaL_error(l, "Invalid property");
|
||||
@ -240,12 +249,12 @@ int luacon_elementwrite(lua_State* l)
|
||||
lua_rawget(l, 1);
|
||||
int i = lua_tointeger (l, lua_gettop(l));
|
||||
lua_pop(l, 1);
|
||||
if (!luacon_sim->IsElement(i))
|
||||
if (!sd.IsElement(i))
|
||||
{
|
||||
return luaL_error(l, "Invalid index");
|
||||
}
|
||||
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&elements[i]) + prop.Offset);
|
||||
LuaScriptInterface::LuaSetProperty(l, prop, propertyAddress, 3);
|
||||
|
||||
luacon_model->BuildMenus();
|
||||
@ -278,21 +287,23 @@ String luacon_geterror()
|
||||
//tpt. api methods
|
||||
int luatpt_getelement(lua_State *l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int t;
|
||||
if (lua_isnumber(l, 1))
|
||||
{
|
||||
t = luaL_optint(l, 1, 1);
|
||||
if (!luacon_sim->IsElementOrNone(t))
|
||||
if (!sd.IsElementOrNone(t))
|
||||
{
|
||||
return luaL_error(l, "Unrecognised element number '%d'", t);
|
||||
}
|
||||
tpt_lua_pushString(l, luacon_sim->elements[t].Name);
|
||||
tpt_lua_pushString(l, elements[t].Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
luaL_checktype(l, 1, LUA_TSTRING);
|
||||
auto name = tpt_lua_optByteString(l, 1, "");
|
||||
if ((t = luacon_sim->GetParticleType(name))==-1)
|
||||
if ((t = sd.GetParticleType(name))==-1)
|
||||
return luaL_error(l, "Unrecognised element '%s'", name.c_str());
|
||||
lua_pushinteger(l, t);
|
||||
}
|
||||
@ -326,6 +337,7 @@ int luatpt_drawtext(lua_State* l)
|
||||
|
||||
int luatpt_create(lua_State* l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
int x, y, retid, t = -1;
|
||||
x = abs(luaL_optint(l, 1, 0));
|
||||
y = abs(luaL_optint(l, 2, 0));
|
||||
@ -334,13 +346,13 @@ int luatpt_create(lua_State* l)
|
||||
if (lua_isnumber(l, 3))
|
||||
{
|
||||
t = luaL_optint(l, 3, 0);
|
||||
if (!luacon_sim->IsElement(t))
|
||||
if (!sd.IsElement(t))
|
||||
{
|
||||
return luaL_error(l, "Unrecognised element number '%d'", t);
|
||||
}
|
||||
} else {
|
||||
auto name = tpt_lua_optByteString(l, 3, "dust");
|
||||
if ((t = luacon_sim->GetParticleType(name)) == -1)
|
||||
if ((t = sd.GetParticleType(name)) == -1)
|
||||
return luaL_error(l,"Unrecognised element '%s'", name.c_str());
|
||||
}
|
||||
retid = luacon_sim->create_part(-1, x, y, t);
|
||||
@ -547,6 +559,7 @@ int luatpt_reset_spark(lua_State* l)
|
||||
|
||||
int luatpt_set_property(lua_State* l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||
int r, i, x, y, w, h, t = 0, nx, ny, partsel = 0;
|
||||
float f = 0;
|
||||
@ -565,7 +578,7 @@ int luatpt_set_property(lua_State* l)
|
||||
if(!lua_isnumber(l, acount) && lua_isstring(l, acount))
|
||||
{
|
||||
auto name = tpt_lua_optByteString(l, acount, "none");
|
||||
if ((partsel = luacon_sim->GetParticleType(name)) == -1)
|
||||
if ((partsel = sd.GetParticleType(name)) == -1)
|
||||
return luaL_error(l, "Unrecognised element '%s'", name.c_str());
|
||||
}
|
||||
}
|
||||
@ -576,13 +589,13 @@ int luatpt_set_property(lua_State* l)
|
||||
else
|
||||
t = luaL_optint(l, 2, 0);
|
||||
|
||||
if (byteStringEqualsLiteral(prop, "type") && !luacon_sim->IsElementOrNone(t))
|
||||
if (byteStringEqualsLiteral(prop, "type") && !sd.IsElementOrNone(t))
|
||||
return luaL_error(l, "Unrecognised element number '%d'", t);
|
||||
}
|
||||
else if (lua_isstring(l, 2))
|
||||
{
|
||||
auto name = tpt_lua_checkByteString(l, 2);
|
||||
if ((t = luacon_sim->GetParticleType(name))==-1)
|
||||
if ((t = sd.GetParticleType(name))==-1)
|
||||
return luaL_error(l, "Unrecognised element '%s'", name.c_str());
|
||||
}
|
||||
else
|
||||
@ -1141,12 +1154,15 @@ int luatpt_menu_enabled(lua_State* l)
|
||||
int acount = lua_gettop(l);
|
||||
if (acount == 1)
|
||||
{
|
||||
lua_pushboolean(l, luacon_sim->msections[menusection].doshow);
|
||||
lua_pushboolean(l, SimulationData::CRef().msections[menusection].doshow);
|
||||
return 1;
|
||||
}
|
||||
luaL_checktype(l, 2, LUA_TBOOLEAN);
|
||||
int enabled = lua_toboolean(l, 2);
|
||||
luacon_sim->msections[menusection].doshow = enabled;
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
sd.msections[menusection].doshow = enabled;
|
||||
}
|
||||
luacon_model->BuildMenus();
|
||||
return 0;
|
||||
}
|
||||
|
@ -451,11 +451,13 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
|
||||
tptPart->Assign(l, -1);
|
||||
lua_pop(l, 1);
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
lua_newtable(l);
|
||||
tptElements = lua_gettop(l);
|
||||
for (int i = 1; i < PT_NUM; i++)
|
||||
{
|
||||
tpt_lua_pushString(l, luacon_sim->elements[i].Name.ToLower());
|
||||
tpt_lua_pushString(l, elements[i].Name.ToLower());
|
||||
lua_newtable(l);
|
||||
currentElement = lua_gettop(l);
|
||||
lua_pushinteger(l, i);
|
||||
@ -475,7 +477,7 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
|
||||
tptElementTransitions = lua_gettop(l);
|
||||
for (int i = 1; i < PT_NUM; i++)
|
||||
{
|
||||
tpt_lua_pushString(l, luacon_sim->elements[i].Name.ToLower());
|
||||
tpt_lua_pushString(l, elements[i].Name.ToLower());
|
||||
lua_newtable(l);
|
||||
currentElement = lua_gettop(l);
|
||||
lua_newtable(l);
|
||||
@ -536,14 +538,15 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
|
||||
|
||||
void LuaScriptInterface::custom_init_can_move()
|
||||
{
|
||||
luacon_sim->init_can_move();
|
||||
auto &sd = SimulationData::Ref();
|
||||
sd.init_can_move();
|
||||
for (auto moving = 0; moving < PT_NUM; ++moving)
|
||||
{
|
||||
for (auto into = 0; into < PT_NUM; ++into)
|
||||
{
|
||||
if (custom_can_move[moving][into] & 0x80)
|
||||
{
|
||||
luacon_sim->can_move[moving][into] = custom_can_move[moving][into] & 0x7F;
|
||||
sd.can_move[moving][into] = custom_can_move[moving][into] & 0x7F;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1112,6 +1115,8 @@ int simulation_deletesign(lua_State *l)
|
||||
|
||||
void LuaScriptInterface::initSimulationAPI()
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
|
||||
//Methods
|
||||
struct luaL_Reg simulationAPIMethods [] = {
|
||||
{"partNeighbours", simulation_partNeighbours},
|
||||
@ -1227,7 +1232,7 @@ void LuaScriptInterface::initSimulationAPI()
|
||||
SETCONST(l, TOOL_NGRV);
|
||||
SETCONST(l, TOOL_MIX);
|
||||
SETCONST(l, TOOL_CYCL);
|
||||
lua_pushinteger(l, luacon_sim->tools.size()); lua_setfield(l, -2, "TOOL_WIND");
|
||||
lua_pushinteger(l, sd.tools.size()); lua_setfield(l, -2, "TOOL_WIND");
|
||||
|
||||
SETCONST(l, DECO_DRAW);
|
||||
SETCONST(l, DECO_CLEAR);
|
||||
@ -1266,12 +1271,12 @@ void LuaScriptInterface::initSimulationAPI()
|
||||
lua_newtable(l);
|
||||
for (int i = 0; i < UI_WALLCOUNT; i++)
|
||||
{
|
||||
tpt_lua_pushByteString(l, luacon_sim->wtypes[i].identifier);
|
||||
tpt_lua_pushByteString(l, sd.wtypes[i].identifier);
|
||||
lua_pushinteger(l, i);
|
||||
lua_settable(l, -3);
|
||||
|
||||
lua_pushinteger(l, i);
|
||||
tpt_lua_pushByteString(l, luacon_sim->wtypes[i].identifier);
|
||||
tpt_lua_pushByteString(l, sd.wtypes[i].identifier);
|
||||
lua_settable(l, -3);
|
||||
}
|
||||
lua_setfield(l, -2, "walls");
|
||||
@ -1898,6 +1903,7 @@ int LuaScriptInterface::simulation_floodWalls(lua_State * l)
|
||||
|
||||
int LuaScriptInterface::simulation_toolBrush(lua_State * l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
int x = luaL_optint(l,1,-1);
|
||||
int y = luaL_optint(l,2,-1);
|
||||
int rx = luaL_optint(l,3,5);
|
||||
@ -1905,12 +1911,12 @@ int LuaScriptInterface::simulation_toolBrush(lua_State * l)
|
||||
int tool = luaL_optint(l,5,0);
|
||||
int brushID = luaL_optint(l,6,CIRCLE_BRUSH);
|
||||
float strength = luaL_optnumber(l,7,1.0f);
|
||||
if (tool == (int)luacon_sim->tools.size())
|
||||
if (tool == (int)sd.tools.size())
|
||||
{
|
||||
lua_pushinteger(l, 0);
|
||||
return 1;
|
||||
}
|
||||
else if (tool < 0 || tool > (int)luacon_sim->tools.size())
|
||||
else if (tool < 0 || tool > (int)sd.tools.size())
|
||||
return luaL_error(l, "Invalid tool id '%d'", tool);
|
||||
|
||||
Brush *brush = luacon_model->GetBrushByID(brushID);
|
||||
@ -1926,6 +1932,7 @@ int LuaScriptInterface::simulation_toolBrush(lua_State * l)
|
||||
|
||||
int LuaScriptInterface::simulation_toolLine(lua_State * l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
int x1 = luaL_optint(l,1,-1);
|
||||
int y1 = luaL_optint(l,2,-1);
|
||||
int x2 = luaL_optint(l,3,-1);
|
||||
@ -1938,7 +1945,7 @@ int LuaScriptInterface::simulation_toolLine(lua_State * l)
|
||||
|
||||
if (x1 < 0 || x2 < 0 || x1 >= XRES || x2 >= XRES || y1 < 0 || y2 < 0 || y1 >= YRES || y2 >= YRES)
|
||||
return luaL_error(l, "coordinates out of range (%d,%d),(%d,%d)", x1, y1, x2, y2);
|
||||
if (tool < 0 || tool >= (int)luacon_sim->tools.size()+1)
|
||||
if (tool < 0 || tool >= (int)sd.tools.size()+1)
|
||||
return luaL_error(l, "Invalid tool id '%d'", tool);
|
||||
|
||||
Brush *brush = luacon_model->GetBrushByID(brushID);
|
||||
@ -1947,7 +1954,7 @@ int LuaScriptInterface::simulation_toolLine(lua_State * l)
|
||||
auto newBrush = brush->Clone();
|
||||
newBrush->SetRadius(ui::Point(rx, ry));
|
||||
|
||||
if (tool == (int)luacon_sim->tools.size())
|
||||
if (tool == (int)sd.tools.size())
|
||||
{
|
||||
Tool *windTool = luacon_model->GetToolFromIdentifier("DEFAULT_UI_WIND");
|
||||
float oldStrength = windTool->Strength;
|
||||
@ -1962,6 +1969,7 @@ int LuaScriptInterface::simulation_toolLine(lua_State * l)
|
||||
|
||||
int LuaScriptInterface::simulation_toolBox(lua_State * l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
int x1 = luaL_optint(l,1,-1);
|
||||
int y1 = luaL_optint(l,2,-1);
|
||||
int x2 = luaL_optint(l,3,-1);
|
||||
@ -1970,12 +1978,12 @@ int LuaScriptInterface::simulation_toolBox(lua_State * l)
|
||||
return luaL_error(l, "coordinates out of range (%d,%d),(%d,%d)", x1, y1, x2, y2);
|
||||
int tool = luaL_optint(l,5,0);
|
||||
float strength = luaL_optnumber(l,6,1.0f);
|
||||
if (tool == (int)luacon_sim->tools.size())
|
||||
if (tool == (int)sd.tools.size())
|
||||
{
|
||||
lua_pushinteger(l, 0);
|
||||
return 1;
|
||||
}
|
||||
else if (tool < 0 || tool >= (int)luacon_sim->tools.size())
|
||||
else if (tool < 0 || tool >= (int)sd.tools.size())
|
||||
return luaL_error(l, "Invalid tool id '%d'", tool);
|
||||
|
||||
luacon_sim->ToolBox(x1, y1, x2, y2, tool, strength);
|
||||
@ -2110,12 +2118,14 @@ int LuaScriptInterface::simulation_clearRect(lua_State * l)
|
||||
|
||||
int LuaScriptInterface::simulation_resetTemp(lua_State * l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
bool onlyConductors = luaL_optint(l, 1, 0);
|
||||
for (int i = 0; i < luacon_sim->parts_lastActiveIndex; i++)
|
||||
{
|
||||
if (luacon_sim->parts[i].type && (luacon_sim->elements[luacon_sim->parts[i].type].HeatConduct || !onlyConductors))
|
||||
if (luacon_sim->parts[i].type && (elements[luacon_sim->parts[i].type].HeatConduct || !onlyConductors))
|
||||
{
|
||||
luacon_sim->parts[i].temp = luacon_sim->elements[luacon_sim->parts[i].type].DefaultProperties.temp;
|
||||
luacon_sim->parts[i].temp = elements[luacon_sim->parts[i].type].DefaultProperties.temp;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -2427,14 +2437,16 @@ int LuaScriptInterface::simulation_canMove(lua_State * l)
|
||||
|
||||
if (lua_gettop(l) < 3)
|
||||
{
|
||||
lua_pushnumber(l, luacon_sim->can_move[movingElement][destinationElement]);
|
||||
auto &sd = SimulationData::CRef();
|
||||
lua_pushnumber(l, sd.can_move[movingElement][destinationElement]);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int setting = luaL_checkint(l, 3) & 0x7F;
|
||||
luacon_ci->custom_can_move[movingElement][destinationElement] = setting | 0x80;
|
||||
luacon_sim->can_move[movingElement][destinationElement] = setting;
|
||||
auto &sd = SimulationData::Ref();
|
||||
sd.can_move[movingElement][destinationElement] = setting;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -2684,9 +2696,10 @@ int LuaScriptInterface::simulation_replaceModeFlags(lua_State *l)
|
||||
|
||||
int LuaScriptInterface::simulation_listCustomGol(lua_State *l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
int i = 0;
|
||||
lua_newtable(l);
|
||||
for (auto &cgol : luacon_sim->GetCustomGol())
|
||||
for (auto &cgol : sd.GetCustomGol())
|
||||
{
|
||||
lua_newtable(l);
|
||||
tpt_lua_pushString(l, cgol.nameString);
|
||||
@ -2706,6 +2719,7 @@ int LuaScriptInterface::simulation_listCustomGol(lua_State *l)
|
||||
|
||||
int LuaScriptInterface::simulation_addCustomGol(lua_State *l)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
int rule;
|
||||
String ruleString;
|
||||
if (lua_isnumber(l, 1))
|
||||
@ -2727,7 +2741,7 @@ int LuaScriptInterface::simulation_addCustomGol(lua_State *l)
|
||||
return luaL_error(l, "Invalid name provided");
|
||||
if (rule == -1)
|
||||
return luaL_error(l, "Invalid rule provided");
|
||||
if (luacon_sim->GetCustomGOLByRule(rule))
|
||||
if (sd.GetCustomGOLByRule(rule))
|
||||
return luaL_error(l, "This Custom GoL rule already exists");
|
||||
|
||||
if (!AddCustomGol(ruleString, nameString, color1, color2))
|
||||
@ -3145,15 +3159,17 @@ void LuaScriptInterface::initElementsAPI()
|
||||
SETCONST(l, SC_DECO);
|
||||
|
||||
//Element identifiers
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for(int i = 0; i < PT_NUM; i++)
|
||||
{
|
||||
if(luacon_sim->elements[i].Enabled)
|
||||
if(elements[i].Enabled)
|
||||
{
|
||||
tpt_lua_pushByteString(l, luacon_sim->elements[i].Identifier);
|
||||
tpt_lua_pushByteString(l, elements[i].Identifier);
|
||||
lua_pushinteger(l, i);
|
||||
lua_settable(l, -3);
|
||||
ByteString realIdentifier = ByteString::Build("DEFAULT_PT_", luacon_sim->elements[i].Name.ToUtf8());
|
||||
if (i != 0 && i != PT_NBHL && i != PT_NWHL && luacon_sim->elements[i].Identifier != realIdentifier)
|
||||
ByteString realIdentifier = ByteString::Build("DEFAULT_PT_", elements[i].Name.ToUtf8());
|
||||
if (i != 0 && i != PT_NBHL && i != PT_NWHL && elements[i].Identifier != realIdentifier)
|
||||
{
|
||||
tpt_lua_pushByteString(l, realIdentifier);
|
||||
lua_pushinteger(l, i);
|
||||
@ -3270,52 +3286,64 @@ void LuaScriptInterface::LuaSetParticleProperty(lua_State* l, int particleID, St
|
||||
|
||||
int LuaScriptInterface::elements_loadDefault(lua_State * l)
|
||||
{
|
||||
auto &builtinElements = GetElements();
|
||||
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||
int args = lua_gettop(l);
|
||||
if (args)
|
||||
{
|
||||
luaL_checktype(l, 1, LUA_TNUMBER);
|
||||
int id = lua_tointeger(l, 1);
|
||||
if (id < 0 || id >= PT_NUM)
|
||||
return luaL_error(l, "Invalid element");
|
||||
|
||||
lua_getglobal(l, "elements");
|
||||
tpt_lua_pushByteString(l, luacon_sim->elements[id].Identifier);
|
||||
lua_pushnil(l);
|
||||
lua_settable(l, -3);
|
||||
|
||||
auto const &elementList = GetElements();
|
||||
if (id < (int)elementList.size())
|
||||
luacon_sim->elements[id] = elementList[id];
|
||||
else
|
||||
luacon_sim->elements[id] = Element();
|
||||
|
||||
tpt_lua_pushByteString(l, luacon_sim->elements[id].Identifier);
|
||||
lua_pushinteger(l, id);
|
||||
lua_settable(l, -3);
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const &elementList = GetElements();
|
||||
for (int i = 0; i < PT_NUM; i++)
|
||||
int args = lua_gettop(l);
|
||||
if (args)
|
||||
{
|
||||
if (i < (int)elementList.size())
|
||||
luacon_sim->elements[i] = elementList[i];
|
||||
else
|
||||
luacon_sim->elements[i] = Element();
|
||||
luaL_checktype(l, 1, LUA_TNUMBER);
|
||||
int id = lua_tointeger(l, 1);
|
||||
if (id < 0 || id >= PT_NUM)
|
||||
return luaL_error(l, "Invalid element");
|
||||
|
||||
lua_getglobal(l, "elements");
|
||||
ByteString identifier = SimulationData::CRef().elements[id].Identifier;
|
||||
tpt_lua_pushByteString(l, identifier);
|
||||
lua_pushnil(l);
|
||||
lua_settable(l, -3);
|
||||
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
std::unique_lock lk(sd.elementGraphicsMx);
|
||||
auto &elements = sd.elements;
|
||||
if (id < (int)builtinElements.size())
|
||||
elements[id] = builtinElements[id];
|
||||
else
|
||||
elements[id] = Element();
|
||||
}
|
||||
|
||||
tpt_lua_pushByteString(l, identifier);
|
||||
lua_pushinteger(l, id);
|
||||
lua_settable(l, -3);
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
lua_pushnil(l);
|
||||
lua_setglobal(l, "elements");
|
||||
lua_pushnil(l);
|
||||
lua_setglobal(l, "elem");
|
||||
else
|
||||
{
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
std::unique_lock lk(sd.elementGraphicsMx);
|
||||
auto &elements = sd.elements;
|
||||
for (int i = 0; i < PT_NUM; i++)
|
||||
{
|
||||
if (i < (int)builtinElements.size())
|
||||
elements[i] = builtinElements[i];
|
||||
else
|
||||
elements[i] = Element();
|
||||
}
|
||||
}
|
||||
lua_pushnil(l);
|
||||
lua_setglobal(l, "elements");
|
||||
lua_pushnil(l);
|
||||
lua_setglobal(l, "elem");
|
||||
|
||||
lua_getglobal(l, "package");
|
||||
lua_getfield(l, -1, "loaded");
|
||||
lua_pushnil(l);
|
||||
lua_setfield(l, -2, "elements");
|
||||
lua_getglobal(l, "package");
|
||||
lua_getfield(l, -1, "loaded");
|
||||
lua_pushnil(l);
|
||||
lua_setfield(l, -2, "elements");
|
||||
|
||||
luacon_ci->initElementsAPI();
|
||||
luacon_ci->initElementsAPI();
|
||||
}
|
||||
}
|
||||
|
||||
luacon_model->BuildMenus();
|
||||
@ -3355,40 +3383,49 @@ int LuaScriptInterface::elements_allocate(lua_State * l)
|
||||
|
||||
auto identifier = group + "_PT_" + id;
|
||||
|
||||
for(int i = 0; i < PT_NUM; i++)
|
||||
{
|
||||
if(luacon_sim->elements[i].Enabled && ByteString(luacon_sim->elements[i].Identifier) == identifier)
|
||||
return luaL_error(l, "Element identifier already in use");
|
||||
}
|
||||
|
||||
int newID = -1;
|
||||
// Start out at 255 so that lua element IDs are still one byte (better save compatibility)
|
||||
for (int i = PT_NUM >= 255 ? 255 : PT_NUM; i >= 0; i--)
|
||||
{
|
||||
if (!luacon_sim->elements[i].Enabled)
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for(int i = 0; i < PT_NUM; i++)
|
||||
{
|
||||
newID = i;
|
||||
break;
|
||||
if(elements[i].Enabled && ByteString(elements[i].Identifier) == identifier)
|
||||
return luaL_error(l, "Element identifier already in use");
|
||||
}
|
||||
}
|
||||
// If not enough space, then we start with the new maimum ID
|
||||
if (newID == -1)
|
||||
{
|
||||
for (int i = PT_NUM-1; i >= 255; i--)
|
||||
|
||||
// Start out at 255 so that lua element IDs are still one byte (better save compatibility)
|
||||
for (int i = PT_NUM >= 255 ? 255 : PT_NUM; i >= 0; i--)
|
||||
{
|
||||
if (!luacon_sim->elements[i].Enabled)
|
||||
if (!elements[i].Enabled)
|
||||
{
|
||||
newID = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If not enough space, then we start with the new maimum ID
|
||||
if (newID == -1)
|
||||
{
|
||||
for (int i = PT_NUM-1; i >= 255; i--)
|
||||
{
|
||||
if (!elements[i].Enabled)
|
||||
{
|
||||
newID = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newID != -1)
|
||||
{
|
||||
luacon_sim->elements[newID] = Element();
|
||||
luacon_sim->elements[newID].Enabled = true;
|
||||
luacon_sim->elements[newID].Identifier = identifier;
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
std::unique_lock lk(sd.elementGraphicsMx);
|
||||
auto &elements = sd.elements;
|
||||
elements[newID] = Element();
|
||||
elements[newID].Enabled = true;
|
||||
elements[newID].Identifier = identifier;
|
||||
}
|
||||
|
||||
lua_getglobal(l, "elements");
|
||||
tpt_lua_pushByteString(l, identifier);
|
||||
@ -3412,7 +3449,8 @@ int LuaScriptInterface::elements_allocate(lua_State * l)
|
||||
static int luaUpdateWrapper(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||
auto *builtinUpdate = GetElements()[parts[i].type].Update;
|
||||
auto &builtinElements = GetElements();
|
||||
auto *builtinUpdate = builtinElements[parts[i].type].Update;
|
||||
if (builtinUpdate && lua_el_mode[parts[i].type] == 1)
|
||||
{
|
||||
if (builtinUpdate(UPDATE_FUNC_SUBCALL_ARGS))
|
||||
@ -3591,109 +3629,115 @@ static bool luaCtypeDrawWrapper(CTYPEDRAW_FUNC_ARGS)
|
||||
|
||||
int LuaScriptInterface::elements_element(lua_State * l)
|
||||
{
|
||||
auto &builtinElements = GetElements();
|
||||
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||
int id = luaL_checkinteger(l, 1);
|
||||
if (!luacon_sim->IsElementOrNone(id))
|
||||
if (!SimulationData::CRef().IsElementOrNone(id))
|
||||
{
|
||||
return luaL_error(l, "Invalid element");
|
||||
}
|
||||
|
||||
if (lua_gettop(l) > 1)
|
||||
{
|
||||
luaL_checktype(l, 2, LUA_TTABLE);
|
||||
//Write values from native data to a table
|
||||
for (auto &prop : Element::GetProperties())
|
||||
{
|
||||
tpt_lua_pushByteString(l, prop.Name);
|
||||
lua_gettable(l, -2);
|
||||
if (lua_type(l, -1) != LUA_TNIL)
|
||||
auto &sd = SimulationData::Ref();
|
||||
std::unique_lock lk(sd.elementGraphicsMx);
|
||||
auto &elements = sd.elements;
|
||||
luaL_checktype(l, 2, LUA_TTABLE);
|
||||
//Write values from native data to a table
|
||||
for (auto &prop : Element::GetProperties())
|
||||
{
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[id]) + prop.Offset);
|
||||
LuaSetProperty(l, prop, propertyAddress, -1);
|
||||
tpt_lua_pushByteString(l, prop.Name);
|
||||
lua_gettable(l, -2);
|
||||
if (lua_type(l, -1) != LUA_TNIL)
|
||||
{
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&elements[id]) + prop.Offset);
|
||||
LuaSetProperty(l, prop, propertyAddress, -1);
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
|
||||
lua_getfield(l, -1, "Update");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
lua_el_func[id].Assign(l, -1);
|
||||
lua_el_mode[id] = 1;
|
||||
elements[id].Update = luaUpdateWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
lua_el_func[id].Clear();
|
||||
lua_el_mode[id] = 0;
|
||||
elements[id].Update = builtinElements[id].Update;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "Graphics");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
lua_gr_func[id].Assign(l, -1);
|
||||
elements[id].Graphics = luaGraphicsWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
lua_gr_func[id].Clear();
|
||||
elements[id].Graphics = builtinElements[id].Graphics;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "Create");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
luaCreateHandlers[id].Assign(l, -1);
|
||||
elements[id].Create = luaCreateWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
luaCreateHandlers[id].Clear();
|
||||
elements[id].Create = builtinElements[id].Create;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "CreateAllowed");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
luaCreateAllowedHandlers[id].Assign(l, -1);
|
||||
elements[id].CreateAllowed = luaCreateAllowedWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
luaCreateAllowedHandlers[id].Clear();
|
||||
elements[id].CreateAllowed = builtinElements[id].CreateAllowed;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "ChangeType");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
luaChangeTypeHandlers[id].Assign(l, -1);
|
||||
elements[id].ChangeType = luaChangeTypeWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
luaChangeTypeHandlers[id].Clear();
|
||||
elements[id].ChangeType = builtinElements[id].ChangeType;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "CtypeDraw");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
luaCtypeDrawHandlers[id].Assign(l, -1);
|
||||
elements[id].CtypeDraw = luaCtypeDrawWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
luaCtypeDrawHandlers[id].Clear();
|
||||
elements[id].CtypeDraw = builtinElements[id].CtypeDraw;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
|
||||
lua_getfield(l, -1, "Update");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
lua_el_func[id].Assign(l, -1);
|
||||
lua_el_mode[id] = 1;
|
||||
luacon_sim->elements[id].Update = luaUpdateWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
lua_el_func[id].Clear();
|
||||
lua_el_mode[id] = 0;
|
||||
luacon_sim->elements[id].Update = GetElements()[id].Update;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "Graphics");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
lua_gr_func[id].Assign(l, -1);
|
||||
luacon_sim->elements[id].Graphics = luaGraphicsWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
lua_gr_func[id].Clear();
|
||||
luacon_sim->elements[id].Graphics = GetElements()[id].Graphics;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "Create");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
luaCreateHandlers[id].Assign(l, -1);
|
||||
luacon_sim->elements[id].Create = luaCreateWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
luaCreateHandlers[id].Clear();
|
||||
luacon_sim->elements[id].Create = GetElements()[id].Create;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "CreateAllowed");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
luaCreateAllowedHandlers[id].Assign(l, -1);
|
||||
luacon_sim->elements[id].CreateAllowed = luaCreateAllowedWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
luaCreateAllowedHandlers[id].Clear();
|
||||
luacon_sim->elements[id].CreateAllowed = GetElements()[id].CreateAllowed;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "ChangeType");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
luaChangeTypeHandlers[id].Assign(l, -1);
|
||||
luacon_sim->elements[id].ChangeType = luaChangeTypeWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
luaChangeTypeHandlers[id].Clear();
|
||||
luacon_sim->elements[id].ChangeType = GetElements()[id].ChangeType;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "CtypeDraw");
|
||||
if (lua_type(l, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
luaCtypeDrawHandlers[id].Assign(l, -1);
|
||||
luacon_sim->elements[id].CtypeDraw = luaCtypeDrawWrapper;
|
||||
}
|
||||
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
|
||||
{
|
||||
luaCtypeDrawHandlers[id].Clear();
|
||||
luacon_sim->elements[id].CtypeDraw = GetElements()[id].CtypeDraw;
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
|
||||
lua_getfield(l, -1, "DefaultProperties");
|
||||
SetDefaultProperties(l, id, lua_gettop(l));
|
||||
lua_pop(l, 1);
|
||||
@ -3707,17 +3751,19 @@ int LuaScriptInterface::elements_element(lua_State * l)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
//Write values from native data to a table
|
||||
lua_newtable(l);
|
||||
for (auto &prop : Element::GetProperties())
|
||||
{
|
||||
tpt_lua_pushByteString(l, prop.Name);
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[id]) + prop.Offset);
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&elements[id]) + prop.Offset);
|
||||
LuaGetProperty(l, prop, propertyAddress);
|
||||
lua_settable(l, -3);
|
||||
}
|
||||
|
||||
tpt_lua_pushByteString(l, luacon_sim->elements[id].Identifier);
|
||||
tpt_lua_pushByteString(l, elements[id].Identifier);
|
||||
lua_setfield(l, -2, "Identifier");
|
||||
|
||||
GetDefaultProperties(l, id);
|
||||
@ -3729,10 +3775,12 @@ int LuaScriptInterface::elements_element(lua_State * l)
|
||||
|
||||
void LuaScriptInterface::GetDefaultProperties(lua_State * l, int id)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
lua_newtable(l);
|
||||
for (auto &prop : Particle::GetProperties())
|
||||
{
|
||||
auto propertyAddress = reinterpret_cast<intptr_t>((reinterpret_cast<unsigned char*>(&luacon_sim->elements[id].DefaultProperties)) + prop.Offset);
|
||||
auto propertyAddress = reinterpret_cast<intptr_t>((reinterpret_cast<const unsigned char*>(&elements[id].DefaultProperties)) + prop.Offset);
|
||||
tpt_lua_pushByteString(l, prop.Name);
|
||||
LuaGetProperty(l, prop, propertyAddress);
|
||||
lua_settable(l, -3);
|
||||
@ -3748,6 +3796,8 @@ void LuaScriptInterface::GetDefaultProperties(lua_State * l, int id)
|
||||
|
||||
void LuaScriptInterface::SetDefaultProperties(lua_State * l, int id, int stackPos)
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
auto &elements = sd.elements;
|
||||
if (lua_type(l, stackPos) == LUA_TTABLE)
|
||||
{
|
||||
for (auto &prop : Particle::GetProperties())
|
||||
@ -3768,7 +3818,7 @@ void LuaScriptInterface::SetDefaultProperties(lua_State * l, int id, int stackPo
|
||||
}
|
||||
if (lua_type(l, -1) != LUA_TNIL)
|
||||
{
|
||||
auto propertyAddress = reinterpret_cast<intptr_t>((reinterpret_cast<unsigned char*>(&luacon_sim->elements[id].DefaultProperties)) + prop.Offset);
|
||||
auto propertyAddress = reinterpret_cast<intptr_t>((reinterpret_cast<unsigned char*>(&elements[id].DefaultProperties)) + prop.Offset);
|
||||
LuaSetProperty(l, prop, propertyAddress, -1);
|
||||
}
|
||||
lua_pop(l, 1);
|
||||
@ -3778,9 +3828,10 @@ void LuaScriptInterface::SetDefaultProperties(lua_State * l, int id, int stackPo
|
||||
|
||||
int LuaScriptInterface::elements_property(lua_State * l)
|
||||
{
|
||||
auto &builtinElements = GetElements();
|
||||
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
||||
int id = luaL_checkinteger(l, 1);
|
||||
if (!luacon_sim->IsElementOrNone(id))
|
||||
if (!SimulationData::CRef().IsElementOrNone(id))
|
||||
{
|
||||
return luaL_error(l, "Invalid element");
|
||||
}
|
||||
@ -3800,14 +3851,18 @@ int LuaScriptInterface::elements_property(lua_State * l)
|
||||
if (prop->Type == StructProperty::TransitionType)
|
||||
{
|
||||
int type = luaL_checkinteger(l, 3);
|
||||
if (!luacon_sim->IsElementOrNone(type) && type != NT && type != ST)
|
||||
if (!SimulationData::CRef().IsElementOrNone(type) && type != NT && type != ST)
|
||||
{
|
||||
return luaL_error(l, "Invalid element");
|
||||
}
|
||||
}
|
||||
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[id]) + prop->Offset);
|
||||
LuaSetProperty(l, *prop, propertyAddress, 3);
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
std::unique_lock lk(sd.elementGraphicsMx);
|
||||
auto &elements = sd.elements;
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&elements[id]) + prop->Offset);
|
||||
LuaSetProperty(l, *prop, propertyAddress, 3);
|
||||
}
|
||||
}
|
||||
|
||||
luacon_model->BuildMenus();
|
||||
@ -3817,6 +3872,8 @@ int LuaScriptInterface::elements_property(lua_State * l)
|
||||
}
|
||||
else if (propertyName == "Update")
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
auto &elements = sd.elements;
|
||||
if (lua_type(l, 3) == LUA_TFUNCTION)
|
||||
{
|
||||
switch (luaL_optint(l, 4, 0))
|
||||
@ -3834,80 +3891,90 @@ int LuaScriptInterface::elements_property(lua_State * l)
|
||||
break;
|
||||
}
|
||||
lua_el_func[id].Assign(l, 3);
|
||||
luacon_sim->elements[id].Update = luaUpdateWrapper;
|
||||
elements[id].Update = luaUpdateWrapper;
|
||||
}
|
||||
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
|
||||
{
|
||||
lua_el_func[id].Clear();
|
||||
lua_el_mode[id] = 0;
|
||||
luacon_sim->elements[id].Update = GetElements()[id].Update;
|
||||
elements[id].Update = builtinElements[id].Update;
|
||||
}
|
||||
}
|
||||
else if (propertyName == "Graphics")
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
auto &elements = sd.elements;
|
||||
if (lua_type(l, 3) == LUA_TFUNCTION)
|
||||
{
|
||||
lua_gr_func[id].Assign(l, 3);
|
||||
luacon_sim->elements[id].Graphics = luaGraphicsWrapper;
|
||||
elements[id].Graphics = luaGraphicsWrapper;
|
||||
}
|
||||
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
|
||||
{
|
||||
lua_gr_func[id].Clear();
|
||||
luacon_sim->elements[id].Graphics = GetElements()[id].Graphics;
|
||||
elements[id].Graphics = builtinElements[id].Graphics;
|
||||
}
|
||||
luacon_ren->graphicscache[id].isready = 0;
|
||||
SaveRenderer::Ref().Flush(id, id + 1);
|
||||
}
|
||||
else if (propertyName == "Create")
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
auto &elements = sd.elements;
|
||||
if (lua_type(l, 3) == LUA_TFUNCTION)
|
||||
{
|
||||
luaCreateHandlers[id].Assign(l, 3);
|
||||
luacon_sim->elements[id].Create = luaCreateWrapper;
|
||||
elements[id].Create = luaCreateWrapper;
|
||||
}
|
||||
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
|
||||
{
|
||||
luaCreateHandlers[id].Clear();
|
||||
luacon_sim->elements[id].Create = GetElements()[id].Create;
|
||||
elements[id].Create = builtinElements[id].Create;
|
||||
}
|
||||
}
|
||||
else if (propertyName == "CreateAllowed")
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
auto &elements = sd.elements;
|
||||
if (lua_type(l, 3) == LUA_TFUNCTION)
|
||||
{
|
||||
luaCreateAllowedHandlers[id].Assign(l, 3);
|
||||
luacon_sim->elements[id].CreateAllowed = luaCreateAllowedWrapper;
|
||||
elements[id].CreateAllowed = luaCreateAllowedWrapper;
|
||||
}
|
||||
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
|
||||
{
|
||||
luaCreateAllowedHandlers[id].Clear();
|
||||
luacon_sim->elements[id].CreateAllowed = GetElements()[id].CreateAllowed;
|
||||
elements[id].CreateAllowed = builtinElements[id].CreateAllowed;
|
||||
}
|
||||
}
|
||||
else if (propertyName == "ChangeType")
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
auto &elements = sd.elements;
|
||||
if (lua_type(l, 3) == LUA_TFUNCTION)
|
||||
{
|
||||
luaChangeTypeHandlers[id].Assign(l, 3);
|
||||
luacon_sim->elements[id].ChangeType = luaChangeTypeWrapper;
|
||||
elements[id].ChangeType = luaChangeTypeWrapper;
|
||||
}
|
||||
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
|
||||
{
|
||||
luaChangeTypeHandlers[id].Clear();
|
||||
luacon_sim->elements[id].ChangeType = GetElements()[id].ChangeType;
|
||||
elements[id].ChangeType = builtinElements[id].ChangeType;
|
||||
}
|
||||
}
|
||||
else if (propertyName == "CtypeDraw")
|
||||
{
|
||||
auto &sd = SimulationData::Ref();
|
||||
auto &elements = sd.elements;
|
||||
if (lua_type(l, 3) == LUA_TFUNCTION)
|
||||
{
|
||||
luaCtypeDrawHandlers[id].Assign(l, 3);
|
||||
luacon_sim->elements[id].CtypeDraw = luaCtypeDrawWrapper;
|
||||
elements[id].CtypeDraw = luaCtypeDrawWrapper;
|
||||
}
|
||||
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
|
||||
{
|
||||
luaCtypeDrawHandlers[id].Clear();
|
||||
luacon_sim->elements[id].CtypeDraw = GetElements()[id].CtypeDraw;
|
||||
elements[id].CtypeDraw = builtinElements[id].CtypeDraw;
|
||||
}
|
||||
}
|
||||
else if (propertyName == "DefaultProperties")
|
||||
@ -3922,15 +3989,17 @@ int LuaScriptInterface::elements_property(lua_State * l)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (prop != properties.end())
|
||||
{
|
||||
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[id]) + prop->Offset);
|
||||
intptr_t propertyAddress = (intptr_t)(((const unsigned char*)&elements[id]) + prop->Offset);
|
||||
LuaGetProperty(l, *prop, propertyAddress);
|
||||
return 1;
|
||||
}
|
||||
else if (propertyName == "Identifier")
|
||||
{
|
||||
tpt_lua_pushByteString(l, luacon_sim->elements[id].Identifier);
|
||||
tpt_lua_pushByteString(l, elements[id].Identifier);
|
||||
return 1;
|
||||
}
|
||||
else if (propertyName == "DefaultProperties")
|
||||
@ -3948,18 +4017,26 @@ int LuaScriptInterface::elements_property(lua_State * l)
|
||||
int LuaScriptInterface::elements_free(lua_State * l)
|
||||
{
|
||||
int id = luaL_checkinteger(l, 1);
|
||||
if (!luacon_sim->IsElement(id))
|
||||
ByteString identifier;
|
||||
{
|
||||
return luaL_error(l, "Invalid element");
|
||||
auto &sd = SimulationData::CRef();
|
||||
if (!sd.IsElement(id))
|
||||
{
|
||||
return luaL_error(l, "Invalid element");
|
||||
}
|
||||
|
||||
identifier = sd.elements[id].Identifier;
|
||||
if (identifier.BeginsWith("DEFAULT_PT_"))
|
||||
{
|
||||
return luaL_error(l, "Cannot free default elements");
|
||||
}
|
||||
}
|
||||
|
||||
ByteString identifier = luacon_sim->elements[id].Identifier;
|
||||
if (identifier.BeginsWith("DEFAULT_PT_"))
|
||||
{
|
||||
return luaL_error(l, "Cannot free default elements");
|
||||
auto &sd = SimulationData::Ref();
|
||||
std::unique_lock lk(sd.elementGraphicsMx);
|
||||
sd.elements[id].Enabled = false;
|
||||
}
|
||||
|
||||
luacon_sim->elements[id].Enabled = false;
|
||||
luacon_model->BuildMenus();
|
||||
|
||||
lua_getglobal(l, "elements");
|
||||
@ -3973,7 +4050,8 @@ int LuaScriptInterface::elements_free(lua_State * l)
|
||||
|
||||
int LuaScriptInterface::elements_exists(lua_State * l)
|
||||
{
|
||||
lua_pushboolean(l, luacon_sim->IsElement(luaL_checkinteger(l, 1)));
|
||||
auto &sd = SimulationData::CRef();
|
||||
lua_pushboolean(l, sd.IsElement(luaL_checkinteger(l, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -244,6 +244,7 @@ String TPTScriptInterface::FormatCommand(String command)
|
||||
|
||||
AnyType TPTScriptInterface::tptS_set(std::deque<String> * words)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
//Arguments from stack
|
||||
StringType property = eval(words);
|
||||
AnyType selector = eval(words);
|
||||
@ -300,7 +301,7 @@ AnyType TPTScriptInterface::tptS_set(std::deque<String> * words)
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue = m->GetSimulation()->GetParticleType(((StringType)value).Value().ToUtf8());
|
||||
newValue = sd.GetParticleType(((StringType)value).Value().ToUtf8());
|
||||
if (newValue < 0 || newValue >= PT_NUM)
|
||||
{
|
||||
// TODO: add element CAKE to invalidate this
|
||||
@ -312,7 +313,7 @@ AnyType TPTScriptInterface::tptS_set(std::deque<String> * words)
|
||||
}
|
||||
else
|
||||
throw GeneralException("Invalid value for assignment");
|
||||
if (property.Value() == "type" && (newValue < 0 || newValue >= PT_NUM || !sim->elements[newValue].Enabled))
|
||||
if (property.Value() == "type" && (newValue < 0 || newValue >= PT_NUM || !sd.elements[newValue].Enabled))
|
||||
throw GeneralException("Invalid element");
|
||||
|
||||
if (selector.GetType() == TypePoint || selector.GetType() == TypeNumber)
|
||||
@ -390,7 +391,7 @@ AnyType TPTScriptInterface::tptS_set(std::deque<String> * words)
|
||||
if (selector.GetType() == TypeNumber)
|
||||
type = ((NumberType)selector).Value();
|
||||
else if (selector.GetType() == TypeString)
|
||||
type = m->GetSimulation()->GetParticleType(((StringType)selector).Value().ToUtf8());
|
||||
type = sd.GetParticleType(((StringType)selector).Value().ToUtf8());
|
||||
|
||||
if (type<0 || type>=PT_NUM)
|
||||
throw GeneralException("Invalid particle type");
|
||||
@ -439,6 +440,7 @@ AnyType TPTScriptInterface::tptS_set(std::deque<String> * words)
|
||||
|
||||
AnyType TPTScriptInterface::tptS_create(std::deque<String> * words)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
//Arguments from stack
|
||||
AnyType createType = eval(words);
|
||||
PointType position = eval(words);
|
||||
@ -449,7 +451,7 @@ AnyType TPTScriptInterface::tptS_create(std::deque<String> * words)
|
||||
if(createType.GetType() == TypeNumber)
|
||||
type = ((NumberType)createType).Value();
|
||||
else if(createType.GetType() == TypeString)
|
||||
type = m->GetSimulation()->GetParticleType(((StringType)createType).Value().ToUtf8());
|
||||
type = sd.GetParticleType(((StringType)createType).Value().ToUtf8());
|
||||
else
|
||||
throw GeneralException("Invalid type");
|
||||
|
||||
@ -549,6 +551,7 @@ AnyType TPTScriptInterface::tptS_bubble(std::deque<String> * words)
|
||||
|
||||
AnyType TPTScriptInterface::tptS_reset(std::deque<String> * words)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
//Arguments from stack
|
||||
StringType reset = eval(words);
|
||||
String resetStr = reset.Value();
|
||||
@ -582,7 +585,7 @@ AnyType TPTScriptInterface::tptS_reset(std::deque<String> * words)
|
||||
{
|
||||
if (sim->parts[i].type)
|
||||
{
|
||||
sim->parts[i].temp = sim->elements[sim->parts[i].type].DefaultProperties.temp;
|
||||
sim->parts[i].temp = sd.elements[sim->parts[i].type].DefaultProperties.temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -354,6 +354,8 @@ void Air::Invert()
|
||||
// called when loading saves / stamps to ensure nothing "leaks" the first frame
|
||||
void Air::ApproximateBlockAirMaps()
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (int i = 0; i <= sim.parts_lastActiveIndex; i++)
|
||||
{
|
||||
int type = sim.parts[i].type;
|
||||
@ -372,7 +374,7 @@ void Air::ApproximateBlockAirMaps()
|
||||
}
|
||||
}
|
||||
// mostly accurate insulator blocking, besides checking GEL
|
||||
else if ((type == PT_HSWC && sim.parts[i].life != 10) || sim.elements[type].HeatConduct <= (sim.rng()%250))
|
||||
else if ((type == PT_HSWC && sim.parts[i].life != 10) || elements[type].HeatConduct <= (sim.rng()%250))
|
||||
{
|
||||
int x = ((int)(sim.parts[i].x+0.5f))/CELL, y = ((int)(sim.parts[i].y+0.5f))/CELL;
|
||||
if (InBounds(x, y) && !(bmap_blockairh[y][x]&0x8))
|
||||
|
@ -8,7 +8,8 @@ struct BuiltinGOL
|
||||
String name;
|
||||
int oldtype;
|
||||
int ruleset;
|
||||
RGB<uint8_t> colour, colour2;
|
||||
RGB<uint8_t> colour = RGB<uint8_t>(0, 0, 0);
|
||||
RGB<uint8_t> colour2 = RGB<uint8_t>(0, 0, 0);
|
||||
int goltype;
|
||||
String description;
|
||||
};
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
std::unique_ptr<Snapshot> Simulation::CreateSnapshot()
|
||||
std::unique_ptr<Snapshot> Simulation::CreateSnapshot() const
|
||||
{
|
||||
auto snap = std::make_unique<Snapshot>();
|
||||
snap->AirPressure .insert (snap->AirPressure .begin(), &pv [0][0] , &pv [0][0] + NCELL);
|
||||
@ -188,7 +188,8 @@ int Simulation::Tool(int x, int y, int tool, int brushX, int brushY, float stren
|
||||
cpart = &(parts[ID(r)]);
|
||||
else if ((r = photons[y][x]))
|
||||
cpart = &(parts[ID(r)]);
|
||||
return tools[tool].Perform(this, cpart, x, y, brushX, brushY, strength);
|
||||
auto &sd = SimulationData::CRef();
|
||||
return sd.tools[tool].Perform(this, cpart, x, y, brushX, brushY, strength);
|
||||
}
|
||||
|
||||
int Simulation::CreateWalls(int x, int y, int rx, int ry, int wall, Brush const *cBrush)
|
||||
@ -428,27 +429,6 @@ int Simulation::CreatePartFlags(int x, int y, int c, int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Simulation::GetParticleType(ByteString type)
|
||||
{
|
||||
type = type.ToUpper();
|
||||
|
||||
// alternative names for some elements
|
||||
if (byteStringEqualsLiteral(type, "C4"))
|
||||
return PT_PLEX;
|
||||
else if (byteStringEqualsLiteral(type, "C5"))
|
||||
return PT_C5;
|
||||
else if (byteStringEqualsLiteral(type, "NONE"))
|
||||
return PT_NONE;
|
||||
for (int i = 1; i < PT_NUM; i++)
|
||||
{
|
||||
if (elements[i].Name.size() && elements[i].Enabled && type == elements[i].Name.ToUtf8().ToUpper())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Simulation::ApplyDecoration(int x, int y, int colR_, int colG_, int colB_, int colA_, int mode)
|
||||
{
|
||||
int rp;
|
||||
@ -1058,6 +1038,8 @@ int Simulation::FloodParts(int x, int y, int fullc, int cm, int flags)
|
||||
coord_stack[coord_stack_size][1] = y;
|
||||
coord_stack_size++;
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
do
|
||||
{
|
||||
coord_stack_size--;
|
||||
|
@ -216,14 +216,16 @@ int Element::legacyUpdate(UPDATE_FUNC_ARGS) {
|
||||
|
||||
int Element::defaultGraphics(GRAPHICS_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int t = cpart->type;
|
||||
//Property based defaults
|
||||
if(ren->sim->elements[t].Properties & PROP_RADIOACTIVE) *pixel_mode |= PMODE_GLOW;
|
||||
if(ren->sim->elements[t].Properties & TYPE_LIQUID)
|
||||
if(elements[t].Properties & PROP_RADIOACTIVE) *pixel_mode |= PMODE_GLOW;
|
||||
if(elements[t].Properties & TYPE_LIQUID)
|
||||
{
|
||||
*pixel_mode |= PMODE_BLUR;
|
||||
}
|
||||
if(ren->sim->elements[t].Properties & TYPE_GAS)
|
||||
if(elements[t].Properties & TYPE_GAS)
|
||||
{
|
||||
*pixel_mode &= ~PMODE;
|
||||
*pixel_mode |= FIRE_BLEND;
|
||||
@ -238,7 +240,9 @@ int Element::defaultGraphics(GRAPHICS_FUNC_ARGS)
|
||||
|
||||
bool Element::basicCtypeDraw(CTYPEDRAW_FUNC_ARGS)
|
||||
{
|
||||
if (sim->parts[i].type == t || sim->elements[t].Properties & PROP_NOCTYPEDRAW)
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (sim->parts[i].type == t || elements[t].Properties & PROP_NOCTYPEDRAW)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include "ElementCommon.h"
|
||||
|
||||
std::vector<Element> const &GetElements()
|
||||
std::array<Element, PT_NUM> const &GetElements()
|
||||
{
|
||||
struct DoOnce
|
||||
{
|
||||
std::vector<Element> elements;
|
||||
std::array<Element, PT_NUM> elements;
|
||||
|
||||
DoOnce() : elements(PT_NUM)
|
||||
DoOnce()
|
||||
{
|
||||
#define ELEMENT_NUMBERS_CALL
|
||||
#include "ElementNumbers.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "SimulationData.h"
|
||||
#include "Element.h"
|
||||
@ -8,4 +8,4 @@
|
||||
#include "ElementNumbers.h"
|
||||
#undef ELEMENT_NUMBERS_ENUMERATE
|
||||
|
||||
std::vector<Element> const &GetElements();
|
||||
std::array<Element, PT_NUM> const &GetElements();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "Particle.h"
|
||||
#include "ElementGraphics.h"
|
||||
#include "Simulation.h"
|
||||
#include "SimulationData.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "graphics/Renderer.h"
|
||||
|
||||
#include "Simulation.h"
|
||||
#include "SimulationData.h"
|
||||
|
||||
SaveRenderer::SaveRenderer(){
|
||||
sim = new Simulation();
|
||||
@ -22,6 +23,9 @@ void SaveRenderer::Flush(int begin, int end)
|
||||
|
||||
std::pair<std::unique_ptr<VideoBuffer>, MissingElements> SaveRenderer::Render(const GameSave *save, bool decorations, bool fire, Renderer *renderModeSource)
|
||||
{
|
||||
// this function usually runs on a thread different from where element info in SimulationData may be written, so we acquire a read-only lock on it
|
||||
auto &sd = SimulationData::CRef();
|
||||
std::shared_lock lk(sd.elementGraphicsMx);
|
||||
std::lock_guard<std::mutex> gx(renderMutex);
|
||||
|
||||
ren->ResetModes();
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include "Sign.h"
|
||||
|
||||
#include "graphics/Graphics.h"
|
||||
#include "simulation/Simulation.h"
|
||||
#include "Simulation.h"
|
||||
#include "SimulationData.h"
|
||||
|
||||
sign::sign(String text_, int x_, int y_, Justification justification_):
|
||||
x(x_),
|
||||
@ -13,6 +14,7 @@ sign::sign(String text_, int x_, int y_, Justification justification_):
|
||||
|
||||
String sign::getDisplayText(Simulation *sim, int &x0, int &y0, int &w, int &h, bool colorize, bool *v95) const
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
String drawable_text;
|
||||
auto si = std::make_pair(0, Type::Normal);
|
||||
if (text.find('{') == text.npos)
|
||||
@ -79,13 +81,13 @@ String sign::getDisplayText(Simulation *sim, int &x0, int &y0, int &w, int &h, b
|
||||
}
|
||||
else if (between_curlies == "type")
|
||||
{
|
||||
formatted_text << (part ? sim->BasicParticleInfo(*part) : (formatted_text.Size() ? String::Build("empty") : String::Build("Empty")));
|
||||
formatted_text << (part ? sd.BasicParticleInfo(*part) : (formatted_text.Size() ? String::Build("empty") : String::Build("Empty")));
|
||||
if (v95)
|
||||
*v95 = true;
|
||||
}
|
||||
else if (between_curlies == "ctype")
|
||||
{
|
||||
formatted_text << (part ? (sim->IsElementOrNone(part->ctype) ? sim->ElementResolve(part->ctype, -1) : String::Build(part->ctype)) : (formatted_text.Size() ? String::Build("empty") : String::Build("Empty")));
|
||||
formatted_text << (part ? (sd.IsElementOrNone(part->ctype) ? sd.ElementResolve(part->ctype, -1) : String::Build(part->ctype)) : (formatted_text.Size() ? String::Build("empty") : String::Build("Empty")));
|
||||
if (v95)
|
||||
*v95 = true;
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "gravity/Gravity.h"
|
||||
#include "ToolClasses.h"
|
||||
#include "SimulationData.h"
|
||||
#include "GOLString.h"
|
||||
#include "client/GameSave.h"
|
||||
#include "common/tpt-compat.h"
|
||||
#include "common/tpt-rand.h"
|
||||
@ -30,6 +29,9 @@ MissingElements Simulation::Load(const GameSave *save, bool includePressure, Vec
|
||||
{
|
||||
partMap[i] = i;
|
||||
}
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if(save->palette.size())
|
||||
{
|
||||
for(int i = 0; i < PT_NUM; i++)
|
||||
@ -359,6 +361,9 @@ std::unique_ptr<GameSave> Simulation::Save(bool includePressure, Rect<int> partR
|
||||
// Now stores all particles, not just SOAP (but still only used for soap)
|
||||
std::map<unsigned int, unsigned int> particleMap;
|
||||
std::set<int> paletteSet;
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (int i = 0; i < NPART; i++)
|
||||
{
|
||||
int x, y;
|
||||
@ -493,8 +498,10 @@ void Simulation::SaveSimOptions(GameSave &gameSave)
|
||||
gameSave.aheatEnable = aheat_enable;
|
||||
}
|
||||
|
||||
bool Simulation::FloodFillPmapCheck(int x, int y, int type)
|
||||
bool Simulation::FloodFillPmapCheck(int x, int y, int type) const
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (type == 0)
|
||||
return !pmap[y][x] && !photons[y][x];
|
||||
if (elements[type].Properties&TYPE_ENERGY)
|
||||
@ -711,6 +718,8 @@ bool Simulation::flood_water(int x, int y, int i)
|
||||
char *bitmap = bitmapPtr.get();
|
||||
std::fill(&bitmap[0], &bitmap[0] + XRES * YRES, 0);
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
try
|
||||
{
|
||||
CoordStack& cs = getCoordStackSingleton();
|
||||
@ -1101,6 +1110,8 @@ void Simulation::clear_sim(void)
|
||||
|
||||
bool Simulation::IsWallBlocking(int x, int y, int type) const
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (bmap[y/CELL][x/CELL])
|
||||
{
|
||||
int wall = bmap[y/CELL][x/CELL];
|
||||
@ -1122,145 +1133,6 @@ bool Simulation::IsWallBlocking(int x, int y, int type) const
|
||||
return false;
|
||||
}
|
||||
|
||||
void Simulation::init_can_move()
|
||||
{
|
||||
int movingType, destinationType;
|
||||
// can_move[moving type][type at destination]
|
||||
// 0 = No move/Bounce
|
||||
// 1 = Swap
|
||||
// 2 = Both particles occupy the same space.
|
||||
// 3 = Varies, go run some extra checks
|
||||
|
||||
//particles that don't exist shouldn't move...
|
||||
for (destinationType = 0; destinationType < PT_NUM; destinationType++)
|
||||
can_move[0][destinationType] = 0;
|
||||
|
||||
//initialize everything else to swapping by default
|
||||
for (movingType = 1; movingType < PT_NUM; movingType++)
|
||||
for (destinationType = 0; destinationType < PT_NUM; destinationType++)
|
||||
can_move[movingType][destinationType] = 1;
|
||||
|
||||
//photons go through everything by default
|
||||
for (destinationType = 1; destinationType < PT_NUM; destinationType++)
|
||||
can_move[PT_PHOT][destinationType] = 2;
|
||||
|
||||
for (movingType = 1; movingType < PT_NUM; movingType++)
|
||||
{
|
||||
for (destinationType = 1; destinationType < PT_NUM; destinationType++)
|
||||
{
|
||||
//weight check, also prevents particles of same type displacing each other
|
||||
if (elements[movingType].Weight <= elements[destinationType].Weight || destinationType == PT_GEL)
|
||||
can_move[movingType][destinationType] = 0;
|
||||
|
||||
//other checks for NEUT and energy particles
|
||||
if (movingType == PT_NEUT && (elements[destinationType].Properties&PROP_NEUTPASS))
|
||||
can_move[movingType][destinationType] = 2;
|
||||
if (movingType == PT_NEUT && (elements[destinationType].Properties&PROP_NEUTABSORB))
|
||||
can_move[movingType][destinationType] = 1;
|
||||
if (movingType == PT_NEUT && (elements[destinationType].Properties&PROP_NEUTPENETRATE))
|
||||
can_move[movingType][destinationType] = 1;
|
||||
if (destinationType == PT_NEUT && (elements[movingType].Properties&PROP_NEUTPENETRATE))
|
||||
can_move[movingType][destinationType] = 0;
|
||||
if ((elements[movingType].Properties&TYPE_ENERGY) && (elements[destinationType].Properties&TYPE_ENERGY))
|
||||
can_move[movingType][destinationType] = 2;
|
||||
}
|
||||
}
|
||||
for (destinationType = 0; destinationType < PT_NUM; destinationType++)
|
||||
{
|
||||
//set what stickmen can move through
|
||||
int stkm_move = 0;
|
||||
if (elements[destinationType].Properties & (TYPE_LIQUID | TYPE_GAS))
|
||||
stkm_move = 2;
|
||||
if (!destinationType || destinationType == PT_PRTO || destinationType == PT_SPAWN || destinationType == PT_SPAWN2)
|
||||
stkm_move = 2;
|
||||
can_move[PT_STKM][destinationType] = stkm_move;
|
||||
can_move[PT_STKM2][destinationType] = stkm_move;
|
||||
can_move[PT_FIGH][destinationType] = stkm_move;
|
||||
|
||||
//spark shouldn't move
|
||||
can_move[PT_SPRK][destinationType] = 0;
|
||||
}
|
||||
for (movingType = 1; movingType < PT_NUM; movingType++)
|
||||
{
|
||||
//everything "swaps" with VACU and BHOL to make them eat things
|
||||
can_move[movingType][PT_BHOL] = 1;
|
||||
can_move[movingType][PT_NBHL] = 1;
|
||||
//nothing goes through stickmen
|
||||
can_move[movingType][PT_STKM] = 0;
|
||||
can_move[movingType][PT_STKM2] = 0;
|
||||
can_move[movingType][PT_FIGH] = 0;
|
||||
//INVS behaviour varies with pressure
|
||||
can_move[movingType][PT_INVIS] = 3;
|
||||
//stop CNCT from being displaced by other particles
|
||||
can_move[movingType][PT_CNCT] = 0;
|
||||
//VOID and PVOD behaviour varies with powered state and ctype
|
||||
can_move[movingType][PT_PVOD] = 3;
|
||||
can_move[movingType][PT_VOID] = 3;
|
||||
//nothing moves through EMBR (not sure why, but it's killed when it touches anything)
|
||||
can_move[movingType][PT_EMBR] = 0;
|
||||
can_move[PT_EMBR][movingType] = 0;
|
||||
//Energy particles move through VIBR and BVBR, so it can absorb them
|
||||
if (elements[movingType].Properties & TYPE_ENERGY)
|
||||
{
|
||||
can_move[movingType][PT_VIBR] = 1;
|
||||
can_move[movingType][PT_BVBR] = 1;
|
||||
}
|
||||
|
||||
//SAWD cannot be displaced by other powders
|
||||
if (elements[movingType].Properties & TYPE_PART)
|
||||
can_move[movingType][PT_SAWD] = 0;
|
||||
}
|
||||
//a list of lots of things PHOT can move through
|
||||
// TODO: replace with property
|
||||
for (destinationType = 0; destinationType < PT_NUM; destinationType++)
|
||||
{
|
||||
if (destinationType == PT_GLAS || destinationType == PT_PHOT || destinationType == PT_FILT || destinationType == PT_INVIS
|
||||
|| destinationType == PT_CLNE || destinationType == PT_PCLN || destinationType == PT_BCLN || destinationType == PT_PBCN
|
||||
|| destinationType == PT_WATR || destinationType == PT_DSTW || destinationType == PT_SLTW || destinationType == PT_GLOW
|
||||
|| destinationType == PT_ISOZ || destinationType == PT_ISZS || destinationType == PT_QRTZ || destinationType == PT_PQRT
|
||||
|| destinationType == PT_H2 || destinationType == PT_BGLA || destinationType == PT_C5)
|
||||
can_move[PT_PHOT][destinationType] = 2;
|
||||
if (destinationType != PT_DMND && destinationType != PT_INSL && destinationType != PT_VOID && destinationType != PT_PVOD && destinationType != PT_VIBR && destinationType != PT_BVBR && destinationType != PT_PRTI && destinationType != PT_PRTO)
|
||||
{
|
||||
can_move[PT_PROT][destinationType] = 2;
|
||||
can_move[PT_GRVT][destinationType] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//other special cases that weren't covered above
|
||||
can_move[PT_DEST][PT_DMND] = 0;
|
||||
can_move[PT_DEST][PT_CLNE] = 0;
|
||||
can_move[PT_DEST][PT_PCLN] = 0;
|
||||
can_move[PT_DEST][PT_BCLN] = 0;
|
||||
can_move[PT_DEST][PT_PBCN] = 0;
|
||||
can_move[PT_DEST][PT_ROCK] = 0;
|
||||
|
||||
can_move[PT_NEUT][PT_INVIS] = 2;
|
||||
can_move[PT_ELEC][PT_LCRY] = 2;
|
||||
can_move[PT_ELEC][PT_EXOT] = 2;
|
||||
can_move[PT_ELEC][PT_GLOW] = 2;
|
||||
can_move[PT_PHOT][PT_LCRY] = 3; //varies according to LCRY life
|
||||
can_move[PT_PHOT][PT_GPMP] = 3;
|
||||
|
||||
can_move[PT_PHOT][PT_BIZR] = 2;
|
||||
can_move[PT_ELEC][PT_BIZR] = 2;
|
||||
can_move[PT_PHOT][PT_BIZRG] = 2;
|
||||
can_move[PT_ELEC][PT_BIZRG] = 2;
|
||||
can_move[PT_PHOT][PT_BIZRS] = 2;
|
||||
can_move[PT_ELEC][PT_BIZRS] = 2;
|
||||
can_move[PT_BIZR][PT_FILT] = 2;
|
||||
can_move[PT_BIZRG][PT_FILT] = 2;
|
||||
|
||||
can_move[PT_ANAR][PT_WHOL] = 1; //WHOL eats ANAR
|
||||
can_move[PT_ANAR][PT_NWHL] = 1;
|
||||
can_move[PT_ELEC][PT_DEUT] = 1;
|
||||
can_move[PT_THDR][PT_THDR] = 2;
|
||||
can_move[PT_EMBR][PT_EMBR] = 2;
|
||||
can_move[PT_TRON][PT_SWCH] = 3;
|
||||
can_move[PT_SOAP][PT_OIL] = 0;
|
||||
can_move[PT_OIL][PT_SOAP] = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
RETURN-value explanation
|
||||
1 = Swap
|
||||
@ -1282,6 +1154,9 @@ int Simulation::eval_move(int pt, int nx, int ny, unsigned *rr) const
|
||||
*rr = r;
|
||||
if (pt>=PT_NUM || TYP(r)>=PT_NUM)
|
||||
return 0;
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &can_move = sd.can_move;
|
||||
auto &elements = sd.elements;
|
||||
result = can_move[pt][TYP(r)];
|
||||
if (result == 3)
|
||||
{
|
||||
@ -1365,6 +1240,8 @@ int Simulation::try_move(int i, int x, int y, int nx, int ny)
|
||||
if (!e && parts[i].type==PT_PHOT && ((TYP(r)==PT_BMTL && rng.chance(1, 2)) || TYP(pmap[y][x])==PT_BMTL))
|
||||
e = 2;
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (!e) //if no movement
|
||||
{
|
||||
int rt = TYP(r);
|
||||
@ -1700,6 +1577,8 @@ int Simulation::do_move(int i, int x, int y, float nxf, float nyf)
|
||||
|
||||
bool Simulation::move(int i, int x, int y, float nxf, float nyf)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int nx = (int)(nxf+0.5f), ny = (int)(nyf+0.5f);
|
||||
int t = parts[i].type;
|
||||
parts[i].x = nxf;
|
||||
@ -1883,6 +1762,8 @@ void Simulation::kill_part(int i)//kills particle number i
|
||||
int x = (int)(parts[i].x + 0.5f);
|
||||
int y = (int)(parts[i].y + 0.5f);
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int t = parts[i].type;
|
||||
if (t && elements[t].ChangeType)
|
||||
{
|
||||
@ -1914,6 +1795,9 @@ bool Simulation::part_change_type(int i, int x, int y, int t)
|
||||
{
|
||||
if (x<0 || y<0 || x>=XRES || y>=YRES || i>=NPART || t<0 || t>=PT_NUM || !parts[i].type)
|
||||
return false;
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (!elements[t].Enabled || t == PT_NONE)
|
||||
{
|
||||
kill_part(i);
|
||||
@ -1956,6 +1840,8 @@ int Simulation::create_part(int p, int x, int y, int t, int v)
|
||||
{
|
||||
int i, oldType = PT_NONE;
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (x<0 || y<0 || x>=XRES || y>=YRES || t<=0 || t>=PT_NUM || !elements[t].Enabled)
|
||||
return -1;
|
||||
|
||||
@ -2238,6 +2124,8 @@ void Simulation::delete_part(int x, int y)//calls kill_part with the particle lo
|
||||
|
||||
Simulation::PlanMoveResult Simulation::PlanMove(int i, int x, int y, bool update_emap)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &can_move = sd.can_move;
|
||||
// This function would be const if not for calling set_emap if update_emap is true,
|
||||
// and users of this function *expect* it to be const if update_emap is false. So
|
||||
// whenever you change something here, make sure it compiles *as const* if you
|
||||
@ -2348,6 +2236,8 @@ Simulation::PlanMoveResult Simulation::PlanMove(int i, int x, int y, bool update
|
||||
void Simulation::UpdateParticles(int start, int end)
|
||||
{
|
||||
//the main particle loop function, goes over all particles.
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (auto i = start; i < end && i <= parts_lastActiveIndex; i++)
|
||||
{
|
||||
if (parts[i].type)
|
||||
@ -2585,16 +2475,16 @@ void Simulation::UpdateParticles(int start, int end)
|
||||
auto ctemph = pt;
|
||||
auto ctempl = pt;
|
||||
// change boiling point with pressure
|
||||
if (((elements[t].Properties&TYPE_LIQUID) && IsElementOrNone(elements[t].HighTemperatureTransition) && (elements[elements[t].HighTemperatureTransition].Properties&TYPE_GAS))
|
||||
if (((elements[t].Properties&TYPE_LIQUID) && sd.IsElementOrNone(elements[t].HighTemperatureTransition) && (elements[elements[t].HighTemperatureTransition].Properties&TYPE_GAS))
|
||||
|| t==PT_LNTG || t==PT_SLTW)
|
||||
ctemph -= 2.0f*pv[y/CELL][x/CELL];
|
||||
else if (((elements[t].Properties&TYPE_GAS) && IsElementOrNone(elements[t].LowTemperatureTransition) && (elements[elements[t].LowTemperatureTransition].Properties&TYPE_LIQUID))
|
||||
else if (((elements[t].Properties&TYPE_GAS) && sd.IsElementOrNone(elements[t].LowTemperatureTransition) && (elements[elements[t].LowTemperatureTransition].Properties&TYPE_LIQUID))
|
||||
|| t==PT_WTRV)
|
||||
ctempl -= 2.0f*pv[y/CELL][x/CELL];
|
||||
auto s = 1;
|
||||
|
||||
//A fix for ice with ctype = 0
|
||||
if ((t==PT_ICEI || t==PT_SNOW) && (!IsElement(parts[i].ctype) || parts[i].ctype==PT_ICEI || parts[i].ctype==PT_SNOW))
|
||||
if ((t==PT_ICEI || t==PT_SNOW) && (!sd.IsElement(parts[i].ctype) || parts[i].ctype==PT_ICEI || parts[i].ctype==PT_SNOW))
|
||||
parts[i].ctype = PT_WATR;
|
||||
|
||||
if (elements[t].HighTemperatureTransition>-1 && ctemph>=elements[t].HighTemperature)
|
||||
@ -3470,6 +3360,8 @@ void Simulation::RecalcFreeParticles(bool do_life_dec)
|
||||
memset(photons, 0, sizeof(photons));
|
||||
|
||||
NUM_PARTS = 0;
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
//the particle loop that resets the pmap/photon maps every frame, to update them.
|
||||
for (int i = 0; i <= parts_lastActiveIndex; i++)
|
||||
{
|
||||
@ -3552,6 +3444,7 @@ void Simulation::RecalcFreeParticles(bool do_life_dec)
|
||||
|
||||
void Simulation::SimulateGoL()
|
||||
{
|
||||
auto &builtinGol = SimulationData::builtinGol;
|
||||
CGOL = 0;
|
||||
for (int i = 0; i <= parts_lastActiveIndex; ++i)
|
||||
{
|
||||
@ -3728,6 +3621,8 @@ void Simulation::SimulateGoL()
|
||||
|
||||
void Simulation::CheckStacking()
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
bool excessive_stacking_found = false;
|
||||
force_stacking_check = false;
|
||||
for (int y = 0; y < YRES; y++)
|
||||
@ -3997,10 +3892,7 @@ void Simulation::AfterSim()
|
||||
frameCount += 1;
|
||||
}
|
||||
|
||||
Simulation::~Simulation()
|
||||
{
|
||||
delete air;
|
||||
}
|
||||
Simulation::~Simulation() = default;
|
||||
|
||||
Simulation::Simulation():
|
||||
replaceModeSelected(0),
|
||||
@ -4050,7 +3942,7 @@ Simulation::Simulation():
|
||||
gravmap = &grav->gravmap[0];
|
||||
|
||||
//Create and attach air simulation
|
||||
air = new Air(*this);
|
||||
air = std::make_unique<Air>(*this);
|
||||
//Give air sim references to our data
|
||||
air->bmap = bmap;
|
||||
air->emap = emap;
|
||||
@ -4062,88 +3954,14 @@ Simulation::Simulation():
|
||||
pv = air->pv;
|
||||
hv = air->hv;
|
||||
|
||||
msections = LoadMenus();
|
||||
wtypes = LoadWalls();
|
||||
platent = LoadLatent();
|
||||
std::copy(GetElements().begin(), GetElements().end(), elements.begin());
|
||||
tools = GetTools();
|
||||
|
||||
player.comm = 0;
|
||||
player2.comm = 0;
|
||||
|
||||
init_can_move();
|
||||
clear_sim();
|
||||
|
||||
grav->gravity_mask();
|
||||
}
|
||||
|
||||
const Simulation::CustomGOLData *Simulation::GetCustomGOLByRule(int rule) const
|
||||
{
|
||||
// * Binary search. customGol is already sorted, see SetCustomGOL.
|
||||
auto it = std::lower_bound(customGol.begin(), customGol.end(), rule, [](const CustomGOLData &item, int rule) {
|
||||
return item.rule < rule;
|
||||
});
|
||||
if (it != customGol.end() && !(rule < it->rule))
|
||||
{
|
||||
return &*it;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Simulation::SetCustomGOL(std::vector<CustomGOLData> newCustomGol)
|
||||
{
|
||||
std::sort(newCustomGol.begin(), newCustomGol.end());
|
||||
customGol = newCustomGol;
|
||||
}
|
||||
|
||||
String Simulation::ElementResolve(int type, int ctype) const
|
||||
{
|
||||
if (type == PT_LIFE)
|
||||
{
|
||||
if (ctype >= 0 && ctype < NGOL)
|
||||
{
|
||||
return builtinGol[ctype].name;
|
||||
}
|
||||
auto *cgol = GetCustomGOLByRule(ctype);
|
||||
if (cgol)
|
||||
{
|
||||
return cgol->nameString;
|
||||
}
|
||||
return SerialiseGOLRule(ctype);
|
||||
}
|
||||
else if (type >= 0 && type < PT_NUM)
|
||||
return elements[type].Name;
|
||||
return "Empty";
|
||||
}
|
||||
|
||||
String Simulation::BasicParticleInfo(Particle const &sample_part) const
|
||||
{
|
||||
StringBuilder sampleInfo;
|
||||
int type = sample_part.type;
|
||||
int ctype = sample_part.ctype;
|
||||
int storedCtype = sample_part.tmp4;
|
||||
if (type == PT_LAVA && IsElement(ctype))
|
||||
{
|
||||
sampleInfo << "Molten " << ElementResolve(ctype, -1);
|
||||
}
|
||||
else if ((type == PT_PIPE || type == PT_PPIP) && IsElement(ctype))
|
||||
{
|
||||
if (ctype == PT_LAVA && IsElement(storedCtype))
|
||||
{
|
||||
sampleInfo << ElementResolve(type, -1) << " with molten " << ElementResolve(storedCtype, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sampleInfo << ElementResolve(type, -1) << " with " << ElementResolve(ctype, storedCtype);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sampleInfo << ElementResolve(type, ctype);
|
||||
}
|
||||
return sampleInfo.Build();
|
||||
}
|
||||
|
||||
int Simulation::remainder_p(int x, int y)
|
||||
{
|
||||
return (x % y) + (x>=0 ? 0 : y);
|
||||
|
@ -22,7 +22,6 @@
|
||||
constexpr int CHANNELS = int(MAX_TEMP - 73) / 100 + 2;
|
||||
|
||||
class Snapshot;
|
||||
class SimTool;
|
||||
class Brush;
|
||||
class SimulationSample;
|
||||
struct matrix2d;
|
||||
@ -37,24 +36,17 @@ class GameSave;
|
||||
class Simulation
|
||||
{
|
||||
public:
|
||||
|
||||
GravityPtr grav;
|
||||
Air * air;
|
||||
std::unique_ptr<Air> air;
|
||||
RNG rng;
|
||||
|
||||
std::vector<sign> signs;
|
||||
std::array<Element, PT_NUM> elements;
|
||||
//Element * elements;
|
||||
std::vector<SimTool> tools;
|
||||
std::vector<unsigned int> platent;
|
||||
std::vector<wall_type> wtypes;
|
||||
std::vector<menu_section> msections;
|
||||
|
||||
int currentTick;
|
||||
int replaceModeSelected;
|
||||
int replaceModeFlags;
|
||||
|
||||
char can_move[PT_NUM][PT_NUM];
|
||||
int debug_nextToUpdate;
|
||||
int debug_mostRecentlyUpdated = -1; // -1 when between full update loops
|
||||
int parts_lastActiveIndex;
|
||||
@ -127,7 +119,7 @@ public:
|
||||
void SaveSimOptions(GameSave &gameSave);
|
||||
SimulationSample GetSample(int x, int y);
|
||||
|
||||
std::unique_ptr<Snapshot> CreateSnapshot();
|
||||
std::unique_ptr<Snapshot> CreateSnapshot() const;
|
||||
void Restore(const Snapshot &snap);
|
||||
|
||||
int is_blocking(int t, int x, int y);
|
||||
@ -145,18 +137,11 @@ public:
|
||||
float vx, vy;
|
||||
};
|
||||
PlanMoveResult PlanMove(int i, int x, int y, bool update_emap);
|
||||
void init_can_move();
|
||||
bool IsWallBlocking(int x, int y, int type) const;
|
||||
bool IsElement(int type) const {
|
||||
return (type > 0 && type < PT_NUM && elements[type].Enabled);
|
||||
}
|
||||
bool IsElementOrNone(int type) const {
|
||||
return (type >= 0 && type < PT_NUM && elements[type].Enabled);
|
||||
}
|
||||
void create_cherenkov_photon(int pp);
|
||||
void create_gain_photon(int pp);
|
||||
void kill_part(int i);
|
||||
bool FloodFillPmapCheck(int x, int y, int type);
|
||||
bool FloodFillPmapCheck(int x, int y, int type) const;
|
||||
int flood_prop(int x, int y, StructProperty prop, PropertyValue propvalue);
|
||||
bool flood_water(int x, int y, int i);
|
||||
int FloodINST(int x, int y);
|
||||
@ -177,7 +162,6 @@ public:
|
||||
void CheckStacking();
|
||||
void BeforeSim();
|
||||
void AfterSim();
|
||||
void rotate_area(int area_x, int area_y, int area_w, int area_h, int invert);
|
||||
void clear_area(int area_x, int area_y, int area_w, int area_h);
|
||||
|
||||
void SetEdgeMode(int newEdgeMode);
|
||||
@ -212,11 +196,8 @@ public:
|
||||
void CreateBox(int x1, int y1, int x2, int y2, int c, int flags = -1);
|
||||
int FloodParts(int x, int y, int c, int cm, int flags = -1);
|
||||
|
||||
|
||||
void GetGravityField(int x, int y, float particleGrav, float newtonGrav, float & pGravX, float & pGravY);
|
||||
|
||||
int GetParticleType(ByteString type);
|
||||
|
||||
void orbitalparts_get(int block1, int block2, int resblock1[], int resblock2[]);
|
||||
void orbitalparts_set(int *block1, int *block2, int resblock1[], int resblock2[]);
|
||||
int get_wavelength_bin(int *wm);
|
||||
@ -236,29 +217,6 @@ public:
|
||||
static int remainder_p(int x, int y);
|
||||
static float remainder_p(float x, float y);
|
||||
|
||||
String ElementResolve(int type, int ctype) const;
|
||||
String BasicParticleInfo(Particle const &sample_part) const;
|
||||
|
||||
|
||||
struct CustomGOLData
|
||||
{
|
||||
int rule, colour1, colour2;
|
||||
String nameString, ruleString;
|
||||
|
||||
inline bool operator <(const CustomGOLData &other) const
|
||||
{
|
||||
return rule < other.rule;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<CustomGOLData> customGol;
|
||||
|
||||
public:
|
||||
const CustomGOLData *GetCustomGOLByRule(int rule) const;
|
||||
const std::vector<CustomGOLData> GetCustomGol() { return customGol; }
|
||||
void SetCustomGOL(std::vector<CustomGOLData> newCustomGol);
|
||||
|
||||
private:
|
||||
CoordStack& getCoordStackSingleton();
|
||||
};
|
||||
|
@ -1,16 +1,16 @@
|
||||
#include "SimulationData.h"
|
||||
|
||||
#include "ElementGraphics.h"
|
||||
#include "ElementDefs.h"
|
||||
#include "ElementClasses.h"
|
||||
|
||||
#include "GOLString.h"
|
||||
#include "BuiltinGOL.h"
|
||||
#include "WallType.h"
|
||||
#include "MenuSection.h"
|
||||
|
||||
#include "ToolClasses.h"
|
||||
#include "Misc.h"
|
||||
#include "graphics/Renderer.h"
|
||||
|
||||
const BuiltinGOL builtinGol[NGOL] = {
|
||||
const std::array<BuiltinGOL, NGOL> SimulationData::builtinGol = {{
|
||||
// * Ruleset:
|
||||
// * bits x = 8..0: stay if x neighbours present
|
||||
// * bits x = 16..9: begin if x-8 neighbours present
|
||||
@ -45,9 +45,9 @@ const BuiltinGOL builtinGol[NGOL] = {
|
||||
{ "STAR", GT_STAR, 0x98478, 0x000040_rgb, 0x0000E6_rgb, NGT_STAR, String("Like Star Wars rule: B278/S3456/6") },
|
||||
{ "FROG", GT_FROG, 0x21806, 0x006400_rgb, 0x00FF00_rgb, NGT_FROG, String("Frogs: B34/S12/3") },
|
||||
{ "BRAN", GT_BRAN, 0x25440, 0xFFFF00_rgb, 0x969600_rgb, NGT_BRAN, String("Brian 6: B246/S6/3" )}
|
||||
};
|
||||
}};
|
||||
|
||||
std::vector<wall_type> LoadWalls()
|
||||
static std::vector<wall_type> LoadWalls()
|
||||
{
|
||||
return
|
||||
std::vector<wall_type>{
|
||||
@ -73,7 +73,7 @@ std::vector<wall_type> LoadWalls()
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<menu_section> LoadMenus()
|
||||
static std::vector<menu_section> LoadMenus()
|
||||
{
|
||||
return
|
||||
std::vector<menu_section>{
|
||||
@ -98,7 +98,7 @@ std::vector<menu_section> LoadMenus()
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<unsigned int> LoadLatent()
|
||||
static std::vector<unsigned int> LoadLatent()
|
||||
{
|
||||
return
|
||||
std::vector<unsigned int>{
|
||||
@ -265,3 +265,246 @@ std::vector<unsigned int> LoadLatent()
|
||||
/* REPL */ 0,
|
||||
};
|
||||
}
|
||||
|
||||
void SimulationData::init_can_move()
|
||||
{
|
||||
int movingType, destinationType;
|
||||
// can_move[moving type][type at destination]
|
||||
// 0 = No move/Bounce
|
||||
// 1 = Swap
|
||||
// 2 = Both particles occupy the same space.
|
||||
// 3 = Varies, go run some extra checks
|
||||
|
||||
//particles that don't exist shouldn't move...
|
||||
for (destinationType = 0; destinationType < PT_NUM; destinationType++)
|
||||
can_move[0][destinationType] = 0;
|
||||
|
||||
//initialize everything else to swapping by default
|
||||
for (movingType = 1; movingType < PT_NUM; movingType++)
|
||||
for (destinationType = 0; destinationType < PT_NUM; destinationType++)
|
||||
can_move[movingType][destinationType] = 1;
|
||||
|
||||
//photons go through everything by default
|
||||
for (destinationType = 1; destinationType < PT_NUM; destinationType++)
|
||||
can_move[PT_PHOT][destinationType] = 2;
|
||||
|
||||
for (movingType = 1; movingType < PT_NUM; movingType++)
|
||||
{
|
||||
for (destinationType = 1; destinationType < PT_NUM; destinationType++)
|
||||
{
|
||||
//weight check, also prevents particles of same type displacing each other
|
||||
if (elements[movingType].Weight <= elements[destinationType].Weight || destinationType == PT_GEL)
|
||||
can_move[movingType][destinationType] = 0;
|
||||
|
||||
//other checks for NEUT and energy particles
|
||||
if (movingType == PT_NEUT && (elements[destinationType].Properties&PROP_NEUTPASS))
|
||||
can_move[movingType][destinationType] = 2;
|
||||
if (movingType == PT_NEUT && (elements[destinationType].Properties&PROP_NEUTABSORB))
|
||||
can_move[movingType][destinationType] = 1;
|
||||
if (movingType == PT_NEUT && (elements[destinationType].Properties&PROP_NEUTPENETRATE))
|
||||
can_move[movingType][destinationType] = 1;
|
||||
if (destinationType == PT_NEUT && (elements[movingType].Properties&PROP_NEUTPENETRATE))
|
||||
can_move[movingType][destinationType] = 0;
|
||||
if ((elements[movingType].Properties&TYPE_ENERGY) && (elements[destinationType].Properties&TYPE_ENERGY))
|
||||
can_move[movingType][destinationType] = 2;
|
||||
}
|
||||
}
|
||||
for (destinationType = 0; destinationType < PT_NUM; destinationType++)
|
||||
{
|
||||
//set what stickmen can move through
|
||||
int stkm_move = 0;
|
||||
if (elements[destinationType].Properties & (TYPE_LIQUID | TYPE_GAS))
|
||||
stkm_move = 2;
|
||||
if (!destinationType || destinationType == PT_PRTO || destinationType == PT_SPAWN || destinationType == PT_SPAWN2)
|
||||
stkm_move = 2;
|
||||
can_move[PT_STKM][destinationType] = stkm_move;
|
||||
can_move[PT_STKM2][destinationType] = stkm_move;
|
||||
can_move[PT_FIGH][destinationType] = stkm_move;
|
||||
|
||||
//spark shouldn't move
|
||||
can_move[PT_SPRK][destinationType] = 0;
|
||||
}
|
||||
for (movingType = 1; movingType < PT_NUM; movingType++)
|
||||
{
|
||||
//everything "swaps" with VACU and BHOL to make them eat things
|
||||
can_move[movingType][PT_BHOL] = 1;
|
||||
can_move[movingType][PT_NBHL] = 1;
|
||||
//nothing goes through stickmen
|
||||
can_move[movingType][PT_STKM] = 0;
|
||||
can_move[movingType][PT_STKM2] = 0;
|
||||
can_move[movingType][PT_FIGH] = 0;
|
||||
//INVS behaviour varies with pressure
|
||||
can_move[movingType][PT_INVIS] = 3;
|
||||
//stop CNCT from being displaced by other particles
|
||||
can_move[movingType][PT_CNCT] = 0;
|
||||
//VOID and PVOD behaviour varies with powered state and ctype
|
||||
can_move[movingType][PT_PVOD] = 3;
|
||||
can_move[movingType][PT_VOID] = 3;
|
||||
//nothing moves through EMBR (not sure why, but it's killed when it touches anything)
|
||||
can_move[movingType][PT_EMBR] = 0;
|
||||
can_move[PT_EMBR][movingType] = 0;
|
||||
//Energy particles move through VIBR and BVBR, so it can absorb them
|
||||
if (elements[movingType].Properties & TYPE_ENERGY)
|
||||
{
|
||||
can_move[movingType][PT_VIBR] = 1;
|
||||
can_move[movingType][PT_BVBR] = 1;
|
||||
}
|
||||
|
||||
//SAWD cannot be displaced by other powders
|
||||
if (elements[movingType].Properties & TYPE_PART)
|
||||
can_move[movingType][PT_SAWD] = 0;
|
||||
}
|
||||
//a list of lots of things PHOT can move through
|
||||
// TODO: replace with property
|
||||
for (destinationType = 0; destinationType < PT_NUM; destinationType++)
|
||||
{
|
||||
if (destinationType == PT_GLAS || destinationType == PT_PHOT || destinationType == PT_FILT || destinationType == PT_INVIS
|
||||
|| destinationType == PT_CLNE || destinationType == PT_PCLN || destinationType == PT_BCLN || destinationType == PT_PBCN
|
||||
|| destinationType == PT_WATR || destinationType == PT_DSTW || destinationType == PT_SLTW || destinationType == PT_GLOW
|
||||
|| destinationType == PT_ISOZ || destinationType == PT_ISZS || destinationType == PT_QRTZ || destinationType == PT_PQRT
|
||||
|| destinationType == PT_H2 || destinationType == PT_BGLA || destinationType == PT_C5)
|
||||
can_move[PT_PHOT][destinationType] = 2;
|
||||
if (destinationType != PT_DMND && destinationType != PT_INSL && destinationType != PT_VOID && destinationType != PT_PVOD && destinationType != PT_VIBR && destinationType != PT_BVBR && destinationType != PT_PRTI && destinationType != PT_PRTO)
|
||||
{
|
||||
can_move[PT_PROT][destinationType] = 2;
|
||||
can_move[PT_GRVT][destinationType] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//other special cases that weren't covered above
|
||||
can_move[PT_DEST][PT_DMND] = 0;
|
||||
can_move[PT_DEST][PT_CLNE] = 0;
|
||||
can_move[PT_DEST][PT_PCLN] = 0;
|
||||
can_move[PT_DEST][PT_BCLN] = 0;
|
||||
can_move[PT_DEST][PT_PBCN] = 0;
|
||||
can_move[PT_DEST][PT_ROCK] = 0;
|
||||
|
||||
can_move[PT_NEUT][PT_INVIS] = 2;
|
||||
can_move[PT_ELEC][PT_LCRY] = 2;
|
||||
can_move[PT_ELEC][PT_EXOT] = 2;
|
||||
can_move[PT_ELEC][PT_GLOW] = 2;
|
||||
can_move[PT_PHOT][PT_LCRY] = 3; //varies according to LCRY life
|
||||
can_move[PT_PHOT][PT_GPMP] = 3;
|
||||
|
||||
can_move[PT_PHOT][PT_BIZR] = 2;
|
||||
can_move[PT_ELEC][PT_BIZR] = 2;
|
||||
can_move[PT_PHOT][PT_BIZRG] = 2;
|
||||
can_move[PT_ELEC][PT_BIZRG] = 2;
|
||||
can_move[PT_PHOT][PT_BIZRS] = 2;
|
||||
can_move[PT_ELEC][PT_BIZRS] = 2;
|
||||
can_move[PT_BIZR][PT_FILT] = 2;
|
||||
can_move[PT_BIZRG][PT_FILT] = 2;
|
||||
|
||||
can_move[PT_ANAR][PT_WHOL] = 1; //WHOL eats ANAR
|
||||
can_move[PT_ANAR][PT_NWHL] = 1;
|
||||
can_move[PT_ELEC][PT_DEUT] = 1;
|
||||
can_move[PT_THDR][PT_THDR] = 2;
|
||||
can_move[PT_EMBR][PT_EMBR] = 2;
|
||||
can_move[PT_TRON][PT_SWCH] = 3;
|
||||
can_move[PT_SOAP][PT_OIL] = 0;
|
||||
can_move[PT_OIL][PT_SOAP] = 1;
|
||||
}
|
||||
|
||||
const CustomGOLData *SimulationData::GetCustomGOLByRule(int rule) const
|
||||
{
|
||||
// * Binary search. customGol is already sorted, see SetCustomGOL.
|
||||
auto it = std::lower_bound(customGol.begin(), customGol.end(), rule, [](const CustomGOLData &item, int rule) {
|
||||
return item.rule < rule;
|
||||
});
|
||||
if (it != customGol.end() && !(rule < it->rule))
|
||||
{
|
||||
return &*it;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SimulationData::SetCustomGOL(std::vector<CustomGOLData> newCustomGol)
|
||||
{
|
||||
std::sort(newCustomGol.begin(), newCustomGol.end());
|
||||
customGol = newCustomGol;
|
||||
}
|
||||
|
||||
String SimulationData::ElementResolve(int type, int ctype) const
|
||||
{
|
||||
if (type == PT_LIFE)
|
||||
{
|
||||
if (ctype >= 0 && ctype < NGOL)
|
||||
{
|
||||
return builtinGol[ctype].name;
|
||||
}
|
||||
auto *cgol = GetCustomGOLByRule(ctype);
|
||||
if (cgol)
|
||||
{
|
||||
return cgol->nameString;
|
||||
}
|
||||
return SerialiseGOLRule(ctype);
|
||||
}
|
||||
else if (type >= 0 && type < PT_NUM)
|
||||
return elements[type].Name;
|
||||
return "Empty";
|
||||
}
|
||||
|
||||
String SimulationData::BasicParticleInfo(Particle const &sample_part) const
|
||||
{
|
||||
StringBuilder sampleInfo;
|
||||
int type = sample_part.type;
|
||||
int ctype = sample_part.ctype;
|
||||
int storedCtype = sample_part.tmp4;
|
||||
if (type == PT_LAVA && IsElement(ctype))
|
||||
{
|
||||
sampleInfo << "Molten " << ElementResolve(ctype, -1);
|
||||
}
|
||||
else if ((type == PT_PIPE || type == PT_PPIP) && IsElement(ctype))
|
||||
{
|
||||
if (ctype == PT_LAVA && IsElement(storedCtype))
|
||||
{
|
||||
sampleInfo << ElementResolve(type, -1) << " with molten " << ElementResolve(storedCtype, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sampleInfo << ElementResolve(type, -1) << " with " << ElementResolve(ctype, storedCtype);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sampleInfo << ElementResolve(type, ctype);
|
||||
}
|
||||
return sampleInfo.Build();
|
||||
}
|
||||
|
||||
int SimulationData::GetParticleType(ByteString type) const
|
||||
{
|
||||
type = type.ToUpper();
|
||||
|
||||
// alternative names for some elements
|
||||
if (byteStringEqualsLiteral(type, "C4"))
|
||||
{
|
||||
return PT_PLEX;
|
||||
}
|
||||
else if (byteStringEqualsLiteral(type, "C5"))
|
||||
{
|
||||
return PT_C5;
|
||||
}
|
||||
else if (byteStringEqualsLiteral(type, "NONE"))
|
||||
{
|
||||
return PT_NONE;
|
||||
}
|
||||
for (int i = 1; i < PT_NUM; i++)
|
||||
{
|
||||
if (elements[i].Name.size() && elements[i].Enabled && type == elements[i].Name.ToUtf8().ToUpper())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
SimulationData::SimulationData()
|
||||
{
|
||||
init_can_move();
|
||||
msections = LoadMenus();
|
||||
wtypes = LoadWalls();
|
||||
platent = LoadLatent();
|
||||
elements = GetElements();
|
||||
tools = GetTools();
|
||||
}
|
||||
|
@ -1,8 +1,18 @@
|
||||
#pragma once
|
||||
#include "SimulationConfig.h"
|
||||
#include "ElementDefs.h"
|
||||
#include "common/ExplicitSingleton.h"
|
||||
#include "common/String.h"
|
||||
#include "MenuSection.h"
|
||||
#include "BuiltinGOL.h"
|
||||
#include "SimTool.h"
|
||||
#include "Element.h"
|
||||
#include "Particle.h"
|
||||
#include "WallType.h"
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <shared_mutex>
|
||||
|
||||
constexpr int SC_WALL = 0;
|
||||
constexpr int SC_ELEC = 1;
|
||||
@ -148,20 +158,61 @@ enum GravityMode
|
||||
GRAV_VERTICAL, GRAV_OFF, GRAV_RADIAL, GRAV_CUSTOM, NUM_GRAV_MODES
|
||||
};
|
||||
|
||||
struct part_type;
|
||||
struct part_transition;
|
||||
struct CustomGOLData
|
||||
{
|
||||
int rule, colour1, colour2;
|
||||
String nameString, ruleString;
|
||||
|
||||
struct wall_type;
|
||||
struct BuiltinGOL;
|
||||
struct menu_section;
|
||||
inline bool operator <(const CustomGOLData &other) const
|
||||
{
|
||||
return rule < other.rule;
|
||||
}
|
||||
};
|
||||
|
||||
class SimTool;
|
||||
class Element;
|
||||
class SimulationData : public ExplicitSingleton<SimulationData>
|
||||
{
|
||||
public:
|
||||
std::array<Element, PT_NUM> elements;
|
||||
std::vector<SimTool> tools;
|
||||
std::vector<unsigned int> platent;
|
||||
std::vector<wall_type> wtypes;
|
||||
std::vector<menu_section> msections;
|
||||
char can_move[PT_NUM][PT_NUM];
|
||||
static const std::array<BuiltinGOL, NGOL> builtinGol;
|
||||
|
||||
extern const BuiltinGOL builtinGol[];
|
||||
// Element properties that enable basic graphics (i.e. every property that has to do with graphics other than
|
||||
// the graphics callback itself) are only ever written by the main thread, but they are read by some other
|
||||
// threads that use Renderer to render thumbnails and such. Take this std::shared_mutex with an std::unique_lock
|
||||
// when writing such properties in the main thread, and with an std::shared_lock when reading such properties
|
||||
// in these secondary Renderer threads. Don't take it with an std::shared_lock when reading such properties in
|
||||
// the main thread; the main thread doesn't race with itself.
|
||||
mutable std::shared_mutex elementGraphicsMx;
|
||||
|
||||
std::vector<wall_type> LoadWalls();
|
||||
private:
|
||||
std::vector<CustomGOLData> customGol;
|
||||
|
||||
std::vector<menu_section> LoadMenus();
|
||||
public:
|
||||
SimulationData();
|
||||
void InitElements();
|
||||
|
||||
std::vector<unsigned int> LoadLatent();
|
||||
void init_can_move();
|
||||
|
||||
const CustomGOLData *GetCustomGOLByRule(int rule) const;
|
||||
const std::vector<CustomGOLData> &GetCustomGol() const { return customGol; }
|
||||
void SetCustomGOL(std::vector<CustomGOLData> newCustomGol);
|
||||
|
||||
String ElementResolve(int type, int ctype) const;
|
||||
String BasicParticleInfo(Particle const &sample_part) const;
|
||||
int GetParticleType(ByteString type) const;
|
||||
|
||||
bool IsElement(int type) const
|
||||
{
|
||||
return (type > 0 && type < PT_NUM && elements[type].Enabled);
|
||||
}
|
||||
|
||||
bool IsElementOrNone(int type) const
|
||||
{
|
||||
return (type >= 0 && type < PT_NUM && elements[type].Enabled);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -49,6 +49,8 @@ void Element::Element_ACEL()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
float multiplier;
|
||||
if (parts[i].life!=0)
|
||||
{
|
||||
@ -71,7 +73,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
r = sim->photons[y+ry][x+rx];
|
||||
if (!r)
|
||||
continue;
|
||||
if(sim->elements[TYP(r)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY))
|
||||
if(elements[TYP(r)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY))
|
||||
{
|
||||
parts[ID(r)].vx *= multiplier;
|
||||
parts[ID(r)].vy *= multiplier;
|
||||
|
@ -52,6 +52,8 @@ void Element::Element_ACID()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
{
|
||||
for (auto ry = -2; ry <= 2; ry++)
|
||||
@ -80,11 +82,11 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
sim->kill_part(ID(r));
|
||||
}
|
||||
}
|
||||
else if (rt != PT_CLNE && rt != PT_PCLN && parts[i].life >= 50 && sim->rng.chance(sim->elements[rt].Hardness, 1000))
|
||||
else if (rt != PT_CLNE && rt != PT_PCLN && parts[i].life >= 50 && sim->rng.chance(elements[rt].Hardness, 1000))
|
||||
{
|
||||
if (sim->parts_avg(i, ID(r),PT_GLAS)!= PT_GLAS)//GLAS protects stuff from acid
|
||||
{
|
||||
float newtemp = ((60.0f-(float)sim->elements[rt].Hardness))*7.0f;
|
||||
float newtemp = ((60.0f-(float)elements[rt].Hardness))*7.0f;
|
||||
if(newtemp < 0){
|
||||
newtemp = 0;
|
||||
}
|
||||
|
@ -47,6 +47,8 @@ void Element::Element_ARAY()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int short_bray_life = parts[i].life > 0 ? parts[i].life : 30;
|
||||
int long_bray_life = parts[i].life > 0 ? parts[i].life : 1020;
|
||||
for (int rx = -1; rx <= 1; rx++)
|
||||
@ -170,7 +172,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
if (nyy!=0 || nxx!=0)
|
||||
sim->create_part(-1, x+nxi+nxx, y+nyi+nyy, PT_SPRK);
|
||||
|
||||
if (!(nostop && parts[r].type==PT_SPRK && parts[r].ctype >= 0 && parts[r].ctype < PT_NUM && (sim->elements[parts[r].ctype].Properties&PROP_CONDUCTS)))
|
||||
if (!(nostop && parts[r].type==PT_SPRK && parts[r].ctype >= 0 && parts[r].ctype < PT_NUM && (elements[parts[r].ctype].Properties&PROP_CONDUCTS)))
|
||||
docontinue = 0;
|
||||
else
|
||||
docontinue = 1;
|
||||
|
@ -51,6 +51,8 @@ constexpr float ADVECTION = 0.1f;
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (!parts[i].life && sim->pv[y/CELL][x/CELL]>4.0f)
|
||||
parts[i].life = sim->rng.between(80, 119);
|
||||
if (parts[i].life)
|
||||
@ -58,7 +60,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
parts[i].vx += ADVECTION*sim->vx[y/CELL][x/CELL];
|
||||
parts[i].vy += ADVECTION*sim->vy[y/CELL][x/CELL];
|
||||
}
|
||||
if (parts[i].ctype<=0 || parts[i].ctype>=PT_NUM || !sim->elements[parts[i].ctype].Enabled)
|
||||
if (parts[i].ctype<=0 || parts[i].ctype>=PT_NUM || !elements[parts[i].ctype].Enabled)
|
||||
{
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
{
|
||||
@ -90,7 +92,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
int np = sim->create_part(-1, x + sim->rng.between(-1, 1), y + sim->rng.between(-1, 1), TYP(parts[i].ctype));
|
||||
if (np>=0)
|
||||
{
|
||||
if (parts[i].ctype==PT_LAVA && parts[i].tmp>0 && parts[i].tmp<PT_NUM && sim->elements[parts[i].tmp].HighTemperatureTransition==PT_LAVA)
|
||||
if (parts[i].ctype==PT_LAVA && parts[i].tmp>0 && parts[i].tmp<PT_NUM && elements[parts[i].tmp].HighTemperatureTransition==PT_LAVA)
|
||||
parts[np].ctype = parts[i].tmp;
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,8 @@ void Element::Element_BTRY()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
{
|
||||
for (auto ry = -2; ry <= 2; ry++)
|
||||
@ -59,7 +61,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
auto rt = TYP(r);
|
||||
if (sim->parts_avg(i,ID(r),PT_INSL) != PT_INSL)
|
||||
{
|
||||
if ((sim->elements[rt].Properties&PROP_CONDUCTS) && !(rt==PT_WATR||rt==PT_SLTW||rt==PT_NTCT||rt==PT_PTCT||rt==PT_INWR) && parts[ID(r)].life==0)
|
||||
if ((elements[rt].Properties&PROP_CONDUCTS) && !(rt==PT_WATR||rt==PT_SLTW||rt==PT_NTCT||rt==PT_PTCT||rt==PT_INWR) && parts[ID(r)].life==0)
|
||||
{
|
||||
parts[ID(r)].life = 4;
|
||||
parts[ID(r)].ctype = rt;
|
||||
|
@ -49,6 +49,8 @@ void Element::Element_C5()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
{
|
||||
for (auto ry = -2; ry <= 2; ry++)
|
||||
@ -58,7 +60,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
auto r = pmap[y+ry][x+rx];
|
||||
if (!r)
|
||||
continue;
|
||||
if ((TYP(r)!=PT_C5 && parts[ID(r)].temp<100 && sim->elements[TYP(r)].HeatConduct && (TYP(r)!=PT_HSWC||parts[ID(r)].life==10)) || TYP(r)==PT_CFLM)
|
||||
if ((TYP(r)!=PT_C5 && parts[ID(r)].temp<100 && elements[TYP(r)].HeatConduct && (TYP(r)!=PT_HSWC||parts[ID(r)].life==10)) || TYP(r)==PT_CFLM)
|
||||
{
|
||||
if (sim->rng.chance(1, 6))
|
||||
{
|
||||
|
@ -49,6 +49,8 @@ void Element::Element_CAUS()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (int rx = -2; rx <= 2; rx++)
|
||||
{
|
||||
for (int ry = -2; ry <= 2; ry++)
|
||||
@ -68,12 +70,12 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
}
|
||||
else if (TYP(r) != PT_ACID && TYP(r) != PT_CAUS && TYP(r) != PT_RFRG && TYP(r) != PT_RFGL)
|
||||
{
|
||||
if ((TYP(r) != PT_CLNE && TYP(r) != PT_PCLN && sim->rng.chance(sim->elements[TYP(r)].Hardness, 1000)) && parts[i].life >= 50)
|
||||
if ((TYP(r) != PT_CLNE && TYP(r) != PT_PCLN && sim->rng.chance(elements[TYP(r)].Hardness, 1000)) && parts[i].life >= 50)
|
||||
{
|
||||
// GLAS protects stuff from acid
|
||||
if (sim->parts_avg(i, ID(r),PT_GLAS) != PT_GLAS)
|
||||
{
|
||||
float newtemp = ((60.0f - (float)sim->elements[TYP(r)].Hardness)) * 7.0f;
|
||||
float newtemp = ((60.0f - (float)elements[TYP(r)].Hardness)) * 7.0f;
|
||||
if (newtemp < 0)
|
||||
newtemp = 0;
|
||||
parts[i].temp += newtemp;
|
||||
|
@ -50,6 +50,8 @@ void Element::Element_CBNW()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (sim->pv[y/CELL][x/CELL]<=3)
|
||||
{
|
||||
if (sim->pv[y/CELL][x/CELL] <= -0.5 || sim->rng.chance(1, 4000))
|
||||
@ -87,12 +89,12 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
auto r = pmap[y+ry][x+rx];
|
||||
if (!r)
|
||||
continue;
|
||||
if ((sim->elements[TYP(r)].Properties&TYPE_PART) && parts[i].tmp == 0 && sim->rng.chance(1, 83))
|
||||
if ((elements[TYP(r)].Properties&TYPE_PART) && parts[i].tmp == 0 && sim->rng.chance(1, 83))
|
||||
{
|
||||
//Start explode
|
||||
parts[i].tmp = sim->rng.between(0, 24);
|
||||
}
|
||||
else if((sim->elements[TYP(r)].Properties&TYPE_SOLID) && TYP(r)!=PT_DMND && TYP(r)!=PT_GLAS && parts[i].tmp == 0 && sim->rng.chance(int(2 - sim->pv[y/CELL][x/CELL]), 6667))
|
||||
else if((elements[TYP(r)].Properties&TYPE_SOLID) && TYP(r)!=PT_DMND && TYP(r)!=PT_GLAS && parts[i].tmp == 0 && sim->rng.chance(int(2 - sim->pv[y/CELL][x/CELL]), 6667))
|
||||
{
|
||||
sim->part_change_type(i,x,y,PT_CO2);
|
||||
parts[i].ctype = 5;
|
||||
|
@ -49,7 +49,9 @@ void Element::Element_CLNE()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
if (parts[i].ctype<=0 || parts[i].ctype>=PT_NUM || !sim->elements[parts[i].ctype].Enabled)
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (parts[i].ctype<=0 || parts[i].ctype>=PT_NUM || !elements[parts[i].ctype].Enabled)
|
||||
{
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
{
|
||||
@ -81,7 +83,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
int np = sim->create_part(-1, x + sim->rng.between(-1, 1), y + sim->rng.between(-1, 1), TYP(parts[i].ctype));
|
||||
if (np>=0)
|
||||
{
|
||||
if (parts[i].ctype==PT_LAVA && parts[i].tmp>0 && parts[i].tmp<PT_NUM && sim->elements[parts[i].tmp].HighTemperatureTransition==PT_LAVA)
|
||||
if (parts[i].ctype==PT_LAVA && parts[i].tmp>0 && parts[i].tmp<PT_NUM && elements[parts[i].tmp].HighTemperatureTransition==PT_LAVA)
|
||||
parts[np].ctype = parts[i].tmp;
|
||||
}
|
||||
}
|
||||
|
@ -49,8 +49,10 @@ void Element::Element_CONV()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int ctype = TYP(parts[i].ctype);
|
||||
if (ctype<=0 || ctype>=PT_NUM || !sim->elements[ctype].Enabled || ctype==PT_CONV)
|
||||
if (ctype<=0 || ctype>=PT_NUM || !elements[ctype].Enabled || ctype==PT_CONV)
|
||||
{
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
{
|
||||
@ -76,7 +78,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
}
|
||||
else
|
||||
{
|
||||
int restrictElement = sim->IsElement(parts[i].tmp) ? parts[i].tmp : 0;
|
||||
int restrictElement = sd.IsElement(parts[i].tmp) ? parts[i].tmp : 0;
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
{
|
||||
for (auto ry = -1; ry <= 1; ry++)
|
||||
|
@ -51,9 +51,11 @@ void Element::Element_CRAY()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int nxx, nyy, docontinue, nxi, nyi;
|
||||
// set ctype to things that touch it if it doesn't have one already
|
||||
if (parts[i].ctype<=0 || !sim->elements[TYP(parts[i].ctype)].Enabled)
|
||||
if (parts[i].ctype<=0 || !elements[TYP(parts[i].ctype)].Enabled)
|
||||
{
|
||||
for (int rx = -1; rx <= 1; rx++)
|
||||
{
|
||||
@ -166,6 +168,8 @@ static unsigned int wavelengthToDecoColour(int wavelength)
|
||||
|
||||
static bool ctypeDraw(CTYPEDRAW_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (!Element::ctypeDrawVInCtype(CTYPEDRAW_FUNC_SUBCALL_ARGS))
|
||||
{
|
||||
return false;
|
||||
@ -174,6 +178,6 @@ static bool ctypeDraw(CTYPEDRAW_FUNC_ARGS)
|
||||
{
|
||||
sim->parts[i].ctype |= PMAPID(30);
|
||||
}
|
||||
sim->parts[i].temp = sim->elements[t].DefaultProperties.temp;
|
||||
sim->parts[i].temp = elements[t].DefaultProperties.temp;
|
||||
return true;
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ void Element::Element_DCEL()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
float multiplier = 1.0f/1.1f;
|
||||
if (parts[i].life!=0)
|
||||
{
|
||||
@ -66,7 +68,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
r = sim->photons[y+ry][x+rx];
|
||||
if (!r)
|
||||
continue;
|
||||
if (sim->elements[TYP(r)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY))
|
||||
if (elements[TYP(r)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY))
|
||||
{
|
||||
parts[ID(r)].vx *= multiplier;
|
||||
parts[ID(r)].vy *= multiplier;
|
||||
|
@ -49,6 +49,8 @@ void Element::Element_DEST()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int rx = sim->rng.between(-2, 2);
|
||||
int ry = sim->rng.between(-2, 2);
|
||||
int r = pmap[y+ry][x+rx];
|
||||
@ -81,11 +83,11 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
else if (sim->rng.chance(1, 3))
|
||||
{
|
||||
sim->kill_part(ID(r));
|
||||
parts[i].life -= 4*((sim->elements[rt].Properties&TYPE_SOLID)?3:1);
|
||||
parts[i].life -= 4*((elements[rt].Properties&TYPE_SOLID)?3:1);
|
||||
if (parts[i].life<=0)
|
||||
parts[i].life=1;
|
||||
}
|
||||
else if (sim->elements[rt].HeatConduct)
|
||||
else if (elements[rt].HeatConduct)
|
||||
parts[ID(r)].temp = MAX_TEMP;
|
||||
parts[i].temp=MAX_TEMP;
|
||||
sim->pv[y/CELL][x/CELL]+=80.0f;
|
||||
|
@ -50,6 +50,8 @@ void Element::Element_DMG()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int rad = 25;
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
{
|
||||
@ -84,8 +86,8 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
sim->vy[(y+nxj)/CELL][(x+nxi)/CELL] += fy;
|
||||
sim->pv[(y+nxj)/CELL][(x+nxi)/CELL] += 1.0f;
|
||||
auto t = TYP(rr);
|
||||
if (t && sim->elements[t].HighPressureTransition>-1 && sim->elements[t].HighPressureTransition<PT_NUM)
|
||||
sim->part_change_type(ID(rr), x+nxi, y+nxj, sim->elements[t].HighPressureTransition);
|
||||
if (t && elements[t].HighPressureTransition>-1 && elements[t].HighPressureTransition<PT_NUM)
|
||||
sim->part_change_type(ID(rr), x+nxi, y+nxj, elements[t].HighPressureTransition);
|
||||
else if (t == PT_BMTL)
|
||||
sim->part_change_type(ID(rr), x+nxi, y+nxj, PT_BRMT);
|
||||
else if (t == PT_GLAS)
|
||||
|
@ -50,6 +50,8 @@ void Element::Element_DRAY()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int ctype = TYP(parts[i].ctype), ctypeExtra = ID(parts[i].ctype), copyLength = parts[i].tmp, copySpaces = parts[i].tmp2;
|
||||
if (copySpaces < 0)
|
||||
copySpaces = parts[i].tmp2 = 0;
|
||||
@ -98,7 +100,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
foundParticle = true;
|
||||
}
|
||||
// now that it knows what kind of particle it is copying, do some extra stuff here so we can determine when to stop
|
||||
if ((ctype && sim->elements[ctype].Properties&TYPE_ENERGY) || isEnergy)
|
||||
if ((ctype && elements[ctype].Properties&TYPE_ENERGY) || isEnergy)
|
||||
rr = sim->photons[yCurrent][xCurrent];
|
||||
else
|
||||
rr = pmap[yCurrent][xCurrent];
|
||||
|
@ -51,6 +51,8 @@ void Element::Element_DTEC()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int rd = parts[i].tmp2;
|
||||
if (rd > 25) parts[i].tmp2 = rd = 25;
|
||||
if (parts[i].life)
|
||||
@ -68,7 +70,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
auto rt = TYP(r);
|
||||
if (sim->parts_avg(i,ID(r),PT_INSL) != PT_INSL)
|
||||
{
|
||||
if ((sim->elements[rt].Properties&PROP_CONDUCTS) && !(rt==PT_WATR||rt==PT_SLTW||rt==PT_NTCT||rt==PT_PTCT||rt==PT_INWR) && parts[ID(r)].life==0)
|
||||
if ((elements[rt].Properties&PROP_CONDUCTS) && !(rt==PT_WATR||rt==PT_SLTW||rt==PT_NTCT||rt==PT_PTCT||rt==PT_INWR) && parts[ID(r)].life==0)
|
||||
{
|
||||
parts[ID(r)].life = 4;
|
||||
parts[ID(r)].ctype = rt;
|
||||
|
@ -52,6 +52,8 @@ void Element::Element_ELEC()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
{
|
||||
for (auto ry = -2; ry <= 2; ry++)
|
||||
@ -118,7 +120,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
case PT_NONE: //seems to speed up ELEC even if it isn't used
|
||||
break;
|
||||
default:
|
||||
if ((sim->elements[rt].Properties & PROP_CONDUCTS) && (rt!=PT_NBLE||parts[i].temp<2273.15))
|
||||
if ((elements[rt].Properties & PROP_CONDUCTS) && (rt!=PT_NBLE||parts[i].temp<2273.15))
|
||||
{
|
||||
sim->create_part(-1, x+rx, y+ry, PT_SPRK);
|
||||
sim->kill_part(i);
|
||||
|
@ -52,6 +52,8 @@ void Element::Element_EMBR()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
{
|
||||
for (auto ry = -1; ry <= 1; ry++)
|
||||
@ -61,7 +63,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
auto r = pmap[y+ry][x+rx];
|
||||
if (!r)
|
||||
continue;
|
||||
if ((sim->elements[TYP(r)].Properties & (TYPE_SOLID | TYPE_PART | TYPE_LIQUID)) && !(sim->elements[TYP(r)].Properties & PROP_SPARKSETTLE))
|
||||
if ((elements[TYP(r)].Properties & (TYPE_SOLID | TYPE_PART | TYPE_LIQUID)) && !(elements[TYP(r)].Properties & PROP_SPARKSETTLE))
|
||||
{
|
||||
sim->kill_part(i);
|
||||
return 1;
|
||||
|
@ -64,6 +64,8 @@ void Element::Element_FIGH()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (parts[i].tmp < 0 || parts[i].tmp >= MAX_FIGHTERS)
|
||||
{
|
||||
sim->kill_part(i);
|
||||
@ -104,8 +106,8 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
if ((pow(float(tarx-x), 2) + pow(float(tary-y), 2))<600)
|
||||
{
|
||||
if (figh->elem == PT_LIGH || figh->elem == PT_NEUT
|
||||
|| sim->elements[figh->elem].Properties & (PROP_DEADLY | PROP_RADIOACTIVE)
|
||||
|| sim->elements[figh->elem].DefaultProperties.temp >= 323 || sim->elements[figh->elem].DefaultProperties.temp <= 243)
|
||||
|| elements[figh->elem].Properties & (PROP_DEADLY | PROP_RADIOACTIVE)
|
||||
|| elements[figh->elem].DefaultProperties.temp >= 323 || elements[figh->elem].DefaultProperties.temp <= 243)
|
||||
figh->comm = (int)figh->comm | 0x08;
|
||||
}
|
||||
else if (tarx<x)
|
||||
|
@ -54,6 +54,8 @@ void Element::Element_FIRE()
|
||||
|
||||
int Element_FIRE_update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int t = parts[i].type;
|
||||
switch (t)
|
||||
{
|
||||
@ -131,7 +133,7 @@ int Element_FIRE_update(UPDATE_FUNC_ARGS)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((parts[i].ctype == PT_STNE || !parts[i].ctype) && pres >= 30.0f && (parts[i].temp > sim->elements[PT_ROCK].HighTemperature || pres < sim->elements[PT_ROCK].HighPressure)) // Form ROCK with pressure, if it will stay molten or not immediately break
|
||||
else if ((parts[i].ctype == PT_STNE || !parts[i].ctype) && pres >= 30.0f && (parts[i].temp > elements[PT_ROCK].HighTemperature || pres < elements[PT_ROCK].HighPressure)) // Form ROCK with pressure, if it will stay molten or not immediately break
|
||||
{
|
||||
parts[i].tmp2 = sim->rng.between(0, 10); // Provide tmp2 for color noise
|
||||
parts[i].ctype = PT_ROCK;
|
||||
@ -202,7 +204,7 @@ int Element_FIRE_update(UPDATE_FUNC_ARGS)
|
||||
if (parts[i].ctype == PT_QRTZ && rt == PT_LAVA && parts[ID(r)].ctype == PT_CLST)
|
||||
{
|
||||
float pres = std::max(sim->pv[y/CELL][x/CELL]*10.0f, 0.0f);
|
||||
if (parts[i].temp >= pres+sim->elements[PT_CRMC].HighTemperature+50.0f)
|
||||
if (parts[i].temp >= pres+elements[PT_CRMC].HighTemperature+50.0f)
|
||||
{
|
||||
parts[i].ctype = PT_CRMC;
|
||||
parts[ID(r)].ctype = PT_CRMC;
|
||||
@ -219,7 +221,7 @@ int Element_FIRE_update(UPDATE_FUNC_ARGS)
|
||||
case 1:
|
||||
parts[i].ctype = PT_CLST;
|
||||
// avoid creating CRMC.
|
||||
if (parts[i].temp >= sim->elements[PT_PQRT].HighTemperature * 3)
|
||||
if (parts[i].temp >= elements[PT_PQRT].HighTemperature * 3)
|
||||
{
|
||||
parts[i].ctype = PT_PQRT;
|
||||
}
|
||||
@ -241,7 +243,7 @@ int Element_FIRE_update(UPDATE_FUNC_ARGS)
|
||||
}
|
||||
else if (rt == PT_HEAC && parts[i].ctype == PT_HEAC)
|
||||
{
|
||||
if (parts[ID(r)].temp > sim->elements[PT_HEAC].HighTemperature)
|
||||
if (parts[ID(r)].temp > elements[PT_HEAC].HighTemperature)
|
||||
{
|
||||
sim->part_change_type(ID(r), x+rx, y+ry, PT_LAVA);
|
||||
parts[ID(r)].ctype = PT_HEAC;
|
||||
@ -260,18 +262,18 @@ int Element_FIRE_update(UPDATE_FUNC_ARGS)
|
||||
}
|
||||
}
|
||||
|
||||
if ((surround_space || sim->elements[rt].Explosive) &&
|
||||
sim->elements[rt].Flammable && sim->rng.chance(int(sim->elements[rt].Flammable + (sim->pv[(y+ry)/CELL][(x+rx)/CELL] * 10.0f)), 1000) &&
|
||||
if ((surround_space || elements[rt].Explosive) &&
|
||||
elements[rt].Flammable && sim->rng.chance(int(elements[rt].Flammable + (sim->pv[(y+ry)/CELL][(x+rx)/CELL] * 10.0f)), 1000) &&
|
||||
//exceptions, t is the thing causing the spark and rt is what's burning
|
||||
(t != PT_SPRK || (rt != PT_RBDM && rt != PT_LRBD && rt != PT_INSL)) &&
|
||||
(t != PT_PHOT || rt != PT_INSL) &&
|
||||
(rt != PT_SPNG || parts[ID(r)].life == 0))
|
||||
{
|
||||
sim->part_change_type(ID(r), x+rx, y+ry, PT_FIRE);
|
||||
parts[ID(r)].temp = restrict_flt(sim->elements[PT_FIRE].DefaultProperties.temp + (sim->elements[rt].Flammable/2), MIN_TEMP, MAX_TEMP);
|
||||
parts[ID(r)].temp = restrict_flt(elements[PT_FIRE].DefaultProperties.temp + (elements[rt].Flammable/2), MIN_TEMP, MAX_TEMP);
|
||||
parts[ID(r)].life = sim->rng.between(180, 259);
|
||||
parts[ID(r)].tmp = parts[ID(r)].ctype = 0;
|
||||
if (sim->elements[rt].Explosive)
|
||||
if (elements[rt].Explosive)
|
||||
sim->pv[y/CELL][x/CELL] += 0.25f * CFDS;
|
||||
}
|
||||
}
|
||||
@ -284,6 +286,8 @@ int Element_FIRE_update(UPDATE_FUNC_ARGS)
|
||||
|
||||
static int updateLegacy(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int t = parts[i].type;
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
{
|
||||
@ -300,10 +304,10 @@ static int updateLegacy(UPDATE_FUNC_ARGS)
|
||||
|
||||
auto lpv = (int)sim->pv[(y+ry)/CELL][(x+rx)/CELL];
|
||||
if (lpv < 1) lpv = 1;
|
||||
if (sim->elements[rt].Meltable &&
|
||||
if (elements[rt].Meltable &&
|
||||
((rt!=PT_RBDM && rt!=PT_LRBD) || t!=PT_SPRK)
|
||||
&& ((t!=PT_FIRE&&t!=PT_PLSM) || (rt!=PT_METL && rt!=PT_IRON && rt!=PT_ETRD && rt!=PT_PSCN && rt!=PT_NSCN && rt!=PT_NTCT && rt!=PT_PTCT && rt!=PT_BMTL && rt!=PT_BRMT && rt!=PT_SALT && rt!=PT_INWR))
|
||||
&& sim->rng.chance(sim->elements[rt].Meltable*lpv, 1000))
|
||||
&& sim->rng.chance(elements[rt].Meltable*lpv, 1000))
|
||||
{
|
||||
if (t!=PT_LAVA || parts[i].life>0)
|
||||
{
|
||||
|
@ -49,6 +49,8 @@ void Element::Element_FIRW()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (parts[i].tmp<=0)
|
||||
{
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
@ -64,12 +66,12 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
if (rt==PT_FIRE||rt==PT_PLSM||rt==PT_THDR)
|
||||
{
|
||||
float gx, gy, multiplier;
|
||||
sim->GetGravityField(x, y, sim->elements[PT_FIRW].Gravity, 1.0f, gx, gy);
|
||||
sim->GetGravityField(x, y, elements[PT_FIRW].Gravity, 1.0f, gx, gy);
|
||||
if (gx*gx+gy*gy < 0.001f)
|
||||
{
|
||||
float angle = sim->rng.between(0, 6283) * 0.001f;//(in radians, between 0 and 2*pi)
|
||||
gx += sinf(angle)*sim->elements[PT_FIRW].Gravity*0.5f;
|
||||
gy += cosf(angle)*sim->elements[PT_FIRW].Gravity*0.5f;
|
||||
gx += sinf(angle)*elements[PT_FIRW].Gravity*0.5f;
|
||||
gy += cosf(angle)*elements[PT_FIRW].Gravity*0.5f;
|
||||
}
|
||||
parts[i].tmp = 1;
|
||||
parts[i].life = sim->rng.between(20, 29);
|
||||
|
@ -48,6 +48,8 @@ void Element::Element_FOG()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
{
|
||||
for (auto ry = -1; ry <= 1; ry++)
|
||||
@ -57,7 +59,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
auto r = pmap[y+ry][x+rx];
|
||||
if (!r)
|
||||
continue;
|
||||
if ((sim->elements[TYP(r)].Properties&TYPE_SOLID) && sim->rng.chance(1, 10) && parts[i].life==0 && !(TYP(r)==PT_CLNE || TYP(r)==PT_PCLN)) // TODO: should this also exclude BCLN?
|
||||
if ((elements[TYP(r)].Properties&TYPE_SOLID) && sim->rng.chance(1, 10) && parts[i].life==0 && !(TYP(r)==PT_CLNE || TYP(r)==PT_PCLN)) // TODO: should this also exclude BCLN?
|
||||
{
|
||||
sim->part_change_type(i,x,y,PT_RIME);
|
||||
}
|
||||
|
@ -48,6 +48,8 @@ void Element::Element_FRAY()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int curlen;
|
||||
if (parts[i].tmp > 0)
|
||||
curlen = parts[i].tmp;
|
||||
@ -73,7 +75,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
r = pmap[y+nyi+nyy][x+nxi+nxx];
|
||||
if (!r)
|
||||
r = sim->photons[y+nyi+nyy][x+nxi+nxx];
|
||||
if (r && !(sim->elements[TYP(r)].Properties & TYPE_SOLID)){
|
||||
if (r && !(elements[TYP(r)].Properties & TYPE_SOLID)){
|
||||
parts[ID(r)].vx += nxi*((parts[i].temp-273.15f)/10.0f);
|
||||
parts[ID(r)].vy += nyi*((parts[i].temp-273.15f)/10.0f);
|
||||
}
|
||||
|
@ -48,16 +48,18 @@ void Element::Element_FWRK()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (parts[i].life == 0 && ((surround_space && parts[i].temp>400 && sim->rng.chance(int(9+parts[i].temp/40), 100000)) || parts[i].ctype == PT_DUST))
|
||||
{
|
||||
float gx, gy, multiplier, gmax;
|
||||
int randTmp;
|
||||
sim->GetGravityField(x, y, sim->elements[PT_FWRK].Gravity, 1.0f, gx, gy);
|
||||
sim->GetGravityField(x, y, elements[PT_FWRK].Gravity, 1.0f, gx, gy);
|
||||
if (gx*gx+gy*gy < 0.001f)
|
||||
{
|
||||
float angle = sim->rng.between(0, 6283) * 0.001f;//(in radians, between 0 and 2*pi)
|
||||
gx += sinf(angle)*sim->elements[PT_FWRK].Gravity*0.5f;
|
||||
gy += cosf(angle)*sim->elements[PT_FWRK].Gravity*0.5f;
|
||||
gx += sinf(angle)*elements[PT_FWRK].Gravity*0.5f;
|
||||
gy += cosf(angle)*elements[PT_FWRK].Gravity*0.5f;
|
||||
}
|
||||
gmax = std::max(fabsf(gx), fabsf(gy));
|
||||
if (sim->eval_move(PT_FWRK, (int)(x-(gx/gmax)+0.5f), (int)(y-(gy/gmax)+0.5f), NULL))
|
||||
|
@ -50,6 +50,8 @@ void Element::Element_GEL()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (parts[i].tmp > 100)
|
||||
parts[i].tmp = 100;
|
||||
if (parts[i].tmp < 0)
|
||||
@ -133,17 +135,17 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
dy = parts[i].y - parts[ID(r)].y;
|
||||
|
||||
//Stickiness
|
||||
if ((dx*dx + dy*dy)>1.5 && (gel || !sim->elements[rt].Falldown || (fabs((float)rx)<2 && fabs((float)ry)<2)))
|
||||
if ((dx*dx + dy*dy)>1.5 && (gel || !elements[rt].Falldown || (fabs((float)rx)<2 && fabs((float)ry)<2)))
|
||||
{
|
||||
float per, nd;
|
||||
nd = dx*dx + dy*dy - 0.5;
|
||||
per = 5*(1 - parts[i].tmp/100)*(nd/(dx*dx + dy*dy + nd) - 0.5);
|
||||
if (sim->elements[rt].Properties&TYPE_LIQUID)
|
||||
if (elements[rt].Properties&TYPE_LIQUID)
|
||||
per *= 0.1f;
|
||||
dx *= per; dy *= per;
|
||||
parts[i].vx += dx;
|
||||
parts[i].vy += dy;
|
||||
if ((sim->elements[rt].Properties&TYPE_PART) || rt==PT_GOO)
|
||||
if ((elements[rt].Properties&TYPE_PART) || rt==PT_GOO)
|
||||
{
|
||||
parts[ID(r)].vx -= dx;
|
||||
parts[ID(r)].vy -= dy;
|
||||
|
@ -47,6 +47,8 @@ void Element::Element_H2()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &can_move = sd.can_move;
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
{
|
||||
for (auto ry = -2; ry <= 2; ry++)
|
||||
@ -119,7 +121,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
parts[j].tmp = 0x1;
|
||||
}
|
||||
auto rx = x + sim->rng.between(-1, 1), ry = y + sim->rng.between(-1, 1), rt = TYP(pmap[ry][rx]);
|
||||
if (sim->can_move[PT_PLSM][rt] || rt == PT_H2)
|
||||
if (can_move[PT_PLSM][rt] || rt == PT_H2)
|
||||
{
|
||||
j = sim->create_part(-3,rx,ry,PT_PLSM);
|
||||
if (j>-1)
|
||||
|
@ -48,7 +48,8 @@ void Element::Element_HEAC()
|
||||
}
|
||||
|
||||
static const auto isInsulator = [](Simulation* a, int b) -> bool {
|
||||
return b && (a->elements[TYP(b)].HeatConduct == 0 || (TYP(b) == PT_HSWC && a->parts[ID(b)].life != 10));
|
||||
auto &sd = SimulationData::CRef();
|
||||
return b && (sd.elements[TYP(b)].HeatConduct == 0 || (TYP(b) == PT_HSWC && a->parts[ID(b)].life != 10));
|
||||
};
|
||||
|
||||
// If this is used elsewhere (GOLD), it should be moved into Simulation.h
|
||||
@ -118,6 +119,8 @@ bool CheckLine(Simulation* sim, int x1, int y1, int x2, int y2, BinaryPredicate
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
const int rad = 4;
|
||||
int rry, rrx, r, count = 0;
|
||||
float tempAgg = 0;
|
||||
@ -130,13 +133,13 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
if (x+rrx >= 0 && x+rrx < XRES && y+rry >= 0 && y+rry < YRES && !CheckLine(sim, x, y, x+rrx, y+rry, isInsulator))
|
||||
{
|
||||
r = pmap[y+rry][x+rrx];
|
||||
if (r && sim->elements[TYP(r)].HeatConduct > 0 && (TYP(r) != PT_HSWC || parts[ID(r)].life == 10))
|
||||
if (r && elements[TYP(r)].HeatConduct > 0 && (TYP(r) != PT_HSWC || parts[ID(r)].life == 10))
|
||||
{
|
||||
count++;
|
||||
tempAgg += parts[ID(r)].temp;
|
||||
}
|
||||
r = sim->photons[y+rry][x+rrx];
|
||||
if (r && sim->elements[TYP(r)].HeatConduct > 0 && (TYP(r) != PT_HSWC || parts[ID(r)].life == 10))
|
||||
if (r && elements[TYP(r)].HeatConduct > 0 && (TYP(r) != PT_HSWC || parts[ID(r)].life == 10))
|
||||
{
|
||||
count++;
|
||||
tempAgg += parts[ID(r)].temp;
|
||||
@ -158,12 +161,12 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
if (x+rrx >= 0 && x+rrx < XRES && y+rry >= 0 && y+rry < YRES && !CheckLine(sim, x, y, x+rrx, y+rry, isInsulator))
|
||||
{
|
||||
r = pmap[y+rry][x+rrx];
|
||||
if (r && sim->elements[TYP(r)].HeatConduct > 0 && (TYP(r) != PT_HSWC || parts[ID(r)].life == 10))
|
||||
if (r && elements[TYP(r)].HeatConduct > 0 && (TYP(r) != PT_HSWC || parts[ID(r)].life == 10))
|
||||
{
|
||||
parts[ID(r)].temp = parts[i].temp;
|
||||
}
|
||||
r = sim->photons[y+rry][x+rrx];
|
||||
if (r && sim->elements[TYP(r)].HeatConduct > 0 && (TYP(r) != PT_HSWC || parts[ID(r)].life == 10))
|
||||
if (r && elements[TYP(r)].HeatConduct > 0 && (TYP(r) != PT_HSWC || parts[ID(r)].life == 10))
|
||||
{
|
||||
parts[ID(r)].temp = parts[i].temp;
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ void Element::Element_ICEI()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (parts[i].ctype==PT_FRZW)//get colder if it is from FRZW
|
||||
{
|
||||
parts[i].temp = restrict_flt(parts[i].temp-1.0f, MIN_TEMP, MAX_TEMP);
|
||||
@ -65,7 +67,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
continue;
|
||||
if (TYP(r)==PT_SALT || TYP(r)==PT_SLTW)
|
||||
{
|
||||
if (parts[i].temp > sim->elements[PT_SLTW].LowTemperature && sim->rng.chance(1, 200))
|
||||
if (parts[i].temp > elements[PT_SLTW].LowTemperature && sim->rng.chance(1, 200))
|
||||
{
|
||||
sim->part_change_type(i,x,y,PT_SLTW);
|
||||
sim->part_change_type(ID(r),x+rx,y+ry,PT_SLTW);
|
||||
|
@ -74,8 +74,10 @@ static bool phot_data_type(int rt)
|
||||
*/
|
||||
static bool accepted_conductor(Simulation* sim, int r)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int rt = TYP(r);
|
||||
return (sim->elements[rt].Properties & PROP_CONDUCTS) &&
|
||||
return (elements[rt].Properties & PROP_CONDUCTS) &&
|
||||
!(rt == PT_WATR || rt == PT_SLTW || rt == PT_NTCT ||
|
||||
rt == PT_PTCT || rt == PT_INWR) &&
|
||||
sim->parts[ID(r)].life == 0;
|
||||
|
@ -50,6 +50,7 @@ void Element::Element_LIFE()
|
||||
|
||||
static int graphics(GRAPHICS_FUNC_ARGS)
|
||||
{
|
||||
auto &builtinGol = SimulationData::builtinGol;
|
||||
auto colour1 = RGB<uint8_t>::Unpack(cpart->dcolour);
|
||||
auto colour2 = RGB<uint8_t>::Unpack(cpart->tmp);
|
||||
if (!cpart->dcolour)
|
||||
@ -91,6 +92,8 @@ static int graphics(GRAPHICS_FUNC_ARGS)
|
||||
|
||||
static void create(ELEMENT_CREATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &builtinGol = sd.builtinGol;
|
||||
if (v == -1)
|
||||
v = 0;
|
||||
// * 0x200000: No need to look for colours, they'll be set later anyway.
|
||||
@ -105,7 +108,7 @@ static void create(ELEMENT_CREATE_FUNC_ARGS)
|
||||
}
|
||||
else if (!skipLookup)
|
||||
{
|
||||
auto *cgol = sim->GetCustomGOLByRule(v);
|
||||
auto *cgol = sd.GetCustomGOLByRule(v);
|
||||
if (cgol)
|
||||
{
|
||||
sim->parts[i].dcolour = cgol->colour1;
|
||||
|
@ -79,6 +79,8 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
sim->hv[y/CELL][x/CELL] = MAX_TEMP;
|
||||
}
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
{
|
||||
for (auto ry = -2; ry <= 2; ry++)
|
||||
@ -89,15 +91,15 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
if (!r)
|
||||
continue;
|
||||
auto rt = TYP(r);
|
||||
if ((surround_space || sim->elements[rt].Explosive) &&
|
||||
if ((surround_space || elements[rt].Explosive) &&
|
||||
(rt!=PT_SPNG || parts[ID(r)].life==0) &&
|
||||
sim->elements[rt].Flammable && sim->rng.chance(sim->elements[rt].Flammable + int(sim->pv[(y+ry)/CELL][(x+rx)/CELL] * 10.0f), 1000))
|
||||
elements[rt].Flammable && sim->rng.chance(elements[rt].Flammable + int(sim->pv[(y+ry)/CELL][(x+rx)/CELL] * 10.0f), 1000))
|
||||
{
|
||||
sim->part_change_type(ID(r),x+rx,y+ry,PT_FIRE);
|
||||
parts[ID(r)].temp = restrict_flt(sim->elements[PT_FIRE].DefaultProperties.temp + (sim->elements[rt].Flammable/2), MIN_TEMP, MAX_TEMP);
|
||||
parts[ID(r)].temp = restrict_flt(elements[PT_FIRE].DefaultProperties.temp + (elements[rt].Flammable/2), MIN_TEMP, MAX_TEMP);
|
||||
parts[ID(r)].life = sim->rng.between(180, 259);
|
||||
parts[ID(r)].tmp = parts[ID(r)].ctype = 0;
|
||||
if (sim->elements[rt].Explosive)
|
||||
if (elements[rt].Explosive)
|
||||
sim->pv[y/CELL][x/CELL] += 0.25f * CFDS;
|
||||
}
|
||||
switch (rt)
|
||||
@ -138,7 +140,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
break;
|
||||
case PT_HEAC:
|
||||
parts[ID(r)].temp = restrict_flt(parts[ID(r)].temp+powderful/10, MIN_TEMP, MAX_TEMP);
|
||||
if (parts[ID(r)].temp > sim->elements[PT_HEAC].HighTemperature)
|
||||
if (parts[ID(r)].temp > elements[PT_HEAC].HighTemperature)
|
||||
{
|
||||
sim->part_change_type(ID(r), x+rx, y+ry, PT_LAVA);
|
||||
parts[ID(r)].ctype = PT_HEAC;
|
||||
@ -147,10 +149,10 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ((sim->elements[TYP(r)].Properties&PROP_CONDUCTS) && parts[ID(r)].life==0)
|
||||
if ((elements[TYP(r)].Properties&PROP_CONDUCTS) && parts[ID(r)].life==0)
|
||||
sim->create_part(ID(r),x+rx,y+ry,PT_SPRK);
|
||||
sim->pv[y/CELL][x/CELL] += powderful/400;
|
||||
if (sim->elements[TYP(r)].HeatConduct) parts[ID(r)].temp = restrict_flt(parts[ID(r)].temp+powderful/1.3, MIN_TEMP, MAX_TEMP);
|
||||
if (elements[TYP(r)].HeatConduct) parts[ID(r)].temp = restrict_flt(parts[ID(r)].temp+powderful/1.3, MIN_TEMP, MAX_TEMP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ void Element::Element_LSNS()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int rd = parts[i].tmp2;
|
||||
if (rd > 25) parts[i].tmp2 = rd = 25;
|
||||
if (parts[i].life)
|
||||
@ -69,7 +71,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
int rt = TYP(r);
|
||||
if (sim->parts_avg(i, ID(r), PT_INSL) != PT_INSL)
|
||||
{
|
||||
if ((sim->elements[rt].Properties&PROP_CONDUCTS) && !(rt == PT_WATR || rt == PT_SLTW || rt == PT_NTCT || rt == PT_PTCT || rt == PT_INWR) && parts[ID(r)].life == 0)
|
||||
if ((elements[rt].Properties&PROP_CONDUCTS) && !(rt == PT_WATR || rt == PT_SLTW || rt == PT_NTCT || rt == PT_PTCT || rt == PT_INWR) && parts[ID(r)].life == 0)
|
||||
{
|
||||
parts[ID(r)].life = 4;
|
||||
parts[ID(r)].ctype = rt;
|
||||
|
@ -49,6 +49,8 @@ void Element::Element_NBLE()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &can_move = sd.can_move;
|
||||
if (parts[i].temp > 5273.15 && sim->pv[y/CELL][x/CELL] > 100.0f)
|
||||
{
|
||||
parts[i].tmp |= 0x1;
|
||||
@ -75,7 +77,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
parts[j].tmp = 0x1;
|
||||
}
|
||||
int rx = x + sim->rng.between(-1, 1), ry = y + sim->rng.between(-1, 1), rt = TYP(pmap[ry][rx]);
|
||||
if (sim->can_move[PT_PLSM][rt] || rt == PT_NBLE)
|
||||
if (can_move[PT_PLSM][rt] || rt == PT_NBLE)
|
||||
{
|
||||
j = sim->create_part(-3,rx,ry,PT_PLSM);
|
||||
if (j != -1)
|
||||
|
@ -47,6 +47,8 @@ void Element::Element_O2()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &can_move = sd.can_move;
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
{
|
||||
for (auto ry = -2; ry <= 2; ry++)
|
||||
@ -99,7 +101,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
parts[j].tmp = 0x1;
|
||||
}
|
||||
auto rx = x + sim->rng.between(-1, 1), ry = y + sim->rng.between(-1, 1), r = TYP(pmap[ry][rx]);
|
||||
if (sim->can_move[PT_PLSM][r] || r == PT_O2)
|
||||
if (can_move[PT_PLSM][r] || r == PT_O2)
|
||||
{
|
||||
j = sim->create_part(-3,rx,ry,PT_PLSM);
|
||||
if (j > -1)
|
||||
|
@ -54,6 +54,8 @@ constexpr float ADVECTION = 0.1f;
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (!parts[i].tmp2 && sim->pv[y/CELL][x/CELL]>4.0f)
|
||||
parts[i].tmp2 = sim->rng.between(80, 119);
|
||||
if (parts[i].tmp2)
|
||||
@ -66,7 +68,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (parts[i].ctype<=0 || parts[i].ctype>=PT_NUM || !sim->elements[parts[i].ctype].Enabled)
|
||||
if (parts[i].ctype<=0 || parts[i].ctype>=PT_NUM || !elements[parts[i].ctype].Enabled)
|
||||
{
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
{
|
||||
@ -117,7 +119,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parts[i].ctype>0 && parts[i].ctype<PT_NUM && sim->elements[parts[i].ctype].Enabled)
|
||||
if (parts[i].ctype>0 && parts[i].ctype<PT_NUM && elements[parts[i].ctype].Enabled)
|
||||
{
|
||||
if (parts[i].ctype==PT_PHOT) {//create photons a different way
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
@ -156,7 +158,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
int np = sim->create_part(-1, x + sim->rng.between(-1, 1), y + sim->rng.between(-1, 1), TYP(parts[i].ctype));
|
||||
if (np>-1)
|
||||
{
|
||||
if (parts[i].ctype==PT_LAVA && parts[i].tmp>0 && parts[i].tmp<PT_NUM && sim->elements[parts[i].tmp].HighTemperatureTransition==PT_LAVA)
|
||||
if (parts[i].ctype==PT_LAVA && parts[i].tmp>0 && parts[i].tmp<PT_NUM && elements[parts[i].tmp].HighTemperatureTransition==PT_LAVA)
|
||||
parts[np].ctype = parts[i].tmp;
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,8 @@ void Element::Element_PCLN()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (parts[i].life>0 && parts[i].life!=10)
|
||||
parts[i].life--;
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
@ -83,7 +85,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parts[i].ctype<=0 || parts[i].ctype>=PT_NUM || !sim->elements[parts[i].ctype].Enabled)
|
||||
if (parts[i].ctype<=0 || parts[i].ctype>=PT_NUM || !elements[parts[i].ctype].Enabled)
|
||||
{
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
{
|
||||
@ -108,7 +110,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parts[i].ctype>0 && parts[i].ctype<PT_NUM && sim->elements[parts[i].ctype].Enabled && parts[i].life==10)
|
||||
if (parts[i].ctype>0 && parts[i].ctype<PT_NUM && elements[parts[i].ctype].Enabled && parts[i].life==10)
|
||||
{
|
||||
if (parts[i].ctype==PT_PHOT) {//create photons a different way
|
||||
for (auto rx = -1; rx <= 1; rx++)
|
||||
@ -147,7 +149,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
int np = sim->create_part(-1, x + sim->rng.between(-1, 1), y + sim->rng.between(-1, 1), TYP(parts[i].ctype));
|
||||
if (np>=0)
|
||||
{
|
||||
if (parts[i].ctype==PT_LAVA && parts[i].tmp>0 && parts[i].tmp<PT_NUM && sim->elements[parts[i].tmp].HighTemperatureTransition==PT_LAVA)
|
||||
if (parts[i].ctype==PT_LAVA && parts[i].tmp>0 && parts[i].tmp<PT_NUM && elements[parts[i].tmp].HighTemperatureTransition==PT_LAVA)
|
||||
parts[np].ctype = parts[i].tmp;
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +123,9 @@ static unsigned int nextColor(unsigned int flags)
|
||||
|
||||
int Element_PIPE_update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
if (parts[i].ctype && !sim->elements[TYP(parts[i].ctype)].Enabled)
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (parts[i].ctype && !elements[TYP(parts[i].ctype)].Enabled)
|
||||
parts[i].ctype = 0;
|
||||
if (parts[i].tmp & PPIP_TMPFLAG_TRIGGERS)
|
||||
{
|
||||
@ -259,14 +261,14 @@ int Element_PIPE_update(UPDATE_FUNC_ARGS)
|
||||
}
|
||||
}
|
||||
//try eating particle at entrance
|
||||
else if (!TYP(parts[i].ctype) && (sim->elements[TYP(r)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)))
|
||||
else if (!TYP(parts[i].ctype) && (elements[TYP(r)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)))
|
||||
{
|
||||
if (TYP(r)==PT_SOAP)
|
||||
Element_SOAP_detach(sim, ID(r));
|
||||
transfer_part_to_pipe(parts+(ID(r)), parts+i);
|
||||
sim->kill_part(ID(r));
|
||||
}
|
||||
else if (!TYP(parts[i].ctype) && TYP(r)==PT_STOR && sim->IsElement(parts[ID(r)].tmp) && (sim->elements[parts[ID(r)].tmp].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)))
|
||||
else if (!TYP(parts[i].ctype) && TYP(r)==PT_STOR && sd.IsElement(parts[ID(r)].tmp) && (elements[parts[ID(r)].tmp].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)))
|
||||
{
|
||||
// STOR stores properties in the same places as PIPE does
|
||||
transfer_pipe_to_pipe(parts+(ID(r)), parts+i, true);
|
||||
@ -344,8 +346,10 @@ int Element_PIPE_update(UPDATE_FUNC_ARGS)
|
||||
|
||||
int Element_PIPE_graphics(GRAPHICS_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int t = TYP(cpart->ctype);
|
||||
if (t>0 && t<PT_NUM && ren->sim->elements[t].Enabled)
|
||||
if (t>0 && t<PT_NUM && elements[t].Enabled)
|
||||
{
|
||||
if (t == PT_STKM || t == PT_STKM2 || t == PT_FIGH)
|
||||
return 0;
|
||||
@ -374,13 +378,13 @@ int Element_PIPE_graphics(GRAPHICS_FUNC_ARGS)
|
||||
cpart->tmp = tpart.tmp3;
|
||||
cpart->ctype = tpart.tmp4;
|
||||
|
||||
RGB<uint8_t> colour = ren->sim->elements[t].Colour;
|
||||
RGB<uint8_t> colour = elements[t].Colour;
|
||||
*colr = colour.Red;
|
||||
*colg = colour.Green;
|
||||
*colb = colour.Blue;
|
||||
if (ren->sim->elements[t].Graphics)
|
||||
if (elements[t].Graphics)
|
||||
{
|
||||
(*(ren->sim->elements[t].Graphics))(ren, cpart, nx, ny, pixel_mode, cola, colr, colg, colb, firea, firer, fireg, fireb);
|
||||
(*(elements[t].Graphics))(ren, cpart, nx, ny, pixel_mode, cola, colr, colg, colb, firea, firer, fireg, fireb);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -419,6 +423,8 @@ int Element_PIPE_graphics(GRAPHICS_FUNC_ARGS)
|
||||
|
||||
void Element_PIPE_transfer_pipe_to_part(Simulation * sim, Particle *pipe, Particle *part, bool STOR)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
// STOR also calls this function to move particles from STOR to PRTI
|
||||
// PIPE was changed, so now PIPE and STOR don't use the same particle storage format
|
||||
if (STOR)
|
||||
@ -436,7 +442,7 @@ void Element_PIPE_transfer_pipe_to_part(Simulation * sim, Particle *pipe, Partic
|
||||
part->tmp = pipe->tmp3;
|
||||
part->ctype = pipe->tmp4;
|
||||
|
||||
if (!(sim->elements[part->type].Properties & TYPE_ENERGY))
|
||||
if (!(elements[part->type].Properties & TYPE_ENERGY))
|
||||
{
|
||||
part->vx = 0.0f;
|
||||
part->vy = 0.0f;
|
||||
|
@ -54,6 +54,8 @@ void Element::Element_PROT()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
sim->pv[y/CELL][x/CELL] -= .003f;
|
||||
int under = pmap[y][x];
|
||||
int utype = TYP(under);
|
||||
@ -111,14 +113,14 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
break;
|
||||
default:
|
||||
//set off explosives (only when hot because it wasn't as fun when it made an entire save explode)
|
||||
if (parts[i].temp > 273.15f + 500.0f && (sim->elements[utype].Flammable || sim->elements[utype].Explosive || utype == PT_BANG))
|
||||
if (parts[i].temp > 273.15f + 500.0f && (elements[utype].Flammable || elements[utype].Explosive || utype == PT_BANG))
|
||||
{
|
||||
sim->create_part(uID, x, y, PT_FIRE);
|
||||
parts[uID].temp += restrict_flt(float(sim->elements[utype].Flammable * 5), MIN_TEMP, MAX_TEMP);
|
||||
parts[uID].temp += restrict_flt(float(elements[utype].Flammable * 5), MIN_TEMP, MAX_TEMP);
|
||||
sim->pv[y / CELL][x / CELL] += 1.00f;
|
||||
}
|
||||
//prevent inactive sparkable elements from being sparked
|
||||
else if ((sim->elements[utype].Properties&PROP_CONDUCTS) && parts[uID].life <= 4)
|
||||
else if ((elements[utype].Properties&PROP_CONDUCTS) && parts[uID].life <= 4)
|
||||
{
|
||||
parts[uID].life = 40 + parts[uID].life;
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ void Element::Element_PRTI()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int fe = 0;
|
||||
|
||||
parts[i].tmp = (int)((parts[i].temp-73.15f)/100+1);
|
||||
@ -76,7 +78,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
int r = pmap[y+ry][x+rx];
|
||||
if (!r || TYP(r) == PT_STOR)
|
||||
fe = 1;
|
||||
if (!r || (!(sim->elements[TYP(r)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)) && TYP(r)!=PT_SPRK && TYP(r)!=PT_STOR))
|
||||
if (!r || (!(elements[TYP(r)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)) && TYP(r)!=PT_SPRK && TYP(r)!=PT_STOR))
|
||||
{
|
||||
r = sim->photons[y+ry][x+rx];
|
||||
if (!r)
|
||||
@ -94,7 +96,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
if (TYP(r) == PT_STOR)
|
||||
{
|
||||
if (sim->IsElement(parts[ID(r)].tmp) && (sim->elements[parts[ID(r)].tmp].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)))
|
||||
if (sd.IsElement(parts[ID(r)].tmp) && (elements[parts[ID(r)].tmp].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS | TYPE_ENERGY)))
|
||||
{
|
||||
// STOR uses same format as PIPE, so we can use this function to do the transfer
|
||||
Element_PIPE_transfer_pipe_to_part(sim, parts+(ID(r)), &sim->portalp[parts[i].tmp][count][nnx], true);
|
||||
|
@ -48,6 +48,8 @@ void Element::Element_PSNS()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if ((parts[i].tmp == 0 && sim->pv[y/CELL][x/CELL] > parts[i].temp-273.15f) || (parts[i].tmp == 2 && sim->pv[y/CELL][x/CELL] < parts[i].temp-273.15f))
|
||||
{
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
@ -62,7 +64,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
if (sim->parts_avg(i,ID(r),PT_INSL) != PT_INSL)
|
||||
{
|
||||
auto rt = TYP(r);
|
||||
if ((sim->elements[rt].Properties&PROP_CONDUCTS) && !(rt==PT_WATR||rt==PT_SLTW||rt==PT_NTCT||rt==PT_PTCT||rt==PT_INWR) && parts[ID(r)].life==0)
|
||||
if ((elements[rt].Properties&PROP_CONDUCTS) && !(rt==PT_WATR||rt==PT_SLTW||rt==PT_NTCT||rt==PT_PTCT||rt==PT_INWR) && parts[ID(r)].life==0)
|
||||
{
|
||||
parts[ID(r)].life = 4;
|
||||
parts[ID(r)].ctype = rt;
|
||||
|
@ -49,6 +49,8 @@ void Element::Element_RPEL()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int r, rx, ry, ri;
|
||||
for(ri = 0; ri <= 10; ri++)
|
||||
{
|
||||
@ -60,7 +62,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
if (!r)
|
||||
r = sim->photons[y+ry][x+rx];
|
||||
|
||||
if (r && !(sim->elements[TYP(r)].Properties & TYPE_SOLID)) {
|
||||
if (r && !(elements[TYP(r)].Properties & TYPE_SOLID)) {
|
||||
if (!parts[i].ctype || parts[i].ctype == parts[ID(r)].type) {
|
||||
parts[ID(r)].vx += isign(rx)*((parts[i].temp-273.15)/10.0f);
|
||||
parts[ID(r)].vy += isign(ry)*((parts[i].temp-273.15)/10.0f);
|
||||
|
@ -99,6 +99,8 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
//0x02 - first mate yes/no
|
||||
//0x04 - "back" mate yes/no
|
||||
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (parts[i].ctype&1)
|
||||
{
|
||||
// reset invalid SOAP links
|
||||
@ -171,7 +173,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
if (parts[i].temp>FREEZING)
|
||||
{
|
||||
if (sim->bmap[(y+ry)/CELL][(x+rx)/CELL]
|
||||
|| (r && !(sim->elements[TYP(r)].Properties&TYPE_GAS)
|
||||
|| (r && !(elements[TYP(r)].Properties&TYPE_GAS)
|
||||
&& TYP(r) != PT_SOAP && TYP(r) != PT_GLAS))
|
||||
{
|
||||
Element_SOAP_detach(sim, i);
|
||||
|
@ -52,6 +52,8 @@ void Element::Element_SPRK()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int ct = parts[i].ctype;
|
||||
Element_FIRE_update(UPDATE_FUNC_SUBCALL_ARGS);
|
||||
|
||||
@ -59,7 +61,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
if (ct==PT_WATR||ct==PT_SLTW||ct==PT_PSCN||ct==PT_NSCN||ct==PT_ETRD||ct==PT_INWR)
|
||||
parts[i].temp = R_TEMP + 273.15f;
|
||||
if (ct<=0 || ct>=PT_NUM || !sim->elements[parts[i].ctype].Enabled)
|
||||
if (ct<=0 || ct>=PT_NUM || !elements[parts[i].ctype].Enabled)
|
||||
ct = PT_METL;
|
||||
parts[i].ctype = PT_NONE;
|
||||
parts[i].life = 4;
|
||||
@ -271,7 +273,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
}
|
||||
|
||||
if (pavg == PT_INSL) continue; //Insulation blocks everything past here
|
||||
if (!((sim->elements[receiver].Properties&PROP_CONDUCTS)||receiver==PT_INST||receiver==PT_QRTZ)) continue; //Stop non-conducting receivers, allow INST and QRTZ as special cases
|
||||
if (!((elements[receiver].Properties&PROP_CONDUCTS)||receiver==PT_INST||receiver==PT_QRTZ)) continue; //Stop non-conducting receivers, allow INST and QRTZ as special cases
|
||||
if (abs(rx)+abs(ry)>=4 &&sender!=PT_SWCH&&receiver!=PT_SWCH) continue; //Only switch conducts really far
|
||||
if (receiver==sender && receiver!=PT_INST && receiver!=PT_QRTZ) goto conduct; //Everything conducts to itself, except INST.
|
||||
|
||||
|
@ -114,6 +114,8 @@ void die(Simulation *sim, playerst *playerp, int i)
|
||||
|
||||
int Element_STKM_run_stickman(playerst *playerp, UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int r, rx, ry;
|
||||
int t = parts[i].type;
|
||||
float pp, d;
|
||||
@ -125,7 +127,7 @@ int Element_STKM_run_stickman(playerst *playerp, UPDATE_FUNC_ARGS)
|
||||
float rocketBootsHeadEffectV = 0.3f;// stronger acceleration vertically, to counteract gravity
|
||||
float rocketBootsFeetEffectV = 0.45f;
|
||||
|
||||
if (!playerp->fan && parts[i].ctype && sim->IsElementOrNone(parts[i].ctype))
|
||||
if (!playerp->fan && parts[i].ctype && sd.IsElementOrNone(parts[i].ctype))
|
||||
Element_STKM_set_element(sim, playerp, parts[i].ctype);
|
||||
playerp->frames++;
|
||||
|
||||
@ -449,7 +451,7 @@ int Element_STKM_run_stickman(playerst *playerp, UPDATE_FUNC_ARGS)
|
||||
{
|
||||
ry -= 2 * sim->rng.between(0, 1) + 1;
|
||||
r = pmap[ry][rx];
|
||||
if (sim->elements[TYP(r)].Properties&TYPE_SOLID)
|
||||
if (elements[TYP(r)].Properties&TYPE_SOLID)
|
||||
{
|
||||
sim->create_part(-1, rx, ry, PT_SPRK);
|
||||
playerp->frames = 0;
|
||||
@ -520,7 +522,7 @@ int Element_STKM_run_stickman(playerst *playerp, UPDATE_FUNC_ARGS)
|
||||
{
|
||||
parts[np].vx -= -mvy*(5*((((int)playerp->pcomm)&0x02) == 0x02) - 5*(((int)(playerp->pcomm)&0x01) == 0x01));
|
||||
parts[np].vy -= mvx*(5*((((int)playerp->pcomm)&0x02) == 0x02) - 5*(((int)(playerp->pcomm)&0x01) == 0x01));
|
||||
parts[i].vx -= (sim->elements[(int)playerp->elem].Weight*parts[np].vx)/1000;
|
||||
parts[i].vx -= (elements[(int)playerp->elem].Weight*parts[np].vx)/1000;
|
||||
}
|
||||
playerp->frames = 0;
|
||||
}
|
||||
@ -627,6 +629,8 @@ int Element_STKM_run_stickman(playerst *playerp, UPDATE_FUNC_ARGS)
|
||||
|
||||
void Element_STKM_interact(Simulation *sim, playerst *playerp, int i, int x, int y)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int r;
|
||||
if (x<0 || y<0 || x>=XRES || y>=YRES || !sim->parts[i].type)
|
||||
return;
|
||||
@ -639,13 +643,13 @@ void Element_STKM_interact(Simulation *sim, playerst *playerp, int i, int x, int
|
||||
damage += sim->rng.between(32, 51);
|
||||
}
|
||||
|
||||
if (sim->elements[TYP(r)].HeatConduct && (TYP(r)!=PT_HSWC||sim->parts[ID(r)].life==10) && ((playerp->elem!=PT_LIGH && sim->parts[ID(r)].temp>=323) || sim->parts[ID(r)].temp<=243) && (!playerp->rocketBoots || TYP(r)!=PT_PLSM))
|
||||
if (elements[TYP(r)].HeatConduct && (TYP(r)!=PT_HSWC||sim->parts[ID(r)].life==10) && ((playerp->elem!=PT_LIGH && sim->parts[ID(r)].temp>=323) || sim->parts[ID(r)].temp<=243) && (!playerp->rocketBoots || TYP(r)!=PT_PLSM))
|
||||
{
|
||||
damage += 2;
|
||||
playerp->accs[3] -= 1;
|
||||
}
|
||||
|
||||
if (sim->elements[TYP(r)].Properties&PROP_DEADLY)
|
||||
if (elements[TYP(r)].Properties&PROP_DEADLY)
|
||||
switch (TYP(r))
|
||||
{
|
||||
case PT_ACID:
|
||||
@ -656,7 +660,7 @@ void Element_STKM_interact(Simulation *sim, playerst *playerp, int i, int x, int
|
||||
break;
|
||||
}
|
||||
|
||||
if (sim->elements[TYP(r)].Properties&PROP_RADIOACTIVE)
|
||||
if (elements[TYP(r)].Properties&PROP_RADIOACTIVE)
|
||||
damage++;
|
||||
|
||||
if (damage)
|
||||
@ -741,10 +745,12 @@ void Element_STKM_init_legs(Simulation * sim, playerst *playerp, int i)
|
||||
|
||||
void Element_STKM_set_element(Simulation *sim, playerst *playerp, int element)
|
||||
{
|
||||
if (sim->elements[element].Falldown != 0
|
||||
|| sim->elements[element].Properties&TYPE_GAS
|
||||
|| sim->elements[element].Properties&TYPE_LIQUID
|
||||
|| sim->elements[element].Properties&TYPE_ENERGY
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (elements[element].Falldown != 0
|
||||
|| elements[element].Properties&TYPE_GAS
|
||||
|| elements[element].Properties&TYPE_LIQUID
|
||||
|| elements[element].Properties&TYPE_ENERGY
|
||||
|| element == PT_LOLZ || element == PT_LOVE)
|
||||
{
|
||||
if (!playerp->rocketBoots || element != PT_PLSM)
|
||||
|
@ -53,7 +53,9 @@ void Element::Element_STOR()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
if (!sim->IsElementOrNone(parts[i].tmp))
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (!sd.IsElementOrNone(parts[i].tmp))
|
||||
parts[i].tmp = 0;
|
||||
if(parts[i].life && !parts[i].tmp)
|
||||
parts[i].life--;
|
||||
@ -66,7 +68,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
auto r = pmap[y+ry][x+rx];
|
||||
if ((ID(r))>=NPART || !r)
|
||||
continue;
|
||||
if (!parts[i].tmp && !parts[i].life && TYP(r)!=PT_STOR && !(sim->elements[TYP(r)].Properties&TYPE_SOLID) && (!parts[i].ctype || TYP(r)==parts[i].ctype))
|
||||
if (!parts[i].tmp && !parts[i].life && TYP(r)!=PT_STOR && !(elements[TYP(r)].Properties&TYPE_SOLID) && (!parts[i].ctype || TYP(r)==parts[i].ctype))
|
||||
{
|
||||
if (TYP(r) == PT_SOAP)
|
||||
Element_SOAP_detach(sim, ID(r));
|
||||
@ -120,7 +122,9 @@ static int graphics(GRAPHICS_FUNC_ARGS)
|
||||
|
||||
static bool ctypeDraw(CTYPEDRAW_FUNC_ARGS)
|
||||
{
|
||||
if (sim->elements[t].Properties & TYPE_SOLID)
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (elements[t].Properties & TYPE_SOLID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ void Element::Element_THDR()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
bool kill=false;
|
||||
for (auto rx = -2; rx <= 2; rx++)
|
||||
{
|
||||
@ -61,7 +63,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
if (!r)
|
||||
continue;
|
||||
auto rt = TYP(r);
|
||||
if ((sim->elements[TYP(r)].Properties&PROP_CONDUCTS) && parts[ID(r)].life==0 && !(rt==PT_WATR||rt==PT_SLTW) && parts[ID(r)].ctype!=PT_SPRK)
|
||||
if ((elements[TYP(r)].Properties&PROP_CONDUCTS) && parts[ID(r)].life==0 && !(rt==PT_WATR||rt==PT_SLTW) && parts[ID(r)].ctype!=PT_SPRK)
|
||||
{
|
||||
parts[ID(r)].ctype = parts[ID(r)].type;
|
||||
sim->part_change_type(ID(r),x+rx,y+ry,PT_SPRK);
|
||||
|
@ -270,9 +270,11 @@ static int trymovetron(Simulation * sim, int x, int y, int dir, int i, int len)
|
||||
|
||||
static bool canmovetron(Simulation * sim, int r, int len)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
if (!r || (TYP(r) == PT_SWCH && sim->parts[ID(r)].life >= 10) || (TYP(r) == PT_INVIS && sim->parts[ID(r)].tmp2 == 1))
|
||||
return true;
|
||||
if ((((sim->elements[TYP(r)].Properties & PROP_LIFE_KILL_DEC) && sim->parts[ID(r)].life > 0)|| ((sim->elements[TYP(r)].Properties & PROP_LIFE_KILL) && (sim->elements[TYP(r)].Properties & PROP_LIFE_DEC))) && sim->parts[ID(r)].life < len)
|
||||
if ((((elements[TYP(r)].Properties & PROP_LIFE_KILL_DEC) && sim->parts[ID(r)].life > 0)|| ((elements[TYP(r)].Properties & PROP_LIFE_KILL) && (elements[TYP(r)].Properties & PROP_LIFE_DEC))) && sim->parts[ID(r)].life < len)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ void Element::Element_TSNS()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int rd = parts[i].tmp2;
|
||||
if (rd > 25)
|
||||
parts[i].tmp2 = rd = 25;
|
||||
@ -69,7 +71,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
int rt = TYP(r);
|
||||
if (sim->parts_avg(i, ID(r), PT_INSL) != PT_INSL)
|
||||
{
|
||||
if ((sim->elements[rt].Properties&PROP_CONDUCTS) && !(rt == PT_WATR || rt == PT_SLTW || rt == PT_NTCT || rt == PT_PTCT || rt == PT_INWR) && parts[ID(r)].life == 0)
|
||||
if ((elements[rt].Properties&PROP_CONDUCTS) && !(rt == PT_WATR || rt == PT_SLTW || rt == PT_NTCT || rt == PT_PTCT || rt == PT_INWR) && parts[ID(r)].life == 0)
|
||||
{
|
||||
parts[ID(r)].life = 4;
|
||||
parts[ID(r)].ctype = rt;
|
||||
|
@ -52,8 +52,10 @@ void Element::Element_TUNG()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
bool splode = false;
|
||||
const float MELTING_POINT = sim->elements[PT_TUNG].HighTemperature;
|
||||
const float MELTING_POINT = elements[PT_TUNG].HighTemperature;
|
||||
|
||||
if(parts[i].temp > 2400.0)
|
||||
{
|
||||
@ -112,7 +114,9 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
|
||||
static int graphics(GRAPHICS_FUNC_ARGS)
|
||||
{
|
||||
const float MELTING_POINT = ren->sim->elements[PT_TUNG].HighTemperature;
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
const float MELTING_POINT = elements[PT_TUNG].HighTemperature;
|
||||
double startTemp = (MELTING_POINT - 1500.0);
|
||||
double tempOver = (((cpart->temp - startTemp)/1500.0)*TPT_PI_FLT) - (TPT_PI_FLT/2.0);
|
||||
if(tempOver > -(TPT_PI_FLT/2.0))
|
||||
|
@ -50,6 +50,8 @@ void Element::Element_VIBR()
|
||||
|
||||
int Element_VIBR_update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int rndstore = 0;
|
||||
if (!parts[i].life) //if not exploding
|
||||
{
|
||||
@ -89,7 +91,7 @@ int Element_VIBR_update(UPDATE_FUNC_ARGS)
|
||||
auto ry = (rndstore>>2)%3-1;
|
||||
rndstore = rndstore >> 4;
|
||||
auto r = pmap[y+ry][x+rx];
|
||||
if (TYP(r) && TYP(r) != PT_BREC && (sim->elements[TYP(r)].Properties&PROP_CONDUCTS) && !parts[ID(r)].life)
|
||||
if (TYP(r) && TYP(r) != PT_BREC && (elements[TYP(r)].Properties&PROP_CONDUCTS) && !parts[ID(r)].life)
|
||||
{
|
||||
parts[ID(r)].life = 4;
|
||||
parts[ID(r)].ctype = TYP(r);
|
||||
@ -102,7 +104,7 @@ int Element_VIBR_update(UPDATE_FUNC_ARGS)
|
||||
auto rx = rndstore%7-3;
|
||||
auto ry = (rndstore>>3)%7-3;
|
||||
auto r = pmap[y+ry][x+rx];
|
||||
if (TYP(r) && TYP(r)!=PT_VIBR && TYP(r)!=PT_BVBR && sim->elements[TYP(r)].HeatConduct && (TYP(r)!=PT_HSWC||parts[ID(r)].life==10))
|
||||
if (TYP(r) && TYP(r)!=PT_VIBR && TYP(r)!=PT_BVBR && elements[TYP(r)].HeatConduct && (TYP(r)!=PT_HSWC||parts[ID(r)].life==10))
|
||||
{
|
||||
parts[ID(r)].temp += parts[i].tmp*3;
|
||||
parts[i].tmp = 0;
|
||||
|
@ -50,6 +50,8 @@ void Element::Element_VSNS()
|
||||
|
||||
static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int rd = parts[i].tmp2;
|
||||
if (rd > 25) parts[i].tmp2 = rd = 25;
|
||||
if (parts[i].life)
|
||||
@ -67,7 +69,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
int rt = TYP(r);
|
||||
if (sim->parts_avg(i, ID(r), PT_INSL) != PT_INSL)
|
||||
{
|
||||
if ((sim->elements[rt].Properties &PROP_CONDUCTS) && !(rt == PT_WATR || rt == PT_SLTW || rt == PT_NTCT || rt == PT_PTCT || rt == PT_INWR) && parts[ID(r)].life == 0)
|
||||
if ((elements[rt].Properties &PROP_CONDUCTS) && !(rt == PT_WATR || rt == PT_SLTW || rt == PT_NTCT || rt == PT_PTCT || rt == PT_INWR) && parts[ID(r)].life == 0)
|
||||
{
|
||||
parts[ID(r)].life = 4;
|
||||
parts[ID(r)].ctype = rt;
|
||||
@ -98,7 +100,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
{
|
||||
case 1:
|
||||
// serialization
|
||||
if (TYP(r) != PT_VSNS && TYP(r) != PT_FILT && !(sim->elements[TYP(r)].Properties & TYPE_SOLID))
|
||||
if (TYP(r) != PT_VSNS && TYP(r) != PT_FILT && !(elements[TYP(r)].Properties & TYPE_SOLID))
|
||||
{
|
||||
doSerialization = true;
|
||||
Vs = Vm;
|
||||
@ -118,12 +120,12 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
break;
|
||||
case 2:
|
||||
// Invert mode
|
||||
if (!(sim->elements[TYP(r)].Properties & TYPE_SOLID) && Vm <= parts[i].temp - 273.15)
|
||||
if (!(elements[TYP(r)].Properties & TYPE_SOLID) && Vm <= parts[i].temp - 273.15)
|
||||
parts[i].life = 1;
|
||||
break;
|
||||
default:
|
||||
// Normal mode
|
||||
if (!(sim->elements[TYP(r)].Properties & TYPE_SOLID) && Vm > parts[i].temp - 273.15)
|
||||
if (!(elements[TYP(r)].Properties & TYPE_SOLID) && Vm > parts[i].temp - 273.15)
|
||||
parts[i].life = 1;
|
||||
break;
|
||||
}
|
||||
@ -158,7 +160,7 @@ static int update(UPDATE_FUNC_ARGS)
|
||||
//Deserialization.
|
||||
if (doDeserialization)
|
||||
{
|
||||
if (TYP(r) != PT_FILT && !(sim->elements[TYP(r)].Properties & TYPE_SOLID))
|
||||
if (TYP(r) != PT_FILT && !(elements[TYP(r)].Properties & TYPE_SOLID))
|
||||
{
|
||||
float Vx = parts[ID(r)].vx;
|
||||
float Vy = parts[ID(r)].vy;
|
||||
|
@ -16,6 +16,8 @@ void SimTool::Tool_MIX()
|
||||
|
||||
static int perform(Simulation * sim, Particle * cpart, int x, int y, int brushX, int brushY, float strength)
|
||||
{
|
||||
auto &sd = SimulationData::CRef();
|
||||
auto &elements = sd.elements;
|
||||
int thisPart = sim->pmap[y][x];
|
||||
if(!thisPart)
|
||||
return 0;
|
||||
@ -25,7 +27,7 @@ static int perform(Simulation * sim, Particle * cpart, int x, int y, int brushX,
|
||||
|
||||
int distance = (int)(std::pow(strength, .5f) * 10);
|
||||
|
||||
if(!(sim->elements[TYP(thisPart)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS)))
|
||||
if(!(elements[TYP(thisPart)].Properties & (TYPE_PART | TYPE_LIQUID | TYPE_GAS)))
|
||||
return 0;
|
||||
|
||||
int newX = x + (sim->rng() % distance) - (distance/2);
|
||||
@ -38,7 +40,7 @@ static int perform(Simulation * sim, Particle * cpart, int x, int y, int brushX,
|
||||
if(!thatPart)
|
||||
return 0;
|
||||
|
||||
if ((sim->elements[TYP(thisPart)].Properties&STATE_FLAGS) != (sim->elements[TYP(thatPart)].Properties&STATE_FLAGS))
|
||||
if ((elements[TYP(thisPart)].Properties&STATE_FLAGS) != (elements[TYP(thatPart)].Properties&STATE_FLAGS))
|
||||
return 0;
|
||||
|
||||
sim->pmap[y][x] = thatPart;
|
||||
|
Reference in New Issue
Block a user