1337 lines
32 KiB
C++
1337 lines
32 KiB
C++
#include "Format.h"
|
|
#include "LuaScriptHelper.h"
|
|
#include "LuaScriptInterface.h"
|
|
#include "LuaSmartRef.h"
|
|
#include "PowderToySDL.h"
|
|
#include "prefs/GlobalPrefs.h"
|
|
#include "common/platform/Platform.h"
|
|
#include "graphics/Graphics.h"
|
|
#include "graphics/Renderer.h"
|
|
#include "simulation/ElementCommon.h"
|
|
#include "simulation/gravity/Gravity.h"
|
|
#include "simulation/Simulation.h"
|
|
#include "simulation/SimulationData.h"
|
|
#include "gui/game/GameController.h"
|
|
#include "gui/game/GameModel.h"
|
|
#include "gui/interface/Engine.h"
|
|
#include <iomanip>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <locale>
|
|
|
|
std::map<ByteString, StructProperty> legacyPropNames;
|
|
std::map<ByteString, StructProperty> legacyTransitionNames;
|
|
void initLegacyProps()
|
|
{
|
|
std::vector<StructProperty> properties = Element::GetProperties();
|
|
for (auto prop : properties)
|
|
{
|
|
if (prop.Name == "MenuVisible")
|
|
legacyPropNames.insert(std::pair<ByteString, StructProperty>("menu", prop));
|
|
else if (prop.Name == "PhotonReflectWavelengths")
|
|
continue;
|
|
else if (prop.Name == "CarriesTypeIn")
|
|
continue;
|
|
else if (prop.Name == "Temperature")
|
|
legacyPropNames.insert(std::pair<ByteString, StructProperty>("heat", prop));
|
|
else if (prop.Name == "HeatConduct")
|
|
legacyPropNames.insert(std::pair<ByteString, StructProperty>("hconduct", prop));
|
|
|
|
// Put all transition stuff into separate map
|
|
else if (prop.Name == "LowPressure")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("presLowValue", prop));
|
|
else if (prop.Name == "LowPressureTransition")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("presLowType", prop));
|
|
else if (prop.Name == "HighPressure")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("presHighValue", prop));
|
|
else if (prop.Name == "HighPressureTransition")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("presHighType", prop));
|
|
else if (prop.Name == "LowTemperature")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("tempLowValue", prop));
|
|
else if (prop.Name == "LowTemperatureTransition")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("tempLowType", prop));
|
|
else if (prop.Name == "HighTemperature")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("tempHighValue", prop));
|
|
else if (prop.Name == "HighTemperatureTransition")
|
|
legacyTransitionNames.insert(std::pair<ByteString, StructProperty>("tempHighType", prop));
|
|
|
|
else
|
|
{
|
|
legacyPropNames.insert(std::pair<ByteString, StructProperty>(prop.Name.ToLower(), prop));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifndef FFI
|
|
int luacon_partread(lua_State* l)
|
|
{
|
|
int i = cIndex;
|
|
if (i < 0 || i >= NPART)
|
|
return luaL_error(l, "Out of range");
|
|
if (!luacon_sim->parts[i].type)
|
|
return luaL_error(l, "Dead particle");
|
|
|
|
auto &properties = Particle::GetProperties();
|
|
auto prop = properties.end();
|
|
|
|
ByteString fieldName = tpt_lua_toByteString(l, 2);
|
|
if (fieldName == "id")
|
|
{
|
|
lua_pushnumber(l, i);
|
|
return 1;
|
|
}
|
|
for (auto &alias : Particle::GetPropertyAliases())
|
|
{
|
|
if (fieldName == alias.from)
|
|
{
|
|
fieldName = alias.to;
|
|
}
|
|
}
|
|
prop = std::find_if(properties.begin(), properties.end(), [&fieldName](StructProperty const &p) {
|
|
return p.Name == fieldName;
|
|
});
|
|
if (prop == properties.end())
|
|
return luaL_error(l, "Invalid property");
|
|
|
|
//Calculate memory address of property
|
|
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->parts[i]) + prop->Offset);
|
|
|
|
LuaScriptInterface::LuaGetProperty(l, *prop, propertyAddress);
|
|
return 1;
|
|
}
|
|
|
|
int luacon_partwrite(lua_State* l)
|
|
{
|
|
int i = cIndex;
|
|
if (i < 0 || i >= NPART)
|
|
return luaL_error(l, "Out of range");
|
|
if (!luacon_sim->parts[i].type)
|
|
return luaL_error(l, "Dead particle");
|
|
|
|
auto &properties = Particle::GetProperties();
|
|
auto prop = properties.end();
|
|
|
|
ByteString fieldName = tpt_lua_toByteString(l, 2);
|
|
for (auto &alias : Particle::GetPropertyAliases())
|
|
{
|
|
if (fieldName == alias.from)
|
|
{
|
|
fieldName = alias.to;
|
|
}
|
|
}
|
|
prop = std::find_if(properties.begin(), properties.end(), [&fieldName](StructProperty const &p) {
|
|
return p.Name == fieldName;
|
|
});
|
|
if (prop == properties.end())
|
|
return luaL_error(l, "Invalid property");
|
|
|
|
//Calculate memory address of property
|
|
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->parts[i]) + prop->Offset);
|
|
|
|
LuaScriptInterface::LuaSetParticleProperty(l, i, *prop, propertyAddress, 3);
|
|
return 0;
|
|
}
|
|
|
|
int luacon_partsread(lua_State* l)
|
|
{
|
|
int i = luaL_optinteger(l, 2, 0);
|
|
if (i < 0 || i >= NPART)
|
|
return luaL_error(l, "array index out of bounds");
|
|
|
|
lua_rawgeti(l, LUA_REGISTRYINDEX, *tptPart);
|
|
cIndex = i;
|
|
return 1;
|
|
}
|
|
|
|
int luacon_partswrite(lua_State* l)
|
|
{
|
|
return luaL_error(l, "table readonly");
|
|
}
|
|
#endif
|
|
|
|
int luacon_transitionread(lua_State* l)
|
|
{
|
|
ByteString key = tpt_lua_optByteString(l, 2, "");
|
|
if (legacyTransitionNames.find(key) == legacyTransitionNames.end())
|
|
return luaL_error(l, "Invalid property");
|
|
StructProperty prop = legacyTransitionNames[key];
|
|
|
|
//Get Raw Index value for element
|
|
lua_pushliteral(l, "id");
|
|
lua_rawget(l, 1);
|
|
int i = lua_tointeger (l, lua_gettop(l));
|
|
lua_pop(l, 1);
|
|
if (!luacon_sim->IsElement(i))
|
|
{
|
|
return luaL_error(l, "Invalid index");
|
|
}
|
|
|
|
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
|
LuaScriptInterface::LuaGetProperty(l, prop, propertyAddress);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int luacon_transitionwrite(lua_State* l)
|
|
{
|
|
ByteString key = tpt_lua_optByteString(l, 2, "");
|
|
if (legacyTransitionNames.find(key) == legacyTransitionNames.end())
|
|
return luaL_error(l, "Invalid property");
|
|
StructProperty prop = legacyTransitionNames[key];
|
|
|
|
//Get Raw Index value for element
|
|
lua_pushliteral(l, "id");
|
|
lua_rawget(l, 1);
|
|
int i = lua_tointeger (l, lua_gettop(l));
|
|
lua_pop(l, 1);
|
|
if (!luacon_sim->IsElement(i))
|
|
{
|
|
return luaL_error(l, "Invalid index");
|
|
}
|
|
|
|
if (prop.Type == StructProperty::TransitionType)
|
|
{
|
|
int type = luaL_checkinteger(l, 3);
|
|
if (!luacon_sim->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);
|
|
LuaScriptInterface::LuaSetProperty(l, prop, propertyAddress, 3);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int luacon_elementread(lua_State* l)
|
|
{
|
|
ByteString key = tpt_lua_optByteString(l, 2, "");
|
|
if (legacyPropNames.find(key) == legacyPropNames.end())
|
|
return luaL_error(l, "Invalid property");
|
|
StructProperty prop = legacyPropNames[key];
|
|
|
|
//Get Raw Index value for element
|
|
lua_pushliteral(l, "id");
|
|
lua_rawget(l, 1);
|
|
int i = lua_tointeger (l, lua_gettop(l));
|
|
lua_pop(l, 1);
|
|
if (!luacon_sim->IsElement(i))
|
|
{
|
|
return luaL_error(l, "Invalid index");
|
|
}
|
|
|
|
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
|
LuaScriptInterface::LuaGetProperty(l, prop, propertyAddress);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int luacon_elementwrite(lua_State* l)
|
|
{
|
|
ByteString key = tpt_lua_optByteString(l, 2, "");
|
|
if (legacyPropNames.find(key) == legacyPropNames.end())
|
|
return luaL_error(l, "Invalid property");
|
|
StructProperty prop = legacyPropNames[key];
|
|
|
|
//Get Raw Index value for element
|
|
lua_pushliteral(l, "id");
|
|
lua_rawget(l, 1);
|
|
int i = lua_tointeger (l, lua_gettop(l));
|
|
lua_pop(l, 1);
|
|
if (!luacon_sim->IsElement(i))
|
|
{
|
|
return luaL_error(l, "Invalid index");
|
|
}
|
|
|
|
intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset);
|
|
LuaScriptInterface::LuaSetProperty(l, prop, propertyAddress, 3);
|
|
|
|
luacon_model->BuildMenus();
|
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
|
luacon_ci->custom_init_can_move();
|
|
std::fill(&luacon_ren->graphicscache[0], &luacon_ren->graphicscache[0] + PT_NUM, gcache_item());
|
|
|
|
return 0;
|
|
}
|
|
|
|
void luacon_hook(lua_State * l, lua_Debug * ar)
|
|
{
|
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
|
if (ar->event == LUA_HOOKCOUNT && Platform::GetTime() - luacon_ci->luaExecutionStart > 3000)
|
|
{
|
|
luaL_error(l, "Error: Script not responding");
|
|
luacon_ci->luaExecutionStart = Platform::GetTime();
|
|
}
|
|
}
|
|
|
|
String luacon_geterror()
|
|
{
|
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
|
luaL_tostring(luacon_ci->l, -1);
|
|
String err = tpt_lua_optString(luacon_ci->l, -1, "failed to execute");
|
|
lua_pop(luacon_ci->l, 1);
|
|
return err;
|
|
}
|
|
|
|
//tpt. api methods
|
|
int luatpt_getelement(lua_State *l)
|
|
{
|
|
int t;
|
|
if (lua_isnumber(l, 1))
|
|
{
|
|
t = luaL_optint(l, 1, 1);
|
|
if (!luacon_sim->IsElementOrNone(t))
|
|
{
|
|
return luaL_error(l, "Unrecognised element number '%d'", t);
|
|
}
|
|
tpt_lua_pushString(l, luacon_sim->elements[t].Name);
|
|
}
|
|
else
|
|
{
|
|
luaL_checktype(l, 1, LUA_TSTRING);
|
|
auto name = tpt_lua_optByteString(l, 1, "");
|
|
if ((t = luacon_sim->GetParticleType(name))==-1)
|
|
return luaL_error(l, "Unrecognised element '%s'", name.c_str());
|
|
lua_pushinteger(l, t);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_drawtext(lua_State* l)
|
|
{
|
|
int textx, texty, textred, textgreen, textblue, textalpha;
|
|
textx = luaL_optint(l, 1, 0);
|
|
texty = luaL_optint(l, 2, 0);
|
|
auto string = tpt_lua_optString(l, 3, "");
|
|
textred = luaL_optint(l, 4, 255);
|
|
textgreen = luaL_optint(l, 5, 255);
|
|
textblue = luaL_optint(l, 6, 255);
|
|
textalpha = luaL_optint(l, 7, 255);
|
|
if (textx<0 || texty<0 || textx>=WINDOWW || texty>=WINDOWH)
|
|
return luaL_error(l, "Screen coordinates out of range (%d,%d)", textx, texty);
|
|
if (textred<0) textred = 0;
|
|
if (textred>255) textred = 255;
|
|
if (textgreen<0) textgreen = 0;
|
|
if (textgreen>255) textgreen = 255;
|
|
if (textblue<0) textblue = 0;
|
|
if (textblue>255) textblue = 255;
|
|
if (textalpha<0) textalpha = 0;
|
|
if (textalpha>255) textalpha = 255;
|
|
|
|
luacon_g->BlendText({ textx, texty }, string, RGBA<uint8_t>(textred, textgreen, textblue, textalpha));
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_create(lua_State* l)
|
|
{
|
|
int x, y, retid, t = -1;
|
|
x = abs(luaL_optint(l, 1, 0));
|
|
y = abs(luaL_optint(l, 2, 0));
|
|
if(x < XRES && y < YRES)
|
|
{
|
|
if (lua_isnumber(l, 3))
|
|
{
|
|
t = luaL_optint(l, 3, 0);
|
|
if (!luacon_sim->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)
|
|
return luaL_error(l,"Unrecognised element '%s'", name.c_str());
|
|
}
|
|
retid = luacon_sim->create_part(-1, x, y, t);
|
|
// failing to create a particle often happens (e.g. if space is already occupied) and isn't usually important, so don't raise an error
|
|
lua_pushinteger(l, retid);
|
|
return 1;
|
|
}
|
|
return luaL_error(l, "Coordinates out of range (%d,%d)", x, y);
|
|
}
|
|
|
|
int luatpt_setpause(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushnumber(l, luacon_model->GetPaused());
|
|
return 1;
|
|
}
|
|
int pausestate = luaL_checkinteger(l, 1);
|
|
luacon_model->SetPaused(pausestate==0?0:1);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_togglepause(lua_State* l)
|
|
{
|
|
luacon_model->SetPaused(!luacon_model->GetPaused());
|
|
lua_pushnumber(l, luacon_model->GetPaused());
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_togglewater(lua_State* l)
|
|
{
|
|
luacon_sim->water_equal_test=!luacon_sim->water_equal_test;
|
|
lua_pushnumber(l, luacon_sim->water_equal_test);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_setconsole(lua_State* l)
|
|
{
|
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushnumber(l, luacon_ci->Window != ui::Engine::Ref().GetWindow());
|
|
return 1;
|
|
}
|
|
if (luaL_checkinteger(l, 1))
|
|
luacon_controller->ShowConsole();
|
|
else
|
|
luacon_controller->HideConsole();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_log(lua_State* l)
|
|
{
|
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
|
int args = lua_gettop(l);
|
|
String text;
|
|
bool hasText = false;
|
|
for(int i = 1; i <= args; i++)
|
|
{
|
|
luaL_tostring(l, -1);
|
|
if (hasText)
|
|
{
|
|
text = tpt_lua_optString(l, -1, "") + ", " + text;
|
|
}
|
|
else
|
|
{
|
|
text = tpt_lua_optString(l, -1, "");
|
|
hasText = true;
|
|
}
|
|
lua_pop(l, 2);
|
|
}
|
|
if ((*luacon_currentCommand))
|
|
{
|
|
if (luacon_hasLastError)
|
|
*luacon_lastError += "; ";
|
|
*luacon_lastError += text;
|
|
luacon_hasLastError = true;
|
|
}
|
|
else
|
|
luacon_ci->Log(CommandInterface::LogNotice, text);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_set_pressure(lua_State* l)
|
|
{
|
|
int nx, ny;
|
|
int x1, y1, width, height;
|
|
float value;
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XCELLS));
|
|
height = abs(luaL_optint(l, 4, YCELLS));
|
|
value = luaL_optnumber(l, 5, 0.0f);
|
|
if(value > MAX_PRESSURE)
|
|
value = MAX_PRESSURE;
|
|
else if(value < MIN_PRESSURE)
|
|
value = MIN_PRESSURE;
|
|
|
|
if(x1 > XCELLS-1)
|
|
x1 = XCELLS-1;
|
|
if(y1 > YCELLS-1)
|
|
y1 = YCELLS-1;
|
|
if(x1+width > XCELLS-1)
|
|
width = XCELLS-x1;
|
|
if(y1+height > YCELLS-1)
|
|
height = YCELLS-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->pv[ny][nx] = value;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_set_gravity(lua_State* l)
|
|
{
|
|
int nx, ny;
|
|
int x1, y1, width, height;
|
|
float value;
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XCELLS));
|
|
height = abs(luaL_optint(l, 4, YCELLS));
|
|
value = luaL_optnumber(l, 5, 0.0f);
|
|
if(value > MAX_PRESSURE)
|
|
value = MAX_PRESSURE;
|
|
else if(value < MIN_PRESSURE)
|
|
value = MIN_PRESSURE;
|
|
|
|
if(x1 > XCELLS-1)
|
|
x1 = XCELLS-1;
|
|
if(y1 > YCELLS-1)
|
|
y1 = YCELLS-1;
|
|
if(x1+width > XCELLS-1)
|
|
width = XCELLS-x1;
|
|
if(y1+height > YCELLS-1)
|
|
height = YCELLS-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->gravmap[ny*XCELLS+nx] = value;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_reset_gravity_field(lua_State* l)
|
|
{
|
|
int nx, ny;
|
|
int x1, y1, width, height;
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XCELLS));
|
|
height = abs(luaL_optint(l, 4, YCELLS));
|
|
if(x1 > XCELLS-1)
|
|
x1 = XCELLS-1;
|
|
if(y1 > YCELLS-1)
|
|
y1 = YCELLS-1;
|
|
if(x1+width > XCELLS-1)
|
|
width = XCELLS-x1;
|
|
if(y1+height > YCELLS-1)
|
|
height = YCELLS-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->gravx[ny*XCELLS+nx] = 0;
|
|
luacon_sim->gravy[ny*XCELLS+nx] = 0;
|
|
luacon_sim->gravp[ny*XCELLS+nx] = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_reset_velocity(lua_State* l)
|
|
{
|
|
int nx, ny;
|
|
int x1, y1, width, height;
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XCELLS));
|
|
height = abs(luaL_optint(l, 4, YCELLS));
|
|
if(x1 > XCELLS-1)
|
|
x1 = XCELLS-1;
|
|
if(y1 > YCELLS-1)
|
|
y1 = YCELLS-1;
|
|
if(x1+width > XCELLS-1)
|
|
width = XCELLS-x1;
|
|
if(y1+height > YCELLS-1)
|
|
height = YCELLS-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->vx[ny][nx] = 0;
|
|
luacon_sim->vy[ny][nx] = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_reset_spark(lua_State* l)
|
|
{
|
|
luacon_controller->ResetSpark();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_set_property(lua_State* l)
|
|
{
|
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
|
int r, i, x, y, w, h, t = 0, nx, ny, partsel = 0;
|
|
float f = 0;
|
|
int acount = lua_gettop(l);
|
|
auto prop = tpt_lua_optByteString(l, 1, "");
|
|
|
|
CommandInterface::FormatType format;
|
|
int offset = luacon_ci->GetPropertyOffset(prop, format);
|
|
if (offset == -1)
|
|
return luaL_error(l, "Invalid property '%s'", prop.c_str());
|
|
bool isX = byteStringEqualsLiteral(prop, "x");
|
|
bool isY = byteStringEqualsLiteral(prop, "y");
|
|
|
|
if (acount > 2)
|
|
{
|
|
if(!lua_isnumber(l, acount) && lua_isstring(l, acount))
|
|
{
|
|
auto name = tpt_lua_optByteString(l, acount, "none");
|
|
if ((partsel = luacon_sim->GetParticleType(name)) == -1)
|
|
return luaL_error(l, "Unrecognised element '%s'", name.c_str());
|
|
}
|
|
}
|
|
if (lua_isnumber(l, 2))
|
|
{
|
|
if (format == CommandInterface::FormatFloat)
|
|
f = luaL_optnumber(l, 2, 0);
|
|
else
|
|
t = luaL_optint(l, 2, 0);
|
|
|
|
if (byteStringEqualsLiteral(prop, "type") && !luacon_sim->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)
|
|
return luaL_error(l, "Unrecognised element '%s'", name.c_str());
|
|
}
|
|
else
|
|
luaL_error(l, "Expected number or element name as argument 2");
|
|
|
|
if (!lua_isnumber(l, 3) || acount >= 6)
|
|
{
|
|
// Got a region
|
|
if (acount < 6)
|
|
{
|
|
i = 0;
|
|
y = 0;
|
|
w = XRES;
|
|
h = YRES;
|
|
}
|
|
else
|
|
{
|
|
i = abs(luaL_checkint(l, 3));
|
|
y = abs(luaL_checkint(l, 4));
|
|
w = abs(luaL_checkint(l, 5));
|
|
h = abs(luaL_checkint(l, 6));
|
|
}
|
|
if (i>=XRES || y>=YRES)
|
|
return luaL_error(l, "Coordinates out of range (%d,%d)", i, y);
|
|
x = i;
|
|
if(x+w > XRES)
|
|
w = XRES-x;
|
|
if(y+h > YRES)
|
|
h = YRES-y;
|
|
Particle * parts = luacon_sim->parts;
|
|
for (i = 0; i < NPART; i++)
|
|
{
|
|
if (parts[i].type)
|
|
{
|
|
nx = (int)(parts[i].x + .5f);
|
|
ny = (int)(parts[i].y + .5f);
|
|
if (nx >= x && nx < x+w && ny >= y && ny < y+h && (!partsel || partsel == parts[i].type))
|
|
{
|
|
if (format == CommandInterface::FormatElement)
|
|
luacon_sim->part_change_type(i, nx, ny, t);
|
|
else if (isX || isY)
|
|
{
|
|
float x = luacon_sim->parts[i].x;
|
|
float y = luacon_sim->parts[i].y;
|
|
float nx = isX ? f : x;
|
|
float ny = isY ? f : y;
|
|
luacon_sim->move(i, (int)(x + 0.5f), (int)(y + 0.5f), nx, ny);
|
|
}
|
|
else if(format == CommandInterface::FormatFloat)
|
|
*((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = f;
|
|
else
|
|
*((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = t;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
i = abs(luaL_checkint(l, 3));
|
|
// Got coords or particle index
|
|
if (lua_isnumber(l, 4))
|
|
{
|
|
y = abs(luaL_checkint(l, 4));
|
|
if (i>=XRES || y>=YRES)
|
|
return luaL_error(l, "Coordinates out of range (%d,%d)", i, y);
|
|
r = luacon_sim->pmap[y][i];
|
|
if (!r || (partsel && partsel != TYP(r)))
|
|
r = luacon_sim->photons[y][i];
|
|
if (!r || (partsel && partsel != TYP(r)))
|
|
return 0;
|
|
i = ID(r);
|
|
}
|
|
if (i < 0 || i >= NPART)
|
|
return luaL_error(l, "Invalid particle ID '%d'", i);
|
|
if (!luacon_sim->parts[i].type)
|
|
return 0;
|
|
if (partsel && partsel != luacon_sim->parts[i].type)
|
|
return 0;
|
|
|
|
if (format == CommandInterface::FormatElement)
|
|
luacon_sim->part_change_type(i, int(luacon_sim->parts[i].x + 0.5f), int(luacon_sim->parts[i].y + 0.5f), t);
|
|
else if (isX || isY)
|
|
{
|
|
float x = luacon_sim->parts[i].x;
|
|
float y = luacon_sim->parts[i].y;
|
|
float nx = isX ? f : x;
|
|
float ny = isY ? f : y;
|
|
luacon_sim->move(i, (int)(x + 0.5f), (int)(y + 0.5f), nx, ny);
|
|
}
|
|
else if (format == CommandInterface::FormatFloat)
|
|
*((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = f;
|
|
else
|
|
*((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = t;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_get_wallmap(lua_State* l)
|
|
{
|
|
int x1 = abs(luaL_optint(l, 1, 0));
|
|
int y1 = abs(luaL_optint(l, 2, 0));
|
|
|
|
if(x1 > XCELLS || y1 > YCELLS)
|
|
return luaL_error(l, "Out of range");
|
|
|
|
lua_pushinteger(l, luacon_sim->bmap[y1][x1]);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_set_wallmap(lua_State* l)
|
|
{
|
|
int args = lua_gettop(l);
|
|
if (args < 3 || args > 7 || args % 2 != 1)
|
|
return luaL_error(l, "Incorrect numbner of arguments");
|
|
int x = luaL_optint(l, 1, 0);
|
|
int y = luaL_optint(l, 2, 0);
|
|
int w = luaL_optint(l, 3, 0);
|
|
int h = luaL_optint(l, 4, 0);
|
|
float fvx = float(luaL_optnumber(l, 5, 0));
|
|
float fvy = float(luaL_optnumber(l, 6, 0));
|
|
|
|
int wallType = luaL_optint(l, args, 0);
|
|
if (wallType < 0 || wallType >= UI_WALLCOUNT)
|
|
{
|
|
return luaL_error(l, "Unrecognised wall number %d", wallType);
|
|
}
|
|
|
|
bool setFv = args == 7;
|
|
if (args < 5)
|
|
{
|
|
w = 1;
|
|
h = 1;
|
|
}
|
|
if (x < 0 ) x = 0 ;
|
|
if (y < 0 ) y = 0 ;
|
|
if (x > XCELLS ) x = XCELLS ;
|
|
if (y > YCELLS ) y = YCELLS ;
|
|
if (w > XCELLS - x) w = XCELLS - x;
|
|
if (h > YCELLS - y) h = YCELLS - y;
|
|
for (int yy = y; yy < y + h; ++yy)
|
|
{
|
|
for (int xx = x; xx < x + w; ++xx)
|
|
{
|
|
luacon_sim->bmap[yy][xx] = wallType;
|
|
if (setFv)
|
|
{
|
|
luacon_sim->fvx[yy][xx] = fvx;
|
|
luacon_sim->fvy[yy][xx] = fvy;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_set_elecmap(lua_State* l)
|
|
{
|
|
int nx, ny, acount;
|
|
int x1, y1, width, height;
|
|
unsigned char value;
|
|
acount = lua_gettop(l);
|
|
|
|
x1 = abs(luaL_optint(l, 1, 0));
|
|
y1 = abs(luaL_optint(l, 2, 0));
|
|
width = abs(luaL_optint(l, 3, XCELLS));
|
|
height = abs(luaL_optint(l, 4, YCELLS));
|
|
value = luaL_optint(l, acount, 0);
|
|
|
|
if(acount==5) //Draw rect
|
|
{
|
|
if(x1 > XCELLS)
|
|
x1 = XCELLS;
|
|
if(y1 > YCELLS)
|
|
y1 = YCELLS;
|
|
if(x1+width > XCELLS)
|
|
width = XCELLS-x1;
|
|
if(y1+height > YCELLS)
|
|
height = YCELLS-y1;
|
|
for (nx = x1; nx<x1+width; nx++)
|
|
for (ny = y1; ny<y1+height; ny++)
|
|
{
|
|
luacon_sim->emap[ny][nx] = value;
|
|
}
|
|
}
|
|
else //Set point
|
|
{
|
|
if(x1 > XCELLS)
|
|
x1 = XCELLS;
|
|
if(y1 > YCELLS)
|
|
y1 = YCELLS;
|
|
luacon_sim->emap[y1][x1] = value;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_get_elecmap(lua_State* l)
|
|
{
|
|
int x1 = abs(luaL_optint(l, 1, 0));
|
|
int y1 = abs(luaL_optint(l, 2, 0));
|
|
|
|
if(x1 > XCELLS || y1 > YCELLS)
|
|
return luaL_error(l, "Out of range");
|
|
|
|
lua_pushinteger(l, luacon_sim->emap[y1][x1]);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_get_property(lua_State* l)
|
|
{
|
|
auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
|
|
ByteString prop = tpt_lua_optByteString(l, 1, "");
|
|
int i = luaL_optint(l, 2, 0); //x coord or particle index, depending on arguments
|
|
int y = luaL_optint(l, 3, -1);
|
|
if (y!=-1 && y<YRES && y>=0 && i < XRES && i>=0)
|
|
{
|
|
int r = luacon_sim->pmap[y][i];
|
|
if (!r)
|
|
{
|
|
r = luacon_sim->photons[y][i];
|
|
if (!r)
|
|
{
|
|
if (byteStringEqualsLiteral(prop, "type"))
|
|
{
|
|
lua_pushinteger(l, 0);
|
|
return 1;
|
|
}
|
|
return luaL_error(l, "Particle does not exist");
|
|
}
|
|
}
|
|
i = ID(r);
|
|
}
|
|
else if (y != -1)
|
|
return luaL_error(l, "Coordinates out of range (%d,%d)", i, y);
|
|
if (i < 0 || i >= NPART)
|
|
return luaL_error(l, "Invalid particle ID '%d'", i);
|
|
|
|
if (luacon_sim->parts[i].type)
|
|
{
|
|
int tempinteger;
|
|
float tempfloat;
|
|
CommandInterface::FormatType format;
|
|
int offset = luacon_ci->GetPropertyOffset(prop, format);
|
|
|
|
if (offset == -1)
|
|
{
|
|
if (byteStringEqualsLiteral(prop, "id"))
|
|
{
|
|
lua_pushnumber(l, i);
|
|
return 1;
|
|
}
|
|
else
|
|
return luaL_error(l, "Invalid property");
|
|
}
|
|
switch(format)
|
|
{
|
|
case CommandInterface::FormatInt:
|
|
case CommandInterface::FormatElement:
|
|
tempinteger = *((int*)(((unsigned char*)&luacon_sim->parts[i])+offset));
|
|
lua_pushnumber(l, tempinteger);
|
|
break;
|
|
case CommandInterface::FormatFloat:
|
|
tempfloat = *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset));
|
|
lua_pushnumber(l, tempfloat);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
else if (byteStringEqualsLiteral(prop, "type"))
|
|
{
|
|
lua_pushinteger(l, 0);
|
|
return 1;
|
|
}
|
|
return luaL_error(l, "Particle does not exist");
|
|
}
|
|
|
|
int luatpt_drawpixel(lua_State* l)
|
|
{
|
|
int x, y, r, g, b, a;
|
|
x = luaL_optint(l, 1, 0);
|
|
y = luaL_optint(l, 2, 0);
|
|
r = luaL_optint(l, 3, 255);
|
|
g = luaL_optint(l, 4, 255);
|
|
b = luaL_optint(l, 5, 255);
|
|
a = luaL_optint(l, 6, 255);
|
|
|
|
if (x<0 || y<0 || x>=WINDOWW || y>=WINDOWH)
|
|
return luaL_error(l, "Screen coordinates out of range (%d,%d)", x, y);
|
|
if (r<0) r = 0;
|
|
else if (r>255) r = 255;
|
|
if (g<0) g = 0;
|
|
else if (g>255) g = 255;
|
|
if (b<0) b = 0;
|
|
else if (b>255) b = 255;
|
|
if (a<0) a = 0;
|
|
else if (a>255) a = 255;
|
|
luacon_g->BlendPixel({ x, y }, RGBA<uint8_t>(r, g, b, a));
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_drawrect(lua_State* l)
|
|
{
|
|
int x, y, w, h, r, g, b, a;
|
|
x = luaL_optint(l, 1, 0);
|
|
y = luaL_optint(l, 2, 0);
|
|
w = luaL_optint(l, 3, 10)+1;
|
|
h = luaL_optint(l, 4, 10)+1;
|
|
r = luaL_optint(l, 5, 255);
|
|
g = luaL_optint(l, 6, 255);
|
|
b = luaL_optint(l, 7, 255);
|
|
a = luaL_optint(l, 8, 255);
|
|
|
|
if (x<0 || y<0 || x>=WINDOWW || y>=WINDOWH)
|
|
return luaL_error(l, "Screen coordinates out of range (%d,%d)", x, y);
|
|
if(x+w > WINDOWW)
|
|
w = WINDOWW-x;
|
|
if(y+h > WINDOWH)
|
|
h = WINDOWH-y;
|
|
if (r<0) r = 0;
|
|
else if (r>255) r = 255;
|
|
if (g<0) g = 0;
|
|
else if (g>255) g = 255;
|
|
if (b<0) b = 0;
|
|
else if (b>255) b = 255;
|
|
if (a<0) a = 0;
|
|
else if (a>255) a = 255;
|
|
if (a == 255)
|
|
{
|
|
luacon_g->DrawRect(RectSized(Vec2{ x, y }, Vec2{ w, h }), RGB<uint8_t>(r, g, b));
|
|
}
|
|
else
|
|
{
|
|
luacon_g->BlendRect(RectSized(Vec2{ x, y }, Vec2{ w, h }), RGBA<uint8_t>(r, g, b, a));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_fillrect(lua_State* l)
|
|
{
|
|
int x,y,w,h,r,g,b,a;
|
|
x = luaL_optint(l, 1, 0)+1;
|
|
y = luaL_optint(l, 2, 0)+1;
|
|
w = luaL_optint(l, 3, 10)-1;
|
|
h = luaL_optint(l, 4, 10)-1;
|
|
r = luaL_optint(l, 5, 255);
|
|
g = luaL_optint(l, 6, 255);
|
|
b = luaL_optint(l, 7, 255);
|
|
a = luaL_optint(l, 8, 255);
|
|
|
|
if (x<0 || y<0 || x>=WINDOWW || y>=WINDOWH)
|
|
return luaL_error(l, "Screen coordinates out of range (%d,%d)", x, y);
|
|
if(x+w > WINDOWW)
|
|
w = WINDOWW-x;
|
|
if(y+h > WINDOWH)
|
|
h = WINDOWH-y;
|
|
if (r<0) r = 0;
|
|
else if (r>255) r = 255;
|
|
if (g<0) g = 0;
|
|
else if (g>255) g = 255;
|
|
if (b<0) b = 0;
|
|
else if (b>255) b = 255;
|
|
if (a<0) a = 0;
|
|
else if (a>255) a = 255;
|
|
if (a == 255)
|
|
{
|
|
luacon_g->DrawFilledRect(RectSized(Vec2{ x, y }, Vec2{ w, h }), RGB<uint8_t>(r, g, b));
|
|
}
|
|
else
|
|
{
|
|
luacon_g->BlendFilledRect(RectSized(Vec2{ x, y }, Vec2{ w, h }), RGBA<uint8_t>(r, g, b, a));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_drawline(lua_State* l)
|
|
{
|
|
int x1,y1,x2,y2,r,g,b,a;
|
|
x1 = luaL_optint(l, 1, 0);
|
|
y1 = luaL_optint(l, 2, 0);
|
|
x2 = luaL_optint(l, 3, 10);
|
|
y2 = luaL_optint(l, 4, 10);
|
|
r = luaL_optint(l, 5, 255);
|
|
g = luaL_optint(l, 6, 255);
|
|
b = luaL_optint(l, 7, 255);
|
|
a = luaL_optint(l, 8, 255);
|
|
|
|
//Don't need to check coordinates, as they are checked in blendpixel
|
|
if (r<0) r = 0;
|
|
else if (r>255) r = 255;
|
|
if (g<0) g = 0;
|
|
else if (g>255) g = 255;
|
|
if (b<0) b = 0;
|
|
else if (b>255) b = 255;
|
|
if (a<0) a = 0;
|
|
else if (a>255) a = 255;
|
|
if (a == 255)
|
|
{
|
|
luacon_g->DrawLine({ x1, y1 }, { x2, y2 }, RGB<uint8_t>(r, g, b));
|
|
}
|
|
else
|
|
{
|
|
luacon_g->BlendLine({ x1, y1 }, { x2, y2 }, RGBA<uint8_t>(r, g, b, a));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_textwidth(lua_State* l)
|
|
{
|
|
auto string = tpt_lua_optString(l, 1, "");
|
|
int strwidth = Graphics::TextSize(string).X - 1;
|
|
lua_pushinteger(l, strwidth);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_get_name(lua_State* l)
|
|
{
|
|
if (luacon_model->GetUser().UserID)
|
|
{
|
|
tpt_lua_pushByteString(l, luacon_model->GetUser().Username);
|
|
return 1;
|
|
}
|
|
lua_pushliteral(l, "");
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_delete(lua_State* l)
|
|
{
|
|
int arg1, arg2;
|
|
arg1 = abs(luaL_optint(l, 1, 0));
|
|
arg2 = luaL_optint(l, 2, -1);
|
|
if (arg2 == -1 && arg1 < NPART)
|
|
{
|
|
luacon_sim->kill_part(arg1);
|
|
return 0;
|
|
}
|
|
arg2 = abs(arg2);
|
|
if(arg2 < YRES && arg1 < XRES)
|
|
{
|
|
luacon_sim->delete_part(arg1, arg2);
|
|
return 0;
|
|
}
|
|
return luaL_error(l,"Invalid coordinates or particle ID");
|
|
}
|
|
|
|
int luatpt_get_numOfParts(lua_State* l)
|
|
{
|
|
lua_pushinteger(l, luacon_sim->NUM_PARTS);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_start_getPartIndex(lua_State* l)
|
|
{
|
|
getPartIndex_curIdx = -1;
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_next_getPartIndex(lua_State* l)
|
|
{
|
|
while(1)
|
|
{
|
|
getPartIndex_curIdx++;
|
|
if (getPartIndex_curIdx >= NPART)
|
|
{
|
|
getPartIndex_curIdx = -1;
|
|
lua_pushboolean(l, 0);
|
|
return 1;
|
|
}
|
|
if (luacon_sim->parts[getPartIndex_curIdx].type)
|
|
break;
|
|
|
|
}
|
|
|
|
lua_pushboolean(l, 1);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_getPartIndex(lua_State* l)
|
|
{
|
|
if(getPartIndex_curIdx < 0)
|
|
{
|
|
lua_pushinteger(l, -1);
|
|
return 1;
|
|
}
|
|
lua_pushinteger(l, getPartIndex_curIdx);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_hud(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, luacon_controller->GetHudEnable());
|
|
return 1;
|
|
}
|
|
int hudstate = luaL_checkint(l, 1);
|
|
if (hudstate)
|
|
luacon_controller->SetHudEnable(1);
|
|
else
|
|
luacon_controller->SetHudEnable(0);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_gravity(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, luacon_sim->grav->IsEnabled() ? 1 : 0);
|
|
return 1;
|
|
}
|
|
int gravstate = luaL_checkint(l, 1);
|
|
if(gravstate)
|
|
luacon_sim->grav->start_grav_async();
|
|
else
|
|
luacon_sim->grav->stop_grav_async();
|
|
luacon_model->UpdateQuickOptions();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_airheat(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, luacon_sim->aheat_enable);
|
|
return 1;
|
|
}
|
|
int aheatstate = luaL_checkint(l, 1);
|
|
luacon_sim->aheat_enable = (aheatstate==0?0:1);
|
|
luacon_model->UpdateQuickOptions();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_active_menu(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, luacon_model->GetActiveMenu());
|
|
return 1;
|
|
}
|
|
int menuid = luaL_checkint(l, 1);
|
|
if (menuid >= 0 && menuid < SC_TOTAL)
|
|
luacon_controller->SetActiveMenu(menuid);
|
|
else
|
|
return luaL_error(l, "Invalid menu");
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_menu_enabled(lua_State* l)
|
|
{
|
|
int menusection = luaL_checkint(l, 1);
|
|
if (menusection < 0 || menusection >= SC_TOTAL)
|
|
return luaL_error(l, "Invalid menu");
|
|
int acount = lua_gettop(l);
|
|
if (acount == 1)
|
|
{
|
|
lua_pushboolean(l, luacon_sim->msections[menusection].doshow);
|
|
return 1;
|
|
}
|
|
luaL_checktype(l, 2, LUA_TBOOLEAN);
|
|
int enabled = lua_toboolean(l, 2);
|
|
luacon_sim->msections[menusection].doshow = enabled;
|
|
luacon_model->BuildMenus();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_num_menus(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
bool onlyEnabled = true;
|
|
if (acount > 0)
|
|
{
|
|
luaL_checktype(l, 1, LUA_TBOOLEAN);
|
|
onlyEnabled = lua_toboolean(l, 1);
|
|
}
|
|
lua_pushinteger(l, luacon_controller->GetNumMenus(onlyEnabled));
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_decorations_enable(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, luacon_model->GetDecoration());
|
|
return 1;
|
|
}
|
|
int decostate = luaL_checkint(l, 1);
|
|
luacon_model->SetDecoration(decostate==0?false:true);
|
|
luacon_model->UpdateQuickOptions();
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_heat(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, !luacon_sim->legacy_enable);
|
|
return 1;
|
|
}
|
|
int heatstate = luaL_checkint(l, 1);
|
|
luacon_sim->legacy_enable = (heatstate==1?0:1);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_cmode_set(lua_State* l)
|
|
{
|
|
int cmode = luaL_optint(l, 1, 3)+1;
|
|
if (cmode == 11)
|
|
cmode = 0;
|
|
if (cmode >= 0 && cmode <= 10)
|
|
luacon_controller->LoadRenderPreset(cmode);
|
|
else
|
|
return luaL_error(l, "Invalid display mode");
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_setfire(lua_State* l)
|
|
{
|
|
int firesize = luaL_optint(l, 2, 4);
|
|
float fireintensity = (float)luaL_optnumber(l, 1, 1.0f);
|
|
luacon_model->GetRenderer()->prepare_alpha(firesize, fireintensity);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_setdebug(lua_State* l)
|
|
{
|
|
int debugFlags = luaL_optint(l, 1, 0);
|
|
luacon_controller->SetDebugFlags(debugFlags);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_setfpscap(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
auto fpsLimit = ui::Engine::Ref().GetFpsLimit();
|
|
if (std::holds_alternative<FpsLimitVsync>(fpsLimit))
|
|
{
|
|
lua_pushliteral(l, "vsync");
|
|
}
|
|
else if (std::holds_alternative<FpsLimitNone>(fpsLimit))
|
|
{
|
|
lua_pushnumber(l, 2);
|
|
}
|
|
else
|
|
{
|
|
lua_pushnumber(l, std::get<FpsLimitExplicit>(fpsLimit).value);
|
|
}
|
|
return 1;
|
|
}
|
|
if (lua_isstring(l, 1) && byteStringEqualsLiteral(tpt_lua_toByteString(l, 1), "vsync"))
|
|
{
|
|
ui::Engine::Ref().SetFpsLimit(FpsLimitVsync{});
|
|
return 0;
|
|
}
|
|
float fpscap = luaL_checknumber(l, 1);
|
|
if (fpscap < 2)
|
|
{
|
|
return luaL_error(l, "fps cap too small");
|
|
}
|
|
if (fpscap == 2)
|
|
{
|
|
ui::Engine::Ref().SetFpsLimit(FpsLimitNone{});
|
|
return 0;
|
|
}
|
|
ui::Engine::Ref().SetFpsLimit(FpsLimitExplicit{ fpscap });
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_setdrawcap(lua_State* l)
|
|
{
|
|
int acount = lua_gettop(l);
|
|
if (acount == 0)
|
|
{
|
|
lua_pushinteger(l, ui::Engine::Ref().GetDrawingFrequencyLimit());
|
|
return 1;
|
|
}
|
|
int drawcap = luaL_checkint(l, 1);
|
|
if(drawcap < 0)
|
|
return luaL_error(l, "draw cap too small");
|
|
ui::Engine::Ref().SetDrawingFrequencyLimit(drawcap);
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_setwindowsize(lua_State* l)
|
|
{
|
|
int scale = luaL_optint(l,1,1);
|
|
int kiosk = luaL_optint(l,2,0);
|
|
// TODO: handle this the same way as it's handled in PowderToySDL.cpp
|
|
// > maybe bind the maximum allowed scale to screen size somehow
|
|
if (scale < 1 || scale > 10)
|
|
{
|
|
scale = 1;
|
|
}
|
|
if (kiosk!=1)
|
|
{
|
|
kiosk = 0;
|
|
}
|
|
{
|
|
auto &prefs = GlobalPrefs::Ref();
|
|
Prefs::DeferWrite dw(prefs);
|
|
prefs.Set("Scale", scale);
|
|
prefs.Set("Fullscreen", bool(kiosk));
|
|
}
|
|
ui::Engine::Ref().SetScale(scale);
|
|
ui::Engine::Ref().SetFullscreen(kiosk);
|
|
return 0;
|
|
}
|
|
|
|
int screenshotIndex = 0;
|
|
|
|
int luatpt_screenshot(lua_State* l)
|
|
{
|
|
int captureUI = luaL_optint(l, 1, 0);
|
|
int fileType = luaL_optint(l, 2, 0);
|
|
|
|
ByteString filename = luacon_controller->TakeScreenshot(captureUI, fileType);
|
|
if (filename.size())
|
|
{
|
|
tpt_lua_pushByteString(l, filename);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int luatpt_record(lua_State* l)
|
|
{
|
|
if (!lua_isboolean(l, -1))
|
|
return luaL_typerror(l, 1, lua_typename(l, LUA_TBOOLEAN));
|
|
bool record = lua_toboolean(l, -1);
|
|
int recordingFolder = luacon_controller->Record(record);
|
|
lua_pushinteger(l, recordingFolder);
|
|
return 1;
|
|
}
|
|
|
|
int luatpt_perfectCircle(lua_State* l)
|
|
{
|
|
if (!lua_gettop(l))
|
|
{
|
|
lua_pushboolean(l, luacon_model->GetPerfectCircle());
|
|
return 1;
|
|
}
|
|
luaL_checktype(l, 1, LUA_TBOOLEAN);
|
|
luacon_model->SetPerfectCircle(lua_toboolean(l, 1));
|
|
return 0;
|
|
}
|